@marcoscale98/pi-extensible-workflows 5.19.1-fork.1 → 6.2.1-fork.1

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.
Files changed (123) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/README.md +2 -2
  3. package/dist/src/agent-execution.d.ts +43 -10
  4. package/dist/src/agent-execution.js +365 -127
  5. package/dist/src/background-widget.d.ts +0 -1
  6. package/dist/src/background-widget.js +4 -9
  7. package/dist/src/decoders.d.ts +2 -3
  8. package/dist/src/decoders.js +33 -37
  9. package/dist/src/execution.d.ts +2 -0
  10. package/dist/src/execution.js +5 -5
  11. package/dist/src/host-delivery.js +4 -8
  12. package/dist/src/host-navigator.js +5 -2
  13. package/dist/src/host-phases.d.ts +1 -0
  14. package/dist/src/host-recovery.d.ts +6 -6
  15. package/dist/src/host-recovery.js +14 -22
  16. package/dist/src/host-runtime.js +56 -5
  17. package/dist/src/host-view.d.ts +1 -1
  18. package/dist/src/host-view.js +17 -15
  19. package/dist/src/host.js +62 -87
  20. package/dist/src/index.d.ts +1 -2
  21. package/dist/src/index.js +1523 -1630
  22. package/dist/src/index.js.map +3 -3
  23. package/dist/src/paths.d.ts +7 -6
  24. package/dist/src/paths.js +24 -15
  25. package/dist/src/persistence.d.ts +1 -0
  26. package/dist/src/persistence.js +1 -0
  27. package/dist/src/pi-runtime-runner.js +4 -1
  28. package/dist/src/registry.d.ts +9 -7
  29. package/dist/src/registry.js +28 -70
  30. package/dist/src/runtime/agent-runner.d.ts +2 -0
  31. package/dist/src/session-lease.d.ts +1 -1
  32. package/dist/src/session-lease.js +45 -11
  33. package/dist/src/settings.d.ts +6 -3
  34. package/dist/src/settings.js +36 -47
  35. package/dist/src/store.d.ts +3 -1
  36. package/dist/src/store.js +17 -1
  37. package/dist/src/trajectory.d.ts +0 -1
  38. package/dist/src/trajectory.js +2 -3
  39. package/dist/src/types.d.ts +100 -44
  40. package/dist/src/types.js +4 -7
  41. package/dist/src/utils.d.ts +3 -2
  42. package/dist/src/utils.js +20 -10
  43. package/dist/src/validation.d.ts +8 -2
  44. package/dist/src/validation.js +122 -86
  45. package/dist/starter/index.js +8 -9
  46. package/dist/starter/index.js.map +1 -1
  47. package/dist/starter/review-loop.js +8 -7
  48. package/dist/subagents/index.js +654 -814
  49. package/dist/subagents/index.js.map +3 -3
  50. package/dist/subagents/src/contracts.d.ts +4 -3
  51. package/dist/subagents/src/contracts.js +2 -2
  52. package/dist/subagents/src/index.d.ts +1 -1
  53. package/dist/subagents/src/index.js +1 -2
  54. package/dist/subagents/src/manager.js +49 -70
  55. package/dist/subagents/src/navigator.js +3 -14
  56. package/dist/subagents/src/view.d.ts +0 -1
  57. package/dist/subagents/src/view.js +2 -16
  58. package/dist/subagents/src/worktree.js +1 -1
  59. package/dist/trajectory/assets/index.html +8 -8
  60. package/dist/trajectory/index.js +487 -891
  61. package/dist/trajectory/index.js.map +3 -3
  62. package/dist/trajectory/src/assets/index.html +8 -8
  63. package/dist/trajectory/src/index.js +126 -86
  64. package/dist/trajectory/src/server.js +264 -25
  65. package/dist/trajectory/src/server.js.map +3 -3
  66. package/dist/trajectory/src/startup-mutex.d.ts +17 -0
  67. package/dist/trajectory/src/startup-mutex.js +172 -0
  68. package/examples/workflow-extension-template/README.md +4 -7
  69. package/examples/workflow-extension-template/extension.test.mjs +4 -8
  70. package/examples/workflow-extension-template/index.js +0 -3
  71. package/package.json +5 -5
  72. package/skills/pi-extensible-workflows/SKILL.md +10 -8
  73. package/src/agent-execution.ts +339 -127
  74. package/src/background-widget.ts +4 -10
  75. package/src/decoders.ts +31 -37
  76. package/src/execution.ts +5 -5
  77. package/src/host-delivery.ts +4 -8
  78. package/src/host-navigator.ts +4 -2
  79. package/src/host-phases.ts +1 -1
  80. package/src/host-recovery.ts +20 -26
  81. package/src/host-runtime.ts +44 -6
  82. package/src/host-view.ts +18 -11
  83. package/src/host.ts +62 -113
  84. package/src/index.ts +1 -2
  85. package/src/paths.ts +18 -12
  86. package/src/persistence.ts +1 -0
  87. package/src/pi-runtime-runner.ts +3 -1
  88. package/src/registry.ts +27 -63
  89. package/src/runtime/agent-runner.ts +2 -0
  90. package/src/session-lease.ts +34 -6
  91. package/src/settings.ts +35 -47
  92. package/src/store.ts +18 -2
  93. package/src/trajectory.ts +2 -4
  94. package/src/types.ts +71 -30
  95. package/src/utils.ts +18 -9
  96. package/src/validation.ts +102 -79
  97. package/starter/index.ts +0 -1
  98. package/starter/review-loop.ts +8 -7
  99. package/starter/roles/developer.md +0 -1
  100. package/starter/roles/oracle.md +0 -1
  101. package/starter/roles/researcher.md +0 -1
  102. package/starter/roles/reviewer.md +0 -1
  103. package/starter/roles/scout.md +0 -1
  104. package/subagents/README.md +8 -14
  105. package/subagents/src/contracts.ts +3 -4
  106. package/subagents/src/index.ts +2 -3
  107. package/subagents/src/manager.ts +45 -125
  108. package/subagents/src/navigator.ts +4 -13
  109. package/subagents/src/view.ts +4 -14
  110. package/subagents/src/worktree.ts +1 -1
  111. package/trajectory/src/assets/index.html +8 -8
  112. package/trajectory/src/index.ts +106 -82
  113. package/trajectory/src/server.ts +44 -8
  114. package/trajectory/src/startup-mutex.ts +127 -0
  115. package/dist/src/roles.d.ts +0 -70
  116. package/dist/src/roles.js +0 -326
  117. package/dist/starter/roles/developer.md +0 -6
  118. package/dist/starter/roles/oracle.md +0 -18
  119. package/dist/starter/roles/researcher.md +0 -20
  120. package/dist/starter/roles/reviewer.md +0 -19
  121. package/dist/starter/roles/scout.md +0 -18
  122. package/examples/workflow-extension-template/roles/reviewer.md +0 -4
  123. package/src/roles.ts +0 -327
@@ -1,16 +1,18 @@
1
1
  import { atomicWriteFile } from "./persistence.js";
2
2
  import { mkdirSync, readFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
3
5
  import { homedir } from "node:os";
4
- import { dirname, join, resolve } from "node:path";
6
+ import { resolve } from "node:path";
5
7
  import { fileURLToPath } from "node:url";
6
- import { getAgentDir } from "@earendil-works/pi-coding-agent";
7
- import { isContextFileScope } from "./types.js";
8
- import { annotateModelAliasError, deepFreeze, errorText, fail, isNodeError, jsonValue, modelCapability, object, positiveInteger, resourcePatternHasMagic, unknownModel, validateModelAliases, validateResourcePattern, validWorkflowExtensionNamespace } from "./utils.js";
9
8
  import { canonicalPath, workflowProjectSettingsPath } from "./paths.js";
10
9
  export { workflowProjectSettingsPath } from "./paths.js";
11
- const ROLE_DIRECTORY = "pi-extensible-workflows";
10
+ import { isContextFileScope } from "./types.js";
11
+ import { annotateModelAliasError, deepFreeze, errorText, fail, isNodeError, modelCapability, object, positiveInteger, unknownModel, validateModelAliases } from "./utils.js";
12
+ import { jsonValue, resourcePatternHasMagic, validateResourcePattern, validWorkflowExtensionNamespace } from "./utils.js";
13
+ const WORKFLOW_DIRECTORY = "pi-extensible-workflows";
12
14
  export const DEFAULT_SETTINGS = Object.freeze({ concurrency: 8, backgroundWidget: true });
13
- export function workflowSettingsPath(agentDir = getAgentDir()) { return join(agentDir, ROLE_DIRECTORY, "settings.json"); }
15
+ export function workflowSettingsPath(agentDir = getAgentDir()) { return join(agentDir, WORKFLOW_DIRECTORY, "settings.json"); }
14
16
  function normalizedResourcePath(value, settingsPath) {
15
17
  // Built-in extensions are named `builtin:<name>`, not by a path.
16
18
  if (value === "*" || value.startsWith("builtin:"))
@@ -82,23 +84,25 @@ function selectorsFromSettings(settings) {
82
84
  };
83
85
  }
84
86
  function selectorSet(value) { return { skills: [...(value?.skills ?? [])], extensions: [...(value?.extensions ?? [])], ...(value?.tools === undefined ? {} : { tools: [...value.tools] }) }; }
85
- export function validateContextFileScopes(value, rolePath) {
87
+ export function validateContextFileScopes(value, sourcePath) {
86
88
  if (value === undefined)
87
89
  return undefined;
88
90
  if (!Array.isArray(value) || !value.every(isContextFileScope))
89
- fail("INVALID_METADATA", `${rolePath}.contextFiles must be an array containing only global, project, or cwd`);
91
+ fail("INVALID_METADATA", `${sourcePath}.contextFiles must be an array containing only global, project, or cwd`);
90
92
  return [...value];
91
93
  }
92
94
  export function validateWorkflowExtensionSettings(value, settingsPath, errorCode = "INVALID_SETTINGS") {
93
95
  if (value === undefined)
94
96
  return undefined;
97
+ if (!object(value) || !jsonValue(value))
98
+ fail(errorCode, `${settingsPath}.extensionSettings must be a JSON object`);
99
+ for (const namespace of Object.keys(value))
100
+ if (!validWorkflowExtensionNamespace(namespace))
101
+ fail(errorCode, `${settingsPath}.extensionSettings contains an invalid namespace: ${namespace}`);
102
+ const generic = value;
95
103
  const base = `${settingsPath}.extensionSettings`;
96
- if (!object(value))
97
- fail(errorCode, `${base} must be an object`);
98
104
  const normalized = {};
99
- for (const [namespace, raw] of Object.entries(value)) {
100
- if (!validWorkflowExtensionNamespace(namespace))
101
- fail(errorCode, `${base} contains an invalid namespace: ${namespace}`);
105
+ for (const [namespace, raw] of Object.entries(generic)) {
102
106
  if (namespace === "herdr") {
103
107
  if (!object(raw))
104
108
  fail(errorCode, `${base}.herdr must be an object`);
@@ -119,8 +123,6 @@ export function validateWorkflowExtensionSettings(value, settingsPath, errorCode
119
123
  normalized.trajectory = Object.freeze({ ...(raw.port === undefined ? {} : { port: raw.port }) });
120
124
  continue;
121
125
  }
122
- if (!jsonValue(raw))
123
- fail(errorCode, `${base}.${namespace} must be JSON-compatible`);
124
126
  normalized[namespace] = structuredClone(raw);
125
127
  }
126
128
  return deepFreeze(normalized);
@@ -206,39 +208,22 @@ export function loadCodemodeToolsSetting(agentDir) {
206
208
  export function loadSettingsOverrides(path) { return parseSettings(path, true); }
207
209
  export function resolveWorkflowSettings(cwd, projectTrusted, globalSettingsPath = workflowSettingsPath()) {
208
210
  const projectSettingsPath = workflowProjectSettingsPath(cwd);
209
- const global = loadSettings(globalSettingsPath);
210
- const project = projectTrusted ? loadSettingsOverrides(projectSettingsPath) : Object.freeze({});
211
- const projectHas = (key) => Object.prototype.hasOwnProperty.call(project, key);
212
- const sourceFor = (key) => projectHas(key) ? projectSettingsPath : globalSettingsPath;
213
- const globalSelectors = selectorsFromSettings(global);
214
- const projectSelectors = selectorsFromSettings(project);
215
- const effectiveSelectors = selectorSet({
216
- skills: [...(globalSelectors.skills ?? []), ...(projectSelectors.skills ?? [])],
217
- extensions: [...(globalSelectors.extensions ?? []), ...(projectSelectors.extensions ?? [])],
218
- ...(globalSelectors.tools === undefined && projectSelectors.tools === undefined ? {} : { tools: [...(globalSelectors.tools ?? []), ...(projectSelectors.tools ?? [])] }),
219
- });
220
- const hasExtensionSelectors = global.extensions !== undefined || project.extensions !== undefined;
221
- const extensionSettings = projectHas("extensionSettings") ? project.extensionSettings : global.extensionSettings;
222
- const sources = {
223
- concurrency: projectHas("concurrency") ? projectSettingsPath : globalSettingsPath,
224
- modelAliases: projectHas("modelAliases") ? projectSettingsPath : globalSettingsPath,
225
- skills: sourceFor("skills"), extensions: sourceFor("extensions"), tools: sourceFor("tools"),
226
- ...(extensionSettings === undefined ? {} : { extensionSettings: projectHas("extensionSettings") ? projectSettingsPath : globalSettingsPath }),
227
- ...(project.retention === undefined && global.retention === undefined ? {} : { retention: project.retention === undefined ? globalSettingsPath : projectSettingsPath }),
228
- ...(projectHas("worktreePostCreateCommand") || global.worktreePostCreateCommand !== undefined ? { worktreePostCreateCommand: projectHas("worktreePostCreateCommand") ? projectSettingsPath : globalSettingsPath } : {}),
229
- };
211
+ const consumerGlobal = loadSettings(globalSettingsPath);
212
+ const consumerProject = projectTrusted ? loadSettingsOverrides(projectSettingsPath) : Object.freeze({});
213
+ const global = consumerGlobal;
214
+ const project = consumerProject;
215
+ const selectorSources = { global: selectorsFromSettings(global), project: selectorsFromSettings(project) };
230
216
  const effective = Object.freeze({
231
- concurrency: project.concurrency ?? global.concurrency,
232
- backgroundWidget: global.backgroundWidget ?? true,
233
- ...(projectHas("modelAliases") ? { modelAliases: project.modelAliases } : global.modelAliases === undefined ? {} : { modelAliases: global.modelAliases }),
234
- ...(effectiveSelectors.skills.length ? { skills: effectiveSelectors.skills } : global.skills !== undefined || project.skills !== undefined ? { skills: effectiveSelectors.skills } : {}),
235
- ...(hasExtensionSelectors ? { extensions: effectiveSelectors.extensions } : {}),
236
- ...(extensionSettings === undefined ? {} : { extensionSettings }),
237
- ...(effectiveSelectors.tools?.length ? { tools: effectiveSelectors.tools } : global.tools !== undefined || project.tools !== undefined ? { tools: effectiveSelectors.tools } : {}),
238
- ...((project.retention ?? global.retention) === undefined ? {} : { retention: project.retention ?? global.retention }),
239
- ...(projectHas("worktreePostCreateCommand") ? { worktreePostCreateCommand: project.worktreePostCreateCommand } : global.worktreePostCreateCommand === undefined ? {} : { worktreePostCreateCommand: global.worktreePostCreateCommand }),
217
+ ...global, ...project,
218
+ skills: [...(global.skills ?? []), ...(project.skills ?? [])],
219
+ extensions: [...(global.extensions ?? []), ...(project.extensions ?? [])],
220
+ ...(global.tools === undefined && project.tools === undefined ? {} : { tools: [...(global.tools ?? []), ...(project.tools ?? [])] }),
240
221
  });
241
- return { globalSettingsPath, projectSettingsPath, projectTrusted, global, project, effective, sources };
222
+ const sources = { concurrency: project.concurrency === undefined ? globalSettingsPath : projectSettingsPath, modelAliases: project.modelAliases === undefined ? globalSettingsPath : projectSettingsPath };
223
+ for (const key of ["skills", "extensions", "tools", "extensionSettings", "retention", "worktreePostCreateCommand"])
224
+ if (effective[key] !== undefined)
225
+ sources[key] = project[key] === undefined ? globalSettingsPath : projectSettingsPath;
226
+ return { globalSettingsPath, projectSettingsPath, projectTrusted, global, project, effective, sources, selectorSources };
242
227
  }
243
228
  export function validateModelAliasAvailability(aliases, names, availableModels, knownModels, settingsPath) {
244
229
  for (const name of names) {
@@ -257,7 +242,7 @@ export function resolveAgentResourcePolicy(cwd, projectTrusted, globalSettingsPa
257
242
  const global = selectorSet(selectorsFromSettings(resolved.global));
258
243
  const project = selectorSet(selectorsFromSettings(resolved.project));
259
244
  const effective = selectorSet(selectorsFromSettings(resolved.effective));
260
- return { globalSettingsPath: resolved.globalSettingsPath, projectSettingsPath: resolved.projectSettingsPath, projectTrusted, global, project, effective, unmatchedSkills: [], unmatchedExtensions: [], unmatchedTools: [], selectorSources: { global: selectorsFromSettings(resolved.global), project: selectorsFromSettings(resolved.project) } };
245
+ return { globalSettingsPath: resolved.globalSettingsPath, projectSettingsPath: resolved.projectSettingsPath, projectTrusted, global, project, effective, unmatchedSkills: [], unmatchedExtensions: [], unmatchedTools: [], selectorSources: resolved.selectorSources };
261
246
  }
262
247
  export function saveModelAliases(path = workflowSettingsPath(), aliases = {}) {
263
248
  const normalized = validateModelAliases(aliases, path);
@@ -275,3 +260,7 @@ export function saveModelAliases(path = workflowSettingsPath(), aliases = {}) {
275
260
  mkdirSync(dirname(path), { recursive: true });
276
261
  atomicWriteFile(path, `${JSON.stringify({ ...parsed, modelAliases: normalized }, null, 2)}\n`, true);
277
262
  }
263
+ export function canonicalExtensionSelector(selector, cwd) {
264
+ const negated = selector.startsWith("!");
265
+ return `${negated ? "!" : ""}${normalizedResourcePath(negated ? selector.slice(1) : selector, join(cwd, "settings.json"))}`;
266
+ }
@@ -1,4 +1,4 @@
1
- import { type JsonValue, type LaunchSnapshot, type WorkflowRunEvent } from "./types.js";
1
+ import { type PreparedAgentConfiguration, type JsonValue, type LaunchSnapshot, type WorkflowLaunchMode, type WorkflowRunEvent } from "./types.js";
2
2
  import { type AwaitingCheckpoint, type BorrowedWorktreeBinding, type CompletedOperation, type EffectiveSystemPrompt, type PendingWorkflowDecision, type PersistedOwnershipNode, type PersistedRun, type RunSummary, type WorktreeReference } from "./decoders.js";
3
3
  export declare class RunStore {
4
4
  #private;
@@ -28,6 +28,8 @@ export declare class RunStore {
28
28
  loadSummary(): Promise<RunSummary>;
29
29
  saveState(run: PersistedRun): Promise<void>;
30
30
  updateState(update: (run: PersistedRun) => PersistedRun | Promise<PersistedRun>): Promise<PersistedRun>;
31
+ saveAgentConfiguration(key: string, configuration: PreparedAgentConfiguration): Promise<void>;
32
+ setLaunchMode(launchMode: WorkflowLaunchMode): Promise<void>;
31
33
  saveSnapshot(snapshot: Readonly<LaunchSnapshot>): Promise<void>;
32
34
  appendEvent(event: WorkflowRunEvent): Promise<void>;
33
35
  saveOwnership(nodes: readonly PersistedOwnershipNode[]): Promise<void>;
package/dist/src/store.js CHANGED
@@ -24,7 +24,7 @@ function summaryFromRun(run, directory, journal, previous, fallbackCreatedAt, no
24
24
  const failedAt = run.failedAt ?? run.error?.failedAt;
25
25
  const replayablePaths = [...new Set([...(run.retry?.completedPaths ?? []), ...Object.keys(journal.completed)])];
26
26
  const incompletePaths = [...new Set([...(run.retry?.incompletePaths ?? []), ...(failedAt ? [failedAt] : [])])];
27
- return { schemaVersion: 1, runId: run.id, sessionId: run.sessionId, workflowName: run.workflowName, state: run.state, createdAt, updatedAt: now, ...(previous?.terminalAt || HARD_TERMINAL_RUN_STATES.has(run.state) ? { terminalAt: previous?.terminalAt ?? now } : {}), usage: budgetUsage(run.usage), agents: run.agents.map(({ id, name, label, state, role, attempts }) => ({ id, name, ...(label ? { label } : {}), state, ...(role ? { role } : {}), attempts })), ...(run.error ? { error: run.error } : {}), ...(failedAt ? { failedAt } : {}), replayablePaths, incompletePaths, artifacts: summaryArtifacts(directory) };
27
+ return { schemaVersion: 1, runId: run.id, sessionId: run.sessionId, workflowName: run.workflowName, state: run.state, createdAt, updatedAt: now, ...(previous?.terminalAt || HARD_TERMINAL_RUN_STATES.has(run.state) ? { terminalAt: previous?.terminalAt ?? now } : {}), usage: budgetUsage(run.usage), agents: run.agents.map(({ id, name, label, state, attempts }) => ({ id, name, ...(label ? { label } : {}), state, attempts })), ...(run.error ? { error: run.error } : {}), ...(failedAt ? { failedAt } : {}), replayablePaths, incompletePaths, artifacts: summaryArtifacts(directory) };
28
28
  }
29
29
  function systemPromptStoragePath(directory) { return join(directory, SYSTEM_PROMPT_STORAGE); }
30
30
  function systemPromptRecordsPath(directory) { return join(systemPromptStoragePath(directory), SYSTEM_PROMPT_RECORDS); }
@@ -171,6 +171,22 @@ export class RunStore {
171
171
  });
172
172
  return write;
173
173
  }
174
+ async saveAgentConfiguration(key, configuration) {
175
+ await this.launchSnapshotLane.run(async () => {
176
+ const snapshot = decodeLaunchSnapshot(await json(join(this.directory, "snapshot.json")));
177
+ if (!snapshot)
178
+ throw new WorkflowError("RESUME_INCOMPATIBLE", "Workflow launch snapshot identity version is incompatible");
179
+ await atomicJson(join(this.directory, "snapshot.json"), { ...snapshot, agentConfigurations: { ...snapshot.agentConfigurations, [key]: configuration } });
180
+ });
181
+ }
182
+ async setLaunchMode(launchMode) {
183
+ await this.launchSnapshotLane.run(async () => {
184
+ const snapshot = decodeLaunchSnapshot(await json(join(this.directory, "snapshot.json")));
185
+ if (!snapshot)
186
+ throw new WorkflowError("RESUME_INCOMPATIBLE", "Workflow launch snapshot identity version is incompatible");
187
+ await atomicJson(join(this.directory, "snapshot.json"), { ...snapshot, launchMode });
188
+ });
189
+ }
174
190
  async saveSnapshot(snapshot) {
175
191
  const write = this.launchSnapshotLane.run(() => atomicJson(join(this.directory, "snapshot.json"), snapshot));
176
192
  await write;
@@ -63,7 +63,6 @@ export type TrajectorySubagent = {
63
63
  sessionId: string;
64
64
  cwd: string;
65
65
  label?: string;
66
- role?: string;
67
66
  mode: "background" | "foreground";
68
67
  state: SubagentStatus["state"];
69
68
  startedAt?: number;
@@ -238,8 +238,8 @@ async function resolveResourceInspection(inspection, cwd, selectorCwd = cwd) {
238
238
  return inspection;
239
239
  }
240
240
  const sources = inspection.selectorSources ?? { global: inspection.selectors, project: {} };
241
- const skills = inspection.skills.length ? inspection.skills : selectResourcesByLayers([sources.global.skills, sources.project.skills, sources.role?.skills, sources.call?.skills], discovered.skills);
242
- const extensions = inspection.extensions.length ? inspection.extensions : selectResourcesByLayers([sources.global.extensions, sources.project.extensions, sources.role?.extensions, sources.call?.extensions].map((layer) => layer?.map((selector) => canonicalExtensionSelector(selector, selectorCwd))), discovered.extensions);
241
+ const skills = inspection.skills.length ? inspection.skills : selectResourcesByLayers([sources.global.skills, sources.project.skills, sources.call?.skills], discovered.skills);
242
+ const extensions = inspection.extensions.length ? inspection.extensions : selectResourcesByLayers([sources.global.extensions, sources.project.extensions, sources.call?.extensions].map((layer) => layer?.map((selector) => canonicalExtensionSelector(selector, selectorCwd))), discovered.extensions);
243
243
  return skills === inspection.skills && extensions === inspection.extensions ? inspection : { ...inspection, skills, extensions };
244
244
  }
245
245
  export async function withResolvedAttemptResources(attempt, cwd) {
@@ -577,7 +577,6 @@ async function loadTrajectorySubagent(directory, cwd, sessionId, includeTranscri
577
577
  return {
578
578
  id, sessionId, cwd, mode: request.mode ?? "background", state: status.state, request, tools, transcript,
579
579
  ...(request.label === undefined ? {} : { label: request.label }),
580
- ...(request.role === undefined ? {} : { role: request.role }),
581
580
  ...(status.startedAt === undefined ? {} : { startedAt: status.startedAt }),
582
581
  ...(status.finishedAt === undefined ? {} : { finishedAt: status.finishedAt }),
583
582
  ...(status.attempts === undefined ? {} : { attempts: status.attempts }),
@@ -23,9 +23,12 @@ export declare const WORKFLOW_CHECKPOINT_STATE_CHANGED_EVENT = "workflow:checkpo
23
23
  export declare const WORKFLOW_BUDGET_EVENT = "workflow:budget-event";
24
24
  export declare const WORKFLOW_WORKTREE_CREATED_EVENT = "workflow:worktree-created";
25
25
  export declare const WORKFLOW_BLOCKED_EVENT = "workflow:blocked";
26
- export declare const ERROR_CODES: readonly ["CONFIG_ERROR", "INVALID_SETTINGS", "INVALID_SYNTAX", "INVALID_METADATA", "DUPLICATE_NAME", "INVALID_SCHEMA", "UNKNOWN_MODEL", "UNKNOWN_TOOL", "UNKNOWN_AGENT_TYPE", "RUN_OWNED", "RUN_NOT_FOUND", "REGISTRY_FROZEN", "GLOBAL_COLLISION", "MISSING_WORKFLOW", "RPC_LIMIT_EXCEEDED", "SHELL_FAILED", "AGENT_TIMEOUT", "AGENT_FAILED", "AGENT_RESULT_COLLECTED", "RESULT_INVALID", "TOOL_FAILED", "CANCELLED", "WORKER_UNRESPONSIVE", "WORKTREE_FAILED", "RESUME_INCOMPATIBLE", "BUDGET_EXHAUSTED", "INTERNAL_ERROR"];
26
+ export declare const ERROR_CODES: readonly ["CONFIG_ERROR", "INVALID_SETTINGS", "INVALID_SYNTAX", "INVALID_METADATA", "DUPLICATE_NAME", "INVALID_SCHEMA", "UNKNOWN_MODEL", "UNKNOWN_TOOL", "UNKNOWN_AGENT", "RUN_OWNED", "RUN_NOT_FOUND", "REGISTRY_FROZEN", "GLOBAL_COLLISION", "MISSING_WORKFLOW", "RPC_LIMIT_EXCEEDED", "SHELL_FAILED", "AGENT_TIMEOUT", "AGENT_FAILED", "AGENT_RESULT_COLLECTED", "RESULT_INVALID", "TOOL_FAILED", "CANCELLED", "WORKER_UNRESPONSIVE", "WORKTREE_FAILED", "RESUME_INCOMPATIBLE", "BUDGET_EXHAUSTED", "INTERNAL_ERROR"];
27
27
  export declare const THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
28
28
  export type ThinkingLevel = (typeof THINKING_LEVELS)[number];
29
+ export declare const CONTEXT_FILE_SCOPES: readonly ["global", "project", "cwd"];
30
+ export type ContextFileScope = (typeof CONTEXT_FILE_SCOPES)[number];
31
+ export declare function isContextFileScope(value: unknown): value is ContextFileScope;
29
32
  export type WorkflowErrorCode = (typeof ERROR_CODES)[number];
30
33
  export type JsonValue = null | boolean | number | string | JsonValue[] | {
31
34
  [key: string]: JsonValue;
@@ -34,15 +37,15 @@ export type JsonSchema = {
34
37
  [key: string]: JsonValue;
35
38
  };
36
39
  type WorkflowSchema = JsonSchema | TSchema;
37
- export declare function roleNameOf(value: unknown): string | undefined;
38
40
  export interface AgentOptions<Schema extends TSchema = never> {
39
41
  label?: string;
40
42
  model?: string;
41
43
  tools?: string[];
44
+ /** Exact tool names removed after preparation hooks; never widens the parent ceiling. */
45
+ excludeTools?: string[];
42
46
  skills?: string[];
43
47
  extensions?: string[];
44
48
  contextFiles?: ContextFileScope[];
45
- role?: string;
46
49
  outputSchema?: JsonSchema | Schema;
47
50
  retries?: number;
48
51
  timeoutMs?: number | null;
@@ -137,7 +140,6 @@ export interface WorkflowRunFailedEvent extends WorkflowEventBase {
137
140
  export interface WorkflowAgentStateChangedEvent extends WorkflowEventBase {
138
141
  agentId: string;
139
142
  displayLabel: string;
140
- role?: string;
141
143
  structuralPath: readonly string[];
142
144
  parentId?: string;
143
145
  parentBreadcrumb?: string;
@@ -196,13 +198,12 @@ export interface WorkflowExtensionSettings {
196
198
  readonly herdr?: Readonly<HerdrExtensionSettings>;
197
199
  readonly trajectory?: Readonly<TrajectoryExtensionSettings>;
198
200
  }
199
- export type WorkflowExtensionSettingsSource = "global" | "project" | "role" | "effective";
201
+ export type WorkflowExtensionSettingsSource = "global" | "project" | "effective";
200
202
  export interface WorkflowExtensionSettingsValidatorContext {
201
203
  source: WorkflowExtensionSettingsSource;
202
204
  cwd: string;
203
205
  projectTrusted: boolean;
204
206
  settingsPath?: string;
205
- role?: string;
206
207
  }
207
208
  export type WorkflowExtensionSettingsValidator = (settings: Readonly<WorkflowExtensionSettings>, context: Readonly<WorkflowExtensionSettingsValidatorContext>) => void;
208
209
  export interface WorkflowSessionStartEvent {
@@ -240,6 +241,7 @@ export interface WorkflowSettingsSources {
240
241
  worktreePostCreateCommand?: string;
241
242
  }
242
243
  export interface WorkflowSettingsResolution {
244
+ selectorSources?: AgentResourceSelectorSources;
243
245
  globalSettingsPath: string;
244
246
  projectSettingsPath: string;
245
247
  projectTrusted: boolean;
@@ -261,13 +263,14 @@ export interface AgentResourceSelectorSet {
261
263
  export interface AgentResourceSelectorSources {
262
264
  global: AgentResourceSelectors;
263
265
  project: AgentResourceSelectors;
264
- role?: AgentResourceSelectors;
265
266
  call?: AgentResourceSelectors;
266
267
  }
267
- export declare const CONTEXT_FILE_SCOPES: readonly ["global", "project", "cwd"];
268
- export type ContextFileScope = (typeof CONTEXT_FILE_SCOPES)[number];
269
- export declare function isContextFileScope(value: unknown): value is ContextFileScope;
270
268
  export interface AgentResourcePolicy {
269
+ capabilities?: Readonly<{
270
+ tools: readonly string[];
271
+ skills: readonly string[];
272
+ extensions: readonly string[];
273
+ }>;
271
274
  globalSettingsPath: string;
272
275
  projectSettingsPath: string;
273
276
  projectTrusted: boolean;
@@ -281,6 +284,8 @@ export interface AgentResourcePolicy {
281
284
  unmatchedExtensions: readonly string[];
282
285
  unmatchedTools?: readonly string[];
283
286
  selectorSources: AgentResourceSelectorSources;
287
+ /** Skills loaded by the parent session; ceiling for skills that extensions contribute through resources_discover. Absent for top-level agents. */
288
+ parentSkills?: readonly string[];
284
289
  }
285
290
  export interface AgentResourceInspection {
286
291
  selectors: AgentResourceSelectorSet;
@@ -356,7 +361,6 @@ export interface AgentRecord {
356
361
  handle?: string;
357
362
  turn?: number;
358
363
  continuity?: AgentContinuity;
359
- role?: string;
360
364
  requestedModel?: string;
361
365
  model: ModelSpec;
362
366
  tools: readonly string[];
@@ -450,22 +454,10 @@ export interface RunRecord {
450
454
  events?: readonly WorkflowRunEvent[];
451
455
  delivery?: WorkflowRunDelivery;
452
456
  }
453
- export declare const LAUNCH_SNAPSHOT_IDENTITY_VERSION = 5;
457
+ export declare const LAUNCH_SNAPSHOT_IDENTITY_VERSION = 6;
454
458
  export type WorkflowLaunchMode = "foreground" | "background";
455
- export interface AgentDefinition {
456
- prompt?: string;
457
- description?: string;
458
- model?: string;
459
- thinking?: NonNullable<ModelSpec["thinking"]>;
460
- tools?: readonly string[];
461
- skills?: readonly string[];
462
- extensions?: readonly string[];
463
- overrideSystemPrompt?: boolean;
464
- contextFiles?: readonly ContextFileScope[];
465
- extensionSettings?: Readonly<WorkflowExtensionSettings>;
466
- }
467
459
  export interface LaunchSnapshot {
468
- identityVersion?: number;
460
+ identityVersion: number;
469
461
  launchMode?: WorkflowLaunchMode;
470
462
  script: string;
471
463
  args: JsonValue;
@@ -478,15 +470,12 @@ export interface LaunchSnapshot {
478
470
  phases?: readonly string[];
479
471
  models: readonly string[];
480
472
  tools: readonly string[];
481
- agentTypes: readonly string[];
482
- roles?: Readonly<Record<string, AgentDefinition>>;
483
- projectRoles?: readonly string[];
473
+ agentConfigurations: Readonly<Record<string, PreparedAgentConfiguration>>;
484
474
  schemas: readonly JsonSchema[];
485
475
  }
486
476
  export interface PreflightCapabilities {
487
477
  models: ReadonlySet<string>;
488
478
  tools: ReadonlySet<string>;
489
- agentTypes: ReadonlySet<string>;
490
479
  modelAliases?: Readonly<Record<string, string>>;
491
480
  knownModels?: ReadonlySet<string>;
492
481
  settingsPath?: string;
@@ -498,10 +487,22 @@ export interface PreflightResult {
498
487
  phases: readonly string[];
499
488
  models: readonly string[];
500
489
  tools: readonly string[];
501
- agentTypes: readonly string[];
502
490
  };
503
491
  schemas: readonly JsonSchema[];
504
- dynamicAgentRoles: boolean;
492
+ }
493
+ export interface AgentHandleSendOptions<Schema extends TSchema = never> {
494
+ outputSchema?: JsonSchema | Schema;
495
+ timeoutMs?: number | null;
496
+ }
497
+ /** A persistent agent: each send continues the transcript of the previous completed turn. Sends must be awaited one at a time, in the scope that created the handle. */
498
+ export interface AgentHandle {
499
+ readonly name: string;
500
+ send: {
501
+ <Schema extends TSchema>(prompt: string, options: Readonly<AgentHandleSendOptions<Schema> & {
502
+ outputSchema: Schema;
503
+ }>): Promise<Static<Schema>>;
504
+ (prompt: string, options?: Readonly<AgentHandleSendOptions>): Promise<JsonValue>;
505
+ };
505
506
  }
506
507
  export interface WorkflowOrchestrationContext {
507
508
  agent: {
@@ -509,6 +510,9 @@ export interface WorkflowOrchestrationContext {
509
510
  outputSchema: Schema;
510
511
  }>): Promise<Static<Schema>>;
511
512
  (prompt: string, options?: Readonly<AgentOptions>): Promise<JsonValue>;
513
+ create: (options: Readonly<AgentOptions & {
514
+ name: string;
515
+ }>) => AgentHandle;
512
516
  };
513
517
  shell: (command: string, options?: ShellOptions) => Promise<ShellResult>;
514
518
  prompt: (template: string, values: Readonly<Record<string, JsonValue>>) => string;
@@ -616,6 +620,8 @@ export interface WorkflowAgentSession {
616
620
  getState(): Readonly<WorkflowAgentSessionState>;
617
621
  getSessionStats(): WorkflowAgentSessionStats;
618
622
  getLastAssistant(): WorkflowAgentMessage | undefined;
623
+ /** Set by a transport that already delivered `PreparedAgentSession.turnControl` itself; otherwise the runner steers it before the first prompt. */
624
+ readonly turnControlDelivered?: boolean;
619
625
  subscribe(listener: (event: WorkflowAgentSessionEvent) => void): () => void;
620
626
  subscribeAsync?(listener: (event: WorkflowAgentSessionEvent) => void | Promise<void>): () => void;
621
627
  prompt(text: string): Promise<WorkflowAgentTurnResult>;
@@ -632,7 +638,8 @@ export interface WorkflowAgentSession {
632
638
  type SessionTools = NonNullable<CreateAgentSessionOptions["tools"]>;
633
639
  type SessionCustomTools = NonNullable<CreateAgentSessionOptions["customTools"]>;
634
640
  export interface SessionInput {
635
- cwd: string;
641
+ /** Read-only: setup hooks cannot move an agent, because Pi derives trust, settings and `.pi` resources from cwd. */
642
+ readonly cwd: string;
636
643
  model: ModelSpec;
637
644
  tools: SessionTools;
638
645
  sessionLabel: string;
@@ -661,6 +668,8 @@ export interface PreparedAgentSession {
661
668
  readonly sessionLabel: string;
662
669
  readonly sessionPath?: string;
663
670
  readonly initialPrompt?: string;
671
+ /** Dynamic per-attempt control text (retry state, budget). The runner steers it before the first prompt unless the session reports `turnControlDelivered`. */
672
+ readonly turnControl?: string;
664
673
  readonly agentDir?: string;
665
674
  readonly customTools?: readonly ToolDefinition[];
666
675
  readonly resultTool?: ToolDefinition;
@@ -707,6 +716,64 @@ export interface AgentSetupContext {
707
716
  readonly mode?: AgentInspectionMode;
708
717
  readonly settings: Readonly<WorkflowExtensionSettings>;
709
718
  }
719
+ export interface AgentPreparation {
720
+ label?: string;
721
+ model?: string;
722
+ tools: string[];
723
+ skills: string[];
724
+ extensions: string[];
725
+ contextFiles?: ContextFileScope[];
726
+ systemPrompt?: string;
727
+ systemPromptAppend: string;
728
+ settings: WorkflowExtensionSettings;
729
+ }
730
+ export interface AgentPreparationContext {
731
+ readonly options: Readonly<AgentOptions>;
732
+ readonly cwd: string;
733
+ /** Launch project root that owns project configuration; differs from `cwd` inside worktree scopes. Optional for older hosts. */
734
+ readonly projectCwd?: string;
735
+ readonly agentDir: string;
736
+ readonly projectTrusted: boolean;
737
+ /** `dynamicModelAliasNames` lists the `modelAliases` entries resolved by extensions rather than read from static settings. */
738
+ readonly defaults: Readonly<{
739
+ model: ModelSpec;
740
+ modelAliases: Readonly<Record<string, string>>;
741
+ dynamicModelAliasNames?: readonly string[];
742
+ selectorSources: AgentResourceSelectorSources;
743
+ settings: Readonly<WorkflowExtensionSettings>;
744
+ }>;
745
+ readonly capabilities: Readonly<{
746
+ tools: readonly string[];
747
+ skills: readonly string[];
748
+ extensions: readonly string[];
749
+ }>;
750
+ readonly knownModels: ReadonlySet<string>;
751
+ readonly availableModels: ReadonlySet<string>;
752
+ readonly signal: AbortSignal;
753
+ readonly mode: AgentInspectionMode;
754
+ }
755
+ export interface AgentPreparationHook {
756
+ priority?: number;
757
+ optionsSchema?: JsonSchema;
758
+ prepare: (configuration: AgentPreparation, context: Readonly<AgentPreparationContext>) => void | Promise<void>;
759
+ }
760
+ /** `source` is the registering extension's module provenance, when it declared one. */
761
+ export interface RegisteredAgentPreparationHook {
762
+ name: string;
763
+ priority: number;
764
+ optionsSchema?: JsonSchema;
765
+ source?: string;
766
+ prepare: AgentPreparationHook["prepare"];
767
+ }
768
+ /**
769
+ * `excludeTools` holds the exact tool names the agent and its ancestors excluded, frozen with the configuration so setup and
770
+ * children apply them even when re-evaluated options change. It is absent only in configurations prepared before it existed, which cannot resume.
771
+ */
772
+ export interface PreparedAgentConfiguration extends Omit<AgentPreparation, "model"> {
773
+ model: ModelSpec;
774
+ projectTrusted: boolean;
775
+ excludeTools?: string[];
776
+ }
710
777
  export interface AgentSetupHook {
711
778
  priority?: number;
712
779
  setup: (agent: AgentSetup, context: Readonly<AgentSetupContext>) => void | Promise<void>;
@@ -725,11 +792,6 @@ export interface WorkflowFunctionSource {
725
792
  readonly export: string;
726
793
  readonly dependencies: readonly string[];
727
794
  }
728
- export interface WorkflowRoleDirectoryRegistration {
729
- path: string;
730
- extension: WorkflowExtensionMetadata;
731
- readonly builtin?: true;
732
- }
733
795
  export interface AgentAttemptActionUi {
734
796
  notify(message: string, level?: "info" | "warning" | "error"): void;
735
797
  confirm(title: string, message: string): Promise<boolean>;
@@ -779,9 +841,9 @@ export interface WorkflowExtension extends WorkflowExtensionMetadata {
779
841
  validateSettings?: WorkflowExtensionSettingsValidator;
780
842
  functions?: Readonly<Record<string, WorkflowFunction>>;
781
843
  modelAliases?: Readonly<Record<string, WorkflowModelAlias>>;
844
+ agentPreparationHooks?: Readonly<Record<string, AgentPreparationHook>>;
782
845
  agentSetupHooks?: Readonly<Record<string, AgentSetupHook>>;
783
846
  agentAttemptActions?: Readonly<Record<string, AgentAttemptAction>>;
784
- roleDirectories?: readonly (string | URL)[];
785
847
  }
786
848
  export interface WorkflowJournal {
787
849
  get(path: string): JsonValue | undefined;
@@ -795,7 +857,6 @@ export declare class WorkflowError extends Error {
795
857
  export interface WorkflowFailureAgent {
796
858
  id: string;
797
859
  label?: string;
798
- role?: string;
799
860
  structuralPath: readonly string[];
800
861
  attempt: number;
801
862
  transport?: string;
@@ -804,7 +865,6 @@ export interface WorkflowFailureAgent {
804
865
  export interface WorkflowSiblingAgent {
805
866
  id: string;
806
867
  label?: string;
807
- role?: string;
808
868
  structuralPath: readonly string[];
809
869
  }
810
870
  export interface WorkflowFailureDiagnostics {
@@ -893,7 +953,6 @@ export interface StaticWorkflowCall {
893
953
  prompt: string | null;
894
954
  model: string | null;
895
955
  label?: string | null;
896
- role: string | null;
897
956
  retries?: number | null;
898
957
  outputSchema?: JsonSchema | null;
899
958
  options?: Readonly<Record<string, JsonValue>> | null;
@@ -980,8 +1039,5 @@ export interface WorkflowValidationContext {
980
1039
  export interface ValidatedWorkflowLaunch {
981
1040
  script: string;
982
1041
  checked: PreflightResult;
983
- agentDefinitions: Readonly<Record<string, AgentDefinition>>;
984
- projectAgentDefinitions: Readonly<Record<string, AgentDefinition>>;
985
- roleNames: readonly string[];
986
1042
  }
987
1043
  export {};
package/dist/src/types.js CHANGED
@@ -17,18 +17,15 @@ export const WORKFLOW_BUDGET_EVENT = "workflow:budget-event";
17
17
  export const WORKFLOW_WORKTREE_CREATED_EVENT = "workflow:worktree-created";
18
18
  export const WORKFLOW_BLOCKED_EVENT = "workflow:blocked";
19
19
  export const ERROR_CODES = [
20
- "CONFIG_ERROR", "INVALID_SETTINGS", "INVALID_SYNTAX", "INVALID_METADATA", "DUPLICATE_NAME", "INVALID_SCHEMA", "UNKNOWN_MODEL", "UNKNOWN_TOOL", "UNKNOWN_AGENT_TYPE",
20
+ "CONFIG_ERROR", "INVALID_SETTINGS", "INVALID_SYNTAX", "INVALID_METADATA", "DUPLICATE_NAME", "INVALID_SCHEMA", "UNKNOWN_MODEL", "UNKNOWN_TOOL", "UNKNOWN_AGENT",
21
21
  "RUN_OWNED", "RUN_NOT_FOUND", "REGISTRY_FROZEN", "GLOBAL_COLLISION", "MISSING_WORKFLOW", "RPC_LIMIT_EXCEEDED", "SHELL_FAILED", "AGENT_TIMEOUT", "AGENT_FAILED", "AGENT_RESULT_COLLECTED", "RESULT_INVALID",
22
22
  "TOOL_FAILED", "CANCELLED", "WORKER_UNRESPONSIVE", "WORKTREE_FAILED", "RESUME_INCOMPATIBLE", "BUDGET_EXHAUSTED", "INTERNAL_ERROR",
23
23
  ];
24
24
  export const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
25
- export function roleNameOf(value) {
26
- return typeof value === "string" ? value : undefined;
27
- }
28
- export const BUDGET_DIMENSIONS = ["tokens", "costUsd", "durationMs", "agentLaunches"];
29
- export const BUDGET_EVENT_TYPES = ["soft_crossed", "hard_overrun", "hard_exhausted", "adjustment_requested", "adjustment_approved", "adjustment_rejected"];
30
25
  export const CONTEXT_FILE_SCOPES = ["global", "project", "cwd"];
31
26
  export function isContextFileScope(value) { return CONTEXT_FILE_SCOPES.some((scope) => scope === value); }
27
+ export const BUDGET_DIMENSIONS = ["tokens", "costUsd", "durationMs", "agentLaunches"];
28
+ export const BUDGET_EVENT_TYPES = ["soft_crossed", "hard_overrun", "hard_exhausted", "adjustment_requested", "adjustment_approved", "adjustment_rejected"];
32
29
  export const WORKFLOW_AGENT_STALL_THRESHOLD_MS = 10 * 60 * 1000;
33
30
  export function zeroAccounting() { return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 }; }
34
31
  export function addAccounting(left, right) { return { input: left.input + right.input, output: left.output + right.output, cacheRead: left.cacheRead + right.cacheRead, cacheWrite: left.cacheWrite + right.cacheWrite, cost: left.cost + right.cost }; }
@@ -38,7 +35,7 @@ export function sumAccounting(values) {
38
35
  total = addAccounting(total, value);
39
36
  return total;
40
37
  }
41
- export const LAUNCH_SNAPSHOT_IDENTITY_VERSION = 5;
38
+ export const LAUNCH_SNAPSHOT_IDENTITY_VERSION = 6;
42
39
  export function defineWorkflowFunction(workflowFunction) { return workflowFunction; }
43
40
  // The brand keeps instanceof working across the bundled extension entries, which each inline their own copy of this class.
44
41
  const WORKFLOW_ERROR_BRAND = Symbol.for("pi-extensible-workflows.workflow-error");
@@ -1,4 +1,5 @@
1
- import { WorkflowError, type JsonSchema, type JsonValue, type ModelSpec, type ThinkingLevel, type WorkflowErrorCode, type WorkflowExtensionSettings } from "./types.js";
1
+ import { WorkflowError, type JsonSchema, type JsonValue, type ModelSpec, type WorkflowErrorCode, type WorkflowExtensionSettings } from "./types.js";
2
+ import { type ThinkingLevel } from "./types.js";
2
3
  export declare class SerialLane {
3
4
  #private;
4
5
  run<T>(task: () => Promise<T>): Promise<T>;
@@ -46,6 +47,7 @@ export declare function modelAliasName(value: string, aliases: Readonly<Record<s
46
47
  export declare function validateModelAliases(value: unknown, settingsPath?: string): Readonly<Record<string, string>>;
47
48
  export declare function unknownModel(value: string, target: string | undefined, settingsPath?: string): never;
48
49
  export declare function resolveModelReference(value: string, aliases?: Readonly<Record<string, string>>, knownModels?: ReadonlySet<string>, settingsPath?: string): ModelSpec;
50
+ export declare function modelCapability(value: string | ModelSpec, aliases?: Readonly<Record<string, string>>, knownModels?: ReadonlySet<string>, settingsPath?: string): string;
49
51
  type ToolSource = {
50
52
  getActiveTools(): string[];
51
53
  getAllTools?(): readonly {
@@ -63,7 +65,6 @@ export declare function reachableTools(pi: ToolSource): string[];
63
65
  export declare const VIRTUAL_MODEL_PROVIDER = "workflow";
64
66
  /** Child sessions do not load the workflow extension, so they receive the alias target instead of its virtual model. */
65
67
  export declare function physicalModel(spec: ModelSpec, aliases?: Readonly<Record<string, string>>, knownModels?: ReadonlySet<string>, settingsPath?: string): ModelSpec;
66
- export declare function modelCapability(value: string | ModelSpec, aliases?: Readonly<Record<string, string>>, knownModels?: ReadonlySet<string>, settingsPath?: string): string;
67
68
  export declare function aliasDrift(previous: Readonly<Record<string, string>>, current: Readonly<Record<string, string>>): string[];
68
69
  export declare function validateResourcePattern(pattern: string): void;
69
70
  export declare function resourcePatternMatches(resource: string, pattern: string): boolean;