@autohq/cli 0.1.448 → 0.1.450
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/agent-bridge.js +275 -133
- package/dist/index.js +278 -134
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20694,34 +20694,26 @@ var init_pricing = __esm({
|
|
|
20694
20694
|
});
|
|
20695
20695
|
|
|
20696
20696
|
// ../../packages/schemas/src/platform-usage-feed.ts
|
|
20697
|
-
var SafeTelemetryTextSchema,
|
|
20697
|
+
var SafeTelemetryTextSchema, PlatformUsageActorSchema, PlatformUsageAgentSchema, PlatformUsageScopeSchema, ScopedActorEventSchema, PlatformUsageEventSchema;
|
|
20698
20698
|
var init_platform_usage_feed = __esm({
|
|
20699
20699
|
"../../packages/schemas/src/platform-usage-feed.ts"() {
|
|
20700
20700
|
"use strict";
|
|
20701
20701
|
init_zod();
|
|
20702
|
+
init_agents();
|
|
20702
20703
|
SafeTelemetryTextSchema = external_exports.string().transform(
|
|
20703
20704
|
(value) => [...value].map((character) => {
|
|
20704
20705
|
const codePoint = character.codePointAt(0) ?? 0;
|
|
20705
20706
|
return codePoint < 32 || codePoint === 127 ? " " : character;
|
|
20706
20707
|
}).join("").replace(/\s+/g, " ").trim().slice(0, 300).trim()
|
|
20707
20708
|
).pipe(external_exports.string().min(1).max(300));
|
|
20708
|
-
|
|
20709
|
-
|
|
20710
|
-
|
|
20711
|
-
|
|
20712
|
-
|
|
20713
|
-
|
|
20714
|
-
|
|
20715
|
-
|
|
20716
|
-
user: PlatformUsageUserSchema
|
|
20717
|
-
}),
|
|
20718
|
-
external_exports.object({
|
|
20719
|
-
kind: external_exports.literal("provider"),
|
|
20720
|
-
provider: SafeTelemetryTextSchema,
|
|
20721
|
-
externalId: external_exports.string().trim().min(1).max(200),
|
|
20722
|
-
displayName: SafeTelemetryTextSchema.nullable()
|
|
20723
|
-
})
|
|
20724
|
-
]);
|
|
20709
|
+
PlatformUsageActorSchema = external_exports.object({
|
|
20710
|
+
displayName: SafeTelemetryTextSchema,
|
|
20711
|
+
source: SafeTelemetryTextSchema.nullable()
|
|
20712
|
+
}).strict();
|
|
20713
|
+
PlatformUsageAgentSchema = external_exports.object({
|
|
20714
|
+
displayName: SafeTelemetryTextSchema,
|
|
20715
|
+
model: SafeTelemetryTextSchema.nullable()
|
|
20716
|
+
}).strict();
|
|
20725
20717
|
PlatformUsageScopeSchema = external_exports.object({
|
|
20726
20718
|
environment: SafeTelemetryTextSchema,
|
|
20727
20719
|
organizationId: external_exports.string().trim().min(1).max(200),
|
|
@@ -20729,13 +20721,13 @@ var init_platform_usage_feed = __esm({
|
|
|
20729
20721
|
projectId: external_exports.string().trim().min(1).max(200).nullable(),
|
|
20730
20722
|
projectName: SafeTelemetryTextSchema.nullable()
|
|
20731
20723
|
});
|
|
20732
|
-
|
|
20733
|
-
|
|
20724
|
+
ScopedActorEventSchema = external_exports.object({
|
|
20725
|
+
actor: PlatformUsageActorSchema,
|
|
20734
20726
|
scope: PlatformUsageScopeSchema
|
|
20735
20727
|
});
|
|
20736
20728
|
PlatformUsageEventSchema = external_exports.discriminatedUnion("kind", [
|
|
20737
|
-
|
|
20738
|
-
|
|
20729
|
+
ScopedActorEventSchema.extend({ kind: external_exports.literal("user.signup") }),
|
|
20730
|
+
ScopedActorEventSchema.extend({
|
|
20739
20731
|
kind: external_exports.literal("onboarding.lifecycle"),
|
|
20740
20732
|
stage: external_exports.enum(["team_selected", "github_connected", "team_applied"]),
|
|
20741
20733
|
team: SafeTelemetryTextSchema,
|
|
@@ -20745,23 +20737,21 @@ var init_platform_usage_feed = __esm({
|
|
|
20745
20737
|
failureSummary: SafeTelemetryTextSchema.nullable()
|
|
20746
20738
|
}).nullable()
|
|
20747
20739
|
}),
|
|
20748
|
-
|
|
20740
|
+
ScopedActorEventSchema.extend({
|
|
20749
20741
|
kind: external_exports.literal("agent.created"),
|
|
20750
|
-
|
|
20742
|
+
agent: PlatformUsageAgentSchema
|
|
20751
20743
|
}),
|
|
20752
|
-
|
|
20744
|
+
ScopedActorEventSchema.extend({
|
|
20753
20745
|
kind: external_exports.literal("session.started"),
|
|
20754
|
-
|
|
20755
|
-
scope: PlatformUsageScopeSchema,
|
|
20756
|
-
agentName: SafeTelemetryTextSchema,
|
|
20746
|
+
agent: PlatformUsageAgentSchema,
|
|
20757
20747
|
sessionId: external_exports.string().trim().min(1).max(200)
|
|
20758
20748
|
}),
|
|
20759
|
-
|
|
20749
|
+
ScopedActorEventSchema.extend({
|
|
20760
20750
|
kind: external_exports.literal("credits.added"),
|
|
20761
20751
|
amountUsd: external_exports.number().positive().finite(),
|
|
20762
20752
|
source: external_exports.enum(["purchase", "auto_topup", "adjustment"])
|
|
20763
20753
|
}),
|
|
20764
|
-
|
|
20754
|
+
ScopedActorEventSchema.extend({
|
|
20765
20755
|
kind: external_exports.literal("credits.exhausted"),
|
|
20766
20756
|
autoReloadOutcome: external_exports.enum([
|
|
20767
20757
|
"not_enabled",
|
|
@@ -27217,6 +27207,15 @@ triggers:
|
|
|
27217
27207
|
content: "harness: claude-code\nenvironment:\n name: auto-default-runtime\n image:\n kind: preset\n name: node24\nidentity:\n displayName: Default\n username: default\n description: Auto's built-in general-purpose agent.\ntools:\n auto:\n kind: local\n implementation: auto\n"
|
|
27218
27208
|
}
|
|
27219
27209
|
]
|
|
27210
|
+
},
|
|
27211
|
+
{
|
|
27212
|
+
version: "1.1.0",
|
|
27213
|
+
files: [
|
|
27214
|
+
{
|
|
27215
|
+
path: "fragments/default.yaml",
|
|
27216
|
+
content: "# 1.1.0 bakes the built-in catalog avatar (default.png) into Default's identity so\n# every provisioned agent/default shows the house face instead of an initials\n# fallback. Otherwise byte-identical to 1.0.0.\nharness: claude-code\nenvironment:\n name: auto-default-runtime\n image:\n kind: preset\n name: node24\nidentity:\n displayName: Default\n username: default\n avatar:\n asset: .auto/assets/default.png\n sha256: a5dd97676173a83dfc6fb9bdf30e7f50c7392f9e382fca40a23d6ab9285e9bf2\n description: Auto's built-in general-purpose agent.\ntools:\n auto:\n kind: local\n implementation: auto\n"
|
|
27217
|
+
}
|
|
27218
|
+
]
|
|
27220
27219
|
}
|
|
27221
27220
|
],
|
|
27222
27221
|
"@auto/engineering-tier": [
|
|
@@ -49212,7 +49211,7 @@ var init_package = __esm({
|
|
|
49212
49211
|
"package.json"() {
|
|
49213
49212
|
package_default = {
|
|
49214
49213
|
name: "@autohq/cli",
|
|
49215
|
-
version: "0.1.
|
|
49214
|
+
version: "0.1.450",
|
|
49216
49215
|
license: "SEE LICENSE IN README.md",
|
|
49217
49216
|
publishConfig: {
|
|
49218
49217
|
access: "public"
|
|
@@ -62053,6 +62052,10 @@ function jsonRecordString2(value, key) {
|
|
|
62053
62052
|
// src/commands/agent-bridge/harness/claude-code/projector.ts
|
|
62054
62053
|
init_src();
|
|
62055
62054
|
var ClaudeCodeProjector = class {
|
|
62055
|
+
constructor(input = {}) {
|
|
62056
|
+
this.input = input;
|
|
62057
|
+
}
|
|
62058
|
+
input;
|
|
62056
62059
|
currentMessageId = null;
|
|
62057
62060
|
// The turn's UI message id. Claude emits a `message_start` per assistant
|
|
62058
62061
|
// message, but a tool-using turn spans several (message A with the tool call,
|
|
@@ -62071,13 +62074,17 @@ var ClaudeCodeProjector = class {
|
|
|
62071
62074
|
// real turn failure (FRA-3548). Cleared on every result and on the next
|
|
62072
62075
|
// message_start so a stale marker can never reclassify a later failure.
|
|
62073
62076
|
interruptMarkerSeen = false;
|
|
62074
|
-
project(message) {
|
|
62077
|
+
project(message, context = {}) {
|
|
62075
62078
|
if (isClaudeCodeInterruptMarker(message)) {
|
|
62076
62079
|
this.interruptMarkerSeen = true;
|
|
62077
62080
|
}
|
|
62078
62081
|
if (message.type === "stream_event") {
|
|
62079
62082
|
return this.projectStreamEvent(message);
|
|
62080
62083
|
}
|
|
62084
|
+
const interruptContext = {
|
|
62085
|
+
marker: this.interruptMarkerSeen,
|
|
62086
|
+
bridge: context.bridgeInterruptSettling === true
|
|
62087
|
+
};
|
|
62081
62088
|
const parsed = parseClaudeCodeStreamRecord(message);
|
|
62082
62089
|
const snapshotMessageId = assistantSnapshotMessageId(message);
|
|
62083
62090
|
const suppressStreamed = snapshotMessageId !== null && this.streamedMessageIds.has(snapshotMessageId);
|
|
@@ -62089,18 +62096,24 @@ var ClaudeCodeProjector = class {
|
|
|
62089
62096
|
return [];
|
|
62090
62097
|
}
|
|
62091
62098
|
return conversationProjectionToUiChunks(entry, {
|
|
62092
|
-
|
|
62099
|
+
interruptContext,
|
|
62100
|
+
emitDiagnostic: this.input.writeOutput
|
|
62093
62101
|
});
|
|
62094
62102
|
});
|
|
62095
62103
|
if (parsed.result) {
|
|
62096
62104
|
outputs.push(...this.endActiveParts(), ...this.finishActiveToolInputs());
|
|
62097
62105
|
this.currentMessageId = null;
|
|
62098
62106
|
this.activeResponseMessageId = null;
|
|
62099
|
-
|
|
62100
|
-
|
|
62101
|
-
|
|
62102
|
-
})
|
|
62107
|
+
const interrupted = this.isInterruptCancellation(
|
|
62108
|
+
parsed.result,
|
|
62109
|
+
interruptContext
|
|
62103
62110
|
);
|
|
62111
|
+
if (interrupted) {
|
|
62112
|
+
this.input.writeOutput?.(
|
|
62113
|
+
`agent_bridge_claude_result_interrupt_cancellation gate=${interruptGate(interruptContext)}`
|
|
62114
|
+
);
|
|
62115
|
+
}
|
|
62116
|
+
outputs.push(projectClaudeCodeResult(parsed.result, { interrupted }));
|
|
62104
62117
|
this.interruptMarkerSeen = false;
|
|
62105
62118
|
}
|
|
62106
62119
|
return outputs;
|
|
@@ -62110,9 +62123,11 @@ var ClaudeCodeProjector = class {
|
|
|
62110
62123
|
// surfaces as a diagnostic-only `error_during_execution`. Treating that as a
|
|
62111
62124
|
// turn failure fed the FRA-3548 redelivery loop (the bridge redelivered a
|
|
62112
62125
|
// message the SDK was actively answering), so a failed result bracketed by
|
|
62113
|
-
// the SDK's own
|
|
62114
|
-
|
|
62115
|
-
|
|
62126
|
+
// interrupt context — the SDK's own marker, or the session's knowledge that
|
|
62127
|
+
// a bridge interrupt is settling (which covers a missing or late marker) —
|
|
62128
|
+
// is classified as a cancellation instead.
|
|
62129
|
+
isInterruptCancellation(result, context) {
|
|
62130
|
+
return result.isError && (context.marker || context.bridge) && isClaudeCodeEdeDiagnosticOnlyError(result.errorMessage);
|
|
62116
62131
|
}
|
|
62117
62132
|
flushPendingAssistantMessages() {
|
|
62118
62133
|
const outputs = [
|
|
@@ -62233,7 +62248,8 @@ var ClaudeCodeProjector = class {
|
|
|
62233
62248
|
const messageChunks = this.assistantSnapshotMessageChunks(projections);
|
|
62234
62249
|
const rest = projections.filter((projection) => !isAssistantMessageOrToolCall(projection)).flatMap(
|
|
62235
62250
|
(projection) => conversationProjectionToUiChunks(projection, {
|
|
62236
|
-
|
|
62251
|
+
interruptContext: { marker: this.interruptMarkerSeen, bridge: false },
|
|
62252
|
+
emitDiagnostic: this.input.writeOutput
|
|
62237
62253
|
})
|
|
62238
62254
|
);
|
|
62239
62255
|
const last = messageChunks.at(-1);
|
|
@@ -62457,7 +62473,7 @@ function textContentFromDelta(delta) {
|
|
|
62457
62473
|
return null;
|
|
62458
62474
|
}
|
|
62459
62475
|
}
|
|
62460
|
-
function conversationProjectionToUiChunks(projection, options
|
|
62476
|
+
function conversationProjectionToUiChunks(projection, options) {
|
|
62461
62477
|
if (projection.role === "assistant" && projection.kind === "message") {
|
|
62462
62478
|
return messageContentChunks(projection);
|
|
62463
62479
|
}
|
|
@@ -62478,15 +62494,12 @@ function conversationProjectionToUiChunks(projection, options = { interrupted: f
|
|
|
62478
62494
|
})
|
|
62479
62495
|
];
|
|
62480
62496
|
}
|
|
62481
|
-
const remapped = typeof part.output === "string" ? remapClaudeCodeInterruptToolResultErrorText(part.output, {
|
|
62482
|
-
interrupted: options.interrupted
|
|
62483
|
-
}) : null;
|
|
62484
62497
|
return [
|
|
62485
|
-
|
|
62486
|
-
|
|
62487
|
-
|
|
62488
|
-
|
|
62489
|
-
|
|
62498
|
+
toolResultErrorChunk(
|
|
62499
|
+
part.toolUseId ?? UNKNOWN_MESSAGE_ID,
|
|
62500
|
+
part.output,
|
|
62501
|
+
options
|
|
62502
|
+
)
|
|
62490
62503
|
];
|
|
62491
62504
|
});
|
|
62492
62505
|
}
|
|
@@ -62530,6 +62543,32 @@ function conversationProjectionToUiChunks(projection, options = { interrupted: f
|
|
|
62530
62543
|
}
|
|
62531
62544
|
];
|
|
62532
62545
|
}
|
|
62546
|
+
function toolResultErrorChunk(toolCallId, output, options) {
|
|
62547
|
+
const context = options.interruptContext;
|
|
62548
|
+
const remapped = typeof output === "string" ? remapClaudeCodeInterruptToolResultErrorText(output, {
|
|
62549
|
+
interrupted: context.marker || context.bridge
|
|
62550
|
+
}) : null;
|
|
62551
|
+
if (remapped !== null) {
|
|
62552
|
+
options.emitDiagnostic?.(
|
|
62553
|
+
`agent_bridge_claude_tool_cancellation_remapped tool_use_id=${toolCallId} gate=${interruptGate(context)}`
|
|
62554
|
+
);
|
|
62555
|
+
} else if (typeof output === "string" && isClaudeCodePermissionDenialText(output)) {
|
|
62556
|
+
options.emitDiagnostic?.(
|
|
62557
|
+
`agent_bridge_claude_permission_denial_passthrough tool_use_id=${toolCallId}`
|
|
62558
|
+
);
|
|
62559
|
+
}
|
|
62560
|
+
return uiChunk({
|
|
62561
|
+
type: "tool-output-error",
|
|
62562
|
+
toolCallId,
|
|
62563
|
+
errorText: remapped ?? JSON.stringify(output)
|
|
62564
|
+
});
|
|
62565
|
+
}
|
|
62566
|
+
function interruptGate(context) {
|
|
62567
|
+
if (context.marker && context.bridge) {
|
|
62568
|
+
return "marker+bridge";
|
|
62569
|
+
}
|
|
62570
|
+
return context.marker ? "marker" : "bridge";
|
|
62571
|
+
}
|
|
62533
62572
|
function isAssistantMessageOrToolCall(projection) {
|
|
62534
62573
|
return projection.role === "assistant" && (projection.kind === "message" || projection.kind === "tool_call");
|
|
62535
62574
|
}
|
|
@@ -62808,6 +62847,7 @@ function parseReadStateRecord(raw) {
|
|
|
62808
62847
|
}
|
|
62809
62848
|
|
|
62810
62849
|
// src/commands/agent-bridge/harness/claude-code/session.ts
|
|
62850
|
+
init_src();
|
|
62811
62851
|
import {
|
|
62812
62852
|
startup as startupClaudeAgent
|
|
62813
62853
|
} from "@anthropic-ai/claude-agent-sdk";
|
|
@@ -63002,7 +63042,7 @@ function withClaudeStderrDiagnosticsPointer(error51, capturedStderr) {
|
|
|
63002
63042
|
|
|
63003
63043
|
// src/commands/agent-bridge/harness/claude-code/session.ts
|
|
63004
63044
|
var CLAUDE_AGENT_STARTUP_TIMEOUT_MS = 3e4;
|
|
63005
|
-
var
|
|
63045
|
+
var CLAUDE_TOOL_BOUNDARY_WAIT_TIMEOUT_MS = 12e4;
|
|
63006
63046
|
var CLAUDE_INTERRUPT_ACK_TIMEOUT_MS = 1e4;
|
|
63007
63047
|
var CLAUDE_MCP_REGISTRATION_TIMEOUT_MS = 3e4;
|
|
63008
63048
|
var CLAUDE_MCP_REGISTRATION_POLL_INTERVAL_MS = 100;
|
|
@@ -63078,16 +63118,33 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63078
63118
|
// flushed command id.
|
|
63079
63119
|
openTurnCommandIds = [];
|
|
63080
63120
|
// tool_use ids the assistant has emitted whose tool_result has not yet been
|
|
63081
|
-
// observed
|
|
63082
|
-
//
|
|
63121
|
+
// observed, with the name/detail needed to describe them in a cancellation
|
|
63122
|
+
// notice. A non-empty map means a tool call is in flight: interrupting now
|
|
63123
|
+
// would destroy its work and record a denial-worded cancellation, and
|
|
63124
|
+
// injecting now would append the new user message after an unresolved
|
|
63083
63125
|
// stop_reason=tool_use — the invalid transcript that trips Claude Code's
|
|
63084
63126
|
// ede_diagnostic and auto-restarts the session (FRA-3049).
|
|
63085
|
-
|
|
63086
|
-
// Incremented on every turn-terminal `result
|
|
63087
|
-
//
|
|
63088
|
-
// message lands only once the interrupted turn has settled its tool_use.
|
|
63127
|
+
pendingToolUses = /* @__PURE__ */ new Map();
|
|
63128
|
+
// Incremented on every turn-terminal `result`; the interrupt-timeout latch
|
|
63129
|
+
// compares against it to tell whether the same wedged turn is still running.
|
|
63089
63130
|
turnResultCount = 0;
|
|
63090
|
-
|
|
63131
|
+
// A steering message is waiting for the in-flight tool call to settle so the
|
|
63132
|
+
// turn can be interrupted at the tool boundary instead of mid-tool. Armed by
|
|
63133
|
+
// sendMessage, fired by the output pump when the pending tool_use set
|
|
63134
|
+
// drains, bounded by the budget timer below.
|
|
63135
|
+
toolBoundaryWait = null;
|
|
63136
|
+
// True from the moment a bridge-initiated interrupt control request fires
|
|
63137
|
+
// until the targeted turn emits its terminal result (or the stream ends).
|
|
63138
|
+
// Reported to the projector on every message so the SDK's denial-worded
|
|
63139
|
+
// cancellation records are classified as platform cancellations even though
|
|
63140
|
+
// the SDK's own interrupt marker arrives after them (probe-verified wire
|
|
63141
|
+
// order, 2026-07-13: tool_result → marker → error_during_execution result).
|
|
63142
|
+
interruptSettling = false;
|
|
63143
|
+
// Tool calls the SDK cancelled while a bridge-initiated interrupt was
|
|
63144
|
+
// settling. Consumed by the deferred flush: the injected message gets a
|
|
63145
|
+
// platform-cancellation notice naming this work so the model re-runs it
|
|
63146
|
+
// instead of treating the denial-worded tool_result as a human rejection.
|
|
63147
|
+
cancelledToolRuns = [];
|
|
63091
63148
|
// Memoized MCP-registration gate, keyed by the attached query. A runtime
|
|
63092
63149
|
// restart warms a brand-new session + query, so keying off the query object
|
|
63093
63150
|
// (rather than a session-lifetime flag) re-arms the gate on every restart:
|
|
@@ -63146,18 +63203,34 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63146
63203
|
delivery_mode: mode,
|
|
63147
63204
|
state: this.state.kind,
|
|
63148
63205
|
active_turn_count: this.activeTurnCount,
|
|
63149
|
-
pending_tool_use_count: this.
|
|
63206
|
+
pending_tool_use_count: this.pendingToolUses.size,
|
|
63150
63207
|
deferred_count: this.deferredMessages.length
|
|
63151
63208
|
});
|
|
63152
63209
|
if (mode === "deferred" && this.hasInterruptibleTurn()) {
|
|
63153
63210
|
this.deferredMessages.push({ text: message, commandIds });
|
|
63154
63211
|
this.input.runtimeLogger?.info("agent_bridge_claude_message_deferred", {
|
|
63155
63212
|
active_turn_count: this.activeTurnCount,
|
|
63156
|
-
pending_tool_use_count: this.
|
|
63213
|
+
pending_tool_use_count: this.pendingToolUses.size,
|
|
63157
63214
|
deferred_count: this.deferredMessages.length
|
|
63158
63215
|
});
|
|
63159
63216
|
return;
|
|
63160
63217
|
}
|
|
63218
|
+
if (this.hasInterruptibleTurn() && this.hasInFlightToolUse()) {
|
|
63219
|
+
this.deferredMessages.push({ text: message, commandIds });
|
|
63220
|
+
this.armToolBoundaryWait();
|
|
63221
|
+
this.input.runtimeLogger?.info(
|
|
63222
|
+
"agent_bridge_claude_message_deferred_tool_boundary",
|
|
63223
|
+
{
|
|
63224
|
+
active_turn_count: this.activeTurnCount,
|
|
63225
|
+
pending_tool_use_count: this.pendingToolUses.size,
|
|
63226
|
+
pending_tools: [...this.pendingToolUses.values()].map(
|
|
63227
|
+
(tool) => tool.name
|
|
63228
|
+
),
|
|
63229
|
+
deferred_count: this.deferredMessages.length
|
|
63230
|
+
}
|
|
63231
|
+
);
|
|
63232
|
+
return;
|
|
63233
|
+
}
|
|
63161
63234
|
const interruption = await this.interruptActiveTurnBeforeMessage();
|
|
63162
63235
|
if (interruption === "defer" && this.hasInterruptibleTurn()) {
|
|
63163
63236
|
this.deferredMessages.push({ text: message, commandIds });
|
|
@@ -63165,7 +63238,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63165
63238
|
"agent_bridge_claude_message_deferred_after_interrupt_timeout",
|
|
63166
63239
|
{
|
|
63167
63240
|
active_turn_count: this.activeTurnCount,
|
|
63168
|
-
pending_tool_use_count: this.
|
|
63241
|
+
pending_tool_use_count: this.pendingToolUses.size,
|
|
63169
63242
|
deferred_count: this.deferredMessages.length
|
|
63170
63243
|
}
|
|
63171
63244
|
);
|
|
@@ -63178,7 +63251,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63178
63251
|
duration_ms: Date.now() - startedAt,
|
|
63179
63252
|
state: this.state.kind,
|
|
63180
63253
|
active_turn_count: this.activeTurnCount,
|
|
63181
|
-
pending_tool_use_count: this.
|
|
63254
|
+
pending_tool_use_count: this.pendingToolUses.size,
|
|
63182
63255
|
deferred_count: this.deferredMessages.length
|
|
63183
63256
|
});
|
|
63184
63257
|
}
|
|
@@ -63262,8 +63335,10 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63262
63335
|
}
|
|
63263
63336
|
this.state = { kind: "closed" };
|
|
63264
63337
|
this.activeTurnCount = 0;
|
|
63265
|
-
this.
|
|
63266
|
-
this.
|
|
63338
|
+
this.pendingToolUses.clear();
|
|
63339
|
+
this.cancelledToolRuns = [];
|
|
63340
|
+
this.interruptSettling = false;
|
|
63341
|
+
this.disarmToolBoundaryWait();
|
|
63267
63342
|
if (this.deferredMessages.length > 0) {
|
|
63268
63343
|
this.input.writeOutput?.(
|
|
63269
63344
|
`agent_bridge_claude_deferred_dropped count=${this.deferredMessages.length} reason=session_closed`
|
|
@@ -63354,19 +63429,21 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63354
63429
|
void (async () => {
|
|
63355
63430
|
try {
|
|
63356
63431
|
for await (const message of query) {
|
|
63432
|
+
const interruptSettling = this.interruptSettling;
|
|
63357
63433
|
this.trackToolUseLifecycle(message);
|
|
63358
|
-
let meta3;
|
|
63434
|
+
let meta3 = { interruptSettling };
|
|
63359
63435
|
if (isClaudeAgentTurnResult(message)) {
|
|
63360
63436
|
this.activeTurnCount = Math.max(0, this.activeTurnCount - 1);
|
|
63361
63437
|
meta3 = {
|
|
63438
|
+
interruptSettling,
|
|
63362
63439
|
consumedCommandIds: this.openTurnCommandIds.shift() ?? []
|
|
63363
63440
|
};
|
|
63364
|
-
this.
|
|
63441
|
+
this.pendingToolUses.clear();
|
|
63442
|
+
this.interruptSettling = false;
|
|
63365
63443
|
this.turnResultCount += 1;
|
|
63366
|
-
this.resolveTurnSettlement(true);
|
|
63367
63444
|
this.input.runtimeLogger?.info("agent_bridge_claude_turn_result", {
|
|
63368
63445
|
active_turn_count: this.activeTurnCount,
|
|
63369
|
-
pending_tool_use_count: this.
|
|
63446
|
+
pending_tool_use_count: this.pendingToolUses.size,
|
|
63370
63447
|
turn_result_count: this.turnResultCount,
|
|
63371
63448
|
deferred_count: this.deferredMessages.length,
|
|
63372
63449
|
consumed_command_ids: meta3.consumedCommandIds
|
|
@@ -63374,6 +63451,9 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63374
63451
|
if (this.activeTurnCount === 0) {
|
|
63375
63452
|
this.flushDeferredMessages();
|
|
63376
63453
|
}
|
|
63454
|
+
if (this.deferredMessages.length === 0) {
|
|
63455
|
+
this.cancelledToolRuns = [];
|
|
63456
|
+
}
|
|
63377
63457
|
}
|
|
63378
63458
|
const failure = probeClaudeAgentMessage(
|
|
63379
63459
|
message,
|
|
@@ -63398,8 +63478,9 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63398
63478
|
} finally {
|
|
63399
63479
|
this.activeTurnCount = 0;
|
|
63400
63480
|
this.openTurnCommandIds.length = 0;
|
|
63401
|
-
this.
|
|
63402
|
-
this.
|
|
63481
|
+
this.pendingToolUses.clear();
|
|
63482
|
+
this.interruptSettling = false;
|
|
63483
|
+
this.disarmToolBoundaryWait();
|
|
63403
63484
|
this.state = { kind: "closed" };
|
|
63404
63485
|
this.reportExit();
|
|
63405
63486
|
}
|
|
@@ -63416,7 +63497,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63416
63497
|
this.input.runtimeLogger?.info("agent_bridge_claude_message_enqueued", {
|
|
63417
63498
|
state: this.state.kind,
|
|
63418
63499
|
active_turn_count: this.activeTurnCount,
|
|
63419
|
-
pending_tool_use_count: this.
|
|
63500
|
+
pending_tool_use_count: this.pendingToolUses.size,
|
|
63420
63501
|
deferred_count: this.deferredMessages.length
|
|
63421
63502
|
});
|
|
63422
63503
|
void this.ensureRunningQuery().catch((error51) => {
|
|
@@ -63429,75 +63510,105 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63429
63510
|
return this.activeTurnCount > 0 && this.state.kind === "running";
|
|
63430
63511
|
}
|
|
63431
63512
|
// True while the assistant has an emitted tool_use with no matching
|
|
63432
|
-
// tool_result yet — the window where an immediate interrupt would
|
|
63513
|
+
// tool_result yet — the window where an immediate interrupt would cancel
|
|
63514
|
+
// real tool work, and where an immediate injection would strand an
|
|
63433
63515
|
// unresolved stop_reason=tool_use ahead of the injected user message.
|
|
63434
63516
|
hasInFlightToolUse() {
|
|
63435
|
-
return this.
|
|
63517
|
+
return this.pendingToolUses.size > 0;
|
|
63436
63518
|
}
|
|
63437
63519
|
// Track tool_use/tool_result pairs as they stream so hasInFlightToolUse()
|
|
63438
63520
|
// reflects the live transcript. A tool_use may appear first as a streaming
|
|
63439
63521
|
// content block before the full assistant message is available; the matching
|
|
63440
63522
|
// tool_result closes it; the turn's terminal result clears any remainder.
|
|
63523
|
+
// Two side jobs ride on the same observation point:
|
|
63524
|
+
// - a denial-worded error tool_result arriving while a bridge interrupt is
|
|
63525
|
+
// settling is that interrupt's cancellation of the tool — record it so the
|
|
63526
|
+
// flushed message can tell the model to re-run the cancelled work;
|
|
63527
|
+
// - a tool_result that drains the pending set is the tool boundary an armed
|
|
63528
|
+
// steering message has been waiting for — interrupt the turn now, while no
|
|
63529
|
+
// tool work is at risk.
|
|
63441
63530
|
trackToolUseLifecycle(message) {
|
|
63442
|
-
for (const
|
|
63443
|
-
this.
|
|
63531
|
+
for (const entry of toolUseEntries(message)) {
|
|
63532
|
+
this.pendingToolUses.set(entry.id, {
|
|
63533
|
+
name: entry.name,
|
|
63534
|
+
detail: entry.detail
|
|
63535
|
+
});
|
|
63536
|
+
}
|
|
63537
|
+
const hadInFlightToolUse = this.hasInFlightToolUse();
|
|
63538
|
+
for (const result of toolResultEntries(message)) {
|
|
63539
|
+
const pending = this.pendingToolUses.get(result.id);
|
|
63540
|
+
this.pendingToolUses.delete(result.id);
|
|
63541
|
+
if (pending && this.interruptSettling && result.isError && result.text !== null && isClaudeCodePermissionDenialText(result.text)) {
|
|
63542
|
+
this.cancelledToolRuns.push(pending);
|
|
63543
|
+
this.input.writeOutput?.(
|
|
63544
|
+
`agent_bridge_claude_tool_cancellation_observed tool=${pending.name}`
|
|
63545
|
+
);
|
|
63546
|
+
}
|
|
63444
63547
|
}
|
|
63445
|
-
|
|
63446
|
-
this.
|
|
63548
|
+
if (hadInFlightToolUse && !this.hasInFlightToolUse()) {
|
|
63549
|
+
this.fireToolBoundaryInterrupt();
|
|
63447
63550
|
}
|
|
63448
63551
|
}
|
|
63449
|
-
//
|
|
63450
|
-
//
|
|
63451
|
-
//
|
|
63452
|
-
//
|
|
63453
|
-
//
|
|
63454
|
-
|
|
63455
|
-
if (this.
|
|
63456
|
-
return
|
|
63552
|
+
// The pending tool_use set just drained mid-turn. If a steering message is
|
|
63553
|
+
// waiting on that boundary, interrupt the turn now: nothing is executing, so
|
|
63554
|
+
// the cancellation costs only the model's remaining reasoning, and the
|
|
63555
|
+
// turn's terminal result flushes the message. Fire-and-forget — the flush at
|
|
63556
|
+
// the turn result owns delivery whether or not this interrupt lands.
|
|
63557
|
+
fireToolBoundaryInterrupt() {
|
|
63558
|
+
if (!this.toolBoundaryWait || this.deferredMessages.length === 0 || !this.hasInterruptibleTurn()) {
|
|
63559
|
+
return;
|
|
63457
63560
|
}
|
|
63458
|
-
|
|
63459
|
-
|
|
63460
|
-
|
|
63461
|
-
|
|
63462
|
-
|
|
63463
|
-
|
|
63464
|
-
|
|
63465
|
-
|
|
63466
|
-
|
|
63467
|
-
|
|
63468
|
-
|
|
63469
|
-
|
|
63470
|
-
|
|
63471
|
-
|
|
63472
|
-
|
|
63473
|
-
|
|
63474
|
-
|
|
63475
|
-
|
|
63561
|
+
this.disarmToolBoundaryWait();
|
|
63562
|
+
this.input.writeOutput?.(
|
|
63563
|
+
`agent_bridge_claude_tool_boundary_interrupt deferred_count=${this.deferredMessages.length}`
|
|
63564
|
+
);
|
|
63565
|
+
void this.interruptActiveTurn();
|
|
63566
|
+
}
|
|
63567
|
+
// Bound the tool-boundary wait: past the budget the steering message is
|
|
63568
|
+
// judged more urgent than the in-flight tool, which is cancelled mid-run.
|
|
63569
|
+
// The cancellation is observed by trackToolUseLifecycle and reported to the
|
|
63570
|
+
// model in the flushed message's platform notice.
|
|
63571
|
+
armToolBoundaryWait() {
|
|
63572
|
+
if (this.toolBoundaryWait) {
|
|
63573
|
+
return;
|
|
63574
|
+
}
|
|
63575
|
+
const timer = setTimeout(() => {
|
|
63576
|
+
this.toolBoundaryWait = null;
|
|
63577
|
+
if (!this.hasInterruptibleTurn() || this.deferredMessages.length === 0) {
|
|
63578
|
+
return;
|
|
63579
|
+
}
|
|
63580
|
+
this.input.writeOutput?.(
|
|
63581
|
+
`agent_bridge_claude_tool_boundary_wait_timeout pending_tools=${[
|
|
63582
|
+
...this.pendingToolUses.values()
|
|
63583
|
+
].map((tool) => tool.name).join(",")} deferred_count=${this.deferredMessages.length}`
|
|
63476
63584
|
);
|
|
63477
|
-
|
|
63478
|
-
|
|
63479
|
-
|
|
63585
|
+
void this.interruptActiveTurn();
|
|
63586
|
+
}, CLAUDE_TOOL_BOUNDARY_WAIT_TIMEOUT_MS);
|
|
63587
|
+
timer.unref?.();
|
|
63588
|
+
this.toolBoundaryWait = { timer };
|
|
63480
63589
|
}
|
|
63481
|
-
|
|
63482
|
-
if (this.
|
|
63590
|
+
disarmToolBoundaryWait() {
|
|
63591
|
+
if (!this.toolBoundaryWait) {
|
|
63483
63592
|
return;
|
|
63484
63593
|
}
|
|
63485
|
-
|
|
63486
|
-
this.
|
|
63487
|
-
for (const waiter of waiters) {
|
|
63488
|
-
waiter(settled);
|
|
63489
|
-
}
|
|
63594
|
+
clearTimeout(this.toolBoundaryWait.timer);
|
|
63595
|
+
this.toolBoundaryWait = null;
|
|
63490
63596
|
}
|
|
63491
63597
|
flushDeferredMessages() {
|
|
63492
63598
|
if (this.deferredMessages.length === 0) {
|
|
63493
63599
|
return;
|
|
63494
63600
|
}
|
|
63495
63601
|
const pending = this.deferredMessages.splice(0);
|
|
63602
|
+
const cancelledToolRuns = this.cancelledToolRuns.splice(0);
|
|
63603
|
+
this.disarmToolBoundaryWait();
|
|
63496
63604
|
this.input.writeOutput?.(
|
|
63497
|
-
`agent_bridge_claude_deferred_flush count=${pending.length}`
|
|
63605
|
+
`agent_bridge_claude_deferred_flush count=${pending.length} cancelled_tool_count=${cancelledToolRuns.length}`
|
|
63498
63606
|
);
|
|
63607
|
+
const text = pending.map((entry) => entry.text).join("\n\n");
|
|
63499
63608
|
this.enqueueUserMessage(
|
|
63500
|
-
|
|
63609
|
+
cancelledToolRuns.length > 0 ? `${text}
|
|
63610
|
+
|
|
63611
|
+
${cancelledToolPlatformNotice(cancelledToolRuns)}` : text,
|
|
63501
63612
|
pending.flatMap((entry) => entry.commandIds)
|
|
63502
63613
|
);
|
|
63503
63614
|
}
|
|
@@ -63518,11 +63629,10 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63518
63629
|
return "proceed";
|
|
63519
63630
|
}
|
|
63520
63631
|
const query = this.state.query;
|
|
63521
|
-
const hadInFlightToolUse = this.hasInFlightToolUse();
|
|
63522
63632
|
const settlementBaseline = this.turnResultCount;
|
|
63523
63633
|
const startedAt = Date.now();
|
|
63524
63634
|
this.input.writeOutput?.(
|
|
63525
|
-
`agent_bridge_claude_mid_turn_interrupt_started at=${new Date(startedAt).toISOString()} in_flight_tool_use=${
|
|
63635
|
+
`agent_bridge_claude_mid_turn_interrupt_started at=${new Date(startedAt).toISOString()} in_flight_tool_use=${this.hasInFlightToolUse()}`
|
|
63526
63636
|
);
|
|
63527
63637
|
const interruptPromise = (async () => {
|
|
63528
63638
|
const ack = await this.requestInterruptAck(query, startedAt);
|
|
@@ -63530,16 +63640,6 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63530
63640
|
this.interruptTimeoutTurn = settlementBaseline;
|
|
63531
63641
|
return "defer";
|
|
63532
63642
|
}
|
|
63533
|
-
if (hadInFlightToolUse) {
|
|
63534
|
-
const settle = await this.awaitTurnSettlement(
|
|
63535
|
-
settlementBaseline,
|
|
63536
|
-
startedAt
|
|
63537
|
-
);
|
|
63538
|
-
if (settle === "timeout") {
|
|
63539
|
-
this.interruptTimeoutTurn = settlementBaseline;
|
|
63540
|
-
return "defer";
|
|
63541
|
-
}
|
|
63542
|
-
}
|
|
63543
63643
|
return "proceed";
|
|
63544
63644
|
})();
|
|
63545
63645
|
this.interruptInFlight = interruptPromise;
|
|
@@ -63576,6 +63676,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
63576
63676
|
);
|
|
63577
63677
|
}, CLAUDE_INTERRUPT_ACK_TIMEOUT_MS);
|
|
63578
63678
|
timer.unref?.();
|
|
63679
|
+
this.interruptSettling = true;
|
|
63579
63680
|
query.interrupt().then(
|
|
63580
63681
|
() => {
|
|
63581
63682
|
if (done) {
|
|
@@ -63932,10 +64033,10 @@ function claudeAgentUserMessage(message) {
|
|
|
63932
64033
|
function isClaudeAgentTurnResult(message) {
|
|
63933
64034
|
return message.type === "result";
|
|
63934
64035
|
}
|
|
63935
|
-
function
|
|
64036
|
+
function toolUseEntries(message) {
|
|
63936
64037
|
if (message.type === "assistant") {
|
|
63937
64038
|
return contentBlocks2(message.message.content).flatMap(
|
|
63938
|
-
(block2) => block2.type === "tool_use" && typeof block2.id === "string" ? [block2
|
|
64039
|
+
(block2) => block2.type === "tool_use" && typeof block2.id === "string" ? [toolUseEntryFromBlock(block2)] : []
|
|
63939
64040
|
);
|
|
63940
64041
|
}
|
|
63941
64042
|
if (message.type !== "stream_event") {
|
|
@@ -63946,16 +64047,54 @@ function toolUseIds(message) {
|
|
|
63946
64047
|
return [];
|
|
63947
64048
|
}
|
|
63948
64049
|
const block = event.content_block;
|
|
63949
|
-
return block.type === "tool_use" && typeof block.id === "string" ? [block
|
|
64050
|
+
return block.type === "tool_use" && typeof block.id === "string" ? [toolUseEntryFromBlock(block)] : [];
|
|
64051
|
+
}
|
|
64052
|
+
function toolUseEntryFromBlock(block) {
|
|
64053
|
+
return {
|
|
64054
|
+
id: String(block.id),
|
|
64055
|
+
name: typeof block.name === "string" ? block.name : "unknown_tool",
|
|
64056
|
+
detail: toolUseDetail(block.input)
|
|
64057
|
+
};
|
|
63950
64058
|
}
|
|
63951
|
-
function
|
|
64059
|
+
function toolUseDetail(input) {
|
|
64060
|
+
if (input === void 0 || input === null) {
|
|
64061
|
+
return "";
|
|
64062
|
+
}
|
|
64063
|
+
let text;
|
|
64064
|
+
try {
|
|
64065
|
+
text = JSON.stringify(input);
|
|
64066
|
+
} catch {
|
|
64067
|
+
return "";
|
|
64068
|
+
}
|
|
64069
|
+
if (!text || text === "{}") {
|
|
64070
|
+
return "";
|
|
64071
|
+
}
|
|
64072
|
+
return text.length > 160 ? `${text.slice(0, 160)}\u2026` : text;
|
|
64073
|
+
}
|
|
64074
|
+
function toolResultEntries(message) {
|
|
63952
64075
|
if (message.type !== "user") {
|
|
63953
64076
|
return [];
|
|
63954
64077
|
}
|
|
63955
64078
|
return contentBlocks2(message.message.content).flatMap(
|
|
63956
|
-
(block) => block.type === "tool_result" && typeof block.tool_use_id === "string" ? [
|
|
64079
|
+
(block) => block.type === "tool_result" && typeof block.tool_use_id === "string" ? [
|
|
64080
|
+
{
|
|
64081
|
+
id: block.tool_use_id,
|
|
64082
|
+
isError: block.is_error === true,
|
|
64083
|
+
text: typeof block.content === "string" ? block.content : null
|
|
64084
|
+
}
|
|
64085
|
+
] : []
|
|
63957
64086
|
);
|
|
63958
64087
|
}
|
|
64088
|
+
function cancelledToolPlatformNotice(cancelled) {
|
|
64089
|
+
const lines = cancelled.map(
|
|
64090
|
+
(tool) => `- ${tool.name}${tool.detail ? ` ${tool.detail}` : ""}`
|
|
64091
|
+
);
|
|
64092
|
+
return [
|
|
64093
|
+
"[Auto platform notice] To deliver the message above, the platform cancelled the following in-flight tool call(s) mid-execution:",
|
|
64094
|
+
...lines,
|
|
64095
|
+
"This was a platform-initiated cancellation for message delivery, NOT a rejection or permission denial by the user \u2014 ignore any tool result saying the user doesn't want to proceed. Re-run or resume that tool work if it is still needed once you have applied the message."
|
|
64096
|
+
].join("\n");
|
|
64097
|
+
}
|
|
63959
64098
|
function contentBlocks2(content) {
|
|
63960
64099
|
if (!Array.isArray(content)) {
|
|
63961
64100
|
return [];
|
|
@@ -63974,6 +64113,9 @@ var ClaudeCodeCommandHandler = class {
|
|
|
63974
64113
|
this.input = input;
|
|
63975
64114
|
this.claudeConfig = input.claude;
|
|
63976
64115
|
this.outputBuffer = new AgentBridgeOutputBuffer(input);
|
|
64116
|
+
this.projector = new ClaudeCodeProjector({
|
|
64117
|
+
writeOutput: input.writeOutput
|
|
64118
|
+
});
|
|
63977
64119
|
this.readState = input.readState ? new ClaudeReadStateTracker(input.readState) : null;
|
|
63978
64120
|
}
|
|
63979
64121
|
input;
|
|
@@ -63995,7 +64137,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
63995
64137
|
inFlightMessageCommands = /* @__PURE__ */ new Map();
|
|
63996
64138
|
pendingQuestions = /* @__PURE__ */ new Map();
|
|
63997
64139
|
outputBuffer;
|
|
63998
|
-
projector
|
|
64140
|
+
projector;
|
|
63999
64141
|
readState;
|
|
64000
64142
|
livenessTicker = null;
|
|
64001
64143
|
// -----------------------------------------------------------------------------
|
|
@@ -64376,7 +64518,9 @@ var ClaudeCodeCommandHandler = class {
|
|
|
64376
64518
|
this.trackReadState(activeContext, message);
|
|
64377
64519
|
let projections;
|
|
64378
64520
|
try {
|
|
64379
|
-
projections = this.projector.project(message
|
|
64521
|
+
projections = this.projector.project(message, {
|
|
64522
|
+
bridgeInterruptSettling: meta3?.interruptSettling === true
|
|
64523
|
+
});
|
|
64380
64524
|
} catch (error51) {
|
|
64381
64525
|
this.input.writeOutput?.(
|
|
64382
64526
|
`agent_bridge_claude_parse_failed error=${error51 instanceof Error ? error51.message : String(error51)}`
|