@sagentlab/navarch-runtime 0.1.34 → 0.1.35
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/adapters/pi.cjs +61 -15
- package/package.json +1 -1
package/dist/adapters/pi.cjs
CHANGED
|
@@ -3,7 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.piAdapter = exports.DEFAULT_HOSTED_PI_MODEL = exports.HOSTED_PI_MODELS = exports.DEEPSEEK_API_KEY_ENV = exports.PI_PROVIDER_NAME = void 0;
|
|
6
|
+
exports.piAdapter = exports.HOSTED_PI_MAX_PROVIDER_TURNS = exports.DEFAULT_HOSTED_PI_MODEL = exports.HOSTED_PI_MODELS = exports.DEEPSEEK_API_KEY_ENV = exports.PI_PROVIDER_NAME = void 0;
|
|
7
|
+
exports.buildHostedPiBudgetExtension = buildHostedPiBudgetExtension;
|
|
7
8
|
exports.resolveHostedPiModel = resolveHostedPiModel;
|
|
8
9
|
exports.buildPiProviderConfig = buildPiProviderConfig;
|
|
9
10
|
exports.parsePiJsonEvents = parsePiJsonEvents;
|
|
@@ -27,9 +28,9 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
27
28
|
* shared parsing/provider-config contract.
|
|
28
29
|
*
|
|
29
30
|
* Secret hygiene: the generated models.json references the DeepSeek key ONLY
|
|
30
|
-
* as
|
|
31
|
-
* child environment at
|
|
32
|
-
* the config file, or in any file that survives cleanup. A missing
|
|
31
|
+
* as the `DEEPSEEK_API_KEY` environment-variable name (Pi resolves it from
|
|
32
|
+
* the child environment at request time). The literal key never appears in
|
|
33
|
+
* argv, in the config file, or in any file that survives cleanup. A missing
|
|
33
34
|
* DEEPSEEK_API_KEY in the session environment is a hard configuration
|
|
34
35
|
* failure — the adapter refuses to launch rather than fall back to an
|
|
35
36
|
* ambient credential.
|
|
@@ -47,6 +48,17 @@ exports.PI_PROVIDER_NAME = "deepseek";
|
|
|
47
48
|
exports.DEEPSEEK_API_KEY_ENV = "DEEPSEEK_API_KEY";
|
|
48
49
|
exports.HOSTED_PI_MODELS = ["deepseek-v4-flash", "deepseek-v4-pro"];
|
|
49
50
|
exports.DEFAULT_HOSTED_PI_MODEL = "deepseek-v4-flash";
|
|
51
|
+
exports.HOSTED_PI_MAX_PROVIDER_TURNS = 3;
|
|
52
|
+
function buildHostedPiBudgetExtension() {
|
|
53
|
+
return `export default function navarchHostedPiBudget(pi) {
|
|
54
|
+
let providerTurns = 0;
|
|
55
|
+
pi.on("turn_start", (_event, ctx) => {
|
|
56
|
+
providerTurns += 1;
|
|
57
|
+
if (providerTurns > ${exports.HOSTED_PI_MAX_PROVIDER_TURNS}) ctx.abort();
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
50
62
|
function resolveHostedPiModel(configured) {
|
|
51
63
|
const trimmed = (configured ?? "").trim();
|
|
52
64
|
const bare = trimmed.startsWith(`${exports.PI_PROVIDER_NAME}/`)
|
|
@@ -88,7 +100,7 @@ function buildPiProviderConfig() {
|
|
|
88
100
|
[exports.PI_PROVIDER_NAME]: {
|
|
89
101
|
baseUrl: "https://api.deepseek.com",
|
|
90
102
|
api: "openai-completions",
|
|
91
|
-
apiKey:
|
|
103
|
+
apiKey: exports.DEEPSEEK_API_KEY_ENV,
|
|
92
104
|
models,
|
|
93
105
|
},
|
|
94
106
|
},
|
|
@@ -195,6 +207,13 @@ function attachPiOutput(result) {
|
|
|
195
207
|
// Invocation
|
|
196
208
|
// ---------------------------------------------------------------------------
|
|
197
209
|
const CONTAINER_PI_DIR = "/tmp/navarch-pi-agent";
|
|
210
|
+
const BUDGET_EXTENSION_NAME = "navarch-budget.js";
|
|
211
|
+
function withBudgetExtension(args, extensionPath) {
|
|
212
|
+
const promptIndex = args.indexOf("-p");
|
|
213
|
+
if (promptIndex < 0)
|
|
214
|
+
return [...args, "--extension", extensionPath];
|
|
215
|
+
return [...args.slice(0, promptIndex), "--extension", extensionPath, ...args.slice(promptIndex)];
|
|
216
|
+
}
|
|
198
217
|
function hasArg(args, ...flags) {
|
|
199
218
|
return args.some((arg) => flags.some((flag) => arg === flag || arg.startsWith(`${flag}=`)));
|
|
200
219
|
}
|
|
@@ -205,7 +224,7 @@ async function runPiAdapter(options) {
|
|
|
205
224
|
throw new Error(`pi adapter: ${exports.DEEPSEEK_API_KEY_ENV} is missing from the session environment; ` +
|
|
206
225
|
"the managed provider credential must be injected by the hosted runner");
|
|
207
226
|
}
|
|
208
|
-
const args = ["--mode", "json"];
|
|
227
|
+
const args = ["--mode", "json", "--no-extensions"];
|
|
209
228
|
if (!hasArg(options.extraArgs, "--no-session")) {
|
|
210
229
|
// Ephemeral by default: session persistence would leave conversation
|
|
211
230
|
// files (which may quote repository content) behind after cleanup.
|
|
@@ -215,9 +234,9 @@ async function runPiAdapter(options) {
|
|
|
215
234
|
const model = resolveHostedPiModel(options.model);
|
|
216
235
|
args.push("--model", `${exports.PI_PROVIDER_NAME}/${model}`);
|
|
217
236
|
if (options.reasoningEffort) {
|
|
218
|
-
// Pi
|
|
219
|
-
//
|
|
220
|
-
args.push("--thinking", options.reasoningEffort);
|
|
237
|
+
// Pi 0.73.1 tops out at xhigh. Navarch's max effort must clamp rather
|
|
238
|
+
// than passing an invalid value that Pi warns about and ignores.
|
|
239
|
+
args.push("--thinking", options.reasoningEffort === "max" ? "xhigh" : options.reasoningEffort);
|
|
221
240
|
}
|
|
222
241
|
args.push("-p", options.prompt);
|
|
223
242
|
const raw = options.dockerExec
|
|
@@ -230,14 +249,19 @@ async function runOnHost(options, args) {
|
|
|
230
249
|
// reads) an operator's ~/.pi configuration/credentials.
|
|
231
250
|
const agentDir = await node_fs_1.promises.mkdtemp(node_path_1.default.join(node_os_1.default.tmpdir(), "navarch-pi-agent-"));
|
|
232
251
|
await node_fs_1.promises.writeFile(node_path_1.default.join(agentDir, "models.json"), buildPiProviderConfig(), { mode: 0o600 });
|
|
252
|
+
const budgetExtensionPath = node_path_1.default.join(agentDir, BUDGET_EXTENSION_NAME);
|
|
253
|
+
await node_fs_1.promises.writeFile(budgetExtensionPath, buildHostedPiBudgetExtension(), {
|
|
254
|
+
mode: 0o600,
|
|
255
|
+
});
|
|
233
256
|
const env = { ...options.env, PI_CODING_AGENT_DIR: agentDir };
|
|
257
|
+
const boundedArgs = withBudgetExtension(args, budgetExtensionPath);
|
|
234
258
|
try {
|
|
235
259
|
return await new Promise((resolve) => {
|
|
236
260
|
let stdout = "";
|
|
237
261
|
let stderr = "";
|
|
238
262
|
let timedOut = false;
|
|
239
263
|
let killedByLeaseLoss = false;
|
|
240
|
-
const child = (0, node_child_process_1.spawn)(options.bin,
|
|
264
|
+
const child = (0, node_child_process_1.spawn)(options.bin, boundedArgs, {
|
|
241
265
|
cwd: options.cwd,
|
|
242
266
|
env: { ...process.env, ...env },
|
|
243
267
|
});
|
|
@@ -261,12 +285,24 @@ async function runOnHost(options, args) {
|
|
|
261
285
|
clearTimeout(timer);
|
|
262
286
|
options.signal?.removeEventListener("abort", onAbort);
|
|
263
287
|
stderr += `\n${String(err)}`;
|
|
264
|
-
resolve({
|
|
288
|
+
resolve({
|
|
289
|
+
exitCode: null,
|
|
290
|
+
timedOut,
|
|
291
|
+
killedByLeaseLoss,
|
|
292
|
+
stdout,
|
|
293
|
+
stderr,
|
|
294
|
+
});
|
|
265
295
|
});
|
|
266
296
|
child.on("close", (code) => {
|
|
267
297
|
clearTimeout(timer);
|
|
268
298
|
options.signal?.removeEventListener("abort", onAbort);
|
|
269
|
-
resolve({
|
|
299
|
+
resolve({
|
|
300
|
+
exitCode: code,
|
|
301
|
+
timedOut,
|
|
302
|
+
killedByLeaseLoss,
|
|
303
|
+
stdout,
|
|
304
|
+
stderr,
|
|
305
|
+
});
|
|
270
306
|
});
|
|
271
307
|
});
|
|
272
308
|
}
|
|
@@ -276,12 +312,19 @@ async function runOnHost(options, args) {
|
|
|
276
312
|
}
|
|
277
313
|
async function runViaDocker(options, args) {
|
|
278
314
|
const { containerName, runner } = options.dockerExec;
|
|
279
|
-
// The provider config carries no secret values (only the
|
|
315
|
+
// The provider config carries no secret values (only the DEEPSEEK_API_KEY
|
|
280
316
|
// env reference), so materializing it through the container shell is safe.
|
|
281
317
|
const command = `[ -f /tmp/session.env ] && . /tmp/session.env; cd repo 2>/dev/null; ` +
|
|
282
318
|
`mkdir -p ${CONTAINER_PI_DIR} && cat > ${CONTAINER_PI_DIR}/models.json <<'NAVARCH_PI_EOF'\n` +
|
|
283
319
|
`${buildPiProviderConfig()}NAVARCH_PI_EOF\n` +
|
|
284
|
-
`
|
|
320
|
+
`cat > ${CONTAINER_PI_DIR}/${BUDGET_EXTENSION_NAME} <<'NAVARCH_PI_BUDGET_EOF'\n` +
|
|
321
|
+
`${buildHostedPiBudgetExtension()}NAVARCH_PI_BUDGET_EOF\n` +
|
|
322
|
+
`PI_CODING_AGENT_DIR=${CONTAINER_PI_DIR} ${[
|
|
323
|
+
options.bin,
|
|
324
|
+
...withBudgetExtension(args, `${CONTAINER_PI_DIR}/${BUDGET_EXTENSION_NAME}`),
|
|
325
|
+
]
|
|
326
|
+
.map(shellQuote)
|
|
327
|
+
.join(" ")}`;
|
|
285
328
|
let killedByLeaseLoss = false;
|
|
286
329
|
const onAbort = () => {
|
|
287
330
|
killedByLeaseLoss = true;
|
|
@@ -290,7 +333,10 @@ async function runViaDocker(options, args) {
|
|
|
290
333
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
291
334
|
try {
|
|
292
335
|
const forwardedEnv = Object.keys(options.env).flatMap((name) => ["--env", name]);
|
|
293
|
-
const result = await runner.run("docker", ["exec", ...forwardedEnv, containerName, "sh", "-c", command], {
|
|
336
|
+
const result = await runner.run("docker", ["exec", ...forwardedEnv, containerName, "sh", "-c", command], {
|
|
337
|
+
timeoutMs: options.timeoutMs,
|
|
338
|
+
env: { ...process.env, ...options.env },
|
|
339
|
+
});
|
|
294
340
|
return {
|
|
295
341
|
exitCode: result.code,
|
|
296
342
|
timedOut: false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sagentlab/navarch-runtime",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.35",
|
|
4
4
|
"description": "Navarch machine-side session manager: claims delivery tasks and runs them through Claude Code, Codex, Gemini, or OpenCode.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"license": "MIT",
|