@wrenai/genbi 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -3
- package/dist/assets/{echarts-LTFC-ysd.js → echarts-DYM4hjvk.js} +2 -2
- package/dist/assets/index-A_Wrq7Ey.css +1 -0
- package/dist/assets/{index-Bo--QMUN.js → index-DsH129tV.js} +18 -17
- package/dist/index.html +2 -2
- package/dist-server/harness/bundle/schema.d.ts +38 -0
- package/dist-server/harness/bundle/schema.js +18 -10
- package/dist-server/harness/bundle/version.js +1 -1
- package/dist-server/harness/cli-args.d.ts +10 -2
- package/dist-server/harness/cli-args.js +24 -8
- package/dist-server/harness/cli.js +75 -9
- package/dist-server/harness/compile/cache.js +4 -4
- package/dist-server/harness/compile/compose-profile.d.ts +51 -14
- package/dist-server/harness/compile/compose-profile.js +85 -19
- package/dist-server/harness/compile/context-loader.d.ts +56 -0
- package/dist-server/harness/compile/context-loader.js +237 -0
- package/dist-server/harness/compile/errors.d.ts +19 -0
- package/dist-server/harness/compile/errors.js +35 -0
- package/dist-server/harness/compile/index.d.ts +4 -3
- package/dist-server/harness/compile/index.js +4 -3
- package/dist-server/harness/compile/pipeline.d.ts +15 -7
- package/dist-server/harness/compile/pipeline.js +62 -14
- package/dist-server/harness/compile/resolve-binary.d.ts +2 -2
- package/dist-server/harness/compile/resolve-binary.js +3 -3
- package/dist-server/harness/compile/types.d.ts +29 -0
- package/dist-server/harness/compile/warble-identity.d.ts +11 -0
- package/dist-server/harness/compile/warble-identity.js +13 -0
- package/dist-server/harness/components/ai-step.d.ts +4 -0
- package/dist-server/harness/components/ai-step.js +40 -0
- package/dist-server/harness/components/broker.d.ts +60 -0
- package/dist-server/harness/components/broker.js +117 -0
- package/dist-server/harness/components/capability-card.d.ts +98 -0
- package/dist-server/harness/components/capability-card.js +169 -0
- package/dist-server/harness/components/context.d.ts +2 -0
- package/dist-server/harness/components/context.js +30 -0
- package/dist-server/harness/components/display.d.ts +6 -0
- package/dist-server/harness/components/display.js +29 -0
- package/dist-server/harness/components/egress-judge.d.ts +12 -0
- package/dist-server/harness/components/egress-judge.js +27 -0
- package/dist-server/harness/components/egress.d.ts +142 -0
- package/dist-server/harness/components/egress.js +469 -0
- package/dist-server/harness/components/in-process.d.ts +7 -0
- package/dist-server/harness/components/in-process.js +245 -0
- package/dist-server/harness/components/normalize.d.ts +35 -0
- package/dist-server/harness/components/normalize.js +245 -0
- package/dist-server/harness/components/plan.d.ts +31 -0
- package/dist-server/harness/components/plan.js +184 -0
- package/dist-server/harness/components/report.d.ts +207 -0
- package/dist-server/harness/components/report.js +309 -0
- package/dist-server/harness/components/runner.d.ts +193 -0
- package/dist-server/harness/components/runner.js +492 -0
- package/dist-server/harness/components/semantic-guards.d.ts +20 -0
- package/dist-server/harness/components/semantic-guards.js +42 -0
- package/dist-server/harness/components/terminal-json.d.ts +18 -0
- package/dist-server/harness/components/terminal-json.js +82 -0
- package/dist-server/harness/components/usage.d.ts +14 -0
- package/dist-server/harness/components/usage.js +19 -0
- package/dist-server/harness/components/wren-access.d.ts +29 -0
- package/dist-server/harness/components/wren-access.js +233 -0
- package/dist-server/harness/components/zone-dry-run.d.ts +43 -0
- package/dist-server/harness/components/zone-dry-run.js +107 -0
- package/dist-server/harness/components/zone-gate.d.ts +76 -0
- package/dist-server/harness/components/zone-gate.js +144 -0
- package/dist-server/harness/events/index.d.ts +1 -1
- package/dist-server/harness/events/types.d.ts +52 -0
- package/dist-server/harness/index.d.ts +9 -2
- package/dist-server/harness/index.js +5 -1
- package/dist-server/harness/loop/executor.d.ts +1 -0
- package/dist-server/harness/loop/executor.js +37 -15
- package/dist-server/harness/npm-package-resolve.d.ts +2 -0
- package/dist-server/harness/npm-package-resolve.js +16 -4
- package/dist-server/harness/providers/adapters/openai-compatible.d.ts +13 -0
- package/dist-server/harness/providers/adapters/openai-compatible.js +17 -0
- package/dist-server/harness/providers/adapters/openai.d.ts +7 -0
- package/dist-server/harness/providers/adapters/openai.js +6 -0
- package/dist-server/harness/providers/adapters/pi-ai.d.ts +48 -0
- package/dist-server/harness/providers/adapters/pi-ai.js +518 -0
- package/dist-server/harness/providers/binding.d.ts +45 -4
- package/dist-server/harness/providers/binding.js +44 -8
- package/dist-server/harness/providers/index.d.ts +9 -3
- package/dist-server/harness/providers/index.js +10 -3
- package/dist-server/harness/providers/zone.d.ts +96 -0
- package/dist-server/harness/providers/zone.js +112 -0
- package/dist-server/harness/render/answering-query.d.ts +29 -0
- package/dist-server/harness/render/answering-query.js +62 -0
- package/dist-server/harness/render/envelope.d.ts +6 -0
- package/dist-server/harness/render/envelope.js +10 -3
- package/dist-server/harness/route/adapter-spec.d.ts +8 -9
- package/dist-server/harness/route/adapter-spec.js +13 -14
- package/dist-server/harness/route/codex-ask-events.js +2 -1
- package/dist-server/harness/route/codex-ask.d.ts +4 -0
- package/dist-server/harness/route/codex-ask.js +43 -45
- package/dist-server/harness/route/codex-local-manifest.d.ts +9 -1
- package/dist-server/harness/route/codex-local-manifest.js +96 -15
- package/dist-server/harness/route/describe.js +45 -6
- package/dist-server/harness/route/dispatched.d.ts +20 -0
- package/dist-server/harness/route/dispatched.js +122 -24
- package/dist-server/harness/route/host-query.d.ts +93 -0
- package/dist-server/harness/route/host-query.js +257 -0
- package/dist-server/harness/route/in-process.d.ts +22 -1
- package/dist-server/harness/route/in-process.js +54 -4
- package/dist-server/harness/route/route.js +8 -2
- package/dist-server/harness/route/types.d.ts +47 -1
- package/dist-server/harness/route/wren-host-proxy.d.ts +33 -0
- package/dist-server/harness/route/wren-host-proxy.js +228 -0
- package/dist-server/harness/session/run.js +30 -10
- package/dist-server/harness/setup/runner.d.ts +17 -3
- package/dist-server/harness/setup/runner.js +272 -89
- package/dist-server/harness/setup/yaml-scalar.d.ts +23 -0
- package/dist-server/harness/setup/yaml-scalar.js +62 -0
- package/dist-server/harness/tools/setup-native.d.ts +7 -0
- package/dist-server/harness/tools/setup-native.js +7 -4
- package/dist-server/server/adopt.js +1 -17
- package/dist-server/server/app.d.ts +1 -0
- package/dist-server/server/app.js +175 -17
- package/dist-server/server/auth-choice.d.ts +13 -1
- package/dist-server/server/auth-choice.js +66 -1
- package/dist-server/server/bin.js +185 -25
- package/dist-server/server/codex-native-session.d.ts +25 -0
- package/dist-server/server/codex-native-session.js +1 -0
- package/dist-server/server/codex-runtime-composition.d.ts +34 -0
- package/dist-server/server/codex-runtime-composition.js +250 -0
- package/dist-server/server/codex-structured-ask.d.ts +23 -0
- package/dist-server/server/codex-structured-ask.js +102 -0
- package/dist-server/server/conn-config.js +4 -16
- package/dist-server/server/conversation-socket.d.ts +16 -0
- package/dist-server/server/conversation-socket.js +65 -0
- package/dist-server/server/db.d.ts +46 -0
- package/dist-server/server/db.js +88 -9
- package/dist-server/server/env-detect.d.ts +6 -0
- package/dist-server/server/env-detect.js +7 -0
- package/dist-server/server/fold.d.ts +23 -4
- package/dist-server/server/fold.js +42 -5
- package/dist-server/server/harness.d.ts +2 -2
- package/dist-server/server/harness.js +33 -7
- package/dist-server/server/host-evidence-grounding.d.ts +21 -0
- package/dist-server/server/host-evidence-grounding.js +93 -0
- package/dist-server/server/interactive-terminal.d.ts +10 -6
- package/dist-server/server/interactive-terminal.js +33 -8
- package/dist-server/server/managed-wren-runtime.d.ts +116 -0
- package/dist-server/server/managed-wren-runtime.js +670 -0
- package/dist-server/server/native-artifacts.d.ts +112 -7
- package/dist-server/server/native-artifacts.js +194 -14
- package/dist-server/server/native-component-context.d.ts +19 -0
- package/dist-server/server/native-component-context.js +76 -0
- package/dist-server/server/native-component-preparation.d.ts +20 -0
- package/dist-server/server/native-component-preparation.js +129 -0
- package/dist-server/server/native-component-runtime.d.ts +36 -0
- package/dist-server/server/native-component-runtime.js +92 -0
- package/dist-server/server/native-components.d.ts +84 -0
- package/dist-server/server/native-components.js +160 -0
- package/dist-server/server/native-dispatch-process.d.ts +8 -0
- package/dist-server/server/native-dispatch-process.js +65 -0
- package/dist-server/server/native-runtime-spec.d.ts +89 -0
- package/dist-server/server/native-runtime-spec.js +169 -0
- package/dist-server/server/native-sessions.d.ts +172 -19
- package/dist-server/server/native-sessions.js +839 -244
- package/dist-server/server/native-shutdown.d.ts +6 -0
- package/dist-server/server/native-shutdown.js +28 -0
- package/dist-server/server/native-wren-home.d.ts +18 -0
- package/dist-server/server/native-wren-home.js +262 -0
- package/dist-server/server/node-pty-host.d.ts +2 -1
- package/dist-server/server/node-pty-host.js +3 -2
- package/dist-server/server/profile-registry.d.ts +139 -0
- package/dist-server/server/profile-registry.js +620 -0
- package/dist-server/server/runtime-binding.d.ts +4 -1
- package/dist-server/server/runtime-binding.js +50 -2
- package/dist-server/server/runtime-host/claude-component-step.d.ts +25 -0
- package/dist-server/server/runtime-host/claude-component-step.js +186 -0
- package/dist-server/server/runtime-host/codex-app-server.d.ts +75 -0
- package/dist-server/server/runtime-host/codex-app-server.js +239 -0
- package/dist-server/server/runtime-host/codex-compatibility.d.ts +110 -0
- package/dist-server/server/runtime-host/codex-compatibility.js +162 -0
- package/dist-server/server/runtime-host/codex-component-step.d.ts +19 -0
- package/dist-server/server/runtime-host/codex-component-step.js +308 -0
- package/dist-server/server/runtime-host/codex-conversation.d.ts +109 -0
- package/dist-server/server/runtime-host/codex-conversation.js +295 -0
- package/dist-server/server/runtime-host/codex-direct-tools.d.ts +23 -0
- package/dist-server/server/runtime-host/codex-direct-tools.js +59 -0
- package/dist-server/server/runtime-host/codex-events.d.ts +647 -0
- package/dist-server/server/runtime-host/codex-events.js +66 -0
- package/dist-server/server/runtime-host/codex-policy.d.ts +16 -0
- package/dist-server/server/runtime-host/codex-policy.js +151 -0
- package/dist-server/server/runtime-host/codex-process.d.ts +8 -0
- package/dist-server/server/runtime-host/codex-process.js +96 -0
- package/dist-server/server/runtime-host/codex-rpc.d.ts +47 -0
- package/dist-server/server/runtime-host/codex-rpc.js +182 -0
- package/dist-server/server/runtime-host/codex-session.d.ts +74 -0
- package/dist-server/server/runtime-host/codex-session.js +492 -0
- package/dist-server/server/runtime-host/codex-terminal-protocol.d.ts +35 -0
- package/dist-server/server/runtime-host/codex-terminal-protocol.js +243 -0
- package/dist-server/server/runtime-host/codex-terminal.d.ts +16 -0
- package/dist-server/server/runtime-host/codex-terminal.js +120 -0
- package/dist-server/server/runtime-host/index.d.ts +5 -0
- package/dist-server/server/runtime-host/index.js +3 -0
- package/dist-server/server/runtime-host/local.d.ts +29 -0
- package/dist-server/server/runtime-host/local.js +90 -0
- package/dist-server/server/runtime-host/policy.d.ts +8 -0
- package/dist-server/server/runtime-host/policy.js +78 -0
- package/dist-server/server/runtime-host/types.d.ts +52 -0
- package/dist-server/server/runtime-host/types.js +62 -0
- package/dist-server/server/structured-query-evidence.d.ts +7 -0
- package/dist-server/server/structured-query-evidence.js +47 -0
- package/dist-server/server/structured-runtime.d.ts +52 -0
- package/dist-server/server/structured-runtime.js +130 -0
- package/dist-server/server/structured-scope.d.ts +4 -0
- package/dist-server/server/structured-scope.js +12 -0
- package/dist-server/server/turn.d.ts +6 -1
- package/dist-server/server/turn.js +86 -26
- package/dist-server/server/wire-types.d.ts +67 -3
- package/dist-server/server/wren-profiles.js +1 -1
- package/managed-wren/README.md +60 -0
- package/managed-wren/dependency-wheels.json +282 -0
- package/managed-wren/manifest.json +373 -0
- package/managed-wren/release-inputs.json +45 -0
- package/managed-wren/runtime-tree.cjs +115 -0
- package/managed-wren/source-inputs.json +40 -0
- package/package.json +15 -6
- package/profiles/genbi-default/context/binding.yml +17 -7
- package/profiles/genbi-default/context/context.json +146 -0
- package/profiles/genbi-default/ir.golden.json +39 -43
- package/profiles/genbi-default/profile.yml +31 -0
- package/profiles/genbi-enrich-context/context/binding.yml +14 -3
- package/profiles/genbi-enrich-context/context/context.json +146 -0
- package/profiles/genbi-enrich-context/ir.golden.json +4 -5
- package/profiles/genbi-monitor/context/binding.yml +13 -5
- package/profiles/genbi-monitor/context/context.json +146 -0
- package/profiles/genbi-monitor/ir.golden.json +13 -7
- package/profiles/genbi-report/context/binding.yml +19 -0
- package/profiles/genbi-report/context/context.json +223 -0
- package/profiles/genbi-report/ir.golden.json +328 -0
- package/profiles/genbi-report/profile.yml +38 -0
- package/profiles/genbi-setup/ir.golden.json +3 -1
- package/dist/assets/index-Xs4q7pNo.css +0 -1
|
@@ -0,0 +1,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:
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
|
|
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
|
-
|
|
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
|