mirror of
https://github.com/cline/cline.git
synced 2026-10-28 02:58:44 +08:00
* Let hosts choose the hub daemon launcher and defer spawn-only setup Adds setHubDaemonLauncher so an embedding process can start the hub daemon through a bundled Cline CLI instead of its own executable, and a beforeSpawn hook on ensureDetachedHubServer that only runs when a new daemon is actually started. * Add programmatic options to cline hub ensure hub ensure/start gain --json (URL + auth token), --allow-port-fallback, --no-connectors and --login-shell-path, and the hub command accepts --discovery-path for a dedicated discovery record. These let the desktop app and SSH remotes start or reuse a hub through the CLI. Also extracts the standalone binary compile step into script/compile-binary.ts so other packages can build the CLI binary. * Run SSH remote hubs through the Cline CLI SSH remotes now upload the Cline CLI binary and start or reuse the remote hub with 'cline hub ensure --json --discovery-path ...', stopping it with 'cline hub stop'. The dedicated remote helper entrypoint is removed; cleanup records from older releases still stop through the old flag. * Run the desktop backend on the bundled Cline CLI The desktop app no longer compiles its own executable. It bundles the self-contained Cline CLI (externalBin cline-cli) plus the backend as a JS bundle that runs on the CLI's embedded runtime. At startup the backend has the CLI run 'hub ensure', which reuses a compatible healthy Hub or starts one, and any Hub it starts later also goes through the CLI binary. Linux CLI copies are bundled for SSH remotes. * Launch the desktop backend through the bundled Cline CLI The Tauri shell resolves the bundled cline-cli and the backend bundle (per-platform resource layouts) and starts 'cline-cli run' on it. The Windows installer stops users of cline-cli.exe, and also stops and removes the backend executable of earlier releases on upgrade. * Recognize the CLI-hosted desktop backend in cline doctor --fix * Update desktop publish workflow and docs for the bundled Cline CLI Telemetry selfchecks and smoke tests run the backend bundle on the bundled CLI, and the Windows signature gate verifies cline-cli.exe. * fix(desktop): address runtime packaging review findings * fix(desktop): preserve failed hub cleanup and handle exited daemons * fix(hub): distinguish missing discovery records from read failures * fix(hub): preserve discovery recovery while enforcing strict shutdown reads * fix(cli): do not count hub commands as CLI activations (#14870) * fix(cli): do not count hub commands as CLI activations The desktop app runs `cline-cli hub ensure` on every launch and the SSH remote flow runs `cline hub ensure` on every connect. Both went through runCli(), which captured user.extension_activated unconditionally, so each desktop launch was double-counted as a CLI activation and every SSH remote host (with its own distinct id) showed up as a new CLI user. Skip the activation capture for the hub subcommand; it is plumbing other clients invoke, not a user activation. Hub-owned task telemetry is unaffected since the daemon path never enters runCli(). * test(cli): clear the hub command mock between main.test.ts cases * test(cli): stop stubbing the hub command module in main.test.ts The module-wide vi.mock("./commands/hub") replaced createHubCommand with a no-op, so `cline hub dashboard` (routed through createHubCommand) never reached the dashboard mock and three dashboard tests failed. Drop the module mock and assert the activation exclusion through `hub dashboard --no-open`, which is already mocked. --------- Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
80 lines
3.3 KiB
PowerShell
80 lines
3.3 KiB
PowerShell
# Authenticode-signs one PE file with Azure Trusted Signing via jsign.
|
|
#
|
|
# Invoked by the Tauri bundler through `bundle > windows > signCommand` (the
|
|
# desktop-publish workflow generates a config overlay pointing here), once per
|
|
# binary it stages: the main app exe, the bundled cline-cli external binary, the
|
|
# NSIS uninstaller, and the NSIS installer itself.
|
|
#
|
|
# Requirements (all provided by the desktop-publish Windows job):
|
|
# - an azure/login OIDC session (jsign's token comes from `az account get-access-token`)
|
|
# - AZURE_TRUSTED_SIGNING_ENDPOINT / _ACCOUNT_NAME / _CERTIFICATE_PROFILE env vars
|
|
# - java on PATH (preinstalled on GitHub Windows runners)
|
|
#
|
|
# Mirrors the CLI pipeline (.github/actions/sign-windows-cli): same jsign
|
|
# version and flags, same Microsoft timestamp service. Kept as a standalone
|
|
# script so the signing behavior is reviewable in the repo rather than inlined
|
|
# in a generated config string.
|
|
|
|
param(
|
|
[Parameter(Mandatory = $true, Position = 0)]
|
|
[string] $Path
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$jsignVersion = "7.5"
|
|
$jsignSha256 = "602A51C3545A6DC4FB99BD2EA7152B26D1345916D0C93DDFBD5936CB735AF91C"
|
|
|
|
$endpoint = $env:AZURE_TRUSTED_SIGNING_ENDPOINT
|
|
$account = $env:AZURE_TRUSTED_SIGNING_ACCOUNT_NAME
|
|
$certProfile = $env:AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE
|
|
if (-not $endpoint -or -not $account -or -not $certProfile) {
|
|
throw "Azure Trusted Signing env vars are not set (AZURE_TRUSTED_SIGNING_ENDPOINT/_ACCOUNT_NAME/_CERTIFICATE_PROFILE)"
|
|
}
|
|
|
|
$resolved = (Resolve-Path $Path).Path
|
|
|
|
# jsign expects the endpoint host; tolerate the portal's trailing-slash form.
|
|
$keystore = $endpoint -replace '^https://', '' -replace '/$', ''
|
|
|
|
$jar = Join-Path $env:RUNNER_TEMP "jsign-$jsignVersion.jar"
|
|
if (-not (Test-Path $jar)) {
|
|
Invoke-WebRequest -Uri "https://github.com/ebourg/jsign/releases/download/$jsignVersion/jsign-$jsignVersion.jar" -OutFile $jar
|
|
}
|
|
$actualHash = (Get-FileHash -Algorithm SHA256 $jar).Hash
|
|
if ($actualHash -ne $jsignSha256) {
|
|
Remove-Item $jar -Force
|
|
throw "jsign jar checksum mismatch: expected $jsignSha256, got $actualHash"
|
|
}
|
|
|
|
# Bearer token from the azure/login OIDC session, served from az's cache: the
|
|
# workflow primes it right after login because the OIDC assertion behind the
|
|
# session expires ~10 minutes in, before the Rust build finishes. Fetched per
|
|
# invocation (signCommand runs once per file) rather than passed in, so no
|
|
# token sits in the job environment. Passed to jsign via env, not argv.
|
|
$env:JSIGN_STOREPASS = (az account get-access-token --resource https://codesigning.azure.net --query accessToken --output tsv)
|
|
if (-not $env:JSIGN_STOREPASS) {
|
|
throw "failed to acquire an Azure access token; is azure/login configured on this job?"
|
|
}
|
|
|
|
Write-Host "Signing $resolved"
|
|
java -jar $jar `
|
|
--storetype TRUSTEDSIGNING `
|
|
--keystore $keystore `
|
|
--storepass env:JSIGN_STOREPASS `
|
|
--alias "$account/$certProfile" `
|
|
--alg SHA-256 `
|
|
--tsaurl http://timestamp.acs.microsoft.com `
|
|
--tsmode RFC3161 `
|
|
--replace `
|
|
$resolved
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "jsign failed for $resolved (exit $LASTEXITCODE)"
|
|
}
|
|
|
|
$signature = Get-AuthenticodeSignature $resolved
|
|
if ($signature.Status -ne "Valid") {
|
|
throw "signature verification failed for ${resolved}: $($signature.Status) - $($signature.StatusMessage)"
|
|
}
|
|
Write-Host "Signed and verified: $resolved ($($signature.SignerCertificate.Subject))"
|