@rallycry/conveyor-agent 10.13.71 → 11.0.0

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/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 } from '@project/shared';
2
+ import { RunnerMode, AgentSessionServiceMethods, AgentMode, PtyChatEventPayload, WorkspaceDiscoveredPort, AgentQuestion, PackExecution, AgentRunnerStatus } from '@project/shared';
3
3
  export * from '@project/shared';
4
4
  import { ChildProcess } from 'node:child_process';
5
5
 
@@ -56,6 +56,31 @@ interface SpawnReviewData {
56
56
  prNumber?: number | null;
57
57
  checkoutRef?: string | null;
58
58
  }
59
+ /**
60
+ * Server push asking a PLANNER pod to spawn the Builder child: a second
61
+ * conveyor-agent process bound to a fresh `mode:"build"` WorkspaceSession. The
62
+ * lifecycle handoff — a human pressing Build, or a Yolomatic plan landing —
63
+ * without cold-booting a second pod, and without flipping the planner's own
64
+ * session into a builder in place.
65
+ *
66
+ * Same wire discipline as SpawnReviewData: no taskId (the child inherits the
67
+ * parent's CONVEYOR_TASK_ID and the server derives it from the JWT), and the
68
+ * runner mode rides the JWT claim rather than this field — `mode` here is what
69
+ * the supervisor exports as CONVEYOR_MODE for the child process.
70
+ */
71
+ interface SpawnBuilderData {
72
+ sessionId: string;
73
+ sessionJwt: string;
74
+ /**
75
+ * Runner mode for the child — `pack` when the card has children, so the
76
+ * coordinator gets the single-pod pack prompt and toolset. Optional so a pod
77
+ * running against an older server (which sends none) still boots as `task`.
78
+ */
79
+ mode?: "task" | "pack";
80
+ branch?: string | null;
81
+ /** The agent whose model/settings/instructions the Builder runs under. */
82
+ agentName?: string | null;
83
+ }
59
84
  /**
60
85
  * Server push asking the builder pod to spawn an extra interactive child on
61
86
  * this pod: a second Claude TUI (mode "adhoc") or a raw login shell (mode
@@ -98,6 +123,8 @@ declare class AgentConnection {
98
123
  private earlyPullBranches;
99
124
  private spawnReviewCallback;
100
125
  private earlySpawnReviews;
126
+ private spawnBuilderCallback;
127
+ private earlySpawnBuilders;
101
128
  private spawnTuiCallback;
102
129
  private earlySpawnTuis;
103
130
  private probeUsageCallback;
@@ -168,6 +195,9 @@ declare class AgentConnection {
168
195
  branch: string;
169
196
  }) => void): void;
170
197
  onSpawnReview(callback: (data: SpawnReviewData) => void): void;
198
+ /** Mirror of onSpawnReview for the Builder handoff. Drains the early buffer
199
+ * so a Build pressed during boot is not lost. */
200
+ onSpawnBuilder(callback: (data: SpawnBuilderData) => void): void;
171
201
  /**
172
202
  * Report that a same-pod review child failed to spawn (fire-and-forget).
173
203
  * The server Ends the orphaned review session and falls back to a dedicated
@@ -175,6 +205,15 @@ declare class AgentConnection {
175
205
  * it; the review session is identified separately.
176
206
  */
177
207
  reportReviewSpawnFailure(reviewSessionId: string, error?: string): void;
208
+ /**
209
+ * Report that this (planner) pod could not spawn the Builder child, so the
210
+ * server can End the orphaned build session and reopen the card instead of
211
+ * leaving it InProgress with a Builder tab that never appears.
212
+ *
213
+ * sessionId is OUR (planner) session — the task-identity guard runs on it;
214
+ * the build session is identified separately.
215
+ */
216
+ reportBuilderSpawnFailure(buildSessionId: string, error?: string): void;
178
217
  /**
179
218
  * Report that this pod's git credential is dead and refreshing did not fix
180
219
  * it (fire-and-forget).
@@ -412,14 +451,66 @@ declare class ModeController {
412
451
  private _pendingModeRestart;
413
452
  private _runnerMode;
414
453
  private _isAuto;
454
+ /**
455
+ * Which planner this is. Only read when `_runnerMode` is `plan`; see
456
+ * `effectiveMode` for the full reasoning, and `latchPlanFlavor` for why this
457
+ * latches toward `chat` and never away from it.
458
+ */
459
+ private _planFlavor;
415
460
  constructor(initialMode: AgentMode, runnerMode?: RunnerMode, isAuto?: boolean);
461
+ /**
462
+ * Promote this planner to the chat flavor, once, and never demote it.
463
+ *
464
+ * It cannot be a constructor-only assignment, because the constructor usually
465
+ * has nothing to go on. A GKE pod's bootstrap bundle carries no agentMode, so
466
+ * `CONVEYOR_AGENT_MODE` is unset and `initialMode` falls back to `"building"`
467
+ * for EVERY pod — which is the whole reason `applyServerMode` exists. Pinning
468
+ * the flavor at construction alone would therefore make every chat card in the
469
+ * cloud a discovery planner and silently re-open the defect this replaced.
470
+ *
471
+ * One-way, and both directions matter:
472
+ *
473
+ * - Only the literal card mode `chat` promotes. The server reports `chat` only
474
+ * for a card whose agentMode IS `chat`, so a discovery card can never be
475
+ * talked into the build-capable flavor. The original hazard — `auto` stamped
476
+ * onto a plan-less auto card's planner — is untouched, because `auto` is not
477
+ * `chat`.
478
+ * - Nothing demotes. The Build press overwrites `Task.agentMode` to
479
+ * `auto`/`building` before the server sees it, so a later stamp would
480
+ * otherwise strip a live conversation's prompt and file deliverables
481
+ * mid-turn.
482
+ *
483
+ * The asymmetry with `auto` is principled rather than convenient: an auto
484
+ * card's mode and its planner phase legitimately differ, while a chat card's
485
+ * mode IS what its session is, for the session's whole life.
486
+ */
487
+ private latchPlanFlavor;
416
488
  get mode(): AgentMode;
417
489
  get isAuto(): boolean;
418
490
  get hasExitedPlanMode(): boolean;
419
491
  set hasExitedPlanMode(val: boolean);
420
492
  get pendingModeRestart(): boolean;
421
493
  set pendingModeRestart(val: boolean);
422
- /** Effective mode accounting for PM/task defaults */
494
+ /**
495
+ * Effective mode accounting for PM/task defaults.
496
+ *
497
+ * A `plan` runner is pinned to ONE mode for its whole life, whatever the
498
+ * card's own agentMode later says. That pin is what makes the planner
499
+ * read-only, non-build-capable, and prompted for planning — all three derive
500
+ * from here — and it has to be immune to `applyServerMode`, which runs AFTER
501
+ * boot and would otherwise stamp `auto` onto the planner of a plan-less auto
502
+ * card, handing it the build prompt and `--dangerously-skip-permissions`
503
+ * inside a session whose whole purpose is not to have them.
504
+ *
505
+ * There are TWO planner flavors, and which one this session is was decided at
506
+ * boot (`_planFlavor`) — never re-read from the mutable `_mode`. A chat card
507
+ * boots a plan session too (it is a Planner-session flavor, not a builder in
508
+ * disguise), and it must keep `buildChatPrompt`, its file deliverables, and
509
+ * the build-capable tool handler. Reading the flavor from `_mode` would put
510
+ * that choice back under server control and re-open the exact hole the
511
+ * paragraph above closes, in the other direction: a stamp of `chat` onto a
512
+ * discovery planner would hand it build capability.
513
+ */
423
514
  get effectiveMode(): AgentMode;
424
515
  get isReadOnly(): boolean;
425
516
  get isAutoPlanning(): boolean;
@@ -507,7 +598,13 @@ declare class Lifecycle {
507
598
  stopGitFlush(): void;
508
599
  startUsageSample(): void;
509
600
  stopUsageSample(): void;
510
- startIdleTimer(): void;
601
+ /** Start (or restart) the idle timer.
602
+ * @param overrideMs Optional custom delay in ms, mirroring
603
+ * `startDormantTimer`. SessionRunner passes a short delay when it DEFERS a
604
+ * shutdown because a spawned child is still working: the pod must re-check
605
+ * soon after that child exits, rather than granting itself a fresh full idle
606
+ * window every time it defers. */
607
+ startIdleTimer(overrideMs?: number): void;
511
608
  cancelIdleTimer(): void;
512
609
  /** Start (or restart) the dormant timer.
513
610
  * @param overrideMs Optional custom delay in ms. When provided, the timer
@@ -522,10 +619,43 @@ declare class Lifecycle {
522
619
  private clearIdleTimers;
523
620
  }
524
621
 
622
+ /**
623
+ * Who else is working on this pod?
624
+ *
625
+ * The Planner is the pod's MAIN process, so its idle/dormant timeouts end the
626
+ * whole pod: `stopped = true` → `shutdown("finished")` → `process.exit(0)` →
627
+ * the supervisor logs "agent exited cleanly, shutting down pod". Nothing used
628
+ * to ask whether a spawned child was still working. A handed-off build that
629
+ * outlived the Planner's idle window therefore died mid-run — the work survived
630
+ * only as far as the last `conveyor-wip` flush, the janitor parked the
631
+ * workspace, and the card reverted to Open.
632
+ *
633
+ * This is the seam that lets `SessionRunner` ask without importing the
634
+ * supervisors: `cli.ts` owns them and hands the runner a probe. Keeping the
635
+ * dependency pointing that way also keeps the runner testable with a fake.
636
+ *
637
+ * Ordering is deliberate — `builder` first — so the deferral log names the
638
+ * session a human is most likely looking for when they ask why a pod is still
639
+ * up.
640
+ */
641
+ /** A child supervisor, reduced to the one question the shutdown path asks. */
642
+ interface ChildSessionSource {
643
+ /**
644
+ * Names the child kind in the deferral log. `tui` rather than `session` —
645
+ * these come from `session:spawnTui`, but "session session <id>" stutters in
646
+ * the one place this string is read.
647
+ */
648
+ readonly kind: "builder" | "review" | "tui";
649
+ /** Sessions this supervisor currently hosts. Empty when it hosts none. */
650
+ activeSessionIds(): string[];
651
+ }
652
+
525
653
  interface SessionRunnerConfig {
526
654
  connection: AgentConnectionConfig;
527
655
  agentMode?: AgentMode;
528
656
  runnerMode?: RunnerMode;
657
+ /** Only read when `runnerMode` is "pack". Defaults to single-pod. */
658
+ packExecution?: PackExecution;
529
659
  isAuto?: boolean;
530
660
  workspaceDir: string;
531
661
  model?: string;
@@ -601,6 +731,33 @@ declare class SessionRunner {
601
731
  private agentLiveReported;
602
732
  constructor(config: SessionRunnerConfig, callbacks: SessionRunnerCallbacks, deps?: SessionRunnerDependencies);
603
733
  get state(): AgentRunnerStatus;
734
+ /**
735
+ * Supervisors whose live children keep this pod alive. Empty until `cli.ts`
736
+ * wires them, which is deliberate: the supervisors are constructed AFTER the
737
+ * runner, and an empty list simply means "no children to protect" — the
738
+ * pre-existing shutdown behavior.
739
+ */
740
+ private liveChildSources;
741
+ /** Called by `cli.ts` once the child supervisors exist. */
742
+ setLiveChildSources(sources: readonly ChildSessionSource[]): void;
743
+ /**
744
+ * Suppress an idle/dormant shutdown while a spawned child is still working.
745
+ *
746
+ * The Planner is the pod's main process, so its timeouts take the pod — and
747
+ * the Builder's in-flight work — down with it. Returns true when the shutdown
748
+ * was deferred and the caller must not proceed.
749
+ *
750
+ * Re-arms with a SHORT delay rather than a fresh full window: the pod should
751
+ * converge on shutdown soon after the last child exits, not one more idle
752
+ * window later. Bounded by the configured timeout so a test with a 50ms idle
753
+ * window re-checks in 50ms rather than a minute.
754
+ *
755
+ * Fail-open by construction — if the probe throws, or no sources are wired,
756
+ * the shutdown proceeds exactly as before. The opposite bias (a pod that
757
+ * cannot die) is the more expensive mistake here only in money; killing a
758
+ * live build costs work.
759
+ */
760
+ private deferShutdownForLiveChild;
604
761
  get sessionId(): string;
605
762
  get isStopped(): boolean;
606
763
  /** Wire the boot supervisor handle post-construction — cli.ts constructs it
@@ -815,6 +972,16 @@ interface AgentRunnerConfig {
815
972
  mode?: _project_shared.RunnerMode;
816
973
  isAuto?: boolean;
817
974
  agentSettings?: _project_shared.AgentSettings;
975
+ /**
976
+ * How a `mode: "pack"` session executes its children.
977
+ *
978
+ * "single-pod" (the default): this session implements every child itself,
979
+ * serially. "fan-out": the legacy coordinator — it fires one pod per child
980
+ * and writes no code. Carried as a sub-flag rather than a new `RunnerMode`
981
+ * so `resolveModeEnv`, the JWT mode claim, and every `mode === "pack"`
982
+ * reader keep working unchanged.
983
+ */
984
+ packExecution?: _project_shared.PackExecution;
818
985
  }
819
986
  interface AgentRunnerCallbacks {
820
987
  onEvent: (event: Record<string, unknown>) => void | Promise<void>;
package/dist/index.js CHANGED
@@ -1,7 +1,11 @@
1
+ import {
2
+ SessionRunner,
3
+ unshallowRepo
4
+ } from "./chunk-PEEGCZAR.js";
5
+ import "./chunk-XORJ6SII.js";
1
6
  import {
2
7
  AgentConnection,
3
8
  GIT_TIMEOUT_MS,
4
- SessionRunner,
5
9
  flushPendingChanges,
6
10
  getCurrentBranch,
7
11
  hasUncommittedChanges,
@@ -10,11 +14,10 @@ import {
10
14
  loadForwardPorts,
11
15
  pushToOrigin,
12
16
  stageAndCommit,
13
- unshallowRepo,
14
17
  updateRemoteToken,
15
18
  workspacePathExists
16
- } from "./chunk-7MMECTTJ.js";
17
- import "./chunk-QU53HND5.js";
19
+ } from "./chunk-N4WSUTGV.js";
20
+ import "./chunk-GL2DIQEQ.js";
18
21
  import "./chunk-IA45XHOA.js";
19
22
  import {
20
23
  getWorkbenchClient
@@ -22,11 +25,12 @@ import {
22
25
  import {
23
26
  workbenchEnabled
24
27
  } from "./chunk-KMB3BU4S.js";
28
+ import "./chunk-3F4ZZKCA.js";
25
29
  import {
26
30
  runAuthTokenCommand,
27
31
  runSetupCommand,
28
32
  runStartCommand
29
- } from "./chunk-GJXAAPJ6.js";
33
+ } from "./chunk-W4LZ7R6Z.js";
30
34
  import "./chunk-6Q6LQBWO.js";
31
35
 
32
36
  // src/runner/worktree.ts
@@ -0,0 +1,225 @@
1
+ import {
2
+ WorkspaceCommandSupervisor
3
+ } from "./chunk-JQVAWRVL.js";
4
+ import {
5
+ AgentConnection,
6
+ CodespacePortVisibility,
7
+ DEFAULT_LIFECYCLE_CONFIG,
8
+ Lifecycle,
9
+ PortDiscovery,
10
+ awaitGitReady,
11
+ createServiceLogger,
12
+ ensureOnTaskBranch,
13
+ loadConveyorConfig
14
+ } from "./chunk-N4WSUTGV.js";
15
+ import "./chunk-GL2DIQEQ.js";
16
+ import "./chunk-IA45XHOA.js";
17
+ import "./chunk-EXQ6AHOY.js";
18
+ import "./chunk-KMB3BU4S.js";
19
+ import "./chunk-W4LZ7R6Z.js";
20
+ import "./chunk-6Q6LQBWO.js";
21
+
22
+ // src/runner/serve-session-runner.ts
23
+ var ServeSessionRunner = class {
24
+ connection;
25
+ lifecycle;
26
+ config;
27
+ callbacks;
28
+ portDiscovery;
29
+ commandSupervisor;
30
+ git;
31
+ stopped = false;
32
+ stopResolver = null;
33
+ _finalState = null;
34
+ constructor(config, callbacks = {}, deps) {
35
+ this.config = config;
36
+ this.callbacks = callbacks;
37
+ this.connection = deps?.connection ?? new AgentConnection(config.connection);
38
+ const portVisibility = new CodespacePortVisibility();
39
+ this.portDiscovery = deps?.portDiscovery ?? new PortDiscovery({
40
+ report: (ports) => this.connection.reportDiscoveredPorts(ports),
41
+ onReported: (ports) => portVisibility.ensureVisible(ports.map(({ port }) => port))
42
+ });
43
+ this.commandSupervisor = deps?.commandSupervisor ?? new WorkspaceCommandSupervisor({
44
+ config: loadConveyorConfig(),
45
+ workspaceDir: config.workspaceDir,
46
+ connection: this.connection
47
+ });
48
+ this.git = deps?.git ?? {
49
+ awaitGitReady: (opts) => awaitGitReady(opts),
50
+ checkoutBranch: (cwd, branch) => ensureOnTaskBranch(cwd, branch)
51
+ };
52
+ this.lifecycle = new Lifecycle(
53
+ // No git flush and no usage sample: nothing here writes to the checkout,
54
+ // and the serving bundle selects no coding-agent key to measure.
55
+ {
56
+ ...DEFAULT_LIFECYCLE_CONFIG,
57
+ gitFlushIntervalMs: 0,
58
+ usageSampleIntervalMs: 0,
59
+ ...config.lifecycle
60
+ },
61
+ {
62
+ onHeartbeat: () => this.connection.sendHeartbeat(),
63
+ // Never armed (see the file header) — supplied because Lifecycle
64
+ // requires the full callback set.
65
+ onIdleTimeout: () => this.requestStop(),
66
+ onDormantTimeout: () => this.requestStop(),
67
+ onTokenRefresh: () => void this.connection.refreshTaskTokenFromBootstrap().catch(() => {
68
+ }),
69
+ onGitFlush: () => {
70
+ },
71
+ onUsageSample: () => {
72
+ }
73
+ }
74
+ );
75
+ }
76
+ get finalState() {
77
+ return this._finalState;
78
+ }
79
+ get isStopped() {
80
+ return this.stopped;
81
+ }
82
+ /** Connect, register the session, launch the start command, then hold open. */
83
+ async run() {
84
+ try {
85
+ await this.connection.connect();
86
+ this.connection.sendEvent({
87
+ type: "connected",
88
+ sessionId: this.config.connection.sessionId
89
+ });
90
+ this.connection.onStop(() => this.requestStop());
91
+ this.lifecycle.startHeartbeat();
92
+ this.lifecycle.startTokenRefresh();
93
+ await this.connection.call("connectAgent", {
94
+ sessionId: this.config.connection.sessionId
95
+ });
96
+ await this.portDiscovery.start().catch(() => {
97
+ });
98
+ if (this.stopped) {
99
+ this._finalState = "finished";
100
+ return;
101
+ }
102
+ const gitState = await this.git.awaitGitReady({
103
+ onLog: (m) => process.stderr.write(`[conveyor-agent] ${m}
104
+ `)
105
+ });
106
+ if (this.stopped) {
107
+ this._finalState = "finished";
108
+ return;
109
+ }
110
+ if (gitState === "failed" || gitState === "timeout") {
111
+ throw new Error(
112
+ gitState === "failed" ? "Workspace git preparation failed (see pod logs)" : "Workspace git preparation timed out (see pod logs)"
113
+ );
114
+ }
115
+ const onBranch = await this.git.checkoutBranch(this.config.workspaceDir, this.config.branch);
116
+ if (this.stopped) {
117
+ this._finalState = "finished";
118
+ return;
119
+ }
120
+ if (!onBranch) {
121
+ throw new Error(
122
+ `Task-branch checkout failed for "${this.config.branch}"; refusing to serve base-branch code`
123
+ );
124
+ }
125
+ this.commandSupervisor.start();
126
+ this.commandSupervisor.notifyLoopReady?.();
127
+ await this.connection.emitStatus("idle");
128
+ this.callbacks.onEvent?.({ type: "serve_runner_started", taskId: this.config.taskId });
129
+ await this.waitUntilStopped();
130
+ this._finalState = "finished";
131
+ } catch (error) {
132
+ const message = error instanceof Error ? error.message : String(error);
133
+ process.stderr.write(`[conveyor-agent] Serve runner failed: ${message}
134
+ `);
135
+ this.connection.sendEvent({ type: "error", message });
136
+ this._finalState = "error";
137
+ } finally {
138
+ await this.shutdown();
139
+ }
140
+ }
141
+ /** External stop (SIGTERM/SIGINT or server session:stop). */
142
+ stop() {
143
+ this.requestStop();
144
+ }
145
+ requestStop() {
146
+ if (this.stopped) return;
147
+ this.stopped = true;
148
+ this.portDiscovery.stop();
149
+ if (this.stopResolver) {
150
+ const resolve = this.stopResolver;
151
+ this.stopResolver = null;
152
+ resolve();
153
+ }
154
+ }
155
+ waitUntilStopped() {
156
+ if (this.stopped) return Promise.resolve();
157
+ return new Promise((resolve) => {
158
+ this.stopResolver = resolve;
159
+ });
160
+ }
161
+ async shutdown() {
162
+ this.stopped = true;
163
+ this.portDiscovery.stop();
164
+ this.lifecycle.destroy();
165
+ await this.commandSupervisor.stop().catch(() => {
166
+ });
167
+ this.connection.sendEvent({ type: "shutdown", reason: this._finalState ?? "finished" });
168
+ this.connection.disconnect();
169
+ }
170
+ };
171
+
172
+ // src/runner/serve-boot.ts
173
+ var logger = createServiceLogger("ServeBoot");
174
+ function outcomeFor(runner) {
175
+ const errored = runner.finalState === "error";
176
+ return {
177
+ exitCode: errored ? 1 : 0,
178
+ reason: errored ? "error" : "clean",
179
+ finalState: runner.finalState ?? void 0
180
+ };
181
+ }
182
+ async function runServingSession(params) {
183
+ if (!params.sessionId) {
184
+ logger.error("Serving mode requires CONVEYOR_SESSION_ID");
185
+ return { exitCode: 1, reason: "error", finalState: "error" };
186
+ }
187
+ if (!params.branch) {
188
+ logger.error("Serving mode requires BRANCH (the card's branch to serve)");
189
+ return { exitCode: 1, reason: "error", finalState: "error" };
190
+ }
191
+ logger.info("Starting preview-only serving runner", {
192
+ taskId: params.taskId,
193
+ sessionId: params.sessionId,
194
+ branch: params.branch
195
+ });
196
+ const runner = new ServeSessionRunner(
197
+ {
198
+ connection: {
199
+ apiUrl: params.apiUrl,
200
+ taskToken: params.taskToken,
201
+ sessionId: params.sessionId,
202
+ runnerMode: "serving"
203
+ },
204
+ taskId: params.taskId,
205
+ workspaceDir: params.workspaceDir,
206
+ branch: params.branch
207
+ },
208
+ {
209
+ onEvent: (event) => {
210
+ logger.info("Serve runner event", { eventType: event.type });
211
+ }
212
+ }
213
+ );
214
+ const stop = () => {
215
+ params.onSignal?.();
216
+ runner.stop();
217
+ };
218
+ process.on("SIGTERM", stop);
219
+ process.on("SIGINT", stop);
220
+ await runner.run();
221
+ return outcomeFor(runner);
222
+ }
223
+ export {
224
+ runServingSession
225
+ };
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  startWorkbenchServer
3
- } from "./chunk-DOB2XE2I.js";
4
- import "./chunk-GJXAAPJ6.js";
3
+ } from "./chunk-UBDSLM44.js";
4
+ import "./chunk-3F4ZZKCA.js";
5
+ import "./chunk-W4LZ7R6Z.js";
5
6
  import "./chunk-6Q6LQBWO.js";
6
7
  import "./chunk-6W6UZ4SJ.js";
7
8
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-agent",
3
- "version": "10.13.71",
3
+ "version": "11.0.0",
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",
@@ -15,7 +15,8 @@
15
15
  },
16
16
  "files": [
17
17
  "dist",
18
- "runtime"
18
+ "runtime",
19
+ "skills"
19
20
  ],
20
21
  "type": "module",
21
22
  "main": "./dist/index.js",
@@ -36,8 +37,8 @@
36
37
  "typecheck": "tsgo --noEmit"
37
38
  },
38
39
  "dependencies": {
39
- "@anthropic-ai/claude-agent-sdk": "^0.3.219",
40
- "@modelcontextprotocol/sdk": "^1.12.1",
40
+ "@anthropic-ai/claude-agent-sdk": "^0.3.246",
41
+ "@modelcontextprotocol/sdk": "^1.30.0",
41
42
  "node-pty": "^1.0.0",
42
43
  "socket.io-client": "^4.8.3",
43
44
  "tar": "^7.5.21",