thoth-agents 0.13.1 → 0.14.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/README.md +50 -11
- package/dist/{chunk-HFBCW4MD.js → chunk-5ANFI4LW.js} +18 -16
- package/dist/{chunk-422L76R5.js → chunk-7B7JYFIJ.js} +3 -4
- package/dist/{chunk-A7IGKE4R.js → chunk-ECCXTDVD.js} +138 -89
- package/dist/{chunk-KUA3F4D6.js → chunk-T2K7DYTA.js} +3 -3
- package/dist/cli/index.js +4 -4
- package/dist/cli/pi-install.d.ts +13 -5
- package/dist/cli/tui/index.js +3 -3
- package/dist/harness/core/agent-pack.d.ts +11 -11
- package/dist/index.js +2 -2
- package/dist/pi.js +2 -2
- package/package.json +1 -1
- package/pi/.thoth-agents-assets.json +3 -3
- package/pi/agents/thoth-designer.md +10 -9
- package/pi/agents/thoth-librarian.md +1 -1
- package/pi/agents/thoth-worker.md +5 -5
- package/plugin/.claude-plugin/.thoth-agents-plugin-assets.json +3 -3
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/.thoth-agents-plugin-assets.json +3 -3
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/agents/designer.md +9 -8
- package/plugin/agents/orchestrator.md +3 -2
- package/plugin/agents/worker.md +5 -5
- package/plugin/codex-hooks/payloads/designer.md +9 -8
- package/plugin/codex-hooks/payloads/root.md +3 -2
- package/plugin/codex-hooks/payloads/worker.md +4 -4
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
savePiModelConfig,
|
|
18
18
|
syncPiSpecialists,
|
|
19
19
|
writePiManagedText
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-7B7JYFIJ.js";
|
|
21
21
|
import {
|
|
22
22
|
ALL_AGENT_NAMES,
|
|
23
23
|
CLAUDE_CODE_PROMPT_DIALECT,
|
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
withoutLegacyPresets,
|
|
58
58
|
writeConfig,
|
|
59
59
|
writeLiteConfig
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-5ANFI4LW.js";
|
|
61
61
|
|
|
62
62
|
// src/cli/model-effort.ts
|
|
63
63
|
function normalizeEffortSelection(value) {
|
|
@@ -9277,12 +9277,6 @@ var PI_PACKAGE_SPECS = [
|
|
|
9277
9277
|
packageName: "@thoth-agents/pi-subagents",
|
|
9278
9278
|
version: "0.3.0"
|
|
9279
9279
|
},
|
|
9280
|
-
{
|
|
9281
|
-
id: "context7",
|
|
9282
|
-
source: "npm:@upstash/context7-pi@>=0.1.2",
|
|
9283
|
-
packageName: "@upstash/context7-pi",
|
|
9284
|
-
version: "0.1.2"
|
|
9285
|
-
},
|
|
9286
9280
|
{
|
|
9287
9281
|
id: "web-access",
|
|
9288
9282
|
source: "npm:pi-web-access@>=0.27.0",
|
|
@@ -9327,6 +9321,12 @@ var PI_PACKAGE_SPECS = [
|
|
|
9327
9321
|
packageName: "@thoth-agents/pi-sidebar",
|
|
9328
9322
|
version: "0.3.0",
|
|
9329
9323
|
preserveUserCopy: true
|
|
9324
|
+
},
|
|
9325
|
+
{
|
|
9326
|
+
id: "contained-shell",
|
|
9327
|
+
source: "npm:@thoth-agents/pi-contained-shell@>=0.1.0",
|
|
9328
|
+
packageName: "@thoth-agents/pi-contained-shell",
|
|
9329
|
+
version: "0.1.0"
|
|
9330
9330
|
}
|
|
9331
9331
|
];
|
|
9332
9332
|
var PI_GREP_MCP_ENTRY = {
|
|
@@ -9334,6 +9334,13 @@ var PI_GREP_MCP_ENTRY = {
|
|
|
9334
9334
|
protocolVersion: "legacy",
|
|
9335
9335
|
lifecycle: "lazy"
|
|
9336
9336
|
};
|
|
9337
|
+
var PI_CONTEXT7_MCP_ENTRY = {
|
|
9338
|
+
url: "https://mcp.context7.com/mcp",
|
|
9339
|
+
protocolVersion: "auto",
|
|
9340
|
+
lifecycle: "lazy",
|
|
9341
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: MCP adapter environment expansion, not JavaScript interpolation.
|
|
9342
|
+
headers: { CONTEXT7_API_KEY: "${CONTEXT7_API_KEY:-}" }
|
|
9343
|
+
};
|
|
9337
9344
|
function getPiFirstPartySource(version) {
|
|
9338
9345
|
return `npm:thoth-agents@${version}`;
|
|
9339
9346
|
}
|
|
@@ -9488,41 +9495,47 @@ function piPreservedPackageRecovery(spec, evidence) {
|
|
|
9488
9495
|
}
|
|
9489
9496
|
var PI_INCUMBENT_TODO_NAME = "@juicesharp/rpiv-todo";
|
|
9490
9497
|
var PI_INCUMBENT_QUESTIONS_NAME = "@juicesharp/rpiv-ask-user-question";
|
|
9491
|
-
|
|
9498
|
+
var PI_REPLACED_PACKAGES = [
|
|
9499
|
+
PI_INCUMBENT_QUESTIONS_NAME,
|
|
9500
|
+
"@upstash/context7-pi"
|
|
9501
|
+
];
|
|
9502
|
+
function piNpmSourceName(source) {
|
|
9492
9503
|
if (!source.startsWith("npm:")) return void 0;
|
|
9493
9504
|
const spec = source.slice(4).trim();
|
|
9494
9505
|
const alias = spec.indexOf("@npm:");
|
|
9495
9506
|
const target = alias >= 0 ? spec.slice(alias + 5) : spec;
|
|
9496
9507
|
return target.match(/^(@[^/@\s]+\/[^/@\s]+|[^/@\s]+)(?:@.+)?$/)?.[1];
|
|
9497
9508
|
}
|
|
9498
|
-
function
|
|
9509
|
+
function findPiReplacedPackages(packages) {
|
|
9499
9510
|
return packages.filter(
|
|
9500
|
-
(candidate) =>
|
|
9511
|
+
(candidate) => PI_REPLACED_PACKAGES.includes(piNpmSourceName(candidate.source) ?? "") || PI_REPLACED_PACKAGES.includes(
|
|
9512
|
+
configuredPackageIdentity(candidate).packageName ?? ""
|
|
9513
|
+
)
|
|
9501
9514
|
);
|
|
9502
9515
|
}
|
|
9503
|
-
function
|
|
9516
|
+
function piReplacedPackageIdentityBlockers(packages, plan) {
|
|
9504
9517
|
return packages.flatMap((candidate) => {
|
|
9505
9518
|
const manifest = configuredPackageManifest(candidate);
|
|
9506
9519
|
if (typeof manifest?.name === "string" && manifest.name) return [];
|
|
9507
9520
|
const npmSource = candidate.source.startsWith("npm:");
|
|
9508
|
-
const
|
|
9521
|
+
const replacedSource = /(?:^|[\\/:@?#._-])(?:rpiv-ask-user-question|context7-pi)(?:$|[\\/:@?#._-])/i.test(
|
|
9509
9522
|
candidate.source
|
|
9510
9523
|
);
|
|
9511
9524
|
const unresolvedNpmLocation = npmSource && !candidate.installedPath;
|
|
9512
|
-
const unresolvedAlias = npmSource && candidate.source.includes("@npm:") && !
|
|
9513
|
-
const
|
|
9525
|
+
const unresolvedAlias = npmSource && candidate.source.includes("@npm:") && !piNpmSourceName(candidate.source);
|
|
9526
|
+
const previewedPackage = candidate.scope === "user" && plan?.items.some(
|
|
9514
9527
|
({ command }) => command?.command === "pi" && command.args[0] === "remove" && command.args[1] === candidate.source && command.args[2] === "--no-approve"
|
|
9515
9528
|
);
|
|
9516
|
-
if (manifest && !
|
|
9517
|
-
if (!
|
|
9529
|
+
if (manifest && !previewedPackage) return [];
|
|
9530
|
+
if (!replacedSource && !unresolvedNpmLocation && !unresolvedAlias && !previewedPackage)
|
|
9518
9531
|
return [];
|
|
9519
9532
|
const flags = candidate.scope === "project" ? "--local --approve" : "--no-approve";
|
|
9520
9533
|
return [
|
|
9521
|
-
`Cannot verify configured Pi package ${candidate.source}: installed manifest identity is unavailable. Review its ownership and inspect its package.json using pi list; if it is ${
|
|
9534
|
+
`Cannot verify configured Pi package ${candidate.source}: installed manifest identity is unavailable. Review its ownership and inspect its package.json using pi list; if it is ${PI_REPLACED_PACKAGES.join(" or ")}, manually run pi remove ${candidate.source} ${flags}. Verify removal, then rerun setup preview.`
|
|
9522
9535
|
];
|
|
9523
9536
|
});
|
|
9524
9537
|
}
|
|
9525
|
-
function
|
|
9538
|
+
function piUnpreviewedPackageRecovery(plan, packages) {
|
|
9526
9539
|
const previewed = new Set(
|
|
9527
9540
|
plan.items.flatMap(
|
|
9528
9541
|
({ command }) => command?.command === "pi" && command.args[0] === "remove" && command.args[2] === "--no-approve" ? [command.args[1]] : []
|
|
@@ -9533,12 +9546,15 @@ function piUnpreviewedQuestionRecovery(plan, packages) {
|
|
|
9533
9546
|
);
|
|
9534
9547
|
if (unpreviewed.length === 0) return void 0;
|
|
9535
9548
|
return unpreviewed.map(
|
|
9536
|
-
({ source }) => `Pi
|
|
9549
|
+
({ source }) => `Pi replaced-package migration blocked: incumbent ${source} was not previewed for removal. Review its ownership, then manually run: pi remove ${source} --no-approve. Verify with pi list, then rerun setup preview; no unpreviewed incumbent may be removed automatically.`
|
|
9537
9550
|
).join("\n");
|
|
9538
9551
|
}
|
|
9539
|
-
function
|
|
9552
|
+
function piProjectReplacedPackageConflict(candidate) {
|
|
9540
9553
|
const source = candidate.unmappedSource ? "<source>" : candidate.source;
|
|
9541
|
-
|
|
9554
|
+
const context7 = piNpmSourceName(candidate.source) === "@upstash/context7-pi" || configuredPackageIdentity(candidate).packageName === "@upstash/context7-pi";
|
|
9555
|
+
const replacement = context7 ? "the managed Context7 MCP entry" : "@thoth-agents/pi-questions-user";
|
|
9556
|
+
const kind = context7 ? "Context7 extension" : "question package";
|
|
9557
|
+
return `Incumbent Pi ${kind} ${candidate.source} conflicts with ${replacement}. ${candidate.identityLimitation ? `${candidate.identityLimitation} ` : ""}Review the project's ownership and trust first; --approve trusts project-local settings for this command only without saving a trust decision. ${candidate.unmappedSource ? "Find the matching project settings entry, then" : "Then"} run: pi remove ${source} --local --approve. Verify removal, then rerun setup.`;
|
|
9542
9558
|
}
|
|
9543
9559
|
function isPiIncumbentTodoSource(source) {
|
|
9544
9560
|
return /^npm:@juicesharp\/rpiv-todo(?:@|$)/.test(source);
|
|
@@ -9737,7 +9753,7 @@ function scanPiProjectInstalledIncumbents(options, configuredPackages) {
|
|
|
9737
9753
|
unmappedSource: true
|
|
9738
9754
|
};
|
|
9739
9755
|
const identity = configuredPackageIdentity(candidate);
|
|
9740
|
-
if ((identity.packageName === PI_INCUMBENT_TODO_NAME || identity.packageName
|
|
9756
|
+
if ((identity.packageName === PI_INCUMBENT_TODO_NAME || PI_REPLACED_PACKAGES.includes(identity.packageName)) && !knownPaths.has(key))
|
|
9741
9757
|
incumbents.push({
|
|
9742
9758
|
...candidate,
|
|
9743
9759
|
...identity,
|
|
@@ -9759,12 +9775,14 @@ function mergePiCodemodeSettings(current) {
|
|
|
9759
9775
|
if (current.codemode !== void 0 && !isRecord7(current.codemode))
|
|
9760
9776
|
throw new Error("Global Pi codemode must be a JSON object.");
|
|
9761
9777
|
const codemode = isRecord7(current.codemode) ? current.codemode : {};
|
|
9762
|
-
let defaultTools = tools ?? ["+codemode"];
|
|
9763
|
-
|
|
9764
|
-
(
|
|
9765
|
-
|
|
9778
|
+
let defaultTools = tools ?? ["+codemode", "+tool_search"];
|
|
9779
|
+
for (const name of ["codemode", "tool_search"]) {
|
|
9780
|
+
if (defaultTools.some(
|
|
9781
|
+
(tool) => [name, `+${name}`, `-${name}`].includes(tool)
|
|
9782
|
+
))
|
|
9783
|
+
continue;
|
|
9766
9784
|
const additive = defaultTools.length > 0 && defaultTools.every((tool) => /^[+-]/.test(tool));
|
|
9767
|
-
defaultTools = [...defaultTools, additive ?
|
|
9785
|
+
defaultTools = [...defaultTools, additive ? `+${name}` : name];
|
|
9768
9786
|
}
|
|
9769
9787
|
return {
|
|
9770
9788
|
...current,
|
|
@@ -9788,15 +9806,27 @@ function mergePiGrepMcpConfig(current) {
|
|
|
9788
9806
|
throw new Error("Global MCP mcpServers must be a JSON object.");
|
|
9789
9807
|
}
|
|
9790
9808
|
const servers = isRecord7(rawServers) ? rawServers : {};
|
|
9791
|
-
const
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
|
|
9809
|
+
for (const [name, entry] of Object.entries({
|
|
9810
|
+
grep: PI_GREP_MCP_ENTRY,
|
|
9811
|
+
context7: PI_CONTEXT7_MCP_ENTRY
|
|
9812
|
+
})) {
|
|
9813
|
+
const existing = servers[name];
|
|
9814
|
+
if (existing !== void 0 && JSON.stringify(existing) !== JSON.stringify(entry)) {
|
|
9815
|
+
throw new Error(
|
|
9816
|
+
`Global MCP server "${name}" is not owned by thoth-agents and conflicts with the required ${name === "grep" ? "grep.app" : "Context7"} entry.`
|
|
9817
|
+
);
|
|
9818
|
+
}
|
|
9796
9819
|
}
|
|
9797
9820
|
return {
|
|
9798
9821
|
...current,
|
|
9799
|
-
mcpServers: {
|
|
9822
|
+
mcpServers: {
|
|
9823
|
+
...servers,
|
|
9824
|
+
grep: { ...PI_GREP_MCP_ENTRY },
|
|
9825
|
+
context7: {
|
|
9826
|
+
...PI_CONTEXT7_MCP_ENTRY,
|
|
9827
|
+
headers: { ...PI_CONTEXT7_MCP_ENTRY.headers }
|
|
9828
|
+
}
|
|
9829
|
+
}
|
|
9800
9830
|
};
|
|
9801
9831
|
}
|
|
9802
9832
|
function frontmatterValue(content, field) {
|
|
@@ -9870,7 +9900,7 @@ function buildPiSetupPlan(options = {}) {
|
|
|
9870
9900
|
}
|
|
9871
9901
|
}
|
|
9872
9902
|
let userPackages = [];
|
|
9873
|
-
let
|
|
9903
|
+
let plannedPackageRemovals = [];
|
|
9874
9904
|
let codemodeSettingsContent;
|
|
9875
9905
|
let subagentsConfigContent;
|
|
9876
9906
|
let mcpContent;
|
|
@@ -9898,8 +9928,8 @@ function buildPiSetupPlan(options = {}) {
|
|
|
9898
9928
|
if (incumbentBlockers.length > 0)
|
|
9899
9929
|
throw new Error(incumbentBlockers.join("\n"));
|
|
9900
9930
|
userPackages = resolvePiConfiguredPackages(userSettings, "user", options);
|
|
9901
|
-
blockers.push(...
|
|
9902
|
-
|
|
9931
|
+
blockers.push(...piReplacedPackageIdentityBlockers(userPackages));
|
|
9932
|
+
plannedPackageRemovals = findPiReplacedPackages(userPackages);
|
|
9903
9933
|
subagentsConfigContent = `${JSON.stringify(
|
|
9904
9934
|
mergePiSubagentsConfig(readJsonObject(paths.subagentsConfigPath)),
|
|
9905
9935
|
null,
|
|
@@ -9933,7 +9963,7 @@ function buildPiSetupPlan(options = {}) {
|
|
|
9933
9963
|
} catch (error) {
|
|
9934
9964
|
blockers.push(error instanceof Error ? error.message : String(error));
|
|
9935
9965
|
}
|
|
9936
|
-
blockers.push(...
|
|
9966
|
+
blockers.push(...piReplacedPackageIdentityBlockers(projectPackages));
|
|
9937
9967
|
for (const pkg of getPiExternalPackageSpecs(options)) {
|
|
9938
9968
|
if (!pkg.preserveUserCopy) continue;
|
|
9939
9969
|
const recovery = piPreservedPackageRecovery(
|
|
@@ -9960,8 +9990,8 @@ function buildPiSetupPlan(options = {}) {
|
|
|
9960
9990
|
`Incumbent Pi task-list package ${incumbent.source} ${location} and conflicts with @thoth-agents/pi-todo. ${recovery}`
|
|
9961
9991
|
);
|
|
9962
9992
|
}
|
|
9963
|
-
for (const incumbent of
|
|
9964
|
-
blockers.push(
|
|
9993
|
+
for (const incumbent of findPiReplacedPackages(projectPackages))
|
|
9994
|
+
blockers.push(piProjectReplacedPackageConflict(incumbent));
|
|
9965
9995
|
for (const path of [...paths.projectAgentRoots, ...paths.projectMcpPaths]) {
|
|
9966
9996
|
if (existsSync14(path))
|
|
9967
9997
|
diagnostics.push(
|
|
@@ -9991,9 +10021,9 @@ function buildPiSetupPlan(options = {}) {
|
|
|
9991
10021
|
args: ["install", firstPartySource, "--no-approve"]
|
|
9992
10022
|
}
|
|
9993
10023
|
},
|
|
9994
|
-
...
|
|
10024
|
+
...plannedPackageRemovals.map(({ source }) => ({
|
|
9995
10025
|
kind: "preflight",
|
|
9996
|
-
description: "Remove the
|
|
10026
|
+
description: "Remove the replaced user package through native Pi removal after root-package verification",
|
|
9997
10027
|
target: source,
|
|
9998
10028
|
command: { command: "pi", args: ["remove", source, "--no-approve"] }
|
|
9999
10029
|
})),
|
|
@@ -10022,7 +10052,7 @@ function buildPiSetupPlan(options = {}) {
|
|
|
10022
10052
|
...mcpContent === void 0 ? [] : [
|
|
10023
10053
|
{
|
|
10024
10054
|
kind: "mcp",
|
|
10025
|
-
description: "Merge attributable global grep.app MCP
|
|
10055
|
+
description: "Merge attributable global grep.app and Context7 MCP entries",
|
|
10026
10056
|
target: paths.mcpConfigPath,
|
|
10027
10057
|
content: mcpContent
|
|
10028
10058
|
}
|
|
@@ -10044,7 +10074,7 @@ function buildPiSetupPlan(options = {}) {
|
|
|
10044
10074
|
projectIncumbentTodos,
|
|
10045
10075
|
disclaimers: [
|
|
10046
10076
|
"Pi extensions execute with the invoking user's system permissions; package minimums and tool allowlists are not a security sandbox.",
|
|
10047
|
-
"
|
|
10077
|
+
"Web access is a native Pi extension; Context7 and grep.app use lazy pi-mcp-adapter entries with directTools intentionally omitted.",
|
|
10048
10078
|
"Project-local resources require Pi trust and may shadow global resources.",
|
|
10049
10079
|
"Global subagents.json requests lean session resources; project-local subagents.json may override it, and full child resource mode is unsupported."
|
|
10050
10080
|
],
|
|
@@ -10314,12 +10344,12 @@ function applyPiSetup(plan) {
|
|
|
10314
10344
|
installedPackages
|
|
10315
10345
|
};
|
|
10316
10346
|
}
|
|
10317
|
-
const
|
|
10347
|
+
const projectReplacedPackages = findPiReplacedPackages([
|
|
10318
10348
|
...configuredBefore.filter(({ scope }) => scope === "project"),
|
|
10319
10349
|
...configuredProjectPackages
|
|
10320
10350
|
]);
|
|
10321
|
-
if (
|
|
10322
|
-
const recovery =
|
|
10351
|
+
if (projectReplacedPackages.length > 0) {
|
|
10352
|
+
const recovery = projectReplacedPackages.map(piProjectReplacedPackageConflict).join("\n");
|
|
10323
10353
|
return {
|
|
10324
10354
|
success: false,
|
|
10325
10355
|
changed,
|
|
@@ -10330,19 +10360,19 @@ function applyPiSetup(plan) {
|
|
|
10330
10360
|
manualRecovery: recovery
|
|
10331
10361
|
};
|
|
10332
10362
|
}
|
|
10333
|
-
const
|
|
10363
|
+
const unpreviewedPackages = piUnpreviewedPackageRecovery(
|
|
10334
10364
|
plan,
|
|
10335
|
-
|
|
10365
|
+
findPiReplacedPackages(configuredBefore)
|
|
10336
10366
|
);
|
|
10337
|
-
if (
|
|
10367
|
+
if (unpreviewedPackages)
|
|
10338
10368
|
return {
|
|
10339
10369
|
success: false,
|
|
10340
10370
|
changed,
|
|
10341
10371
|
diagnostics,
|
|
10342
|
-
error:
|
|
10372
|
+
error: unpreviewedPackages,
|
|
10343
10373
|
failedStep: "preflight",
|
|
10344
10374
|
installedPackages,
|
|
10345
|
-
manualRecovery:
|
|
10375
|
+
manualRecovery: unpreviewedPackages
|
|
10346
10376
|
};
|
|
10347
10377
|
const incumbentTodos = findPiIncumbentTodos([
|
|
10348
10378
|
...configuredBefore,
|
|
@@ -10399,7 +10429,7 @@ function applyPiSetup(plan) {
|
|
|
10399
10429
|
throw new Error(
|
|
10400
10430
|
`First-party Pi package ownership conflict: ${ownership.reason ?? ownership.state}`
|
|
10401
10431
|
);
|
|
10402
|
-
const identityRecovery =
|
|
10432
|
+
const identityRecovery = piReplacedPackageIdentityBlockers(
|
|
10403
10433
|
[...configuredBefore, ...configuredProjectPackages],
|
|
10404
10434
|
plan
|
|
10405
10435
|
).join("\n");
|
|
@@ -10539,31 +10569,33 @@ function applyPiSetup(plan) {
|
|
|
10539
10569
|
if (!migration.success)
|
|
10540
10570
|
throw new Error(migration.error ?? "Pi legacy migration failed.");
|
|
10541
10571
|
changed.push(...migration.changed);
|
|
10542
|
-
const
|
|
10543
|
-
if (
|
|
10572
|
+
const replacementListing = execute("pi", ["list", "--no-approve"]);
|
|
10573
|
+
if (replacementListing.exitCode !== 0)
|
|
10544
10574
|
throw new Error(
|
|
10545
|
-
`Unable to inspect
|
|
10575
|
+
`Unable to inspect replaced Pi packages: ${replacementListing.stderr.trim() || "pi list unavailable"}`
|
|
10546
10576
|
);
|
|
10547
|
-
const
|
|
10548
|
-
|
|
10577
|
+
const replacementPackages = resolvePiListedPackages(
|
|
10578
|
+
replacementListing.stdout,
|
|
10549
10579
|
plan.options
|
|
10550
10580
|
);
|
|
10551
|
-
const
|
|
10552
|
-
|
|
10581
|
+
const freshProjectReplacements = findPiReplacedPackages(
|
|
10582
|
+
replacementPackages
|
|
10553
10583
|
).filter(({ scope }) => scope === "project");
|
|
10554
|
-
const
|
|
10584
|
+
const replacementRecovery = freshProjectReplacements.length > 0 ? freshProjectReplacements.map(piProjectReplacedPackageConflict).join("\n") : piUnpreviewedPackageRecovery(
|
|
10555
10585
|
plan,
|
|
10556
|
-
|
|
10557
|
-
) ?? (
|
|
10558
|
-
|
|
10559
|
-
|
|
10560
|
-
|
|
10561
|
-
|
|
10562
|
-
|
|
10563
|
-
|
|
10586
|
+
findPiReplacedPackages(replacementPackages)
|
|
10587
|
+
) ?? (piReplacedPackageIdentityBlockers(replacementPackages, plan).join(
|
|
10588
|
+
"\n"
|
|
10589
|
+
) || void 0);
|
|
10590
|
+
if (replacementRecovery) {
|
|
10591
|
+
manualRecovery = replacementRecovery;
|
|
10592
|
+
throw new Error(replacementRecovery);
|
|
10593
|
+
}
|
|
10594
|
+
const incumbentReplacements = findPiReplacedPackages(
|
|
10595
|
+
replacementPackages
|
|
10564
10596
|
).filter(({ scope }) => scope === "user");
|
|
10565
|
-
for (const incumbent of
|
|
10566
|
-
const unpreviewed =
|
|
10597
|
+
for (const incumbent of incumbentReplacements) {
|
|
10598
|
+
const unpreviewed = piUnpreviewedPackageRecovery(plan, [incumbent]);
|
|
10567
10599
|
if (unpreviewed) {
|
|
10568
10600
|
manualRecovery = unpreviewed;
|
|
10569
10601
|
throw new Error(unpreviewed);
|
|
@@ -10575,29 +10607,32 @@ function applyPiSetup(plan) {
|
|
|
10575
10607
|
]);
|
|
10576
10608
|
if (removed.exitCode !== 0)
|
|
10577
10609
|
throw new Error(
|
|
10578
|
-
`Failed to remove
|
|
10610
|
+
`Failed to remove replaced Pi package ${incumbent.source}: ${removed.stderr.trim() || "unknown Pi error"}`
|
|
10579
10611
|
);
|
|
10580
10612
|
}
|
|
10581
|
-
if (
|
|
10613
|
+
if (incumbentReplacements.length > 0) {
|
|
10582
10614
|
const afterRemoval = execute("pi", ["list", "--no-approve"]);
|
|
10583
10615
|
const remaining = resolvePiListedPackages(
|
|
10584
10616
|
afterRemoval.stdout,
|
|
10585
10617
|
plan.options
|
|
10586
10618
|
);
|
|
10587
|
-
const identityRecovery2 =
|
|
10588
|
-
|
|
10589
|
-
|
|
10619
|
+
const identityRecovery2 = piReplacedPackageIdentityBlockers(
|
|
10620
|
+
remaining,
|
|
10621
|
+
plan
|
|
10622
|
+
).join("\n");
|
|
10590
10623
|
if (identityRecovery2) {
|
|
10591
10624
|
manualRecovery = identityRecovery2;
|
|
10592
10625
|
throw new Error(identityRecovery2);
|
|
10593
10626
|
}
|
|
10594
|
-
if (afterRemoval.exitCode !== 0 ||
|
|
10627
|
+
if (afterRemoval.exitCode !== 0 || findPiReplacedPackages(remaining).some(
|
|
10595
10628
|
({ scope }) => scope === "user"
|
|
10596
10629
|
) || remaining.some(
|
|
10597
|
-
({ scope, source }) => scope === "user" &&
|
|
10630
|
+
({ scope, source }) => scope === "user" && incumbentReplacements.some(
|
|
10631
|
+
(incumbent) => incumbent.source === source
|
|
10632
|
+
)
|
|
10598
10633
|
))
|
|
10599
10634
|
throw new Error(
|
|
10600
|
-
"Pi did not verify removal of the
|
|
10635
|
+
"Pi did not verify removal of the replaced user package; rerun pi list and remove it before retrying setup."
|
|
10601
10636
|
);
|
|
10602
10637
|
}
|
|
10603
10638
|
for (const pkg of getPiExternalPackageSpecs(plan.options)) {
|
|
@@ -10820,15 +10855,15 @@ var RESEARCH_PROVIDER_LABEL = {
|
|
|
10820
10855
|
function researchRuntimeState(provider, targets, evidence) {
|
|
10821
10856
|
const observed = evidence.research?.[provider];
|
|
10822
10857
|
if (observed) return observed;
|
|
10823
|
-
const packageId = provider === "
|
|
10858
|
+
const packageId = provider === "web-access" ? provider : "grep-adapter";
|
|
10824
10859
|
const packageSource = PI_PACKAGE_SPECS.find(
|
|
10825
10860
|
({ id }) => id === packageId
|
|
10826
10861
|
)?.source;
|
|
10827
10862
|
const packageReady = targets.some(
|
|
10828
10863
|
({ path, state }) => path === packageSource && state === "installed"
|
|
10829
10864
|
);
|
|
10830
|
-
const configReady = provider
|
|
10831
|
-
({ kind, label, state }) => kind === "config" && label
|
|
10865
|
+
const configReady = provider === "web-access" || targets.some(
|
|
10866
|
+
({ kind, label, state }) => kind === "config" && label === `${RESEARCH_PROVIDER_LABEL[provider]} MCP entry` && state === "installed"
|
|
10832
10867
|
);
|
|
10833
10868
|
if (!packageReady || !configReady)
|
|
10834
10869
|
return {
|
|
@@ -10837,15 +10872,10 @@ function researchRuntimeState(provider, targets, evidence) {
|
|
|
10837
10872
|
"managed package or configuration preconditions are not satisfied"
|
|
10838
10873
|
]
|
|
10839
10874
|
};
|
|
10840
|
-
return
|
|
10875
|
+
return {
|
|
10841
10876
|
state: "unverified",
|
|
10842
10877
|
basis: [
|
|
10843
|
-
"
|
|
10844
|
-
]
|
|
10845
|
-
} : {
|
|
10846
|
-
state: "ready",
|
|
10847
|
-
basis: [
|
|
10848
|
-
"managed package and configuration preconditions are satisfied; no live probe was requested"
|
|
10878
|
+
"managed package/configuration evidence is present; no live provider request was observed"
|
|
10849
10879
|
]
|
|
10850
10880
|
};
|
|
10851
10881
|
}
|
|
@@ -10885,6 +10915,25 @@ function statusFromPlan(plan, context2, evidence = {}) {
|
|
|
10885
10915
|
expected: item.kind === "package" ? item.target : "attributable managed content",
|
|
10886
10916
|
description: item.kind === "package" ? "Validated installed-package manifest evidence; this does not prove live tool availability." : void 0
|
|
10887
10917
|
}));
|
|
10918
|
+
let mcpServers;
|
|
10919
|
+
try {
|
|
10920
|
+
const config = JSON.parse(readFileSync14(plan.paths.mcpConfigPath, "utf8"));
|
|
10921
|
+
mcpServers = config.mcpServers;
|
|
10922
|
+
} catch {
|
|
10923
|
+
}
|
|
10924
|
+
for (const [provider, entry] of Object.entries({
|
|
10925
|
+
context7: PI_CONTEXT7_MCP_ENTRY,
|
|
10926
|
+
grep: PI_GREP_MCP_ENTRY
|
|
10927
|
+
})) {
|
|
10928
|
+
const existing = mcpServers?.[provider];
|
|
10929
|
+
targets.push({
|
|
10930
|
+
kind: "config",
|
|
10931
|
+
path: plan.paths.mcpConfigPath,
|
|
10932
|
+
label: `${RESEARCH_PROVIDER_LABEL[provider]} MCP entry`,
|
|
10933
|
+
state: existing === void 0 ? "missing" : JSON.stringify(existing) === JSON.stringify(entry) ? "installed" : "drift",
|
|
10934
|
+
description: "Managed MCP entry evidence only; no live provider request was observed."
|
|
10935
|
+
});
|
|
10936
|
+
}
|
|
10888
10937
|
const execute = context2.piCommandExecutor ?? ((command, args) => {
|
|
10889
10938
|
const result = spawnSync8(command, [...args], {
|
|
10890
10939
|
windowsHide: true,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
loadAgentPrompt,
|
|
17
17
|
renderAgentRoutingDescription,
|
|
18
18
|
renderRolePrompt
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-5ANFI4LW.js";
|
|
20
20
|
|
|
21
21
|
// src/agents/designer.ts
|
|
22
22
|
var DESIGNER_PROMPT = renderRolePrompt(
|
|
@@ -34,7 +34,7 @@ function createDesignerAgent(model, customPrompt, customAppendPrompt) {
|
|
|
34
34
|
});
|
|
35
35
|
return {
|
|
36
36
|
name: "designer",
|
|
37
|
-
description: "Write-capable UI/UX
|
|
37
|
+
description: "Write-capable UI/UX and creative/artistic specialist owning approach, execution, and visual and creative verification.",
|
|
38
38
|
config: {
|
|
39
39
|
model,
|
|
40
40
|
temperature: 0.4,
|
|
@@ -173,7 +173,7 @@ function createWorkerAgent(model, customPrompt, customAppendPrompt) {
|
|
|
173
173
|
});
|
|
174
174
|
return {
|
|
175
175
|
name: "worker",
|
|
176
|
-
description: "Write-capable agent for bounded
|
|
176
|
+
description: "Write-capable agent for bounded engineering implementation regardless of complexity, with thorough context analysis, edge-case handling, and correctness verification.",
|
|
177
177
|
config: {
|
|
178
178
|
model,
|
|
179
179
|
temperature: 0.1,
|
package/dist/cli/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
opencodeAdapter
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-T2K7DYTA.js";
|
|
5
5
|
import {
|
|
6
6
|
CODEX_PLUGIN_ID,
|
|
7
7
|
CODEX_ROLE_NAMES,
|
|
@@ -80,11 +80,11 @@ import {
|
|
|
80
80
|
safeAtomicWriteFileSync,
|
|
81
81
|
scalarLocation,
|
|
82
82
|
syncOpenCodeOwnedSkills
|
|
83
|
-
} from "../chunk-
|
|
83
|
+
} from "../chunk-ECCXTDVD.js";
|
|
84
84
|
import "../chunk-MIDGZE34.js";
|
|
85
85
|
import {
|
|
86
86
|
piAdapter
|
|
87
|
-
} from "../chunk-
|
|
87
|
+
} from "../chunk-7B7JYFIJ.js";
|
|
88
88
|
import {
|
|
89
89
|
ALL_AGENT_NAMES,
|
|
90
90
|
detectCurrentConfig,
|
|
@@ -95,7 +95,7 @@ import {
|
|
|
95
95
|
resolveExecutingPackageVersion,
|
|
96
96
|
updateOpenCodeMainConfig,
|
|
97
97
|
writeLiteConfig
|
|
98
|
-
} from "../chunk-
|
|
98
|
+
} from "../chunk-5ANFI4LW.js";
|
|
99
99
|
|
|
100
100
|
// src/cli/index.ts
|
|
101
101
|
import { pathToFileURL } from "url";
|
package/dist/cli/pi-install.d.ts
CHANGED
|
@@ -13,11 +13,6 @@ export declare const PI_PACKAGE_SPECS: readonly [{
|
|
|
13
13
|
readonly source: "npm:@thoth-agents/pi-subagents@>=0.3.0";
|
|
14
14
|
readonly packageName: "@thoth-agents/pi-subagents";
|
|
15
15
|
readonly version: "0.3.0";
|
|
16
|
-
}, {
|
|
17
|
-
readonly id: "context7";
|
|
18
|
-
readonly source: "npm:@upstash/context7-pi@>=0.1.2";
|
|
19
|
-
readonly packageName: "@upstash/context7-pi";
|
|
20
|
-
readonly version: "0.1.2";
|
|
21
16
|
}, {
|
|
22
17
|
readonly id: "web-access";
|
|
23
18
|
readonly source: "npm:pi-web-access@>=0.27.0";
|
|
@@ -56,12 +51,25 @@ export declare const PI_PACKAGE_SPECS: readonly [{
|
|
|
56
51
|
readonly packageName: "@thoth-agents/pi-sidebar";
|
|
57
52
|
readonly version: "0.3.0";
|
|
58
53
|
readonly preserveUserCopy: true;
|
|
54
|
+
}, {
|
|
55
|
+
readonly id: "contained-shell";
|
|
56
|
+
readonly source: "npm:@thoth-agents/pi-contained-shell@>=0.1.0";
|
|
57
|
+
readonly packageName: "@thoth-agents/pi-contained-shell";
|
|
58
|
+
readonly version: "0.1.0";
|
|
59
59
|
}];
|
|
60
60
|
export declare const PI_GREP_MCP_ENTRY: {
|
|
61
61
|
readonly url: "https://mcp.grep.app";
|
|
62
62
|
readonly protocolVersion: "legacy";
|
|
63
63
|
readonly lifecycle: "lazy";
|
|
64
64
|
};
|
|
65
|
+
export declare const PI_CONTEXT7_MCP_ENTRY: {
|
|
66
|
+
readonly url: "https://mcp.context7.com/mcp";
|
|
67
|
+
readonly protocolVersion: "auto";
|
|
68
|
+
readonly lifecycle: "lazy";
|
|
69
|
+
readonly headers: {
|
|
70
|
+
readonly CONTEXT7_API_KEY: "${CONTEXT7_API_KEY:-}";
|
|
71
|
+
};
|
|
72
|
+
};
|
|
65
73
|
export interface PiCommandResult {
|
|
66
74
|
exitCode: number | null;
|
|
67
75
|
stdout: string;
|
package/dist/cli/tui/index.js
CHANGED
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
defaultTuiOperations,
|
|
3
3
|
effortChoicesForModel,
|
|
4
4
|
listOperationHarnesses
|
|
5
|
-
} from "../../chunk-
|
|
5
|
+
} from "../../chunk-ECCXTDVD.js";
|
|
6
6
|
import "../../chunk-MIDGZE34.js";
|
|
7
|
-
import "../../chunk-
|
|
8
|
-
import "../../chunk-
|
|
7
|
+
import "../../chunk-7B7JYFIJ.js";
|
|
8
|
+
import "../../chunk-5ANFI4LW.js";
|
|
9
9
|
|
|
10
10
|
// src/cli/tui/index.tsx
|
|
11
11
|
import { render } from "ink";
|
|
@@ -127,22 +127,22 @@ export declare const AGENT_ROLES: readonly [{
|
|
|
127
127
|
readonly mode: "write-capable";
|
|
128
128
|
readonly dispatch: "task";
|
|
129
129
|
readonly canMutateWorkspace: true;
|
|
130
|
-
readonly scope: "UI/UX decisions, implementation, and
|
|
131
|
-
readonly responsibility: "Own
|
|
132
|
-
readonly useWhen: ["
|
|
133
|
-
readonly doNotUseWhen: ["Not for
|
|
130
|
+
readonly scope: "UI/UX and creative/artistic decisions, implementation, and verification";
|
|
131
|
+
readonly responsibility: "Own UI/UX, creative/artistic output, and aesthetic quality.";
|
|
132
|
+
readonly useWhen: ["Material UI/UX, interaction, accessibility, visual quality, or creative/artistic work: visual style, motion/animation, layouts/levels/maps, characters, visual/audio assets, branding, creative copy, narrative."];
|
|
133
|
+
readonly doNotUseWhen: ["Not for engineering-only or correctness-heavy cross-cutting work."];
|
|
134
134
|
readonly escalateWhen: ["Escalate coupled contracts, migrations, or high risk to worker."];
|
|
135
|
-
readonly toolGovernance: ["may edit focused UI/UX files", "owns
|
|
136
|
-
readonly verification: ["includes visual verification when applicable"];
|
|
135
|
+
readonly toolGovernance: ["may edit focused UI/UX and creative/artistic files", "owns visual and creative QA, including screenshots", "does not delegate further"];
|
|
136
|
+
readonly verification: ["includes visual and creative verification when applicable"];
|
|
137
137
|
}, {
|
|
138
138
|
readonly name: "worker";
|
|
139
139
|
readonly mode: "write-capable";
|
|
140
140
|
readonly dispatch: "task";
|
|
141
141
|
readonly canMutateWorkspace: true;
|
|
142
|
-
readonly scope: "bounded
|
|
143
|
-
readonly responsibility: "Handle bounded
|
|
144
|
-
readonly useWhen: ["Known bounded
|
|
145
|
-
readonly doNotUseWhen: ["Not for visual-only work, reviewed commits, or work explicitly retained by the user in root."];
|
|
142
|
+
readonly scope: "bounded engineering implementation and verification";
|
|
143
|
+
readonly responsibility: "Handle bounded engineering implementation (business logic, backend, systems, mechanic scripts, calculations, AI) with full local context, including exact low-risk edits and correctness-critical, multi-file, edge-case-heavy, or high-risk work.";
|
|
144
|
+
readonly useWhen: ["Known bounded engineering implementation, regardless of complexity; root direct work only under bounded implementation-ownership exceptions.", "Correctness-critical work may be multi-file, edge-case-heavy, migration, concurrency, shared-contract, or high-risk."];
|
|
145
|
+
readonly doNotUseWhen: ["Not for visual-only or artistic/creative work, reviewed commits, or work explicitly retained by the user in root."];
|
|
146
146
|
readonly escalateWhen: ["Return product or architecture choices to root."];
|
|
147
147
|
readonly toolGovernance: ["may edit implementation and tests within the assigned surface", "validates shared behavior against related code and call sites", "does not delegate further"];
|
|
148
148
|
readonly verification: ["reports focused checks and relevant edge-case evidence"];
|
|
@@ -159,7 +159,7 @@ export declare const AGENT_RETURN_CONTRACT: {
|
|
|
159
159
|
readonly designer: readonly ["conclusion", "evidence", "verification", "risks", "openQuestions", "nextAction", "changedFiles"];
|
|
160
160
|
readonly worker: readonly ["conclusion", "evidence", "verification", "risks", "openQuestions", "nextAction", "changedFiles"];
|
|
161
161
|
};
|
|
162
|
-
export declare const VERIFICATION_PROTOCOL: readonly ["Completion reports identify changed files and verification evidence.", "Behavior changes receive the smallest sufficient automated check or a declared manual check.", "Visual
|
|
162
|
+
export declare const VERIFICATION_PROTOCOL: readonly ["Completion reports identify changed files and verification evidence.", "Behavior changes receive the smallest sufficient automated check or a declared manual check.", "Visual and creative output receives designer-owned visual and creative QA when applicable."];
|
|
163
163
|
export declare const AGENT_PACK_CONTRACT: AgentPackContract;
|
|
164
164
|
export declare function getAgentRole(name: AgentRoleName): AgentRoleContract;
|
|
165
165
|
/** Keep non-gate returns independent of the Oracle validator contract. */
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
createAgents,
|
|
11
11
|
renderOpenCodeAgentConfigs
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-T2K7DYTA.js";
|
|
13
13
|
import {
|
|
14
14
|
context7,
|
|
15
15
|
exa,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
mergeProfileModelChain,
|
|
27
27
|
resolveRoleProfile,
|
|
28
28
|
validateProfileName
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-5ANFI4LW.js";
|
|
30
30
|
|
|
31
31
|
// src/opencode/permission-rules.ts
|
|
32
32
|
var ACTIONS = {
|