@astrosheep/keiyaku 2.9.2 → 2.9.4
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/build/.tsbuildinfo +1 -1
- package/build/agents/call-terms.js +13 -94
- package/build/agents/harness/activity-values.js +16 -0
- package/build/agents/harness/event-persistence.js +218 -0
- package/build/agents/harness/execution-handle.js +25 -222
- package/build/agents/harness/index.js +3 -1
- package/build/agents/harness/outcome.js +47 -4
- package/build/agents/harness/projection.js +42 -59
- package/build/agents/harness/provider-adapter.js +58 -0
- package/build/agents/harness/router.js +11 -187
- package/build/agents/harness/runtime.js +17 -4
- package/build/agents/harness/session.js +15 -0
- package/build/agents/launch-snapshot/model.js +15 -236
- package/build/agents/launch-snapshot/parse-helpers.js +114 -0
- package/build/agents/launch-snapshot/resolve.js +17 -43
- package/build/agents/opencode-sdk.js +45 -12
- package/build/agents/providers/claude-agent-sdk/adapter.js +6 -17
- package/build/agents/providers/claude-agent-sdk/registration.js +214 -0
- package/build/agents/providers/claude-agent-sdk/session-schema.js +2 -0
- package/build/agents/providers/codex-app-server/adapter.js +50 -53
- package/build/agents/providers/codex-app-server/events.js +67 -11
- package/build/agents/providers/codex-app-server/identity.js +1 -0
- package/build/agents/providers/codex-app-server/policy.js +29 -0
- package/build/agents/providers/codex-app-server/registration.js +248 -0
- package/build/agents/providers/codex-app-server/session-schema.js +6 -0
- package/build/agents/providers/codex-app-server/session.js +23 -17
- package/build/agents/providers/codex-app-server/terms.js +1 -0
- package/build/agents/providers/opencode-sdk/adapter.js +94 -50
- package/build/agents/providers/opencode-sdk/events.js +8 -4
- package/build/agents/providers/opencode-sdk/registration.js +135 -0
- package/build/agents/providers/opencode-sdk/session-schema.js +2 -0
- package/build/agents/providers/opencode-sdk/session.js +21 -14
- package/build/agents/providers/opencode-sdk/terms.js +1 -0
- package/build/agents/providers/pi/adapter.js +36 -30
- package/build/agents/providers/pi/registration.js +145 -0
- package/build/agents/providers/pi/session-schema.js +6 -0
- package/build/agents/providers/pi/terms.js +1 -0
- package/build/agents/providers/registration.js +7 -0
- package/build/agents/providers/registry.js +76 -0
- package/build/agents/selector.js +2 -29
- package/build/agents/types.js +8 -0
- package/build/artifact-directories.js +22 -0
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/view/handler.js +5 -4
- package/build/cli/commands/akuma.js +6 -0
- package/build/cli/commands/contract/amend/handler.js +8 -2
- package/build/cli/commands/contract/arc/handler.js +7 -1
- package/build/cli/commands/contract/bind/handler.js +4 -3
- package/build/cli/commands/contract/bind/meta.js +34 -7
- package/build/cli/commands/contract/forfeit/handler.js +4 -4
- package/build/cli/commands/contract/log/handler.js +3 -3
- package/build/cli/commands/contract/petition/handler.js +4 -6
- package/build/cli/commands/contract/renew/handler.js +20 -6
- package/build/cli/commands/contract/renew/meta.js +5 -4
- package/build/cli/commands/metadata.js +58 -0
- package/build/cli/commands/projection/call/handler.js +6 -5
- package/build/cli/commands/projection/kill/handler.js +16 -32
- package/build/cli/commands/projection/shared.js +28 -0
- package/build/cli/commands/projection/status/handler.js +1 -1
- package/build/cli/commands/projection/tell/handler.js +14 -30
- package/build/cli/commands/projection/wait/handler.js +45 -22
- package/build/cli/commands/projection/wait/meta.js +7 -2
- package/build/cli/commands/registry.js +2 -54
- package/build/cli/commands/shared.js +10 -7
- package/build/cli/commands/skills/install/handler.js +2 -5
- package/build/cli/commands/skills/skills/handler.js +1 -1
- package/build/cli/commands/task/add/handler.js +5 -13
- package/build/cli/commands/task/catalog.js +2 -2
- package/build/cli/commands/task/done/handler.js +4 -8
- package/build/cli/commands/task/drop/handler.js +3 -6
- package/build/cli/commands/task/ls/handler.js +3 -5
- package/build/cli/commands/task/shared.js +14 -4
- package/build/cli/commands/task/{view → show}/handler.js +7 -8
- package/build/cli/commands/task/show/meta.js +8 -0
- package/build/cli/commands/task/start/handler.js +3 -6
- package/build/cli/commands/task/stop/handler.js +4 -8
- package/build/cli/commands/task/task/handler.js +1 -1
- package/build/cli/commands/task/update/handler.js +4 -8
- package/build/cli/completion.js +1 -1
- package/build/cli/flags.js +19 -3
- package/build/cli/help.js +4 -11
- package/build/cli/index.js +57 -83
- package/build/cli/missing-subcommand.js +7 -0
- package/build/cli/parse-flags.js +14 -5
- package/build/cli/parse-metadata.js +3 -3
- package/build/cli/parse-selectors.js +1 -1
- package/build/cli/parse.js +21 -0
- package/build/cli/projection-address.js +7 -12
- package/build/cli/render/address.js +41 -37
- package/build/cli/render/arc.js +24 -12
- package/build/cli/render/call.js +11 -5
- package/build/cli/render/errors.js +36 -1
- package/build/cli/render/format.js +4 -0
- package/build/cli/render/kanshi.js +6 -12
- package/build/cli/render/kill.js +9 -0
- package/build/cli/render/misc.js +55 -12
- package/build/cli/render/petition.js +20 -15
- package/build/cli/render/projection-activity.js +3 -0
- package/build/cli/render/shared.js +60 -21
- package/build/cli/render/skills.js +10 -0
- package/build/cli/render/status.js +37 -14
- package/build/cli/render/success-response.js +77 -0
- package/build/cli/render/task.js +54 -14
- package/build/cli/render/tell.js +5 -0
- package/build/cli/render/terminal-failure.js +58 -0
- package/build/cli/render/types.js +1 -0
- package/build/cli/render/wait.js +38 -36
- package/build/cli/types.js +1 -1
- package/build/config/akuma-loader.js +0 -5
- package/build/config/env-keys.js +1 -1
- package/build/config/provider-policy-ownership.js +3 -32
- package/build/config/settings/disease.js +8 -1
- package/build/config/settings/loader.js +11 -3
- package/build/config/settings/provider-instance-fields.js +51 -0
- package/build/config/settings/schema.js +6 -176
- package/build/core/addressing.js +66 -16
- package/build/core/amend.js +135 -18
- package/build/core/arc.js +19 -67
- package/build/core/bind.js +82 -35
- package/build/core/call/call.js +15 -9
- package/build/core/call/context.js +6 -51
- package/build/core/call/execution.js +21 -22
- package/build/core/call/prompt.js +14 -1
- package/build/core/command-markdown.js +45 -0
- package/build/core/context.js +13 -7
- package/build/core/contract-view.js +20 -3
- package/build/core/draft.js +123 -16
- package/build/core/forfeit.js +5 -2
- package/build/core/hints.js +1 -75
- package/build/core/identifier-slug.js +66 -0
- package/build/core/ids.js +25 -11
- package/build/core/ledger.js +20 -68
- package/build/core/markdown/parser.js +0 -68
- package/build/core/markdown/render.js +68 -0
- package/build/core/markdown/sections.js +2 -1
- package/build/core/outcome-base.js +4 -0
- package/build/core/projection/generation/database.js +2 -38
- package/build/core/projection/generation/model.js +42 -1
- package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
- package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +19 -49
- package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
- package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +5 -3
- package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
- package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +18 -3
- package/build/core/projection/generation/store.js +2 -2
- package/build/core/projection/generation/transitions.js +1 -1
- package/build/core/projection/index.js +27 -0
- package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
- package/build/core/{projection-alias.js → projection/projection-alias.js} +14 -19
- package/build/core/projection/projection-coordinate.js +61 -0
- package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
- package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +2 -57
- package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
- package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
- package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +1 -1
- package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
- package/build/core/{projection-status.js → projection/projection-status.js} +98 -25
- package/build/core/projection/projection-terminal-failure.js +104 -0
- package/build/core/projection/projection-wait.js +278 -0
- package/build/core/projection/projection-wake.js +203 -0
- package/build/core/provider-loader-ports.js +4 -0
- package/build/core/ref-log.js +65 -40
- package/build/core/registry.js +63 -10
- package/build/core/renew-session.js +128 -0
- package/build/core/renew.js +426 -99
- package/build/core/scope.js +143 -66
- package/build/core/seal.js +139 -35
- package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +9 -14
- package/build/core/{claim.js → settlement/claim.js} +32 -8
- package/build/core/settlement/index.js +19 -0
- package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +22 -18
- package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
- package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
- package/build/core/settlement/petition-io.js +1 -0
- package/build/core/{petition-preview.js → settlement/petition-preview.js} +1 -1
- package/build/core/{petition.js → settlement/petition.js} +12 -10
- package/build/core/settlement/queue-read-model.js +143 -0
- package/build/core/settlement/queue-seat-allocation.js +156 -0
- package/build/core/settlement/queue.js +6 -0
- package/build/core/settlement/settlement.js +295 -0
- package/build/core/{verdict.js → settlement/verdict.js} +9 -37
- package/build/core/status/board.js +24 -23
- package/build/core/status/ledger-batch.js +158 -0
- package/build/core/status/reconciliation.js +10 -4
- package/build/core/stored-agent-event.js +3 -0
- package/build/core/task/board.js +40 -4
- package/build/core/task/commands.js +30 -21
- package/build/core/task/index.js +12 -0
- package/build/core/task/settlement-git.js +157 -65
- package/build/core/task/settlement-policy.js +54 -24
- package/build/core/task/task-contract.js +370 -0
- package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
- package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
- package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
- package/build/core/{task-git-store.js → task/task-git-store.js} +92 -29
- package/build/core/task/task-repository.js +1 -0
- package/build/core/{task-store-repository.js → task/task-store-repository.js} +5 -4
- package/build/core/task/task-store.js +1 -0
- package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
- package/build/core/task/task.js +5 -0
- package/build/core/task/tree.js +37 -0
- package/build/core/task/validation.js +5 -2
- package/build/core/transcripts.js +15 -3
- package/build/core/worktree-path.js +43 -28
- package/build/flow-error.js +85 -39
- package/build/fs/durability.js +27 -0
- package/build/fs/path-coordinate.js +16 -0
- package/build/generated/version.js +3 -2
- package/build/git/branches.js +2 -1
- package/build/git/core.js +106 -2
- package/build/git/path-coordinate.js +17 -0
- package/build/git/refs.js +57 -0
- package/build/git/streaming-batch.js +301 -0
- package/build/git/worktree.js +65 -0
- package/build/index.js +3 -3
- package/build/keiyaku.js +2 -36
- package/package.json +4 -10
- package/skills/keiyaku/SKILL.md +3 -2
- package/skills/keiyaku-akuma/SKILL.md +10 -6
- package/skills/keiyaku-task/SKILL.md +1 -1
- package/skills/keiyaku-workflow/SKILL.md +25 -4
- package/build/agents/providers/codex-sdk.js +0 -329
- package/build/cli/commands/task/view/meta.js +0 -8
- package/build/core/command-io.js +0 -174
- package/build/core/path-coordinate.js +0 -27
- package/build/core/petition-claim.js +0 -117
- package/build/core/petition-run.js +0 -83
- package/build/core/projection-coordinate.js +0 -63
- package/build/core/projection-wait.js +0 -165
- package/build/core/projection-wake.js +0 -136
- package/build/core/queue.js +0 -343
- package/build/core/task-contract.js +0 -237
- package/build/core/task.js +0 -4
- /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
- /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
- /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
- /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
- /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { claudeSettingSourceSchema, executableSchema, providerCommonFields, providerEnvSchema, } from "../../../config/settings/provider-instance-fields.js";
|
|
3
|
+
import { FlowError } from "../../../flow-error.js";
|
|
4
|
+
import { exactKeys, optionalString, optionalStringRecord, requiredEnum, snapshotError, } from "../../launch-snapshot/parse-helpers.js";
|
|
5
|
+
import { SUBAGENT_SESSION_VERSION, subagentSessionEnvelopeSchema, } from "../../session.js";
|
|
6
|
+
import { CLAUDE_AGENT_SDK_PROVIDER } from "./session.js";
|
|
7
|
+
import { claudeSessionSchema } from "./session-schema.js";
|
|
8
|
+
const startClaudeAgentSdk = async (prompt, cwd, options) => {
|
|
9
|
+
const { startClaudeAgentSdk: start } = await import("./adapter.js");
|
|
10
|
+
return start(prompt, cwd, options);
|
|
11
|
+
};
|
|
12
|
+
const CLAUDE_SETTING_SOURCES = new Set(["project", "user", "local"]);
|
|
13
|
+
const ACCESS_VALUES = ["read", "write", "auto"];
|
|
14
|
+
function admitResumeShape(schema, session, resumePath) {
|
|
15
|
+
const envelopeResult = subagentSessionEnvelopeSchema.safeParse(session);
|
|
16
|
+
if (!envelopeResult.success) {
|
|
17
|
+
throw new FlowError("INVALID_RESPONSE_PATH", `Resume path file '${resumePath}' includes an invalid session envelope.`);
|
|
18
|
+
}
|
|
19
|
+
if (session.provider !== CLAUDE_AGENT_SDK_PROVIDER) {
|
|
20
|
+
throw new FlowError("INVALID_RESPONSE_PATH", `Resume path file '${resumePath}' was created with provider '${session.provider}', but the selected subagent resolves to '${CLAUDE_AGENT_SDK_PROVIDER}'. Cross-provider resume is not supported.`);
|
|
21
|
+
}
|
|
22
|
+
if (session.version !== SUBAGENT_SESSION_VERSION) {
|
|
23
|
+
throw new FlowError("INVALID_RESPONSE_PATH", `Resume path file '${resumePath}' uses unsupported session version '${session.version}' for provider '${session.provider}'.`);
|
|
24
|
+
}
|
|
25
|
+
const shapeResult = schema.safeParse(session.handle);
|
|
26
|
+
if (!shapeResult.success) {
|
|
27
|
+
throw new FlowError("INVALID_RESPONSE_PATH", `Resume path file '${resumePath}' includes an invalid session handle for provider '${session.provider}'.`);
|
|
28
|
+
}
|
|
29
|
+
return shapeResult.data;
|
|
30
|
+
}
|
|
31
|
+
export const claudeAgentSdkRegistration = {
|
|
32
|
+
name: CLAUDE_AGENT_SDK_PROVIDER,
|
|
33
|
+
start: startClaudeAgentSdk,
|
|
34
|
+
sessionSchema: claudeSessionSchema,
|
|
35
|
+
effortField: "effort",
|
|
36
|
+
instanceSchema: z
|
|
37
|
+
.object({
|
|
38
|
+
kind: z.literal(CLAUDE_AGENT_SDK_PROVIDER),
|
|
39
|
+
...providerCommonFields,
|
|
40
|
+
executable: executableSchema.optional(),
|
|
41
|
+
settingSources: z.array(claudeSettingSourceSchema).optional(),
|
|
42
|
+
env: providerEnvSchema,
|
|
43
|
+
})
|
|
44
|
+
.strict(),
|
|
45
|
+
builtinInstance: {
|
|
46
|
+
name: CLAUDE_AGENT_SDK_PROVIDER,
|
|
47
|
+
source: "builtin",
|
|
48
|
+
instance: {
|
|
49
|
+
kind: CLAUDE_AGENT_SDK_PROVIDER,
|
|
50
|
+
executable: "claude",
|
|
51
|
+
settingSources: ["project"],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
builtinAkumaProfiles: [
|
|
55
|
+
{ name: "akuma-claude", description: "Default Claude Agent SDK Akuma." },
|
|
56
|
+
],
|
|
57
|
+
portablePolicy: {
|
|
58
|
+
access: new Set(ACCESS_VALUES),
|
|
59
|
+
network: new Set(),
|
|
60
|
+
webSearch: new Set(["disabled"]),
|
|
61
|
+
},
|
|
62
|
+
maxCaptureChars: (config) => config.claude.execMaxCaptureChars,
|
|
63
|
+
buildCallTerms: ({ snapshot, baseTerms, body }) => {
|
|
64
|
+
const provider = snapshot.provider;
|
|
65
|
+
return {
|
|
66
|
+
...baseTerms,
|
|
67
|
+
provider: CLAUDE_AGENT_SDK_PROVIDER,
|
|
68
|
+
...(provider.model !== undefined ? { model: provider.model } : {}),
|
|
69
|
+
...(provider.effort !== undefined ? { effort: provider.effort } : {}),
|
|
70
|
+
...(provider.executable !== undefined ? { executable: provider.executable } : {}),
|
|
71
|
+
...(provider.settingSources !== undefined ? { settingSources: provider.settingSources } : {}),
|
|
72
|
+
permissionMode: provider.permissionMode,
|
|
73
|
+
...(provider.allowDangerouslySkipPermissions !== undefined
|
|
74
|
+
? { allowDangerouslySkipPermissions: provider.allowDangerouslySkipPermissions }
|
|
75
|
+
: {}),
|
|
76
|
+
...(provider.disallowedTools !== undefined ? { disallowedTools: provider.disallowedTools } : {}),
|
|
77
|
+
...(provider.env !== undefined ? { env: provider.env } : {}),
|
|
78
|
+
systemPrompt: body
|
|
79
|
+
? { type: "preset", preset: "claude_code", append: body }
|
|
80
|
+
: undefined,
|
|
81
|
+
onCheckpoint() { },
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
resolveLaunchProvider: ({ common, instance, model, effort, access, webSearch }) => {
|
|
85
|
+
if (instance.kind !== CLAUDE_AGENT_SDK_PROVIDER) {
|
|
86
|
+
throw new Error(`resolveLaunchProvider expected ${CLAUDE_AGENT_SDK_PROVIDER}`);
|
|
87
|
+
}
|
|
88
|
+
const claudeInstance = instance;
|
|
89
|
+
const permissionMode = access === "read"
|
|
90
|
+
? "plan"
|
|
91
|
+
: access === "write"
|
|
92
|
+
? "acceptEdits"
|
|
93
|
+
: access === "auto"
|
|
94
|
+
? "bypassPermissions"
|
|
95
|
+
: "default";
|
|
96
|
+
return Object.freeze({
|
|
97
|
+
...common,
|
|
98
|
+
kind: CLAUDE_AGENT_SDK_PROVIDER,
|
|
99
|
+
...(claudeInstance.executable !== undefined ? { executable: claudeInstance.executable } : {}),
|
|
100
|
+
...(model !== undefined ? { model } : {}),
|
|
101
|
+
...(effort !== undefined ? { effort } : {}),
|
|
102
|
+
...(claudeInstance.settingSources !== undefined ? { settingSources: claudeInstance.settingSources } : {}),
|
|
103
|
+
permissionMode,
|
|
104
|
+
...(permissionMode === "bypassPermissions" ? { allowDangerouslySkipPermissions: true } : {}),
|
|
105
|
+
...(webSearch === "disabled" ? { disallowedTools: ["WebSearch"] } : {}),
|
|
106
|
+
...(claudeInstance.env !== undefined ? { env: claudeInstance.env } : {}),
|
|
107
|
+
});
|
|
108
|
+
},
|
|
109
|
+
parseLaunchProvider: (provider, common) => {
|
|
110
|
+
exactKeys(provider, [
|
|
111
|
+
"name",
|
|
112
|
+
"source",
|
|
113
|
+
"kind",
|
|
114
|
+
"executable",
|
|
115
|
+
"model",
|
|
116
|
+
"effort",
|
|
117
|
+
"settingSources",
|
|
118
|
+
"permissionMode",
|
|
119
|
+
"allowDangerouslySkipPermissions",
|
|
120
|
+
"disallowedTools",
|
|
121
|
+
"env",
|
|
122
|
+
], "provider");
|
|
123
|
+
const modes = new Set(["default", "plan", "acceptEdits", "bypassPermissions"]);
|
|
124
|
+
const permissionMode = requiredEnum(provider, "permissionMode", "provider", modes);
|
|
125
|
+
if (permissionMode === "bypassPermissions") {
|
|
126
|
+
if (provider.allowDangerouslySkipPermissions !== true) {
|
|
127
|
+
throw snapshotError("provider.allowDangerouslySkipPermissions", "must be true for bypassPermissions");
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else if ("allowDangerouslySkipPermissions" in provider) {
|
|
131
|
+
throw snapshotError("provider.allowDangerouslySkipPermissions", "is only valid for bypassPermissions");
|
|
132
|
+
}
|
|
133
|
+
let settingSources;
|
|
134
|
+
if ("settingSources" in provider) {
|
|
135
|
+
if (!Array.isArray(provider.settingSources))
|
|
136
|
+
throw snapshotError("provider.settingSources", "must be an array");
|
|
137
|
+
settingSources = Object.freeze(provider.settingSources.map((source, index) => {
|
|
138
|
+
if (typeof source !== "string" || !CLAUDE_SETTING_SOURCES.has(source)) {
|
|
139
|
+
throw snapshotError(`provider.settingSources[${index}]`, "has an invalid setting source");
|
|
140
|
+
}
|
|
141
|
+
return source;
|
|
142
|
+
}));
|
|
143
|
+
}
|
|
144
|
+
let disallowedTools;
|
|
145
|
+
if ("disallowedTools" in provider) {
|
|
146
|
+
if (!Array.isArray(provider.disallowedTools) ||
|
|
147
|
+
provider.disallowedTools.length !== 1 ||
|
|
148
|
+
provider.disallowedTools[0] !== "WebSearch") {
|
|
149
|
+
throw snapshotError("provider.disallowedTools", "must equal ['WebSearch']");
|
|
150
|
+
}
|
|
151
|
+
disallowedTools = Object.freeze(["WebSearch"]);
|
|
152
|
+
}
|
|
153
|
+
const executable = optionalString(provider, "executable", "provider");
|
|
154
|
+
const model = optionalString(provider, "model", "provider");
|
|
155
|
+
const effort = optionalString(provider, "effort", "provider");
|
|
156
|
+
const env = optionalStringRecord(provider, "env");
|
|
157
|
+
return Object.freeze({
|
|
158
|
+
...common,
|
|
159
|
+
kind: CLAUDE_AGENT_SDK_PROVIDER,
|
|
160
|
+
...(executable !== undefined ? { executable } : {}),
|
|
161
|
+
...(model !== undefined ? { model } : {}),
|
|
162
|
+
...(effort !== undefined ? { effort } : {}),
|
|
163
|
+
...(settingSources !== undefined ? { settingSources } : {}),
|
|
164
|
+
permissionMode,
|
|
165
|
+
...(permissionMode === "bypassPermissions" ? { allowDangerouslySkipPermissions: true } : {}),
|
|
166
|
+
...(disallowedTools !== undefined ? { disallowedTools } : {}),
|
|
167
|
+
...(env !== undefined ? { env } : {}),
|
|
168
|
+
});
|
|
169
|
+
},
|
|
170
|
+
applyEffort: (provider, effort) => Object.freeze({ ...provider, effort }),
|
|
171
|
+
providerEffortAndModel: (provider) => {
|
|
172
|
+
const resolved = provider;
|
|
173
|
+
return { model: resolved.model, effort: resolved.effort };
|
|
174
|
+
},
|
|
175
|
+
attachLoader: (terms, ports) => {
|
|
176
|
+
if (terms.provider !== CLAUDE_AGENT_SDK_PROVIDER)
|
|
177
|
+
return terms;
|
|
178
|
+
const loader = ports.claudeAgentSdk;
|
|
179
|
+
return loader ? { ...terms, loader } : terms;
|
|
180
|
+
},
|
|
181
|
+
nativePolicyOwnership: () => null,
|
|
182
|
+
startLive: async ({ terms, signal, reviveTerms, onSyncCheckpoint, onIngress }) => {
|
|
183
|
+
if (terms.provider !== CLAUDE_AGENT_SDK_PROVIDER) {
|
|
184
|
+
throw new Error(`startLive expected ${CLAUDE_AGENT_SDK_PROVIDER}`);
|
|
185
|
+
}
|
|
186
|
+
const claudeTerms = terms;
|
|
187
|
+
const claudeOptions = {
|
|
188
|
+
model: claudeTerms.model,
|
|
189
|
+
executable: claudeTerms.executable,
|
|
190
|
+
effort: claudeTerms.effort,
|
|
191
|
+
env: claudeTerms.env,
|
|
192
|
+
signal,
|
|
193
|
+
permissionMode: claudeTerms.permissionMode,
|
|
194
|
+
settingSources: claudeTerms.settingSources,
|
|
195
|
+
allowDangerouslySkipPermissions: claudeTerms.allowDangerouslySkipPermissions,
|
|
196
|
+
disallowedTools: claudeTerms.disallowedTools,
|
|
197
|
+
systemPrompt: claudeTerms.systemPrompt,
|
|
198
|
+
onSyncCheckpoint,
|
|
199
|
+
onEvidence: claudeTerms.onEvidence,
|
|
200
|
+
onIngress,
|
|
201
|
+
initialTurn: claudeTerms.initialTurn,
|
|
202
|
+
loader: claudeTerms.loader,
|
|
203
|
+
};
|
|
204
|
+
const { startClaudeAgentSdk: start } = await import("./adapter.js");
|
|
205
|
+
if (reviveTerms) {
|
|
206
|
+
const session = admitResumeShape(claudeSessionSchema, reviveTerms.session, reviveTerms.resumePath);
|
|
207
|
+
return start(claudeTerms.prompt, claudeTerms.workdir, {
|
|
208
|
+
...claudeOptions,
|
|
209
|
+
sessionId: session.sessionId,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return start(claudeTerms.prompt, claudeTerms.workdir, claudeOptions);
|
|
213
|
+
},
|
|
214
|
+
};
|
|
@@ -1,52 +1,22 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
1
|
import { appendDebugLog } from "../../../telemetry/debug-log.js";
|
|
3
2
|
import { SUBAGENT_SESSION_VERSION } from "../../session.js";
|
|
4
3
|
import { createProjectionDriver } from "../../harness/execution-handle.js";
|
|
5
|
-
import {
|
|
4
|
+
import { createProviderFailure } from "../../harness/provider-adapter.js";
|
|
5
|
+
import { awaitProviderAbortSettlement, buildSubagentEnv, createAbortError, emitProviderEvidence, coerceString, } from "../../harness/runtime.js";
|
|
6
|
+
import { CODEX_APP_SERVER_PROVIDER } from "./identity.js";
|
|
6
7
|
import { CodexAppServerProcess } from "./session.js";
|
|
7
8
|
import { createCodexAppServerTurnMonitor, createCodexAppServerTurnState, recordTurnStartResponse, } from "./events.js";
|
|
9
|
+
export { CODEX_APP_SERVER_PROVIDER } from "./identity.js";
|
|
8
10
|
/** Identity-only opacity boundary for codex-app-server turn/start effort. */
|
|
9
11
|
function toCodexAppServerEffort(effort) {
|
|
10
12
|
return effort;
|
|
11
13
|
}
|
|
12
|
-
|
|
13
|
-
export const codexAppServerSessionSchema = z.object({
|
|
14
|
-
threadId: z.string().trim().min(1),
|
|
15
|
-
codexHome: z.string().trim().min(1).optional(),
|
|
16
|
-
});
|
|
17
|
-
const CODEX_APP_SERVER_PROVIDER = "codex-app-server";
|
|
14
|
+
export { codexAppServerSessionSchema } from "./session-schema.js";
|
|
18
15
|
const MINIMUM_CODEX_APP_SERVER_VERSION = { major: 0, minor: 143, patch: 0 };
|
|
19
16
|
/** Non-interactive defaults for turn/start (faye #316 policy A). */
|
|
20
17
|
export const CODEX_APP_SERVER_TURN_APPROVAL_POLICY = "never";
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
type: "workspaceWrite",
|
|
24
|
-
writableRoots: [...input.writableRoots],
|
|
25
|
-
networkAccess: input.networkAccess,
|
|
26
|
-
excludeTmpdirEnvVar: false,
|
|
27
|
-
excludeSlashTmp: false,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
/** True when config.* already owns approval policy — omit turn-level approvalPolicy default. */
|
|
31
|
-
export function configOwnsApprovalPolicy(config) {
|
|
32
|
-
if (!config)
|
|
33
|
-
return false;
|
|
34
|
-
return Object.prototype.hasOwnProperty.call(config, "approval_policy");
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* True when config.* already owns sandbox settings — omit turn-level sandboxPolicy default.
|
|
38
|
-
* Matches `sandbox_mode` or any `sandbox_workspace_write` / `sandbox_workspace_write.*` key.
|
|
39
|
-
*/
|
|
40
|
-
export function configOwnsSandboxPolicy(config) {
|
|
41
|
-
if (!config)
|
|
42
|
-
return false;
|
|
43
|
-
for (const key of Object.keys(config)) {
|
|
44
|
-
if (key === "sandbox_mode" || key === "sandbox_workspace_write" || key.startsWith("sandbox_workspace_write.")) {
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
18
|
+
export { buildCodexAppServerWorkspaceWriteSandboxPolicy, configOwnsApprovalPolicy, configOwnsSandboxPolicy, } from "./policy.js";
|
|
19
|
+
import { buildCodexAppServerWorkspaceWriteSandboxPolicy, configOwnsApprovalPolicy, configOwnsSandboxPolicy, } from "./policy.js";
|
|
50
20
|
function parseSemver(version) {
|
|
51
21
|
const match = version.trim().match(/(\d+)\.(\d+)\.(\d+)/);
|
|
52
22
|
if (!match)
|
|
@@ -83,6 +53,14 @@ function extractVersionFromInitialize(result) {
|
|
|
83
53
|
}
|
|
84
54
|
return coerceString(record.version) ?? coerceString(record.cliVersion);
|
|
85
55
|
}
|
|
56
|
+
export async function settleCodexGracefulInterrupt(input) {
|
|
57
|
+
await input.requestInterrupt();
|
|
58
|
+
const terminal = await input.completion;
|
|
59
|
+
const terminalTurnId = coerceString(terminal.turn.id);
|
|
60
|
+
if (terminalTurnId !== input.turnId || terminal.status !== "interrupted") {
|
|
61
|
+
throw new Error(`${CODEX_APP_SERVER_PROVIDER} graceful abort expected interrupted turn '${input.turnId}', got '${terminalTurnId ?? "unknown"}' status '${terminal.status}'`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
86
64
|
/** Gate-facing production entry: the harness owns clocks, capture, classification, and outcome construction. */
|
|
87
65
|
export async function startCodexAppServer(prompt, cwd, options = {}) {
|
|
88
66
|
const executable = options.executable?.trim() || "codex";
|
|
@@ -91,6 +69,7 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
|
|
|
91
69
|
const turnState = createCodexAppServerTurnState();
|
|
92
70
|
let activeThreadId;
|
|
93
71
|
let interruptRequested = false;
|
|
72
|
+
let activeTurnCompletion;
|
|
94
73
|
let builderDiagnostic;
|
|
95
74
|
let emitTurnStarted;
|
|
96
75
|
const pendingTells = [];
|
|
@@ -204,19 +183,29 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
|
|
|
204
183
|
await server?.close("force");
|
|
205
184
|
return;
|
|
206
185
|
}
|
|
207
|
-
if (server
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
catch {
|
|
216
|
-
// idle interrupt may error; still rely on process teardown
|
|
186
|
+
if (!server)
|
|
187
|
+
return;
|
|
188
|
+
if (activeThreadId && turnState.activeTurnId) {
|
|
189
|
+
const turnId = turnState.activeTurnId;
|
|
190
|
+
const completion = activeTurnCompletion;
|
|
191
|
+
if (!completion) {
|
|
192
|
+
throw new Error(`${CODEX_APP_SERVER_PROVIDER} graceful abort lacked an active turn monitor`);
|
|
217
193
|
}
|
|
194
|
+
await awaitProviderAbortSettlement(CODEX_APP_SERVER_PROVIDER, (async () => {
|
|
195
|
+
// RPC acknowledgement is submission evidence only. Keep the monitor
|
|
196
|
+
// and server alive until the matching terminal notification arrives.
|
|
197
|
+
await settleCodexGracefulInterrupt({
|
|
198
|
+
turnId,
|
|
199
|
+
requestInterrupt: () => server.request("turn/interrupt", {
|
|
200
|
+
threadId: activeThreadId,
|
|
201
|
+
turnId,
|
|
202
|
+
}),
|
|
203
|
+
completion,
|
|
204
|
+
});
|
|
205
|
+
})());
|
|
206
|
+
return;
|
|
218
207
|
}
|
|
219
|
-
await server
|
|
208
|
+
await awaitProviderAbortSettlement(CODEX_APP_SERVER_PROVIDER, server.close("force"), "startup abort could not force-close owned server");
|
|
220
209
|
},
|
|
221
210
|
async run(builder) {
|
|
222
211
|
builderDiagnostic = (text) => builder.emit({ type: "diagnostic", text });
|
|
@@ -239,6 +228,7 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
|
|
|
239
228
|
isDrainingTells: () => drainingTells,
|
|
240
229
|
setFinishAfterTellDrain: (finish) => { finishAfterTellDrain = finish; },
|
|
241
230
|
});
|
|
231
|
+
activeTurnCompletion = turnCompleted;
|
|
242
232
|
try {
|
|
243
233
|
const initResult = await server.request("initialize", {
|
|
244
234
|
clientInfo: {
|
|
@@ -255,7 +245,7 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
|
|
|
255
245
|
if (isCodexAppServerVersionBelowMinimum(version)) {
|
|
256
246
|
const message = `${CODEX_APP_SERVER_PROVIDER} refused: initialize version '${version}' is below minimum supported version 0.143.0`;
|
|
257
247
|
builder.emit({ type: "fail", message });
|
|
258
|
-
throw
|
|
248
|
+
throw createProviderFailure(message);
|
|
259
249
|
}
|
|
260
250
|
const initRecord = (initResult && typeof initResult === "object" ? initResult : {});
|
|
261
251
|
const serverCodexHome = coerceString(initRecord.codexHome) ?? options.codexHome;
|
|
@@ -280,7 +270,7 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
|
|
|
280
270
|
if (!activeThreadId) {
|
|
281
271
|
const message = `${CODEX_APP_SERVER_PROVIDER} exec could not determine thread id`;
|
|
282
272
|
builder.emit({ type: "fail", message });
|
|
283
|
-
throw
|
|
273
|
+
throw createProviderFailure(message);
|
|
284
274
|
}
|
|
285
275
|
if (options.onEvidence)
|
|
286
276
|
emitProviderEvidence(options.onEvidence, { type: "session", provider: CODEX_APP_SERVER_PROVIDER, threadId: activeThreadId }, builderDiagnostic);
|
|
@@ -303,6 +293,8 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
|
|
|
303
293
|
turnState.activeTurnId = undefined;
|
|
304
294
|
turnState.activeTurnSource = undefined;
|
|
305
295
|
turnState.activeTurnAcceptingSteer = false;
|
|
296
|
+
turnState.failureCause = undefined;
|
|
297
|
+
turnState.turnInFlight = true;
|
|
306
298
|
const turnStart = await server.request("turn/start", turnStartParams);
|
|
307
299
|
const turn = turnStart && typeof turnStart === "object"
|
|
308
300
|
? (turnStart.turn ?? undefined)
|
|
@@ -311,18 +303,20 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
|
|
|
311
303
|
if (options.onEvidence)
|
|
312
304
|
emitProviderEvidence(options.onEvidence, { type: "checkpoint", provider: CODEX_APP_SERVER_PROVIDER, fence: { kind: "turn", turnId }, source: "response" }, builderDiagnostic);
|
|
313
305
|
const completed = await turnCompleted;
|
|
306
|
+
turnState.turnInFlight = false;
|
|
314
307
|
if (completed.status === "interrupted" || interruptRequested) {
|
|
315
308
|
throw createAbortError(`${CODEX_APP_SERVER_PROVIDER} turn interrupted`);
|
|
316
309
|
}
|
|
317
310
|
if (completed.status === "failed") {
|
|
318
311
|
const message = `${CODEX_APP_SERVER_PROVIDER} turn failed`;
|
|
319
|
-
|
|
320
|
-
|
|
312
|
+
throw createProviderFailure(message, {
|
|
313
|
+
...(turnState.failureCause ? { publicCause: turnState.failureCause } : {}),
|
|
314
|
+
});
|
|
321
315
|
}
|
|
322
316
|
if (completed.status !== "completed") {
|
|
323
317
|
const message = `${CODEX_APP_SERVER_PROVIDER} turn ended with status '${completed.status}'`;
|
|
324
318
|
builder.emit({ type: "fail", message });
|
|
325
|
-
throw
|
|
319
|
+
throw createProviderFailure(message);
|
|
326
320
|
}
|
|
327
321
|
// Successful turn/completed is consumption evidence; interrupt ack alone is not terminal proof.
|
|
328
322
|
const session = {
|
|
@@ -338,6 +332,7 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
|
|
|
338
332
|
return { finalMessage, session };
|
|
339
333
|
}
|
|
340
334
|
finally {
|
|
335
|
+
activeTurnCompletion = undefined;
|
|
341
336
|
rejectPendingTells(new Error(`${CODEX_APP_SERVER_PROVIDER} execution ended before queued tell acceptance`));
|
|
342
337
|
await server?.close();
|
|
343
338
|
server = undefined;
|
|
@@ -345,3 +340,5 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
|
|
|
345
340
|
},
|
|
346
341
|
});
|
|
347
342
|
}
|
|
343
|
+
// Compiler-level binding to the named ProviderAdapter function contract.
|
|
344
|
+
startCodexAppServer;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { boundActivityExcerpt, diffstatFromUnifiedPatch } from "../../harness/activity-values.js";
|
|
2
2
|
import { AGENT_PLAN_ITEM_TEXT_MAX_CHARS, AGENT_PLAN_MAX_ITEMS, AGENT_THOUGHT_TEXT_MAX_CHARS, } from "../../harness/events.js";
|
|
3
|
+
import { createProviderFailure } from "../../harness/provider-adapter.js";
|
|
3
4
|
import { createAbortError, emitProviderEvidence, coerceString } from "../../harness/runtime.js";
|
|
4
|
-
|
|
5
|
+
import { CODEX_APP_SERVER_PROVIDER } from "./identity.js";
|
|
5
6
|
const CODEX_APP_SERVER_NOTIFICATION_ACKNOWLEDGED = new Set([
|
|
6
7
|
"item/agentMessage/delta",
|
|
7
8
|
"item/commandExecution/outputDelta",
|
|
@@ -16,11 +17,13 @@ const CODEX_APP_SERVER_NOTIFICATION_MAPPED = new Set([
|
|
|
16
17
|
"turn/completed",
|
|
17
18
|
"error",
|
|
18
19
|
]);
|
|
19
|
-
export function codexAppServerNotificationDisposition(method) {
|
|
20
|
+
export function codexAppServerNotificationDisposition(method, params) {
|
|
20
21
|
if (CODEX_APP_SERVER_NOTIFICATION_ACKNOWLEDGED.has(method))
|
|
21
22
|
return "acknowledged-unpersisted";
|
|
22
23
|
if (CODEX_APP_SERVER_NOTIFICATION_MAPPED.has(method))
|
|
23
24
|
return "mapped";
|
|
25
|
+
if (method === "account/rateLimits/updated" && codexAppServerRateLimitCause(params))
|
|
26
|
+
return "mapped";
|
|
24
27
|
return "unknown";
|
|
25
28
|
}
|
|
26
29
|
export function appServerRecord(value) {
|
|
@@ -37,6 +40,41 @@ const CODEX_APP_SERVER_ACTIVITY_ITEM_TYPES = [
|
|
|
37
40
|
function isCodexAppServerActivityItemType(value) {
|
|
38
41
|
return CODEX_APP_SERVER_ACTIVITY_ITEM_TYPES.includes(value);
|
|
39
42
|
}
|
|
43
|
+
/** Map a native or legacy fileChange kind fact into the public op. */
|
|
44
|
+
function appServerFileChangeOp(kind) {
|
|
45
|
+
if (kind === "add" || kind === "update" || kind === "delete")
|
|
46
|
+
return kind;
|
|
47
|
+
const record = appServerRecord(kind);
|
|
48
|
+
if (!record)
|
|
49
|
+
return undefined;
|
|
50
|
+
if (record.type === "add" || record.type === "update" || record.type === "delete")
|
|
51
|
+
return record.type;
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
/** Trustworthy provider patch text only: per-change native `diff`, else legacy `details.patch`. */
|
|
55
|
+
function appServerFileChangeDiffstat(item) {
|
|
56
|
+
let additions = 0;
|
|
57
|
+
let deletions = 0;
|
|
58
|
+
let saw = false;
|
|
59
|
+
if (Array.isArray(item.changes)) {
|
|
60
|
+
for (const entry of item.changes) {
|
|
61
|
+
const change = appServerRecord(entry);
|
|
62
|
+
if (!change || typeof change.diff !== "string" || !change.diff)
|
|
63
|
+
continue;
|
|
64
|
+
const partial = diffstatFromUnifiedPatch(change.diff);
|
|
65
|
+
if (!partial)
|
|
66
|
+
continue;
|
|
67
|
+
saw = true;
|
|
68
|
+
additions += partial.additions;
|
|
69
|
+
deletions += partial.deletions;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (saw)
|
|
73
|
+
return additions || deletions ? { additions, deletions } : undefined;
|
|
74
|
+
const details = appServerRecord(item.details);
|
|
75
|
+
const patch = typeof details?.patch === "string" ? details.patch : undefined;
|
|
76
|
+
return patch ? diffstatFromUnifiedPatch(patch) : undefined;
|
|
77
|
+
}
|
|
40
78
|
export function appServerActivityCall(itemType, item) {
|
|
41
79
|
switch (itemType) {
|
|
42
80
|
case "commandExecution":
|
|
@@ -53,9 +91,9 @@ export function appServerActivityCall(itemType, item) {
|
|
|
53
91
|
const change = appServerRecord(entry);
|
|
54
92
|
if (!change || typeof change.path !== "string")
|
|
55
93
|
return [];
|
|
56
|
-
|
|
94
|
+
const op = appServerFileChangeOp(change.kind);
|
|
95
|
+
if (!op)
|
|
57
96
|
return [];
|
|
58
|
-
const op = change.kind;
|
|
59
97
|
return [{ op, path: change.path }];
|
|
60
98
|
})
|
|
61
99
|
: [];
|
|
@@ -80,11 +118,7 @@ export function appServerActivityResult(item) {
|
|
|
80
118
|
: typeof item.error === "string" && item.error
|
|
81
119
|
? boundActivityExcerpt(item.error)
|
|
82
120
|
: undefined;
|
|
83
|
-
const
|
|
84
|
-
? item.details
|
|
85
|
-
: undefined;
|
|
86
|
-
const patch = typeof details?.patch === "string" ? details.patch : undefined;
|
|
87
|
-
const diffstat = patch ? diffstatFromUnifiedPatch(patch) : undefined;
|
|
121
|
+
const diffstat = appServerFileChangeDiffstat(item);
|
|
88
122
|
return {
|
|
89
123
|
status: item.status === "failed" || (exitCode !== undefined && exitCode !== 0) ? "error" : "ok",
|
|
90
124
|
...(message ? { message } : {}),
|
|
@@ -131,9 +165,23 @@ export function createCodexAppServerTurnState() {
|
|
|
131
165
|
responseSeenTurnIds: new Set(),
|
|
132
166
|
completedBeforeResponseTurnIds: new Set(),
|
|
133
167
|
activeTurnAcceptingSteer: false,
|
|
168
|
+
turnInFlight: false,
|
|
134
169
|
lastAgentMessage: "",
|
|
135
170
|
};
|
|
136
171
|
}
|
|
172
|
+
/** Admit only positive native exhaustion evidence; no provider strings survive. */
|
|
173
|
+
export function codexAppServerRateLimitCause(params) {
|
|
174
|
+
const rateLimits = appServerRecord(appServerRecord(params)?.rateLimits);
|
|
175
|
+
if (!rateLimits)
|
|
176
|
+
return undefined;
|
|
177
|
+
for (const value of Object.values(rateLimits)) {
|
|
178
|
+
const window = appServerRecord(value);
|
|
179
|
+
if (typeof window?.usedPercent === "number" && window.usedPercent >= 100) {
|
|
180
|
+
return { kind: "rate_limit_exhausted" };
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
137
185
|
export function recordActiveTurnId(state, candidate, source) {
|
|
138
186
|
const turnId = coerceString(candidate);
|
|
139
187
|
if (!turnId)
|
|
@@ -178,7 +226,7 @@ export function createCodexAppServerTurnMonitor(options) {
|
|
|
178
226
|
const failServerRequest = (request) => {
|
|
179
227
|
// Policy A forbids interactive server→client requests. Fail immediately with named diagnostic.
|
|
180
228
|
const message = `${CODEX_APP_SERVER_PROVIDER} unexpected server request '${request.method}' (id=${String(request.id)}); non-interactive policy forbids server→client requests`;
|
|
181
|
-
failTurn(
|
|
229
|
+
failTurn(createProviderFailure(message));
|
|
182
230
|
};
|
|
183
231
|
const requestDeliveryOpportunity = () => {
|
|
184
232
|
try {
|
|
@@ -200,7 +248,7 @@ export function createCodexAppServerTurnMonitor(options) {
|
|
|
200
248
|
});
|
|
201
249
|
unsubNotifications = server.onNotification((notification) => {
|
|
202
250
|
try {
|
|
203
|
-
builder.ingress(CODEX_APP_SERVER_PROVIDER, notification.method, notification, codexAppServerNotificationDisposition(notification.method), () => {
|
|
251
|
+
builder.ingress(CODEX_APP_SERVER_PROVIDER, notification.method, notification, codexAppServerNotificationDisposition(notification.method, notification.params), () => {
|
|
204
252
|
if (notification.method === "item/agentMessage/delta") {
|
|
205
253
|
const delta = coerceString(notification.params?.delta);
|
|
206
254
|
if (delta) {
|
|
@@ -274,6 +322,14 @@ export function createCodexAppServerTurnMonitor(options) {
|
|
|
274
322
|
onSyncCheckpoint?.({ enqueue }, checkpoint);
|
|
275
323
|
void drainPendingTells();
|
|
276
324
|
}
|
|
325
|
+
if (notification.method === "account/rateLimits/updated") {
|
|
326
|
+
const cause = codexAppServerRateLimitCause(notification.params);
|
|
327
|
+
if (cause) {
|
|
328
|
+
builder.emit({ type: "warning", warning: { reason: "rate-limit", state: "exhausted" } });
|
|
329
|
+
if (state.turnInFlight)
|
|
330
|
+
state.failureCause ??= cause;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
277
333
|
if (notification.method === "turn/completed") {
|
|
278
334
|
const turn = notification.params?.turn ?? {};
|
|
279
335
|
const status = coerceString(turn.status) ?? "unknown";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CODEX_APP_SERVER_PROVIDER = "codex-app-server";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function buildCodexAppServerWorkspaceWriteSandboxPolicy(input) {
|
|
2
|
+
return {
|
|
3
|
+
type: "workspaceWrite",
|
|
4
|
+
writableRoots: [...input.writableRoots],
|
|
5
|
+
networkAccess: input.networkAccess,
|
|
6
|
+
excludeTmpdirEnvVar: false,
|
|
7
|
+
excludeSlashTmp: false,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/** True when config.* already owns approval policy — omit turn-level approvalPolicy default. */
|
|
11
|
+
export function configOwnsApprovalPolicy(config) {
|
|
12
|
+
if (!config)
|
|
13
|
+
return false;
|
|
14
|
+
return Object.prototype.hasOwnProperty.call(config, "approval_policy");
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* True when config.* already owns sandbox settings — omit turn-level sandboxPolicy default.
|
|
18
|
+
* Matches `sandbox_mode` or any `sandbox_workspace_write` / `sandbox_workspace_write.*` key.
|
|
19
|
+
*/
|
|
20
|
+
export function configOwnsSandboxPolicy(config) {
|
|
21
|
+
if (!config)
|
|
22
|
+
return false;
|
|
23
|
+
for (const key of Object.keys(config)) {
|
|
24
|
+
if (key === "sandbox_mode" || key === "sandbox_workspace_write" || key.startsWith("sandbox_workspace_write.")) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|