@wrenai/genbi 0.0.4 → 0.0.5

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.
Files changed (230) hide show
  1. package/README.md +64 -2
  2. package/dist/assets/{echarts-LTFC-ysd.js → echarts-DYM4hjvk.js} +2 -2
  3. package/dist/assets/index-A_Wrq7Ey.css +1 -0
  4. package/dist/assets/{index-Bo--QMUN.js → index-DsH129tV.js} +18 -17
  5. package/dist/index.html +2 -2
  6. package/dist-server/harness/bundle/schema.d.ts +38 -0
  7. package/dist-server/harness/bundle/schema.js +18 -10
  8. package/dist-server/harness/bundle/version.js +1 -1
  9. package/dist-server/harness/cli-args.d.ts +10 -2
  10. package/dist-server/harness/cli-args.js +24 -8
  11. package/dist-server/harness/cli.js +75 -9
  12. package/dist-server/harness/compile/cache.js +4 -4
  13. package/dist-server/harness/compile/compose-profile.d.ts +51 -14
  14. package/dist-server/harness/compile/compose-profile.js +85 -19
  15. package/dist-server/harness/compile/context-loader.d.ts +56 -0
  16. package/dist-server/harness/compile/context-loader.js +237 -0
  17. package/dist-server/harness/compile/errors.d.ts +19 -0
  18. package/dist-server/harness/compile/errors.js +35 -0
  19. package/dist-server/harness/compile/index.d.ts +4 -3
  20. package/dist-server/harness/compile/index.js +4 -3
  21. package/dist-server/harness/compile/pipeline.d.ts +15 -7
  22. package/dist-server/harness/compile/pipeline.js +62 -14
  23. package/dist-server/harness/compile/resolve-binary.d.ts +2 -2
  24. package/dist-server/harness/compile/resolve-binary.js +3 -3
  25. package/dist-server/harness/compile/types.d.ts +29 -0
  26. package/dist-server/harness/compile/warble-identity.d.ts +11 -0
  27. package/dist-server/harness/compile/warble-identity.js +13 -0
  28. package/dist-server/harness/components/ai-step.d.ts +4 -0
  29. package/dist-server/harness/components/ai-step.js +40 -0
  30. package/dist-server/harness/components/broker.d.ts +60 -0
  31. package/dist-server/harness/components/broker.js +117 -0
  32. package/dist-server/harness/components/capability-card.d.ts +98 -0
  33. package/dist-server/harness/components/capability-card.js +169 -0
  34. package/dist-server/harness/components/context.d.ts +2 -0
  35. package/dist-server/harness/components/context.js +30 -0
  36. package/dist-server/harness/components/display.d.ts +6 -0
  37. package/dist-server/harness/components/display.js +29 -0
  38. package/dist-server/harness/components/egress-judge.d.ts +12 -0
  39. package/dist-server/harness/components/egress-judge.js +27 -0
  40. package/dist-server/harness/components/egress.d.ts +142 -0
  41. package/dist-server/harness/components/egress.js +469 -0
  42. package/dist-server/harness/components/in-process.d.ts +7 -0
  43. package/dist-server/harness/components/in-process.js +245 -0
  44. package/dist-server/harness/components/normalize.d.ts +35 -0
  45. package/dist-server/harness/components/normalize.js +245 -0
  46. package/dist-server/harness/components/plan.d.ts +31 -0
  47. package/dist-server/harness/components/plan.js +184 -0
  48. package/dist-server/harness/components/report.d.ts +207 -0
  49. package/dist-server/harness/components/report.js +309 -0
  50. package/dist-server/harness/components/runner.d.ts +193 -0
  51. package/dist-server/harness/components/runner.js +492 -0
  52. package/dist-server/harness/components/semantic-guards.d.ts +20 -0
  53. package/dist-server/harness/components/semantic-guards.js +42 -0
  54. package/dist-server/harness/components/terminal-json.d.ts +18 -0
  55. package/dist-server/harness/components/terminal-json.js +82 -0
  56. package/dist-server/harness/components/usage.d.ts +14 -0
  57. package/dist-server/harness/components/usage.js +19 -0
  58. package/dist-server/harness/components/wren-access.d.ts +29 -0
  59. package/dist-server/harness/components/wren-access.js +233 -0
  60. package/dist-server/harness/components/zone-dry-run.d.ts +43 -0
  61. package/dist-server/harness/components/zone-dry-run.js +107 -0
  62. package/dist-server/harness/components/zone-gate.d.ts +76 -0
  63. package/dist-server/harness/components/zone-gate.js +144 -0
  64. package/dist-server/harness/events/index.d.ts +1 -1
  65. package/dist-server/harness/events/types.d.ts +52 -0
  66. package/dist-server/harness/index.d.ts +9 -2
  67. package/dist-server/harness/index.js +5 -1
  68. package/dist-server/harness/loop/executor.d.ts +1 -0
  69. package/dist-server/harness/loop/executor.js +37 -15
  70. package/dist-server/harness/npm-package-resolve.d.ts +2 -0
  71. package/dist-server/harness/npm-package-resolve.js +16 -4
  72. package/dist-server/harness/providers/adapters/openai-compatible.d.ts +13 -0
  73. package/dist-server/harness/providers/adapters/openai-compatible.js +17 -0
  74. package/dist-server/harness/providers/adapters/openai.d.ts +7 -0
  75. package/dist-server/harness/providers/adapters/openai.js +6 -0
  76. package/dist-server/harness/providers/adapters/pi-ai.d.ts +48 -0
  77. package/dist-server/harness/providers/adapters/pi-ai.js +518 -0
  78. package/dist-server/harness/providers/binding.d.ts +45 -4
  79. package/dist-server/harness/providers/binding.js +44 -8
  80. package/dist-server/harness/providers/index.d.ts +9 -3
  81. package/dist-server/harness/providers/index.js +10 -3
  82. package/dist-server/harness/providers/zone.d.ts +96 -0
  83. package/dist-server/harness/providers/zone.js +112 -0
  84. package/dist-server/harness/render/answering-query.d.ts +29 -0
  85. package/dist-server/harness/render/answering-query.js +62 -0
  86. package/dist-server/harness/render/envelope.d.ts +6 -0
  87. package/dist-server/harness/render/envelope.js +10 -3
  88. package/dist-server/harness/route/adapter-spec.d.ts +8 -9
  89. package/dist-server/harness/route/adapter-spec.js +13 -14
  90. package/dist-server/harness/route/codex-ask-events.js +2 -1
  91. package/dist-server/harness/route/codex-ask.d.ts +4 -0
  92. package/dist-server/harness/route/codex-ask.js +69 -30
  93. package/dist-server/harness/route/codex-host-query.d.ts +52 -0
  94. package/dist-server/harness/route/codex-host-query.js +191 -0
  95. package/dist-server/harness/route/codex-local-manifest.d.ts +9 -1
  96. package/dist-server/harness/route/codex-local-manifest.js +96 -15
  97. package/dist-server/harness/route/codex-wren-proxy.d.ts +33 -0
  98. package/dist-server/harness/route/codex-wren-proxy.js +227 -0
  99. package/dist-server/harness/route/describe.js +45 -6
  100. package/dist-server/harness/route/in-process.d.ts +22 -1
  101. package/dist-server/harness/route/in-process.js +54 -4
  102. package/dist-server/harness/route/route.js +5 -2
  103. package/dist-server/harness/route/types.d.ts +30 -1
  104. package/dist-server/harness/session/run.js +30 -10
  105. package/dist-server/harness/setup/runner.d.ts +2 -0
  106. package/dist-server/harness/setup/runner.js +38 -17
  107. package/dist-server/harness/setup/yaml-scalar.d.ts +23 -0
  108. package/dist-server/harness/setup/yaml-scalar.js +62 -0
  109. package/dist-server/server/adopt.js +1 -17
  110. package/dist-server/server/app.d.ts +1 -0
  111. package/dist-server/server/app.js +163 -14
  112. package/dist-server/server/auth-choice.d.ts +13 -1
  113. package/dist-server/server/auth-choice.js +66 -1
  114. package/dist-server/server/bin.js +177 -25
  115. package/dist-server/server/codex-local-grounding.d.ts +18 -0
  116. package/dist-server/server/codex-local-grounding.js +92 -0
  117. package/dist-server/server/codex-native-session.d.ts +25 -0
  118. package/dist-server/server/codex-native-session.js +1 -0
  119. package/dist-server/server/codex-runtime-composition.d.ts +34 -0
  120. package/dist-server/server/codex-runtime-composition.js +250 -0
  121. package/dist-server/server/codex-structured-ask.d.ts +23 -0
  122. package/dist-server/server/codex-structured-ask.js +102 -0
  123. package/dist-server/server/conn-config.js +4 -16
  124. package/dist-server/server/conversation-socket.d.ts +16 -0
  125. package/dist-server/server/conversation-socket.js +65 -0
  126. package/dist-server/server/db.d.ts +46 -0
  127. package/dist-server/server/db.js +88 -9
  128. package/dist-server/server/env-detect.d.ts +6 -0
  129. package/dist-server/server/env-detect.js +7 -0
  130. package/dist-server/server/fold.d.ts +22 -4
  131. package/dist-server/server/fold.js +37 -5
  132. package/dist-server/server/harness.d.ts +2 -2
  133. package/dist-server/server/harness.js +33 -7
  134. package/dist-server/server/interactive-terminal.d.ts +10 -6
  135. package/dist-server/server/interactive-terminal.js +33 -8
  136. package/dist-server/server/managed-wren-runtime.d.ts +116 -0
  137. package/dist-server/server/managed-wren-runtime.js +670 -0
  138. package/dist-server/server/native-artifacts.d.ts +23 -7
  139. package/dist-server/server/native-artifacts.js +43 -12
  140. package/dist-server/server/native-component-context.d.ts +19 -0
  141. package/dist-server/server/native-component-context.js +76 -0
  142. package/dist-server/server/native-component-preparation.d.ts +20 -0
  143. package/dist-server/server/native-component-preparation.js +129 -0
  144. package/dist-server/server/native-component-runtime.d.ts +36 -0
  145. package/dist-server/server/native-component-runtime.js +92 -0
  146. package/dist-server/server/native-components.d.ts +84 -0
  147. package/dist-server/server/native-components.js +160 -0
  148. package/dist-server/server/native-dispatch-process.d.ts +8 -0
  149. package/dist-server/server/native-dispatch-process.js +65 -0
  150. package/dist-server/server/native-runtime-spec.d.ts +89 -0
  151. package/dist-server/server/native-runtime-spec.js +169 -0
  152. package/dist-server/server/native-sessions.d.ts +172 -19
  153. package/dist-server/server/native-sessions.js +839 -244
  154. package/dist-server/server/native-shutdown.d.ts +6 -0
  155. package/dist-server/server/native-shutdown.js +28 -0
  156. package/dist-server/server/native-wren-home.d.ts +18 -0
  157. package/dist-server/server/native-wren-home.js +262 -0
  158. package/dist-server/server/node-pty-host.d.ts +2 -1
  159. package/dist-server/server/node-pty-host.js +3 -2
  160. package/dist-server/server/profile-registry.d.ts +139 -0
  161. package/dist-server/server/profile-registry.js +620 -0
  162. package/dist-server/server/runtime-binding.d.ts +4 -1
  163. package/dist-server/server/runtime-binding.js +50 -2
  164. package/dist-server/server/runtime-host/claude-component-step.d.ts +25 -0
  165. package/dist-server/server/runtime-host/claude-component-step.js +186 -0
  166. package/dist-server/server/runtime-host/codex-app-server.d.ts +75 -0
  167. package/dist-server/server/runtime-host/codex-app-server.js +239 -0
  168. package/dist-server/server/runtime-host/codex-compatibility.d.ts +110 -0
  169. package/dist-server/server/runtime-host/codex-compatibility.js +162 -0
  170. package/dist-server/server/runtime-host/codex-component-step.d.ts +19 -0
  171. package/dist-server/server/runtime-host/codex-component-step.js +308 -0
  172. package/dist-server/server/runtime-host/codex-conversation.d.ts +109 -0
  173. package/dist-server/server/runtime-host/codex-conversation.js +295 -0
  174. package/dist-server/server/runtime-host/codex-direct-tools.d.ts +23 -0
  175. package/dist-server/server/runtime-host/codex-direct-tools.js +59 -0
  176. package/dist-server/server/runtime-host/codex-events.d.ts +647 -0
  177. package/dist-server/server/runtime-host/codex-events.js +66 -0
  178. package/dist-server/server/runtime-host/codex-policy.d.ts +16 -0
  179. package/dist-server/server/runtime-host/codex-policy.js +151 -0
  180. package/dist-server/server/runtime-host/codex-process.d.ts +8 -0
  181. package/dist-server/server/runtime-host/codex-process.js +96 -0
  182. package/dist-server/server/runtime-host/codex-rpc.d.ts +47 -0
  183. package/dist-server/server/runtime-host/codex-rpc.js +182 -0
  184. package/dist-server/server/runtime-host/codex-session.d.ts +74 -0
  185. package/dist-server/server/runtime-host/codex-session.js +492 -0
  186. package/dist-server/server/runtime-host/codex-terminal-protocol.d.ts +35 -0
  187. package/dist-server/server/runtime-host/codex-terminal-protocol.js +243 -0
  188. package/dist-server/server/runtime-host/codex-terminal.d.ts +16 -0
  189. package/dist-server/server/runtime-host/codex-terminal.js +120 -0
  190. package/dist-server/server/runtime-host/index.d.ts +5 -0
  191. package/dist-server/server/runtime-host/index.js +3 -0
  192. package/dist-server/server/runtime-host/local.d.ts +29 -0
  193. package/dist-server/server/runtime-host/local.js +90 -0
  194. package/dist-server/server/runtime-host/policy.d.ts +8 -0
  195. package/dist-server/server/runtime-host/policy.js +78 -0
  196. package/dist-server/server/runtime-host/types.d.ts +52 -0
  197. package/dist-server/server/runtime-host/types.js +62 -0
  198. package/dist-server/server/structured-query-evidence.d.ts +7 -0
  199. package/dist-server/server/structured-query-evidence.js +47 -0
  200. package/dist-server/server/structured-runtime.d.ts +52 -0
  201. package/dist-server/server/structured-runtime.js +130 -0
  202. package/dist-server/server/structured-scope.d.ts +4 -0
  203. package/dist-server/server/structured-scope.js +12 -0
  204. package/dist-server/server/turn.d.ts +6 -1
  205. package/dist-server/server/turn.js +82 -25
  206. package/dist-server/server/wire-types.d.ts +67 -3
  207. package/dist-server/server/wren-profiles.js +1 -1
  208. package/managed-wren/README.md +60 -0
  209. package/managed-wren/dependency-wheels.json +282 -0
  210. package/managed-wren/manifest.json +373 -0
  211. package/managed-wren/release-inputs.json +45 -0
  212. package/managed-wren/runtime-tree.cjs +115 -0
  213. package/managed-wren/source-inputs.json +40 -0
  214. package/package.json +15 -6
  215. package/profiles/genbi-default/context/binding.yml +17 -7
  216. package/profiles/genbi-default/context/context.json +146 -0
  217. package/profiles/genbi-default/ir.golden.json +39 -43
  218. package/profiles/genbi-default/profile.yml +31 -0
  219. package/profiles/genbi-enrich-context/context/binding.yml +14 -3
  220. package/profiles/genbi-enrich-context/context/context.json +146 -0
  221. package/profiles/genbi-enrich-context/ir.golden.json +4 -5
  222. package/profiles/genbi-monitor/context/binding.yml +13 -5
  223. package/profiles/genbi-monitor/context/context.json +146 -0
  224. package/profiles/genbi-monitor/ir.golden.json +13 -7
  225. package/profiles/genbi-report/context/binding.yml +19 -0
  226. package/profiles/genbi-report/context/context.json +223 -0
  227. package/profiles/genbi-report/ir.golden.json +328 -0
  228. package/profiles/genbi-report/profile.yml +38 -0
  229. package/profiles/genbi-setup/ir.golden.json +3 -1
  230. 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 (mirrors `server/adopt.ts`'s own `readYamlScalarField`).
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 = readManifestScalar(content, "data_source");
180
- const profile = readManifestScalar(content, "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;