@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.
- package/CHANGELOG.md +8 -0
- package/dist/bundle/{anthropic-CWQBVVHC.js → anthropic-CILMWJ23.js} +1 -1
- package/dist/bundle/{azure-openai-responses-7JP64QDL.js → azure-openai-responses-TPNZ54LG.js} +2 -2
- package/dist/bundle/{bundled-modules-DZAECPSN.js → bundled-modules-SKYRKITN.js} +3 -3
- package/dist/bundle/{chunk-7HN2VZJJ.js → chunk-7QIBGY2R.js} +74 -74
- package/dist/bundle/{chunk-O7SB7LML.js → chunk-EFDSSG52.js} +69 -18
- package/dist/bundle/{chunk-FCQTXDPX.js → chunk-IYXHHLR6.js} +1 -1
- package/dist/bundle/{chunk-4KQVBOJB.js → chunk-YYVQTKC6.js} +2 -2
- package/dist/bundle/{cli-main-YXP4FEPB.js → cli-main-O3HK7MNQ.js} +3 -3
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/{google-DPYNVS7L.js → google-3TL5FKLN.js} +1 -1
- package/dist/bundle/{google-vertex-SKMI6LMM.js → google-vertex-WVFMK6QO.js} +1 -1
- package/dist/bundle/{main-DOLQ46ZM.js → main-4QYKME2K.js} +3 -3
- package/dist/bundle/{mistral-DUU7KDZ3.js → mistral-QV2OSBWW.js} +1 -1
- package/dist/bundle/{openai-codex-responses-D7FCP7DO.js → openai-codex-responses-J2GJ2FAO.js} +2 -2
- package/dist/bundle/{openai-completions-AH6TQF5C.js → openai-completions-W622H2EL.js} +1 -1
- package/dist/bundle/{openai-responses-DDC3EYTG.js → openai-responses-V75QG5T7.js} +2 -2
- package/dist/core/always-applied-skills.d.ts +3 -0
- package/dist/core/always-applied-skills.d.ts.map +1 -0
- package/dist/core/always-applied-skills.js +47 -0
- package/dist/core/always-applied-skills.js.map +1 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +9 -0
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/skills/final-response-summary/SKILL.md +39 -0
- package/dist/skills/request-report/SKILL.md +46 -0
- package/dist/skills/request-report/pyproject.toml +16 -0
- package/dist/skills/request-report/src/request_report/__init__.py +160 -0
- package/dist/skills/skill-creator/SKILL.md +2 -1
- package/dist/skills/solid-source-modularity/SKILL.md +48 -0
- package/dist/skills/solid-source-modularity/pyproject.toml +16 -0
- package/dist/skills/solid-source-modularity/src/solid_source_modularity/__init__.py +154 -0
- package/docs/skills.md +8 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +5 -5
- package/skills/final-response-summary/SKILL.md +39 -0
- package/skills/request-report/SKILL.md +46 -0
- package/skills/request-report/pyproject.toml +16 -0
- package/skills/request-report/src/request_report/__init__.py +160 -0
- package/skills/skill-creator/SKILL.md +2 -1
- package/skills/solid-source-modularity/SKILL.md +48 -0
- package/skills/solid-source-modularity/pyproject.toml +16 -0
- 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-
|
|
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-
|
|
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-
|
|
185
|
+
import("./main-4QYKME2K.js")
|
|
186
186
|
]);
|
|
187
187
|
setGlobalDispatcher(new EnvHttpProxyAgent({ bodyTimeout: 0, headersTimeout: 0 }));
|
|
188
188
|
try {
|
package/dist/bundle/cli.js
CHANGED
|
@@ -17,8 +17,8 @@ import {
|
|
|
17
17
|
shouldUseDaemonClientRuntime,
|
|
18
18
|
shouldUseDaemonInteractive,
|
|
19
19
|
shouldUseEphemeralSessionManagerForDaemonInteractive
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
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-
|
|
31
|
+
import "./chunk-7QIBGY2R.js";
|
|
32
32
|
import "./chunk-BAWSWWEU.js";
|
|
33
33
|
export {
|
|
34
34
|
createSessionManager,
|
package/dist/bundle/{openai-codex-responses-D7FCP7DO.js → openai-codex-responses-J2GJ2FAO.js}
RENAMED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
convertResponsesMessages,
|
|
7
7
|
convertResponsesTools,
|
|
8
8
|
processResponsesStream
|
|
9
|
-
} from "./chunk-
|
|
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-
|
|
29
|
+
} from "./chunk-7QIBGY2R.js";
|
|
30
30
|
import "./chunk-BAWSWWEU.js";
|
|
31
31
|
|
|
32
32
|
// ../ai/src/providers/openai-codex-responses.ts
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
convertResponsesMessages,
|
|
10
10
|
convertResponsesTools,
|
|
11
11
|
processResponsesStream
|
|
12
|
-
} from "./chunk-
|
|
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-
|
|
35
|
+
} from "./chunk-7QIBGY2R.js";
|
|
36
36
|
import "./chunk-BAWSWWEU.js";
|
|
37
37
|
|
|
38
38
|
// ../ai/src/providers/openai-responses.ts
|
|
@@ -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, \"&\")\n\t\t.replace(/</g, \"<\")\n\t\t.replace(/>/g, \">\")\n\t\t.replace(/\"/g, \""\")\n\t\t.replace(/'/g, \"'\");\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, "&")
|
|
42
|
+
.replace(/</g, "<")
|
|
43
|
+
.replace(/>/g, ">")
|
|
44
|
+
.replace(/"/g, """)
|
|
45
|
+
.replace(/'/g, "'");
|
|
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, \"&\")\n\t\t.replace(/</g, \"<\")\n\t\t.replace(/>/g, \">\")\n\t\t.replace(/\"/g, \""\")\n\t\t.replace(/'/g, \"'\");\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
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":"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","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
|
|
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. |
|