maestro-agent-sdk 0.1.32 → 0.1.34
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/README.md +19 -10
- package/dist/index.d.ts +2 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -9
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts +0 -62
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +23 -167
- package/dist/provider.js.map +1 -1
- package/dist/session-store.d.ts +0 -12
- package/dist/session-store.d.ts.map +1 -1
- package/dist/session-store.js +0 -10
- package/dist/session-store.js.map +1 -1
- package/dist/sub-agent/runner.d.ts +14 -6
- package/dist/sub-agent/runner.d.ts.map +1 -1
- package/dist/sub-agent/runner.js +16 -13
- package/dist/sub-agent/runner.js.map +1 -1
- package/dist/tools/builtin/agent.d.ts +8 -7
- package/dist/tools/builtin/agent.d.ts.map +1 -1
- package/dist/tools/builtin/agent.js +6 -6
- package/dist/tools/builtin/agent.js.map +1 -1
- package/dist/tools/index.d.ts +0 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +0 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/registry.d.ts +9 -0
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +11 -0
- package/dist/tools/registry.js.map +1 -1
- package/dist/types.d.ts +25 -39
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/dist/skills/curator.d.ts +0 -106
- package/dist/skills/curator.d.ts.map +0 -1
- package/dist/skills/curator.js +0 -168
- package/dist/skills/curator.js.map +0 -1
- package/dist/skills/index-builder.d.ts +0 -41
- package/dist/skills/index-builder.d.ts.map +0 -1
- package/dist/skills/index-builder.js +0 -93
- package/dist/skills/index-builder.js.map +0 -1
- package/dist/skills/loader.d.ts +0 -132
- package/dist/skills/loader.d.ts.map +0 -1
- package/dist/skills/loader.js +0 -331
- package/dist/skills/loader.js.map +0 -1
- package/dist/skills/preprocess.d.ts +0 -45
- package/dist/skills/preprocess.d.ts.map +0 -1
- package/dist/skills/preprocess.js +0 -126
- package/dist/skills/preprocess.js.map +0 -1
- package/dist/skills/usage.d.ts +0 -76
- package/dist/skills/usage.d.ts.map +0 -1
- package/dist/skills/usage.js +0 -147
- package/dist/skills/usage.js.map +0 -1
- package/dist/tools/builtin/skill_view.d.ts +0 -37
- package/dist/tools/builtin/skill_view.d.ts.map +0 -1
- package/dist/tools/builtin/skill_view.js +0 -82
- package/dist/tools/builtin/skill_view.js.map +0 -1
- package/dist/tools/builtin/skill_write.d.ts +0 -53
- package/dist/tools/builtin/skill_write.d.ts.map +0 -1
- package/dist/tools/builtin/skill_write.js +0 -264
- package/dist/tools/builtin/skill_write.js.map +0 -1
package/dist/skills/curator.d.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import type { SkillEntry } from "../skills/loader.js";
|
|
2
|
-
import { type SkillCounters } from "../skills/usage.js";
|
|
3
|
-
/**
|
|
4
|
-
* Skill Curator — assigns lifecycle states (active / stale / archived) to
|
|
5
|
-
* every loaded skill based on the usage sidecar, then filters the catalog
|
|
6
|
-
* fed to the system prompt so attention isn't shredded by 100 dormant
|
|
7
|
-
* entries.
|
|
8
|
-
*
|
|
9
|
-
* Lifecycle:
|
|
10
|
-
*
|
|
11
|
-
* - active — recently viewed OR brand-new. Surface in the index.
|
|
12
|
-
* - stale — has been viewed at least once but hasn't been touched in
|
|
13
|
-
* a long time. Still in the index, but at the bottom (and
|
|
14
|
-
* marked) so the model can recognize "this exists" without
|
|
15
|
-
* being nudged toward it.
|
|
16
|
-
* - archived — old + never viewed. Dropped from the index entirely.
|
|
17
|
-
* The skill file stays on disk; the model can still reach
|
|
18
|
-
* it via skill_view if the user explicitly names it, but
|
|
19
|
-
* it stops costing tokens on every turn.
|
|
20
|
-
*
|
|
21
|
-
* The `bundled` vs `agent-created` provenance bit is no longer derivable
|
|
22
|
-
* from path under the `(cwd, skillKey)` model — every skill lives under
|
|
23
|
-
* `<cwd>/.skills/<skillKey>/` regardless of origin. `isBundled` returns
|
|
24
|
-
* true for everything, which protects project-shipped skills from
|
|
25
|
-
* archival; the side effect is that agent-created skills also persist
|
|
26
|
-
* indefinitely. If accumulation becomes a problem, a future release can
|
|
27
|
-
* re-introduce provenance via a frontmatter marker (e.g.
|
|
28
|
-
* `provenance: agent`).
|
|
29
|
-
*
|
|
30
|
-
* The state file lives at `${DATA_DIR}/agents/maestro/skills/state.json`.
|
|
31
|
-
* Like the usage sidecar it's process-local + atomic-write — a host loop
|
|
32
|
-
* is single-process and the curator runs at most once per turn.
|
|
33
|
-
*
|
|
34
|
-
* The SDK ships the rule-based lifecycle transitions only. The LLM-review
|
|
35
|
-
* pass that upstream uses to propose merges between near-duplicate skills
|
|
36
|
-
* is intentionally deferred — it needs a cost budget and operator-confirmed
|
|
37
|
-
* action, both of which are host-side concerns.
|
|
38
|
-
*/
|
|
39
|
-
export type SkillLifecycle = "active" | "stale" | "archived";
|
|
40
|
-
export interface SkillState {
|
|
41
|
-
lifecycle: SkillLifecycle;
|
|
42
|
-
/** ISO timestamp of the last transition (any direction). */
|
|
43
|
-
changedTs: string;
|
|
44
|
-
/** Provenance hint — bundled skills are protected from archival. */
|
|
45
|
-
bundled: boolean;
|
|
46
|
-
}
|
|
47
|
-
export interface SkillStateFile {
|
|
48
|
-
schemaVersion: 1;
|
|
49
|
-
states: Record<string, SkillState>;
|
|
50
|
-
}
|
|
51
|
-
/** How many days since `lastTouchedTs` before a previously-viewed skill is
|
|
52
|
-
* marked `stale`. Default 30. */
|
|
53
|
-
export declare const STALE_AFTER_DAYS = 30;
|
|
54
|
-
/** How many days since `firstSeenTs` (and never viewed) before an unused
|
|
55
|
-
* agent-created skill is archived. Default 60. Bundled skills are exempt. */
|
|
56
|
-
export declare const ARCHIVE_AFTER_DAYS = 60;
|
|
57
|
-
/** Default state file path. Overridable via `MAESTRO_SKILL_STATE_PATH`. */
|
|
58
|
-
export declare function defaultStatePath(): string;
|
|
59
|
-
/** Read the state file synchronously, or return an empty one on
|
|
60
|
-
* ENOENT / schema mismatch / parse error. Cached in-process. */
|
|
61
|
-
export declare function loadState(path?: string): SkillStateFile;
|
|
62
|
-
/**
|
|
63
|
-
* Decide the lifecycle for one skill given its counters + provenance + a
|
|
64
|
-
* reference `now`. Pure function — no I/O. Drives both the in-memory
|
|
65
|
-
* filter and the state-file persistence.
|
|
66
|
-
*
|
|
67
|
-
* Rules:
|
|
68
|
-
* - bundled + never viewed → "active" (operator shipped it for a reason)
|
|
69
|
-
* - viewCount > 0 + recent → "active"
|
|
70
|
-
* - viewCount > 0 + N days old → "stale"
|
|
71
|
-
* - agent-created + never viewed + M days old → "archived"
|
|
72
|
-
* - default (just-loaded, no record yet) → "active"
|
|
73
|
-
*/
|
|
74
|
-
export declare function decideLifecycle(counters: SkillCounters | undefined, bundled: boolean, now?: Date): SkillLifecycle;
|
|
75
|
-
export interface CurateOptions {
|
|
76
|
-
/** Use a fixed `now` for reproducible tests. */
|
|
77
|
-
now?: Date;
|
|
78
|
-
/** Override the state path for tests. */
|
|
79
|
-
statePath?: string;
|
|
80
|
-
/** Override the usage path for tests. */
|
|
81
|
-
usagePath?: string;
|
|
82
|
-
/** Skip writing the state file (read-only inspection). */
|
|
83
|
-
readOnly?: boolean;
|
|
84
|
-
}
|
|
85
|
-
export interface CuratedSkill {
|
|
86
|
-
skill: SkillEntry;
|
|
87
|
-
state: SkillState;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Walk the loaded catalog, compute each skill's lifecycle from the usage
|
|
91
|
-
* sidecar, persist the assignments, and return only the `active` + `stale`
|
|
92
|
-
* entries (callers feed these into the system prompt index builder).
|
|
93
|
-
*
|
|
94
|
-
* Archived skills are kept on disk but dropped from the returned list so
|
|
95
|
-
* the per-turn system prompt stays slim. `skill_view(name=...)` for an
|
|
96
|
-
* archived skill still works — the model just won't be prompted with it.
|
|
97
|
-
*
|
|
98
|
-
* The state-file update is idempotent: skills that didn't change lifecycle
|
|
99
|
-
* since the last call get a no-op write (still atomic).
|
|
100
|
-
*/
|
|
101
|
-
export declare function curateSkills(skills: SkillEntry[], opts?: CurateOptions): CuratedSkill[];
|
|
102
|
-
/** Test-only: drop the in-process state cache. Disk file is NOT erased —
|
|
103
|
-
* tests that need filesystem isolation should point
|
|
104
|
-
* `MAESTRO_SKILL_STATE_PATH` at a tmp file and remove it themselves. */
|
|
105
|
-
export declare function __resetForTests(): void;
|
|
106
|
-
//# sourceMappingURL=curator.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"curator.d.ts","sourceRoot":"","sources":["../../src/skills/curator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAa,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAE7D,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,cAAc,CAAC;IAC1B,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,CAAC,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACpC;AAID;kCACkC;AAClC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AACnC;8EAC8E;AAC9E,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAIrC,2EAA2E;AAC3E,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAWD;iEACiE;AACjE,wBAAgB,SAAS,CAAC,IAAI,GAAE,MAA2B,GAAG,cAAc,CAM3E;AAyCD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,aAAa,GAAG,SAAS,EACnC,OAAO,EAAE,OAAO,EAChB,GAAG,GAAE,IAAiB,GACrB,cAAc,CAYhB;AAED,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,UAAU,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,GAAE,aAAkB,GAAG,YAAY,EAAE,CAoD3F;AAED;;yEAEyE;AACzE,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
|
package/dist/skills/curator.js
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
import { DATA_DIR } from "../platform/config.js";
|
|
4
|
-
import { logger } from "../platform/logger.js";
|
|
5
|
-
import { loadUsage } from "../skills/usage.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 the operator (or project) shipped it deliberately,
|
|
61
|
-
* vs `agent-created` if it was synthesized at runtime by the model.
|
|
62
|
-
*
|
|
63
|
-
* In the `(cwd, skillKey)` model every skill lives under
|
|
64
|
-
* `<cwd>/.skills/<skillKey>/`, so path alone can't tell the two apart —
|
|
65
|
-
* both end up in the same directory. We treat everything as bundled so
|
|
66
|
-
* the curator never archives a project-shipped skill. Agent-created
|
|
67
|
-
* skills also stop archiving as a side effect; if accumulation becomes
|
|
68
|
-
* a problem, a future release can re-introduce provenance via a marker
|
|
69
|
-
* in SKILL.md frontmatter (`provenance: agent` etc.) rather than by
|
|
70
|
-
* path heuristics that the new layout doesn't support. */
|
|
71
|
-
function isBundled(_skill) {
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Decide the lifecycle for one skill given its counters + provenance + a
|
|
76
|
-
* reference `now`. Pure function — no I/O. Drives both the in-memory
|
|
77
|
-
* filter and the state-file persistence.
|
|
78
|
-
*
|
|
79
|
-
* Rules:
|
|
80
|
-
* - bundled + never viewed → "active" (operator shipped it for a reason)
|
|
81
|
-
* - viewCount > 0 + recent → "active"
|
|
82
|
-
* - viewCount > 0 + N days old → "stale"
|
|
83
|
-
* - agent-created + never viewed + M days old → "archived"
|
|
84
|
-
* - default (just-loaded, no record yet) → "active"
|
|
85
|
-
*/
|
|
86
|
-
export function decideLifecycle(counters, bundled, now = new Date()) {
|
|
87
|
-
if (!counters)
|
|
88
|
-
return "active";
|
|
89
|
-
const lastTouched = Date.parse(counters.lastTouchedTs);
|
|
90
|
-
const firstSeen = Date.parse(counters.firstSeenTs);
|
|
91
|
-
const nowMs = now.getTime();
|
|
92
|
-
if (counters.viewCount > 0) {
|
|
93
|
-
const idleDays = (nowMs - lastTouched) / DAY_MS;
|
|
94
|
-
return idleDays >= STALE_AFTER_DAYS ? "stale" : "active";
|
|
95
|
-
}
|
|
96
|
-
if (bundled)
|
|
97
|
-
return "active";
|
|
98
|
-
const ageDays = (nowMs - firstSeen) / DAY_MS;
|
|
99
|
-
return ageDays >= ARCHIVE_AFTER_DAYS ? "archived" : "active";
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Walk the loaded catalog, compute each skill's lifecycle from the usage
|
|
103
|
-
* sidecar, persist the assignments, and return only the `active` + `stale`
|
|
104
|
-
* entries (callers feed these into the system prompt index builder).
|
|
105
|
-
*
|
|
106
|
-
* Archived skills are kept on disk but dropped from the returned list so
|
|
107
|
-
* the per-turn system prompt stays slim. `skill_view(name=...)` for an
|
|
108
|
-
* archived skill still works — the model just won't be prompted with it.
|
|
109
|
-
*
|
|
110
|
-
* The state-file update is idempotent: skills that didn't change lifecycle
|
|
111
|
-
* since the last call get a no-op write (still atomic).
|
|
112
|
-
*/
|
|
113
|
-
export function curateSkills(skills, opts = {}) {
|
|
114
|
-
const usage = loadUsage(opts.usagePath).skills;
|
|
115
|
-
const prior = loadState(opts.statePath);
|
|
116
|
-
const now = opts.now ?? new Date();
|
|
117
|
-
const next = { schemaVersion: SCHEMA_VERSION, states: {} };
|
|
118
|
-
const out = [];
|
|
119
|
-
let changed = false;
|
|
120
|
-
for (const skill of skills) {
|
|
121
|
-
const bundled = isBundled(skill);
|
|
122
|
-
const counters = usage[skill.name];
|
|
123
|
-
const lifecycle = decideLifecycle(counters, bundled, now);
|
|
124
|
-
const priorState = prior.states[skill.name];
|
|
125
|
-
let changedTs;
|
|
126
|
-
if (priorState && priorState.lifecycle === lifecycle && priorState.bundled === bundled) {
|
|
127
|
-
// Stable — preserve the existing change timestamp.
|
|
128
|
-
changedTs = priorState.changedTs;
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
changedTs = now.toISOString();
|
|
132
|
-
changed = true;
|
|
133
|
-
}
|
|
134
|
-
const state = { lifecycle, changedTs, bundled };
|
|
135
|
-
next.states[skill.name] = state;
|
|
136
|
-
if (lifecycle !== "archived")
|
|
137
|
-
out.push({ skill, state });
|
|
138
|
-
}
|
|
139
|
-
// Skills that were in `prior` but no longer in the catalog (renamed /
|
|
140
|
-
// deleted) get implicitly dropped — `next.states` only carries the
|
|
141
|
-
// current catalog. Treat that as a change so the file shrinks too.
|
|
142
|
-
for (const oldName of Object.keys(prior.states)) {
|
|
143
|
-
if (!next.states[oldName]) {
|
|
144
|
-
changed = true;
|
|
145
|
-
break;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
if (changed && !opts.readOnly) {
|
|
149
|
-
const path = opts.statePath ?? defaultStatePath();
|
|
150
|
-
try {
|
|
151
|
-
writeAtomic(path, next);
|
|
152
|
-
// Install post-write file as the new cache reference so the next
|
|
153
|
-
// loadState call sees the freshly-persisted state without re-reading.
|
|
154
|
-
stateCacheByPath.set(path, next);
|
|
155
|
-
}
|
|
156
|
-
catch (err) {
|
|
157
|
-
logger.warn({ err, path }, "skill curator: state write failed (continuing with in-memory result)");
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return out;
|
|
161
|
-
}
|
|
162
|
-
/** Test-only: drop the in-process state cache. Disk file is NOT erased —
|
|
163
|
-
* tests that need filesystem isolation should point
|
|
164
|
-
* `MAESTRO_SKILL_STATE_PATH` at a tmp file and remove it themselves. */
|
|
165
|
-
export function __resetForTests() {
|
|
166
|
-
stateCacheByPath.clear();
|
|
167
|
-
}
|
|
168
|
-
//# sourceMappingURL=curator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"curator.js","sourceRoot":"","sources":["../../src/skills/curator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,41 +0,0 @@
|
|
|
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
|
-
* Ported from upstream `agent/prompt_builder.py::build_skills_prompt` with
|
|
7
|
-
* two changes:
|
|
8
|
-
* 1. CLI-installer-specific guidance from the upstream tree is dropped —
|
|
9
|
-
* the SDK ships no bundled SKILL.md catalog, so suggesting a tool that
|
|
10
|
-
* isn't there would just produce `unknown tool` noise.
|
|
11
|
-
* 2. The `skill_manage(action='patch')` invitation is dropped — the
|
|
12
|
-
* Curator's mutation path is intentionally deferred; surfacing the
|
|
13
|
-
* tool before then would invite a `unknown tool` error.
|
|
14
|
-
*
|
|
15
|
-
* Everything else is preserved word-for-word because it's the "MUST load /
|
|
16
|
-
* err on the side of loading" framing that actually raises the skill-call
|
|
17
|
-
* rate. Empty / softer phrasings tested by upstream regressed activation by
|
|
18
|
-
* ~30%.
|
|
19
|
-
*
|
|
20
|
-
* Why system-prompt placement (not user message): upstream caches this block
|
|
21
|
-
* (`_SKILLS_PROMPT_CACHE`) and embeds it in the system prompt so Anthropic's
|
|
22
|
-
* prefix cache covers it across every turn. Putting it in a user message
|
|
23
|
-
* would invalidate the cache the moment the user sends a follow-up. The
|
|
24
|
-
* trade-off: skill_view output is large enough that we always want it in a
|
|
25
|
-
* fresh user/tool message (cache-busting it once per skill load is fine —
|
|
26
|
-
* it's the index that needs the rolling hit).
|
|
27
|
-
*
|
|
28
|
-
* Returns the empty string when there are no skills — the caller can then
|
|
29
|
-
* skip the append entirely instead of injecting an empty header.
|
|
30
|
-
*/
|
|
31
|
-
export declare function buildSkillsIndex(skills: SkillEntry[]): string;
|
|
32
|
-
/**
|
|
33
|
-
* Cap a skill description to the index limit (`SKILL_INDEX_DESCRIPTION_CAP`).
|
|
34
|
-
* Trims trailing whitespace + ellipsis-truncates so the index stays at one
|
|
35
|
-
* line per skill. The full description still ships with `skill_view`, so the
|
|
36
|
-
* model can read it in full once it decides to load.
|
|
37
|
-
*
|
|
38
|
-
* Empty input returns "" so the caller can suppress the trailing `: …`.
|
|
39
|
-
*/
|
|
40
|
-
export declare function capDescription(desc: string): string;
|
|
41
|
-
//# sourceMappingURL=index-builder.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CA6C7D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMnD"}
|
|
@@ -1,93 +0,0 @@
|
|
|
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
|
-
* Ported from upstream `agent/prompt_builder.py::build_skills_prompt` with
|
|
7
|
-
* two changes:
|
|
8
|
-
* 1. CLI-installer-specific guidance from the upstream tree is dropped —
|
|
9
|
-
* the SDK ships no bundled SKILL.md catalog, so suggesting a tool that
|
|
10
|
-
* isn't there would just produce `unknown tool` noise.
|
|
11
|
-
* 2. The `skill_manage(action='patch')` invitation is dropped — the
|
|
12
|
-
* Curator's mutation path is intentionally deferred; surfacing the
|
|
13
|
-
* tool before then would invite a `unknown tool` error.
|
|
14
|
-
*
|
|
15
|
-
* Everything else is preserved word-for-word because it's the "MUST load /
|
|
16
|
-
* err on the side of loading" framing that actually raises the skill-call
|
|
17
|
-
* rate. Empty / softer phrasings tested by upstream regressed activation by
|
|
18
|
-
* ~30%.
|
|
19
|
-
*
|
|
20
|
-
* Why system-prompt placement (not user message): upstream caches this block
|
|
21
|
-
* (`_SKILLS_PROMPT_CACHE`) and embeds it in the system prompt so Anthropic's
|
|
22
|
-
* prefix cache covers it across every turn. Putting it in a user message
|
|
23
|
-
* would invalidate the cache the moment the user sends a follow-up. The
|
|
24
|
-
* trade-off: skill_view output is large enough that we always want it in a
|
|
25
|
-
* fresh user/tool message (cache-busting it once per skill load is fine —
|
|
26
|
-
* it's the index that needs the rolling hit).
|
|
27
|
-
*
|
|
28
|
-
* Returns the empty string when there are no skills — the caller can then
|
|
29
|
-
* skip the append entirely instead of injecting an empty header.
|
|
30
|
-
*/
|
|
31
|
-
export function buildSkillsIndex(skills) {
|
|
32
|
-
if (skills.length === 0)
|
|
33
|
-
return "";
|
|
34
|
-
const byCategory = new Map();
|
|
35
|
-
for (const s of skills) {
|
|
36
|
-
const bucket = byCategory.get(s.category) ?? [];
|
|
37
|
-
bucket.push(s);
|
|
38
|
-
byCategory.set(s.category, bucket);
|
|
39
|
-
}
|
|
40
|
-
const lines = [];
|
|
41
|
-
const sortedCategories = [...byCategory.keys()].sort((a, b) => a.localeCompare(b));
|
|
42
|
-
for (const category of sortedCategories) {
|
|
43
|
-
lines.push(` ${category}:`);
|
|
44
|
-
const inCat = byCategory.get(category) ?? [];
|
|
45
|
-
inCat.sort((a, b) => a.name.localeCompare(b.name));
|
|
46
|
-
for (const s of inCat) {
|
|
47
|
-
const trimmed = capDescription(s.description);
|
|
48
|
-
if (trimmed) {
|
|
49
|
-
lines.push(` - ${s.name}: ${trimmed}`);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
lines.push(` - ${s.name}`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return [
|
|
57
|
-
"## Skills (mandatory)",
|
|
58
|
-
"Before replying, scan the skills below. If a skill matches or is even partially relevant " +
|
|
59
|
-
"to your task, you MUST load it with skill_view(name) and follow its instructions. " +
|
|
60
|
-
"Err on the side of loading — it is always better to have context you don't need " +
|
|
61
|
-
"than to miss critical steps, pitfalls, or established workflows. " +
|
|
62
|
-
"Skills contain specialized knowledge — API endpoints, tool-specific commands, " +
|
|
63
|
-
"and proven workflows that outperform general-purpose approaches. Load the skill " +
|
|
64
|
-
"even if you think you could handle the task with basic tools. " +
|
|
65
|
-
"Skills also encode the user's preferred approach, conventions, and quality standards " +
|
|
66
|
-
"for tasks like code review, planning, and testing — load them even for tasks you " +
|
|
67
|
-
"already know how to do, because the skill defines how it should be done here.",
|
|
68
|
-
"",
|
|
69
|
-
"<available_skills>",
|
|
70
|
-
...lines,
|
|
71
|
-
"</available_skills>",
|
|
72
|
-
"",
|
|
73
|
-
"Only proceed without loading a skill if genuinely none are relevant to the task.",
|
|
74
|
-
].join("\n");
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Cap a skill description to the index limit (`SKILL_INDEX_DESCRIPTION_CAP`).
|
|
78
|
-
* Trims trailing whitespace + ellipsis-truncates so the index stays at one
|
|
79
|
-
* line per skill. The full description still ships with `skill_view`, so the
|
|
80
|
-
* model can read it in full once it decides to load.
|
|
81
|
-
*
|
|
82
|
-
* Empty input returns "" so the caller can suppress the trailing `: …`.
|
|
83
|
-
*/
|
|
84
|
-
export function capDescription(desc) {
|
|
85
|
-
const collapsed = desc.replace(/\s+/g, " ").trim();
|
|
86
|
-
if (!collapsed)
|
|
87
|
-
return "";
|
|
88
|
-
if (collapsed.length <= SKILL_INDEX_DESCRIPTION_CAP)
|
|
89
|
-
return collapsed;
|
|
90
|
-
// -1 for the ellipsis.
|
|
91
|
-
return `${collapsed.slice(0, SKILL_INDEX_DESCRIPTION_CAP - 1)}…`;
|
|
92
|
-
}
|
|
93
|
-
//# sourceMappingURL=index-builder.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;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"}
|
package/dist/skills/loader.d.ts
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skill loader for the Maestro TS port — accepts two on-disk conventions:
|
|
3
|
-
*
|
|
4
|
-
* 1. **Upstream v0.13.0** — `SKILL.md` (UPPERCASE) with a leading
|
|
5
|
-
* `---\nYAML\n---\n` frontmatter block carrying `name` + `description`
|
|
6
|
-
* and an optional `platforms` filter.
|
|
7
|
-
*
|
|
8
|
-
* 2. **Clawgram body-based** — `skill.md` (lowercase) with no YAML
|
|
9
|
-
* block; the first `# Heading` is treated as the display title and
|
|
10
|
-
* a `> **Description**: ...` blockquote on a single line carries the
|
|
11
|
-
* trigger keywords / summary. Canonical `name` falls back to the
|
|
12
|
-
* parent directory's kebab-case identifier so the rest of the
|
|
13
|
-
* pipeline (index, skill_view, usage counters) is convention-agnostic.
|
|
14
|
-
*
|
|
15
|
-
* Both filename casings and both metadata sources are merged transparently
|
|
16
|
-
* — a SKILL.md with frontmatter wins on conflicting fields, and a project
|
|
17
|
-
* can mix the two styles in the same `.skills/<key>/` tree without
|
|
18
|
-
* configuration. The full YAML parser is still avoided; the minimal
|
|
19
|
-
* fallback parser (top-level scalars + flat `platforms: [...]` list)
|
|
20
|
-
* covers every real-world frontmatter we've seen.
|
|
21
|
-
*
|
|
22
|
-
* Directory layout (both styles):
|
|
23
|
-
* <root>/<category>/<skill-name>/{SKILL.md|skill.md}
|
|
24
|
-
* The penultimate path segment is treated as `category` (used for the
|
|
25
|
-
* Skills index grouping); a skill file at the root level is bucketed
|
|
26
|
-
* under "general".
|
|
27
|
-
*
|
|
28
|
-
* Filters:
|
|
29
|
-
* - Hidden / build dirs (`.git`, `.github`, `.archive`, `.hub`) are
|
|
30
|
-
* skipped recursively (same skip set as upstream).
|
|
31
|
-
* - Platform mismatch (`platforms: [macos]` on Linux) drops the skill so
|
|
32
|
-
* the index doesn't suggest tools that won't run.
|
|
33
|
-
*/
|
|
34
|
-
/** One loaded SKILL.md entry, ready for index rendering or full-load via skill_view. */
|
|
35
|
-
export interface SkillEntry {
|
|
36
|
-
/** `name:` from frontmatter, falling back to the parent directory name. */
|
|
37
|
-
name: string;
|
|
38
|
-
/** Short summary surfaced in the index. Empty string if missing. */
|
|
39
|
-
description: string;
|
|
40
|
-
/** Directory bucket = the parent of the skill's own directory. "general" at root. */
|
|
41
|
-
category: string;
|
|
42
|
-
/** Absolute path to the directory containing SKILL.md. Used for
|
|
43
|
-
* `${MAESTRO_SKILL_DIR}` template substitution and for resolving
|
|
44
|
-
* relative paths inside the skill body. */
|
|
45
|
-
skillDir: string;
|
|
46
|
-
/** Absolute path to SKILL.md itself. */
|
|
47
|
-
mdPath: string;
|
|
48
|
-
/** Raw file contents (frontmatter + body). Kept so skill_view can return
|
|
49
|
-
* the body without a second disk read. */
|
|
50
|
-
raw: string;
|
|
51
|
-
/** Parsed frontmatter as a flat string map. Multi-value entries (e.g.
|
|
52
|
-
* `platforms: [macos, linux]`) are joined with `,`. */
|
|
53
|
-
frontmatter: Record<string, string>;
|
|
54
|
-
}
|
|
55
|
-
/** Description length cap for the rendered index. Raised from 60 → 300 in
|
|
56
|
-
* v0.1.5 because the original 60-char ceiling truncated the "trigger
|
|
57
|
-
* keywords" line that clawgram-style skills rely on for activation —
|
|
58
|
-
* hosts intentionally pack a comma-separated list of search terms into
|
|
59
|
-
* the description, and chopping it at 60 chars regularly lost half the
|
|
60
|
-
* keywords. 300 is generous enough that every real-world description we
|
|
61
|
-
* audited fits intact, while still keeping the per-skill system-prompt
|
|
62
|
-
* footprint bounded if a runaway author writes a 5KB description. The
|
|
63
|
-
* full description still ships with `skill_view` for the body view. */
|
|
64
|
-
export declare const SKILL_INDEX_DESCRIPTION_CAP = 300;
|
|
65
|
-
/**
|
|
66
|
-
* Walk `rootDir` recursively and return one `SkillEntry` per SKILL.md found,
|
|
67
|
-
* subject to platform compatibility + the skip-dir filter.
|
|
68
|
-
*
|
|
69
|
-
* Errors per-file (unreadable, malformed) are logged at debug and the file
|
|
70
|
-
* is dropped — one bad SKILL.md never aborts the whole scan, same stance as
|
|
71
|
-
* upstream `scan_skill_commands`.
|
|
72
|
-
*/
|
|
73
|
-
export declare function loadSkills(rootDir: string): SkillEntry[];
|
|
74
|
-
/**
|
|
75
|
-
* Pull a `> **Description**: ...` (or `> Description: ...`) blockquote out
|
|
76
|
-
* of a markdown body. Matches the clawgram convention where a single-line
|
|
77
|
-
* blockquote near the top of the file carries the trigger keywords.
|
|
78
|
-
*
|
|
79
|
-
* Case-insensitive on the label, tolerant of either `**Description**` or
|
|
80
|
-
* plain `Description`. Only the first match is returned — multi-line
|
|
81
|
-
* blockquotes get joined into one line by trimming trailing whitespace and
|
|
82
|
-
* collapsing inner newlines.
|
|
83
|
-
*
|
|
84
|
-
* Returns "" when no blockquote matches, so the caller can decide whether
|
|
85
|
-
* to fall back to a different source.
|
|
86
|
-
*/
|
|
87
|
-
export declare function extractBlockquoteDescription(body: string): string;
|
|
88
|
-
/**
|
|
89
|
-
* Parse a `---\n...\n---\n` YAML frontmatter block into a flat string map.
|
|
90
|
-
*
|
|
91
|
-
* Supports the SKILL.md surface that matters in v0.13.0:
|
|
92
|
-
* - `key: value` scalars (with optional surrounding quotes)
|
|
93
|
-
* - `key: [a, b, c]` flow-list literals (joined with "," for storage)
|
|
94
|
-
* - Nested blocks (`metadata:\n maestro:\n tags: [...]`) are flattened
|
|
95
|
-
* by ignoring indented lines — we only need top-level keys for the
|
|
96
|
-
* index + platform filter.
|
|
97
|
-
*
|
|
98
|
-
* Lines that don't fit the `key: value` shape are dropped silently. This
|
|
99
|
-
* matches the upstream "fallback" parser; the full YAML parser is omitted
|
|
100
|
-
* because every real-world SKILL.md in v0.13.0 round-trips cleanly through
|
|
101
|
-
* this subset.
|
|
102
|
-
*
|
|
103
|
-
* Returns `body` as the post-frontmatter text. If no frontmatter is
|
|
104
|
-
* present, `frontmatter` is empty and `body` is the original input.
|
|
105
|
-
*/
|
|
106
|
-
export declare function parseFrontmatter(content: string): {
|
|
107
|
-
frontmatter: Record<string, string>;
|
|
108
|
-
body: string;
|
|
109
|
-
};
|
|
110
|
-
/**
|
|
111
|
-
* Return true if the skill's `platforms:` list contains the current OS, or
|
|
112
|
-
* if the field is missing/empty (skill claims cross-platform).
|
|
113
|
-
*
|
|
114
|
-
* Match logic is upstream-compatible: any listed platform whose mapped
|
|
115
|
-
* runtime prefix is a prefix of `process.platform` counts as a hit (so
|
|
116
|
-
* `darwin` matches `darwin23.6.0`).
|
|
117
|
-
*/
|
|
118
|
-
export declare function matchesPlatform(frontmatter: Record<string, string>, platform?: string): boolean;
|
|
119
|
-
/**
|
|
120
|
-
* Cached variant of `loadSkills` — same return shape, but memoizes on the
|
|
121
|
-
* (rootDir, rootDir-mtime) pair with a TTL backstop. Use this from any hot
|
|
122
|
-
* path (per-turn callers, per-iteration callers). Tests or operators that
|
|
123
|
-
* need a guaranteed fresh load can call `invalidateSkillsCache()` first.
|
|
124
|
-
*/
|
|
125
|
-
export declare function loadSkillsCached(rootDir: string): SkillEntry[];
|
|
126
|
-
/** Drop the in-memory cache so the next `loadSkillsCached` call rebuilds.
|
|
127
|
-
* Call after writing a new SKILL.md to disk, or between tests. */
|
|
128
|
-
export declare function invalidateSkillsCache(): void;
|
|
129
|
-
/** Find a single skill by name. Used by `skill_view`. Returns null if the
|
|
130
|
-
* name doesn't resolve to a loaded entry. */
|
|
131
|
-
export declare function findSkillByName(skills: SkillEntry[], name: string): SkillEntry | null;
|
|
132
|
-
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/skills/loader.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;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;;;;;;;;wEAQwE;AACxE,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CAgBxD;AAsGD;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED;;;;;;;;;;;;;;;;;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"}
|