@llm4ts/runner 2.41.0 → 2.43.0
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/dist/AgentTree.d.ts +11 -0
- package/dist/AgentTree.d.ts.map +1 -1
- package/dist/AgentTree.js +67 -15
- package/dist/AgentTree.js.map +1 -1
- package/dist/Doctor.d.ts +12 -1
- package/dist/Doctor.d.ts.map +1 -1
- package/dist/Doctor.js +46 -2
- package/dist/Doctor.js.map +1 -1
- package/dist/FlowRunner.d.ts +2 -0
- package/dist/FlowRunner.d.ts.map +1 -1
- package/dist/FlowRunner.js +33 -9
- package/dist/FlowRunner.js.map +1 -1
- package/dist/NodeGeminiAcpBridge.d.ts +11 -0
- package/dist/NodeGeminiAcpBridge.d.ts.map +1 -1
- package/dist/NodeGeminiAcpBridge.js +20 -6
- package/dist/NodeGeminiAcpBridge.js.map +1 -1
- package/dist/NodeGeminiModelBridge.d.ts +56 -0
- package/dist/NodeGeminiModelBridge.d.ts.map +1 -0
- package/dist/NodeGeminiModelBridge.js +206 -0
- package/dist/NodeGeminiModelBridge.js.map +1 -0
- package/dist/PiModels.d.ts +13 -0
- package/dist/PiModels.d.ts.map +1 -1
- package/dist/PiModels.js +8 -0
- package/dist/PiModels.js.map +1 -1
- package/package.json +4 -3
- package/src/AgentTree.ts +90 -13
- package/src/Doctor.ts +54 -2
- package/src/FlowRunner.ts +41 -9
- package/src/NodeGeminiAcpBridge.ts +23 -6
- package/src/NodeGeminiModelBridge.ts +350 -0
- package/src/PiModels.ts +20 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Stream from "effect/Stream";
|
|
5
|
+
import { InvalidRequestError, ProviderError } from "@llm4ts/core/Errors";
|
|
6
|
+
import { parseGeminiCliStreamEvent } from "@llm4ts/core/providers/GeminiCliProvider";
|
|
7
|
+
import { chatRequestFrom, completionChunks, completionJson, correctionTranscript, denyAllToolsPolicyToml, modelModeSettingsJson, openAiUsage, parseModelReply, systemFileFor, transcriptFor } from "@llm4ts/core/providers/GeminiModelBridge";
|
|
8
|
+
import { acquireServer, errorStatus, parseJsonBody, readBody, requestPath, writeJson } from "./NodeGeminiAcpBridge.js";
|
|
9
|
+
/** The standard directories Gemini CLI reads system (admin) policies from. */
|
|
10
|
+
export const systemPolicyDirectories = [
|
|
11
|
+
"/etc/gemini-cli/policies",
|
|
12
|
+
"/Library/Application Support/GeminiCli/policies",
|
|
13
|
+
"C:\\ProgramData\\gemini-cli\\policies"
|
|
14
|
+
];
|
|
15
|
+
/** The admin policy files on this machine that would make Gemini CLI ignore `--admin-policy`. */
|
|
16
|
+
export const systemAdminPolicies = () => systemPolicyDirectories.flatMap((directory) => {
|
|
17
|
+
try {
|
|
18
|
+
return existsSync(directory)
|
|
19
|
+
? readdirSync(directory)
|
|
20
|
+
.filter((file) => file.endsWith(".toml"))
|
|
21
|
+
.map((file) => join(directory, file))
|
|
22
|
+
: [];
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
export const systemPolicyProblem = (policies) => [
|
|
29
|
+
`Gemini CLI has system admin policies (${policies.join(", ")}), so it ignores the`,
|
|
30
|
+
"--admin-policy the model bridge relies on to take every tool out of the model's view.",
|
|
31
|
+
"The bridge will not run Gemini with its tools still in reach (ADR 0037); use",
|
|
32
|
+
"LLM4TS_GEMINI_BRIDGE_MODE=acp, or ask the administrator to allow this policy."
|
|
33
|
+
].join(" ");
|
|
34
|
+
/** One `gemini` call over `transcript`, its system file and lock-down written for the call. */
|
|
35
|
+
const geminiTurn = (config, model, system, transcript) => Effect.scoped(Effect.gen(function* () {
|
|
36
|
+
const systemFile = yield* config.temporaryFiles.write("gemini-system-", ".md", system);
|
|
37
|
+
const settings = yield* config.temporaryFiles.write("gemini-settings-", ".json", modelModeSettingsJson);
|
|
38
|
+
const policy = yield* config.temporaryFiles.write("gemini-deny-all-", ".toml", denyAllToolsPolicyToml);
|
|
39
|
+
const events = yield* Stream.runCollect(config.executor
|
|
40
|
+
.runStreamingWithStdin([
|
|
41
|
+
"gemini",
|
|
42
|
+
// Bound to its flag, so it can never read as a flag of its own.
|
|
43
|
+
`--model=${model}`,
|
|
44
|
+
"--output-format",
|
|
45
|
+
"stream-json",
|
|
46
|
+
"-e",
|
|
47
|
+
"none",
|
|
48
|
+
"--admin-policy",
|
|
49
|
+
policy
|
|
50
|
+
], config.cwd, {
|
|
51
|
+
...config.envVars,
|
|
52
|
+
GEMINI_CLI_TRUST_WORKSPACE: "true",
|
|
53
|
+
GEMINI_SYSTEM_MD: systemFile,
|
|
54
|
+
GEMINI_CLI_SYSTEM_SETTINGS_PATH: settings
|
|
55
|
+
}, transcript)
|
|
56
|
+
.pipe(Stream.map(parseGeminiCliStreamEvent)));
|
|
57
|
+
let text = "";
|
|
58
|
+
let tokens;
|
|
59
|
+
for (const event of events) {
|
|
60
|
+
switch (event._tag) {
|
|
61
|
+
case "Message":
|
|
62
|
+
if (event.role === "assistant" && event.content !== undefined) {
|
|
63
|
+
text += event.content;
|
|
64
|
+
}
|
|
65
|
+
break;
|
|
66
|
+
case "Error":
|
|
67
|
+
return yield* ProviderError.make({
|
|
68
|
+
message: `gemini: ${event.message ?? "error"}`
|
|
69
|
+
});
|
|
70
|
+
case "Result":
|
|
71
|
+
if (event.status === "error") {
|
|
72
|
+
return yield* ProviderError.make({
|
|
73
|
+
message: `gemini: ${event.errorMessage ?? "the call failed"}`
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
tokens =
|
|
77
|
+
event.stats === undefined
|
|
78
|
+
? undefined
|
|
79
|
+
: {
|
|
80
|
+
...(event.stats.inputTokens === undefined
|
|
81
|
+
? {}
|
|
82
|
+
: { inputTokens: event.stats.inputTokens }),
|
|
83
|
+
...(event.stats.outputTokens === undefined
|
|
84
|
+
? {}
|
|
85
|
+
: { outputTokens: event.stats.outputTokens }),
|
|
86
|
+
...(event.stats.cached === undefined ? {} : { cached: event.stats.cached })
|
|
87
|
+
};
|
|
88
|
+
break;
|
|
89
|
+
default:
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return { text, tokens };
|
|
94
|
+
}));
|
|
95
|
+
const addTokens = (left, right) => ({
|
|
96
|
+
inputTokens: (left?.inputTokens ?? 0) + (right?.inputTokens ?? 0),
|
|
97
|
+
outputTokens: (left?.outputTokens ?? 0) + (right?.outputTokens ?? 0),
|
|
98
|
+
cached: (left?.cached ?? 0) + (right?.cached ?? 0)
|
|
99
|
+
});
|
|
100
|
+
/** The largest request the bridge reads: a long conversation, not an unbounded upload. */
|
|
101
|
+
const maxRequestBytes = 32 * 1024 * 1024;
|
|
102
|
+
/** What a Gemini model id looks like: `gemini-3.8-flash`, `gemini-2.5-pro-001`. */
|
|
103
|
+
const modelName = /^[A-Za-z0-9][A-Za-z0-9._:-]*$/u;
|
|
104
|
+
/**
|
|
105
|
+
* One chat completion: a `gemini` call, and a second one only when the
|
|
106
|
+
* first reply holds a tool call that cannot be used — the model then sees
|
|
107
|
+
* its reply and why. A second bad reply goes back to pi as text.
|
|
108
|
+
*/
|
|
109
|
+
export const handleChatCompletion = Effect.fn("@llm4ts/runner/NodeGeminiModelBridge.handle")(function* (config, body) {
|
|
110
|
+
const request = chatRequestFrom(body);
|
|
111
|
+
if (request._tag === "Invalid") {
|
|
112
|
+
return yield* InvalidRequestError.make({ message: request.reason });
|
|
113
|
+
}
|
|
114
|
+
const model = config.model ?? request.model;
|
|
115
|
+
// The model reaches Gemini CLI's arguments: a name only, never a flag.
|
|
116
|
+
if (!modelName.test(model)) {
|
|
117
|
+
return yield* InvalidRequestError.make({
|
|
118
|
+
message: `"${model}" is not a model name (letters, digits, . _ : -, starting with a letter or digit)`
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const system = systemFileFor(request);
|
|
122
|
+
const transcript = transcriptFor(request.messages);
|
|
123
|
+
const toolNames = request.tools.map((tool) => tool.name);
|
|
124
|
+
const first = yield* geminiTurn(config, model, system, transcript);
|
|
125
|
+
const reply = parseModelReply(first.text, toolNames);
|
|
126
|
+
if (reply._tag !== "Malformed") {
|
|
127
|
+
return { model, reply, usage: openAiUsage(first.tokens) };
|
|
128
|
+
}
|
|
129
|
+
const second = yield* geminiTurn(config, model, system, correctionTranscript(transcript, first.text, reply.error));
|
|
130
|
+
return {
|
|
131
|
+
model,
|
|
132
|
+
reply: parseModelReply(second.text, toolNames),
|
|
133
|
+
usage: openAiUsage(addTokens(first.tokens, second.tokens))
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
let completions = 0;
|
|
137
|
+
const nextIds = () => {
|
|
138
|
+
completions += 1;
|
|
139
|
+
return { id: `chatcmpl-llm4ts-${completions}`, callId: `call_llm4ts_${completions}` };
|
|
140
|
+
};
|
|
141
|
+
const writeChunks = (response, chunks) => {
|
|
142
|
+
response.writeHead(200, {
|
|
143
|
+
"Content-Type": "text/event-stream",
|
|
144
|
+
"Cache-Control": "no-cache",
|
|
145
|
+
Connection: "keep-alive"
|
|
146
|
+
});
|
|
147
|
+
for (const chunk of chunks) {
|
|
148
|
+
response.write(`data: ${JSON.stringify(chunk)}\n\n`);
|
|
149
|
+
}
|
|
150
|
+
response.write("data: [DONE]\n\n");
|
|
151
|
+
response.end();
|
|
152
|
+
};
|
|
153
|
+
const streamWanted = (body) => {
|
|
154
|
+
const request = chatRequestFrom(body);
|
|
155
|
+
return request._tag === "Request" && request.stream;
|
|
156
|
+
};
|
|
157
|
+
export const runGeminiModelBridge = Effect.fn("@llm4ts/runner/NodeGeminiModelBridge.run")(function* (config) {
|
|
158
|
+
const policies = config.systemPolicies ?? systemAdminPolicies();
|
|
159
|
+
if (policies.length > 0) {
|
|
160
|
+
return yield* ProviderError.make({ message: systemPolicyProblem(policies) });
|
|
161
|
+
}
|
|
162
|
+
const listener = (request, response) => {
|
|
163
|
+
if (request.method !== "POST" || requestPath(request.url) !== "/v1/chat/completions") {
|
|
164
|
+
writeJson(response, 404, { error: { message: "not found" } });
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
// pi posts JSON from Node, with no Origin. A browser page posting to
|
|
168
|
+
// this loopback port (a cross-site form needs no preflight as
|
|
169
|
+
// text/plain) is refused before anything runs.
|
|
170
|
+
const contentType = request.headers["content-type"] ?? "";
|
|
171
|
+
// A DNS name rebound to 127.0.0.1 still sends its own Host.
|
|
172
|
+
const host = (request.headers.host ?? "").replace(/:\d+$/u, "");
|
|
173
|
+
if (request.headers.origin !== undefined ||
|
|
174
|
+
!contentType.includes("application/json") ||
|
|
175
|
+
!["127.0.0.1", "localhost", "[::1]"].includes(host)) {
|
|
176
|
+
writeJson(response, 403, {
|
|
177
|
+
error: { message: "the bridge answers JSON requests from local tools only" }
|
|
178
|
+
});
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const handled = Effect.gen(function* () {
|
|
182
|
+
const body = yield* parseJsonBody(yield* readBody(request, maxRequestBytes));
|
|
183
|
+
const outcome = yield* handleChatCompletion(config, body);
|
|
184
|
+
const { id, callId } = nextIds();
|
|
185
|
+
const created = Math.floor(Date.now() / 1000);
|
|
186
|
+
if (streamWanted(body)) {
|
|
187
|
+
return yield* Effect.sync(() => writeChunks(response, completionChunks(id, outcome.model, outcome.reply, outcome.usage, created, callId)));
|
|
188
|
+
}
|
|
189
|
+
return yield* Effect.sync(() => writeJson(response, 200, completionJson(id, outcome.model, outcome.reply, outcome.usage, created, callId)));
|
|
190
|
+
}).pipe(Effect.catch((error) => Effect.sync(() => {
|
|
191
|
+
if (!response.headersSent) {
|
|
192
|
+
writeJson(response, errorStatus(error), { error: { message: error.message } });
|
|
193
|
+
}
|
|
194
|
+
})));
|
|
195
|
+
Effect.runPromise(handled).catch((defect) => {
|
|
196
|
+
if (!response.headersSent) {
|
|
197
|
+
writeJson(response, 500, { error: { message: String(defect) } });
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
const server = yield* acquireServer(config.port, listener);
|
|
202
|
+
const address = server.address();
|
|
203
|
+
const port = address !== null && typeof address !== "string" ? address.port : config.port;
|
|
204
|
+
return { port, baseUrl: `http://127.0.0.1:${port}` };
|
|
205
|
+
});
|
|
206
|
+
//# sourceMappingURL=NodeGeminiModelBridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NodeGeminiModelBridge.js","sourceRoot":"","sources":["../src/NodeGeminiModelBridge.ts"],"names":[],"mappings":"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"}
|
package/dist/PiModels.d.ts
CHANGED
|
@@ -5,6 +5,19 @@ export declare const defaultGeminiBridgePort = "8731";
|
|
|
5
5
|
*/
|
|
6
6
|
export declare const defaultReadPiModelsJson: () => string | undefined;
|
|
7
7
|
export declare const geminiBridgePort: (environment: Readonly<Record<string, string | undefined>>) => string;
|
|
8
|
+
/**
|
|
9
|
+
* Which route the bridge serves (ADR 0037): `acp` (ADR 0016's Anthropic
|
|
10
|
+
* Messages over a Gemini ACP session, the default) or `model` (OpenAI chat
|
|
11
|
+
* completions over one locked-down `gemini` call per request).
|
|
12
|
+
*/
|
|
13
|
+
export type GeminiBridgeMode = {
|
|
14
|
+
readonly _tag: "Mode";
|
|
15
|
+
readonly mode: "acp" | "model";
|
|
16
|
+
} | {
|
|
17
|
+
readonly _tag: "Unknown";
|
|
18
|
+
readonly value: string;
|
|
19
|
+
};
|
|
20
|
+
export declare const geminiBridgeMode: (environment: Readonly<Record<string, string | undefined>>) => GeminiBridgeMode;
|
|
8
21
|
/**
|
|
9
22
|
* One value pi accepts for `--model`: `<provider>/<model>`, where the
|
|
10
23
|
* provider is a key under `providers` in `~/.pi/agent/models.json` and the
|
package/dist/PiModels.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PiModels.d.ts","sourceRoot":"","sources":["../src/PiModels.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,uBAAuB,SAAS,CAAA;AAE7C;;;GAGG;AACH,eAAO,MAAM,uBAAuB,QAAO,MAAM,GAAG,SAMnD,CAAA;AAED,eAAO,MAAM,gBAAgB,GAC3B,aAAa,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,KACxD,MAG0B,CAAA;AAE7B;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;CACjC;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;IACxC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACzC;AA2BD;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,YAAY,MAAM,GAAG,SAAS,EAAE,MAAM,MAAM,KAAG,cA8C7E,CAAA;AAED,8DAA8D;AAC9D,eAAO,MAAM,WAAW,GACtB,YAAY,MAAM,GAAG,SAAS,EAC9B,MAAM,MAAM,KACX,aAAa,CAAC,UAAU,CAA0C,CAAA;AAErE,wEAAwE;AACxE,eAAO,MAAM,eAAe,GAC1B,YAAY,MAAM,GAAG,SAAS,EAC9B,MAAM,MAAM,KACX,aAAa,CAAC,MAAM,CAGO,CAAA;AAE9B;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAC7B;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,GAC1E;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,CAAA;AAE9E,eAAO,MAAM,kBAAkB,GAC7B,YAAY,MAAM,GAAG,SAAS,EAC9B,MAAM,MAAM,EACZ,YAAY,MAAM,GAAG,SAAS,KAC7B,qBAoBF,CAAA;AAED,6EAA6E;AAC7E,eAAO,MAAM,kBAAkB,GAC7B,YAAY,qBAAqB,EACjC,MAAM,MAAM,KACX,MAAM,GAAG,SAqBX,CAAA"}
|
|
1
|
+
{"version":3,"file":"PiModels.d.ts","sourceRoot":"","sources":["../src/PiModels.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,uBAAuB,SAAS,CAAA;AAE7C;;;GAGG;AACH,eAAO,MAAM,uBAAuB,QAAO,MAAM,GAAG,SAMnD,CAAA;AAED,eAAO,MAAM,gBAAgB,GAC3B,aAAa,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,KACxD,MAG0B,CAAA;AAE7B;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,OAAO,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAExD,eAAO,MAAM,gBAAgB,GAC3B,aAAa,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,KACxD,gBAOF,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;CACjC;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;IACxC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACzC;AA2BD;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,YAAY,MAAM,GAAG,SAAS,EAAE,MAAM,MAAM,KAAG,cA8C7E,CAAA;AAED,8DAA8D;AAC9D,eAAO,MAAM,WAAW,GACtB,YAAY,MAAM,GAAG,SAAS,EAC9B,MAAM,MAAM,KACX,aAAa,CAAC,UAAU,CAA0C,CAAA;AAErE,wEAAwE;AACxE,eAAO,MAAM,eAAe,GAC1B,YAAY,MAAM,GAAG,SAAS,EAC9B,MAAM,MAAM,KACX,aAAa,CAAC,MAAM,CAGO,CAAA;AAE9B;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAC7B;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,GAC1E;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,CAAA;AAE9E,eAAO,MAAM,kBAAkB,GAC7B,YAAY,MAAM,GAAG,SAAS,EAC9B,MAAM,MAAM,EACZ,YAAY,MAAM,GAAG,SAAS,KAC7B,qBAoBF,CAAA;AAED,6EAA6E;AAC7E,eAAO,MAAM,kBAAkB,GAC7B,YAAY,qBAAqB,EACjC,MAAM,MAAM,KACX,MAAM,GAAG,SAqBX,CAAA"}
|
package/dist/PiModels.js
CHANGED
|
@@ -25,6 +25,14 @@ export const defaultReadPiModelsJson = () => {
|
|
|
25
25
|
export const geminiBridgePort = (environment) => isSet(environment.LLM4TS_GEMINI_BRIDGE_PORT)
|
|
26
26
|
? environment.LLM4TS_GEMINI_BRIDGE_PORT.trim()
|
|
27
27
|
: defaultGeminiBridgePort;
|
|
28
|
+
export const geminiBridgeMode = (environment) => {
|
|
29
|
+
const value = (environment.LLM4TS_GEMINI_BRIDGE_MODE ?? "").trim().toLowerCase();
|
|
30
|
+
return value === "" || value === "acp"
|
|
31
|
+
? { _tag: "Mode", mode: "acp" }
|
|
32
|
+
: value === "model"
|
|
33
|
+
? { _tag: "Mode", mode: "model" }
|
|
34
|
+
: { _tag: "Unknown", value };
|
|
35
|
+
};
|
|
28
36
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29
37
|
/** Annotated rather than asserted, matching `NodeGeminiAcpBridge.parseJson`. */
|
|
30
38
|
const parseJson = (raw) => {
|
package/dist/PiModels.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PiModels.js","sourceRoot":"","sources":["../src/PiModels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC;;;;;;GAMG;AAEH,MAAM,KAAK,GAAG,CAAC,KAAyB,EAAmB,EAAE,CAC3D,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAA;AAEhD,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAA;AAE7C;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAuB,EAAE;IAC9D,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAA;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,WAAyD,EACjD,EAAE,CACV,KAAK,CAAC,WAAW,CAAC,yBAAyB,CAAC;IAC1C,CAAC,CAAC,WAAW,CAAC,yBAAyB,CAAC,IAAI,EAAE;IAC9C,CAAC,CAAC,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"PiModels.js","sourceRoot":"","sources":["../src/PiModels.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llm4ts/runner",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.43.0",
|
|
4
4
|
"description": "Node runner, CLI, terminal, and MCP composition for llm4ts",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"./Kits": "./dist/Kits.js",
|
|
29
29
|
"./McpStdio": "./dist/McpStdio.js",
|
|
30
30
|
"./NodeGeminiAcpBridge": "./dist/NodeGeminiAcpBridge.js",
|
|
31
|
+
"./NodeGeminiModelBridge": "./dist/NodeGeminiModelBridge.js",
|
|
31
32
|
"./NodeHttpClient": "./dist/NodeHttpClient.js",
|
|
32
33
|
"./NodeGeminiCliExecutor": "./dist/NodeGeminiCliExecutor.js",
|
|
33
34
|
"./NodePlainFileStore": "./dist/NodePlainFileStore.js",
|
|
@@ -70,8 +71,8 @@
|
|
|
70
71
|
"typescript"
|
|
71
72
|
],
|
|
72
73
|
"dependencies": {
|
|
73
|
-
"@llm4ts/core": "2.
|
|
74
|
-
"@llm4ts/flow": "2.
|
|
74
|
+
"@llm4ts/core": "2.43.0",
|
|
75
|
+
"@llm4ts/flow": "2.43.0"
|
|
75
76
|
},
|
|
76
77
|
"peerDependencies": {
|
|
77
78
|
"effect": "4.0.0"
|
package/src/AgentTree.ts
CHANGED
|
@@ -66,6 +66,18 @@ export interface TreeLane {
|
|
|
66
66
|
readonly children: ReadonlyArray<TreeChild>
|
|
67
67
|
/** A harness pause under way: `pi retry`, `pi compaction`. */
|
|
68
68
|
readonly pause: { readonly label: string; readonly since: number } | undefined
|
|
69
|
+
/** Tasks running beside the lane's coder, each on a coder of its own (ADR 0034). */
|
|
70
|
+
readonly taskCoders: ReadonlyArray<TreeTaskCoder>
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** A task running beside a story's coder, in its own worktree (ADR 0034). */
|
|
74
|
+
export interface TreeTaskCoder {
|
|
75
|
+
readonly index: number
|
|
76
|
+
readonly count: number
|
|
77
|
+
readonly title: string
|
|
78
|
+
readonly executor: string | undefined
|
|
79
|
+
readonly clone: number | undefined
|
|
80
|
+
readonly since: number
|
|
69
81
|
}
|
|
70
82
|
|
|
71
83
|
/** One task of a lane's plan, as the checklist shows it. */
|
|
@@ -410,7 +422,8 @@ const reduceEvent = (state: TreeState, at: number, event: FlowEvent): TreeState
|
|
|
410
422
|
tasks: [],
|
|
411
423
|
task: undefined,
|
|
412
424
|
children: [],
|
|
413
|
-
pause: undefined
|
|
425
|
+
pause: undefined,
|
|
426
|
+
taskCoders: []
|
|
414
427
|
}
|
|
415
428
|
return {
|
|
416
429
|
...current,
|
|
@@ -424,7 +437,10 @@ const reduceEvent = (state: TreeState, at: number, event: FlowEvent): TreeState
|
|
|
424
437
|
stages: [...open.stages, event.stage]
|
|
425
438
|
}))
|
|
426
439
|
}
|
|
427
|
-
|
|
440
|
+
// A lane that is not a story's (a task run aside, ADR 0034) is not the run's either.
|
|
441
|
+
return event.lane === undefined
|
|
442
|
+
? { ...current, stages: [...current.stages, event.stage] }
|
|
443
|
+
: current
|
|
428
444
|
}
|
|
429
445
|
case "StageCompleted":
|
|
430
446
|
case "StageFailed": {
|
|
@@ -449,7 +465,9 @@ const reduceEvent = (state: TreeState, at: number, event: FlowEvent): TreeState
|
|
|
449
465
|
stages: withoutLast(open.stages, event.stage)
|
|
450
466
|
}))
|
|
451
467
|
}
|
|
452
|
-
return
|
|
468
|
+
return event.lane === undefined
|
|
469
|
+
? { ...current, stages: withoutLast(current.stages, event.stage) }
|
|
470
|
+
: current
|
|
453
471
|
}
|
|
454
472
|
case "Info": {
|
|
455
473
|
// A story's own milestones are `story <id>: …` (resuming, merged,
|
|
@@ -655,15 +673,36 @@ const reduceEvent = (state: TreeState, at: number, event: FlowEvent): TreeState
|
|
|
655
673
|
return current
|
|
656
674
|
}
|
|
657
675
|
const satisfies = event.satisfies === undefined ? {} : { satisfies: event.satisfies }
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
task: { index: event.index, count: event.count, title: event.title, ...satisfies },
|
|
661
|
-
tasks: open.tasks.some((task) => task.index === event.index)
|
|
676
|
+
const listed = (open: TreeLane): ReadonlyArray<TreeTask> =>
|
|
677
|
+
open.tasks.some((task) => task.index === event.index)
|
|
662
678
|
? open.tasks
|
|
663
679
|
: [
|
|
664
680
|
...open.tasks,
|
|
665
681
|
{ index: event.index, title: event.title, done: false, ...satisfies }
|
|
666
682
|
].sort((left, right) => left.index - right.index)
|
|
683
|
+
if (event.parallel === true) {
|
|
684
|
+
return updateLane(current, lane.id, (open) => ({
|
|
685
|
+
...open,
|
|
686
|
+
tasks: listed(open),
|
|
687
|
+
taskCoders: [
|
|
688
|
+
...open.taskCoders.filter((coder) => coder.index !== event.index),
|
|
689
|
+
{
|
|
690
|
+
index: event.index,
|
|
691
|
+
count: event.count,
|
|
692
|
+
title: event.title,
|
|
693
|
+
executor: event.executor,
|
|
694
|
+
clone: event.clone,
|
|
695
|
+
since: at
|
|
696
|
+
}
|
|
697
|
+
]
|
|
698
|
+
}))
|
|
699
|
+
}
|
|
700
|
+
return updateLane(current, lane.id, (open) => ({
|
|
701
|
+
...open,
|
|
702
|
+
task: { index: event.index, count: event.count, title: event.title, ...satisfies },
|
|
703
|
+
tasks: listed(open),
|
|
704
|
+
// Back with the story's coder: no longer beside it.
|
|
705
|
+
taskCoders: open.taskCoders.filter((coder) => coder.index !== event.index)
|
|
667
706
|
}))
|
|
668
707
|
}
|
|
669
708
|
case "TaskCompleted":
|
|
@@ -671,7 +710,8 @@ const reduceEvent = (state: TreeState, at: number, event: FlowEvent): TreeState
|
|
|
671
710
|
? current
|
|
672
711
|
: updateLane(current, lane.id, (open) => ({
|
|
673
712
|
...open,
|
|
674
|
-
task: undefined,
|
|
713
|
+
task: open.task?.index === event.index ? undefined : open.task,
|
|
714
|
+
taskCoders: open.taskCoders.filter((coder) => coder.index !== event.index),
|
|
675
715
|
tasks: open.tasks.map((task) =>
|
|
676
716
|
task.index === event.index ? { ...task, done: true } : task
|
|
677
717
|
)
|
|
@@ -1270,6 +1310,19 @@ const laneLine = (
|
|
|
1270
1310
|
}
|
|
1271
1311
|
|
|
1272
1312
|
/** A sub-agent the lane's harness spawned, indented under it. */
|
|
1313
|
+
/** A task running beside the lane's coder, indented under it (ADR 0034). */
|
|
1314
|
+
const taskCoderLine = (coder: TreeTaskCoder, width: number, now: number | undefined): Line =>
|
|
1315
|
+
headThenTail(
|
|
1316
|
+
[
|
|
1317
|
+
span(" └ "),
|
|
1318
|
+
span("task coder ", "dim"),
|
|
1319
|
+
span(`${cloneName(coder.executor ?? "(leasing)", coder.clone)} · `),
|
|
1320
|
+
span(`${coder.index}/${coder.count} ${coder.title}`)
|
|
1321
|
+
],
|
|
1322
|
+
span(` · ${elapsed(coder.since, now)}`, "dim"),
|
|
1323
|
+
width
|
|
1324
|
+
)
|
|
1325
|
+
|
|
1273
1326
|
const childLine = (child: TreeChild, width: number, now: number | undefined): Line =>
|
|
1274
1327
|
headThenTail(
|
|
1275
1328
|
[
|
|
@@ -1285,7 +1338,8 @@ const childLine = (child: TreeChild, width: number, now: number | undefined): Li
|
|
|
1285
1338
|
/** The list's rows: a running lane, then each sub-agent still running under it. */
|
|
1286
1339
|
const listRowsOf = (state: TreeState): number =>
|
|
1287
1340
|
runningLanes(state).reduce(
|
|
1288
|
-
(total, lane) =>
|
|
1341
|
+
(total, lane) =>
|
|
1342
|
+
total + 1 + lane.taskCoders.length + lane.children.filter((child) => !child.ended).length,
|
|
1289
1343
|
0
|
|
1290
1344
|
)
|
|
1291
1345
|
|
|
@@ -1306,6 +1360,10 @@ const agentRows = (
|
|
|
1306
1360
|
lane: lane.id,
|
|
1307
1361
|
line: laneLine(lane, width, state.now, lane.id === selected?.id, state.idleAfterMs)
|
|
1308
1362
|
},
|
|
1363
|
+
...lane.taskCoders.map((coder) => ({
|
|
1364
|
+
lane: lane.id,
|
|
1365
|
+
line: taskCoderLine(coder, width, state.now)
|
|
1366
|
+
})),
|
|
1309
1367
|
...lane.children
|
|
1310
1368
|
.filter((child) => !child.ended)
|
|
1311
1369
|
.map((child) => ({ lane: lane.id, line: childLine(child, width, state.now) }))
|
|
@@ -1362,10 +1420,17 @@ const detailBox = (
|
|
|
1362
1420
|
lane.tasks.length === 0
|
|
1363
1421
|
? [[span("no task plan yet", "dim")]]
|
|
1364
1422
|
: lane.tasks.map((task): Line => {
|
|
1365
|
-
const
|
|
1423
|
+
const beside = lane.taskCoders.find((coder) => coder.index === task.index)
|
|
1424
|
+
const running = lane.task?.index === task.index || beside !== undefined
|
|
1366
1425
|
const right = task.satisfies === undefined ? "" : `satisfies ${task.satisfies.join(",")}`
|
|
1367
1426
|
const left: Line = [
|
|
1368
|
-
span(
|
|
1427
|
+
span(
|
|
1428
|
+
`${tick(task, running)} ${task.index} ${task.title}`,
|
|
1429
|
+
running ? "bold" : undefined
|
|
1430
|
+
),
|
|
1431
|
+
...(beside === undefined
|
|
1432
|
+
? []
|
|
1433
|
+
: [span(` ← ${cloneName(beside.executor ?? "(leasing)", beside.clone)}`, "dim")])
|
|
1369
1434
|
]
|
|
1370
1435
|
return right.length === 0
|
|
1371
1436
|
? left
|
|
@@ -1475,8 +1540,20 @@ const boardsOf = (
|
|
|
1475
1540
|
return [[span("epic board", "bold")], ...epic]
|
|
1476
1541
|
}
|
|
1477
1542
|
const taskColumns: ReadonlyArray<readonly [string, (task: TreeTask) => boolean]> = [
|
|
1478
|
-
[
|
|
1479
|
-
|
|
1543
|
+
[
|
|
1544
|
+
"todo",
|
|
1545
|
+
(task) =>
|
|
1546
|
+
!task.done &&
|
|
1547
|
+
task.index !== selected.task?.index &&
|
|
1548
|
+
!selected.taskCoders.some((coder) => coder.index === task.index)
|
|
1549
|
+
],
|
|
1550
|
+
[
|
|
1551
|
+
"doing",
|
|
1552
|
+
(task) =>
|
|
1553
|
+
!task.done &&
|
|
1554
|
+
(task.index === selected.task?.index ||
|
|
1555
|
+
selected.taskCoders.some((coder) => coder.index === task.index))
|
|
1556
|
+
],
|
|
1480
1557
|
["review", () => false],
|
|
1481
1558
|
["done", (task) => task.done]
|
|
1482
1559
|
]
|
package/src/Doctor.ts
CHANGED
|
@@ -9,8 +9,10 @@ import { nodeProcessExecutor } from "./NodeProcessExecutor.ts"
|
|
|
9
9
|
import {
|
|
10
10
|
defaultReadPiModelsJson as readPiModels,
|
|
11
11
|
geminiBridgePort as bridgePort,
|
|
12
|
-
piModelsConfig as parsePiModels
|
|
12
|
+
piModelsConfig as parsePiModels,
|
|
13
|
+
geminiBridgeMode
|
|
13
14
|
} from "./PiModels.ts"
|
|
15
|
+
import { systemAdminPolicies, systemPolicyProblem } from "./NodeGeminiModelBridge.ts"
|
|
14
16
|
import { otelConfig, otelDoctorLine, probeOtelEndpoint, type OtelConfig } from "./Otel.ts"
|
|
15
17
|
|
|
16
18
|
const credentialKeys = [
|
|
@@ -210,6 +212,50 @@ export const geminiBridgePrerequisites = (
|
|
|
210
212
|
}
|
|
211
213
|
}
|
|
212
214
|
|
|
215
|
+
/** Gemini CLI's own words on third-party access (0.62.0, `docs/resources/tos-privacy.md`). */
|
|
216
|
+
export const geminiTermsClause =
|
|
217
|
+
"Directly accessing the services powering Gemini CLI (for example, the Gemini Code Assist " +
|
|
218
|
+
"service) using third-party software, tools, or services (for example, using OpenClaw with " +
|
|
219
|
+
"Gemini CLI OAuth) is a violation of applicable terms and policies. Such actions may be " +
|
|
220
|
+
"grounds for suspension or termination of your account."
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* The model mode of the bridge (ADR 0037): whether a system admin policy
|
|
224
|
+
* would keep Gemini's tools in view, how pi's provider must be shaped, and
|
|
225
|
+
* the terms clause the customer confirms against. `undefined` unless the
|
|
226
|
+
* bridge runs in model mode.
|
|
227
|
+
*/
|
|
228
|
+
export const geminiModelModePrerequisites = (
|
|
229
|
+
environment: Readonly<Record<string, string | undefined>>,
|
|
230
|
+
systemPolicies: ReadonlyArray<string>
|
|
231
|
+
): PrerequisiteReport | undefined => {
|
|
232
|
+
const mode = geminiBridgeMode(environment)
|
|
233
|
+
if (!truthy(environment.LLM4TS_GEMINI_BRIDGE) || mode._tag !== "Mode" || mode.mode !== "model") {
|
|
234
|
+
return undefined
|
|
235
|
+
}
|
|
236
|
+
const detail = [
|
|
237
|
+
'pi\'s bridge provider in ~/.pi/agent/models.json needs "api": "openai-completions"',
|
|
238
|
+
"(the route is /v1/chat/completions); only Gemini CLI talks to Google, under its own",
|
|
239
|
+
"login, and llm4ts never reads or forwards its credentials. Gemini CLI's terms say:",
|
|
240
|
+
` "${geminiTermsClause}"`,
|
|
241
|
+
"Using Gemini CLI as a model for pi stays close to that clause: confirm with Google",
|
|
242
|
+
"before relying on it."
|
|
243
|
+
]
|
|
244
|
+
return systemPolicies.length > 0
|
|
245
|
+
? {
|
|
246
|
+
satisfied: false,
|
|
247
|
+
summary: `system admin policies make Gemini CLI ignore the bridge's: ${systemPolicies.join(", ")}`,
|
|
248
|
+
hint: systemPolicyProblem(systemPolicies),
|
|
249
|
+
detail
|
|
250
|
+
}
|
|
251
|
+
: {
|
|
252
|
+
satisfied: true,
|
|
253
|
+
summary:
|
|
254
|
+
"model mode: Gemini CLI answers as a plain model, its prompt replaced and every tool denied",
|
|
255
|
+
detail
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
213
259
|
export const makeDoctorProgram = (
|
|
214
260
|
registry: ConnectorRegistryShape = nodeFlowRunnerDependencies().registry,
|
|
215
261
|
environment: Readonly<Record<string, string | undefined>> = process.env,
|
|
@@ -223,7 +269,9 @@ export const makeDoctorProgram = (
|
|
|
223
269
|
environment
|
|
224
270
|
),
|
|
225
271
|
/** Whether the OTLP endpoint answers (ADR 0026); the network probe by default. */
|
|
226
|
-
probeOtel: (config: OtelConfig) => Effect.Effect<boolean | undefined> = probeOtelEndpoint
|
|
272
|
+
probeOtel: (config: OtelConfig) => Effect.Effect<boolean | undefined> = probeOtelEndpoint,
|
|
273
|
+
/** Gemini CLI's system admin policy files (ADR 0037); this machine's by default. */
|
|
274
|
+
systemPolicies: () => ReadonlyArray<string> = systemAdminPolicies
|
|
227
275
|
): Effect.Effect<string> => {
|
|
228
276
|
const otel = otelConfig(environment)
|
|
229
277
|
return Effect.map(
|
|
@@ -266,6 +314,7 @@ export const makeDoctorProgram = (
|
|
|
266
314
|
id.value === ConnectorIds.GeminiCli.value || id.value === ConnectorIds.GeminiApi.value
|
|
267
315
|
)
|
|
268
316
|
const bridge = geminiBridgePrerequisites(environment, readPiModelsJson())
|
|
317
|
+
const modelMode = geminiModelModePrerequisites(environment, systemPolicies())
|
|
269
318
|
if (geminiRelevant || bridge !== undefined) {
|
|
270
319
|
lines.push("")
|
|
271
320
|
lines.push("prerequisites:")
|
|
@@ -284,6 +333,9 @@ export const makeDoctorProgram = (
|
|
|
284
333
|
if (bridge !== undefined) {
|
|
285
334
|
pushReport("pi-gemini-bridge", bridge)
|
|
286
335
|
}
|
|
336
|
+
if (modelMode !== undefined) {
|
|
337
|
+
pushReport("pi-gemini-bridge model mode", modelMode)
|
|
338
|
+
}
|
|
287
339
|
}
|
|
288
340
|
|
|
289
341
|
lines.push("")
|