@cargo-ai/cli 1.0.125 → 1.0.126

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.
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../../src/commands/ask/harness/create.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AAIxC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAwB3C,OAAO,EAEL,KAAK,kBAAkB,EAKxB,MAAM,WAAW,CAAC;AAGnB,MAAM,MAAM,YAAY,GAAG;IACzB,YAAY,EAAE,CACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,kBAAkB,KACzB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAC5C,sEAAsE;IACtE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAcF,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,GAAG,EAAE,GAAG,CAAC;IACT;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,uBAAuB,EAAE,OAAO,CAAC;CAClC,GAAG,OAAO,CAAC,YAAY,CAAC,CAgVxB"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../../src/commands/ask/harness/create.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AAIxC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAwB3C,OAAO,EAEL,KAAK,kBAAkB,EAKxB,MAAM,WAAW,CAAC;AAGnB,MAAM,MAAM,YAAY,GAAG;IACzB,YAAY,EAAE,CACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,kBAAkB,KACzB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAC5C,sEAAsE;IACtE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAcF,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,GAAG,EAAE,GAAG,CAAC;IACT;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,uBAAuB,EAAE,OAAO,CAAC;CAClC,GAAG,OAAO,CAAC,YAAY,CAAC,CAiVxB"}
@@ -64,7 +64,8 @@ export async function createLocalHarness(input) {
64
64
  // createClaudeCode auto-detect AI Gateway from the host process and ignore
65
65
  // the Cargo proxy.
66
66
  // Wrapped so a batched tool call stays known to the stream that is asked to
67
- // approve it (see `toolCallReplay.ts`).
67
+ // approve it, and a second approval asked at the same time reaches the next
68
+ // stream instead of one nobody reads (see `toolCallReplay.ts`).
68
69
  const claudeCode = withToolCallReplay(createClaudeCode({
69
70
  auth: {
70
71
  ANTHROPIC_BASE_URL: anthropicBaseUrl,
@@ -4,7 +4,7 @@ export { createLocalHarness, type LocalHarness } from "./create.js";
4
4
  export { localHarnessInstructions, localHarnessSkills, } from "./instructions.js";
5
5
  export { resolveWorkspaceLayout } from "./layout.js";
6
6
  export { CARGO_MCP_SERVER_NAME } from "./mcp.js";
7
- export { replayKnownToolCalls, withToolCallReplay, wrapSession, } from "./toolCallReplay.js";
7
+ export { replayKnownToolCalls, routeSessionEvents, withToolCallReplay, wrapSession, } from "./toolCallReplay.js";
8
8
  export { HarnessTurnStalled, HarnessTurnStuck, isBridgeClosedError, type LocalStreamHandlers, type LocalStreamOptions, type LocalToolActivity, type LocalToolApproval, runPromptTurn, settleWithin, type StreamLike, type TurnDriver, } from "./turn.js";
9
9
  export { createTurnAccumulator, type LocalTurnAccumulator, type LocalTurnUsage, readClaudeCodeCostUsd, } from "./usage.js";
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/ask/harness/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EACL,+BAA+B,EAC/B,sCAAsC,EACtC,2BAA2B,EAC3B,4BAA4B,EAC5B,yBAAyB,EACzB,4BAA4B,EAC5B,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EACL,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,aAAa,EACb,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/ask/harness/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EACL,+BAA+B,EAC/B,sCAAsC,EACtC,2BAA2B,EAC3B,4BAA4B,EAC5B,yBAAyB,EACzB,4BAA4B,EAC5B,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EACL,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,aAAa,EACb,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
@@ -4,6 +4,6 @@ export { createLocalHarness } from "./create.js";
4
4
  export { localHarnessInstructions, localHarnessSkills, } from "./instructions.js";
5
5
  export { resolveWorkspaceLayout } from "./layout.js";
6
6
  export { CARGO_MCP_SERVER_NAME } from "./mcp.js";
7
- export { replayKnownToolCalls, withToolCallReplay, wrapSession, } from "./toolCallReplay.js";
7
+ export { replayKnownToolCalls, routeSessionEvents, withToolCallReplay, wrapSession, } from "./toolCallReplay.js";
8
8
  export { HarnessTurnStalled, HarnessTurnStuck, isBridgeClosedError, runPromptTurn, settleWithin, } from "./turn.js";
9
9
  export { createTurnAccumulator, readClaudeCodeCostUsd, } from "./usage.js";
@@ -15,11 +15,42 @@
15
15
  * own `emit`, so the session remembers every tool call and replays one into a
16
16
  * stream that is about to receive an approval for a call it never saw. Remove
17
17
  * this once the agent keeps tool calls for the session.
18
+ *
19
+ * The same batch also loses events outright, which is the stall
20
+ * `HarnessTurnStalled` reports. The agent stops reading a stream at the first
21
+ * approval request in it, but the adapter keeps that stream's listener on the
22
+ * bridge until the turn's `finish`, so whatever the bridge says next goes into
23
+ * a stream nobody reads. When Claude Code asks about two tools at once, the
24
+ * second request lands there: the next stream never hears of it, Claude Code
25
+ * waits for an answer, and the turn waits for output. `routeSessionEvents`
26
+ * holds those events and hands them to the next stream instead.
18
27
  */
19
28
  import type { HarnessV1, HarnessV1Session, HarnessV1StreamPart } from "@ai-sdk/harness";
20
29
  type Emit = (event: HarnessV1StreamPart) => void;
21
30
  /** Exported for tests: one stream's `emit`, fed from a session-wide memory. */
22
31
  export declare function replayKnownToolCalls(known: Map<string, HarnessV1StreamPart>, emit: Emit): Emit;
32
+ /**
33
+ * Exported for tests: delivers every bridge event of a session once, to the
34
+ * stream the agent is still reading.
35
+ *
36
+ * Each stream's listener stays on the bridge after the agent is done with it,
37
+ * so one event reaches every listener still attached — the same object each
38
+ * time, which is what lets it be delivered once. It goes to the stream opened
39
+ * last. Once that stream has carried an approval request the agent has
40
+ * stopped reading it, so the rest is also held, in order, and opening the next
41
+ * stream hands it over.
42
+ *
43
+ * Held events are still delivered to the stopped stream, so if the agent ever
44
+ * does read past an approval, it misses nothing; it would see them twice.
45
+ */
46
+ export declare function routeSessionEvents(): {
47
+ /** The `emit` every stream hands the bridge, current or not. */
48
+ listen: () => Emit;
49
+ /** A new stream is about to be read: send it everything held. */
50
+ open: (emit: Emit, options: {
51
+ freshTurn: boolean;
52
+ }) => void;
53
+ };
23
54
  /** Exported for tests. */
24
55
  export declare function wrapSession(session: HarnessV1Session): HarnessV1Session;
25
56
  /** The harness, with every session it starts keeping its tool calls. */
@@ -1 +1 @@
1
- {"version":3,"file":"toolCallReplay.d.ts","sourceRoot":"","sources":["../../../../src/commands/ask/harness/toolCallReplay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,iBAAiB,CAAC;AAEzB,KAAK,IAAI,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAEjD,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,EACvC,IAAI,EAAE,IAAI,GACT,IAAI,CAqBN;AAED,0BAA0B;AAC1B,wBAAgB,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CA+BvE;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,CAKhE"}
1
+ {"version":3,"file":"toolCallReplay.d.ts","sourceRoot":"","sources":["../../../../src/commands/ask/harness/toolCallReplay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,iBAAiB,CAAC;AAEzB,KAAK,IAAI,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAEjD,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,EACvC,IAAI,EAAE,IAAI,GACT,IAAI,CAqBN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,IAAI;IACpC,gEAAgE;IAChE,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,iEAAiE;IACjE,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CAC7D,CAsDA;AAED,0BAA0B;AAC1B,wBAAgB,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CA4CvE;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,CAKhE"}
@@ -15,6 +15,15 @@
15
15
  * own `emit`, so the session remembers every tool call and replays one into a
16
16
  * stream that is about to receive an approval for a call it never saw. Remove
17
17
  * this once the agent keeps tool calls for the session.
18
+ *
19
+ * The same batch also loses events outright, which is the stall
20
+ * `HarnessTurnStalled` reports. The agent stops reading a stream at the first
21
+ * approval request in it, but the adapter keeps that stream's listener on the
22
+ * bridge until the turn's `finish`, so whatever the bridge says next goes into
23
+ * a stream nobody reads. When Claude Code asks about two tools at once, the
24
+ * second request lands there: the next stream never hears of it, Claude Code
25
+ * waits for an answer, and the turn waits for output. `routeSessionEvents`
26
+ * holds those events and hands them to the next stream instead.
18
27
  */
19
28
  /** Exported for tests: one stream's `emit`, fed from a session-wide memory. */
20
29
  export function replayKnownToolCalls(known, emit) {
@@ -35,17 +44,89 @@ export function replayKnownToolCalls(known, emit) {
35
44
  emit(event);
36
45
  };
37
46
  }
47
+ /**
48
+ * Exported for tests: delivers every bridge event of a session once, to the
49
+ * stream the agent is still reading.
50
+ *
51
+ * Each stream's listener stays on the bridge after the agent is done with it,
52
+ * so one event reaches every listener still attached — the same object each
53
+ * time, which is what lets it be delivered once. It goes to the stream opened
54
+ * last. Once that stream has carried an approval request the agent has
55
+ * stopped reading it, so the rest is also held, in order, and opening the next
56
+ * stream hands it over.
57
+ *
58
+ * Held events are still delivered to the stopped stream, so if the agent ever
59
+ * does read past an approval, it misses nothing; it would see them twice.
60
+ */
61
+ export function routeSessionEvents() {
62
+ const delivered = new WeakSet();
63
+ const held = [];
64
+ const current = {
65
+ emit: undefined,
66
+ stopped: false,
67
+ };
68
+ const deliver = (event) => {
69
+ if (current.emit === undefined) {
70
+ held.push(event);
71
+ return;
72
+ }
73
+ if (current.stopped === true) {
74
+ held.push(event);
75
+ }
76
+ current.emit(event);
77
+ // The agent ends the stream right here to ask; nothing after this in
78
+ // the same stream is read.
79
+ if (event.type === "tool-approval-request") {
80
+ current.stopped = true;
81
+ }
82
+ };
83
+ return {
84
+ listen: () => (event) => {
85
+ if (delivered.has(event) === true) {
86
+ return;
87
+ }
88
+ delivered.add(event);
89
+ deliver(event);
90
+ },
91
+ open: (emit, options) => {
92
+ current.emit = emit;
93
+ current.stopped = false;
94
+ const backlog = held.splice(0, held.length);
95
+ // A new prompt replaces whatever the bridge was still doing, so what
96
+ // the last turn left behind belongs to nobody.
97
+ if (options.freshTurn === true) {
98
+ return;
99
+ }
100
+ for (const event of backlog) {
101
+ deliver(event);
102
+ }
103
+ },
104
+ };
105
+ }
38
106
  /** Exported for tests. */
39
107
  export function wrapSession(session) {
40
108
  const known = new Map();
41
- const doPromptTurn = (options) => session.doPromptTurn({
42
- ...options,
43
- emit: replayKnownToolCalls(known, options.emit),
44
- });
45
- const doContinueTurn = (options) => session.doContinueTurn({
46
- ...options,
47
- emit: replayKnownToolCalls(known, options.emit),
48
- });
109
+ const router = routeSessionEvents();
110
+ const doPromptTurn = (options) => {
111
+ router.open(replayKnownToolCalls(known, options.emit), {
112
+ freshTurn: true,
113
+ });
114
+ return session.doPromptTurn({
115
+ ...options,
116
+ emit: router.listen(),
117
+ });
118
+ };
119
+ const doContinueTurn = (options) => {
120
+ // Opened before the adapter wires the stream: its emit already queues,
121
+ // and anything the bridge says in between belongs to this stream too.
122
+ router.open(replayKnownToolCalls(known, options.emit), {
123
+ freshTurn: false,
124
+ });
125
+ return session.doContinueTurn({
126
+ ...options,
127
+ emit: router.listen(),
128
+ });
129
+ };
49
130
  // A proxy rather than a spread or a prototype: a session may be a class
50
131
  // with private state, so every other member is read from it and its methods
51
132
  // run bound to it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cargo-ai/cli",
3
- "version": "1.0.125",
3
+ "version": "1.0.126",
4
4
  "mcpName": "io.github.getcargohq/cargo",
5
5
  "private": false,
6
6
  "license": "UNLICENSED",
@@ -76,8 +76,8 @@
76
76
  "@ai-sdk/harness-claude-code": "1.0.148",
77
77
  "@cargo-ai/api": "^1.0.101",
78
78
  "@cargo-ai/app-sdk": "^1.0.11",
79
- "@cargo-ai/cdk": "^1.0.119",
80
- "@cargo-ai/types": "^1.0.102",
79
+ "@cargo-ai/cdk": "^1.0.120",
80
+ "@cargo-ai/types": "^1.0.103",
81
81
  "@cargo-ai/utils": "^1.0.35",
82
82
  "@cargo-ai/worker-sdk": "^1.0.21",
83
83
  "@modelcontextprotocol/sdk": "^1.31.0",