@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,250 @@
|
|
|
1
|
+
import { lstatSync, realpathSync } from "node:fs";
|
|
2
|
+
import { mkdir, mkdtemp, readFile, realpath, rm } from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { isDeepStrictEqual } from "node:util";
|
|
8
|
+
import { codexModelsForRuntime } from "./runtime-binding.js";
|
|
9
|
+
import { compileProfile } from "../harness/compile/index.js";
|
|
10
|
+
import { resolveContextLoaderBinary } from "../harness/compile/context-loader.js";
|
|
11
|
+
import { attestNativeExecutable, assertNativeExecutableIdentity, buildNativeRuntimeSpec } from "./native-runtime-spec.js";
|
|
12
|
+
import { createEmptyCodexWrenHome } from "./native-wren-home.js";
|
|
13
|
+
import { prepareCapturedCodexDirectTools } from "./native-component-context.js";
|
|
14
|
+
import { CodexAppServerBackend, CodexBackendError } from "./runtime-host/codex-app-server.js";
|
|
15
|
+
import { buildCodexSessionPolicy } from "./runtime-host/codex-policy.js";
|
|
16
|
+
import { isCodexExecutionCertified, isCodexTerminalCertified } from "./runtime-host/codex-compatibility.js";
|
|
17
|
+
import { runtimeNotReady } from "./runtime-host/policy.js";
|
|
18
|
+
/** Read once at composition. No browser values, PATH discovery or credential copying. */
|
|
19
|
+
export function readCodexBootConfiguration(env) {
|
|
20
|
+
const selected = env.GENBI_CODEX_RUNTIME ?? "local";
|
|
21
|
+
const local = env.GENBI_ALLOW_LOCAL_RUNTIME ?? "1";
|
|
22
|
+
if (!["local", "app-server"].includes(selected) || !["0", "1"].includes(local))
|
|
23
|
+
throw new Error("Invalid server runtime selection.");
|
|
24
|
+
return Object.freeze({ selected: selected === "app-server" ? "codex-app-server" : "local", allowLocal: local === "1",
|
|
25
|
+
...(env.GENBI_CODEX_EXECUTABLE ? { executable: env.GENBI_CODEX_EXECUTABLE } : {}),
|
|
26
|
+
...(env.GENBI_CODEX_SOURCE ? { source: env.GENBI_CODEX_SOURCE } : {}),
|
|
27
|
+
...(env.WREN_HARNESS_CODEX_HOME ? { loginHome: env.WREN_HARNESS_CODEX_HOME } : {}),
|
|
28
|
+
...(env.GENBI_CODEX_ACCOUNT_EMAIL ? { accountEmail: env.GENBI_CODEX_ACCOUNT_EMAIL } : {}) });
|
|
29
|
+
}
|
|
30
|
+
const unavailable = () => new CodexBackendError("runtime_policy_unavailable");
|
|
31
|
+
/** Real composition for both entry surfaces; certification is enforced by the packaged backend. */
|
|
32
|
+
export function createCodexRuntimeComposition(options) {
|
|
33
|
+
const config = Object.freeze({ ...options.configuration });
|
|
34
|
+
const backend = new CodexAppServerBackend({ executable: config.executable ?? "", source: config.source ?? "", packageRoot: options.packageRoot });
|
|
35
|
+
const checkConfiguration = () => {
|
|
36
|
+
if (!config.executable || !path.isAbsolute(config.executable) || !config.source?.startsWith("https://")
|
|
37
|
+
|| !config.loginHome || !path.isAbsolute(config.loginHome) || !config.accountEmail?.trim())
|
|
38
|
+
throw unavailable();
|
|
39
|
+
const login = realpathSync(config.loginHome);
|
|
40
|
+
const directory = lstatSync(config.loginHome);
|
|
41
|
+
const auth = lstatSync(path.join(login, "auth.json"));
|
|
42
|
+
if (directory.isSymbolicLink() || !directory.isDirectory() || (directory.mode & 0o777) !== 0o700
|
|
43
|
+
|| login === path.join(os.homedir(), ".codex") || !auth.isFile() || auth.isSymbolicLink() || (auth.mode & 0o077) !== 0)
|
|
44
|
+
throw unavailable();
|
|
45
|
+
return login;
|
|
46
|
+
};
|
|
47
|
+
const checkExecutionScope = (entry) => {
|
|
48
|
+
const models = codexModelsForRuntime(options.store.getRuntimeSettings());
|
|
49
|
+
const vendor = attestNativeExecutable("vendor", config.executable);
|
|
50
|
+
if (!isCodexExecutionCertified(config.source, vendor.digest.slice(7), Object.values(models), entry))
|
|
51
|
+
throw unavailable();
|
|
52
|
+
};
|
|
53
|
+
const probe = async () => {
|
|
54
|
+
const result = await backend.probe();
|
|
55
|
+
if (result.readiness.state !== "ready")
|
|
56
|
+
return result;
|
|
57
|
+
try {
|
|
58
|
+
checkConfiguration();
|
|
59
|
+
checkExecutionScope("answer_query");
|
|
60
|
+
attestNativeExecutable("producer", options.producerBinary);
|
|
61
|
+
resolveContextLoaderBinary();
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return { readiness: runtimeNotReady("codex-app-server", "unprovisioned", "runtime_policy_unavailable"), diagnostic: { phase: "policy" } };
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
async function prepare(input) {
|
|
69
|
+
input.permit.assertActive();
|
|
70
|
+
input.assertActive();
|
|
71
|
+
input.signal.throwIfAborted();
|
|
72
|
+
if (!["answer_query", "generate_dashboard"].includes(input.entry))
|
|
73
|
+
throw unavailable();
|
|
74
|
+
const loginHome = checkConfiguration();
|
|
75
|
+
checkExecutionScope(input.entry);
|
|
76
|
+
const binding = structuredClone(input.binding);
|
|
77
|
+
const settings = structuredClone(options.store.getRuntimeSettings());
|
|
78
|
+
const generation = options.store.getNativeRuntimeBinding().generation;
|
|
79
|
+
if (settings.authMode !== "subscription" || settings.subscriptionProvider !== "codex")
|
|
80
|
+
throw unavailable();
|
|
81
|
+
const models = codexModelsForRuntime(settings);
|
|
82
|
+
if (!models.orchestrator.trim())
|
|
83
|
+
throw unavailable();
|
|
84
|
+
const sourceHome = options.sourceWrenHome();
|
|
85
|
+
const runtime = input.permit.runtime;
|
|
86
|
+
const vendor = attestNativeExecutable("vendor", config.executable);
|
|
87
|
+
const producer = attestNativeExecutable("producer", options.producerBinary);
|
|
88
|
+
const loader = attestNativeExecutable("producer", resolveContextLoaderBinary());
|
|
89
|
+
const node = attestNativeExecutable("node", process.execPath);
|
|
90
|
+
const wren = attestNativeExecutable("wren", runtime.launcher);
|
|
91
|
+
const python = attestNativeExecutable("python", runtime.venv_python);
|
|
92
|
+
const identity = { session_id: input.id, vendor: "codex", auth_identity: config.accountEmail, runtime_generation: String(generation),
|
|
93
|
+
binding: { project_identity: binding.identity, generation: String(binding.generation), revision: binding.revision } };
|
|
94
|
+
let retired = false;
|
|
95
|
+
const checkLive = () => {
|
|
96
|
+
input.signal.throwIfAborted();
|
|
97
|
+
input.assertActive();
|
|
98
|
+
if (retired || !isDeepStrictEqual(options.getBinding(), binding) || !isDeepStrictEqual(options.store.getRuntimeSettings(), settings)
|
|
99
|
+
|| options.store.getNativeRuntimeBinding().generation !== generation || sourceHome !== options.sourceWrenHome() || checkConfiguration() !== loginHome)
|
|
100
|
+
throw unavailable();
|
|
101
|
+
};
|
|
102
|
+
const check = () => {
|
|
103
|
+
checkLive();
|
|
104
|
+
for (const executable of [vendor, producer, loader, node, wren, python])
|
|
105
|
+
assertNativeExecutableIdentity(executable);
|
|
106
|
+
};
|
|
107
|
+
check();
|
|
108
|
+
input.permit.assertActive();
|
|
109
|
+
const root = await realpath(await mkdtemp(path.join(os.tmpdir(), "genbi-codex-session-")));
|
|
110
|
+
let tools;
|
|
111
|
+
const steps = new Set();
|
|
112
|
+
let cleanupFailed = false;
|
|
113
|
+
let cleaned = false;
|
|
114
|
+
const dispose = async () => {
|
|
115
|
+
if (cleaned)
|
|
116
|
+
return;
|
|
117
|
+
if (cleanupFailed || steps.size)
|
|
118
|
+
throw new CodexBackendError("codex_app_server_cleanup_failed");
|
|
119
|
+
retired = true;
|
|
120
|
+
await rm(root, { recursive: true, force: true });
|
|
121
|
+
cleaned = true;
|
|
122
|
+
};
|
|
123
|
+
try {
|
|
124
|
+
check();
|
|
125
|
+
input.permit.assertActive();
|
|
126
|
+
const workspace = path.join(root, "workspace"), home = path.join(root, "home");
|
|
127
|
+
await mkdir(workspace, { mode: 0o700 });
|
|
128
|
+
await mkdir(home, { mode: 0o700 });
|
|
129
|
+
const wrenHome = createEmptyCodexWrenHome(workspace);
|
|
130
|
+
const spec = buildNativeRuntimeSpec({ backend: "codex-app-server", vendor: "codex", executables: [vendor, producer, node, wren, python],
|
|
131
|
+
toolDirectories: await Promise.all([path.dirname(node.executable), "/usr/bin", "/bin", path.dirname(runtime.launcher)].map((directory) => realpath(directory))), workspace, home,
|
|
132
|
+
binding, sessionWrenHome: wrenHome.home, codexHome: loginHome });
|
|
133
|
+
buildCodexSessionPolicy(spec, runtime, wrenHome, true, models.orchestrator);
|
|
134
|
+
const compiled = await compileProfile({ profileSource: options.profileSource, userProject: binding.path, mode: "native", warbleBin: producer.executable });
|
|
135
|
+
check();
|
|
136
|
+
input.permit.assertActive();
|
|
137
|
+
const irDocument = await readFile(compiled.irPath, "utf8");
|
|
138
|
+
tools = await prepareCapturedCodexDirectTools(irDocument, { binding: identity.binding, entry: { kind: "agent", verb: input.entry, prompt: "Use the selected analysis tool." } }, {
|
|
139
|
+
identity, currentIdentity: () => { checkLive(); return identity; }, assertCurrent: check, assertLive: checkLive,
|
|
140
|
+
verifierBinary: producer.executable, producerBinary: producer.executable, contextLoaderBinary: loader.executable,
|
|
141
|
+
wrenBinary: wren.executable, project: binding.path, signal: input.signal, expiresAt: Date.now() + 60 * 60_000,
|
|
142
|
+
wrenEnvironment: { PATH: [path.dirname(runtime.launcher), path.dirname(runtime.venv_python), "/usr/bin", "/bin"].join(path.delimiter), HOME: home,
|
|
143
|
+
WREN_HOME: sourceHome, WREN_PROJECT_HOME: binding.path, PYTHONNOUSERSITE: "1", PYTHONUTF8: "1", PYTHONDONTWRITEBYTECODE: "1" },
|
|
144
|
+
...(input.persistRoot ? { persistRoot: input.persistRoot } : {}),
|
|
145
|
+
vendor: { vendor: "codex", authIdentity: config.accountEmail, accountEmail: config.accountEmail, generation: String(generation),
|
|
146
|
+
models: { cheap: models.cheap, strong: models.strong }, assertCurrent: check, assertLive: checkLive,
|
|
147
|
+
async open(model, signal) {
|
|
148
|
+
check();
|
|
149
|
+
signal.throwIfAborted();
|
|
150
|
+
const permit = backend.prepareLaunch();
|
|
151
|
+
try {
|
|
152
|
+
if (!isDeepStrictEqual(permit.runtime, runtime))
|
|
153
|
+
throw unavailable();
|
|
154
|
+
const resource = backend.openStep(permit, { spec, wrenHome, model, accountEmail: config.accountEmail, signal, assertScopeActive: checkLive });
|
|
155
|
+
const raw = resource.transport;
|
|
156
|
+
let closing;
|
|
157
|
+
const transport = { listen: raw.listen.bind(raw), write: raw.write.bind(raw), close: () => closing ??= (async () => {
|
|
158
|
+
try {
|
|
159
|
+
await raw.close();
|
|
160
|
+
steps.delete(transport);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
cleanupFailed = true;
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
})() };
|
|
167
|
+
steps.add(transport);
|
|
168
|
+
return { ...resource, transport };
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
permit.release();
|
|
172
|
+
}
|
|
173
|
+
} },
|
|
174
|
+
});
|
|
175
|
+
check();
|
|
176
|
+
input.permit.assertActive();
|
|
177
|
+
const preparedTools = tools;
|
|
178
|
+
const scopedTools = { ...tools, async close() {
|
|
179
|
+
const results = await Promise.allSettled([preparedTools.close(), ...[...steps].map((step) => step.close())]);
|
|
180
|
+
if (cleanupFailed || results.some((item) => item.status === "rejected")) {
|
|
181
|
+
cleanupFailed = true;
|
|
182
|
+
throw new CodexBackendError("codex_app_server_cleanup_failed");
|
|
183
|
+
}
|
|
184
|
+
} };
|
|
185
|
+
return { input: { spec, wrenHome, model: models.orchestrator, tools: scopedTools, assertScopeActive: checkLive }, dispose };
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
try {
|
|
189
|
+
await tools?.close();
|
|
190
|
+
await dispose();
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
throw new CodexBackendError("codex_app_server_cleanup_failed");
|
|
194
|
+
}
|
|
195
|
+
throw error;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const terminalCertified = (entry) => {
|
|
199
|
+
try {
|
|
200
|
+
const vendor = attestNativeExecutable("vendor", config.executable);
|
|
201
|
+
return isCodexTerminalCertified(config.source, vendor.digest.slice(7), Object.values(codexModelsForRuntime(options.store.getRuntimeSettings())), entry);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
const native = { backend, terminal: true, terminalCertified, async prepare(input) {
|
|
208
|
+
input.permit.assertActive();
|
|
209
|
+
input.assertActive();
|
|
210
|
+
input.signal.throwIfAborted();
|
|
211
|
+
checkConfiguration();
|
|
212
|
+
checkExecutionScope(input.session.entryVerb ?? "answer_query");
|
|
213
|
+
if (!terminalCertified(input.session.entryVerb ?? "answer_query"))
|
|
214
|
+
throw unavailable();
|
|
215
|
+
const credential = options.artifacts.issue(input.session, input.binding).credential;
|
|
216
|
+
try {
|
|
217
|
+
const prepared = await prepare({ id: input.session.id, binding: input.binding, entry: input.session.entryVerb ?? "answer_query",
|
|
218
|
+
permit: input.permit, signal: input.signal, assertActive: input.assertActive,
|
|
219
|
+
async persistRoot(result, _binding, signal) {
|
|
220
|
+
signal.throwIfAborted();
|
|
221
|
+
input.assertActive();
|
|
222
|
+
if (result.provenance?.verified !== true)
|
|
223
|
+
return;
|
|
224
|
+
if (result.output.kind === "render") {
|
|
225
|
+
options.artifacts.saveGrounded(credential, { version: "1", idempotency_key: randomUUID(), name: "Generated dashboard",
|
|
226
|
+
envelope: { blocks: result.output.blocks, ...(result.output.summary ? { summary: result.output.summary } : {}), verified: true } });
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
const table = z.object({ columns: z.array(z.string()), rows: z.array(z.union([z.array(z.unknown()), z.record(z.string(), z.unknown())])) }).parse(result.output.value);
|
|
230
|
+
const blocks = [{ type: "table", columns: table.columns, rows: table.rows }];
|
|
231
|
+
if (result.provenance.definition)
|
|
232
|
+
blocks.push({ type: "definition", ...z.record(z.string(), z.unknown()).parse(result.provenance.definition) });
|
|
233
|
+
options.artifacts.persistGroundedAnswer(credential, { version: "1", idempotency_key: randomUUID(), envelope: { blocks, verified: true } });
|
|
234
|
+
}
|
|
235
|
+
} });
|
|
236
|
+
return { ...prepared, async dispose() { options.artifacts.revoke(credential); await prepared.dispose(); } };
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
options.artifacts.revoke(credential);
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
242
|
+
} };
|
|
243
|
+
const structured = { backend: { probe, prepareLaunch: backend.prepareLaunch.bind(backend), open: backend.open.bind(backend) }, async prepare({ options: request, scope, permit }) {
|
|
244
|
+
const binding = options.getBinding();
|
|
245
|
+
if (!binding || request.userProject !== binding.path || !scope.signal)
|
|
246
|
+
throw unavailable();
|
|
247
|
+
return prepare({ id: `${scope.sessionId}:${scope.turnId}`, binding, entry: request.agentId ?? "answer_query", permit, signal: scope.signal, assertActive: scope.assertCurrent });
|
|
248
|
+
} };
|
|
249
|
+
return { probe, native, structured, shutdown: () => backend.shutdown() };
|
|
250
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type RouteOptions } from "../harness/index.js";
|
|
2
|
+
import { type CodexAppServerBackend, type CodexLaunchPermit } from "./runtime-host/codex-app-server.js";
|
|
3
|
+
import type { CodexSessionTools } from "./runtime-host/codex-direct-tools.js";
|
|
4
|
+
import { type StructuredAdapter, type StructuredScope } from "./structured-runtime.js";
|
|
5
|
+
type OpenInput = Omit<Parameters<CodexAppServerBackend["open"]>[1], "onEvent" | "tools"> & {
|
|
6
|
+
readonly tools: CodexSessionTools;
|
|
7
|
+
};
|
|
8
|
+
export interface CodexStructuredProvisioner {
|
|
9
|
+
readonly backend: Pick<CodexAppServerBackend, "prepareLaunch" | "open" | "probe">;
|
|
10
|
+
/** Own partial allocations on failure; use only captured scope and server-resolved credentials. */
|
|
11
|
+
prepare(input: {
|
|
12
|
+
readonly options: RouteOptions;
|
|
13
|
+
readonly scope: StructuredScope;
|
|
14
|
+
readonly permit: CodexLaunchPermit;
|
|
15
|
+
}): Promise<{
|
|
16
|
+
readonly input: OpenInput;
|
|
17
|
+
/** Delete materialization only after process and scoped tools have confirmed close. */
|
|
18
|
+
dispose(): Promise<void>;
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
/** Supported direct composition is analysis only; no Setup producer contract is implied. */
|
|
22
|
+
export declare function createCodexStructuredAdapter(provisioner: CodexStructuredProvisioner): StructuredAdapter;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { createAgentEventEmitter, enforceCompliance } from "../harness/index.js";
|
|
2
|
+
import { CodexBackendError } from "./runtime-host/codex-app-server.js";
|
|
3
|
+
import { CodexRpcError } from "./runtime-host/codex-rpc.js";
|
|
4
|
+
import { structuredQueryEnvelope, analyticalAskPrompt } from "./structured-query-evidence.js";
|
|
5
|
+
import { StructuredRuntimeError } from "./structured-runtime.js";
|
|
6
|
+
/** Supported direct composition is analysis only; no Setup producer contract is implied. */
|
|
7
|
+
export function createCodexStructuredAdapter(provisioner) {
|
|
8
|
+
return {
|
|
9
|
+
vendor: "codex", backend: "codex-app-server",
|
|
10
|
+
async probe() { return (await provisioner.backend.probe()).readiness; },
|
|
11
|
+
async ask(options, scope) {
|
|
12
|
+
if (options.authChoice.mode !== "subscription" || options.authChoice.provider !== "codex"
|
|
13
|
+
|| !["answer_query", "generate_dashboard"].includes(options.agentId ?? "answer_query")
|
|
14
|
+
|| options.modelsConfig !== undefined || options.tierBinding !== undefined || options.disclosurePolicy !== undefined || options.zoneRoles !== undefined)
|
|
15
|
+
throw new StructuredRuntimeError("unsupported");
|
|
16
|
+
scope.assertCurrent();
|
|
17
|
+
const { warnings } = enforceCompliance(options.authChoice, { deployment: options.deployment ?? "personal" });
|
|
18
|
+
const permit = provisioner.backend.prepareLaunch();
|
|
19
|
+
let prepared;
|
|
20
|
+
let driver;
|
|
21
|
+
const emitter = createAgentEventEmitter(options.onEvent);
|
|
22
|
+
let closing;
|
|
23
|
+
let unconfirmedOpenCleanup = false;
|
|
24
|
+
const close = () => closing ??= (async () => {
|
|
25
|
+
const results = await Promise.allSettled([driver?.close(), prepared?.input.tools.close()]);
|
|
26
|
+
if (unconfirmedOpenCleanup || results.some((result) => result.status === "rejected"))
|
|
27
|
+
throw new StructuredRuntimeError("cleanup");
|
|
28
|
+
await prepared?.dispose();
|
|
29
|
+
})();
|
|
30
|
+
const abort = () => { void close().catch(() => { }); };
|
|
31
|
+
try {
|
|
32
|
+
permit.assertActive();
|
|
33
|
+
scope.assertCurrent();
|
|
34
|
+
prepared = await provisioner.prepare({ options, scope, permit });
|
|
35
|
+
scope.assertCurrent();
|
|
36
|
+
permit.assertActive();
|
|
37
|
+
prepared.input.tools.assertCurrent();
|
|
38
|
+
const hostGuard = prepared.input.assertScopeActive;
|
|
39
|
+
const hostTools = prepared.input.tools;
|
|
40
|
+
const rootResults = [];
|
|
41
|
+
let toolFailed = false;
|
|
42
|
+
const tools = { ...hostTools, async call(...args) {
|
|
43
|
+
try {
|
|
44
|
+
const value = await hostTools.call(...args);
|
|
45
|
+
scope.assertCurrent();
|
|
46
|
+
hostTools.assertCurrent();
|
|
47
|
+
rootResults.push(structuredClone(value));
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
toolFailed = true;
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
} };
|
|
55
|
+
driver = await provisioner.backend.open(permit, { ...prepared.input, tools, assertScopeActive: () => { scope.assertCurrent(); hostGuard(); }, onEvent(event) {
|
|
56
|
+
scope.assertCurrent();
|
|
57
|
+
if ((event.method === "item/started" || event.method === "item/completed") && event.params.item.type === "dynamicToolCall") {
|
|
58
|
+
const item = event.params.item;
|
|
59
|
+
if (event.method === "item/started")
|
|
60
|
+
emitter.emit({ kind: "tool.call", stepId: "analysis", callId: item.id, tool: "component", depth: 0, status: "running" });
|
|
61
|
+
else
|
|
62
|
+
emitter.emit({ kind: "tool.result", stepId: "analysis", callId: item.id, tool: "component", status: item.success === false || item.status === "failed" ? "error" : "success" });
|
|
63
|
+
}
|
|
64
|
+
} });
|
|
65
|
+
scope.signal?.addEventListener("abort", abort, { once: true });
|
|
66
|
+
scope.assertCurrent();
|
|
67
|
+
emitter.emit({ kind: "run.start", mode: "B", agentId: options.agentId ?? "answer_query" });
|
|
68
|
+
await driver.startThread();
|
|
69
|
+
scope.assertCurrent();
|
|
70
|
+
const result = await driver.runTurn(analyticalAskPrompt(options.question, new Date()), { ...(scope.signal ? { signal: scope.signal } : {}), timeoutMs: options.chatTimeoutMs ?? 300_000 });
|
|
71
|
+
scope.assertCurrent();
|
|
72
|
+
prepared.input.tools.assertCurrent();
|
|
73
|
+
if (result.status !== "completed")
|
|
74
|
+
throw new StructuredRuntimeError("failed");
|
|
75
|
+
const finalText = result.items.filter((item) => item.type === "agentMessage").map((item) => item.text).join("\n");
|
|
76
|
+
if (!finalText.trim() || Buffer.byteLength(finalText) > 1_048_576)
|
|
77
|
+
throw new StructuredRuntimeError("failed");
|
|
78
|
+
const envelope = toolFailed ? undefined : structuredQueryEnvelope(rootResults, finalText);
|
|
79
|
+
await close();
|
|
80
|
+
scope.assertCurrent();
|
|
81
|
+
emitter.emit({ kind: "run.finish", status: "answer" });
|
|
82
|
+
return { backend: "codex-app-server", warnings, finalText, ...(envelope ? { envelope } : {}), dataAttempted: toolFailed || rootResults.length > 0 };
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (error instanceof CodexBackendError && error.code === "codex_app_server_cleanup_failed")
|
|
86
|
+
unconfirmedOpenCleanup = true;
|
|
87
|
+
try {
|
|
88
|
+
await close();
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
throw new StructuredRuntimeError("cleanup");
|
|
92
|
+
}
|
|
93
|
+
throw error instanceof StructuredRuntimeError ? error : new StructuredRuntimeError(scope.signal?.aborted ? "cancelled"
|
|
94
|
+
: error instanceof CodexRpcError && error.reason === "timeout" ? "timeout" : "failed");
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
scope.signal?.removeEventListener("abort", abort);
|
|
98
|
+
permit.release();
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
* so a small line-based parser is enough here; pulling in a full YAML
|
|
36
36
|
* library for one flat file would be overkill. `wren_project.yml` only ever
|
|
37
37
|
* needs two scalar fields read out of it, so it gets the same small-parser
|
|
38
|
-
* treatment (
|
|
38
|
+
* treatment (shares `readYamlScalarField` with `server/adopt.ts`, from `harness/setup/yaml-scalar.ts`).
|
|
39
39
|
*
|
|
40
40
|
* SECURITY: `describeConnection` only ever reads from a fixed ALLOWLIST of
|
|
41
41
|
* non-secret field names (host/port/database/project id/…) when building the
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
import { existsSync, readFileSync } from "node:fs";
|
|
49
49
|
import path from "node:path";
|
|
50
50
|
import { loadProfileStore } from "./wren-profiles.js";
|
|
51
|
+
import { readYamlScalarField } from "../harness/setup/yaml-scalar.js";
|
|
51
52
|
function stripQuotes(value) {
|
|
52
53
|
if (value.length >= 2) {
|
|
53
54
|
const first = value[0];
|
|
@@ -156,19 +157,6 @@ export function loadConnConfig(projectDir) {
|
|
|
156
157
|
}
|
|
157
158
|
return raw.datasource !== undefined ? { datasource: raw.datasource, fields } : { fields };
|
|
158
159
|
}
|
|
159
|
-
/**
|
|
160
|
-
* Matches a `wren_project.yml` top-level `field: value` scalar line — a
|
|
161
|
-
* second small instance of `server/adopt.ts`'s own `readYamlScalarField`
|
|
162
|
-
* rather than an import from it: this module only ever needs the same two
|
|
163
|
-
* fields (`data_source`, `profile`), and adopt.ts's function isn't exported
|
|
164
|
-
* for reuse, so a four-line regex duplicated here is cheaper than adding a
|
|
165
|
-
* cross-module export just for it.
|
|
166
|
-
*/
|
|
167
|
-
function readManifestScalar(content, field) {
|
|
168
|
-
const re = new RegExp(`^${field}:\\s*(.+?)\\s*$`, "m");
|
|
169
|
-
const match = re.exec(content);
|
|
170
|
-
return match ? stripQuotes(match[1].trim()) : undefined;
|
|
171
|
-
}
|
|
172
160
|
/** Reads `<projectDir>/wren_project.yml`'s persistent `data_source:`/`profile:` scalars. Unlike `conn.yml`, this file always exists on a bound wren project. Returns `undefined` only when the manifest itself is missing/unreadable — never throws. */
|
|
173
161
|
export function loadProjectManifest(projectDir) {
|
|
174
162
|
const manifestPath = path.join(projectDir, "wren_project.yml");
|
|
@@ -176,8 +164,8 @@ export function loadProjectManifest(projectDir) {
|
|
|
176
164
|
return undefined;
|
|
177
165
|
try {
|
|
178
166
|
const content = readFileSync(manifestPath, "utf-8");
|
|
179
|
-
const dataSource =
|
|
180
|
-
const profile =
|
|
167
|
+
const dataSource = readYamlScalarField(content, "data_source") || undefined;
|
|
168
|
+
const profile = readYamlScalarField(content, "profile") || undefined;
|
|
181
169
|
return { ...(dataSource !== undefined ? { dataSource } : {}), ...(profile !== undefined ? { profile } : {}) };
|
|
182
170
|
}
|
|
183
171
|
catch {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { NativeSessionService } from "./native-sessions.js";
|
|
2
|
+
interface Socket {
|
|
3
|
+
send(data: string): void;
|
|
4
|
+
close(code?: number, reason?: string): void;
|
|
5
|
+
raw?: unknown;
|
|
6
|
+
}
|
|
7
|
+
/** A socket owns exactly one attachment; a rejected socket cannot detach another. */
|
|
8
|
+
export declare function conversationSocket(service: NativeSessionService | undefined, id: string, capability: string, cursor: string): {
|
|
9
|
+
onOpen(_event: unknown, ws: Socket): void;
|
|
10
|
+
onMessage(event: {
|
|
11
|
+
data: unknown;
|
|
12
|
+
}, ws: Socket): void;
|
|
13
|
+
onClose(): void;
|
|
14
|
+
onError(): void;
|
|
15
|
+
};
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CodexConversationError } from "./runtime-host/codex-conversation.js";
|
|
3
|
+
const command = z.discriminatedUnion("type", [
|
|
4
|
+
z.object({ type: z.literal("prompt"), text: z.string().trim().min(1) }).strict(),
|
|
5
|
+
z.object({ type: z.literal("interrupt") }).strict(),
|
|
6
|
+
]);
|
|
7
|
+
/** A socket owns exactly one attachment; a rejected socket cannot detach another. */
|
|
8
|
+
export function conversationSocket(service, id, capability, cursor) {
|
|
9
|
+
let attachment;
|
|
10
|
+
let disposed = false;
|
|
11
|
+
const detach = () => { disposed = true; attachment?.detach(); attachment = undefined; };
|
|
12
|
+
const send = (ws, value) => {
|
|
13
|
+
if (disposed)
|
|
14
|
+
return;
|
|
15
|
+
const raw = ws.raw;
|
|
16
|
+
const json = JSON.stringify(value);
|
|
17
|
+
if ((raw?.bufferedAmount ?? 0) + Buffer.byteLength(json) > 2_097_152)
|
|
18
|
+
throw new Error("conversation backpressure");
|
|
19
|
+
ws.send(json);
|
|
20
|
+
};
|
|
21
|
+
const reject = (ws) => { detach(); ws.close(1008, "Conversation unavailable"); };
|
|
22
|
+
return {
|
|
23
|
+
onOpen(_event, ws) {
|
|
24
|
+
if (disposed)
|
|
25
|
+
return reject(ws);
|
|
26
|
+
if (!/^(0|[1-9][0-9]{0,15})$/.test(cursor))
|
|
27
|
+
return reject(ws);
|
|
28
|
+
attachment = service?.attachConversation(id, capability, (frame) => send(ws, frame), Number(cursor));
|
|
29
|
+
if (!attachment)
|
|
30
|
+
reject(ws);
|
|
31
|
+
},
|
|
32
|
+
onMessage(event, ws) {
|
|
33
|
+
if (!attachment || disposed)
|
|
34
|
+
return reject(ws);
|
|
35
|
+
try {
|
|
36
|
+
if (typeof event.data !== "string" || Buffer.byteLength(event.data) > 270_000)
|
|
37
|
+
return reject(ws);
|
|
38
|
+
const value = command.parse(JSON.parse(event.data));
|
|
39
|
+
const pending = value.type === "prompt" ? attachment.submit(value.text) : attachment.interrupt();
|
|
40
|
+
void pending.catch((error) => {
|
|
41
|
+
try {
|
|
42
|
+
send(ws, { type: "error", code: error instanceof CodexConversationError && error.code === "busy" ? "busy" : "unavailable" });
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
reject(ws);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (error instanceof CodexConversationError && error.code === "busy") {
|
|
51
|
+
try {
|
|
52
|
+
send(ws, { type: "error", code: "busy" });
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
reject(ws);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else
|
|
59
|
+
reject(ws);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
onClose() { detach(); },
|
|
63
|
+
onError() { detach(); },
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -25,10 +25,12 @@ export type NativeSetupRecoveryPhase = "connect" | "context";
|
|
|
25
25
|
export type NativeSetupRecoveryState = "working" | "needs_input" | "needs_decision" | "retryable_failure" | "reported_complete";
|
|
26
26
|
export type NativeSetupRecoveryCode = "in_progress" | "user_action_required" | "continue_or_stop" | "retryable" | "completion_reported";
|
|
27
27
|
export interface NativeSessionRow {
|
|
28
|
+
readonly transport?: "conversation";
|
|
28
29
|
readonly id: string;
|
|
29
30
|
readonly purpose: NativeSessionPurpose;
|
|
30
31
|
readonly vendor: NativeSessionVendor;
|
|
31
32
|
readonly agent: string;
|
|
33
|
+
readonly entryVerb?: string | null;
|
|
32
34
|
readonly scopeKind: NativeSessionScopeKind;
|
|
33
35
|
readonly scopeId: string;
|
|
34
36
|
readonly projectIdentity: string | null;
|
|
@@ -62,6 +64,33 @@ export interface NativeSessionResumeAction {
|
|
|
62
64
|
readonly scopeFingerprint: string;
|
|
63
65
|
readonly resumedSessionId: string;
|
|
64
66
|
}
|
|
67
|
+
export type WarbleProfileKind = "builtin" | "user";
|
|
68
|
+
export type WarbleProfileRole = "conversation" | "system";
|
|
69
|
+
export type WarbleProfileAdmissionStatus = "admitted" | "unavailable";
|
|
70
|
+
export type WarbleProfileEntryKind = "scope" | "agent";
|
|
71
|
+
/**
|
|
72
|
+
* One registered Warble profile (see server/profile-registry.ts). `componentsJson` is the
|
|
73
|
+
* admission-time component summary, kept so the UI can explain a verdict without recompiling.
|
|
74
|
+
*/
|
|
75
|
+
export interface WarbleProfileRow {
|
|
76
|
+
readonly id: string;
|
|
77
|
+
readonly kind: WarbleProfileKind;
|
|
78
|
+
readonly role: WarbleProfileRole;
|
|
79
|
+
readonly sourceDir: string;
|
|
80
|
+
readonly profileHash: string;
|
|
81
|
+
readonly warbleIdentity: string;
|
|
82
|
+
readonly admissionStatus: WarbleProfileAdmissionStatus;
|
|
83
|
+
readonly admissionReason: string | null;
|
|
84
|
+
readonly entryKind: WarbleProfileEntryKind | null;
|
|
85
|
+
readonly entryVerb: string | null;
|
|
86
|
+
readonly irVersion: string | null;
|
|
87
|
+
readonly componentsJson: string;
|
|
88
|
+
/** The admission rule set the verdict was computed under; a newer set re-runs admission. */
|
|
89
|
+
readonly rulesVersion: number;
|
|
90
|
+
readonly createdAt: string;
|
|
91
|
+
readonly updatedAt: string;
|
|
92
|
+
readonly admittedAt: string | null;
|
|
93
|
+
}
|
|
65
94
|
/**
|
|
66
95
|
* Session-scoped, typed answer material retained for native follow-up tools.
|
|
67
96
|
* `envelopeJson` is limited by the native-artifact contract to table and
|
|
@@ -76,6 +105,8 @@ export interface NativeStructuredAnswerRow {
|
|
|
76
105
|
readonly envelopeJson: string;
|
|
77
106
|
readonly digest: string;
|
|
78
107
|
readonly createdAt: string;
|
|
108
|
+
/** True only when the host persisted a grounded component root; a model-typed answer is never grounded. */
|
|
109
|
+
readonly grounded: boolean;
|
|
79
110
|
}
|
|
80
111
|
/** Retained answers are intentionally bounded without a global cleanup job. */
|
|
81
112
|
export declare const MAX_NATIVE_STRUCTURED_ANSWERS_PER_SESSION = 32;
|
|
@@ -382,6 +413,7 @@ export interface ContextSetupSuccessPersistence {
|
|
|
382
413
|
}
|
|
383
414
|
export declare class Store {
|
|
384
415
|
private readonly db;
|
|
416
|
+
private closed;
|
|
385
417
|
private readonly onContextSuccessWrite;
|
|
386
418
|
private readonly onEnrichmentTransitionWrite;
|
|
387
419
|
private readonly onEnrichmentCreationWrite;
|
|
@@ -416,12 +448,16 @@ export declare class Store {
|
|
|
416
448
|
private migrateSchema;
|
|
417
449
|
private addColumnIfMissing;
|
|
418
450
|
close(): void;
|
|
451
|
+
/** Lets delayed process-local cleanup avoid touching SQLite after shutdown. */
|
|
452
|
+
isClosed(): boolean;
|
|
419
453
|
createSession(title: string): SessionRow;
|
|
420
454
|
createNativeSession(params: {
|
|
455
|
+
transport?: "conversation";
|
|
421
456
|
id: string;
|
|
422
457
|
purpose: NativeSessionPurpose;
|
|
423
458
|
vendor: NativeSessionVendor;
|
|
424
459
|
agent: string;
|
|
460
|
+
entryVerb?: string | undefined;
|
|
425
461
|
scopeKind: NativeSessionScopeKind;
|
|
426
462
|
scopeId: string;
|
|
427
463
|
projectIdentity?: string;
|
|
@@ -452,6 +488,7 @@ export declare class Store {
|
|
|
452
488
|
readonly purpose: NativeSessionPurpose;
|
|
453
489
|
readonly vendor: NativeSessionVendor;
|
|
454
490
|
readonly agent: string;
|
|
491
|
+
readonly entryVerb?: string | undefined;
|
|
455
492
|
readonly scopeKind: NativeSessionScopeKind;
|
|
456
493
|
readonly scopeId: string;
|
|
457
494
|
readonly projectIdentity?: string;
|
|
@@ -473,6 +510,7 @@ export declare class Store {
|
|
|
473
510
|
readonly idempotencyKey: string;
|
|
474
511
|
readonly envelopeJson: string;
|
|
475
512
|
readonly digest: string;
|
|
513
|
+
readonly grounded: boolean;
|
|
476
514
|
}): {
|
|
477
515
|
readonly row: NativeStructuredAnswerRow;
|
|
478
516
|
readonly created: boolean;
|
|
@@ -480,6 +518,13 @@ export declare class Store {
|
|
|
480
518
|
getNativeStructuredAnswer(id: string): NativeStructuredAnswerRow | undefined;
|
|
481
519
|
getNativeStructuredAnswerByIdempotency(nativeSessionId: string, idempotencyKey: string): NativeStructuredAnswerRow | undefined;
|
|
482
520
|
getLatestNativeStructuredAnswer(nativeSessionId: string): NativeStructuredAnswerRow | undefined;
|
|
521
|
+
upsertWarbleProfile(row: WarbleProfileRow): WarbleProfileRow;
|
|
522
|
+
getWarbleProfile(id: string): WarbleProfileRow | undefined;
|
|
523
|
+
/** Built-ins first (in registration order), then user profiles by id. */
|
|
524
|
+
listWarbleProfiles(): WarbleProfileRow[];
|
|
525
|
+
deleteWarbleProfile(id: string): boolean;
|
|
526
|
+
/** How many native sessions ever ran inside this profile; the registry refuses to remove a referenced one. */
|
|
527
|
+
countNativeSessionsByDispatchProfile(profileId: string): number;
|
|
483
528
|
listNativeSessions(): NativeSessionRow[];
|
|
484
529
|
transitionNativeSession(id: string, status: NativeSessionStatus, patch?: {
|
|
485
530
|
exitCode?: number | null;
|
|
@@ -631,6 +676,7 @@ export declare class Store {
|
|
|
631
676
|
agent: string;
|
|
632
677
|
digest: string;
|
|
633
678
|
idempotencyKey: string;
|
|
679
|
+
verified: boolean;
|
|
634
680
|
sourceAnswerId?: string;
|
|
635
681
|
}): {
|
|
636
682
|
readonly row: ArtifactRow;
|