@autohq/cli 0.1.286 → 0.1.288
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 +156 -39
- package/dist/index.js +158 -41
- package/package.json +1 -1
package/dist/agent-bridge.js
CHANGED
|
@@ -23384,7 +23384,7 @@ Object.assign(lookup, {
|
|
|
23384
23384
|
// package.json
|
|
23385
23385
|
var package_default = {
|
|
23386
23386
|
name: "@autohq/cli",
|
|
23387
|
-
version: "0.1.
|
|
23387
|
+
version: "0.1.288",
|
|
23388
23388
|
license: "SEE LICENSE IN README.md",
|
|
23389
23389
|
publishConfig: {
|
|
23390
23390
|
access: "public"
|
|
@@ -28362,6 +28362,9 @@ var ProjectTemplateSubscriptionSchema = external_exports.object({
|
|
|
28362
28362
|
});
|
|
28363
28363
|
|
|
28364
28364
|
// ../../packages/schemas/src/temporal.ts
|
|
28365
|
+
var SessionCheckTimeoutWorkflowInputSchema = external_exports.object({
|
|
28366
|
+
checkId: external_exports.string().trim().min(1)
|
|
28367
|
+
});
|
|
28365
28368
|
var ResourceReconciliationScopeSchema = external_exports.object({
|
|
28366
28369
|
organizationId: external_exports.string().trim().min(1),
|
|
28367
28370
|
projectId: external_exports.string().trim().min(1).nullable()
|
|
@@ -28428,6 +28431,42 @@ var SessionUsageResponseSchema = external_exports.object({
|
|
|
28428
28431
|
firstUsageAt: external_exports.string().datetime().nullable(),
|
|
28429
28432
|
lastUsageAt: external_exports.string().datetime().nullable()
|
|
28430
28433
|
});
|
|
28434
|
+
var PROJECT_USAGE_RANGE_KEYS = ["7d", "30d"];
|
|
28435
|
+
var ProjectUsageRangeKeySchema = external_exports.enum(PROJECT_USAGE_RANGE_KEYS);
|
|
28436
|
+
var UtcDateSchema = external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
28437
|
+
var ProjectUsageTotalsSchema = UsageTotalsSchema.extend({
|
|
28438
|
+
sessionCount: NonNegativeTokenCountSchema,
|
|
28439
|
+
// Share of all tokens served from prompt-cache reads (0..1); 0 when the
|
|
28440
|
+
// window has no tokens at all.
|
|
28441
|
+
cacheReadShare: external_exports.number().min(0).max(1)
|
|
28442
|
+
});
|
|
28443
|
+
var ProjectUsageAgentSummarySchema = UsageTotalsSchema.extend({
|
|
28444
|
+
agentResourceId: external_exports.string().trim().min(1),
|
|
28445
|
+
// Resolved from the agent resource (archived agents included); null only
|
|
28446
|
+
// when the agent row no longer exists at all — the ledger deliberately
|
|
28447
|
+
// outlives its attribution targets.
|
|
28448
|
+
agentName: external_exports.string().trim().min(1).nullable(),
|
|
28449
|
+
sessionCount: NonNegativeTokenCountSchema
|
|
28450
|
+
});
|
|
28451
|
+
var ProjectUsageModelSummarySchema = UsageTotalsSchema.extend({
|
|
28452
|
+
model: external_exports.string().trim().min(1)
|
|
28453
|
+
});
|
|
28454
|
+
var ProjectUsageDayPointSchema = UsageTotalsSchema.extend({
|
|
28455
|
+
date: UtcDateSchema
|
|
28456
|
+
});
|
|
28457
|
+
var ProjectUsageResponseSchema = external_exports.object({
|
|
28458
|
+
organizationId: OrganizationIdSchema,
|
|
28459
|
+
projectId: ProjectIdSchema,
|
|
28460
|
+
range: external_exports.object({
|
|
28461
|
+
key: ProjectUsageRangeKeySchema,
|
|
28462
|
+
since: external_exports.string().datetime(),
|
|
28463
|
+
until: external_exports.string().datetime()
|
|
28464
|
+
}),
|
|
28465
|
+
totals: ProjectUsageTotalsSchema,
|
|
28466
|
+
byAgent: external_exports.array(ProjectUsageAgentSummarySchema),
|
|
28467
|
+
byModel: external_exports.array(ProjectUsageModelSummarySchema),
|
|
28468
|
+
daily: external_exports.array(ProjectUsageDayPointSchema)
|
|
28469
|
+
});
|
|
28431
28470
|
|
|
28432
28471
|
// ../../node_modules/ai/node_modules/@ai-sdk/provider/dist/index.mjs
|
|
28433
28472
|
var marker = "vercel.ai.error";
|
|
@@ -57304,6 +57343,12 @@ var claudeAgentBridgeRuntime = {
|
|
|
57304
57343
|
var claudeAgentSdkRuntime = {
|
|
57305
57344
|
startup: (input) => aj$(input)
|
|
57306
57345
|
};
|
|
57346
|
+
var ClaudeMcpRegistryEmptyError = class extends Error {
|
|
57347
|
+
constructor(detail) {
|
|
57348
|
+
super(`MCP tool registry came up empty at session start: ${detail}`);
|
|
57349
|
+
this.name = "ClaudeMcpRegistryEmptyError";
|
|
57350
|
+
}
|
|
57351
|
+
};
|
|
57307
57352
|
var ClaudeAgentBridgeSessionImpl = class {
|
|
57308
57353
|
input;
|
|
57309
57354
|
inputQueue;
|
|
@@ -57693,17 +57738,20 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
57693
57738
|
}
|
|
57694
57739
|
// Why this gate is correct without a provider-backed test (it relies on real
|
|
57695
57740
|
// SDK mcpServerStatus() timing that fakes cannot prove):
|
|
57696
|
-
// - Safe-degrade: pollMcpRegistration never rejects — on
|
|
57697
|
-
// status-read failure, or a closed session it resolves, so
|
|
57698
|
-
//
|
|
57699
|
-
//
|
|
57741
|
+
// - Safe-degrade on uncertainty: pollMcpRegistration never rejects — on
|
|
57742
|
+
// timeout, a status-read failure, or a closed session it resolves, so an
|
|
57743
|
+
// *unconfirmed* registry still degrades to today's immediate injection.
|
|
57744
|
+
// The one fail-closed exit is the confirmed-empty registry: every
|
|
57745
|
+
// configured server settled and none is serving tools, which is exactly
|
|
57746
|
+
// the state that produced silent toolless runs in production (FRA-3458).
|
|
57700
57747
|
// - Provider-path validation is deferred deliberately: the failure is the
|
|
57701
57748
|
// intermittent live-prod race on the chief-of-staff singleton (a real
|
|
57702
57749
|
// runtime restart dispatching turn-1 while real mcp__* servers reconnect),
|
|
57703
57750
|
// which cannot be reproduced deterministically without live credentials
|
|
57704
57751
|
// and a forced restart racing reconnect.
|
|
57705
57752
|
// - Live confirmation comes from the agent_bridge_claude_mcp_gate_started/
|
|
57706
|
-
// _ready/_timeout diagnostics on the next real restart, not a CI
|
|
57753
|
+
// _ready/_timeout/_empty diagnostics on the next real restart, not a CI
|
|
57754
|
+
// fake.
|
|
57707
57755
|
//
|
|
57708
57756
|
// Block until the freshly-warmed query's MCP servers have left `pending`, so
|
|
57709
57757
|
// the first turn's prompt is built with the mcp__* tools registered. Memoized
|
|
@@ -57727,15 +57775,22 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
57727
57775
|
promise: this.pollMcpRegistration(query)
|
|
57728
57776
|
};
|
|
57729
57777
|
}
|
|
57730
|
-
await this.mcpRegistrationGate.promise;
|
|
57778
|
+
const result = await this.mcpRegistrationGate.promise;
|
|
57779
|
+
if (result.outcome !== "empty") {
|
|
57780
|
+
return;
|
|
57781
|
+
}
|
|
57782
|
+
this.close();
|
|
57783
|
+
throw new ClaudeMcpRegistryEmptyError(result.detail);
|
|
57731
57784
|
}
|
|
57732
57785
|
// Poll the live query's MCP server status until no configured server is still
|
|
57733
57786
|
// `pending`, bounded by CLAUDE_MCP_REGISTRATION_TIMEOUT_MS. Terminal states
|
|
57734
57787
|
// (connected/failed/needs-auth/disabled) all count as settled, so a server
|
|
57735
57788
|
// that cannot connect in this runtime (e.g. an interactively-authed server in
|
|
57736
|
-
// a headless sandbox) never holds the gate to the timeout.
|
|
57789
|
+
// a headless sandbox) never holds the gate to the timeout. A settled state
|
|
57790
|
+
// where no configured server is serving tools resolves "empty" — the caller
|
|
57791
|
+
// fails the send rather than injecting a toolless turn. Never rejects:
|
|
57737
57792
|
// status-read failure, timeout, or a closed session all resolve so the caller
|
|
57738
|
-
// degrades to immediate injection.
|
|
57793
|
+
// degrades to immediate injection when the registry state is uncertain.
|
|
57739
57794
|
async pollMcpRegistration(query) {
|
|
57740
57795
|
const configuredNames = Object.keys(this.options.mcpServers ?? {});
|
|
57741
57796
|
const startedAt = Date.now();
|
|
@@ -57745,7 +57800,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
57745
57800
|
);
|
|
57746
57801
|
while (true) {
|
|
57747
57802
|
if (this.state.kind === "closed") {
|
|
57748
|
-
return;
|
|
57803
|
+
return { outcome: "closed" };
|
|
57749
57804
|
}
|
|
57750
57805
|
let statuses;
|
|
57751
57806
|
try {
|
|
@@ -57754,19 +57809,26 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
57754
57809
|
this.input.writeOutput?.(
|
|
57755
57810
|
`agent_bridge_claude_mcp_gate_status_failed duration_ms=${Date.now() - startedAt} error=${error51 instanceof Error ? error51.message : String(error51)}`
|
|
57756
57811
|
);
|
|
57757
|
-
return;
|
|
57812
|
+
return { outcome: "status_failed" };
|
|
57758
57813
|
}
|
|
57759
57814
|
if (mcpServersSettled(statuses, configuredNames)) {
|
|
57815
|
+
if (!mcpRegistryHasTools(statuses, configuredNames)) {
|
|
57816
|
+
const detail = mcpStatusDetailList(statuses);
|
|
57817
|
+
this.input.writeOutput?.(
|
|
57818
|
+
`agent_bridge_claude_mcp_gate_empty duration_ms=${Date.now() - startedAt} servers=${detail}`
|
|
57819
|
+
);
|
|
57820
|
+
return { outcome: "empty", detail };
|
|
57821
|
+
}
|
|
57760
57822
|
this.input.writeOutput?.(
|
|
57761
57823
|
`agent_bridge_claude_mcp_gate_ready duration_ms=${Date.now() - startedAt} servers=${mcpStatusList(statuses)}`
|
|
57762
57824
|
);
|
|
57763
|
-
return;
|
|
57825
|
+
return { outcome: "ready" };
|
|
57764
57826
|
}
|
|
57765
57827
|
if (Date.now() >= deadline) {
|
|
57766
57828
|
this.input.writeOutput?.(
|
|
57767
57829
|
`agent_bridge_claude_mcp_gate_timeout duration_ms=${Date.now() - startedAt} servers=${mcpStatusList(statuses)}`
|
|
57768
57830
|
);
|
|
57769
|
-
return;
|
|
57831
|
+
return { outcome: "timeout" };
|
|
57770
57832
|
}
|
|
57771
57833
|
await delay(CLAUDE_MCP_REGISTRATION_POLL_INTERVAL_MS);
|
|
57772
57834
|
}
|
|
@@ -57909,9 +57971,20 @@ function mcpServersSettled(statuses, configuredNames) {
|
|
|
57909
57971
|
return status !== void 0 && status !== "pending";
|
|
57910
57972
|
});
|
|
57911
57973
|
}
|
|
57974
|
+
function mcpRegistryHasTools(statuses, configuredNames) {
|
|
57975
|
+
const configured = new Set(configuredNames);
|
|
57976
|
+
return statuses.some(
|
|
57977
|
+
(server) => configured.has(server.name) && server.status === "connected" && (server.tools === void 0 || server.tools.length > 0)
|
|
57978
|
+
);
|
|
57979
|
+
}
|
|
57912
57980
|
function mcpStatusList(statuses) {
|
|
57913
57981
|
return statuses.map((server) => `${server.name}:${server.status}`).join(",");
|
|
57914
57982
|
}
|
|
57983
|
+
function mcpStatusDetailList(statuses) {
|
|
57984
|
+
return statuses.map(
|
|
57985
|
+
(server) => server.error ? `${server.name}:${server.status}(${server.error})` : `${server.name}:${server.status}`
|
|
57986
|
+
).join(",");
|
|
57987
|
+
}
|
|
57915
57988
|
function delay(ms) {
|
|
57916
57989
|
return new Promise((resolve2) => {
|
|
57917
57990
|
const timer = setTimeout(resolve2, ms);
|
|
@@ -58019,6 +58092,13 @@ var ClaudeCodeCommandHandler = class {
|
|
|
58019
58092
|
agentSession = null;
|
|
58020
58093
|
persistedAgentId = null;
|
|
58021
58094
|
injectedCommands = /* @__PURE__ */ new Set();
|
|
58095
|
+
// Message commands whose injection has started but not settled. A fresh SDK
|
|
58096
|
+
// warm inside sendMessage can outlast the bridge's command-ack window, so a
|
|
58097
|
+
// redelivery may arrive while the first attempt is still in flight; acking it
|
|
58098
|
+
// "duplicate" then would let the worker accept a command whose injection
|
|
58099
|
+
// later fails, silently stalling the turn (FRA-3458). The duplicate branch
|
|
58100
|
+
// awaits the in-flight outcome here and relays it instead.
|
|
58101
|
+
inFlightMessageCommands = /* @__PURE__ */ new Map();
|
|
58022
58102
|
pendingQuestions = /* @__PURE__ */ new Map();
|
|
58023
58103
|
outputBuffer;
|
|
58024
58104
|
projector = new ClaudeCodeProjector();
|
|
@@ -58066,13 +58146,25 @@ var ClaudeCodeCommandHandler = class {
|
|
|
58066
58146
|
});
|
|
58067
58147
|
}
|
|
58068
58148
|
if (this.injectedCommands.has(delivery.commandId)) {
|
|
58149
|
+
const inFlight = this.inFlightMessageCommands.get(delivery.commandId);
|
|
58150
|
+
const outcome2 = inFlight ? await inFlight : { status: "injected" };
|
|
58069
58151
|
this.input.runtimeLogger?.info(
|
|
58070
58152
|
"agent_bridge_claude_command_duplicate",
|
|
58071
58153
|
commandLogContext(delivery, {
|
|
58072
58154
|
socket_id: socketId,
|
|
58073
|
-
duration_ms: Date.now() - startedAt
|
|
58155
|
+
duration_ms: Date.now() - startedAt,
|
|
58156
|
+
awaited_in_flight: Boolean(inFlight),
|
|
58157
|
+
in_flight_status: outcome2.status
|
|
58074
58158
|
})
|
|
58075
58159
|
);
|
|
58160
|
+
if (outcome2.status === "failed") {
|
|
58161
|
+
return commandAck({
|
|
58162
|
+
delivery,
|
|
58163
|
+
socketId,
|
|
58164
|
+
status: "failed",
|
|
58165
|
+
error: outcome2.error
|
|
58166
|
+
});
|
|
58167
|
+
}
|
|
58076
58168
|
return commandAck({
|
|
58077
58169
|
delivery,
|
|
58078
58170
|
socketId,
|
|
@@ -58123,6 +58215,53 @@ var ClaudeCodeCommandHandler = class {
|
|
|
58123
58215
|
});
|
|
58124
58216
|
}
|
|
58125
58217
|
this.injectedCommands.add(delivery.commandId);
|
|
58218
|
+
const injection = this.injectMessageCommand(
|
|
58219
|
+
activeContext,
|
|
58220
|
+
delivery,
|
|
58221
|
+
message,
|
|
58222
|
+
socketId
|
|
58223
|
+
);
|
|
58224
|
+
this.inFlightMessageCommands.set(delivery.commandId, injection);
|
|
58225
|
+
let outcome;
|
|
58226
|
+
try {
|
|
58227
|
+
outcome = await injection;
|
|
58228
|
+
} finally {
|
|
58229
|
+
this.inFlightMessageCommands.delete(delivery.commandId);
|
|
58230
|
+
}
|
|
58231
|
+
if (outcome.status === "failed") {
|
|
58232
|
+
this.injectedCommands.delete(delivery.commandId);
|
|
58233
|
+
this.input.runtimeLogger?.warn(
|
|
58234
|
+
"agent_bridge_claude_command_failed",
|
|
58235
|
+
commandLogContext(delivery, {
|
|
58236
|
+
socket_id: socketId,
|
|
58237
|
+
duration_ms: Date.now() - startedAt,
|
|
58238
|
+
error: outcome.error
|
|
58239
|
+
})
|
|
58240
|
+
);
|
|
58241
|
+
return commandAck({
|
|
58242
|
+
delivery,
|
|
58243
|
+
socketId,
|
|
58244
|
+
status: "failed",
|
|
58245
|
+
error: outcome.error
|
|
58246
|
+
});
|
|
58247
|
+
}
|
|
58248
|
+
this.input.runtimeLogger?.info(
|
|
58249
|
+
"agent_bridge_claude_command_injected",
|
|
58250
|
+
commandLogContext(delivery, {
|
|
58251
|
+
socket_id: socketId,
|
|
58252
|
+
duration_ms: Date.now() - startedAt
|
|
58253
|
+
})
|
|
58254
|
+
);
|
|
58255
|
+
return commandAck({
|
|
58256
|
+
delivery,
|
|
58257
|
+
socketId,
|
|
58258
|
+
status: "injected"
|
|
58259
|
+
});
|
|
58260
|
+
}
|
|
58261
|
+
// Runs one message command's injection to a terminal outcome. Never rejects:
|
|
58262
|
+
// the returned promise is stored in the in-flight map and awaited by both the
|
|
58263
|
+
// original delivery and any redeliveries, so failures travel as values.
|
|
58264
|
+
async injectMessageCommand(activeContext, delivery, message, socketId) {
|
|
58126
58265
|
try {
|
|
58127
58266
|
const emitStartedAt = Date.now();
|
|
58128
58267
|
this.input.runtimeLogger?.info(
|
|
@@ -58168,35 +58307,13 @@ var ClaudeCodeCommandHandler = class {
|
|
|
58168
58307
|
duration_ms: Date.now() - sendStartedAt
|
|
58169
58308
|
})
|
|
58170
58309
|
);
|
|
58310
|
+
return { status: "injected" };
|
|
58171
58311
|
} catch (error51) {
|
|
58172
|
-
|
|
58173
|
-
this.input.runtimeLogger?.warn(
|
|
58174
|
-
"agent_bridge_claude_command_failed",
|
|
58175
|
-
commandLogContext(delivery, {
|
|
58176
|
-
socket_id: socketId,
|
|
58177
|
-
duration_ms: Date.now() - startedAt,
|
|
58178
|
-
error: error51 instanceof Error ? error51.message : String(error51)
|
|
58179
|
-
})
|
|
58180
|
-
);
|
|
58181
|
-
return commandAck({
|
|
58182
|
-
delivery,
|
|
58183
|
-
socketId,
|
|
58312
|
+
return {
|
|
58184
58313
|
status: "failed",
|
|
58185
58314
|
error: error51 instanceof Error ? error51.message : String(error51)
|
|
58186
|
-
}
|
|
58315
|
+
};
|
|
58187
58316
|
}
|
|
58188
|
-
this.input.runtimeLogger?.info(
|
|
58189
|
-
"agent_bridge_claude_command_injected",
|
|
58190
|
-
commandLogContext(delivery, {
|
|
58191
|
-
socket_id: socketId,
|
|
58192
|
-
duration_ms: Date.now() - startedAt
|
|
58193
|
-
})
|
|
58194
|
-
);
|
|
58195
|
-
return commandAck({
|
|
58196
|
-
delivery,
|
|
58197
|
-
socketId,
|
|
58198
|
-
status: "injected"
|
|
58199
|
-
});
|
|
58200
58317
|
}
|
|
58201
58318
|
// -----------------------------------------------------------------------------
|
|
58202
58319
|
// Question answering
|
package/dist/index.js
CHANGED
|
@@ -20265,11 +20265,14 @@ var init_templates = __esm({
|
|
|
20265
20265
|
});
|
|
20266
20266
|
|
|
20267
20267
|
// ../../packages/schemas/src/temporal.ts
|
|
20268
|
-
var ResourceReconciliationScopeSchema;
|
|
20268
|
+
var SessionCheckTimeoutWorkflowInputSchema, ResourceReconciliationScopeSchema;
|
|
20269
20269
|
var init_temporal = __esm({
|
|
20270
20270
|
"../../packages/schemas/src/temporal.ts"() {
|
|
20271
20271
|
"use strict";
|
|
20272
20272
|
init_zod();
|
|
20273
|
+
SessionCheckTimeoutWorkflowInputSchema = external_exports.object({
|
|
20274
|
+
checkId: external_exports.string().trim().min(1)
|
|
20275
|
+
});
|
|
20273
20276
|
ResourceReconciliationScopeSchema = external_exports.object({
|
|
20274
20277
|
organizationId: external_exports.string().trim().min(1),
|
|
20275
20278
|
projectId: external_exports.string().trim().min(1).nullable()
|
|
@@ -20278,7 +20281,7 @@ var init_temporal = __esm({
|
|
|
20278
20281
|
});
|
|
20279
20282
|
|
|
20280
20283
|
// ../../packages/schemas/src/usage.ts
|
|
20281
|
-
var UsageHarnessSchema, ModelCredentialFundingSourceSchema, NonNegativeTokenCountSchema, NonNegativeUsdSchema, UsageEventSchema, UsageEventRecordSchema, UsageTotalsSchema, SessionUsageModelSummarySchema, SessionUsageResponseSchema;
|
|
20284
|
+
var UsageHarnessSchema, ModelCredentialFundingSourceSchema, NonNegativeTokenCountSchema, NonNegativeUsdSchema, UsageEventSchema, UsageEventRecordSchema, UsageTotalsSchema, SessionUsageModelSummarySchema, SessionUsageResponseSchema, PROJECT_USAGE_RANGE_KEYS, ProjectUsageRangeKeySchema, UtcDateSchema, ProjectUsageTotalsSchema, ProjectUsageAgentSummarySchema, ProjectUsageModelSummarySchema, ProjectUsageDayPointSchema, ProjectUsageResponseSchema;
|
|
20282
20285
|
var init_usage = __esm({
|
|
20283
20286
|
"../../packages/schemas/src/usage.ts"() {
|
|
20284
20287
|
"use strict";
|
|
@@ -20345,6 +20348,42 @@ var init_usage = __esm({
|
|
|
20345
20348
|
firstUsageAt: external_exports.string().datetime().nullable(),
|
|
20346
20349
|
lastUsageAt: external_exports.string().datetime().nullable()
|
|
20347
20350
|
});
|
|
20351
|
+
PROJECT_USAGE_RANGE_KEYS = ["7d", "30d"];
|
|
20352
|
+
ProjectUsageRangeKeySchema = external_exports.enum(PROJECT_USAGE_RANGE_KEYS);
|
|
20353
|
+
UtcDateSchema = external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
20354
|
+
ProjectUsageTotalsSchema = UsageTotalsSchema.extend({
|
|
20355
|
+
sessionCount: NonNegativeTokenCountSchema,
|
|
20356
|
+
// Share of all tokens served from prompt-cache reads (0..1); 0 when the
|
|
20357
|
+
// window has no tokens at all.
|
|
20358
|
+
cacheReadShare: external_exports.number().min(0).max(1)
|
|
20359
|
+
});
|
|
20360
|
+
ProjectUsageAgentSummarySchema = UsageTotalsSchema.extend({
|
|
20361
|
+
agentResourceId: external_exports.string().trim().min(1),
|
|
20362
|
+
// Resolved from the agent resource (archived agents included); null only
|
|
20363
|
+
// when the agent row no longer exists at all — the ledger deliberately
|
|
20364
|
+
// outlives its attribution targets.
|
|
20365
|
+
agentName: external_exports.string().trim().min(1).nullable(),
|
|
20366
|
+
sessionCount: NonNegativeTokenCountSchema
|
|
20367
|
+
});
|
|
20368
|
+
ProjectUsageModelSummarySchema = UsageTotalsSchema.extend({
|
|
20369
|
+
model: external_exports.string().trim().min(1)
|
|
20370
|
+
});
|
|
20371
|
+
ProjectUsageDayPointSchema = UsageTotalsSchema.extend({
|
|
20372
|
+
date: UtcDateSchema
|
|
20373
|
+
});
|
|
20374
|
+
ProjectUsageResponseSchema = external_exports.object({
|
|
20375
|
+
organizationId: OrganizationIdSchema,
|
|
20376
|
+
projectId: ProjectIdSchema,
|
|
20377
|
+
range: external_exports.object({
|
|
20378
|
+
key: ProjectUsageRangeKeySchema,
|
|
20379
|
+
since: external_exports.string().datetime(),
|
|
20380
|
+
until: external_exports.string().datetime()
|
|
20381
|
+
}),
|
|
20382
|
+
totals: ProjectUsageTotalsSchema,
|
|
20383
|
+
byAgent: external_exports.array(ProjectUsageAgentSummarySchema),
|
|
20384
|
+
byModel: external_exports.array(ProjectUsageModelSummarySchema),
|
|
20385
|
+
daily: external_exports.array(ProjectUsageDayPointSchema)
|
|
20386
|
+
});
|
|
20348
20387
|
}
|
|
20349
20388
|
});
|
|
20350
20389
|
|
|
@@ -23134,7 +23173,7 @@ var init_package = __esm({
|
|
|
23134
23173
|
"package.json"() {
|
|
23135
23174
|
package_default = {
|
|
23136
23175
|
name: "@autohq/cli",
|
|
23137
|
-
version: "0.1.
|
|
23176
|
+
version: "0.1.288",
|
|
23138
23177
|
license: "SEE LICENSE IN README.md",
|
|
23139
23178
|
publishConfig: {
|
|
23140
23179
|
access: "public"
|
|
@@ -34750,6 +34789,12 @@ var claudeAgentBridgeRuntime = {
|
|
|
34750
34789
|
var claudeAgentSdkRuntime = {
|
|
34751
34790
|
startup: (input) => startupClaudeAgent(input)
|
|
34752
34791
|
};
|
|
34792
|
+
var ClaudeMcpRegistryEmptyError = class extends Error {
|
|
34793
|
+
constructor(detail) {
|
|
34794
|
+
super(`MCP tool registry came up empty at session start: ${detail}`);
|
|
34795
|
+
this.name = "ClaudeMcpRegistryEmptyError";
|
|
34796
|
+
}
|
|
34797
|
+
};
|
|
34753
34798
|
var ClaudeAgentBridgeSessionImpl = class {
|
|
34754
34799
|
input;
|
|
34755
34800
|
inputQueue;
|
|
@@ -35139,17 +35184,20 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
35139
35184
|
}
|
|
35140
35185
|
// Why this gate is correct without a provider-backed test (it relies on real
|
|
35141
35186
|
// SDK mcpServerStatus() timing that fakes cannot prove):
|
|
35142
|
-
// - Safe-degrade: pollMcpRegistration never rejects — on
|
|
35143
|
-
// status-read failure, or a closed session it resolves, so
|
|
35144
|
-
//
|
|
35145
|
-
//
|
|
35187
|
+
// - Safe-degrade on uncertainty: pollMcpRegistration never rejects — on
|
|
35188
|
+
// timeout, a status-read failure, or a closed session it resolves, so an
|
|
35189
|
+
// *unconfirmed* registry still degrades to today's immediate injection.
|
|
35190
|
+
// The one fail-closed exit is the confirmed-empty registry: every
|
|
35191
|
+
// configured server settled and none is serving tools, which is exactly
|
|
35192
|
+
// the state that produced silent toolless runs in production (FRA-3458).
|
|
35146
35193
|
// - Provider-path validation is deferred deliberately: the failure is the
|
|
35147
35194
|
// intermittent live-prod race on the chief-of-staff singleton (a real
|
|
35148
35195
|
// runtime restart dispatching turn-1 while real mcp__* servers reconnect),
|
|
35149
35196
|
// which cannot be reproduced deterministically without live credentials
|
|
35150
35197
|
// and a forced restart racing reconnect.
|
|
35151
35198
|
// - Live confirmation comes from the agent_bridge_claude_mcp_gate_started/
|
|
35152
|
-
// _ready/_timeout diagnostics on the next real restart, not a CI
|
|
35199
|
+
// _ready/_timeout/_empty diagnostics on the next real restart, not a CI
|
|
35200
|
+
// fake.
|
|
35153
35201
|
//
|
|
35154
35202
|
// Block until the freshly-warmed query's MCP servers have left `pending`, so
|
|
35155
35203
|
// the first turn's prompt is built with the mcp__* tools registered. Memoized
|
|
@@ -35173,15 +35221,22 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
35173
35221
|
promise: this.pollMcpRegistration(query)
|
|
35174
35222
|
};
|
|
35175
35223
|
}
|
|
35176
|
-
await this.mcpRegistrationGate.promise;
|
|
35224
|
+
const result = await this.mcpRegistrationGate.promise;
|
|
35225
|
+
if (result.outcome !== "empty") {
|
|
35226
|
+
return;
|
|
35227
|
+
}
|
|
35228
|
+
this.close();
|
|
35229
|
+
throw new ClaudeMcpRegistryEmptyError(result.detail);
|
|
35177
35230
|
}
|
|
35178
35231
|
// Poll the live query's MCP server status until no configured server is still
|
|
35179
35232
|
// `pending`, bounded by CLAUDE_MCP_REGISTRATION_TIMEOUT_MS. Terminal states
|
|
35180
35233
|
// (connected/failed/needs-auth/disabled) all count as settled, so a server
|
|
35181
35234
|
// that cannot connect in this runtime (e.g. an interactively-authed server in
|
|
35182
|
-
// a headless sandbox) never holds the gate to the timeout.
|
|
35235
|
+
// a headless sandbox) never holds the gate to the timeout. A settled state
|
|
35236
|
+
// where no configured server is serving tools resolves "empty" — the caller
|
|
35237
|
+
// fails the send rather than injecting a toolless turn. Never rejects:
|
|
35183
35238
|
// status-read failure, timeout, or a closed session all resolve so the caller
|
|
35184
|
-
// degrades to immediate injection.
|
|
35239
|
+
// degrades to immediate injection when the registry state is uncertain.
|
|
35185
35240
|
async pollMcpRegistration(query) {
|
|
35186
35241
|
const configuredNames = Object.keys(this.options.mcpServers ?? {});
|
|
35187
35242
|
const startedAt = Date.now();
|
|
@@ -35191,7 +35246,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
35191
35246
|
);
|
|
35192
35247
|
while (true) {
|
|
35193
35248
|
if (this.state.kind === "closed") {
|
|
35194
|
-
return;
|
|
35249
|
+
return { outcome: "closed" };
|
|
35195
35250
|
}
|
|
35196
35251
|
let statuses;
|
|
35197
35252
|
try {
|
|
@@ -35200,19 +35255,26 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
35200
35255
|
this.input.writeOutput?.(
|
|
35201
35256
|
`agent_bridge_claude_mcp_gate_status_failed duration_ms=${Date.now() - startedAt} error=${error51 instanceof Error ? error51.message : String(error51)}`
|
|
35202
35257
|
);
|
|
35203
|
-
return;
|
|
35258
|
+
return { outcome: "status_failed" };
|
|
35204
35259
|
}
|
|
35205
35260
|
if (mcpServersSettled(statuses, configuredNames)) {
|
|
35261
|
+
if (!mcpRegistryHasTools(statuses, configuredNames)) {
|
|
35262
|
+
const detail = mcpStatusDetailList(statuses);
|
|
35263
|
+
this.input.writeOutput?.(
|
|
35264
|
+
`agent_bridge_claude_mcp_gate_empty duration_ms=${Date.now() - startedAt} servers=${detail}`
|
|
35265
|
+
);
|
|
35266
|
+
return { outcome: "empty", detail };
|
|
35267
|
+
}
|
|
35206
35268
|
this.input.writeOutput?.(
|
|
35207
35269
|
`agent_bridge_claude_mcp_gate_ready duration_ms=${Date.now() - startedAt} servers=${mcpStatusList(statuses)}`
|
|
35208
35270
|
);
|
|
35209
|
-
return;
|
|
35271
|
+
return { outcome: "ready" };
|
|
35210
35272
|
}
|
|
35211
35273
|
if (Date.now() >= deadline) {
|
|
35212
35274
|
this.input.writeOutput?.(
|
|
35213
35275
|
`agent_bridge_claude_mcp_gate_timeout duration_ms=${Date.now() - startedAt} servers=${mcpStatusList(statuses)}`
|
|
35214
35276
|
);
|
|
35215
|
-
return;
|
|
35277
|
+
return { outcome: "timeout" };
|
|
35216
35278
|
}
|
|
35217
35279
|
await delay(CLAUDE_MCP_REGISTRATION_POLL_INTERVAL_MS);
|
|
35218
35280
|
}
|
|
@@ -35355,9 +35417,20 @@ function mcpServersSettled(statuses, configuredNames) {
|
|
|
35355
35417
|
return status !== void 0 && status !== "pending";
|
|
35356
35418
|
});
|
|
35357
35419
|
}
|
|
35420
|
+
function mcpRegistryHasTools(statuses, configuredNames) {
|
|
35421
|
+
const configured = new Set(configuredNames);
|
|
35422
|
+
return statuses.some(
|
|
35423
|
+
(server) => configured.has(server.name) && server.status === "connected" && (server.tools === void 0 || server.tools.length > 0)
|
|
35424
|
+
);
|
|
35425
|
+
}
|
|
35358
35426
|
function mcpStatusList(statuses) {
|
|
35359
35427
|
return statuses.map((server) => `${server.name}:${server.status}`).join(",");
|
|
35360
35428
|
}
|
|
35429
|
+
function mcpStatusDetailList(statuses) {
|
|
35430
|
+
return statuses.map(
|
|
35431
|
+
(server) => server.error ? `${server.name}:${server.status}(${server.error})` : `${server.name}:${server.status}`
|
|
35432
|
+
).join(",");
|
|
35433
|
+
}
|
|
35361
35434
|
function delay(ms) {
|
|
35362
35435
|
return new Promise((resolve4) => {
|
|
35363
35436
|
const timer = setTimeout(resolve4, ms);
|
|
@@ -35465,6 +35538,13 @@ var ClaudeCodeCommandHandler = class {
|
|
|
35465
35538
|
agentSession = null;
|
|
35466
35539
|
persistedAgentId = null;
|
|
35467
35540
|
injectedCommands = /* @__PURE__ */ new Set();
|
|
35541
|
+
// Message commands whose injection has started but not settled. A fresh SDK
|
|
35542
|
+
// warm inside sendMessage can outlast the bridge's command-ack window, so a
|
|
35543
|
+
// redelivery may arrive while the first attempt is still in flight; acking it
|
|
35544
|
+
// "duplicate" then would let the worker accept a command whose injection
|
|
35545
|
+
// later fails, silently stalling the turn (FRA-3458). The duplicate branch
|
|
35546
|
+
// awaits the in-flight outcome here and relays it instead.
|
|
35547
|
+
inFlightMessageCommands = /* @__PURE__ */ new Map();
|
|
35468
35548
|
pendingQuestions = /* @__PURE__ */ new Map();
|
|
35469
35549
|
outputBuffer;
|
|
35470
35550
|
projector = new ClaudeCodeProjector();
|
|
@@ -35512,13 +35592,25 @@ var ClaudeCodeCommandHandler = class {
|
|
|
35512
35592
|
});
|
|
35513
35593
|
}
|
|
35514
35594
|
if (this.injectedCommands.has(delivery.commandId)) {
|
|
35595
|
+
const inFlight = this.inFlightMessageCommands.get(delivery.commandId);
|
|
35596
|
+
const outcome2 = inFlight ? await inFlight : { status: "injected" };
|
|
35515
35597
|
this.input.runtimeLogger?.info(
|
|
35516
35598
|
"agent_bridge_claude_command_duplicate",
|
|
35517
35599
|
commandLogContext(delivery, {
|
|
35518
35600
|
socket_id: socketId,
|
|
35519
|
-
duration_ms: Date.now() - startedAt
|
|
35601
|
+
duration_ms: Date.now() - startedAt,
|
|
35602
|
+
awaited_in_flight: Boolean(inFlight),
|
|
35603
|
+
in_flight_status: outcome2.status
|
|
35520
35604
|
})
|
|
35521
35605
|
);
|
|
35606
|
+
if (outcome2.status === "failed") {
|
|
35607
|
+
return commandAck({
|
|
35608
|
+
delivery,
|
|
35609
|
+
socketId,
|
|
35610
|
+
status: "failed",
|
|
35611
|
+
error: outcome2.error
|
|
35612
|
+
});
|
|
35613
|
+
}
|
|
35522
35614
|
return commandAck({
|
|
35523
35615
|
delivery,
|
|
35524
35616
|
socketId,
|
|
@@ -35569,6 +35661,53 @@ var ClaudeCodeCommandHandler = class {
|
|
|
35569
35661
|
});
|
|
35570
35662
|
}
|
|
35571
35663
|
this.injectedCommands.add(delivery.commandId);
|
|
35664
|
+
const injection = this.injectMessageCommand(
|
|
35665
|
+
activeContext,
|
|
35666
|
+
delivery,
|
|
35667
|
+
message,
|
|
35668
|
+
socketId
|
|
35669
|
+
);
|
|
35670
|
+
this.inFlightMessageCommands.set(delivery.commandId, injection);
|
|
35671
|
+
let outcome;
|
|
35672
|
+
try {
|
|
35673
|
+
outcome = await injection;
|
|
35674
|
+
} finally {
|
|
35675
|
+
this.inFlightMessageCommands.delete(delivery.commandId);
|
|
35676
|
+
}
|
|
35677
|
+
if (outcome.status === "failed") {
|
|
35678
|
+
this.injectedCommands.delete(delivery.commandId);
|
|
35679
|
+
this.input.runtimeLogger?.warn(
|
|
35680
|
+
"agent_bridge_claude_command_failed",
|
|
35681
|
+
commandLogContext(delivery, {
|
|
35682
|
+
socket_id: socketId,
|
|
35683
|
+
duration_ms: Date.now() - startedAt,
|
|
35684
|
+
error: outcome.error
|
|
35685
|
+
})
|
|
35686
|
+
);
|
|
35687
|
+
return commandAck({
|
|
35688
|
+
delivery,
|
|
35689
|
+
socketId,
|
|
35690
|
+
status: "failed",
|
|
35691
|
+
error: outcome.error
|
|
35692
|
+
});
|
|
35693
|
+
}
|
|
35694
|
+
this.input.runtimeLogger?.info(
|
|
35695
|
+
"agent_bridge_claude_command_injected",
|
|
35696
|
+
commandLogContext(delivery, {
|
|
35697
|
+
socket_id: socketId,
|
|
35698
|
+
duration_ms: Date.now() - startedAt
|
|
35699
|
+
})
|
|
35700
|
+
);
|
|
35701
|
+
return commandAck({
|
|
35702
|
+
delivery,
|
|
35703
|
+
socketId,
|
|
35704
|
+
status: "injected"
|
|
35705
|
+
});
|
|
35706
|
+
}
|
|
35707
|
+
// Runs one message command's injection to a terminal outcome. Never rejects:
|
|
35708
|
+
// the returned promise is stored in the in-flight map and awaited by both the
|
|
35709
|
+
// original delivery and any redeliveries, so failures travel as values.
|
|
35710
|
+
async injectMessageCommand(activeContext, delivery, message, socketId) {
|
|
35572
35711
|
try {
|
|
35573
35712
|
const emitStartedAt = Date.now();
|
|
35574
35713
|
this.input.runtimeLogger?.info(
|
|
@@ -35614,35 +35753,13 @@ var ClaudeCodeCommandHandler = class {
|
|
|
35614
35753
|
duration_ms: Date.now() - sendStartedAt
|
|
35615
35754
|
})
|
|
35616
35755
|
);
|
|
35756
|
+
return { status: "injected" };
|
|
35617
35757
|
} catch (error51) {
|
|
35618
|
-
|
|
35619
|
-
this.input.runtimeLogger?.warn(
|
|
35620
|
-
"agent_bridge_claude_command_failed",
|
|
35621
|
-
commandLogContext(delivery, {
|
|
35622
|
-
socket_id: socketId,
|
|
35623
|
-
duration_ms: Date.now() - startedAt,
|
|
35624
|
-
error: error51 instanceof Error ? error51.message : String(error51)
|
|
35625
|
-
})
|
|
35626
|
-
);
|
|
35627
|
-
return commandAck({
|
|
35628
|
-
delivery,
|
|
35629
|
-
socketId,
|
|
35758
|
+
return {
|
|
35630
35759
|
status: "failed",
|
|
35631
35760
|
error: error51 instanceof Error ? error51.message : String(error51)
|
|
35632
|
-
}
|
|
35761
|
+
};
|
|
35633
35762
|
}
|
|
35634
|
-
this.input.runtimeLogger?.info(
|
|
35635
|
-
"agent_bridge_claude_command_injected",
|
|
35636
|
-
commandLogContext(delivery, {
|
|
35637
|
-
socket_id: socketId,
|
|
35638
|
-
duration_ms: Date.now() - startedAt
|
|
35639
|
-
})
|
|
35640
|
-
);
|
|
35641
|
-
return commandAck({
|
|
35642
|
-
delivery,
|
|
35643
|
-
socketId,
|
|
35644
|
-
status: "injected"
|
|
35645
|
-
});
|
|
35646
35763
|
}
|
|
35647
35764
|
// -----------------------------------------------------------------------------
|
|
35648
35765
|
// Question answering
|