@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.
- package/dist/{chunk-YRC57EYG.js → chunk-LZM5OKAC.js} +2 -68
- package/dist/chunk-LZM5OKAC.js.map +1 -0
- package/dist/{chunk-2K6RRTQC.js → chunk-RSIW2UCR.js} +4 -180
- package/dist/chunk-RSIW2UCR.js.map +1 -0
- package/dist/{chunk-TB5SQIGX.js → chunk-SAHOFQBQ.js} +216 -457
- package/dist/chunk-SAHOFQBQ.js.map +1 -0
- package/dist/{chunk-IE7EOKMD.js → chunk-VKZ5W2VO.js} +1 -1
- package/dist/chunk-VKZ5W2VO.js.map +1 -0
- package/dist/cli.js +35 -75
- package/dist/cli.js.map +1 -1
- package/dist/{client-ICIWKSK2.js → client-VQIBGPE6.js} +3 -3
- package/dist/index.d.ts +27 -77
- package/dist/index.js +5 -17
- package/dist/index.js.map +1 -1
- package/dist/{protocol-QJRHTTMQ.js → protocol-IHRTO5C4.js} +2 -2
- package/dist/{server-UGE67KIZ.js → server-TVIXWCAI.js} +7 -72
- package/dist/server-TVIXWCAI.js.map +1 -0
- package/package.json +1 -1
- package/runtime/entrypoint.sh +34 -98
- package/dist/chunk-2K6RRTQC.js.map +0 -1
- package/dist/chunk-IE7EOKMD.js.map +0 -1
- package/dist/chunk-TB5SQIGX.js.map +0 -1
- package/dist/chunk-YRC57EYG.js.map +0 -1
- package/dist/server-UGE67KIZ.js.map +0 -1
- /package/dist/{client-ICIWKSK2.js.map → client-VQIBGPE6.js.map} +0 -0
- /package/dist/{protocol-QJRHTTMQ.js.map → protocol-IHRTO5C4.js.map} +0 -0
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
WorkbenchError,
|
|
5
5
|
getWorkbenchClient,
|
|
6
6
|
resetWorkbenchClient
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-LZM5OKAC.js";
|
|
8
8
|
import "./chunk-4VUQ2NPF.js";
|
|
9
|
-
import "./chunk-
|
|
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-
|
|
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
|
|
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
|
|
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-
|
|
16
|
+
} from "./chunk-SAHOFQBQ.js";
|
|
23
17
|
import "./chunk-7TQO4ZF4.js";
|
|
24
18
|
import {
|
|
25
19
|
getWorkbenchClient
|
|
26
|
-
} from "./chunk-
|
|
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-
|
|
35
|
-
import "./chunk-
|
|
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":"
|
|
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-
|
|
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-
|
|
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-
|
|
4
|
+
} from "./chunk-RSIW2UCR.js";
|
|
7
5
|
import {
|
|
8
6
|
FrameReader,
|
|
9
7
|
timingSafeTokenEqual,
|
|
10
8
|
writeFrame
|
|
11
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-VKZ5W2VO.js";
|
|
12
10
|
|
|
13
11
|
// src/workbench/server.ts
|
|
14
12
|
import { spawn } from "child_process";
|
|
15
|
-
import {
|
|
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
|
-
|
|
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 +=
|
|
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 +
|
|
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-
|
|
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.
|
|
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",
|