maestro-agent-sdk 0.1.0

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 (196) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +24 -0
  3. package/README.md +133 -0
  4. package/dist/agents/contracts.d.ts +49 -0
  5. package/dist/agents/contracts.d.ts.map +1 -0
  6. package/dist/agents/contracts.js +2 -0
  7. package/dist/agents/contracts.js.map +1 -0
  8. package/dist/agents/rollout/shared.d.ts +24 -0
  9. package/dist/agents/rollout/shared.d.ts.map +1 -0
  10. package/dist/agents/rollout/shared.js +105 -0
  11. package/dist/agents/rollout/shared.js.map +1 -0
  12. package/dist/core/agent.d.ts +71 -0
  13. package/dist/core/agent.d.ts.map +1 -0
  14. package/dist/core/agent.js +22 -0
  15. package/dist/core/agent.js.map +1 -0
  16. package/dist/core/loop.d.ts +26 -0
  17. package/dist/core/loop.d.ts.map +1 -0
  18. package/dist/core/loop.js +317 -0
  19. package/dist/core/loop.js.map +1 -0
  20. package/dist/index.d.ts +49 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +53 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/mcp/client.d.ts +79 -0
  25. package/dist/mcp/client.d.ts.map +1 -0
  26. package/dist/mcp/client.js +176 -0
  27. package/dist/mcp/client.js.map +1 -0
  28. package/dist/mcp/pool-cache.d.ts +103 -0
  29. package/dist/mcp/pool-cache.d.ts.map +1 -0
  30. package/dist/mcp/pool-cache.js +249 -0
  31. package/dist/mcp/pool-cache.js.map +1 -0
  32. package/dist/mcp/pool.d.ts +65 -0
  33. package/dist/mcp/pool.d.ts.map +1 -0
  34. package/dist/mcp/pool.js +86 -0
  35. package/dist/mcp/pool.js.map +1 -0
  36. package/dist/media/file-events.d.ts +8 -0
  37. package/dist/media/file-events.d.ts.map +1 -0
  38. package/dist/media/file-events.js +15 -0
  39. package/dist/media/file-events.js.map +1 -0
  40. package/dist/memory/active-task-template.d.ts +34 -0
  41. package/dist/memory/active-task-template.d.ts.map +1 -0
  42. package/dist/memory/active-task-template.js +63 -0
  43. package/dist/memory/active-task-template.js.map +1 -0
  44. package/dist/memory/compressor.d.ts +87 -0
  45. package/dist/memory/compressor.d.ts.map +1 -0
  46. package/dist/memory/compressor.js +164 -0
  47. package/dist/memory/compressor.js.map +1 -0
  48. package/dist/memory/hash.d.ts +17 -0
  49. package/dist/memory/hash.d.ts.map +1 -0
  50. package/dist/memory/hash.js +20 -0
  51. package/dist/memory/hash.js.map +1 -0
  52. package/dist/memory/prune.d.ts +117 -0
  53. package/dist/memory/prune.d.ts.map +1 -0
  54. package/dist/memory/prune.js +416 -0
  55. package/dist/memory/prune.js.map +1 -0
  56. package/dist/memory/reminder.d.ts +57 -0
  57. package/dist/memory/reminder.d.ts.map +1 -0
  58. package/dist/memory/reminder.js +57 -0
  59. package/dist/memory/reminder.js.map +1 -0
  60. package/dist/memory/scrubber.d.ts +28 -0
  61. package/dist/memory/scrubber.d.ts.map +1 -0
  62. package/dist/memory/scrubber.js +147 -0
  63. package/dist/memory/scrubber.js.map +1 -0
  64. package/dist/memory/token-estimate.d.ts +10 -0
  65. package/dist/memory/token-estimate.d.ts.map +1 -0
  66. package/dist/memory/token-estimate.js +69 -0
  67. package/dist/memory/token-estimate.js.map +1 -0
  68. package/dist/platform/config.d.ts +12 -0
  69. package/dist/platform/config.d.ts.map +1 -0
  70. package/dist/platform/config.js +54 -0
  71. package/dist/platform/config.js.map +1 -0
  72. package/dist/platform/jsonl.d.ts +15 -0
  73. package/dist/platform/jsonl.d.ts.map +1 -0
  74. package/dist/platform/jsonl.js +80 -0
  75. package/dist/platform/jsonl.js.map +1 -0
  76. package/dist/platform/lifecycle.d.ts +22 -0
  77. package/dist/platform/lifecycle.d.ts.map +1 -0
  78. package/dist/platform/lifecycle.js +60 -0
  79. package/dist/platform/lifecycle.js.map +1 -0
  80. package/dist/platform/logger.d.ts +26 -0
  81. package/dist/platform/logger.d.ts.map +1 -0
  82. package/dist/platform/logger.js +41 -0
  83. package/dist/platform/logger.js.map +1 -0
  84. package/dist/platform/mcp-config.d.ts +15 -0
  85. package/dist/platform/mcp-config.d.ts.map +1 -0
  86. package/dist/platform/mcp-config.js +8 -0
  87. package/dist/platform/mcp-config.js.map +1 -0
  88. package/dist/provider.d.ts +81 -0
  89. package/dist/provider.d.ts.map +1 -0
  90. package/dist/provider.js +444 -0
  91. package/dist/provider.js.map +1 -0
  92. package/dist/providers/anthropic.d.ts +132 -0
  93. package/dist/providers/anthropic.d.ts.map +1 -0
  94. package/dist/providers/anthropic.js +518 -0
  95. package/dist/providers/anthropic.js.map +1 -0
  96. package/dist/providers/base.d.ts +140 -0
  97. package/dist/providers/base.d.ts.map +1 -0
  98. package/dist/providers/base.js +2 -0
  99. package/dist/providers/base.js.map +1 -0
  100. package/dist/providers/deepseek.d.ts +118 -0
  101. package/dist/providers/deepseek.d.ts.map +1 -0
  102. package/dist/providers/deepseek.js +467 -0
  103. package/dist/providers/deepseek.js.map +1 -0
  104. package/dist/registry.d.ts +3 -0
  105. package/dist/registry.d.ts.map +1 -0
  106. package/dist/registry.js +94 -0
  107. package/dist/registry.js.map +1 -0
  108. package/dist/session-store.d.ts +133 -0
  109. package/dist/session-store.d.ts.map +1 -0
  110. package/dist/session-store.js +277 -0
  111. package/dist/session-store.js.map +1 -0
  112. package/dist/skills/curator.d.ts +104 -0
  113. package/dist/skills/curator.d.ts.map +1 -0
  114. package/dist/skills/curator.js +162 -0
  115. package/dist/skills/curator.js.map +1 -0
  116. package/dist/skills/index-builder.d.ts +42 -0
  117. package/dist/skills/index-builder.d.ts.map +1 -0
  118. package/dist/skills/index-builder.js +94 -0
  119. package/dist/skills/index-builder.js.map +1 -0
  120. package/dist/skills/loader.d.ts +107 -0
  121. package/dist/skills/loader.d.ts.map +1 -0
  122. package/dist/skills/loader.js +286 -0
  123. package/dist/skills/loader.js.map +1 -0
  124. package/dist/skills/preprocess.d.ts +45 -0
  125. package/dist/skills/preprocess.d.ts.map +1 -0
  126. package/dist/skills/preprocess.js +126 -0
  127. package/dist/skills/preprocess.js.map +1 -0
  128. package/dist/skills/usage.d.ts +75 -0
  129. package/dist/skills/usage.d.ts.map +1 -0
  130. package/dist/skills/usage.js +147 -0
  131. package/dist/skills/usage.js.map +1 -0
  132. package/dist/state/todos.d.ts +95 -0
  133. package/dist/state/todos.d.ts.map +1 -0
  134. package/dist/state/todos.js +198 -0
  135. package/dist/state/todos.js.map +1 -0
  136. package/dist/storage/conversations.d.ts +28 -0
  137. package/dist/storage/conversations.d.ts.map +1 -0
  138. package/dist/storage/conversations.js +8 -0
  139. package/dist/storage/conversations.js.map +1 -0
  140. package/dist/sub-agent/runner.d.ts +78 -0
  141. package/dist/sub-agent/runner.d.ts.map +1 -0
  142. package/dist/sub-agent/runner.js +215 -0
  143. package/dist/sub-agent/runner.js.map +1 -0
  144. package/dist/tools/builtin/agent.d.ts +33 -0
  145. package/dist/tools/builtin/agent.d.ts.map +1 -0
  146. package/dist/tools/builtin/agent.js +76 -0
  147. package/dist/tools/builtin/agent.js.map +1 -0
  148. package/dist/tools/builtin/bash.d.ts +11 -0
  149. package/dist/tools/builtin/bash.d.ts.map +1 -0
  150. package/dist/tools/builtin/bash.js +91 -0
  151. package/dist/tools/builtin/bash.js.map +1 -0
  152. package/dist/tools/builtin/edit.d.ts +21 -0
  153. package/dist/tools/builtin/edit.d.ts.map +1 -0
  154. package/dist/tools/builtin/edit.js +238 -0
  155. package/dist/tools/builtin/edit.js.map +1 -0
  156. package/dist/tools/builtin/read.d.ts +17 -0
  157. package/dist/tools/builtin/read.d.ts.map +1 -0
  158. package/dist/tools/builtin/read.js +139 -0
  159. package/dist/tools/builtin/read.js.map +1 -0
  160. package/dist/tools/builtin/sandbox.d.ts +16 -0
  161. package/dist/tools/builtin/sandbox.d.ts.map +1 -0
  162. package/dist/tools/builtin/sandbox.js +58 -0
  163. package/dist/tools/builtin/sandbox.js.map +1 -0
  164. package/dist/tools/builtin/skill_view.d.ts +37 -0
  165. package/dist/tools/builtin/skill_view.d.ts.map +1 -0
  166. package/dist/tools/builtin/skill_view.js +82 -0
  167. package/dist/tools/builtin/skill_view.js.map +1 -0
  168. package/dist/tools/builtin/todo_write.d.ts +29 -0
  169. package/dist/tools/builtin/todo_write.d.ts.map +1 -0
  170. package/dist/tools/builtin/todo_write.js +96 -0
  171. package/dist/tools/builtin/todo_write.js.map +1 -0
  172. package/dist/tools/builtin/web_fetch.d.ts +10 -0
  173. package/dist/tools/builtin/web_fetch.d.ts.map +1 -0
  174. package/dist/tools/builtin/web_fetch.js +150 -0
  175. package/dist/tools/builtin/web_fetch.js.map +1 -0
  176. package/dist/tools/builtin/write.d.ts +35 -0
  177. package/dist/tools/builtin/write.d.ts.map +1 -0
  178. package/dist/tools/builtin/write.js +70 -0
  179. package/dist/tools/builtin/write.js.map +1 -0
  180. package/dist/tools/file-state.d.ts +99 -0
  181. package/dist/tools/file-state.d.ts.map +1 -0
  182. package/dist/tools/file-state.js +133 -0
  183. package/dist/tools/file-state.js.map +1 -0
  184. package/dist/tools/hooks/sandbox-fs.d.ts +25 -0
  185. package/dist/tools/hooks/sandbox-fs.d.ts.map +1 -0
  186. package/dist/tools/hooks/sandbox-fs.js +48 -0
  187. package/dist/tools/hooks/sandbox-fs.js.map +1 -0
  188. package/dist/tools/registry.d.ts +102 -0
  189. package/dist/tools/registry.d.ts.map +1 -0
  190. package/dist/tools/registry.js +93 -0
  191. package/dist/tools/registry.js.map +1 -0
  192. package/dist/types.d.ts +109 -0
  193. package/dist/types.d.ts.map +1 -0
  194. package/dist/types.js +20 -0
  195. package/dist/types.js.map +1 -0
  196. package/package.json +72 -0
@@ -0,0 +1,162 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { loadUsage } from "../skills/usage.js";
4
+ import { DATA_DIR } from "../platform/config.js";
5
+ import { logger } from "../platform/logger.js";
6
+ const SCHEMA_VERSION = 1;
7
+ /** How many days since `lastTouchedTs` before a previously-viewed skill is
8
+ * marked `stale`. Default 30. */
9
+ export const STALE_AFTER_DAYS = 30;
10
+ /** How many days since `firstSeenTs` (and never viewed) before an unused
11
+ * agent-created skill is archived. Default 60. Bundled skills are exempt. */
12
+ export const ARCHIVE_AFTER_DAYS = 60;
13
+ const DAY_MS = 24 * 60 * 60 * 1000;
14
+ /** Default state file path. Overridable via `MAESTRO_SKILL_STATE_PATH`. */
15
+ export function defaultStatePath() {
16
+ return (process.env.MAESTRO_SKILL_STATE_PATH ??
17
+ join(DATA_DIR, "agents", "maestro", "skills", "state.json"));
18
+ }
19
+ function emptyFile() {
20
+ return { schemaVersion: SCHEMA_VERSION, states: {} };
21
+ }
22
+ // Write-through cache: curateSkills is the sole writer, runs once per turn
23
+ // at most, and produces an explicit `next` object that we install into the
24
+ // cache after writeAtomic. Eliminates the per-turn state.json readFileSync.
25
+ const stateCacheByPath = new Map();
26
+ /** Read the state file synchronously, or return an empty one on
27
+ * ENOENT / schema mismatch / parse error. Cached in-process. */
28
+ export function loadState(path = defaultStatePath()) {
29
+ const cached = stateCacheByPath.get(path);
30
+ if (cached)
31
+ return cached;
32
+ const fresh = readStateFromDisk(path);
33
+ stateCacheByPath.set(path, fresh);
34
+ return fresh;
35
+ }
36
+ function readStateFromDisk(path) {
37
+ if (!existsSync(path))
38
+ return emptyFile();
39
+ try {
40
+ const raw = readFileSync(path, "utf8");
41
+ const parsed = JSON.parse(raw);
42
+ if (parsed.schemaVersion !== SCHEMA_VERSION || typeof parsed.states !== "object") {
43
+ logger.warn({ path }, "skill curator: state schema mismatch, resetting");
44
+ return emptyFile();
45
+ }
46
+ return parsed;
47
+ }
48
+ catch (err) {
49
+ logger.warn({ err, path }, "skill curator: state read/parse failed, resetting");
50
+ return emptyFile();
51
+ }
52
+ }
53
+ /** Atomic tmp + rename write. */
54
+ function writeAtomic(path, contents) {
55
+ mkdirSync(dirname(path), { recursive: true });
56
+ const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
57
+ writeFileSync(tmp, JSON.stringify(contents, null, 2));
58
+ renameSync(tmp, path);
59
+ }
60
+ /** A skill is `bundled` if its file lives under the upstream snapshot
61
+ * directory (defaults to `~/__KEEP_MAESTRO_AGENT__/skills`, overridable via the
62
+ * same `MAESTRO_SKILL_DIR` env that loader.ts uses). Anything outside
63
+ * that tree is treated as agent-created. */
64
+ function isBundled(skill) {
65
+ const snapshotRoot = process.env.MAESTRO_SKILL_DIR ?? `${process.env.HOME ?? ""}/__KEEP_MAESTRO_AGENT__/skills`;
66
+ return skill.skillDir.startsWith(snapshotRoot);
67
+ }
68
+ /**
69
+ * Decide the lifecycle for one skill given its counters + provenance + a
70
+ * reference `now`. Pure function — no I/O. Drives both the in-memory
71
+ * filter and the state-file persistence.
72
+ *
73
+ * Rules:
74
+ * - bundled + never viewed → "active" (operator shipped it for a reason)
75
+ * - viewCount > 0 + recent → "active"
76
+ * - viewCount > 0 + N days old → "stale"
77
+ * - agent-created + never viewed + M days old → "archived"
78
+ * - default (just-loaded, no record yet) → "active"
79
+ */
80
+ export function decideLifecycle(counters, bundled, now = new Date()) {
81
+ if (!counters)
82
+ return "active";
83
+ const lastTouched = Date.parse(counters.lastTouchedTs);
84
+ const firstSeen = Date.parse(counters.firstSeenTs);
85
+ const nowMs = now.getTime();
86
+ if (counters.viewCount > 0) {
87
+ const idleDays = (nowMs - lastTouched) / DAY_MS;
88
+ return idleDays >= STALE_AFTER_DAYS ? "stale" : "active";
89
+ }
90
+ if (bundled)
91
+ return "active";
92
+ const ageDays = (nowMs - firstSeen) / DAY_MS;
93
+ return ageDays >= ARCHIVE_AFTER_DAYS ? "archived" : "active";
94
+ }
95
+ /**
96
+ * Walk the loaded catalog, compute each skill's lifecycle from the usage
97
+ * sidecar, persist the assignments, and return only the `active` + `stale`
98
+ * entries (callers feed these into the system prompt index builder).
99
+ *
100
+ * Archived skills are kept on disk but dropped from the returned list so
101
+ * the per-turn system prompt stays slim. `skill_view(name=...)` for an
102
+ * archived skill still works — the model just won't be prompted with it.
103
+ *
104
+ * The state-file update is idempotent: skills that didn't change lifecycle
105
+ * since the last call get a no-op write (still atomic).
106
+ */
107
+ export function curateSkills(skills, opts = {}) {
108
+ const usage = loadUsage(opts.usagePath).skills;
109
+ const prior = loadState(opts.statePath);
110
+ const now = opts.now ?? new Date();
111
+ const next = { schemaVersion: SCHEMA_VERSION, states: {} };
112
+ const out = [];
113
+ let changed = false;
114
+ for (const skill of skills) {
115
+ const bundled = isBundled(skill);
116
+ const counters = usage[skill.name];
117
+ const lifecycle = decideLifecycle(counters, bundled, now);
118
+ const priorState = prior.states[skill.name];
119
+ let changedTs;
120
+ if (priorState && priorState.lifecycle === lifecycle && priorState.bundled === bundled) {
121
+ // Stable — preserve the existing change timestamp.
122
+ changedTs = priorState.changedTs;
123
+ }
124
+ else {
125
+ changedTs = now.toISOString();
126
+ changed = true;
127
+ }
128
+ const state = { lifecycle, changedTs, bundled };
129
+ next.states[skill.name] = state;
130
+ if (lifecycle !== "archived")
131
+ out.push({ skill, state });
132
+ }
133
+ // Skills that were in `prior` but no longer in the catalog (renamed /
134
+ // deleted) get implicitly dropped — `next.states` only carries the
135
+ // current catalog. Treat that as a change so the file shrinks too.
136
+ for (const oldName of Object.keys(prior.states)) {
137
+ if (!next.states[oldName]) {
138
+ changed = true;
139
+ break;
140
+ }
141
+ }
142
+ if (changed && !opts.readOnly) {
143
+ const path = opts.statePath ?? defaultStatePath();
144
+ try {
145
+ writeAtomic(path, next);
146
+ // Install post-write file as the new cache reference so the next
147
+ // loadState call sees the freshly-persisted state without re-reading.
148
+ stateCacheByPath.set(path, next);
149
+ }
150
+ catch (err) {
151
+ logger.warn({ err, path }, "skill curator: state write failed (continuing with in-memory result)");
152
+ }
153
+ }
154
+ return out;
155
+ }
156
+ /** Test-only: drop the in-process state cache. Disk file is NOT erased —
157
+ * tests that need filesystem isolation should point
158
+ * `MAESTRO_SKILL_STATE_PATH` at a tmp file and remove it themselves. */
159
+ export function __resetForTests() {
160
+ stateCacheByPath.clear();
161
+ }
162
+ //# sourceMappingURL=curator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"curator.js","sourceRoot":"","sources":["../../src/skills/curator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { type SkillEntry } from "../skills/loader.js";
2
+ /**
3
+ * Render the `## Skills (mandatory)` block that gets appended to the Maestro
4
+ * system prompt.
5
+ *
6
+ * Lifted verbatim from upstream `agent/prompt_builder.py::build_skills_prompt`
7
+ * with two changes:
8
+ * 1. Maestro-CLI-specific guidance ("load the `__KEEP_MAESTRO_AGENT__` skill first
9
+ * when configuring Maestro...") is dropped — Clawgram doesn't ship the
10
+ * __KEEP_MAESTRO_AGENT__ skill, and the instruction would suggest a tool the
11
+ * model can't reach.
12
+ * 2. The `skill_manage(action='patch')` invitation is dropped — Phase 4
13
+ * (Curator) lands that tool; surfacing it before then would invite a
14
+ * `unknown tool` error.
15
+ *
16
+ * Everything else is preserved word-for-word because it's the "MUST load /
17
+ * err on the side of loading" framing that actually raises the skill-call
18
+ * rate. Empty / softer phrasings tested by upstream regressed activation by
19
+ * ~30%.
20
+ *
21
+ * Why system-prompt placement (not user message): upstream caches this block
22
+ * (`_SKILLS_PROMPT_CACHE`) and embeds it in the system prompt so Anthropic's
23
+ * prefix cache covers it across every turn. Putting it in a user message
24
+ * would invalidate the cache the moment the user sends a follow-up. The
25
+ * trade-off: skill_view output is large enough that we always want it in a
26
+ * fresh user/tool message (cache-busting it once per skill load is fine —
27
+ * it's the index that needs the rolling hit).
28
+ *
29
+ * Returns the empty string when there are no skills — the caller can then
30
+ * skip the append entirely instead of injecting an empty header.
31
+ */
32
+ export declare function buildSkillsIndex(skills: SkillEntry[]): string;
33
+ /**
34
+ * Cap a skill description to the index limit (`SKILL_INDEX_DESCRIPTION_CAP`).
35
+ * Trims trailing whitespace + ellipsis-truncates so the index stays at one
36
+ * line per skill. The full description still ships with `skill_view`, so the
37
+ * model can read it in full once it decides to load.
38
+ *
39
+ * Empty input returns "" so the caller can suppress the trailing `: …`.
40
+ */
41
+ export declare function capDescription(desc: string): string;
42
+ //# sourceMappingURL=index-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-builder.d.ts","sourceRoot":"","sources":["../../src/skills/index-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CA6C7D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMnD"}
@@ -0,0 +1,94 @@
1
+ import { SKILL_INDEX_DESCRIPTION_CAP } from "../skills/loader.js";
2
+ /**
3
+ * Render the `## Skills (mandatory)` block that gets appended to the Maestro
4
+ * system prompt.
5
+ *
6
+ * Lifted verbatim from upstream `agent/prompt_builder.py::build_skills_prompt`
7
+ * with two changes:
8
+ * 1. Maestro-CLI-specific guidance ("load the `__KEEP_MAESTRO_AGENT__` skill first
9
+ * when configuring Maestro...") is dropped — Clawgram doesn't ship the
10
+ * __KEEP_MAESTRO_AGENT__ skill, and the instruction would suggest a tool the
11
+ * model can't reach.
12
+ * 2. The `skill_manage(action='patch')` invitation is dropped — Phase 4
13
+ * (Curator) lands that tool; surfacing it before then would invite a
14
+ * `unknown tool` error.
15
+ *
16
+ * Everything else is preserved word-for-word because it's the "MUST load /
17
+ * err on the side of loading" framing that actually raises the skill-call
18
+ * rate. Empty / softer phrasings tested by upstream regressed activation by
19
+ * ~30%.
20
+ *
21
+ * Why system-prompt placement (not user message): upstream caches this block
22
+ * (`_SKILLS_PROMPT_CACHE`) and embeds it in the system prompt so Anthropic's
23
+ * prefix cache covers it across every turn. Putting it in a user message
24
+ * would invalidate the cache the moment the user sends a follow-up. The
25
+ * trade-off: skill_view output is large enough that we always want it in a
26
+ * fresh user/tool message (cache-busting it once per skill load is fine —
27
+ * it's the index that needs the rolling hit).
28
+ *
29
+ * Returns the empty string when there are no skills — the caller can then
30
+ * skip the append entirely instead of injecting an empty header.
31
+ */
32
+ export function buildSkillsIndex(skills) {
33
+ if (skills.length === 0)
34
+ return "";
35
+ const byCategory = new Map();
36
+ for (const s of skills) {
37
+ const bucket = byCategory.get(s.category) ?? [];
38
+ bucket.push(s);
39
+ byCategory.set(s.category, bucket);
40
+ }
41
+ const lines = [];
42
+ const sortedCategories = [...byCategory.keys()].sort((a, b) => a.localeCompare(b));
43
+ for (const category of sortedCategories) {
44
+ lines.push(` ${category}:`);
45
+ const inCat = byCategory.get(category) ?? [];
46
+ inCat.sort((a, b) => a.name.localeCompare(b.name));
47
+ for (const s of inCat) {
48
+ const trimmed = capDescription(s.description);
49
+ if (trimmed) {
50
+ lines.push(` - ${s.name}: ${trimmed}`);
51
+ }
52
+ else {
53
+ lines.push(` - ${s.name}`);
54
+ }
55
+ }
56
+ }
57
+ return [
58
+ "## Skills (mandatory)",
59
+ "Before replying, scan the skills below. If a skill matches or is even partially relevant " +
60
+ "to your task, you MUST load it with skill_view(name) and follow its instructions. " +
61
+ "Err on the side of loading — it is always better to have context you don't need " +
62
+ "than to miss critical steps, pitfalls, or established workflows. " +
63
+ "Skills contain specialized knowledge — API endpoints, tool-specific commands, " +
64
+ "and proven workflows that outperform general-purpose approaches. Load the skill " +
65
+ "even if you think you could handle the task with basic tools. " +
66
+ "Skills also encode the user's preferred approach, conventions, and quality standards " +
67
+ "for tasks like code review, planning, and testing — load them even for tasks you " +
68
+ "already know how to do, because the skill defines how it should be done here.",
69
+ "",
70
+ "<available_skills>",
71
+ ...lines,
72
+ "</available_skills>",
73
+ "",
74
+ "Only proceed without loading a skill if genuinely none are relevant to the task.",
75
+ ].join("\n");
76
+ }
77
+ /**
78
+ * Cap a skill description to the index limit (`SKILL_INDEX_DESCRIPTION_CAP`).
79
+ * Trims trailing whitespace + ellipsis-truncates so the index stays at one
80
+ * line per skill. The full description still ships with `skill_view`, so the
81
+ * model can read it in full once it decides to load.
82
+ *
83
+ * Empty input returns "" so the caller can suppress the trailing `: …`.
84
+ */
85
+ export function capDescription(desc) {
86
+ const collapsed = desc.replace(/\s+/g, " ").trim();
87
+ if (!collapsed)
88
+ return "";
89
+ if (collapsed.length <= SKILL_INDEX_DESCRIPTION_CAP)
90
+ return collapsed;
91
+ // -1 for the ellipsis.
92
+ return `${collapsed.slice(0, SKILL_INDEX_DESCRIPTION_CAP - 1)}…`;
93
+ }
94
+ //# sourceMappingURL=index-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-builder.js","sourceRoot":"","sources":["../../src/skills/index-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAmB,MAAM,iBAAiB,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAwB,CAAC;IACnD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACf,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,gBAAgB,GAAG,CAAC,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,GAAG,CAAC,CAAC;QAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC7C,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACnD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;YAC9C,IAAI,OAAO,EAAE,CAAC;gBACZ,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;YAC5C,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,uBAAuB;QACvB,2FAA2F;YACzF,oFAAoF;YACpF,kFAAkF;YAClF,mEAAmE;YACnE,gFAAgF;YAChF,kFAAkF;YAClF,gEAAgE;YAChE,uFAAuF;YACvF,mFAAmF;YACnF,+EAA+E;QACjF,EAAE;QACF,oBAAoB;QACpB,GAAG,KAAK;QACR,qBAAqB;QACrB,EAAE;QACF,kFAAkF;KACnF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACnD,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,CAAC;IAC1B,IAAI,SAAS,CAAC,MAAM,IAAI,2BAA2B;QAAE,OAAO,SAAS,CAAC;IACtE,uBAAuB;IACvB,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,2BAA2B,GAAG,CAAC,CAAC,GAAG,CAAC;AACnE,CAAC"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * SKILL.md frontmatter loader for the Maestro TS port.
3
+ *
4
+ * Mirrors the v0.13.0 `agent/skill_utils.py::parse_frontmatter` contract: a
5
+ * SKILL.md file starts with a `---` fenced YAML block containing at least
6
+ * `name` + `description`, optionally `platforms`, then a markdown body the
7
+ * model consumes via `skill_view`.
8
+ *
9
+ * We don't pull in a full YAML dep (gray-matter / yaml) — SKILL.md
10
+ * frontmatter is small and stable in shape (top-level scalars + a flat
11
+ * `platforms: [...]` list), and the upstream `parse_frontmatter` already
12
+ * ships a minimal fallback for malformed YAML. We use that same fallback
13
+ * shape exclusively, which keeps the surface area zero-dep and covers every
14
+ * real-world SKILL.md in the v0.13.0 snapshot.
15
+ *
16
+ * Directory layout follows upstream:
17
+ * <root>/<category>/<skill-name>/SKILL.md
18
+ * The penultimate path segment is treated as `category` (used for the
19
+ * Skills index grouping); a SKILL.md at the root level is bucketed under
20
+ * "general".
21
+ *
22
+ * Filters:
23
+ * - Hidden / build dirs (`.git`, `.github`, `.archive`, `.hub`) are
24
+ * skipped recursively (same skip set as upstream).
25
+ * - Platform mismatch (`platforms: [macos]` on Linux) drops the skill so
26
+ * the index doesn't suggest tools that won't run.
27
+ */
28
+ /** One loaded SKILL.md entry, ready for index rendering or full-load via skill_view. */
29
+ export interface SkillEntry {
30
+ /** `name:` from frontmatter, falling back to the parent directory name. */
31
+ name: string;
32
+ /** Short summary surfaced in the index. Empty string if missing. */
33
+ description: string;
34
+ /** Directory bucket = the parent of the skill's own directory. "general" at root. */
35
+ category: string;
36
+ /** Absolute path to the directory containing SKILL.md. Used for
37
+ * `${MAESTRO_SKILL_DIR}` template substitution and for resolving
38
+ * relative paths inside the skill body. */
39
+ skillDir: string;
40
+ /** Absolute path to SKILL.md itself. */
41
+ mdPath: string;
42
+ /** Raw file contents (frontmatter + body). Kept so skill_view can return
43
+ * the body without a second disk read. */
44
+ raw: string;
45
+ /** Parsed frontmatter as a flat string map. Multi-value entries (e.g.
46
+ * `platforms: [macos, linux]`) are joined with `,`. */
47
+ frontmatter: Record<string, string>;
48
+ }
49
+ /** Description length cap for the rendered index. Upstream uses 80, but the
50
+ * Clawgram routing review settled on 60 to keep the system-prompt block
51
+ * tight (~6K tokens hard ceiling once the catalog has 60+ skills). The
52
+ * full description survives in `frontmatter.description` for skill_view. */
53
+ export declare const SKILL_INDEX_DESCRIPTION_CAP = 60;
54
+ /**
55
+ * Walk `rootDir` recursively and return one `SkillEntry` per SKILL.md found,
56
+ * subject to platform compatibility + the skip-dir filter.
57
+ *
58
+ * Errors per-file (unreadable, malformed) are logged at debug and the file
59
+ * is dropped — one bad SKILL.md never aborts the whole scan, same stance as
60
+ * upstream `scan_skill_commands`.
61
+ */
62
+ export declare function loadSkills(rootDir: string): SkillEntry[];
63
+ /**
64
+ * Parse a `---\n...\n---\n` YAML frontmatter block into a flat string map.
65
+ *
66
+ * Supports the SKILL.md surface that matters in v0.13.0:
67
+ * - `key: value` scalars (with optional surrounding quotes)
68
+ * - `key: [a, b, c]` flow-list literals (joined with "," for storage)
69
+ * - Nested blocks (`metadata:\n maestro:\n tags: [...]`) are flattened
70
+ * by ignoring indented lines — we only need top-level keys for the
71
+ * index + platform filter.
72
+ *
73
+ * Lines that don't fit the `key: value` shape are dropped silently. This
74
+ * matches the upstream "fallback" parser; the full YAML parser is omitted
75
+ * because every real-world SKILL.md in v0.13.0 round-trips cleanly through
76
+ * this subset.
77
+ *
78
+ * Returns `body` as the post-frontmatter text. If no frontmatter is
79
+ * present, `frontmatter` is empty and `body` is the original input.
80
+ */
81
+ export declare function parseFrontmatter(content: string): {
82
+ frontmatter: Record<string, string>;
83
+ body: string;
84
+ };
85
+ /**
86
+ * Return true if the skill's `platforms:` list contains the current OS, or
87
+ * if the field is missing/empty (skill claims cross-platform).
88
+ *
89
+ * Match logic is upstream-compatible: any listed platform whose mapped
90
+ * runtime prefix is a prefix of `process.platform` counts as a hit (so
91
+ * `darwin` matches `darwin23.6.0`).
92
+ */
93
+ export declare function matchesPlatform(frontmatter: Record<string, string>, platform?: string): boolean;
94
+ /**
95
+ * Cached variant of `loadSkills` — same return shape, but memoizes on the
96
+ * (rootDir, rootDir-mtime) pair with a TTL backstop. Use this from any hot
97
+ * path (per-turn callers, per-iteration callers). Tests or operators that
98
+ * need a guaranteed fresh load can call `invalidateSkillsCache()` first.
99
+ */
100
+ export declare function loadSkillsCached(rootDir: string): SkillEntry[];
101
+ /** Drop the in-memory cache so the next `loadSkillsCached` call rebuilds.
102
+ * Call after writing a new SKILL.md to disk, or between tests. */
103
+ export declare function invalidateSkillsCache(): void;
104
+ /** Find a single skill by name. Used by `skill_view`. Returns null if the
105
+ * name doesn't resolve to a loaded entry. */
106
+ export declare function findSkillByName(skills: SkillEntry[], name: string): SkillEntry | null;
107
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/skills/loader.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,wFAAwF;AACxF,MAAM,WAAW,UAAU;IACzB,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC;IACjB;;gDAE4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf;+CAC2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ;4DACwD;IACxD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAMD;;;6EAG6E;AAC7E,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAE9C;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CAgBxD;AAoFD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IACjD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;CACd,CAkCA;AAaD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,QAAQ,GAAE,MAAyB,GAClC,OAAO,CAaT;AA8CD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CAoB9D;AAED;mEACmE;AACnE,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;8CAC8C;AAC9C,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAYrF"}