@bastani/atomic 0.9.53-alpha.1 → 0.9.54-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/package.json +1 -1
  4. package/dist/builtin/subagents/package.json +1 -1
  5. package/dist/builtin/web-access/package.json +1 -1
  6. package/dist/builtin/workflows/package.json +1 -1
  7. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  8. package/dist/core/agent-session-auto-compaction.js +2 -1
  9. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  10. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  11. package/dist/core/agent-session-compaction.js +2 -1
  12. package/dist/core/agent-session-compaction.js.map +1 -1
  13. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  14. package/dist/core/agent-session-extension-bindings.js +2 -1
  15. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  16. package/dist/core/agent-session-models.d.ts +17 -1
  17. package/dist/core/agent-session-models.d.ts.map +1 -1
  18. package/dist/core/agent-session-models.js +19 -0
  19. package/dist/core/agent-session-models.js.map +1 -1
  20. package/dist/core/agent-session-post-tool-compaction.d.ts.map +1 -1
  21. package/dist/core/agent-session-post-tool-compaction.js +2 -1
  22. package/dist/core/agent-session-post-tool-compaction.js.map +1 -1
  23. package/dist/core/agent-session-summary.d.ts.map +1 -1
  24. package/dist/core/agent-session-summary.js +2 -1
  25. package/dist/core/agent-session-summary.js.map +1 -1
  26. package/dist/core/agent-session-tree.d.ts.map +1 -1
  27. package/dist/core/agent-session-tree.js +2 -1
  28. package/dist/core/agent-session-tree.js.map +1 -1
  29. package/dist/core/exec.d.ts +9 -1
  30. package/dist/core/exec.d.ts.map +1 -1
  31. package/dist/core/exec.js +109 -74
  32. package/dist/core/exec.js.map +1 -1
  33. package/dist/core/extensions/loader-virtual-modules.js +2 -2
  34. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  35. package/dist/core/model-resolver-patterns.d.ts.map +1 -1
  36. package/dist/core/model-resolver-patterns.js +15 -9
  37. package/dist/core/model-resolver-patterns.js.map +1 -1
  38. package/dist/core/package-manager-auto-resources.d.ts.map +1 -1
  39. package/dist/core/package-manager-auto-resources.js +3 -2
  40. package/dist/core/package-manager-auto-resources.js.map +1 -1
  41. package/dist/core/package-manager-git.d.ts +1 -1
  42. package/dist/core/package-manager-git.d.ts.map +1 -1
  43. package/dist/core/package-manager-git.js +12 -1
  44. package/dist/core/package-manager-git.js.map +1 -1
  45. package/dist/core/package-manager-npm.d.ts +1 -1
  46. package/dist/core/package-manager-npm.d.ts.map +1 -1
  47. package/dist/core/package-manager-npm.js +8 -4
  48. package/dist/core/package-manager-npm.js.map +1 -1
  49. package/dist/core/package-manager-operations.d.ts.map +1 -1
  50. package/dist/core/package-manager-operations.js +33 -8
  51. package/dist/core/package-manager-operations.js.map +1 -1
  52. package/dist/core/package-manager-resolver.d.ts.map +1 -1
  53. package/dist/core/package-manager-resolver.js +22 -4
  54. package/dist/core/package-manager-resolver.js.map +1 -1
  55. package/dist/core/package-manager-resource-accumulator.d.ts.map +1 -1
  56. package/dist/core/package-manager-resource-accumulator.js +4 -4
  57. package/dist/core/package-manager-resource-accumulator.js.map +1 -1
  58. package/dist/core/package-manager-source.js +5 -5
  59. package/dist/core/package-manager-source.js.map +1 -1
  60. package/dist/core/package-manager-types.d.ts +5 -1
  61. package/dist/core/package-manager-types.d.ts.map +1 -1
  62. package/dist/core/package-manager-types.js.map +1 -1
  63. package/dist/core/package-manager.d.ts.map +1 -1
  64. package/dist/core/package-manager.js +3 -3
  65. package/dist/core/package-manager.js.map +1 -1
  66. package/dist/core/project-trust.d.ts.map +1 -1
  67. package/dist/core/project-trust.js +2 -1
  68. package/dist/core/project-trust.js.map +1 -1
  69. package/dist/core/prompt-templates-async.d.ts.map +1 -1
  70. package/dist/core/prompt-templates-async.js +4 -9
  71. package/dist/core/prompt-templates-async.js.map +1 -1
  72. package/dist/core/prompt-templates.d.ts.map +1 -1
  73. package/dist/core/prompt-templates.js +4 -12
  74. package/dist/core/prompt-templates.js.map +1 -1
  75. package/dist/core/resource-loader-extensions.d.ts.map +1 -1
  76. package/dist/core/resource-loader-extensions.js +8 -7
  77. package/dist/core/resource-loader-extensions.js.map +1 -1
  78. package/dist/core/resource-loader-paths.js +5 -5
  79. package/dist/core/resource-loader-paths.js.map +1 -1
  80. package/dist/core/resource-loader-source-info.d.ts +0 -1
  81. package/dist/core/resource-loader-source-info.d.ts.map +1 -1
  82. package/dist/core/resource-loader-source-info.js +6 -17
  83. package/dist/core/resource-loader-source-info.js.map +1 -1
  84. package/dist/core/sdk.d.ts.map +1 -1
  85. package/dist/core/sdk.js +3 -0
  86. package/dist/core/sdk.js.map +1 -1
  87. package/dist/core/session-manager-core.js +2 -2
  88. package/dist/core/session-manager-core.js.map +1 -1
  89. package/dist/core/session-manager-list.js +2 -2
  90. package/dist/core/session-manager-list.js.map +1 -1
  91. package/dist/core/skills-async.d.ts.map +1 -1
  92. package/dist/core/skills-async.js +5 -10
  93. package/dist/core/skills-async.js.map +1 -1
  94. package/dist/core/skills.d.ts.map +1 -1
  95. package/dist/core/skills.js +5 -13
  96. package/dist/core/skills.js.map +1 -1
  97. package/dist/core/source-info.d.ts +2 -0
  98. package/dist/core/source-info.d.ts.map +1 -1
  99. package/dist/core/source-info.js +5 -0
  100. package/dist/core/source-info.js.map +1 -1
  101. package/dist/core/tool-loadout.d.ts +4 -0
  102. package/dist/core/tool-loadout.d.ts.map +1 -1
  103. package/dist/core/tool-loadout.js +7 -1
  104. package/dist/core/tool-loadout.js.map +1 -1
  105. package/dist/core/tools/render-utils.d.ts.map +1 -1
  106. package/dist/core/tools/render-utils.js +2 -7
  107. package/dist/core/tools/render-utils.js.map +1 -1
  108. package/dist/core/trust-manager.d.ts.map +1 -1
  109. package/dist/core/trust-manager.js +15 -9
  110. package/dist/core/trust-manager.js.map +1 -1
  111. package/dist/extensions/codemode/tool.d.ts.map +1 -1
  112. package/dist/extensions/codemode/tool.js +33 -8
  113. package/dist/extensions/codemode/tool.js.map +1 -1
  114. package/dist/main.d.ts.map +1 -1
  115. package/dist/main.js +20 -3
  116. package/dist/main.js.map +1 -1
  117. package/dist/modes/interactive/components/config-selector-list.d.ts.map +1 -1
  118. package/dist/modes/interactive/components/config-selector-list.js +2 -13
  119. package/dist/modes/interactive/components/config-selector-list.js.map +1 -1
  120. package/dist/modes/interactive/components/session-selector-list.js +2 -2
  121. package/dist/modes/interactive/components/session-selector-list.js.map +1 -1
  122. package/dist/modes/interactive/components/session-selector-tree.d.ts.map +1 -1
  123. package/dist/modes/interactive/components/session-selector-tree.js +4 -6
  124. package/dist/modes/interactive/components/session-selector-tree.js.map +1 -1
  125. package/dist/modes/interactive/components/session-selector-utils.d.ts +2 -1
  126. package/dist/modes/interactive/components/session-selector-utils.d.ts.map +1 -1
  127. package/dist/modes/interactive/components/session-selector-utils.js +5 -13
  128. package/dist/modes/interactive/components/session-selector-utils.js.map +1 -1
  129. package/dist/modes/interactive/components/tree-selector-content.d.ts.map +1 -1
  130. package/dist/modes/interactive/components/tree-selector-content.js +2 -6
  131. package/dist/modes/interactive/components/tree-selector-content.js.map +1 -1
  132. package/dist/modes/interactive/interactive-mode-base.d.ts +2 -0
  133. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  134. package/dist/modes/interactive/interactive-mode-base.js +4 -0
  135. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  136. package/dist/modes/interactive/interactive-mode-surface.d.ts +1 -0
  137. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  138. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  139. package/dist/modes/interactive/interactive-mode-types.d.ts +6 -0
  140. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  141. package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
  142. package/dist/modes/interactive/interactive-resource-rendering.js +1 -1
  143. package/dist/modes/interactive/interactive-resource-rendering.js.map +1 -1
  144. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  145. package/dist/modes/interactive/interactive-startup.js +15 -8
  146. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  147. package/dist/modes/interactive/interactive-tui.d.ts +1 -0
  148. package/dist/modes/interactive/interactive-tui.d.ts.map +1 -1
  149. package/dist/modes/interactive/interactive-tui.js +1 -1
  150. package/dist/modes/interactive/interactive-tui.js.map +1 -1
  151. package/dist/package-manager-cli.d.ts.map +1 -1
  152. package/dist/package-manager-cli.js +3 -0
  153. package/dist/package-manager-cli.js.map +1 -1
  154. package/dist/utils/ansi.d.ts.map +1 -1
  155. package/dist/utils/ansi.js +5 -2
  156. package/dist/utils/ansi.js.map +1 -1
  157. package/dist/utils/git.d.ts +1 -1
  158. package/dist/utils/git.d.ts.map +1 -1
  159. package/dist/utils/git.js.map +1 -1
  160. package/dist/utils/image-resize-core.d.ts.map +1 -1
  161. package/dist/utils/image-resize-core.js +5 -3
  162. package/dist/utils/image-resize-core.js.map +1 -1
  163. package/dist/utils/paths.d.ts +14 -0
  164. package/dist/utils/paths.d.ts.map +1 -1
  165. package/dist/utils/paths.js +39 -1
  166. package/dist/utils/paths.js.map +1 -1
  167. package/docs/extensions/api-reference.md +4 -2
  168. package/docs/packages.md +2 -0
  169. package/npm-shrinkwrap.json +32 -32
  170. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"skills-async.js","sourceRoot":"","sources":["../../src/core/skills-async.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, readdir, readFile, stat } from \"node:fs/promises\";\nimport { basename, dirname, join, relative, resolve, sep } from \"node:path\";\nimport ignore from \"ignore\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.js\";\nimport { yieldToEventLoopIfSlow } from \"../utils/event-loop.ts\";\nimport { parseFrontmatter } from \"../utils/frontmatter.ts\";\nimport { canonicalizePath, resolvePath } from \"../utils/paths.ts\";\nimport type { ResourceDiagnostic } from \"./diagnostics.ts\";\nimport type { LoadSkillsOptions, LoadSkillsResult, Skill, SkillFrontmatter } from \"./skills.ts\";\nimport { createSyntheticSourceInfo, type SourceInfo } from \"./source-info.ts\";\n\nconst MAX_NAME_LENGTH = 64;\nconst MAX_DESCRIPTION_LENGTH = 1024;\nconst IGNORE_FILE_NAMES = [\".gitignore\", \".ignore\", \".fdignore\"];\nconst YIELD_AFTER_MS = 8;\ntype IgnoreMatcher = ReturnType<typeof ignore>;\n\nasync function exists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction toPosixPath(path: string): string {\n\treturn path.split(sep).join(\"/\");\n}\n\nfunction prefixIgnorePattern(line: string, prefix: string): string | null {\n\tconst trimmed = line.trim();\n\tif (!trimmed || (trimmed.startsWith(\"#\") && !trimmed.startsWith(\"\\\\#\"))) return null;\n\tlet pattern = line;\n\tlet negated = false;\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\tif (pattern.startsWith(\"/\")) pattern = pattern.slice(1);\n\tconst prefixed = prefix ? `${prefix}${pattern}` : pattern;\n\treturn negated ? `!${prefixed}` : prefixed;\n}\n\nasync function addIgnoreRules(ig: IgnoreMatcher, dir: string, rootDir: string): Promise<void> {\n\tconst relativeDir = relative(rootDir, dir);\n\tconst prefix = relativeDir ? `${toPosixPath(relativeDir)}/` : \"\";\n\tfor (const filename of IGNORE_FILE_NAMES) {\n\t\tconst ignorePath = join(dir, filename);\n\t\ttry {\n\t\t\tconst content = await readFile(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) ig.add(patterns);\n\t\t} catch {}\n\t}\n}\n\nfunction createSkillSourceInfo(filePath: string, baseDir: string, source: string): SourceInfo {\n\tswitch (source) {\n\t\tcase \"user\":\n\t\t\treturn createSyntheticSourceInfo(filePath, { source: \"local\", scope: \"user\", baseDir });\n\t\tcase \"project\":\n\t\t\treturn createSyntheticSourceInfo(filePath, { source: \"local\", scope: \"project\", baseDir });\n\t\tcase \"path\":\n\t\t\treturn createSyntheticSourceInfo(filePath, { source: \"local\", baseDir });\n\t\tdefault:\n\t\t\treturn createSyntheticSourceInfo(filePath, { source, baseDir });\n\t}\n}\n\nfunction validateName(name: string): string[] {\n\tconst errors: string[] = [];\n\tif (name.length > MAX_NAME_LENGTH) errors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);\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\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) errors.push(\"name must not start or end with a hyphen\");\n\tif (name.includes(\"--\")) errors.push(\"name must not contain consecutive hyphens\");\n\treturn errors;\n}\n\nfunction validateDescription(description: string | undefined): string[] {\n\tif (!description || description.trim() === \"\") return [\"description is required\"];\n\tif (description.length > MAX_DESCRIPTION_LENGTH) {\n\t\treturn [`description exceeds ${MAX_DESCRIPTION_LENGTH} characters (${description.length})`];\n\t}\n\treturn [];\n}\n\nasync function loadSkillFromFile(\n\tfilePath: string,\n\tsource: string,\n): Promise<{ skill: Skill | null; diagnostics: ResourceDiagnostic[] }> {\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\ttry {\n\t\tconst rawContent = await readFile(filePath, \"utf-8\");\n\t\tconst { frontmatter } = parseFrontmatter<SkillFrontmatter>(rawContent);\n\t\tconst skillDir = dirname(filePath);\n\t\tfor (const error of validateDescription(frontmatter.description))\n\t\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t\tconst name = frontmatter.name || basename(skillDir);\n\t\tfor (const error of validateName(name)) diagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t\tif (!frontmatter.description || frontmatter.description.trim() === \"\") return { skill: null, diagnostics };\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\nasync function loadSkillsFromDirInternal(\n\tdir: string,\n\tsource: string,\n\tincludeRootFiles: boolean,\n\tignoreMatcher?: IgnoreMatcher,\n\trootDir?: string,\n): Promise<LoadSkillsResult> {\n\tconst skills: Skill[] = [];\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\tif (!(await exists(dir))) return { skills, candidates: skills, diagnostics };\n\tconst startedAt = Date.now();\n\tconst root = rootDir ?? dir;\n\tconst ig = ignoreMatcher ?? ignore();\n\tawait addIgnoreRules(ig, dir, root);\n\ttry {\n\t\tconst entries = await readdir(dir, { withFileTypes: true });\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.name !== \"SKILL.md\") continue;\n\t\t\tconst fullPath = join(dir, entry.name);\n\t\t\tlet isFile = entry.isFile();\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\ttry {\n\t\t\t\t\tisFile = (await stat(fullPath)).isFile();\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst relPath = toPosixPath(relative(root, fullPath));\n\t\t\tif (!isFile || ig.ignores(relPath)) continue;\n\t\t\tconst result = await loadSkillFromFile(fullPath, source);\n\t\t\tif (result.skill) skills.push(result.skill);\n\t\t\tdiagnostics.push(...result.diagnostics);\n\t\t\treturn { skills, candidates: skills, diagnostics };\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tawait yieldToEventLoopIfSlow(startedAt, YIELD_AFTER_MS);\n\t\t\tif (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n\t\t\tconst fullPath = join(dir, entry.name);\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 = await stat(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\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst relPath = toPosixPath(relative(root, fullPath));\n\t\t\tif (ig.ignores(isDirectory ? `${relPath}/` : relPath)) continue;\n\t\t\tif (isDirectory) {\n\t\t\t\tconst subResult = await 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\t\t\tif (!isFile || !includeRootFiles || !entry.name.endsWith(\".md\")) continue;\n\t\t\tconst result = await loadSkillFromFile(fullPath, source);\n\t\t\tif (result.skill) skills.push(result.skill);\n\t\t\tdiagnostics.push(...result.diagnostics);\n\t\t}\n\t} catch {}\n\treturn { skills, candidates: skills, diagnostics };\n}\n\nexport async function loadSkillsAsync(options: LoadSkillsOptions): Promise<LoadSkillsResult> {\n\tconst { agentDir, skillPaths, includeDefaults } = options;\n\tconst resolvedCwd = resolvePath(options.cwd);\n\tconst resolvedAgentDir = resolvePath(agentDir ?? getAgentDir());\n\tconst skillMap = new Map<string, Skill>();\n\tconst candidates: Skill[] = [];\n\tconst realPathSet = new Set<string>();\n\tconst allDiagnostics: ResourceDiagnostic[] = [];\n\tconst collisionDiagnostics: ResourceDiagnostic[] = [];\n\tconst userSkillsDir = join(resolvedAgentDir, \"skills\");\n\tconst projectSkillsDir = resolve(resolvedCwd, CONFIG_DIR_NAME, \"skills\");\n\tconst addSkills = (result: LoadSkillsResult) => {\n\t\tallDiagnostics.push(...result.diagnostics);\n\t\tfor (const skill of result.skills) {\n\t\t\tconst realPath = canonicalizePath(skill.filePath);\n\t\t\tif (realPathSet.has(realPath)) continue;\n\t\t\trealPathSet.add(realPath);\n\t\t\tcandidates.push(skill);\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}\n\t\t}\n\t};\n\tif (includeDefaults) {\n\t\taddSkills(await loadSkillsFromDirInternal(userSkillsDir, \"user\", true));\n\t\taddSkills(await loadSkillsFromDirInternal(projectSkillsDir, \"project\", true));\n\t}\n\tconst isUnderPath = (target: string, root: string): boolean => {\n\t\tconst normalizedRoot = resolve(root);\n\t\treturn (\n\t\t\ttarget === normalizedRoot ||\n\t\t\ttarget.startsWith(normalizedRoot.endsWith(sep) ? normalizedRoot : `${normalizedRoot}${sep}`)\n\t\t);\n\t};\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\tconst startedAt = Date.now();\n\tfor (const rawPath of skillPaths) {\n\t\tawait yieldToEventLoopIfSlow(startedAt, YIELD_AFTER_MS);\n\t\tconst resolvedPath = resolvePath(rawPath, resolvedCwd, { trim: true });\n\t\tif (!(await exists(resolvedPath))) {\n\t\t\tallDiagnostics.push({ type: \"warning\", message: \"skill path does not exist\", path: resolvedPath });\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\tconst stats = await stat(resolvedPath);\n\t\t\tconst source = getSource(resolvedPath);\n\t\t\tif (stats.isDirectory()) {\n\t\t\t\taddSkills(await loadSkillsFromDirInternal(resolvedPath, source, true));\n\t\t\t} else if (stats.isFile() && resolvedPath.endsWith(\".md\")) {\n\t\t\t\tconst result = await loadSkillFromFile(resolvedPath, source);\n\t\t\t\tif (result.skill)\n\t\t\t\t\taddSkills({ skills: [result.skill], candidates: [result.skill], diagnostics: result.diagnostics });\n\t\t\t\telse allDiagnostics.push(...result.diagnostics);\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\treturn {\n\t\tskills: Array.from(skillMap.values()),\n\t\tcandidates,\n\t\tdiagnostics: [...allDiagnostics, ...collisionDiagnostics],\n\t};\n}\n"]}
1
+ {"version":3,"file":"skills-async.js","sourceRoot":"","sources":["../../src/core/skills-async.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, readdir, readFile, stat } from \"node:fs/promises\";\nimport { basename, dirname, join, relative, resolve, sep } from \"node:path\";\nimport ignore from \"ignore\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.js\";\nimport { yieldToEventLoopIfSlow } from \"../utils/event-loop.ts\";\nimport { parseFrontmatter } from \"../utils/frontmatter.ts\";\nimport { isPathWithin, resolvePath } from \"../utils/paths.ts\";\nimport type { ResourceDiagnostic } from \"./diagnostics.ts\";\nimport type { LoadSkillsOptions, LoadSkillsResult, Skill, SkillFrontmatter } from \"./skills.ts\";\nimport { createSyntheticSourceInfo, getResourcePathKey, type SourceInfo } from \"./source-info.ts\";\n\nconst MAX_NAME_LENGTH = 64;\nconst MAX_DESCRIPTION_LENGTH = 1024;\nconst IGNORE_FILE_NAMES = [\".gitignore\", \".ignore\", \".fdignore\"];\nconst YIELD_AFTER_MS = 8;\ntype IgnoreMatcher = ReturnType<typeof ignore>;\n\nasync function exists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction toPosixPath(path: string): string {\n\treturn path.split(sep).join(\"/\");\n}\n\nfunction prefixIgnorePattern(line: string, prefix: string): string | null {\n\tconst trimmed = line.trim();\n\tif (!trimmed || (trimmed.startsWith(\"#\") && !trimmed.startsWith(\"\\\\#\"))) return null;\n\tlet pattern = line;\n\tlet negated = false;\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\tif (pattern.startsWith(\"/\")) pattern = pattern.slice(1);\n\tconst prefixed = prefix ? `${prefix}${pattern}` : pattern;\n\treturn negated ? `!${prefixed}` : prefixed;\n}\n\nasync function addIgnoreRules(ig: IgnoreMatcher, dir: string, rootDir: string): Promise<void> {\n\tconst relativeDir = relative(rootDir, dir);\n\tconst prefix = relativeDir ? `${toPosixPath(relativeDir)}/` : \"\";\n\tfor (const filename of IGNORE_FILE_NAMES) {\n\t\tconst ignorePath = join(dir, filename);\n\t\ttry {\n\t\t\tconst content = await readFile(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) ig.add(patterns);\n\t\t} catch {}\n\t}\n}\n\nfunction createSkillSourceInfo(filePath: string, baseDir: string, source: string): SourceInfo {\n\tswitch (source) {\n\t\tcase \"user\":\n\t\t\treturn createSyntheticSourceInfo(filePath, { source: \"local\", scope: \"user\", baseDir });\n\t\tcase \"project\":\n\t\t\treturn createSyntheticSourceInfo(filePath, { source: \"local\", scope: \"project\", baseDir });\n\t\tcase \"path\":\n\t\t\treturn createSyntheticSourceInfo(filePath, { source: \"local\", baseDir });\n\t\tdefault:\n\t\t\treturn createSyntheticSourceInfo(filePath, { source, baseDir });\n\t}\n}\n\nfunction validateName(name: string): string[] {\n\tconst errors: string[] = [];\n\tif (name.length > MAX_NAME_LENGTH) errors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);\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\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) errors.push(\"name must not start or end with a hyphen\");\n\tif (name.includes(\"--\")) errors.push(\"name must not contain consecutive hyphens\");\n\treturn errors;\n}\n\nfunction validateDescription(description: string | undefined): string[] {\n\tif (!description || description.trim() === \"\") return [\"description is required\"];\n\tif (description.length > MAX_DESCRIPTION_LENGTH) {\n\t\treturn [`description exceeds ${MAX_DESCRIPTION_LENGTH} characters (${description.length})`];\n\t}\n\treturn [];\n}\n\nasync function loadSkillFromFile(\n\tfilePath: string,\n\tsource: string,\n): Promise<{ skill: Skill | null; diagnostics: ResourceDiagnostic[] }> {\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\ttry {\n\t\tconst rawContent = await readFile(filePath, \"utf-8\");\n\t\tconst { frontmatter } = parseFrontmatter<SkillFrontmatter>(rawContent);\n\t\tconst skillDir = dirname(filePath);\n\t\tfor (const error of validateDescription(frontmatter.description))\n\t\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t\tconst name = frontmatter.name || basename(skillDir);\n\t\tfor (const error of validateName(name)) diagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t\tif (!frontmatter.description || frontmatter.description.trim() === \"\") return { skill: null, diagnostics };\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\nasync function loadSkillsFromDirInternal(\n\tdir: string,\n\tsource: string,\n\tincludeRootFiles: boolean,\n\tignoreMatcher?: IgnoreMatcher,\n\trootDir?: string,\n): Promise<LoadSkillsResult> {\n\tconst skills: Skill[] = [];\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\tif (!(await exists(dir))) return { skills, candidates: skills, diagnostics };\n\tconst startedAt = Date.now();\n\tconst root = rootDir ?? dir;\n\tconst ig = ignoreMatcher ?? ignore();\n\tawait addIgnoreRules(ig, dir, root);\n\ttry {\n\t\tconst entries = await readdir(dir, { withFileTypes: true });\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.name !== \"SKILL.md\") continue;\n\t\t\tconst fullPath = join(dir, entry.name);\n\t\t\tlet isFile = entry.isFile();\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\ttry {\n\t\t\t\t\tisFile = (await stat(fullPath)).isFile();\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst relPath = toPosixPath(relative(root, fullPath));\n\t\t\tif (!isFile || ig.ignores(relPath)) continue;\n\t\t\tconst result = await loadSkillFromFile(fullPath, source);\n\t\t\tif (result.skill) skills.push(result.skill);\n\t\t\tdiagnostics.push(...result.diagnostics);\n\t\t\treturn { skills, candidates: skills, diagnostics };\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tawait yieldToEventLoopIfSlow(startedAt, YIELD_AFTER_MS);\n\t\t\tif (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n\t\t\tconst fullPath = join(dir, entry.name);\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 = await stat(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\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst relPath = toPosixPath(relative(root, fullPath));\n\t\t\tif (ig.ignores(isDirectory ? `${relPath}/` : relPath)) continue;\n\t\t\tif (isDirectory) {\n\t\t\t\tconst subResult = await 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\t\t\tif (!isFile || !includeRootFiles || !entry.name.endsWith(\".md\")) continue;\n\t\t\tconst result = await loadSkillFromFile(fullPath, source);\n\t\t\tif (result.skill) skills.push(result.skill);\n\t\t\tdiagnostics.push(...result.diagnostics);\n\t\t}\n\t} catch {}\n\treturn { skills, candidates: skills, diagnostics };\n}\n\nexport async function loadSkillsAsync(options: LoadSkillsOptions): Promise<LoadSkillsResult> {\n\tconst { agentDir, skillPaths, includeDefaults } = options;\n\tconst resolvedCwd = resolvePath(options.cwd);\n\tconst resolvedAgentDir = resolvePath(agentDir ?? getAgentDir());\n\tconst skillMap = new Map<string, Skill>();\n\tconst candidates: Skill[] = [];\n\tconst realPathSet = new Set<string>();\n\tconst allDiagnostics: ResourceDiagnostic[] = [];\n\tconst collisionDiagnostics: ResourceDiagnostic[] = [];\n\tconst userSkillsDir = join(resolvedAgentDir, \"skills\");\n\tconst projectSkillsDir = resolve(resolvedCwd, CONFIG_DIR_NAME, \"skills\");\n\tconst addSkills = (result: LoadSkillsResult) => {\n\t\tallDiagnostics.push(...result.diagnostics);\n\t\tfor (const skill of result.skills) {\n\t\t\tconst realPath = getResourcePathKey(skill.filePath);\n\t\t\tif (realPathSet.has(realPath)) continue;\n\t\t\trealPathSet.add(realPath);\n\t\t\tcandidates.push(skill);\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}\n\t\t}\n\t};\n\tif (includeDefaults) {\n\t\taddSkills(await loadSkillsFromDirInternal(userSkillsDir, \"user\", true));\n\t\taddSkills(await loadSkillsFromDirInternal(projectSkillsDir, \"project\", true));\n\t}\n\tconst getSource = (resolvedPath: string): \"user\" | \"project\" | \"path\" => {\n\t\tif (!includeDefaults) {\n\t\t\tif (isPathWithin(userSkillsDir, resolvedPath)) return \"user\";\n\t\t\tif (isPathWithin(projectSkillsDir, resolvedPath)) return \"project\";\n\t\t}\n\t\treturn \"path\";\n\t};\n\tconst startedAt = Date.now();\n\tfor (const rawPath of skillPaths) {\n\t\tawait yieldToEventLoopIfSlow(startedAt, YIELD_AFTER_MS);\n\t\tconst resolvedPath = resolvePath(rawPath, resolvedCwd, { trim: true });\n\t\tif (!(await exists(resolvedPath))) {\n\t\t\tallDiagnostics.push({ type: \"warning\", message: \"skill path does not exist\", path: resolvedPath });\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\tconst stats = await stat(resolvedPath);\n\t\t\tconst source = getSource(resolvedPath);\n\t\t\tif (stats.isDirectory()) {\n\t\t\t\taddSkills(await loadSkillsFromDirInternal(resolvedPath, source, true));\n\t\t\t} else if (stats.isFile() && resolvedPath.endsWith(\".md\")) {\n\t\t\t\tconst result = await loadSkillFromFile(resolvedPath, source);\n\t\t\t\tif (result.skill)\n\t\t\t\t\taddSkills({ skills: [result.skill], candidates: [result.skill], diagnostics: result.diagnostics });\n\t\t\t\telse allDiagnostics.push(...result.diagnostics);\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\treturn {\n\t\tskills: Array.from(skillMap.values()),\n\t\tcandidates,\n\t\tdiagnostics: [...allDiagnostics, ...collisionDiagnostics],\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAA6B,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AA2D9E,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,KAAK;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,sBAAsB,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,0FAA0F;IAC1F,UAAU,EAAE,KAAK,EAAE,CAAC;IACpB,WAAW,EAAE,kBAAkB,EAAE,CAAC;CAClC;AA2CD,MAAM,WAAW,wBAAwB;IACxC,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;CACf;AA0BD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,gBAAgB,CAGrF;AAgLD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,YAAY,GAAE,MAAM,GAAG,MAAM,GAAG,UAAmB,GAAG,MAAM,CA8BlH;AAWD,MAAM,WAAW,iBAAiB;IACjC,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,0CAA0C;IAC1C,eAAe,EAAE,OAAO,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CAuGvE"}
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAiD,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AA2DlG,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,KAAK;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,sBAAsB,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,0FAA0F;IAC1F,UAAU,EAAE,KAAK,EAAE,CAAC;IACpB,WAAW,EAAE,kBAAkB,EAAE,CAAC;CAClC;AA2CD,MAAM,WAAW,wBAAwB;IACxC,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;CACf;AA0BD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,gBAAgB,CAGrF;AAgLD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,YAAY,GAAE,MAAM,GAAG,MAAM,GAAG,UAAmB,GAAG,MAAM,CA8BlH;AAWD,MAAM,WAAW,iBAAiB;IACjC,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,0CAA0C;IAC1C,eAAe,EAAE,OAAO,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CA8FvE"}
@@ -3,8 +3,8 @@ import ignore from "ignore";
3
3
  import { basename, dirname, join, relative, resolve, sep } from "path";
4
4
  import { CONFIG_DIR_NAME, getAgentDir } from "../config.js";
5
5
  import { parseFrontmatter } from "../utils/frontmatter.js";
6
- import { canonicalizePath, resolvePath } from "../utils/paths.js";
7
- import { createSyntheticSourceInfo } from "./source-info.js";
6
+ import { isPathWithin, resolvePath } from "../utils/paths.js";
7
+ import { createSyntheticSourceInfo, getResourcePathKey } from "./source-info.js";
8
8
  /** Max name length per spec */
9
9
  const MAX_NAME_LENGTH = 64;
10
10
  /** Max description length per spec */
@@ -324,7 +324,7 @@ export function loadSkills(options) {
324
324
  allDiagnostics.push(...result.diagnostics);
325
325
  for (const skill of result.skills) {
326
326
  // Resolve symlinks to detect duplicate files
327
- const realPath = canonicalizePath(skill.filePath);
327
+ const realPath = getResourcePathKey(skill.filePath);
328
328
  // Skip silently if we've already loaded this exact file (via symlink)
329
329
  if (realPathSet.has(realPath)) {
330
330
  continue;
@@ -356,19 +356,11 @@ export function loadSkills(options) {
356
356
  }
357
357
  const userSkillsDir = join(resolvedAgentDir, "skills");
358
358
  const projectSkillsDir = resolve(resolvedCwd, CONFIG_DIR_NAME, "skills");
359
- const isUnderPath = (target, root) => {
360
- const normalizedRoot = resolve(root);
361
- if (target === normalizedRoot) {
362
- return true;
363
- }
364
- const prefix = normalizedRoot.endsWith(sep) ? normalizedRoot : `${normalizedRoot}${sep}`;
365
- return target.startsWith(prefix);
366
- };
367
359
  const getSource = (resolvedPath) => {
368
360
  if (!includeDefaults) {
369
- if (isUnderPath(resolvedPath, userSkillsDir))
361
+ if (isPathWithin(userSkillsDir, resolvedPath))
370
362
  return "user";
371
- if (isUnderPath(resolvedPath, projectSkillsDir))
363
+ if (isPathWithin(projectSkillsDir, resolvedPath))
372
364
  return "project";
373
365
  }
374
366
  return "path";
@@ -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.js\";\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\t/** Every distinct real skill file in discovery order, including name-collision losers. */\n\tcandidates: 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: unknown): string[] {\n\tconst errors: string[] = [];\n\n\tif (typeof description !== \"string\" || 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, candidates: 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, candidates: 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, candidates: skills, diagnostics };\n}\n\nfunction loadSkillFromFile(\n\tfilePath: string,\n\tsource: string,\n): { skill: Skill | null; diagnostics: ResourceDiagnostic[] } {\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\tconst isDeclaredSkill = basename(filePath) === \"SKILL.md\";\n\n\tlet rawContent: string;\n\ttry {\n\t\trawContent = readFileSync(filePath, \"utf-8\");\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : \"failed to read skill file\";\n\t\tdiagnostics.push({ type: \"warning\", message, path: filePath });\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\tlet frontmatter: SkillFrontmatter;\n\ttry {\n\t\t({ frontmatter } = parseFrontmatter<SkillFrontmatter>(rawContent));\n\t} catch (error) {\n\t\tif (isDeclaredSkill) {\n\t\t\tconst message = error instanceof Error ? error.message : \"failed to parse skill file\";\n\t\t\tdiagnostics.push({ type: \"warning\", message, path: filePath });\n\t\t}\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\tconst description = frontmatter.description;\n\tconst hasDescription = typeof description === \"string\" && description.trim() !== \"\";\n\tif (!isDeclaredSkill && !hasDescription) {\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\tconst skillDir = dirname(filePath);\n\tconst parentDirName = basename(skillDir);\n\n\t// Validate description\n\tconst descErrors = validateDescription(description);\n\tfor (const error of descErrors) {\n\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t}\n\n\t// Use name from frontmatter, or fall back to parent directory name\n\tconst frontmatterName = typeof frontmatter.name === \"string\" ? frontmatter.name : undefined;\n\tconst name = frontmatterName || parentDirName;\n\n\t// Validate name\n\tconst nameErrors = validateName(name);\n\tfor (const error of nameErrors) {\n\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t}\n\n\t// Still load the skill even with warnings, unless description is missing or empty.\n\tif (!hasDescription) {\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\treturn {\n\t\tskill: {\n\t\t\tname,\n\t\t\tdescription,\n\t\t\tfilePath,\n\t\t\tbaseDir: skillDir,\n\t\t\tsourceInfo: createSkillSourceInfo(filePath, skillDir, source),\n\t\t\tdisableModelInvocation: frontmatter[\"disable-model-invocation\"] === true,\n\t\t},\n\t\tdiagnostics,\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[], fileReadTool: \"read\" | \"bash\" | \"indirect\" = \"read\"): 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\tfileReadTool === \"read\"\n\t\t\t? \"Use the read tool to load a skill's file when the task matches its description.\"\n\t\t\t: fileReadTool === \"bash\"\n\t\t\t\t? \"Use bash to load a skill's file when the task matches its description.\"\n\t\t\t\t: \"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, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t.replace(/\"/g, \"&quot;\")\n\t\t.replace(/'/g, \"&apos;\");\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 candidates: 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\t\t\trealPathSet.add(realPath);\n\t\t\tcandidates.push(skill);\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}\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], candidates: [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\tcandidates,\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.js\";\nimport { parseFrontmatter } from \"../utils/frontmatter.ts\";\nimport { isPathWithin, resolvePath } from \"../utils/paths.ts\";\nimport type { ResourceDiagnostic } from \"./diagnostics.ts\";\nimport { createSyntheticSourceInfo, getResourcePathKey, 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\t/** Every distinct real skill file in discovery order, including name-collision losers. */\n\tcandidates: 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: unknown): string[] {\n\tconst errors: string[] = [];\n\n\tif (typeof description !== \"string\" || 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, candidates: 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, candidates: 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, candidates: skills, diagnostics };\n}\n\nfunction loadSkillFromFile(\n\tfilePath: string,\n\tsource: string,\n): { skill: Skill | null; diagnostics: ResourceDiagnostic[] } {\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\tconst isDeclaredSkill = basename(filePath) === \"SKILL.md\";\n\n\tlet rawContent: string;\n\ttry {\n\t\trawContent = readFileSync(filePath, \"utf-8\");\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : \"failed to read skill file\";\n\t\tdiagnostics.push({ type: \"warning\", message, path: filePath });\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\tlet frontmatter: SkillFrontmatter;\n\ttry {\n\t\t({ frontmatter } = parseFrontmatter<SkillFrontmatter>(rawContent));\n\t} catch (error) {\n\t\tif (isDeclaredSkill) {\n\t\t\tconst message = error instanceof Error ? error.message : \"failed to parse skill file\";\n\t\t\tdiagnostics.push({ type: \"warning\", message, path: filePath });\n\t\t}\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\tconst description = frontmatter.description;\n\tconst hasDescription = typeof description === \"string\" && description.trim() !== \"\";\n\tif (!isDeclaredSkill && !hasDescription) {\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\tconst skillDir = dirname(filePath);\n\tconst parentDirName = basename(skillDir);\n\n\t// Validate description\n\tconst descErrors = validateDescription(description);\n\tfor (const error of descErrors) {\n\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t}\n\n\t// Use name from frontmatter, or fall back to parent directory name\n\tconst frontmatterName = typeof frontmatter.name === \"string\" ? frontmatter.name : undefined;\n\tconst name = frontmatterName || parentDirName;\n\n\t// Validate name\n\tconst nameErrors = validateName(name);\n\tfor (const error of nameErrors) {\n\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t}\n\n\t// Still load the skill even with warnings, unless description is missing or empty.\n\tif (!hasDescription) {\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\treturn {\n\t\tskill: {\n\t\t\tname,\n\t\t\tdescription,\n\t\t\tfilePath,\n\t\t\tbaseDir: skillDir,\n\t\t\tsourceInfo: createSkillSourceInfo(filePath, skillDir, source),\n\t\t\tdisableModelInvocation: frontmatter[\"disable-model-invocation\"] === true,\n\t\t},\n\t\tdiagnostics,\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[], fileReadTool: \"read\" | \"bash\" | \"indirect\" = \"read\"): 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\tfileReadTool === \"read\"\n\t\t\t? \"Use the read tool to load a skill's file when the task matches its description.\"\n\t\t\t: fileReadTool === \"bash\"\n\t\t\t\t? \"Use bash to load a skill's file when the task matches its description.\"\n\t\t\t\t: \"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, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t.replace(/\"/g, \"&quot;\")\n\t\t.replace(/'/g, \"&apos;\");\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 candidates: 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 = getResourcePathKey(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\t\t\trealPathSet.add(realPath);\n\t\t\tcandidates.push(skill);\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}\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 getSource = (resolvedPath: string): \"user\" | \"project\" | \"path\" => {\n\t\tif (!includeDefaults) {\n\t\t\tif (isPathWithin(userSkillsDir, resolvedPath)) return \"user\";\n\t\t\tif (isPathWithin(projectSkillsDir, resolvedPath)) 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], candidates: [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\tcandidates,\n\t\tdiagnostics: [...allDiagnostics, ...collisionDiagnostics],\n\t};\n}\n"]}
@@ -12,6 +12,8 @@ export interface SourceInfo {
12
12
  export declare const BUILTIN_PATH_PREFIX = "builtin:";
13
13
  export declare function getSyntheticPathSource(path: string): string | undefined;
14
14
  export declare function isSyntheticPath(path: string): boolean;
15
+ /** Key for deduplicating resource paths: synthetic paths as-is, file paths via realpath and platform casing. */
16
+ export declare function getResourcePathKey(path: string): string;
15
17
  export declare function createSourceInfo(path: string, metadata: PathMetadata): SourceInfo;
16
18
  export declare function createSyntheticSourceInfo(path: string, options: {
17
19
  source: string;
@@ -1 +1 @@
1
- {"version":3,"file":"source-info.d.ts","sourceRoot":"","sources":["../../src/core/source-info.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAEtF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;AAC3D,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,CAAC;AAEnD,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,2BAA2B,CAAC;CAClD;AAED,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAE9C,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIvE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,UAAU,CASjF;AAED,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;IACR,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,2BAA2B,CAAC;CAClD,GACC,UAAU,CASZ"}
1
+ {"version":3,"file":"source-info.d.ts","sourceRoot":"","sources":["../../src/core/source-info.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAEtF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;AAC3D,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,CAAC;AAEnD,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,2BAA2B,CAAC;CAClD;AAED,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAE9C,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIvE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,gHAAgH;AAChH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,UAAU,CASjF;AAED,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;IACR,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,2BAA2B,CAAC;CAClD,GACC,UAAU,CASZ"}
@@ -1,3 +1,4 @@
1
+ import { canonicalizePath, getPathComparisonKey } from "../utils/paths.js";
1
2
  export const BUILTIN_PATH_PREFIX = "builtin:";
2
3
  export function getSyntheticPathSource(path) {
3
4
  if (path.startsWith(BUILTIN_PATH_PREFIX))
@@ -9,6 +10,10 @@ export function getSyntheticPathSource(path) {
9
10
  export function isSyntheticPath(path) {
10
11
  return path.startsWith(BUILTIN_PATH_PREFIX) || path.startsWith("<");
11
12
  }
13
+ /** Key for deduplicating resource paths: synthetic paths as-is, file paths via realpath and platform casing. */
14
+ export function getResourcePathKey(path) {
15
+ return isSyntheticPath(path) ? path : getPathComparisonKey(canonicalizePath(path));
16
+ }
12
17
  export function createSourceInfo(path, metadata) {
13
18
  return {
14
19
  path,
@@ -1 +1 @@
1
- {"version":3,"file":"source-info.js","sourceRoot":"","sources":["../../src/core/source-info.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAE9C,MAAM,UAAU,sBAAsB,CAAC,IAAY;IAClD,IAAI,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3D,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC;IACtG,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,QAAsB;IACpE,OAAO;QACN,IAAI;QACJ,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB;KACjD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,yBAAyB,CACxC,IAAY,EACZ,OAMC;IAED,OAAO;QACN,IAAI;QACJ,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,WAAW;QACnC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,WAAW;QACrC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;KAChD,CAAC;AACH,CAAC","sourcesContent":["import type { PathMetadata, ResourceConfigurationOrigin } from \"./package-manager.ts\";\n\nexport type SourceScope = \"user\" | \"project\" | \"temporary\";\nexport type SourceOrigin = \"package\" | \"top-level\";\n\nexport interface SourceInfo {\n\tpath: string;\n\tsource: string;\n\tscope: SourceScope;\n\torigin: SourceOrigin;\n\tbaseDir?: string;\n\tconfigurationOrigin?: ResourceConfigurationOrigin;\n}\n\nexport const BUILTIN_PATH_PREFIX = \"builtin:\";\n\nexport function getSyntheticPathSource(path: string): string | undefined {\n\tif (path.startsWith(BUILTIN_PATH_PREFIX)) return \"builtin\";\n\tif (path.startsWith(\"<\") && path.endsWith(\">\")) return path.slice(1, -1).split(\":\")[0] || \"temporary\";\n\treturn undefined;\n}\n\nexport function isSyntheticPath(path: string): boolean {\n\treturn path.startsWith(BUILTIN_PATH_PREFIX) || path.startsWith(\"<\");\n}\n\nexport function createSourceInfo(path: string, metadata: PathMetadata): SourceInfo {\n\treturn {\n\t\tpath,\n\t\tsource: metadata.source,\n\t\tscope: metadata.scope,\n\t\torigin: metadata.origin,\n\t\tbaseDir: metadata.baseDir,\n\t\tconfigurationOrigin: metadata.configurationOrigin,\n\t};\n}\n\nexport function createSyntheticSourceInfo(\n\tpath: string,\n\toptions: {\n\t\tsource: string;\n\t\tscope?: SourceScope;\n\t\torigin?: SourceOrigin;\n\t\tbaseDir?: string;\n\t\tconfigurationOrigin?: ResourceConfigurationOrigin;\n\t},\n): SourceInfo {\n\treturn {\n\t\tpath,\n\t\tsource: options.source,\n\t\tscope: options.scope ?? \"temporary\",\n\t\torigin: options.origin ?? \"top-level\",\n\t\tbaseDir: options.baseDir,\n\t\tconfigurationOrigin: options.configurationOrigin,\n\t};\n}\n"]}
1
+ {"version":3,"file":"source-info.js","sourceRoot":"","sources":["../../src/core/source-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAe3E,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAE9C,MAAM,UAAU,sBAAsB,CAAC,IAAY;IAClD,IAAI,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3D,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC;IACtG,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AACrE,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC9C,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,QAAsB;IACpE,OAAO;QACN,IAAI;QACJ,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB;KACjD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,yBAAyB,CACxC,IAAY,EACZ,OAMC;IAED,OAAO;QACN,IAAI;QACJ,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,WAAW;QACnC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,WAAW;QACrC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;KAChD,CAAC;AACH,CAAC","sourcesContent":["import { canonicalizePath, getPathComparisonKey } from \"../utils/paths.ts\";\nimport type { PathMetadata, ResourceConfigurationOrigin } from \"./package-manager.ts\";\n\nexport type SourceScope = \"user\" | \"project\" | \"temporary\";\nexport type SourceOrigin = \"package\" | \"top-level\";\n\nexport interface SourceInfo {\n\tpath: string;\n\tsource: string;\n\tscope: SourceScope;\n\torigin: SourceOrigin;\n\tbaseDir?: string;\n\tconfigurationOrigin?: ResourceConfigurationOrigin;\n}\n\nexport const BUILTIN_PATH_PREFIX = \"builtin:\";\n\nexport function getSyntheticPathSource(path: string): string | undefined {\n\tif (path.startsWith(BUILTIN_PATH_PREFIX)) return \"builtin\";\n\tif (path.startsWith(\"<\") && path.endsWith(\">\")) return path.slice(1, -1).split(\":\")[0] || \"temporary\";\n\treturn undefined;\n}\n\nexport function isSyntheticPath(path: string): boolean {\n\treturn path.startsWith(BUILTIN_PATH_PREFIX) || path.startsWith(\"<\");\n}\n\n/** Key for deduplicating resource paths: synthetic paths as-is, file paths via realpath and platform casing. */\nexport function getResourcePathKey(path: string): string {\n\treturn isSyntheticPath(path) ? path : getPathComparisonKey(canonicalizePath(path));\n}\n\nexport function createSourceInfo(path: string, metadata: PathMetadata): SourceInfo {\n\treturn {\n\t\tpath,\n\t\tsource: metadata.source,\n\t\tscope: metadata.scope,\n\t\torigin: metadata.origin,\n\t\tbaseDir: metadata.baseDir,\n\t\tconfigurationOrigin: metadata.configurationOrigin,\n\t};\n}\n\nexport function createSyntheticSourceInfo(\n\tpath: string,\n\toptions: {\n\t\tsource: string;\n\t\tscope?: SourceScope;\n\t\torigin?: SourceOrigin;\n\t\tbaseDir?: string;\n\t\tconfigurationOrigin?: ResourceConfigurationOrigin;\n\t},\n): SourceInfo {\n\treturn {\n\t\tpath,\n\t\tsource: options.source,\n\t\tscope: options.scope ?? \"temporary\",\n\t\torigin: options.origin ?? \"top-level\",\n\t\tbaseDir: options.baseDir,\n\t\tconfigurationOrigin: options.configurationOrigin,\n\t};\n}\n"]}
@@ -1,6 +1,10 @@
1
1
  import type { AgentMessage, AgentTool } from "@earendil-works/pi-agent-core";
2
2
  import type { AgentSessionInternalSurface as AgentSession } from "./agent-session-methods.ts";
3
3
  export declare function isToolDeclarationHidden(session: AgentSession, name: string): boolean;
4
+ /**
5
+ * The active tools are a set: tools that stay active keep their current order and newly active ones are
6
+ * appended, so reordering the same names does not change the prompt (#11495).
7
+ */
4
8
  export declare function applyToolLoadout(session: AgentSession, names: readonly string[]): AgentTool[];
5
9
  /** Hide only request declarations. The transcript retains activation and branch history. */
6
10
  export declare function projectToolLoadout(session: AgentSession, messages: AgentMessage[]): AgentMessage[];
@@ -1 +1 @@
1
- {"version":3,"file":"tool-loadout.d.ts","sourceRoot":"","sources":["../../src/core/tool-loadout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,KAAK,EAAE,2BAA2B,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAM9F,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpF;AACD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,CA4C7F;AAED,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAclG"}
1
+ {"version":3,"file":"tool-loadout.d.ts","sourceRoot":"","sources":["../../src/core/tool-loadout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,KAAK,EAAE,2BAA2B,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAM9F,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpF;AACD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,CA8C7F;AAED,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAclG"}
@@ -4,8 +4,14 @@ const hiddenDeclarations = new WeakMap();
4
4
  export function isToolDeclarationHidden(session, name) {
5
5
  return hiddenDeclarations.get(session)?.has(name) ?? false;
6
6
  }
7
+ /**
8
+ * The active tools are a set: tools that stay active keep their current order and newly active ones are
9
+ * appended, so reordering the same names does not change the prompt (#11495).
10
+ */
7
11
  export function applyToolLoadout(session, names) {
8
- const tools = [...new Set(names)].flatMap((name) => {
12
+ const requested = new Set(names);
13
+ const kept = session.getActiveToolNames().filter((name) => requested.has(name));
14
+ const tools = [...new Set([...kept, ...requested])].flatMap((name) => {
9
15
  const tool = session._toolRegistry.get(name);
10
16
  const exposure = session.getToolDefinition(name)?.exposure ?? "direct";
11
17
  return tool &&
@@ -1 +1 @@
1
- {"version":3,"file":"tool-loadout.js","sourceRoot":"","sources":["../../src/core/tool-loadout.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage, AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport { getCallableTools } from \"./agent-session-nested-tools.js\";\nimport type { ToolLoadout } from \"./extensions/tool-types.ts\";\nimport { isToolActivatable } from \"./tool-selection.ts\";\n\nconst hiddenDeclarations = new WeakMap<AgentSession, ReadonlySet<string>>();\nexport function isToolDeclarationHidden(session: AgentSession, name: string): boolean {\n\treturn hiddenDeclarations.get(session)?.has(name) ?? false;\n}\nexport function applyToolLoadout(session: AgentSession, names: readonly string[]): AgentTool[] {\n\tconst tools = [...new Set(names)].flatMap((name) => {\n\t\tconst tool = session._toolRegistry.get(name);\n\t\tconst exposure = session.getToolDefinition(name)?.exposure ?? \"direct\";\n\t\treturn tool &&\n\t\t\texposure !== \"hidden\" &&\n\t\t\tisToolActivatable(session, name, exposure, session._toolRegistry.has(\"tool_search\"))\n\t\t\t? [tool]\n\t\t\t: [];\n\t});\n\tconst loadout: ToolLoadout = {\n\t\tdeclared: tools,\n\t\tcallable: getCallableTools(session, new Set(tools.map((tool) => tool.name))),\n\t\tregistered: [...session._toolRegistry.values()],\n\t\tgetExposure: (name) => session.getToolDefinition(name)?.exposure ?? \"direct\",\n\t\tgetNamespace: (name) => session.getToolDefinition(name)?.namespace,\n\t\tgetPromptGuidelines: (name) => session._toolPromptGuidelines.get(name) ?? [],\n\t};\n\tconst descriptions = new Map<string, string>();\n\tconst hidden = new Set<string>();\n\tfor (const tool of tools) {\n\t\tconst entry = session._toolDefinitions.get(tool.name);\n\t\tif (!entry?.definition.prepareLoadout) continue;\n\t\ttry {\n\t\t\tconst changes = entry.definition.prepareLoadout(loadout);\n\t\t\tfor (const [name, description] of Object.entries(changes?.descriptions ?? {}))\n\t\t\t\tdescriptions.set(name, description);\n\t\t\tfor (const name of changes?.hiddenDeclarations ?? []) hidden.add(name);\n\t\t} catch (error) {\n\t\t\tsession.extensionRunner.emitError({\n\t\t\t\textensionPath: entry.sourceInfo.path,\n\t\t\t\tevent: \"prepare_loadout\",\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\tstack: error instanceof Error ? error.stack : undefined,\n\t\t\t});\n\t\t}\n\t}\n\thiddenDeclarations.set(session, hidden);\n\tconst declared = tools.map((tool) => {\n\t\tconst description = descriptions.get(tool.name);\n\t\treturn description === undefined ? tool : { ...tool, description };\n\t});\n\tsession.agent.state.tools = declared;\n\treturn declared;\n}\n\n/** Hide only request declarations. The transcript retains activation and branch history. */\nexport function projectToolLoadout(session: AgentSession, messages: AgentMessage[]): AgentMessage[] {\n\tconst hidden = hiddenDeclarations.get(session);\n\tif (!hidden?.size) return messages;\n\treturn messages.map((message) => {\n\t\tif (message.role !== \"system\" || (!message.toolsAdded && !message.toolsRemoved)) return message;\n\t\tconst { toolsAdded, toolsRemoved, ...rest } = message;\n\t\tconst added = toolsAdded?.filter((tool) => !hidden.has(tool.name)) ?? [];\n\t\tconst removed = toolsRemoved?.filter((tool) => !hidden.has(tool.name)) ?? [];\n\t\treturn {\n\t\t\t...rest,\n\t\t\t...(added.length ? { toolsAdded: added } : {}),\n\t\t\t...(removed.length ? { toolsRemoved: removed } : {}),\n\t\t};\n\t});\n}\n"]}
1
+ {"version":3,"file":"tool-loadout.js","sourceRoot":"","sources":["../../src/core/tool-loadout.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage, AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport { getCallableTools } from \"./agent-session-nested-tools.js\";\nimport type { ToolLoadout } from \"./extensions/tool-types.ts\";\nimport { isToolActivatable } from \"./tool-selection.ts\";\n\nconst hiddenDeclarations = new WeakMap<AgentSession, ReadonlySet<string>>();\nexport function isToolDeclarationHidden(session: AgentSession, name: string): boolean {\n\treturn hiddenDeclarations.get(session)?.has(name) ?? false;\n}\n/**\n * The active tools are a set: tools that stay active keep their current order and newly active ones are\n * appended, so reordering the same names does not change the prompt (#11495).\n */\nexport function applyToolLoadout(session: AgentSession, names: readonly string[]): AgentTool[] {\n\tconst requested = new Set(names);\n\tconst kept = session.getActiveToolNames().filter((name) => requested.has(name));\n\tconst tools = [...new Set([...kept, ...requested])].flatMap((name) => {\n\t\tconst tool = session._toolRegistry.get(name);\n\t\tconst exposure = session.getToolDefinition(name)?.exposure ?? \"direct\";\n\t\treturn tool &&\n\t\t\texposure !== \"hidden\" &&\n\t\t\tisToolActivatable(session, name, exposure, session._toolRegistry.has(\"tool_search\"))\n\t\t\t? [tool]\n\t\t\t: [];\n\t});\n\tconst loadout: ToolLoadout = {\n\t\tdeclared: tools,\n\t\tcallable: getCallableTools(session, new Set(tools.map((tool) => tool.name))),\n\t\tregistered: [...session._toolRegistry.values()],\n\t\tgetExposure: (name) => session.getToolDefinition(name)?.exposure ?? \"direct\",\n\t\tgetNamespace: (name) => session.getToolDefinition(name)?.namespace,\n\t\tgetPromptGuidelines: (name) => session._toolPromptGuidelines.get(name) ?? [],\n\t};\n\tconst descriptions = new Map<string, string>();\n\tconst hidden = new Set<string>();\n\tfor (const tool of tools) {\n\t\tconst entry = session._toolDefinitions.get(tool.name);\n\t\tif (!entry?.definition.prepareLoadout) continue;\n\t\ttry {\n\t\t\tconst changes = entry.definition.prepareLoadout(loadout);\n\t\t\tfor (const [name, description] of Object.entries(changes?.descriptions ?? {}))\n\t\t\t\tdescriptions.set(name, description);\n\t\t\tfor (const name of changes?.hiddenDeclarations ?? []) hidden.add(name);\n\t\t} catch (error) {\n\t\t\tsession.extensionRunner.emitError({\n\t\t\t\textensionPath: entry.sourceInfo.path,\n\t\t\t\tevent: \"prepare_loadout\",\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\tstack: error instanceof Error ? error.stack : undefined,\n\t\t\t});\n\t\t}\n\t}\n\thiddenDeclarations.set(session, hidden);\n\tconst declared = tools.map((tool) => {\n\t\tconst description = descriptions.get(tool.name);\n\t\treturn description === undefined ? tool : { ...tool, description };\n\t});\n\tsession.agent.state.tools = declared;\n\treturn declared;\n}\n\n/** Hide only request declarations. The transcript retains activation and branch history. */\nexport function projectToolLoadout(session: AgentSession, messages: AgentMessage[]): AgentMessage[] {\n\tconst hidden = hiddenDeclarations.get(session);\n\tif (!hidden?.size) return messages;\n\treturn messages.map((message) => {\n\t\tif (message.role !== \"system\" || (!message.toolsAdded && !message.toolsRemoved)) return message;\n\t\tconst { toolsAdded, toolsRemoved, ...rest } = message;\n\t\tconst added = toolsAdded?.filter((tool) => !hidden.has(tool.name)) ?? [];\n\t\tconst removed = toolsRemoved?.filter((tool) => !hidden.has(tool.name)) ?? [];\n\t\treturn {\n\t\t\t...rest,\n\t\t\t...(added.length ? { toolsAdded: added } : {}),\n\t\t\t...(removed.length ? { toolsRemoved: removed } : {}),\n\t\t};\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"render-utils.d.ts","sourceRoot":"","sources":["../../../src/core/tools/render-utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAIzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAOjD;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIjF;AAED,wBAAgB,cAAc,CAC7B,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,KAAK,EAAE;IAAE,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,EACzD,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAClC,MAAM,CAKR;AAED,wBAAgB,GAAG,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAIjD;AAOD,gGAAgG;AAChG,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAS3E;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,aAAa,CAC5B,MAAM,EAAE;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,SAAS,EACzG,UAAU,EAAE,OAAO,GACjB,MAAM,CAsBR;AAED,MAAM,MAAM,oBAAoB,CAAC,QAAQ,IAAI;IAC5C,OAAO,EAAE,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,CAAC;IACxC,OAAO,EAAE,QAAQ,CAAC;CAClB,CAAC;AAEF,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,OAAO,EACb,KAAK,EAAE;IAAE,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,EACzF,QAAQ,EAAE,OAAO,GACf,MAAM,CAgBR;AAaD,6GAA6G;AAC7G,MAAM,WAAW,cAAc;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;CAC1C;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,OAAO,EAAE,iBAAiB,CAAC,cAAc,CAAC,GAAG,IAAI,CAM/E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,OAAO,EAAE,iBAAiB,CAAC,cAAc,CAAC,EAC1C,SAAS,EAAE,OAAO,EAClB,UAAU,SAAS,GACjB,MAAM,GAAG,SAAS,CAkBpB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,GAAG,MAAM,CAEhG"}
1
+ {"version":3,"file":"render-utils.d.ts","sourceRoot":"","sources":["../../../src/core/tools/render-utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAIzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAGjD;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIjF;AAED,wBAAgB,cAAc,CAC7B,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,KAAK,EAAE;IAAE,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,EACzD,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAClC,MAAM,CAKR;AAED,wBAAgB,GAAG,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAIjD;AAOD,gGAAgG;AAChG,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAS3E;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,aAAa,CAC5B,MAAM,EAAE;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,SAAS,EACzG,UAAU,EAAE,OAAO,GACjB,MAAM,CAsBR;AAED,MAAM,MAAM,oBAAoB,CAAC,QAAQ,IAAI;IAC5C,OAAO,EAAE,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,CAAC;IACxC,OAAO,EAAE,QAAQ,CAAC;CAClB,CAAC;AAEF,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,OAAO,EACb,KAAK,EAAE;IAAE,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,EACzF,QAAQ,EAAE,OAAO,GACf,MAAM,CAgBR;AAaD,6GAA6G;AAC7G,MAAM,WAAW,cAAc;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;CAC1C;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,OAAO,EAAE,iBAAiB,CAAC,cAAc,CAAC,GAAG,IAAI,CAM/E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,OAAO,EAAE,iBAAiB,CAAC,cAAc,CAAC,EAC1C,SAAS,EAAE,OAAO,EAClB,UAAU,SAAS,GACjB,MAAM,GAAG,SAAS,CAkBpB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,GAAG,MAAM,CAEhG"}
@@ -1,17 +1,12 @@
1
- import * as os from "node:os";
2
1
  import { pathToFileURL } from "node:url";
3
2
  import { getCapabilities, getImageDimensions, hyperlink, imageFallback } from "@earendil-works/pi-tui";
4
3
  import { stripAnsi } from "../../utils/ansi.js";
5
- import { resolvePath } from "../../utils/paths.js";
4
+ import { resolvePath, shortenHomePath } from "../../utils/paths.js";
6
5
  import { sanitizeBinaryOutput } from "../../utils/shell.js";
7
6
  export function shortenPath(path) {
8
7
  if (typeof path !== "string")
9
8
  return "";
10
- const home = os.homedir();
11
- if (path.startsWith(home)) {
12
- return `~${path.slice(home.length)}`;
13
- }
14
- return path;
9
+ return shortenHomePath(path);
15
10
  }
16
11
  export function linkPath(styledText, rawPath, cwd) {
17
12
  if (!getCapabilities().hyperlinks)
@@ -1 +1 @@
1
- {"version":3,"file":"render-utils.js","sourceRoot":"","sources":["../../../src/core/tools/render-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvG,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG5D,MAAM,UAAU,WAAW,CAAC,IAAa;IACxC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACxC,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC1B,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,UAAkB,EAAE,OAAe,EAAE,GAAW;IACxE,IAAI,CAAC,eAAe,EAAE,CAAC,UAAU;QAAE,OAAO,UAAU,CAAC;IACrD,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC/C,OAAO,SAAS,CAAC,UAAU,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,cAAc,CAC7B,OAAsB,EACtB,KAAyD,EACzD,GAAW,EACX,OAAoC;IAEpC,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,OAAO,IAAI,OAAO,EAAE,aAAa,CAAC;IAChD,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IACjD,OAAO,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,KAAc;IACjC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC7B,OAAO,IAAI,CAAC;AACb,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACtC,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3F,OAAO,OAAO,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5F,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,mBAAmB,CAAC,MAAe,EAAE,KAAc;IAClE,IAAI,MAAM,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAC3D,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,KAAK,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,GAAG,GAAG,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC;IAC9B,OAAO,IAAI,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAChD,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,aAAa,CAC5B,MAAyG,EACzG,UAAmB;IAEnB,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAEvB,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACnE,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IAErE,IAAI,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEhH,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7D,MAAM,eAAe,GAAG,WAAW;aACjC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACZ,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,eAAe,CAAC;YACjD,MAAM,IAAI,GACT,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAClG,OAAO,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACtC,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,KAAK,eAAe,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC;IACrE,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC;AAOD,MAAM,UAAU,sBAAsB,CACrC,KAAa,EACb,IAAa,EACb,KAAyF,EACzF,QAAiB;IAEjB,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/D,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,MAAM,CAAC;IAChC,MAAM,OAAO,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3G,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACxC,IAAI,QAAQ,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YAC1C,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACnG,OAAO,KAAK,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7G,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,MAAM,KAAK,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;IAC5D,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACjH,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACxE,OAAO,GAAG,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;AAClD,CAAC;AAED,uEAAuE;AACvE,SAAS,kBAAkB,CAAC,EAAU;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC;IACvC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAClD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,YAAY,GAAG,EAAE,CAAC;IACpC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,KAAK,SAAS,GAAG,CAAC;IACrD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,KAAK,OAAO,GAAG,EAAE,KAAK,SAAS,GAAG,CAAC;AACtE,CAAC;AASD,2EAA2E;AAC3E,MAAM,UAAU,cAAc,CAAC,OAA0C;IACxE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC5B,IAAI,OAAO,CAAC,gBAAgB,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAC/D,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC;IAC3B,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC5B,OAA0C,EAC1C,SAAkB,EAClB,UAAU,GAAG,MAAM;IAEnB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC5B,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,SAAS,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnE,KAAK,CAAC,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACnC,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACpB,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC9B,KAAK,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC5B,CAAC;IACF,CAAC;IACD,iHAAiH;IACjH,iEAAiE;IACjE,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS;QAAE,OAAO,GAAG,UAAU,IAAI,kBAAkB,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;IACrH,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACpD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5C,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,IAAI,kBAAkB,CAAC,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;AACjG,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAyD;IACvF,OAAO,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;AAC3C,CAAC","sourcesContent":["import * as os from \"node:os\";\nimport { pathToFileURL } from \"node:url\";\nimport type { ImageContent, TextContent } from \"@bastani/pi-ai/compat\";\nimport { getCapabilities, getImageDimensions, hyperlink, imageFallback } from \"@earendil-works/pi-tui\";\nimport type { ThemeColor } from \"../../modes/interactive/theme/theme.js\";\nimport { stripAnsi } from \"../../utils/ansi.js\";\nimport { resolvePath } from \"../../utils/paths.ts\";\nimport { sanitizeBinaryOutput } from \"../../utils/shell.ts\";\nimport type { ToolRenderContext } from \"../extensions/tool-types.ts\";\n\nexport function shortenPath(path: unknown): string {\n\tif (typeof path !== \"string\") return \"\";\n\tconst home = os.homedir();\n\tif (path.startsWith(home)) {\n\t\treturn `~${path.slice(home.length)}`;\n\t}\n\treturn path;\n}\n\nexport function linkPath(styledText: string, rawPath: string, cwd: string): string {\n\tif (!getCapabilities().hyperlinks) return styledText;\n\tconst absolutePath = resolvePath(rawPath, cwd);\n\treturn hyperlink(styledText, pathToFileURL(absolutePath).href);\n}\n\nexport function renderToolPath(\n\trawPath: string | null,\n\ttheme: { fg: (name: ThemeColor, text: string) => string },\n\tcwd: string,\n\toptions?: { emptyFallback?: string },\n): string {\n\tif (rawPath === null) return invalidArgText(theme);\n\tconst value = rawPath || options?.emptyFallback;\n\tif (!value) return theme.fg(\"toolOutput\", \"...\");\n\treturn linkPath(theme.fg(\"accent\", shortenPath(value)), value, cwd);\n}\n\nexport function str(value: unknown): string | null {\n\tif (typeof value === \"string\") return value;\n\tif (value == null) return \"\";\n\treturn null;\n}\n\nfunction parseLineNumber(value: unknown): number | undefined {\n\tconst candidate = typeof value === \"string\" && value.trim() !== \"\" ? Number(value) : value;\n\treturn typeof candidate === \"number\" && Number.isFinite(candidate) ? candidate : undefined;\n}\n\n/** Format finite numbers or numeric strings as a read line range, omitting malformed ranges. */\nexport function formatReadLineRange(offset: unknown, limit: unknown): string {\n\tif (offset == null && limit == null) return \"\";\n\tconst start = offset == null ? 1 : parseLineNumber(offset);\n\tif (start === undefined) return \"\";\n\tif (limit == null) return `:${start}`;\n\tconst count = parseLineNumber(limit);\n\tif (count === undefined) return \"\";\n\tconst end = start + count - 1;\n\treturn `:${start}${end ? `-${end}` : \"\"}`;\n}\n\nexport function replaceTabs(text: string): string {\n\treturn text.replace(/\\t/g, \" \");\n}\n\nexport function normalizeDisplayText(text: string): string {\n\treturn text.replace(/\\r/g, \"\");\n}\n\nexport function getTextOutput(\n\tresult: { content: Array<{ type: string; text?: string; data?: string; mimeType?: string }> } | undefined,\n\tshowImages: boolean,\n): string {\n\tif (!result) return \"\";\n\n\tconst textBlocks = result.content.filter((c) => c.type === \"text\");\n\tconst imageBlocks = result.content.filter((c) => c.type === \"image\");\n\n\tlet output = textBlocks.map((c) => sanitizeBinaryOutput(stripAnsi(c.text || \"\")).replace(/\\r/g, \"\")).join(\"\\n\");\n\n\tconst caps = getCapabilities();\n\tif (imageBlocks.length > 0 && (!caps.images || !showImages)) {\n\t\tconst imageIndicators = imageBlocks\n\t\t\t.map((img) => {\n\t\t\t\tconst mimeType = img.mimeType ?? \"image/unknown\";\n\t\t\t\tconst dims =\n\t\t\t\t\timg.data && img.mimeType ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;\n\t\t\t\treturn imageFallback(mimeType, dims);\n\t\t\t})\n\t\t\t.join(\"\\n\");\n\t\toutput = output ? `${output}\\n${imageIndicators}` : imageIndicators;\n\t}\n\n\treturn output;\n}\n\nexport type ToolRenderResultLike<TDetails> = {\n\tcontent: (TextContent | ImageContent)[];\n\tdetails: TDetails;\n};\n\nexport function formatToolCallWithArgs(\n\ttitle: string,\n\targs: unknown,\n\ttheme: { fg: (name: ThemeColor, text: string) => string; bold: (text: string) => string },\n\texpanded: boolean,\n): string {\n\tconst clean = (text: string) => sanitizeBinaryOutput(stripAnsi(text));\n\tconst header = theme.fg(\"toolTitle\", theme.bold(clean(title)));\n\tif (args == null) return header;\n\tconst entries = typeof args === \"object\" && !Array.isArray(args) ? Object.entries(args) : [[\"args\", args]];\n\tif (entries.length === 0) return header;\n\tif (expanded) {\n\t\tconst lines = entries.map(([key, value]) => {\n\t\t\tconst text = typeof value === \"string\" ? value : (JSON.stringify(value, null, 2) ?? String(value));\n\t\t\treturn ` ${clean(String(key))}: ${replaceTabs(clean(text)).replace(/\\r/g, \"\").split(\"\\n\").join(\"\\n \")}`;\n\t\t});\n\t\treturn `${header}\\n${theme.fg(\"muted\", lines.join(\"\\n\"))}`;\n\t}\n\tconst pairs = clean(entries.map(([key, value]) => `${key}=${JSON.stringify(value) ?? String(value)}`).join(\" \"));\n\tconst preview = pairs.length > 100 ? `${pairs.slice(0, 97)}...` : pairs;\n\treturn `${header} ${theme.fg(\"muted\", preview)}`;\n}\n\n/** Duration as `4.2s` below a minute, then `1m 30s` and `2h 3m 4s`. */\nfunction formatToolDuration(ms: number): string {\n\tconst seconds = Math.max(0, ms) / 1000;\n\tif (seconds < 60) return `${seconds.toFixed(1)}s`;\n\tconst totalSeconds = Math.floor(seconds);\n\tconst minutes = Math.floor(totalSeconds / 60);\n\tconst remainder = totalSeconds % 60;\n\tif (minutes < 60) return `${minutes}m ${remainder}s`;\n\treturn `${Math.floor(minutes / 60)}h ${minutes % 60}m ${remainder}s`;\n}\n\n/** Renderer state of {@link startToolTimer} and {@link toolTimerText}, kept in `ToolRenderContext.state`. */\nexport interface ToolTimerState {\n\tstartedAt?: number;\n\tendedAt?: number;\n\tinterval?: ReturnType<typeof setInterval>;\n}\n\n/** Start the row's clock once execution starts. Call from `renderCall`. */\nexport function startToolTimer(context: ToolRenderContext<ToolTimerState>): void {\n\tconst state = context.state;\n\tif (context.executionStarted && state.startedAt === undefined) {\n\t\tstate.startedAt = Date.now();\n\t\tstate.endedAt = undefined;\n\t}\n}\n\n/**\n * The row's timing line, from `renderResult`: `Elapsed 4.2s` while the result is partial, redrawn\n * every second, and `<finalLabel> 4.2s` once it is final. Undefined when the row has no start time\n * and no recorded duration.\n */\nexport function toolTimerText(\n\tcontext: ToolRenderContext<ToolTimerState>,\n\tisPartial: boolean,\n\tfinalLabel = \"Took\",\n): string | undefined {\n\tconst state = context.state;\n\tif (state.startedAt !== undefined && isPartial && !state.interval) {\n\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t}\n\tif (!isPartial || context.isError) {\n\t\tstate.endedAt ??= Date.now();\n\t\tif (state.interval) {\n\t\t\tclearInterval(state.interval);\n\t\t\tstate.interval = undefined;\n\t\t}\n\t}\n\t// A final result's recorded duration wins: it is monotonic and survives reloads. The renderer's own clock is the\n\t// fallback for live progress and for results stored without one.\n\tif (!isPartial && context.durationMs !== undefined) return `${finalLabel} ${formatToolDuration(context.durationMs)}`;\n\tif (state.startedAt === undefined) return undefined;\n\tconst endTime = state.endedAt ?? Date.now();\n\treturn `${isPartial ? \"Elapsed\" : finalLabel} ${formatToolDuration(endTime - state.startedAt)}`;\n}\n\nexport function invalidArgText(theme: { fg: (name: ThemeColor, text: string) => string }): string {\n\treturn theme.fg(\"error\", \"[invalid arg]\");\n}\n"]}
1
+ {"version":3,"file":"render-utils.js","sourceRoot":"","sources":["../../../src/core/tools/render-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { pathToFileURL } from \"node:url\";\nimport type { ImageContent, TextContent } from \"@bastani/pi-ai/compat\";\nimport { getCapabilities, getImageDimensions, hyperlink, imageFallback } from \"@earendil-works/pi-tui\";\nimport type { ThemeColor } from \"../../modes/interactive/theme/theme.js\";\nimport { stripAnsi } from \"../../utils/ansi.js\";\nimport { resolvePath, shortenHomePath } from \"../../utils/paths.ts\";\nimport { sanitizeBinaryOutput } from \"../../utils/shell.ts\";\nimport type { ToolRenderContext } from \"../extensions/tool-types.ts\";\n\nexport function shortenPath(path: unknown): string {\n\tif (typeof path !== \"string\") return \"\";\n\treturn shortenHomePath(path);\n}\n\nexport function linkPath(styledText: string, rawPath: string, cwd: string): string {\n\tif (!getCapabilities().hyperlinks) return styledText;\n\tconst absolutePath = resolvePath(rawPath, cwd);\n\treturn hyperlink(styledText, pathToFileURL(absolutePath).href);\n}\n\nexport function renderToolPath(\n\trawPath: string | null,\n\ttheme: { fg: (name: ThemeColor, text: string) => string },\n\tcwd: string,\n\toptions?: { emptyFallback?: string },\n): string {\n\tif (rawPath === null) return invalidArgText(theme);\n\tconst value = rawPath || options?.emptyFallback;\n\tif (!value) return theme.fg(\"toolOutput\", \"...\");\n\treturn linkPath(theme.fg(\"accent\", shortenPath(value)), value, cwd);\n}\n\nexport function str(value: unknown): string | null {\n\tif (typeof value === \"string\") return value;\n\tif (value == null) return \"\";\n\treturn null;\n}\n\nfunction parseLineNumber(value: unknown): number | undefined {\n\tconst candidate = typeof value === \"string\" && value.trim() !== \"\" ? Number(value) : value;\n\treturn typeof candidate === \"number\" && Number.isFinite(candidate) ? candidate : undefined;\n}\n\n/** Format finite numbers or numeric strings as a read line range, omitting malformed ranges. */\nexport function formatReadLineRange(offset: unknown, limit: unknown): string {\n\tif (offset == null && limit == null) return \"\";\n\tconst start = offset == null ? 1 : parseLineNumber(offset);\n\tif (start === undefined) return \"\";\n\tif (limit == null) return `:${start}`;\n\tconst count = parseLineNumber(limit);\n\tif (count === undefined) return \"\";\n\tconst end = start + count - 1;\n\treturn `:${start}${end ? `-${end}` : \"\"}`;\n}\n\nexport function replaceTabs(text: string): string {\n\treturn text.replace(/\\t/g, \" \");\n}\n\nexport function normalizeDisplayText(text: string): string {\n\treturn text.replace(/\\r/g, \"\");\n}\n\nexport function getTextOutput(\n\tresult: { content: Array<{ type: string; text?: string; data?: string; mimeType?: string }> } | undefined,\n\tshowImages: boolean,\n): string {\n\tif (!result) return \"\";\n\n\tconst textBlocks = result.content.filter((c) => c.type === \"text\");\n\tconst imageBlocks = result.content.filter((c) => c.type === \"image\");\n\n\tlet output = textBlocks.map((c) => sanitizeBinaryOutput(stripAnsi(c.text || \"\")).replace(/\\r/g, \"\")).join(\"\\n\");\n\n\tconst caps = getCapabilities();\n\tif (imageBlocks.length > 0 && (!caps.images || !showImages)) {\n\t\tconst imageIndicators = imageBlocks\n\t\t\t.map((img) => {\n\t\t\t\tconst mimeType = img.mimeType ?? \"image/unknown\";\n\t\t\t\tconst dims =\n\t\t\t\t\timg.data && img.mimeType ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;\n\t\t\t\treturn imageFallback(mimeType, dims);\n\t\t\t})\n\t\t\t.join(\"\\n\");\n\t\toutput = output ? `${output}\\n${imageIndicators}` : imageIndicators;\n\t}\n\n\treturn output;\n}\n\nexport type ToolRenderResultLike<TDetails> = {\n\tcontent: (TextContent | ImageContent)[];\n\tdetails: TDetails;\n};\n\nexport function formatToolCallWithArgs(\n\ttitle: string,\n\targs: unknown,\n\ttheme: { fg: (name: ThemeColor, text: string) => string; bold: (text: string) => string },\n\texpanded: boolean,\n): string {\n\tconst clean = (text: string) => sanitizeBinaryOutput(stripAnsi(text));\n\tconst header = theme.fg(\"toolTitle\", theme.bold(clean(title)));\n\tif (args == null) return header;\n\tconst entries = typeof args === \"object\" && !Array.isArray(args) ? Object.entries(args) : [[\"args\", args]];\n\tif (entries.length === 0) return header;\n\tif (expanded) {\n\t\tconst lines = entries.map(([key, value]) => {\n\t\t\tconst text = typeof value === \"string\" ? value : (JSON.stringify(value, null, 2) ?? String(value));\n\t\t\treturn ` ${clean(String(key))}: ${replaceTabs(clean(text)).replace(/\\r/g, \"\").split(\"\\n\").join(\"\\n \")}`;\n\t\t});\n\t\treturn `${header}\\n${theme.fg(\"muted\", lines.join(\"\\n\"))}`;\n\t}\n\tconst pairs = clean(entries.map(([key, value]) => `${key}=${JSON.stringify(value) ?? String(value)}`).join(\" \"));\n\tconst preview = pairs.length > 100 ? `${pairs.slice(0, 97)}...` : pairs;\n\treturn `${header} ${theme.fg(\"muted\", preview)}`;\n}\n\n/** Duration as `4.2s` below a minute, then `1m 30s` and `2h 3m 4s`. */\nfunction formatToolDuration(ms: number): string {\n\tconst seconds = Math.max(0, ms) / 1000;\n\tif (seconds < 60) return `${seconds.toFixed(1)}s`;\n\tconst totalSeconds = Math.floor(seconds);\n\tconst minutes = Math.floor(totalSeconds / 60);\n\tconst remainder = totalSeconds % 60;\n\tif (minutes < 60) return `${minutes}m ${remainder}s`;\n\treturn `${Math.floor(minutes / 60)}h ${minutes % 60}m ${remainder}s`;\n}\n\n/** Renderer state of {@link startToolTimer} and {@link toolTimerText}, kept in `ToolRenderContext.state`. */\nexport interface ToolTimerState {\n\tstartedAt?: number;\n\tendedAt?: number;\n\tinterval?: ReturnType<typeof setInterval>;\n}\n\n/** Start the row's clock once execution starts. Call from `renderCall`. */\nexport function startToolTimer(context: ToolRenderContext<ToolTimerState>): void {\n\tconst state = context.state;\n\tif (context.executionStarted && state.startedAt === undefined) {\n\t\tstate.startedAt = Date.now();\n\t\tstate.endedAt = undefined;\n\t}\n}\n\n/**\n * The row's timing line, from `renderResult`: `Elapsed 4.2s` while the result is partial, redrawn\n * every second, and `<finalLabel> 4.2s` once it is final. Undefined when the row has no start time\n * and no recorded duration.\n */\nexport function toolTimerText(\n\tcontext: ToolRenderContext<ToolTimerState>,\n\tisPartial: boolean,\n\tfinalLabel = \"Took\",\n): string | undefined {\n\tconst state = context.state;\n\tif (state.startedAt !== undefined && isPartial && !state.interval) {\n\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t}\n\tif (!isPartial || context.isError) {\n\t\tstate.endedAt ??= Date.now();\n\t\tif (state.interval) {\n\t\t\tclearInterval(state.interval);\n\t\t\tstate.interval = undefined;\n\t\t}\n\t}\n\t// A final result's recorded duration wins: it is monotonic and survives reloads. The renderer's own clock is the\n\t// fallback for live progress and for results stored without one.\n\tif (!isPartial && context.durationMs !== undefined) return `${finalLabel} ${formatToolDuration(context.durationMs)}`;\n\tif (state.startedAt === undefined) return undefined;\n\tconst endTime = state.endedAt ?? Date.now();\n\treturn `${isPartial ? \"Elapsed\" : finalLabel} ${formatToolDuration(endTime - state.startedAt)}`;\n}\n\nexport function invalidArgText(theme: { fg: (name: ThemeColor, text: string) => string }): string {\n\treturn theme.fg(\"error\", \"[invalid arg]\");\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"trust-manager.d.ts","sourceRoot":"","sources":["../../src/core/trust-manager.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,IAAI,CAAC;AAElD,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,oBAAoB,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAGD,eAAO,MAAM,wCAAwC,YACpD,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,WAAW,EACX,kBAAkB,CACT,CAAC;AAsBX,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIzE;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,kBAAkB,EAAE,CA8BpH;AAkFD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGxD;AASD;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAmBtE;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CA0B1D;AAED,qBAAa,iBAAiB;IAC7B,OAAO,CAAC,SAAS,CAAS;IAE1B,YAAY,QAAQ,EAAE,MAAM,EAE3B;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAErC;IAED,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG,IAAI,CAKnD;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAErD;IAED,OAAO,CAAC,SAAS,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAa7C;CACD"}
1
+ {"version":3,"file":"trust-manager.d.ts","sourceRoot":"","sources":["../../src/core/trust-manager.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,IAAI,CAAC;AAElD,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,oBAAoB,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAGD,eAAO,MAAM,wCAAwC,YACpD,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,WAAW,EACX,kBAAkB,CACT,CAAC;AA6BX,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIzE;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,kBAAkB,EAAE,CA8BpH;AAkFD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGxD;AASD;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAmBtE;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CA0B1D;AAED,qBAAa,iBAAiB;IAC7B,OAAO,CAAC,SAAS,CAAS;IAE1B,YAAY,QAAQ,EAAE,MAAM,EAE3B;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAErC;IAED,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG,IAAI,CAKnD;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAErD;IAED,OAAO,CAAC,SAAS,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAc7C;CACD"}