apex-code 0.0.1-alpha.4 → 0.0.1-alpha.6
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/CHANGELOG.md +78 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -1
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +2 -2
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +20 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +91 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +17 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +28 -4
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/lsp/client.d.ts +76 -0
- package/dist/core/lsp/client.d.ts.map +1 -0
- package/dist/core/lsp/client.js +469 -0
- package/dist/core/lsp/client.js.map +1 -0
- package/dist/core/lsp/diagnostics.d.ts +47 -0
- package/dist/core/lsp/diagnostics.d.ts.map +1 -0
- package/dist/core/lsp/diagnostics.js +224 -0
- package/dist/core/lsp/diagnostics.js.map +1 -0
- package/dist/core/lsp/pool.d.ts +48 -0
- package/dist/core/lsp/pool.d.ts.map +1 -0
- package/dist/core/lsp/pool.js +150 -0
- package/dist/core/lsp/pool.js.map +1 -0
- package/dist/core/lsp/registry.d.ts +49 -0
- package/dist/core/lsp/registry.d.ts.map +1 -0
- package/dist/core/lsp/registry.js +215 -0
- package/dist/core/lsp/registry.js.map +1 -0
- package/dist/core/lsp/status.d.ts +23 -0
- package/dist/core/lsp/status.d.ts.map +1 -0
- package/dist/core/lsp/status.js +35 -0
- package/dist/core/lsp/status.js.map +1 -0
- package/dist/core/lsp/sync.d.ts +13 -0
- package/dist/core/lsp/sync.d.ts.map +1 -0
- package/dist/core/lsp/sync.js +71 -0
- package/dist/core/lsp/sync.js.map +1 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +15 -0
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/project-trust.d.ts.map +1 -1
- package/dist/core/project-trust.js +1 -1
- package/dist/core/project-trust.js.map +1 -1
- package/dist/core/sandbox/cli-launch.d.ts +43 -0
- package/dist/core/sandbox/cli-launch.d.ts.map +1 -1
- package/dist/core/sandbox/cli-launch.js +70 -3
- package/dist/core/sandbox/cli-launch.js.map +1 -1
- package/dist/core/sandbox/cli-supervisor.d.ts +2 -0
- package/dist/core/sandbox/cli-supervisor.d.ts.map +1 -1
- package/dist/core/sandbox/cli-supervisor.js +1 -0
- package/dist/core/sandbox/cli-supervisor.js.map +1 -1
- package/dist/core/sdk.d.ts +4 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +10 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +3 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +19 -7
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +77 -19
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +3 -3
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/contract.d.ts +29 -2
- package/dist/core/tools/contract.d.ts.map +1 -1
- package/dist/core/tools/contract.js.map +1 -1
- package/dist/core/tools/diagnostics.d.ts +39 -0
- package/dist/core/tools/diagnostics.d.ts.map +1 -0
- package/dist/core/tools/diagnostics.js +62 -0
- package/dist/core/tools/diagnostics.js.map +1 -0
- package/dist/core/tools/edit.d.ts +10 -0
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +17 -8
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/index.d.ts +20 -3
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +18 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/lsp.d.ts +62 -0
- package/dist/core/tools/lsp.d.ts.map +1 -0
- package/dist/core/tools/lsp.js +216 -0
- package/dist/core/tools/lsp.js.map +1 -0
- package/dist/core/tools/skill-search.d.ts +32 -0
- package/dist/core/tools/skill-search.d.ts.map +1 -0
- package/dist/core/tools/skill-search.js +56 -0
- package/dist/core/tools/skill-search.js.map +1 -0
- package/dist/core/tools/write.d.ts +10 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +16 -3
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +49 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +235 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.js +2 -1
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +19 -6
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +172 -89
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/splash-header.d.ts +41 -0
- package/dist/modes/interactive/components/splash-header.d.ts.map +1 -0
- package/dist/modes/interactive/components/splash-header.js +145 -0
- package/dist/modes/interactive/components/splash-header.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +19 -15
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/apex.json +94 -0
- package/dist/modes/interactive/theme/light.json +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +6 -1
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +2 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/themes/apex-logo.d.ts +21 -0
- package/dist/themes/apex-logo.d.ts.map +1 -0
- package/dist/themes/apex-logo.js +31 -0
- package/dist/themes/apex-logo.js.map +1 -0
- package/dist/utils/changelog.d.ts +7 -2
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +82 -13
- package/dist/utils/changelog.js.map +1 -1
- package/docs/skills.md +54 -4
- package/npm-shrinkwrap.json +5 -5
- package/package.json +2 -2
package/dist/core/skills.js
CHANGED
|
@@ -247,34 +247,92 @@ function loadSkillFromFile(filePath, source) {
|
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
/**
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
250
|
+
* Derive a `/skill:<token>` command token from a skill's frontmatter `name`, which
|
|
251
|
+
* `docs/skills.md` § Validation deliberately allows to contain characters a slash
|
|
252
|
+
* command cannot (spaces, capitals) -- lenient loading is a considered divergence
|
|
253
|
+
* from the Agent Skills standard, not a gap to close, so the skill still loads and
|
|
254
|
+
* only its command token changes here. Identity for an already command-safe name
|
|
255
|
+
* (`^[a-z0-9-]+$` with no leading/trailing/consecutive hyphen, matching
|
|
256
|
+
* `validateName`'s own rule), so this is a no-op for the common case.
|
|
257
|
+
*/
|
|
258
|
+
export function slugifySkillCommandName(name) {
|
|
259
|
+
const slug = name
|
|
260
|
+
.toLowerCase()
|
|
261
|
+
.replace(/[^a-z0-9-]+/g, "-")
|
|
262
|
+
.replace(/-+/g, "-")
|
|
263
|
+
.replace(/^-|-$/g, "");
|
|
264
|
+
return slug || "skill";
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Initial catalog budget (ADR 0021). Measured against a real 115-skill library: name
|
|
268
|
+
* and full description cost 6,742 tokens against 128 tokens of prefix headroom, so the
|
|
269
|
+
* catalog carries names only and stops at this budget rather than growing with the
|
|
270
|
+
* user's library size. SKILL.8 re-measures this against the enforced production
|
|
271
|
+
* prefix and finalizes it -- matching `ENFORCED_PRODUCTION_PREFIX_BUDGET`'s own
|
|
272
|
+
* precedent of "fixed by measurement, not assumed" -- so this starting value is not
|
|
273
|
+
* final.
|
|
274
|
+
*/
|
|
275
|
+
export const SKILL_CATALOG_PREFIX_BUDGET_TOKENS = 600;
|
|
276
|
+
/** Same chars/4 heuristic `estimateTokens` uses for messages (compaction.ts), applied to plain text. */
|
|
277
|
+
function estimateTextTokens(text) {
|
|
278
|
+
return Math.ceil(text.length / 4);
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Format a budget-bounded skill catalog for inclusion in a system prompt (ADR 0021).
|
|
253
282
|
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
283
|
+
* Carries names only, alphabetically ordered, added until `budgetTokens` is spent --
|
|
284
|
+
* unlike every other prefix contributor, the catalog is sized by the user's skill
|
|
285
|
+
* library rather than by the product, so a token budget bounds it rather than a
|
|
286
|
+
* fixed schema. Descriptions resolve on demand through the `skill_search` tool
|
|
287
|
+
* (`core/tools/skill-search.ts`, SKILL.7); content still loads through `read`,
|
|
288
|
+
* unchanged. Once one name fails to fit, every remaining name (in sorted order) is
|
|
289
|
+
* counted as omitted rather than skipping ahead to a shorter one that might fit --
|
|
290
|
+
* the catalog is always a clean prefix of the sorted list, not a best-fit selection.
|
|
291
|
+
*
|
|
292
|
+
* Skills with `disableModelInvocation=true` are excluded (invocable only via
|
|
293
|
+
* `/skill:<token>`, per `slugifySkillCommandName`).
|
|
256
294
|
*/
|
|
257
|
-
|
|
295
|
+
function omittedCommentLine(omittedCount) {
|
|
296
|
+
return ` <!-- ${omittedCount} more skill${omittedCount === 1 ? "" : "s"} omitted for space; call skill_search to find them -->`;
|
|
297
|
+
}
|
|
298
|
+
export function formatSkillsForPrompt(skills, budgetTokens = SKILL_CATALOG_PREFIX_BUDGET_TOKENS) {
|
|
258
299
|
const visibleSkills = skills.filter((s) => !s.disableModelInvocation);
|
|
259
300
|
if (visibleSkills.length === 0) {
|
|
260
301
|
return "";
|
|
261
302
|
}
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
"
|
|
265
|
-
"
|
|
303
|
+
const sortedNames = visibleSkills.map((s) => s.name).sort((a, b) => a.localeCompare(b));
|
|
304
|
+
const header = [
|
|
305
|
+
"",
|
|
306
|
+
"",
|
|
307
|
+
"The following skill names are available. Each provides specialized instructions for a specific task.",
|
|
308
|
+
"Call skill_search with a name or a query to see a skill's description, then use the read tool to load its file when the task matches.",
|
|
266
309
|
"",
|
|
267
310
|
"<available_skills>",
|
|
268
|
-
];
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
311
|
+
].join("\n");
|
|
312
|
+
const footer = "</available_skills>";
|
|
313
|
+
const nameLines = sortedNames.map((name) => ` <name>${escapeXml(name)}</name>`);
|
|
314
|
+
const fullText = [header, ...nameLines, footer].join("\n");
|
|
315
|
+
if (estimateTextTokens(fullText) <= budgetTokens) {
|
|
316
|
+
return fullText;
|
|
317
|
+
}
|
|
318
|
+
// The full catalog doesn't fit: at least one name will be omitted, so the
|
|
319
|
+
// returned text must also carry the omitted-count comment line, and that line's
|
|
320
|
+
// own cost has to be reserved up front. Checking each candidate only against
|
|
321
|
+
// header+names+footer (no comment line) would let the comment line's own cost
|
|
322
|
+
// push the final assembled text over budgetTokens once it's appended after the
|
|
323
|
+
// loop -- reserving worst-case (every name omitted, the widest possible count)
|
|
324
|
+
// keeps the reservation a safe upper bound regardless of the actual cutoff.
|
|
325
|
+
const availableForNames = budgetTokens - estimateTextTokens(omittedCommentLine(sortedNames.length));
|
|
326
|
+
const includedLines = [];
|
|
327
|
+
let cutoffIndex = 0;
|
|
328
|
+
for (; cutoffIndex < sortedNames.length; cutoffIndex++) {
|
|
329
|
+
const candidateText = [header, ...includedLines, nameLines[cutoffIndex], footer].join("\n");
|
|
330
|
+
if (estimateTextTokens(candidateText) > availableForNames)
|
|
331
|
+
break;
|
|
332
|
+
includedLines.push(nameLines[cutoffIndex]);
|
|
275
333
|
}
|
|
276
|
-
|
|
277
|
-
return
|
|
334
|
+
const omittedCount = sortedNames.length - cutoffIndex;
|
|
335
|
+
return [header, ...includedLines, omittedCommentLine(omittedCount), footer].join("\n");
|
|
278
336
|
}
|
|
279
337
|
function escapeXml(str) {
|
|
280
338
|
return str
|
package/dist/core/skills.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readdirSync, readFileSync, statSync } from \"fs\";\nimport ignore from \"ignore\";\nimport { basename, dirname, join, relative, resolve, sep } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.ts\";\nimport { parseFrontmatter } from \"../utils/frontmatter.ts\";\nimport { canonicalizePath, resolvePath } from \"../utils/paths.ts\";\nimport type { ResourceDiagnostic } from \"./diagnostics.ts\";\nimport { createSyntheticSourceInfo, type SourceInfo } from \"./source-info.ts\";\n\n/** Max name length per spec */\nconst MAX_NAME_LENGTH = 64;\n\n/** Max description length per spec */\nconst MAX_DESCRIPTION_LENGTH = 1024;\n\nconst IGNORE_FILE_NAMES = [\".gitignore\", \".ignore\", \".fdignore\"];\n\ntype IgnoreMatcher = ReturnType<typeof ignore>;\n\nfunction toPosixPath(p: string): string {\n\treturn p.split(sep).join(\"/\");\n}\n\nfunction prefixIgnorePattern(line: string, prefix: string): string | null {\n\tconst trimmed = line.trim();\n\tif (!trimmed) return null;\n\tif (trimmed.startsWith(\"#\") && !trimmed.startsWith(\"\\\\#\")) return null;\n\n\tlet pattern = line;\n\tlet negated = false;\n\n\tif (pattern.startsWith(\"!\")) {\n\t\tnegated = true;\n\t\tpattern = pattern.slice(1);\n\t} else if (pattern.startsWith(\"\\\\!\")) {\n\t\tpattern = pattern.slice(1);\n\t}\n\n\tif (pattern.startsWith(\"/\")) {\n\t\tpattern = pattern.slice(1);\n\t}\n\n\tconst prefixed = prefix ? `${prefix}${pattern}` : pattern;\n\treturn negated ? `!${prefixed}` : prefixed;\n}\n\nfunction addIgnoreRules(ig: IgnoreMatcher, dir: string, rootDir: string): void {\n\tconst relativeDir = relative(rootDir, dir);\n\tconst prefix = relativeDir ? `${toPosixPath(relativeDir)}/` : \"\";\n\n\tfor (const filename of IGNORE_FILE_NAMES) {\n\t\tconst ignorePath = join(dir, filename);\n\t\tif (!existsSync(ignorePath)) continue;\n\t\ttry {\n\t\t\tconst content = readFileSync(ignorePath, \"utf-8\");\n\t\t\tconst patterns = content\n\t\t\t\t.split(/\\r?\\n/)\n\t\t\t\t.map((line) => prefixIgnorePattern(line, prefix))\n\t\t\t\t.filter((line): line is string => Boolean(line));\n\t\t\tif (patterns.length > 0) {\n\t\t\t\tig.add(patterns);\n\t\t\t}\n\t\t} catch {}\n\t}\n}\n\nexport interface SkillFrontmatter {\n\tname?: string;\n\tdescription?: string;\n\t\"disable-model-invocation\"?: boolean;\n\t[key: string]: unknown;\n}\n\nexport interface Skill {\n\tname: string;\n\tdescription: string;\n\tfilePath: string;\n\tbaseDir: string;\n\tsourceInfo: SourceInfo;\n\tdisableModelInvocation: boolean;\n}\n\nexport interface LoadSkillsResult {\n\tskills: Skill[];\n\tdiagnostics: ResourceDiagnostic[];\n}\n\n/**\n * Validate skill name per Agent Skills spec.\n * Returns array of validation error messages (empty if valid).\n */\nfunction validateName(name: string): string[] {\n\tconst errors: string[] = [];\n\n\tif (name.length > MAX_NAME_LENGTH) {\n\t\terrors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);\n\t}\n\n\tif (!/^[a-z0-9-]+$/.test(name)) {\n\t\terrors.push(`name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)`);\n\t}\n\n\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) {\n\t\terrors.push(`name must not start or end with a hyphen`);\n\t}\n\n\tif (name.includes(\"--\")) {\n\t\terrors.push(`name must not contain consecutive hyphens`);\n\t}\n\n\treturn errors;\n}\n\n/**\n * Validate description per Agent Skills spec.\n */\nfunction validateDescription(description: string | undefined): string[] {\n\tconst errors: string[] = [];\n\n\tif (!description || description.trim() === \"\") {\n\t\terrors.push(\"description is required\");\n\t} else if (description.length > MAX_DESCRIPTION_LENGTH) {\n\t\terrors.push(`description exceeds ${MAX_DESCRIPTION_LENGTH} characters (${description.length})`);\n\t}\n\n\treturn errors;\n}\n\nexport interface LoadSkillsFromDirOptions {\n\t/** Directory to scan for skills */\n\tdir: string;\n\t/** Source identifier for these skills */\n\tsource: string;\n}\n\nfunction createSkillSourceInfo(filePath: string, baseDir: string, source: string): SourceInfo {\n\tswitch (source) {\n\t\tcase \"user\":\n\t\t\treturn createSyntheticSourceInfo(filePath, {\n\t\t\t\tsource: \"local\",\n\t\t\t\tscope: \"user\",\n\t\t\t\tbaseDir,\n\t\t\t});\n\t\tcase \"project\":\n\t\t\treturn createSyntheticSourceInfo(filePath, {\n\t\t\t\tsource: \"local\",\n\t\t\t\tscope: \"project\",\n\t\t\t\tbaseDir,\n\t\t\t});\n\t\tcase \"path\":\n\t\t\treturn createSyntheticSourceInfo(filePath, {\n\t\t\t\tsource: \"local\",\n\t\t\t\tbaseDir,\n\t\t\t});\n\t\tdefault:\n\t\t\treturn createSyntheticSourceInfo(filePath, { source, baseDir });\n\t}\n}\n\n/**\n * Load skills from a directory.\n *\n * Discovery rules:\n * - if a directory contains SKILL.md, treat it as a skill root and do not recurse further\n * - otherwise, load direct .md children in the root\n * - recurse into subdirectories to find SKILL.md\n */\nexport function loadSkillsFromDir(options: LoadSkillsFromDirOptions): LoadSkillsResult {\n\tconst { dir, source } = options;\n\treturn loadSkillsFromDirInternal(dir, source, true);\n}\n\nfunction loadSkillsFromDirInternal(\n\tdir: string,\n\tsource: string,\n\tincludeRootFiles: boolean,\n\tignoreMatcher?: IgnoreMatcher,\n\trootDir?: string,\n): LoadSkillsResult {\n\tconst skills: Skill[] = [];\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\n\tif (!existsSync(dir)) {\n\t\treturn { skills, diagnostics };\n\t}\n\n\tconst root = rootDir ?? dir;\n\tconst ig = ignoreMatcher ?? ignore();\n\taddIgnoreRules(ig, dir, root);\n\n\ttry {\n\t\tconst entries = readdirSync(dir, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.name !== \"SKILL.md\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst fullPath = join(dir, entry.name);\n\n\t\t\tlet isFile = entry.isFile();\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\ttry {\n\t\t\t\t\tisFile = statSync(fullPath).isFile();\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst relPath = toPosixPath(relative(root, fullPath));\n\t\t\tif (!isFile || ig.ignores(relPath)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst result = loadSkillFromFile(fullPath, source);\n\t\t\tif (result.skill) {\n\t\t\t\tskills.push(result.skill);\n\t\t\t}\n\t\t\tdiagnostics.push(...result.diagnostics);\n\t\t\treturn { skills, diagnostics };\n\t\t}\n\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.name.startsWith(\".\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Skip node_modules to avoid scanning dependencies\n\t\t\tif (entry.name === \"node_modules\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst fullPath = join(dir, entry.name);\n\n\t\t\t// For symlinks, check if they point to a directory and follow them\n\t\t\tlet isDirectory = entry.isDirectory();\n\t\t\tlet isFile = entry.isFile();\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\ttry {\n\t\t\t\t\tconst stats = statSync(fullPath);\n\t\t\t\t\tisDirectory = stats.isDirectory();\n\t\t\t\t\tisFile = stats.isFile();\n\t\t\t\t} catch {\n\t\t\t\t\t// Broken symlink, skip it\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst relPath = toPosixPath(relative(root, fullPath));\n\t\t\tconst ignorePath = isDirectory ? `${relPath}/` : relPath;\n\t\t\tif (ig.ignores(ignorePath)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (isDirectory) {\n\t\t\t\tconst subResult = loadSkillsFromDirInternal(fullPath, source, false, ig, root);\n\t\t\t\tskills.push(...subResult.skills);\n\t\t\t\tdiagnostics.push(...subResult.diagnostics);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!isFile || !includeRootFiles || !entry.name.endsWith(\".md\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst result = loadSkillFromFile(fullPath, source);\n\t\t\tif (result.skill) {\n\t\t\t\tskills.push(result.skill);\n\t\t\t}\n\t\t\tdiagnostics.push(...result.diagnostics);\n\t\t}\n\t} catch {}\n\n\treturn { skills, diagnostics };\n}\n\nfunction loadSkillFromFile(\n\tfilePath: string,\n\tsource: string,\n): { skill: Skill | null; diagnostics: ResourceDiagnostic[] } {\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\n\ttry {\n\t\tconst rawContent = readFileSync(filePath, \"utf-8\");\n\t\tconst { frontmatter } = parseFrontmatter<SkillFrontmatter>(rawContent);\n\t\tconst skillDir = dirname(filePath);\n\t\tconst parentDirName = basename(skillDir);\n\n\t\t// Validate description\n\t\tconst descErrors = validateDescription(frontmatter.description);\n\t\tfor (const error of descErrors) {\n\t\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t\t}\n\n\t\t// Use name from frontmatter, or fall back to parent directory name\n\t\tconst name = frontmatter.name || parentDirName;\n\n\t\t// Validate name\n\t\tconst nameErrors = validateName(name);\n\t\tfor (const error of nameErrors) {\n\t\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t\t}\n\n\t\t// Still load the skill even with warnings (unless description is completely missing)\n\t\tif (!frontmatter.description || frontmatter.description.trim() === \"\") {\n\t\t\treturn { skill: null, diagnostics };\n\t\t}\n\n\t\treturn {\n\t\t\tskill: {\n\t\t\t\tname,\n\t\t\t\tdescription: frontmatter.description,\n\t\t\t\tfilePath,\n\t\t\t\tbaseDir: skillDir,\n\t\t\t\tsourceInfo: createSkillSourceInfo(filePath, skillDir, source),\n\t\t\t\tdisableModelInvocation: frontmatter[\"disable-model-invocation\"] === true,\n\t\t\t},\n\t\t\tdiagnostics,\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : \"failed to parse skill file\";\n\t\tdiagnostics.push({ type: \"warning\", message, path: filePath });\n\t\treturn { skill: null, diagnostics };\n\t}\n}\n\n/**\n * Format skills for inclusion in a system prompt.\n * Uses XML format per Agent Skills standard.\n * See: https://agentskills.io/integrate-skills\n *\n * Skills with disableModelInvocation=true are excluded from the prompt\n * (they can only be invoked explicitly via /skill:name commands).\n */\nexport function formatSkillsForPrompt(skills: Skill[]): string {\n\tconst visibleSkills = skills.filter((s) => !s.disableModelInvocation);\n\n\tif (visibleSkills.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst lines = [\n\t\t\"\\n\\nThe following skills provide specialized instructions for specific tasks.\",\n\t\t\"Use the read tool to load a skill's file when the task matches its description.\",\n\t\t\"When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\",\n\t\t\"\",\n\t\t\"<available_skills>\",\n\t];\n\n\tfor (const skill of visibleSkills) {\n\t\tlines.push(\" <skill>\");\n\t\tlines.push(` <name>${escapeXml(skill.name)}</name>`);\n\t\tlines.push(` <description>${escapeXml(skill.description)}</description>`);\n\t\tlines.push(` <location>${escapeXml(skill.filePath)}</location>`);\n\t\tlines.push(\" </skill>\");\n\t}\n\n\tlines.push(\"</available_skills>\");\n\n\treturn lines.join(\"\\n\");\n}\n\nfunction escapeXml(str: string): string {\n\treturn str\n\t\t.replace(/&/g, \"&\")\n\t\t.replace(/</g, \"<\")\n\t\t.replace(/>/g, \">\")\n\t\t.replace(/\"/g, \""\")\n\t\t.replace(/'/g, \"'\");\n}\n\nexport interface LoadSkillsOptions {\n\t/** Working directory for project-local skills. */\n\tcwd: string;\n\t/** Agent config directory for global skills. */\n\tagentDir: string;\n\t/** Explicit skill paths (files or directories) */\n\tskillPaths: string[];\n\t/** Include default skills directories. */\n\tincludeDefaults: boolean;\n}\n\n/**\n * Load skills from all configured locations.\n * Returns skills and any validation diagnostics.\n */\nexport function loadSkills(options: LoadSkillsOptions): LoadSkillsResult {\n\tconst { agentDir, skillPaths, includeDefaults } = options;\n\n\t// Resolve agentDir - if not provided, use default from config\n\tconst resolvedCwd = resolvePath(options.cwd);\n\tconst resolvedAgentDir = resolvePath(agentDir ?? getAgentDir());\n\n\tconst skillMap = new Map<string, Skill>();\n\tconst realPathSet = new Set<string>();\n\tconst allDiagnostics: ResourceDiagnostic[] = [];\n\tconst collisionDiagnostics: ResourceDiagnostic[] = [];\n\n\tfunction addSkills(result: LoadSkillsResult) {\n\t\tallDiagnostics.push(...result.diagnostics);\n\t\tfor (const skill of result.skills) {\n\t\t\t// Resolve symlinks to detect duplicate files\n\t\t\tconst realPath = canonicalizePath(skill.filePath);\n\n\t\t\t// Skip silently if we've already loaded this exact file (via symlink)\n\t\t\tif (realPathSet.has(realPath)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst existing = skillMap.get(skill.name);\n\t\t\tif (existing) {\n\t\t\t\tcollisionDiagnostics.push({\n\t\t\t\t\ttype: \"collision\",\n\t\t\t\t\tmessage: `name \"${skill.name}\" collision`,\n\t\t\t\t\tpath: skill.filePath,\n\t\t\t\t\tcollision: {\n\t\t\t\t\t\tresourceType: \"skill\",\n\t\t\t\t\t\tname: skill.name,\n\t\t\t\t\t\twinnerPath: existing.filePath,\n\t\t\t\t\t\tloserPath: skill.filePath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tskillMap.set(skill.name, skill);\n\t\t\t\trealPathSet.add(realPath);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (includeDefaults) {\n\t\taddSkills(loadSkillsFromDirInternal(join(resolvedAgentDir, \"skills\"), \"user\", true));\n\t\taddSkills(loadSkillsFromDirInternal(resolve(resolvedCwd, CONFIG_DIR_NAME, \"skills\"), \"project\", true));\n\t}\n\n\tconst userSkillsDir = join(resolvedAgentDir, \"skills\");\n\tconst projectSkillsDir = resolve(resolvedCwd, CONFIG_DIR_NAME, \"skills\");\n\n\tconst isUnderPath = (target: string, root: string): boolean => {\n\t\tconst normalizedRoot = resolve(root);\n\t\tif (target === normalizedRoot) {\n\t\t\treturn true;\n\t\t}\n\t\tconst prefix = normalizedRoot.endsWith(sep) ? normalizedRoot : `${normalizedRoot}${sep}`;\n\t\treturn target.startsWith(prefix);\n\t};\n\n\tconst getSource = (resolvedPath: string): \"user\" | \"project\" | \"path\" => {\n\t\tif (!includeDefaults) {\n\t\t\tif (isUnderPath(resolvedPath, userSkillsDir)) return \"user\";\n\t\t\tif (isUnderPath(resolvedPath, projectSkillsDir)) return \"project\";\n\t\t}\n\t\treturn \"path\";\n\t};\n\n\tfor (const rawPath of skillPaths) {\n\t\tconst resolvedPath = resolvePath(rawPath, resolvedCwd, { trim: true });\n\t\tif (!existsSync(resolvedPath)) {\n\t\t\tallDiagnostics.push({ type: \"warning\", message: \"skill path does not exist\", path: resolvedPath });\n\t\t\tcontinue;\n\t\t}\n\n\t\ttry {\n\t\t\tconst stats = statSync(resolvedPath);\n\t\t\tconst source = getSource(resolvedPath);\n\t\t\tif (stats.isDirectory()) {\n\t\t\t\taddSkills(loadSkillsFromDirInternal(resolvedPath, source, true));\n\t\t\t} else if (stats.isFile() && resolvedPath.endsWith(\".md\")) {\n\t\t\t\tconst result = loadSkillFromFile(resolvedPath, source);\n\t\t\t\tif (result.skill) {\n\t\t\t\t\taddSkills({ skills: [result.skill], diagnostics: result.diagnostics });\n\t\t\t\t} else {\n\t\t\t\t\tallDiagnostics.push(...result.diagnostics);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tallDiagnostics.push({ type: \"warning\", message: \"skill path is not a markdown file\", path: resolvedPath });\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : \"failed to read skill path\";\n\t\t\tallDiagnostics.push({ type: \"warning\", message, path: resolvedPath });\n\t\t}\n\t}\n\n\treturn {\n\t\tskills: Array.from(skillMap.values()),\n\t\tdiagnostics: [...allDiagnostics, ...collisionDiagnostics],\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readdirSync, readFileSync, statSync } from \"fs\";\nimport ignore from \"ignore\";\nimport { basename, dirname, join, relative, resolve, sep } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.ts\";\nimport { parseFrontmatter } from \"../utils/frontmatter.ts\";\nimport { canonicalizePath, resolvePath } from \"../utils/paths.ts\";\nimport type { ResourceDiagnostic } from \"./diagnostics.ts\";\nimport { createSyntheticSourceInfo, type SourceInfo } from \"./source-info.ts\";\n\n/** Max name length per spec */\nconst MAX_NAME_LENGTH = 64;\n\n/** Max description length per spec */\nconst MAX_DESCRIPTION_LENGTH = 1024;\n\nconst IGNORE_FILE_NAMES = [\".gitignore\", \".ignore\", \".fdignore\"];\n\ntype IgnoreMatcher = ReturnType<typeof ignore>;\n\nfunction toPosixPath(p: string): string {\n\treturn p.split(sep).join(\"/\");\n}\n\nfunction prefixIgnorePattern(line: string, prefix: string): string | null {\n\tconst trimmed = line.trim();\n\tif (!trimmed) return null;\n\tif (trimmed.startsWith(\"#\") && !trimmed.startsWith(\"\\\\#\")) return null;\n\n\tlet pattern = line;\n\tlet negated = false;\n\n\tif (pattern.startsWith(\"!\")) {\n\t\tnegated = true;\n\t\tpattern = pattern.slice(1);\n\t} else if (pattern.startsWith(\"\\\\!\")) {\n\t\tpattern = pattern.slice(1);\n\t}\n\n\tif (pattern.startsWith(\"/\")) {\n\t\tpattern = pattern.slice(1);\n\t}\n\n\tconst prefixed = prefix ? `${prefix}${pattern}` : pattern;\n\treturn negated ? `!${prefixed}` : prefixed;\n}\n\nfunction addIgnoreRules(ig: IgnoreMatcher, dir: string, rootDir: string): void {\n\tconst relativeDir = relative(rootDir, dir);\n\tconst prefix = relativeDir ? `${toPosixPath(relativeDir)}/` : \"\";\n\n\tfor (const filename of IGNORE_FILE_NAMES) {\n\t\tconst ignorePath = join(dir, filename);\n\t\tif (!existsSync(ignorePath)) continue;\n\t\ttry {\n\t\t\tconst content = readFileSync(ignorePath, \"utf-8\");\n\t\t\tconst patterns = content\n\t\t\t\t.split(/\\r?\\n/)\n\t\t\t\t.map((line) => prefixIgnorePattern(line, prefix))\n\t\t\t\t.filter((line): line is string => Boolean(line));\n\t\t\tif (patterns.length > 0) {\n\t\t\t\tig.add(patterns);\n\t\t\t}\n\t\t} catch {}\n\t}\n}\n\nexport interface SkillFrontmatter {\n\tname?: string;\n\tdescription?: string;\n\t\"disable-model-invocation\"?: boolean;\n\t[key: string]: unknown;\n}\n\nexport interface Skill {\n\tname: string;\n\tdescription: string;\n\tfilePath: string;\n\tbaseDir: string;\n\tsourceInfo: SourceInfo;\n\tdisableModelInvocation: boolean;\n}\n\nexport interface LoadSkillsResult {\n\tskills: Skill[];\n\tdiagnostics: ResourceDiagnostic[];\n}\n\n/**\n * Validate skill name per Agent Skills spec.\n * Returns array of validation error messages (empty if valid).\n */\nfunction validateName(name: string): string[] {\n\tconst errors: string[] = [];\n\n\tif (name.length > MAX_NAME_LENGTH) {\n\t\terrors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);\n\t}\n\n\tif (!/^[a-z0-9-]+$/.test(name)) {\n\t\terrors.push(`name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)`);\n\t}\n\n\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) {\n\t\terrors.push(`name must not start or end with a hyphen`);\n\t}\n\n\tif (name.includes(\"--\")) {\n\t\terrors.push(`name must not contain consecutive hyphens`);\n\t}\n\n\treturn errors;\n}\n\n/**\n * Validate description per Agent Skills spec.\n */\nfunction validateDescription(description: string | undefined): string[] {\n\tconst errors: string[] = [];\n\n\tif (!description || description.trim() === \"\") {\n\t\terrors.push(\"description is required\");\n\t} else if (description.length > MAX_DESCRIPTION_LENGTH) {\n\t\terrors.push(`description exceeds ${MAX_DESCRIPTION_LENGTH} characters (${description.length})`);\n\t}\n\n\treturn errors;\n}\n\nexport interface LoadSkillsFromDirOptions {\n\t/** Directory to scan for skills */\n\tdir: string;\n\t/** Source identifier for these skills */\n\tsource: string;\n}\n\nfunction createSkillSourceInfo(filePath: string, baseDir: string, source: string): SourceInfo {\n\tswitch (source) {\n\t\tcase \"user\":\n\t\t\treturn createSyntheticSourceInfo(filePath, {\n\t\t\t\tsource: \"local\",\n\t\t\t\tscope: \"user\",\n\t\t\t\tbaseDir,\n\t\t\t});\n\t\tcase \"project\":\n\t\t\treturn createSyntheticSourceInfo(filePath, {\n\t\t\t\tsource: \"local\",\n\t\t\t\tscope: \"project\",\n\t\t\t\tbaseDir,\n\t\t\t});\n\t\tcase \"path\":\n\t\t\treturn createSyntheticSourceInfo(filePath, {\n\t\t\t\tsource: \"local\",\n\t\t\t\tbaseDir,\n\t\t\t});\n\t\tdefault:\n\t\t\treturn createSyntheticSourceInfo(filePath, { source, baseDir });\n\t}\n}\n\n/**\n * Load skills from a directory.\n *\n * Discovery rules:\n * - if a directory contains SKILL.md, treat it as a skill root and do not recurse further\n * - otherwise, load direct .md children in the root\n * - recurse into subdirectories to find SKILL.md\n */\nexport function loadSkillsFromDir(options: LoadSkillsFromDirOptions): LoadSkillsResult {\n\tconst { dir, source } = options;\n\treturn loadSkillsFromDirInternal(dir, source, true);\n}\n\nfunction loadSkillsFromDirInternal(\n\tdir: string,\n\tsource: string,\n\tincludeRootFiles: boolean,\n\tignoreMatcher?: IgnoreMatcher,\n\trootDir?: string,\n): LoadSkillsResult {\n\tconst skills: Skill[] = [];\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\n\tif (!existsSync(dir)) {\n\t\treturn { skills, diagnostics };\n\t}\n\n\tconst root = rootDir ?? dir;\n\tconst ig = ignoreMatcher ?? ignore();\n\taddIgnoreRules(ig, dir, root);\n\n\ttry {\n\t\tconst entries = readdirSync(dir, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.name !== \"SKILL.md\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst fullPath = join(dir, entry.name);\n\n\t\t\tlet isFile = entry.isFile();\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\ttry {\n\t\t\t\t\tisFile = statSync(fullPath).isFile();\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst relPath = toPosixPath(relative(root, fullPath));\n\t\t\tif (!isFile || ig.ignores(relPath)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst result = loadSkillFromFile(fullPath, source);\n\t\t\tif (result.skill) {\n\t\t\t\tskills.push(result.skill);\n\t\t\t}\n\t\t\tdiagnostics.push(...result.diagnostics);\n\t\t\treturn { skills, diagnostics };\n\t\t}\n\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.name.startsWith(\".\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Skip node_modules to avoid scanning dependencies\n\t\t\tif (entry.name === \"node_modules\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst fullPath = join(dir, entry.name);\n\n\t\t\t// For symlinks, check if they point to a directory and follow them\n\t\t\tlet isDirectory = entry.isDirectory();\n\t\t\tlet isFile = entry.isFile();\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\ttry {\n\t\t\t\t\tconst stats = statSync(fullPath);\n\t\t\t\t\tisDirectory = stats.isDirectory();\n\t\t\t\t\tisFile = stats.isFile();\n\t\t\t\t} catch {\n\t\t\t\t\t// Broken symlink, skip it\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst relPath = toPosixPath(relative(root, fullPath));\n\t\t\tconst ignorePath = isDirectory ? `${relPath}/` : relPath;\n\t\t\tif (ig.ignores(ignorePath)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (isDirectory) {\n\t\t\t\tconst subResult = loadSkillsFromDirInternal(fullPath, source, false, ig, root);\n\t\t\t\tskills.push(...subResult.skills);\n\t\t\t\tdiagnostics.push(...subResult.diagnostics);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!isFile || !includeRootFiles || !entry.name.endsWith(\".md\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst result = loadSkillFromFile(fullPath, source);\n\t\t\tif (result.skill) {\n\t\t\t\tskills.push(result.skill);\n\t\t\t}\n\t\t\tdiagnostics.push(...result.diagnostics);\n\t\t}\n\t} catch {}\n\n\treturn { skills, diagnostics };\n}\n\nfunction loadSkillFromFile(\n\tfilePath: string,\n\tsource: string,\n): { skill: Skill | null; diagnostics: ResourceDiagnostic[] } {\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\n\ttry {\n\t\tconst rawContent = readFileSync(filePath, \"utf-8\");\n\t\tconst { frontmatter } = parseFrontmatter<SkillFrontmatter>(rawContent);\n\t\tconst skillDir = dirname(filePath);\n\t\tconst parentDirName = basename(skillDir);\n\n\t\t// Validate description\n\t\tconst descErrors = validateDescription(frontmatter.description);\n\t\tfor (const error of descErrors) {\n\t\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t\t}\n\n\t\t// Use name from frontmatter, or fall back to parent directory name\n\t\tconst name = frontmatter.name || parentDirName;\n\n\t\t// Validate name\n\t\tconst nameErrors = validateName(name);\n\t\tfor (const error of nameErrors) {\n\t\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t\t}\n\n\t\t// Still load the skill even with warnings (unless description is completely missing)\n\t\tif (!frontmatter.description || frontmatter.description.trim() === \"\") {\n\t\t\treturn { skill: null, diagnostics };\n\t\t}\n\n\t\treturn {\n\t\t\tskill: {\n\t\t\t\tname,\n\t\t\t\tdescription: frontmatter.description,\n\t\t\t\tfilePath,\n\t\t\t\tbaseDir: skillDir,\n\t\t\t\tsourceInfo: createSkillSourceInfo(filePath, skillDir, source),\n\t\t\t\tdisableModelInvocation: frontmatter[\"disable-model-invocation\"] === true,\n\t\t\t},\n\t\t\tdiagnostics,\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : \"failed to parse skill file\";\n\t\tdiagnostics.push({ type: \"warning\", message, path: filePath });\n\t\treturn { skill: null, diagnostics };\n\t}\n}\n\n/**\n * Derive a `/skill:<token>` command token from a skill's frontmatter `name`, which\n * `docs/skills.md` § Validation deliberately allows to contain characters a slash\n * command cannot (spaces, capitals) -- lenient loading is a considered divergence\n * from the Agent Skills standard, not a gap to close, so the skill still loads and\n * only its command token changes here. Identity for an already command-safe name\n * (`^[a-z0-9-]+$` with no leading/trailing/consecutive hyphen, matching\n * `validateName`'s own rule), so this is a no-op for the common case.\n */\nexport function slugifySkillCommandName(name: string): string {\n\tconst slug = name\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9-]+/g, \"-\")\n\t\t.replace(/-+/g, \"-\")\n\t\t.replace(/^-|-$/g, \"\");\n\treturn slug || \"skill\";\n}\n\n/**\n * Initial catalog budget (ADR 0021). Measured against a real 115-skill library: name\n * and full description cost 6,742 tokens against 128 tokens of prefix headroom, so the\n * catalog carries names only and stops at this budget rather than growing with the\n * user's library size. SKILL.8 re-measures this against the enforced production\n * prefix and finalizes it -- matching `ENFORCED_PRODUCTION_PREFIX_BUDGET`'s own\n * precedent of \"fixed by measurement, not assumed\" -- so this starting value is not\n * final.\n */\nexport const SKILL_CATALOG_PREFIX_BUDGET_TOKENS = 600;\n\n/** Same chars/4 heuristic `estimateTokens` uses for messages (compaction.ts), applied to plain text. */\nfunction estimateTextTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\n/**\n * Format a budget-bounded skill catalog for inclusion in a system prompt (ADR 0021).\n *\n * Carries names only, alphabetically ordered, added until `budgetTokens` is spent --\n * unlike every other prefix contributor, the catalog is sized by the user's skill\n * library rather than by the product, so a token budget bounds it rather than a\n * fixed schema. Descriptions resolve on demand through the `skill_search` tool\n * (`core/tools/skill-search.ts`, SKILL.7); content still loads through `read`,\n * unchanged. Once one name fails to fit, every remaining name (in sorted order) is\n * counted as omitted rather than skipping ahead to a shorter one that might fit --\n * the catalog is always a clean prefix of the sorted list, not a best-fit selection.\n *\n * Skills with `disableModelInvocation=true` are excluded (invocable only via\n * `/skill:<token>`, per `slugifySkillCommandName`).\n */\nfunction omittedCommentLine(omittedCount: number): string {\n\treturn ` <!-- ${omittedCount} more skill${omittedCount === 1 ? \"\" : \"s\"} omitted for space; call skill_search to find them -->`;\n}\n\nexport function formatSkillsForPrompt(\n\tskills: Skill[],\n\tbudgetTokens: number = SKILL_CATALOG_PREFIX_BUDGET_TOKENS,\n): string {\n\tconst visibleSkills = skills.filter((s) => !s.disableModelInvocation);\n\tif (visibleSkills.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst sortedNames = visibleSkills.map((s) => s.name).sort((a, b) => a.localeCompare(b));\n\tconst header = [\n\t\t\"\",\n\t\t\"\",\n\t\t\"The following skill names are available. Each provides specialized instructions for a specific task.\",\n\t\t\"Call skill_search with a name or a query to see a skill's description, then use the read tool to load its file when the task matches.\",\n\t\t\"\",\n\t\t\"<available_skills>\",\n\t].join(\"\\n\");\n\tconst footer = \"</available_skills>\";\n\tconst nameLines = sortedNames.map((name) => ` <name>${escapeXml(name)}</name>`);\n\n\tconst fullText = [header, ...nameLines, footer].join(\"\\n\");\n\tif (estimateTextTokens(fullText) <= budgetTokens) {\n\t\treturn fullText;\n\t}\n\n\t// The full catalog doesn't fit: at least one name will be omitted, so the\n\t// returned text must also carry the omitted-count comment line, and that line's\n\t// own cost has to be reserved up front. Checking each candidate only against\n\t// header+names+footer (no comment line) would let the comment line's own cost\n\t// push the final assembled text over budgetTokens once it's appended after the\n\t// loop -- reserving worst-case (every name omitted, the widest possible count)\n\t// keeps the reservation a safe upper bound regardless of the actual cutoff.\n\tconst availableForNames = budgetTokens - estimateTextTokens(omittedCommentLine(sortedNames.length));\n\n\tconst includedLines: string[] = [];\n\tlet cutoffIndex = 0;\n\tfor (; cutoffIndex < sortedNames.length; cutoffIndex++) {\n\t\tconst candidateText = [header, ...includedLines, nameLines[cutoffIndex], footer].join(\"\\n\");\n\t\tif (estimateTextTokens(candidateText) > availableForNames) break;\n\t\tincludedLines.push(nameLines[cutoffIndex]);\n\t}\n\n\tconst omittedCount = sortedNames.length - cutoffIndex;\n\treturn [header, ...includedLines, omittedCommentLine(omittedCount), footer].join(\"\\n\");\n}\n\nfunction escapeXml(str: string): string {\n\treturn str\n\t\t.replace(/&/g, \"&\")\n\t\t.replace(/</g, \"<\")\n\t\t.replace(/>/g, \">\")\n\t\t.replace(/\"/g, \""\")\n\t\t.replace(/'/g, \"'\");\n}\n\nexport interface LoadSkillsOptions {\n\t/** Working directory for project-local skills. */\n\tcwd: string;\n\t/** Agent config directory for global skills. */\n\tagentDir: string;\n\t/** Explicit skill paths (files or directories) */\n\tskillPaths: string[];\n\t/** Include default skills directories. */\n\tincludeDefaults: boolean;\n}\n\n/**\n * Load skills from all configured locations.\n * Returns skills and any validation diagnostics.\n */\nexport function loadSkills(options: LoadSkillsOptions): LoadSkillsResult {\n\tconst { agentDir, skillPaths, includeDefaults } = options;\n\n\t// Resolve agentDir - if not provided, use default from config\n\tconst resolvedCwd = resolvePath(options.cwd);\n\tconst resolvedAgentDir = resolvePath(agentDir ?? getAgentDir());\n\n\tconst skillMap = new Map<string, Skill>();\n\tconst realPathSet = new Set<string>();\n\tconst allDiagnostics: ResourceDiagnostic[] = [];\n\tconst collisionDiagnostics: ResourceDiagnostic[] = [];\n\n\tfunction addSkills(result: LoadSkillsResult) {\n\t\tallDiagnostics.push(...result.diagnostics);\n\t\tfor (const skill of result.skills) {\n\t\t\t// Resolve symlinks to detect duplicate files\n\t\t\tconst realPath = canonicalizePath(skill.filePath);\n\n\t\t\t// Skip silently if we've already loaded this exact file (via symlink)\n\t\t\tif (realPathSet.has(realPath)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst existing = skillMap.get(skill.name);\n\t\t\tif (existing) {\n\t\t\t\tcollisionDiagnostics.push({\n\t\t\t\t\ttype: \"collision\",\n\t\t\t\t\tmessage: `name \"${skill.name}\" collision`,\n\t\t\t\t\tpath: skill.filePath,\n\t\t\t\t\tcollision: {\n\t\t\t\t\t\tresourceType: \"skill\",\n\t\t\t\t\t\tname: skill.name,\n\t\t\t\t\t\twinnerPath: existing.filePath,\n\t\t\t\t\t\tloserPath: skill.filePath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tskillMap.set(skill.name, skill);\n\t\t\t\trealPathSet.add(realPath);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (includeDefaults) {\n\t\taddSkills(loadSkillsFromDirInternal(join(resolvedAgentDir, \"skills\"), \"user\", true));\n\t\taddSkills(loadSkillsFromDirInternal(resolve(resolvedCwd, CONFIG_DIR_NAME, \"skills\"), \"project\", true));\n\t}\n\n\tconst userSkillsDir = join(resolvedAgentDir, \"skills\");\n\tconst projectSkillsDir = resolve(resolvedCwd, CONFIG_DIR_NAME, \"skills\");\n\n\tconst isUnderPath = (target: string, root: string): boolean => {\n\t\tconst normalizedRoot = resolve(root);\n\t\tif (target === normalizedRoot) {\n\t\t\treturn true;\n\t\t}\n\t\tconst prefix = normalizedRoot.endsWith(sep) ? normalizedRoot : `${normalizedRoot}${sep}`;\n\t\treturn target.startsWith(prefix);\n\t};\n\n\tconst getSource = (resolvedPath: string): \"user\" | \"project\" | \"path\" => {\n\t\tif (!includeDefaults) {\n\t\t\tif (isUnderPath(resolvedPath, userSkillsDir)) return \"user\";\n\t\t\tif (isUnderPath(resolvedPath, projectSkillsDir)) return \"project\";\n\t\t}\n\t\treturn \"path\";\n\t};\n\n\tfor (const rawPath of skillPaths) {\n\t\tconst resolvedPath = resolvePath(rawPath, resolvedCwd, { trim: true });\n\t\tif (!existsSync(resolvedPath)) {\n\t\t\tallDiagnostics.push({ type: \"warning\", message: \"skill path does not exist\", path: resolvedPath });\n\t\t\tcontinue;\n\t\t}\n\n\t\ttry {\n\t\t\tconst stats = statSync(resolvedPath);\n\t\t\tconst source = getSource(resolvedPath);\n\t\t\tif (stats.isDirectory()) {\n\t\t\t\taddSkills(loadSkillsFromDirInternal(resolvedPath, source, true));\n\t\t\t} else if (stats.isFile() && resolvedPath.endsWith(\".md\")) {\n\t\t\t\tconst result = loadSkillFromFile(resolvedPath, source);\n\t\t\t\tif (result.skill) {\n\t\t\t\t\taddSkills({ skills: [result.skill], diagnostics: result.diagnostics });\n\t\t\t\t} else {\n\t\t\t\t\tallDiagnostics.push(...result.diagnostics);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tallDiagnostics.push({ type: \"warning\", message: \"skill path is not a markdown file\", path: resolvedPath });\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : \"failed to read skill path\";\n\t\t\tallDiagnostics.push({ type: \"warning\", message, path: resolvedPath });\n\t\t}\n\t}\n\n\treturn {\n\t\tskills: Array.from(skillMap.values()),\n\t\tdiagnostics: [...allDiagnostics, ...collisionDiagnostics],\n\t};\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slash-commands.d.ts","sourceRoot":"","sources":["../../src/core/slash-commands.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElE,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,sBAAsB,EAAE,aAAa,CAAC,mBAAmB,CAuBrE,CAAC","sourcesContent":["import { APP_NAME } from \"../config.ts\";\nimport type { SourceInfo } from \"./source-info.ts\";\n\nexport type SlashCommandSource = \"extension\" | \"prompt\" | \"skill\";\n\nexport interface SlashCommandInfo {\n\tname: string;\n\tdescription?: string;\n\tsource: SlashCommandSource;\n\tsourceInfo: SourceInfo;\n}\n\nexport interface BuiltinSlashCommand {\n\tname: string;\n\tdescription: string;\n\targumentHint?: string;\n}\n\nexport const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [\n\t{ name: \"settings\", description: \"Open settings menu\" },\n\t{ name: \"model\", description: \"
|
|
1
|
+
{"version":3,"file":"slash-commands.d.ts","sourceRoot":"","sources":["../../src/core/slash-commands.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElE,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,sBAAsB,EAAE,aAAa,CAAC,mBAAmB,CAuBrE,CAAC","sourcesContent":["import { APP_NAME } from \"../config.ts\";\nimport type { SourceInfo } from \"./source-info.ts\";\n\nexport type SlashCommandSource = \"extension\" | \"prompt\" | \"skill\";\n\nexport interface SlashCommandInfo {\n\tname: string;\n\tdescription?: string;\n\tsource: SlashCommandSource;\n\tsourceInfo: SourceInfo;\n}\n\nexport interface BuiltinSlashCommand {\n\tname: string;\n\tdescription: string;\n\targumentHint?: string;\n}\n\nexport const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [\n\t{ name: \"settings\", description: \"Open settings menu\" },\n\t{ name: \"model\", description: \"Pick a provider, then a model\", argumentHint: \"<provider/model>\" },\n\t{ name: \"scoped-models\", description: \"Enable/disable models for Ctrl+P cycling\" },\n\t{ name: \"export\", description: \"Export session (HTML default, or specify path: .html/.jsonl)\" },\n\t{ name: \"import\", description: \"Import and resume a session from a JSONL file\" },\n\t{ name: \"share\", description: \"Share session as a secret GitHub gist\" },\n\t{ name: \"copy\", description: \"Copy last agent message to clipboard\" },\n\t{ name: \"name\", description: \"Set session display name\" },\n\t{ name: \"session\", description: \"Show session info and stats\" },\n\t{ name: \"changelog\", description: \"Show changelog entries\" },\n\t{ name: \"hotkeys\", description: \"Show all keyboard shortcuts\" },\n\t{ name: \"fork\", description: \"Create a new fork from a previous user message\" },\n\t{ name: \"clone\", description: \"Duplicate the current session at the current position\" },\n\t{ name: \"tree\", description: \"Navigate session tree (switch branches)\" },\n\t{ name: \"trust\", description: \"Save project trust decision for future sessions\" },\n\t{ name: \"login\", description: \"Configure provider authentication\", argumentHint: \"<provider>\" },\n\t{ name: \"logout\", description: \"Remove provider authentication\" },\n\t{ name: \"new\", description: \"Start a new session\" },\n\t{ name: \"compact\", description: \"Manually compact the session context\" },\n\t{ name: \"resume\", description: \"Resume a different session\" },\n\t{ name: \"reload\", description: \"Reload keybindings, extensions, skills, prompts, themes, and context files\" },\n\t{ name: \"quit\", description: `Quit ${APP_NAME}` },\n];\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { APP_NAME } from "../config.js";
|
|
2
2
|
export const BUILTIN_SLASH_COMMANDS = [
|
|
3
3
|
{ name: "settings", description: "Open settings menu" },
|
|
4
|
-
{ name: "model", description: "
|
|
4
|
+
{ name: "model", description: "Pick a provider, then a model", argumentHint: "<provider/model>" },
|
|
5
5
|
{ name: "scoped-models", description: "Enable/disable models for Ctrl+P cycling" },
|
|
6
6
|
{ name: "export", description: "Export session (HTML default, or specify path: .html/.jsonl)" },
|
|
7
7
|
{ name: "import", description: "Import and resume a session from a JSONL file" },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slash-commands.js","sourceRoot":"","sources":["../../src/core/slash-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAkBxC,MAAM,CAAC,MAAM,sBAAsB,GAAuC;IACzE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,oBAAoB,EAAE;IACvD,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"slash-commands.js","sourceRoot":"","sources":["../../src/core/slash-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAkBxC,MAAM,CAAC,MAAM,sBAAsB,GAAuC;IACzE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,oBAAoB,EAAE;IACvD,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,+BAA+B,EAAE,YAAY,EAAE,kBAAkB,EAAE;IACjG,EAAE,IAAI,EAAE,eAAe,EAAE,WAAW,EAAE,0CAA0C,EAAE;IAClF,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8DAA8D,EAAE;IAC/F,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+CAA+C,EAAE;IAChF,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,uCAAuC,EAAE;IACvE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,sCAAsC,EAAE;IACrE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,0BAA0B,EAAE;IACzD,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,EAAE;IAC/D,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,wBAAwB,EAAE;IAC5D,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,EAAE;IAC/D,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,gDAAgD,EAAE;IAC/E,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,uDAAuD,EAAE;IACvF,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,yCAAyC,EAAE;IACxE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,iDAAiD,EAAE;IACjF,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,mCAAmC,EAAE,YAAY,EAAE,YAAY,EAAE;IAC/F,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gCAAgC,EAAE;IACjE,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE;IACnD,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,sCAAsC,EAAE;IACxE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4BAA4B,EAAE;IAC7D,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4EAA4E,EAAE;IAC7G,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,QAAQ,EAAE,EAAE;CACjD,CAAC","sourcesContent":["import { APP_NAME } from \"../config.ts\";\nimport type { SourceInfo } from \"./source-info.ts\";\n\nexport type SlashCommandSource = \"extension\" | \"prompt\" | \"skill\";\n\nexport interface SlashCommandInfo {\n\tname: string;\n\tdescription?: string;\n\tsource: SlashCommandSource;\n\tsourceInfo: SourceInfo;\n}\n\nexport interface BuiltinSlashCommand {\n\tname: string;\n\tdescription: string;\n\targumentHint?: string;\n}\n\nexport const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [\n\t{ name: \"settings\", description: \"Open settings menu\" },\n\t{ name: \"model\", description: \"Pick a provider, then a model\", argumentHint: \"<provider/model>\" },\n\t{ name: \"scoped-models\", description: \"Enable/disable models for Ctrl+P cycling\" },\n\t{ name: \"export\", description: \"Export session (HTML default, or specify path: .html/.jsonl)\" },\n\t{ name: \"import\", description: \"Import and resume a session from a JSONL file\" },\n\t{ name: \"share\", description: \"Share session as a secret GitHub gist\" },\n\t{ name: \"copy\", description: \"Copy last agent message to clipboard\" },\n\t{ name: \"name\", description: \"Set session display name\" },\n\t{ name: \"session\", description: \"Show session info and stats\" },\n\t{ name: \"changelog\", description: \"Show changelog entries\" },\n\t{ name: \"hotkeys\", description: \"Show all keyboard shortcuts\" },\n\t{ name: \"fork\", description: \"Create a new fork from a previous user message\" },\n\t{ name: \"clone\", description: \"Duplicate the current session at the current position\" },\n\t{ name: \"tree\", description: \"Navigate session tree (switch branches)\" },\n\t{ name: \"trust\", description: \"Save project trust decision for future sessions\" },\n\t{ name: \"login\", description: \"Configure provider authentication\", argumentHint: \"<provider>\" },\n\t{ name: \"logout\", description: \"Remove provider authentication\" },\n\t{ name: \"new\", description: \"Start a new session\" },\n\t{ name: \"compact\", description: \"Manually compact the session context\" },\n\t{ name: \"resume\", description: \"Resume a different session\" },\n\t{ name: \"reload\", description: \"Reload keybindings, extensions, skills, prompts, themes, and context files\" },\n\t{ name: \"quit\", description: `Quit ${APP_NAME}` },\n];\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAA6D,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpG,MAAM,WAAW,wBAAwB;IACxC,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,uCAAuC;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,gCAAgC;IAChC,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,yBAAyB;IACzB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;CACjB;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CAsI3E","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.ts\";\nimport { formatSkillsForPrompt, SKILL_CATALOG_PREFIX_BUDGET_TOKENS, type Skill } from \"./skills.ts\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t} = options;\n\tconst promptCwd = cwd.replace(/\\\\/g, \"/\");\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t\t}\n\t\t\tprompt += \"</project_context>\\n\";\n\t\t}\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (customPromptHasRead && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills, SKILL_CATALOG_PREFIX_BUDGET_TOKENS);\n\t\t}\n\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\n\t// Build tools list based on selected tools.\n\t// A tool appears in Available tools only when the caller provides a one-line snippet.\n\tconst tools = selectedTools || [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst visibleTools = tools.filter((name) => !!toolSnippets?.[name]);\n\tconst toolsList =\n\t\tvisibleTools.length > 0 ? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join(\"\\n\") : \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use bash for file operations like ls, rg, find\");\n\t}\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\t// Always include these\n\taddGuideline(\"Be concise in your responses\");\n\taddGuideline(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant operating inside Apex Code, a provider-agnostic coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n\nGuidelines:\n${guidelines}\n\nApex Code documentation (read only when the user asks about Apex Code itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- When reading Apex Code docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory\n- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md), environment variables (docs/environment-variables.md)\n- When working on Apex Code topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read Apex Code .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t}\n\t\tprompt += \"</project_context>\\n\";\n\t}\n\n\t// Append skills section (only if read tool is available)\n\tif (hasRead && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills, SKILL_CATALOG_PREFIX_BUDGET_TOKENS);\n\t}\n\n\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\treturn prompt;\n}\n"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* System prompt construction and project context loading
|
|
3
3
|
*/
|
|
4
4
|
import { getDocsPath, getExamplesPath, getReadmePath } from "../config.js";
|
|
5
|
-
import { formatSkillsForPrompt } from "./skills.js";
|
|
5
|
+
import { formatSkillsForPrompt, SKILL_CATALOG_PREFIX_BUDGET_TOKENS } from "./skills.js";
|
|
6
6
|
/** Build the system prompt with tools, guidelines, and context */
|
|
7
7
|
export function buildSystemPrompt(options) {
|
|
8
8
|
const { customPrompt, selectedTools, toolSnippets, promptGuidelines, appendSystemPrompt, cwd, contextFiles: providedContextFiles, skills: providedSkills, } = options;
|
|
@@ -27,7 +27,7 @@ export function buildSystemPrompt(options) {
|
|
|
27
27
|
// Append skills section (only if read tool is available)
|
|
28
28
|
const customPromptHasRead = !selectedTools || selectedTools.includes("read");
|
|
29
29
|
if (customPromptHasRead && skills.length > 0) {
|
|
30
|
-
prompt += formatSkillsForPrompt(skills);
|
|
30
|
+
prompt += formatSkillsForPrompt(skills, SKILL_CATALOG_PREFIX_BUDGET_TOKENS);
|
|
31
31
|
}
|
|
32
32
|
prompt += `\nCurrent working directory: ${promptCwd}`;
|
|
33
33
|
return prompt;
|
|
@@ -102,7 +102,7 @@ Apex Code documentation (read only when the user asks about Apex Code itself, it
|
|
|
102
102
|
}
|
|
103
103
|
// Append skills section (only if read tool is available)
|
|
104
104
|
if (hasRead && skills.length > 0) {
|
|
105
|
-
prompt += formatSkillsForPrompt(skills);
|
|
105
|
+
prompt += formatSkillsForPrompt(skills, SKILL_CATALOG_PREFIX_BUDGET_TOKENS);
|
|
106
106
|
}
|
|
107
107
|
prompt += `\nCurrent working directory: ${promptCwd}`;
|
|
108
108
|
return prompt;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.ts\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.ts\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t} = options;\n\tconst promptCwd = cwd.replace(/\\\\/g, \"/\");\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t\t}\n\t\t\tprompt += \"</project_context>\\n\";\n\t\t}\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (customPromptHasRead && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\n\t// Build tools list based on selected tools.\n\t// A tool appears in Available tools only when the caller provides a one-line snippet.\n\tconst tools = selectedTools || [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst visibleTools = tools.filter((name) => !!toolSnippets?.[name]);\n\tconst toolsList =\n\t\tvisibleTools.length > 0 ? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join(\"\\n\") : \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use bash for file operations like ls, rg, find\");\n\t}\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\t// Always include these\n\taddGuideline(\"Be concise in your responses\");\n\taddGuideline(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant operating inside Apex Code, a provider-agnostic coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n\nGuidelines:\n${guidelines}\n\nApex Code documentation (read only when the user asks about Apex Code itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- When reading Apex Code docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory\n- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md), environment variables (docs/environment-variables.md)\n- When working on Apex Code topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read Apex Code .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t}\n\t\tprompt += \"</project_context>\\n\";\n\t}\n\n\t// Append skills section (only if read tool is available)\n\tif (hasRead && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\n\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\treturn prompt;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.ts\";\nimport { formatSkillsForPrompt, SKILL_CATALOG_PREFIX_BUDGET_TOKENS, type Skill } from \"./skills.ts\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t} = options;\n\tconst promptCwd = cwd.replace(/\\\\/g, \"/\");\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t\t}\n\t\t\tprompt += \"</project_context>\\n\";\n\t\t}\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (customPromptHasRead && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills, SKILL_CATALOG_PREFIX_BUDGET_TOKENS);\n\t\t}\n\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\n\t// Build tools list based on selected tools.\n\t// A tool appears in Available tools only when the caller provides a one-line snippet.\n\tconst tools = selectedTools || [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst visibleTools = tools.filter((name) => !!toolSnippets?.[name]);\n\tconst toolsList =\n\t\tvisibleTools.length > 0 ? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join(\"\\n\") : \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use bash for file operations like ls, rg, find\");\n\t}\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\t// Always include these\n\taddGuideline(\"Be concise in your responses\");\n\taddGuideline(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant operating inside Apex Code, a provider-agnostic coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n\nGuidelines:\n${guidelines}\n\nApex Code documentation (read only when the user asks about Apex Code itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- When reading Apex Code docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory\n- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md), environment variables (docs/environment-variables.md)\n- When working on Apex Code topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read Apex Code .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t}\n\t\tprompt += \"</project_context>\\n\";\n\t}\n\n\t// Append skills section (only if read tool is available)\n\tif (hasRead && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills, SKILL_CATALOG_PREFIX_BUDGET_TOKENS);\n\t}\n\n\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\treturn prompt;\n}\n"]}
|
|
@@ -49,7 +49,7 @@ export interface ContextSpec {
|
|
|
49
49
|
/** Soft cap on result tokens before truncation. */
|
|
50
50
|
outputBudgetTokens?: number;
|
|
51
51
|
}
|
|
52
|
-
export type EvidenceKind = "diff" | "test" | "command" | "manual" | "workflow";
|
|
52
|
+
export type EvidenceKind = "diff" | "test" | "command" | "manual" | "workflow" | "diagnostic";
|
|
53
53
|
/** Source-observed command facts. `exitCode` is absent only when execution never began. */
|
|
54
54
|
export interface CommandEvidenceRecord {
|
|
55
55
|
kind: "command";
|
|
@@ -67,6 +67,33 @@ export interface DiffEvidenceRecord {
|
|
|
67
67
|
contentHash?: string;
|
|
68
68
|
byteCount?: number;
|
|
69
69
|
}
|
|
70
|
+
/** Zero-filled diagnostic severity buckets for one bounded language-server outcome. */
|
|
71
|
+
export interface DiagnosticSeverityCounts {
|
|
72
|
+
error: number;
|
|
73
|
+
warning: number;
|
|
74
|
+
information: number;
|
|
75
|
+
hint: number;
|
|
76
|
+
unspecified: number;
|
|
77
|
+
other: number;
|
|
78
|
+
}
|
|
79
|
+
/** Stable durable classification. Free-form server and process errors never enter evidence. */
|
|
80
|
+
export type DiagnosticUnavailableKind = "no-server" | "disposed" | "unsupported-sync" | "timed-out" | "aborted" | "superseded" | "server-failed";
|
|
81
|
+
/** Bounded post-mutation diagnostic facts, never diagnostic messages or rendered failure reasons. */
|
|
82
|
+
export type DiagnosticEvidenceRecord = {
|
|
83
|
+
kind: "diagnostic";
|
|
84
|
+
path: string;
|
|
85
|
+
status: "ok";
|
|
86
|
+
serverId: string;
|
|
87
|
+
diagnosticCount: number;
|
|
88
|
+
severityCounts: DiagnosticSeverityCounts;
|
|
89
|
+
truncated: boolean;
|
|
90
|
+
} | {
|
|
91
|
+
kind: "diagnostic";
|
|
92
|
+
path: string;
|
|
93
|
+
status: "unavailable";
|
|
94
|
+
serverId?: string;
|
|
95
|
+
unavailableKind: DiagnosticUnavailableKind;
|
|
96
|
+
};
|
|
70
97
|
/** Normalized argv-based test execution facts. */
|
|
71
98
|
export interface TestEvidenceRecord {
|
|
72
99
|
kind: "test";
|
|
@@ -92,7 +119,7 @@ export interface WorkflowEvidenceRecord {
|
|
|
92
119
|
handle?: string;
|
|
93
120
|
}
|
|
94
121
|
/** A structured source record. Policy is a separate consumer, not an additional variant. */
|
|
95
|
-
export type EvidenceRecord = CommandEvidenceRecord | DiffEvidenceRecord | TestEvidenceRecord | ManualEvidenceRecord | WorkflowEvidenceRecord;
|
|
122
|
+
export type EvidenceRecord = CommandEvidenceRecord | DiffEvidenceRecord | DiagnosticEvidenceRecord | TestEvidenceRecord | ManualEvidenceRecord | WorkflowEvidenceRecord;
|
|
96
123
|
/** Durable destination for source-level tool evidence. Policy is deliberately not part of this boundary. */
|
|
97
124
|
export interface EvidenceSink {
|
|
98
125
|
record(entry: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/core/tools/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,yFAAuF;AACvF,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC;AAE/F,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,UAAU,CAQnD,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,OAAO,GAAG,OAAO;IAChE,6EAA6E;IAC7E,eAAe,EAAE,kBAAkB,CAAC;IAEpC,2EAA2E;IAC3E,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAE/D,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAEtC;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,WAAW;IAC3B;;;;;;;;OAQG;IACH,iBAAiB,EAAE,OAAO,CAAC;IAE3B,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,kEAAkE;IAClE,WAAW,EAAE,OAAO,CAAC;IAErB,mDAAmD;IACnD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE/E,2FAA2F;AAC3F,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,2FAA2F;AAC3F,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,oFAAoF;AACpF,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,2DAA2D;AAC3D,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,4FAA4F;AAC5F,MAAM,MAAM,cAAc,GACvB,qBAAqB,GACrB,kBAAkB,GAClB,kBAAkB,GAClB,oBAAoB,GACpB,sBAAsB,CAAC;AAE1B,4GAA4G;AAC5G,MAAM,WAAW,YAAY;IAC5B,MAAM,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,cAAc,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IACrE,gBAAgB,CAAC,CAAC,UAAU,EAAE,yBAAyB,GAAG,IAAI,CAAC;CAC/D;AAED,0FAA0F;AAC1F,MAAM,WAAW,yBAAyB;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY,CAAC,OAAO,SAAS,OAAO,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IAClF,iEAAiE;IACjE,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC;IAEjC;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,GAAG,cAAc,EAAE,CAAC;CACtF;AAED,MAAM,WAAW,YAAY,CAAC,OAAO,SAAS,OAAO,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IAClF,YAAY,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IACtC,UAAU,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IACpC,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;CAC1C;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB,CAAC,OAAO,SAAS,OAAO,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO,EAAE,MAAM,GAAG,GAAG,CACtG,SAAQ,cAAc,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC;IACjD,QAAQ,EAAE,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;CAC1C;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,YAAY,CAAC,OAAO,EAAE,OAAO,CAUvD,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,YAAY,GAAG,SAAS,EACtD,QAAQ,EAAE,MAAM,GACd,YAAY,CAEd;AAED,qFAAqF;AACrF,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,GAAG,SAAS,EACvE,QAAQ,EAAE,MAAM,GACd,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAE/B","sourcesContent":["/**\n * The canonical tool contract. Settled by ADR 0010 and specified in full at\n * docs/architecture/contracts.md § 1 — this module implements that shape, it does\n * not redesign it. `contract` is required on every registered tool, and so is every\n * sub-field: a tool cannot compile without answering all four axes (capabilities,\n * permission, context, evidence), which is what keeps a new tool from silently\n * defaulting into \"unclassified\".\n */\n\nimport type { AgentToolResult } from \"apex-code-agent-core\";\nimport type { Static, TSchema } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\n\n/** What class of thing a tool does. A set, not a single value — `bash` is `{exec}`. */\nexport type Capability = \"fs.read\" | \"fs.write\" | \"exec\" | \"net\" | \"delegate\" | \"ui\" | \"state\";\n\nexport const ALL_CAPABILITIES: ReadonlySet<Capability> = new Set<Capability>([\n\t\"fs.read\",\n\t\"fs.write\",\n\t\"exec\",\n\t\"net\",\n\t\"delegate\",\n\t\"ui\",\n\t\"state\",\n]);\n\nexport type PermissionBehavior = \"allow\" | \"deny\" | \"ask\";\n\n/**\n * `ruleContent` is interpreted by the tool, never by the rule engine (ADR 0010).\n * That is what lets `Bash(git commit:*)` and `Read(~/.ssh/**)` mean entirely\n * different things while the engine that resolves precedence stays tool-agnostic.\n */\nexport interface PermissionSpec<TParams extends TSchema = TSchema> {\n\t/** Behavior when no rule matches. Read-only tools may default to \"allow\". */\n\tdefaultBehavior: PermissionBehavior;\n\n\t/** Does this call match this rule's content? The tool owns the grammar. */\n\tmatches(ruleContent: string, params: Static<TParams>): boolean;\n\n\t/** Human-readable rendering of a rule, for prompts and denial messages. */\n\tdescribe(ruleContent: string): string;\n\n\t/**\n\t * The rule that would allow this exact call — what \"always allow this\"\n\t * persists. Return null when the call is not generalizable into a rule.\n\t */\n\truleForCall(params: Static<TParams>): string | null;\n}\n\nexport interface ContextSpec {\n\t/**\n\t * True when the result's information is recoverable — the same content can be\n\t * obtained again by re-running the tool or reading the workspace.\n\t *\n\t * ONLY recoverable results may be evicted (Phase 3). A tool whose result cannot\n\t * be regenerated (a nondeterministic command, a consumed one-shot resource)\n\t * must set this false, or eviction would silently destroy information the\n\t * transcript is the only record of.\n\t */\n\tresultRecoverable: boolean;\n\n\t/** Marker substituted for an evicted result. */\n\tevictionMarker?: string;\n\n\t/** Announce by name only; load the parameter schema on demand. */\n\tdeferSchema: boolean;\n\n\t/** Soft cap on result tokens before truncation. */\n\toutputBudgetTokens?: number;\n}\n\nexport type EvidenceKind = \"diff\" | \"test\" | \"command\" | \"manual\" | \"workflow\";\n\n/** Source-observed command facts. `exitCode` is absent only when execution never began. */\nexport interface CommandEvidenceRecord {\n\tkind: \"command\";\n\tcommand: string;\n\tcwd?: string;\n\texecutable?: string;\n\targv?: string[];\n\texitCode?: number | null;\n}\n\n/** A file mutation is identified by hashes and paths, never raw file or patch contents. */\nexport interface DiffEvidenceRecord {\n\tkind: \"diff\";\n\tpath: string;\n\tpatchHash?: string;\n\tcontentHash?: string;\n\tbyteCount?: number;\n}\n\n/** Normalized argv-based test execution facts. */\nexport interface TestEvidenceRecord {\n\tkind: \"test\";\n\tcwd: string;\n\texecutable: string;\n\targv: string[];\n\texitCode: number | null;\n}\n\n/** Explicit human attestation; policy decides how, or whether, it is sufficient. */\nexport interface ManualEvidenceRecord {\n\tkind: \"manual\";\n\tvalue?: unknown;\n\tobserved?: unknown;\n\tstatus?: string;\n}\n\n/** Source facts from approval and delegation workflows. */\nexport interface WorkflowEvidenceRecord {\n\tkind: \"workflow\";\n\tplan?: string;\n\tapproved?: boolean;\n\tagentType?: string;\n\ttask?: string;\n\thandle?: string;\n}\n\n/** A structured source record. Policy is a separate consumer, not an additional variant. */\nexport type EvidenceRecord =\n\t| CommandEvidenceRecord\n\t| DiffEvidenceRecord\n\t| TestEvidenceRecord\n\t| ManualEvidenceRecord\n\t| WorkflowEvidenceRecord;\n\n/** Durable destination for source-level tool evidence. Policy is deliberately not part of this boundary. */\nexport interface EvidenceSink {\n\trecord(entry: { toolName: string; records: EvidenceRecord[] }): void;\n\trecordDiagnostic?(diagnostic: EvidenceCaptureDiagnostic): void;\n}\n\n/** A capture failure is observable but never changes an already-completed tool result. */\nexport interface EvidenceCaptureDiagnostic {\n\ttoolName: string;\n\treason: string;\n}\n\nexport interface EvidenceSpec<TParams extends TSchema = TSchema, TDetails = unknown> {\n\t/** Kinds this tool can emit. Empty set is valid and explicit. */\n\temits: ReadonlySet<EvidenceKind>;\n\n\t/**\n\t * Derive evidence from a completed call. Runs inside the tool's own execution\n\t * path, with access to what actually happened, not a reconstruction from\n\t * rendered output.\n\t */\n\tcapture(params: Static<TParams>, result: AgentToolResult<TDetails>): EvidenceRecord[];\n}\n\nexport interface ToolContract<TParams extends TSchema = TSchema, TDetails = unknown> {\n\tcapabilities: ReadonlySet<Capability>;\n\tpermission: PermissionSpec<TParams>;\n\tcontext: ContextSpec;\n\tevidence: EvidenceSpec<TParams, TDetails>;\n}\n\n/**\n * Apex Code extends upstream ToolDefinition with exactly one required field.\n *\n * `TState` defaults to `any`, matching upstream `ToolDefinition` exactly (not\n * `unknown`). That default is load-bearing: TypeScript compares two instantiations\n * of the *same* generic interface (here, both rooted in `ToolDefinition`) using each\n * type parameter's declared variance, without expanding `Static<TParams>`\n * structurally — but only when every type argument lines up, including the ones a\n * caller left defaulted. A mismatched default reintroduces a full structural check,\n * where `Static<any>` does not behave like `any`, and breaks every pre-existing\n * `ToolDefinition<any, X>`-typed consumer across the codebase.\n */\nexport interface ApexToolDefinition<TParams extends TSchema = TSchema, TDetails = unknown, TState = any>\n\textends ToolDefinition<TParams, TDetails, TState> {\n\tcontract: ToolContract<TParams, TDetails>;\n}\n\n/**\n * Conservative contract for a tool registered without one — MCP servers and\n * third-party extensions cannot supply a `contract`. Full capability set (so it can\n * never widen a delegation ceiling), `ask` by default, never evicted, schema\n * deferred, emits nothing. Matching is exact-argument only: a foreign tool's rule\n * authorizes exactly the call it was generated from, never a pattern.\n *\n * This must also be reported as unclassified wherever a consumer describes the tool\n * registry (contracts.md invariant 1) — a conservative default nobody can see is\n * indistinguishable from a bug.\n */\nexport const UNCLASSIFIED: ToolContract<TSchema, unknown> = {\n\tcapabilities: ALL_CAPABILITIES,\n\tpermission: {\n\t\tdefaultBehavior: \"ask\",\n\t\tmatches: (ruleContent, params) => ruleContent === JSON.stringify(params),\n\t\tdescribe: (ruleContent) => `Exact call: ${ruleContent}`,\n\t\truleForCall: (params) => JSON.stringify(params),\n\t},\n\tcontext: { resultRecoverable: false, deferSchema: false },\n\tevidence: { emits: new Set(), capture: () => [] },\n};\n\n/** Resolve a complete tool contract for enforcement consumers. */\nexport function resolveToolContract(\n\tlookup: (toolName: string) => ToolContract | undefined,\n\ttoolName: string,\n): ToolContract {\n\treturn lookup(toolName) ?? UNCLASSIFIED;\n}\n\n/** Resolve the context projection using the same canonical foreign-tool fallback. */\nexport function resolveToolContext(\n\tlookup: (toolName: string) => Pick<ToolContract, \"context\"> | undefined,\n\ttoolName: string,\n): Pick<ToolContract, \"context\"> {\n\treturn lookup(toolName) ?? UNCLASSIFIED;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/core/tools/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,yFAAuF;AACvF,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC;AAE/F,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,UAAU,CAQnD,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,OAAO,GAAG,OAAO;IAChE,6EAA6E;IAC7E,eAAe,EAAE,kBAAkB,CAAC;IAEpC,2EAA2E;IAC3E,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAE/D,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAEtC;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,WAAW;IAC3B;;;;;;;;OAQG;IACH,iBAAiB,EAAE,OAAO,CAAC;IAE3B,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,kEAAkE;IAClE,WAAW,EAAE,OAAO,CAAC;IAErB,mDAAmD;IACnD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,YAAY,CAAC;AAE9F,2FAA2F;AAC3F,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,2FAA2F;AAC3F,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,uFAAuF;AACvF,MAAM,WAAW,wBAAwB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,+FAA+F;AAC/F,MAAM,MAAM,yBAAyB,GAClC,WAAW,GACX,UAAU,GACV,kBAAkB,GAClB,WAAW,GACX,SAAS,GACT,YAAY,GACZ,eAAe,CAAC;AAEnB,qGAAqG;AACrG,MAAM,MAAM,wBAAwB,GACjC;IACA,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,wBAAwB,CAAC;IACzC,SAAS,EAAE,OAAO,CAAC;CAClB,GACD;IACA,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,yBAAyB,CAAC;CAC1C,CAAC;AAEL,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,oFAAoF;AACpF,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,2DAA2D;AAC3D,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,4FAA4F;AAC5F,MAAM,MAAM,cAAc,GACvB,qBAAqB,GACrB,kBAAkB,GAClB,wBAAwB,GACxB,kBAAkB,GAClB,oBAAoB,GACpB,sBAAsB,CAAC;AAE1B,4GAA4G;AAC5G,MAAM,WAAW,YAAY;IAC5B,MAAM,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,cAAc,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IACrE,gBAAgB,CAAC,CAAC,UAAU,EAAE,yBAAyB,GAAG,IAAI,CAAC;CAC/D;AAED,0FAA0F;AAC1F,MAAM,WAAW,yBAAyB;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY,CAAC,OAAO,SAAS,OAAO,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IAClF,iEAAiE;IACjE,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC;IAEjC;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,GAAG,cAAc,EAAE,CAAC;CACtF;AAED,MAAM,WAAW,YAAY,CAAC,OAAO,SAAS,OAAO,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IAClF,YAAY,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IACtC,UAAU,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IACpC,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;CAC1C;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB,CAAC,OAAO,SAAS,OAAO,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO,EAAE,MAAM,GAAG,GAAG,CACtG,SAAQ,cAAc,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC;IACjD,QAAQ,EAAE,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;CAC1C;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,YAAY,CAAC,OAAO,EAAE,OAAO,CAUvD,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,YAAY,GAAG,SAAS,EACtD,QAAQ,EAAE,MAAM,GACd,YAAY,CAEd;AAED,qFAAqF;AACrF,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,GAAG,SAAS,EACvE,QAAQ,EAAE,MAAM,GACd,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAE/B","sourcesContent":["/**\n * The canonical tool contract. Settled by ADR 0010 and specified in full at\n * docs/architecture/contracts.md § 1 — this module implements that shape, it does\n * not redesign it. `contract` is required on every registered tool, and so is every\n * sub-field: a tool cannot compile without answering all four axes (capabilities,\n * permission, context, evidence), which is what keeps a new tool from silently\n * defaulting into \"unclassified\".\n */\n\nimport type { AgentToolResult } from \"apex-code-agent-core\";\nimport type { Static, TSchema } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\n\n/** What class of thing a tool does. A set, not a single value — `bash` is `{exec}`. */\nexport type Capability = \"fs.read\" | \"fs.write\" | \"exec\" | \"net\" | \"delegate\" | \"ui\" | \"state\";\n\nexport const ALL_CAPABILITIES: ReadonlySet<Capability> = new Set<Capability>([\n\t\"fs.read\",\n\t\"fs.write\",\n\t\"exec\",\n\t\"net\",\n\t\"delegate\",\n\t\"ui\",\n\t\"state\",\n]);\n\nexport type PermissionBehavior = \"allow\" | \"deny\" | \"ask\";\n\n/**\n * `ruleContent` is interpreted by the tool, never by the rule engine (ADR 0010).\n * That is what lets `Bash(git commit:*)` and `Read(~/.ssh/**)` mean entirely\n * different things while the engine that resolves precedence stays tool-agnostic.\n */\nexport interface PermissionSpec<TParams extends TSchema = TSchema> {\n\t/** Behavior when no rule matches. Read-only tools may default to \"allow\". */\n\tdefaultBehavior: PermissionBehavior;\n\n\t/** Does this call match this rule's content? The tool owns the grammar. */\n\tmatches(ruleContent: string, params: Static<TParams>): boolean;\n\n\t/** Human-readable rendering of a rule, for prompts and denial messages. */\n\tdescribe(ruleContent: string): string;\n\n\t/**\n\t * The rule that would allow this exact call — what \"always allow this\"\n\t * persists. Return null when the call is not generalizable into a rule.\n\t */\n\truleForCall(params: Static<TParams>): string | null;\n}\n\nexport interface ContextSpec {\n\t/**\n\t * True when the result's information is recoverable — the same content can be\n\t * obtained again by re-running the tool or reading the workspace.\n\t *\n\t * ONLY recoverable results may be evicted (Phase 3). A tool whose result cannot\n\t * be regenerated (a nondeterministic command, a consumed one-shot resource)\n\t * must set this false, or eviction would silently destroy information the\n\t * transcript is the only record of.\n\t */\n\tresultRecoverable: boolean;\n\n\t/** Marker substituted for an evicted result. */\n\tevictionMarker?: string;\n\n\t/** Announce by name only; load the parameter schema on demand. */\n\tdeferSchema: boolean;\n\n\t/** Soft cap on result tokens before truncation. */\n\toutputBudgetTokens?: number;\n}\n\nexport type EvidenceKind = \"diff\" | \"test\" | \"command\" | \"manual\" | \"workflow\" | \"diagnostic\";\n\n/** Source-observed command facts. `exitCode` is absent only when execution never began. */\nexport interface CommandEvidenceRecord {\n\tkind: \"command\";\n\tcommand: string;\n\tcwd?: string;\n\texecutable?: string;\n\targv?: string[];\n\texitCode?: number | null;\n}\n\n/** A file mutation is identified by hashes and paths, never raw file or patch contents. */\nexport interface DiffEvidenceRecord {\n\tkind: \"diff\";\n\tpath: string;\n\tpatchHash?: string;\n\tcontentHash?: string;\n\tbyteCount?: number;\n}\n\n/** Zero-filled diagnostic severity buckets for one bounded language-server outcome. */\nexport interface DiagnosticSeverityCounts {\n\terror: number;\n\twarning: number;\n\tinformation: number;\n\thint: number;\n\tunspecified: number;\n\tother: number;\n}\n\n/** Stable durable classification. Free-form server and process errors never enter evidence. */\nexport type DiagnosticUnavailableKind =\n\t| \"no-server\"\n\t| \"disposed\"\n\t| \"unsupported-sync\"\n\t| \"timed-out\"\n\t| \"aborted\"\n\t| \"superseded\"\n\t| \"server-failed\";\n\n/** Bounded post-mutation diagnostic facts, never diagnostic messages or rendered failure reasons. */\nexport type DiagnosticEvidenceRecord =\n\t| {\n\t\t\tkind: \"diagnostic\";\n\t\t\tpath: string;\n\t\t\tstatus: \"ok\";\n\t\t\tserverId: string;\n\t\t\tdiagnosticCount: number;\n\t\t\tseverityCounts: DiagnosticSeverityCounts;\n\t\t\ttruncated: boolean;\n\t }\n\t| {\n\t\t\tkind: \"diagnostic\";\n\t\t\tpath: string;\n\t\t\tstatus: \"unavailable\";\n\t\t\tserverId?: string;\n\t\t\tunavailableKind: DiagnosticUnavailableKind;\n\t };\n\n/** Normalized argv-based test execution facts. */\nexport interface TestEvidenceRecord {\n\tkind: \"test\";\n\tcwd: string;\n\texecutable: string;\n\targv: string[];\n\texitCode: number | null;\n}\n\n/** Explicit human attestation; policy decides how, or whether, it is sufficient. */\nexport interface ManualEvidenceRecord {\n\tkind: \"manual\";\n\tvalue?: unknown;\n\tobserved?: unknown;\n\tstatus?: string;\n}\n\n/** Source facts from approval and delegation workflows. */\nexport interface WorkflowEvidenceRecord {\n\tkind: \"workflow\";\n\tplan?: string;\n\tapproved?: boolean;\n\tagentType?: string;\n\ttask?: string;\n\thandle?: string;\n}\n\n/** A structured source record. Policy is a separate consumer, not an additional variant. */\nexport type EvidenceRecord =\n\t| CommandEvidenceRecord\n\t| DiffEvidenceRecord\n\t| DiagnosticEvidenceRecord\n\t| TestEvidenceRecord\n\t| ManualEvidenceRecord\n\t| WorkflowEvidenceRecord;\n\n/** Durable destination for source-level tool evidence. Policy is deliberately not part of this boundary. */\nexport interface EvidenceSink {\n\trecord(entry: { toolName: string; records: EvidenceRecord[] }): void;\n\trecordDiagnostic?(diagnostic: EvidenceCaptureDiagnostic): void;\n}\n\n/** A capture failure is observable but never changes an already-completed tool result. */\nexport interface EvidenceCaptureDiagnostic {\n\ttoolName: string;\n\treason: string;\n}\n\nexport interface EvidenceSpec<TParams extends TSchema = TSchema, TDetails = unknown> {\n\t/** Kinds this tool can emit. Empty set is valid and explicit. */\n\temits: ReadonlySet<EvidenceKind>;\n\n\t/**\n\t * Derive evidence from a completed call. Runs inside the tool's own execution\n\t * path, with access to what actually happened, not a reconstruction from\n\t * rendered output.\n\t */\n\tcapture(params: Static<TParams>, result: AgentToolResult<TDetails>): EvidenceRecord[];\n}\n\nexport interface ToolContract<TParams extends TSchema = TSchema, TDetails = unknown> {\n\tcapabilities: ReadonlySet<Capability>;\n\tpermission: PermissionSpec<TParams>;\n\tcontext: ContextSpec;\n\tevidence: EvidenceSpec<TParams, TDetails>;\n}\n\n/**\n * Apex Code extends upstream ToolDefinition with exactly one required field.\n *\n * `TState` defaults to `any`, matching upstream `ToolDefinition` exactly (not\n * `unknown`). That default is load-bearing: TypeScript compares two instantiations\n * of the *same* generic interface (here, both rooted in `ToolDefinition`) using each\n * type parameter's declared variance, without expanding `Static<TParams>`\n * structurally — but only when every type argument lines up, including the ones a\n * caller left defaulted. A mismatched default reintroduces a full structural check,\n * where `Static<any>` does not behave like `any`, and breaks every pre-existing\n * `ToolDefinition<any, X>`-typed consumer across the codebase.\n */\nexport interface ApexToolDefinition<TParams extends TSchema = TSchema, TDetails = unknown, TState = any>\n\textends ToolDefinition<TParams, TDetails, TState> {\n\tcontract: ToolContract<TParams, TDetails>;\n}\n\n/**\n * Conservative contract for a tool registered without one — MCP servers and\n * third-party extensions cannot supply a `contract`. Full capability set (so it can\n * never widen a delegation ceiling), `ask` by default, never evicted, schema\n * deferred, emits nothing. Matching is exact-argument only: a foreign tool's rule\n * authorizes exactly the call it was generated from, never a pattern.\n *\n * This must also be reported as unclassified wherever a consumer describes the tool\n * registry (contracts.md invariant 1) — a conservative default nobody can see is\n * indistinguishable from a bug.\n */\nexport const UNCLASSIFIED: ToolContract<TSchema, unknown> = {\n\tcapabilities: ALL_CAPABILITIES,\n\tpermission: {\n\t\tdefaultBehavior: \"ask\",\n\t\tmatches: (ruleContent, params) => ruleContent === JSON.stringify(params),\n\t\tdescribe: (ruleContent) => `Exact call: ${ruleContent}`,\n\t\truleForCall: (params) => JSON.stringify(params),\n\t},\n\tcontext: { resultRecoverable: false, deferSchema: false },\n\tevidence: { emits: new Set(), capture: () => [] },\n};\n\n/** Resolve a complete tool contract for enforcement consumers. */\nexport function resolveToolContract(\n\tlookup: (toolName: string) => ToolContract | undefined,\n\ttoolName: string,\n): ToolContract {\n\treturn lookup(toolName) ?? UNCLASSIFIED;\n}\n\n/** Resolve the context projection using the same canonical foreign-tool fallback. */\nexport function resolveToolContext(\n\tlookup: (toolName: string) => Pick<ToolContract, \"context\"> | undefined,\n\ttoolName: string,\n): Pick<ToolContract, \"context\"> {\n\treturn lookup(toolName) ?? UNCLASSIFIED;\n}\n"]}
|