@h-rig/runtime 0.0.6-alpha.33 → 0.0.6-alpha.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/bin/rig-agent-dispatch.js +518 -459
- package/dist/bin/rig-agent.js +431 -362
- package/dist/src/control-plane/agent-wrapper.js +523 -464
- package/dist/src/control-plane/harness-main.js +529 -459
- package/dist/src/control-plane/hooks/completion-verification.js +353 -283
- package/dist/src/control-plane/hooks/inject-context.js +158 -99
- package/dist/src/control-plane/hooks/submodule-branch.js +538 -479
- package/dist/src/control-plane/hooks/task-runtime-start.js +538 -479
- package/dist/src/control-plane/materialize-task-config.js +68 -8
- package/dist/src/control-plane/native/git-ops.js +11 -1
- package/dist/src/control-plane/native/harness-cli.js +514 -444
- package/dist/src/control-plane/native/task-ops.js +392 -322
- package/dist/src/control-plane/native/validator.js +159 -100
- package/dist/src/control-plane/native/verifier.js +227 -166
- package/dist/src/control-plane/pi-sessiond/bin.js +62 -0
- package/dist/src/control-plane/pi-sessiond/server.js +62 -0
- package/dist/src/control-plane/pi-sessiond/session-service.js +62 -0
- package/dist/src/control-plane/pi-settings-materializer.js +52 -0
- package/dist/src/control-plane/plugin-host-context.js +59 -0
- package/dist/src/control-plane/runtime/index.js +469 -410
- package/dist/src/control-plane/runtime/isolation/index.js +493 -434
- package/dist/src/control-plane/runtime/isolation.js +493 -434
- package/dist/src/control-plane/runtime/queue.js +411 -352
- package/dist/src/control-plane/tasks/source-lifecycle.js +87 -28
- package/package.json +8 -8
|
@@ -273,11 +273,15 @@ function normalizeResponse(value) {
|
|
|
273
273
|
// packages/runtime/src/control-plane/pi-sessiond/session-service.ts
|
|
274
274
|
var BUILTIN_COMMANDS = [
|
|
275
275
|
{ name: "session", description: "Show session info and stats", source: "builtin" },
|
|
276
|
+
{ name: "settings", description: "Show worker session settings (model, thinking, name, cwd)", source: "builtin" },
|
|
277
|
+
{ name: "model", description: "Show or set the worker model: /model [provider/id]", source: "builtin" },
|
|
278
|
+
{ name: "thinking", description: "Set the worker thinking level: /thinking <off|minimal|low|medium|high|xhigh>", source: "builtin" },
|
|
276
279
|
{ name: "name", description: "Set session display name", source: "builtin" },
|
|
277
280
|
{ name: "compact", description: "Manually compact session context", source: "builtin" },
|
|
278
281
|
{ name: "reload", description: "Reload keybindings, extensions, skills, prompts, and themes", source: "builtin" },
|
|
279
282
|
{ name: "quit", description: "Detach from the current local Pi frontend", source: "builtin" }
|
|
280
283
|
];
|
|
284
|
+
var THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"];
|
|
281
285
|
|
|
282
286
|
class RigPiSessionService {
|
|
283
287
|
hub;
|
|
@@ -440,6 +444,64 @@ class RigPiSessionService {
|
|
|
440
444
|
const rest = args.join(" ").trim();
|
|
441
445
|
if (rawName === "session")
|
|
442
446
|
return { type: "done", message: formatSessionStats(active.runtime.session) };
|
|
447
|
+
if (rawName === "settings") {
|
|
448
|
+
const session = active.runtime.session;
|
|
449
|
+
const model = session.model;
|
|
450
|
+
return {
|
|
451
|
+
type: "done",
|
|
452
|
+
message: [
|
|
453
|
+
"Worker session settings:",
|
|
454
|
+
` model ${model ? `${model.provider}/${model.id}` : "(none)"} \u2014 change with /model <provider/id>`,
|
|
455
|
+
` thinking ${session.thinkingLevel} \u2014 change with /thinking <${THINKING_LEVELS.join("|")}>`,
|
|
456
|
+
` name ${session.sessionName || "(unnamed)"} \u2014 change with /name <name>`,
|
|
457
|
+
` cwd ${active.runtime.cwd}`,
|
|
458
|
+
` messages ${session.messages.length}`
|
|
459
|
+
].join(`
|
|
460
|
+
`)
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
if (rawName === "model") {
|
|
464
|
+
const session = active.runtime.session;
|
|
465
|
+
if (!rest) {
|
|
466
|
+
const available = session.modelRegistry.getAvailable().map((m) => `${m.provider}/${m.id}`);
|
|
467
|
+
const current = session.model ? `${session.model.provider}/${session.model.id}` : "(none)";
|
|
468
|
+
return {
|
|
469
|
+
type: "done",
|
|
470
|
+
message: [
|
|
471
|
+
`Current model: ${current}`,
|
|
472
|
+
available.length > 0 ? `Available: ${available.join(", ")}` : "No models with configured auth.",
|
|
473
|
+
"Switch with /model <provider/id>."
|
|
474
|
+
].join(`
|
|
475
|
+
`)
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
const [provider, ...idParts] = rest.split("/");
|
|
479
|
+
const id = idParts.join("/");
|
|
480
|
+
const target = provider && id ? session.modelRegistry.find(provider, id) : session.modelRegistry.getAvailable().find((m) => m.id === rest);
|
|
481
|
+
if (!target) {
|
|
482
|
+
return { type: "unsupported", message: `Unknown model "${rest}". Use /model to list available models.` };
|
|
483
|
+
}
|
|
484
|
+
try {
|
|
485
|
+
await session.setModel(target);
|
|
486
|
+
} catch (error) {
|
|
487
|
+
return { type: "unsupported", message: error instanceof Error ? error.message : String(error) };
|
|
488
|
+
}
|
|
489
|
+
this.publishStatus(active);
|
|
490
|
+
return { type: "done", message: `Model set to ${target.provider}/${target.id}.` };
|
|
491
|
+
}
|
|
492
|
+
if (rawName === "thinking") {
|
|
493
|
+
const session = active.runtime.session;
|
|
494
|
+
const level = rest.toLowerCase();
|
|
495
|
+
if (!THINKING_LEVELS.includes(level)) {
|
|
496
|
+
return {
|
|
497
|
+
type: "unsupported",
|
|
498
|
+
message: `Current thinking level: ${session.thinkingLevel}. Usage: /thinking <${THINKING_LEVELS.join("|")}>`
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
session.setThinkingLevel(level);
|
|
502
|
+
this.publishStatus(active);
|
|
503
|
+
return { type: "done", message: `Thinking level set to ${session.thinkingLevel}.` };
|
|
504
|
+
}
|
|
443
505
|
if (rawName === "name") {
|
|
444
506
|
if (!rest)
|
|
445
507
|
return { type: "unsupported", message: "Usage: /name <session name>" };
|
|
@@ -271,11 +271,15 @@ function normalizeResponse(value) {
|
|
|
271
271
|
// packages/runtime/src/control-plane/pi-sessiond/session-service.ts
|
|
272
272
|
var BUILTIN_COMMANDS = [
|
|
273
273
|
{ name: "session", description: "Show session info and stats", source: "builtin" },
|
|
274
|
+
{ name: "settings", description: "Show worker session settings (model, thinking, name, cwd)", source: "builtin" },
|
|
275
|
+
{ name: "model", description: "Show or set the worker model: /model [provider/id]", source: "builtin" },
|
|
276
|
+
{ name: "thinking", description: "Set the worker thinking level: /thinking <off|minimal|low|medium|high|xhigh>", source: "builtin" },
|
|
274
277
|
{ name: "name", description: "Set session display name", source: "builtin" },
|
|
275
278
|
{ name: "compact", description: "Manually compact session context", source: "builtin" },
|
|
276
279
|
{ name: "reload", description: "Reload keybindings, extensions, skills, prompts, and themes", source: "builtin" },
|
|
277
280
|
{ name: "quit", description: "Detach from the current local Pi frontend", source: "builtin" }
|
|
278
281
|
];
|
|
282
|
+
var THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"];
|
|
279
283
|
|
|
280
284
|
class RigPiSessionService {
|
|
281
285
|
hub;
|
|
@@ -438,6 +442,64 @@ class RigPiSessionService {
|
|
|
438
442
|
const rest = args.join(" ").trim();
|
|
439
443
|
if (rawName === "session")
|
|
440
444
|
return { type: "done", message: formatSessionStats(active.runtime.session) };
|
|
445
|
+
if (rawName === "settings") {
|
|
446
|
+
const session = active.runtime.session;
|
|
447
|
+
const model = session.model;
|
|
448
|
+
return {
|
|
449
|
+
type: "done",
|
|
450
|
+
message: [
|
|
451
|
+
"Worker session settings:",
|
|
452
|
+
` model ${model ? `${model.provider}/${model.id}` : "(none)"} \u2014 change with /model <provider/id>`,
|
|
453
|
+
` thinking ${session.thinkingLevel} \u2014 change with /thinking <${THINKING_LEVELS.join("|")}>`,
|
|
454
|
+
` name ${session.sessionName || "(unnamed)"} \u2014 change with /name <name>`,
|
|
455
|
+
` cwd ${active.runtime.cwd}`,
|
|
456
|
+
` messages ${session.messages.length}`
|
|
457
|
+
].join(`
|
|
458
|
+
`)
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
if (rawName === "model") {
|
|
462
|
+
const session = active.runtime.session;
|
|
463
|
+
if (!rest) {
|
|
464
|
+
const available = session.modelRegistry.getAvailable().map((m) => `${m.provider}/${m.id}`);
|
|
465
|
+
const current = session.model ? `${session.model.provider}/${session.model.id}` : "(none)";
|
|
466
|
+
return {
|
|
467
|
+
type: "done",
|
|
468
|
+
message: [
|
|
469
|
+
`Current model: ${current}`,
|
|
470
|
+
available.length > 0 ? `Available: ${available.join(", ")}` : "No models with configured auth.",
|
|
471
|
+
"Switch with /model <provider/id>."
|
|
472
|
+
].join(`
|
|
473
|
+
`)
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
const [provider, ...idParts] = rest.split("/");
|
|
477
|
+
const id = idParts.join("/");
|
|
478
|
+
const target = provider && id ? session.modelRegistry.find(provider, id) : session.modelRegistry.getAvailable().find((m) => m.id === rest);
|
|
479
|
+
if (!target) {
|
|
480
|
+
return { type: "unsupported", message: `Unknown model "${rest}". Use /model to list available models.` };
|
|
481
|
+
}
|
|
482
|
+
try {
|
|
483
|
+
await session.setModel(target);
|
|
484
|
+
} catch (error) {
|
|
485
|
+
return { type: "unsupported", message: error instanceof Error ? error.message : String(error) };
|
|
486
|
+
}
|
|
487
|
+
this.publishStatus(active);
|
|
488
|
+
return { type: "done", message: `Model set to ${target.provider}/${target.id}.` };
|
|
489
|
+
}
|
|
490
|
+
if (rawName === "thinking") {
|
|
491
|
+
const session = active.runtime.session;
|
|
492
|
+
const level = rest.toLowerCase();
|
|
493
|
+
if (!THINKING_LEVELS.includes(level)) {
|
|
494
|
+
return {
|
|
495
|
+
type: "unsupported",
|
|
496
|
+
message: `Current thinking level: ${session.thinkingLevel}. Usage: /thinking <${THINKING_LEVELS.join("|")}>`
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
session.setThinkingLevel(level);
|
|
500
|
+
this.publishStatus(active);
|
|
501
|
+
return { type: "done", message: `Thinking level set to ${session.thinkingLevel}.` };
|
|
502
|
+
}
|
|
441
503
|
if (rawName === "name") {
|
|
442
504
|
if (!rest)
|
|
443
505
|
return { type: "unsupported", message: "Usage: /name <session name>" };
|
|
@@ -210,11 +210,15 @@ function normalizeResponse(value) {
|
|
|
210
210
|
// packages/runtime/src/control-plane/pi-sessiond/session-service.ts
|
|
211
211
|
var BUILTIN_COMMANDS = [
|
|
212
212
|
{ name: "session", description: "Show session info and stats", source: "builtin" },
|
|
213
|
+
{ name: "settings", description: "Show worker session settings (model, thinking, name, cwd)", source: "builtin" },
|
|
214
|
+
{ name: "model", description: "Show or set the worker model: /model [provider/id]", source: "builtin" },
|
|
215
|
+
{ name: "thinking", description: "Set the worker thinking level: /thinking <off|minimal|low|medium|high|xhigh>", source: "builtin" },
|
|
213
216
|
{ name: "name", description: "Set session display name", source: "builtin" },
|
|
214
217
|
{ name: "compact", description: "Manually compact session context", source: "builtin" },
|
|
215
218
|
{ name: "reload", description: "Reload keybindings, extensions, skills, prompts, and themes", source: "builtin" },
|
|
216
219
|
{ name: "quit", description: "Detach from the current local Pi frontend", source: "builtin" }
|
|
217
220
|
];
|
|
221
|
+
var THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"];
|
|
218
222
|
|
|
219
223
|
class RigPiSessionService {
|
|
220
224
|
hub;
|
|
@@ -377,6 +381,64 @@ class RigPiSessionService {
|
|
|
377
381
|
const rest = args.join(" ").trim();
|
|
378
382
|
if (rawName === "session")
|
|
379
383
|
return { type: "done", message: formatSessionStats(active.runtime.session) };
|
|
384
|
+
if (rawName === "settings") {
|
|
385
|
+
const session = active.runtime.session;
|
|
386
|
+
const model = session.model;
|
|
387
|
+
return {
|
|
388
|
+
type: "done",
|
|
389
|
+
message: [
|
|
390
|
+
"Worker session settings:",
|
|
391
|
+
` model ${model ? `${model.provider}/${model.id}` : "(none)"} \u2014 change with /model <provider/id>`,
|
|
392
|
+
` thinking ${session.thinkingLevel} \u2014 change with /thinking <${THINKING_LEVELS.join("|")}>`,
|
|
393
|
+
` name ${session.sessionName || "(unnamed)"} \u2014 change with /name <name>`,
|
|
394
|
+
` cwd ${active.runtime.cwd}`,
|
|
395
|
+
` messages ${session.messages.length}`
|
|
396
|
+
].join(`
|
|
397
|
+
`)
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
if (rawName === "model") {
|
|
401
|
+
const session = active.runtime.session;
|
|
402
|
+
if (!rest) {
|
|
403
|
+
const available = session.modelRegistry.getAvailable().map((m) => `${m.provider}/${m.id}`);
|
|
404
|
+
const current = session.model ? `${session.model.provider}/${session.model.id}` : "(none)";
|
|
405
|
+
return {
|
|
406
|
+
type: "done",
|
|
407
|
+
message: [
|
|
408
|
+
`Current model: ${current}`,
|
|
409
|
+
available.length > 0 ? `Available: ${available.join(", ")}` : "No models with configured auth.",
|
|
410
|
+
"Switch with /model <provider/id>."
|
|
411
|
+
].join(`
|
|
412
|
+
`)
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
const [provider, ...idParts] = rest.split("/");
|
|
416
|
+
const id = idParts.join("/");
|
|
417
|
+
const target = provider && id ? session.modelRegistry.find(provider, id) : session.modelRegistry.getAvailable().find((m) => m.id === rest);
|
|
418
|
+
if (!target) {
|
|
419
|
+
return { type: "unsupported", message: `Unknown model "${rest}". Use /model to list available models.` };
|
|
420
|
+
}
|
|
421
|
+
try {
|
|
422
|
+
await session.setModel(target);
|
|
423
|
+
} catch (error) {
|
|
424
|
+
return { type: "unsupported", message: error instanceof Error ? error.message : String(error) };
|
|
425
|
+
}
|
|
426
|
+
this.publishStatus(active);
|
|
427
|
+
return { type: "done", message: `Model set to ${target.provider}/${target.id}.` };
|
|
428
|
+
}
|
|
429
|
+
if (rawName === "thinking") {
|
|
430
|
+
const session = active.runtime.session;
|
|
431
|
+
const level = rest.toLowerCase();
|
|
432
|
+
if (!THINKING_LEVELS.includes(level)) {
|
|
433
|
+
return {
|
|
434
|
+
type: "unsupported",
|
|
435
|
+
message: `Current thinking level: ${session.thinkingLevel}. Usage: /thinking <${THINKING_LEVELS.join("|")}>`
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
session.setThinkingLevel(level);
|
|
439
|
+
this.publishStatus(active);
|
|
440
|
+
return { type: "done", message: `Thinking level set to ${session.thinkingLevel}.` };
|
|
441
|
+
}
|
|
380
442
|
if (rawName === "name") {
|
|
381
443
|
if (!rest)
|
|
382
444
|
return { type: "unsupported", message: "Usage: /name <session name>" };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/runtime/src/control-plane/pi-settings-materializer.ts
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
4
|
+
import { dirname, resolve } from "path";
|
|
5
|
+
var SETTINGS_RELATIVE_PATH = ".pi/settings.json";
|
|
6
|
+
var MANAGED_RECORD_RELATIVE_PATH = ".rig/state/pi-managed-packages.json";
|
|
7
|
+
function readJson(path, fallback) {
|
|
8
|
+
if (!existsSync(path))
|
|
9
|
+
return fallback;
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
12
|
+
} catch {
|
|
13
|
+
return fallback;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function packageKey(entry) {
|
|
17
|
+
if (typeof entry === "string")
|
|
18
|
+
return entry;
|
|
19
|
+
if (entry && typeof entry === "object" && typeof entry.source === "string") {
|
|
20
|
+
return entry.source;
|
|
21
|
+
}
|
|
22
|
+
return JSON.stringify(entry);
|
|
23
|
+
}
|
|
24
|
+
function materializePiPackages(projectRoot, declaredPackages) {
|
|
25
|
+
const settingsPath = resolve(projectRoot, SETTINGS_RELATIVE_PATH);
|
|
26
|
+
const managedRecordPath = resolve(projectRoot, MANAGED_RECORD_RELATIVE_PATH);
|
|
27
|
+
const settings = readJson(settingsPath, {});
|
|
28
|
+
const previouslyManaged = new Set(readJson(managedRecordPath, []));
|
|
29
|
+
const existing = Array.isArray(settings.packages) ? settings.packages : [];
|
|
30
|
+
const operatorEntries = existing.filter((entry) => !previouslyManaged.has(packageKey(entry)));
|
|
31
|
+
const operatorKeys = new Set(operatorEntries.map(packageKey));
|
|
32
|
+
const managedToAdd = declaredPackages.filter((pkg) => !operatorKeys.has(pkg));
|
|
33
|
+
const nextPackages = [...operatorEntries, ...managedToAdd];
|
|
34
|
+
if (nextPackages.length > 0 || existsSync(settingsPath)) {
|
|
35
|
+
const nextSettings = { ...settings };
|
|
36
|
+
if (nextPackages.length > 0) {
|
|
37
|
+
nextSettings.packages = nextPackages;
|
|
38
|
+
} else {
|
|
39
|
+
delete nextSettings.packages;
|
|
40
|
+
}
|
|
41
|
+
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
42
|
+
writeFileSync(settingsPath, `${JSON.stringify(nextSettings, null, 2)}
|
|
43
|
+
`, "utf-8");
|
|
44
|
+
}
|
|
45
|
+
mkdirSync(dirname(managedRecordPath), { recursive: true });
|
|
46
|
+
writeFileSync(managedRecordPath, `${JSON.stringify(managedToAdd, null, 2)}
|
|
47
|
+
`, "utf-8");
|
|
48
|
+
return { settingsPath, packages: managedToAdd };
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
materializePiPackages
|
|
52
|
+
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/runtime/src/control-plane/plugin-host-context.ts
|
|
3
|
+
import { existsSync as existsSync5 } from "fs";
|
|
4
|
+
import { resolve as resolvePath } from "path";
|
|
3
5
|
import { createPluginHost } from "@rig/core";
|
|
4
6
|
import { loadConfig } from "@rig/core/load-config";
|
|
5
7
|
|
|
@@ -326,6 +328,55 @@ async function materializeSkills(projectRoot, entries) {
|
|
|
326
328
|
return written;
|
|
327
329
|
}
|
|
328
330
|
|
|
331
|
+
// packages/runtime/src/control-plane/pi-settings-materializer.ts
|
|
332
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
333
|
+
import { dirname as dirname2, resolve as resolve3 } from "path";
|
|
334
|
+
var SETTINGS_RELATIVE_PATH = ".pi/settings.json";
|
|
335
|
+
var MANAGED_RECORD_RELATIVE_PATH = ".rig/state/pi-managed-packages.json";
|
|
336
|
+
function readJson(path, fallback) {
|
|
337
|
+
if (!existsSync4(path))
|
|
338
|
+
return fallback;
|
|
339
|
+
try {
|
|
340
|
+
return JSON.parse(readFileSync3(path, "utf-8"));
|
|
341
|
+
} catch {
|
|
342
|
+
return fallback;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function packageKey(entry) {
|
|
346
|
+
if (typeof entry === "string")
|
|
347
|
+
return entry;
|
|
348
|
+
if (entry && typeof entry === "object" && typeof entry.source === "string") {
|
|
349
|
+
return entry.source;
|
|
350
|
+
}
|
|
351
|
+
return JSON.stringify(entry);
|
|
352
|
+
}
|
|
353
|
+
function materializePiPackages(projectRoot, declaredPackages) {
|
|
354
|
+
const settingsPath = resolve3(projectRoot, SETTINGS_RELATIVE_PATH);
|
|
355
|
+
const managedRecordPath = resolve3(projectRoot, MANAGED_RECORD_RELATIVE_PATH);
|
|
356
|
+
const settings = readJson(settingsPath, {});
|
|
357
|
+
const previouslyManaged = new Set(readJson(managedRecordPath, []));
|
|
358
|
+
const existing = Array.isArray(settings.packages) ? settings.packages : [];
|
|
359
|
+
const operatorEntries = existing.filter((entry) => !previouslyManaged.has(packageKey(entry)));
|
|
360
|
+
const operatorKeys = new Set(operatorEntries.map(packageKey));
|
|
361
|
+
const managedToAdd = declaredPackages.filter((pkg) => !operatorKeys.has(pkg));
|
|
362
|
+
const nextPackages = [...operatorEntries, ...managedToAdd];
|
|
363
|
+
if (nextPackages.length > 0 || existsSync4(settingsPath)) {
|
|
364
|
+
const nextSettings = { ...settings };
|
|
365
|
+
if (nextPackages.length > 0) {
|
|
366
|
+
nextSettings.packages = nextPackages;
|
|
367
|
+
} else {
|
|
368
|
+
delete nextSettings.packages;
|
|
369
|
+
}
|
|
370
|
+
mkdirSync3(dirname2(settingsPath), { recursive: true });
|
|
371
|
+
writeFileSync3(settingsPath, `${JSON.stringify(nextSettings, null, 2)}
|
|
372
|
+
`, "utf-8");
|
|
373
|
+
}
|
|
374
|
+
mkdirSync3(dirname2(managedRecordPath), { recursive: true });
|
|
375
|
+
writeFileSync3(managedRecordPath, `${JSON.stringify(managedToAdd, null, 2)}
|
|
376
|
+
`, "utf-8");
|
|
377
|
+
return { settingsPath, packages: managedToAdd };
|
|
378
|
+
}
|
|
379
|
+
|
|
329
380
|
// packages/runtime/src/control-plane/plugin-host-context.ts
|
|
330
381
|
async function buildPluginHostContext(projectRoot) {
|
|
331
382
|
let config;
|
|
@@ -373,6 +424,14 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
373
424
|
} catch (err) {
|
|
374
425
|
console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
375
426
|
}
|
|
427
|
+
try {
|
|
428
|
+
const piPackages = config.runtime?.pi?.packages ?? [];
|
|
429
|
+
if (piPackages.length > 0 || existsSync5(resolvePath(projectRoot, ".rig/state/pi-managed-packages.json"))) {
|
|
430
|
+
materializePiPackages(projectRoot, piPackages);
|
|
431
|
+
}
|
|
432
|
+
} catch (err) {
|
|
433
|
+
console.warn(`[plugin-host] Pi package materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
434
|
+
}
|
|
376
435
|
return {
|
|
377
436
|
config,
|
|
378
437
|
pluginHost,
|