@difflab/pi 0.7.1 → 0.8.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 +23 -39
- package/agents/diffpi-copilot.md +2 -2
- package/agents/diffpi-orchestrator.md +9 -14
- package/agents/diffpi-plan-reviewer.md +4 -12
- package/agents/diffpi-planner.md +6 -12
- package/agents/diffpi-reviewer.md +6 -10
- package/agents/diffpi-tutor.md +2 -2
- package/agents/diffpi-worker.md +3 -6
- package/dist/commands/dispatch.d.ts +4 -0
- package/dist/commands/dispatch.d.ts.map +1 -0
- package/dist/commands/index.d.ts +1 -3
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/plan.d.ts +1 -1
- package/dist/commands/plan.d.ts.map +1 -1
- package/dist/commands/review.d.ts +1 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/doctor.d.ts +9 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/extensions/index.js +2705 -3114
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -403
- package/dist/tools/ci.d.ts +1 -1
- package/dist/tools/doctor.d.ts +3 -0
- package/dist/tools/doctor.d.ts.map +1 -0
- package/dist/tools/index.d.ts +2 -3
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2601 -2610
- package/package.json +2 -2
- package/skills/diffpi-doctor/SKILL.md +10 -0
- package/skills/diffpi-setup/SKILL.md +1 -1
- package/skills/plan/SKILL.md +13 -23
- package/skills/plan/references/design-quality.md +3 -3
- package/skills/plan/references/workflows/annotate.md +9 -3
- package/skills/plan/references/workflows/finalize.md +10 -6
- package/skills/plan/references/workflows/go.md +25 -7
- package/skills/plan/references/workflows/help.md +20 -3
- package/skills/plan/references/workflows/init.md +23 -6
- package/skills/plan/references/workflows/inline-fallback.md +9 -0
- package/skills/plan/references/workflows/new.md +22 -7
- package/skills/plan/references/workflows/update.md +22 -6
- package/skills/plan/references/workflows/validate.md +31 -0
- package/skills/review/SKILL.md +15 -7
- package/skills/review/references/workflows/address.md +19 -6
- package/skills/review/references/workflows/auto.md +21 -5
- package/skills/review/references/workflows/complete.md +17 -4
- package/skills/review/references/workflows/edit.md +8 -2
- package/skills/review/references/workflows/foreground-fallback.md +7 -0
- package/skills/review/references/workflows/help.md +22 -13
- package/skills/review/references/workflows/merge.md +17 -2
- package/skills/review/references/workflows/new.md +17 -5
- package/skills/review/references/workflows/open.md +8 -2
- package/skills/review/references/workflows/publish.md +17 -4
- package/skills/review/references/workflows/status.md +7 -2
- package/templates/plan/PLAN.md +1 -1
- package/dist/commands/mode.d.ts +0 -5
- package/dist/commands/mode.d.ts.map +0 -1
- package/dist/modes.d.ts +0 -75
- package/dist/modes.d.ts.map +0 -1
- package/dist/tools/modes.d.ts +0 -4
- package/dist/tools/modes.d.ts.map +0 -1
- package/skills/mode/SKILL.md +0 -38
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ export { checkConventionalSubject, CONVENTIONAL_COMMIT, runMiseGates } from './g
|
|
|
6
6
|
export { assertReviewEventSupported, createLocalReviewBackend, createRemoteReviewBackend, githubReviewSubmissionEndpoint, hasGitlabDraftNotes, parseGitlabDiffRefs, } from './review';
|
|
7
7
|
export { mcp } from './mcp';
|
|
8
8
|
export { mise } from './extensions/misex';
|
|
9
|
-
export { createModeController, discoverAgentModes, resolveAgentMode } from './modes';
|
|
10
9
|
export { pi } from './pi';
|
|
11
10
|
export { loadReviewPublicationState, reviewBodyFingerprint, reviewCommentFingerprint, reviewReplyFingerprint, saveReviewPublicationState, unpublishedReviewComments, } from './review';
|
|
12
11
|
export { computeProjectSlug, ensureStore, plansDir, reviewsDir, sessionsDir, storeDir, storeGlobalRoot } from './store';
|
|
@@ -17,7 +16,6 @@ export { dedupeFindings, findingSchema, findingsSchema, yymmdd, localReviewAutho
|
|
|
17
16
|
export { ensureMcpAdapters, ensureMise, ensureMiseDeps, ensureMiseHooks, ensurePiAgents, ensurePiPlugins, ensurePiSkills, setupPi, } from './setup';
|
|
18
17
|
export { loadTemplate, renderTemplate, templateRelativePath } from './templates';
|
|
19
18
|
export type { DiffpiAgentConfig, DiffpiConfig, DiffpiConfigPaths, LoadedDiffpiConfig } from './config';
|
|
20
|
-
export type { AgentMode, ModeCatalog, ModeController, ModeListOptions, ModePromptStrategy, ModeSelectionResult, ModeThinkingLevel, } from './modes';
|
|
21
19
|
export type { CommandResult } from './extensions/processx';
|
|
22
20
|
export type { ForgeProvider, Ide, LaunchOptions, LaunchResult, Mux, VcsInfo } from './environment';
|
|
23
21
|
export type { Forge, OpenPrOptions, PrRef, VcsBackend } from './vcs';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAC;AACjH,OAAO,EACL,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,WAAW,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,sBAAsB,EACtB,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACtF,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,EAC9B,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -15,15 +15,6 @@ var zx = {
|
|
|
15
15
|
|
|
16
16
|
// src/fsx.ts
|
|
17
17
|
import { readdir, readFile } from "node:fs/promises";
|
|
18
|
-
async function readDirectoryIfExists(path) {
|
|
19
|
-
try {
|
|
20
|
-
return await readdir(path, { withFileTypes: true });
|
|
21
|
-
} catch (error) {
|
|
22
|
-
if (isMissingPath(error))
|
|
23
|
-
return [];
|
|
24
|
-
throw error;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
18
|
async function readTextIfExists(path) {
|
|
28
19
|
try {
|
|
29
20
|
return await readFile(path, "utf8");
|
|
@@ -2108,361 +2099,10 @@ async function getOptionalFile2(path) {
|
|
|
2108
2099
|
function isRecord(value) {
|
|
2109
2100
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2110
2101
|
}
|
|
2111
|
-
// src/modes.ts
|
|
2112
|
-
import {
|
|
2113
|
-
getAgentDir,
|
|
2114
|
-
parseFrontmatter as parseFrontmatter2
|
|
2115
|
-
} from "@earendil-works/pi-coding-agent";
|
|
2116
|
-
import { readFile as readFile9 } from "node:fs/promises";
|
|
2117
|
-
import { homedir as homedir6 } from "node:os";
|
|
2118
|
-
import { basename as basename4, extname, join as join11 } from "node:path";
|
|
2119
|
-
async function discoverAgentModes(options) {
|
|
2120
|
-
const agentDir = options.agentDir ?? getAgentDir();
|
|
2121
|
-
const homeDir = options.homeDir ?? homedir6();
|
|
2122
|
-
const modes = new Map;
|
|
2123
|
-
const diagnostics = [];
|
|
2124
|
-
await loadAgentModes(options.bundledAgentsDir ?? BUNDLED_AGENTS_DIR, "diffpi agent", modes, diagnostics);
|
|
2125
|
-
await loadAgentModes(join11(agentDir, "agents"), "user agent", modes, diagnostics);
|
|
2126
|
-
if (options.includeSkills) {
|
|
2127
|
-
await loadSkillModes(join11(homeDir, ".agents", "skills"), "user skill", modes, diagnostics);
|
|
2128
|
-
await loadSkillModes(join11(agentDir, "skills"), "pi user skill", modes, diagnostics);
|
|
2129
|
-
}
|
|
2130
|
-
if (options.projectTrusted === true) {
|
|
2131
|
-
if (options.includeSkills) {
|
|
2132
|
-
await loadSkillModes(join11(options.cwd, ".agents", "skills"), "project skill", modes, diagnostics);
|
|
2133
|
-
await loadSkillModes(join11(options.cwd, ".pi", "skills"), "pi project skill", modes, diagnostics);
|
|
2134
|
-
}
|
|
2135
|
-
await loadAgentModes(join11(options.cwd, ".agents", "agents"), "project agent", modes, diagnostics);
|
|
2136
|
-
await loadAgentModes(join11(options.cwd, ".pi", "agents"), "pi project agent", modes, diagnostics);
|
|
2137
|
-
}
|
|
2138
|
-
const userConfig = await loadDiffpiConfig({ homeDir });
|
|
2139
|
-
const configuredModes = [...modes.values()].map((mode) => ({
|
|
2140
|
-
...mode,
|
|
2141
|
-
modelPreferences: resolveAgentModelPreferences(mode.id, mode.modelPreferences, userConfig.config)
|
|
2142
|
-
}));
|
|
2143
|
-
return {
|
|
2144
|
-
modes: configuredModes.sort((left, right) => left.id.localeCompare(right.id)),
|
|
2145
|
-
diagnostics
|
|
2146
|
-
};
|
|
2147
|
-
}
|
|
2148
|
-
function resolveAgentMode(modes, requested) {
|
|
2149
|
-
const name = requested.trim();
|
|
2150
|
-
if (!name)
|
|
2151
|
-
return { ok: false, message: "Agent name is required." };
|
|
2152
|
-
const exact = modes.find((mode) => mode.id === name);
|
|
2153
|
-
if (exact)
|
|
2154
|
-
return { ok: true, active: exact, message: `Active inline agent: ${exact.id}.` };
|
|
2155
|
-
const lowerName = name.toLowerCase();
|
|
2156
|
-
const matches = modes.filter((mode) => mode.id.toLowerCase() === lowerName);
|
|
2157
|
-
if (matches.length === 1) {
|
|
2158
|
-
const active = matches[0];
|
|
2159
|
-
return { ok: true, active, message: `Active inline agent: ${active.id}.` };
|
|
2160
|
-
}
|
|
2161
|
-
if (matches.length > 1) {
|
|
2162
|
-
return {
|
|
2163
|
-
ok: false,
|
|
2164
|
-
message: `Inline agent "${name}" is ambiguous. Use one of: ${matches.map((mode) => mode.id).join(", ")}.`
|
|
2165
|
-
};
|
|
2166
|
-
}
|
|
2167
|
-
return { ok: false, message: `Unknown inline agent "${name}". Run /skill:mode or diffpi_modes_list.` };
|
|
2168
|
-
}
|
|
2169
|
-
function createModeController(pi, options = {}) {
|
|
2170
|
-
let active;
|
|
2171
|
-
let baseline;
|
|
2172
|
-
const updateStatus = (ctx) => {
|
|
2173
|
-
const model = ctx.model ? ` · ${ctx.model.provider}/${ctx.model.id}` : "";
|
|
2174
|
-
const label = active?.label.toUpperCase() ?? "DEFAULT";
|
|
2175
|
-
const badge = `AGENT ${label}${model}`;
|
|
2176
|
-
ctx.ui.setStatus(MODE_STATUS_KEY, undefined);
|
|
2177
|
-
ctx.ui.setWidget?.(MODE_WIDGET_KEY, [badge], { placement: "belowEditor" });
|
|
2178
|
-
};
|
|
2179
|
-
const list = (ctx, listOptions = {}) => discoverAgentModes({
|
|
2180
|
-
cwd: ctx.cwd,
|
|
2181
|
-
agentDir: options.agentDir,
|
|
2182
|
-
bundledAgentsDir: options.bundledAgentsDir,
|
|
2183
|
-
homeDir: options.homeDir,
|
|
2184
|
-
projectTrusted: ctx.isProjectTrusted(),
|
|
2185
|
-
includeSkills: listOptions.includeSkills
|
|
2186
|
-
});
|
|
2187
|
-
return {
|
|
2188
|
-
list,
|
|
2189
|
-
async set(agent, ctx) {
|
|
2190
|
-
const catalog = await list(ctx, { includeSkills: agent.includes(":") });
|
|
2191
|
-
const result = resolveAgentMode(catalog.modes, agent);
|
|
2192
|
-
if (!result.ok || !result.active)
|
|
2193
|
-
return result;
|
|
2194
|
-
const previousActive = active;
|
|
2195
|
-
const previousBaseline = baseline;
|
|
2196
|
-
baseline ??= captureRuntime(pi, ctx);
|
|
2197
|
-
if (active && baseline)
|
|
2198
|
-
await restoreRuntime(pi, baseline, ctx);
|
|
2199
|
-
active = result.active;
|
|
2200
|
-
try {
|
|
2201
|
-
const runtimeMessage = await applyModeRuntime(pi, active, ctx);
|
|
2202
|
-
pi.appendEntry(MODE_STATE_ENTRY, { active, baseline });
|
|
2203
|
-
updateStatus(ctx);
|
|
2204
|
-
return { ...result, message: `${result.message} ${runtimeMessage}` };
|
|
2205
|
-
} catch (error) {
|
|
2206
|
-
await restoreRuntime(pi, baseline, ctx);
|
|
2207
|
-
active = undefined;
|
|
2208
|
-
baseline = undefined;
|
|
2209
|
-
if (previousActive && previousBaseline) {
|
|
2210
|
-
try {
|
|
2211
|
-
active = previousActive;
|
|
2212
|
-
baseline = previousBaseline;
|
|
2213
|
-
await applyModeRuntime(pi, active, ctx);
|
|
2214
|
-
} catch {
|
|
2215
|
-
active = undefined;
|
|
2216
|
-
baseline = undefined;
|
|
2217
|
-
}
|
|
2218
|
-
}
|
|
2219
|
-
if (!active)
|
|
2220
|
-
pi.appendEntry(MODE_STATE_ENTRY, { active: null });
|
|
2221
|
-
updateStatus(ctx);
|
|
2222
|
-
return { ok: false, message: error instanceof Error ? error.message : String(error) };
|
|
2223
|
-
}
|
|
2224
|
-
},
|
|
2225
|
-
async unset(ctx) {
|
|
2226
|
-
if (!active)
|
|
2227
|
-
return { ok: true, message: "Inline agent is already clear." };
|
|
2228
|
-
if (baseline)
|
|
2229
|
-
await restoreRuntime(pi, baseline, ctx);
|
|
2230
|
-
active = undefined;
|
|
2231
|
-
pi.appendEntry(MODE_STATE_ENTRY, { active: null });
|
|
2232
|
-
baseline = undefined;
|
|
2233
|
-
updateStatus(ctx);
|
|
2234
|
-
return { ok: true, message: "Inline agent cleared. The previous model, thinking, tools, and prompt resume." };
|
|
2235
|
-
},
|
|
2236
|
-
async restore(ctx) {
|
|
2237
|
-
const previousActive = active;
|
|
2238
|
-
const previousBaseline = baseline;
|
|
2239
|
-
const entry = [...ctx.sessionManager.getBranch()].reverse().find((candidate) => candidate.type === "custom" && candidate.customType === MODE_STATE_ENTRY);
|
|
2240
|
-
const restored = entry?.data?.active;
|
|
2241
|
-
const restoredBaseline = entry?.data?.baseline;
|
|
2242
|
-
if (isAgentModeSnapshot(restored)) {
|
|
2243
|
-
const catalog = await list(ctx, { includeSkills: restored.id.includes(":") });
|
|
2244
|
-
const current = catalog.modes.find((mode) => mode.id === restored.id);
|
|
2245
|
-
active = current ?? normalizeAgentModeSnapshot(restored);
|
|
2246
|
-
baseline = isModeBaseline(restoredBaseline) ? restoredBaseline : previousBaseline;
|
|
2247
|
-
try {
|
|
2248
|
-
await applyModeRuntime(pi, active, ctx);
|
|
2249
|
-
} catch (error) {
|
|
2250
|
-
const fallbackBaseline = previousBaseline ?? (isModeBaseline(restoredBaseline) ? restoredBaseline : undefined);
|
|
2251
|
-
if (fallbackBaseline)
|
|
2252
|
-
await restoreRuntime(pi, fallbackBaseline, ctx);
|
|
2253
|
-
active = undefined;
|
|
2254
|
-
baseline = undefined;
|
|
2255
|
-
throw error;
|
|
2256
|
-
}
|
|
2257
|
-
} else {
|
|
2258
|
-
if (previousActive && previousBaseline)
|
|
2259
|
-
pi.setActiveTools(previousBaseline.tools);
|
|
2260
|
-
active = undefined;
|
|
2261
|
-
baseline = undefined;
|
|
2262
|
-
}
|
|
2263
|
-
updateStatus(ctx);
|
|
2264
|
-
},
|
|
2265
|
-
refresh(ctx) {
|
|
2266
|
-
updateStatus(ctx);
|
|
2267
|
-
},
|
|
2268
|
-
apply(systemPrompt) {
|
|
2269
|
-
if (!active)
|
|
2270
|
-
return systemPrompt;
|
|
2271
|
-
if (active.promptStrategy === "replace")
|
|
2272
|
-
return active.systemPrompt;
|
|
2273
|
-
return `${systemPrompt}
|
|
2274
|
-
|
|
2275
|
-
## Active inline agent: ${active.label}
|
|
2276
|
-
|
|
2277
|
-
${active.systemPrompt}`;
|
|
2278
|
-
},
|
|
2279
|
-
getActive() {
|
|
2280
|
-
return active;
|
|
2281
|
-
},
|
|
2282
|
-
getStatus(ctx) {
|
|
2283
|
-
return {
|
|
2284
|
-
active: active?.id,
|
|
2285
|
-
model: ctx.model ? { provider: ctx.model.provider, id: ctx.model.id } : undefined,
|
|
2286
|
-
thinkingLevel: pi.getThinkingLevel(),
|
|
2287
|
-
activeTools: pi.getActiveTools(),
|
|
2288
|
-
capabilityError: active ? validateModeRuntime(pi, active, ctx) : undefined
|
|
2289
|
-
};
|
|
2290
|
-
}
|
|
2291
|
-
};
|
|
2292
|
-
}
|
|
2293
|
-
var MODE_STATE_ENTRY = "diffpi-mode-state";
|
|
2294
|
-
var MODE_STATUS_KEY = "diffpi-mode";
|
|
2295
|
-
var MODE_WIDGET_KEY = "diffpi-mode-badge";
|
|
2296
|
-
var MODE_CONTROL_TOOLS = [
|
|
2297
|
-
"ask_user_question",
|
|
2298
|
-
"diffpi_modes_list",
|
|
2299
|
-
"diffpi_modes_set",
|
|
2300
|
-
"diffpi_modes_unset",
|
|
2301
|
-
"diffpi_modes_status"
|
|
2302
|
-
];
|
|
2303
|
-
var BUNDLED_AGENTS_DIR = resolveBundledAgentsDir();
|
|
2304
|
-
var THINKING_LEVELS = new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
2305
|
-
async function applyModeRuntime(pi, mode, ctx) {
|
|
2306
|
-
let selectedModel;
|
|
2307
|
-
if (mode.modelPreferences.length > 0) {
|
|
2308
|
-
const scoped = ctx.scopedModels.length > 0 ? ctx.scopedModels.map((entry) => entry.model) : undefined;
|
|
2309
|
-
const availableModels = scoped ?? ctx.modelRegistry.getAvailable();
|
|
2310
|
-
for (const preference of mode.modelPreferences) {
|
|
2311
|
-
const model = findPreferredModel(availableModels, preference);
|
|
2312
|
-
if (model && await pi.setModel(model)) {
|
|
2313
|
-
selectedModel = `${model.provider}/${model.id}`;
|
|
2314
|
-
break;
|
|
2315
|
-
}
|
|
2316
|
-
}
|
|
2317
|
-
}
|
|
2318
|
-
if (mode.thinkingLevel)
|
|
2319
|
-
pi.setThinkingLevel(mode.thinkingLevel);
|
|
2320
|
-
if (mode.tools.length > 0) {
|
|
2321
|
-
const availableTools = new Set(pi.getAllTools().map((tool) => tool.name));
|
|
2322
|
-
const selectedTools = [...new Set([...mode.tools, ...MODE_CONTROL_TOOLS])].filter((tool) => availableTools.has(tool));
|
|
2323
|
-
if (selectedTools.length > 0)
|
|
2324
|
-
pi.setActiveTools(selectedTools);
|
|
2325
|
-
}
|
|
2326
|
-
const availableTools = new Set(pi.getAllTools().map((tool) => tool.name));
|
|
2327
|
-
const unavailableTools = mode.requiredTools.filter((tool) => !availableTools.has(tool));
|
|
2328
|
-
const activeTools = new Set(pi.getActiveTools());
|
|
2329
|
-
const missingTools = mode.requiredTools.filter((tool) => !activeTools.has(tool));
|
|
2330
|
-
const forbiddenTools = mode.forbiddenTools.filter((tool) => activeTools.has(tool));
|
|
2331
|
-
if (unavailableTools.length > 0 || missingTools.length > 0 || forbiddenTools.length > 0)
|
|
2332
|
-
throw new Error(`Profile preflight failed: missing required tools [${[...new Set([...unavailableTools, ...missingTools])].join(", ")}]${forbiddenTools.length > 0 ? `; forbidden tools active [${forbiddenTools.join(", ")}]` : ""}`);
|
|
2333
|
-
if (mode.requireModel && !selectedModel)
|
|
2334
|
-
throw new Error("Profile preflight failed: requested model was not selected.");
|
|
2335
|
-
if (mode.requireThinking && (!mode.thinkingLevel || pi.getThinkingLevel() !== mode.thinkingLevel))
|
|
2336
|
-
throw new Error(`Profile preflight failed: thinking level ${mode.thinkingLevel ?? "unset"} was not applied.`);
|
|
2337
|
-
const parts = [];
|
|
2338
|
-
if (mode.modelPreferences.length > 0) {
|
|
2339
|
-
parts.push(selectedModel ? `Model: ${selectedModel}.` : "No preferred model was available; kept the current model.");
|
|
2340
|
-
}
|
|
2341
|
-
if (mode.thinkingLevel)
|
|
2342
|
-
parts.push(`Thinking: ${mode.thinkingLevel}.`);
|
|
2343
|
-
if (mode.tools.length > 0)
|
|
2344
|
-
parts.push("Applied the profile tool set.");
|
|
2345
|
-
return parts.join(" ") || "The profile changes the prompt only.";
|
|
2346
|
-
}
|
|
2347
|
-
function validateModeRuntime(pi, mode, ctx) {
|
|
2348
|
-
const activeTools = new Set(pi.getActiveTools());
|
|
2349
|
-
const missingTools = mode.requiredTools.filter((tool) => !activeTools.has(tool));
|
|
2350
|
-
const forbiddenTools = mode.forbiddenTools.filter((tool) => activeTools.has(tool));
|
|
2351
|
-
if (missingTools.length > 0 || forbiddenTools.length > 0)
|
|
2352
|
-
return `Profile capability check failed: missing required tools [${missingTools.join(", ")}]${forbiddenTools.length > 0 ? `; forbidden tools active [${forbiddenTools.join(", ")}]` : ""}`;
|
|
2353
|
-
if (mode.requireModel && mode.modelPreferences.length > 0) {
|
|
2354
|
-
const actual = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : "unset";
|
|
2355
|
-
const available = ctx.scopedModels.length > 0 ? ctx.scopedModels.map((entry) => entry.model) : ctx.modelRegistry.getAvailable();
|
|
2356
|
-
const expected = mode.modelPreferences.map((preference) => findPreferredModel(available, preference)).find(Boolean);
|
|
2357
|
-
if (!expected || `${expected.provider}/${expected.id}` !== actual)
|
|
2358
|
-
return `Profile capability check failed: requested model was not active (actual ${actual}).`;
|
|
2359
|
-
}
|
|
2360
|
-
if (mode.requireThinking && (!mode.thinkingLevel || pi.getThinkingLevel() !== mode.thinkingLevel))
|
|
2361
|
-
return `Profile capability check failed: thinking level ${mode.thinkingLevel ?? "unset"} was not applied.`;
|
|
2362
|
-
return;
|
|
2363
|
-
}
|
|
2364
|
-
async function restoreRuntime(pi, state, ctx) {
|
|
2365
|
-
if (state.model) {
|
|
2366
|
-
const model = ctx.modelRegistry.find(state.model.provider, state.model.id);
|
|
2367
|
-
if (model)
|
|
2368
|
-
await pi.setModel(model);
|
|
2369
|
-
}
|
|
2370
|
-
pi.setThinkingLevel(state.thinkingLevel);
|
|
2371
|
-
pi.setActiveTools(state.tools);
|
|
2372
|
-
const restoredTools = pi.getActiveTools();
|
|
2373
|
-
if (state.tools.some((tool) => !restoredTools.includes(tool)))
|
|
2374
|
-
throw new Error("Failed to restore the previous active tool set.");
|
|
2375
|
-
}
|
|
2376
|
-
function captureRuntime(pi, ctx) {
|
|
2377
|
-
return {
|
|
2378
|
-
model: ctx.model ? { provider: ctx.model.provider, id: ctx.model.id } : undefined,
|
|
2379
|
-
thinkingLevel: pi.getThinkingLevel(),
|
|
2380
|
-
tools: pi.getActiveTools()
|
|
2381
|
-
};
|
|
2382
|
-
}
|
|
2383
|
-
async function loadSkillModes(skillsDir, source, modes, diagnostics) {
|
|
2384
|
-
const entries = await readDirectoryIfExists(skillsDir);
|
|
2385
|
-
for (const entry of entries.filter((item) => item.isDirectory()).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
2386
|
-
await loadAgentModes(join11(skillsDir, entry.name, "agents"), `${source} ${entry.name}`, modes, diagnostics, entry.name);
|
|
2387
|
-
}
|
|
2388
|
-
}
|
|
2389
|
-
async function loadAgentModes(directory, source, modes, diagnostics, skillName) {
|
|
2390
|
-
const entries = await readDirectoryIfExists(directory);
|
|
2391
|
-
for (const entry of entries.filter((item) => item.isFile() && item.name.endsWith(".md")).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
2392
|
-
const path = join11(directory, entry.name);
|
|
2393
|
-
try {
|
|
2394
|
-
const content = await readFile9(path, "utf8");
|
|
2395
|
-
const { frontmatter, body } = parseFrontmatter2(content.startsWith("\uFEFF") ? content.slice(1) : content);
|
|
2396
|
-
if (frontmatter.enabled === false || frontmatter.inline === false)
|
|
2397
|
-
continue;
|
|
2398
|
-
const name = getFrontmatterText(frontmatter.name) ?? basename4(path, extname(path));
|
|
2399
|
-
const systemPrompt = body.trim();
|
|
2400
|
-
if (!name || name.includes(":") || !systemPrompt) {
|
|
2401
|
-
diagnostics.push(`Skipped ${path}: agent name must not contain ":" and prompt body is required.`);
|
|
2402
|
-
continue;
|
|
2403
|
-
}
|
|
2404
|
-
const id = skillName ? `${skillName}:${name}` : name;
|
|
2405
|
-
modes.set(id, {
|
|
2406
|
-
id,
|
|
2407
|
-
label: getFrontmatterText(frontmatter.display_name) ?? name,
|
|
2408
|
-
description: getFrontmatterText(frontmatter.description) ?? `Inline agent from ${basename4(path)}`,
|
|
2409
|
-
systemPrompt,
|
|
2410
|
-
promptStrategy: frontmatter.prompt_mode === "append" ? "append" : "replace",
|
|
2411
|
-
modelPreferences: [
|
|
2412
|
-
...getFrontmatterList(frontmatter.model),
|
|
2413
|
-
...getFrontmatterList(frontmatter.model_fallbacks)
|
|
2414
|
-
],
|
|
2415
|
-
thinkingLevel: getThinkingLevel(frontmatter.thinking),
|
|
2416
|
-
requiredTools: getFrontmatterList(frontmatter.required_tools),
|
|
2417
|
-
forbiddenTools: getFrontmatterList(frontmatter.forbidden_tools),
|
|
2418
|
-
requireModel: frontmatter.required_model === true,
|
|
2419
|
-
requireThinking: frontmatter.required_thinking === true,
|
|
2420
|
-
tools: getFrontmatterList(frontmatter.tools),
|
|
2421
|
-
source,
|
|
2422
|
-
sourcePath: path
|
|
2423
|
-
});
|
|
2424
|
-
} catch (error) {
|
|
2425
|
-
diagnostics.push(`Skipped ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
2426
|
-
}
|
|
2427
|
-
}
|
|
2428
|
-
}
|
|
2429
|
-
function getFrontmatterText(value) {
|
|
2430
|
-
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
2431
|
-
}
|
|
2432
|
-
function getFrontmatterList(value) {
|
|
2433
|
-
const values = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : [];
|
|
2434
|
-
return values.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
|
|
2435
|
-
}
|
|
2436
|
-
function getThinkingLevel(value) {
|
|
2437
|
-
const level = getFrontmatterText(value);
|
|
2438
|
-
return level && THINKING_LEVELS.has(level) ? level : undefined;
|
|
2439
|
-
}
|
|
2440
|
-
function normalizeAgentModeSnapshot(value) {
|
|
2441
|
-
return {
|
|
2442
|
-
...value,
|
|
2443
|
-
requiredTools: Array.isArray(value.requiredTools) ? value.requiredTools : [],
|
|
2444
|
-
forbiddenTools: Array.isArray(value.forbiddenTools) ? value.forbiddenTools : [],
|
|
2445
|
-
requireModel: value.requireModel === true,
|
|
2446
|
-
requireThinking: value.requireThinking === true
|
|
2447
|
-
};
|
|
2448
|
-
}
|
|
2449
|
-
function isAgentModeSnapshot(value) {
|
|
2450
|
-
if (!value || typeof value !== "object")
|
|
2451
|
-
return false;
|
|
2452
|
-
const candidate = value;
|
|
2453
|
-
return typeof candidate.id === "string" && typeof candidate.label === "string" && typeof candidate.description === "string" && typeof candidate.systemPrompt === "string" && (candidate.promptStrategy === "append" || candidate.promptStrategy === "replace") && Array.isArray(candidate.modelPreferences) && (candidate.thinkingLevel === undefined || THINKING_LEVELS.has(candidate.thinkingLevel)) && (candidate.requiredTools === undefined || Array.isArray(candidate.requiredTools)) && (candidate.forbiddenTools === undefined || Array.isArray(candidate.forbiddenTools)) && (candidate.requireModel === undefined || typeof candidate.requireModel === "boolean") && (candidate.requireThinking === undefined || typeof candidate.requireThinking === "boolean") && Array.isArray(candidate.tools) && typeof candidate.source === "string" && typeof candidate.sourcePath === "string";
|
|
2454
|
-
}
|
|
2455
|
-
function isModeBaseline(value) {
|
|
2456
|
-
if (!value || typeof value !== "object")
|
|
2457
|
-
return false;
|
|
2458
|
-
const candidate = value;
|
|
2459
|
-
const model = candidate.model;
|
|
2460
|
-
return (model === undefined || typeof model.provider === "string" && typeof model.id === "string") && candidate.thinkingLevel !== undefined && THINKING_LEVELS.has(candidate.thinkingLevel) && Array.isArray(candidate.tools) && candidate.tools.every((tool) => typeof tool === "string");
|
|
2461
|
-
}
|
|
2462
2102
|
// src/pi.ts
|
|
2463
2103
|
import { mkdir as mkdir5, writeFile as writeFile6 } from "node:fs/promises";
|
|
2464
|
-
import { homedir as
|
|
2465
|
-
import { dirname as dirname6, join as
|
|
2104
|
+
import { homedir as homedir6 } from "node:os";
|
|
2105
|
+
import { dirname as dirname6, join as join11 } from "node:path";
|
|
2466
2106
|
var pi = {
|
|
2467
2107
|
executableCheck: findPiExecutable,
|
|
2468
2108
|
packageList: listPiPackages,
|
|
@@ -2475,7 +2115,7 @@ var pi = {
|
|
|
2475
2115
|
configEnsure: ensurePiConfig
|
|
2476
2116
|
};
|
|
2477
2117
|
async function ensurePiAgent(filename, content, agentDir = resolvePiAgentDir(), dryRun = false) {
|
|
2478
|
-
const path =
|
|
2118
|
+
const path = join11(agentDir, "agents", filename);
|
|
2479
2119
|
const currentText = await readTextIfExists(path);
|
|
2480
2120
|
const changed = currentText !== content;
|
|
2481
2121
|
if (changed && !dryRun) {
|
|
@@ -2484,10 +2124,10 @@ async function ensurePiAgent(filename, content, agentDir = resolvePiAgentDir(),
|
|
|
2484
2124
|
}
|
|
2485
2125
|
return { path, changed, existed: currentText !== undefined, planned: changed && dryRun };
|
|
2486
2126
|
}
|
|
2487
|
-
async function checkGlobalPiSkill(name, agentDir = resolvePiAgentDir(), sharedSkillsDir =
|
|
2488
|
-
const roots = [
|
|
2127
|
+
async function checkGlobalPiSkill(name, agentDir = resolvePiAgentDir(), sharedSkillsDir = join11(homedir6(), ".agents", "skills")) {
|
|
2128
|
+
const roots = [join11(agentDir, "skills"), sharedSkillsDir];
|
|
2489
2129
|
for (const root of roots) {
|
|
2490
|
-
if (await readTextIfExists(
|
|
2130
|
+
if (await readTextIfExists(join11(root, name, "SKILL.md")) !== undefined)
|
|
2491
2131
|
return true;
|
|
2492
2132
|
}
|
|
2493
2133
|
return false;
|
|
@@ -2536,8 +2176,8 @@ function hasPiPackage(listOutput, source) {
|
|
|
2536
2176
|
async function installPiPackage(executable, source) {
|
|
2537
2177
|
await runChecked(executable, ["install", source]);
|
|
2538
2178
|
}
|
|
2539
|
-
function resolvePiAgentDir(homeDir =
|
|
2540
|
-
return process.env.PI_CODING_AGENT_DIR ?? (process.env.XDG_CONFIG_HOME ?
|
|
2179
|
+
function resolvePiAgentDir(homeDir = homedir6()) {
|
|
2180
|
+
return process.env.PI_CODING_AGENT_DIR ?? (process.env.XDG_CONFIG_HOME ? join11(process.env.XDG_CONFIG_HOME, "pi") : join11(homeDir, ".pi", "agent"));
|
|
2541
2181
|
}
|
|
2542
2182
|
function parseJsonObject(content, path) {
|
|
2543
2183
|
if (!content?.trim())
|
|
@@ -2550,27 +2190,27 @@ function parseJsonObject(content, path) {
|
|
|
2550
2190
|
throw new Error(`Expected valid JSON object in ${path}.`);
|
|
2551
2191
|
}
|
|
2552
2192
|
// src/plan/verify.ts
|
|
2553
|
-
import { readFile as
|
|
2554
|
-
import { basename as
|
|
2193
|
+
import { readFile as readFile9, readdir as readdir2, stat } from "node:fs/promises";
|
|
2194
|
+
import { basename as basename4, dirname as dirname7, join as join12, resolve as resolve4 } from "node:path";
|
|
2555
2195
|
async function verifyLivePlan(requested, cwd = process.cwd()) {
|
|
2556
2196
|
const path = resolve4(cwd, requested);
|
|
2557
2197
|
let planPath = path;
|
|
2558
2198
|
try {
|
|
2559
2199
|
if ((await stat(path)).isDirectory())
|
|
2560
|
-
planPath =
|
|
2200
|
+
planPath = join12(path, "PLAN.md");
|
|
2561
2201
|
} catch {}
|
|
2562
2202
|
const issues = [];
|
|
2563
2203
|
const briefPaths = [];
|
|
2564
2204
|
const planDir = dirname7(planPath);
|
|
2565
|
-
if (
|
|
2205
|
+
if (basename4(planPath) !== "PLAN.md") {
|
|
2566
2206
|
addIssue(issues, planPath, 0, "path", "Select PLAN.md or its directory.");
|
|
2567
2207
|
return { planPath, briefPaths, ok: false, issues };
|
|
2568
2208
|
}
|
|
2569
|
-
if (!/^\d{6}(?:-[a-z0-9]+)+$/.test(
|
|
2209
|
+
if (!/^\d{6}(?:-[a-z0-9]+)+$/.test(basename4(planDir)) || basename4(dirname7(planDir)) !== "plan" || basename4(dirname7(dirname7(planDir))) !== ".diffpi")
|
|
2570
2210
|
addIssue(issues, planPath, 0, "layout", "Place PLAN.md under .diffpi/plan/<YYMMDD[-ticket]-short-slug>/.");
|
|
2571
2211
|
let source;
|
|
2572
2212
|
try {
|
|
2573
|
-
source = await
|
|
2213
|
+
source = await readFile9(planPath, "utf8");
|
|
2574
2214
|
} catch {
|
|
2575
2215
|
addIssue(issues, planPath, 0, "missing-plan", "PLAN.md is not readable.");
|
|
2576
2216
|
return { planPath, briefPaths, ok: false, issues };
|
|
@@ -2584,7 +2224,7 @@ async function verifyLivePlan(requested, cwd = process.cwd()) {
|
|
|
2584
2224
|
if (!planLines[line]?.startsWith(`### Phase ${index + 1}: `))
|
|
2585
2225
|
addIssue(issues, planPath, line + 1, "phase-order", "Number phase headings from 1 without gaps.");
|
|
2586
2226
|
}
|
|
2587
|
-
const implementation =
|
|
2227
|
+
const implementation = join12(planDir, "implementation");
|
|
2588
2228
|
let rootEntries = [];
|
|
2589
2229
|
let briefEntries = [];
|
|
2590
2230
|
try {
|
|
@@ -2593,18 +2233,18 @@ async function verifyLivePlan(requested, cwd = process.cwd()) {
|
|
|
2593
2233
|
} catch {}
|
|
2594
2234
|
for (const entry of rootEntries) {
|
|
2595
2235
|
if (entry !== "PLAN.md" && entry !== "implementation")
|
|
2596
|
-
addIssue(issues,
|
|
2236
|
+
addIssue(issues, join12(planDir, entry), 0, "layout", "Only PLAN.md and implementation/ belong in the plan directory.");
|
|
2597
2237
|
}
|
|
2598
2238
|
for (const entry of briefEntries) {
|
|
2599
2239
|
const ordinal = /^phase-(\d+)\.md$/.exec(entry)?.[1];
|
|
2600
2240
|
if (!ordinal || !Number(ordinal) || Number(ordinal) > phases.length || entry !== `phase-${Number(ordinal)}.md`)
|
|
2601
|
-
addIssue(issues,
|
|
2241
|
+
addIssue(issues, join12(implementation, entry), 0, "extra-brief", "Only matching numbered phase briefs belong in implementation/.");
|
|
2602
2242
|
}
|
|
2603
2243
|
for (let index = 0;index < phases.length; index++) {
|
|
2604
|
-
const brief =
|
|
2244
|
+
const brief = join12(implementation, `phase-${index + 1}.md`);
|
|
2605
2245
|
briefPaths.push(brief);
|
|
2606
2246
|
try {
|
|
2607
|
-
const lines = visibleLines(await
|
|
2247
|
+
const lines = visibleLines(await readFile9(brief, "utf8"));
|
|
2608
2248
|
if (!/^# Phase \d+:\s*\S/.test(lines[0] ?? "") || !lines[0]?.startsWith(`# Phase ${index + 1}: `))
|
|
2609
2249
|
addIssue(issues, brief, 1, "phase-title", `Start with # Phase ${index + 1}: <title>.`);
|
|
2610
2250
|
checkHeadings(lines, brief, ["Objective", "Files Affected", "Tasks", "Implementation Constraints"], issues);
|
|
@@ -2636,10 +2276,10 @@ function checkHeadings(lines, file, names, issues) {
|
|
|
2636
2276
|
addIssue(issues, file, found[0]?.line ?? 0, "headings", `Expected headings, in order: ${expected.join(", ")}.`);
|
|
2637
2277
|
}
|
|
2638
2278
|
// src/setup.ts
|
|
2639
|
-
import { parseFrontmatter as
|
|
2640
|
-
import { readdir as readdir3, readFile as
|
|
2641
|
-
import { homedir as
|
|
2642
|
-
import { basename as
|
|
2279
|
+
import { parseFrontmatter as parseFrontmatter2 } from "@earendil-works/pi-coding-agent";
|
|
2280
|
+
import { readdir as readdir3, readFile as readFile10 } from "node:fs/promises";
|
|
2281
|
+
import { homedir as homedir7 } from "node:os";
|
|
2282
|
+
import { basename as basename5, join as join13 } from "node:path";
|
|
2643
2283
|
var MISE_DEPENDENCIES = [
|
|
2644
2284
|
{ name: "node", tool: "node", spec: "node@22", minimumVersion: "22.19.0" },
|
|
2645
2285
|
{ name: "zellij", tool: "zellij", spec: "zellij@latest", minimumVersion: undefined },
|
|
@@ -2672,14 +2312,14 @@ var PI_SKILL_SOURCES = [
|
|
|
2672
2312
|
{ repository: "cloudvoyant/codevoyant", skills: ["git"] }
|
|
2673
2313
|
];
|
|
2674
2314
|
var MCP_ADAPTER_PACKAGE = "npm:pi-mcp-adapter";
|
|
2675
|
-
var
|
|
2315
|
+
var BUNDLED_AGENTS_DIR = resolveBundledAgentsDir();
|
|
2676
2316
|
var FORGE_DEPENDENCIES = {
|
|
2677
2317
|
github: { name: "gh", tool: "gh", spec: "gh@latest", minimumVersion: undefined },
|
|
2678
2318
|
gitlab: { name: "glab", tool: "glab", spec: "glab@latest", minimumVersion: undefined }
|
|
2679
2319
|
};
|
|
2680
2320
|
async function ensureMise(options = {}) {
|
|
2681
|
-
const homeDir = options.homeDir ??
|
|
2682
|
-
const current = await mise.executableCheck() ?? await mise.executableCheck(
|
|
2321
|
+
const homeDir = options.homeDir ?? homedir7();
|
|
2322
|
+
const current = await mise.executableCheck() ?? await mise.executableCheck(join13(homeDir, ".local", "bin", "mise"));
|
|
2683
2323
|
if (current)
|
|
2684
2324
|
return { executable: current, action: createSetupAction("mise", "ready", current) };
|
|
2685
2325
|
reportProgress(options, "Installing mise");
|
|
@@ -2728,9 +2368,9 @@ async function ensureMiseDeps(miseExecutable, options = {}) {
|
|
|
2728
2368
|
async function ensurePiPlugins(options = {}) {
|
|
2729
2369
|
const actions = await ensurePiPackages(PI_PACKAGES, options);
|
|
2730
2370
|
const agentDir = options.agentDir ?? pi.agentDir(options.homeDir);
|
|
2731
|
-
const webSearch = await pi.configEnsure(
|
|
2371
|
+
const webSearch = await pi.configEnsure(join13(agentDir, "web-search.json"), (config) => ({ ...config, workflow: "auto-summary" }), options.dryRun);
|
|
2732
2372
|
actions.push(getConfigSetupAction("web search settings", webSearch));
|
|
2733
|
-
const lsp = await pi.configEnsure(
|
|
2373
|
+
const lsp = await pi.configEnsure(join13(agentDir, "pi-lsp.json"), (config) => ({
|
|
2734
2374
|
...config,
|
|
2735
2375
|
progressive: { ...getRecord(config.progressive), enabled: true, inject: "none" }
|
|
2736
2376
|
}), options.dryRun);
|
|
@@ -2739,13 +2379,13 @@ async function ensurePiPlugins(options = {}) {
|
|
|
2739
2379
|
}
|
|
2740
2380
|
async function ensurePiAgents(options = {}) {
|
|
2741
2381
|
const agentDir = options.agentDir ?? pi.agentDir(options.homeDir);
|
|
2742
|
-
const bundledAgentsDir = options.bundledAgentsDir ??
|
|
2382
|
+
const bundledAgentsDir = options.bundledAgentsDir ?? BUNDLED_AGENTS_DIR;
|
|
2743
2383
|
const userConfig = await loadDiffpiConfig({ homeDir: options.homeDir });
|
|
2744
2384
|
const entries = (await readdir3(bundledAgentsDir, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.startsWith("diffpi-") && entry.name.endsWith(".md")).sort((left, right) => left.name.localeCompare(right.name));
|
|
2745
2385
|
const actions = [];
|
|
2746
2386
|
for (const entry of entries) {
|
|
2747
|
-
const id =
|
|
2748
|
-
const source = await
|
|
2387
|
+
const id = basename5(entry.name, ".md").replace(/^diffpi-/, "");
|
|
2388
|
+
const source = await readFile10(join13(bundledAgentsDir, entry.name), "utf8");
|
|
2749
2389
|
const content = materializeAgentModels(source, id, userConfig.config, options.availableModels);
|
|
2750
2390
|
const result = await pi.agentEnsure(entry.name, content, agentDir, options.dryRun);
|
|
2751
2391
|
actions.push(getConfigSetupAction(`pi agent ${id}`, result));
|
|
@@ -2754,7 +2394,7 @@ async function ensurePiAgents(options = {}) {
|
|
|
2754
2394
|
}
|
|
2755
2395
|
async function ensurePiSkills(miseExecutable, options = {}) {
|
|
2756
2396
|
const agentDir = options.agentDir ?? pi.agentDir(options.homeDir);
|
|
2757
|
-
const sharedSkillsDir =
|
|
2397
|
+
const sharedSkillsDir = join13(options.homeDir ?? homedir7(), ".agents", "skills");
|
|
2758
2398
|
const actions = [];
|
|
2759
2399
|
for (const source of PI_SKILL_SOURCES) {
|
|
2760
2400
|
const missing = [];
|
|
@@ -2870,7 +2510,7 @@ async function gitlabMcpHost(projectDir) {
|
|
|
2870
2510
|
}
|
|
2871
2511
|
}
|
|
2872
2512
|
function materializeAgentModels(content, agentId, config, availableModels) {
|
|
2873
|
-
const { frontmatter } =
|
|
2513
|
+
const { frontmatter } = parseFrontmatter2(content.startsWith("\uFEFF") ? content.slice(1) : content);
|
|
2874
2514
|
const profilePreferences = [...getTextList(frontmatter.model), ...getTextList(frontmatter.model_fallbacks)];
|
|
2875
2515
|
const preferences = resolveAgentModelPreferences(agentId, profilePreferences, config);
|
|
2876
2516
|
let selectedIndex = availableModels === undefined && preferences.length > 0 ? 0 : -1;
|
|
@@ -2950,7 +2590,7 @@ function reportProgress(options, message) {
|
|
|
2950
2590
|
options.onProgress?.(message);
|
|
2951
2591
|
}
|
|
2952
2592
|
async function packageVersion2() {
|
|
2953
|
-
const source = await
|
|
2593
|
+
const source = await readFile10(join13(resolveBundledAgentsDir(), "..", "package.json"), "utf8");
|
|
2954
2594
|
let value;
|
|
2955
2595
|
try {
|
|
2956
2596
|
value = JSON.parse(source);
|
|
@@ -2965,13 +2605,13 @@ function getRecord(value) {
|
|
|
2965
2605
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2966
2606
|
}
|
|
2967
2607
|
// src/templates.ts
|
|
2968
|
-
import { readFile as
|
|
2969
|
-
import { homedir as
|
|
2970
|
-
import { join as
|
|
2608
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
2609
|
+
import { homedir as homedir8 } from "node:os";
|
|
2610
|
+
import { join as join14, normalize } from "node:path";
|
|
2971
2611
|
async function loadTemplate(name, options = {}) {
|
|
2972
2612
|
const relative = templateRelativePath(name);
|
|
2973
|
-
const userPath =
|
|
2974
|
-
const bundledPath =
|
|
2613
|
+
const userPath = join14(options.homeDir ?? homedir8(), ".difflab", "diffpi", "templates", relative);
|
|
2614
|
+
const bundledPath = join14(options.bundledDir ?? resolveBundledTemplatesDir(), relative);
|
|
2975
2615
|
const user = await readOptionalFile(userPath);
|
|
2976
2616
|
if (user !== undefined)
|
|
2977
2617
|
return { name, path: userPath, source: "user", content: user };
|
|
@@ -2992,7 +2632,7 @@ function templateRelativePath(name) {
|
|
|
2992
2632
|
}
|
|
2993
2633
|
async function readOptionalFile(path) {
|
|
2994
2634
|
try {
|
|
2995
|
-
return await
|
|
2635
|
+
return await readFile11(path, "utf8");
|
|
2996
2636
|
} catch (error) {
|
|
2997
2637
|
if (error.code === "ENOENT")
|
|
2998
2638
|
return;
|
|
@@ -3015,7 +2655,6 @@ export {
|
|
|
3015
2655
|
createForge,
|
|
3016
2656
|
createForgeBackend,
|
|
3017
2657
|
createLocalReviewBackend,
|
|
3018
|
-
createModeController,
|
|
3019
2658
|
createRemoteReviewBackend,
|
|
3020
2659
|
createVcsBackend,
|
|
3021
2660
|
dedupeFindings,
|
|
@@ -3025,7 +2664,6 @@ export {
|
|
|
3025
2664
|
detectVcs,
|
|
3026
2665
|
diffpiConfigPaths,
|
|
3027
2666
|
diffpiLaunchName,
|
|
3028
|
-
discoverAgentModes,
|
|
3029
2667
|
ensureMcpAdapters,
|
|
3030
2668
|
ensureMise,
|
|
3031
2669
|
ensureMiseDeps,
|
|
@@ -3062,7 +2700,6 @@ export {
|
|
|
3062
2700
|
renderReviewDoc,
|
|
3063
2701
|
renderTemplate,
|
|
3064
2702
|
renderThreadArtifact,
|
|
3065
|
-
resolveAgentMode,
|
|
3066
2703
|
resolveAgentModelPreferences,
|
|
3067
2704
|
resolvePrSession,
|
|
3068
2705
|
resolveReviewSession,
|
package/dist/tools/ci.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ToolDefinition } from '@earendil-works/pi-coding-agent';
|
|
2
2
|
export declare const watchCiTool: ToolDefinition<import("typebox").TSchema, {
|
|
3
|
-
status: "
|
|
3
|
+
status: "skipped" | "passed" | "failed";
|
|
4
4
|
detail: string;
|
|
5
5
|
}, any> & ToolDefinition<any, any, any>;
|
|
6
6
|
//# sourceMappingURL=ci.d.ts.map
|