@rallycry/conveyor-agent 10.13.13 → 10.13.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,9 +4,9 @@ import {
4
4
  WorkbenchError,
5
5
  getWorkbenchClient,
6
6
  resetWorkbenchClient
7
- } from "./chunk-YRC57EYG.js";
7
+ } from "./chunk-LZM5OKAC.js";
8
8
  import "./chunk-4VUQ2NPF.js";
9
- import "./chunk-IE7EOKMD.js";
9
+ import "./chunk-VKZ5W2VO.js";
10
10
  export {
11
11
  RemoteProcessHandle,
12
12
  WorkbenchClient,
@@ -14,4 +14,4 @@ export {
14
14
  getWorkbenchClient,
15
15
  resetWorkbenchClient
16
16
  };
17
- //# sourceMappingURL=client-ICIWKSK2.js.map
17
+ //# sourceMappingURL=client-VQIBGPE6.js.map
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _project_shared from '@project/shared';
2
- import { RunnerMode, AgentSessionServiceMethods, AgentMode, PtyChatEventPayload, WorkspaceDiscoveredPort, AgentQuestion, AgentRunnerStatus, BootstrapBundle } from '@project/shared';
2
+ import { RunnerMode, AgentSessionServiceMethods, AgentMode, PtyChatEventPayload, WorkspaceDiscoveredPort, AgentQuestion, AgentRunnerStatus } from '@project/shared';
3
3
  export * from '@project/shared';
4
4
  import { ChildProcess } from 'node:child_process';
5
5
 
@@ -88,7 +88,6 @@ declare class AgentConnection {
88
88
  private modeChangeCallback;
89
89
  private apiKeyUpdateCallback;
90
90
  private pullBranchCallback;
91
- private finalizeSnapshotCallback;
92
91
  private runStartCommandCallback;
93
92
  private earlyPullBranches;
94
93
  private spawnReviewCallback;
@@ -164,7 +163,6 @@ declare class AgentConnection {
164
163
  * sessionId is OUR (builder) session — the SEC-9 guard runs on it.
165
164
  */
166
165
  reportSessionSpawnFailure(spawnedSessionId: string, error?: string): void;
167
- onFinalizeSnapshot(callback: () => void): void;
168
166
  onRunStartCommand(callback: () => void): void;
169
167
  /**
170
168
  * Forward a raw chunk of terminal output to the S2 relay (fire-and-forget).
@@ -223,7 +221,6 @@ declare class AgentConnection {
223
221
  sendTypingStop(): void;
224
222
  emitRateLimitPause(resetsAt: string): void;
225
223
  updateStatus(status: string): void;
226
- emitCodeReviewResult(content: string, approved: boolean): void;
227
224
  /**
228
225
  * The session's key hit a hard usage cap — ask the server to stamp it
229
226
  * limited and hand back the best remaining key's credential env (or a
@@ -437,6 +434,12 @@ interface SessionRunnerPortDiscovery {
437
434
  start(): Promise<void>;
438
435
  stop(): void;
439
436
  }
437
+ /** Duck-typed handle onto the boot supervisor — just enough surface for the
438
+ * runner to release the app's start command once the core loop is live.
439
+ * Avoids importing the concrete WorkspaceCommandSupervisor class here. */
440
+ interface SessionRunnerWorkspaceCommands {
441
+ notifyLoopReady(): void;
442
+ }
440
443
  interface SessionRunnerDependencies {
441
444
  portDiscovery?: SessionRunnerPortDiscovery;
442
445
  }
@@ -474,10 +477,20 @@ declare class SessionRunner {
474
477
  private readonly portDiscovery;
475
478
  /** Main event-loop lag measurement, shared with the heartbeat worker. */
476
479
  private readonly loopLag;
480
+ /** Boot supervisor handle, set post-construction once it's known (it is
481
+ * started alongside connect(), before the runner itself exists in some
482
+ * call sites) — notified when the core loop goes live so it can release
483
+ * the app's start command. Optional: never set in tests/paths that don't
484
+ * wire a supervisor. */
485
+ private workspaceCommands;
477
486
  constructor(config: SessionRunnerConfig, callbacks: SessionRunnerCallbacks, deps?: SessionRunnerDependencies);
478
487
  get state(): AgentRunnerStatus;
479
488
  get sessionId(): string;
480
489
  get isStopped(): boolean;
490
+ /** Wire the boot supervisor handle post-construction — cli.ts constructs it
491
+ * via startWorkspaceCommandsAfterConnect() (which needs connect() to already
492
+ * be callable), so it can't be a constructor dependency. */
493
+ setWorkspaceCommands(supervisor: SessionRunnerWorkspaceCommands | null): void;
481
494
  /**
482
495
  * Establish the API connection, wire callbacks, and join the session room.
483
496
  * Call this before run() when you need to send events (e.g. setup/start
@@ -558,6 +571,15 @@ declare class SessionRunner {
558
571
  private onPassiveTuiActivity;
559
572
  /** Run queryBridge.executePassive, swallowing abort errors from stop/softStop. */
560
573
  private executePassive;
574
+ /** Shared token-refresh closure for the git-flush call sites (periodic
575
+ * backstop + per-turn flush). Never throws — returns undefined so the
576
+ * caller falls back to its existing remote credentials. */
577
+ private refreshGithubTokenForFlush;
578
+ /** Push uncommitted work to the conveyor-wip ref after a turn. Git-only (no
579
+ * GCS). Primary-branch only — cheap enough to run every turn. Shares the
580
+ * in-flight guard with the periodic backstop so a turn-end flush and a
581
+ * timer tick never overlap. Best-effort, never throws. */
582
+ private flushWipNow;
561
583
  /** Periodic best-effort WIP commit + push during normal agent execution.
562
584
  * Covers ungraceful pod termination (OOMKilled, node crash/eviction) where
563
585
  * the preStop hook + SIGTERM flush don't get a chance to run. No-ops on a
@@ -570,9 +592,6 @@ declare class SessionRunner {
570
592
  * `selectBestKey` rotation honest. Best-effort — never throws, no-op when the
571
593
  * pod has no OAuth token (e.g. API-key projects). */
572
594
  private sampleAndReportKeyUsage;
573
- /** PUT the WorkPreservation snapshot tar to the bundle's capability URL
574
- * when this pod is v3 (CONVEYOR_SNAPSHOT_UPLOAD_URL set). Never throws. */
575
- private uploadGcsSnapshotIfConfigured;
576
595
  /** Best-effort WIP commit + push on shutdown so in-flight work isn't lost
577
596
  * when a claudespace pod is killed. Must be called BEFORE stop() so the
578
597
  * connection is still alive for token refresh. Never throws. */
@@ -582,14 +601,6 @@ declare class SessionRunner {
582
601
  private buildFullContext;
583
602
  private createQueryBridge;
584
603
  private wireConnectionCallbacks;
585
- /** Eager finalize snapshot triggered by the reconciler's sleep signal
586
- * (session:finalizeSnapshot). Runs a full workspace capture and uploads it
587
- * NOW so the sleep confirms on this snapshot instead of waiting for the
588
- * ~2min periodic flush. Sidecar DB state is intentionally NOT captured — it
589
- * is no longer durable across sleep/wake (#2623); only the agent's
590
- * /workspace rides the snapshot. Best-effort: on failure the
591
- * periodic/shutdown path stays the fallback. No-op on non-v3 pods. */
592
- private finalizeSnapshotNow;
593
604
  /** Proactively refresh the GitHub token before the 1-hour expiry. */
594
605
  private refreshGithubToken;
595
606
  /** Re-fetch task context to pick up a newly created branch and check it out. */
@@ -659,67 +670,6 @@ declare function detachWorktreeBranch(projectDir: string, branch: string): Promi
659
670
  */
660
671
  declare function removeWorktree(projectDir: string, taskId: string): Promise<void>;
661
672
 
662
- interface CaptureContext {
663
- cwd: string;
664
- branch: string;
665
- snapshotUploadUrl?: string;
666
- refreshToken?: () => Promise<string | undefined>;
667
- wipMessage?: string;
668
- /** Force the GCS PUT even when the tar is empty (sizeBytes === 0). Used by the
669
- * sleep FINALIZE path so `snapshotAt` is stamped and the reconciler's
670
- * teardown confirm lands immediately — an empty workspace is a valid (empty)
671
- * snapshot; on wake the restore's manifest check falls back to a clean
672
- * checkout. The periodic path leaves this false so a racing empty capture
673
- * never clobbers a good snapshot. */
674
- forceUpload?: boolean;
675
- }
676
- interface SnapshotArtifact {
677
- fileCount: number;
678
- deletionCount: number;
679
- sizeBytes: number;
680
- gcsUploaded: boolean;
681
- wipPushed: boolean;
682
- }
683
- interface RestoreResult {
684
- source: "gcs" | "wip" | "clean";
685
- fileCount?: number;
686
- }
687
- interface GcsUploadResult {
688
- uploaded: boolean;
689
- fileCount: number;
690
- deletionCount: number;
691
- sizeBytes: number;
692
- }
693
- /**
694
- * The GCS sink on its own: assemble the snapshot tar (the single capture
695
- * path) and PUT it to the capability URL. Exposed so a runner whose git-tier
696
- * flush is driven elsewhere (SessionRunner's periodic flushAllPendingWork)
697
- * can add the GCS sink to the SAME trigger instead of running a second,
698
- * racing snapshotter. Calls are serialized: a later capture always PUTs
699
- * after any earlier in-flight one has settled.
700
- */
701
- declare function uploadSnapshotToGcs(cwd: string, uploadUrl: string | undefined, opts?: {
702
- forceUpload?: boolean;
703
- }): Promise<GcsUploadResult>;
704
- declare function captureSnapshot(ctx: CaptureContext): Promise<SnapshotArtifact>;
705
- declare function startPeriodic(intervalMs: number, ctx: CaptureContext): void;
706
- declare function stop(): void;
707
- declare function finalizeForSleep(ctx: CaptureContext): Promise<SnapshotArtifact>;
708
- /**
709
- * Restore precedence at boot: GCS snapshot (tracked+untracked+deletions),
710
- * else the conveyor-wip ref, else a clean checkout. Accepts the narrow slice
711
- * of the bundle it reads so v3 pods can call it from env-derived values
712
- * (CONVEYOR_SNAPSHOT_URL + the task branch) as well as from a full bundle.
713
- *
714
- * GCS is only authoritative when the archive's manifest HEAD matches the
715
- * current clone (checked BEFORE any tree mutation) — a stale or invalid
716
- * snapshot leaves the tree untouched and falls through to the wip ref, whose
717
- * own parent-HEAD guard handles staleness.
718
- */
719
- declare function restoreOnBoot(bundle: Pick<BootstrapBundle, "snapshotUrl"> & {
720
- gitPlan: Pick<BootstrapBundle["gitPlan"], "branch">;
721
- }, cwd: string): Promise<RestoreResult>;
722
-
723
673
  interface ConveyorConfig {
724
674
  setupCommand?: string;
725
675
  startCommand?: string;
@@ -742,4 +692,4 @@ declare function runStartCommand(cmd: string, cwd: string, onOutput: (stream: "s
742
692
  /** Fetch full git history if the repo was cloned with --depth=1. */
743
693
  declare function unshallowRepo(workspaceDir: string): void;
744
694
 
745
- export { AgentConnection, type AgentConnectionConfig, type AgentRunnerCallbacks, type AgentRunnerConfig, type ApiKeyUpdateData, type CaptureContext, type ConveyorConfig, type GcsUploadResult, type IncomingMessage, type LifecycleCallbacks, type LifecycleConfig, type ModeAction, type ModeTaskContext, type RestoreResult, SessionRunner, type SessionRunnerCallbacks, type SessionRunnerConfig, type SetModeData, type SnapshotArtifact, captureSnapshot, detachWorktreeBranch, ensureWorktree, finalizeForSleep, flushPendingChanges, getCurrentBranch, hasUncommittedChanges, hasUnpushedCommits, loadConveyorConfig, loadForwardPorts, pushToOrigin, removeWorktree, restoreOnBoot, runAuthTokenCommand, runSetupCommand, runStartCommand, stageAndCommit, startPeriodic as startWorkPreservation, stop as stopWorkPreservation, unshallowRepo, updateRemoteToken, uploadSnapshotToGcs };
695
+ export { AgentConnection, type AgentConnectionConfig, type AgentRunnerCallbacks, type AgentRunnerConfig, type ApiKeyUpdateData, type ConveyorConfig, type IncomingMessage, type LifecycleCallbacks, type LifecycleConfig, type ModeAction, type ModeTaskContext, SessionRunner, type SessionRunnerCallbacks, type SessionRunnerConfig, type SetModeData, detachWorktreeBranch, ensureWorktree, flushPendingChanges, getCurrentBranch, hasUncommittedChanges, hasUnpushedCommits, loadConveyorConfig, loadForwardPorts, pushToOrigin, removeWorktree, runAuthTokenCommand, runSetupCommand, runStartCommand, stageAndCommit, unshallowRepo, updateRemoteToken };
package/dist/index.js CHANGED
@@ -2,8 +2,6 @@ import {
2
2
  AgentConnection,
3
3
  GIT_TIMEOUT_MS,
4
4
  SessionRunner,
5
- captureSnapshot,
6
- finalizeForSleep,
7
5
  flushPendingChanges,
8
6
  getCurrentBranch,
9
7
  hasUncommittedChanges,
@@ -11,19 +9,15 @@ import {
11
9
  loadConveyorConfig,
12
10
  loadForwardPorts,
13
11
  pushToOrigin,
14
- restoreOnBoot,
15
12
  stageAndCommit,
16
- startPeriodic,
17
- stop,
18
13
  unshallowRepo,
19
14
  updateRemoteToken,
20
- uploadSnapshotToGcs,
21
15
  workspacePathExists
22
- } from "./chunk-TB5SQIGX.js";
16
+ } from "./chunk-SAHOFQBQ.js";
23
17
  import "./chunk-7TQO4ZF4.js";
24
18
  import {
25
19
  getWorkbenchClient
26
- } from "./chunk-YRC57EYG.js";
20
+ } from "./chunk-LZM5OKAC.js";
27
21
  import {
28
22
  workbenchEnabled
29
23
  } from "./chunk-4VUQ2NPF.js";
@@ -31,8 +25,8 @@ import {
31
25
  runAuthTokenCommand,
32
26
  runSetupCommand,
33
27
  runStartCommand
34
- } from "./chunk-2K6RRTQC.js";
35
- import "./chunk-IE7EOKMD.js";
28
+ } from "./chunk-RSIW2UCR.js";
29
+ import "./chunk-VKZ5W2VO.js";
36
30
 
37
31
  // src/runner/worktree.ts
38
32
  import { execFile } from "child_process";
@@ -102,10 +96,8 @@ async function removeWorktree(projectDir, taskId) {
102
96
  export {
103
97
  AgentConnection,
104
98
  SessionRunner,
105
- captureSnapshot,
106
99
  detachWorktreeBranch,
107
100
  ensureWorktree,
108
- finalizeForSleep,
109
101
  flushPendingChanges,
110
102
  getCurrentBranch,
111
103
  hasUncommittedChanges,
@@ -114,15 +106,11 @@ export {
114
106
  loadForwardPorts,
115
107
  pushToOrigin,
116
108
  removeWorktree,
117
- restoreOnBoot,
118
109
  runAuthTokenCommand,
119
110
  runSetupCommand,
120
111
  runStartCommand,
121
112
  stageAndCommit,
122
- startPeriodic as startWorkPreservation,
123
- stop as stopWorkPreservation,
124
113
  unshallowRepo,
125
- updateRemoteToken,
126
- uploadSnapshotToGcs
114
+ updateRemoteToken
127
115
  };
128
116
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runner/worktree.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { GIT_TIMEOUT_MS, hasUncommittedChanges } from \"./git-utils.js\";\nimport { getWorkbenchClient } from \"../workbench/client.js\";\nimport { workbenchEnabled } from \"../workbench/mode.js\";\nimport { workspacePathExists } from \"../workbench/fs.js\";\n\n// Async git (execFile, no shell) — synchronous child processes freeze the\n// agent's event loop and starve the socket heartbeat; see git-utils.ts.\n// Split-mode pods route over the launcher (the repo lives in the workbench).\nconst execFileAsync = promisify(execFile);\n\nasync function git(cwd: string, args: string[]): Promise<string> {\n if (workbenchEnabled()) {\n const { stdout } = await getWorkbenchClient().execFile(\"git\", args, {\n cwd,\n timeout: GIT_TIMEOUT_MS,\n });\n return stdout;\n }\n const { stdout } = await execFileAsync(\"git\", args, { cwd, timeout: GIT_TIMEOUT_MS });\n return stdout.toString();\n}\n\nconst WORKTREE_DIR = \".worktrees\";\n\nexport async function ensureWorktree(\n projectDir: string,\n taskId: string,\n branch?: string,\n): Promise<string> {\n if (projectDir.includes(`/${WORKTREE_DIR}/`)) {\n return projectDir;\n }\n\n const worktreePath = join(projectDir, WORKTREE_DIR, taskId);\n\n if (await workspacePathExists(worktreePath)) {\n if (branch) {\n if (await hasUncommittedChanges(worktreePath)) {\n return worktreePath;\n }\n try {\n await git(worktreePath, [\"checkout\", \"--detach\", `origin/${branch}`]);\n } catch {\n /* branch doesn't exist on remote yet */\n }\n }\n return worktreePath;\n }\n\n const ref = branch ? `origin/${branch}` : \"HEAD\";\n await git(projectDir, [\"worktree\", \"add\", \"--detach\", worktreePath, ref]);\n\n return worktreePath;\n}\n\n/**\n * Detach any task worktree that has `branch` checked out, releasing the branch lock\n * so the main project directory can check it out. Only touches worktrees inside\n * `.worktrees/` — never the main project directory.\n */\nexport async function detachWorktreeBranch(projectDir: string, branch: string): Promise<void> {\n try {\n const output = await git(projectDir, [\"worktree\", \"list\", \"--porcelain\"]);\n const entries = output.split(\"\\n\\n\");\n for (const entry of entries) {\n const lines = entry.trim().split(\"\\n\");\n const worktreeLine = lines.find((l) => l.startsWith(\"worktree \"));\n const branchLine = lines.find((l) => l.startsWith(\"branch \"));\n if (!worktreeLine || branchLine !== `branch refs/heads/${branch}`) continue;\n\n const worktreePath = worktreeLine.replace(\"worktree \", \"\");\n if (!worktreePath.includes(`/${WORKTREE_DIR}/`)) continue;\n\n try {\n await git(worktreePath, [\"checkout\", \"--detach\"]);\n } catch {\n /* best effort */\n }\n }\n } catch {\n /* best effort */\n }\n}\n\n/**\n * Force-remove is intentional: this runs after task completion or explicit stop.\n * Any uncommitted changes at this point are scratch artifacts, not valuable work.\n */\nexport async function removeWorktree(projectDir: string, taskId: string): Promise<void> {\n const worktreePath = join(projectDir, WORKTREE_DIR, taskId);\n if (!(await workspacePathExists(worktreePath))) return;\n try {\n await git(projectDir, [\"worktree\", \"remove\", worktreePath, \"--force\"]);\n } catch {\n /* best effort */\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,gBAAgB;AACzB,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAS1B,IAAM,gBAAgB,UAAU,QAAQ;AAExC,eAAe,IAAI,KAAa,MAAiC;AAC/D,MAAI,iBAAiB,GAAG;AACtB,UAAM,EAAE,QAAAA,QAAO,IAAI,MAAM,mBAAmB,EAAE,SAAS,OAAO,MAAM;AAAA,MAClE;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AACD,WAAOA;AAAA,EACT;AACA,QAAM,EAAE,OAAO,IAAI,MAAM,cAAc,OAAO,MAAM,EAAE,KAAK,SAAS,eAAe,CAAC;AACpF,SAAO,OAAO,SAAS;AACzB;AAEA,IAAM,eAAe;AAErB,eAAsB,eACpB,YACA,QACA,QACiB;AACjB,MAAI,WAAW,SAAS,IAAI,YAAY,GAAG,GAAG;AAC5C,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,KAAK,YAAY,cAAc,MAAM;AAE1D,MAAI,MAAM,oBAAoB,YAAY,GAAG;AAC3C,QAAI,QAAQ;AACV,UAAI,MAAM,sBAAsB,YAAY,GAAG;AAC7C,eAAO;AAAA,MACT;AACA,UAAI;AACF,cAAM,IAAI,cAAc,CAAC,YAAY,YAAY,UAAU,MAAM,EAAE,CAAC;AAAA,MACtE,QAAQ;AAAA,MAER;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,SAAS,UAAU,MAAM,KAAK;AAC1C,QAAM,IAAI,YAAY,CAAC,YAAY,OAAO,YAAY,cAAc,GAAG,CAAC;AAExE,SAAO;AACT;AAOA,eAAsB,qBAAqB,YAAoB,QAA+B;AAC5F,MAAI;AACF,UAAM,SAAS,MAAM,IAAI,YAAY,CAAC,YAAY,QAAQ,aAAa,CAAC;AACxE,UAAM,UAAU,OAAO,MAAM,MAAM;AACnC,eAAW,SAAS,SAAS;AAC3B,YAAM,QAAQ,MAAM,KAAK,EAAE,MAAM,IAAI;AACrC,YAAM,eAAe,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,WAAW,CAAC;AAChE,YAAM,aAAa,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,SAAS,CAAC;AAC5D,UAAI,CAAC,gBAAgB,eAAe,qBAAqB,MAAM,GAAI;AAEnE,YAAM,eAAe,aAAa,QAAQ,aAAa,EAAE;AACzD,UAAI,CAAC,aAAa,SAAS,IAAI,YAAY,GAAG,EAAG;AAEjD,UAAI;AACF,cAAM,IAAI,cAAc,CAAC,YAAY,UAAU,CAAC;AAAA,MAClD,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAMA,eAAsB,eAAe,YAAoB,QAA+B;AACtF,QAAM,eAAe,KAAK,YAAY,cAAc,MAAM;AAC1D,MAAI,CAAE,MAAM,oBAAoB,YAAY,EAAI;AAChD,MAAI;AACF,UAAM,IAAI,YAAY,CAAC,YAAY,UAAU,cAAc,SAAS,CAAC;AAAA,EACvE,QAAQ;AAAA,EAER;AACF;","names":["stdout"]}
1
+ {"version":3,"sources":["../src/runner/worktree.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { GIT_TIMEOUT_MS, hasUncommittedChanges } from \"./git-utils.js\";\nimport { getWorkbenchClient } from \"../workbench/client.js\";\nimport { workbenchEnabled } from \"../workbench/mode.js\";\nimport { workspacePathExists } from \"../workbench/fs.js\";\n\n// Async git (execFile, no shell) — synchronous child processes freeze the\n// agent's event loop and starve the socket heartbeat; see git-utils.ts.\n// Split-mode pods route over the launcher (the repo lives in the workbench).\nconst execFileAsync = promisify(execFile);\n\nasync function git(cwd: string, args: string[]): Promise<string> {\n if (workbenchEnabled()) {\n const { stdout } = await getWorkbenchClient().execFile(\"git\", args, {\n cwd,\n timeout: GIT_TIMEOUT_MS,\n });\n return stdout;\n }\n const { stdout } = await execFileAsync(\"git\", args, { cwd, timeout: GIT_TIMEOUT_MS });\n return stdout.toString();\n}\n\nconst WORKTREE_DIR = \".worktrees\";\n\nexport async function ensureWorktree(\n projectDir: string,\n taskId: string,\n branch?: string,\n): Promise<string> {\n if (projectDir.includes(`/${WORKTREE_DIR}/`)) {\n return projectDir;\n }\n\n const worktreePath = join(projectDir, WORKTREE_DIR, taskId);\n\n if (await workspacePathExists(worktreePath)) {\n if (branch) {\n if (await hasUncommittedChanges(worktreePath)) {\n return worktreePath;\n }\n try {\n await git(worktreePath, [\"checkout\", \"--detach\", `origin/${branch}`]);\n } catch {\n /* branch doesn't exist on remote yet */\n }\n }\n return worktreePath;\n }\n\n const ref = branch ? `origin/${branch}` : \"HEAD\";\n await git(projectDir, [\"worktree\", \"add\", \"--detach\", worktreePath, ref]);\n\n return worktreePath;\n}\n\n/**\n * Detach any task worktree that has `branch` checked out, releasing the branch lock\n * so the main project directory can check it out. Only touches worktrees inside\n * `.worktrees/` — never the main project directory.\n */\nexport async function detachWorktreeBranch(projectDir: string, branch: string): Promise<void> {\n try {\n const output = await git(projectDir, [\"worktree\", \"list\", \"--porcelain\"]);\n const entries = output.split(\"\\n\\n\");\n for (const entry of entries) {\n const lines = entry.trim().split(\"\\n\");\n const worktreeLine = lines.find((l) => l.startsWith(\"worktree \"));\n const branchLine = lines.find((l) => l.startsWith(\"branch \"));\n if (!worktreeLine || branchLine !== `branch refs/heads/${branch}`) continue;\n\n const worktreePath = worktreeLine.replace(\"worktree \", \"\");\n if (!worktreePath.includes(`/${WORKTREE_DIR}/`)) continue;\n\n try {\n await git(worktreePath, [\"checkout\", \"--detach\"]);\n } catch {\n /* best effort */\n }\n }\n } catch {\n /* best effort */\n }\n}\n\n/**\n * Force-remove is intentional: this runs after task completion or explicit stop.\n * Any uncommitted changes at this point are scratch artifacts, not valuable work.\n */\nexport async function removeWorktree(projectDir: string, taskId: string): Promise<void> {\n const worktreePath = join(projectDir, WORKTREE_DIR, taskId);\n if (!(await workspacePathExists(worktreePath))) return;\n try {\n await git(projectDir, [\"worktree\", \"remove\", worktreePath, \"--force\"]);\n } catch {\n /* best effort */\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,gBAAgB;AACzB,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAS1B,IAAM,gBAAgB,UAAU,QAAQ;AAExC,eAAe,IAAI,KAAa,MAAiC;AAC/D,MAAI,iBAAiB,GAAG;AACtB,UAAM,EAAE,QAAAA,QAAO,IAAI,MAAM,mBAAmB,EAAE,SAAS,OAAO,MAAM;AAAA,MAClE;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AACD,WAAOA;AAAA,EACT;AACA,QAAM,EAAE,OAAO,IAAI,MAAM,cAAc,OAAO,MAAM,EAAE,KAAK,SAAS,eAAe,CAAC;AACpF,SAAO,OAAO,SAAS;AACzB;AAEA,IAAM,eAAe;AAErB,eAAsB,eACpB,YACA,QACA,QACiB;AACjB,MAAI,WAAW,SAAS,IAAI,YAAY,GAAG,GAAG;AAC5C,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,KAAK,YAAY,cAAc,MAAM;AAE1D,MAAI,MAAM,oBAAoB,YAAY,GAAG;AAC3C,QAAI,QAAQ;AACV,UAAI,MAAM,sBAAsB,YAAY,GAAG;AAC7C,eAAO;AAAA,MACT;AACA,UAAI;AACF,cAAM,IAAI,cAAc,CAAC,YAAY,YAAY,UAAU,MAAM,EAAE,CAAC;AAAA,MACtE,QAAQ;AAAA,MAER;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,SAAS,UAAU,MAAM,KAAK;AAC1C,QAAM,IAAI,YAAY,CAAC,YAAY,OAAO,YAAY,cAAc,GAAG,CAAC;AAExE,SAAO;AACT;AAOA,eAAsB,qBAAqB,YAAoB,QAA+B;AAC5F,MAAI;AACF,UAAM,SAAS,MAAM,IAAI,YAAY,CAAC,YAAY,QAAQ,aAAa,CAAC;AACxE,UAAM,UAAU,OAAO,MAAM,MAAM;AACnC,eAAW,SAAS,SAAS;AAC3B,YAAM,QAAQ,MAAM,KAAK,EAAE,MAAM,IAAI;AACrC,YAAM,eAAe,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,WAAW,CAAC;AAChE,YAAM,aAAa,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,SAAS,CAAC;AAC5D,UAAI,CAAC,gBAAgB,eAAe,qBAAqB,MAAM,GAAI;AAEnE,YAAM,eAAe,aAAa,QAAQ,aAAa,EAAE;AACzD,UAAI,CAAC,aAAa,SAAS,IAAI,YAAY,GAAG,EAAG;AAEjD,UAAI;AACF,cAAM,IAAI,cAAc,CAAC,YAAY,UAAU,CAAC;AAAA,MAClD,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAMA,eAAsB,eAAe,YAAoB,QAA+B;AACtF,QAAM,eAAe,KAAK,YAAY,cAAc,MAAM;AAC1D,MAAI,CAAE,MAAM,oBAAoB,YAAY,EAAI;AAChD,MAAI;AACF,UAAM,IAAI,YAAY,CAAC,YAAY,UAAU,cAAc,SAAS,CAAC;AAAA,EACvE,QAAQ;AAAA,EAER;AACF;","names":["stdout"]}
@@ -4,7 +4,7 @@ import {
4
4
  parseLine,
5
5
  timingSafeTokenEqual,
6
6
  writeFrame
7
- } from "./chunk-IE7EOKMD.js";
7
+ } from "./chunk-VKZ5W2VO.js";
8
8
  export {
9
9
  DEFAULT_WORKBENCH_PORT,
10
10
  FrameReader,
@@ -12,4 +12,4 @@ export {
12
12
  timingSafeTokenEqual,
13
13
  writeFrame
14
14
  };
15
- //# sourceMappingURL=protocol-QJRHTTMQ.js.map
15
+ //# sourceMappingURL=protocol-IHRTO5C4.js.map
@@ -1,23 +1,18 @@
1
1
  import {
2
- buildSnapshotTar,
3
- extractSnapshotTar,
4
2
  loadPtySpawn,
5
3
  terminateProcessGroup
6
- } from "./chunk-2K6RRTQC.js";
4
+ } from "./chunk-RSIW2UCR.js";
7
5
  import {
8
6
  FrameReader,
9
7
  timingSafeTokenEqual,
10
8
  writeFrame
11
- } from "./chunk-IE7EOKMD.js";
9
+ } from "./chunk-VKZ5W2VO.js";
12
10
 
13
11
  // src/workbench/server.ts
14
12
  import { spawn } from "child_process";
15
- import { createReadStream, createWriteStream } from "fs";
16
- import { mkdtemp, readdir, readFile, rm, stat } from "fs/promises";
13
+ import { readdir, readFile, stat } from "fs/promises";
17
14
  import { createServer } from "net";
18
- import { tmpdir } from "os";
19
- import { join } from "path";
20
- var TAR_CHUNK_BYTES = 64 * 1024;
15
+ var READ_CHUNK_BYTES = 64 * 1024;
21
16
  function errCode(err) {
22
17
  return typeof err?.code === "string" ? err.code : void 0;
23
18
  }
@@ -90,12 +85,6 @@ function dispatch(socket, req, sink, opts) {
90
85
  case "pty":
91
86
  void runPty(socket, req, sink);
92
87
  return;
93
- case "snapshotBuild":
94
- void runSnapshotBuild(socket, req);
95
- return;
96
- case "snapshotExtract":
97
- void runSnapshotExtract(socket, req, sink);
98
- return;
99
88
  case "readFile":
100
89
  void runReadFile(socket, req);
101
90
  return;
@@ -203,67 +192,13 @@ async function runPty(socket, req, sink) {
203
192
  }
204
193
  });
205
194
  }
206
- async function runSnapshotBuild(socket, req) {
207
- try {
208
- const result = await buildSnapshotTar(req.cwd);
209
- try {
210
- writeFrame(socket, {
211
- t: "meta",
212
- sizeBytes: result.sizeBytes,
213
- fileCount: result.fileCount,
214
- deletionCount: result.deletionCount,
215
- capturedAt: result.capturedAt
216
- });
217
- await new Promise((resolve, reject) => {
218
- const stream = createReadStream(result.tarPath, { highWaterMark: TAR_CHUNK_BYTES });
219
- stream.on("data", (chunk) => {
220
- writeFrame(socket, { t: "data", d: Buffer.from(chunk).toString("base64") });
221
- });
222
- stream.on("end", () => resolve());
223
- stream.on("error", reject);
224
- socket.on("close", () => stream.destroy());
225
- });
226
- writeFrame(socket, { t: "end" });
227
- } finally {
228
- await result.cleanup();
229
- }
230
- } catch (err) {
231
- sendError(socket, err);
232
- }
233
- socket.end();
234
- }
235
- async function runSnapshotExtract(socket, req, sink) {
236
- const staging = await mkdtemp(join(tmpdir(), "conveyor-workbench-extract-"));
237
- const tarPath = join(staging, "snapshot.tar.gz");
238
- const out = createWriteStream(tarPath);
239
- try {
240
- await new Promise((resolve, reject) => {
241
- sink.setHandler((frame) => {
242
- if (frame.t === "data" && typeof frame.d === "string") {
243
- out.write(Buffer.from(frame.d, "base64"));
244
- } else if (frame.t === "end") {
245
- out.end(() => resolve());
246
- }
247
- });
248
- out.on("error", reject);
249
- socket.on("close", () => reject(new Error("connection closed before end frame")));
250
- });
251
- const value = await extractSnapshotTar(req.cwd, tarPath);
252
- writeFrame(socket, { t: "result", value });
253
- } catch (err) {
254
- sendError(socket, err);
255
- } finally {
256
- await rm(staging, { recursive: true, force: true }).catch(() => void 0);
257
- socket.end();
258
- }
259
- }
260
195
  async function runReadFile(socket, req) {
261
196
  try {
262
197
  const content = await readFile(req.path);
263
- for (let offset = 0; offset < content.length; offset += TAR_CHUNK_BYTES) {
198
+ for (let offset = 0; offset < content.length; offset += READ_CHUNK_BYTES) {
264
199
  writeFrame(socket, {
265
200
  t: "data",
266
- d: content.subarray(offset, offset + TAR_CHUNK_BYTES).toString("base64")
201
+ d: content.subarray(offset, offset + READ_CHUNK_BYTES).toString("base64")
267
202
  });
268
203
  }
269
204
  writeFrame(socket, { t: "end" });
@@ -310,4 +245,4 @@ async function runReaddir(socket, req) {
310
245
  export {
311
246
  startWorkbenchServer
312
247
  };
313
- //# sourceMappingURL=server-UGE67KIZ.js.map
248
+ //# sourceMappingURL=server-TVIXWCAI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/workbench/server.ts"],"sourcesContent":["/**\n * The workbench launcher — PID 1 of the workbench container in split-mode\n * pods (CONVEYOR_MODE=workbench). A token-authed, loopback-only exec daemon:\n * the agent container drives every workspace-touching operation through it\n * (shell commands, the claude PTY, git, file reads) while staying insulated\n * from workload OOMs in its own container cgroup.\n *\n * One connection = one operation. A dropped connection kills the operation's\n * process (group) — the agent dying, restarting, or timing out must never\n * leave orphans accumulating against the workbench memory budget.\n */\n\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { readdir, readFile, stat } from \"node:fs/promises\";\nimport { createServer, type Socket } from \"node:net\";\nimport { terminateProcessGroup } from \"../setup/commands.js\";\nimport { loadPtySpawn, type PtyProcess } from \"../harness/pty/pty-support.js\";\nimport {\n FrameReader,\n timingSafeTokenEqual,\n writeFrame,\n type WorkbenchFrame,\n type WorkbenchRequest,\n} from \"./protocol.js\";\n\nconst READ_CHUNK_BYTES = 64 * 1024;\n\nexport interface WorkbenchServerOptions {\n port: number;\n token: string;\n version: string;\n}\n\nexport interface WorkbenchServerHandle {\n port: number;\n close(): Promise<void>;\n}\n\nfunction errCode(err: unknown): string | undefined {\n return typeof (err as { code?: unknown })?.code === \"string\"\n ? (err as { code: string }).code\n : undefined;\n}\n\nfunction sendError(socket: Socket, err: unknown): void {\n const frame: WorkbenchFrame = {\n t: \"error\",\n message: err instanceof Error ? err.message : String(err),\n ...(errCode(err) ? { code: errCode(err) } : {}),\n };\n writeFrame(socket, frame);\n}\n\n/** Merge request env over the daemon's own (mirrors the local spawn paths,\n * which inherit process.env and let callers override). */\nfunction mergedEnv(overrides?: Record<string, string>): NodeJS.ProcessEnv {\n return overrides ? { ...process.env, ...overrides } : { ...process.env };\n}\n\n/**\n * Post-dispatch inbound frames for the connection's operation. Handlers\n * assign `onNext`; frames arriving before assignment are queued so an input\n * racing the (async) pty spawn is never dropped.\n */\nclass FrameSink {\n private pending: WorkbenchFrame[] = [];\n private handler: ((frame: WorkbenchFrame) => void) | null = null;\n\n push(frame: WorkbenchFrame): void {\n if (this.handler) this.handler(frame);\n else this.pending.push(frame);\n }\n\n setHandler(handler: (frame: WorkbenchFrame) => void): void {\n this.handler = handler;\n for (const frame of this.pending.splice(0)) handler(frame);\n }\n}\n\nexport async function startWorkbenchServer(\n opts: WorkbenchServerOptions,\n): Promise<WorkbenchServerHandle> {\n const server = createServer((socket) => handleConnection(socket, opts));\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(opts.port, \"127.0.0.1\", () => resolve());\n });\n const address = server.address();\n const port = typeof address === \"object\" && address ? address.port : opts.port;\n return {\n port,\n close: () =>\n new Promise<void>((resolve) => {\n server.close(() => resolve());\n }),\n };\n}\n\nfunction handleConnection(socket: Socket, opts: WorkbenchServerOptions): void {\n socket.on(\"error\", () => undefined);\n const sink = new FrameSink();\n let dispatched = false;\n const reader = new FrameReader((frame) => {\n if (dispatched) {\n sink.push(frame as unknown as WorkbenchFrame);\n return;\n }\n dispatched = true;\n dispatch(socket, frame as unknown as WorkbenchRequest, sink, opts);\n });\n socket.on(\"data\", (chunk: Buffer) => reader.push(chunk));\n}\n\nfunction dispatch(\n socket: Socket,\n req: WorkbenchRequest,\n sink: FrameSink,\n opts: WorkbenchServerOptions,\n): void {\n if (!req || typeof req !== \"object\" || !timingSafeTokenEqual(req.token ?? \"\", opts.token)) {\n writeFrame(socket, { t: \"error\", message: \"unauthorized\", code: \"unauthorized\" });\n socket.destroy();\n return;\n }\n switch (req.op) {\n case \"ping\":\n writeFrame(socket, { t: \"pong\", version: opts.version });\n socket.end();\n return;\n case \"exec\":\n runExec(socket, req, sink);\n return;\n case \"pty\":\n void runPty(socket, req, sink);\n return;\n case \"readFile\":\n void runReadFile(socket, req);\n return;\n case \"stat\":\n void runStat(socket, req);\n return;\n case \"readdir\":\n void runReaddir(socket, req);\n return;\n default:\n writeFrame(socket, { t: \"error\", message: \"unknown op\", code: \"bad_request\" });\n socket.end();\n }\n}\n\nfunction runExec(\n socket: Socket,\n req: Extract<WorkbenchRequest, { op: \"exec\" }>,\n sink: FrameSink,\n): void {\n let child: ChildProcess;\n try {\n // Argv form (git and friends) spawns directly with no shell; shell form\n // (setup/start commands) mirrors the local `spawn(\"sh\", [\"-c\", cmd])`.\n const [argvFile, ...argvRest] = req.argv ?? [];\n child = argvFile\n ? spawn(argvFile, argvRest, {\n cwd: req.cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: true,\n env: mergedEnv(req.env),\n })\n : spawn(\"sh\", [\"-c\", req.command ?? \"\"], {\n cwd: req.cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: true,\n env: mergedEnv(req.env),\n });\n } catch (err) {\n sendError(socket, err);\n socket.end();\n return;\n }\n\n let settled = false;\n sink.setHandler((frame) => {\n if (frame.t === \"signal\" && frame.mode === \"term-group\" && !settled) {\n void terminateProcessGroup(child);\n }\n });\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n writeFrame(socket, { t: \"out\", s: \"stdout\", d: chunk.toString(\"base64\") });\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n writeFrame(socket, { t: \"out\", s: \"stderr\", d: chunk.toString(\"base64\") });\n });\n child.on(\"close\", (code, signal) => {\n settled = true;\n writeFrame(socket, { t: \"exit\", code, signal });\n socket.end();\n });\n child.on(\"error\", (err) => {\n if (settled) return;\n settled = true;\n sendError(socket, err);\n socket.end();\n });\n // Agent gone (crash, timeout-abort, container death) → no orphans.\n socket.on(\"close\", () => {\n if (!settled) void terminateProcessGroup(child);\n });\n}\n\nasync function runPty(\n socket: Socket,\n req: Extract<WorkbenchRequest, { op: \"pty\" }>,\n sink: FrameSink,\n): Promise<void> {\n let pty: PtyProcess;\n try {\n const ptySpawn = await loadPtySpawn();\n pty = ptySpawn(req.file, req.args, {\n name: \"xterm-color\",\n cols: req.cols,\n rows: req.rows,\n cwd: req.cwd,\n env: req.env,\n });\n } catch (err) {\n sendError(socket, err);\n socket.end();\n return;\n }\n\n let exited = false;\n sink.setHandler((frame) => {\n try {\n if (frame.t === \"input\" && typeof frame.d === \"string\") {\n pty.write(Buffer.from(frame.d, \"base64\").toString(\"utf8\"));\n } else if (\n frame.t === \"resize\" &&\n typeof frame.cols === \"number\" &&\n typeof frame.rows === \"number\"\n ) {\n pty.resize(frame.cols, frame.rows);\n } else if (frame.t === \"kill\") {\n pty.kill(typeof frame.sig === \"string\" ? frame.sig : undefined);\n }\n } catch {\n /* pty already dead — exit handler owns teardown */\n }\n });\n pty.onData((data) => {\n writeFrame(socket, { t: \"data\", d: Buffer.from(data, \"utf8\").toString(\"base64\") });\n });\n pty.onExit((event) => {\n exited = true;\n writeFrame(socket, { t: \"exit\", code: event.exitCode, signal: null });\n socket.end();\n });\n socket.on(\"close\", () => {\n if (!exited) {\n try {\n pty.kill();\n } catch {\n /* already dead */\n }\n }\n });\n}\n\nasync function runReadFile(\n socket: Socket,\n req: Extract<WorkbenchRequest, { op: \"readFile\" }>,\n): Promise<void> {\n try {\n const content = await readFile(req.path);\n for (let offset = 0; offset < content.length; offset += READ_CHUNK_BYTES) {\n writeFrame(socket, {\n t: \"data\",\n d: content.subarray(offset, offset + READ_CHUNK_BYTES).toString(\"base64\"),\n });\n }\n writeFrame(socket, { t: \"end\" });\n } catch (err) {\n sendError(socket, err);\n }\n socket.end();\n}\n\nasync function runStat(\n socket: Socket,\n req: Extract<WorkbenchRequest, { op: \"stat\" }>,\n): Promise<void> {\n try {\n const s = await stat(req.path);\n writeFrame(socket, {\n t: \"stat\",\n exists: true,\n isFile: s.isFile(),\n isDirectory: s.isDirectory(),\n size: s.size,\n mtimeMs: s.mtimeMs,\n });\n } catch (err) {\n if (errCode(err) === \"ENOENT\") {\n writeFrame(socket, {\n t: \"stat\",\n exists: false,\n isFile: false,\n isDirectory: false,\n size: 0,\n mtimeMs: 0,\n });\n } else {\n sendError(socket, err);\n }\n }\n socket.end();\n}\n\nasync function runReaddir(\n socket: Socket,\n req: Extract<WorkbenchRequest, { op: \"readdir\" }>,\n): Promise<void> {\n try {\n writeFrame(socket, { t: \"entries\", names: await readdir(req.path) });\n } catch (err) {\n sendError(socket, err);\n }\n socket.end();\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-agent",
3
- "version": "10.13.13",
3
+ "version": "10.13.15",
4
4
  "description": "Conveyor Agent Runner v10 - PTY harness for the task chat (SDK harness for audit/project-chat). Agent-as-User architecture with BaseService patterns. Works locally too.",
5
5
  "keywords": [
6
6
  "agent",