@di-code/coding-agent 0.1.1 → 0.1.2

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 (80) hide show
  1. package/dist/cli.d.ts +11 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +59 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/core/resources/index.d.ts +3 -0
  6. package/dist/core/resources/index.d.ts.map +1 -0
  7. package/dist/core/resources/index.js +2 -0
  8. package/dist/core/resources/index.js.map +1 -0
  9. package/dist/core/resources/loader.d.ts +8 -0
  10. package/dist/core/resources/loader.d.ts.map +1 -0
  11. package/dist/core/resources/loader.js +174 -0
  12. package/dist/core/resources/loader.js.map +1 -0
  13. package/dist/core/resources/skills.d.ts +10 -0
  14. package/dist/core/resources/skills.d.ts.map +1 -0
  15. package/dist/core/resources/skills.js +167 -0
  16. package/dist/core/resources/skills.js.map +1 -0
  17. package/dist/core/resources/types.d.ts +41 -0
  18. package/dist/core/resources/types.d.ts.map +1 -0
  19. package/dist/core/resources/types.js +2 -0
  20. package/dist/core/resources/types.js.map +1 -0
  21. package/dist/core/session.d.ts +7 -0
  22. package/dist/core/session.d.ts.map +1 -1
  23. package/dist/core/session.js +23 -3
  24. package/dist/core/session.js.map +1 -1
  25. package/dist/core/skill-command.d.ts +3 -0
  26. package/dist/core/skill-command.d.ts.map +1 -0
  27. package/dist/core/skill-command.js +34 -0
  28. package/dist/core/skill-command.js.map +1 -0
  29. package/dist/core/system-prompt.d.ts +6 -0
  30. package/dist/core/system-prompt.d.ts.map +1 -0
  31. package/dist/core/system-prompt.js +57 -0
  32. package/dist/core/system-prompt.js.map +1 -0
  33. package/dist/extensions/runtime.d.ts +7 -4
  34. package/dist/extensions/runtime.d.ts.map +1 -1
  35. package/dist/extensions/runtime.js +45 -10
  36. package/dist/extensions/runtime.js.map +1 -1
  37. package/dist/index.d.ts +3 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +3 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/main.d.ts +1 -0
  42. package/dist/main.d.ts.map +1 -1
  43. package/dist/main.js +85 -2
  44. package/dist/main.js.map +1 -1
  45. package/dist/modes/interactive-components.d.ts.map +1 -1
  46. package/dist/modes/interactive-components.js +4 -0
  47. package/dist/modes/interactive-components.js.map +1 -1
  48. package/dist/modes/interactive-state.js +1 -1
  49. package/dist/modes/interactive-state.js.map +1 -1
  50. package/dist/modes/interactive.d.ts +4 -0
  51. package/dist/modes/interactive.d.ts.map +1 -1
  52. package/dist/modes/interactive.js +26 -5
  53. package/dist/modes/interactive.js.map +1 -1
  54. package/dist/plugins/index.d.ts +5 -0
  55. package/dist/plugins/index.d.ts.map +1 -0
  56. package/dist/plugins/index.js +5 -0
  57. package/dist/plugins/index.js.map +1 -0
  58. package/dist/plugins/loader.d.ts +18 -0
  59. package/dist/plugins/loader.d.ts.map +1 -0
  60. package/dist/plugins/loader.js +92 -0
  61. package/dist/plugins/loader.js.map +1 -0
  62. package/dist/plugins/manager.d.ts +23 -0
  63. package/dist/plugins/manager.d.ts.map +1 -0
  64. package/dist/plugins/manager.js +152 -0
  65. package/dist/plugins/manager.js.map +1 -0
  66. package/dist/plugins/manifest.d.ts +7 -0
  67. package/dist/plugins/manifest.d.ts.map +1 -0
  68. package/dist/plugins/manifest.js +116 -0
  69. package/dist/plugins/manifest.js.map +1 -0
  70. package/dist/plugins/types.d.ts +41 -0
  71. package/dist/plugins/types.d.ts.map +1 -0
  72. package/dist/plugins/types.js +2 -0
  73. package/dist/plugins/types.js.map +1 -0
  74. package/dist/provider-onboarding.d.ts.map +1 -1
  75. package/dist/provider-onboarding.js +13 -1
  76. package/dist/provider-onboarding.js.map +1 -1
  77. package/dist/startup.d.ts.map +1 -1
  78. package/dist/startup.js +37 -15
  79. package/dist/startup.js.map +1 -1
  80. package/package.json +15 -4
package/dist/cli.d.ts CHANGED
@@ -3,12 +3,20 @@ export type CliCommand = {
3
3
  kind: "help";
4
4
  } | {
5
5
  kind: "version";
6
+ } | {
7
+ kind: "plugin";
8
+ action: "install" | "list" | "enable" | "disable" | "update" | "remove";
9
+ argument?: string;
6
10
  } | {
7
11
  kind: "run";
8
12
  mode: OutputMode;
9
13
  prompt: string;
10
14
  sessionPath?: string;
11
15
  continueSession?: true;
16
+ noSkills?: true;
17
+ noContextFiles?: true;
18
+ skillPaths?: readonly string[];
19
+ projectTrust?: boolean;
12
20
  };
13
21
  export declare class CliUsageError extends Error {
14
22
  constructor(message: string);
@@ -20,6 +28,9 @@ export interface CliDependencies {
20
28
  run(command: Extract<CliCommand, {
21
29
  kind: "run";
22
30
  }>): Promise<number>;
31
+ plugin?(command: Extract<CliCommand, {
32
+ kind: "plugin";
33
+ }>): Promise<number>;
23
34
  readonly version: string;
24
35
  }
25
36
  export declare function runCli(args: readonly string[], dependencies: CliDependencies): Promise<number>;
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,aAAa,CAAC;AAE1D,MAAM,MAAM,UAAU,GACnB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAEnG,qBAAa,aAAc,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI3B;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CA+EhE;AAcD,MAAM,WAAW,eAAe;IAC/B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,YAAY,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBpG"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,aAAa,CAAC;AAE1D,MAAM,MAAM,UAAU,GACnB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9G;IACA,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEL,qBAAa,aAAc,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI3B;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAoIhE;AAoBD,MAAM,WAAW,eAAe;IAC/B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,MAAM,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,YAAY,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBpG"}
package/dist/cli.js CHANGED
@@ -5,6 +5,22 @@ export class CliUsageError extends Error {
5
5
  }
6
6
  }
7
7
  export function parseCliArgs(args) {
8
+ if (args[0] === "plugin") {
9
+ const action = args[1];
10
+ if (action !== "install" &&
11
+ action !== "list" &&
12
+ action !== "enable" &&
13
+ action !== "disable" &&
14
+ action !== "update" &&
15
+ action !== "remove")
16
+ throw new CliUsageError("Plugin command must be install, list, enable, disable, update, or remove.");
17
+ const argument = args[2];
18
+ if (args.length > 3 ||
19
+ (action !== "list" && (argument === undefined || argument.trim() === "")) ||
20
+ (action === "list" && argument !== undefined))
21
+ throw new CliUsageError("Plugin command has invalid arguments.");
22
+ return { kind: "plugin", action, ...(argument ? { argument } : {}) };
23
+ }
8
24
  const staticOption = args.find((argument) => ["-h", "--help", "-v", "--version"].includes(argument));
9
25
  if (staticOption !== undefined) {
10
26
  const kind = staticOption === "-h" || staticOption === "--help" ? "help" : "version";
@@ -17,6 +33,10 @@ export function parseCliArgs(args) {
17
33
  let printAlias = false;
18
34
  let sessionPath;
19
35
  let continueSession = false;
36
+ let noSkills = false;
37
+ let noContextFiles = false;
38
+ let projectTrust;
39
+ const skillPaths = [];
20
40
  const promptParts = [];
21
41
  for (let index = 0; index < args.length; index++) {
22
42
  const argument = args[index];
@@ -32,6 +52,31 @@ export function parseCliArgs(args) {
32
52
  continueSession = true;
33
53
  continue;
34
54
  }
55
+ if (argument === "--no-skills") {
56
+ noSkills = true;
57
+ continue;
58
+ }
59
+ if (argument === "--no-context-files") {
60
+ noContextFiles = true;
61
+ continue;
62
+ }
63
+ if (argument === "--trust-project" || argument === "--untrust-project") {
64
+ const nextTrust = argument === "--trust-project";
65
+ if (projectTrust !== undefined && projectTrust !== nextTrust) {
66
+ throw new CliUsageError("Cannot combine --trust-project with --untrust-project.");
67
+ }
68
+ projectTrust = nextTrust;
69
+ continue;
70
+ }
71
+ if (argument === "--skill") {
72
+ const value = args[index + 1];
73
+ if (value === undefined || value.trim().length === 0) {
74
+ throw new CliUsageError("Option --skill requires a non-empty value.");
75
+ }
76
+ skillPaths.push(value);
77
+ index++;
78
+ continue;
79
+ }
35
80
  if (argument === "--mode") {
36
81
  const value = args[index + 1];
37
82
  if (value === undefined) {
@@ -78,6 +123,10 @@ export function parseCliArgs(args) {
78
123
  prompt: promptParts.join(" "),
79
124
  ...(sessionPath ? { sessionPath } : {}),
80
125
  ...(continueSession ? { continueSession: true } : {}),
126
+ ...(noSkills ? { noSkills: true } : {}),
127
+ ...(noContextFiles ? { noContextFiles: true } : {}),
128
+ ...(skillPaths.length > 0 ? { skillPaths } : {}),
129
+ ...(projectTrust === undefined ? {} : { projectTrust }),
81
130
  };
82
131
  }
83
132
  const HELP_TEXT = `Usage: di-code [options] <prompt>
@@ -88,6 +137,12 @@ Options:
88
137
  --interactive Start interactive terminal mode
89
138
  --continue, -c Continue the most recently modified session
90
139
  --session <path> Create or resume a JSONL session (relative to the work root)
140
+ --skill <path> Add a SKILL.md file or skill directory (repeatable)
141
+ --no-skills Disable all Skill loading
142
+ --no-context-files Disable AGENTS.md discovery and loading
143
+ --trust-project Persist trust for project-local Skill discovery
144
+ --untrust-project Persist denial for project-local Skill discovery
145
+ plugin <action> Install, list, enable, disable, update, or remove a plugin
91
146
  -h, --help Show help
92
147
  -v, --version Show version
93
148
  `;
@@ -107,6 +162,10 @@ export async function runCli(args, dependencies) {
107
162
  case "help":
108
163
  dependencies.stdout(HELP_TEXT);
109
164
  return 0;
165
+ case "plugin":
166
+ if (!dependencies.plugin)
167
+ throw new Error("Plugin command handler is unavailable.");
168
+ return dependencies.plugin(command);
110
169
  case "version":
111
170
  dependencies.stdout(`${dependencies.version}\n`);
112
171
  return 0;
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["export type OutputMode = \"print\" | \"json\" | \"interactive\";\n\nexport type CliCommand =\n\t| { kind: \"help\" }\n\t| { kind: \"version\" }\n\t| { kind: \"run\"; mode: OutputMode; prompt: string; sessionPath?: string; continueSession?: true };\n\nexport class CliUsageError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CliUsageError\";\n\t}\n}\n\nexport function parseCliArgs(args: readonly string[]): CliCommand {\n\tconst staticOption = args.find((argument) => [\"-h\", \"--help\", \"-v\", \"--version\"].includes(argument));\n\tif (staticOption !== undefined) {\n\t\tconst kind = staticOption === \"-h\" || staticOption === \"--help\" ? \"help\" : \"version\";\n\t\tif (args.length !== 1) {\n\t\t\tthrow new CliUsageError(`--${kind} must be used on its own.`);\n\t\t}\n\t\treturn { kind };\n\t}\n\n\tlet mode: OutputMode = \"print\";\n\tlet printAlias = false;\n\tlet sessionPath: string | undefined;\n\tlet continueSession = false;\n\tconst promptParts: string[] = [];\n\n\tfor (let index = 0; index < args.length; index++) {\n\t\tconst argument = args[index];\n\t\tif (argument === \"-p\" || argument === \"--print\") {\n\t\t\tprintAlias = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--interactive\") {\n\t\t\tmode = \"interactive\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"-c\" || argument === \"--continue\") {\n\t\t\tcontinueSession = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--mode\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined) {\n\t\t\t\tthrow new CliUsageError(\"Option --mode requires a value.\");\n\t\t\t}\n\t\t\tif (value !== \"print\" && value !== \"json\" && value !== \"interactive\") {\n\t\t\t\tthrow new CliUsageError(`Unsupported mode \"${value}\". Expected print, json, or interactive.`);\n\t\t\t}\n\t\t\tmode = value;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--session\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined) {\n\t\t\t\tthrow new CliUsageError(\"Option --session requires a value.\");\n\t\t\t}\n\t\t\tif (value.trim().length === 0) {\n\t\t\t\tthrow new CliUsageError(\"Option --session requires a non-empty value.\");\n\t\t\t}\n\t\t\tsessionPath = value;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument?.startsWith(\"-\")) {\n\t\t\tthrow new CliUsageError(`Unknown option \"${argument}\".`);\n\t\t}\n\t\tif (argument !== undefined) {\n\t\t\tpromptParts.push(argument);\n\t\t}\n\t}\n\n\tif (printAlias && mode !== \"print\") {\n\t\tthrow new CliUsageError(`Cannot combine --print with --mode ${mode}.`);\n\t}\n\tif (continueSession && sessionPath !== undefined) {\n\t\tthrow new CliUsageError(\"Cannot combine --continue with --session.\");\n\t}\n\tif (promptParts.length === 0 && mode !== \"interactive\") {\n\t\tthrow new CliUsageError(\"A prompt is required.\");\n\t}\n\n\treturn {\n\t\tkind: \"run\",\n\t\tmode,\n\t\tprompt: promptParts.join(\" \"),\n\t\t...(sessionPath ? { sessionPath } : {}),\n\t\t...(continueSession ? { continueSession: true as const } : {}),\n\t};\n}\n\nconst HELP_TEXT = `Usage: di-code [options] <prompt>\n\nOptions:\n -p, --print Print only the final assistant text (default)\n --mode <mode> Output mode: print, json, or interactive\n --interactive Start interactive terminal mode\n --continue, -c Continue the most recently modified session\n --session <path> Create or resume a JSONL session (relative to the work root)\n -h, --help Show help\n -v, --version Show version\n`;\n\nexport interface CliDependencies {\n\tstdout(text: string): void;\n\tstderr(text: string): void;\n\trun(command: Extract<CliCommand, { kind: \"run\" }>): Promise<number>;\n\treadonly version: string;\n}\n\nexport async function runCli(args: readonly string[], dependencies: CliDependencies): Promise<number> {\n\tlet command: CliCommand;\n\ttry {\n\t\tcommand = parseCliArgs(args);\n\t} catch (cause) {\n\t\tif (cause instanceof CliUsageError) {\n\t\t\tdependencies.stderr(`${cause.message}\\n`);\n\t\t\treturn 1;\n\t\t}\n\t\tthrow cause;\n\t}\n\n\tswitch (command.kind) {\n\t\tcase \"help\":\n\t\t\tdependencies.stdout(HELP_TEXT);\n\t\t\treturn 0;\n\t\tcase \"version\":\n\t\t\tdependencies.stdout(`${dependencies.version}\\n`);\n\t\t\treturn 0;\n\t\tcase \"run\":\n\t\t\treturn dependencies.run(command);\n\t}\n}\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["export type OutputMode = \"print\" | \"json\" | \"interactive\";\n\nexport type CliCommand =\n\t| { kind: \"help\" }\n\t| { kind: \"version\" }\n\t| { kind: \"plugin\"; action: \"install\" | \"list\" | \"enable\" | \"disable\" | \"update\" | \"remove\"; argument?: string }\n\t| {\n\t\t\tkind: \"run\";\n\t\t\tmode: OutputMode;\n\t\t\tprompt: string;\n\t\t\tsessionPath?: string;\n\t\t\tcontinueSession?: true;\n\t\t\tnoSkills?: true;\n\t\t\tnoContextFiles?: true;\n\t\t\tskillPaths?: readonly string[];\n\t\t\tprojectTrust?: boolean;\n\t };\n\nexport class CliUsageError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CliUsageError\";\n\t}\n}\n\nexport function parseCliArgs(args: readonly string[]): CliCommand {\n\tif (args[0] === \"plugin\") {\n\t\tconst action = args[1];\n\t\tif (\n\t\t\taction !== \"install\" &&\n\t\t\taction !== \"list\" &&\n\t\t\taction !== \"enable\" &&\n\t\t\taction !== \"disable\" &&\n\t\t\taction !== \"update\" &&\n\t\t\taction !== \"remove\"\n\t\t)\n\t\t\tthrow new CliUsageError(\"Plugin command must be install, list, enable, disable, update, or remove.\");\n\t\tconst argument = args[2];\n\t\tif (\n\t\t\targs.length > 3 ||\n\t\t\t(action !== \"list\" && (argument === undefined || argument.trim() === \"\")) ||\n\t\t\t(action === \"list\" && argument !== undefined)\n\t\t)\n\t\t\tthrow new CliUsageError(\"Plugin command has invalid arguments.\");\n\t\treturn { kind: \"plugin\", action, ...(argument ? { argument } : {}) };\n\t}\n\tconst staticOption = args.find((argument) => [\"-h\", \"--help\", \"-v\", \"--version\"].includes(argument));\n\tif (staticOption !== undefined) {\n\t\tconst kind = staticOption === \"-h\" || staticOption === \"--help\" ? \"help\" : \"version\";\n\t\tif (args.length !== 1) {\n\t\t\tthrow new CliUsageError(`--${kind} must be used on its own.`);\n\t\t}\n\t\treturn { kind };\n\t}\n\n\tlet mode: OutputMode = \"print\";\n\tlet printAlias = false;\n\tlet sessionPath: string | undefined;\n\tlet continueSession = false;\n\tlet noSkills = false;\n\tlet noContextFiles = false;\n\tlet projectTrust: boolean | undefined;\n\tconst skillPaths: string[] = [];\n\tconst promptParts: string[] = [];\n\n\tfor (let index = 0; index < args.length; index++) {\n\t\tconst argument = args[index];\n\t\tif (argument === \"-p\" || argument === \"--print\") {\n\t\t\tprintAlias = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--interactive\") {\n\t\t\tmode = \"interactive\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"-c\" || argument === \"--continue\") {\n\t\t\tcontinueSession = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--no-skills\") {\n\t\t\tnoSkills = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--no-context-files\") {\n\t\t\tnoContextFiles = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--trust-project\" || argument === \"--untrust-project\") {\n\t\t\tconst nextTrust = argument === \"--trust-project\";\n\t\t\tif (projectTrust !== undefined && projectTrust !== nextTrust) {\n\t\t\t\tthrow new CliUsageError(\"Cannot combine --trust-project with --untrust-project.\");\n\t\t\t}\n\t\t\tprojectTrust = nextTrust;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--skill\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined || value.trim().length === 0) {\n\t\t\t\tthrow new CliUsageError(\"Option --skill requires a non-empty value.\");\n\t\t\t}\n\t\t\tskillPaths.push(value);\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--mode\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined) {\n\t\t\t\tthrow new CliUsageError(\"Option --mode requires a value.\");\n\t\t\t}\n\t\t\tif (value !== \"print\" && value !== \"json\" && value !== \"interactive\") {\n\t\t\t\tthrow new CliUsageError(`Unsupported mode \"${value}\". Expected print, json, or interactive.`);\n\t\t\t}\n\t\t\tmode = value;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--session\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined) {\n\t\t\t\tthrow new CliUsageError(\"Option --session requires a value.\");\n\t\t\t}\n\t\t\tif (value.trim().length === 0) {\n\t\t\t\tthrow new CliUsageError(\"Option --session requires a non-empty value.\");\n\t\t\t}\n\t\t\tsessionPath = value;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument?.startsWith(\"-\")) {\n\t\t\tthrow new CliUsageError(`Unknown option \"${argument}\".`);\n\t\t}\n\t\tif (argument !== undefined) {\n\t\t\tpromptParts.push(argument);\n\t\t}\n\t}\n\n\tif (printAlias && mode !== \"print\") {\n\t\tthrow new CliUsageError(`Cannot combine --print with --mode ${mode}.`);\n\t}\n\tif (continueSession && sessionPath !== undefined) {\n\t\tthrow new CliUsageError(\"Cannot combine --continue with --session.\");\n\t}\n\tif (promptParts.length === 0 && mode !== \"interactive\") {\n\t\tthrow new CliUsageError(\"A prompt is required.\");\n\t}\n\n\treturn {\n\t\tkind: \"run\",\n\t\tmode,\n\t\tprompt: promptParts.join(\" \"),\n\t\t...(sessionPath ? { sessionPath } : {}),\n\t\t...(continueSession ? { continueSession: true as const } : {}),\n\t\t...(noSkills ? { noSkills: true as const } : {}),\n\t\t...(noContextFiles ? { noContextFiles: true as const } : {}),\n\t\t...(skillPaths.length > 0 ? { skillPaths } : {}),\n\t\t...(projectTrust === undefined ? {} : { projectTrust }),\n\t};\n}\n\nconst HELP_TEXT = `Usage: di-code [options] <prompt>\n\nOptions:\n -p, --print Print only the final assistant text (default)\n --mode <mode> Output mode: print, json, or interactive\n --interactive Start interactive terminal mode\n --continue, -c Continue the most recently modified session\n --session <path> Create or resume a JSONL session (relative to the work root)\n --skill <path> Add a SKILL.md file or skill directory (repeatable)\n --no-skills Disable all Skill loading\n --no-context-files Disable AGENTS.md discovery and loading\n --trust-project Persist trust for project-local Skill discovery\n --untrust-project Persist denial for project-local Skill discovery\n plugin <action> Install, list, enable, disable, update, or remove a plugin\n -h, --help Show help\n -v, --version Show version\n`;\n\nexport interface CliDependencies {\n\tstdout(text: string): void;\n\tstderr(text: string): void;\n\trun(command: Extract<CliCommand, { kind: \"run\" }>): Promise<number>;\n\tplugin?(command: Extract<CliCommand, { kind: \"plugin\" }>): Promise<number>;\n\treadonly version: string;\n}\n\nexport async function runCli(args: readonly string[], dependencies: CliDependencies): Promise<number> {\n\tlet command: CliCommand;\n\ttry {\n\t\tcommand = parseCliArgs(args);\n\t} catch (cause) {\n\t\tif (cause instanceof CliUsageError) {\n\t\t\tdependencies.stderr(`${cause.message}\\n`);\n\t\t\treturn 1;\n\t\t}\n\t\tthrow cause;\n\t}\n\n\tswitch (command.kind) {\n\t\tcase \"help\":\n\t\t\tdependencies.stdout(HELP_TEXT);\n\t\t\treturn 0;\n\t\tcase \"plugin\":\n\t\t\tif (!dependencies.plugin) throw new Error(\"Plugin command handler is unavailable.\");\n\t\t\treturn dependencies.plugin(command);\n\t\tcase \"version\":\n\t\t\tdependencies.stdout(`${dependencies.version}\\n`);\n\t\t\treturn 0;\n\t\tcase \"run\":\n\t\t\treturn dependencies.run(command);\n\t}\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export { DefaultResourceLoader, loadResources } from "./loader.ts";
2
+ export type { ContextFile, ResourceDiagnostic, ResourceDiagnosticStage, ResourceLoader, ResourceLoaderOptions, ResourceScope, ResourceSnapshot, SkillResource, } from "./types.ts";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EACX,WAAW,EACX,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,gBAAgB,EAChB,aAAa,GACb,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { DefaultResourceLoader, loadResources } from "./loader.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC","sourcesContent":["export { DefaultResourceLoader, loadResources } from \"./loader.ts\";\nexport type {\n\tContextFile,\n\tResourceDiagnostic,\n\tResourceDiagnosticStage,\n\tResourceLoader,\n\tResourceLoaderOptions,\n\tResourceScope,\n\tResourceSnapshot,\n\tSkillResource,\n} from \"./types.ts\";\n"]}
@@ -0,0 +1,8 @@
1
+ import type { ResourceLoader, ResourceLoaderOptions, ResourceSnapshot } from "./types.ts";
2
+ export declare class DefaultResourceLoader implements ResourceLoader {
3
+ private readonly options;
4
+ constructor(options: ResourceLoaderOptions);
5
+ load(): Promise<ResourceSnapshot>;
6
+ }
7
+ export declare function loadResources(options: ResourceLoaderOptions): Promise<ResourceSnapshot>;
8
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/core/resources/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGX,cAAc,EACd,qBAAqB,EAErB,gBAAgB,EAEhB,MAAM,YAAY,CAAC;AAyFpB,qBAAa,qBAAsB,YAAW,cAAc;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;gBAEpC,OAAO,EAAE,qBAAqB;IAIpC,IAAI,IAAI,OAAO,CAAC,gBAAgB,CAAC;CAmEvC;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAE7F"}
@@ -0,0 +1,174 @@
1
+ import { access, readFile, stat } from "node:fs/promises";
2
+ import { dirname, join, parse, resolve } from "node:path";
3
+ import { discoverSkills, loadSkill } from "./skills.js";
4
+ const MAX_CONTEXT_FILE_BYTES = 256 * 1024;
5
+ function isMissingPath(cause) {
6
+ return cause instanceof Error && "code" in cause && cause.code === "ENOENT";
7
+ }
8
+ function contextDiagnostic(path, stage, message) {
9
+ return { path, kind: "agents", stage, severity: "warning", message };
10
+ }
11
+ async function locateAgentsFile(directory) {
12
+ for (const name of ["AGENTS.md", "AGENTS.MD"]) {
13
+ const path = join(directory, name);
14
+ try {
15
+ if ((await stat(path)).isFile())
16
+ return path;
17
+ }
18
+ catch (cause) {
19
+ if (!isMissingPath(cause))
20
+ throw cause;
21
+ }
22
+ }
23
+ return undefined;
24
+ }
25
+ async function loadContextFile(path, scope) {
26
+ try {
27
+ const metadata = await stat(path);
28
+ if (metadata.size > MAX_CONTEXT_FILE_BYTES) {
29
+ return { diagnostic: contextDiagnostic(path, "read", `AGENTS.md exceeds ${MAX_CONTEXT_FILE_BYTES} byte limit`) };
30
+ }
31
+ return { file: { kind: "agents", path: resolve(path), scope, content: await readFile(path, "utf8") } };
32
+ }
33
+ catch (cause) {
34
+ const message = cause instanceof Error ? cause.message : String(cause);
35
+ return { diagnostic: contextDiagnostic(path, "read", `Failed to read AGENTS.md: ${message}`) };
36
+ }
37
+ }
38
+ async function loadContextFiles(options) {
39
+ if (options.noContextFiles)
40
+ return { contextFiles: [], diagnostics: [] };
41
+ const contextFiles = [];
42
+ const diagnostics = [];
43
+ const seen = new Set();
44
+ const add = async (directory, scope) => {
45
+ let path;
46
+ try {
47
+ path = await locateAgentsFile(directory);
48
+ }
49
+ catch (cause) {
50
+ const message = cause instanceof Error ? cause.message : String(cause);
51
+ diagnostics.push(contextDiagnostic(directory, "discover", `Failed to discover AGENTS.md: ${message}`));
52
+ return;
53
+ }
54
+ if (!path)
55
+ return;
56
+ const absolutePath = resolve(path);
57
+ if (seen.has(absolutePath))
58
+ return;
59
+ seen.add(absolutePath);
60
+ const loaded = await loadContextFile(absolutePath, scope);
61
+ if (loaded.file)
62
+ contextFiles.push(loaded.file);
63
+ if (loaded.diagnostic)
64
+ diagnostics.push(loaded.diagnostic);
65
+ };
66
+ await add(resolve(options.agentDir), "global");
67
+ const ancestors = [];
68
+ let current = resolve(options.cwd);
69
+ while (true) {
70
+ ancestors.unshift(current);
71
+ const parent = dirname(current);
72
+ if (parent === current || parse(current).root === current)
73
+ break;
74
+ current = parent;
75
+ }
76
+ for (const directory of ancestors)
77
+ await add(directory, directory === resolve(options.cwd) ? "project" : "ancestor");
78
+ return { contextFiles, diagnostics };
79
+ }
80
+ async function exists(directory) {
81
+ try {
82
+ await access(directory);
83
+ return true;
84
+ }
85
+ catch (cause) {
86
+ if (isMissingPath(cause))
87
+ return false;
88
+ throw cause;
89
+ }
90
+ }
91
+ export class DefaultResourceLoader {
92
+ options;
93
+ constructor(options) {
94
+ this.options = options;
95
+ }
96
+ async load() {
97
+ const context = await loadContextFiles(this.options);
98
+ const diagnostics = [...context.diagnostics];
99
+ const skills = new Map();
100
+ const add = (candidate, candidateDiagnostics) => {
101
+ diagnostics.push(...candidateDiagnostics);
102
+ const existing = skills.get(candidate.name);
103
+ if (existing) {
104
+ diagnostics.push({
105
+ path: candidate.filePath,
106
+ kind: "skill",
107
+ stage: "collision",
108
+ severity: "warning",
109
+ message: `Skill name collision: "${candidate.name}"; using ${existing.filePath}`,
110
+ });
111
+ return;
112
+ }
113
+ skills.set(candidate.name, candidate);
114
+ };
115
+ const addResults = (results) => {
116
+ for (const result of results) {
117
+ if (result.skill)
118
+ add(result.skill, result.diagnostics);
119
+ else
120
+ diagnostics.push(...result.diagnostics);
121
+ }
122
+ };
123
+ if (!this.options.noSkills) {
124
+ for (const rawPath of this.options.skillPaths ?? []) {
125
+ const path = resolve(this.options.cwd, rawPath);
126
+ try {
127
+ const metadata = await stat(path);
128
+ if (metadata.isDirectory())
129
+ addResults(await discoverSkills(path, "explicit"));
130
+ else {
131
+ const result = await loadSkill(path, "explicit");
132
+ if (result.skill)
133
+ add(result.skill, result.diagnostics);
134
+ else
135
+ diagnostics.push(...result.diagnostics);
136
+ }
137
+ }
138
+ catch (cause) {
139
+ const message = isMissingPath(cause)
140
+ ? "Skill path does not exist"
141
+ : `Failed to discover skill path: ${String(cause)}`;
142
+ diagnostics.push({ path, kind: "skill", stage: "discover", severity: "warning", message });
143
+ }
144
+ }
145
+ const projectDirectories = [
146
+ join(this.options.cwd, ".di-code", "skills"),
147
+ join(this.options.cwd, ".pi", "skills"),
148
+ ];
149
+ if (this.options.projectTrusted === true) {
150
+ for (const directory of projectDirectories)
151
+ addResults(await discoverSkills(directory, "project"));
152
+ }
153
+ else {
154
+ for (const directory of projectDirectories) {
155
+ if (await exists(directory)) {
156
+ diagnostics.push({
157
+ path: resolve(directory),
158
+ kind: "skill",
159
+ stage: "trust",
160
+ severity: "warning",
161
+ message: "Project skill skipped because project trust is not granted",
162
+ });
163
+ }
164
+ }
165
+ }
166
+ addResults(await discoverSkills(join(this.options.agentDir, "skills"), "global"));
167
+ }
168
+ return { contextFiles: context.contextFiles, skills: [...skills.values()], diagnostics };
169
+ }
170
+ }
171
+ export async function loadResources(options) {
172
+ return new DefaultResourceLoader(options).load();
173
+ }
174
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/core/resources/loader.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, readFile, stat } from \"node:fs/promises\";\nimport { dirname, join, parse, resolve } from \"node:path\";\nimport { discoverSkills, loadSkill } from \"./skills.ts\";\nimport type {\n\tContextFile,\n\tResourceDiagnostic,\n\tResourceLoader,\n\tResourceLoaderOptions,\n\tResourceScope,\n\tResourceSnapshot,\n\tSkillResource,\n} from \"./types.ts\";\n\nconst MAX_CONTEXT_FILE_BYTES = 256 * 1024;\n\nfunction isMissingPath(cause: unknown): boolean {\n\treturn cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\";\n}\n\nfunction contextDiagnostic(path: string, stage: ResourceDiagnostic[\"stage\"], message: string): ResourceDiagnostic {\n\treturn { path, kind: \"agents\", stage, severity: \"warning\", message };\n}\n\nasync function locateAgentsFile(directory: string): Promise<string | undefined> {\n\tfor (const name of [\"AGENTS.md\", \"AGENTS.MD\"]) {\n\t\tconst path = join(directory, name);\n\t\ttry {\n\t\t\tif ((await stat(path)).isFile()) return path;\n\t\t} catch (cause) {\n\t\t\tif (!isMissingPath(cause)) throw cause;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nasync function loadContextFile(\n\tpath: string,\n\tscope: ResourceScope,\n): Promise<{ file?: ContextFile; diagnostic?: ResourceDiagnostic }> {\n\ttry {\n\t\tconst metadata = await stat(path);\n\t\tif (metadata.size > MAX_CONTEXT_FILE_BYTES) {\n\t\t\treturn { diagnostic: contextDiagnostic(path, \"read\", `AGENTS.md exceeds ${MAX_CONTEXT_FILE_BYTES} byte limit`) };\n\t\t}\n\t\treturn { file: { kind: \"agents\", path: resolve(path), scope, content: await readFile(path, \"utf8\") } };\n\t} catch (cause) {\n\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\treturn { diagnostic: contextDiagnostic(path, \"read\", `Failed to read AGENTS.md: ${message}`) };\n\t}\n}\n\nasync function loadContextFiles(options: ResourceLoaderOptions): Promise<{\n\tcontextFiles: ContextFile[];\n\tdiagnostics: ResourceDiagnostic[];\n}> {\n\tif (options.noContextFiles) return { contextFiles: [], diagnostics: [] };\n\tconst contextFiles: ContextFile[] = [];\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\tconst seen = new Set<string>();\n\tconst add = async (directory: string, scope: ResourceScope): Promise<void> => {\n\t\tlet path: string | undefined;\n\t\ttry {\n\t\t\tpath = await locateAgentsFile(directory);\n\t\t} catch (cause) {\n\t\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\t\tdiagnostics.push(contextDiagnostic(directory, \"discover\", `Failed to discover AGENTS.md: ${message}`));\n\t\t\treturn;\n\t\t}\n\t\tif (!path) return;\n\t\tconst absolutePath = resolve(path);\n\t\tif (seen.has(absolutePath)) return;\n\t\tseen.add(absolutePath);\n\t\tconst loaded = await loadContextFile(absolutePath, scope);\n\t\tif (loaded.file) contextFiles.push(loaded.file);\n\t\tif (loaded.diagnostic) diagnostics.push(loaded.diagnostic);\n\t};\n\n\tawait add(resolve(options.agentDir), \"global\");\n\tconst ancestors: string[] = [];\n\tlet current = resolve(options.cwd);\n\twhile (true) {\n\t\tancestors.unshift(current);\n\t\tconst parent = dirname(current);\n\t\tif (parent === current || parse(current).root === current) break;\n\t\tcurrent = parent;\n\t}\n\tfor (const directory of ancestors) await add(directory, directory === resolve(options.cwd) ? \"project\" : \"ancestor\");\n\treturn { contextFiles, diagnostics };\n}\n\nasync function exists(directory: string): Promise<boolean> {\n\ttry {\n\t\tawait access(directory);\n\t\treturn true;\n\t} catch (cause) {\n\t\tif (isMissingPath(cause)) return false;\n\t\tthrow cause;\n\t}\n}\n\nexport class DefaultResourceLoader implements ResourceLoader {\n\tprivate readonly options: ResourceLoaderOptions;\n\n\tconstructor(options: ResourceLoaderOptions) {\n\t\tthis.options = options;\n\t}\n\n\tasync load(): Promise<ResourceSnapshot> {\n\t\tconst context = await loadContextFiles(this.options);\n\t\tconst diagnostics = [...context.diagnostics];\n\t\tconst skills = new Map<string, SkillResource>();\n\t\tconst add = (candidate: SkillResource, candidateDiagnostics: readonly ResourceDiagnostic[]): void => {\n\t\t\tdiagnostics.push(...candidateDiagnostics);\n\t\t\tconst existing = skills.get(candidate.name);\n\t\t\tif (existing) {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\tpath: candidate.filePath,\n\t\t\t\t\tkind: \"skill\",\n\t\t\t\t\tstage: \"collision\",\n\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\tmessage: `Skill name collision: \"${candidate.name}\"; using ${existing.filePath}`,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tskills.set(candidate.name, candidate);\n\t\t};\n\t\tconst addResults = (results: Awaited<ReturnType<typeof discoverSkills>>): void => {\n\t\t\tfor (const result of results) {\n\t\t\t\tif (result.skill) add(result.skill, result.diagnostics);\n\t\t\t\telse diagnostics.push(...result.diagnostics);\n\t\t\t}\n\t\t};\n\n\t\tif (!this.options.noSkills) {\n\t\t\tfor (const rawPath of this.options.skillPaths ?? []) {\n\t\t\t\tconst path = resolve(this.options.cwd, rawPath);\n\t\t\t\ttry {\n\t\t\t\t\tconst metadata = await stat(path);\n\t\t\t\t\tif (metadata.isDirectory()) addResults(await discoverSkills(path, \"explicit\"));\n\t\t\t\t\telse {\n\t\t\t\t\t\tconst result = await loadSkill(path, \"explicit\");\n\t\t\t\t\t\tif (result.skill) add(result.skill, result.diagnostics);\n\t\t\t\t\t\telse diagnostics.push(...result.diagnostics);\n\t\t\t\t\t}\n\t\t\t\t} catch (cause) {\n\t\t\t\t\tconst message = isMissingPath(cause)\n\t\t\t\t\t\t? \"Skill path does not exist\"\n\t\t\t\t\t\t: `Failed to discover skill path: ${String(cause)}`;\n\t\t\t\t\tdiagnostics.push({ path, kind: \"skill\", stage: \"discover\", severity: \"warning\", message });\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst projectDirectories = [\n\t\t\t\tjoin(this.options.cwd, \".di-code\", \"skills\"),\n\t\t\t\tjoin(this.options.cwd, \".pi\", \"skills\"),\n\t\t\t];\n\t\t\tif (this.options.projectTrusted === true) {\n\t\t\t\tfor (const directory of projectDirectories) addResults(await discoverSkills(directory, \"project\"));\n\t\t\t} else {\n\t\t\t\tfor (const directory of projectDirectories) {\n\t\t\t\t\tif (await exists(directory)) {\n\t\t\t\t\t\tdiagnostics.push({\n\t\t\t\t\t\t\tpath: resolve(directory),\n\t\t\t\t\t\t\tkind: \"skill\",\n\t\t\t\t\t\t\tstage: \"trust\",\n\t\t\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\t\t\tmessage: \"Project skill skipped because project trust is not granted\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\taddResults(await discoverSkills(join(this.options.agentDir, \"skills\"), \"global\"));\n\t\t}\n\t\treturn { contextFiles: context.contextFiles, skills: [...skills.values()], diagnostics };\n\t}\n}\n\nexport async function loadResources(options: ResourceLoaderOptions): Promise<ResourceSnapshot> {\n\treturn new DefaultResourceLoader(options).load();\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { ResourceDiagnostic, ResourceScope, SkillResource } from "./types.ts";
2
+ interface ParsedSkill {
3
+ readonly skill?: SkillResource;
4
+ readonly diagnostics: readonly ResourceDiagnostic[];
5
+ }
6
+ export declare function loadSkill(path: string, scope: ResourceScope): Promise<ParsedSkill>;
7
+ export declare function readSkillContent(skill: SkillResource, signal?: AbortSignal): Promise<string>;
8
+ export declare function discoverSkills(directory: string, scope: ResourceScope): Promise<ParsedSkill[]>;
9
+ export {};
10
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../../src/core/resources/skills.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAMnF,UAAU,WAAW;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACpD;AAyDD,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CA6CxF;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBlG;AAED,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CA2BpG"}
@@ -0,0 +1,167 @@
1
+ import { readdir, readFile, stat } from "node:fs/promises";
2
+ import { dirname, join, resolve } from "node:path";
3
+ const MAX_SKILL_BYTES = 256 * 1024;
4
+ const MAX_NAME_LENGTH = 64;
5
+ const MAX_DESCRIPTION_LENGTH = 1024;
6
+ function diagnostic(path, stage, message, severity = "warning") {
7
+ return { path, kind: "skill", stage, severity, message };
8
+ }
9
+ function parseScalar(value) {
10
+ const trimmed = value.trim();
11
+ if ((trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
12
+ return trimmed.slice(1, -1);
13
+ }
14
+ return trimmed;
15
+ }
16
+ function parseFrontmatter(source) {
17
+ const lines = source.replace(/^\uFEFF/, "").split(/\r?\n/);
18
+ if (lines[0] !== "---")
19
+ return undefined;
20
+ const end = lines.findIndex((line, index) => index > 0 && line === "---");
21
+ if (end < 0)
22
+ return undefined;
23
+ const entries = {};
24
+ for (const line of lines.slice(1, end)) {
25
+ if (!line.trim() || line.trimStart().startsWith("#"))
26
+ continue;
27
+ const separator = line.indexOf(":");
28
+ if (separator < 1)
29
+ continue;
30
+ entries[line.slice(0, separator).trim()] = parseScalar(line.slice(separator + 1));
31
+ }
32
+ return entries;
33
+ }
34
+ function extractSkillBody(source) {
35
+ const lines = source.replace(/^\uFEFF/, "").split(/\r?\n/);
36
+ if (lines[0] !== "---")
37
+ return undefined;
38
+ const end = lines.findIndex((line, index) => index > 0 && line === "---");
39
+ if (end < 0)
40
+ return undefined;
41
+ return lines.slice(end + 1).join("\n");
42
+ }
43
+ function validateName(name) {
44
+ if (name.length === 0)
45
+ return "name is required";
46
+ if (name.length > MAX_NAME_LENGTH)
47
+ return `name exceeds ${MAX_NAME_LENGTH} characters`;
48
+ if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) {
49
+ return "name must contain only lowercase letters, numbers, and single hyphens";
50
+ }
51
+ return undefined;
52
+ }
53
+ function validateDescription(description) {
54
+ if (description.length === 0)
55
+ return "description is required";
56
+ if (description.length > MAX_DESCRIPTION_LENGTH)
57
+ return `description exceeds ${MAX_DESCRIPTION_LENGTH} characters`;
58
+ return undefined;
59
+ }
60
+ export async function loadSkill(path, scope) {
61
+ const filePath = resolve(path);
62
+ const diagnostics = [];
63
+ try {
64
+ const metadata = await stat(filePath);
65
+ if (!metadata.isFile())
66
+ return { diagnostics: [diagnostic(filePath, "discover", "Skill path is not a file")] };
67
+ if (metadata.size > MAX_SKILL_BYTES) {
68
+ return { diagnostics: [diagnostic(filePath, "read", `Skill exceeds ${MAX_SKILL_BYTES} byte limit`)] };
69
+ }
70
+ const source = await readFile(filePath, "utf8");
71
+ const frontmatter = parseFrontmatter(source);
72
+ if (!frontmatter)
73
+ return { diagnostics: [diagnostic(filePath, "parse", "Skill frontmatter is required")] };
74
+ const name = frontmatter.name ?? "";
75
+ const description = frontmatter.description ?? "";
76
+ const nameError = validateName(name);
77
+ const descriptionError = validateDescription(description);
78
+ if (nameError)
79
+ diagnostics.push(diagnostic(filePath, "parse", nameError));
80
+ if (descriptionError)
81
+ diagnostics.push(diagnostic(filePath, "parse", descriptionError));
82
+ if (nameError || descriptionError)
83
+ return { diagnostics };
84
+ const disableModelInvocationValue = frontmatter["disable-model-invocation"];
85
+ if (disableModelInvocationValue !== undefined &&
86
+ disableModelInvocationValue !== "true" &&
87
+ disableModelInvocationValue !== "false") {
88
+ return {
89
+ diagnostics: [diagnostic(filePath, "parse", "disable-model-invocation must be true or false")],
90
+ };
91
+ }
92
+ return {
93
+ skill: {
94
+ kind: "skill",
95
+ name,
96
+ description,
97
+ filePath,
98
+ baseDir: dirname(filePath),
99
+ scope,
100
+ disableModelInvocation: disableModelInvocationValue === "true",
101
+ },
102
+ diagnostics,
103
+ };
104
+ }
105
+ catch (cause) {
106
+ const message = cause instanceof Error ? cause.message : String(cause);
107
+ return { diagnostics: [diagnostic(filePath, "read", `Failed to read skill: ${message}`, "error")] };
108
+ }
109
+ }
110
+ export async function readSkillContent(skill, signal) {
111
+ if (signal?.aborted)
112
+ throw new Error("Operation aborted");
113
+ const path = resolve(skill.filePath);
114
+ try {
115
+ const metadata = await stat(path);
116
+ if (!metadata.isFile())
117
+ throw new Error("Skill path is not a file");
118
+ if (metadata.size > MAX_SKILL_BYTES)
119
+ throw new Error(`Skill exceeds ${MAX_SKILL_BYTES} byte limit`);
120
+ const source = await readFile(path, { encoding: "utf8", signal });
121
+ const body = extractSkillBody(source);
122
+ if (body === undefined)
123
+ throw new Error("Skill frontmatter is required");
124
+ return body;
125
+ }
126
+ catch (cause) {
127
+ if (cause instanceof Error && cause.message === "Operation aborted")
128
+ throw cause;
129
+ const message = cause instanceof Error ? cause.message : String(cause);
130
+ throw new Error(`Failed to load skill "${skill.name}": ${message}`, { cause });
131
+ }
132
+ }
133
+ export async function discoverSkills(directory, scope) {
134
+ const root = resolve(directory);
135
+ const results = [];
136
+ async function visit(current) {
137
+ let entries;
138
+ try {
139
+ entries = await readdir(current, { withFileTypes: true });
140
+ }
141
+ catch (cause) {
142
+ if (isMissingPath(cause))
143
+ return;
144
+ const message = cause instanceof Error ? cause.message : String(cause);
145
+ results.push({
146
+ diagnostics: [diagnostic(current, "discover", `Failed to read skill directory: ${message}`, "error")],
147
+ });
148
+ return;
149
+ }
150
+ const skillEntry = entries.find((entry) => entry.name === "SKILL.md" && entry.isFile());
151
+ if (skillEntry) {
152
+ results.push(await loadSkill(join(current, skillEntry.name), scope));
153
+ return;
154
+ }
155
+ for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
156
+ if (entry.name.startsWith(".") || entry.name === "node_modules" || !entry.isDirectory())
157
+ continue;
158
+ await visit(join(current, entry.name));
159
+ }
160
+ }
161
+ await visit(root);
162
+ return results;
163
+ }
164
+ function isMissingPath(cause) {
165
+ return cause instanceof Error && "code" in cause && cause.code === "ENOENT";
166
+ }
167
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../../src/core/resources/skills.ts"],"names":[],"mappings":"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","sourcesContent":["import { readdir, readFile, stat } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport type { ResourceDiagnostic, ResourceScope, SkillResource } from \"./types.ts\";\n\nconst MAX_SKILL_BYTES = 256 * 1024;\nconst MAX_NAME_LENGTH = 64;\nconst MAX_DESCRIPTION_LENGTH = 1024;\n\ninterface ParsedSkill {\n\treadonly skill?: SkillResource;\n\treadonly diagnostics: readonly ResourceDiagnostic[];\n}\n\nfunction diagnostic(\n\tpath: string,\n\tstage: ResourceDiagnostic[\"stage\"],\n\tmessage: string,\n\tseverity: ResourceDiagnostic[\"severity\"] = \"warning\",\n): ResourceDiagnostic {\n\treturn { path, kind: \"skill\", stage, severity, message };\n}\n\nfunction parseScalar(value: string): string {\n\tconst trimmed = value.trim();\n\tif ((trimmed.startsWith('\"') && trimmed.endsWith('\"')) || (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))) {\n\t\treturn trimmed.slice(1, -1);\n\t}\n\treturn trimmed;\n}\n\nfunction parseFrontmatter(source: string): Record<string, string> | undefined {\n\tconst lines = source.replace(/^\\uFEFF/, \"\").split(/\\r?\\n/);\n\tif (lines[0] !== \"---\") return undefined;\n\tconst end = lines.findIndex((line, index) => index > 0 && line === \"---\");\n\tif (end < 0) return undefined;\n\tconst entries: Record<string, string> = {};\n\tfor (const line of lines.slice(1, end)) {\n\t\tif (!line.trim() || line.trimStart().startsWith(\"#\")) continue;\n\t\tconst separator = line.indexOf(\":\");\n\t\tif (separator < 1) continue;\n\t\tentries[line.slice(0, separator).trim()] = parseScalar(line.slice(separator + 1));\n\t}\n\treturn entries;\n}\n\nfunction extractSkillBody(source: string): string | undefined {\n\tconst lines = source.replace(/^\\uFEFF/, \"\").split(/\\r?\\n/);\n\tif (lines[0] !== \"---\") return undefined;\n\tconst end = lines.findIndex((line, index) => index > 0 && line === \"---\");\n\tif (end < 0) return undefined;\n\treturn lines.slice(end + 1).join(\"\\n\");\n}\n\nfunction validateName(name: string): string | undefined {\n\tif (name.length === 0) return \"name is required\";\n\tif (name.length > MAX_NAME_LENGTH) return `name exceeds ${MAX_NAME_LENGTH} characters`;\n\tif (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) {\n\t\treturn \"name must contain only lowercase letters, numbers, and single hyphens\";\n\t}\n\treturn undefined;\n}\n\nfunction validateDescription(description: string): string | undefined {\n\tif (description.length === 0) return \"description is required\";\n\tif (description.length > MAX_DESCRIPTION_LENGTH) return `description exceeds ${MAX_DESCRIPTION_LENGTH} characters`;\n\treturn undefined;\n}\n\nexport async function loadSkill(path: string, scope: ResourceScope): Promise<ParsedSkill> {\n\tconst filePath = resolve(path);\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\ttry {\n\t\tconst metadata = await stat(filePath);\n\t\tif (!metadata.isFile()) return { diagnostics: [diagnostic(filePath, \"discover\", \"Skill path is not a file\")] };\n\t\tif (metadata.size > MAX_SKILL_BYTES) {\n\t\t\treturn { diagnostics: [diagnostic(filePath, \"read\", `Skill exceeds ${MAX_SKILL_BYTES} byte limit`)] };\n\t\t}\n\t\tconst source = await readFile(filePath, \"utf8\");\n\t\tconst frontmatter = parseFrontmatter(source);\n\t\tif (!frontmatter) return { diagnostics: [diagnostic(filePath, \"parse\", \"Skill frontmatter is required\")] };\n\t\tconst name = frontmatter.name ?? \"\";\n\t\tconst description = frontmatter.description ?? \"\";\n\t\tconst nameError = validateName(name);\n\t\tconst descriptionError = validateDescription(description);\n\t\tif (nameError) diagnostics.push(diagnostic(filePath, \"parse\", nameError));\n\t\tif (descriptionError) diagnostics.push(diagnostic(filePath, \"parse\", descriptionError));\n\t\tif (nameError || descriptionError) return { diagnostics };\n\t\tconst disableModelInvocationValue = frontmatter[\"disable-model-invocation\"];\n\t\tif (\n\t\t\tdisableModelInvocationValue !== undefined &&\n\t\t\tdisableModelInvocationValue !== \"true\" &&\n\t\t\tdisableModelInvocationValue !== \"false\"\n\t\t) {\n\t\t\treturn {\n\t\t\t\tdiagnostics: [diagnostic(filePath, \"parse\", \"disable-model-invocation must be true or false\")],\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tskill: {\n\t\t\t\tkind: \"skill\",\n\t\t\t\tname,\n\t\t\t\tdescription,\n\t\t\t\tfilePath,\n\t\t\t\tbaseDir: dirname(filePath),\n\t\t\t\tscope,\n\t\t\t\tdisableModelInvocation: disableModelInvocationValue === \"true\",\n\t\t\t},\n\t\t\tdiagnostics,\n\t\t};\n\t} catch (cause) {\n\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\treturn { diagnostics: [diagnostic(filePath, \"read\", `Failed to read skill: ${message}`, \"error\")] };\n\t}\n}\n\nexport async function readSkillContent(skill: SkillResource, signal?: AbortSignal): Promise<string> {\n\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\tconst path = resolve(skill.filePath);\n\ttry {\n\t\tconst metadata = await stat(path);\n\t\tif (!metadata.isFile()) throw new Error(\"Skill path is not a file\");\n\t\tif (metadata.size > MAX_SKILL_BYTES) throw new Error(`Skill exceeds ${MAX_SKILL_BYTES} byte limit`);\n\t\tconst source = await readFile(path, { encoding: \"utf8\", signal });\n\t\tconst body = extractSkillBody(source);\n\t\tif (body === undefined) throw new Error(\"Skill frontmatter is required\");\n\t\treturn body;\n\t} catch (cause) {\n\t\tif (cause instanceof Error && cause.message === \"Operation aborted\") throw cause;\n\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\tthrow new Error(`Failed to load skill \"${skill.name}\": ${message}`, { cause });\n\t}\n}\n\nexport async function discoverSkills(directory: string, scope: ResourceScope): Promise<ParsedSkill[]> {\n\tconst root = resolve(directory);\n\tconst results: ParsedSkill[] = [];\n\tasync function visit(current: string): Promise<void> {\n\t\tlet entries: import(\"node:fs\").Dirent<string>[];\n\t\ttry {\n\t\t\tentries = await readdir(current, { withFileTypes: true });\n\t\t} catch (cause) {\n\t\t\tif (isMissingPath(cause)) return;\n\t\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\t\tresults.push({\n\t\t\t\tdiagnostics: [diagnostic(current, \"discover\", `Failed to read skill directory: ${message}`, \"error\")],\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst skillEntry = entries.find((entry) => entry.name === \"SKILL.md\" && entry.isFile());\n\t\tif (skillEntry) {\n\t\t\tresults.push(await loadSkill(join(current, skillEntry.name), scope));\n\t\t\treturn;\n\t\t}\n\t\tfor (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {\n\t\t\tif (entry.name.startsWith(\".\") || entry.name === \"node_modules\" || !entry.isDirectory()) continue;\n\t\t\tawait visit(join(current, entry.name));\n\t\t}\n\t}\n\tawait visit(root);\n\treturn results;\n}\n\nfunction isMissingPath(cause: unknown): boolean {\n\treturn cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\";\n}\n"]}