@wrenai/genbi 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/README.md +65 -3
  2. package/dist/assets/{echarts-LTFC-ysd.js → echarts-DYM4hjvk.js} +2 -2
  3. package/dist/assets/index-A_Wrq7Ey.css +1 -0
  4. package/dist/assets/{index-Bo--QMUN.js → index-DsH129tV.js} +18 -17
  5. package/dist/index.html +2 -2
  6. package/dist-server/harness/bundle/schema.d.ts +38 -0
  7. package/dist-server/harness/bundle/schema.js +18 -10
  8. package/dist-server/harness/bundle/version.js +1 -1
  9. package/dist-server/harness/cli-args.d.ts +10 -2
  10. package/dist-server/harness/cli-args.js +24 -8
  11. package/dist-server/harness/cli.js +75 -9
  12. package/dist-server/harness/compile/cache.js +4 -4
  13. package/dist-server/harness/compile/compose-profile.d.ts +51 -14
  14. package/dist-server/harness/compile/compose-profile.js +85 -19
  15. package/dist-server/harness/compile/context-loader.d.ts +56 -0
  16. package/dist-server/harness/compile/context-loader.js +237 -0
  17. package/dist-server/harness/compile/errors.d.ts +19 -0
  18. package/dist-server/harness/compile/errors.js +35 -0
  19. package/dist-server/harness/compile/index.d.ts +4 -3
  20. package/dist-server/harness/compile/index.js +4 -3
  21. package/dist-server/harness/compile/pipeline.d.ts +15 -7
  22. package/dist-server/harness/compile/pipeline.js +62 -14
  23. package/dist-server/harness/compile/resolve-binary.d.ts +2 -2
  24. package/dist-server/harness/compile/resolve-binary.js +3 -3
  25. package/dist-server/harness/compile/types.d.ts +29 -0
  26. package/dist-server/harness/compile/warble-identity.d.ts +11 -0
  27. package/dist-server/harness/compile/warble-identity.js +13 -0
  28. package/dist-server/harness/components/ai-step.d.ts +4 -0
  29. package/dist-server/harness/components/ai-step.js +40 -0
  30. package/dist-server/harness/components/broker.d.ts +60 -0
  31. package/dist-server/harness/components/broker.js +117 -0
  32. package/dist-server/harness/components/capability-card.d.ts +98 -0
  33. package/dist-server/harness/components/capability-card.js +169 -0
  34. package/dist-server/harness/components/context.d.ts +2 -0
  35. package/dist-server/harness/components/context.js +30 -0
  36. package/dist-server/harness/components/display.d.ts +6 -0
  37. package/dist-server/harness/components/display.js +29 -0
  38. package/dist-server/harness/components/egress-judge.d.ts +12 -0
  39. package/dist-server/harness/components/egress-judge.js +27 -0
  40. package/dist-server/harness/components/egress.d.ts +142 -0
  41. package/dist-server/harness/components/egress.js +469 -0
  42. package/dist-server/harness/components/in-process.d.ts +7 -0
  43. package/dist-server/harness/components/in-process.js +245 -0
  44. package/dist-server/harness/components/normalize.d.ts +35 -0
  45. package/dist-server/harness/components/normalize.js +245 -0
  46. package/dist-server/harness/components/plan.d.ts +31 -0
  47. package/dist-server/harness/components/plan.js +184 -0
  48. package/dist-server/harness/components/report.d.ts +207 -0
  49. package/dist-server/harness/components/report.js +309 -0
  50. package/dist-server/harness/components/runner.d.ts +193 -0
  51. package/dist-server/harness/components/runner.js +492 -0
  52. package/dist-server/harness/components/semantic-guards.d.ts +20 -0
  53. package/dist-server/harness/components/semantic-guards.js +42 -0
  54. package/dist-server/harness/components/terminal-json.d.ts +18 -0
  55. package/dist-server/harness/components/terminal-json.js +82 -0
  56. package/dist-server/harness/components/usage.d.ts +14 -0
  57. package/dist-server/harness/components/usage.js +19 -0
  58. package/dist-server/harness/components/wren-access.d.ts +29 -0
  59. package/dist-server/harness/components/wren-access.js +233 -0
  60. package/dist-server/harness/components/zone-dry-run.d.ts +43 -0
  61. package/dist-server/harness/components/zone-dry-run.js +107 -0
  62. package/dist-server/harness/components/zone-gate.d.ts +76 -0
  63. package/dist-server/harness/components/zone-gate.js +144 -0
  64. package/dist-server/harness/events/index.d.ts +1 -1
  65. package/dist-server/harness/events/types.d.ts +52 -0
  66. package/dist-server/harness/index.d.ts +9 -2
  67. package/dist-server/harness/index.js +5 -1
  68. package/dist-server/harness/loop/executor.d.ts +1 -0
  69. package/dist-server/harness/loop/executor.js +37 -15
  70. package/dist-server/harness/npm-package-resolve.d.ts +2 -0
  71. package/dist-server/harness/npm-package-resolve.js +16 -4
  72. package/dist-server/harness/providers/adapters/openai-compatible.d.ts +13 -0
  73. package/dist-server/harness/providers/adapters/openai-compatible.js +17 -0
  74. package/dist-server/harness/providers/adapters/openai.d.ts +7 -0
  75. package/dist-server/harness/providers/adapters/openai.js +6 -0
  76. package/dist-server/harness/providers/adapters/pi-ai.d.ts +48 -0
  77. package/dist-server/harness/providers/adapters/pi-ai.js +518 -0
  78. package/dist-server/harness/providers/binding.d.ts +45 -4
  79. package/dist-server/harness/providers/binding.js +44 -8
  80. package/dist-server/harness/providers/index.d.ts +9 -3
  81. package/dist-server/harness/providers/index.js +10 -3
  82. package/dist-server/harness/providers/zone.d.ts +96 -0
  83. package/dist-server/harness/providers/zone.js +112 -0
  84. package/dist-server/harness/render/answering-query.d.ts +29 -0
  85. package/dist-server/harness/render/answering-query.js +62 -0
  86. package/dist-server/harness/render/envelope.d.ts +6 -0
  87. package/dist-server/harness/render/envelope.js +10 -3
  88. package/dist-server/harness/route/adapter-spec.d.ts +8 -9
  89. package/dist-server/harness/route/adapter-spec.js +13 -14
  90. package/dist-server/harness/route/codex-ask-events.js +2 -1
  91. package/dist-server/harness/route/codex-ask.d.ts +4 -0
  92. package/dist-server/harness/route/codex-ask.js +43 -45
  93. package/dist-server/harness/route/codex-local-manifest.d.ts +9 -1
  94. package/dist-server/harness/route/codex-local-manifest.js +96 -15
  95. package/dist-server/harness/route/describe.js +45 -6
  96. package/dist-server/harness/route/dispatched.d.ts +20 -0
  97. package/dist-server/harness/route/dispatched.js +122 -24
  98. package/dist-server/harness/route/host-query.d.ts +93 -0
  99. package/dist-server/harness/route/host-query.js +257 -0
  100. package/dist-server/harness/route/in-process.d.ts +22 -1
  101. package/dist-server/harness/route/in-process.js +54 -4
  102. package/dist-server/harness/route/route.js +8 -2
  103. package/dist-server/harness/route/types.d.ts +47 -1
  104. package/dist-server/harness/route/wren-host-proxy.d.ts +33 -0
  105. package/dist-server/harness/route/wren-host-proxy.js +228 -0
  106. package/dist-server/harness/session/run.js +30 -10
  107. package/dist-server/harness/setup/runner.d.ts +17 -3
  108. package/dist-server/harness/setup/runner.js +272 -89
  109. package/dist-server/harness/setup/yaml-scalar.d.ts +23 -0
  110. package/dist-server/harness/setup/yaml-scalar.js +62 -0
  111. package/dist-server/harness/tools/setup-native.d.ts +7 -0
  112. package/dist-server/harness/tools/setup-native.js +7 -4
  113. package/dist-server/server/adopt.js +1 -17
  114. package/dist-server/server/app.d.ts +1 -0
  115. package/dist-server/server/app.js +175 -17
  116. package/dist-server/server/auth-choice.d.ts +13 -1
  117. package/dist-server/server/auth-choice.js +66 -1
  118. package/dist-server/server/bin.js +185 -25
  119. package/dist-server/server/codex-native-session.d.ts +25 -0
  120. package/dist-server/server/codex-native-session.js +1 -0
  121. package/dist-server/server/codex-runtime-composition.d.ts +34 -0
  122. package/dist-server/server/codex-runtime-composition.js +250 -0
  123. package/dist-server/server/codex-structured-ask.d.ts +23 -0
  124. package/dist-server/server/codex-structured-ask.js +102 -0
  125. package/dist-server/server/conn-config.js +4 -16
  126. package/dist-server/server/conversation-socket.d.ts +16 -0
  127. package/dist-server/server/conversation-socket.js +65 -0
  128. package/dist-server/server/db.d.ts +46 -0
  129. package/dist-server/server/db.js +88 -9
  130. package/dist-server/server/env-detect.d.ts +6 -0
  131. package/dist-server/server/env-detect.js +7 -0
  132. package/dist-server/server/fold.d.ts +23 -4
  133. package/dist-server/server/fold.js +42 -5
  134. package/dist-server/server/harness.d.ts +2 -2
  135. package/dist-server/server/harness.js +33 -7
  136. package/dist-server/server/host-evidence-grounding.d.ts +21 -0
  137. package/dist-server/server/host-evidence-grounding.js +93 -0
  138. package/dist-server/server/interactive-terminal.d.ts +10 -6
  139. package/dist-server/server/interactive-terminal.js +33 -8
  140. package/dist-server/server/managed-wren-runtime.d.ts +116 -0
  141. package/dist-server/server/managed-wren-runtime.js +670 -0
  142. package/dist-server/server/native-artifacts.d.ts +112 -7
  143. package/dist-server/server/native-artifacts.js +194 -14
  144. package/dist-server/server/native-component-context.d.ts +19 -0
  145. package/dist-server/server/native-component-context.js +76 -0
  146. package/dist-server/server/native-component-preparation.d.ts +20 -0
  147. package/dist-server/server/native-component-preparation.js +129 -0
  148. package/dist-server/server/native-component-runtime.d.ts +36 -0
  149. package/dist-server/server/native-component-runtime.js +92 -0
  150. package/dist-server/server/native-components.d.ts +84 -0
  151. package/dist-server/server/native-components.js +160 -0
  152. package/dist-server/server/native-dispatch-process.d.ts +8 -0
  153. package/dist-server/server/native-dispatch-process.js +65 -0
  154. package/dist-server/server/native-runtime-spec.d.ts +89 -0
  155. package/dist-server/server/native-runtime-spec.js +169 -0
  156. package/dist-server/server/native-sessions.d.ts +172 -19
  157. package/dist-server/server/native-sessions.js +839 -244
  158. package/dist-server/server/native-shutdown.d.ts +6 -0
  159. package/dist-server/server/native-shutdown.js +28 -0
  160. package/dist-server/server/native-wren-home.d.ts +18 -0
  161. package/dist-server/server/native-wren-home.js +262 -0
  162. package/dist-server/server/node-pty-host.d.ts +2 -1
  163. package/dist-server/server/node-pty-host.js +3 -2
  164. package/dist-server/server/profile-registry.d.ts +139 -0
  165. package/dist-server/server/profile-registry.js +620 -0
  166. package/dist-server/server/runtime-binding.d.ts +4 -1
  167. package/dist-server/server/runtime-binding.js +50 -2
  168. package/dist-server/server/runtime-host/claude-component-step.d.ts +25 -0
  169. package/dist-server/server/runtime-host/claude-component-step.js +186 -0
  170. package/dist-server/server/runtime-host/codex-app-server.d.ts +75 -0
  171. package/dist-server/server/runtime-host/codex-app-server.js +239 -0
  172. package/dist-server/server/runtime-host/codex-compatibility.d.ts +110 -0
  173. package/dist-server/server/runtime-host/codex-compatibility.js +162 -0
  174. package/dist-server/server/runtime-host/codex-component-step.d.ts +19 -0
  175. package/dist-server/server/runtime-host/codex-component-step.js +308 -0
  176. package/dist-server/server/runtime-host/codex-conversation.d.ts +109 -0
  177. package/dist-server/server/runtime-host/codex-conversation.js +295 -0
  178. package/dist-server/server/runtime-host/codex-direct-tools.d.ts +23 -0
  179. package/dist-server/server/runtime-host/codex-direct-tools.js +59 -0
  180. package/dist-server/server/runtime-host/codex-events.d.ts +647 -0
  181. package/dist-server/server/runtime-host/codex-events.js +66 -0
  182. package/dist-server/server/runtime-host/codex-policy.d.ts +16 -0
  183. package/dist-server/server/runtime-host/codex-policy.js +151 -0
  184. package/dist-server/server/runtime-host/codex-process.d.ts +8 -0
  185. package/dist-server/server/runtime-host/codex-process.js +96 -0
  186. package/dist-server/server/runtime-host/codex-rpc.d.ts +47 -0
  187. package/dist-server/server/runtime-host/codex-rpc.js +182 -0
  188. package/dist-server/server/runtime-host/codex-session.d.ts +74 -0
  189. package/dist-server/server/runtime-host/codex-session.js +492 -0
  190. package/dist-server/server/runtime-host/codex-terminal-protocol.d.ts +35 -0
  191. package/dist-server/server/runtime-host/codex-terminal-protocol.js +243 -0
  192. package/dist-server/server/runtime-host/codex-terminal.d.ts +16 -0
  193. package/dist-server/server/runtime-host/codex-terminal.js +120 -0
  194. package/dist-server/server/runtime-host/index.d.ts +5 -0
  195. package/dist-server/server/runtime-host/index.js +3 -0
  196. package/dist-server/server/runtime-host/local.d.ts +29 -0
  197. package/dist-server/server/runtime-host/local.js +90 -0
  198. package/dist-server/server/runtime-host/policy.d.ts +8 -0
  199. package/dist-server/server/runtime-host/policy.js +78 -0
  200. package/dist-server/server/runtime-host/types.d.ts +52 -0
  201. package/dist-server/server/runtime-host/types.js +62 -0
  202. package/dist-server/server/structured-query-evidence.d.ts +7 -0
  203. package/dist-server/server/structured-query-evidence.js +47 -0
  204. package/dist-server/server/structured-runtime.d.ts +52 -0
  205. package/dist-server/server/structured-runtime.js +130 -0
  206. package/dist-server/server/structured-scope.d.ts +4 -0
  207. package/dist-server/server/structured-scope.js +12 -0
  208. package/dist-server/server/turn.d.ts +6 -1
  209. package/dist-server/server/turn.js +86 -26
  210. package/dist-server/server/wire-types.d.ts +67 -3
  211. package/dist-server/server/wren-profiles.js +1 -1
  212. package/managed-wren/README.md +60 -0
  213. package/managed-wren/dependency-wheels.json +282 -0
  214. package/managed-wren/manifest.json +373 -0
  215. package/managed-wren/release-inputs.json +45 -0
  216. package/managed-wren/runtime-tree.cjs +115 -0
  217. package/managed-wren/source-inputs.json +40 -0
  218. package/package.json +15 -6
  219. package/profiles/genbi-default/context/binding.yml +17 -7
  220. package/profiles/genbi-default/context/context.json +146 -0
  221. package/profiles/genbi-default/ir.golden.json +39 -43
  222. package/profiles/genbi-default/profile.yml +31 -0
  223. package/profiles/genbi-enrich-context/context/binding.yml +14 -3
  224. package/profiles/genbi-enrich-context/context/context.json +146 -0
  225. package/profiles/genbi-enrich-context/ir.golden.json +4 -5
  226. package/profiles/genbi-monitor/context/binding.yml +13 -5
  227. package/profiles/genbi-monitor/context/context.json +146 -0
  228. package/profiles/genbi-monitor/ir.golden.json +13 -7
  229. package/profiles/genbi-report/context/binding.yml +19 -0
  230. package/profiles/genbi-report/context/context.json +223 -0
  231. package/profiles/genbi-report/ir.golden.json +328 -0
  232. package/profiles/genbi-report/profile.yml +38 -0
  233. package/profiles/genbi-setup/ir.golden.json +3 -1
  234. package/dist/assets/index-Xs4q7pNo.css +0 -1
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * The Wren MCP server of a subscription Ask turn (codex:local, and the Claude agent-sdk host MCP):
4
+ * a stdio proxy in front of `wren serve mcp`.
5
+ *
6
+ * node wren-host-proxy.js --credential-file <abs path> -- <wren> serve mcp --project <p> --quiet
7
+ *
8
+ * Every JSON-RPC line passes through to the child `wren serve mcp` unchanged, so the model sees
9
+ * the same tool names and schemas, except a `tools/call` of `run_sql`: that goes to this turn's
10
+ * host query service (see `host-query.ts`), which executes it through governed access and
11
+ * records it as host evidence. The credential file (0600, owned by this user) names the turn's
12
+ * unix socket and token; without a valid one, `run_sql` is refused rather than run elsewhere.
13
+ *
14
+ * Node builtins only, and erasable TypeScript only, so it also runs from source.
15
+ */
16
+ import { spawn } from "node:child_process";
17
+ import { closeSync, constants as fsConstants, fstatSync, openSync, readFileSync, realpathSync } from "node:fs";
18
+ import { connect } from "node:net";
19
+ import path from "node:path";
20
+ import { createInterface } from "node:readline";
21
+ import { fileURLToPath } from "node:url";
22
+ const RUN_SQL = "run_sql";
23
+ const MAX_SQL_BYTES = 65_536;
24
+ /** The sentence the model sees per host error class; nothing from the host's wire is forwarded. */
25
+ const ERROR_TEXT = {
26
+ invalid_request: "The request did not match the governed run_sql contract: pass a non-empty sql string and an optional positive integer limit.",
27
+ model_not_found: "The query references a table that is not a model in the bound semantic context; query only the models it defines.",
28
+ policy_rejected: "The read-only analytical policy rejected the query: use one SELECT that reads at least one bound model.",
29
+ invalid_sql: "The SQL could not be parsed or planned against the semantic context.",
30
+ execution_failed: "The data source rejected the query at execution time, for example an unknown column or a type mismatch.",
31
+ timeout: "The query exceeded the statement time limit.",
32
+ datasource_unavailable: "The bound data source could not be reached.",
33
+ result_too_large: "The result exceeded the governed byte limit; narrow the query.",
34
+ budget_exhausted: "This turn's query budget is exhausted; answer from the results you already have.",
35
+ unauthorized: "run_sql is unavailable: the host query service rejected this session.",
36
+ internal: "The governed query failed for an unclassified reason.",
37
+ transport: "The host query service is unavailable.",
38
+ };
39
+ const NO_CREDENTIAL = "run_sql is unavailable: no valid host query credential was provided for this turn.";
40
+ /**
41
+ * Accepts only an absolute, regular, user-owned file no one else can read or write. The file is
42
+ * opened without following a symlink and checked and read through that one descriptor, so what
43
+ * is checked is what is read.
44
+ */
45
+ export function readCredential(file) {
46
+ if (!file || !path.isAbsolute(file))
47
+ return undefined;
48
+ let fd;
49
+ try {
50
+ fd = openSync(file, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
51
+ const stat = fstatSync(fd);
52
+ if (!stat.isFile() || (stat.mode & 0o077) !== 0)
53
+ return undefined;
54
+ if (typeof process.getuid === "function" && stat.uid !== process.getuid())
55
+ return undefined;
56
+ const value = JSON.parse(readFileSync(fd, "utf8"));
57
+ if (typeof value.socket !== "string" || !path.isAbsolute(value.socket))
58
+ return undefined;
59
+ if (typeof value.token !== "string" || value.token.length < 32)
60
+ return undefined;
61
+ return { socket: value.socket, token: value.token };
62
+ }
63
+ catch {
64
+ return undefined;
65
+ }
66
+ finally {
67
+ if (fd !== undefined)
68
+ closeSync(fd);
69
+ }
70
+ }
71
+ /**
72
+ * One connection at a time to the turn's host query service, reconnecting after a drop. Only
73
+ * the current socket's failure fails the pending requests (all of which were sent on it): a
74
+ * stale socket closing late never fails a request pending on its replacement. Each socket has
75
+ * its own read buffer.
76
+ */
77
+ export class HostConnection {
78
+ credential;
79
+ open;
80
+ pending = new Map();
81
+ socket;
82
+ nextId = 1;
83
+ constructor(credential, open = connect) {
84
+ this.credential = credential;
85
+ this.open = open;
86
+ }
87
+ request(sql, limit) {
88
+ return new Promise((resolve) => {
89
+ const id = this.nextId++;
90
+ try {
91
+ const socket = this.current();
92
+ this.pending.set(id, resolve);
93
+ socket.write(`${JSON.stringify({ token: this.credential.token, id, sql, ...(limit !== undefined ? { limit } : {}) })}\n`);
94
+ }
95
+ catch {
96
+ this.pending.delete(id);
97
+ resolve({ error: "transport" });
98
+ }
99
+ });
100
+ }
101
+ close() {
102
+ this.socket?.end();
103
+ }
104
+ current() {
105
+ if (this.socket && !this.socket.destroyed)
106
+ return this.socket;
107
+ const socket = this.open(this.credential.socket);
108
+ let buffer = "";
109
+ const fail = () => {
110
+ if (this.socket !== socket)
111
+ return;
112
+ this.socket = undefined;
113
+ for (const waiter of this.pending.values())
114
+ waiter({ error: "transport" });
115
+ this.pending.clear();
116
+ };
117
+ socket.setEncoding("utf8");
118
+ socket.on("data", (chunk) => {
119
+ buffer += chunk;
120
+ let newline = buffer.indexOf("\n");
121
+ while (newline >= 0) {
122
+ const line = buffer.slice(0, newline);
123
+ buffer = buffer.slice(newline + 1);
124
+ newline = buffer.indexOf("\n");
125
+ try {
126
+ const frame = JSON.parse(line);
127
+ const waiter = typeof frame.id === "number" ? this.pending.get(frame.id) : undefined;
128
+ if (!waiter || typeof frame.id !== "number")
129
+ continue;
130
+ this.pending.delete(frame.id);
131
+ if (frame.error !== undefined)
132
+ waiter({ error: typeof frame.error?.class === "string" ? frame.error.class : "internal" });
133
+ else
134
+ waiter({ result: frame.result });
135
+ }
136
+ catch {
137
+ socket.destroy();
138
+ }
139
+ }
140
+ });
141
+ socket.on("error", fail);
142
+ socket.on("close", fail);
143
+ this.socket = socket;
144
+ return socket;
145
+ }
146
+ }
147
+ function parseArgs(argv) {
148
+ const separator = argv.indexOf("--");
149
+ if (separator < 0 || separator === argv.length - 1) {
150
+ process.stderr.write("wren host proxy: usage: --credential-file <path> -- <command> [args...]\n");
151
+ process.exit(2);
152
+ }
153
+ const own = argv.slice(0, separator);
154
+ const index = own.indexOf("--credential-file");
155
+ const credentialFile = index >= 0 ? own[index + 1] : undefined;
156
+ return { ...(credentialFile !== undefined ? { credentialFile } : {}), command: argv[separator + 1], args: argv.slice(separator + 2) };
157
+ }
158
+ function main() {
159
+ const options = parseArgs(process.argv.slice(2));
160
+ const credential = readCredential(options.credentialFile);
161
+ const host = credential ? new HostConnection(credential) : undefined;
162
+ const child = spawn(options.command, options.args, { stdio: ["pipe", "pipe", "inherit"] });
163
+ child.on("error", (error) => {
164
+ process.stderr.write(`wren host proxy: could not start the Wren MCP server: ${error.message}\n`);
165
+ process.exit(1);
166
+ });
167
+ child.on("exit", (code, signal) => process.exit(code ?? (signal ? 1 : 0)));
168
+ const send = (line) => { process.stdout.write(`${line}\n`); };
169
+ createInterface({ input: child.stdout, crlfDelay: Infinity }).on("line", send);
170
+ const toolResult = (id, text, isError, structured) => {
171
+ send(JSON.stringify({ jsonrpc: "2.0", id, result: {
172
+ content: [{ type: "text", text }],
173
+ ...(structured !== undefined ? { structuredContent: structured } : {}),
174
+ isError,
175
+ } }));
176
+ };
177
+ const runSql = async (id, input) => {
178
+ if (!host) {
179
+ toolResult(id, NO_CREDENTIAL, true);
180
+ return;
181
+ }
182
+ const args = typeof input === "object" && input !== null && !Array.isArray(input) ? input : {};
183
+ const { sql, limit } = args;
184
+ if (typeof sql !== "string" || !sql.trim() || Buffer.byteLength(sql) > MAX_SQL_BYTES
185
+ || (limit !== undefined && limit !== null && (typeof limit !== "number" || !Number.isInteger(limit) || limit < 1))) {
186
+ toolResult(id, ERROR_TEXT.invalid_request, true);
187
+ return;
188
+ }
189
+ const outcome = await host.request(sql, typeof limit === "number" ? limit : undefined);
190
+ if (outcome.error !== undefined) {
191
+ const known = outcome.error in ERROR_TEXT ? outcome.error : "internal";
192
+ toolResult(id, `Governed Wren query failed [${known}]: ${ERROR_TEXT[known]}`, true);
193
+ return;
194
+ }
195
+ toolResult(id, JSON.stringify(outcome.result), false, outcome.result);
196
+ };
197
+ createInterface({ input: process.stdin, crlfDelay: Infinity })
198
+ .on("line", (line) => {
199
+ let message;
200
+ try {
201
+ message = JSON.parse(line);
202
+ }
203
+ catch {
204
+ message = undefined;
205
+ }
206
+ if (message && message.method === "tools/call" && message.id !== undefined && message.params?.name === RUN_SQL) {
207
+ void runSql(message.id, message.params.arguments);
208
+ return;
209
+ }
210
+ child.stdin.write(`${line}\n`);
211
+ })
212
+ .on("close", () => {
213
+ child.stdin.end();
214
+ host?.close();
215
+ });
216
+ }
217
+ function invokedDirectly() {
218
+ if (process.argv[1] === undefined)
219
+ return false;
220
+ try {
221
+ return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));
222
+ }
223
+ catch {
224
+ return false;
225
+ }
226
+ }
227
+ if (invokedDirectly())
228
+ main();
@@ -4,6 +4,7 @@ import { createLocalExecutionEnv } from "../exec/index.js";
4
4
  import { deriveEnforcement } from "../guardrails/index.js";
5
5
  import { executeAgent, summarizeToolOutput } from "../loop/index.js";
6
6
  import { getAllowedBlockTypes, renderEnvelope } from "../render/index.js";
7
+ import { selectAnsweringCandidate } from "../render/answering-query.js";
7
8
  import { BUILD_DASHBOARD_TOOL_NAME, WREN_QUERY_TOOL_NAME, withResolvedTools } from "../tools/index.js";
8
9
  import { UnknownAgentError } from "./errors.js";
9
10
  import { findLockedGatedCheck } from "./gate.js";
@@ -23,11 +24,16 @@ import { findLockedGatedCheck } from "./gate.js";
23
24
  * becomes a `RefusalResult`.
24
25
  */
25
26
  export async function runAgent(bundle, agentId, userInput, ctx) {
27
+ if (bundle.vercel_bundle_version === "0.2")
28
+ throw new Error("Composed plans require the component host runner");
26
29
  assertCapabilities(bundle, ctx.capabilityRegistry);
27
30
  const agent = bundle.agents.find((candidate) => candidate.id === agentId);
28
31
  if (!agent) {
29
32
  throw new UnknownAgentError(agentId);
30
33
  }
34
+ if (agent.entrypoint === false || (agent.dependencies?.length ?? 0) > 0 || bundle.manifest_version === "0.3") {
35
+ throw new Error("This manifest requires its owning component runtime");
36
+ }
31
37
  const emitter = createAgentEventEmitter(ctx.onEvent);
32
38
  emitter.emit({ kind: "run.start", mode: "A", agentId });
33
39
  try {
@@ -50,15 +56,16 @@ export async function runAgent(bundle, agentId, userInput, ctx) {
50
56
  // forced to a refusal by this check.
51
57
  let sawSuccessfulDataAccessCall = false;
52
58
  const requiresDataAccess = agent.capabilities.some((entry) => entry.capability.startsWith("sql_execution:"));
53
- // Deterministic table capture: the most recent *successful* `query`
54
- // tool result, kept as a flat table payload (columns + positional
55
- // rows + the SQL that produced it). This is the agent's real data —
56
- // `renderEnvelope` builds the table/definition blocks straight from
57
- // it instead of asking the render model to re-emit structure it tends
58
- // to summarize away (leaving a bare `{type:"table"}`). The last
59
- // success wins because, in the answer_query flow, it is the query
60
- // whose rows are the answer.
61
- let toolTable;
59
+ // Deterministic table capture: every *successful* `query` tool result,
60
+ // kept as a flat table payload (columns + positional rows + the SQL that
61
+ // produced it). This is the agent's real data — `renderEnvelope` builds
62
+ // the table/definition blocks straight from it instead of asking the
63
+ // render model to re-emit structure it tends to summarize away (leaving
64
+ // a bare `{type:"table"}`). Which capture is the answer is decided after
65
+ // the loop (see `selectAnsweringCandidate`): the one whose SQL the
66
+ // terminal artifact names, because a model that runs a stray check after
67
+ // the right query must not turn that check into a verified answer.
68
+ const toolTables = [];
62
69
  // Deterministic dashboard-envelope capture: the most recent
63
70
  // *successful* `build_dashboard` tool result, kept as-is (it's
64
71
  // already a complete, ordered `{blocks}` envelope — see
@@ -110,7 +117,7 @@ export async function runAgent(bundle, agentId, userInput, ctx) {
110
117
  sawSuccessfulDataAccessCall = true;
111
118
  const seed = toToolTableSeed(outcome.output, outcome.input);
112
119
  if (seed !== undefined)
113
- toolTable = seed;
120
+ toolTables.push(seed);
114
121
  }
115
122
  if (outcome.tool === BUILD_DASHBOARD_TOOL_NAME && outcome.outcome === "success") {
116
123
  const seed = toDashboardSeed(outcome.output);
@@ -124,6 +131,7 @@ export async function runAgent(bundle, agentId, userInput, ctx) {
124
131
  },
125
132
  onEvent: emitter.emit,
126
133
  });
134
+ const toolTable = selectAnsweringCandidate(toolTables, terminalArtifactValue(artifacts));
127
135
  const envelope = await renderEnvelope(agent, artifacts, {
128
136
  binding: ctx.binding,
129
137
  registry: ctx.registry,
@@ -278,6 +286,18 @@ export async function runAgent(bundle, agentId, userInput, ctx) {
278
286
  throw error;
279
287
  }
280
288
  }
289
+ /** The last dataflow artifact as a value: JSON text is parsed so a named `definition.sql` is visible. */
290
+ function terminalArtifactValue(artifacts) {
291
+ const last = [...artifacts.values()].at(-1);
292
+ if (typeof last !== "string")
293
+ return last;
294
+ try {
295
+ return JSON.parse(last);
296
+ }
297
+ catch {
298
+ return last;
299
+ }
300
+ }
281
301
  function describeRunError(error) {
282
302
  if (error instanceof Error)
283
303
  return error.message;
@@ -18,6 +18,8 @@ export declare const BUILD_CONTEXT_AGENT_ID = "build_context";
18
18
  */
19
19
  export declare const DEFAULT_SETUP_MAX_TURNS = 120;
20
20
  export interface SetupStepRunOptions {
21
+ /** Owned turn cancellation, forwarded to the selected runtime. */
22
+ readonly signal?: AbortSignal;
21
23
  /** The composed single-line prompt (see `composeSetupPrompt`). */
22
24
  readonly prompt: string;
23
25
  /** The workspace root the initial connect turn scaffolds `<name>/` into. */
@@ -421,6 +423,15 @@ export interface HostContractDiagnostic {
421
423
  /** The concrete artifact/workflow conditions that must be true before another claimed success. */
422
424
  readonly expectedArtifactContract: readonly string[];
423
425
  }
426
+ /**
427
+ * Where the bound project lives, so a recorded command's optional
428
+ * `cd <dir> &&` prefix can be resolved against it. Absent binding means the
429
+ * prefix cannot be verified and is not accepted.
430
+ */
431
+ export interface ProjectBinding {
432
+ readonly root: string;
433
+ readonly projectDir: string;
434
+ }
424
435
  export type RecordedSchemaDiscovery = {
425
436
  readonly kind: "successful";
426
437
  readonly command: string;
@@ -439,7 +450,7 @@ export type RecordedSchemaDiscovery = {
439
450
  * this for both terminal acceptance and the no-introspection diagnostic,
440
451
  * rather than reimplementing the allowlist elsewhere.
441
452
  */
442
- export declare function classifyRecordedSchemaDiscovery(worklog: readonly SetupWorklogEntry[]): RecordedSchemaDiscovery;
453
+ export declare function classifyRecordedSchemaDiscovery(worklog: readonly SetupWorklogEntry[], binding?: ProjectBinding): RecordedSchemaDiscovery;
443
454
  /** Ordered, host-recorded progress; each value includes all preceding work. */
444
455
  export type ContextLifecyclePrefix = "none" | "discovery" | "validate" | "build";
445
456
  export type RecordedContextLifecycle = {
@@ -449,12 +460,15 @@ export type RecordedContextLifecycle = {
449
460
  } | {
450
461
  readonly kind: "validate_missing";
451
462
  readonly observed: string;
463
+ readonly unrecognised?: string;
452
464
  } | {
453
465
  readonly kind: "build_missing";
454
466
  readonly observed: string;
467
+ readonly unrecognised?: string;
455
468
  } | {
456
469
  readonly kind: "out_of_order";
457
470
  readonly observed: string;
471
+ readonly unrecognised?: string;
458
472
  };
459
473
  /**
460
474
  * Returns the greatest ordered prefix proved by the supplied successful tool
@@ -462,8 +476,8 @@ export type RecordedContextLifecycle = {
462
476
  * call in the same attempt is out of order, so a corrective attempt can ask
463
477
  * only for the unproven suffix.
464
478
  */
465
- export declare function recordedContextLifecyclePrefix(worklog: readonly SetupWorklogEntry[], prior?: ContextLifecyclePrefix): ContextLifecyclePrefix;
466
- export declare function classifyRecordedContextLifecycle(worklog: readonly SetupWorklogEntry[], prior?: ContextLifecyclePrefix): RecordedContextLifecycle;
479
+ export declare function recordedContextLifecyclePrefix(worklog: readonly SetupWorklogEntry[], prior?: ContextLifecyclePrefix, binding?: ProjectBinding): ContextLifecyclePrefix;
480
+ export declare function classifyRecordedContextLifecycle(worklog: readonly SetupWorklogEntry[], prior?: ContextLifecyclePrefix, binding?: ProjectBinding): RecordedContextLifecycle;
467
481
  /**
468
482
  * Parses the LAST `SETUP_STATUS: ok|needs_input|error` line out of a setup
469
483
  * turn's finalText (the terminal contract lives in the composed