@agentproto/runtime 5.7.0 → 5.8.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/config-schema.mjs.map +1 -1
- package/dist/config.mjs.map +1 -1
- package/dist/index.d.ts +16 -2
- package/dist/index.mjs +196 -23
- package/dist/index.mjs.map +1 -1
- package/dist/session-presence.mjs.map +1 -1
- package/dist/{sessions-DHSLsPHA.d.ts → sessions-SrISpFsH.d.ts} +11 -0
- package/dist/user-presets.d.ts +1 -1
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { h as WorktreeIsolationMode, i as SpawnAttachMode, j as SpawnDedupeMode,
|
|
|
3
3
|
export { k as DEFAULT_MODEL_ROLES, M as MODEL_ROLE_REF_PREFIX, l as ModelRoleContext, m as ModelRoleEntry, n as ModelRoleSource, o as ModelRoleValue, p as ModelRolesConfig, q as listModelRoles, r as parseModelRoleRef, s as resolveModelRole } from './config-Gz7q9yfJ.js';
|
|
4
4
|
import { B as BuildHeartbeatAgent } from './heartbeat-BJtxbDb9.js';
|
|
5
5
|
export { H as HeartbeatAgent, a as HeartbeatRunner, R as RuntimeEvent, b as RuntimeEvents, p as parseDuration } from './heartbeat-BJtxbDb9.js';
|
|
6
|
-
import { M as MessageUrgency, S as SessionEvent, a as SessionEventType, b as SessionEventBus, c as SessionsRegistry, C as CompletionPolicySupervisor, T as TaskLedger, d as SessionDescriptor, e as SessionEndReason, A as ActivityPolicySlice, f as ActivityListFilter, g as ActivityRecord, h as ActivityTurnSession, i as ActivityPrSession, j as ActivityWorkflowRunSlice, P as PrResolvedState, k as ActivityTaskSlice, W as WorktreeProvisioner, l as AgentsMdResolution, U as UserPreset, R as RestartPolicy, m as SandboxAppServeSpec, n as WorktreeField, o as AgentSessionLike, p as UsageReadContext, q as UsageReadResult, r as MessageKind, s as SessionMessage, t as AgentStreamEvent, u as SessionUsage, v as ToolCallRecord, w as StatsSessionDescriptor, x as ProcRow, y as ProvisionInFlight, z as ProvisionTracker, B as UsageRollup, D as RemainingQuotaReader, Q as QuotaReadableProfile, E as UsageSnapshotRecord, F as SessionAwaitingQuestion, G as PolicyRunState, H as PtyFactory, I as WorktreeAutoReclaimer } from './sessions-
|
|
7
|
-
export { J as ActivityKind, K as ActivitySource, L as ActivityState, N as ActivityWaitingOn, O as AnthropicReaderConfig, V as AnthropicRemainingQuotaReader, X as AttachPolicyInput, Y as CommandGroupStats, Z as CommitSpec, _ as DEFAULT_WORKTREE_ISOLATION, $ as DEFAULT_WORKTREE_PROVISION_CONCURRENCY, a0 as EagerResumeFailReason, a1 as EagerResumeOutcome, a2 as EagerResumeSkipReason, a3 as GateSpec, a4 as HostInfo, a5 as JudgeGateSpec, a6 as LabeledProcessStatsReport, a7 as LabeledSessionStats, a8 as MAX_MESSAGE_DATA_BYTES, a9 as MESSAGE_KINDS, aa as MESSAGE_PREAMBLE, ab as MESSAGE_TAG, ac as MESSAGE_URGENCIES, ad as MessageDeliveryVia, ae as MessageFilter, af as MessageRelation, ag as MessageTreeNode, ah as OnFailSpec, ai as OrphanGroup, aj as PendingPermission, ak as PermissionRespondInput, al as PermissionRespondResult, am as PolicyRunStatus, an as PricingResolver, ao as ProcessDetail, ap as ProcessStatsReport, aq as ProcessStatsService, ar as QuotaStoreFile, as as QuotaStoreOptions, at as RegisterBrowserInput, au as RegisterSessionInput, av as RemainingQuota, aw as ResourceStats, ax as ResumeDisabledError, ay as SESSION_END_REASONS, az as SESSION_ID_ENV, aA as SessionCurrentPhase, aB as SessionKind, aC as SessionMessageFrom, aD as SessionOutcome, aE as SessionOutcomeArtifact, aF as SessionOutcomeCompact, aG as SessionOutcomeLink, aH as SessionResourceStats, aI as SessionSnapshots, aJ as SessionStatus, aK as ShellGateSpec, aL as SpawnAgentInput, aM as SpawnSessionInput, aN as StatsDetail, aO as StoredProfileQuota, aP as TASK_STATUSES, aQ as TaskCaller, aR as TaskChangedEvent, aS as TaskClaimInput, aT as TaskCreateInput, aU as TaskGateOutcome, aV as TaskGateRunner, aW as TaskLedgerRegistry, aX as TaskLedgerSessionSlice, aY as TaskListFilter, aZ as TaskRecord, a_ as TaskStatus, a$ as TaskUpdateInput, b0 as TaskVerification, b1 as TaskVerifySupervisor, b2 as TaskWriteResult, b3 as TokenPricing, b4 as UsageBucket, b5 as UsageComputeInput, b6 as UsageDetail, b7 as UsageSource, b8 as UserPresetsFile, b9 as WORKSPACE_SLUG_ENV, ba as WORKTREE_ISOLATION_ENV, bb as WORKTREE_PROVISION_CONCURRENCY_ENV, bc as WorktreeDecision, bd as WorktreeProvisionOutcome, be as WorktreeProvisionPhase, bf as WorktreeProvisionProgress, bg as WorktreeProvisionRequest, bh as WorktreeRequest, bi as activityCounts, bj as compactOutcome, bk as createProcessStatsService, bl as createSessionMessage, bm as createSupervisorTaskGateRunner, bn as createTaskLedger, bo as decideWorktreeIsolation, bp as deleteUserPreset, bq as deriveSessionOutcome, br as deriveSessionUsage, bs as escapeHumanPrompt, bt as escapeMessageBody, bu as filterActivities, bv as getProcessStatsService, bw as getUserPreset, bx as isClosedTaskStatus, by as isKnownSessionEndReason, bz as isMessageAllowed, bA as isProviderLimitError, bB as isTerminalActivityState, bC as listUserPresets, bD as loadQuotaStore, bE as loadUserPresets, bF as loadWorktreeIsolation, bG as matchesMessageFilter, bH as messageFrom, bI as mintMessageId, bJ as normalizeCommand, bK as normalizeWorktreeField, bL as parseAnthropicRateLimitHeaders, bM as parseTaskStatus, bN as parseWindow, bO as parseWorktreeIsolationMode, bP as pickUsageDetail, bQ as policyToActivities, bR as policyWatchesSession, bS as prToActivities, bT as projectSessionUsage, bU as readProfileQuota, bV as recordProfileQuota, bW as renderInboxDigest, bX as renderSessionMessage, bY as renderSessionMessages, bZ as resolveRelation, b_ as rollupUsage, b$ as sanitizeLabel, c0 as saveUserPreset, c1 as trackWorktreeProvision, c2 as turnToActivities, c3 as userPresetsPath, c4 as workflowToActivities } from './sessions-
|
|
6
|
+
import { M as MessageUrgency, S as SessionEvent, a as SessionEventType, b as SessionEventBus, c as SessionsRegistry, C as CompletionPolicySupervisor, T as TaskLedger, d as SessionDescriptor, e as SessionEndReason, A as ActivityPolicySlice, f as ActivityListFilter, g as ActivityRecord, h as ActivityTurnSession, i as ActivityPrSession, j as ActivityWorkflowRunSlice, P as PrResolvedState, k as ActivityTaskSlice, W as WorktreeProvisioner, l as AgentsMdResolution, U as UserPreset, R as RestartPolicy, m as SandboxAppServeSpec, n as WorktreeField, o as AgentSessionLike, p as UsageReadContext, q as UsageReadResult, r as MessageKind, s as SessionMessage, t as AgentStreamEvent, u as SessionUsage, v as ToolCallRecord, w as StatsSessionDescriptor, x as ProcRow, y as ProvisionInFlight, z as ProvisionTracker, B as UsageRollup, D as RemainingQuotaReader, Q as QuotaReadableProfile, E as UsageSnapshotRecord, F as SessionAwaitingQuestion, G as PolicyRunState, H as PtyFactory, I as WorktreeAutoReclaimer } from './sessions-SrISpFsH.js';
|
|
7
|
+
export { J as ActivityKind, K as ActivitySource, L as ActivityState, N as ActivityWaitingOn, O as AnthropicReaderConfig, V as AnthropicRemainingQuotaReader, X as AttachPolicyInput, Y as CommandGroupStats, Z as CommitSpec, _ as DEFAULT_WORKTREE_ISOLATION, $ as DEFAULT_WORKTREE_PROVISION_CONCURRENCY, a0 as EagerResumeFailReason, a1 as EagerResumeOutcome, a2 as EagerResumeSkipReason, a3 as GateSpec, a4 as HostInfo, a5 as JudgeGateSpec, a6 as LabeledProcessStatsReport, a7 as LabeledSessionStats, a8 as MAX_MESSAGE_DATA_BYTES, a9 as MESSAGE_KINDS, aa as MESSAGE_PREAMBLE, ab as MESSAGE_TAG, ac as MESSAGE_URGENCIES, ad as MessageDeliveryVia, ae as MessageFilter, af as MessageRelation, ag as MessageTreeNode, ah as OnFailSpec, ai as OrphanGroup, aj as PendingPermission, ak as PermissionRespondInput, al as PermissionRespondResult, am as PolicyRunStatus, an as PricingResolver, ao as ProcessDetail, ap as ProcessStatsReport, aq as ProcessStatsService, ar as QuotaStoreFile, as as QuotaStoreOptions, at as RegisterBrowserInput, au as RegisterSessionInput, av as RemainingQuota, aw as ResourceStats, ax as ResumeDisabledError, ay as SESSION_END_REASONS, az as SESSION_ID_ENV, aA as SessionCurrentPhase, aB as SessionKind, aC as SessionMessageFrom, aD as SessionOutcome, aE as SessionOutcomeArtifact, aF as SessionOutcomeCompact, aG as SessionOutcomeLink, aH as SessionResourceStats, aI as SessionSnapshots, aJ as SessionStatus, aK as ShellGateSpec, aL as SpawnAgentInput, aM as SpawnSessionInput, aN as StatsDetail, aO as StoredProfileQuota, aP as TASK_STATUSES, aQ as TaskCaller, aR as TaskChangedEvent, aS as TaskClaimInput, aT as TaskCreateInput, aU as TaskGateOutcome, aV as TaskGateRunner, aW as TaskLedgerRegistry, aX as TaskLedgerSessionSlice, aY as TaskListFilter, aZ as TaskRecord, a_ as TaskStatus, a$ as TaskUpdateInput, b0 as TaskVerification, b1 as TaskVerifySupervisor, b2 as TaskWriteResult, b3 as TokenPricing, b4 as UsageBucket, b5 as UsageComputeInput, b6 as UsageDetail, b7 as UsageSource, b8 as UserPresetsFile, b9 as WORKSPACE_SLUG_ENV, ba as WORKTREE_ISOLATION_ENV, bb as WORKTREE_PROVISION_CONCURRENCY_ENV, bc as WorktreeDecision, bd as WorktreeProvisionOutcome, be as WorktreeProvisionPhase, bf as WorktreeProvisionProgress, bg as WorktreeProvisionRequest, bh as WorktreeRequest, bi as activityCounts, bj as compactOutcome, bk as createProcessStatsService, bl as createSessionMessage, bm as createSupervisorTaskGateRunner, bn as createTaskLedger, bo as decideWorktreeIsolation, bp as deleteUserPreset, bq as deriveSessionOutcome, br as deriveSessionUsage, bs as escapeHumanPrompt, bt as escapeMessageBody, bu as filterActivities, bv as getProcessStatsService, bw as getUserPreset, bx as isClosedTaskStatus, by as isKnownSessionEndReason, bz as isMessageAllowed, bA as isProviderLimitError, bB as isTerminalActivityState, bC as listUserPresets, bD as loadQuotaStore, bE as loadUserPresets, bF as loadWorktreeIsolation, bG as matchesMessageFilter, bH as messageFrom, bI as mintMessageId, bJ as normalizeCommand, bK as normalizeWorktreeField, bL as parseAnthropicRateLimitHeaders, bM as parseTaskStatus, bN as parseWindow, bO as parseWorktreeIsolationMode, bP as pickUsageDetail, bQ as policyToActivities, bR as policyWatchesSession, bS as prToActivities, bT as projectSessionUsage, bU as readProfileQuota, bV as recordProfileQuota, bW as renderInboxDigest, bX as renderSessionMessage, bY as renderSessionMessages, bZ as resolveRelation, b_ as rollupUsage, b$ as sanitizeLabel, c0 as saveUserPreset, c1 as trackWorktreeProvision, c2 as turnToActivities, c3 as userPresetsPath, c4 as workflowToActivities } from './sessions-SrISpFsH.js';
|
|
8
8
|
import { R as RouteSpec, P as Posture, C as ContextProfile, a as CanonicalPosture } from './session-config-DxIIuJFY.js';
|
|
9
9
|
export { A as AuthMethod, D as DeclaredAdapterMode, E as EffortLevel, S as SessionConfig, c as composeMode, d as decomposeMode } from './session-config-DxIIuJFY.js';
|
|
10
10
|
import { AcpMcpServer } from '@agentproto/acp';
|
|
@@ -2201,6 +2201,12 @@ interface SpawnAgentSessionDeps {
|
|
|
2201
2201
|
* tool and HTTP route each have their own "not enabled" response
|
|
2202
2202
|
* shape for the missing-resolver case). */
|
|
2203
2203
|
resolveAgentAdapter: AgentAdapterResolver;
|
|
2204
|
+
/** Installed-adapter lister — ONLY used to enumerate the valid slugs in
|
|
2205
|
+
* the generic `adapter_not_found` error, so a genuinely unknown adapter
|
|
2206
|
+
* name names what IS installed instead of just saying "install it".
|
|
2207
|
+
* Omitted ⇒ the error keeps its previous wording. Mirrors
|
|
2208
|
+
* `CronAdapterCheckDeps.listAgentAdapters` (cron's create-time check). */
|
|
2209
|
+
listAgentAdapters?: AgentAdapterLister;
|
|
2204
2210
|
/** Optional orchestrator-injection builder (WP3). See
|
|
2205
2211
|
* `RegisterAgentToolsOptions.buildOrchestratorMcp` for the full
|
|
2206
2212
|
* contract. Omitted → `orchestrator` is rejected with
|
|
@@ -3819,6 +3825,10 @@ type GhRunner$1 = (args: readonly string[], cwd: string) => Promise<{
|
|
|
3819
3825
|
* B. BRANCH — resolve the OPEN PR for the session cwd's current branch
|
|
3820
3826
|
* (via the injected {@link OpenPrResolver} port), the fallback for
|
|
3821
3827
|
* adapters whose tool calls aren't recorded.
|
|
3828
|
+
* C. TEXTUAL — pull-request urls mentioned in the session's own assistant
|
|
3829
|
+
* output (bounded transcript-tail scan); records on `openedPrs`
|
|
3830
|
+
* (adapter "output-scan") but never stamps a footer — a mention is
|
|
3831
|
+
* not proof of creation.
|
|
3822
3832
|
*
|
|
3823
3833
|
* Turn-end/exit are only poll checkpoints, never an assertion the PR is
|
|
3824
3834
|
* ready: the real predicate is "did this session create a PR / does an open
|
|
@@ -3855,6 +3865,10 @@ interface ReconcilerSession extends FooterSession {
|
|
|
3855
3865
|
url: string;
|
|
3856
3866
|
number?: number;
|
|
3857
3867
|
}[];
|
|
3868
|
+
/** Ephemeral transcript path the live registry stamps on every read
|
|
3869
|
+
* (see `SessionDescriptor.eventsPath`); lane C's bounded tail read
|
|
3870
|
+
* needs it. Absent from test fakes without a transcript on disk. */
|
|
3871
|
+
eventsPath?: string;
|
|
3858
3872
|
}
|
|
3859
3873
|
/** The registry slice the reconciler needs — structurally satisfied by the full
|
|
3860
3874
|
* `SessionsRegistry`, and by a trivial fake in tests. It is also a valid
|
package/dist/index.mjs
CHANGED
|
@@ -9046,6 +9046,20 @@ var init_mcp_credential_deps = __esm({
|
|
|
9046
9046
|
});
|
|
9047
9047
|
|
|
9048
9048
|
// src/sandbox-agent-session-proxy.ts
|
|
9049
|
+
function stripAnsiCodes(s) {
|
|
9050
|
+
return s.replace(/\x1b\[[0-9;?]*[A-Za-z]/g, "");
|
|
9051
|
+
}
|
|
9052
|
+
async function* harvestHostErrorNotice(host, remoteSessionId) {
|
|
9053
|
+
let tail;
|
|
9054
|
+
try {
|
|
9055
|
+
tail = await host.output(remoteSessionId, MAX_OUTPUT_LINES);
|
|
9056
|
+
} catch {
|
|
9057
|
+
return;
|
|
9058
|
+
}
|
|
9059
|
+
const lines = tail.split(/\r?\n/).map((l) => stripAnsiCodes(l).trim()).filter((l) => l.length > 0 && HOST_ERROR_LINE_RE.test(l));
|
|
9060
|
+
if (lines.length === 0) return;
|
|
9061
|
+
yield { kind: "notice", text: lines.join("\n") };
|
|
9062
|
+
}
|
|
9049
9063
|
function extractPromptText(message) {
|
|
9050
9064
|
if (typeof message === "string") return message;
|
|
9051
9065
|
if (message && typeof message === "object" && "text" in message) {
|
|
@@ -9168,13 +9182,18 @@ function createSandboxAgentSessionProxy(opts) {
|
|
|
9168
9182
|
let lastPrompt;
|
|
9169
9183
|
let closed = false;
|
|
9170
9184
|
let transcriptCursor = 0;
|
|
9185
|
+
let turnsSent = 0;
|
|
9171
9186
|
return {
|
|
9172
9187
|
sessionId: remoteSessionId,
|
|
9173
9188
|
async *send(message) {
|
|
9174
9189
|
const prompt = extractPromptText(message);
|
|
9175
9190
|
lastPrompt = prompt;
|
|
9191
|
+
const isFirstTurn = turnsSent === 0;
|
|
9192
|
+
turnsSent++;
|
|
9176
9193
|
const since = await host.currentEventsCursor();
|
|
9177
|
-
|
|
9194
|
+
if (!(opts.promptCarriedInStart && isFirstTurn)) {
|
|
9195
|
+
await host.prompt(remoteSessionId, prompt);
|
|
9196
|
+
}
|
|
9178
9197
|
const controller = new AbortController();
|
|
9179
9198
|
let sseBody;
|
|
9180
9199
|
try {
|
|
@@ -9193,15 +9212,23 @@ function createSandboxAgentSessionProxy(opts) {
|
|
|
9193
9212
|
}
|
|
9194
9213
|
try {
|
|
9195
9214
|
let sawTurnEnd = false;
|
|
9215
|
+
let sawAssistantText = false;
|
|
9216
|
+
let sawToolCall = false;
|
|
9196
9217
|
for await (const record2 of readSseRecords(sseBody)) {
|
|
9197
9218
|
if (typeof record2.seq === "number") transcriptCursor = record2.seq;
|
|
9198
9219
|
const evt = recordToStreamEvent(record2);
|
|
9199
9220
|
if (!evt) continue;
|
|
9200
|
-
|
|
9221
|
+
if (evt.kind === "text-delta" && evt.text?.trim()) sawAssistantText = true;
|
|
9222
|
+
else if (evt.kind === "tool-call") sawToolCall = true;
|
|
9201
9223
|
if (evt.kind === "turn-end") {
|
|
9202
9224
|
sawTurnEnd = true;
|
|
9225
|
+
if (opts.surfaceHostTurnErrors && isFirstTurn && (evt.reason === "error" || !sawAssistantText && !sawToolCall)) {
|
|
9226
|
+
yield* harvestHostErrorNotice(host, remoteSessionId);
|
|
9227
|
+
}
|
|
9228
|
+
yield evt;
|
|
9203
9229
|
break;
|
|
9204
9230
|
}
|
|
9231
|
+
yield evt;
|
|
9205
9232
|
}
|
|
9206
9233
|
if (!sawTurnEnd) {
|
|
9207
9234
|
throw new Error(
|
|
@@ -9249,7 +9276,7 @@ function createSandboxAgentSessionProxy(opts) {
|
|
|
9249
9276
|
}
|
|
9250
9277
|
};
|
|
9251
9278
|
}
|
|
9252
|
-
var MAX_POLL_MS, MAX_OUTPUT_LINES, MAX_CONSECUTIVE_POLL_FAILURES, POLL_RETRY_DELAY_MS, STREAM_EVENT_RECORD_KINDS;
|
|
9279
|
+
var MAX_POLL_MS, MAX_OUTPUT_LINES, MAX_CONSECUTIVE_POLL_FAILURES, POLL_RETRY_DELAY_MS, HOST_ERROR_LINE_RE, STREAM_EVENT_RECORD_KINDS;
|
|
9253
9280
|
var init_sandbox_agent_session_proxy = __esm({
|
|
9254
9281
|
"src/sandbox-agent-session-proxy.ts"() {
|
|
9255
9282
|
init_sandbox_ledger();
|
|
@@ -9257,6 +9284,7 @@ var init_sandbox_agent_session_proxy = __esm({
|
|
|
9257
9284
|
MAX_OUTPUT_LINES = 500;
|
|
9258
9285
|
MAX_CONSECUTIVE_POLL_FAILURES = 6;
|
|
9259
9286
|
POLL_RETRY_DELAY_MS = 5e3;
|
|
9287
|
+
HOST_ERROR_LINE_RE = /\[(?:error|warning)\]|\berror\b|\bwarning\b|invalid model|model not found|unknown model|unsupported model/i;
|
|
9260
9288
|
STREAM_EVENT_RECORD_KINDS = /* @__PURE__ */ new Set([
|
|
9261
9289
|
"text-delta",
|
|
9262
9290
|
"thought",
|
|
@@ -10428,6 +10456,7 @@ async function spawnAgentSession(deps2, input) {
|
|
|
10428
10456
|
const {
|
|
10429
10457
|
registry,
|
|
10430
10458
|
resolveAgentAdapter,
|
|
10459
|
+
listAgentAdapters,
|
|
10431
10460
|
buildOrchestratorMcp,
|
|
10432
10461
|
daemonMcpUrl,
|
|
10433
10462
|
callerScope,
|
|
@@ -10914,10 +10943,16 @@ async function spawnAgentSession(deps2, input) {
|
|
|
10914
10943
|
if (input.sandbox === void 0 && !resolved) {
|
|
10915
10944
|
const profileHint = await authProfileAsAdapterHint(input.adapter, getAuthProfile);
|
|
10916
10945
|
const gatewayHint = profileHint ? void 0 : gatewayAsAdapterHint(input.adapter);
|
|
10946
|
+
let installedHint;
|
|
10947
|
+
if (!profileHint && !gatewayHint) {
|
|
10948
|
+
const installed = await listAgentAdapters?.().catch(() => void 0);
|
|
10949
|
+
installedHint = installed && installed.length > 0 ? `Installed adapters: ${installed.map((a) => a.slug).sort().join(", ")}.` : void 0;
|
|
10950
|
+
}
|
|
10951
|
+
const genericHint = `If it was working a moment ago, something may be mid-rebuild \u2014 wait and retry. ` + (installedHint ?? `If it has never been installed, run \`agentproto install ${input.adapter}\` first.`);
|
|
10917
10952
|
return {
|
|
10918
10953
|
ok: false,
|
|
10919
10954
|
code: "adapter_not_found",
|
|
10920
|
-
message: profileHint ? `agent_start: adapter "${input.adapter}" could not be resolved. ${profileHint}` : gatewayHint ? `agent_start: adapter "${input.adapter}" could not be resolved. ${gatewayHint}` : `agent_start: adapter "${input.adapter}" could not be resolved.
|
|
10955
|
+
message: profileHint ? `agent_start: adapter "${input.adapter}" could not be resolved. ${profileHint}` : gatewayHint ? `agent_start: adapter "${input.adapter}" could not be resolved. ${gatewayHint}` : `agent_start: adapter "${input.adapter}" could not be resolved. ${genericHint}`
|
|
10921
10956
|
};
|
|
10922
10957
|
}
|
|
10923
10958
|
if (resolveHostAuth && !resolved) {
|
|
@@ -11528,7 +11563,15 @@ ${asyncPrompt}`;
|
|
|
11528
11563
|
// (never the value) before the box boots.
|
|
11529
11564
|
...authSpec ? { authSpec } : {},
|
|
11530
11565
|
...descriptorRoute ? { route: descriptorRoute } : {},
|
|
11531
|
-
...input.appServe ? { appServe: input.appServe } : {}
|
|
11566
|
+
...input.appServe ? { appServe: input.appServe } : {},
|
|
11567
|
+
// F2 single-dial spawn — DEVICE ONLY: carry the composed initial
|
|
11568
|
+
// prompt INSIDE the inner `agent_start` (see `bootSandboxAgentSession`'s
|
|
11569
|
+
// `initialPrompt`) so the device bridge makes ONE dial, not two. The
|
|
11570
|
+
// controller still drives/records the first turn through the proxy
|
|
11571
|
+
// below (`registry.spawnAgent`'s `initialPrompt` / the `wait`
|
|
11572
|
+
// `sendPrompt`); `promptCarriedInStart` stops the proxy from
|
|
11573
|
+
// re-sending it. Non-device sandboxes are untouched (two-dial shape).
|
|
11574
|
+
...isDeviceSpawn && effectivePrompt !== void 0 ? { initialPrompt: effectivePrompt } : {}
|
|
11532
11575
|
});
|
|
11533
11576
|
if (!booted.ok) return booted;
|
|
11534
11577
|
agentSession = booted.agentSession;
|
|
@@ -11902,6 +11945,29 @@ function withSandboxInstallAdapters(spec) {
|
|
|
11902
11945
|
function looksLikeHostOnlyPath(p) {
|
|
11903
11946
|
return HOST_ONLY_PATH_PATTERNS.some((re) => re.test(p));
|
|
11904
11947
|
}
|
|
11948
|
+
function isDeviceTransportError(err) {
|
|
11949
|
+
return DEVICE_TRANSPORT_ERROR_RE.test(err instanceof Error ? err.message : String(err));
|
|
11950
|
+
}
|
|
11951
|
+
function deviceTargetOf(sandbox) {
|
|
11952
|
+
const slug = typeof sandbox === "string" ? sandbox : sandbox.provider;
|
|
11953
|
+
return slug.startsWith("device:") ? slug.slice("device:".length) : void 0;
|
|
11954
|
+
}
|
|
11955
|
+
async function startDeviceSessionWithRetry(host, args, target) {
|
|
11956
|
+
const attempts = 2;
|
|
11957
|
+
let lastErr;
|
|
11958
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
11959
|
+
try {
|
|
11960
|
+
return await host.start(args);
|
|
11961
|
+
} catch (err) {
|
|
11962
|
+
lastErr = err;
|
|
11963
|
+
if (!isDeviceTransportError(err)) throw err;
|
|
11964
|
+
if (attempt < attempts) {
|
|
11965
|
+
await new Promise((resolve42) => setTimeout(resolve42, DEVICE_SPAWN_RETRY_DELAY_MS));
|
|
11966
|
+
}
|
|
11967
|
+
}
|
|
11968
|
+
}
|
|
11969
|
+
throw new DeviceSpawnUnreachableError(target, attempts, lastErr);
|
|
11970
|
+
}
|
|
11905
11971
|
async function bootSandboxAgentSession(opts) {
|
|
11906
11972
|
const providerSlug = typeof opts.sandbox === "string" ? opts.sandbox : opts.sandbox.provider;
|
|
11907
11973
|
if (!opts.resolveSandboxProvider) {
|
|
@@ -12014,10 +12080,12 @@ async function bootSandboxAgentSession(opts) {
|
|
|
12014
12080
|
...lifecyclePolicy.pauseAfterIdleMs !== void 0 ? { expiresAt: new Date(Date.now() + lifecyclePolicy.pauseAfterIdleMs).toISOString() } : {}
|
|
12015
12081
|
});
|
|
12016
12082
|
const omitCwd = handle.omitCwdWhenImplicit === true && !opts.explicitCwd;
|
|
12083
|
+
const deviceTarget = deviceTargetOf(opts.sandbox);
|
|
12084
|
+
const carriedPrompt = deviceTarget !== void 0 && opts.initialPrompt !== void 0 ? typeof opts.initialPrompt === "string" ? [{ type: "text", text: opts.initialPrompt }] : opts.initialPrompt : void 0;
|
|
12017
12085
|
let remoteSessionId;
|
|
12018
12086
|
let resolvedCwd = boxCwd;
|
|
12019
12087
|
try {
|
|
12020
|
-
const
|
|
12088
|
+
const startArgs = {
|
|
12021
12089
|
adapter: opts.adapter,
|
|
12022
12090
|
...omitCwd ? {} : { cwd: boxCwd },
|
|
12023
12091
|
// Issue #1647 — DEVICE-BRIDGE ONLY: forward an EXPLICIT
|
|
@@ -12035,13 +12103,24 @@ async function bootSandboxAgentSession(opts) {
|
|
|
12035
12103
|
...opts.route ? { route: opts.route } : {},
|
|
12036
12104
|
...opts.effort ? { effort: opts.effort } : {},
|
|
12037
12105
|
...opts.label ? { label: opts.label } : {},
|
|
12038
|
-
...opts.auth ? { auth: opts.auth } : {}
|
|
12039
|
-
|
|
12106
|
+
...opts.auth ? { auth: opts.auth } : {},
|
|
12107
|
+
// F2 — the initial prompt rides the SAME dial as the spawn (device only).
|
|
12108
|
+
...carriedPrompt !== void 0 ? { prompt: carriedPrompt } : {}
|
|
12109
|
+
};
|
|
12110
|
+
const remoteDesc = deviceTarget !== void 0 ? await startDeviceSessionWithRetry(host, startArgs, deviceTarget) : await host.start(startArgs);
|
|
12040
12111
|
remoteSessionId = remoteDesc.id;
|
|
12041
12112
|
if (omitCwd && remoteDesc.cwd) resolvedCwd = remoteDesc.cwd;
|
|
12042
12113
|
} catch (err) {
|
|
12043
12114
|
await host.stop().catch(() => void 0);
|
|
12044
12115
|
recordSandboxState(host.sandboxId, "stopped");
|
|
12116
|
+
if (err instanceof DeviceSpawnUnreachableError) {
|
|
12117
|
+
return {
|
|
12118
|
+
ok: false,
|
|
12119
|
+
code: "device_spawn_unreachable",
|
|
12120
|
+
message: err.message,
|
|
12121
|
+
details: { target: err.target, attempts: err.attempts }
|
|
12122
|
+
};
|
|
12123
|
+
}
|
|
12045
12124
|
return {
|
|
12046
12125
|
ok: false,
|
|
12047
12126
|
code: "sandbox_proxy_failed",
|
|
@@ -12068,7 +12147,13 @@ async function bootSandboxAgentSession(opts) {
|
|
|
12068
12147
|
host,
|
|
12069
12148
|
remoteSessionId,
|
|
12070
12149
|
lifecyclePolicy,
|
|
12071
|
-
ledger: { sandboxId: host.sandboxId, provider: providerSlug }
|
|
12150
|
+
ledger: { sandboxId: host.sandboxId, provider: providerSlug },
|
|
12151
|
+
// Device spawns only: surface a first-turn failure's raw host line
|
|
12152
|
+
// (see `surfaceHostTurnErrors`).
|
|
12153
|
+
...deviceTarget !== void 0 ? { surfaceHostTurnErrors: true } : {},
|
|
12154
|
+
// F2 — when the first prompt rode the spawn dial, don't re-send it as a
|
|
12155
|
+
// second `agent_prompt` dial (see `promptCarriedInStart`).
|
|
12156
|
+
...carriedPrompt !== void 0 ? { promptCarriedInStart: true } : {}
|
|
12072
12157
|
}),
|
|
12073
12158
|
commandPreview: `sandbox:${providerSlug} \u2192 ${opts.adapter}`,
|
|
12074
12159
|
sandboxId: host.sandboxId,
|
|
@@ -12148,7 +12233,7 @@ async function resolveEffectiveCommandSandbox(requested, cwd) {
|
|
|
12148
12233
|
return void 0;
|
|
12149
12234
|
}
|
|
12150
12235
|
}
|
|
12151
|
-
var SPAWN_CLAIM_WINDOW_MS, IMPLICIT_SPAWN_CLAIM_WINDOW_MS, MAX_RESOLVED_CLAIMS, spawnClaimsByRegistry, HOST_ONLY_PATH_PATTERNS;
|
|
12236
|
+
var SPAWN_CLAIM_WINDOW_MS, IMPLICIT_SPAWN_CLAIM_WINDOW_MS, MAX_RESOLVED_CLAIMS, spawnClaimsByRegistry, HOST_ONLY_PATH_PATTERNS, DEVICE_TRANSPORT_ERROR_RE, DEVICE_SPAWN_RETRY_DELAY_MS, DeviceSpawnUnreachableError;
|
|
12152
12237
|
var init_session_spawn = __esm({
|
|
12153
12238
|
"src/session-spawn.ts"() {
|
|
12154
12239
|
init_process_stats();
|
|
@@ -12197,6 +12282,21 @@ var init_session_spawn = __esm({
|
|
|
12197
12282
|
/^\/Users\//,
|
|
12198
12283
|
/^[A-Za-z]:[\\/]/
|
|
12199
12284
|
];
|
|
12285
|
+
DEVICE_TRANSPORT_ERROR_RE = /device_unreachable|transport closed|handshake timed out|did not send hello|closed the channel after handshake|socket hang up|other side closed|ECONNRESET|ECONNREFUSED|EPIPE|ETIMEDOUT|fetch failed/i;
|
|
12286
|
+
DEVICE_SPAWN_RETRY_DELAY_MS = 2e3;
|
|
12287
|
+
DeviceSpawnUnreachableError = class extends Error {
|
|
12288
|
+
target;
|
|
12289
|
+
attempts;
|
|
12290
|
+
constructor(target, attempts, cause) {
|
|
12291
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
12292
|
+
super(
|
|
12293
|
+
`agent_start: could not reach paired device "${target}" over its host channel after ${attempts} attempt${attempts === 1 ? "" : "s"} \u2014 the host channel may be flapping; retry in a few seconds and check \`agentproto devices status ${target}\`. Last error: ${detail}`
|
|
12294
|
+
);
|
|
12295
|
+
this.name = "DeviceSpawnUnreachableError";
|
|
12296
|
+
this.target = target;
|
|
12297
|
+
this.attempts = attempts;
|
|
12298
|
+
}
|
|
12299
|
+
};
|
|
12200
12300
|
}
|
|
12201
12301
|
});
|
|
12202
12302
|
function tryParseJson(value) {
|
|
@@ -13667,7 +13767,10 @@ function registerAgentTools(server, opts) {
|
|
|
13667
13767
|
...provisionWorktree ? { provisionWorktree } : {},
|
|
13668
13768
|
...resolveWorktreeIsolation ? { resolveWorktreeIsolation } : {},
|
|
13669
13769
|
...listCatalogModels ? { listCatalogModels } : {},
|
|
13670
|
-
...ensureLlmEndpointRunning ? { ensureLlmEndpointRunning } : {}
|
|
13770
|
+
...ensureLlmEndpointRunning ? { ensureLlmEndpointRunning } : {},
|
|
13771
|
+
// Lets the generic `adapter_not_found` error name the installed
|
|
13772
|
+
// adapters (session-spawn.ts) instead of only saying "install it".
|
|
13773
|
+
...listAgentAdapters ? { listAgentAdapters } : {}
|
|
13671
13774
|
},
|
|
13672
13775
|
{
|
|
13673
13776
|
...spawnInput,
|
|
@@ -13973,6 +14076,11 @@ function registerAgentTools(server, opts) {
|
|
|
13973
14076
|
// Surfaced so a caller can distinguish "idle" from "mid tool
|
|
13974
14077
|
// call" without guessing from empty output.
|
|
13975
14078
|
...desc.blockedOn ? { blockedOn: desc.blockedOn } : {},
|
|
14079
|
+
// Device-spawn first-turn failure (bad model id / host-side
|
|
14080
|
+
// adapter error) — see `SessionDescriptor.firstTurnFailed`.
|
|
14081
|
+
// The underlying host error line rides the `lines` tail above
|
|
14082
|
+
// (surfaced as a `notice` by the sandbox proxy).
|
|
14083
|
+
...desc.firstTurnFailed ? { firstTurnFailed: true } : {},
|
|
13976
14084
|
...activityFallback ? { activityFallback: true } : {},
|
|
13977
14085
|
// An ended session's derived outcome (what it produced) —
|
|
13978
14086
|
// the ring above is empty for a row reloaded after a restart.
|
|
@@ -14209,6 +14317,7 @@ function registerAgentTools(server, opts) {
|
|
|
14209
14317
|
...s.lastTurnErrorMessage !== void 0 ? { lastTurnErrorMessage: s.lastTurnErrorMessage } : {},
|
|
14210
14318
|
...s.lastTurnReason !== void 0 ? { lastTurnReason: s.lastTurnReason } : {},
|
|
14211
14319
|
...s.lastTurnEmpty !== void 0 ? { lastTurnEmpty: s.lastTurnEmpty } : {},
|
|
14320
|
+
...s.firstTurnFailed ? { firstTurnFailed: true } : {},
|
|
14212
14321
|
...s.stats !== void 0 ? { stats: s.stats } : {}
|
|
14213
14322
|
});
|
|
14214
14323
|
const agentSessionsListSchema = z.object({
|
|
@@ -16872,18 +16981,18 @@ function worktreeFields(cwd) {
|
|
|
16872
16981
|
...identity.mainRepoPath === void 0 ? {} : { mainRepoPath: identity.mainRepoPath }
|
|
16873
16982
|
};
|
|
16874
16983
|
}
|
|
16875
|
-
function
|
|
16984
|
+
function stripAnsiCodes2(s) {
|
|
16876
16985
|
return s.replace(/\x1b\[[0-9;?]*[A-Za-z]/g, "");
|
|
16877
16986
|
}
|
|
16878
16987
|
function terminalOutputTail(rt, maxChars = 500) {
|
|
16879
16988
|
if (rt.recentBytes.length === 0) return "";
|
|
16880
16989
|
const text13 = Buffer.concat(rt.recentBytes, rt.recentBytesSize).toString("utf8");
|
|
16881
|
-
const plain =
|
|
16990
|
+
const plain = stripAnsiCodes2(text13).replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g, "").replace(/\x1b[()][A-Za-z0-9]/g, "").replace(/\x1b[0-9A-Za-z=>]/g, "").replace(/[\x00-\x09\x0b-\x1f]/g, "").trim();
|
|
16882
16991
|
if (!plain) return "";
|
|
16883
16992
|
return plain.length > maxChars ? plain.slice(-maxChars) : plain;
|
|
16884
16993
|
}
|
|
16885
16994
|
function deriveHeuristicQuestion(recentLines) {
|
|
16886
|
-
const visible = recentLines.map(
|
|
16995
|
+
const visible = recentLines.map(stripAnsiCodes2).map((l) => l.trim()).filter((l) => l.length > 0 && !SYNTHETIC_LINE.test(l));
|
|
16887
16996
|
if (visible.length === 0) return void 0;
|
|
16888
16997
|
const options = [];
|
|
16889
16998
|
let i = visible.length - 1;
|
|
@@ -17481,7 +17590,7 @@ function createSessionsRegistry(opts) {
|
|
|
17481
17590
|
const strategySlug = rt.desc.adapterSlug ?? conversationTerminalSlugFor(rt.desc);
|
|
17482
17591
|
const strategy = strategySlug ? RESUME_STRATEGIES[strategySlug] : void 0;
|
|
17483
17592
|
if (!strategy?.outputHint) return;
|
|
17484
|
-
const plain =
|
|
17593
|
+
const plain = stripAnsiCodes2(line);
|
|
17485
17594
|
const m = plain.match(strategy.outputHint);
|
|
17486
17595
|
if (m && m[1]) {
|
|
17487
17596
|
rt.desc.resumeMetadata = {
|
|
@@ -17719,6 +17828,14 @@ function createSessionsRegistry(opts) {
|
|
|
17719
17828
|
}
|
|
17720
17829
|
break;
|
|
17721
17830
|
}
|
|
17831
|
+
case "notice": {
|
|
17832
|
+
if (evt.text) {
|
|
17833
|
+
for (const line of evt.text.split(/\r?\n/)) {
|
|
17834
|
+
if (line.trim()) appendLine(rt, `\x1B[2m[notice] ${line}\x1B[0m`, "stderr");
|
|
17835
|
+
}
|
|
17836
|
+
}
|
|
17837
|
+
break;
|
|
17838
|
+
}
|
|
17722
17839
|
case "plan": {
|
|
17723
17840
|
const entries = evt.entries ?? [];
|
|
17724
17841
|
const done = entries.filter((e) => e.status === "completed").length;
|
|
@@ -18638,6 +18755,10 @@ ${message}`;
|
|
|
18638
18755
|
} else if (rt.desc.lastTurnReason !== void 0) {
|
|
18639
18756
|
delete rt.desc.lastTurnReason;
|
|
18640
18757
|
}
|
|
18758
|
+
if (rt.desc.remote === true && rt.desc.sandboxProvider?.startsWith("device:") && rt.desc.turnsCompleted === 1 && (emptyTurn || turnEndReason === "error")) {
|
|
18759
|
+
rt.desc.firstTurnFailed = true;
|
|
18760
|
+
schedulePersist();
|
|
18761
|
+
}
|
|
18641
18762
|
const nextActivity = regenerateActivitySummary(rt.desc, rt.recentLines, Date.now());
|
|
18642
18763
|
if (nextActivity) {
|
|
18643
18764
|
rt.desc.activitySummary = nextActivity;
|
|
@@ -18692,6 +18813,10 @@ ${message}`;
|
|
|
18692
18813
|
} else if (rt.desc.lastTurnReason !== void 0) {
|
|
18693
18814
|
delete rt.desc.lastTurnReason;
|
|
18694
18815
|
}
|
|
18816
|
+
if (rt.desc.remote === true && rt.desc.sandboxProvider?.startsWith("device:") && rt.desc.turnsCompleted === 1 && turnEndReason === "error") {
|
|
18817
|
+
rt.desc.firstTurnFailed = true;
|
|
18818
|
+
schedulePersist();
|
|
18819
|
+
}
|
|
18695
18820
|
if (sessionEvents) {
|
|
18696
18821
|
sessionEvents.emit({
|
|
18697
18822
|
type: "session:turn-end",
|
|
@@ -25995,6 +26120,7 @@ var compactSessionItem = (s) => ({
|
|
|
25995
26120
|
...s.lastTurnErrorMessage !== void 0 ? { lastTurnErrorMessage: s.lastTurnErrorMessage } : {},
|
|
25996
26121
|
...s.lastTurnReason !== void 0 ? { lastTurnReason: s.lastTurnReason } : {},
|
|
25997
26122
|
...s.lastTurnEmpty !== void 0 ? { lastTurnEmpty: s.lastTurnEmpty } : {},
|
|
26123
|
+
...s.firstTurnFailed ? { firstTurnFailed: true } : {},
|
|
25998
26124
|
...s.interrupted ? { interrupted: true } : {},
|
|
25999
26125
|
...s.rssBytes !== void 0 ? { rssBytes: s.rssBytes } : {},
|
|
26000
26126
|
...s.stats !== void 0 ? { stats: s.stats } : {},
|
|
@@ -31672,12 +31798,18 @@ function registerMcpApps(server, apps) {
|
|
|
31672
31798
|
uri: resourceUri,
|
|
31673
31799
|
html,
|
|
31674
31800
|
description: app.description,
|
|
31675
|
-
csp: app.csp
|
|
31801
|
+
csp: app.csp,
|
|
31802
|
+
...app.openai?.resource !== void 0 ? {
|
|
31803
|
+
// Namespaced under `openai/ui` per §3.2 — a sibling of the
|
|
31804
|
+
// canonical `_meta.ui`, never an overwrite of it.
|
|
31805
|
+
meta: { "openai/ui": JSON.parse(JSON.stringify(app.openai.resource)) }
|
|
31806
|
+
} : {}
|
|
31676
31807
|
});
|
|
31677
31808
|
server.registerTool(
|
|
31678
31809
|
app.id,
|
|
31679
31810
|
{
|
|
31680
31811
|
description: app.description ?? app.title,
|
|
31812
|
+
...app.openai !== void 0 ? { title: app.title } : {},
|
|
31681
31813
|
inputSchema: app.inputSchema.shape,
|
|
31682
31814
|
annotations: {
|
|
31683
31815
|
readOnlyHint: true,
|
|
@@ -31687,7 +31819,13 @@ function registerMcpApps(server, apps) {
|
|
|
31687
31819
|
ui: {
|
|
31688
31820
|
resourceUri,
|
|
31689
31821
|
visibility: ["model", "app"]
|
|
31690
|
-
}
|
|
31822
|
+
},
|
|
31823
|
+
...app.openai?.tool?.entrypoints !== void 0 || app.openai?.icons !== void 0 ? {
|
|
31824
|
+
"openai/ui": {
|
|
31825
|
+
...app.openai.tool?.entrypoints !== void 0 ? { entrypoints: JSON.parse(JSON.stringify(app.openai.tool.entrypoints)) } : {},
|
|
31826
|
+
...app.openai.icons !== void 0 ? { icons: JSON.parse(JSON.stringify(app.openai.icons)) } : {}
|
|
31827
|
+
}
|
|
31828
|
+
} : {}
|
|
31691
31829
|
}
|
|
31692
31830
|
},
|
|
31693
31831
|
async (args) => {
|
|
@@ -43534,7 +43672,15 @@ async function performInstall(dir, appRegistry, listRegisteredToolIds, resolveAg
|
|
|
43534
43672
|
...handle.ui?.description !== void 0 ? { description: handle.ui.description } : {},
|
|
43535
43673
|
...handle.ui?.tools !== void 0 ? { tools: handle.ui.tools } : {},
|
|
43536
43674
|
...handle.ui?.csp !== void 0 ? { csp: handle.ui.csp } : {},
|
|
43537
|
-
...handle.ui?.build !== void 0 ? { build: handle.ui.build } : {}
|
|
43675
|
+
...handle.ui?.build !== void 0 ? { build: handle.ui.build } : {},
|
|
43676
|
+
// OpenAI MCP-extensions carrier (plan W-B): the normalized,
|
|
43677
|
+
// app-kit-validated `ui.extensions` block persists verbatim on the
|
|
43678
|
+
// installed record — `makeInstalledAppUiApps` (W-C) is the only
|
|
43679
|
+
// consumer. Frozen already by app-kit; spread-cloned here so the
|
|
43680
|
+
// persisted shape stays a plain JSON-safe object (apps.json is
|
|
43681
|
+
// what actually freezes it). Apps without the block install
|
|
43682
|
+
// identically to before (plan I1).
|
|
43683
|
+
...handle.ui?.extensions !== void 0 ? { extensions: handle.ui.extensions } : {}
|
|
43538
43684
|
} : void 0;
|
|
43539
43685
|
const artifact = refs.artifact ? {
|
|
43540
43686
|
path: refs.artifact.path,
|
|
@@ -46565,6 +46711,7 @@ async function startHttpServer(opts) {
|
|
|
46565
46711
|
opts.resolveSandboxProvider,
|
|
46566
46712
|
opts.webhookNotifier,
|
|
46567
46713
|
opts.ensureLlmEndpointRunning,
|
|
46714
|
+
opts.listAgentAdapters,
|
|
46568
46715
|
opts.deviceMirrorSync
|
|
46569
46716
|
);
|
|
46570
46717
|
if (handled) return;
|
|
@@ -48617,7 +48764,7 @@ async function handleSandboxes(_req, res, path, resolveSandboxProvider2) {
|
|
|
48617
48764
|
json3(200, { alive: true, ...probe.state ? { state: probe.state } : { state: row.state }, checkedAt });
|
|
48618
48765
|
return true;
|
|
48619
48766
|
}
|
|
48620
|
-
async function handleSessions(req, res, path, registry, resolveAgentAdapter, ptyEnabled = false, resolveBrowserAdapter, listBrowserAdapters, sessionEvents, eventRing, buildOrchestratorMcp, daemonMcpUrl, provisionWorktree, listCatalogModels, resolveSandboxProvider2, webhookNotifier, ensureLlmEndpointRunning, deviceMirrorSync) {
|
|
48767
|
+
async function handleSessions(req, res, path, registry, resolveAgentAdapter, ptyEnabled = false, resolveBrowserAdapter, listBrowserAdapters, sessionEvents, eventRing, buildOrchestratorMcp, daemonMcpUrl, provisionWorktree, listCatalogModels, resolveSandboxProvider2, webhookNotifier, ensureLlmEndpointRunning, listAgentAdapters, deviceMirrorSync) {
|
|
48621
48768
|
const json3 = (status, body) => {
|
|
48622
48769
|
res.writeHead(status, { "content-type": "application/json" });
|
|
48623
48770
|
res.end(JSON.stringify(body));
|
|
@@ -48775,12 +48922,13 @@ async function handleSessions(req, res, path, registry, resolveAgentAdapter, pty
|
|
|
48775
48922
|
...listCatalogModels ? { listCatalogModels } : {},
|
|
48776
48923
|
...resolveSandboxProvider2 ? { resolveSandboxProvider: resolveSandboxProvider2 } : {},
|
|
48777
48924
|
...webhookNotifier ? { webhookNotifier } : {},
|
|
48778
|
-
...ensureLlmEndpointRunning ? { ensureLlmEndpointRunning } : {}
|
|
48925
|
+
...ensureLlmEndpointRunning ? { ensureLlmEndpointRunning } : {},
|
|
48926
|
+
...listAgentAdapters ? { listAgentAdapters } : {}
|
|
48779
48927
|
},
|
|
48780
48928
|
spawnArgs
|
|
48781
48929
|
);
|
|
48782
48930
|
if (!result.ok) {
|
|
48783
|
-
const status = result.code === "adapter_not_found" || result.code === "no_cwd" ? 404 : result.code === "orchestrator_not_enabled" ? 501 : result.code === "orchestrator_max_depth_exceeded" || result.code === "orchestrator_child_quota_exceeded" || result.code === "role_spawn_denied" ? 409 : result.code === "invalid_role" || result.code === "browser_unsupported" || result.code === "worktree_requires_explicit_repo" || result.code === "device_spawn_requires_repo_identity" || result.code === "device_bridge_workspace_unknown" || result.code === "access_profile_not_found" || result.code === "access_profile_ineligible" || result.code === "sandbox_cwd_invalid" ? 400 : 500;
|
|
48931
|
+
const status = result.code === "adapter_not_found" || result.code === "no_cwd" ? 404 : result.code === "orchestrator_not_enabled" ? 501 : result.code === "orchestrator_max_depth_exceeded" || result.code === "orchestrator_child_quota_exceeded" || result.code === "role_spawn_denied" ? 409 : result.code === "invalid_role" || result.code === "browser_unsupported" || result.code === "worktree_requires_explicit_repo" || result.code === "device_spawn_requires_repo_identity" || result.code === "device_bridge_workspace_unknown" || result.code === "access_profile_not_found" || result.code === "access_profile_ineligible" || result.code === "sandbox_cwd_invalid" || result.code === "device_spawn_unreachable" ? 400 : 500;
|
|
48784
48932
|
json3(status, {
|
|
48785
48933
|
error: result.code,
|
|
48786
48934
|
message: result.message,
|
|
@@ -48842,12 +48990,13 @@ async function handleSessions(req, res, path, registry, resolveAgentAdapter, pty
|
|
|
48842
48990
|
...listCatalogModels ? { listCatalogModels } : {},
|
|
48843
48991
|
...resolveSandboxProvider2 ? { resolveSandboxProvider: resolveSandboxProvider2 } : {},
|
|
48844
48992
|
...webhookNotifier ? { webhookNotifier } : {},
|
|
48845
|
-
...ensureLlmEndpointRunning ? { ensureLlmEndpointRunning } : {}
|
|
48993
|
+
...ensureLlmEndpointRunning ? { ensureLlmEndpointRunning } : {},
|
|
48994
|
+
...listAgentAdapters ? { listAgentAdapters } : {}
|
|
48846
48995
|
},
|
|
48847
48996
|
spawnArgs
|
|
48848
48997
|
);
|
|
48849
48998
|
if (!result.ok) {
|
|
48850
|
-
const status = result.code === "adapter_not_found" || result.code === "no_cwd" ? 404 : result.code === "orchestrator_not_enabled" ? 501 : result.code === "orchestrator_max_depth_exceeded" || result.code === "orchestrator_child_quota_exceeded" || result.code === "role_spawn_denied" ? 409 : result.code === "invalid_role" || result.code === "browser_unsupported" || result.code === "worktree_requires_explicit_repo" || result.code === "device_spawn_requires_repo_identity" || result.code === "device_bridge_workspace_unknown" || result.code === "access_profile_not_found" || result.code === "access_profile_ineligible" || result.code === "sandbox_cwd_invalid" ? 400 : 500;
|
|
48999
|
+
const status = result.code === "adapter_not_found" || result.code === "no_cwd" ? 404 : result.code === "orchestrator_not_enabled" ? 501 : result.code === "orchestrator_max_depth_exceeded" || result.code === "orchestrator_child_quota_exceeded" || result.code === "role_spawn_denied" ? 409 : result.code === "invalid_role" || result.code === "browser_unsupported" || result.code === "worktree_requires_explicit_repo" || result.code === "device_spawn_requires_repo_identity" || result.code === "device_bridge_workspace_unknown" || result.code === "access_profile_not_found" || result.code === "access_profile_ineligible" || result.code === "sandbox_cwd_invalid" || result.code === "device_spawn_unreachable" ? 400 : 500;
|
|
48851
49000
|
json3(status, {
|
|
48852
49001
|
error: result.code,
|
|
48853
49002
|
message: result.message,
|
|
@@ -57218,6 +57367,7 @@ function createPrProvenanceReconciler(opts) {
|
|
|
57218
57367
|
const stampedPrUrls = /* @__PURE__ */ new Set();
|
|
57219
57368
|
const costRefreshedPrUrls = /* @__PURE__ */ new Set();
|
|
57220
57369
|
const lastPollAt = /* @__PURE__ */ new Map();
|
|
57370
|
+
const scannedPrUrls = /* @__PURE__ */ new Set();
|
|
57221
57371
|
const reconcile = async (sessionId, terminal) => {
|
|
57222
57372
|
const desc = opts.registry.get(sessionId);
|
|
57223
57373
|
if (!desc || desc.kind !== "agent-cli") return;
|
|
@@ -57256,6 +57406,29 @@ function createPrProvenanceReconciler(opts) {
|
|
|
57256
57406
|
if (!shouldStamp(record2.createdPrUrl)) continue;
|
|
57257
57407
|
await stamp({ number: record2.createdPrNumber, url: record2.createdPrUrl });
|
|
57258
57408
|
}
|
|
57409
|
+
if (desc.eventsPath) {
|
|
57410
|
+
for (const turn of readRecentTurnsSync(desc.eventsPath)) {
|
|
57411
|
+
if (turn.role !== "assistant") continue;
|
|
57412
|
+
const re = /https?:\/\/[^\s<>"]+/g;
|
|
57413
|
+
let m;
|
|
57414
|
+
while ((m = re.exec(turn.text)) !== null) {
|
|
57415
|
+
const url = m[0].replace(/[.,;:)\]]+$/, "");
|
|
57416
|
+
const parsed = parsePrUrl(url);
|
|
57417
|
+
if (!parsed) continue;
|
|
57418
|
+
if (desc.openedPrs?.some((known) => known.url === url)) continue;
|
|
57419
|
+
if (scannedPrUrls.has(url)) continue;
|
|
57420
|
+
scannedPrUrls.add(url);
|
|
57421
|
+
try {
|
|
57422
|
+
opts.registry.recordOpenedPr(sessionId, {
|
|
57423
|
+
adapter: "output-scan",
|
|
57424
|
+
number: parsed.number,
|
|
57425
|
+
url
|
|
57426
|
+
});
|
|
57427
|
+
} catch {
|
|
57428
|
+
}
|
|
57429
|
+
}
|
|
57430
|
+
}
|
|
57431
|
+
}
|
|
57259
57432
|
const pr = await opts.resolveOpenPr(cwd);
|
|
57260
57433
|
if (pr && shouldStamp(pr.url)) await stamp(pr);
|
|
57261
57434
|
await refreshCost(desc, supervisor, cwd);
|