pi-extensible-workflows 2.0.0 → 3.1.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 +18 -11
- package/dist/src/agent-execution.d.ts +4 -94
- package/dist/src/agent-execution.js +34 -208
- package/dist/src/budget.d.ts +38 -0
- package/dist/src/budget.js +160 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +60 -8
- package/dist/src/doctor-cleanup.d.ts +41 -0
- package/dist/src/doctor-cleanup.js +597 -0
- package/dist/src/doctor.d.ts +7 -2
- package/dist/src/doctor.js +127 -22
- package/dist/src/execution.d.ts +17 -0
- package/dist/src/execution.js +630 -0
- package/dist/src/host.d.ts +101 -0
- package/dist/src/host.js +3084 -0
- package/dist/src/index.d.ts +13 -634
- package/dist/src/index.js +10 -4432
- package/dist/src/persistence.d.ts +9 -19
- package/dist/src/persistence.js +175 -61
- package/dist/src/registry.d.ts +43 -0
- package/dist/src/registry.js +279 -0
- package/dist/src/session-inspector.js +5 -3
- package/dist/src/types.d.ts +692 -0
- package/dist/src/types.js +27 -0
- package/dist/src/utils.d.ts +32 -0
- package/dist/src/utils.js +168 -0
- package/dist/src/validation.d.ts +28 -0
- package/dist/src/validation.js +832 -0
- package/package.json +3 -2
- package/skills/pi-extensible-workflows/SKILL.md +69 -34
- package/src/agent-execution.ts +37 -189
- package/src/budget.ts +75 -0
- package/src/cli.ts +47 -7
- package/src/doctor-cleanup.ts +337 -0
- package/src/doctor.ts +117 -24
- package/src/execution.ts +540 -0
- package/src/host.ts +2598 -0
- package/src/index.ts +14 -3856
- package/src/persistence.ts +122 -37
- package/src/registry.ts +240 -0
- package/src/session-inspector.ts +5 -3
- package/src/types.ts +158 -0
- package/src/utils.ts +142 -0
- package/src/validation.ts +688 -0
package/dist/src/doctor.js
CHANGED
|
@@ -2,7 +2,9 @@ import { readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
|
2
2
|
import { basename, dirname, extname, join, resolve } from "node:path";
|
|
3
3
|
import { InMemoryCredentialStore } from "@earendil-works/pi-ai";
|
|
4
4
|
import { ModelRuntime, createAgentSessionFromServices, createAgentSessionServices, getAgentDir, hasTrustRequiringProjectResources, SessionManager, SettingsManager, } from "@earendil-works/pi-coding-agent";
|
|
5
|
-
import { DEFAULT_SETTINGS, loadSettings, resolveAgentResourcePolicy, resolveModelReference, parseRoleMarkdown, registeredWorkflowFunctions, workflowRoleDirectories, workflowProjectSettingsPath, workflowSettingsPath, } from "./index.js";
|
|
5
|
+
import { DEFAULT_SETTINGS, loadSettings, resolveAgentResourcePolicy, resolveWorkflowSettings, resolveModelReference, parseThinking, parseRoleMarkdown, registeredWorkflowFunctions, registeredWorkflowRoleDirectoryRegistrations, workflowRoleDirectories, workflowProjectSettingsPath, workflowSettingsPath, } from "./index.js";
|
|
6
|
+
import { loadingRegistry } from "./registry.js";
|
|
7
|
+
import { disabledResources, unmatchedResourcePatterns } from "./utils.js";
|
|
6
8
|
const THINKING_HINT = "Use off, minimal, low, medium, high, xhigh, or max.";
|
|
7
9
|
function canonical(path) {
|
|
8
10
|
const absolute = resolve(path);
|
|
@@ -13,6 +15,11 @@ function canonical(path) {
|
|
|
13
15
|
return absolute;
|
|
14
16
|
}
|
|
15
17
|
}
|
|
18
|
+
function isDynamicModelAlias(value, aliases) {
|
|
19
|
+
const match = /^([^/\s:]+)(?::([^\s]+))?$/.exec(value);
|
|
20
|
+
const name = match?.[1];
|
|
21
|
+
return Boolean(name && (match[2] === undefined || parseThinking(match[2]) !== undefined) && aliases.has(name));
|
|
22
|
+
}
|
|
16
23
|
async function readCredentials(agentDir) {
|
|
17
24
|
const credentials = new InMemoryCredentialStore();
|
|
18
25
|
try {
|
|
@@ -112,6 +119,30 @@ function roleFilesFrom(dirs) {
|
|
|
112
119
|
const paths = dirs.flatMap((dir) => roleFiles(dir));
|
|
113
120
|
return [...new Map(paths.map((path) => [basename(path, ".md"), path])).values()].sort();
|
|
114
121
|
}
|
|
122
|
+
function extensionLabel(extension) { return `Extension "${extension.headline}" (${extension.version})`; }
|
|
123
|
+
function scanExtensionRoleFiles(registrations) {
|
|
124
|
+
const files = [];
|
|
125
|
+
const empty = [];
|
|
126
|
+
const errors = [];
|
|
127
|
+
for (const registration of registrations) {
|
|
128
|
+
try {
|
|
129
|
+
const entries = readdirSync(registration.path, { withFileTypes: true });
|
|
130
|
+
const roleFiles = entries.filter((entry) => entry.isFile() && extname(entry.name) === ".md");
|
|
131
|
+
if (!roleFiles.length)
|
|
132
|
+
empty.push(registration);
|
|
133
|
+
for (const entry of roleFiles)
|
|
134
|
+
files.push({ name: basename(entry.name, ".md"), path: join(registration.path, entry.name), directory: registration.path, extension: registration.extension });
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
errors.push({ registration, error });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
files.sort((left, right) => left.name.localeCompare(right.name) || left.path.localeCompare(right.path));
|
|
141
|
+
return { files, empty, errors };
|
|
142
|
+
}
|
|
143
|
+
function roleProvenance(source) {
|
|
144
|
+
return source ? `${extensionLabel(source.extension)} role directory "${source.directory}"` : "Role";
|
|
145
|
+
}
|
|
115
146
|
function diagnostic(severity, code, message, source, hint) {
|
|
116
147
|
return { severity, code, message, ...(source ? { source } : {}), ...(hint ? { hint } : {}) };
|
|
117
148
|
}
|
|
@@ -119,7 +150,9 @@ function emptyResourcePolicy(globalSettingsPath, cwd, projectTrusted) {
|
|
|
119
150
|
const empty = { skills: [], extensions: [] };
|
|
120
151
|
return { globalSettingsPath, projectSettingsPath: workflowProjectSettingsPath(cwd), projectTrusted, global: empty, project: empty, effective: empty, unmatchedSkills: [], unmatchedExtensions: [] };
|
|
121
152
|
}
|
|
122
|
-
function validateModel(value, known, available, source, diagnostics, aliases, settingsPath) {
|
|
153
|
+
function validateModel(value, known, available, source, diagnostics, aliases, dynamicAliases, settingsPath) {
|
|
154
|
+
if (isDynamicModelAlias(value, dynamicAliases))
|
|
155
|
+
return;
|
|
123
156
|
try {
|
|
124
157
|
const parsed = resolveModelReference(value, aliases, known, settingsPath);
|
|
125
158
|
const name = `${parsed.provider}/${parsed.model}`;
|
|
@@ -130,13 +163,14 @@ function validateModel(value, known, available, source, diagnostics, aliases, se
|
|
|
130
163
|
diagnostics.push(diagnostic("error", "MODEL_INVALID", error.message, source, error.message.includes("thinking") ? THINKING_HINT : "Use provider/model or provider/model:thinking."));
|
|
131
164
|
}
|
|
132
165
|
}
|
|
133
|
-
function inspectRole(path, activeTools, knownModels, availableModels, diagnostics, aliases, settingsPath) {
|
|
166
|
+
function inspectRole(path, activeTools, knownModels, availableModels, diagnostics, aliases, dynamicAliases, settingsPath, source) {
|
|
134
167
|
let definition;
|
|
135
168
|
try {
|
|
136
169
|
definition = parseRoleMarkdown(readFileSync(path, "utf8"), true, path);
|
|
137
170
|
}
|
|
138
171
|
catch (error) {
|
|
139
|
-
|
|
172
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
173
|
+
diagnostics.push(diagnostic("error", "ROLE_FRONTMATTER", source ? `${roleProvenance(source)} contains invalid role at "${path}": ${message}` : message, path, "Fix the role YAML frontmatter."));
|
|
140
174
|
return undefined;
|
|
141
175
|
}
|
|
142
176
|
const body = definition.prompt ?? "";
|
|
@@ -147,20 +181,18 @@ function inspectRole(path, activeTools, knownModels, availableModels, diagnostic
|
|
|
147
181
|
if (/{{\s*[^{}]+\s*}}/.test(body))
|
|
148
182
|
diagnostics.push(diagnostic("warning", "ROLE_PLACEHOLDER", "Role body contains an unsupported placeholder-looking token", path));
|
|
149
183
|
if (definition.model)
|
|
150
|
-
validateModel(definition.model, knownModels, availableModels, path, diagnostics, aliases, settingsPath);
|
|
184
|
+
validateModel(definition.model, knownModels, availableModels, path, diagnostics, aliases, dynamicAliases, settingsPath);
|
|
151
185
|
for (const tool of definition.tools ?? [])
|
|
152
186
|
if (!activeTools.has(tool))
|
|
153
187
|
diagnostics.push(diagnostic("error", "ROLE_TOOL_INACTIVE", `Tool is unknown or inactive: ${tool}`, path, "Use a tool listed under Active tools or enable its Pi extension."));
|
|
154
188
|
return definition;
|
|
155
189
|
}
|
|
156
190
|
function matchResourcePolicy(policy, pi) {
|
|
157
|
-
const extensions = new Set((pi.extensions ?? []).map(canonical));
|
|
158
|
-
const skills = new Set(pi.skills ?? []);
|
|
159
|
-
return { ...policy,
|
|
160
|
-
}
|
|
161
|
-
function resourcePolicySource(policy, kind, selector) {
|
|
162
|
-
return policy.project[kind].includes(selector) && !policy.global[kind].includes(selector) ? policy.projectSettingsPath : policy.globalSettingsPath;
|
|
191
|
+
const extensions = [...new Set((pi.extensions ?? []).map(canonical))];
|
|
192
|
+
const skills = [...new Set(pi.skills ?? [])];
|
|
193
|
+
return { ...policy, excludedSkills: disabledResources(policy.effective.skills, skills), excludedExtensions: disabledResources(policy.effective.extensions, extensions), unmatchedSkills: unmatchedResourcePatterns(policy.effective.skills, skills), unmatchedExtensions: unmatchedResourcePatterns(policy.effective.extensions, extensions) };
|
|
163
194
|
}
|
|
195
|
+
function resourcePolicySource(settingsSource) { return settingsSource; }
|
|
164
196
|
export async function doctor(options = {}) {
|
|
165
197
|
const cwd = canonical(options.cwd ?? process.cwd());
|
|
166
198
|
const agentDir = canonical(options.agentDir ?? getAgentDir());
|
|
@@ -173,6 +205,8 @@ export async function doctor(options = {}) {
|
|
|
173
205
|
catch (error) {
|
|
174
206
|
diagnostics.push(diagnostic("error", "SETTINGS_INVALID", error.message, settingsPath, "Fix or remove the invalid workflow settings file."));
|
|
175
207
|
}
|
|
208
|
+
let settingsSources = { concurrency: settingsPath, modelAliases: settingsPath, disabledAgentResources: settingsPath };
|
|
209
|
+
const projectSettingsPath = workflowProjectSettingsPath(cwd);
|
|
176
210
|
let pi;
|
|
177
211
|
try {
|
|
178
212
|
pi = await (options.discoverPi ?? discoverPi)(cwd, agentDir);
|
|
@@ -187,41 +221,98 @@ export async function doctor(options = {}) {
|
|
|
187
221
|
diagnostics.push(diagnostic("warning", "PROJECT_UNTRUSTED", "Pi project resources are inactive because the project is not trusted", cwd, "Open this project in Pi, choose Trust, then rerun doctor."));
|
|
188
222
|
for (const error of pi.extensionErrors)
|
|
189
223
|
diagnostics.push(diagnostic("error", "EXTENSION_LOAD", error.message, error.path, "Fix or disable the failing Pi extension."));
|
|
224
|
+
try {
|
|
225
|
+
const resolved = resolveWorkflowSettings(cwd, pi.trust.trusted, settingsPath);
|
|
226
|
+
settings = resolved.effective;
|
|
227
|
+
settingsSources = resolved.sources;
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
231
|
+
const source = message.includes(projectSettingsPath) ? projectSettingsPath : settingsPath;
|
|
232
|
+
if (!diagnostics.some(({ code, source: itemSource }) => code === "SETTINGS_INVALID" && itemSource === source))
|
|
233
|
+
diagnostics.push(diagnostic("error", "SETTINGS_INVALID", message, source, "Fix or remove the invalid workflow settings file."));
|
|
234
|
+
}
|
|
190
235
|
let resourcePolicy;
|
|
191
236
|
try {
|
|
192
237
|
resourcePolicy = matchResourcePolicy(resolveAgentResourcePolicy(cwd, pi.trust.trusted, settingsPath), pi);
|
|
193
238
|
}
|
|
194
239
|
catch (error) {
|
|
195
240
|
const message = error instanceof Error ? error.message : String(error);
|
|
196
|
-
|
|
197
|
-
|
|
241
|
+
const source = message.includes(projectSettingsPath) ? projectSettingsPath : settingsPath;
|
|
242
|
+
if (!diagnostics.some(({ code, source: itemSource }) => code === "SETTINGS_INVALID" && itemSource === source))
|
|
243
|
+
diagnostics.push(diagnostic("error", "SETTINGS_INVALID", message, source, "Fix or remove the invalid workflow settings file."));
|
|
198
244
|
resourcePolicy = emptyResourcePolicy(settingsPath, cwd, pi.trust.trusted);
|
|
199
245
|
}
|
|
200
246
|
for (const skill of resourcePolicy.unmatchedSkills)
|
|
201
|
-
diagnostics.push(diagnostic("warning", "AGENT_RESOURCE_UNMATCHED", `Disabled skill selector currently matches no discovered skill: ${skill}`, `${resourcePolicySource(
|
|
247
|
+
diagnostics.push(diagnostic("warning", "AGENT_RESOURCE_UNMATCHED", `Disabled skill selector currently matches no discovered skill: ${skill}`, `${resourcePolicySource(settingsSources.disabledAgentResources)}.disabledAgentResources.skills`));
|
|
202
248
|
for (const extension of resourcePolicy.unmatchedExtensions)
|
|
203
|
-
diagnostics.push(diagnostic("warning", "AGENT_RESOURCE_UNMATCHED", `Disabled extension selector currently matches no discovered extension source: ${extension}`, `${resourcePolicySource(
|
|
249
|
+
diagnostics.push(diagnostic("warning", "AGENT_RESOURCE_UNMATCHED", `Disabled extension selector currently matches no discovered extension source: ${extension}`, `${resourcePolicySource(settingsSources.disabledAgentResources)}.disabledAgentResources.extensions`));
|
|
204
250
|
const activeTools = new Set(pi.activeTools);
|
|
205
251
|
const knownModels = new Set(pi.knownModels);
|
|
206
252
|
const availableModels = new Set(pi.availableModels);
|
|
207
253
|
const aliases = settings.modelAliases ?? {};
|
|
254
|
+
const registry = options.registry ?? loadingRegistry();
|
|
255
|
+
const registeredModelAliases = registry.modelAliases();
|
|
256
|
+
const dynamicAliases = new Set(registeredModelAliases.map(({ name }) => name).filter((name) => !Object.prototype.hasOwnProperty.call(aliases, name)));
|
|
257
|
+
const modelAliases = [
|
|
258
|
+
...Object.keys(aliases).map((name) => ({ name, kind: "static", provenance: settingsSources.modelAliases })),
|
|
259
|
+
...registeredModelAliases.map(({ name, version, headline, extensionDescription }) => ({ name, kind: "dynamic", provenance: `extension: ${headline}`, version, headline, extensionDescription })),
|
|
260
|
+
].sort((left, right) => left.name.localeCompare(right.name) || left.kind.localeCompare(right.kind));
|
|
208
261
|
const roles = [];
|
|
209
262
|
const definitions = new Map();
|
|
263
|
+
const extensionScan = scanExtensionRoleFiles(registeredWorkflowRoleDirectoryRegistrations());
|
|
264
|
+
for (const { registration, error } of extensionScan.errors) {
|
|
265
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
266
|
+
diagnostics.push(diagnostic("error", "ROLE_DIRECTORY", `${extensionLabel(registration.extension)} role directory "${registration.path}" could not be scanned: ${message}`, registration.path, "Fix or remove the registered role directory."));
|
|
267
|
+
}
|
|
268
|
+
for (const registration of extensionScan.empty)
|
|
269
|
+
diagnostics.push(diagnostic("warning", "ROLE_DIRECTORY_EMPTY", `${extensionLabel(registration.extension)} role directory "${registration.path}" contains no .md role files`, registration.path, "Add packaged role files or remove the directory registration."));
|
|
270
|
+
const extensionFilesByName = new Map();
|
|
271
|
+
for (const file of extensionScan.files)
|
|
272
|
+
extensionFilesByName.set(file.name, [...(extensionFilesByName.get(file.name) ?? []), file]);
|
|
273
|
+
const duplicateExtensionNames = new Set();
|
|
274
|
+
for (const [name, matches] of extensionFilesByName)
|
|
275
|
+
if (matches.length > 1) {
|
|
276
|
+
duplicateExtensionNames.add(name);
|
|
277
|
+
diagnostics.push(diagnostic("error", "ROLE_DUPLICATE", `Duplicate extension role "${name}": ${matches.map(({ path, directory, extension }) => `${extensionLabel(extension)} role directory "${directory}" (${path})`).join("; ")}`, matches[0]?.path, "Keep one extension role with this name; global and project roles may override packaged defaults."));
|
|
278
|
+
}
|
|
279
|
+
const extensionPaths = new Map();
|
|
280
|
+
for (const file of extensionScan.files) {
|
|
281
|
+
roles.push({ name: file.name, path: file.path, scope: "extension", active: true, extension: file.extension });
|
|
282
|
+
const definition = inspectRole(file.path, activeTools, knownModels, availableModels, diagnostics, aliases, dynamicAliases, settingsPath, { directory: file.directory, extension: file.extension });
|
|
283
|
+
if (duplicateExtensionNames.has(file.name))
|
|
284
|
+
continue;
|
|
285
|
+
extensionPaths.set(file.name, file.path);
|
|
286
|
+
if (definition)
|
|
287
|
+
definitions.set(file.name, definition);
|
|
288
|
+
}
|
|
210
289
|
const globalPaths = new Map();
|
|
211
290
|
const globalRoleDirs = workflowRoleDirectories(agentDir);
|
|
212
291
|
for (const path of roleFilesFrom(globalRoleDirs)) {
|
|
213
292
|
const name = basename(path, ".md");
|
|
214
|
-
|
|
293
|
+
const extensionPath = extensionPaths.get(name);
|
|
294
|
+
roles.push({ name, path, scope: "global", active: true, ...(extensionPath ? { overrides: extensionPath } : {}) });
|
|
215
295
|
globalPaths.set(name, path);
|
|
216
|
-
|
|
296
|
+
if (extensionPath) {
|
|
297
|
+
const extension = roles.find((role) => role.path === extensionPath);
|
|
298
|
+
if (extension) {
|
|
299
|
+
extension.active = false;
|
|
300
|
+
extension.overriddenBy = path;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const definition = inspectRole(path, activeTools, knownModels, availableModels, diagnostics, aliases, dynamicAliases, settingsPath);
|
|
217
304
|
if (definition)
|
|
218
305
|
definitions.set(name, definition);
|
|
306
|
+
else
|
|
307
|
+
definitions.delete(name);
|
|
219
308
|
}
|
|
220
309
|
for (const path of roleFilesFrom([join(cwd, ".pi", "pi-extensible-workflows", "roles")])) {
|
|
221
310
|
const name = basename(path, ".md");
|
|
222
311
|
const globalPath = globalPaths.get(name);
|
|
312
|
+
const extensionPath = extensionPaths.get(name);
|
|
313
|
+
const overriddenPath = globalPath ?? extensionPath;
|
|
223
314
|
const active = pi.trust.trusted;
|
|
224
|
-
roles.push({ name, path, scope: "project", active, ...(active &&
|
|
315
|
+
roles.push({ name, path, scope: "project", active, ...(active && overriddenPath ? { overrides: overriddenPath } : {}) });
|
|
225
316
|
if (!active)
|
|
226
317
|
continue;
|
|
227
318
|
if (globalPath) {
|
|
@@ -231,7 +322,14 @@ export async function doctor(options = {}) {
|
|
|
231
322
|
global.overriddenBy = path;
|
|
232
323
|
}
|
|
233
324
|
}
|
|
234
|
-
|
|
325
|
+
else if (extensionPath) {
|
|
326
|
+
const extension = roles.find((role) => role.path === extensionPath);
|
|
327
|
+
if (extension) {
|
|
328
|
+
extension.active = false;
|
|
329
|
+
extension.overriddenBy = path;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
const definition = inspectRole(path, activeTools, knownModels, availableModels, diagnostics, aliases, dynamicAliases, settingsPath);
|
|
235
333
|
if (definition)
|
|
236
334
|
definitions.set(name, definition);
|
|
237
335
|
else
|
|
@@ -244,7 +342,7 @@ export async function doctor(options = {}) {
|
|
|
244
342
|
const severityOrder = { error: 0, warning: 1 };
|
|
245
343
|
diagnostics.sort((left, right) => severityOrder[left.severity] - severityOrder[right.severity] || (left.source ?? "").localeCompare(right.source ?? "") || left.code.localeCompare(right.code) || left.message.localeCompare(right.message));
|
|
246
344
|
roles.sort((left, right) => left.name.localeCompare(right.name) || left.scope.localeCompare(right.scope));
|
|
247
|
-
return { cwd, agentDir, settingsPath, settings, trust: pi.trust, activeTools: [...activeTools].sort(), roles, functions, resourcePolicy, diagnostics };
|
|
345
|
+
return { cwd, agentDir, settingsPath, settings, settingsSources, trust: pi.trust, activeTools: [...activeTools].sort(), roles, functions, modelAliases, resourcePolicy, diagnostics };
|
|
248
346
|
}
|
|
249
347
|
function count(report, severity) { return report.diagnostics.filter((item) => item.severity === severity).length; }
|
|
250
348
|
export function doctorExitCode(report) { return count(report, "error") > 0 ? 1 : 0; }
|
|
@@ -255,7 +353,9 @@ export function formatDoctorReport(report) {
|
|
|
255
353
|
"## Environment",
|
|
256
354
|
`- CWD: \`${report.cwd}\``,
|
|
257
355
|
`- Agent dir: \`${report.agentDir}\``,
|
|
258
|
-
`-
|
|
356
|
+
`- Global workflow settings: \`${report.settingsPath}\``,
|
|
357
|
+
`- Project workflow settings: \`${report.resourcePolicy.projectSettingsPath}\` (${report.resourcePolicy.projectTrusted ? "trusted" : "ignored: project untrusted"})`,
|
|
358
|
+
`- Effective setting sources: concurrency=\`${report.settingsSources.concurrency}\`, modelAliases=\`${report.settingsSources.modelAliases}\`, disabledAgentResources=\`${report.settingsSources.disabledAgentResources}\``,
|
|
259
359
|
`- Limits: concurrency=${String(report.settings.concurrency)}`,
|
|
260
360
|
"",
|
|
261
361
|
"## Trust/resources",
|
|
@@ -270,6 +370,8 @@ export function formatDoctorReport(report) {
|
|
|
270
370
|
`- Project extensions: ${report.resourcePolicy.project.extensions.join(", ") || "(none)"}`,
|
|
271
371
|
`- Effective skills: ${report.resourcePolicy.effective.skills.join(", ") || "(none)"}`,
|
|
272
372
|
`- Effective extensions: ${report.resourcePolicy.effective.extensions.join(", ") || "(none)"}`,
|
|
373
|
+
`- Excluded skills: ${report.resourcePolicy.excludedSkills?.join(", ") || "(none)"}`,
|
|
374
|
+
`- Excluded extensions: ${report.resourcePolicy.excludedExtensions?.join(", ") || "(none)"}`,
|
|
273
375
|
`- Unmatched skills: ${report.resourcePolicy.unmatchedSkills.join(", ") || "(none)"}`,
|
|
274
376
|
`- Unmatched extensions: ${report.resourcePolicy.unmatchedExtensions.join(", ") || "(none)"}`,
|
|
275
377
|
"",
|
|
@@ -277,7 +379,10 @@ export function formatDoctorReport(report) {
|
|
|
277
379
|
...(report.activeTools.length ? report.activeTools.map((tool) => `- \`${tool}\``) : ["- None resolved"]),
|
|
278
380
|
"",
|
|
279
381
|
"## Roles",
|
|
280
|
-
...(report.roles.length ? report.roles.map((role) => `- \`${role.name}\` (${role.scope}, ${role.active ? "active" : role.overriddenBy ? `overridden by ${role.overriddenBy}` : "inactive: project untrusted"}) - \`${role.path}\`${role.overrides ? `; overrides \`${role.overrides}\`` : ""}`) : ["- None found"]),
|
|
382
|
+
...(report.roles.length ? report.roles.map((role) => `- \`${role.name}\` (${role.scope}, ${role.active ? "active" : role.overriddenBy ? `overridden by ${role.overriddenBy}` : "inactive: project untrusted"}) - \`${role.path}\`${role.extension ? `; ${extensionLabel(role.extension)} role directory "${dirname(role.path)}"` : ""}${role.overrides ? `; overrides \`${role.overrides}\`` : ""}`) : ["- None found"]),
|
|
383
|
+
"",
|
|
384
|
+
"## Model aliases",
|
|
385
|
+
...(report.modelAliases.length ? report.modelAliases.map((alias) => `- [${alias.kind}] \`${alias.name}\`${alias.kind === "static" ? ` -> ${report.settings.modelAliases?.[alias.name] ?? "(unresolved)"}` : ""} (${alias.provenance})`) : ["- None registered"]),
|
|
281
386
|
"",
|
|
282
387
|
"## Reusable functions",
|
|
283
388
|
...(report.functions.length ? report.functions.map((fn) => `- [${fn.valid ? "ok" : "error"}] \`${fn.name}\` - ${fn.description}`) : ["- None registered"]),
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RunStore } from "./persistence.js";
|
|
2
|
+
import type { AgentAttempt } from "./agent-execution.js";
|
|
3
|
+
import type { AgentIdentity, JsonValue, ShellIdentity, ShellOptions, ShellResult, WorkflowBridge, WorkflowExecution } from "./types.js";
|
|
4
|
+
export declare const RPC_LIMIT_BYTES: number;
|
|
5
|
+
export declare const HEARTBEAT_TIMEOUT_MS = 5000;
|
|
6
|
+
export declare function encoded(value: unknown): string;
|
|
7
|
+
export declare function agentIdentityPath(identity: AgentIdentity): string;
|
|
8
|
+
export declare function shellIdentityPath(identity: ShellIdentity): string;
|
|
9
|
+
export declare function readShellResult(value: unknown): ShellResult;
|
|
10
|
+
export declare function agentWorktree(identity: AgentIdentity): {
|
|
11
|
+
worktreeOwner?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function executeShellCommand(command: string, options: ShellOptions, signal: AbortSignal, cwd?: string): Promise<ShellResult>;
|
|
14
|
+
export declare function runWorkflow(script: string, args?: JsonValue, bridge?: WorkflowBridge, signal?: AbortSignal): WorkflowExecution;
|
|
15
|
+
export declare function persistActiveAgentAttempt(store: RunStore, id: string, active: Pick<AgentAttempt, "attempt" | "sessionId" | "sessionFile" | "setup">): Promise<void>;
|
|
16
|
+
export declare function persistAgentAttempts(store: RunStore, id: string, attempts: readonly AgentAttempt[]): Promise<void>;
|
|
17
|
+
export type { AgentIdentity, ShellIdentity, WorkflowBridge, WorkflowExecution } from "./types.js";
|