From 39ae62851bce3e4f15df5a9ec5d0f8071aad821f Mon Sep 17 00:00:00 2001 From: Will Washburn Date: Sun, 12 Jul 2026 21:47:23 -0400 Subject: [PATCH 1/5] feat(cli): warm fast path spawns the harness in ~20ms; 10x faster cold launches agent launches now keep the session's sandbox mount warm and record a digest-validated launch plan. The next launch of the same selector validates the plan with a handful of stats (~20ms including node boot), claims the warm mount by atomic rename, and spawns the harness immediately; the heavy CLI module loads afterward, reattaches the mount with the previous session's autosync state, and reconciles while the harness boots. Any change to the persona, source dirs, skills, dotfiles, or pinned env falls back to the full path (AGENTWORKFORCE_NO_FAST=1 disables). Cold launches populate mounts from git ls-files (local-mount population: 'auto'), start autosync from population-seeded state, skip the npm cache when mirroring skills, and lazy-load cloud subcommand handlers. In the relay repo: 26s -> 2.5s cold, ~20ms warm; teardown 11s -> <1s. Requires @relayfile/local-mount ^0.11.0 (release upstream first). Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 25 + packages/cli/package.json | 2 +- packages/cli/src/cli-impl.ts | 5326 ++++++++++++++++++++++++++ packages/cli/src/cli.test.ts | 2 +- packages/cli/src/cli.ts | 4751 +---------------------- packages/cli/src/fast-launch.test.ts | 169 + packages/cli/src/fast-launch.ts | 313 ++ 7 files changed, 5854 insertions(+), 4734 deletions(-) create mode 100644 packages/cli/src/cli-impl.ts create mode 100644 packages/cli/src/fast-launch.test.ts create mode 100644 packages/cli/src/fast-launch.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index f69958ae..f7e09704 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,3 +7,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +### Added + +- `@agentworkforce/cli`: warm fast path for `agent `. Repeat + launches of the same persona in the same repo reuse the previous session's + sandbox mount plus a digest-validated launch plan, spawning the harness in + tens of milliseconds; the mount reconciles with the repo in the background + while the harness boots. Any change to the persona, its source dirs, + skills, dotfiles, or relevant environment falls back to the full launch. + Disable with `AGENTWORKFORCE_NO_FAST=1`. Launch-phase timings are printable + with `AGENTWORKFORCE_PERF=1`. + +### Changed + +- `@agentworkforce/cli`: cold launches are an order of magnitude faster. + Sandbox mounts populate from `git ls-files` (`@relayfile/local-mount` + `population: 'auto'`), so gitignored trees never get mirrored or rescanned; + autosync starts from population-seeded state instead of re-reading every + file pair; the skill-cache mirror no longer copies the install-time npm + cache into the mount; and cloud subcommand handlers load lazily off the + launch path. In the relay repo, launch-to-harness went from ~26s to ~2.5s + cold and ~20ms warm, and session teardown from ~11s to under 1s. +- `@agentworkforce/cli`: requires `@relayfile/local-mount` ^0.11.0 + (git-list population, `attachMount`, exported autosync state, and the + external-teardown safety guard). diff --git a/packages/cli/package.json b/packages/cli/package.json index 3c2fe06c..bf73b6a1 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -16,7 +16,7 @@ "@agentworkforce/runtime": "workspace:*", "@agentworkforce/workload-router": "workspace:*", "@relayburn/sdk": "^2.5.2", - "@relayfile/local-mount": "^0.7.24", + "@relayfile/local-mount": "^0.11.0", "ora": "^9.4.0" }, "repository": { diff --git a/packages/cli/src/cli-impl.ts b/packages/cli/src/cli-impl.ts new file mode 100644 index 00000000..24650c1e --- /dev/null +++ b/packages/cli/src/cli-impl.ts @@ -0,0 +1,5326 @@ +#!/usr/bin/env node +import { spawn, spawnSync } from 'node:child_process'; +import { randomBytes } from 'node:crypto'; +import { + appendFileSync, + closeSync, + cpSync, + existsSync, + mkdirSync, + mkdtempSync, + openSync, + readdirSync, + readFileSync, + readSync, + renameSync, + rmSync, + statSync, + writeFileSync, + type Dirent +} from 'node:fs'; +import { constants, homedir, tmpdir } from 'node:os'; +import { dirname, isAbsolute, join, resolve as resolvePath } from 'node:path'; +import { pathToFileURL } from 'node:url'; + +import { + buildCleanupArtifacts, + buildInstallArtifacts, + buildInteractiveSpec, + buildNonInteractiveSpec, + buildUpstreamRecordsFromCacheDir, + computeSkillCacheFingerprint, + detectHarnesses, + detectSkillUpstreamDrift, + formatDropWarnings, + HARNESS_VALUES, + isSkillCacheValid, + isUpstreamCheckDue, + materializeSkills, + MissingPersonaInputError, + parseCheckInterval, + PERSONA_TAGS, + readSkillCacheMarker, + renderPersonaInputs, + resolveAiMemory, + resolveMcpServersLenient, + resolvePersonaInputs, + resolveSidecar, + resolveSkillCacheDir, + resolveStringMapLenient, + updateSkillCacheMarkerUpstream, + writeSkillCacheMarker, + type Harness, + type HarnessAvailability, + type InteractiveSpec, + type NonInteractiveSpec, + type PersonaMount, + type AiHistMcpConfig, + type PersonaSelection, + type PersonaSpec, + type PersonaTag, + type RelayMcpConfig, + type SidecarMdMode, + type SkillMaterializationPlan +} from '@agentworkforce/persona-kit'; +import { + claudeMcpConfigHasRelayOverride, + codexExistingArgs, + injectClaudeAgentRelayMcpConfig, + injectCodexSubcommandArgs, + resolveAgentRelayBrokerMcpArgs, + resolveRelayMcpFromEnv as resolveRelayMcpFromEnvShared +} from '@agentworkforce/runtime'; +import { + listBuiltInPersonas, + personaCatalog, + routingProfiles +} from '@agentworkforce/workload-router'; +import { + attachMount, + createMount, + readAgentDotfiles, + type AutoSyncHandle, + type FileState, + type MountHandle +} from '@relayfile/local-mount'; +import { + deleteLaunchPlan, + statDigestOf, + warmMountDir, + writeLaunchPlan, + type FastLaunch, + type LaunchPlan, + type StatDigest, + LAUNCH_PLAN_SCHEMA_VERSION +} from './fast-launch.js'; +import ora, { type Ora } from 'ora'; +// Cloud-facing subcommand handlers (deploy/invoke/runs/destroy/integrations/ +// deployments) are imported lazily at dispatch: their module graphs pull in +// @agent-relay/cloud and friends, which costs hundreds of milliseconds that +// the hot `agent ` launch path must not pay. +import { + startLaunchMetadataRecording, + type LaunchMetadataRun +} from './launch-metadata.js'; +import { createLogger } from './logger.js'; +import { + buildPersonaSourceDirectories, + defaultCwdPersonaDir, + formatPersonaSourceLabel, + loadLocalPersonas, + loadPersonaSourceConfig, + normalizePersonaDir, + savePersonaSourceConfig, + type PersonaSource +} from './local-personas.js'; +import { installPersonas, type PersonaInstallResult } from './persona-install.js'; +import { runPersonaCompileCommand } from './persona-compile.js'; +import { pickPersona, type PickCandidate, type PickResult } from './persona-picker.js'; +import { recordRecent, loadRecents, runPersonaPickerTui, type TuiCandidate } from './persona-tui.js'; +import { runTrigger } from './trigger-command.js'; + +const launchMetadataLog = createLogger('launch-metadata'); + +/** + * Launch-phase timing marks, enabled with AGENTWORKFORCE_PERF=1. Each line is + * `[perf] +