@marcoscale98/pi-extensible-workflows 5.17.0-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 (128) hide show
  1. package/CHANGELOG.md +145 -0
  2. package/README.md +2 -2
  3. package/dist/src/agent-execution.d.ts +43 -10
  4. package/dist/src/agent-execution.js +442 -162
  5. package/dist/src/background-widget.d.ts +5 -1
  6. package/dist/src/background-widget.js +5 -10
  7. package/dist/src/decoders.d.ts +2 -3
  8. package/dist/src/decoders.js +59 -37
  9. package/dist/src/execution.d.ts +6 -2
  10. package/dist/src/execution.js +48 -7
  11. package/dist/src/host-delivery.js +5 -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 +11 -8
  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 +6 -1
  18. package/dist/src/host-view.js +46 -20
  19. package/dist/src/host.d.ts +2 -2
  20. package/dist/src/host.js +246 -118
  21. package/dist/src/index.d.ts +1 -2
  22. package/dist/src/index.js +1985 -1690
  23. package/dist/src/index.js.map +3 -3
  24. package/dist/src/paths.d.ts +8 -5
  25. package/dist/src/paths.js +24 -13
  26. package/dist/src/persistence.d.ts +1 -0
  27. package/dist/src/persistence.js +1 -0
  28. package/dist/src/pi-runtime-runner.js +4 -1
  29. package/dist/src/registry.d.ts +9 -7
  30. package/dist/src/registry.js +29 -71
  31. package/dist/src/runtime/agent-runner.d.ts +2 -0
  32. package/dist/src/script-tools.d.ts +27 -0
  33. package/dist/src/script-tools.js +87 -0
  34. package/dist/src/session-lease.d.ts +1 -1
  35. package/dist/src/session-lease.js +45 -11
  36. package/dist/src/settings.d.ts +19 -3
  37. package/dist/src/settings.js +63 -50
  38. package/dist/src/store.d.ts +3 -1
  39. package/dist/src/store.js +17 -1
  40. package/dist/src/trajectory.d.ts +12 -3
  41. package/dist/src/trajectory.js +32 -11
  42. package/dist/src/types.d.ts +129 -45
  43. package/dist/src/types.js +5 -8
  44. package/dist/src/utils.d.ts +21 -1
  45. package/dist/src/utils.js +46 -6
  46. package/dist/src/validation.d.ts +14 -3
  47. package/dist/src/validation.js +143 -87
  48. package/dist/starter/index.js +8 -11
  49. package/dist/starter/index.js.map +1 -1
  50. package/dist/starter/review-loop.d.ts +0 -13
  51. package/dist/starter/review-loop.js +8 -9
  52. package/dist/subagents/index.js +904 -956
  53. package/dist/subagents/index.js.map +3 -3
  54. package/dist/subagents/src/contracts.d.ts +48 -31
  55. package/dist/subagents/src/contracts.js +20 -9
  56. package/dist/subagents/src/index.d.ts +1 -1
  57. package/dist/subagents/src/index.js +14 -8
  58. package/dist/subagents/src/manager.js +52 -73
  59. package/dist/subagents/src/navigator.js +3 -14
  60. package/dist/subagents/src/view.d.ts +1 -1
  61. package/dist/subagents/src/view.js +15 -68
  62. package/dist/subagents/src/worktree.js +1 -1
  63. package/dist/trajectory/assets/index.html +35 -13
  64. package/dist/trajectory/index.js +576 -932
  65. package/dist/trajectory/index.js.map +3 -3
  66. package/dist/trajectory/src/assets/index.html +35 -13
  67. package/dist/trajectory/src/index.js +134 -104
  68. package/dist/trajectory/src/server.js +268 -27
  69. package/dist/trajectory/src/server.js.map +3 -3
  70. package/dist/trajectory/src/startup-mutex.d.ts +17 -0
  71. package/dist/trajectory/src/startup-mutex.js +172 -0
  72. package/examples/workflow-extension-template/README.md +4 -7
  73. package/examples/workflow-extension-template/extension.test.mjs +4 -8
  74. package/examples/workflow-extension-template/index.js +0 -3
  75. package/package.json +10 -10
  76. package/skills/pi-extensible-workflows/SKILL.md +12 -8
  77. package/src/agent-execution.ts +412 -164
  78. package/src/background-widget.ts +5 -11
  79. package/src/decoders.ts +51 -37
  80. package/src/execution.ts +46 -9
  81. package/src/host-delivery.ts +5 -8
  82. package/src/host-navigator.ts +4 -2
  83. package/src/host-phases.ts +1 -1
  84. package/src/host-recovery.ts +23 -28
  85. package/src/host-runtime.ts +44 -6
  86. package/src/host-view.ts +41 -16
  87. package/src/host.ts +229 -142
  88. package/src/index.ts +1 -2
  89. package/src/paths.ts +18 -9
  90. package/src/persistence.ts +1 -0
  91. package/src/pi-runtime-runner.ts +3 -1
  92. package/src/registry.ts +28 -64
  93. package/src/runtime/agent-runner.ts +2 -0
  94. package/src/script-tools.ts +76 -0
  95. package/src/session-lease.ts +34 -6
  96. package/src/settings.ts +56 -50
  97. package/src/store.ts +18 -2
  98. package/src/trajectory.ts +32 -15
  99. package/src/types.ts +82 -34
  100. package/src/utils.ts +42 -5
  101. package/src/validation.ts +121 -80
  102. package/starter/index.ts +0 -1
  103. package/starter/review-loop.ts +8 -9
  104. package/starter/roles/developer.md +0 -1
  105. package/starter/roles/oracle.md +0 -1
  106. package/starter/roles/researcher.md +0 -1
  107. package/starter/roles/reviewer.md +0 -1
  108. package/starter/roles/scout.md +0 -1
  109. package/subagents/README.md +10 -16
  110. package/subagents/src/contracts.ts +21 -11
  111. package/subagents/src/index.ts +17 -8
  112. package/subagents/src/manager.ts +48 -128
  113. package/subagents/src/navigator.ts +4 -13
  114. package/subagents/src/view.ts +16 -63
  115. package/subagents/src/worktree.ts +1 -1
  116. package/trajectory/src/assets/index.html +35 -13
  117. package/trajectory/src/index.ts +112 -91
  118. package/trajectory/src/server.ts +46 -10
  119. package/trajectory/src/startup-mutex.ts +127 -0
  120. package/dist/src/roles.d.ts +0 -70
  121. package/dist/src/roles.js +0 -325
  122. package/dist/starter/roles/developer.md +0 -6
  123. package/dist/starter/roles/oracle.md +0 -18
  124. package/dist/starter/roles/researcher.md +0 -20
  125. package/dist/starter/roles/reviewer.md +0 -19
  126. package/dist/starter/roles/scout.md +0 -18
  127. package/examples/workflow-extension-template/roles/reviewer.md +0 -4
  128. package/src/roles.ts +0 -326
package/dist/src/roles.js DELETED
@@ -1,325 +0,0 @@
1
- import { readFileSync, readdirSync, statSync } from "node:fs";
2
- import { basename, dirname, extname, join, resolve } from "node:path";
3
- import { getAgentDir, parseFrontmatter } from "@earendil-works/pi-coding-agent";
4
- import { registeredWorkflowRoleDirectoryRegistrations } from "./registry.js";
5
- import { resolveWorkflowSettings, validateContextFileScopes, validateSelectorList, validateWorkflowExtensionSettings, workflowSettingsPath } from "./settings.js";
6
- import { assertModelThinking, deepFreeze, object, errorText, fail, isNodeError, modelAliasName, modelCapability, resourcePatternHasMagic, resolveModelReference, selectResourcesByLayers, unmatchedResourcePatterns } from "./utils.js";
7
- import { canonicalPath } from "./paths.js";
8
- const ROLE_DIRECTORY = "pi-extensible-workflows";
9
- // Preserve the role-file base when a discovered definition is resolved again through the public API.
10
- const roleDefinitionPaths = new WeakMap();
11
- export function parseRoleMarkdown(content, strict = false, rolePath) {
12
- if (!strict) {
13
- if (!content.startsWith("---\n"))
14
- return { prompt: content };
15
- const end = content.indexOf("\n---", 4);
16
- if (end < 0)
17
- return { prompt: content };
18
- const meta = {};
19
- for (const line of content.slice(4, end).split("\n")) {
20
- const match = /^(model|tools|skills|extensions|description|overrideSystemPrompt|override_system_prompt|is_system_prompt|contextFiles|extensionSettings|disabledAgentResources|thinking)\s*:\s*(.+)$/.exec(line.trim());
21
- if (match?.[1] === "disabledAgentResources")
22
- fail("INVALID_METADATA", "disabledAgentResources is no longer supported; use skills, extensions, and tools selectors");
23
- if (match?.[1] === "thinking")
24
- fail("INVALID_METADATA", "Role thinking is not supported; put it on model as provider/model:thinking");
25
- if (match?.[1] && match[2])
26
- meta[match[1]] = match[2].trim();
27
- }
28
- const unquote = (v) => v.replace(/^['"]|['"]$/g, "");
29
- const parseList = (value) => value === undefined ? undefined : value.replace(/^\[|\]$/g, "").split(",").map((entry) => unquote(entry.trim())).filter(Boolean);
30
- const tools = parseList(meta.tools);
31
- const skills = parseList(meta.skills);
32
- const extensions = parseList(meta.extensions);
33
- let extensionSettings;
34
- if (meta.extensionSettings !== undefined) {
35
- try {
36
- extensionSettings = JSON.parse(meta.extensionSettings);
37
- }
38
- catch (error) {
39
- fail("INVALID_METADATA", `Invalid role extensionSettings: ${errorText(error)}`);
40
- }
41
- }
42
- const rolePathValue = rolePath ?? "<role>";
43
- const normalizedExtensionSettings = validateWorkflowExtensionSettings(extensionSettings, rolePathValue, "INVALID_METADATA");
44
- const definition = { prompt: content.slice(end + 4).replace(/^\n/, "") };
45
- if (meta.model) {
46
- const model = unquote(meta.model);
47
- assertModelThinking(model, "Role model");
48
- definition.model = model;
49
- }
50
- if (meta.description)
51
- definition.description = unquote(meta.description);
52
- if (tools)
53
- definition.tools = tools;
54
- if (skills)
55
- definition.skills = skills;
56
- if (extensions)
57
- definition.extensions = extensions;
58
- if (normalizedExtensionSettings !== undefined)
59
- definition.extensionSettings = normalizedExtensionSettings;
60
- const overrideSystemPrompt = meta.overrideSystemPrompt ?? meta.override_system_prompt ?? meta.is_system_prompt;
61
- const contextFiles = meta.contextFiles ? meta.contextFiles.replace(/^\[|\]$/g, "").split(",").map((scope) => unquote(scope.trim())).filter(Boolean) : undefined;
62
- const normalizedContextFiles = validateContextFileScopes(contextFiles, "role");
63
- if (overrideSystemPrompt)
64
- definition.overrideSystemPrompt = overrideSystemPrompt === "true";
65
- if (normalizedContextFiles)
66
- definition.contextFiles = normalizedContextFiles;
67
- return definition;
68
- }
69
- const normalized = content.replace(/\r\n?/g, "\n");
70
- if (normalized.startsWith("---\n") && normalized.indexOf("\n---", 3) < 0)
71
- fail("INVALID_METADATA", "Role frontmatter is missing its closing delimiter");
72
- let parsed;
73
- try {
74
- parsed = parseFrontmatter(content);
75
- }
76
- catch (error) {
77
- fail("INVALID_METADATA", `Invalid role frontmatter: ${errorText(error)}`);
78
- }
79
- if (!object(parsed.frontmatter))
80
- fail("INVALID_METADATA", "Role frontmatter must be an object");
81
- const { model, tools, skills, extensions, extensionSettings, description, contextFiles } = parsed.frontmatter;
82
- if (Object.prototype.hasOwnProperty.call(parsed.frontmatter, "disabledAgentResources"))
83
- fail("INVALID_METADATA", "disabledAgentResources is no longer supported; use skills, extensions, and tools selectors");
84
- if (Object.prototype.hasOwnProperty.call(parsed.frontmatter, "thinking"))
85
- fail("INVALID_METADATA", "Role thinking is not supported; put it on model as provider/model:thinking");
86
- const overrideSystemPrompt = parsed.frontmatter.overrideSystemPrompt ?? parsed.frontmatter.override_system_prompt ?? parsed.frontmatter.is_system_prompt;
87
- if (model !== undefined && (typeof model !== "string" || model.trim() === ""))
88
- fail("INVALID_METADATA", "Role model must be a non-empty string");
89
- if (description !== undefined && (typeof description !== "string" || description.trim() === "" || description.length > 1024 || /[\r\n]/.test(description)))
90
- fail("INVALID_METADATA", "Role description must be a non-empty single-line string of at most 1024 characters");
91
- if (overrideSystemPrompt !== undefined && typeof overrideSystemPrompt !== "boolean")
92
- fail("INVALID_METADATA", "Role overrideSystemPrompt must be a boolean");
93
- const normalizedContextFiles = validateContextFileScopes(contextFiles, rolePath ?? "<role>");
94
- const rolePathValue = rolePath ?? "<role>";
95
- const normalizedTools = validateSelectorList(tools, rolePathValue, "tools", "INVALID_METADATA");
96
- const normalizedSkills = validateSelectorList(skills, rolePathValue, "skills", "INVALID_METADATA");
97
- const normalizedExtensions = validateSelectorList(extensions, rolePathValue, "extensions", "INVALID_METADATA");
98
- const normalizedExtensionSettings = validateWorkflowExtensionSettings(extensionSettings, rolePathValue, "INVALID_METADATA");
99
- const normalizedDescription = typeof description === "string" ? description.trim() : undefined;
100
- const normalizedModel = typeof model === "string" ? model.trim() : undefined;
101
- if (normalizedModel !== undefined)
102
- assertModelThinking(normalizedModel, "Role model");
103
- const definition = { prompt: parsed.body };
104
- if (normalizedDescription !== undefined)
105
- definition.description = normalizedDescription;
106
- if (normalizedModel !== undefined)
107
- definition.model = normalizedModel;
108
- if (normalizedTools !== undefined)
109
- definition.tools = normalizedTools;
110
- if (normalizedSkills !== undefined)
111
- definition.skills = normalizedSkills;
112
- if (normalizedExtensions !== undefined)
113
- definition.extensions = normalizedExtensions;
114
- if (normalizedExtensionSettings !== undefined)
115
- definition.extensionSettings = normalizedExtensionSettings;
116
- if (typeof overrideSystemPrompt === "boolean")
117
- definition.overrideSystemPrompt = overrideSystemPrompt;
118
- if (normalizedContextFiles !== undefined)
119
- definition.contextFiles = normalizedContextFiles;
120
- return definition;
121
- }
122
- export function workflowRoleDirectories(agentDir = getAgentDir()) {
123
- return [join(agentDir, ROLE_DIRECTORY, "roles")];
124
- }
125
- function projectRoleDirectories(root) {
126
- return [join(root, ROLE_DIRECTORY, "roles")];
127
- }
128
- function roleDirectorySources(dirs) {
129
- const seen = new Set();
130
- return dirs.flatMap((value) => {
131
- const source = typeof value === "string" ? { path: value } : { path: value.path, extension: value.extension, ...(value.builtin === true ? { builtin: true } : {}) };
132
- if (seen.has(source.path))
133
- return [];
134
- seen.add(source.path);
135
- return [source];
136
- });
137
- }
138
- function roleDirectoryLabel(source, extension = true) {
139
- return source.extension ? `Extension "${source.extension.headline}" (${source.extension.version})` : extension ? "Registered workflow extension" : "Standard workflow";
140
- }
141
- function isRoleFile(dir, entry) {
142
- if (extname(entry.name) !== ".md")
143
- return false;
144
- if (entry.isFile())
145
- return true;
146
- if (!entry.isSymbolicLink())
147
- return false;
148
- try {
149
- return statSync(join(dir, entry.name)).isFile();
150
- }
151
- catch (error) {
152
- if (isNodeError(error, "ENOENT"))
153
- return false;
154
- throw error;
155
- }
156
- }
157
- function scanRoleFiles(dirs, extension) {
158
- const files = [];
159
- for (const source of roleDirectorySources(dirs)) {
160
- let entries;
161
- try {
162
- entries = readdirSync(source.path, { withFileTypes: true });
163
- }
164
- catch (error) {
165
- if (!extension && isNodeError(error, "ENOENT"))
166
- continue;
167
- fail("INVALID_METADATA", `${roleDirectoryLabel(source, extension)} role directory "${source.path}" could not be scanned: ${errorText(error)}`);
168
- }
169
- for (const entry of entries)
170
- if (isRoleFile(source.path, entry))
171
- files.push({ name: basename(entry.name, ".md"), path: join(source.path, entry.name), source });
172
- }
173
- return files.sort((left, right) => left.name.localeCompare(right.name) || left.path.localeCompare(right.path));
174
- }
175
- function roleEntries(dirs, extension) {
176
- const files = scanRoleFiles(dirs, extension);
177
- const starterFiles = files.filter(({ source }) => source.builtin === true);
178
- const regularFiles = files.filter(({ source }) => source.builtin !== true);
179
- if (extension) {
180
- const byName = new Map();
181
- for (const file of regularFiles)
182
- byName.set(file.name, [...(byName.get(file.name) ?? []), file]);
183
- for (const [name, matches] of byName)
184
- if (matches.length > 1)
185
- fail("INVALID_METADATA", `Duplicate extension role "${name}": ${matches.map(({ path, source }) => `${roleDirectoryLabel(source)} role directory "${source.path}" (${path})`).join("; ")}`);
186
- }
187
- const read = (roleFiles) => Object.fromEntries(roleFiles.map(({ name, path, source }) => {
188
- try {
189
- const definition = parseRoleMarkdown(readFileSync(path, "utf8"), true, path);
190
- roleDefinitionPaths.set(definition, path);
191
- return [name, { name, path, source, definition }];
192
- }
193
- catch (error) {
194
- if (extension)
195
- fail("INVALID_METADATA", `${roleDirectoryLabel(source)} role directory "${source.path}" contains invalid role "${name}" at "${path}": ${errorText(error)}`);
196
- throw error;
197
- }
198
- }));
199
- return extension ? { ...read(starterFiles), ...read(regularFiles) } : read(files);
200
- }
201
- function discoveryInput(input) {
202
- return { cwd: input.cwd, agentDir: input.agentDir ?? getAgentDir(), projectTrusted: input.projectTrusted ?? true, extensionRoleDirectories: input.extensionRoleDirectories ?? registeredWorkflowRoleDirectoryRegistrations() };
203
- }
204
- function discoveredRoleEntries(input) {
205
- const resolved = discoveryInput(input);
206
- return {
207
- ...roleEntries(resolved.extensionRoleDirectories, true),
208
- ...roleEntries(workflowRoleDirectories(resolved.agentDir), false),
209
- ...(resolved.projectTrusted ? roleEntries(projectRoleDirectories(join(resolved.cwd, ".pi")), false) : {}),
210
- };
211
- }
212
- export function loadProjectAgentDefinitions(cwd) {
213
- return deepFreeze(Object.fromEntries(Object.entries(roleEntries(projectRoleDirectories(join(cwd, ".pi")), false)).map(([name, entry]) => [name, entry.definition])));
214
- }
215
- export function discoverRoles(input) {
216
- return deepFreeze(Object.fromEntries(Object.entries(discoveredRoleEntries(input)).map(([name, entry]) => [name, entry.definition])));
217
- }
218
- export function loadRole(name, input) {
219
- const entry = discoveredRoleEntries(input)[name];
220
- if (!entry)
221
- fail("UNKNOWN_AGENT_TYPE", `Unknown agent role: ${name}`);
222
- return entry.definition;
223
- }
224
- export function loadAgentDefinitions(cwd, agentDir = getAgentDir(), projectTrusted = true, extensionRoleDirectories = registeredWorkflowRoleDirectoryRegistrations()) {
225
- return discoverRoles({ cwd, agentDir, projectTrusted, extensionRoleDirectories });
226
- }
227
- export function canonicalExtensionSelector(selector, base = process.cwd()) {
228
- const negated = selector.startsWith("!");
229
- const body = negated ? selector.slice(1) : selector;
230
- if (body === "*" || body === "**" || body.startsWith("**/"))
231
- return selector;
232
- const resolved = resolve(base, body);
233
- if (resourcePatternHasMagic(body))
234
- return `${negated ? "!" : ""}${resolved}`;
235
- return `${negated ? "!" : ""}${canonicalPath(resolved)}`;
236
- }
237
- function selectorsFromSettings(settings) {
238
- return { ...(settings.skills === undefined ? {} : { skills: settings.skills }), ...(settings.extensions === undefined ? {} : { extensions: settings.extensions }), ...(settings.tools === undefined ? {} : { tools: settings.tools }) };
239
- }
240
- function rootToolNames(value) {
241
- return value === undefined ? undefined : value instanceof Set ? [...value] : [...value];
242
- }
243
- function roleDefinitionFor(name, options) {
244
- if (name === undefined)
245
- return {};
246
- if (options.definition !== undefined) {
247
- const path = roleDefinitionPaths.get(options.definition);
248
- return { definition: options.definition, ...(path === undefined ? {} : { path }) };
249
- }
250
- if (options.definitions?.[name] !== undefined) {
251
- const definition = options.definitions[name];
252
- const path = roleDefinitionPaths.get(definition);
253
- return { definition, ...(path === undefined ? {} : { path }) };
254
- }
255
- const entries = discoveredRoleEntries(options);
256
- const entry = entries[name];
257
- if (!entry)
258
- fail("UNKNOWN_AGENT_TYPE", `Unknown agent role: ${name}`);
259
- return entry;
260
- }
261
- /** Without a supplied root/tool/resource boundary, this API reports selector layers but does not infer available resources; tools and model remain undefined when no candidates are supplied. When selector sources are supplied, model aliases default to none and blocked aliases are not applied unless provided. */
262
- export function resolveRole(name, options) {
263
- const { definition, path } = roleDefinitionFor(name, options);
264
- const settings = options.selectorSources === undefined ? resolveWorkflowSettings(options.cwd, options.projectTrusted ?? true, options.settingsPath ?? workflowSettingsPath(options.agentDir ?? getAgentDir())) : undefined;
265
- const baseSources = options.selectorSources ?? { global: selectorsFromSettings(settings?.global ?? {}), project: selectorsFromSettings(settings?.project ?? {}) };
266
- const canonicalSources = (sources) => ({
267
- ...sources,
268
- global: { ...sources.global, ...(sources.global.extensions === undefined ? {} : { extensions: sources.global.extensions.map((selector) => canonicalExtensionSelector(selector, options.cwd)) }) },
269
- project: { ...sources.project, ...(sources.project.extensions === undefined ? {} : { extensions: sources.project.extensions.map((selector) => canonicalExtensionSelector(selector, options.cwd)) }) },
270
- ...(sources.role === undefined ? {} : { role: { ...sources.role, ...(sources.role.extensions === undefined ? {} : { extensions: sources.role.extensions.map((selector) => canonicalExtensionSelector(selector, options.cwd)) }) } }),
271
- ...(sources.call === undefined ? {} : { call: { ...sources.call, ...(sources.call.extensions === undefined ? {} : { extensions: sources.call.extensions.map((selector) => canonicalExtensionSelector(selector, options.cwd)) }) } }),
272
- });
273
- const roleLayer = definition?.skills !== undefined || definition?.extensions !== undefined || definition?.tools !== undefined ? { ...(definition.skills === undefined ? {} : { skills: definition.skills }), ...(definition.extensions === undefined ? {} : { extensions: definition.extensions.map((selector) => canonicalExtensionSelector(selector, path ? dirname(path) : options.cwd)) }), ...(definition.tools === undefined ? {} : { tools: definition.tools }) } : baseSources.role;
274
- const callLayer = options.skills !== undefined || options.extensions !== undefined || options.tools !== undefined ? { ...(options.skills === undefined ? {} : { skills: options.skills }), ...(options.extensions === undefined ? {} : { extensions: options.extensions.map((selector) => canonicalExtensionSelector(selector, options.cwd)) }), ...(options.tools === undefined ? {} : { tools: options.tools }) } : baseSources.call;
275
- const selectorSources = canonicalSources({ global: baseSources.global, project: baseSources.project, ...(roleLayer === undefined ? {} : { role: roleLayer }), ...(callLayer === undefined ? {} : { call: callLayer }) });
276
- const callSelectors = selectorSources.call;
277
- const roleSelectors = selectorSources.role;
278
- const selectorLayers = {
279
- skills: [selectorSources.global.skills, selectorSources.project.skills, roleSelectors?.skills, callSelectors?.skills],
280
- extensions: [selectorSources.global.extensions, selectorSources.project.extensions, roleSelectors?.extensions, callSelectors?.extensions],
281
- tools: [selectorSources.global.tools, selectorSources.project.tools, roleSelectors?.tools, callSelectors?.tools],
282
- };
283
- const resources = options.resources ?? {};
284
- const candidateTools = options.inheritedTools ?? rootToolNames(options.rootTools) ?? resources.tools;
285
- const tools = options.effectiveTools ?? (candidateTools === undefined ? undefined : selectResourcesByLayers(selectorLayers.tools, candidateTools));
286
- const rootTools = rootToolNames(options.rootTools);
287
- if (rootTools !== undefined) {
288
- const outsideEffectiveTool = options.effectiveTools?.find((tool) => !candidateTools?.includes(tool));
289
- if (outsideEffectiveTool)
290
- fail("UNKNOWN_TOOL", `Tool is outside the launching session boundary: ${outsideEffectiveTool}`);
291
- const outsideCallTool = (options.tools ?? []).find((tool) => !tool.startsWith("!") && !resourcePatternHasMagic(tool) && !candidateTools?.includes(tool));
292
- if (outsideCallTool)
293
- fail("UNKNOWN_TOOL", `Tool is outside the launching session boundary: ${outsideCallTool}`);
294
- const outsideRootTool = tools?.find((tool) => !rootTools.includes(tool));
295
- if (outsideRootTool)
296
- fail("UNKNOWN_TOOL", `Tool is outside the launching session boundary: ${outsideRootTool}`);
297
- }
298
- const selectedSkills = resources.skills === undefined ? undefined : selectResourcesByLayers(selectorLayers.skills, resources.skills);
299
- const extensionResources = resources.extensions?.map((extension) => canonicalPath(extension));
300
- const selectedExtensions = extensionResources === undefined ? undefined : selectResourcesByLayers(selectorLayers.extensions, extensionResources);
301
- const unmatchedSkills = resources.skills === undefined ? undefined : unmatchedResourcePatterns(selectorLayers.skills.flatMap((layer) => layer ?? []), resources.skills);
302
- const unmatchedExtensions = extensionResources === undefined ? undefined : unmatchedResourcePatterns(selectorLayers.extensions.flatMap((layer) => layer ?? []), extensionResources);
303
- const unmatchedTools = candidateTools === undefined ? undefined : unmatchedResourcePatterns(selectorLayers.tools.flatMap((layer) => layer ?? []), candidateTools);
304
- const aliases = options.modelAliases ?? settings?.effective.modelAliases ?? {};
305
- const requestedModel = options.model ?? (definition?.model && definition.thinking && !definition.model.includes(":") ? `${definition.model}:${definition.thinking}` : definition?.model);
306
- const blockedAlias = requestedModel?.split(":", 1)[0];
307
- if (requestedModel !== undefined && blockedAlias && options.blockedAliases?.has(blockedAlias) && !modelAliasName(requestedModel, aliases)) {
308
- const target = options.blockedAliasTargets?.[blockedAlias];
309
- fail("UNKNOWN_MODEL", `Unknown model alias ${requestedModel}${target ? ` resolved to ${target}` : ""}${options.settingsPath ? ` (settings: ${options.settingsPath})` : ""}`);
310
- }
311
- let model = options.modelOverride;
312
- if (model === undefined && requestedModel !== undefined) {
313
- assertModelThinking(requestedModel);
314
- model = resolveModelReference(requestedModel, aliases, options.knownModels ?? options.availableModels, options.settingsPath ?? settings?.sources.modelAliases);
315
- }
316
- if (model === undefined)
317
- model = options.rootModel;
318
- const availableModels = options.knownModels ?? options.availableModels ?? (options.rootModel === undefined ? undefined : new Set([modelCapability(options.rootModel)]));
319
- if (model !== undefined && availableModels !== undefined && !availableModels.has(modelCapability(model)))
320
- fail("UNKNOWN_MODEL", `Unknown model${requestedModel ? ` ${requestedModel} resolved to ${modelCapability(model)}` : ""}${options.settingsPath ? ` (settings: ${options.settingsPath})` : ""}`);
321
- const prompt = definition?.prompt ?? "";
322
- const overrideSystemPrompt = definition?.overrideSystemPrompt === true;
323
- const contextFiles = options.contextFiles ?? definition?.contextFiles;
324
- return { ...(name === undefined ? {} : { name }), ...(definition === undefined ? {} : { definition }), ...(model === undefined ? {} : { model }), ...(modelAliasName(requestedModel ?? "", aliases) && requestedModel ? { requestedModel } : {}), ...(tools === undefined ? {} : { tools }), prompt, overrideSystemPrompt, systemPrompt: { mode: overrideSystemPrompt ? "override" : "append", text: prompt }, ...(contextFiles === undefined ? {} : { contextFiles: [...contextFiles] }), ...(definition?.extensionSettings === undefined ? {} : { extensionSettings: definition.extensionSettings }), selectorSources, selectorLayers, ...(selectedSkills === undefined ? {} : { selectedSkills }), ...(selectedExtensions === undefined ? {} : { selectedExtensions }), ...(unmatchedSkills === undefined ? {} : { unmatchedSkills }), ...(unmatchedExtensions === undefined ? {} : { unmatchedExtensions }), ...(unmatchedTools === undefined ? {} : { unmatchedTools }) };
325
- }
@@ -1,6 +0,0 @@
1
- ---
2
- model: developer-model
3
- description: Developer focused agent
4
- ---
5
-
6
- Act as a senior developer. Implement the requested task with the smallest working change. Read the relevant flow first, reuse existing project patterns, keep the change surgical, and verify the result with the smallest relevant check.
@@ -1,18 +0,0 @@
1
- ---
2
- model: oracle-model
3
- tools: ["!*", "read", "grep", "find", "ls", "bash"]
4
- description: Oracle. Use for a second opinion on a plan, design, or decision before committing to it
5
- ---
6
-
7
- Give a second opinion on the presented plan, design, or decision. Do not edit files. You are not a second decision-maker; you challenge, verify, and report.
8
-
9
- Reconstruct the stated goals and constraints first, then verify the claims against the actual code, tests, and docs. Run read-only commands when they settle a question. When source contradicts the plan or its assumptions, trust source and report the conflict.
10
-
11
- Return:
12
-
13
- - The strongest challenge to the proposal, with evidence.
14
- - Hidden assumptions or contradictions you found.
15
- - What the proposal gets right and should keep.
16
- - A recommendation, naming any decision that still belongs to the caller.
17
-
18
- If the proposal is sound, say so plainly instead of inventing objections.
@@ -1,20 +0,0 @@
1
- ---
2
- model: researcher-model
3
- tools: ["!edit", "!write", "!bash"]
4
- description: Researcher. Use for deep research across the codebase, docs, and the web when web tools are available
5
- ---
6
-
7
- Research the requested question in depth. Do not edit files.
8
-
9
- Use every read and search capability you have: code, files, docs, and any web search or fetch tools present in this session. If the question needs web evidence and no web tool is available, say so explicitly instead of guessing.
10
-
11
- Verify claims against primary sources: the actual code, official docs, or the cited page. Prefer primary sources over aggregators.
12
-
13
- Return a research brief:
14
-
15
- - Direct answer to the question.
16
- - Evidence per claim, citing files and lines for code and URLs for web sources.
17
- - Contradictions or version-specific caveats you found.
18
- - What is known, what is uncertain, and what would settle the open questions.
19
-
20
- Report only what you verified. Mark everything else as unverified.
@@ -1,19 +0,0 @@
1
- ---
2
- model: reviewer-model
3
- tools: ["!*", "read", "grep", "find", "ls"]
4
- description: Reviewer. Use when we need to review decisions or code changes
5
- ---
6
-
7
- Inspect the requested change for correctness, missed callers, broken assumptions, regressions, security or data-loss risk, and missing verification. Do not edit files.
8
-
9
- Filter findings on evidence, not severity: report only concrete, current issues caused or made reachable by the change, backed by source proof, a failing test or repro, or a contract contradiction. Cite exact files and lines. Ignore style unless it hides a real defect. Do not report speculative or pre-existing issues unless asked.
10
-
11
- Label each finding:
12
-
13
- - P0: blocks merge (broken behavior, data loss, security).
14
- - P1: should be fixed before release.
15
- - P2: report-only note.
16
-
17
- If nothing qualifies, say exactly `No issues found.`
18
-
19
- End with one line: `Merge verdict: BLOCK`, `Merge verdict: OK`, or `Merge verdict: OK with notes`.
@@ -1,18 +0,0 @@
1
- ---
2
- model: scout-model
3
- tools: ["!*", "read", "grep", "find", "ls"]
4
- description: Scout. Use for fast read-only codebase recon before planning or implementing
5
- ---
6
-
7
- Perform fast, read-only reconnaissance of the codebase for the requested question. Do not edit files.
8
-
9
- Locate the relevant files, entry points, and data flow. Trace the actual code paths instead of inferring from names. Note existing patterns, helpers, and tests the task should reuse.
10
-
11
- Return a compact brief:
12
-
13
- - Relevant files with one-line purpose each.
14
- - How the flow works end to end, citing files and lines.
15
- - Existing patterns or utilities to reuse.
16
- - What is known, what is uncertain, and the smallest next step.
17
-
18
- Report only what you verified in the code. Mark anything unverified as an open question. Keep output concise; no implementation plan.
@@ -1,4 +0,0 @@
1
- ---
2
- description: Packaged reviewer role
3
- ---
4
- Review the requested change carefully. Return concrete findings with file names and a next check.