@asm-agent/coding-agent 0.8.4 → 0.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/bundle/{anthropic-CWQBVVHC.js → anthropic-CILMWJ23.js} +1 -1
  3. package/dist/bundle/{azure-openai-responses-7JP64QDL.js → azure-openai-responses-TPNZ54LG.js} +2 -2
  4. package/dist/bundle/{bundled-modules-DZAECPSN.js → bundled-modules-SKYRKITN.js} +3 -3
  5. package/dist/bundle/{chunk-7HN2VZJJ.js → chunk-7QIBGY2R.js} +74 -74
  6. package/dist/bundle/{chunk-O7SB7LML.js → chunk-EFDSSG52.js} +69 -18
  7. package/dist/bundle/{chunk-FCQTXDPX.js → chunk-IYXHHLR6.js} +1 -1
  8. package/dist/bundle/{chunk-4KQVBOJB.js → chunk-YYVQTKC6.js} +2 -2
  9. package/dist/bundle/{cli-main-YXP4FEPB.js → cli-main-O3HK7MNQ.js} +3 -3
  10. package/dist/bundle/cli.js +1 -1
  11. package/dist/bundle/{google-DPYNVS7L.js → google-3TL5FKLN.js} +1 -1
  12. package/dist/bundle/{google-vertex-SKMI6LMM.js → google-vertex-WVFMK6QO.js} +1 -1
  13. package/dist/bundle/{main-DOLQ46ZM.js → main-4QYKME2K.js} +3 -3
  14. package/dist/bundle/{mistral-DUU7KDZ3.js → mistral-QV2OSBWW.js} +1 -1
  15. package/dist/bundle/{openai-codex-responses-D7FCP7DO.js → openai-codex-responses-J2GJ2FAO.js} +2 -2
  16. package/dist/bundle/{openai-completions-AH6TQF5C.js → openai-completions-W622H2EL.js} +1 -1
  17. package/dist/bundle/{openai-responses-DDC3EYTG.js → openai-responses-V75QG5T7.js} +2 -2
  18. package/dist/core/always-applied-skills.d.ts +3 -0
  19. package/dist/core/always-applied-skills.d.ts.map +1 -0
  20. package/dist/core/always-applied-skills.js +47 -0
  21. package/dist/core/always-applied-skills.js.map +1 -0
  22. package/dist/core/system-prompt.d.ts.map +1 -1
  23. package/dist/core/system-prompt.js +9 -0
  24. package/dist/core/system-prompt.js.map +1 -1
  25. package/dist/skills/final-response-summary/SKILL.md +39 -0
  26. package/dist/skills/request-report/SKILL.md +46 -0
  27. package/dist/skills/request-report/pyproject.toml +16 -0
  28. package/dist/skills/request-report/src/request_report/__init__.py +160 -0
  29. package/dist/skills/skill-creator/SKILL.md +2 -1
  30. package/dist/skills/solid-source-modularity/SKILL.md +48 -0
  31. package/dist/skills/solid-source-modularity/pyproject.toml +16 -0
  32. package/dist/skills/solid-source-modularity/src/solid_source_modularity/__init__.py +154 -0
  33. package/docs/skills.md +8 -3
  34. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  35. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  36. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  37. package/examples/extensions/sandbox/package-lock.json +2 -2
  38. package/examples/extensions/sandbox/package.json +1 -1
  39. package/examples/extensions/with-deps/package-lock.json +2 -2
  40. package/examples/extensions/with-deps/package.json +1 -1
  41. package/package.json +5 -5
  42. package/skills/final-response-summary/SKILL.md +39 -0
  43. package/skills/request-report/SKILL.md +46 -0
  44. package/skills/request-report/pyproject.toml +16 -0
  45. package/skills/request-report/src/request_report/__init__.py +160 -0
  46. package/skills/skill-creator/SKILL.md +2 -1
  47. package/skills/solid-source-modularity/SKILL.md +48 -0
  48. package/skills/solid-source-modularity/pyproject.toml +16 -0
  49. package/skills/solid-source-modularity/src/solid_source_modularity/__init__.py +154 -0
@@ -7,7 +7,7 @@ import {
7
7
  isOwnedSessionWorkerProcess,
8
8
  maybeRunOwnedSessionWorkerFrontend,
9
9
  maybeStartDaemonEarly
10
- } from "./chunk-O7SB7LML.js";
10
+ } from "./chunk-EFDSSG52.js";
11
11
  import "./chunk-5QCJ5DQU.js";
12
12
  import "./chunk-J6ATXG62.js";
13
13
  import "./chunk-2T7M7VJ4.js";
@@ -15,7 +15,7 @@ import "./chunk-UIRUOAIQ.js";
15
15
  import "./chunk-HXOBFFJX.js";
16
16
  import "./chunk-6GUVYK6P.js";
17
17
  import "./chunk-UPDAFKL5.js";
18
- import "./chunk-7HN2VZJJ.js";
18
+ import "./chunk-7QIBGY2R.js";
19
19
  import "./chunk-BAWSWWEU.js";
20
20
 
21
21
  // dist/cli-main.js
@@ -182,7 +182,7 @@ async function runCli() {
182
182
  }
183
183
  const [{ EnvHttpProxyAgent, setGlobalDispatcher }, { main }] = await Promise.all([
184
184
  import("undici"),
185
- import("./main-DOLQ46ZM.js")
185
+ import("./main-4QYKME2K.js")
186
186
  ]);
187
187
  setGlobalDispatcher(new EnvHttpProxyAgent({ bodyTimeout: 0, headersTimeout: 0 }));
188
188
  try {
@@ -49,6 +49,6 @@ var supported = assertNodeVersion({
49
49
  exit: (code) => process.exit(code)
50
50
  });
51
51
  if (supported) {
52
- const { runCli } = await import("./cli-main-YXP4FEPB.js");
52
+ const { runCli } = await import("./cli-main-O3HK7MNQ.js");
53
53
  await runCli();
54
54
  }
@@ -25,7 +25,7 @@ import {
25
25
  AssistantMessageEventStream,
26
26
  calculateCost,
27
27
  clampThinkingLevel
28
- } from "./chunk-7HN2VZJJ.js";
28
+ } from "./chunk-7QIBGY2R.js";
29
29
  import "./chunk-BAWSWWEU.js";
30
30
 
31
31
  // ../ai/src/providers/google.ts
@@ -24,7 +24,7 @@ import {
24
24
  AssistantMessageEventStream,
25
25
  calculateCost,
26
26
  clampThinkingLevel
27
- } from "./chunk-7HN2VZJJ.js";
27
+ } from "./chunk-7QIBGY2R.js";
28
28
  import "./chunk-BAWSWWEU.js";
29
29
 
30
30
  // ../ai/src/providers/google-vertex.ts
@@ -17,8 +17,8 @@ import {
17
17
  shouldUseDaemonClientRuntime,
18
18
  shouldUseDaemonInteractive,
19
19
  shouldUseEphemeralSessionManagerForDaemonInteractive
20
- } from "./chunk-4KQVBOJB.js";
21
- import "./chunk-O7SB7LML.js";
20
+ } from "./chunk-YYVQTKC6.js";
21
+ import "./chunk-EFDSSG52.js";
22
22
  import "./chunk-VWR3YFK5.js";
23
23
  import "./chunk-N2CSAETN.js";
24
24
  import "./chunk-5QCJ5DQU.js";
@@ -28,7 +28,7 @@ import "./chunk-UIRUOAIQ.js";
28
28
  import "./chunk-HXOBFFJX.js";
29
29
  import "./chunk-6GUVYK6P.js";
30
30
  import "./chunk-UPDAFKL5.js";
31
- import "./chunk-7HN2VZJJ.js";
31
+ import "./chunk-7QIBGY2R.js";
32
32
  import "./chunk-BAWSWWEU.js";
33
33
  export {
34
34
  createSessionManager,
@@ -84,7 +84,7 @@ import {
84
84
  AssistantMessageEventStream,
85
85
  calculateCost,
86
86
  clampThinkingLevel
87
- } from "./chunk-7HN2VZJJ.js";
87
+ } from "./chunk-7QIBGY2R.js";
88
88
  import "./chunk-BAWSWWEU.js";
89
89
 
90
90
  // ../../node_modules/@mistralai/mistralai/esm/lib/url.js
@@ -6,7 +6,7 @@ import {
6
6
  convertResponsesMessages,
7
7
  convertResponsesTools,
8
8
  processResponsesStream
9
- } from "./chunk-FCQTXDPX.js";
9
+ } from "./chunk-IYXHHLR6.js";
10
10
  import "./chunk-NQB5DCFC.js";
11
11
  import {
12
12
  headersToRecord
@@ -26,7 +26,7 @@ import {
26
26
  import {
27
27
  AssistantMessageEventStream,
28
28
  clampThinkingLevel
29
- } from "./chunk-7HN2VZJJ.js";
29
+ } from "./chunk-7QIBGY2R.js";
30
30
  import "./chunk-BAWSWWEU.js";
31
31
 
32
32
  // ../ai/src/providers/openai-codex-responses.ts
@@ -31,7 +31,7 @@ import {
31
31
  AssistantMessageEventStream,
32
32
  calculateCost,
33
33
  clampThinkingLevel
34
- } from "./chunk-7HN2VZJJ.js";
34
+ } from "./chunk-7QIBGY2R.js";
35
35
  import "./chunk-BAWSWWEU.js";
36
36
 
37
37
  // ../ai/src/providers/openai-completions.ts
@@ -9,7 +9,7 @@ import {
9
9
  convertResponsesMessages,
10
10
  convertResponsesTools,
11
11
  processResponsesStream
12
- } from "./chunk-FCQTXDPX.js";
12
+ } from "./chunk-IYXHHLR6.js";
13
13
  import "./chunk-NQB5DCFC.js";
14
14
  import {
15
15
  OpenAI
@@ -32,7 +32,7 @@ import {
32
32
  import {
33
33
  AssistantMessageEventStream,
34
34
  clampThinkingLevel
35
- } from "./chunk-7HN2VZJJ.js";
35
+ } from "./chunk-7QIBGY2R.js";
36
36
  import "./chunk-BAWSWWEU.js";
37
37
 
38
38
  // ../ai/src/providers/openai-responses.ts
@@ -0,0 +1,3 @@
1
+ import type { Skill } from "./skills.js";
2
+ export declare function formatAlwaysAppliedSkills(skills: readonly Skill[]): string;
3
+ //# sourceMappingURL=always-applied-skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"always-applied-skills.d.ts","sourceRoot":"","sources":["../../src/core/always-applied-skills.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAyBzC,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,MAAM,CAqB1E","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { parseFrontmatter } from \"../utils/frontmatter.js\";\nimport type { Skill } from \"./skills.js\";\n\ninterface AlwaysAppliedFrontmatter {\n\t\"always-apply\"?: boolean;\n\t[key: string]: unknown;\n}\n\ninterface AlwaysAppliedSkill {\n\tname: string;\n\tfilePath: string;\n\tinstructions: string;\n}\n\nfunction loadAlwaysAppliedSkill(skill: Skill): AlwaysAppliedSkill | undefined {\n\tif (skill.disableModelInvocation) return undefined;\n\ttry {\n\t\tconst content = readFileSync(skill.filePath, \"utf-8\");\n\t\tconst { frontmatter, body } = parseFrontmatter<AlwaysAppliedFrontmatter>(content);\n\t\tif (frontmatter[\"always-apply\"] !== true || body.length === 0) return undefined;\n\t\treturn { name: skill.name, filePath: skill.filePath, instructions: body };\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function formatAlwaysAppliedSkills(skills: readonly Skill[]): string {\n\tconst requiredSkills = skills\n\t\t.map((skill) => loadAlwaysAppliedSkill(skill))\n\t\t.filter((skill): skill is AlwaysAppliedSkill => skill !== undefined);\n\tif (requiredSkills.length === 0) return \"\";\n\n\tconst lines = [\n\t\t\"The following always-applied skills are mandatory.\",\n\t\t\"Follow their full instructions without waiting for an explicit skill invocation.\",\n\t\t\"\",\n\t\t\"<always_applied_skills>\",\n\t];\n\tfor (const skill of requiredSkills) {\n\t\tlines.push(\" <skill>\");\n\t\tlines.push(` <name>${escapeXml(skill.name)}</name>`);\n\t\tlines.push(` <location>${escapeXml(skill.filePath)}</location>`);\n\t\tlines.push(` <instructions>${escapeXml(skill.instructions)}</instructions>`);\n\t\tlines.push(\" </skill>\");\n\t}\n\tlines.push(\"</always_applied_skills>\");\n\treturn lines.join(\"\\n\");\n}\n\nfunction escapeXml(value: string): string {\n\treturn value\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"]}
@@ -0,0 +1,47 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { parseFrontmatter } from "../utils/frontmatter.js";
3
+ function loadAlwaysAppliedSkill(skill) {
4
+ if (skill.disableModelInvocation)
5
+ return undefined;
6
+ try {
7
+ const content = readFileSync(skill.filePath, "utf-8");
8
+ const { frontmatter, body } = parseFrontmatter(content);
9
+ if (frontmatter["always-apply"] !== true || body.length === 0)
10
+ return undefined;
11
+ return { name: skill.name, filePath: skill.filePath, instructions: body };
12
+ }
13
+ catch {
14
+ return undefined;
15
+ }
16
+ }
17
+ export function formatAlwaysAppliedSkills(skills) {
18
+ const requiredSkills = skills
19
+ .map((skill) => loadAlwaysAppliedSkill(skill))
20
+ .filter((skill) => skill !== undefined);
21
+ if (requiredSkills.length === 0)
22
+ return "";
23
+ const lines = [
24
+ "The following always-applied skills are mandatory.",
25
+ "Follow their full instructions without waiting for an explicit skill invocation.",
26
+ "",
27
+ "<always_applied_skills>",
28
+ ];
29
+ for (const skill of requiredSkills) {
30
+ lines.push(" <skill>");
31
+ lines.push(` <name>${escapeXml(skill.name)}</name>`);
32
+ lines.push(` <location>${escapeXml(skill.filePath)}</location>`);
33
+ lines.push(` <instructions>${escapeXml(skill.instructions)}</instructions>`);
34
+ lines.push(" </skill>");
35
+ }
36
+ lines.push("</always_applied_skills>");
37
+ return lines.join("\n");
38
+ }
39
+ function escapeXml(value) {
40
+ return value
41
+ .replace(/&/g, "&amp;")
42
+ .replace(/</g, "&lt;")
43
+ .replace(/>/g, "&gt;")
44
+ .replace(/"/g, "&quot;")
45
+ .replace(/'/g, "&apos;");
46
+ }
47
+ //# sourceMappingURL=always-applied-skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"always-applied-skills.js","sourceRoot":"","sources":["../../src/core/always-applied-skills.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAc3D,SAAS,sBAAsB,CAAC,KAAY,EAAkC;IAC7E,IAAI,KAAK,CAAC,sBAAsB;QAAE,OAAO,SAAS,CAAC;IACnD,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAA2B,OAAO,CAAC,CAAC;QAClF,IAAI,WAAW,CAAC,cAAc,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QAChF,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AAAA,CACD;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAwB,EAAU;IAC3E,MAAM,cAAc,GAAG,MAAM;SAC3B,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;SAC7C,MAAM,CAAC,CAAC,KAAK,EAA+B,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IACtE,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE3C,MAAM,KAAK,GAAG;QACb,oDAAoD;QACpD,kFAAkF;QAClF,EAAE;QACF,yBAAyB;KACzB,CAAC;IACF,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,aAAa,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,iBAAiB,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACpE,KAAK,CAAC,IAAI,CAAC,qBAAqB,SAAS,CAAC,KAAK,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC;QAChF,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IACvC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CACxB;AAED,SAAS,SAAS,CAAC,KAAa,EAAU;IACzC,OAAO,KAAK;SACV,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAAA,CAC1B","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { parseFrontmatter } from \"../utils/frontmatter.js\";\nimport type { Skill } from \"./skills.js\";\n\ninterface AlwaysAppliedFrontmatter {\n\t\"always-apply\"?: boolean;\n\t[key: string]: unknown;\n}\n\ninterface AlwaysAppliedSkill {\n\tname: string;\n\tfilePath: string;\n\tinstructions: string;\n}\n\nfunction loadAlwaysAppliedSkill(skill: Skill): AlwaysAppliedSkill | undefined {\n\tif (skill.disableModelInvocation) return undefined;\n\ttry {\n\t\tconst content = readFileSync(skill.filePath, \"utf-8\");\n\t\tconst { frontmatter, body } = parseFrontmatter<AlwaysAppliedFrontmatter>(content);\n\t\tif (frontmatter[\"always-apply\"] !== true || body.length === 0) return undefined;\n\t\treturn { name: skill.name, filePath: skill.filePath, instructions: body };\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function formatAlwaysAppliedSkills(skills: readonly Skill[]): string {\n\tconst requiredSkills = skills\n\t\t.map((skill) => loadAlwaysAppliedSkill(skill))\n\t\t.filter((skill): skill is AlwaysAppliedSkill => skill !== undefined);\n\tif (requiredSkills.length === 0) return \"\";\n\n\tconst lines = [\n\t\t\"The following always-applied skills are mandatory.\",\n\t\t\"Follow their full instructions without waiting for an explicit skill invocation.\",\n\t\t\"\",\n\t\t\"<always_applied_skills>\",\n\t];\n\tfor (const skill of requiredSkills) {\n\t\tlines.push(\" <skill>\");\n\t\tlines.push(` <name>${escapeXml(skill.name)}</name>`);\n\t\tlines.push(` <location>${escapeXml(skill.filePath)}</location>`);\n\t\tlines.push(` <instructions>${escapeXml(skill.instructions)}</instructions>`);\n\t\tlines.push(\" </skill>\");\n\t}\n\tlines.push(\"</always_applied_skills>\");\n\treturn lines.join(\"\\n\");\n}\n\nfunction escapeXml(value: string): string {\n\treturn value\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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAA+B,KAAK,YAAY,EAAqB,MAAM,uBAAuB,CAAC;AAC1G,OAAO,EAAoD,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAE3F,MAAM,WAAW,wBAAwB;IACxC,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,wFAAwF;IACxF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,uCAAuC;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gCAAgC;IAChC,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,yBAAyB;IACzB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,kEAAkE;IAClE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,oFAAoF;IACpF,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CA2I3E","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { buildChildAgentDoctrine, buildRlmPrompt, buildSubagentGuidance } from \"./prompts/index.js\";\nimport { formatHarnessStateForPrompt, type HarnessState, REFINE_SKILL_NAME } from \"./refinement/index.js\";\nimport { formatSkillsForPrompt, getPythonSkillRuntimeInfo, type Skill } from \"./skills.js\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Active tools. Tool schemas carry tool descriptions outside the prompt body. */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. Used only for custom prompts. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the system prompt. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Conversation log path. */\n\tmessagesPath?: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n\t/** Whether to include the model-facing rlm recursion guidance. */\n\tallowRecursion?: boolean;\n\t/** Fixed recursive-agent depth for this session. */\n\trlmDepth?: number;\n\t/** Human-readable parent name or id for child communication doctrine. */\n\trlmParentAgent?: string;\n\t/** Global harness state to inject as compact persistent context. */\n\tharnessState?: HarnessState;\n\t/** Enabled user-configured servers available through the generic kernel MCP API. */\n\tgenericMcpServers?: string[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tmessagesPath,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t\tallowRecursion,\n\t\tharnessState,\n\t} = options;\n\tconst promptCwd = cwd.replace(/\\\\/g, \"/\");\n\tconst promptMessagesPath = (messagesPath ?? \"not persisted\").replace(/\\\\/g, \"/\");\n\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\tconst date = `${year}-${month}-${day}`;\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\tconst tools = selectedTools ?? [\"ipython\"];\n\tconst hasIpython = tools.includes(\"ipython\");\n\tconst hasBash = tools.includes(\"bash\");\n\tconst visibleSkills = skills.filter((skill) => !skill.disableModelInvocation);\n\tconst visiblePythonSkillImportNames = getPythonSkillRuntimeInfo(visibleSkills).map((skill) => skill.importName);\n\tconst hasRefineSkill = visibleSkills.some((skill) => skill.name === REFINE_SKILL_NAME);\n\tconst genericMcpSection = hasIpython ? formatGenericMcpGuidance(options.genericMcpServers) : \"\";\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Append skills section only when the model has a way to inspect skill files.\n\t\tconst customPromptHasFileAccess =\n\t\t\t!selectedTools || selectedTools.includes(\"ipython\") || selectedTools.includes(\"bash\");\n\t\tif (customPromptHasFileAccess && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\n\t\t// Add date and working directory last\n\t\tprompt += `\\nCurrent date: ${date}`;\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\tconst childDoctrine = buildChildAgentDoctrine({\n\t\t\tdepth: options.rlmDepth,\n\t\t\tparentAgent: options.rlmParentAgent,\n\t\t\tinstalledSkills: visiblePythonSkillImportNames,\n\t\t\tactiveTools: tools,\n\t\t});\n\t\tif (childDoctrine) {\n\t\t\tprompt += `\\n\\n${childDoctrine}`;\n\t\t}\n\n\t\tif (harnessState) {\n\t\t\tprompt += `\\n\\n${formatHarnessStateForPrompt(harnessState, { includeIpythonExamples: hasIpython, includeShellExamples: hasBash, includeRefineExamples: hasIpython && hasRefineSkill })}`;\n\t\t}\n\n\t\tif (genericMcpSection) {\n\t\t\tprompt += `\\n\\n${genericMcpSection}`;\n\t\t}\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\treturn prompt;\n\t}\n\n\tlet prompt = buildRlmPrompt({\n\t\tcwd: promptCwd,\n\t\tmessagesPath: promptMessagesPath,\n\t\tinstalledSkills: visiblePythonSkillImportNames,\n\t\tactiveTools: tools.filter((name) => name === \"ipython\" || name === \"bash\" || name === \"edit\"),\n\t\tallowRecursion,\n\t\tdepth: options.rlmDepth,\n\t\tparentAgent: options.rlmParentAgent,\n\t});\n\n\t// Appended AFTER the trained buildRlmPrompt prefix, and before the harness-state\n\t// menu, so the model reads when/why to delegate and then sees the concrete subagent\n\t// specs it can match against — the same ordering as Claude Code's Agent tool.\n\tif ((allowRecursion ?? true) && hasIpython) {\n\t\tconst visiblePythonSkillNames = new Set(\n\t\t\tgetPythonSkillRuntimeInfo(visibleSkills).map((skill) => skill.importName),\n\t\t);\n\t\tprompt += `\\n\\n${buildSubagentGuidance({\n\t\t\tincludeRefineExamples: hasRefineSkill,\n\t\t\thasAgentMessage: visiblePythonSkillNames.has(\"agent_message\"),\n\t\t\thasAgentObserve: visiblePythonSkillNames.has(\"agent_observe\"),\n\t\t})}`;\n\t}\n\n\tif (harnessState) {\n\t\tprompt += `\\n\\n${formatHarnessStateForPrompt(harnessState, { includeIpythonExamples: hasIpython, includeShellExamples: hasBash, includeRefineExamples: hasIpython && hasRefineSkill })}`;\n\t}\n\n\tif (genericMcpSection) {\n\t\tprompt += `\\n\\n${genericMcpSection}`;\n\t}\n\n\tconst guidelines = formatPromptGuidelines(promptGuidelines);\n\tif (guidelines) {\n\t\tprompt += `\\n\\n# Additional Guidance\\n\\n${guidelines}`;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Append skills section only when the model has a way to inspect skill files.\n\tconst hasFileAccess = tools.includes(\"ipython\") || tools.includes(\"bash\");\n\tif (hasFileAccess && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\treturn prompt;\n}\n\nfunction formatGenericMcpGuidance(servers: string[] | undefined): string {\n\tconst enabledServers = [...new Set(servers ?? [])].sort((left, right) => left.localeCompare(right));\n\tif (enabledServers.length === 0) return \"\";\n\n\treturn [\n\t\t\"# Generic MCP Connections\",\n\t\t\"\",\n\t\t\"Generic MCP connections are accessed through the pre-imported Python `mcp` object in the Python REPL, not as top-level native tool namespaces or installed Python skills.\",\n\t\t`Enabled generic MCP servers: ${enabledServers.map((server) => `\\`${server}\\``).join(\", \")}.`,\n\t\t...enabledServers.map(\n\t\t\t(server) =>\n\t\t\t\t`For \\`${server}\\`, first discover its tools with \\`await mcp.list_tools(\"${server}\")\\`, then call one with \\`await mcp.call_tool(\"${server}\", \"<tool>\", arguments)\\`.`,\n\t\t),\n\t].join(\"\\n\");\n}\n\nfunction formatPromptGuidelines(promptGuidelines: string[] | undefined): string {\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0 && !guidelinesSet.has(normalized)) {\n\t\t\tguidelinesSet.add(normalized);\n\t\t\tguidelinesList.push(normalized);\n\t\t}\n\t}\n\n\treturn guidelinesList.map((guideline) => `- ${guideline}`).join(\"\\n\");\n}\n"]}
1
+ {"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAA+B,KAAK,YAAY,EAAqB,MAAM,uBAAuB,CAAC;AAC1G,OAAO,EAAoD,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAE3F,MAAM,WAAW,wBAAwB;IACxC,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,wFAAwF;IACxF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,uCAAuC;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gCAAgC;IAChC,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,yBAAyB;IACzB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,kEAAkE;IAClE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,oFAAoF;IACpF,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CAmJ3E","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { formatAlwaysAppliedSkills } from \"./always-applied-skills.js\";\nimport { buildChildAgentDoctrine, buildRlmPrompt, buildSubagentGuidance } from \"./prompts/index.js\";\nimport { formatHarnessStateForPrompt, type HarnessState, REFINE_SKILL_NAME } from \"./refinement/index.js\";\nimport { formatSkillsForPrompt, getPythonSkillRuntimeInfo, type Skill } from \"./skills.js\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Active tools. Tool schemas carry tool descriptions outside the prompt body. */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. Used only for custom prompts. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the system prompt. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Conversation log path. */\n\tmessagesPath?: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n\t/** Whether to include the model-facing rlm recursion guidance. */\n\tallowRecursion?: boolean;\n\t/** Fixed recursive-agent depth for this session. */\n\trlmDepth?: number;\n\t/** Human-readable parent name or id for child communication doctrine. */\n\trlmParentAgent?: string;\n\t/** Global harness state to inject as compact persistent context. */\n\tharnessState?: HarnessState;\n\t/** Enabled user-configured servers available through the generic kernel MCP API. */\n\tgenericMcpServers?: string[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tmessagesPath,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t\tallowRecursion,\n\t\tharnessState,\n\t} = options;\n\tconst promptCwd = cwd.replace(/\\\\/g, \"/\");\n\tconst promptMessagesPath = (messagesPath ?? \"not persisted\").replace(/\\\\/g, \"/\");\n\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\tconst date = `${year}-${month}-${day}`;\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\tconst tools = selectedTools ?? [\"ipython\"];\n\tconst hasIpython = tools.includes(\"ipython\");\n\tconst hasBash = tools.includes(\"bash\");\n\tconst visibleSkills = skills.filter((skill) => !skill.disableModelInvocation);\n\tconst visiblePythonSkillImportNames = getPythonSkillRuntimeInfo(visibleSkills).map((skill) => skill.importName);\n\tconst hasRefineSkill = visibleSkills.some((skill) => skill.name === REFINE_SKILL_NAME);\n\tconst genericMcpSection = hasIpython ? formatGenericMcpGuidance(options.genericMcpServers) : \"\";\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Append skills section only when the model has a way to inspect skill files.\n\t\tconst customPromptHasFileAccess =\n\t\t\t!selectedTools || selectedTools.includes(\"ipython\") || selectedTools.includes(\"bash\");\n\t\tif (customPromptHasFileAccess && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\t\tconst alwaysAppliedSkills = formatAlwaysAppliedSkills(skills);\n\t\tif (alwaysAppliedSkills) {\n\t\t\tprompt += `\\n\\n${alwaysAppliedSkills}`;\n\t\t}\n\n\t\t// Add date and working directory last\n\t\tprompt += `\\nCurrent date: ${date}`;\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\tconst childDoctrine = buildChildAgentDoctrine({\n\t\t\tdepth: options.rlmDepth,\n\t\t\tparentAgent: options.rlmParentAgent,\n\t\t\tinstalledSkills: visiblePythonSkillImportNames,\n\t\t\tactiveTools: tools,\n\t\t});\n\t\tif (childDoctrine) {\n\t\t\tprompt += `\\n\\n${childDoctrine}`;\n\t\t}\n\n\t\tif (harnessState) {\n\t\t\tprompt += `\\n\\n${formatHarnessStateForPrompt(harnessState, { includeIpythonExamples: hasIpython, includeShellExamples: hasBash, includeRefineExamples: hasIpython && hasRefineSkill })}`;\n\t\t}\n\n\t\tif (genericMcpSection) {\n\t\t\tprompt += `\\n\\n${genericMcpSection}`;\n\t\t}\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\treturn prompt;\n\t}\n\n\tlet prompt = buildRlmPrompt({\n\t\tcwd: promptCwd,\n\t\tmessagesPath: promptMessagesPath,\n\t\tinstalledSkills: visiblePythonSkillImportNames,\n\t\tactiveTools: tools.filter((name) => name === \"ipython\" || name === \"bash\" || name === \"edit\"),\n\t\tallowRecursion,\n\t\tdepth: options.rlmDepth,\n\t\tparentAgent: options.rlmParentAgent,\n\t});\n\n\t// Appended AFTER the trained buildRlmPrompt prefix, and before the harness-state\n\t// menu, so the model reads when/why to delegate and then sees the concrete subagent\n\t// specs it can match against — the same ordering as Claude Code's Agent tool.\n\tif ((allowRecursion ?? true) && hasIpython) {\n\t\tconst visiblePythonSkillNames = new Set(\n\t\t\tgetPythonSkillRuntimeInfo(visibleSkills).map((skill) => skill.importName),\n\t\t);\n\t\tprompt += `\\n\\n${buildSubagentGuidance({\n\t\t\tincludeRefineExamples: hasRefineSkill,\n\t\t\thasAgentMessage: visiblePythonSkillNames.has(\"agent_message\"),\n\t\t\thasAgentObserve: visiblePythonSkillNames.has(\"agent_observe\"),\n\t\t})}`;\n\t}\n\n\tif (harnessState) {\n\t\tprompt += `\\n\\n${formatHarnessStateForPrompt(harnessState, { includeIpythonExamples: hasIpython, includeShellExamples: hasBash, includeRefineExamples: hasIpython && hasRefineSkill })}`;\n\t}\n\n\tif (genericMcpSection) {\n\t\tprompt += `\\n\\n${genericMcpSection}`;\n\t}\n\n\tconst guidelines = formatPromptGuidelines(promptGuidelines);\n\tif (guidelines) {\n\t\tprompt += `\\n\\n# Additional Guidance\\n\\n${guidelines}`;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Append skills section only when the model has a way to inspect skill files.\n\tconst hasFileAccess = tools.includes(\"ipython\") || tools.includes(\"bash\");\n\tif (hasFileAccess && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\tconst alwaysAppliedSkills = formatAlwaysAppliedSkills(skills);\n\tif (alwaysAppliedSkills) {\n\t\tprompt += `\\n\\n${alwaysAppliedSkills}`;\n\t}\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\treturn prompt;\n}\n\nfunction formatGenericMcpGuidance(servers: string[] | undefined): string {\n\tconst enabledServers = [...new Set(servers ?? [])].sort((left, right) => left.localeCompare(right));\n\tif (enabledServers.length === 0) return \"\";\n\n\treturn [\n\t\t\"# Generic MCP Connections\",\n\t\t\"\",\n\t\t\"Generic MCP connections are accessed through the pre-imported Python `mcp` object in the Python REPL, not as top-level native tool namespaces or installed Python skills.\",\n\t\t`Enabled generic MCP servers: ${enabledServers.map((server) => `\\`${server}\\``).join(\", \")}.`,\n\t\t...enabledServers.map(\n\t\t\t(server) =>\n\t\t\t\t`For \\`${server}\\`, first discover its tools with \\`await mcp.list_tools(\"${server}\")\\`, then call one with \\`await mcp.call_tool(\"${server}\", \"<tool>\", arguments)\\`.`,\n\t\t),\n\t].join(\"\\n\");\n}\n\nfunction formatPromptGuidelines(promptGuidelines: string[] | undefined): string {\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0 && !guidelinesSet.has(normalized)) {\n\t\t\tguidelinesSet.add(normalized);\n\t\t\tguidelinesList.push(normalized);\n\t\t}\n\t}\n\n\treturn guidelinesList.map((guideline) => `- ${guideline}`).join(\"\\n\");\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * System prompt construction and project context loading
3
3
  */
4
+ import { formatAlwaysAppliedSkills } from "./always-applied-skills.js";
4
5
  import { buildChildAgentDoctrine, buildRlmPrompt, buildSubagentGuidance } from "./prompts/index.js";
5
6
  import { formatHarnessStateForPrompt, REFINE_SKILL_NAME } from "./refinement/index.js";
6
7
  import { formatSkillsForPrompt, getPythonSkillRuntimeInfo } from "./skills.js";
@@ -39,6 +40,10 @@ export function buildSystemPrompt(options) {
39
40
  if (customPromptHasFileAccess && skills.length > 0) {
40
41
  prompt += formatSkillsForPrompt(skills);
41
42
  }
43
+ const alwaysAppliedSkills = formatAlwaysAppliedSkills(skills);
44
+ if (alwaysAppliedSkills) {
45
+ prompt += `\n\n${alwaysAppliedSkills}`;
46
+ }
42
47
  // Add date and working directory last
43
48
  prompt += `\nCurrent date: ${date}`;
44
49
  prompt += `\nCurrent working directory: ${promptCwd}`;
@@ -105,6 +110,10 @@ export function buildSystemPrompt(options) {
105
110
  if (hasFileAccess && skills.length > 0) {
106
111
  prompt += formatSkillsForPrompt(skills);
107
112
  }
113
+ const alwaysAppliedSkills = formatAlwaysAppliedSkills(skills);
114
+ if (alwaysAppliedSkills) {
115
+ prompt += `\n\n${alwaysAppliedSkills}`;
116
+ }
108
117
  if (appendSection) {
109
118
  prompt += appendSection;
110
119
  }
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AACpG,OAAO,EAAE,2BAA2B,EAAqB,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1G,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAc,MAAM,aAAa,CAAC;AAiC3F,kEAAkE;AAClE,MAAM,UAAU,iBAAiB,CAAC,OAAiC,EAAU;IAC5E,MAAM,EACL,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,GAAG,EACH,YAAY,EACZ,YAAY,EAAE,oBAAoB,EAClC,MAAM,EAAE,cAAc,EACtB,cAAc,EACd,YAAY,GACZ,GAAG,OAAO,CAAC;IACZ,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC1C,MAAM,kBAAkB,GAAG,CAAC,YAAY,IAAI,eAAe,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEjF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;IAEvC,MAAM,aAAa,GAAG,kBAAkB,CAAC,CAAC,CAAC,OAAO,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAE5E,MAAM,YAAY,GAAG,oBAAoB,IAAI,EAAE,CAAC;IAChD,MAAM,MAAM,GAAG,cAAc,IAAI,EAAE,CAAC;IACpC,MAAM,KAAK,GAAG,aAAa,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC9E,MAAM,6BAA6B,GAAG,yBAAyB,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAChH,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC;IACvF,MAAM,iBAAiB,GAAG,UAAU,CAAC,CAAC,CAAC,wBAAwB,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEhG,IAAI,YAAY,EAAE,CAAC;QAClB,IAAI,MAAM,GAAG,YAAY,CAAC;QAE1B,+BAA+B;QAC/B,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,2BAA2B,CAAC;YACtC,MAAM,IAAI,mDAAmD,CAAC;YAC9D,KAAK,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,YAAY,EAAE,CAAC;gBACxD,MAAM,IAAI,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC;YAC9C,CAAC;QACF,CAAC;QAED,8EAA8E;QAC9E,MAAM,yBAAyB,GAC9B,CAAC,aAAa,IAAI,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACvF,IAAI,yBAAyB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;QAED,sCAAsC;QACtC,MAAM,IAAI,mBAAmB,IAAI,EAAE,CAAC;QACpC,MAAM,IAAI,gCAAgC,SAAS,EAAE,CAAC;QAEtD,MAAM,aAAa,GAAG,uBAAuB,CAAC;YAC7C,KAAK,EAAE,OAAO,CAAC,QAAQ;YACvB,WAAW,EAAE,OAAO,CAAC,cAAc;YACnC,eAAe,EAAE,6BAA6B;YAC9C,WAAW,EAAE,KAAK;SAClB,CAAC,CAAC;QACH,IAAI,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,OAAO,aAAa,EAAE,CAAC;QAClC,CAAC;QAED,IAAI,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,OAAO,2BAA2B,CAAC,YAAY,EAAE,EAAE,sBAAsB,EAAE,UAAU,EAAE,oBAAoB,EAAE,OAAO,EAAE,qBAAqB,EAAE,UAAU,IAAI,cAAc,EAAE,CAAC,EAAE,CAAC;QAC1L,CAAC;QAED,IAAI,iBAAiB,EAAE,CAAC;YACvB,MAAM,IAAI,OAAO,iBAAiB,EAAE,CAAC;QACtC,CAAC;QAED,IAAI,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,aAAa,CAAC;QACzB,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;IAED,IAAI,MAAM,GAAG,cAAc,CAAC;QAC3B,GAAG,EAAE,SAAS;QACd,YAAY,EAAE,kBAAkB;QAChC,eAAe,EAAE,6BAA6B;QAC9C,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,CAAC;QAC7F,cAAc;QACd,KAAK,EAAE,OAAO,CAAC,QAAQ;QACvB,WAAW,EAAE,OAAO,CAAC,cAAc;KACnC,CAAC,CAAC;IAEH,iFAAiF;IACjF,oFAAoF;IACpF,gFAA8E;IAC9E,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC;QAC5C,MAAM,uBAAuB,GAAG,IAAI,GAAG,CACtC,yBAAyB,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CACzE,CAAC;QACF,MAAM,IAAI,OAAO,qBAAqB,CAAC;YACtC,qBAAqB,EAAE,cAAc;YACrC,eAAe,EAAE,uBAAuB,CAAC,GAAG,CAAC,eAAe,CAAC;YAC7D,eAAe,EAAE,uBAAuB,CAAC,GAAG,CAAC,eAAe,CAAC;SAC7D,CAAC,EAAE,CAAC;IACN,CAAC;IAED,IAAI,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,OAAO,2BAA2B,CAAC,YAAY,EAAE,EAAE,sBAAsB,EAAE,UAAU,EAAE,oBAAoB,EAAE,OAAO,EAAE,qBAAqB,EAAE,UAAU,IAAI,cAAc,EAAE,CAAC,EAAE,CAAC;IAC1L,CAAC;IAED,IAAI,iBAAiB,EAAE,CAAC;QACvB,MAAM,IAAI,OAAO,iBAAiB,EAAE,CAAC;IACtC,CAAC;IAED,MAAM,UAAU,GAAG,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;IAC5D,IAAI,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,gCAAgC,UAAU,EAAE,CAAC;IACxD,CAAC;IAED,+BAA+B;IAC/B,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,2BAA2B,CAAC;QACtC,MAAM,IAAI,mDAAmD,CAAC;QAC9D,KAAK,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,YAAY,EAAE,CAAC;YACxD,MAAM,IAAI,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC;QAC9C,CAAC;IACF,CAAC;IAED,8EAA8E;IAC9E,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1E,IAAI,aAAa,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,aAAa,CAAC;IACzB,CAAC;IAED,OAAO,MAAM,CAAC;AAAA,CACd;AAED,SAAS,wBAAwB,CAAC,OAA6B,EAAU;IACxE,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IACpG,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE3C,OAAO;QACN,2BAA2B;QAC3B,EAAE;QACF,2KAA2K;QAC3K,gCAAgC,cAAc,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QAC7F,GAAG,cAAc,CAAC,GAAG,CACpB,CAAC,MAAM,EAAE,EAAE,CACV,SAAS,MAAM,6DAA6D,MAAM,mDAAmD,MAAM,4BAA4B,CACxK;KACD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CACb;AAED,SAAS,sBAAsB,CAAC,gBAAsC,EAAU;IAC/E,MAAM,cAAc,GAAa,EAAE,CAAC;IACpC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IAExC,KAAK,MAAM,SAAS,IAAI,gBAAgB,IAAI,EAAE,EAAE,CAAC;QAChD,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7D,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC9B,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACjC,CAAC;IACF,CAAC;IAED,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,KAAK,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CACtE","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { buildChildAgentDoctrine, buildRlmPrompt, buildSubagentGuidance } from \"./prompts/index.js\";\nimport { formatHarnessStateForPrompt, type HarnessState, REFINE_SKILL_NAME } from \"./refinement/index.js\";\nimport { formatSkillsForPrompt, getPythonSkillRuntimeInfo, type Skill } from \"./skills.js\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Active tools. Tool schemas carry tool descriptions outside the prompt body. */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. Used only for custom prompts. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the system prompt. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Conversation log path. */\n\tmessagesPath?: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n\t/** Whether to include the model-facing rlm recursion guidance. */\n\tallowRecursion?: boolean;\n\t/** Fixed recursive-agent depth for this session. */\n\trlmDepth?: number;\n\t/** Human-readable parent name or id for child communication doctrine. */\n\trlmParentAgent?: string;\n\t/** Global harness state to inject as compact persistent context. */\n\tharnessState?: HarnessState;\n\t/** Enabled user-configured servers available through the generic kernel MCP API. */\n\tgenericMcpServers?: string[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tmessagesPath,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t\tallowRecursion,\n\t\tharnessState,\n\t} = options;\n\tconst promptCwd = cwd.replace(/\\\\/g, \"/\");\n\tconst promptMessagesPath = (messagesPath ?? \"not persisted\").replace(/\\\\/g, \"/\");\n\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\tconst date = `${year}-${month}-${day}`;\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\tconst tools = selectedTools ?? [\"ipython\"];\n\tconst hasIpython = tools.includes(\"ipython\");\n\tconst hasBash = tools.includes(\"bash\");\n\tconst visibleSkills = skills.filter((skill) => !skill.disableModelInvocation);\n\tconst visiblePythonSkillImportNames = getPythonSkillRuntimeInfo(visibleSkills).map((skill) => skill.importName);\n\tconst hasRefineSkill = visibleSkills.some((skill) => skill.name === REFINE_SKILL_NAME);\n\tconst genericMcpSection = hasIpython ? formatGenericMcpGuidance(options.genericMcpServers) : \"\";\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Append skills section only when the model has a way to inspect skill files.\n\t\tconst customPromptHasFileAccess =\n\t\t\t!selectedTools || selectedTools.includes(\"ipython\") || selectedTools.includes(\"bash\");\n\t\tif (customPromptHasFileAccess && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\n\t\t// Add date and working directory last\n\t\tprompt += `\\nCurrent date: ${date}`;\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\tconst childDoctrine = buildChildAgentDoctrine({\n\t\t\tdepth: options.rlmDepth,\n\t\t\tparentAgent: options.rlmParentAgent,\n\t\t\tinstalledSkills: visiblePythonSkillImportNames,\n\t\t\tactiveTools: tools,\n\t\t});\n\t\tif (childDoctrine) {\n\t\t\tprompt += `\\n\\n${childDoctrine}`;\n\t\t}\n\n\t\tif (harnessState) {\n\t\t\tprompt += `\\n\\n${formatHarnessStateForPrompt(harnessState, { includeIpythonExamples: hasIpython, includeShellExamples: hasBash, includeRefineExamples: hasIpython && hasRefineSkill })}`;\n\t\t}\n\n\t\tif (genericMcpSection) {\n\t\t\tprompt += `\\n\\n${genericMcpSection}`;\n\t\t}\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\treturn prompt;\n\t}\n\n\tlet prompt = buildRlmPrompt({\n\t\tcwd: promptCwd,\n\t\tmessagesPath: promptMessagesPath,\n\t\tinstalledSkills: visiblePythonSkillImportNames,\n\t\tactiveTools: tools.filter((name) => name === \"ipython\" || name === \"bash\" || name === \"edit\"),\n\t\tallowRecursion,\n\t\tdepth: options.rlmDepth,\n\t\tparentAgent: options.rlmParentAgent,\n\t});\n\n\t// Appended AFTER the trained buildRlmPrompt prefix, and before the harness-state\n\t// menu, so the model reads when/why to delegate and then sees the concrete subagent\n\t// specs it can match against — the same ordering as Claude Code's Agent tool.\n\tif ((allowRecursion ?? true) && hasIpython) {\n\t\tconst visiblePythonSkillNames = new Set(\n\t\t\tgetPythonSkillRuntimeInfo(visibleSkills).map((skill) => skill.importName),\n\t\t);\n\t\tprompt += `\\n\\n${buildSubagentGuidance({\n\t\t\tincludeRefineExamples: hasRefineSkill,\n\t\t\thasAgentMessage: visiblePythonSkillNames.has(\"agent_message\"),\n\t\t\thasAgentObserve: visiblePythonSkillNames.has(\"agent_observe\"),\n\t\t})}`;\n\t}\n\n\tif (harnessState) {\n\t\tprompt += `\\n\\n${formatHarnessStateForPrompt(harnessState, { includeIpythonExamples: hasIpython, includeShellExamples: hasBash, includeRefineExamples: hasIpython && hasRefineSkill })}`;\n\t}\n\n\tif (genericMcpSection) {\n\t\tprompt += `\\n\\n${genericMcpSection}`;\n\t}\n\n\tconst guidelines = formatPromptGuidelines(promptGuidelines);\n\tif (guidelines) {\n\t\tprompt += `\\n\\n# Additional Guidance\\n\\n${guidelines}`;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Append skills section only when the model has a way to inspect skill files.\n\tconst hasFileAccess = tools.includes(\"ipython\") || tools.includes(\"bash\");\n\tif (hasFileAccess && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\treturn prompt;\n}\n\nfunction formatGenericMcpGuidance(servers: string[] | undefined): string {\n\tconst enabledServers = [...new Set(servers ?? [])].sort((left, right) => left.localeCompare(right));\n\tif (enabledServers.length === 0) return \"\";\n\n\treturn [\n\t\t\"# Generic MCP Connections\",\n\t\t\"\",\n\t\t\"Generic MCP connections are accessed through the pre-imported Python `mcp` object in the Python REPL, not as top-level native tool namespaces or installed Python skills.\",\n\t\t`Enabled generic MCP servers: ${enabledServers.map((server) => `\\`${server}\\``).join(\", \")}.`,\n\t\t...enabledServers.map(\n\t\t\t(server) =>\n\t\t\t\t`For \\`${server}\\`, first discover its tools with \\`await mcp.list_tools(\"${server}\")\\`, then call one with \\`await mcp.call_tool(\"${server}\", \"<tool>\", arguments)\\`.`,\n\t\t),\n\t].join(\"\\n\");\n}\n\nfunction formatPromptGuidelines(promptGuidelines: string[] | undefined): string {\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0 && !guidelinesSet.has(normalized)) {\n\t\t\tguidelinesSet.add(normalized);\n\t\t\tguidelinesList.push(normalized);\n\t\t}\n\t}\n\n\treturn guidelinesList.map((guideline) => `- ${guideline}`).join(\"\\n\");\n}\n"]}
1
+ {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { formatAlwaysAppliedSkills } from \"./always-applied-skills.js\";\nimport { buildChildAgentDoctrine, buildRlmPrompt, buildSubagentGuidance } from \"./prompts/index.js\";\nimport { formatHarnessStateForPrompt, type HarnessState, REFINE_SKILL_NAME } from \"./refinement/index.js\";\nimport { formatSkillsForPrompt, getPythonSkillRuntimeInfo, type Skill } from \"./skills.js\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Active tools. Tool schemas carry tool descriptions outside the prompt body. */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. Used only for custom prompts. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the system prompt. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Conversation log path. */\n\tmessagesPath?: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n\t/** Whether to include the model-facing rlm recursion guidance. */\n\tallowRecursion?: boolean;\n\t/** Fixed recursive-agent depth for this session. */\n\trlmDepth?: number;\n\t/** Human-readable parent name or id for child communication doctrine. */\n\trlmParentAgent?: string;\n\t/** Global harness state to inject as compact persistent context. */\n\tharnessState?: HarnessState;\n\t/** Enabled user-configured servers available through the generic kernel MCP API. */\n\tgenericMcpServers?: string[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tmessagesPath,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t\tallowRecursion,\n\t\tharnessState,\n\t} = options;\n\tconst promptCwd = cwd.replace(/\\\\/g, \"/\");\n\tconst promptMessagesPath = (messagesPath ?? \"not persisted\").replace(/\\\\/g, \"/\");\n\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\tconst date = `${year}-${month}-${day}`;\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\tconst tools = selectedTools ?? [\"ipython\"];\n\tconst hasIpython = tools.includes(\"ipython\");\n\tconst hasBash = tools.includes(\"bash\");\n\tconst visibleSkills = skills.filter((skill) => !skill.disableModelInvocation);\n\tconst visiblePythonSkillImportNames = getPythonSkillRuntimeInfo(visibleSkills).map((skill) => skill.importName);\n\tconst hasRefineSkill = visibleSkills.some((skill) => skill.name === REFINE_SKILL_NAME);\n\tconst genericMcpSection = hasIpython ? formatGenericMcpGuidance(options.genericMcpServers) : \"\";\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Append skills section only when the model has a way to inspect skill files.\n\t\tconst customPromptHasFileAccess =\n\t\t\t!selectedTools || selectedTools.includes(\"ipython\") || selectedTools.includes(\"bash\");\n\t\tif (customPromptHasFileAccess && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\t\tconst alwaysAppliedSkills = formatAlwaysAppliedSkills(skills);\n\t\tif (alwaysAppliedSkills) {\n\t\t\tprompt += `\\n\\n${alwaysAppliedSkills}`;\n\t\t}\n\n\t\t// Add date and working directory last\n\t\tprompt += `\\nCurrent date: ${date}`;\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\tconst childDoctrine = buildChildAgentDoctrine({\n\t\t\tdepth: options.rlmDepth,\n\t\t\tparentAgent: options.rlmParentAgent,\n\t\t\tinstalledSkills: visiblePythonSkillImportNames,\n\t\t\tactiveTools: tools,\n\t\t});\n\t\tif (childDoctrine) {\n\t\t\tprompt += `\\n\\n${childDoctrine}`;\n\t\t}\n\n\t\tif (harnessState) {\n\t\t\tprompt += `\\n\\n${formatHarnessStateForPrompt(harnessState, { includeIpythonExamples: hasIpython, includeShellExamples: hasBash, includeRefineExamples: hasIpython && hasRefineSkill })}`;\n\t\t}\n\n\t\tif (genericMcpSection) {\n\t\t\tprompt += `\\n\\n${genericMcpSection}`;\n\t\t}\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\treturn prompt;\n\t}\n\n\tlet prompt = buildRlmPrompt({\n\t\tcwd: promptCwd,\n\t\tmessagesPath: promptMessagesPath,\n\t\tinstalledSkills: visiblePythonSkillImportNames,\n\t\tactiveTools: tools.filter((name) => name === \"ipython\" || name === \"bash\" || name === \"edit\"),\n\t\tallowRecursion,\n\t\tdepth: options.rlmDepth,\n\t\tparentAgent: options.rlmParentAgent,\n\t});\n\n\t// Appended AFTER the trained buildRlmPrompt prefix, and before the harness-state\n\t// menu, so the model reads when/why to delegate and then sees the concrete subagent\n\t// specs it can match against — the same ordering as Claude Code's Agent tool.\n\tif ((allowRecursion ?? true) && hasIpython) {\n\t\tconst visiblePythonSkillNames = new Set(\n\t\t\tgetPythonSkillRuntimeInfo(visibleSkills).map((skill) => skill.importName),\n\t\t);\n\t\tprompt += `\\n\\n${buildSubagentGuidance({\n\t\t\tincludeRefineExamples: hasRefineSkill,\n\t\t\thasAgentMessage: visiblePythonSkillNames.has(\"agent_message\"),\n\t\t\thasAgentObserve: visiblePythonSkillNames.has(\"agent_observe\"),\n\t\t})}`;\n\t}\n\n\tif (harnessState) {\n\t\tprompt += `\\n\\n${formatHarnessStateForPrompt(harnessState, { includeIpythonExamples: hasIpython, includeShellExamples: hasBash, includeRefineExamples: hasIpython && hasRefineSkill })}`;\n\t}\n\n\tif (genericMcpSection) {\n\t\tprompt += `\\n\\n${genericMcpSection}`;\n\t}\n\n\tconst guidelines = formatPromptGuidelines(promptGuidelines);\n\tif (guidelines) {\n\t\tprompt += `\\n\\n# Additional Guidance\\n\\n${guidelines}`;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Append skills section only when the model has a way to inspect skill files.\n\tconst hasFileAccess = tools.includes(\"ipython\") || tools.includes(\"bash\");\n\tif (hasFileAccess && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\tconst alwaysAppliedSkills = formatAlwaysAppliedSkills(skills);\n\tif (alwaysAppliedSkills) {\n\t\tprompt += `\\n\\n${alwaysAppliedSkills}`;\n\t}\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\treturn prompt;\n}\n\nfunction formatGenericMcpGuidance(servers: string[] | undefined): string {\n\tconst enabledServers = [...new Set(servers ?? [])].sort((left, right) => left.localeCompare(right));\n\tif (enabledServers.length === 0) return \"\";\n\n\treturn [\n\t\t\"# Generic MCP Connections\",\n\t\t\"\",\n\t\t\"Generic MCP connections are accessed through the pre-imported Python `mcp` object in the Python REPL, not as top-level native tool namespaces or installed Python skills.\",\n\t\t`Enabled generic MCP servers: ${enabledServers.map((server) => `\\`${server}\\``).join(\", \")}.`,\n\t\t...enabledServers.map(\n\t\t\t(server) =>\n\t\t\t\t`For \\`${server}\\`, first discover its tools with \\`await mcp.list_tools(\"${server}\")\\`, then call one with \\`await mcp.call_tool(\"${server}\", \"<tool>\", arguments)\\`.`,\n\t\t),\n\t].join(\"\\n\");\n}\n\nfunction formatPromptGuidelines(promptGuidelines: string[] | undefined): string {\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0 && !guidelinesSet.has(normalized)) {\n\t\t\tguidelinesSet.add(normalized);\n\t\t\tguidelinesList.push(normalized);\n\t\t}\n\t}\n\n\treturn guidelinesList.map((guideline) => `- ${guideline}`).join(\"\\n\");\n}\n"]}
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: final-response-summary
3
+ always-apply: true
4
+ description: Ensure the root ASM Agent sends one concise final response that summarizes the complete user request after all delegated agents, agent follow-ups, validations, and other work have settled. MUST be used for every root user request that reaches completion.
5
+ ---
6
+
7
+ # Final Response Summary
8
+
9
+ Apply this workflow only to the root, user-facing agent. Child agents must report
10
+ their results to their parent instead of producing the user's final summary.
11
+
12
+ ## Completion gate
13
+
14
+ Before sending a final answer:
15
+
16
+ 1. Re-read the user's original request and all later user changes.
17
+ 2. Collect every required reply from delegated agents and their follow-ups.
18
+ 3. Confirm no relevant child is still running, queued, or expected to reply.
19
+ 4. Complete required edits, checks, tests, and the request report.
20
+ 5. Separate verified results from blockers or unverified claims.
21
+
22
+ If relevant delegated work is still active, send only a short progress update and
23
+ end the turn. Do not present that update as the final result. Resume when replies
24
+ arrive.
25
+
26
+ ## Final response
27
+
28
+ Send one concise response that covers:
29
+
30
+ - what the user requested;
31
+ - what was completed;
32
+ - important files or behavior changed;
33
+ - checks and tests run;
34
+ - blockers, remaining work, or next steps, when applicable;
35
+ - the generated `docs/report/...` path when the request-report skill applies.
36
+
37
+ Do not repeat the full transcript. Do not invent completion, test results, or
38
+ agent findings. Keep simple requests short and use sections only when they make
39
+ the result clearer.
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: request-report
3
+ always-apply: true
4
+ description: Create one numbered Markdown report at docs/report/<number_mil>_<feature>_<date>.md for the latest user request. MUST be used by the root ASM Agent for every completed project task or user request in a writable workspace, after all work and validation finish and before the final response.
5
+ ---
6
+
7
+ # Request Report
8
+
9
+ The root, user-facing agent must create exactly one report for each completed
10
+ user request in a writable project workspace. Child agents must send findings
11
+ to their parent and must not create request reports.
12
+
13
+ Create the report after edits and validation finish, but before the final user
14
+ response. Call the prepared Python skill:
15
+
16
+ ```python
17
+ path = await request_report(
18
+ root=".",
19
+ feature="short feature name",
20
+ request="The user's complete request, including later changes.",
21
+ summary="What was completed and the resulting behavior.",
22
+ modified_files=["packages/example/src/file.ts", "docs/example.md"],
23
+ changes=["Changed ...", "Added ..."],
24
+ validation=["npm run check — passed"],
25
+ status="completed",
26
+ )
27
+ ```
28
+
29
+ The skill:
30
+
31
+ - creates `docs/report/` when needed;
32
+ - allocates sequential numbers with at least four digits (`0001`, `0002`, ...);
33
+ - converts `feature` to a safe kebab-case slug;
34
+ - uses an ISO date (`YYYY-MM-DD`);
35
+ - requires `modified_files` and renders every path as a relative Markdown link;
36
+ - always links the generated report itself in the modified-files list;
37
+ - rejects modified-file paths outside the project root;
38
+ - creates the file atomically without overwriting an existing report;
39
+ - returns the created path.
40
+
41
+ Pass every created, modified, or deleted project file in `modified_files`. Use
42
+ paths relative to `root` when possible. Use `status="partial"` or
43
+ `status="blocked"` when appropriate. Record only checks
44
+ that actually ran. If the workspace is read-only or the request does not have a
45
+ project filesystem, state that limitation in the final response instead of
46
+ claiming a report was created.
@@ -0,0 +1,16 @@
1
+ [project]
2
+ name = "request-report"
3
+ version = "0.1.0"
4
+ description = "Create numbered Markdown reports for completed ASM Agent requests."
5
+ requires-python = ">=3.10"
6
+ dependencies = []
7
+
8
+ [project.scripts]
9
+ request_report = "rlm.skill:cli"
10
+
11
+ [build-system]
12
+ requires = ["hatchling"]
13
+ build-backend = "hatchling.build"
14
+
15
+ [tool.hatch.build.targets.wheel]
16
+ packages = ["src/request_report"]
@@ -0,0 +1,160 @@
1
+ """Create numbered Markdown reports for completed user requests."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import re
7
+ import unicodedata
8
+ from datetime import date as date_type
9
+ from datetime import datetime, timezone
10
+ from pathlib import Path
11
+ from typing import Iterable
12
+ from urllib.parse import quote
13
+
14
+ _REPORT_NUMBER_WIDTH = 4
15
+ _REPORT_NAME_PATTERN = re.compile(r"^(\d{4,})_.*\.md$")
16
+ _VALID_STATUSES = frozenset({"blocked", "completed", "partial"})
17
+
18
+
19
+ def _slugify(value: str) -> str:
20
+ normalized = unicodedata.normalize("NFKD", value)
21
+ ascii_value = normalized.encode("ascii", "ignore").decode("ascii").lower()
22
+ slug = re.sub(r"[^a-z0-9]+", "-", ascii_value).strip("-")
23
+ return (slug or "request")[:60].rstrip("-")
24
+
25
+
26
+ def _validate_date(value: str | None) -> str:
27
+ if value is None:
28
+ return datetime.now(timezone.utc).date().isoformat()
29
+ try:
30
+ return date_type.fromisoformat(value).isoformat()
31
+ except ValueError as error:
32
+ raise ValueError("date must use YYYY-MM-DD format") from error
33
+
34
+
35
+ def _next_number(report_dir: Path) -> int:
36
+ highest = 0
37
+ for path in report_dir.glob("*.md"):
38
+ match = _REPORT_NAME_PATTERN.match(path.name)
39
+ if match:
40
+ highest = max(highest, int(match.group(1)))
41
+ return highest + 1
42
+
43
+
44
+ def _section(title: str, content: str) -> list[str]:
45
+ return [f"## {title}", "", content.strip() or "Not provided.", ""]
46
+
47
+
48
+ def _bullet_section(title: str, values: Iterable[str] | None) -> list[str]:
49
+ items = [value.strip() for value in (values or []) if value.strip()]
50
+ content = "\n".join(f"- {item}" for item in items) or "- None recorded."
51
+ return _section(title, content)
52
+
53
+
54
+ def _normalize_modified_files(root: Path, values: list[str]) -> list[str]:
55
+ if not isinstance(values, list):
56
+ raise TypeError("modified_files must be a list of project file paths")
57
+ normalized: list[str] = []
58
+ for value in values:
59
+ if not isinstance(value, str) or not value.strip():
60
+ raise ValueError("modified_files must contain non-empty strings")
61
+ candidate = Path(value).expanduser()
62
+ resolved = candidate.resolve() if candidate.is_absolute() else (root / candidate).resolve()
63
+ try:
64
+ relative = resolved.relative_to(root).as_posix()
65
+ except ValueError as error:
66
+ raise ValueError(f"modified file path is outside the project root: {value}") from error
67
+ if relative not in normalized:
68
+ normalized.append(relative)
69
+ return normalized
70
+
71
+
72
+ def _escape_link_label(value: str) -> str:
73
+ return value.replace("\\", "\\\\").replace("[", "\\[").replace("]", "\\]")
74
+
75
+
76
+ def _modified_files_section(root: Path, report_path: Path, modified_files: list[str]) -> list[str]:
77
+ report_relative = report_path.relative_to(root).as_posix()
78
+ paths = [*modified_files]
79
+ if report_relative not in paths:
80
+ paths.append(report_relative)
81
+ links = []
82
+ for path in paths:
83
+ target = Path(os.path.relpath(root / path, report_path.parent)).as_posix()
84
+ links.append(f"- [{_escape_link_label(path)}]({quote(target, safe='/-._')})")
85
+ return _section("Modified files", "\n".join(links))
86
+
87
+
88
+ def _render_report(
89
+ root: Path,
90
+ report_path: Path,
91
+ request: str,
92
+ summary: str,
93
+ modified_files: list[str],
94
+ changes: list[str] | None,
95
+ validation: list[str] | None,
96
+ status: str,
97
+ generated_date: str,
98
+ ) -> str:
99
+ lines = ["# Request Report", "", f"- Status: {status}", f"- Date: {generated_date}", ""]
100
+ lines.extend(_section("User request", request))
101
+ lines.extend(_section("Summary", summary))
102
+ lines.extend(_modified_files_section(root, report_path, modified_files))
103
+ lines.extend(_bullet_section("Changes", changes))
104
+ lines.extend(_bullet_section("Validation", validation))
105
+ return "\n".join(lines).rstrip() + "\n"
106
+
107
+
108
+ async def run(
109
+ root: str,
110
+ feature: str,
111
+ request: str,
112
+ summary: str,
113
+ modified_files: list[str],
114
+ changes: list[str] | None = None,
115
+ validation: list[str] | None = None,
116
+ status: str = "completed",
117
+ date: str | None = None,
118
+ ) -> str:
119
+ """Create and return one atomic numbered report for a completed request."""
120
+ root_path = Path(root).expanduser().resolve()
121
+ if not root_path.is_dir():
122
+ raise NotADirectoryError(f"{root} is not an existing directory")
123
+ if not isinstance(feature, str) or not feature.strip():
124
+ raise ValueError("feature must be a non-empty string")
125
+ if not isinstance(request, str) or not request.strip():
126
+ raise ValueError("request must be a non-empty string")
127
+ if not isinstance(summary, str) or not summary.strip():
128
+ raise ValueError("summary must be a non-empty string")
129
+ if status not in _VALID_STATUSES:
130
+ raise ValueError(f"status must be one of: {', '.join(sorted(_VALID_STATUSES))}")
131
+
132
+ generated_date = _validate_date(date)
133
+ normalized_modified_files = _normalize_modified_files(root_path, modified_files)
134
+ report_dir = root_path / "docs" / "report"
135
+ report_dir.mkdir(parents=True, exist_ok=True)
136
+ slug = _slugify(feature)
137
+ number = _next_number(report_dir)
138
+
139
+ while True:
140
+ report_path = report_dir / f"{number:0{_REPORT_NUMBER_WIDTH}d}_{slug}_{generated_date}.md"
141
+ content = _render_report(
142
+ root_path,
143
+ report_path,
144
+ request,
145
+ summary,
146
+ normalized_modified_files,
147
+ changes,
148
+ validation,
149
+ status,
150
+ generated_date,
151
+ )
152
+ try:
153
+ with report_path.open("x", encoding="utf-8") as report_file:
154
+ report_file.write(content)
155
+ return str(report_path)
156
+ except FileExistsError:
157
+ number += 1
158
+
159
+
160
+ __all__ = ["run"]
@@ -5,7 +5,7 @@ description: Create, validate, and install ASM Agent skills - both markdown skil
5
5
 
6
6
  # Skill Creator
7
7
 
8
- A skill is a directory with a `SKILL.md` file (YAML frontmatter + markdown instructions). At startup ASM Agent reads only each skill's name and description into the system prompt; the full file loads on demand when a task matches. ASM Agent follows the [Agent Skills standard](https://agentskills.io/specification) and extends it with Python-backed skills.
8
+ A skill is a directory with a `SKILL.md` file (YAML frontmatter + markdown instructions). At startup ASM Agent reads each skill's name and description into the system prompt. The full file normally loads on demand when a task matches. Skills marked `always-apply: true` are an ASM Agent extension whose full instructions are injected at startup. ASM Agent follows the [Agent Skills standard](https://agentskills.io/specification) and extends it with Python-backed and always-applied skills.
9
9
 
10
10
  | Kind | What it is | When to use |
11
11
  |---|---|---|
@@ -51,6 +51,7 @@ description: What this skill does and when to use it. Be specific.
51
51
  |---|---|---|
52
52
  | `name` | Yes | Max 64 chars. Lowercase a-z, 0-9, hyphens. No leading/trailing/consecutive hyphens. Must match the parent directory name. |
53
53
  | `description` | Yes | Max 1024 chars. A skill with a missing or empty description is **silently not loaded**. |
54
+ | `always-apply` | No | `true` injects the full skill instructions into every system prompt. Reserve this for small, universal policies. |
54
55
  | `disable-model-invocation` | No | `true` hides the skill from the system prompt; only explicit `/skill:<name>` invokes it. |
55
56
  | `license` | No | License name or reference to a bundled file. |
56
57
  | `compatibility` | No | Max 500 chars. Environment requirements. |