@wrenai/genbi 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +141 -0
  3. package/bin/genbi.mjs +31 -0
  4. package/dist/assets/echarts-LTFC-ysd.js +40 -0
  5. package/dist/assets/index-Bo--QMUN.js +441 -0
  6. package/dist/assets/index-Xs4q7pNo.css +1 -0
  7. package/dist/index.html +14 -0
  8. package/dist/wrenai_logo.png +0 -0
  9. package/dist/wrenai_logo_white.png +0 -0
  10. package/dist-server/harness/auth/detect.d.ts +18 -0
  11. package/dist-server/harness/auth/detect.js +37 -0
  12. package/dist-server/harness/auth/index.d.ts +4 -0
  13. package/dist-server/harness/auth/index.js +2 -0
  14. package/dist-server/harness/auth/probe.d.ts +18 -0
  15. package/dist-server/harness/auth/probe.js +52 -0
  16. package/dist-server/harness/auth/types.d.ts +42 -0
  17. package/dist-server/harness/auth/types.js +9 -0
  18. package/dist-server/harness/bundle/loader.d.ts +32 -0
  19. package/dist-server/harness/bundle/loader.js +43 -0
  20. package/dist-server/harness/bundle/schema.d.ts +199 -0
  21. package/dist-server/harness/bundle/schema.js +127 -0
  22. package/dist-server/harness/bundle/version.d.ts +10 -0
  23. package/dist-server/harness/bundle/version.js +43 -0
  24. package/dist-server/harness/capability/gate.d.ts +6 -0
  25. package/dist-server/harness/capability/gate.js +29 -0
  26. package/dist-server/harness/capability/registry.d.ts +6 -0
  27. package/dist-server/harness/capability/registry.js +17 -0
  28. package/dist-server/harness/cli-args.d.ts +123 -0
  29. package/dist-server/harness/cli-args.js +247 -0
  30. package/dist-server/harness/cli.d.ts +2 -0
  31. package/dist-server/harness/cli.js +151 -0
  32. package/dist-server/harness/compile/cache.d.ts +23 -0
  33. package/dist-server/harness/compile/cache.js +109 -0
  34. package/dist-server/harness/compile/compose-profile.d.ts +34 -0
  35. package/dist-server/harness/compile/compose-profile.js +95 -0
  36. package/dist-server/harness/compile/errors.d.ts +22 -0
  37. package/dist-server/harness/compile/errors.js +41 -0
  38. package/dist-server/harness/compile/fingerprint.d.ts +22 -0
  39. package/dist-server/harness/compile/fingerprint.js +84 -0
  40. package/dist-server/harness/compile/index.d.ts +8 -0
  41. package/dist-server/harness/compile/index.js +7 -0
  42. package/dist-server/harness/compile/pipeline.d.ts +66 -0
  43. package/dist-server/harness/compile/pipeline.js +176 -0
  44. package/dist-server/harness/compile/resolve-binary.d.ts +55 -0
  45. package/dist-server/harness/compile/resolve-binary.js +133 -0
  46. package/dist-server/harness/compile/types.d.ts +107 -0
  47. package/dist-server/harness/compile/types.js +1 -0
  48. package/dist-server/harness/compile/warble-identity.d.ts +12 -0
  49. package/dist-server/harness/compile/warble-identity.js +33 -0
  50. package/dist-server/harness/compliance/gate.d.ts +35 -0
  51. package/dist-server/harness/compliance/gate.js +48 -0
  52. package/dist-server/harness/compliance/index.d.ts +2 -0
  53. package/dist-server/harness/compliance/index.js +1 -0
  54. package/dist-server/harness/compliance/types.d.ts +16 -0
  55. package/dist-server/harness/compliance/types.js +1 -0
  56. package/dist-server/harness/events/emitter.d.ts +34 -0
  57. package/dist-server/harness/events/emitter.js +25 -0
  58. package/dist-server/harness/events/index.d.ts +4 -0
  59. package/dist-server/harness/events/index.js +2 -0
  60. package/dist-server/harness/events/sse.d.ts +20 -0
  61. package/dist-server/harness/events/sse.js +48 -0
  62. package/dist-server/harness/events/types.d.ts +131 -0
  63. package/dist-server/harness/events/types.js +1 -0
  64. package/dist-server/harness/exec/errors.d.ts +16 -0
  65. package/dist-server/harness/exec/errors.js +29 -0
  66. package/dist-server/harness/exec/index.d.ts +5 -0
  67. package/dist-server/harness/exec/index.js +2 -0
  68. package/dist-server/harness/exec/local.d.ts +32 -0
  69. package/dist-server/harness/exec/local.js +134 -0
  70. package/dist-server/harness/exec/policy.d.ts +12 -0
  71. package/dist-server/harness/exec/policy.js +1 -0
  72. package/dist-server/harness/exec/types.d.ts +63 -0
  73. package/dist-server/harness/exec/types.js +1 -0
  74. package/dist-server/harness/guardrails/index.d.ts +2 -0
  75. package/dist-server/harness/guardrails/index.js +1 -0
  76. package/dist-server/harness/guardrails/policy.d.ts +45 -0
  77. package/dist-server/harness/guardrails/policy.js +57 -0
  78. package/dist-server/harness/index.d.ts +37 -0
  79. package/dist-server/harness/index.js +19 -0
  80. package/dist-server/harness/loop/errors.d.ts +53 -0
  81. package/dist-server/harness/loop/errors.js +72 -0
  82. package/dist-server/harness/loop/executor.d.ts +123 -0
  83. package/dist-server/harness/loop/executor.js +380 -0
  84. package/dist-server/harness/loop/guard.d.ts +16 -0
  85. package/dist-server/harness/loop/guard.js +1 -0
  86. package/dist-server/harness/loop/index.d.ts +5 -0
  87. package/dist-server/harness/loop/index.js +3 -0
  88. package/dist-server/harness/native-producer/index.d.ts +109 -0
  89. package/dist-server/harness/native-producer/index.js +302 -0
  90. package/dist-server/harness/npm-package-resolve.d.ts +28 -0
  91. package/dist-server/harness/npm-package-resolve.js +47 -0
  92. package/dist-server/harness/providers/adapters/anthropic.d.ts +7 -0
  93. package/dist-server/harness/providers/adapters/anthropic.js +6 -0
  94. package/dist-server/harness/providers/adapters/mock.d.ts +4 -0
  95. package/dist-server/harness/providers/adapters/mock.js +5 -0
  96. package/dist-server/harness/providers/adapters/openai-compatible.d.ts +10 -0
  97. package/dist-server/harness/providers/adapters/openai-compatible.js +10 -0
  98. package/dist-server/harness/providers/binding.d.ts +23 -0
  99. package/dist-server/harness/providers/binding.js +13 -0
  100. package/dist-server/harness/providers/errors.d.ts +6 -0
  101. package/dist-server/harness/providers/errors.js +12 -0
  102. package/dist-server/harness/providers/index.d.ts +18 -0
  103. package/dist-server/harness/providers/index.js +22 -0
  104. package/dist-server/harness/providers/registry.d.ts +16 -0
  105. package/dist-server/harness/providers/registry.js +24 -0
  106. package/dist-server/harness/render/envelope.d.ts +145 -0
  107. package/dist-server/harness/render/envelope.js +428 -0
  108. package/dist-server/harness/render/errors.d.ts +33 -0
  109. package/dist-server/harness/render/errors.js +46 -0
  110. package/dist-server/harness/render/index.d.ts +5 -0
  111. package/dist-server/harness/render/index.js +3 -0
  112. package/dist-server/harness/render/validate.d.ts +13 -0
  113. package/dist-server/harness/render/validate.js +88 -0
  114. package/dist-server/harness/route/adapter-spec.d.ts +40 -0
  115. package/dist-server/harness/route/adapter-spec.js +61 -0
  116. package/dist-server/harness/route/agent-sdk-cli.d.ts +30 -0
  117. package/dist-server/harness/route/agent-sdk-cli.js +86 -0
  118. package/dist-server/harness/route/agent-sdk-manifest.d.ts +31 -0
  119. package/dist-server/harness/route/agent-sdk-manifest.js +56 -0
  120. package/dist-server/harness/route/artifact-content.d.ts +53 -0
  121. package/dist-server/harness/route/artifact-content.js +83 -0
  122. package/dist-server/harness/route/chat-event-mapper.d.ts +95 -0
  123. package/dist-server/harness/route/chat-event-mapper.js +164 -0
  124. package/dist-server/harness/route/codex-ask-events.d.ts +25 -0
  125. package/dist-server/harness/route/codex-ask-events.js +395 -0
  126. package/dist-server/harness/route/codex-ask.d.ts +15 -0
  127. package/dist-server/harness/route/codex-ask.js +242 -0
  128. package/dist-server/harness/route/codex-local-cli.d.ts +20 -0
  129. package/dist-server/harness/route/codex-local-cli.js +78 -0
  130. package/dist-server/harness/route/codex-local-manifest.d.ts +22 -0
  131. package/dist-server/harness/route/codex-local-manifest.js +180 -0
  132. package/dist-server/harness/route/describe.d.ts +54 -0
  133. package/dist-server/harness/route/describe.js +84 -0
  134. package/dist-server/harness/route/dispatched.d.ts +138 -0
  135. package/dist-server/harness/route/dispatched.js +339 -0
  136. package/dist-server/harness/route/in-process.d.ts +43 -0
  137. package/dist-server/harness/route/in-process.js +106 -0
  138. package/dist-server/harness/route/index.d.ts +19 -0
  139. package/dist-server/harness/route/index.js +12 -0
  140. package/dist-server/harness/route/profile-source.d.ts +37 -0
  141. package/dist-server/harness/route/profile-source.js +76 -0
  142. package/dist-server/harness/route/route.d.ts +33 -0
  143. package/dist-server/harness/route/route.js +114 -0
  144. package/dist-server/harness/route/tier-binding.d.ts +36 -0
  145. package/dist-server/harness/route/tier-binding.js +63 -0
  146. package/dist-server/harness/route/types.d.ts +286 -0
  147. package/dist-server/harness/route/types.js +1 -0
  148. package/dist-server/harness/session/errors.d.ts +4 -0
  149. package/dist-server/harness/session/errors.js +7 -0
  150. package/dist-server/harness/session/gate.d.ts +11 -0
  151. package/dist-server/harness/session/gate.js +13 -0
  152. package/dist-server/harness/session/index.d.ts +5 -0
  153. package/dist-server/harness/session/index.js +3 -0
  154. package/dist-server/harness/session/run.d.ts +60 -0
  155. package/dist-server/harness/session/run.js +333 -0
  156. package/dist-server/harness/session/types.d.ts +29 -0
  157. package/dist-server/harness/session/types.js +1 -0
  158. package/dist-server/harness/setup/codex-events.d.ts +12 -0
  159. package/dist-server/harness/setup/codex-events.js +108 -0
  160. package/dist-server/harness/setup/runner.d.ts +497 -0
  161. package/dist-server/harness/setup/runner.js +1314 -0
  162. package/dist-server/harness/tools/errors.d.ts +107 -0
  163. package/dist-server/harness/tools/errors.js +141 -0
  164. package/dist-server/harness/tools/index.d.ts +13 -0
  165. package/dist-server/harness/tools/index.js +8 -0
  166. package/dist-server/harness/tools/mcp.d.ts +26 -0
  167. package/dist-server/harness/tools/mcp.js +15 -0
  168. package/dist-server/harness/tools/native.d.ts +179 -0
  169. package/dist-server/harness/tools/native.js +322 -0
  170. package/dist-server/harness/tools/parse.d.ts +14 -0
  171. package/dist-server/harness/tools/parse.js +18 -0
  172. package/dist-server/harness/tools/resolve-wren-binary.d.ts +12 -0
  173. package/dist-server/harness/tools/resolve-wren-binary.js +21 -0
  174. package/dist-server/harness/tools/resolve.d.ts +51 -0
  175. package/dist-server/harness/tools/resolve.js +79 -0
  176. package/dist-server/harness/tools/setup-native.d.ts +84 -0
  177. package/dist-server/harness/tools/setup-native.js +353 -0
  178. package/dist-server/harness/tools/wiring.d.ts +10 -0
  179. package/dist-server/harness/tools/wiring.js +16 -0
  180. package/dist-server/providers/setup.provider.yaml +31 -0
  181. package/dist-server/providers/wren.provider.yaml +33 -0
  182. package/dist-server/server/adopt.d.ts +87 -0
  183. package/dist-server/server/adopt.js +263 -0
  184. package/dist-server/server/app.d.ts +6 -0
  185. package/dist-server/server/app.js +2521 -0
  186. package/dist-server/server/auth-choice.d.ts +16 -0
  187. package/dist-server/server/auth-choice.js +36 -0
  188. package/dist-server/server/bin.d.ts +2 -0
  189. package/dist-server/server/bin.js +601 -0
  190. package/dist-server/server/bootstrap-project-binding.d.ts +31 -0
  191. package/dist-server/server/bootstrap-project-binding.js +71 -0
  192. package/dist-server/server/clarify.d.ts +10 -0
  193. package/dist-server/server/clarify.js +17 -0
  194. package/dist-server/server/codex-setup-mcp.d.ts +2 -0
  195. package/dist-server/server/codex-setup-mcp.js +147 -0
  196. package/dist-server/server/compose.d.ts +89 -0
  197. package/dist-server/server/compose.js +271 -0
  198. package/dist-server/server/conn-config.d.ts +30 -0
  199. package/dist-server/server/conn-config.js +253 -0
  200. package/dist-server/server/context-files.d.ts +12 -0
  201. package/dist-server/server/context-files.js +117 -0
  202. package/dist-server/server/context-map.d.ts +30 -0
  203. package/dist-server/server/context-map.js +95 -0
  204. package/dist-server/server/context-source.d.ts +68 -0
  205. package/dist-server/server/context-source.js +85 -0
  206. package/dist-server/server/db.d.ts +862 -0
  207. package/dist-server/server/db.js +1839 -0
  208. package/dist-server/server/enrichment-runner.d.ts +184 -0
  209. package/dist-server/server/enrichment-runner.js +213 -0
  210. package/dist-server/server/enrichment-verify.d.ts +73 -0
  211. package/dist-server/server/enrichment-verify.js +290 -0
  212. package/dist-server/server/enrichment.d.ts +232 -0
  213. package/dist-server/server/enrichment.js +199 -0
  214. package/dist-server/server/env-detect.d.ts +8 -0
  215. package/dist-server/server/env-detect.js +17 -0
  216. package/dist-server/server/env-field-hints.d.ts +46 -0
  217. package/dist-server/server/env-field-hints.js +48 -0
  218. package/dist-server/server/fold.d.ts +133 -0
  219. package/dist-server/server/fold.js +407 -0
  220. package/dist-server/server/harness-profile-sources.d.ts +3 -0
  221. package/dist-server/server/harness-profile-sources.js +24 -0
  222. package/dist-server/server/harness.d.ts +19 -0
  223. package/dist-server/server/harness.js +439 -0
  224. package/dist-server/server/impact.d.ts +18 -0
  225. package/dist-server/server/impact.js +85 -0
  226. package/dist-server/server/interactive-terminal.d.ts +175 -0
  227. package/dist-server/server/interactive-terminal.js +336 -0
  228. package/dist-server/server/native-artifacts.d.ts +1004 -0
  229. package/dist-server/server/native-artifacts.js +564 -0
  230. package/dist-server/server/native-dispatch-registry.d.ts +42 -0
  231. package/dist-server/server/native-dispatch-registry.js +45 -0
  232. package/dist-server/server/native-producer-fence.d.ts +14 -0
  233. package/dist-server/server/native-producer-fence.js +48 -0
  234. package/dist-server/server/native-session-resume.d.ts +6 -0
  235. package/dist-server/server/native-session-resume.js +103 -0
  236. package/dist-server/server/native-session-workspace.d.ts +40 -0
  237. package/dist-server/server/native-session-workspace.js +175 -0
  238. package/dist-server/server/native-sessions.d.ts +374 -0
  239. package/dist-server/server/native-sessions.js +1517 -0
  240. package/dist-server/server/native-wren-runtime.d.ts +20 -0
  241. package/dist-server/server/native-wren-runtime.js +259 -0
  242. package/dist-server/server/node-pty-host.d.ts +31 -0
  243. package/dist-server/server/node-pty-host.js +100 -0
  244. package/dist-server/server/route-intent.d.ts +40 -0
  245. package/dist-server/server/route-intent.js +23 -0
  246. package/dist-server/server/runtime-binding.d.ts +52 -0
  247. package/dist-server/server/runtime-binding.js +258 -0
  248. package/dist-server/server/source-catalog.d.ts +84 -0
  249. package/dist-server/server/source-catalog.js +221 -0
  250. package/dist-server/server/source-driver.d.ts +35 -0
  251. package/dist-server/server/source-driver.js +124 -0
  252. package/dist-server/server/spa.d.ts +2 -0
  253. package/dist-server/server/spa.js +51 -0
  254. package/dist-server/server/subscription-model-catalog.d.ts +27 -0
  255. package/dist-server/server/subscription-model-catalog.js +203 -0
  256. package/dist-server/server/turn.d.ts +249 -0
  257. package/dist-server/server/turn.js +1074 -0
  258. package/dist-server/server/wire-types.d.ts +799 -0
  259. package/dist-server/server/wire-types.js +1 -0
  260. package/dist-server/server/wren-home.d.ts +19 -0
  261. package/dist-server/server/wren-home.js +33 -0
  262. package/dist-server/server/wren-profiles.d.ts +43 -0
  263. package/dist-server/server/wren-profiles.js +123 -0
  264. package/package.json +93 -0
  265. package/profiles/genbi-default/context/binding.yml +9 -0
  266. package/profiles/genbi-default/ir.golden.json +506 -0
  267. package/profiles/genbi-default/profile.yml +16 -0
  268. package/profiles/genbi-enrich-context/components/apply_enrichment/component.yml +42 -0
  269. package/profiles/genbi-enrich-context/components/draft_enrichment/component.yml +30 -0
  270. package/profiles/genbi-enrich-context/components/draft_enrichment/steps/draft.md +34 -0
  271. package/profiles/genbi-enrich-context/components/inspect_context/component.yml +32 -0
  272. package/profiles/genbi-enrich-context/components/inspect_context/steps/inspect.md +13 -0
  273. package/profiles/genbi-enrich-context/context/binding.yml +4 -0
  274. package/profiles/genbi-enrich-context/ir.golden.json +302 -0
  275. package/profiles/genbi-enrich-context/profile.yml +15 -0
  276. package/profiles/genbi-monitor/context/binding.yml +7 -0
  277. package/profiles/genbi-monitor/ir.golden.json +188 -0
  278. package/profiles/genbi-monitor/profile.yml +27 -0
  279. package/profiles/genbi-setup/components/build_context/component.yml +44 -0
  280. package/profiles/genbi-setup/components/build_context/steps/build.md +14 -0
  281. package/profiles/genbi-setup/components/connect_source/component.yml +51 -0
  282. package/profiles/genbi-setup/components/connect_source/steps/connect.md +23 -0
  283. package/profiles/genbi-setup/context/binding.yml +8 -0
  284. package/profiles/genbi-setup/ir.golden.json +140 -0
  285. package/profiles/genbi-setup/profile.yml +18 -0
  286. package/profiles/genbi-setup/raw/schema.json +5 -0
@@ -0,0 +1,799 @@
1
+ /**
2
+ * The BFF's UI-facing wire contract.
3
+ *
4
+ * These types are the UI's frozen consumer contract, reproduced verbatim
5
+ * (exact field names/casing) from the `WrenAI-genbi` frontend's expected
6
+ * shapes. They are deliberately NOT imported from that repo — this harness
7
+ * repo must not read or depend on it — so this file is the single source of
8
+ * truth for what the BFF serializes onto the wire. Keep it byte-for-byte in
9
+ * sync with the frontend if the UI contract ever changes; do not "improve" the
10
+ * shapes here independently of that source.
11
+ *
12
+ * The one exception is `RenderEnvelope`: that type is owned by this harness
13
+ * (`harness/render/index.ts`) and is imported directly rather than redefined.
14
+ */
15
+ import type { RenderEnvelope } from "../harness/render/index.js";
16
+ import type { ArtifactContentDto, ArtifactContentUnavailableReason } from "../harness/route/index.js";
17
+ export type { RenderEnvelope };
18
+ export type { ArtifactContentDto, ArtifactContentUnavailableReason };
19
+ export type SessionEventKind = "user" | "clarify" | "answer" | "refusal" | "artifact" | "published" | "saved" | "setup_status";
20
+ /**
21
+ * A BFF-owned, bounded inspection record for a Setup work-log row. Unlike
22
+ * `input` and `detail`, this is safe to persist and return from Setup
23
+ * recovery: it contains only an allowlisted command/action summary, output
24
+ * or an actionable error, and an optional elapsed duration.
25
+ */
26
+ export interface ToolStepInspection {
27
+ readonly action?: string;
28
+ readonly output?: string;
29
+ readonly error?: string;
30
+ readonly durationMs?: number;
31
+ }
32
+ export interface ToolStep {
33
+ readonly id: string;
34
+ readonly label: string;
35
+ readonly state: "running" | "done" | "error";
36
+ /**
37
+ * `"tool"` — a tool call. `"subagent"` — a nested sub-agent/Task turn
38
+ * (subscription dispatchers only; the in-process path has no such mechanism). `"step"` — one of
39
+ * In-process's own bundle-declared LLM steps (`step.start`/`step.finish`), i.e.
40
+ * the agent's own reasoning/output for that step, distinct from any tool
41
+ * calls it happened to make along the way. `"decision"` — a
42
+ * deterministic control-flow decision the BFF made for the turn (intent
43
+ * routing, clarify, verify-gate verdict), display-only; it is not produced
44
+ * by the agent runtime and carries no tool/step of its own.
45
+ */
46
+ readonly kind: "tool" | "subagent" | "step" | "decision";
47
+ readonly parent?: string;
48
+ readonly depth?: number;
49
+ /** The tool call's input (e.g. the `query` tool's `{sql}`), so the UI can expand a step to show what it ran. */
50
+ readonly input?: unknown;
51
+ /** A compact, bounded summary — success result summary, or the error message on a failed step. Never full result rows. */
52
+ readonly detail?: string;
53
+ /** Server-owned safe projection used by Setup work logs; never raw tool input or detail. */
54
+ readonly inspection?: ToolStepInspection;
55
+ }
56
+ export interface UserEvent {
57
+ readonly id: string;
58
+ readonly kind: "user";
59
+ readonly text: string;
60
+ }
61
+ /** BFF-produced (see `server/clarify.ts`'s D1 heuristic) — never comes from the agent runtime. */
62
+ export interface ClarifyEvent {
63
+ readonly id: string;
64
+ readonly kind: "clarify";
65
+ readonly prompt: string;
66
+ readonly chips: readonly string[];
67
+ }
68
+ export interface TextAnswerPayload {
69
+ readonly form: "text";
70
+ readonly text: string;
71
+ readonly verified: boolean;
72
+ /**
73
+ * Whether this turn attempted a data task (ran a query or assembled a
74
+ * dashboard), including one that failed or was refused — as opposed to a
75
+ * pure conversational/capability reply that made no data claim at all.
76
+ * The UI shows the Verified/Unverified badge only when this is `true`;
77
+ * a conversational answer (`false`) hides the badge entirely rather than
78
+ * showing a misleading "Unverified".
79
+ */
80
+ readonly dataAnswer: boolean;
81
+ }
82
+ export interface RichAnswerPayload {
83
+ readonly form: "rich";
84
+ readonly envelope: RenderEnvelope;
85
+ }
86
+ export interface AnswerEvent {
87
+ readonly id: string;
88
+ readonly kind: "answer";
89
+ readonly answer: TextAnswerPayload | RichAnswerPayload;
90
+ }
91
+ /** `fix` is BFF-synthesized — the agent runtime's `RefusalResult` carries no remediation text. */
92
+ export interface RefusalEvent {
93
+ readonly id: string;
94
+ readonly kind: "refusal";
95
+ readonly reason: string;
96
+ readonly fix: string;
97
+ }
98
+ export type ArtifactKind = "dashboard" | "report" | "chart";
99
+ export interface ArtifactEvent {
100
+ /** Generic stream event id (`evt-*`) — used by the UI for React keys/dedup. Not the artifact row id. */
101
+ readonly id: string;
102
+ readonly kind: "artifact";
103
+ readonly name: string;
104
+ readonly artifactKind: ArtifactKind;
105
+ readonly location: string;
106
+ /** The persisted artifact row id (`artifact-*`, from `store.createArtifact`) — pass this to the publish route. */
107
+ readonly artifactId: string;
108
+ }
109
+ export type PublishScope = "workspace" | "link" | "public";
110
+ export interface PublishedEvent {
111
+ readonly id: string;
112
+ readonly kind: "published";
113
+ readonly artifactName: string;
114
+ readonly link: string;
115
+ readonly scope: PublishScope;
116
+ }
117
+ /**
118
+ * A distinct, persisted event marking that an artifact was saved
119
+ * to the Artifacts page. Deliberately NOT a field on `ArtifactEvent` itself:
120
+ * session events are replayed verbatim from storage (see
121
+ * `getAskSessionData`), so "is this saved" must be recomputed by the UI
122
+ * scanning for this event rather than baked into the artifact event's own
123
+ * stored payload — that's what makes the saved state correct after a
124
+ * reload/replay with zero extra bookkeeping.
125
+ *
126
+ * Keyed on `artifactId` (the persisted artifact row id), NOT `artifactName`:
127
+ * two artifacts in the same session can share a name (e.g. re-running the
128
+ * same prompt twice), and matching on name alone would mark the *other*,
129
+ * never-saved artifact as saved too — with no way left to save it from the
130
+ * UI. `artifactName` is kept for display only. (`PublishedEvent` has this
131
+ * same name-keyed flaw; it's intentionally left as-is since the publish UI
132
+ * is hidden behind `PUBLISH_UI_ENABLED` and tracked separately.)
133
+ */
134
+ export interface SavedEvent {
135
+ readonly id: string;
136
+ readonly kind: "saved";
137
+ readonly artifactId: string;
138
+ readonly artifactName: string;
139
+ readonly savedAt: string;
140
+ }
141
+ /**
142
+ * The mirror of `SavedEvent`: marks that a previously-saved
143
+ * artifact was un-saved ("unpinned") from the Artifacts page. Appended
144
+ * instead of deleting the earlier `SavedEvent`: the session's event log is a
145
+ * persisted, replayed history (see `getAskSessionData`), and deleting a
146
+ * stored event would corrupt that replay. "Is this artifact currently saved"
147
+ * is instead recomputed by scanning for whichever `SavedEvent`/`UnsavedEvent`
148
+ * for this `artifactId` is most recent (latest-wins) — see the frontend's
149
+ * `isArtifactSaved`. Keyed on `artifactId`, not `artifactName`, for the same
150
+ * reason as `SavedEvent`.
151
+ */
152
+ export interface UnsavedEvent {
153
+ readonly id: string;
154
+ readonly kind: "unsaved";
155
+ readonly artifactId: string;
156
+ readonly artifactName: string;
157
+ readonly unsavedAt: string;
158
+ }
159
+ /**
160
+ * One resumable choice a setup turn is blocked on (`SetupStatusEvent.decision`
161
+ * or `SetupAdoptResponse.decision`, status `"needs_decision"`) — e.g. an
162
+ * `error_max_turns` checkpoint (continue vs stop), a same-name project
163
+ * conflict (rename/clean/cancel), an unbuilt-context confirmation
164
+ * (`build_context`: build/cancel), or an unpinned-project profile choice
165
+ * (`select_profile`: one option per candidate profile). `kind` distinguishes
166
+ * which checkpoint this is. Every kind except `select_profile` resolves via
167
+ * `POST /api/setup/decision`, which carries the `id` of the chosen `options`
168
+ * entry back; `select_profile` is stateless and instead resolves by
169
+ * re-POSTing `/api/setup/adopt` with the chosen option's `id` as `profile`
170
+ * (see `SetupAdoptResponse`'s doc comment). Kept minimal/generic (a bare
171
+ * string `kind`, not a closed union) so adding a future checkpoint kind never
172
+ * requires touching this wire type again.
173
+ */
174
+ export interface SetupDecision {
175
+ readonly kind: string;
176
+ readonly options: readonly {
177
+ readonly id: string;
178
+ readonly label: string;
179
+ }[];
180
+ readonly detail?: string;
181
+ }
182
+ /**
183
+ * `POST /api/setup/adopt`'s request body — the one required input is an
184
+ * absolute path to an existing wren project directory (has its own
185
+ * `wren_project.yml`; may or may not have a pinned `profile:` yet, and may or
186
+ * may not have a built `target/mdl.json` yet). Unlike the create flow's
187
+ * `projectName`, this is a full path, not a single safe path segment under a
188
+ * configured workspace root — adopt points at a project that can live
189
+ * anywhere on disk.
190
+ *
191
+ * `profile` is optional and only ever sent on a *second* call: when the
192
+ * first call comes back `needs_decision` with `decision.kind ===
193
+ * "select_profile"`, the caller re-POSTs the same `projectPath` plus the
194
+ * chosen candidate's `name` as `profile`. That re-POST runs
195
+ * `wren context set-profile <profile>` to write a durable pin before
196
+ * re-verifying — see `server/adopt.ts`'s module doc comment for the full
197
+ * three-state flow this drives.
198
+ */
199
+ export interface SetupAdoptRequest {
200
+ readonly projectPath: string;
201
+ readonly profile?: string;
202
+ }
203
+ /**
204
+ * `POST /api/setup/adopt`'s synchronous response — verification (path
205
+ * validity, profile pin/resolution, live connection smoke test) runs inline,
206
+ * no SSE turn involved, so the outcome comes back as a plain JSON body
207
+ * rather than a streamed `SetupStatusEvent`. The three outcomes mirror
208
+ * `SetupStatusEvent.status` on purpose (same three-way shape the frontend
209
+ * already knows how to render), just delivered synchronously:
210
+ *
211
+ * - `"ok"`: the project verified AND already has a built context — bound
212
+ * immediately, wizard lands on "bind".
213
+ * - `"needs_decision"`: the project verified but needs one more round-trip
214
+ * before it can bind. Two distinct checkpoints share this status, told
215
+ * apart by `decision.kind`:
216
+ * - `"build_context"` (options `"build"` | `"cancel"`) — connection
217
+ * verified, no built context yet. Resolve via the existing
218
+ * `POST /api/setup/decision` endpoint; choosing "build" dispatches the
219
+ * same `build_context` agentic turn the create flow's context step
220
+ * uses (open its `{turnId}` on
221
+ * `GET /api/sessions/:id/stream?turn=<turnId>` exactly like a
222
+ * context-step turn), and binds the project once that turn's
223
+ * `SETUP_STATUS: ok` verifies `target/mdl.json`. Choosing "cancel"
224
+ * just drops the pending decision — nothing was bound, so there's
225
+ * nothing to undo. Returned with HTTP 200.
226
+ * - `"select_profile"` (one option per candidate profile, `id`/`label`
227
+ * both the profile name) — the project has no `profile:` pin, but one
228
+ * or more profiles in `~/.wren/profiles.yml` share its `data_source`.
229
+ * Each candidate is `{name, datasource}` only — never any other
230
+ * profile field (host/port/credentials never cross the wire). Resolve
231
+ * by re-POSTing `/api/setup/adopt` with `profile` set to the chosen
232
+ * candidate's name (NOT via `/api/setup/decision` — that endpoint's
233
+ * session/pending-decision bookkeeping doesn't apply here, this
234
+ * checkpoint is stateless). Returned with **HTTP 409**, not 200 — see
235
+ * below.
236
+ * - `"error"`: verification failed (bad path, no `wren_project.yml`,
237
+ * unsupported connector, no compatible profile found for an unpinned
238
+ * project, or a failed live smoke query) — nothing was bound. `message`
239
+ * names which check failed.
240
+ *
241
+ * HTTP status: `"ok"` and `"needs_decision"` with `decision.kind ===
242
+ * "build_context"` both return 200 (a well-formed request that produced a
243
+ * definite, structured result needing no retry of the *same* request).
244
+ * `"needs_decision"` with `decision.kind === "select_profile"` returns
245
+ * **409 Conflict** instead, since the caller must re-issue a *different*
246
+ * request (this same route, with `profile` now set) to proceed — the 409
247
+ * signals "resubmit with more information," which plain 200 does not.
248
+ * `"error"` also returns 200 (a well-formed request whose verification
249
+ * failed is still a successful call to this endpoint); 400 is reserved for a
250
+ * malformed request (missing/non-string `projectPath`).
251
+ */
252
+ export interface SetupAdoptResponse {
253
+ readonly sessionId?: string;
254
+ readonly status: "ok" | "needs_decision" | "error";
255
+ readonly message: string;
256
+ readonly decision?: SetupDecision;
257
+ }
258
+ /**
259
+ * Terminal event for a setup-wizard turn (agentic `connect`/`connect_resume`
260
+ * dispatch — see `harness/setup/runner.ts`'s `parseSetupTerminal`). Distinct from
261
+ * `AnswerEvent`: a setup turn's finalText is a scaffolding narration, not an
262
+ * answer to show verbatim, and its outcome is one of four states the UI must
263
+ * branch on (advance the wizard / prompt for `.env` completion / show an
264
+ * error / resolve a checkpoint decision), not a yes/no verified answer.
265
+ * `decision` is present iff `status === "needs_decision"`.
266
+ */
267
+ export interface SetupStatusEvent {
268
+ readonly id: string;
269
+ readonly kind: "setup_status";
270
+ readonly status: "ok" | "needs_input" | "error" | "needs_decision";
271
+ readonly message: string;
272
+ readonly decision?: SetupDecision;
273
+ }
274
+ export type SessionEvent = UserEvent | ClarifyEvent | AnswerEvent | RefusalEvent | ArtifactEvent | PublishedEvent | SavedEvent | UnsavedEvent | SetupStatusEvent;
275
+ export interface AskSessionData {
276
+ readonly id: string;
277
+ readonly title: string;
278
+ readonly updatedAt: string;
279
+ readonly events: readonly SessionEvent[];
280
+ readonly workLog: readonly ToolStep[];
281
+ }
282
+ export interface SessionSummary {
283
+ readonly id: string;
284
+ readonly title: string;
285
+ readonly updatedAt: string;
286
+ }
287
+ export type SemanticColumnKey = "pk" | "fk";
288
+ export interface SemanticColumn {
289
+ readonly name: string;
290
+ readonly type: string;
291
+ readonly key?: SemanticColumnKey;
292
+ }
293
+ export interface SemanticModel {
294
+ readonly key: string;
295
+ readonly name: string;
296
+ readonly columns: readonly SemanticColumn[];
297
+ /** Optional: the BFF's live-project remap has no ER layout source and omits this — the UI must lay itself out when absent. Still populated by the seeded fixture path. */
298
+ readonly position?: {
299
+ readonly x: number;
300
+ readonly y: number;
301
+ };
302
+ }
303
+ export type RelationshipType = "one-to-one" | "one-to-many" | "many-to-one" | "many-to-many";
304
+ export interface SemanticRelationship {
305
+ readonly key: string;
306
+ readonly name: string;
307
+ readonly fromModel: string;
308
+ readonly toModel: string;
309
+ readonly type: RelationshipType;
310
+ }
311
+ export type MeasureAdditivity = "additive" | "non-additive";
312
+ export interface SemanticMeasure {
313
+ readonly key: string;
314
+ readonly name: string;
315
+ readonly baseModel: string;
316
+ readonly expression: string;
317
+ readonly additivity: MeasureAdditivity;
318
+ }
319
+ export interface KnowledgeStatus {
320
+ readonly instructionsPresent: boolean;
321
+ readonly verifiedPairCount: number;
322
+ }
323
+ export interface ContextOverview {
324
+ readonly models: readonly SemanticModel[];
325
+ readonly relationships: readonly SemanticRelationship[];
326
+ readonly measures: readonly SemanticMeasure[];
327
+ readonly knowledge: KnowledgeStatus;
328
+ readonly projectName: string;
329
+ /** The full bound project directory path (`resolveUserProject`), not just its basename — "" when unbound, same guard as `projectName`. */
330
+ readonly projectPath: string;
331
+ }
332
+ export type ContextFileKind = "model" | "relationship" | "cube" | "knowledge" | "view";
333
+ export interface ContextFileNode {
334
+ readonly key: string;
335
+ readonly title: string;
336
+ readonly children?: readonly ContextFileNode[];
337
+ readonly kind?: ContextFileKind;
338
+ readonly path?: string;
339
+ readonly content?: string;
340
+ readonly entityKey?: string;
341
+ }
342
+ export type ImpactSeverity = "none" | "compatibility" | "structural" | "semantic";
343
+ export type ImpactNodeKind = "model" | "measure" | "relationship" | "view";
344
+ export interface ImpactNode {
345
+ readonly key: string;
346
+ readonly name: string;
347
+ readonly kind: ImpactNodeKind;
348
+ }
349
+ export interface BlastRadius {
350
+ readonly seed: ImpactNode;
351
+ readonly downstream: readonly ImpactNode[];
352
+ readonly severity: ImpactSeverity;
353
+ }
354
+ export interface BrokenPair {
355
+ readonly question: string;
356
+ readonly refs: readonly string[];
357
+ readonly hitDownstreamKeys: readonly string[];
358
+ }
359
+ export interface ImpactResponse {
360
+ readonly blastRadius: BlastRadius;
361
+ readonly brokenPairs: readonly BrokenPair[];
362
+ }
363
+ export interface EvalRun {
364
+ readonly id: string;
365
+ readonly when: string;
366
+ readonly score: number;
367
+ readonly gateThreshold: number;
368
+ readonly gatePass: boolean;
369
+ readonly regressions: number;
370
+ readonly cost: string;
371
+ readonly p50: string;
372
+ }
373
+ export interface ComponentScore {
374
+ readonly component: string;
375
+ readonly score: number;
376
+ readonly delta: number;
377
+ }
378
+ /**
379
+ * `"adopt"` stands in for `"connect"` in the step SEQUENCE (not alongside it)
380
+ * once the wizard's mode is `"adopt"` — see `SetupMode`/`GET+POST
381
+ * /api/setup/mode`: the adopt flow points at an existing project directory
382
+ * (`POST /api/setup/adopt`) instead of scaffolding+crediting a new one, so it
383
+ * has no need for a separate "connect" step. `POST /api/setup/mode` rewrites
384
+ * `setup.steps` to swap the one entry for the other; the array is always
385
+ * exactly one of {`"connect"`, `"adopt"`}, never both.
386
+ */
387
+ export type StepKey = "runtime" | "connect" | "adopt" | "context" | "bind" | "ask";
388
+ export type StepState = "done" | "current" | "todo";
389
+ export interface SetupStep {
390
+ readonly key: StepKey;
391
+ readonly title: string;
392
+ readonly state: StepState;
393
+ }
394
+ /** A safe, read-only snapshot of the most recent retryable setup failure. */
395
+ export interface SetupFailureRecovery {
396
+ readonly attempt: "connect" | "connect_resume" | "context";
397
+ readonly projectName: string;
398
+ readonly sourceType: string;
399
+ readonly error: string;
400
+ readonly workLog: readonly ToolStep[];
401
+ }
402
+ /** Safe reload snapshot for a completed setup turn paused on user input. */
403
+ export interface SetupNeedsInputRecovery {
404
+ readonly attempt: "connect" | "connect_resume" | "context";
405
+ readonly projectName: string;
406
+ readonly sourceType: string;
407
+ readonly message: string;
408
+ readonly workLog: readonly ToolStep[];
409
+ }
410
+ /** `GET /api/setup/recovery` intentionally exposes no SDK session anchor. */
411
+ export interface SetupRecoveryResponse {
412
+ readonly failure?: SetupFailureRecovery;
413
+ /** Latest public paused terminal; its `sessionId` is the BFF setup session, never an SDK id. */
414
+ readonly needsInput?: SetupNeedsInputRecovery;
415
+ /** Reload-safe public context decision; never includes a provider anchor. */
416
+ readonly sessionId?: string;
417
+ readonly decision?: SetupDecision;
418
+ }
419
+ /**
420
+ * The setup wizard's two entry paths, chosen once at wizard start (`POST
421
+ * /api/setup/mode`): `"create"` scaffolds a brand-new project (the
422
+ * pre-existing connect -> context -> bind flow, unchanged); `"adopt"` points
423
+ * the wizard at an existing wren project directory (`POST /api/setup/adopt`)
424
+ * and — when that project already has a built `target/mdl.json` — skips
425
+ * straight to bind, no context step needed. `GET /api/setup/mode` returns
426
+ * `{ mode: undefined }` before the user has picked either, which the frontend
427
+ * reads as "show the create-vs-adopt choice screen."
428
+ */
429
+ export type SetupMode = "create" | "adopt";
430
+ /**
431
+ * One field key discovered in the scaffolded project's `.env` template (see
432
+ * `GET /api/setup/connect/env-fields`, `server/app.ts`) — never a value, only
433
+ * the key name plus a secret/non-secret display hint so the frontend can
434
+ * render a masked `Input.Password` for credential-shaped keys.
435
+ */
436
+ export interface SetupEnvField {
437
+ readonly key: string;
438
+ readonly secret: boolean;
439
+ }
440
+ export type AuthMode = "subscription" | "byo" | "local";
441
+ export type Deployment = "personal" | "hosted";
442
+ export type SubscriptionProvider = "claude" | "codex";
443
+ /** One non-sensitive model suggestion reported by the signed-in subscription provider. */
444
+ export interface SubscriptionModelCatalogEntry {
445
+ readonly model: string;
446
+ readonly displayName: string;
447
+ readonly description?: string;
448
+ readonly isDefault?: boolean;
449
+ readonly reasoningEfforts?: readonly {
450
+ readonly value: string;
451
+ readonly displayName: string;
452
+ readonly description?: string;
453
+ }[];
454
+ }
455
+ /** Sanitized result of provider-owned model discovery. */
456
+ export type SubscriptionModelCatalog = {
457
+ readonly version: 1;
458
+ readonly status: "ready";
459
+ readonly provider: SubscriptionProvider;
460
+ readonly models: readonly SubscriptionModelCatalogEntry[];
461
+ } | {
462
+ readonly version: 1;
463
+ readonly status: "unavailable";
464
+ readonly provider: SubscriptionProvider;
465
+ readonly code: "not_authenticated" | "runtime_unavailable" | "timeout" | "protocol_error";
466
+ readonly retryable: boolean;
467
+ };
468
+ /** A concrete adapter selectable for an individual compiled-bundle tier. */
469
+ export type RuntimeTierAdapter = "anthropic" | "openai-compatible" | "local";
470
+ /** Kept as the legacy/default-runtime spelling used by the BYO auth control. */
471
+ export type ApiKeyAdapter = "anthropic" | "openai-compatible";
472
+ /** NOTE: unrelated to the harness's own `AdapterSpec`/`tierBinding` — this is UI-facing config only. */
473
+ export interface TierModelBinding {
474
+ readonly tier: string;
475
+ /** Explicit override; when omitted, `RuntimeSettings.apiKeyModel` is the default. */
476
+ readonly model?: string;
477
+ /** Explicit override; when omitted, the runtime's selected/default adapter applies. */
478
+ readonly adapter?: RuntimeTierAdapter;
479
+ /** Required for openai-compatible/local overrides; never contains credentials. */
480
+ readonly baseURL?: string;
481
+ }
482
+ export interface RuntimeSettings {
483
+ readonly authMode: AuthMode;
484
+ /** Which personal subscription CLI is used when `authMode` is `"subscription"`. */
485
+ readonly subscriptionProvider?: SubscriptionProvider;
486
+ readonly tierModels: readonly TierModelBinding[];
487
+ readonly hybrid: boolean;
488
+ readonly deployment: Deployment;
489
+ /** Which api-key adapter `"byo"` dispatches through. Non-secret — never the key itself. */
490
+ readonly apiKeyAdapter?: ApiKeyAdapter;
491
+ /** Model name override for the api-key adapter. Non-secret. */
492
+ readonly apiKeyModel?: string;
493
+ /** Base URL override, `openai-compatible` only. Non-secret. */
494
+ readonly apiKeyBaseURL?: string;
495
+ /**
496
+ * Model for the subscription dispatcher itself. This is deliberately NOT a
497
+ * profile tier: compiled bundles own their step tiers, while subscription
498
+ * dispatchers need a separate driver model.
499
+ */
500
+ readonly subscriptionDriverModel?: string;
501
+ }
502
+ /** Login availability only. No credential contents or metadata cross this boundary. */
503
+ export interface SubscriptionLoginStatus {
504
+ readonly claude: boolean;
505
+ readonly codex: boolean;
506
+ }
507
+ /** `PUT /api/config/runtime`'s response — the persisted settings plus any compliance warnings (e.g. the subscription ToS notice) surfaced for this save. `GET /api/config/runtime` stays a plain `RuntimeSettings` — warnings are a save-time concern only. */
508
+ export interface NativeRuntimeBindingDto {
509
+ readonly configured: boolean;
510
+ readonly generation: number;
511
+ readonly provider?: SubscriptionProvider;
512
+ readonly target?: "claude-code:interactive" | "codex:interactive";
513
+ readonly targetLabel?: "Claude CLI" | "Codex CLI";
514
+ }
515
+ export type RuntimeSettingsPutResponse = RuntimeSettings & {
516
+ readonly warnings: readonly string[];
517
+ readonly nativeSessionBinding: NativeRuntimeBindingDto;
518
+ };
519
+ /** Read-only health of the saved Runtime, for correcting legacy settings before dispatch. */
520
+ export type RuntimeSettingsReadiness = {
521
+ readonly valid: true;
522
+ } | {
523
+ readonly valid: false;
524
+ readonly correction: string;
525
+ };
526
+ /**
527
+ * Whether each api-key adapter's required credential env var is present on the BFF process —
528
+ * booleans only, never the key value/prefix/suffix/length. Powers the setup wizard's api-key
529
+ * step so it can say "detected"/"missing" without ever handling the secret itself. See `GET
530
+ * /api/config/env-detect` (`server/app.ts`) and `detectAdapterEnv` (`server/env-detect.ts`).
531
+ */
532
+ export interface AdapterEnvStatus {
533
+ readonly anthropic: boolean;
534
+ readonly openaiCompatible: boolean;
535
+ }
536
+ export interface PublishedInfo {
537
+ readonly link: string;
538
+ readonly scope: PublishScope;
539
+ }
540
+ export interface ArtifactDto {
541
+ readonly id: string;
542
+ readonly sessionId: string;
543
+ readonly name: string;
544
+ readonly artifactKind: ArtifactKind;
545
+ readonly location: string;
546
+ readonly verified: boolean;
547
+ readonly createdAt: string;
548
+ readonly published?: PublishedInfo;
549
+ /** Present only once the artifact has been saved to the Artifacts page. */
550
+ readonly savedAt?: string;
551
+ /** Native provenance is safe routing metadata; credentials and binding identity never cross this DTO. */
552
+ readonly nativeSessionId?: string;
553
+ }
554
+ export interface HarnessProfile {
555
+ readonly id: string;
556
+ readonly name: string;
557
+ readonly boundContext: string;
558
+ readonly verifyGate: boolean;
559
+ readonly bundleId: string;
560
+ readonly bundleVersion: string;
561
+ /**
562
+ * The bundle's declared IR compatibility range (`bundle.compat`) — e.g.
563
+ * `"0.3"` when `min_ir_version === max_ir_version`, or `"0.3–0.4"` when the
564
+ * bundle spans a range. See `buildProfile` in `server/harness.ts`.
565
+ */
566
+ readonly irVersion: string;
567
+ /** `bundle.target` — the compiled dispatch target, e.g. `"vercel:headless"`. */
568
+ readonly dispatchTarget: string;
569
+ /**
570
+ * A short (first 7 hex chars), deterministic sha256 content hash of the
571
+ * compiled bundle (canonical, sorted-key JSON stringify — see
572
+ * `computeBundleHash` in `server/harness.ts`). NOT a "last compiled"
573
+ * timestamp; the store tracks no such thing.
574
+ */
575
+ readonly bundleHash: string;
576
+ /**
577
+ * Derived from real state (the Setup wizard's "bind" step), not a
578
+ * hardcoded literal — see `deriveProfileStatus` in `server/harness.ts`.
579
+ * `"Bound"` once the user has completed Setup's Compile & Bind step;
580
+ * an honest alternative (e.g. `"Not bound yet"`) otherwise.
581
+ */
582
+ readonly status: string;
583
+ }
584
+ /**
585
+ * Which auth strategy is actually configured — mirrors
586
+ * `AuthChoice["mode"]` (`harness/auth/index.ts`) verbatim. Deliberately NOT the
587
+ * internal `inProcess`/`dispatched` framework-dispatch bucketing (that terminology
588
+ * must never reach the wire); see `runtimeBackendAndLabel` in
589
+ * `server/harness.ts`.
590
+ */
591
+ export type HarnessRuntimeBackend = "subscription" | "api-key" | "local" | "gateway";
592
+ /**
593
+ * Which provider-specific back-end owns this configuration. Claude and
594
+ * Codex subscriptions use their respective local dispatchers; api-key,
595
+ * local, and gateway modes run in-process. Codex Ask can still be disabled
596
+ * independently, which is surfaced on component status.
597
+ */
598
+ export type HarnessRuntimeDispatcher = "claude-agent-sdk" | "codex-local" | "in-process";
599
+ export interface HarnessRuntime {
600
+ readonly backend: HarnessRuntimeBackend;
601
+ readonly label: string;
602
+ /** See `HarnessRuntimeDispatcher`'s doc comment. */
603
+ readonly dispatcher: HarnessRuntimeDispatcher;
604
+ /**
605
+ * The SAME source `GET /api/config/runtime` reports
606
+ * (`store.getRuntimeSettings().tierModels`), filtered to the tiers this
607
+ * bundle actually declares — so the two endpoints always agree on what
608
+ * model backs each tier. Previously this derived the tier -> model
609
+ * binding `route()` would really apply (see `server/harness.ts` git
610
+ * history), but under a `subscription` auth choice that real binding is
611
+ * genuinely unobservable from this harness (the `warble-agent-sdk`
612
+ * dispatcher owns model routing internally), which surfaced the same
613
+ * auth label for every tier instead of a real model name. Reusing the
614
+ * store's settings directly fixes that and keeps this DTO consistent with
615
+ * `RuntimeSettings.tierModels`. Each component's own `model`/`tiers`
616
+ * (`HarnessComponent`) are unaffected — those still report the real
617
+ * per-component binding, see `buildComponent`.
618
+ */
619
+ readonly tierModels: readonly TierModelBinding[];
620
+ }
621
+ export type ConnectionHealth = "healthy" | "degraded" | "down";
622
+ /**
623
+ * The Harness page's "Data source · connection" panel — see `buildConnection`
624
+ * in `server/harness.ts`. `type`/`location` are resolved by
625
+ * `server/conn-config.ts`'s `resolveConnectionSource`, in order:
626
+ * the onboarding-only `conn.yml` first, if it happens to exist and carries a
627
+ * `datasource`; otherwise the project's persistent `wren_project.yml` —
628
+ * `data_source:` (always present) is `type`, and its pinned `profile:`, if
629
+ * any, is resolved against `~/.wren/profiles.yml` to supply the fields
630
+ * `describeConnection` turns into `location` (a duckdb path, or an
631
+ * allowlisted host/database-shaped string for DB-type sources — never a
632
+ * credential). A project with no profile pin honestly reports `type` with
633
+ * `location` `"—"` rather than fabricating one from the profiles store's
634
+ * global `active` profile. `via`/`lastSync` stay honest `"—"` placeholders —
635
+ * there is no real "which mechanism"/"last synced at" signal available from
636
+ * this harness. `tablesSynced` is real (`store.getContextModels().length`).
637
+ */
638
+ export interface HarnessConnection {
639
+ readonly type: string;
640
+ readonly location: string;
641
+ readonly via: string;
642
+ readonly tablesSynced: number;
643
+ readonly lastSync: string;
644
+ readonly health: ConnectionHealth;
645
+ }
646
+ export type CapabilityOutcome = "native" | "realize-via";
647
+ export interface HarnessCapability {
648
+ readonly capability: string;
649
+ readonly outcome: CapabilityOutcome;
650
+ readonly providedBy: string;
651
+ readonly criticality?: string;
652
+ }
653
+ export interface HarnessGuardrail {
654
+ readonly name: string;
655
+ readonly enforcement: string;
656
+ readonly locked: boolean;
657
+ /** Present only when the guardrail carries a numeric limit, e.g. `row_limit` = 1000, `statement_timeout` = 30. */
658
+ readonly threshold?: number;
659
+ }
660
+ /**
661
+ * One step of a component's declared step→artifact dataflow (`agent.steps[]`
662
+ * in the compiled bundle) — read-only introspection of the wiring the
663
+ * executor itself keys on (`consumes` is a hard precondition), not something
664
+ * this DTO executes.
665
+ */
666
+ export interface HarnessStep {
667
+ readonly name: string;
668
+ readonly tier: string;
669
+ readonly consumes: readonly string[];
670
+ readonly produces: string;
671
+ /** `step.realization.kind` — `"independent"` or `"repair_fold"`. */
672
+ readonly realization: string;
673
+ /** `step.when?.guard`, e.g. `"on_failure"` — present only when the step is conditionally gated. */
674
+ readonly guard?: string;
675
+ /** `step.realization.fold_into` — present only for `"repair_fold"` steps. */
676
+ readonly foldInto?: string;
677
+ /** `step.realization.max_attempts` — present only for `"repair_fold"` steps. */
678
+ readonly maxAttempts?: number;
679
+ }
680
+ /**
681
+ * A bundle-declared agent ("component" in the DTO/bundle vocabulary), shown
682
+ * on the frontend as a **Component** — not a "sub-agent": that framing is
683
+ * reserved for the profile level. This harness's runtime routes exactly ONE
684
+ * component per turn from the user's intent, so every other component listed
685
+ * here is a read-only declared part of the compiled bundle, not a
686
+ * concurrently-running sub-agent. `model`/`tiers` are the REAL tier binding
687
+ * resolved as if this component were the one running (see `buildComponent`
688
+ * in `server/harness.ts`), not the Setup page's seeded settings.
689
+ */
690
+ export interface HarnessComponent {
691
+ readonly id: string;
692
+ readonly name: string;
693
+ readonly componentType: string;
694
+ /** `agent.realization_kind`, e.g. `"skill"`. */
695
+ readonly realizationKind: string;
696
+ /** `agent.trigger`, e.g. `"one_shot"`. */
697
+ readonly trigger: string;
698
+ /** `agent.outcome`, e.g. `"none"`. */
699
+ readonly outcome: string;
700
+ readonly callableAs: string;
701
+ readonly model: string;
702
+ readonly tiers: readonly TierModelBinding[];
703
+ readonly capabilities: readonly HarnessCapability[];
704
+ readonly guardrails: readonly HarnessGuardrail[];
705
+ /** `agent.tools[]` — e.g. `{ name: "query", source: "mcp:sample/query" }`. */
706
+ readonly tools: readonly {
707
+ readonly name: string;
708
+ readonly source: string;
709
+ }[];
710
+ /**
711
+ * The declared render-block `type` consts from `agent.output_schema`
712
+ * (`blocks.items.anyOf[].properties.type.const`, or the single-item form
713
+ * when there's no `anyOf`) — `[]` when the component declares no typed
714
+ * output blocks. See `extractOutputBlocks` in `server/harness.ts`.
715
+ */
716
+ readonly outputBlocks: readonly string[];
717
+ /** The component's declared step→artifact dataflow (`agent.steps[]`). */
718
+ readonly steps: readonly HarnessStep[];
719
+ readonly status: string;
720
+ /** Stable display-only explanation; never exposes a target capability or execution plan. */
721
+ readonly unavailableReason?: string;
722
+ /**
723
+ * Present only when this component is unavailable on the compiled dispatch
724
+ * target (`agent.availability`) but the currently-selected purpose's native
725
+ * session IS available — i.e. it actually runs, just not via the
726
+ * programmatic path. `status` is `"ready"` in this case; the programmatic
727
+ * limitation moves here instead of being promoted into `unavailableReason`.
728
+ * Keyed off which `buildComponent` branch produced the status, never off
729
+ * matching Warble's reason string.
730
+ */
731
+ readonly nativeAvailability?: {
732
+ /** The native session's target label, e.g. `"Claude CLI"` — why this actually runs. */
733
+ readonly viaLabel: "Claude CLI" | "Codex CLI";
734
+ /** The compiled dispatch target that cannot run it, e.g. `"claude-agent-sdk:local"`. */
735
+ readonly compiledDispatchTarget: string;
736
+ /** `agent.availability.reason` — the original bundle-level explanation, preserved for the expanded row. */
737
+ readonly compiledUnavailableReason: string;
738
+ };
739
+ }
740
+ export interface HarnessDto {
741
+ /** The single server-owned native purpose whose bundle is described below. */
742
+ readonly purpose: HarnessPurpose;
743
+ readonly profile: HarnessProfile;
744
+ readonly runtime: HarnessRuntime;
745
+ readonly connection: HarnessConnection;
746
+ /** See `HarnessComponent`'s doc comment — bundle agents are shown as Components, not sub-agents. */
747
+ readonly components: readonly HarnessComponent[];
748
+ /** Closed native dispatch registry projected from the same runtime binding as launch. */
749
+ readonly nativeSessions: {
750
+ readonly binding: NativeRuntimeBindingDto;
751
+ readonly dispatches: readonly {
752
+ readonly purpose: "analysis" | "setup" | "context_enrichment";
753
+ readonly profile: string;
754
+ readonly scopeKind: "bootstrap" | "bound_project";
755
+ readonly target?: "claude-code:interactive" | "codex:interactive";
756
+ readonly targetLabel?: "Claude CLI" | "Codex CLI";
757
+ readonly available: boolean;
758
+ readonly reason?: string;
759
+ }[];
760
+ };
761
+ }
762
+ /**
763
+ * A read-only projection of the selected purpose. `executionKind` is the
764
+ * discriminator that keeps form-led Setup runner readiness separate from
765
+ * native terminal readiness; no browser-provided launch/profile/target input
766
+ * is represented here.
767
+ */
768
+ interface HarnessPurposeBase {
769
+ readonly purpose: "setup" | "analysis" | "context_enrichment";
770
+ readonly profile: "genbi-setup" | "genbi-default" | "genbi-enrich-context";
771
+ readonly scopeKind: "bootstrap" | "bound_project";
772
+ readonly available: boolean;
773
+ readonly reason?: string;
774
+ }
775
+ export type HarnessPurpose = HarnessPurposeBase & ({
776
+ readonly executionKind: "setup_runner";
777
+ readonly target: "claude-agent-sdk:setup" | "codex-local:setup" | "in-process:setup";
778
+ readonly targetLabel: "Claude Setup runner" | "Codex Setup runner" | "In-process Setup runner";
779
+ } | {
780
+ readonly executionKind: "native_session";
781
+ readonly target?: "claude-code:interactive" | "codex:interactive";
782
+ readonly targetLabel?: "Claude CLI" | "Codex CLI";
783
+ });
784
+ export type SseEventName = "worklog" | "event" | "error" | "done";
785
+ export type SseFrame = {
786
+ readonly event: "worklog";
787
+ readonly data: readonly ToolStep[];
788
+ } | {
789
+ readonly event: "event";
790
+ readonly data: SessionEvent;
791
+ } | {
792
+ readonly event: "error";
793
+ readonly data: {
794
+ readonly message: string;
795
+ };
796
+ } | {
797
+ readonly event: "done";
798
+ readonly data: Record<string, never>;
799
+ };