@gajae-code/coding-agent 0.16.7 → 0.17.1
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/CHANGELOG.md +180 -1
- package/dist/types/capability/fs.d.ts +37 -4
- package/dist/types/capability/index.d.ts +19 -0
- package/dist/types/capability/types.d.ts +9 -0
- package/dist/types/cli/doctor/args.d.ts +36 -0
- package/dist/types/cli/doctor/checks.d.ts +18 -0
- package/dist/types/cli/doctor/config-repairs.d.ts +38 -0
- package/dist/types/cli/doctor/context.d.ts +89 -0
- package/dist/types/cli/doctor/files.d.ts +27 -0
- package/dist/types/cli/doctor/ids.d.ts +20 -0
- package/dist/types/cli/doctor/install-repairs.d.ts +94 -0
- package/dist/types/cli/doctor/journal.d.ts +43 -0
- package/dist/types/cli/doctor/managed-link.d.ts +39 -0
- package/dist/types/cli/doctor/native-probe.d.ts +2 -0
- package/dist/types/cli/doctor/permission-repairs.d.ts +25 -0
- package/dist/types/cli/doctor/plugin-quarantine.d.ts +77 -0
- package/dist/types/cli/doctor/plugin-restore.d.ts +40 -0
- package/dist/types/cli/doctor/plugin-targets.d.ts +11 -0
- package/dist/types/cli/doctor/probe-client.d.ts +9 -0
- package/dist/types/cli/doctor/probe-types.d.ts +18 -0
- package/dist/types/cli/doctor/probe.d.ts +3 -0
- package/dist/types/cli/doctor/projection-probe.d.ts +2 -0
- package/dist/types/cli/doctor/repairs.d.ts +28 -0
- package/dist/types/cli/doctor/report.d.ts +27 -0
- package/dist/types/cli/doctor/runner.d.ts +4 -0
- package/dist/types/cli/doctor/safety.d.ts +10 -0
- package/dist/types/cli/doctor/service-repairs.d.ts +8 -0
- package/dist/types/cli/doctor/service-targets.d.ts +41 -0
- package/dist/types/cli/doctor/types.d.ts +145 -0
- package/dist/types/cli/doctor-cli.d.ts +7 -0
- package/dist/types/cli/doctor-supervisor.d.ts +121 -0
- package/dist/types/cli/doctor-worker.d.ts +29 -0
- package/dist/types/cli/install-activation.d.ts +158 -0
- package/dist/types/cli/macos-community-app.d.ts +41 -0
- package/dist/types/cli/mcp-cli.d.ts +0 -11
- package/dist/types/cli/update-cli.d.ts +41 -4
- package/dist/types/cli-main.d.ts +174 -0
- package/dist/types/cli.d.ts +1 -171
- package/dist/types/commands/doctor.d.ts +7 -0
- package/dist/types/commands/sdk.d.ts +17 -8
- package/dist/types/config/autorouting-tier-map.d.ts +19 -0
- package/dist/types/config/file-lock.d.ts +27 -3
- package/dist/types/config/model-preset-registry.d.ts +1 -0
- package/dist/types/config/model-registry.d.ts +12 -5
- package/dist/types/config/model-resolver.d.ts +16 -3
- package/dist/types/config/models-config-schema.d.ts +2 -0
- package/dist/types/config/settings-schema.d.ts +1 -1
- package/dist/types/coordinator-mcp/question-gate-codec.d.ts +1 -1
- package/dist/types/coordinator-mcp/session-reaper.d.ts +15 -5
- package/dist/types/cursor.d.ts +9 -9
- package/dist/types/discovery/agents-md.d.ts +6 -1
- package/dist/types/discovery/helpers.d.ts +36 -7
- package/dist/types/discovery/index.d.ts +1 -1
- package/dist/types/discovery/mcp-json.d.ts +2 -0
- package/dist/types/extensibility/extensions/loader.d.ts +22 -1
- package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +14 -1
- package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -1
- package/dist/types/extensibility/gjc-plugins/types.d.ts +25 -0
- package/dist/types/extensibility/plugins/manager.d.ts +33 -4
- package/dist/types/extensibility/plugins/marketplace/cache.d.ts +6 -0
- package/dist/types/extensibility/plugins/marketplace/manager.d.ts +186 -0
- package/dist/types/extensibility/plugins/marketplace/registry.d.ts +27 -0
- package/dist/types/extensibility/plugins/marketplace/source-resolver.d.ts +16 -1
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +16 -3
- package/dist/types/gjc-runtime/autoresearch-runtime.d.ts +6 -0
- package/dist/types/gjc-runtime/launch-worktree.d.ts +53 -0
- package/dist/types/gjc-runtime/session-layout.d.ts +8 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +15 -0
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +13 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +6 -0
- package/dist/types/main.d.ts +19 -1
- package/dist/types/modes/acp/acp-agent.d.ts +40 -0
- package/dist/types/modes/components/agent-dashboard.d.ts +1 -0
- package/dist/types/modes/components/model-selector.d.ts +2 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/runtime-mcp/config-writer.d.ts +47 -0
- package/dist/types/runtime-mcp/policy-json-edit.d.ts +60 -0
- package/dist/types/runtime-mcp/startup-policy.d.ts +4 -0
- package/dist/types/runtime-mcp/types.d.ts +2 -2
- package/dist/types/sdk/acp/adapter.d.ts +5 -1
- package/dist/types/sdk/broker/broker.d.ts +51 -0
- package/dist/types/sdk/broker/daemon-entry.d.ts +39 -0
- package/dist/types/sdk/broker/discovery.d.ts +38 -0
- package/dist/types/sdk/broker/doctor-restart.d.ts +79 -0
- package/dist/types/sdk/broker/endpoint-authority.d.ts +7 -0
- package/dist/types/sdk/broker/ensure.d.ts +14 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +2 -0
- package/dist/types/sdk/broker/process-incarnation.d.ts +50 -0
- package/dist/types/sdk/broker/runtime.d.ts +26 -0
- package/dist/types/sdk/broker/session-index.d.ts +13 -4
- package/dist/types/sdk/broker/worktree-occupancy.d.ts +14 -0
- package/dist/types/sdk/bus/chat-daemon-cli.d.ts +16 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +101 -6
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +16 -0
- package/dist/types/sdk/bus/daemon-startup-exclusion.d.ts +43 -0
- package/dist/types/sdk/bus/doctor-daemon-restart-client.d.ts +51 -0
- package/dist/types/sdk/bus/doctor-daemon-restart.d.ts +39 -0
- package/dist/types/sdk/bus/index.d.ts +2 -0
- package/dist/types/sdk/bus/notification-service.d.ts +3 -0
- package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +11 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -0
- package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +1 -0
- package/dist/types/sdk/bus/telegram-daemon.d.ts +36 -5
- package/dist/types/sdk/cli/session-cli.d.ts +1 -0
- package/dist/types/sdk/host/session-runtime.d.ts +4 -0
- package/dist/types/sdk/host/surface-policy.d.ts +3 -1
- package/dist/types/sdk/lifecycle/service.d.ts +44 -10
- package/dist/types/sdk/prompt-deadline-lease.d.ts +6 -3
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -2
- package/dist/types/sdk/prompt-failure.d.ts +47 -0
- package/dist/types/sdk/prompt-status.d.ts +19 -0
- package/dist/types/sdk/router/session-router.d.ts +3 -4
- package/dist/types/sdk/service-artifact-paths.d.ts +16 -0
- package/dist/types/sdk/session-authority.d.ts +9 -0
- package/dist/types/sdk/session.d.ts +3 -1
- package/dist/types/session/agent-session.d.ts +1 -1
- package/dist/types/session/blob-store.d.ts +1 -1
- package/dist/types/session/fallback-chain-controller.d.ts +3 -6
- package/dist/types/session/internal/managed-session-scope.d.ts +44 -0
- package/dist/types/session/primary-control-surface.d.ts +4 -0
- package/dist/types/session/session-manager.d.ts +6 -0
- package/dist/types/system-prompt.d.ts +6 -0
- package/dist/types/tools/ask.d.ts +25 -0
- package/dist/types/tools/image-gen.d.ts +0 -4
- package/dist/types/tools/skill-discovery.d.ts +7 -5
- package/dist/types/tools/ultragoal-ask-guard.d.ts +7 -4
- package/dist/types/utils/changelog.d.ts +0 -9
- package/dist/types/utils/mupdf-wasm.d.ts +1 -0
- package/package.json +9 -8
- package/scripts/compile-args.ts +8 -4
- package/src/capability/fs.ts +395 -17
- package/src/capability/index.ts +273 -10
- package/src/capability/types.ts +9 -0
- package/src/cli/customize-doctor.ts +18 -12
- package/src/cli/doctor/args.ts +236 -0
- package/src/cli/doctor/checks.ts +431 -0
- package/src/cli/doctor/config-repairs.ts +517 -0
- package/src/cli/doctor/context.ts +149 -0
- package/src/cli/doctor/files.ts +149 -0
- package/src/cli/doctor/ids.ts +115 -0
- package/src/cli/doctor/install-repairs.ts +335 -0
- package/src/cli/doctor/journal.ts +423 -0
- package/src/cli/doctor/managed-link.ts +514 -0
- package/src/cli/doctor/native-probe.ts +13 -0
- package/src/cli/doctor/permission-repairs.ts +242 -0
- package/src/cli/doctor/plugin-quarantine.ts +377 -0
- package/src/cli/doctor/plugin-restore.ts +59 -0
- package/src/cli/doctor/plugin-targets.ts +373 -0
- package/src/cli/doctor/probe-client.ts +195 -0
- package/src/cli/doctor/probe-types.ts +21 -0
- package/src/cli/doctor/probe.ts +42 -0
- package/src/cli/doctor/projection-probe.ts +249 -0
- package/src/cli/doctor/repairs.ts +1157 -0
- package/src/cli/doctor/report.ts +176 -0
- package/src/cli/doctor/runner.ts +342 -0
- package/src/cli/doctor/safety.ts +40 -0
- package/src/cli/doctor/service-repairs.ts +452 -0
- package/src/cli/doctor/service-targets.ts +274 -0
- package/src/cli/doctor/types.ts +164 -0
- package/src/cli/doctor-cli.ts +62 -0
- package/src/cli/doctor-supervisor.ts +571 -0
- package/src/cli/doctor-worker.ts +181 -0
- package/src/cli/install-activation.ts +666 -0
- package/src/cli/macos-community-app.ts +1449 -0
- package/src/cli/mcp-cli.ts +11 -21
- package/src/cli/nofile-limit.ts +5 -1
- package/src/cli/plugin-cli.ts +6 -1
- package/src/cli/update-cli.ts +362 -264
- package/src/cli-main.ts +517 -0
- package/src/cli.ts +64 -433
- package/src/commands/autoresearch.ts +11 -5
- package/src/commands/completion.ts +1 -1
- package/src/commands/doctor.ts +13 -0
- package/src/commands/sdk.ts +58 -10
- package/src/commands/ultragoal.ts +11 -5
- package/src/config/autorouting-tier-map.ts +7 -0
- package/src/config/file-lock.ts +736 -71
- package/src/config/mcp-schema.json +3 -3
- package/src/config/model-preset-registry.ts +1 -0
- package/src/config/model-registry.ts +80 -27
- package/src/config/model-resolver.ts +33 -4
- package/src/config/models-config-schema.ts +2 -0
- package/src/config/settings-schema.ts +6 -2
- package/src/coordinator-mcp/question-gate-codec.ts +1 -0
- package/src/coordinator-mcp/server.ts +534 -51
- package/src/coordinator-mcp/session-reaper.ts +64 -8
- package/src/cursor.ts +223 -53
- package/src/discovery/agents-md.ts +74 -8
- package/src/discovery/agents.ts +32 -7
- package/src/discovery/builtin.ts +184 -75
- package/src/discovery/claude-plugins.ts +85 -17
- package/src/discovery/cline.ts +38 -10
- package/src/discovery/cursor.ts +19 -6
- package/src/discovery/gemini.ts +62 -22
- package/src/discovery/github.ts +13 -3
- package/src/discovery/helpers.ts +483 -89
- package/src/discovery/index.ts +1 -0
- package/src/discovery/mcp-json.ts +36 -10
- package/src/discovery/opencode.ts +36 -19
- package/src/discovery/ssh.ts +11 -8
- package/src/discovery/windsurf.ts +12 -3
- package/src/exec/bash-executor.ts +10 -3
- package/src/exec/isolated-shell.ts +15 -2
- package/src/extensibility/extensions/loader.ts +88 -26
- package/src/extensibility/gjc-plugins/lifecycle.ts +189 -0
- package/src/extensibility/gjc-plugins/paths.ts +4 -1
- package/src/extensibility/gjc-plugins/types.ts +27 -0
- package/src/extensibility/plugins/manager.ts +200 -22
- package/src/extensibility/plugins/marketplace/cache.ts +55 -2
- package/src/extensibility/plugins/marketplace/manager.ts +1262 -162
- package/src/extensibility/plugins/marketplace/registry.ts +153 -0
- package/src/extensibility/plugins/marketplace/source-resolver.ts +116 -10
- package/src/extensibility/runtime-skill-discovery.ts +61 -9
- package/src/extensibility/skill-management.ts +7 -1
- package/src/gjc-runtime/autoresearch-runtime.ts +10 -1
- package/src/gjc-runtime/launch-worktree.test.ts +248 -0
- package/src/gjc-runtime/launch-worktree.ts +275 -38
- package/src/gjc-runtime/repository-binding.ts +26 -1
- package/src/gjc-runtime/session-layout.ts +10 -0
- package/src/gjc-runtime/session-state-lock.ts +330 -23
- package/src/gjc-runtime/session-state-sidecar.ts +328 -80
- package/src/gjc-runtime/ultragoal-runtime.ts +10 -1
- package/src/harness-control-plane/session-lease.ts +2 -2
- package/src/internal-urls/docs-index.generated.ts +28 -26
- package/src/main.ts +150 -29
- package/src/memories/index.ts +24 -2
- package/src/modes/acp/acp-agent.ts +522 -68
- package/src/modes/components/agent-dashboard.ts +3 -1
- package/src/modes/components/model-selector.ts +28 -19
- package/src/modes/components/plugin-settings.ts +2 -1
- package/src/modes/controllers/selector-controller.ts +15 -9
- package/src/modes/interactive-mode.ts +21 -3
- package/src/prompts/system/system-prompt.md +5 -1
- package/src/prompts/tools/browser.md +1 -1
- package/src/prompts/tools/move-session.md +4 -0
- package/src/prompts/tools/read.md +2 -1
- package/src/prompts/tools/skill-discovery.md +6 -5
- package/src/prompts/tools/task.md +1 -0
- package/src/runtime-mcp/config-writer.ts +228 -0
- package/src/runtime-mcp/oauth-discovery.ts +114 -14
- package/src/runtime-mcp/policy-json-edit.ts +129 -0
- package/src/runtime-mcp/startup-policy.ts +14 -0
- package/src/runtime-mcp/types.ts +2 -2
- package/src/sdk/acp/adapter.ts +27 -12
- package/src/sdk/broker/broker.ts +273 -44
- package/src/sdk/broker/daemon-entry.ts +119 -0
- package/src/sdk/broker/discovery.ts +173 -20
- package/src/sdk/broker/doctor-restart.ts +206 -0
- package/src/sdk/broker/endpoint-authority.ts +36 -0
- package/src/sdk/broker/ensure.ts +49 -14
- package/src/sdk/broker/lifecycle.ts +174 -42
- package/src/sdk/broker/process-incarnation.ts +86 -2
- package/src/sdk/broker/runtime.ts +145 -21
- package/src/sdk/broker/session-index.ts +136 -22
- package/src/sdk/broker/spawn-substrate.ts +4 -1
- package/src/sdk/broker/transport.ts +5 -0
- package/src/sdk/broker/worktree-occupancy.ts +21 -1
- package/src/sdk/bus/chat-daemon-cli.ts +63 -0
- package/src/sdk/bus/chat-daemon-control.ts +260 -64
- package/src/sdk/bus/chat-daemon-runtime.ts +141 -25
- package/src/sdk/bus/daemon-startup-exclusion.ts +119 -0
- package/src/sdk/bus/doctor-daemon-restart-client.ts +291 -0
- package/src/sdk/bus/doctor-daemon-restart.ts +92 -0
- package/src/sdk/bus/index.ts +252 -51
- package/src/sdk/bus/kind-aware-reconciliation.ts +76 -41
- package/src/sdk/bus/notification-service.ts +21 -3
- package/src/sdk/bus/reconciliation-store.ts +17 -11
- package/src/sdk/bus/telegram-daemon-cli.ts +91 -5
- package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
- package/src/sdk/bus/telegram-daemon-control.ts +47 -0
- package/src/sdk/bus/telegram-daemon-owner-registry.ts +1 -1
- package/src/sdk/bus/telegram-daemon.ts +178 -13
- package/src/sdk/cli/session-cli.ts +100 -12
- package/src/sdk/host/host.ts +2 -7
- package/src/sdk/host/session-runtime.test.ts +329 -8
- package/src/sdk/host/session-runtime.ts +202 -50
- package/src/sdk/host/surface-policy.ts +8 -1
- package/src/sdk/lifecycle/service.ts +199 -22
- package/src/sdk/mcp/server.ts +1 -1
- package/src/sdk/prompt-deadline-lease.ts +12 -4
- package/src/sdk/prompt-deadline-manager.ts +5 -7
- package/src/sdk/prompt-failure.ts +148 -0
- package/src/sdk/prompt-status.ts +30 -1
- package/src/sdk/prompt-watchdog.ts +11 -3
- package/src/sdk/protocol/operation-inventory.generated.json +18 -0
- package/src/sdk/protocol/operation-registry.ts +20 -8
- package/src/sdk/router/session-router.ts +8 -3
- package/src/sdk/service-artifact-paths.ts +26 -0
- package/src/sdk/session-authority.ts +10 -0
- package/src/sdk/session.ts +361 -194
- package/src/session/agent-session.ts +398 -93
- package/src/session/blob-store.ts +9 -9
- package/src/session/fallback-chain-controller.ts +3 -7
- package/src/session/internal/managed-session-scope.ts +445 -29
- package/src/session/internal/managed-session-storage.ts +38 -6
- package/src/session/primary-control-surface.ts +12 -0
- package/src/session/session-manager.ts +11 -3
- package/src/session/session-storage.ts +1 -1
- package/src/session-import/codex.ts +6 -1
- package/src/session-import/redact.ts +7 -0
- package/src/skill-state/workflow-mutation-guard.ts +645 -39
- package/src/slash-commands/builtin-registry.ts +7 -3
- package/src/system-prompt.ts +8 -0
- package/src/task/executor.ts +36 -3
- package/src/task/types.ts +27 -5
- package/src/tools/ask.ts +114 -34
- package/src/tools/browser/actions.ts +2 -2
- package/src/tools/browser/tab-worker.ts +11 -8
- package/src/tools/descriptors.ts +6 -1
- package/src/tools/fetch.ts +7 -2
- package/src/tools/image-gen.ts +33 -34
- package/src/tools/read.ts +78 -32
- package/src/tools/skill-discovery.ts +17 -7
- package/src/tools/tool-catalog.generated.ts +8 -8
- package/src/tools/ultragoal-ask-guard.ts +16 -26
- package/src/utils/changelog.ts +7 -1
- package/src/utils/git.ts +3 -1
- package/src/utils/markit.ts +24 -2
- package/src/utils/mupdf-wasm.ts +26 -0
- package/src/web/search/providers/openai-compatible.ts +191 -14
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
scopeRequestV1,
|
|
10
10
|
searchRowV1,
|
|
11
11
|
} from "../broker/session-scope";
|
|
12
|
+
import type { SessionBindingAuthority } from "../session-authority";
|
|
12
13
|
import {
|
|
13
14
|
SessionListTraversalError,
|
|
14
15
|
type SessionListTraversalPage,
|
|
@@ -16,6 +17,8 @@ import {
|
|
|
16
17
|
traverseSessionList,
|
|
17
18
|
} from "../session-list";
|
|
18
19
|
|
|
20
|
+
export type { SessionBindingAuthority, SessionEndpointAuthority } from "../session-authority";
|
|
21
|
+
|
|
19
22
|
export type SessionLifecycleOperation =
|
|
20
23
|
| "session.create"
|
|
21
24
|
| "session.fork"
|
|
@@ -23,8 +26,12 @@ export type SessionLifecycleOperation =
|
|
|
23
26
|
| "session.close"
|
|
24
27
|
| "session.delete"
|
|
25
28
|
| "session.reconcile_uncertain"
|
|
29
|
+
| "session.lookup"
|
|
26
30
|
| "session.list";
|
|
27
31
|
|
|
32
|
+
export type SessionLifecycleMutationOperation = Exclude<SessionLifecycleOperation, "session.lookup" | "session.list">;
|
|
33
|
+
export type SessionLifecycleLookupOperation = "session.create";
|
|
34
|
+
|
|
28
35
|
export interface SessionLifecycleActor {
|
|
29
36
|
readonly id: string;
|
|
30
37
|
readonly namespace: string;
|
|
@@ -122,11 +129,13 @@ export type SessionResumeTarget = SessionLifecycleCoordinatorTarget & {
|
|
|
122
129
|
readonly readinessTimeoutMs?: number;
|
|
123
130
|
};
|
|
124
131
|
|
|
125
|
-
export
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
132
|
+
export type SessionCloseTarget =
|
|
133
|
+
| {
|
|
134
|
+
readonly sessionId: string;
|
|
135
|
+
readonly endpointGeneration?: never;
|
|
136
|
+
readonly endpointIncarnation?: never;
|
|
137
|
+
}
|
|
138
|
+
| SessionBindingAuthority;
|
|
130
139
|
|
|
131
140
|
export interface SessionReconcileUncertainTarget {
|
|
132
141
|
readonly sessionId: string;
|
|
@@ -155,10 +164,7 @@ export interface SessionListTarget {
|
|
|
155
164
|
readonly cursor?: string;
|
|
156
165
|
}
|
|
157
166
|
|
|
158
|
-
interface SessionLifecycleMutationRequestBase<
|
|
159
|
-
TOperation extends Exclude<SessionLifecycleOperation, "session.list">,
|
|
160
|
-
TTarget,
|
|
161
|
-
> {
|
|
167
|
+
interface SessionLifecycleMutationRequestBase<TOperation extends SessionLifecycleMutationOperation, TTarget> {
|
|
162
168
|
readonly operation: TOperation;
|
|
163
169
|
readonly actor: SessionLifecycleActor;
|
|
164
170
|
readonly capability: TOperation;
|
|
@@ -184,7 +190,19 @@ export interface SessionListRequest {
|
|
|
184
190
|
readonly timeoutMs?: number;
|
|
185
191
|
}
|
|
186
192
|
|
|
187
|
-
export
|
|
193
|
+
export interface SessionLifecycleLookupRequest {
|
|
194
|
+
readonly operation: SessionLifecycleLookupOperation;
|
|
195
|
+
readonly actor: SessionLifecycleActor;
|
|
196
|
+
readonly capability: "session.lookup";
|
|
197
|
+
readonly requestKey: string;
|
|
198
|
+
readonly target: Readonly<Record<string, unknown>>;
|
|
199
|
+
readonly timeoutMs?: number;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export type SessionLifecycleRequest =
|
|
203
|
+
| SessionLifecycleMutationRequest
|
|
204
|
+
| SessionListRequest
|
|
205
|
+
| SessionLifecycleLookupRequest;
|
|
188
206
|
|
|
189
207
|
export type SessionLifecycleMutationRequest =
|
|
190
208
|
| SessionCreateRequest
|
|
@@ -209,6 +227,7 @@ export interface SessionLifecycleListEntry {
|
|
|
209
227
|
readonly sessionId: string;
|
|
210
228
|
readonly live?: boolean;
|
|
211
229
|
readonly endpointGeneration?: number;
|
|
230
|
+
readonly endpointIncarnation?: string;
|
|
212
231
|
readonly terminalUncertain?: boolean;
|
|
213
232
|
readonly cwd?: string;
|
|
214
233
|
readonly locator?: { readonly cwd: string; readonly worktreeRoot: string | null; readonly stateRoot: string };
|
|
@@ -259,6 +278,30 @@ export interface SessionListSuccessResult {
|
|
|
259
278
|
readonly result: SessionLifecycleListResult | SessionScopedListResult;
|
|
260
279
|
}
|
|
261
280
|
|
|
281
|
+
export interface SessionLifecycleLookupIdentity {
|
|
282
|
+
readonly operation: SessionLifecycleLookupOperation;
|
|
283
|
+
readonly requestKey: string;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export type SessionLifecycleLookupStatus = "found" | "pending" | "not_found" | "conflict" | "uncertain" | "terminal";
|
|
287
|
+
|
|
288
|
+
export interface SessionLifecycleLookupSuccessResult {
|
|
289
|
+
readonly ok: true;
|
|
290
|
+
readonly operation: "session.lookup";
|
|
291
|
+
readonly status: "found";
|
|
292
|
+
readonly request: SessionLifecycleLookupIdentity;
|
|
293
|
+
readonly result: SessionLifecycleSessionResult;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export interface SessionLifecycleLookupFailure {
|
|
297
|
+
readonly ok: false;
|
|
298
|
+
readonly operation: "session.lookup";
|
|
299
|
+
readonly status: Exclude<SessionLifecycleLookupStatus, "found"> | "unavailable";
|
|
300
|
+
readonly request: SessionLifecycleLookupIdentity;
|
|
301
|
+
readonly certainty: SessionLifecycleCertainty;
|
|
302
|
+
readonly error: SessionLifecycleError;
|
|
303
|
+
}
|
|
304
|
+
|
|
262
305
|
export interface SessionLifecycleError {
|
|
263
306
|
readonly code: string;
|
|
264
307
|
readonly message: string;
|
|
@@ -315,6 +358,7 @@ export type SessionCloseOutcome = SessionCloseResult | SessionCloseFailure;
|
|
|
315
358
|
export type SessionDeleteOutcome = SessionDeleteResult | SessionDeleteFailure;
|
|
316
359
|
export type SessionReconcileUncertainOutcome = SessionReconcileUncertainResult | SessionReconcileUncertainFailure;
|
|
317
360
|
export type SessionListOutcome = SessionListSuccessResult | SessionListFailure;
|
|
361
|
+
export type SessionLifecycleLookupOutcome = SessionLifecycleLookupSuccessResult | SessionLifecycleLookupFailure;
|
|
318
362
|
export type SessionLifecycleResult =
|
|
319
363
|
| SessionCreateOutcome
|
|
320
364
|
| SessionForkOutcome
|
|
@@ -322,13 +366,14 @@ export type SessionLifecycleResult =
|
|
|
322
366
|
| SessionCloseOutcome
|
|
323
367
|
| SessionDeleteOutcome
|
|
324
368
|
| SessionReconcileUncertainOutcome
|
|
325
|
-
| SessionListOutcome
|
|
369
|
+
| SessionListOutcome
|
|
370
|
+
| SessionLifecycleLookupOutcome;
|
|
326
371
|
|
|
327
372
|
/** Shared, side-effect-free validation for lifecycle mutation requests. */
|
|
328
373
|
export type SessionLifecycleMutationValidation =
|
|
329
374
|
| {
|
|
330
375
|
readonly ok: true;
|
|
331
|
-
readonly operation:
|
|
376
|
+
readonly operation: SessionLifecycleMutationOperation;
|
|
332
377
|
readonly actor: SessionLifecycleActor;
|
|
333
378
|
readonly requestKey: string;
|
|
334
379
|
readonly target: Readonly<Record<string, unknown>>;
|
|
@@ -381,7 +426,7 @@ export function deriveSessionLifecycleIdempotencyKey(
|
|
|
381
426
|
return createHash("sha256").update(canonicalJson(identity), "utf8").digest("hex");
|
|
382
427
|
}
|
|
383
428
|
|
|
384
|
-
function operationOf(value: unknown):
|
|
429
|
+
function operationOf(value: unknown): SessionLifecycleMutationOperation | "session.list" {
|
|
385
430
|
if (
|
|
386
431
|
value === "session.create" ||
|
|
387
432
|
value === "session.fork" ||
|
|
@@ -395,7 +440,7 @@ function operationOf(value: unknown): SessionLifecycleOperation {
|
|
|
395
440
|
return "session.list";
|
|
396
441
|
}
|
|
397
442
|
|
|
398
|
-
function failure<TOperation extends
|
|
443
|
+
function failure<TOperation extends SessionLifecycleMutationOperation | "session.list">(
|
|
399
444
|
operation: TOperation,
|
|
400
445
|
certainty: SessionLifecycleCertainty,
|
|
401
446
|
code: string,
|
|
@@ -427,6 +472,20 @@ function validTarget(target: unknown): target is Readonly<Record<string, unknown
|
|
|
427
472
|
return isRecord(target);
|
|
428
473
|
}
|
|
429
474
|
|
|
475
|
+
function validSessionCloseTarget(target: Readonly<Record<string, unknown>>): boolean {
|
|
476
|
+
const hasGeneration = Object.hasOwn(target, "endpointGeneration");
|
|
477
|
+
const hasIncarnation = Object.hasOwn(target, "endpointIncarnation");
|
|
478
|
+
if (hasGeneration !== hasIncarnation) return false;
|
|
479
|
+
if (!hasGeneration) return true;
|
|
480
|
+
return (
|
|
481
|
+
typeof target.endpointGeneration === "number" &&
|
|
482
|
+
Number.isSafeInteger(target.endpointGeneration) &&
|
|
483
|
+
target.endpointGeneration > 0 &&
|
|
484
|
+
typeof target.endpointIncarnation === "string" &&
|
|
485
|
+
/^[a-f0-9]{64}$/u.test(target.endpointIncarnation)
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
|
|
430
489
|
export function validateSessionReconcileUncertainTarget(value: unknown): value is SessionReconcileUncertainTarget {
|
|
431
490
|
if (!isRecord(value)) return false;
|
|
432
491
|
const target = value;
|
|
@@ -468,6 +527,8 @@ export function validateSessionLifecycleMutationRequest(request: unknown): Sessi
|
|
|
468
527
|
return failure(operation, "terminal", "capability_denied", `capability does not authorize ${operation}`);
|
|
469
528
|
if (!validTarget(record.target))
|
|
470
529
|
return failure(operation, "terminal", "invalid_request", "target must be an object");
|
|
530
|
+
if (operation === "session.close" && !validSessionCloseTarget(record.target))
|
|
531
|
+
return failure(operation, "terminal", "invalid_input", "session.close endpoint authority is invalid");
|
|
471
532
|
if (operation === "session.reconcile_uncertain" && !validateSessionReconcileUncertainTarget(record.target))
|
|
472
533
|
return failure(
|
|
473
534
|
operation,
|
|
@@ -503,6 +564,23 @@ function credentialFreeRecord(value: Record<string, unknown>): Record<string, un
|
|
|
503
564
|
return output;
|
|
504
565
|
}
|
|
505
566
|
|
|
567
|
+
function sessionEndpointProjection(value: Record<string, unknown>): {
|
|
568
|
+
endpointGeneration?: number;
|
|
569
|
+
endpointIncarnation?: string;
|
|
570
|
+
} {
|
|
571
|
+
const endpointGeneration = value.endpointGeneration;
|
|
572
|
+
const endpointIncarnation = value.endpointIncarnation;
|
|
573
|
+
if (
|
|
574
|
+
typeof endpointGeneration !== "number" ||
|
|
575
|
+
!Number.isSafeInteger(endpointGeneration) ||
|
|
576
|
+
endpointGeneration <= 0 ||
|
|
577
|
+
typeof endpointIncarnation !== "string" ||
|
|
578
|
+
!/^[a-f0-9]{64}$/u.test(endpointIncarnation)
|
|
579
|
+
)
|
|
580
|
+
return {};
|
|
581
|
+
return { endpointGeneration, endpointIncarnation };
|
|
582
|
+
}
|
|
583
|
+
|
|
506
584
|
function sessionResult(value: unknown, expectedSessionId?: string): SessionLifecycleSessionResult | undefined {
|
|
507
585
|
if (!isRecord(value)) return undefined;
|
|
508
586
|
const record = credentialFreeRecord(value);
|
|
@@ -515,13 +593,8 @@ function sessionResult(value: unknown, expectedSessionId?: string): SessionLifec
|
|
|
515
593
|
endpointIncarnation?: string;
|
|
516
594
|
reused?: boolean;
|
|
517
595
|
note?: string;
|
|
518
|
-
} = { sessionId };
|
|
596
|
+
} = { sessionId, ...sessionEndpointProjection(record) };
|
|
519
597
|
if (typeof record.cwd === "string") result.cwd = record.cwd;
|
|
520
|
-
const endpointGeneration = record.endpointGeneration;
|
|
521
|
-
if (typeof endpointGeneration === "number" && Number.isSafeInteger(endpointGeneration) && endpointGeneration > 0)
|
|
522
|
-
result.endpointGeneration = endpointGeneration;
|
|
523
|
-
if (typeof record.endpointIncarnation === "string" && /^[a-f0-9]{64}$/.test(record.endpointIncarnation))
|
|
524
|
-
result.endpointIncarnation = record.endpointIncarnation;
|
|
525
598
|
if (typeof record.reused === "boolean") result.reused = record.reused;
|
|
526
599
|
if (typeof record.note === "string") result.note = record.note;
|
|
527
600
|
return result;
|
|
@@ -601,12 +674,12 @@ function listResult(value: unknown): SessionLifecycleListResult | undefined {
|
|
|
601
674
|
sessionId: string;
|
|
602
675
|
live?: boolean;
|
|
603
676
|
endpointGeneration?: number;
|
|
677
|
+
endpointIncarnation?: string;
|
|
604
678
|
terminalUncertain?: boolean;
|
|
605
679
|
cwd?: string;
|
|
606
680
|
locator?: { cwd: string; worktreeRoot: string | null; stateRoot: string };
|
|
607
|
-
} = { sessionId: entry.sessionId };
|
|
681
|
+
} = { sessionId: entry.sessionId, ...sessionEndpointProjection(entry) };
|
|
608
682
|
if (typeof entry.live === "boolean") item.live = entry.live;
|
|
609
|
-
if (typeof entry.endpointGeneration === "number") item.endpointGeneration = entry.endpointGeneration;
|
|
610
683
|
if (typeof entry.terminalUncertain === "boolean") item.terminalUncertain = entry.terminalUncertain;
|
|
611
684
|
if (isRecord(entry.locator) && typeof entry.locator.cwd === "string") item.cwd = entry.locator.cwd;
|
|
612
685
|
if (
|
|
@@ -746,6 +819,26 @@ function certaintyForThrownError(error: {
|
|
|
746
819
|
return "retryable";
|
|
747
820
|
}
|
|
748
821
|
|
|
822
|
+
function lookupStatusForError(code: string): {
|
|
823
|
+
status: Exclude<SessionLifecycleLookupStatus, "found"> | "unavailable";
|
|
824
|
+
certainty: SessionLifecycleCertainty;
|
|
825
|
+
} {
|
|
826
|
+
if (code === "not_found") return { status: "not_found", certainty: "uncertain" };
|
|
827
|
+
if (code === "idempotency_conflict") return { status: "conflict", certainty: "uncertain" };
|
|
828
|
+
if (code === "lifecycle_pending") return { status: "pending", certainty: "uncertain" };
|
|
829
|
+
if (code === "terminal_uncertain") return { status: "uncertain", certainty: "uncertain" };
|
|
830
|
+
return { status: "terminal", certainty: certaintyForBrokerCode(code) };
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
function lookupFailure(
|
|
834
|
+
request: SessionLifecycleLookupIdentity,
|
|
835
|
+
status: Exclude<SessionLifecycleLookupStatus, "found"> | "unavailable",
|
|
836
|
+
certainty: SessionLifecycleCertainty,
|
|
837
|
+
error: SessionLifecycleError,
|
|
838
|
+
): SessionLifecycleLookupFailure {
|
|
839
|
+
return { ok: false, operation: "session.lookup", status, request, certainty, error };
|
|
840
|
+
}
|
|
841
|
+
|
|
749
842
|
function brokerSuccess(value: unknown): unknown | undefined {
|
|
750
843
|
if (!isRecord(value) || value.ok !== true) return undefined;
|
|
751
844
|
return value.result;
|
|
@@ -758,6 +851,90 @@ export class SessionLifecycleService {
|
|
|
758
851
|
this.#client = client;
|
|
759
852
|
}
|
|
760
853
|
|
|
854
|
+
async lookup(request: SessionLifecycleLookupRequest): Promise<SessionLifecycleLookupOutcome> {
|
|
855
|
+
const operation = request.operation;
|
|
856
|
+
const requestKey = typeof request.requestKey === "string" ? request.requestKey : "";
|
|
857
|
+
const identity: SessionLifecycleLookupIdentity = { operation, requestKey };
|
|
858
|
+
if (!validActor(request.actor))
|
|
859
|
+
return lookupFailure(identity, "terminal", "terminal", {
|
|
860
|
+
code: "unauthorized",
|
|
861
|
+
message: "authenticated actor is required",
|
|
862
|
+
});
|
|
863
|
+
if (request.capability !== "session.lookup")
|
|
864
|
+
return lookupFailure(identity, "terminal", "terminal", {
|
|
865
|
+
code: "capability_denied",
|
|
866
|
+
message: "capability does not authorize session.lookup",
|
|
867
|
+
});
|
|
868
|
+
if (!validRequestKey(request.requestKey))
|
|
869
|
+
return lookupFailure(identity, "terminal", "terminal", {
|
|
870
|
+
code: "invalid_request",
|
|
871
|
+
message: "requestKey is required",
|
|
872
|
+
});
|
|
873
|
+
if (!validTarget(request.target))
|
|
874
|
+
return lookupFailure(identity, "terminal", "terminal", {
|
|
875
|
+
code: "invalid_request",
|
|
876
|
+
message: "target must be an object",
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
const validation = validateSessionLifecycleMutationRequest({
|
|
880
|
+
operation,
|
|
881
|
+
actor: request.actor,
|
|
882
|
+
capability: operation,
|
|
883
|
+
requestKey: request.requestKey,
|
|
884
|
+
target: request.target,
|
|
885
|
+
});
|
|
886
|
+
if (!validation.ok) return lookupFailure(identity, "terminal", validation.certainty, validation.error);
|
|
887
|
+
|
|
888
|
+
let response: unknown;
|
|
889
|
+
try {
|
|
890
|
+
response = await this.#client.global(
|
|
891
|
+
"session.lookup",
|
|
892
|
+
{ operation, target: { ...validation.target } },
|
|
893
|
+
{
|
|
894
|
+
idempotencyKey: deriveSessionLifecycleIdempotencyKey(request.actor, request.requestKey, operation),
|
|
895
|
+
...(request.timeoutMs === undefined ? {} : { timeoutMs: request.timeoutMs }),
|
|
896
|
+
},
|
|
897
|
+
);
|
|
898
|
+
} catch (thrown) {
|
|
899
|
+
const error = brokerError(thrown) ?? brokerErrorFromThrown(thrown);
|
|
900
|
+
if (error) {
|
|
901
|
+
const mapped = lookupStatusForError(error.code);
|
|
902
|
+
const transport = TRANSPORT_ERROR_CODES.has(error.code);
|
|
903
|
+
return lookupFailure(
|
|
904
|
+
identity,
|
|
905
|
+
transport ? "unavailable" : mapped.status,
|
|
906
|
+
transport ? certaintyForThrownError(error) : mapped.certainty,
|
|
907
|
+
{
|
|
908
|
+
code: error.code,
|
|
909
|
+
message: error.message,
|
|
910
|
+
},
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
return lookupFailure(identity, "unavailable", "retryable", {
|
|
914
|
+
code: "unavailable",
|
|
915
|
+
message: "lifecycle broker request was unavailable",
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
const error = brokerError(response);
|
|
920
|
+
if (error) {
|
|
921
|
+
const mapped = lookupStatusForError(error.code);
|
|
922
|
+
return lookupFailure(identity, mapped.status, mapped.certainty, error);
|
|
923
|
+
}
|
|
924
|
+
if (!isRecord(response) || response.ok !== true)
|
|
925
|
+
return lookupFailure(identity, "uncertain", "uncertain", {
|
|
926
|
+
code: "malformed_response",
|
|
927
|
+
message: "lifecycle broker returned a malformed lookup result",
|
|
928
|
+
});
|
|
929
|
+
const result = sessionResult(brokerSuccess(response));
|
|
930
|
+
if (!result)
|
|
931
|
+
return lookupFailure(identity, "uncertain", "uncertain", {
|
|
932
|
+
code: "malformed_response",
|
|
933
|
+
message: "lifecycle broker returned a malformed session result",
|
|
934
|
+
});
|
|
935
|
+
return { ok: true, operation: "session.lookup", status: "found", request: identity, result };
|
|
936
|
+
}
|
|
937
|
+
|
|
761
938
|
async scopedList(scope: ScopeRequestV1, limit?: number, cursor?: string): Promise<SessionListOutcome> {
|
|
762
939
|
return await this.#list(
|
|
763
940
|
{
|
package/src/sdk/mcp/server.ts
CHANGED
|
@@ -150,7 +150,7 @@ function mcpOperationError(
|
|
|
150
150
|
const MCP_LIFECYCLE_ACTOR = { id: "gjc-sdk-mcp", namespace: "sdk:mcp" } as const;
|
|
151
151
|
const ROUTER_START_TIMEOUT_MS = 3_000;
|
|
152
152
|
const ROUTER_STOP_TIMEOUT_MS = 5_000;
|
|
153
|
-
type LifecycleMutationOperation = Exclude<SessionLifecycleOperation, "session.list">;
|
|
153
|
+
type LifecycleMutationOperation = Exclude<SessionLifecycleOperation, "session.lookup" | "session.list">;
|
|
154
154
|
|
|
155
155
|
function isLifecycleOperation(operation: string): operation is LifecycleMutationOperation {
|
|
156
156
|
return (
|
|
@@ -11,7 +11,12 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
/** Agent session event types that constitute attributable agent/skill/tool progress. */
|
|
14
|
-
const ATTRIBUTABLE_PROGRESS_EVENT_TYPES = new Set([
|
|
14
|
+
const ATTRIBUTABLE_PROGRESS_EVENT_TYPES = new Set([
|
|
15
|
+
"tool_execution_start",
|
|
16
|
+
/** Periodic output from a running tool; renews the deadline for long-running tools (e.g. Gradle compiles). */
|
|
17
|
+
"tool_execution_update",
|
|
18
|
+
"tool_execution_end",
|
|
19
|
+
]);
|
|
15
20
|
|
|
16
21
|
export interface PromptDeadlineLease {
|
|
17
22
|
/** When the prompt was accepted; anchors the hard maximum runtime. */
|
|
@@ -57,9 +62,12 @@ export function recordAttributableProgress(lease: PromptDeadlineLease, now: numb
|
|
|
57
62
|
|
|
58
63
|
/**
|
|
59
64
|
* Whether an agent session event at the prompt/agent runtime boundary is
|
|
60
|
-
* attributable progress for the accepted prompt.
|
|
61
|
-
*
|
|
62
|
-
* covered;
|
|
65
|
+
* attributable progress for the accepted prompt. Tool execution boundaries and
|
|
66
|
+
* streaming updates qualify: skills do their work through tools, so skill
|
|
67
|
+
* progress is covered; `tool_execution_update` keeps long-running tools (e.g.
|
|
68
|
+
* a multi-minute Gradle compile that streams stdout) from tripping the
|
|
69
|
+
* inactivity deadline mid-run. Streaming text/thinking deltas, retries, and
|
|
70
|
+
* bookkeeping are not attributable.
|
|
63
71
|
*/
|
|
64
72
|
export function isAttributableProgressEventType(type: string): boolean {
|
|
65
73
|
return ATTRIBUTABLE_PROGRESS_EVENT_TYPES.has(type);
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
promptDeadlineAt,
|
|
8
8
|
recordAttributableProgress,
|
|
9
9
|
} from "./prompt-deadline-lease";
|
|
10
|
+
import { failedPromptOutcome } from "./prompt-failure";
|
|
10
11
|
import type { SdkPromptTerminalOutcome } from "./prompt-status";
|
|
11
12
|
import type { TurnResultContent } from "./turn-result";
|
|
12
13
|
|
|
@@ -17,10 +18,8 @@ const UNCERTAINTY_RETRY_DELAY_MS = 1_000;
|
|
|
17
18
|
|
|
18
19
|
type DeadlineReconciliation = InvocationReconciliation | KindAwareReconciliation;
|
|
19
20
|
|
|
20
|
-
export type PromptDeadlineOutcome = {
|
|
21
|
-
kind: "failed";
|
|
21
|
+
export type PromptDeadlineOutcome = Extract<SdkPromptTerminalOutcome, { kind: "failed" }> & {
|
|
22
22
|
code: "prompt_deadline_exceeded";
|
|
23
|
-
message: string;
|
|
24
23
|
provenance: "deadline";
|
|
25
24
|
};
|
|
26
25
|
|
|
@@ -161,12 +160,11 @@ export class PromptDeadlineManager {
|
|
|
161
160
|
return;
|
|
162
161
|
}
|
|
163
162
|
const generation = lease.generation;
|
|
164
|
-
const outcome: PromptDeadlineOutcome = {
|
|
165
|
-
kind: "failed",
|
|
163
|
+
const outcome: PromptDeadlineOutcome = failedPromptOutcome({
|
|
166
164
|
code: "prompt_deadline_exceeded",
|
|
167
|
-
message: "Prompt deadline exceeded.",
|
|
168
165
|
provenance: "deadline",
|
|
169
|
-
|
|
166
|
+
evidence: {},
|
|
167
|
+
}) as PromptDeadlineOutcome;
|
|
170
168
|
try {
|
|
171
169
|
await this.#reconciliation.claimPendingOutcome("prompt", correlation, outcome);
|
|
172
170
|
} catch {
|
|
@@ -3,9 +3,157 @@
|
|
|
3
3
|
* Provider error text is retained only in the local diagnostic log; wire and
|
|
4
4
|
* persisted reconciliation details expose a fixed redacted message.
|
|
5
5
|
*/
|
|
6
|
+
import type { SdkPromptFailureCategory, SdkPromptFailurePhase, SdkPromptTerminalOutcome } from "./prompt-status";
|
|
7
|
+
|
|
6
8
|
export const PROMPT_FAILURE_CODE_MAX = 64;
|
|
7
9
|
const LOCAL_FAILURE_LOG_MAX = 16_384;
|
|
8
10
|
|
|
11
|
+
export const PROMPT_FAILURE_MESSAGE_SUBMISSION = "Prompt submission failed.";
|
|
12
|
+
export const PROMPT_FAILURE_MESSAGE_POST_START_PROVIDER = "Provider failure after execution started.";
|
|
13
|
+
export const PROMPT_FAILURE_MESSAGE_POST_START_AGENT = "Agent run failed after execution started.";
|
|
14
|
+
export const PROMPT_FAILURE_MESSAGE_DEADLINE = "Prompt deadline exceeded.";
|
|
15
|
+
|
|
16
|
+
/** Evidence that decides whether a failure happened before or after the run started. */
|
|
17
|
+
export interface PromptFailureEvidence {
|
|
18
|
+
startedAt?: number;
|
|
19
|
+
hasActivity?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Start/activity evidence for phase derivation from a reconciliation record. */
|
|
23
|
+
export function failureEvidence(record: { startedAt?: number }, hasActivity?: boolean): PromptFailureEvidence {
|
|
24
|
+
return {
|
|
25
|
+
...(record.startedAt !== undefined ? { startedAt: record.startedAt } : {}),
|
|
26
|
+
...(hasActivity === true ? { hasActivity: true } : {}),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Bounded classifier sets. Only these safe tokens may select a category; any
|
|
32
|
+
* other value (including `undefined`) stays `unknown` instead of guessing, so
|
|
33
|
+
* an unrecognized or provider-invented code cannot masquerade as a known class.
|
|
34
|
+
*/
|
|
35
|
+
const PROVIDER_TRANSPORT_CODES = new Set([
|
|
36
|
+
"provider_down",
|
|
37
|
+
"provider_unavailable",
|
|
38
|
+
"upstream_stream_interrupted",
|
|
39
|
+
"upstream_error",
|
|
40
|
+
"transport_reset",
|
|
41
|
+
"stream_first_event_timeout",
|
|
42
|
+
"empty_response",
|
|
43
|
+
"server_is_overloaded",
|
|
44
|
+
]);
|
|
45
|
+
const PROVIDER_REJECTED_CODES = new Set(["provider_rejected", "provider_http_402", "provider_http_429"]);
|
|
46
|
+
const AGENT_RUNTIME_CODES = new Set([
|
|
47
|
+
"agent_failed",
|
|
48
|
+
"internal",
|
|
49
|
+
"local_snapshot_failure",
|
|
50
|
+
"local_buffer_overflow",
|
|
51
|
+
"argument_validation",
|
|
52
|
+
"execution",
|
|
53
|
+
"io_error",
|
|
54
|
+
"skill_runtime",
|
|
55
|
+
"escaped_arguments_discarded",
|
|
56
|
+
"prompt_failed",
|
|
57
|
+
"aborted",
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
/** Whether the run had already started when the failure was recorded. */
|
|
61
|
+
export function promptFailurePhase(evidence: PromptFailureEvidence): SdkPromptFailurePhase {
|
|
62
|
+
return evidence.startedAt !== undefined || evidence.hasActivity === true ? "post_start" : "submission";
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function isSdkPromptFailurePhase(value: unknown): value is SdkPromptFailurePhase {
|
|
66
|
+
return value === "submission" || value === "post_start";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Allowlisted origin category for a bounded safe classifier + provenance. */
|
|
70
|
+
export function promptFailureCategory(
|
|
71
|
+
code: string | undefined,
|
|
72
|
+
provenance: "agent_failed" | "deadline",
|
|
73
|
+
): SdkPromptFailureCategory {
|
|
74
|
+
if (provenance === "deadline" || code === "prompt_deadline_exceeded") return "deadline";
|
|
75
|
+
if (code === undefined) return "unknown";
|
|
76
|
+
if (PROVIDER_TRANSPORT_CODES.has(code) || /^provider_http_5\d\d$/.test(code)) return "provider_transport";
|
|
77
|
+
if (PROVIDER_REJECTED_CODES.has(code) || /^provider_http_4\d\d$/.test(code)) return "provider_rejected";
|
|
78
|
+
if (AGENT_RUNTIME_CODES.has(code)) return "agent_runtime";
|
|
79
|
+
return "unknown";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Phase- and category-aware safe wording. A post-start failure is never
|
|
84
|
+
* described as a submission rejection; the wording says only what the bounded
|
|
85
|
+
* category actually proves.
|
|
86
|
+
*/
|
|
87
|
+
export function promptFailureMessage(phase: SdkPromptFailurePhase, category: SdkPromptFailureCategory): string {
|
|
88
|
+
if (category === "deadline") return PROMPT_FAILURE_MESSAGE_DEADLINE;
|
|
89
|
+
if (phase === "submission") return PROMPT_FAILURE_MESSAGE_SUBMISSION;
|
|
90
|
+
if (category === "provider_transport" || category === "provider_rejected")
|
|
91
|
+
return PROMPT_FAILURE_MESSAGE_POST_START_PROVIDER;
|
|
92
|
+
return PROMPT_FAILURE_MESSAGE_POST_START_AGENT;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Recompute `phase`, `category` and `message` for a failed outcome from the
|
|
97
|
+
* bounded classifier plus the record's start/activity evidence. Non-failed
|
|
98
|
+
* outcomes pass through untouched. Idempotent.
|
|
99
|
+
*/
|
|
100
|
+
export function rephaseFailedOutcome(
|
|
101
|
+
outcome: SdkPromptTerminalOutcome,
|
|
102
|
+
evidence: PromptFailureEvidence,
|
|
103
|
+
): SdkPromptTerminalOutcome {
|
|
104
|
+
if (outcome.kind !== "failed") return outcome;
|
|
105
|
+
const category = promptFailureCategory(outcome.providerCode ?? outcome.code, outcome.provenance);
|
|
106
|
+
const phase = promptFailurePhase(evidence);
|
|
107
|
+
const message = promptFailureMessage(phase, category);
|
|
108
|
+
if (category === outcome.category && phase === outcome.phase && message === outcome.message) return outcome;
|
|
109
|
+
return { ...outcome, category, phase, message };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Build a complete failed outcome from a bounded classifier and evidence. */
|
|
113
|
+
export function failedPromptOutcome(input: {
|
|
114
|
+
code: "prompt_failed" | "prompt_deadline_exceeded";
|
|
115
|
+
provenance: "agent_failed" | "deadline";
|
|
116
|
+
providerCode?: string;
|
|
117
|
+
phase?: SdkPromptFailurePhase;
|
|
118
|
+
evidence: PromptFailureEvidence;
|
|
119
|
+
}): Extract<SdkPromptTerminalOutcome, { kind: "failed" }> {
|
|
120
|
+
const category = promptFailureCategory(input.providerCode ?? input.code, input.provenance);
|
|
121
|
+
const phase = input.phase ?? promptFailurePhase(input.evidence);
|
|
122
|
+
return {
|
|
123
|
+
kind: "failed",
|
|
124
|
+
code: input.code,
|
|
125
|
+
message: promptFailureMessage(phase, category),
|
|
126
|
+
provenance: input.provenance,
|
|
127
|
+
phase,
|
|
128
|
+
category,
|
|
129
|
+
...(input.providerCode !== undefined ? { providerCode: input.providerCode } : {}),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Bounded safe classifier read off a terminal assistant message: the provider's
|
|
135
|
+
* own `errorCode`, else the typed transport fact's `providerCode`. Only a safe
|
|
136
|
+
* token is accepted; anything else is dropped rather than forwarded.
|
|
137
|
+
*/
|
|
138
|
+
export function assistantFailureCode(assistant: unknown): string | undefined {
|
|
139
|
+
try {
|
|
140
|
+
const candidate = assistant as { errorCode?: unknown; transportFailure?: { providerCode?: unknown } } | undefined;
|
|
141
|
+
const direct = candidate?.errorCode;
|
|
142
|
+
if (typeof direct === "string" && direct.length <= PROMPT_FAILURE_CODE_MAX && /^[A-Za-z0-9._-]+$/.test(direct))
|
|
143
|
+
return direct;
|
|
144
|
+
const transport = candidate?.transportFailure?.providerCode;
|
|
145
|
+
if (
|
|
146
|
+
typeof transport === "string" &&
|
|
147
|
+
transport.length <= PROMPT_FAILURE_CODE_MAX &&
|
|
148
|
+
/^[A-Za-z0-9._-]+$/.test(transport)
|
|
149
|
+
)
|
|
150
|
+
return transport;
|
|
151
|
+
return undefined;
|
|
152
|
+
} catch {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
9
157
|
/** Safe-token code capped at 64; arbitrary failure text is never retained. */
|
|
10
158
|
export function sanitizePromptFailure(error: unknown): { code: string; message: string } {
|
|
11
159
|
let rawCode = "";
|
package/src/sdk/prompt-status.ts
CHANGED
|
@@ -57,9 +57,38 @@ import type { ReceiptState } from "./receipt-state";
|
|
|
57
57
|
export type PromptReconciliationStatus = "accepted" | "in_flight" | "terminal_ok" | "failed";
|
|
58
58
|
export type SdkPromptStopReason = "end_turn" | "max_tokens" | "max_turn_requests" | "refusal" | "cancelled";
|
|
59
59
|
export type SdkPromptFailureCode = "prompt_failed" | "prompt_deadline_exceeded";
|
|
60
|
+
/**
|
|
61
|
+
* Stable, safe execution phase of a failed prompt. `submission` means the
|
|
62
|
+
* failure happened before the run started (a genuine submission rejection);
|
|
63
|
+
* `post_start` means the run had already started, so it must never be described
|
|
64
|
+
* as a submission rejection.
|
|
65
|
+
*/
|
|
66
|
+
export type SdkPromptFailurePhase = "submission" | "post_start";
|
|
67
|
+
/**
|
|
68
|
+
* Allowlisted, bounded origin category for a failed prompt. It is derived only
|
|
69
|
+
* from safe classifiers (never raw provider text) and preserves `unknown` when
|
|
70
|
+
* attribution is uncertain instead of guessing.
|
|
71
|
+
*/
|
|
72
|
+
export type SdkPromptFailureCategory =
|
|
73
|
+
| "provider_transport"
|
|
74
|
+
| "provider_rejected"
|
|
75
|
+
| "agent_runtime"
|
|
76
|
+
| "deadline"
|
|
77
|
+
| "unknown";
|
|
60
78
|
export type SdkPromptTerminalOutcome =
|
|
61
79
|
| { kind: "stopped"; reason: SdkPromptStopReason; provenance: "agent" | "client_cancel" }
|
|
62
|
-
| {
|
|
80
|
+
| {
|
|
81
|
+
kind: "failed";
|
|
82
|
+
code: SdkPromptFailureCode;
|
|
83
|
+
message: string;
|
|
84
|
+
provenance: "agent_failed" | "deadline";
|
|
85
|
+
/** Execution phase at failure time; never a submission rejection when post_start. */
|
|
86
|
+
phase: SdkPromptFailurePhase;
|
|
87
|
+
/** Bounded failure-origin category; `unknown` when attribution is uncertain. */
|
|
88
|
+
category: SdkPromptFailureCategory;
|
|
89
|
+
/** Bounded safe provider/transport classifier when the provider supplied one. */
|
|
90
|
+
providerCode?: string;
|
|
91
|
+
};
|
|
63
92
|
|
|
64
93
|
/** Exactly one selector per lookup. */
|
|
65
94
|
export type TurnPromptStatusSelector = { clientRef: string } | { commandId: string; turnId: string };
|
|
@@ -115,9 +115,17 @@ export class PromptActivity {
|
|
|
115
115
|
this.#awaitingModel = true;
|
|
116
116
|
return;
|
|
117
117
|
}
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
|
|
118
|
+
// `message_update` is a streaming chunk: the model is still producing this response,
|
|
119
|
+
// so the gap that follows it is another inference gap, not a dead producer. Clearing
|
|
120
|
+
// `#awaitingModel` here would drop the turn to the narrow idle bound mid-stream, and a
|
|
121
|
+
// slow next chunk would be killed at that bound (issue #5571). The stream only truly
|
|
122
|
+
// ends at `message_end` (role=assistant) below, so `message_update` is intentionally
|
|
123
|
+
// left as an active model signal and does not clear inference state.
|
|
124
|
+
//
|
|
125
|
+
// The tool call the model asked for, by contrast, marks the model's turn as answered:
|
|
126
|
+
// inference has produced its result, and any following gap is governed by the tool
|
|
127
|
+
// bound while that tool runs.
|
|
128
|
+
if (eventType === "tool_execution_start") {
|
|
121
129
|
this.#awaitingModel = false;
|
|
122
130
|
return;
|
|
123
131
|
}
|