@wrenai/genbi 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -3
- package/dist/assets/{echarts-LTFC-ysd.js → echarts-DYM4hjvk.js} +2 -2
- package/dist/assets/index-A_Wrq7Ey.css +1 -0
- package/dist/assets/{index-Bo--QMUN.js → index-DsH129tV.js} +18 -17
- package/dist/index.html +2 -2
- package/dist-server/harness/bundle/schema.d.ts +38 -0
- package/dist-server/harness/bundle/schema.js +18 -10
- package/dist-server/harness/bundle/version.js +1 -1
- package/dist-server/harness/cli-args.d.ts +10 -2
- package/dist-server/harness/cli-args.js +24 -8
- package/dist-server/harness/cli.js +75 -9
- package/dist-server/harness/compile/cache.js +4 -4
- package/dist-server/harness/compile/compose-profile.d.ts +51 -14
- package/dist-server/harness/compile/compose-profile.js +85 -19
- package/dist-server/harness/compile/context-loader.d.ts +56 -0
- package/dist-server/harness/compile/context-loader.js +237 -0
- package/dist-server/harness/compile/errors.d.ts +19 -0
- package/dist-server/harness/compile/errors.js +35 -0
- package/dist-server/harness/compile/index.d.ts +4 -3
- package/dist-server/harness/compile/index.js +4 -3
- package/dist-server/harness/compile/pipeline.d.ts +15 -7
- package/dist-server/harness/compile/pipeline.js +62 -14
- package/dist-server/harness/compile/resolve-binary.d.ts +2 -2
- package/dist-server/harness/compile/resolve-binary.js +3 -3
- package/dist-server/harness/compile/types.d.ts +29 -0
- package/dist-server/harness/compile/warble-identity.d.ts +11 -0
- package/dist-server/harness/compile/warble-identity.js +13 -0
- package/dist-server/harness/components/ai-step.d.ts +4 -0
- package/dist-server/harness/components/ai-step.js +40 -0
- package/dist-server/harness/components/broker.d.ts +60 -0
- package/dist-server/harness/components/broker.js +117 -0
- package/dist-server/harness/components/capability-card.d.ts +98 -0
- package/dist-server/harness/components/capability-card.js +169 -0
- package/dist-server/harness/components/context.d.ts +2 -0
- package/dist-server/harness/components/context.js +30 -0
- package/dist-server/harness/components/display.d.ts +6 -0
- package/dist-server/harness/components/display.js +29 -0
- package/dist-server/harness/components/egress-judge.d.ts +12 -0
- package/dist-server/harness/components/egress-judge.js +27 -0
- package/dist-server/harness/components/egress.d.ts +142 -0
- package/dist-server/harness/components/egress.js +469 -0
- package/dist-server/harness/components/in-process.d.ts +7 -0
- package/dist-server/harness/components/in-process.js +245 -0
- package/dist-server/harness/components/normalize.d.ts +35 -0
- package/dist-server/harness/components/normalize.js +245 -0
- package/dist-server/harness/components/plan.d.ts +31 -0
- package/dist-server/harness/components/plan.js +184 -0
- package/dist-server/harness/components/report.d.ts +207 -0
- package/dist-server/harness/components/report.js +309 -0
- package/dist-server/harness/components/runner.d.ts +193 -0
- package/dist-server/harness/components/runner.js +492 -0
- package/dist-server/harness/components/semantic-guards.d.ts +20 -0
- package/dist-server/harness/components/semantic-guards.js +42 -0
- package/dist-server/harness/components/terminal-json.d.ts +18 -0
- package/dist-server/harness/components/terminal-json.js +82 -0
- package/dist-server/harness/components/usage.d.ts +14 -0
- package/dist-server/harness/components/usage.js +19 -0
- package/dist-server/harness/components/wren-access.d.ts +29 -0
- package/dist-server/harness/components/wren-access.js +233 -0
- package/dist-server/harness/components/zone-dry-run.d.ts +43 -0
- package/dist-server/harness/components/zone-dry-run.js +107 -0
- package/dist-server/harness/components/zone-gate.d.ts +76 -0
- package/dist-server/harness/components/zone-gate.js +144 -0
- package/dist-server/harness/events/index.d.ts +1 -1
- package/dist-server/harness/events/types.d.ts +52 -0
- package/dist-server/harness/index.d.ts +9 -2
- package/dist-server/harness/index.js +5 -1
- package/dist-server/harness/loop/executor.d.ts +1 -0
- package/dist-server/harness/loop/executor.js +37 -15
- package/dist-server/harness/npm-package-resolve.d.ts +2 -0
- package/dist-server/harness/npm-package-resolve.js +16 -4
- package/dist-server/harness/providers/adapters/openai-compatible.d.ts +13 -0
- package/dist-server/harness/providers/adapters/openai-compatible.js +17 -0
- package/dist-server/harness/providers/adapters/openai.d.ts +7 -0
- package/dist-server/harness/providers/adapters/openai.js +6 -0
- package/dist-server/harness/providers/adapters/pi-ai.d.ts +48 -0
- package/dist-server/harness/providers/adapters/pi-ai.js +518 -0
- package/dist-server/harness/providers/binding.d.ts +45 -4
- package/dist-server/harness/providers/binding.js +44 -8
- package/dist-server/harness/providers/index.d.ts +9 -3
- package/dist-server/harness/providers/index.js +10 -3
- package/dist-server/harness/providers/zone.d.ts +96 -0
- package/dist-server/harness/providers/zone.js +112 -0
- package/dist-server/harness/render/answering-query.d.ts +29 -0
- package/dist-server/harness/render/answering-query.js +62 -0
- package/dist-server/harness/render/envelope.d.ts +6 -0
- package/dist-server/harness/render/envelope.js +10 -3
- package/dist-server/harness/route/adapter-spec.d.ts +8 -9
- package/dist-server/harness/route/adapter-spec.js +13 -14
- package/dist-server/harness/route/codex-ask-events.js +2 -1
- package/dist-server/harness/route/codex-ask.d.ts +4 -0
- package/dist-server/harness/route/codex-ask.js +43 -45
- package/dist-server/harness/route/codex-local-manifest.d.ts +9 -1
- package/dist-server/harness/route/codex-local-manifest.js +96 -15
- package/dist-server/harness/route/describe.js +45 -6
- package/dist-server/harness/route/dispatched.d.ts +20 -0
- package/dist-server/harness/route/dispatched.js +122 -24
- package/dist-server/harness/route/host-query.d.ts +93 -0
- package/dist-server/harness/route/host-query.js +257 -0
- package/dist-server/harness/route/in-process.d.ts +22 -1
- package/dist-server/harness/route/in-process.js +54 -4
- package/dist-server/harness/route/route.js +8 -2
- package/dist-server/harness/route/types.d.ts +47 -1
- package/dist-server/harness/route/wren-host-proxy.d.ts +33 -0
- package/dist-server/harness/route/wren-host-proxy.js +228 -0
- package/dist-server/harness/session/run.js +30 -10
- package/dist-server/harness/setup/runner.d.ts +17 -3
- package/dist-server/harness/setup/runner.js +272 -89
- package/dist-server/harness/setup/yaml-scalar.d.ts +23 -0
- package/dist-server/harness/setup/yaml-scalar.js +62 -0
- package/dist-server/harness/tools/setup-native.d.ts +7 -0
- package/dist-server/harness/tools/setup-native.js +7 -4
- package/dist-server/server/adopt.js +1 -17
- package/dist-server/server/app.d.ts +1 -0
- package/dist-server/server/app.js +175 -17
- package/dist-server/server/auth-choice.d.ts +13 -1
- package/dist-server/server/auth-choice.js +66 -1
- package/dist-server/server/bin.js +185 -25
- package/dist-server/server/codex-native-session.d.ts +25 -0
- package/dist-server/server/codex-native-session.js +1 -0
- package/dist-server/server/codex-runtime-composition.d.ts +34 -0
- package/dist-server/server/codex-runtime-composition.js +250 -0
- package/dist-server/server/codex-structured-ask.d.ts +23 -0
- package/dist-server/server/codex-structured-ask.js +102 -0
- package/dist-server/server/conn-config.js +4 -16
- package/dist-server/server/conversation-socket.d.ts +16 -0
- package/dist-server/server/conversation-socket.js +65 -0
- package/dist-server/server/db.d.ts +46 -0
- package/dist-server/server/db.js +88 -9
- package/dist-server/server/env-detect.d.ts +6 -0
- package/dist-server/server/env-detect.js +7 -0
- package/dist-server/server/fold.d.ts +23 -4
- package/dist-server/server/fold.js +42 -5
- package/dist-server/server/harness.d.ts +2 -2
- package/dist-server/server/harness.js +33 -7
- package/dist-server/server/host-evidence-grounding.d.ts +21 -0
- package/dist-server/server/host-evidence-grounding.js +93 -0
- package/dist-server/server/interactive-terminal.d.ts +10 -6
- package/dist-server/server/interactive-terminal.js +33 -8
- package/dist-server/server/managed-wren-runtime.d.ts +116 -0
- package/dist-server/server/managed-wren-runtime.js +670 -0
- package/dist-server/server/native-artifacts.d.ts +112 -7
- package/dist-server/server/native-artifacts.js +194 -14
- package/dist-server/server/native-component-context.d.ts +19 -0
- package/dist-server/server/native-component-context.js +76 -0
- package/dist-server/server/native-component-preparation.d.ts +20 -0
- package/dist-server/server/native-component-preparation.js +129 -0
- package/dist-server/server/native-component-runtime.d.ts +36 -0
- package/dist-server/server/native-component-runtime.js +92 -0
- package/dist-server/server/native-components.d.ts +84 -0
- package/dist-server/server/native-components.js +160 -0
- package/dist-server/server/native-dispatch-process.d.ts +8 -0
- package/dist-server/server/native-dispatch-process.js +65 -0
- package/dist-server/server/native-runtime-spec.d.ts +89 -0
- package/dist-server/server/native-runtime-spec.js +169 -0
- package/dist-server/server/native-sessions.d.ts +172 -19
- package/dist-server/server/native-sessions.js +839 -244
- package/dist-server/server/native-shutdown.d.ts +6 -0
- package/dist-server/server/native-shutdown.js +28 -0
- package/dist-server/server/native-wren-home.d.ts +18 -0
- package/dist-server/server/native-wren-home.js +262 -0
- package/dist-server/server/node-pty-host.d.ts +2 -1
- package/dist-server/server/node-pty-host.js +3 -2
- package/dist-server/server/profile-registry.d.ts +139 -0
- package/dist-server/server/profile-registry.js +620 -0
- package/dist-server/server/runtime-binding.d.ts +4 -1
- package/dist-server/server/runtime-binding.js +50 -2
- package/dist-server/server/runtime-host/claude-component-step.d.ts +25 -0
- package/dist-server/server/runtime-host/claude-component-step.js +186 -0
- package/dist-server/server/runtime-host/codex-app-server.d.ts +75 -0
- package/dist-server/server/runtime-host/codex-app-server.js +239 -0
- package/dist-server/server/runtime-host/codex-compatibility.d.ts +110 -0
- package/dist-server/server/runtime-host/codex-compatibility.js +162 -0
- package/dist-server/server/runtime-host/codex-component-step.d.ts +19 -0
- package/dist-server/server/runtime-host/codex-component-step.js +308 -0
- package/dist-server/server/runtime-host/codex-conversation.d.ts +109 -0
- package/dist-server/server/runtime-host/codex-conversation.js +295 -0
- package/dist-server/server/runtime-host/codex-direct-tools.d.ts +23 -0
- package/dist-server/server/runtime-host/codex-direct-tools.js +59 -0
- package/dist-server/server/runtime-host/codex-events.d.ts +647 -0
- package/dist-server/server/runtime-host/codex-events.js +66 -0
- package/dist-server/server/runtime-host/codex-policy.d.ts +16 -0
- package/dist-server/server/runtime-host/codex-policy.js +151 -0
- package/dist-server/server/runtime-host/codex-process.d.ts +8 -0
- package/dist-server/server/runtime-host/codex-process.js +96 -0
- package/dist-server/server/runtime-host/codex-rpc.d.ts +47 -0
- package/dist-server/server/runtime-host/codex-rpc.js +182 -0
- package/dist-server/server/runtime-host/codex-session.d.ts +74 -0
- package/dist-server/server/runtime-host/codex-session.js +492 -0
- package/dist-server/server/runtime-host/codex-terminal-protocol.d.ts +35 -0
- package/dist-server/server/runtime-host/codex-terminal-protocol.js +243 -0
- package/dist-server/server/runtime-host/codex-terminal.d.ts +16 -0
- package/dist-server/server/runtime-host/codex-terminal.js +120 -0
- package/dist-server/server/runtime-host/index.d.ts +5 -0
- package/dist-server/server/runtime-host/index.js +3 -0
- package/dist-server/server/runtime-host/local.d.ts +29 -0
- package/dist-server/server/runtime-host/local.js +90 -0
- package/dist-server/server/runtime-host/policy.d.ts +8 -0
- package/dist-server/server/runtime-host/policy.js +78 -0
- package/dist-server/server/runtime-host/types.d.ts +52 -0
- package/dist-server/server/runtime-host/types.js +62 -0
- package/dist-server/server/structured-query-evidence.d.ts +7 -0
- package/dist-server/server/structured-query-evidence.js +47 -0
- package/dist-server/server/structured-runtime.d.ts +52 -0
- package/dist-server/server/structured-runtime.js +130 -0
- package/dist-server/server/structured-scope.d.ts +4 -0
- package/dist-server/server/structured-scope.js +12 -0
- package/dist-server/server/turn.d.ts +6 -1
- package/dist-server/server/turn.js +86 -26
- package/dist-server/server/wire-types.d.ts +67 -3
- package/dist-server/server/wren-profiles.js +1 -1
- package/managed-wren/README.md +60 -0
- package/managed-wren/dependency-wheels.json +282 -0
- package/managed-wren/manifest.json +373 -0
- package/managed-wren/release-inputs.json +45 -0
- package/managed-wren/runtime-tree.cjs +115 -0
- package/managed-wren/source-inputs.json +40 -0
- package/package.json +15 -6
- package/profiles/genbi-default/context/binding.yml +17 -7
- package/profiles/genbi-default/context/context.json +146 -0
- package/profiles/genbi-default/ir.golden.json +39 -43
- package/profiles/genbi-default/profile.yml +31 -0
- package/profiles/genbi-enrich-context/context/binding.yml +14 -3
- package/profiles/genbi-enrich-context/context/context.json +146 -0
- package/profiles/genbi-enrich-context/ir.golden.json +4 -5
- package/profiles/genbi-monitor/context/binding.yml +13 -5
- package/profiles/genbi-monitor/context/context.json +146 -0
- package/profiles/genbi-monitor/ir.golden.json +13 -7
- package/profiles/genbi-report/context/binding.yml +19 -0
- package/profiles/genbi-report/context/context.json +223 -0
- package/profiles/genbi-report/ir.golden.json +328 -0
- package/profiles/genbi-report/profile.yml +38 -0
- package/profiles/genbi-setup/ir.golden.json +3 -1
- package/dist/assets/index-Xs4q7pNo.css +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The session runtime boundary is intentionally smaller than the existing
|
|
3
|
+
* native-session lifecycle. This module describes what the browser may know
|
|
4
|
+
* about a backend; process details remain in the host-only diagnostic surface.
|
|
5
|
+
*/
|
|
6
|
+
export declare const RUNTIME_BACKEND_IDS: readonly ["local", "codex-app-server", "claude-sandbox-runtime"];
|
|
7
|
+
export type RuntimeBackendId = (typeof RUNTIME_BACKEND_IDS)[number];
|
|
8
|
+
export declare const RUNTIME_CAPABILITIES: readonly ["pty", "terminal_replay", "terminal_resize", "terminal_terminate", "app_server_rpc", "sandbox_policy", "filesystem_isolation", "network_isolation"];
|
|
9
|
+
export type RuntimeCapability = (typeof RUNTIME_CAPABILITIES)[number];
|
|
10
|
+
export type RuntimeReadinessState = "ready" | "unavailable" | "incompatible" | "unprovisioned";
|
|
11
|
+
export declare const RUNTIME_BACKEND_REASON_CODES: {
|
|
12
|
+
readonly local: readonly ["local_runtime_disabled", "local_runtime_host_unavailable", "local_runtime_production_forbidden", "runtime_probe_failed"];
|
|
13
|
+
readonly "codex-app-server": readonly ["codex_app_server_unprovisioned", "codex_cli_missing", "codex_cli_version_malformed", "codex_cli_version_unsupported", "codex_identity_uncertified", "codex_dependencies_drifted", "codex_app_server_unreachable", "codex_app_server_cleanup_failed", "codex_app_server_protocol_incompatible", "codex_sandbox_policy_unavailable", "codex_permission_profile_unavailable", "codex_wren_manifest_missing", "codex_wren_manifest_invalid", "codex_wren_platform_unsupported", "codex_wren_runtime_unprovisioned", "codex_wren_provision_failed", "codex_wren_interpreter_mismatch", "codex_wren_launcher_mismatch", "codex_wren_package_mismatch", "codex_wren_closure_mismatch", "codex_wren_profile_unavailable", "codex_wren_secret_unavailable", "codex_wren_session_home_unavailable", "codex_wren_child_env_invalid", "runtime_platform_unsupported", "runtime_policy_unavailable", "runtime_probe_failed"];
|
|
14
|
+
readonly "claude-sandbox-runtime": readonly ["claude_sandbox_runtime_unprovisioned", "claude_cli_missing", "claude_cli_version_malformed", "claude_cli_version_unsupported", "claude_identity_uncertified", "claude_sandbox_runtime_missing", "claude_sandbox_runtime_version_malformed", "claude_sandbox_runtime_version_unsupported", "claude_sandbox_capability_missing", "runtime_platform_unsupported", "runtime_policy_unavailable", "runtime_probe_failed"];
|
|
15
|
+
};
|
|
16
|
+
export type RuntimeBackendReasonCode<B extends RuntimeBackendId = RuntimeBackendId> = (typeof RUNTIME_BACKEND_REASON_CODES)[B][number];
|
|
17
|
+
export interface RuntimeBackendReady {
|
|
18
|
+
readonly state: "ready";
|
|
19
|
+
/** Certified or development-local version token; never command output. */
|
|
20
|
+
readonly version: string;
|
|
21
|
+
/** Public capability names only. */
|
|
22
|
+
readonly capabilities: readonly RuntimeCapability[];
|
|
23
|
+
}
|
|
24
|
+
export interface RuntimeBackendNotReady<B extends RuntimeBackendId = RuntimeBackendId> {
|
|
25
|
+
readonly state: "unavailable" | "incompatible" | "unprovisioned";
|
|
26
|
+
readonly code: RuntimeBackendReasonCode<B>;
|
|
27
|
+
/** Fixed text derived from `code`, never from a command, path, or environment. */
|
|
28
|
+
readonly message: string;
|
|
29
|
+
}
|
|
30
|
+
export type RuntimeBackendReadiness<B extends RuntimeBackendId = RuntimeBackendId> = RuntimeBackendReady | RuntimeBackendNotReady<B>;
|
|
31
|
+
/** Browser/API-safe projection. The selected result is always this record's own member. */
|
|
32
|
+
export interface RuntimeReadiness {
|
|
33
|
+
readonly selected: RuntimeBackendId;
|
|
34
|
+
readonly selectedReadiness: RuntimeBackendReadiness;
|
|
35
|
+
readonly backends: Readonly<Record<RuntimeBackendId, RuntimeBackendReadiness>>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Host-only support evidence. Values are constrained to parsed tokens and
|
|
39
|
+
* declared capabilities; no raw command output, filesystem path, credential,
|
|
40
|
+
* or environment value belongs in this type.
|
|
41
|
+
*/
|
|
42
|
+
export interface RuntimeBackendDiagnostic {
|
|
43
|
+
readonly phase: "policy" | "platform" | "version" | "identity" | "capability" | "provisioning" | "probe";
|
|
44
|
+
readonly observedVersion?: string;
|
|
45
|
+
readonly requiredCapability?: RuntimeCapability;
|
|
46
|
+
readonly attestedIdentity?: `sha256:${string}`;
|
|
47
|
+
}
|
|
48
|
+
export type RuntimeDiagnostics = Readonly<Record<RuntimeBackendId, RuntimeBackendDiagnostic>>;
|
|
49
|
+
export interface RuntimeBackendProbeResult<B extends RuntimeBackendId = RuntimeBackendId> {
|
|
50
|
+
readonly readiness: RuntimeBackendReadiness<B>;
|
|
51
|
+
readonly diagnostic: RuntimeBackendDiagnostic;
|
|
52
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The session runtime boundary is intentionally smaller than the existing
|
|
3
|
+
* native-session lifecycle. This module describes what the browser may know
|
|
4
|
+
* about a backend; process details remain in the host-only diagnostic surface.
|
|
5
|
+
*/
|
|
6
|
+
export const RUNTIME_BACKEND_IDS = ["local", "codex-app-server", "claude-sandbox-runtime"];
|
|
7
|
+
export const RUNTIME_CAPABILITIES = [
|
|
8
|
+
"pty",
|
|
9
|
+
"terminal_replay",
|
|
10
|
+
"terminal_resize",
|
|
11
|
+
"terminal_terminate",
|
|
12
|
+
"app_server_rpc",
|
|
13
|
+
"sandbox_policy",
|
|
14
|
+
"filesystem_isolation",
|
|
15
|
+
"network_isolation",
|
|
16
|
+
];
|
|
17
|
+
export const RUNTIME_BACKEND_REASON_CODES = {
|
|
18
|
+
local: ["local_runtime_disabled", "local_runtime_host_unavailable", "local_runtime_production_forbidden", "runtime_probe_failed"],
|
|
19
|
+
"codex-app-server": [
|
|
20
|
+
"codex_app_server_unprovisioned",
|
|
21
|
+
"codex_cli_missing",
|
|
22
|
+
"codex_cli_version_malformed",
|
|
23
|
+
"codex_cli_version_unsupported",
|
|
24
|
+
"codex_identity_uncertified",
|
|
25
|
+
"codex_dependencies_drifted",
|
|
26
|
+
"codex_app_server_unreachable",
|
|
27
|
+
"codex_app_server_cleanup_failed",
|
|
28
|
+
"codex_app_server_protocol_incompatible",
|
|
29
|
+
"codex_sandbox_policy_unavailable",
|
|
30
|
+
"codex_permission_profile_unavailable",
|
|
31
|
+
"codex_wren_manifest_missing",
|
|
32
|
+
"codex_wren_manifest_invalid",
|
|
33
|
+
"codex_wren_platform_unsupported",
|
|
34
|
+
"codex_wren_runtime_unprovisioned",
|
|
35
|
+
"codex_wren_provision_failed",
|
|
36
|
+
"codex_wren_interpreter_mismatch",
|
|
37
|
+
"codex_wren_launcher_mismatch",
|
|
38
|
+
"codex_wren_package_mismatch",
|
|
39
|
+
"codex_wren_closure_mismatch",
|
|
40
|
+
"codex_wren_profile_unavailable",
|
|
41
|
+
"codex_wren_secret_unavailable",
|
|
42
|
+
"codex_wren_session_home_unavailable",
|
|
43
|
+
"codex_wren_child_env_invalid",
|
|
44
|
+
"runtime_platform_unsupported",
|
|
45
|
+
"runtime_policy_unavailable",
|
|
46
|
+
"runtime_probe_failed",
|
|
47
|
+
],
|
|
48
|
+
"claude-sandbox-runtime": [
|
|
49
|
+
"claude_sandbox_runtime_unprovisioned",
|
|
50
|
+
"claude_cli_missing",
|
|
51
|
+
"claude_cli_version_malformed",
|
|
52
|
+
"claude_cli_version_unsupported",
|
|
53
|
+
"claude_identity_uncertified",
|
|
54
|
+
"claude_sandbox_runtime_missing",
|
|
55
|
+
"claude_sandbox_runtime_version_malformed",
|
|
56
|
+
"claude_sandbox_runtime_version_unsupported",
|
|
57
|
+
"claude_sandbox_capability_missing",
|
|
58
|
+
"runtime_platform_unsupported",
|
|
59
|
+
"runtime_policy_unavailable",
|
|
60
|
+
"runtime_probe_failed",
|
|
61
|
+
],
|
|
62
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RenderEnvelope } from "../harness/render/envelope.js";
|
|
2
|
+
/** Only call with returns from scoped host tools, never vendor messages or tool arguments.
|
|
3
|
+
* Keep every root in call order; mixed failure/success must not look wholly verified.
|
|
4
|
+
*/
|
|
5
|
+
export declare function structuredQueryEnvelope(roots: readonly unknown[], explanation: string): RenderEnvelope | undefined;
|
|
6
|
+
/** Supply the clock explicitly. Historical datasets must never silently become 'recent'. */
|
|
7
|
+
export declare function analyticalAskPrompt(question: string, now: Date): string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const cell = z.union([z.string(), z.number().finite(), z.boolean(), z.null()]);
|
|
3
|
+
const table = z.object({ columns: z.array(z.string()).min(1), rows: z.array(z.union([z.array(cell), z.record(z.string(), cell)])) });
|
|
4
|
+
const definition = z.object({ sql: z.string().trim().min(1), source_tables: z.array(z.string()).optional(), filters: z.array(z.string()).optional() });
|
|
5
|
+
const renderResult = z.object({ status: z.literal("ok"),
|
|
6
|
+
output: z.object({ kind: z.literal("render"), blocks: z.array(z.object({ type: z.string() }).passthrough()) }),
|
|
7
|
+
provenance: z.object({ verified: z.literal(true) }) });
|
|
8
|
+
const result = z.object({ status: z.literal("ok"), output: z.object({ kind: z.literal("value"), value: table }),
|
|
9
|
+
provenance: z.object({ verified: z.literal(true), definition }) });
|
|
10
|
+
/** Only call with returns from scoped host tools, never vendor messages or tool arguments.
|
|
11
|
+
* Keep every root in call order; mixed failure/success must not look wholly verified.
|
|
12
|
+
*/
|
|
13
|
+
export function structuredQueryEnvelope(roots, explanation) {
|
|
14
|
+
if (!roots.length)
|
|
15
|
+
return undefined;
|
|
16
|
+
const blocks = [];
|
|
17
|
+
for (const raw of roots) {
|
|
18
|
+
const parsed = result.safeParse(raw);
|
|
19
|
+
if (!parsed.success) {
|
|
20
|
+
const rendered = renderResult.safeParse(raw);
|
|
21
|
+
if (!rendered.success || !rendered.data.output.blocks.length)
|
|
22
|
+
return undefined;
|
|
23
|
+
blocks.push(...rendered.data.output.blocks);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const { columns, rows } = parsed.data.output.value;
|
|
27
|
+
if (new Set(columns).size !== columns.length || rows.some((row) => Array.isArray(row)
|
|
28
|
+
? row.length !== columns.length : columns.some((name) => !Object.hasOwn(row, name))))
|
|
29
|
+
return undefined;
|
|
30
|
+
blocks.push({ type: "table", columns, rows }, { type: "definition", ...parsed.data.provenance.definition });
|
|
31
|
+
}
|
|
32
|
+
return { blocks, verified: true, verificationScope: "query-results", explanation };
|
|
33
|
+
}
|
|
34
|
+
/** Supply the clock explicitly. Historical datasets must never silently become 'recent'. */
|
|
35
|
+
export function analyticalAskPrompt(question, now) {
|
|
36
|
+
return `Current reference time (UTC): ${now.toISOString()}.
|
|
37
|
+
Use the selected analysis tool for data questions and pass the user's requested period and metric definitions faithfully.
|
|
38
|
+
If no period was specified, use the full available data range and disclose this assumption; do not invent a recent N-week limit.
|
|
39
|
+
For relative periods, distinguish the current calendar from the latest data date. Never silently re-anchor a calendar-relative request.
|
|
40
|
+
The application displays successful query rows and SQL directly. Do not repeat the table or serialize an answer envelope in your final text.
|
|
41
|
+
Instead explain in the user's language: exact date range and anchor, date field, week start, timezone (or unknown), partial periods,
|
|
42
|
+
and the definition of each metric. Separate context-defined metrics from assumptions. Do not invent signup dates or duplicate synonymous metrics.
|
|
43
|
+
If the result cannot establish a date bound or definition, state that it is unknown or ask for clarification. Do not invent evidence.
|
|
44
|
+
|
|
45
|
+
User question:
|
|
46
|
+
${question}`;
|
|
47
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type AuthChoice, type RouteOptions, type RouteResult, type SetupStepRunner, type SetupStepRunOptions, type SetupStepRunResult } from "../harness/index.js";
|
|
2
|
+
import type { RuntimeBackendReadiness } from "./runtime-host/types.js";
|
|
3
|
+
export type StructuredVendor = "codex" | "claude";
|
|
4
|
+
export type StructuredBackend = "local" | "codex-app-server" | "claude-sandbox-runtime";
|
|
5
|
+
export interface StructuredScope {
|
|
6
|
+
readonly sessionId: string;
|
|
7
|
+
readonly turnId: string;
|
|
8
|
+
readonly signal?: AbortSignal;
|
|
9
|
+
/** Captured host state, rechecked before/after preparation, tools, events and results. */
|
|
10
|
+
assertCurrent(): void;
|
|
11
|
+
}
|
|
12
|
+
export declare class StructuredRuntimeError extends Error {
|
|
13
|
+
readonly code: "unavailable" | "unsupported" | "stale" | "cancelled" | "failed" | "cleanup" | "timeout";
|
|
14
|
+
constructor(code: "unavailable" | "unsupported" | "stale" | "cancelled" | "failed" | "cleanup" | "timeout");
|
|
15
|
+
}
|
|
16
|
+
export interface StructuredAdapter {
|
|
17
|
+
readonly vendor: StructuredVendor;
|
|
18
|
+
readonly backend: Exclude<StructuredBackend, "local">;
|
|
19
|
+
probe(): Promise<RuntimeBackendReadiness>;
|
|
20
|
+
ask?(options: RouteOptions, scope: StructuredScope): Promise<RouteResult>;
|
|
21
|
+
setup?(options: SetupStepRunOptions, scope: StructuredScope): Promise<SetupStepRunResult>;
|
|
22
|
+
}
|
|
23
|
+
interface Options {
|
|
24
|
+
readonly selected: {
|
|
25
|
+
readonly codex: "local" | "codex-app-server";
|
|
26
|
+
readonly claude: "local" | "claude-sandbox-runtime";
|
|
27
|
+
};
|
|
28
|
+
/** Explicit compatibility opt-in, never proof of vendor sandboxing. */
|
|
29
|
+
readonly allowLocal: boolean;
|
|
30
|
+
readonly deployment?: RouteOptions["deployment"];
|
|
31
|
+
readonly localRoute: (options: RouteOptions) => Promise<RouteResult>;
|
|
32
|
+
readonly localSetupFor: (auth: AuthChoice) => SetupStepRunner | undefined;
|
|
33
|
+
readonly adapters?: Readonly<Partial<Record<StructuredVendor, StructuredAdapter>>>;
|
|
34
|
+
}
|
|
35
|
+
/** Server composition owns backend choice. No browser paths/configuration select a backend. */
|
|
36
|
+
export declare class StructuredRuntime {
|
|
37
|
+
private readonly options;
|
|
38
|
+
private readonly lifetime;
|
|
39
|
+
private readonly controllers;
|
|
40
|
+
private readonly active;
|
|
41
|
+
private cleanupFailed;
|
|
42
|
+
constructor(options: Options);
|
|
43
|
+
private adapter;
|
|
44
|
+
readiness(): Promise<any>;
|
|
45
|
+
route(options: RouteOptions, scope: StructuredScope): Promise<RouteResult>;
|
|
46
|
+
setup(options: SetupStepRunOptions, scope: StructuredScope): Promise<SetupStepRunResult>;
|
|
47
|
+
private run;
|
|
48
|
+
assertActive(): void;
|
|
49
|
+
revoke(): void;
|
|
50
|
+
shutdown(): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { enforceCompliance } from "../harness/index.js";
|
|
2
|
+
export class StructuredRuntimeError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
constructor(code) {
|
|
5
|
+
super(`Structured runtime ${code}.`);
|
|
6
|
+
this.code = code;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/** Server composition owns backend choice. No browser paths/configuration select a backend. */
|
|
10
|
+
export class StructuredRuntime {
|
|
11
|
+
options;
|
|
12
|
+
lifetime = new AbortController();
|
|
13
|
+
controllers = new Set();
|
|
14
|
+
active = new Set();
|
|
15
|
+
cleanupFailed = false;
|
|
16
|
+
constructor(options) {
|
|
17
|
+
this.options = { ...options, selected: Object.freeze({ ...options.selected }), adapters: Object.freeze({ ...options.adapters }) };
|
|
18
|
+
}
|
|
19
|
+
adapter(vendor) {
|
|
20
|
+
const candidate = this.options.adapters?.[vendor];
|
|
21
|
+
return candidate?.vendor === vendor && candidate.backend === this.options.selected[vendor] ? candidate : undefined;
|
|
22
|
+
}
|
|
23
|
+
async readiness() {
|
|
24
|
+
const entries = await Promise.all(["codex", "claude"].map(async (vendor) => {
|
|
25
|
+
const backend = this.options.selected[vendor];
|
|
26
|
+
const localReady = this.options.allowLocal && !this.lifetime.signal.aborted;
|
|
27
|
+
if (backend === "local")
|
|
28
|
+
return [vendor, { backend, state: localReady ? "ready" : "unavailable", ask: localReady, setup: localReady && !!this.options.localSetupFor({ mode: "subscription", provider: vendor }), reason: this.options.allowLocal ? "Explicit local execution; vendor isolation is not claimed." : "Local execution is disabled." }];
|
|
29
|
+
const adapter = this.adapter(vendor);
|
|
30
|
+
let probe;
|
|
31
|
+
try {
|
|
32
|
+
probe = await adapter?.probe();
|
|
33
|
+
}
|
|
34
|
+
catch { /* fixed public failure below */ }
|
|
35
|
+
const ready = !this.lifetime.signal.aborted && probe?.state === "ready";
|
|
36
|
+
return [vendor, { backend, state: ready ? "ready" : "unavailable", ask: ready && !!adapter?.ask, setup: ready && !!adapter?.setup,
|
|
37
|
+
reason: !adapter ? "Selected vendor backend is not configured." : !ready ? "Selected vendor backend is not ready." : "Only explicitly supported operations are available.",
|
|
38
|
+
...(probe && probe.state !== "ready" ? { code: probe.code } : {}) }];
|
|
39
|
+
}));
|
|
40
|
+
return Object.fromEntries(entries);
|
|
41
|
+
}
|
|
42
|
+
async route(options, scope) {
|
|
43
|
+
return this.run(options.authChoice, scope, async (adapter, guarded) => {
|
|
44
|
+
const request = { ...options, signal: guarded.signal, onEvent: (event) => { guarded.assertCurrent(); options.onEvent?.(event); } };
|
|
45
|
+
if (!adapter)
|
|
46
|
+
return this.options.localRoute(request);
|
|
47
|
+
if (!adapter.ask)
|
|
48
|
+
throw new StructuredRuntimeError("unsupported");
|
|
49
|
+
return adapter.ask(request, guarded);
|
|
50
|
+
}, options.deployment);
|
|
51
|
+
}
|
|
52
|
+
async setup(options, scope) {
|
|
53
|
+
return this.run(options.authChoice, scope, async (adapter, guarded) => {
|
|
54
|
+
const request = { ...options, signal: guarded.signal, onEvent: (event) => { guarded.assertCurrent(); options.onEvent?.(event); } };
|
|
55
|
+
if (!adapter) {
|
|
56
|
+
const runner = this.options.localSetupFor(options.authChoice);
|
|
57
|
+
if (!runner)
|
|
58
|
+
throw new StructuredRuntimeError("unavailable");
|
|
59
|
+
return runner.run(request);
|
|
60
|
+
}
|
|
61
|
+
if (!adapter.setup || options.resumeSessionId !== undefined)
|
|
62
|
+
throw new StructuredRuntimeError("unsupported");
|
|
63
|
+
// Isolated runners must not mint legacy provider-resume anchors.
|
|
64
|
+
const result = await adapter.setup(request, guarded);
|
|
65
|
+
return { finalText: result.finalText };
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
run(auth, scope, operation, deployment = "personal") {
|
|
69
|
+
const controller = new AbortController();
|
|
70
|
+
this.controllers.add(controller);
|
|
71
|
+
const signal = AbortSignal.any([controller.signal, this.lifetime.signal, ...(scope.signal ? [scope.signal] : [])]);
|
|
72
|
+
const assertCurrent = () => {
|
|
73
|
+
if (signal.aborted)
|
|
74
|
+
throw new StructuredRuntimeError("cancelled");
|
|
75
|
+
try {
|
|
76
|
+
scope.assertCurrent();
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
throw new StructuredRuntimeError("stale");
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const pending = (async () => {
|
|
83
|
+
assertCurrent();
|
|
84
|
+
enforceCompliance(auth, { deployment: this.options.deployment ?? deployment });
|
|
85
|
+
let adapter;
|
|
86
|
+
if (auth.mode === "subscription" && this.options.selected[auth.provider] !== "local") {
|
|
87
|
+
adapter = this.adapter(auth.provider);
|
|
88
|
+
if (!adapter)
|
|
89
|
+
throw new StructuredRuntimeError("unavailable");
|
|
90
|
+
let ready;
|
|
91
|
+
try {
|
|
92
|
+
ready = await adapter.probe();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
throw new StructuredRuntimeError("unavailable");
|
|
96
|
+
}
|
|
97
|
+
assertCurrent();
|
|
98
|
+
if (ready.state !== "ready")
|
|
99
|
+
throw new StructuredRuntimeError("unavailable");
|
|
100
|
+
}
|
|
101
|
+
else if (auth.mode === "subscription" && !this.options.allowLocal)
|
|
102
|
+
throw new StructuredRuntimeError("unavailable");
|
|
103
|
+
let result;
|
|
104
|
+
try {
|
|
105
|
+
result = await operation(adapter, { sessionId: scope.sessionId, turnId: scope.turnId, signal, assertCurrent });
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (adapter && !(error instanceof StructuredRuntimeError))
|
|
109
|
+
throw new StructuredRuntimeError(signal.aborted ? "cancelled" : "failed");
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
assertCurrent();
|
|
113
|
+
return result;
|
|
114
|
+
})();
|
|
115
|
+
this.active.add(pending);
|
|
116
|
+
void pending.catch((error) => { if (error instanceof StructuredRuntimeError && error.code === "cleanup")
|
|
117
|
+
this.cleanupFailed = true; }).finally(() => { this.active.delete(pending); this.controllers.delete(controller); });
|
|
118
|
+
return pending;
|
|
119
|
+
}
|
|
120
|
+
assertActive() { if (this.lifetime.signal.aborted)
|
|
121
|
+
throw new StructuredRuntimeError("cancelled"); }
|
|
122
|
+
revoke() { for (const controller of this.controllers)
|
|
123
|
+
controller.abort(); }
|
|
124
|
+
async shutdown() {
|
|
125
|
+
this.lifetime.abort();
|
|
126
|
+
await Promise.allSettled([...this.active]);
|
|
127
|
+
if (this.cleanupFailed)
|
|
128
|
+
throw new StructuredRuntimeError("cleanup");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Store, TurnRow } from "./db.js";
|
|
2
|
+
import { type StructuredScope } from "./structured-runtime.js";
|
|
3
|
+
/** Captured host-only values are compared, never persisted or sent as model/browser authority. */
|
|
4
|
+
export declare function captureStructuredScope(store: Store, turn: TurnRow, getProject: () => string | undefined, signal?: AbortSignal): StructuredScope;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { StructuredRuntimeError } from "./structured-runtime.js";
|
|
2
|
+
/** Captured host-only values are compared, never persisted or sent as model/browser authority. */
|
|
3
|
+
export function captureStructuredScope(store, turn, getProject, signal) {
|
|
4
|
+
const snapshot = () => JSON.stringify({ runtime: store.getRuntimeSettings(), generation: store.getNativeRuntimeBinding().generation,
|
|
5
|
+
binding: store.getEnrichmentBinding(), project: getProject(), ...(turn.setupStepKey !== null ? { form: store.getSetupConnectForm() } : {}) });
|
|
6
|
+
const captured = snapshot();
|
|
7
|
+
return { sessionId: turn.sessionId, turnId: turn.id, ...(signal ? { signal } : {}), assertCurrent() {
|
|
8
|
+
const current = store.getTurn(turn.id);
|
|
9
|
+
if (signal?.aborted || snapshot() !== captured || !current || current.sessionId !== turn.sessionId || current.resultKind !== null)
|
|
10
|
+
throw new StructuredRuntimeError("stale");
|
|
11
|
+
} };
|
|
12
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ProfileRegistry } from "./profile-registry.js";
|
|
2
|
+
import type { StructuredRuntime } from "./structured-runtime.js";
|
|
1
3
|
import type { AuthChoice, Bundle, LoginProbe, RouteOptions, RouteResult, SetupStepRunner } from "../harness/index.js";
|
|
2
4
|
import type { SubscriptionModelCatalog, SubscriptionProvider } from "./wire-types.js";
|
|
3
5
|
import { type Store } from "./db.js";
|
|
@@ -23,6 +25,7 @@ export declare class ArtifactNotFoundError extends Error {
|
|
|
23
25
|
}
|
|
24
26
|
export interface TurnDeps {
|
|
25
27
|
readonly store: Store;
|
|
28
|
+
readonly structuredRuntime?: StructuredRuntime;
|
|
26
29
|
readonly route: (options: RouteOptions) => Promise<RouteResult>;
|
|
27
30
|
/** A native vendor TUI host, deliberately independent from Ask/SSE. */
|
|
28
31
|
readonly startInteractiveTerminal?: (input: {
|
|
@@ -48,6 +51,8 @@ export interface TurnDeps {
|
|
|
48
51
|
readonly nativeSessions?: NativeSessionService;
|
|
49
52
|
/** Session-scoped MCP persistence service; never used by Ask publish routes. */
|
|
50
53
|
readonly nativeArtifacts?: NativeArtifactService;
|
|
54
|
+
/** Server-held registry of conversation profiles; absent means `/api/profiles` answers 503. */
|
|
55
|
+
readonly profileRegistry?: ProfileRegistry;
|
|
51
56
|
readonly baseRouteOptions: Omit<RouteOptions, "question" | "onEvent">;
|
|
52
57
|
/**
|
|
53
58
|
* Ask/compile-bind only: compiles+loads the analysis profile's bundle.
|
|
@@ -64,7 +69,7 @@ export interface TurnDeps {
|
|
|
64
69
|
* dependency resolves the corresponding server-owned profile source. It is
|
|
65
70
|
* intentionally distinct from native-session IR/launch wiring.
|
|
66
71
|
*/
|
|
67
|
-
readonly describeHarnessBundle?: (purpose: NativePurpose, options: Omit<RouteOptions, "question" | "onEvent"
|
|
72
|
+
readonly describeHarnessBundle?: (purpose: NativePurpose, options: Omit<RouteOptions, "question" | "onEvent">, profileSource?: string) => Promise<Bundle>;
|
|
68
73
|
/**
|
|
69
74
|
* Compiles the canonical post-bind profile without rebinding its context and
|
|
70
75
|
* returns its declared tier names. Unlike `describeBundle`, this seam is
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { captureStructuredScope } from "./structured-scope.js";
|
|
1
2
|
/**
|
|
2
3
|
* Orchestrates one turn end-to-end: clarify pre-flight, context
|
|
3
4
|
* composition, invoking `route()`, folding its result/events into the UI's
|
|
@@ -16,7 +17,7 @@ import { assertRuntimeSettingsDispatchable, materializeRuntimeRouteOptions } fro
|
|
|
16
17
|
import { classifyClarify } from "./clarify.js";
|
|
17
18
|
import { classifyIntent } from "./route-intent.js";
|
|
18
19
|
import { composeClarifyFollowUp, composeInput } from "./compose.js";
|
|
19
|
-
import { clarifyDecisionStep, extractTrace, foldTrace, gateDecisionStep, gateFailureStep, hostContractRecoveryStep, LiveWorkLog, redactPublicSetupText, sanitizeLiveSetupWorklog, sanitizePublicSetupWorklog, routeDecisionStep, summarizeResult, toAnswerOrRefusalEvent, toArtifactEvent, } from "./fold.js";
|
|
20
|
+
import { clarifyDecisionStep, extractTrace, foldTrace, gateDecisionStep, gateFailureStep, hostContractRecoveryStep, LiveWorkLog, redactPublicSetupText, sanitizeLiveSetupWorklog, sanitizePublicSetupWorklog, routeDecisionStep, summarizeResult, toAnswerOrRefusalEvent, toArtifactEvent, withHostVerification, } from "./fold.js";
|
|
20
21
|
export class SessionNotFoundError extends Error {
|
|
21
22
|
sessionId;
|
|
22
23
|
constructor(sessionId) {
|
|
@@ -255,7 +256,7 @@ async function replayResolvedTurn(store, turn, emit) {
|
|
|
255
256
|
}
|
|
256
257
|
async function executeTurn(deps, session, turn, emit, signal) {
|
|
257
258
|
if (turn.setupStepKey !== null) {
|
|
258
|
-
await executeSetupTurn(deps, session, turn, emit);
|
|
259
|
+
await executeSetupTurn(deps, session, turn, emit, signal);
|
|
259
260
|
return;
|
|
260
261
|
}
|
|
261
262
|
const liveLog = new LiveWorkLog();
|
|
@@ -285,20 +286,9 @@ async function executeTurn(deps, session, turn, emit, signal) {
|
|
|
285
286
|
chain = chain.then(() => emit({ event: "worklog", data: merged }));
|
|
286
287
|
}
|
|
287
288
|
};
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
...effectiveRouteOptions(deps),
|
|
292
|
-
question: turn.composedInput ?? turn.question,
|
|
293
|
-
onEvent,
|
|
294
|
-
...(signal !== undefined ? { signal } : {}),
|
|
295
|
-
// the turn's own persisted agent id (classified once at postTurn time), so a turn
|
|
296
|
-
// always resolves to the same agent whether executed live or (via a future replay path) re-run.
|
|
297
|
-
...(turn.agentId !== null ? { agentId: turn.agentId } : {}),
|
|
298
|
-
};
|
|
299
|
-
result = await deps.route(routeOptions);
|
|
300
|
-
}
|
|
301
|
-
catch (err) {
|
|
289
|
+
const runtimeScope = deps.structuredRuntime ? captureStructuredScope(deps.store, turn, () => resolveUserProject(deps), signal) : undefined;
|
|
290
|
+
const assertCurrent = () => { deps.structuredRuntime?.assertActive(); runtimeScope?.assertCurrent(); };
|
|
291
|
+
const failTurn = async (err) => {
|
|
302
292
|
await chain;
|
|
303
293
|
const message = err instanceof Error ? err.message : String(err);
|
|
304
294
|
// Persist the PARTIAL work log on failure — the Route/Clarify
|
|
@@ -312,7 +302,25 @@ async function executeTurn(deps, session, turn, emit, signal) {
|
|
|
312
302
|
deps.store.resolveTurn(turn.id, { backend: null, resultKind: "error", answerSummary: null, traceJson: JSON.stringify(partialWorklog), errorMessage: message });
|
|
313
303
|
deps.store.updateSessionStatus(session.id, "active", null);
|
|
314
304
|
await emit({ event: "error", data: { message } });
|
|
315
|
-
|
|
305
|
+
};
|
|
306
|
+
let result;
|
|
307
|
+
try {
|
|
308
|
+
const routeOptions = {
|
|
309
|
+
...effectiveRouteOptions(deps),
|
|
310
|
+
question: turn.composedInput ?? turn.question,
|
|
311
|
+
onEvent,
|
|
312
|
+
...(signal !== undefined ? { signal } : {}),
|
|
313
|
+
// the turn's own persisted agent id (classified once at postTurn time), so a turn
|
|
314
|
+
// always resolves to the same agent whether executed live or (via a future replay path) re-run.
|
|
315
|
+
...(turn.agentId !== null ? { agentId: turn.agentId } : {}),
|
|
316
|
+
};
|
|
317
|
+
result = deps.structuredRuntime
|
|
318
|
+
? await deps.structuredRuntime.route(routeOptions, runtimeScope)
|
|
319
|
+
: await deps.route(routeOptions);
|
|
320
|
+
}
|
|
321
|
+
catch (err) {
|
|
322
|
+
await failTurn(err);
|
|
323
|
+
return;
|
|
316
324
|
}
|
|
317
325
|
await chain;
|
|
318
326
|
// Prefer the live worklog snapshot (LLM step rows interleaved
|
|
@@ -339,7 +347,16 @@ async function executeTurn(deps, session, turn, emit, signal) {
|
|
|
339
347
|
// artifact-producing component (`generate_dashboard`/`explain_change` —
|
|
340
348
|
// NOT a plain `answer_query` table), persist it as a real artifact too, so
|
|
341
349
|
// it's publishable regardless of which backend ran the turn.
|
|
342
|
-
|
|
350
|
+
let artifactEvent;
|
|
351
|
+
try {
|
|
352
|
+
assertCurrent();
|
|
353
|
+
artifactEvent = await maybeCreateDispatchedArtifact(deps, session, turn, result, terminalEvent, assertCurrent);
|
|
354
|
+
assertCurrent();
|
|
355
|
+
}
|
|
356
|
+
catch (err) {
|
|
357
|
+
await failTurn(err);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
343
360
|
// Persist the turn as fully resolved BEFORE emitting any terminal frames.
|
|
344
361
|
// If a client disconnect makes an emit below throw, the turn is already
|
|
345
362
|
// resolved, so the next stream deterministically REPLAYS these stored frames
|
|
@@ -384,11 +401,13 @@ async function executeTurn(deps, session, turn, emit, signal) {
|
|
|
384
401
|
* verbatim as JSON to a session-scoped file under the same artifacts root
|
|
385
402
|
* the in-process `write_artifact` tool uses (`resolveArtifactsDir`) — self-
|
|
386
403
|
* contained from the envelope, no dependency on the dispatcher's `htmlPath`
|
|
387
|
-
* (never present in the NDJSON stream today). `verified` comes
|
|
388
|
-
*
|
|
404
|
+
* (never present in the NDJSON stream today). `verified` comes from the
|
|
405
|
+
* envelope after {@link withHostVerification}, so an artifact is stored as
|
|
406
|
+
* verified only when host evidence grounds it (a codex:local answer citing
|
|
407
|
+
* this turn's host-run queries), never on the model's own claim.
|
|
389
408
|
*/
|
|
390
|
-
async function maybeCreateDispatchedArtifact(deps, session, turn, result, terminalEvent) {
|
|
391
|
-
if (result.backend !== "agent-sdk" && result.backend !== "codex-local")
|
|
409
|
+
async function maybeCreateDispatchedArtifact(deps, session, turn, result, terminalEvent, assertCurrent) {
|
|
410
|
+
if (result.backend !== "agent-sdk" && result.backend !== "codex-local" && result.backend !== "codex-app-server")
|
|
392
411
|
return undefined;
|
|
393
412
|
if (terminalEvent.kind !== "answer" || terminalEvent.answer.form !== "rich")
|
|
394
413
|
return undefined;
|
|
@@ -396,7 +415,8 @@ async function maybeCreateDispatchedArtifact(deps, session, turn, result, termin
|
|
|
396
415
|
return undefined;
|
|
397
416
|
if (!(await isArtifactProducerAgent(deps, turn.agentId)))
|
|
398
417
|
return undefined;
|
|
399
|
-
|
|
418
|
+
assertCurrent();
|
|
419
|
+
const envelope = withHostVerification(result, terminalEvent.answer.envelope);
|
|
400
420
|
const artifactKind = artifactKindForAgent(turn.agentId);
|
|
401
421
|
const verified = envelope.verified === true;
|
|
402
422
|
const sessionArtifactsDir = path.join(resolveArtifactsDir(effectiveRouteOptions(deps).outDir), session.id);
|
|
@@ -516,7 +536,7 @@ function turnRecoveryAnchor(turn, sessionId, authChoice) {
|
|
|
516
536
|
* `status` field, which the frontend inspects (see the wire contract in the
|
|
517
537
|
* final report). Only a parsed `error` persists as `resultKind: "error"`.
|
|
518
538
|
*/
|
|
519
|
-
async function executeSetupTurn(deps, session, turn, emit) {
|
|
539
|
+
async function executeSetupTurn(deps, session, turn, emit, signal) {
|
|
520
540
|
// Provider session anchors are server-only. Keep every anchor that becomes
|
|
521
541
|
// known during this turn so a host-contract continuation that rotates its
|
|
522
542
|
// anchor still redacts both the original and replacement from the combined
|
|
@@ -584,7 +604,10 @@ async function executeSetupTurn(deps, session, turn, emit) {
|
|
|
584
604
|
? undefined
|
|
585
605
|
: deps.store.getSetupContextLifecycleEvidence(session.id, identityFingerprint)?.completed;
|
|
586
606
|
if (identityFingerprint !== undefined) {
|
|
587
|
-
const recorded = recordedContextLifecyclePrefix(worklog, prior ?? "none"
|
|
607
|
+
const recorded = recordedContextLifecyclePrefix(worklog, prior ?? "none", {
|
|
608
|
+
root: workspaceRoot,
|
|
609
|
+
projectDir: path.join(workspaceRoot, form.projectName),
|
|
610
|
+
});
|
|
588
611
|
// A build command is not retained by itself: only a successful terminal
|
|
589
612
|
// parse has independently checked target/mdl.json. Discovery/validate
|
|
590
613
|
// remain useful across an interrupted turn, but build includes artifact
|
|
@@ -645,7 +668,11 @@ async function executeSetupTurn(deps, session, turn, emit) {
|
|
|
645
668
|
const data = initialAuthChoice.mode === "subscription" ? sanitizeLiveSetupWorklog(snapshot) : publicWorklog(snapshot);
|
|
646
669
|
chain = chain.then(() => emit({ event: "worklog", data }));
|
|
647
670
|
};
|
|
648
|
-
const
|
|
671
|
+
const runtimeScope = captureStructuredScope(deps.store, turn, () => resolveUserProject(deps), signal);
|
|
672
|
+
const runSelected = (options) => deps.structuredRuntime
|
|
673
|
+
? deps.structuredRuntime.setup(options, runtimeScope) : setupRunner.run(options);
|
|
674
|
+
const runAttempt = (prompt, authChoice, resumeSessionId) => runSelected({
|
|
675
|
+
...(signal ? { signal } : {}),
|
|
649
676
|
prompt,
|
|
650
677
|
workspaceRoot,
|
|
651
678
|
// The form was validated before persistence. Thread it to dispatched so
|
|
@@ -744,6 +771,16 @@ async function executeSetupTurn(deps, session, turn, emit) {
|
|
|
744
771
|
return;
|
|
745
772
|
}
|
|
746
773
|
await chain.catch(() => { });
|
|
774
|
+
try {
|
|
775
|
+
if (deps.structuredRuntime) {
|
|
776
|
+
deps.structuredRuntime.assertActive();
|
|
777
|
+
runtimeScope.assertCurrent();
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
catch (error) {
|
|
781
|
+
await failWithError(error instanceof Error ? error.message : "Structured runtime stale.", liveLog.snapshot());
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
747
784
|
const worklog = liveLog.snapshot();
|
|
748
785
|
let terminal = parseTerminalWithRetainedLifecycle(finalText, worklog);
|
|
749
786
|
terminal = { ...terminal, message: redactPublicSetupText(terminal.message) };
|
|
@@ -816,6 +853,16 @@ async function executeSetupTurn(deps, session, turn, emit) {
|
|
|
816
853
|
return;
|
|
817
854
|
}
|
|
818
855
|
}
|
|
856
|
+
try {
|
|
857
|
+
if (deps.structuredRuntime) {
|
|
858
|
+
deps.structuredRuntime.assertActive();
|
|
859
|
+
runtimeScope.assertCurrent();
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
catch (error) {
|
|
863
|
+
await failWithError(error instanceof Error ? error.message : "Structured runtime stale.", liveLog.snapshot());
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
819
866
|
// A completed runner result can introduce a new server-owned anchor after
|
|
820
867
|
// the live frames have begun. Re-sanitize every normal terminal boundary
|
|
821
868
|
// with that now-known identity before it reaches SSE or SQLite.
|
|
@@ -882,6 +929,8 @@ async function executeSetupTurn(deps, session, turn, emit) {
|
|
|
882
929
|
if (temporarilyBoundForHealthcheck) {
|
|
883
930
|
deps.bindProject(path.join(workspaceRoot, form.projectName));
|
|
884
931
|
}
|
|
932
|
+
// Refresh only after the host-owned bind, then fence the asynchronous healthcheck.
|
|
933
|
+
const healthcheckScope = captureStructuredScope(deps.store, turn, () => resolveUserProject(deps), signal);
|
|
885
934
|
let compileHealthcheckFailure;
|
|
886
935
|
if (!deps.describeBundle) {
|
|
887
936
|
compileHealthcheckFailure = "the profile compile healthcheck is not configured";
|
|
@@ -894,6 +943,17 @@ async function executeSetupTurn(deps, session, turn, emit) {
|
|
|
894
943
|
compileHealthcheckFailure = summarizeCompileHealthcheckFailure(err);
|
|
895
944
|
}
|
|
896
945
|
}
|
|
946
|
+
try {
|
|
947
|
+
if (deps.structuredRuntime) {
|
|
948
|
+
deps.structuredRuntime.assertActive();
|
|
949
|
+
healthcheckScope.assertCurrent();
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
catch (error) {
|
|
953
|
+
// A newer binding belongs to its new owner; never roll it back here.
|
|
954
|
+
await failWithError(error instanceof Error ? error.message : "Structured runtime stale.", finalWorklog);
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
897
957
|
if (compileHealthcheckFailure !== undefined) {
|
|
898
958
|
if (temporarilyBoundForHealthcheck)
|
|
899
959
|
deps.unbindProject?.();
|