@agentproto/runtime 2.6.0 → 2.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/README.md +16 -0
- package/dist/catalog-models.d.ts +3 -3
- package/dist/config.d.ts +27 -3
- package/dist/config.mjs.map +1 -1
- package/dist/{context-continuity-B9n0t0v-.d.ts → context-continuity-ib9_bVYM.d.ts} +12 -0
- package/dist/index.d.ts +334 -23
- package/dist/index.mjs +1111 -309
- package/dist/index.mjs.map +1 -1
- package/dist/pr-provenance.d.ts +29 -1
- package/dist/pr-provenance.mjs +17 -2
- package/dist/pr-provenance.mjs.map +1 -1
- package/dist/resume-strategies.d.ts +13 -1
- package/dist/resume-strategies.mjs +25 -14
- package/dist/resume-strategies.mjs.map +1 -1
- package/dist/{session-config-DIf6wYYP.d.ts → session-config-DbWP9RRj.d.ts} +1 -1
- package/dist/{spawn-defaults-CYJoeHeO.d.ts → spawn-defaults-DVgmfxWo.d.ts} +1 -1
- package/dist/user-presets.d.ts +2 -2
- package/package.json +11 -11
package/dist/index.d.ts
CHANGED
|
@@ -6,15 +6,15 @@ import { AcpMcpServer, AcpPermissionResolution } from '@agentproto/acp';
|
|
|
6
6
|
import { SessionMode } from '@agentproto/acp/client';
|
|
7
7
|
export { SessionMode } from '@agentproto/acp/client';
|
|
8
8
|
import { ChildProcess } from 'node:child_process';
|
|
9
|
-
import { R as RouteSpec, S as SessionConfig, P as Posture, C as ContextProfile, E as EffortLevel, A as AuthMethod, a as CanonicalPosture } from './session-config-
|
|
10
|
-
export { D as DeclaredAdapterMode, c as composeMode, d as decomposeMode } from './session-config-
|
|
9
|
+
import { R as RouteSpec, S as SessionConfig, P as Posture, C as ContextProfile, E as EffortLevel, A as AuthMethod, a as CanonicalPosture } from './session-config-DbWP9RRj.js';
|
|
10
|
+
export { D as DeclaredAdapterMode, c as composeMode, d as decomposeMode } from './session-config-DbWP9RRj.js';
|
|
11
11
|
import { CostBudget, AuthProfile, CostBudgetScope } from '@agentproto/auth';
|
|
12
12
|
export { CostBudget, CostBudgetScope } from '@agentproto/auth';
|
|
13
|
-
import { R as ResolvedContextContinuityPolicy } from './context-continuity-
|
|
13
|
+
import { R as ResolvedContextContinuityPolicy } from './context-continuity-ib9_bVYM.js';
|
|
14
14
|
import { SandboxMode } from '@agentproto/command-sandbox';
|
|
15
15
|
import { AdapterHandle, SetupField, AdapterResolver, AdapterLister, HarnessCapabilities, AdapterEntry } from '@agentproto/provider-kit';
|
|
16
|
-
import { R as ResolvedAuthSpec, D as DeclaredAdapterOption, A as AdapterAuthDescriptor } from './spawn-defaults-
|
|
17
|
-
export { a as AuthEcho, b as AuthResolutionError, C as CLAUDE_CODE_OAUTH_SOURCE, c as CredentialSource, d as DefaultsAdapterAuthConfig, e as DefaultsAdapterConfig, f as ResolveSubscriptionCredentialInput, g as ResolvedSpawnAuthMaterial, h as ResolvedSpawnDefaults, S as SpawnDefaultsConfig, i as SubscriptionCredentialResolution, j as SubscriptionSourceError, k as credentialFingerprint, n as normalizeSkillsOption, r as resolveAuthSpec, l as resolveSpawnDefaults, m as resolveSubscriptionCredential } from './spawn-defaults-
|
|
16
|
+
import { R as ResolvedAuthSpec, D as DeclaredAdapterOption, A as AdapterAuthDescriptor } from './spawn-defaults-DVgmfxWo.js';
|
|
17
|
+
export { a as AuthEcho, b as AuthResolutionError, C as CLAUDE_CODE_OAUTH_SOURCE, c as CredentialSource, d as DefaultsAdapterAuthConfig, e as DefaultsAdapterConfig, f as ResolveSubscriptionCredentialInput, g as ResolvedSpawnAuthMaterial, h as ResolvedSpawnDefaults, S as SpawnDefaultsConfig, i as SubscriptionCredentialResolution, j as SubscriptionSourceError, k as credentialFingerprint, n as normalizeSkillsOption, r as resolveAuthSpec, l as resolveSpawnDefaults, m as resolveSubscriptionCredential } from './spawn-defaults-DVgmfxWo.js';
|
|
18
18
|
import { CatalogModelsQuery, CatalogModelsResponse } from './catalog-models.js';
|
|
19
19
|
export { CatalogAdapterInput, CatalogAdapterModelInput, CatalogPricing, CatalogProduct, CatalogRoute, CatalogRouteSummary, CatalogVendor, buildCatalogModels } from './catalog-models.js';
|
|
20
20
|
import { FooterSession } from './pr-provenance.js';
|
|
@@ -536,6 +536,16 @@ interface ToolCallRecord {
|
|
|
536
536
|
exitCode?: number;
|
|
537
537
|
isError?: boolean;
|
|
538
538
|
durationMs?: number;
|
|
539
|
+
/** The PR this call CREATED, when the call was a successful shell-shaped
|
|
540
|
+
* `gh pr create` (detected at write time via `detectShellPrCreate` in
|
|
541
|
+
* pr-provenance.ts, from the command string + the call's result text).
|
|
542
|
+
* This is the exact-attribution source the PR-provenance reconciler
|
|
543
|
+
* prefers over branch→PR guessing: the session whose events.jsonl holds
|
|
544
|
+
* this record IS the session that opened the PR, no matter what branch
|
|
545
|
+
* its cwd sits on by the time the turn ends. Absent for every other
|
|
546
|
+
* call. */
|
|
547
|
+
createdPrUrl?: string;
|
|
548
|
+
createdPrNumber?: number;
|
|
539
549
|
ts: string;
|
|
540
550
|
}
|
|
541
551
|
|
|
@@ -1661,7 +1671,7 @@ declare function createTaskLedger(opts: {
|
|
|
1661
1671
|
* and session_monitor MCP tool (long-poll multiplexed).
|
|
1662
1672
|
*/
|
|
1663
1673
|
|
|
1664
|
-
type SessionEventType = "session:turn-end" | "session:awaiting-input" | "session:permission-request" | "session:permission-resolved" | "session:exited" | "session:reaped" | "session:stalled" | "session:stall-cleared" | "session:watcher-attached" | "session:watcher-detached" | "session:bg-tasks-parked" | "session:bg-tasks-cleared" | "session:resumed" | "session:spawned" | "session:command-done" | "session:model-changed" | "session:config-changed" | "session:renamed" | "policy:passed" | "policy:failed" | "policy:commit-ready" | "policy:committed" | "cron:fired" | "cron:succeeded" | "cron:failed" | "activity:changed" | "task:changed";
|
|
1674
|
+
type SessionEventType = "session:turn-end" | "session:awaiting-input" | "session:awaiting-input-flagged" | "session:permission-request" | "session:permission-resolved" | "session:exited" | "session:reaped" | "session:stalled" | "session:stall-cleared" | "session:watcher-attached" | "session:watcher-detached" | "session:bg-tasks-parked" | "session:bg-tasks-cleared" | "session:resumed" | "session:spawned" | "session:command-done" | "session:model-changed" | "session:config-changed" | "session:renamed" | "session:pinned-changed" | "policy:passed" | "policy:failed" | "policy:commit-ready" | "policy:committed" | "cron:fired" | "cron:succeeded" | "cron:failed" | "activity:changed" | "task:changed";
|
|
1665
1675
|
/**
|
|
1666
1676
|
* Fixed severity vocabulary for a judge-gate finding (WP-D). Deliberately
|
|
1667
1677
|
* small and fixed so `policy_status` output is comparable across different
|
|
@@ -1743,6 +1753,39 @@ interface SessionAwaitingInputEvent {
|
|
|
1743
1753
|
ts: string;
|
|
1744
1754
|
question?: SessionAwaitingQuestion;
|
|
1745
1755
|
}
|
|
1756
|
+
/**
|
|
1757
|
+
* Emitted by `SessionsRegistry.flagAwaitingInput` (the `session_flag_status`
|
|
1758
|
+
* MCP verb) when something EXTERNAL — a human, another agent, the future
|
|
1759
|
+
* session watchdog — manually corrects a session's `awaitingInput`/
|
|
1760
|
+
* `awaitingQuestion` classification, overriding (or confirming) what the
|
|
1761
|
+
* internal heuristic (`deriveHeuristicQuestion`) or a driver-reported
|
|
1762
|
+
* `agent-prompt` last set. Distinct from `session:awaiting-input` (which only
|
|
1763
|
+
* ever fires when the flag flips TRUE, from the daemon's own turn-end
|
|
1764
|
+
* detection): this fires for BOTH directions of a manual override, always
|
|
1765
|
+
* carries the mandatory `reason` the caller gave (audit trail — this is the
|
|
1766
|
+
* one write path for this field with no automatic sensor behind it), and
|
|
1767
|
+
* `awaitingInput` states the value the override just set rather than being
|
|
1768
|
+
* implied by the event firing at all. Same bus distribution as every other
|
|
1769
|
+
* lifecycle event (`session_events_poll`, the webhook notifier, the routine
|
|
1770
|
+
* engine, `session_monitor`).
|
|
1771
|
+
*/
|
|
1772
|
+
interface SessionAwaitingInputFlaggedEvent {
|
|
1773
|
+
type: "session:awaiting-input-flagged";
|
|
1774
|
+
sessionId: string;
|
|
1775
|
+
awaitingInput: boolean;
|
|
1776
|
+
/** Required justification the caller passed to `session_flag_status` —
|
|
1777
|
+
* why this override was made. */
|
|
1778
|
+
reason: string;
|
|
1779
|
+
label?: string;
|
|
1780
|
+
ts: string;
|
|
1781
|
+
/** Present only when `awaitingInput:true` and a `question` was attached —
|
|
1782
|
+
* mirrors the descriptor's `awaitingQuestion` after the override, same
|
|
1783
|
+
* shape as every other site that sets it (`source: "structured"`, since a
|
|
1784
|
+
* manual override is at least as authoritative as a driver-reported
|
|
1785
|
+
* prompt). Absent when `awaitingInput:false` (the override always clears
|
|
1786
|
+
* any prior question in that case) or when no `question` was given. */
|
|
1787
|
+
question?: SessionAwaitingQuestion;
|
|
1788
|
+
}
|
|
1746
1789
|
/**
|
|
1747
1790
|
* Emitted when a permission-hold session parks a `session/request_permission`
|
|
1748
1791
|
* (see the pending-permissions inbox in sessions.ts). `permissionId` is the
|
|
@@ -1862,11 +1905,12 @@ interface SessionStallClearedEvent {
|
|
|
1862
1905
|
* is the counter AFTER the attach (read back from the registry, so a
|
|
1863
1906
|
* concurrent waiter is already reflected). `watcherSessionId` names the
|
|
1864
1907
|
* supervising session when the wait was initiated by one (the scoped
|
|
1865
|
-
* orchestrator's `callerScope.ownerSessionId`);
|
|
1866
|
-
*
|
|
1867
|
-
*
|
|
1868
|
-
*
|
|
1869
|
-
*
|
|
1908
|
+
* orchestrator's `callerScope.ownerSessionId`); `label` is that session's
|
|
1909
|
+
* label/title, resolved once at attach time (a best-effort snapshot, not
|
|
1910
|
+
* live). Both absent for an anonymous CLI/HTTP waiter. Same bus distribution
|
|
1911
|
+
* as every other lifecycle event (`session_events_poll`, the webhook
|
|
1912
|
+
* notifier, the routine engine, `session_monitor`). Paired with
|
|
1913
|
+
* `session:watcher-detached` when the wait resolves or times out.
|
|
1870
1914
|
*/
|
|
1871
1915
|
interface SessionWatcherAttachedEvent {
|
|
1872
1916
|
type: "session:watcher-attached";
|
|
@@ -2064,6 +2108,24 @@ interface SessionRenamedEvent {
|
|
|
2064
2108
|
renamedByUser?: boolean;
|
|
2065
2109
|
ts: string;
|
|
2066
2110
|
}
|
|
2111
|
+
/**
|
|
2112
|
+
* Emitted when an operator pins or unpins a session for list visibility
|
|
2113
|
+
* (`POST /sessions/:id/pin`, the `session_set_pinned` MCP verb). Like
|
|
2114
|
+
* `session:renamed`, this is NOT a `SessionConfig` axis — pinning never
|
|
2115
|
+
* touches the live agent, the idle-reaper, or any notification path, it's
|
|
2116
|
+
* purely a `SessionDescriptor.pinned` display/sort flag — so it rides its
|
|
2117
|
+
* own event rather than `session:config-changed`. `pinned` carries the value
|
|
2118
|
+
* now on the descriptor. Same bus distribution as every other lifecycle event
|
|
2119
|
+
* (`session_events_poll`, the webhook notifier, the routine engine), which is
|
|
2120
|
+
* how a live UI (the VS Code sessions webview) learns to resort its list
|
|
2121
|
+
* without waiting for its next snapshot poll.
|
|
2122
|
+
*/
|
|
2123
|
+
interface SessionPinnedEvent {
|
|
2124
|
+
type: "session:pinned-changed";
|
|
2125
|
+
sessionId: string;
|
|
2126
|
+
pinned: boolean;
|
|
2127
|
+
ts: string;
|
|
2128
|
+
}
|
|
2067
2129
|
/**
|
|
2068
2130
|
* Emitted when a session is first registered in the registry (WP-R3) — both
|
|
2069
2131
|
* the agent-cli spawn path (`spawnAgent`) and the terminal path (`spawnPty`).
|
|
@@ -2186,7 +2248,7 @@ interface TaskChangedEvent {
|
|
|
2186
2248
|
sessionId?: string;
|
|
2187
2249
|
ts: string;
|
|
2188
2250
|
}
|
|
2189
|
-
type SessionEvent = SessionTurnEndEvent | SessionAwaitingInputEvent | SessionPermissionRequestEvent | SessionPermissionResolvedEvent | SessionExitedEvent | SessionReapedEvent | SessionStalledEvent | SessionStallClearedEvent | SessionWatcherAttachedEvent | SessionWatcherDetachedEvent | SessionBgTasksParkedEvent | SessionBgTasksClearedEvent | SessionResumedEvent | SessionSpawnedEvent | SessionCommandDoneEvent | SessionModelChangedEvent | SessionConfigChangedEvent | SessionRenamedEvent | PolicyPassedEvent | PolicyFailedEvent | PolicyCommitReadyEvent | PolicyCommittedEvent | CronFiredEvent | CronSucceededEvent | CronFailedEvent | ActivityChangedEvent | TaskChangedEvent;
|
|
2251
|
+
type SessionEvent = SessionTurnEndEvent | SessionAwaitingInputEvent | SessionAwaitingInputFlaggedEvent | SessionPermissionRequestEvent | SessionPermissionResolvedEvent | SessionExitedEvent | SessionReapedEvent | SessionStalledEvent | SessionStallClearedEvent | SessionWatcherAttachedEvent | SessionWatcherDetachedEvent | SessionBgTasksParkedEvent | SessionBgTasksClearedEvent | SessionResumedEvent | SessionSpawnedEvent | SessionCommandDoneEvent | SessionModelChangedEvent | SessionConfigChangedEvent | SessionRenamedEvent | SessionPinnedEvent | PolicyPassedEvent | PolicyFailedEvent | PolicyCommitReadyEvent | PolicyCommittedEvent | CronFiredEvent | CronSucceededEvent | CronFailedEvent | ActivityChangedEvent | TaskChangedEvent;
|
|
2190
2252
|
interface SessionEventBus {
|
|
2191
2253
|
emit(ev: SessionEvent): void;
|
|
2192
2254
|
/** Subscribe to a specific event type. Returns an unsubscribe fn. */
|
|
@@ -3613,6 +3675,14 @@ type AgentAdapterResolver = (slug: string) => Promise<{
|
|
|
3613
3675
|
startSession(opts: {
|
|
3614
3676
|
cwd: string;
|
|
3615
3677
|
resumeSessionId?: string;
|
|
3678
|
+
/** Persistent isolated-config location for the adapter (claude-code's
|
|
3679
|
+
* `CLAUDE_CONFIG_DIR`) — forwarded to the driver's
|
|
3680
|
+
* `start({ configDir })`. The daemon keys it per session lineage
|
|
3681
|
+
* (`SessionDescriptor.adapterConfigDir`) so the provider's own
|
|
3682
|
+
* conversation store survives adapter respawns and `resumeSessionId`
|
|
3683
|
+
* can restore full context instead of falling back to a digest.
|
|
3684
|
+
* Adapters that don't isolate a config dir ignore it. */
|
|
3685
|
+
configDir?: string;
|
|
3616
3686
|
/**
|
|
3617
3687
|
* Manifest-declared mode id forwarded from `agent_start` (AIP-45
|
|
3618
3688
|
* `AgentCliHandle.modes` — e.g. claude-code's `plan` /
|
|
@@ -3849,6 +3919,12 @@ interface AdapterInstallResult {
|
|
|
3849
3919
|
* post-install re-list failed (the install itself may still have
|
|
3850
3920
|
* succeeded — read `ok`). */
|
|
3851
3921
|
status?: "supported" | "available" | "ready" | "unresolvable";
|
|
3922
|
+
/** True when the install failed ONLY because a manifest setup step
|
|
3923
|
+
* declares `interactive: true` and this process has no TTY to run it
|
|
3924
|
+
* in (e.g. openclaw's `onboard --install-daemon` TUI). The remedy is a
|
|
3925
|
+
* real terminal — `agentproto setup <slug>` — which a UI can offer
|
|
3926
|
+
* directly as a PTY terminal session. */
|
|
3927
|
+
needsInteractiveSetup?: boolean;
|
|
3852
3928
|
}
|
|
3853
3929
|
/**
|
|
3854
3930
|
* Installs an agent CLI adapter by slug and reports the outcome. Wired by
|
|
@@ -4214,6 +4290,48 @@ interface SessionAccessProfileEcho {
|
|
|
4214
4290
|
endpoint: string;
|
|
4215
4291
|
method: AuthMethod;
|
|
4216
4292
|
}
|
|
4293
|
+
/**
|
|
4294
|
+
* One live waiter behind a session's {@link SessionDescriptor.watchers} count
|
|
4295
|
+
* (#session-visibility). Captured at `monitorSessionWait` attach time and held
|
|
4296
|
+
* only for the life of that wait — never persisted, never updated in place
|
|
4297
|
+
* (a snapshot of the waiter's label at attach time, not a live mirror of it).
|
|
4298
|
+
*/
|
|
4299
|
+
interface SessionWatcherInfo {
|
|
4300
|
+
/** The waiting session's id, when this wait was initiated by an agent
|
|
4301
|
+
* session via the orchestrator scope (`callerScope.ownerSessionId`).
|
|
4302
|
+
* Absent for an anonymous CLI/HTTP waiter — it still counts toward
|
|
4303
|
+
* `watchers`, it just can't be named. */
|
|
4304
|
+
watcherSessionId?: string;
|
|
4305
|
+
/** Best-effort label/title for `watcherSessionId`, resolved once at attach
|
|
4306
|
+
* time. A later rename of the watching session is not reflected. */
|
|
4307
|
+
watcherLabel?: string;
|
|
4308
|
+
/** What this wait is blocking on — mirrors `session_monitor`'s `event`
|
|
4309
|
+
* parameter (`SessionWaitEvent` in orchestration-tools.ts; kept as a plain
|
|
4310
|
+
* string here so the registry doesn't depend on the tool-layer type). */
|
|
4311
|
+
event: string;
|
|
4312
|
+
/** The wait's configured timeout, ms — absent for the MCP tool's default. */
|
|
4313
|
+
timeoutMs?: number;
|
|
4314
|
+
/** ISO 8601 timestamp this waiter attached. */
|
|
4315
|
+
since: string;
|
|
4316
|
+
}
|
|
4317
|
+
/** One prompt waiting in `SessionDescriptor.promptQueue` — see that
|
|
4318
|
+
* field's doc for the FIFO/force ordering contract. */
|
|
4319
|
+
interface QueuedPrompt {
|
|
4320
|
+
/** Stable id, assigned at queue time (by the HTTP layer for
|
|
4321
|
+
* `POST /sessions/:id/prompt`'s `queue` arm so the caller can echo it
|
|
4322
|
+
* straight back in the response, or minted here for any other
|
|
4323
|
+
* caller). Used by `removeQueuedPrompt` to cancel this one item
|
|
4324
|
+
* before it dispatches. */
|
|
4325
|
+
id: string;
|
|
4326
|
+
/** Same shape `runAgentTurn`'s `message` parameter accepts — a raw
|
|
4327
|
+
* string or an ACP content block/array. */
|
|
4328
|
+
message: unknown;
|
|
4329
|
+
/** ISO 8601 timestamp this item was queued. */
|
|
4330
|
+
queuedAt: string;
|
|
4331
|
+
/** Same as `enqueuePrompt`'s `opts.source` — carried through to the
|
|
4332
|
+
* turn this item eventually becomes. */
|
|
4333
|
+
source?: string;
|
|
4334
|
+
}
|
|
4217
4335
|
interface SessionDescriptor {
|
|
4218
4336
|
id: string;
|
|
4219
4337
|
kind: SessionKind;
|
|
@@ -4303,6 +4421,15 @@ interface SessionDescriptor {
|
|
|
4303
4421
|
* daemon restart). 0/absent ⇒ nothing is watching. Lets a UI mark a
|
|
4304
4422
|
* session "supervised — notify on turn-end". */
|
|
4305
4423
|
watchers?: number;
|
|
4424
|
+
/** Per-waiter detail behind the {@link watchers} count — who is blocked on
|
|
4425
|
+
* this session and what they're blocked on. Same lifetime/source as
|
|
4426
|
+
* `watchers` (stamped at read time from the registry's live waiter list,
|
|
4427
|
+
* never persisted); empty/absent ⇒ nothing is watching. An anonymous
|
|
4428
|
+
* CLI/HTTP waiter (no `callerScope`) carries no `watcherSessionId` — it
|
|
4429
|
+
* still counts, it just can't be named. Lets a UI answer "who is watching
|
|
4430
|
+
* this, and what are they waiting for" without guessing from the bare
|
|
4431
|
+
* count. */
|
|
4432
|
+
watcherDetails?: readonly SessionWatcherInfo[];
|
|
4306
4433
|
/** Count of DESCENDANT sessions (children, grandchildren, …) currently
|
|
4307
4434
|
* mid-turn, derived at read time from the `parentSessionId` lineage
|
|
4308
4435
|
* (#session-visibility, subtree rollup). Lets a UI show an idle parent that
|
|
@@ -4352,6 +4479,24 @@ interface SessionDescriptor {
|
|
|
4352
4479
|
* session exit. Emits `session:bg-tasks-parked` /
|
|
4353
4480
|
* `session:bg-tasks-cleared`. */
|
|
4354
4481
|
pendingBgTasks?: number;
|
|
4482
|
+
/** ISO 8601 timestamp of the last turn that ended because the ADAPTER
|
|
4483
|
+
* ITSELF reported a failure — `runAgentTurn` observed a `turn-end` event
|
|
4484
|
+
* with `reason:"error"` (session-event-bus.ts's `SessionTurnEndEvent`,
|
|
4485
|
+
* e.g. a refused/errored ACP `stopReason` — see adapters/mastra-agent's
|
|
4486
|
+
* host) — as opposed to a thrown/rejected adapter stream, which flips
|
|
4487
|
+
* `status` to `"error"` directly (a genuinely terminal row the existing
|
|
4488
|
+
* crash/error handling already catches). This is the twin gap for a
|
|
4489
|
+
* turn that fails IN-BAND while the process stays alive: `status` stays
|
|
4490
|
+
* `"running"`, `lastError` stays unset (reserved for `markCrashed`), and
|
|
4491
|
+
* nothing else distinguishes the session from one that simply finished
|
|
4492
|
+
* a clean turn and is idle. Folded into the same "stalled" activity/UI
|
|
4493
|
+
* treatment a mid-turn stall gets (see sessionsTree.logic.ts's
|
|
4494
|
+
* `activityFor`) rather than a new state, on the theory that both mean
|
|
4495
|
+
* "the last thing this session did needs a look, not a re-prompt on
|
|
4496
|
+
* faith". Stamped at turn-end when `turnEndReason === "error"`; cleared
|
|
4497
|
+
* the moment a LATER turn completes without one (same reset shape as
|
|
4498
|
+
* `resumeAttempts`/`restartAttempts`). Detection + signal only. */
|
|
4499
|
+
lastTurnErroredAt?: string;
|
|
4355
4500
|
/** DERIVED, read-time only (never persisted — stripped by `snapshotRows`,
|
|
4356
4501
|
* stamped by `stampInterrupted` in list()/get()/findByIdOrName). True when
|
|
4357
4502
|
* this session died with a turn in flight under a daemon restart —
|
|
@@ -4478,6 +4623,17 @@ interface SessionDescriptor {
|
|
|
4478
4623
|
* `session_set_keepalive` (`registry.setKeepAlive`). Absent (not `false`)
|
|
4479
4624
|
* for every session that hasn't opted in. */
|
|
4480
4625
|
keepAlive?: boolean;
|
|
4626
|
+
/** Server-persisted, list-visibility-only favorite flag — set/cleared via
|
|
4627
|
+
* `session_set_pinned` (`registry.setPinned`) or `POST /sessions/:id/pin`.
|
|
4628
|
+
* Purely a sort/display concern: pinned sessions sort to the top of the
|
|
4629
|
+
* session list (CLI table, VS Code webview's dedicated "Pinned" group).
|
|
4630
|
+
* Deliberately orthogonal to — and must NEVER be confused with —
|
|
4631
|
+
* `keepAlive` (idle-reaper exemption, operational), the VS Code
|
|
4632
|
+
* extension's client-side-only "watch" eye (toast notifications, never
|
|
4633
|
+
* persisted here), or `watchers` (live supervisor wait count). No side
|
|
4634
|
+
* effects on reaping, notifications, or anything else. Absent (not
|
|
4635
|
+
* `false`) for every session that hasn't been pinned. */
|
|
4636
|
+
pinned?: boolean;
|
|
4481
4637
|
/** True when the session was spawned under a real PTY (node-pty)
|
|
4482
4638
|
* instead of `child_process.spawn`. PTY sessions carry raw ANSI
|
|
4483
4639
|
* bytes (alt-screen, key bindings, colors); attach goes through
|
|
@@ -4640,6 +4796,17 @@ interface SessionDescriptor {
|
|
|
4640
4796
|
* via sessions.json so `restart` can pass it as `resumeSessionId`
|
|
4641
4797
|
* and reattach to the prior conversation history. */
|
|
4642
4798
|
adapterSessionId?: string;
|
|
4799
|
+
/** Persistent isolated-config dir handed to the adapter at spawn time
|
|
4800
|
+
* (`startSession({ configDir })` → claude-code's `CLAUDE_CONFIG_DIR`).
|
|
4801
|
+
* Keyed by the FIRST session id in a restart lineage
|
|
4802
|
+
* (`adapterConfigDirFor`) and carried forward verbatim across
|
|
4803
|
+
* restarts/lazy resumes — the provider's own conversation store lives
|
|
4804
|
+
* inside it, so reusing the SAME dir is what lets `resumeSessionId`
|
|
4805
|
+
* restore full context after the adapter process died (before this,
|
|
4806
|
+
* each respawn minted a fresh temp dir and native resume always
|
|
4807
|
+
* degraded to the daemon-transcript digest). Absent on legacy rows and
|
|
4808
|
+
* adapters that don't isolate a config dir. */
|
|
4809
|
+
adapterConfigDir?: string;
|
|
4643
4810
|
/** MCP servers mounted into the agent's session at spawn time
|
|
4644
4811
|
* (orchestrator WP1). Persisted so the resume/re-spawn path can
|
|
4645
4812
|
* re-mount the same host-chosen toolset instead of resuming a
|
|
@@ -4739,6 +4906,23 @@ interface SessionDescriptor {
|
|
|
4739
4906
|
* message (`runAgentTurn`) — so delivery survives a busy parent without
|
|
4740
4907
|
* ever cancelling its in-flight work. Absent when nothing is queued. */
|
|
4741
4908
|
pendingChildCrashNotices?: string[];
|
|
4909
|
+
/** FIFO of prompts that arrived while this session was mid-turn and
|
|
4910
|
+
* asked to be QUEUED rather than rejected (`enqueuePrompt`'s
|
|
4911
|
+
* `opts.queue` arm — see its doc comment). Index 0 is next to
|
|
4912
|
+
* dispatch. A plain queued item is appended to the back; a
|
|
4913
|
+
* `force`-queued one is inserted at the front, jumping everything
|
|
4914
|
+
* already waiting WITHOUT cancelling the live turn (that's what
|
|
4915
|
+
* `interrupt` is for). Drained one item at a time, in this order, by
|
|
4916
|
+
* `dispatchQueuedPrompt` at the end of every `runAgentTurn` — never
|
|
4917
|
+
* by the caller that queued it, which already returned. Always
|
|
4918
|
+
* replaced with a NEW array reference on every mutation (push, drain,
|
|
4919
|
+
* removal), never mutated in place — the VS Code webview's
|
|
4920
|
+
* `sessionDescriptorsEqual` diff is a shallow `!==` per field, so an
|
|
4921
|
+
* in-place `.shift()` here would silently stop propagating queue
|
|
4922
|
+
* changes to the transcript panel. `[]` (not absent) once anything
|
|
4923
|
+
* has ever been queued, matching `pendingChildCrashNotices`'s
|
|
4924
|
+
* convention above. */
|
|
4925
|
+
promptQueue?: QueuedPrompt[];
|
|
4742
4926
|
/** Best-effort context-handoff digest (Fix D), stashed on a descriptor
|
|
4743
4927
|
* whose resume degraded to a BLANK spawn — the adapter's own
|
|
4744
4928
|
* conversation store was missing, or the adapter declared `resumable:
|
|
@@ -4893,6 +5077,7 @@ interface SessionSummary {
|
|
|
4893
5077
|
activitySummary?: SessionActivitySummary;
|
|
4894
5078
|
archived?: boolean;
|
|
4895
5079
|
keepAlive?: boolean;
|
|
5080
|
+
pinned?: boolean;
|
|
4896
5081
|
pty?: boolean;
|
|
4897
5082
|
name?: string;
|
|
4898
5083
|
argv?: readonly string[];
|
|
@@ -4919,6 +5104,10 @@ interface SessionSummary {
|
|
|
4919
5104
|
* `SessionDescriptor.pendingBgTasks`. Stamped at turn-end, cleared on the
|
|
4920
5105
|
* next turn start / exit. */
|
|
4921
5106
|
pendingBgTasks?: number;
|
|
5107
|
+
/** Adapter-reported turn-error marker — see
|
|
5108
|
+
* `SessionDescriptor.lastTurnErroredAt`. Stamped at turn-end, cleared on
|
|
5109
|
+
* the next turn that completes without one. */
|
|
5110
|
+
lastTurnErroredAt?: string;
|
|
4922
5111
|
origin?: string;
|
|
4923
5112
|
parentSessionId?: string;
|
|
4924
5113
|
depth?: number;
|
|
@@ -5214,11 +5403,41 @@ interface SessionsRegistry {
|
|
|
5214
5403
|
* `false` reproduces today's mid-turn rejection byte-for-byte. */
|
|
5215
5404
|
/** `opts.source` on either prompt verb is the turn's provenance
|
|
5216
5405
|
* (`agent:<sessionId>` when another session injected it — see
|
|
5217
|
-
* `SessionObserver.recordPrompt`); recording-only, never behavioral.
|
|
5406
|
+
* `SessionObserver.recordPrompt`); recording-only, never behavioral.
|
|
5407
|
+
*
|
|
5408
|
+
* `opts.queue` is the FIFO arm (additive, opt-in — omitted/false
|
|
5409
|
+
* reproduces the byte-for-byte busy rejection above, unchanged):
|
|
5410
|
+
* when the session is mid-turn AND `queue` is true, the prompt is
|
|
5411
|
+
* appended to `SessionDescriptor.promptQueue` instead of being
|
|
5412
|
+
* rejected, and this resolves immediately WITHOUT dispatching
|
|
5413
|
+
* anything — `dispatchQueuedPrompt` fires it once the current (and
|
|
5414
|
+
* any earlier-queued) turns finish. `opts.force` only matters
|
|
5415
|
+
* alongside `queue`: it inserts at the FRONT of the queue instead of
|
|
5416
|
+
* the back, jumping everything already waiting, but — unlike
|
|
5417
|
+
* `interrupt` — never touches the live turn. `opts.queueId` lets the
|
|
5418
|
+
* caller pin the queued item's id up front (the HTTP layer does this
|
|
5419
|
+
* so it can echo the id straight back in its response); omitted, one
|
|
5420
|
+
* is minted here. On an IDLE session `queue`/`force`/`queueId` are
|
|
5421
|
+
* no-ops — admission falls straight through to the normal dispatch
|
|
5422
|
+
* path below, identical to `queue` omitted. `interrupt` is checked
|
|
5423
|
+
* first: an `{interrupt: true, queue: true}` pair interrupts (never
|
|
5424
|
+
* queues) exactly like `interrupt` alone. */
|
|
5218
5425
|
enqueuePrompt(id: string, message: unknown, opts?: {
|
|
5219
5426
|
interrupt?: boolean;
|
|
5220
5427
|
source?: string;
|
|
5428
|
+
queue?: boolean;
|
|
5429
|
+
force?: boolean;
|
|
5430
|
+
queueId?: string;
|
|
5221
5431
|
}): Promise<void>;
|
|
5432
|
+
/** Cancel one not-yet-dispatched item in `SessionDescriptor.promptQueue`
|
|
5433
|
+
* by id — the composer's per-item "remove" action. Idempotent: an
|
|
5434
|
+
* unknown session or an id that's already gone (dispatched, already
|
|
5435
|
+
* removed, or never existed) resolves `{removed: false}` rather than
|
|
5436
|
+
* throwing, same shape as `interruptSession`'s no-op-is-not-an-error
|
|
5437
|
+
* contract. */
|
|
5438
|
+
removeQueuedPrompt(id: string, queueId: string): {
|
|
5439
|
+
removed: boolean;
|
|
5440
|
+
};
|
|
5222
5441
|
/** Eagerly resume ONE dead-but-resumable agent-cli session IN PLACE,
|
|
5223
5442
|
* WITHOUT a prompt — the boot-time counterpart to the lazy resume that
|
|
5224
5443
|
* `sendPrompt`/`enqueuePrompt` trigger on the first prompt after a restart
|
|
@@ -5362,11 +5581,17 @@ interface SessionsRegistry {
|
|
|
5362
5581
|
* ephemeral `watchers` counter surfaced on the descriptor at read time.
|
|
5363
5582
|
* Called by `monitorSessionWait` when a `/sessions/:id/wait` long-poll or
|
|
5364
5583
|
* `session_monitor` subscription actually blocks. A no-op for an unknown id
|
|
5365
|
-
* is fine (the wait may outlive the row).
|
|
5366
|
-
|
|
5584
|
+
* is fine (the wait may outlive the row). `detail`, when passed, is held
|
|
5585
|
+
* (by reference) alongside the count and surfaced as
|
|
5586
|
+
* `SessionDescriptor.watcherDetails` — pass the SAME object reference to
|
|
5587
|
+
* the matching {@link decWatchers} call so removal is exact. */
|
|
5588
|
+
incWatchers(id: string, detail?: SessionWatcherInfo): void;
|
|
5367
5589
|
/** Balance an {@link incWatchers} when the waiter resolves or times out.
|
|
5368
|
-
* Clamps at 0 and drops the map entry at zero so the counter can't leak.
|
|
5369
|
-
|
|
5590
|
+
* Clamps at 0 and drops the map entry at zero so the counter can't leak.
|
|
5591
|
+
* Pass the same `detail` reference given to `incWatchers` to remove it from
|
|
5592
|
+
* `watcherDetails`; omitted/mismatched detail leaves the count balanced but
|
|
5593
|
+
* the detail list untouched (defensive — should not happen in practice). */
|
|
5594
|
+
decWatchers(id: string, detail?: SessionWatcherInfo): void;
|
|
5370
5595
|
/** Archive a TERMINAL-status session (exited/killed/error) — sets
|
|
5371
5596
|
* `archived: true` and persists. Pure housekeeping: hides the row from
|
|
5372
5597
|
* `list()`'s default view, nothing else. Refuses (throws) a still-alive
|
|
@@ -5416,6 +5641,45 @@ interface SessionsRegistry {
|
|
|
5416
5641
|
* policy state — never touches the live agent. Throws when the id is
|
|
5417
5642
|
* unknown. */
|
|
5418
5643
|
setKeepAlive(id: string, keepAlive: boolean): SessionDescriptor;
|
|
5644
|
+
/** Set or clear a session's list-visibility pin (the `session_set_pinned`
|
|
5645
|
+
* MCP verb / `POST /sessions/:id/pin`). `true` flips
|
|
5646
|
+
* `SessionDescriptor.pinned` on — pure sort/display state for the CLI
|
|
5647
|
+
* table and the VS Code webview's list, which sort a pinned session to
|
|
5648
|
+
* the top. `false` clears it. Persists via the same `schedulePersist`
|
|
5649
|
+
* every descriptor mutation uses and emits `session:pinned-changed` so a
|
|
5650
|
+
* live UI resorts without waiting for its next snapshot poll. NEVER
|
|
5651
|
+
* touches `keepAlive`, reaper eligibility, or any notification path —
|
|
5652
|
+
* pin is quiet, structural state only. Throws when the id is unknown. */
|
|
5653
|
+
setPinned(id: string, pinned: boolean): SessionDescriptor;
|
|
5654
|
+
/**
|
|
5655
|
+
* Manually override `awaitingInput`/`awaitingQuestion` (the
|
|
5656
|
+
* `session_flag_status` MCP verb) — the ONE write path for this pair
|
|
5657
|
+
* besides the internal heuristic (`deriveHeuristicQuestion`) and a
|
|
5658
|
+
* driver-reported `agent-prompt`, both of which only ever run inside a
|
|
5659
|
+
* live turn. Lets a human, another agent, or the session watchdog correct
|
|
5660
|
+
* a missed real question (`awaitingInput:true`, optionally attaching
|
|
5661
|
+
* `question`) or clear a false positive (`awaitingInput:false`).
|
|
5662
|
+
* `awaitingInput:false` ALWAYS clears `awaitingQuestion` too, regardless
|
|
5663
|
+
* of what `question` was passed — a question cannot outlive its
|
|
5664
|
+
* awaiting-input flag. When `question` is given alongside `true`, it's
|
|
5665
|
+
* stored as `{ text: question, source: "structured" }` (an explicit
|
|
5666
|
+
* override is at least as authoritative as a driver-reported prompt).
|
|
5667
|
+
* Guard mirrors the INVERSE of `archiveSession`'s: only a LIVE session
|
|
5668
|
+
* (running/starting) may be flagged — a terminal session has no turn left
|
|
5669
|
+
* to be "awaiting" anything, so correcting it there would be fiction with
|
|
5670
|
+
* nothing downstream (`session_monitor`, the webhook notifier) to observe
|
|
5671
|
+
* it. Persists via `schedulePersist` and emits
|
|
5672
|
+
* `session:awaiting-input-flagged` (carrying the required `reason`) so
|
|
5673
|
+
* the correction is visible via `session_events_poll` same as every other
|
|
5674
|
+
* lifecycle event. Cleared automatically like any other awaiting-input
|
|
5675
|
+
* signal on the session's next prompt/turn start. Throws when the id is
|
|
5676
|
+
* unknown or the session is terminal.
|
|
5677
|
+
*/
|
|
5678
|
+
flagAwaitingInput(id: string, patch: {
|
|
5679
|
+
awaitingInput: boolean;
|
|
5680
|
+
question?: string;
|
|
5681
|
+
reason: string;
|
|
5682
|
+
}): SessionDescriptor;
|
|
5419
5683
|
/** Subscribe to a session's output. Returns an unsubscribe fn.
|
|
5420
5684
|
* Initial backfill: synchronously invokes `onLine` once for each
|
|
5421
5685
|
* line currently in the ring buffer so attaches show context. */
|
|
@@ -5691,6 +5955,12 @@ interface SpawnAgentInput {
|
|
|
5691
5955
|
* the resume/re-spawn path can re-mount the same toolset (orchestrator
|
|
5692
5956
|
* WP1). */
|
|
5693
5957
|
mcpServers?: AcpMcpServer[];
|
|
5958
|
+
/** Persistent isolated-config dir this spawn passed to
|
|
5959
|
+
* `startSession({ configDir })` — recorded verbatim onto
|
|
5960
|
+
* {@link SessionDescriptor.adapterConfigDir} so restart/lazy-resume can
|
|
5961
|
+
* point the respawned adapter back at the SAME dir (where the provider's
|
|
5962
|
+
* conversation store lives). See that field's doc. */
|
|
5963
|
+
adapterConfigDir?: string;
|
|
5694
5964
|
/** Spawning orchestrator's session id — set when the spawn arrived
|
|
5695
5965
|
* through the scoped sub-gateway (orchestrator WP4). Recorded on the
|
|
5696
5966
|
* descriptor for subtree scoping + quota accounting. */
|
|
@@ -6122,12 +6392,22 @@ type GhRunner = (args: readonly string[], cwd: string) => Promise<{
|
|
|
6122
6392
|
* footer is never applied.
|
|
6123
6393
|
*
|
|
6124
6394
|
* This closes that gap tool-agnostically: it subscribes to the session event
|
|
6125
|
-
* bus and, at each executor session's turn-end / exit,
|
|
6126
|
-
*
|
|
6127
|
-
*
|
|
6128
|
-
*
|
|
6129
|
-
*
|
|
6130
|
-
*
|
|
6395
|
+
* bus and, at each executor session's turn-end / exit, checks two lanes in
|
|
6396
|
+
* order and stamps the same `@agentproto-bot` footer if it's missing —
|
|
6397
|
+
* reusing {@link stampFooterOnPr}:
|
|
6398
|
+
*
|
|
6399
|
+
* A. EXACT — the session's own recorded tool calls: the transcript writer
|
|
6400
|
+
* marks a successful `gh pr create` with the created PR's url/number
|
|
6401
|
+
* (`ToolCallRecord.createdPrUrl`), naming the author session directly.
|
|
6402
|
+
* Immune to branch switches and shared checkouts.
|
|
6403
|
+
* B. BRANCH — resolve the OPEN PR for the session cwd's current branch
|
|
6404
|
+
* (via the injected {@link OpenPrResolver} port), the fallback for
|
|
6405
|
+
* adapters whose tool calls aren't recorded.
|
|
6406
|
+
*
|
|
6407
|
+
* Turn-end/exit are only poll checkpoints, never an assertion the PR is
|
|
6408
|
+
* ready: the real predicate is "did this session create a PR / does an open
|
|
6409
|
+
* PR for this branch now exist?", answered by the records and resolver, not
|
|
6410
|
+
* by timing.
|
|
6131
6411
|
*
|
|
6132
6412
|
* Strictly best-effort: every handler is wrapped so a missing session, an
|
|
6133
6413
|
* unreachable forge, or a failed `gh` can never throw out of a bus callback.
|
|
@@ -6179,6 +6459,10 @@ declare function createPrProvenanceReconciler(opts: {
|
|
|
6179
6459
|
registry: ReconcilerRegistry;
|
|
6180
6460
|
sessionEvents: SessionEventBus;
|
|
6181
6461
|
resolveOpenPr: OpenPrResolver;
|
|
6462
|
+
/** Session's recorded tool calls, the exact-attribution source (lane A).
|
|
6463
|
+
* Defaults to reading the session's own events.jsonl via
|
|
6464
|
+
* {@link readToolCallRecords}; injectable for tests. */
|
|
6465
|
+
listToolCalls?: (sessionId: string) => Promise<ToolCallRecord[]>;
|
|
6182
6466
|
run?: GhRunner;
|
|
6183
6467
|
host?: string;
|
|
6184
6468
|
}): PrProvenanceReconciler;
|
|
@@ -7577,6 +7861,12 @@ interface ConversationIndexRecord {
|
|
|
7577
7861
|
cwd: string;
|
|
7578
7862
|
adapterSlug: string;
|
|
7579
7863
|
adapterSessionId: string;
|
|
7864
|
+
/** The session's isolated provider config dir at write time (see
|
|
7865
|
+
* `ResolveNativeLinkInput.adapterConfigDir`) — recorded so readers
|
|
7866
|
+
* that go through the store abstraction (`store.read`, not
|
|
7867
|
+
* `native.path`) can resolve the same isolated dir. Absent on
|
|
7868
|
+
* pre-#824 rows and native PTY sessions. */
|
|
7869
|
+
adapterConfigDir?: string;
|
|
7580
7870
|
/** Absent when `adapterSlug` has no known native store (an adapter
|
|
7581
7871
|
* outside claude-code/hermes) — the record still links session ↔
|
|
7582
7872
|
* cwd ↔ adapterSessionId, it just can't point at a native file. */
|
|
@@ -7593,6 +7883,12 @@ interface ResolveNativeLinkInput {
|
|
|
7593
7883
|
cwd: string;
|
|
7594
7884
|
adapterSlug: string;
|
|
7595
7885
|
adapterSessionId: string;
|
|
7886
|
+
/** The session's isolated provider config dir (`SessionDescriptor.
|
|
7887
|
+
* adapterConfigDir`): since #824 a daemon-spawned claude-code session
|
|
7888
|
+
* writes its transcripts under `<adapterConfigDir>/projects/<slug>`,
|
|
7889
|
+
* not `~/.claude/projects/<slug>`. Absent for a native PTY or a
|
|
7890
|
+
* pre-#824 row — the global dir applies. */
|
|
7891
|
+
adapterConfigDir?: string;
|
|
7596
7892
|
}
|
|
7597
7893
|
/**
|
|
7598
7894
|
* Resolve where THIS provider keeps this conversation, computed once (at
|
|
@@ -8129,6 +8425,21 @@ interface CreateGatewayOptions {
|
|
|
8129
8425
|
name?: string;
|
|
8130
8426
|
/** Server version advertised over MCP. */
|
|
8131
8427
|
version?: string;
|
|
8428
|
+
/** Build identity of the binary actually serving — surfaced verbatim via
|
|
8429
|
+
* `/health` and `daemon_health` so an operator can tell a workspace dist
|
|
8430
|
+
* from the published tarball of the same version. `sha`/`builtAt` are
|
|
8431
|
+
* stamped into the CLI at build time (tsup `define`); `source` is the
|
|
8432
|
+
* serve command's runtime judgement of where its own entry lives. */
|
|
8433
|
+
build?: {
|
|
8434
|
+
/** Short git sha of the checkout the dist was built from ("" when the
|
|
8435
|
+
* build ran outside git). */
|
|
8436
|
+
sha?: string;
|
|
8437
|
+
/** ISO timestamp of the build. */
|
|
8438
|
+
builtAt?: string;
|
|
8439
|
+
/** "workspace" (a checkout's dist), "published" (npm/npx install), or
|
|
8440
|
+
* "unknown". */
|
|
8441
|
+
source?: string;
|
|
8442
|
+
};
|
|
8132
8443
|
/**
|
|
8133
8444
|
* Run BOOT.md once at startup. Pass `false` to disable. Defaults to
|
|
8134
8445
|
* `true`. The boot file is plain markdown — frontmatter-free; the
|