@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,164 @@
1
+ function isRecord(value) {
2
+ return typeof value === "object" && value !== null;
3
+ }
4
+ function isStringOrNull(value) {
5
+ return typeof value === "string" || value === null;
6
+ }
7
+ /**
8
+ * Parse + structurally validate one NDJSON line from `warble-agent-sdk chat --stream-json`.
9
+ * Returns `undefined` for a blank line, invalid JSON, or a shape that doesn't match any known
10
+ * `WarbleChatEventLike` variant — the caller drops such lines rather than failing the whole turn
11
+ * over one malformed/forward-incompatible line.
12
+ */
13
+ export function parseWarbleChatEventLine(line) {
14
+ const trimmed = line.trim();
15
+ if (trimmed.length === 0)
16
+ return undefined;
17
+ let raw;
18
+ try {
19
+ raw = JSON.parse(trimmed);
20
+ }
21
+ catch {
22
+ return undefined;
23
+ }
24
+ if (!isRecord(raw) || typeof raw["t"] !== "string")
25
+ return undefined;
26
+ switch (raw["t"]) {
27
+ case "step_start":
28
+ if (typeof raw["id"] === "string" &&
29
+ typeof raw["name"] === "string" &&
30
+ isStringOrNull(raw["parent"]) &&
31
+ typeof raw["depth"] === "number") {
32
+ return { t: "step_start", id: raw["id"], name: raw["name"], parent: raw["parent"], depth: raw["depth"] };
33
+ }
34
+ return undefined;
35
+ case "step_finish":
36
+ if (typeof raw["id"] === "string" && typeof raw["ok"] === "boolean") {
37
+ return {
38
+ t: "step_finish",
39
+ id: raw["id"],
40
+ ok: raw["ok"],
41
+ ...(typeof raw["detail"] === "string" ? { detail: raw["detail"] } : {}),
42
+ };
43
+ }
44
+ return undefined;
45
+ case "tool_call":
46
+ if (typeof raw["id"] === "string" &&
47
+ typeof raw["name"] === "string" &&
48
+ isStringOrNull(raw["parent"]) &&
49
+ typeof raw["depth"] === "number") {
50
+ return {
51
+ t: "tool_call",
52
+ id: raw["id"],
53
+ name: raw["name"],
54
+ ...(raw["input"] !== undefined ? { input: raw["input"] } : {}),
55
+ parent: raw["parent"],
56
+ depth: raw["depth"],
57
+ };
58
+ }
59
+ return undefined;
60
+ case "tool_result":
61
+ if (typeof raw["id"] === "string" && typeof raw["ok"] === "boolean") {
62
+ return {
63
+ t: "tool_result",
64
+ id: raw["id"],
65
+ ok: raw["ok"],
66
+ ...(typeof raw["summary"] === "string" ? { summary: raw["summary"] } : {}),
67
+ ...(typeof raw["error"] === "string" ? { error: raw["error"] } : {}),
68
+ };
69
+ }
70
+ return undefined;
71
+ case "answer":
72
+ if (typeof raw["text"] === "string")
73
+ return { t: "answer", text: raw["text"] };
74
+ return undefined;
75
+ case "session":
76
+ if (isStringOrNull(raw["id"]))
77
+ return { t: "session", id: raw["id"] };
78
+ return undefined;
79
+ default:
80
+ return undefined;
81
+ }
82
+ }
83
+ export function createChatEventMapperState() {
84
+ return { currentStepId: undefined, stepNames: new Map(), toolNames: new Map() };
85
+ }
86
+ /** `AgentEvent.parent` is `string | undefined`; warble's own `parent` field is `string | null`. */
87
+ function toOptionalParent(parent) {
88
+ return parent !== null ? { parent } : {};
89
+ }
90
+ /**
91
+ * Maps one parsed warble chat event to the harness's `AgentEvent` vocabulary, mutating `state` as
92
+ * it goes (remembering step/tool names, tracking the current enclosing step). Returns `undefined`
93
+ * for `answer` (handled by the caller) and for a `tool_call`/`tool_result` this mapper cannot
94
+ * place under any known step — that should never happen given warble always opens its enclosing
95
+ * step before emitting a tool event, but falling back to the raw id rather than throwing keeps a
96
+ * single malformed/reordered line from crashing an otherwise-healthy live stream.
97
+ */
98
+ export function mapChatEventToAgentEvent(raw, state) {
99
+ switch (raw.t) {
100
+ case "step_start": {
101
+ state.currentStepId = raw.id;
102
+ state.stepNames.set(raw.id, raw.name);
103
+ return {
104
+ kind: "step.start",
105
+ stepId: raw.id,
106
+ name: raw.name,
107
+ // Dispatched's NDJSON stream carries no per-step tier info (warble doesn't expose it in
108
+ // `WarbleChatEvent`); `LiveWorkLog.ingest` never reads `tier` when folding to `ToolStep`,
109
+ // so this placeholder has no observable effect on the UI's work log.
110
+ tier: "unknown",
111
+ ...toOptionalParent(raw.parent),
112
+ depth: raw.depth,
113
+ };
114
+ }
115
+ case "step_finish": {
116
+ const name = state.stepNames.get(raw.id) ?? raw.id;
117
+ // Clear the current step once it closes so any stray tool event arriving after it falls back
118
+ // to its own id rather than being attributed to the already-finished step.
119
+ if (state.currentStepId === raw.id)
120
+ state.currentStepId = undefined;
121
+ return {
122
+ kind: "step.finish",
123
+ stepId: raw.id,
124
+ name,
125
+ status: raw.ok ? "ok" : "error",
126
+ ...(raw.detail !== undefined ? { detail: raw.detail } : {}),
127
+ };
128
+ }
129
+ case "tool_call": {
130
+ state.toolNames.set(raw.id, raw.name);
131
+ const stepId = state.currentStepId ?? raw.id;
132
+ return {
133
+ kind: "tool.call",
134
+ stepId,
135
+ callId: raw.id,
136
+ tool: raw.name,
137
+ ...(raw.input !== undefined ? { input: raw.input } : {}),
138
+ ...toOptionalParent(raw.parent),
139
+ depth: raw.depth,
140
+ status: "running",
141
+ };
142
+ }
143
+ case "tool_result": {
144
+ const tool = state.toolNames.get(raw.id) ?? raw.id;
145
+ const stepId = state.currentStepId ?? raw.id;
146
+ return {
147
+ kind: "tool.result",
148
+ stepId,
149
+ callId: raw.id,
150
+ tool,
151
+ status: raw.ok ? "success" : "error",
152
+ ...(raw.ok ? (raw.summary !== undefined ? { summary: raw.summary } : {}) : {}),
153
+ ...(!raw.ok && raw.error !== undefined ? { error: raw.error } : {}),
154
+ };
155
+ }
156
+ case "answer":
157
+ return undefined;
158
+ case "session":
159
+ // Session metadata, not a work-log event — the caller (`spawnChat`) intercepts this line
160
+ // directly (mirroring its existing `t === "answer"` interception) rather than routing it
161
+ // through here.
162
+ return undefined;
163
+ }
164
+ }
@@ -0,0 +1,25 @@
1
+ import type { AgentEventInput } from "../events/index.js";
2
+ import type { CodexAskComponent, CodexManifestModels } from "./codex-local-manifest.js";
3
+ export declare class CodexAskEventMapper {
4
+ private readonly models;
5
+ private readonly component;
6
+ private sessionStarted;
7
+ private parentThreadId;
8
+ private parentTurnId;
9
+ private turnStarted;
10
+ private turnCompleted;
11
+ private finalText;
12
+ private readonly started;
13
+ private readonly finished;
14
+ private readonly agentThreads;
15
+ private readonly mcpEvidence;
16
+ private renderState;
17
+ private renderArtifact;
18
+ constructor(models: CodexManifestModels, component?: CodexAskComponent);
19
+ nextLine(line: string): AgentEventInput[];
20
+ result(): string;
21
+ private validateStepOutcome;
22
+ private stepContract;
23
+ private validateDashboardAnswer;
24
+ private hasSuccessfulDashboardEvidence;
25
+ }
@@ -0,0 +1,395 @@
1
+ const COMPONENT_STEPS = {
2
+ answer_query: [
3
+ { name: "resolve_intent", tier: "cheap", tool: "get_context" },
4
+ { name: "generate_sql", tier: "strong", tool: "run_sql" },
5
+ { name: "repair_sql", tier: "strong", tool: "run_sql" },
6
+ ],
7
+ generate_dashboard: [
8
+ { name: "plan_dashboard", tier: "strong", tool: "get_context" },
9
+ { name: "compose_layout", tier: "cheap", tool: "run_sql" },
10
+ ],
11
+ };
12
+ function isRecord(value) {
13
+ return typeof value === "object" && value !== null && !Array.isArray(value);
14
+ }
15
+ function parseEvent(line) {
16
+ let value;
17
+ try {
18
+ value = JSON.parse(line);
19
+ }
20
+ catch {
21
+ throw new Error("warble-codex-local Ask emitted non-JSON output");
22
+ }
23
+ if (!isRecord(value) || typeof value["t"] !== "string") {
24
+ throw new Error("warble-codex-local Ask emitted a malformed event");
25
+ }
26
+ return value;
27
+ }
28
+ function expectedRole(step) {
29
+ return `warble_${step}`;
30
+ }
31
+ export class CodexAskEventMapper {
32
+ models;
33
+ component;
34
+ sessionStarted = false;
35
+ parentThreadId = "";
36
+ parentTurnId = "";
37
+ turnStarted = false;
38
+ turnCompleted = false;
39
+ finalText;
40
+ started = [];
41
+ finished = new Map();
42
+ agentThreads = new Map();
43
+ mcpEvidence = new Map();
44
+ renderState;
45
+ renderArtifact;
46
+ constructor(models, component = "answer_query") {
47
+ this.models = models;
48
+ this.component = component;
49
+ }
50
+ nextLine(line) {
51
+ const event = parseEvent(line);
52
+ switch (event.t) {
53
+ case "session_started":
54
+ if (this.sessionStarted || event.session?.target !== "codex:local" || !event.session.threadId) {
55
+ throw new Error("warble-codex-local Ask emitted an invalid session start");
56
+ }
57
+ this.sessionStarted = true;
58
+ this.parentThreadId = event.session.threadId;
59
+ return [];
60
+ case "turn_started":
61
+ if (!this.sessionStarted ||
62
+ this.turnStarted ||
63
+ event.turn?.status !== "in_progress" ||
64
+ event.turn.threadId !== this.parentThreadId ||
65
+ !event.turn.turnId) {
66
+ throw new Error("warble-codex-local Ask emitted an invalid turn start");
67
+ }
68
+ this.turnStarted = true;
69
+ this.parentTurnId = event.turn.turnId;
70
+ return [];
71
+ case "agent_started": {
72
+ const step = this.stepContract(event.step);
73
+ if (!this.turnStarted || this.turnCompleted || step === undefined) {
74
+ throw new Error("warble-codex-local Ask emitted an invalid agent start");
75
+ }
76
+ const expected = COMPONENT_STEPS[this.component][this.started.length];
77
+ const previous = COMPONENT_STEPS[this.component][this.started.length - 1];
78
+ if (event.step !== expected?.name ||
79
+ (previous !== undefined && !this.finished.has(previous.name)) ||
80
+ (step.name === "repair_sql"
81
+ ? this.finished.get("generate_sql") !== false
82
+ : previous !== undefined && this.finished.get(previous.name) !== true) ||
83
+ event.agentRole !== expectedRole(step.name) ||
84
+ !event.agentThreadId ||
85
+ event.parentThreadId !== this.parentThreadId ||
86
+ event.parentTurnId !== this.parentTurnId) {
87
+ throw new Error("warble-codex-local Ask agent order or attribution did not match the IR");
88
+ }
89
+ if (event.model !== this.models[step.tier]) {
90
+ throw new Error(`warble-codex-local Ask step "${event.step}" ran on the wrong model`);
91
+ }
92
+ this.started.push(step.name);
93
+ this.agentThreads.set(step.name, event.agentThreadId);
94
+ return [{
95
+ kind: "step.start",
96
+ stepId: step.name,
97
+ name: step.name,
98
+ tier: step.tier,
99
+ parent: event.parentThreadId,
100
+ depth: 1,
101
+ }];
102
+ }
103
+ case "artifact": {
104
+ const reference = event.reference;
105
+ const step = this.stepContract(reference?.step);
106
+ if (step === undefined ||
107
+ this.finished.has(step.name)) {
108
+ throw new Error("warble-codex-local Ask emitted an artifact outside an active step");
109
+ }
110
+ const threadId = this.agentThreads.get(step.name);
111
+ if (threadId === undefined ||
112
+ reference.agentThreadId !== threadId ||
113
+ reference.parentThreadId !== this.parentThreadId ||
114
+ reference.parentTurnId !== this.parentTurnId ||
115
+ reference.agentRole !== expectedRole(step.name) ||
116
+ reference.server !== "wren" ||
117
+ !reference.itemId ||
118
+ reference.tool !== step.tool) {
119
+ throw new Error("warble-codex-local Ask artifact attribution did not match the allowed Wren MCP surface");
120
+ }
121
+ if (this.component === "generate_dashboard") {
122
+ const previousEvidence = this.mcpEvidence.get(step.name);
123
+ this.mcpEvidence.set(step.name, {
124
+ count: (previousEvidence?.count ?? 0) + 1,
125
+ allOk: (previousEvidence?.allOk ?? true) && reference.ok,
126
+ });
127
+ }
128
+ const callId = `${reference.step}:${reference.itemId}`;
129
+ const tool = `${reference.server}.${reference.tool}`;
130
+ return [
131
+ {
132
+ kind: "tool.call",
133
+ stepId: reference.step,
134
+ callId,
135
+ tool,
136
+ parent: reference.agentThreadId,
137
+ depth: 2,
138
+ status: "running",
139
+ },
140
+ {
141
+ kind: "tool.result",
142
+ stepId: reference.step,
143
+ callId,
144
+ tool,
145
+ status: reference.ok ? "success" : "error",
146
+ ...(!reference.ok ? { error: "allowlisted Wren MCP tool failed" } : {}),
147
+ },
148
+ ];
149
+ }
150
+ case "render_artifact": {
151
+ const reference = event.reference;
152
+ const composeThread = this.agentThreads.get("compose_layout");
153
+ const allowedBlockTypes = new Set(["kpi_card", "chart", "table", "definition"]);
154
+ // Protocol shape: a violation here means warble-codex-local emitted
155
+ // something structurally wrong (bad envelope-protocol fields, or a
156
+ // `verified` claim unsupported by tool evidence) -- always a target
157
+ // bug, so it stays loud.
158
+ if (this.component !== "generate_dashboard" ||
159
+ this.renderState !== undefined ||
160
+ this.finished.get("compose_layout") !== true ||
161
+ reference?.version !== "0.1" ||
162
+ reference.kind !== "render_envelope" ||
163
+ reference.parentThreadId !== this.parentThreadId ||
164
+ reference.parentTurnId !== this.parentTurnId ||
165
+ reference.step !== "compose_layout" ||
166
+ reference.agentRole !== expectedRole("compose_layout") ||
167
+ reference.agentThreadId !== composeThread ||
168
+ typeof reference.verified !== "boolean" ||
169
+ (reference.verified && !this.hasSuccessfulDashboardEvidence()) ||
170
+ !Array.isArray(reference.blockTypes) ||
171
+ reference.blockTypes.length === 0 ||
172
+ reference.blockTypes.some((type) => !allowedBlockTypes.has(type))) {
173
+ throw new Error("warble-codex-local Ask emitted an invalid dashboard render artifact");
174
+ }
175
+ // Dashboard CONTENT requirement: genbi owns the product
176
+ // shape of a dashboard -- a rendered dashboard must carry at least
177
+ // one data panel (`kpi_card`/`chart`/`table`) and one `definition`.
178
+ // This is the guarantee's owner now that warble-codex-local no
179
+ // longer enforces it in `render_contract.ts`. A shortfall here is a
180
+ // genbi-product-shape problem, not a protocol bug, so it degrades
181
+ // exactly like a `render_degraded` event (terminal answer retained,
182
+ // artifact suppressed) instead of failing the whole Ask request.
183
+ const blockTypes = new Set(reference.blockTypes);
184
+ const hasDataPanel = reference.blockTypes.some((type) => ["kpi_card", "chart", "table"].includes(type));
185
+ if (!hasDataPanel || !blockTypes.has("definition")) {
186
+ this.renderState = "degraded";
187
+ return [];
188
+ }
189
+ this.renderState = "artifact";
190
+ this.renderArtifact = reference;
191
+ return [];
192
+ }
193
+ case "render_degraded":
194
+ if (this.component !== "generate_dashboard" ||
195
+ this.renderState !== undefined ||
196
+ this.finished.get("compose_layout") !== true ||
197
+ event.parentThreadId !== this.parentThreadId ||
198
+ event.parentTurnId !== this.parentTurnId ||
199
+ event.reason !== "invalid_render_envelope") {
200
+ throw new Error("warble-codex-local Ask emitted an invalid dashboard render degradation");
201
+ }
202
+ this.renderState = "degraded";
203
+ return [];
204
+ case "step_finished": {
205
+ const step = this.stepContract(event.step);
206
+ if (step === undefined || this.finished.has(step.name)) {
207
+ throw new Error("warble-codex-local Ask emitted an invalid step finish");
208
+ }
209
+ const expected = COMPONENT_STEPS[this.component][this.finished.size];
210
+ if (event.step !== expected?.name ||
211
+ !this.started.includes(step.name) ||
212
+ event.agentRole !== expectedRole(step.name) ||
213
+ event.agentThreadId !== this.agentThreads.get(step.name) ||
214
+ event.parentThreadId !== this.parentThreadId ||
215
+ event.parentTurnId !== this.parentTurnId) {
216
+ throw new Error("warble-codex-local Ask step completion order or attribution did not match the IR");
217
+ }
218
+ if (this.component === "generate_dashboard") {
219
+ const evidence = this.mcpEvidence.get(step.name);
220
+ if (evidence === undefined || evidence.count === 0) {
221
+ throw new Error(`warble-codex-local Ask step "${step.name}" finished without required Wren MCP evidence`);
222
+ }
223
+ if (event.ok !== evidence.allOk) {
224
+ throw new Error(`warble-codex-local Ask step "${step.name}" outcome contradicted its Wren MCP evidence`);
225
+ }
226
+ }
227
+ this.finished.set(step.name, event.ok);
228
+ return [{
229
+ kind: "step.finish",
230
+ stepId: event.step,
231
+ name: event.step,
232
+ status: event.ok ? "ok" : "error",
233
+ ...(!event.ok ? { detail: `${event.step} failed` } : {}),
234
+ }];
235
+ }
236
+ case "turn_completed":
237
+ if (!this.turnStarted ||
238
+ this.turnCompleted ||
239
+ event.turn?.status !== "completed" ||
240
+ event.turn.threadId !== this.parentThreadId ||
241
+ event.turn.turnId !== this.parentTurnId ||
242
+ this.finished.size !== this.started.length) {
243
+ throw new Error("warble-codex-local Ask emitted an invalid turn completion");
244
+ }
245
+ this.validateStepOutcome();
246
+ this.turnCompleted = true;
247
+ return [];
248
+ case "answer":
249
+ if (!this.turnCompleted || this.finalText !== undefined || typeof event.text !== "string" || !event.text.trim()) {
250
+ throw new Error("warble-codex-local Ask emitted an invalid terminal answer");
251
+ }
252
+ if (this.component === "generate_dashboard" && this.renderState === "artifact") {
253
+ this.validateDashboardAnswer(event.text);
254
+ }
255
+ this.finalText = this.component === "generate_dashboard" && this.renderState === "degraded"
256
+ ? degradedDashboardText(event.text)
257
+ : event.text;
258
+ return [{ kind: "answer", text: this.finalText }];
259
+ case "session_recoverable":
260
+ case "session_failed":
261
+ throw new Error(`warble-codex-local Ask session failed: ${event.reason}`);
262
+ default:
263
+ throw new Error("warble-codex-local Ask emitted an unknown event");
264
+ }
265
+ }
266
+ result() {
267
+ if (!this.sessionStarted || !this.turnStarted || !this.turnCompleted) {
268
+ throw new Error("warble-codex-local Ask ended with a partial lifecycle");
269
+ }
270
+ if (this.finalText === undefined) {
271
+ throw new Error("warble-codex-local Ask ended without a final answer");
272
+ }
273
+ return this.finalText;
274
+ }
275
+ validateStepOutcome() {
276
+ if (this.component === "generate_dashboard") {
277
+ if (this.finished.get("plan_dashboard") !== true ||
278
+ this.finished.get("compose_layout") !== true ||
279
+ this.started.length !== 2 ||
280
+ !this.hasSuccessfulDashboardEvidence() ||
281
+ this.renderState === undefined) {
282
+ throw new Error("warble-codex-local Ask did not complete the required dashboard steps and render contract");
283
+ }
284
+ return;
285
+ }
286
+ const resolveOk = this.finished.get("resolve_intent");
287
+ const generateOk = this.finished.get("generate_sql");
288
+ const repairOk = this.finished.get("repair_sql");
289
+ if (resolveOk !== true || generateOk === undefined) {
290
+ throw new Error("warble-codex-local Ask did not complete the required resolve/generate steps");
291
+ }
292
+ if (generateOk) {
293
+ if (repairOk !== undefined || this.started.length !== 2) {
294
+ throw new Error("warble-codex-local Ask ran repair after successful generation");
295
+ }
296
+ return;
297
+ }
298
+ if (repairOk !== true || this.started.length !== 3) {
299
+ throw new Error("warble-codex-local Ask did not complete its single bounded repair");
300
+ }
301
+ }
302
+ stepContract(value) {
303
+ return COMPONENT_STEPS[this.component].find((step) => step.name === value);
304
+ }
305
+ validateDashboardAnswer(text) {
306
+ let value;
307
+ try {
308
+ value = JSON.parse(text);
309
+ }
310
+ catch {
311
+ throw new Error("warble-codex-local Ask dashboard answer was not valid JSON");
312
+ }
313
+ if (!isDashboardEnvelope(value)) {
314
+ throw new Error("warble-codex-local Ask dashboard answer did not match its render artifact");
315
+ }
316
+ const blockTypes = value["blocks"].map((block) => isRecord(block) && typeof block["type"] === "string" ? block["type"] : "");
317
+ if (this.renderArtifact === undefined ||
318
+ (value["verified"] && !this.hasSuccessfulDashboardEvidence()) ||
319
+ value["verified"] !== this.renderArtifact.verified ||
320
+ JSON.stringify(blockTypes) !== JSON.stringify(this.renderArtifact.blockTypes)) {
321
+ throw new Error("warble-codex-local Ask dashboard answer did not match its render artifact");
322
+ }
323
+ }
324
+ hasSuccessfulDashboardEvidence() {
325
+ return this.mcpEvidence.size === 2 &&
326
+ this.mcpEvidence.get("plan_dashboard")?.allOk === true &&
327
+ this.mcpEvidence.get("compose_layout")?.allOk === true;
328
+ }
329
+ }
330
+ function isDashboardEnvelope(value) {
331
+ if (!isRecord(value) ||
332
+ !Array.isArray(value["blocks"]) ||
333
+ value["blocks"].length === 0 ||
334
+ typeof value["verified"] !== "boolean" ||
335
+ ("summary" in value && typeof value["summary"] !== "string")) {
336
+ return false;
337
+ }
338
+ let hasDataPanel = false;
339
+ let hasDefinition = false;
340
+ for (const block of value["blocks"]) {
341
+ if (!isRecord(block) || typeof block["type"] !== "string")
342
+ return false;
343
+ switch (block["type"]) {
344
+ case "kpi_card":
345
+ if (typeof block["label"] !== "string" ||
346
+ (typeof block["value"] !== "string" && typeof block["value"] !== "number") ||
347
+ ("unit" in block && typeof block["unit"] !== "string") ||
348
+ ("delta" in block && typeof block["delta"] !== "number"))
349
+ return false;
350
+ hasDataPanel = true;
351
+ break;
352
+ case "table":
353
+ if (!isStringArray(block["columns"]) || !isObjectArray(block["rows"]))
354
+ return false;
355
+ hasDataPanel = true;
356
+ break;
357
+ case "chart":
358
+ if (!["bar", "line", "pie", "area", "scatter"].includes(String(block["chart_type"])) ||
359
+ typeof block["x"] !== "string" ||
360
+ !isStringArray(block["series"]) ||
361
+ !isObjectArray(block["rows"]))
362
+ return false;
363
+ hasDataPanel = true;
364
+ break;
365
+ case "definition":
366
+ if (typeof block["sql"] !== "string" ||
367
+ !isStringArray(block["source_tables"]) ||
368
+ !isStringArray(block["filters"]))
369
+ return false;
370
+ hasDefinition = true;
371
+ break;
372
+ default:
373
+ return false;
374
+ }
375
+ }
376
+ return hasDataPanel && hasDefinition;
377
+ }
378
+ function isStringArray(value) {
379
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
380
+ }
381
+ function isObjectArray(value) {
382
+ return Array.isArray(value) && value.every(isRecord);
383
+ }
384
+ function degradedDashboardText(text) {
385
+ try {
386
+ const value = JSON.parse(text);
387
+ if (isRecord(value) && typeof value["summary"] === "string" && value["summary"].trim()) {
388
+ return value["summary"].trim();
389
+ }
390
+ }
391
+ catch {
392
+ // A degraded renderer may already have emitted a plain-text best effort.
393
+ }
394
+ return text;
395
+ }
@@ -0,0 +1,15 @@
1
+ import type { ResolvedCli } from "./agent-sdk-cli.js";
2
+ import { type CodexAskComponent, type CodexManifestModels } from "./codex-local-manifest.js";
3
+ import type { CodexAskOptions, CodexAskResult } from "./types.js";
4
+ export declare function buildCodexAskArgs(cli: ResolvedCli, options: {
5
+ readonly irPath: string;
6
+ readonly question: string;
7
+ readonly userProject: string;
8
+ readonly codexHome: string;
9
+ readonly models: CodexManifestModels;
10
+ readonly mcpServer: ResolvedCli;
11
+ readonly codexBin?: string;
12
+ readonly timeoutMs: number;
13
+ readonly component?: CodexAskComponent;
14
+ }): readonly string[];
15
+ export declare function runCodexAskDefault(options: CodexAskOptions): Promise<CodexAskResult>;