maestro-agent-sdk 0.1.3 → 0.1.5
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 +216 -20
- package/dist/agents/contracts.d.ts +10 -0
- package/dist/agents/contracts.d.ts.map +1 -1
- package/dist/agents/rollout/shared.d.ts +4 -4
- package/dist/agents/rollout/shared.js +4 -4
- package/dist/core/loop.d.ts.map +1 -1
- package/dist/core/loop.js +9 -8
- package/dist/core/loop.js.map +1 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/dist/memory/compressor.d.ts +8 -5
- package/dist/memory/compressor.d.ts.map +1 -1
- package/dist/memory/compressor.js +10 -4
- package/dist/memory/compressor.js.map +1 -1
- package/dist/memory/reminder.d.ts +11 -12
- package/dist/memory/reminder.d.ts.map +1 -1
- package/dist/memory/reminder.js +22 -32
- package/dist/memory/reminder.js.map +1 -1
- package/dist/platform/config.d.ts +0 -2
- package/dist/platform/config.d.ts.map +1 -1
- package/dist/platform/config.js +9 -18
- package/dist/platform/config.js.map +1 -1
- package/dist/platform/version.d.ts +13 -0
- package/dist/platform/version.d.ts.map +1 -0
- package/dist/platform/version.js +13 -0
- package/dist/platform/version.js.map +1 -0
- package/dist/provider.d.ts +62 -0
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +137 -30
- package/dist/provider.js.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +16 -1
- package/dist/registry.js.map +1 -1
- package/dist/session-store.d.ts +95 -4
- package/dist/session-store.d.ts.map +1 -1
- package/dist/session-store.js +144 -13
- package/dist/session-store.js.map +1 -1
- package/dist/skills/curator.d.ts +8 -6
- package/dist/skills/curator.d.ts.map +1 -1
- package/dist/skills/curator.js +13 -7
- package/dist/skills/curator.js.map +1 -1
- package/dist/skills/loader.d.ts +45 -20
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +56 -11
- package/dist/skills/loader.js.map +1 -1
- package/dist/state/tasks.d.ts +107 -0
- package/dist/state/tasks.d.ts.map +1 -0
- package/dist/state/tasks.js +398 -0
- package/dist/state/tasks.js.map +1 -0
- package/dist/sub-agent/runner.d.ts +1 -1
- package/dist/sub-agent/runner.d.ts.map +1 -1
- package/dist/sub-agent/runner.js +3 -5
- package/dist/sub-agent/runner.js.map +1 -1
- package/dist/tools/builtin/edit.d.ts.map +1 -1
- package/dist/tools/builtin/edit.js +0 -4
- package/dist/tools/builtin/edit.js.map +1 -1
- package/dist/tools/builtin/glob.d.ts +17 -0
- package/dist/tools/builtin/glob.d.ts.map +1 -0
- package/dist/tools/builtin/glob.js +235 -0
- package/dist/tools/builtin/glob.js.map +1 -0
- package/dist/tools/builtin/grep.d.ts +3 -0
- package/dist/tools/builtin/grep.d.ts.map +1 -0
- package/dist/tools/builtin/grep.js +272 -0
- package/dist/tools/builtin/grep.js.map +1 -0
- package/dist/tools/builtin/read.d.ts.map +1 -1
- package/dist/tools/builtin/read.js +0 -4
- package/dist/tools/builtin/read.js.map +1 -1
- package/dist/tools/builtin/skill_write.d.ts +53 -0
- package/dist/tools/builtin/skill_write.d.ts.map +1 -0
- package/dist/tools/builtin/skill_write.js +264 -0
- package/dist/tools/builtin/skill_write.js.map +1 -0
- package/dist/tools/builtin/tasks.d.ts +34 -0
- package/dist/tools/builtin/tasks.d.ts.map +1 -0
- package/dist/tools/builtin/tasks.js +258 -0
- package/dist/tools/builtin/tasks.js.map +1 -0
- package/dist/tools/builtin/write.d.ts +4 -10
- package/dist/tools/builtin/write.d.ts.map +1 -1
- package/dist/tools/builtin/write.js.map +1 -1
- package/dist/tools/file-state.d.ts +1 -1
- package/dist/tools/file-state.js +1 -1
- package/dist/tools/registry.d.ts +1 -1
- package/dist/types.d.ts +64 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/state/todos.d.ts +0 -95
- package/dist/state/todos.d.ts.map +0 -1
- package/dist/state/todos.js +0 -198
- package/dist/state/todos.js.map +0 -1
- package/dist/tools/builtin/sandbox.d.ts +0 -16
- package/dist/tools/builtin/sandbox.d.ts.map +0 -1
- package/dist/tools/builtin/sandbox.js +0 -59
- package/dist/tools/builtin/sandbox.js.map +0 -1
- package/dist/tools/builtin/todo_write.d.ts +0 -29
- package/dist/tools/builtin/todo_write.d.ts.map +0 -1
- package/dist/tools/builtin/todo_write.js +0 -96
- package/dist/tools/builtin/todo_write.js.map +0 -1
- package/dist/tools/hooks/sandbox-fs.d.ts +0 -25
- package/dist/tools/hooks/sandbox-fs.d.ts.map +0 -1
- package/dist/tools/hooks/sandbox-fs.js +0 -48
- package/dist/tools/hooks/sandbox-fs.js.map +0 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { ToolHandler } from "../../tools/registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* `skill_write` builtin — agent-autonomous skill authoring.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the clawgram skill-creation convention (`meta/skills/skill-creation-
|
|
6
|
+
* guide.md` in the host repo):
|
|
7
|
+
*
|
|
8
|
+
* - File layout is `<skillsDir>/<name>/skill.md` (folder per skill, lowercase
|
|
9
|
+
* filename). Folder layout is enforced — progressive-disclosure assets
|
|
10
|
+
* (`scripts/`, `templates/`, `references/`) sit alongside the manifest
|
|
11
|
+
* and the agent ships them in the same call via the `files` map.
|
|
12
|
+
* - Content is plain markdown with a `# Title` heading and a
|
|
13
|
+
* `> **Description**: <trigger keywords>` blockquote near the top. No
|
|
14
|
+
* YAML frontmatter is required (the v0.1.5 loader extracts the
|
|
15
|
+
* description from the blockquote when frontmatter is absent).
|
|
16
|
+
* - Canonical identifier (`name`) is the folder, kebab-case English.
|
|
17
|
+
*
|
|
18
|
+
* The model produces the full markdown body and passes it as `content`,
|
|
19
|
+
* along with an optional `files` map for adjacent assets (scripts,
|
|
20
|
+
* templates, references). The tool enforces:
|
|
21
|
+
*
|
|
22
|
+
* - kebab-case name validation
|
|
23
|
+
* - non-empty manifest content
|
|
24
|
+
* - relative-path safety for `files` (no leading `/`, no `..` escapes)
|
|
25
|
+
* - no collisions with the manifest path (`skill.md` is reserved)
|
|
26
|
+
*
|
|
27
|
+
* All writes happen under `<skillsDir>/<name>/` so the agent can never
|
|
28
|
+
* escape its keyed profile. Writes are best-effort transactional: the tool
|
|
29
|
+
* validates EVERY `files` entry before touching disk, then writes manifest
|
|
30
|
+
* + files in order. A partial-failure midway (disk full, permission
|
|
31
|
+
* change) leaves whatever was written so far in place — the caller can
|
|
32
|
+
* inspect `path` / `files` in the error response and re-try with
|
|
33
|
+
* `overwrite: true`.
|
|
34
|
+
*
|
|
35
|
+
* After a successful write the in-memory skills cache is invalidated so
|
|
36
|
+
* the next turn's catalog reload picks up the new skill immediately. The
|
|
37
|
+
* skill is NOT live in the current turn's catalog — adding it mid-turn
|
|
38
|
+
* would change the system-prompt index hash and bust the prompt cache,
|
|
39
|
+
* costing more than it gains.
|
|
40
|
+
*
|
|
41
|
+
* Factory captures the resolved skillsDir for this session so the agent
|
|
42
|
+
* always lands writes inside its own keyed profile (`.skills/<key>/`) and
|
|
43
|
+
* never escapes to another profile's directory.
|
|
44
|
+
*/
|
|
45
|
+
export interface SkillWriteToolOptions {
|
|
46
|
+
/** Absolute path of the resolved skills directory for this session. New
|
|
47
|
+
* skills land at `<skillsDir>/<name>/skill.md`. Comes from
|
|
48
|
+
* `resolveSkillsDir(opts)` in the provider, so it already reflects the
|
|
49
|
+
* `(cwd, skillKey)` routing. */
|
|
50
|
+
skillsDir: string;
|
|
51
|
+
}
|
|
52
|
+
export declare function createSkillWriteTool(opts: SkillWriteToolOptions): ToolHandler;
|
|
53
|
+
//# sourceMappingURL=skill_write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill_write.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/skill_write.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,MAAM,WAAW,qBAAqB;IACpC;;;qCAGiC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AAuBD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,qBAAqB,GAAG,WAAW,CA8N7E"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, isAbsolute, join, normalize, relative } from "node:path";
|
|
3
|
+
import { invalidateSkillsCache } from "../../skills/loader.js";
|
|
4
|
+
import { logger } from "../../platform/logger.js";
|
|
5
|
+
/** kebab-case validator: lowercase letters, digits, dashes. Must start with
|
|
6
|
+
* a letter; no leading/trailing/consecutive dashes. */
|
|
7
|
+
const NAME_RE = /^[a-z](?:[a-z0-9]|-(?=[a-z0-9]))*$/;
|
|
8
|
+
/** Soft sanity check — the loader will surface the skill regardless, but
|
|
9
|
+
* warning the agent here helps it land a clawgram-conformant file on the
|
|
10
|
+
* first try. */
|
|
11
|
+
function lintContent(content) {
|
|
12
|
+
const warnings = [];
|
|
13
|
+
if (!/^#\s+\S/m.test(content)) {
|
|
14
|
+
warnings.push("Missing a top-level `# Title` heading.");
|
|
15
|
+
}
|
|
16
|
+
if (!/^[ \t]*>[ \t]*(?:\*\*)?\s*description\s*(?:\*\*)?[ \t]*:/im.test(content)) {
|
|
17
|
+
warnings.push("Missing a `> **Description**: ...` blockquote — trigger keywords " +
|
|
18
|
+
"won't surface in the system-prompt index until you add one.");
|
|
19
|
+
}
|
|
20
|
+
return { warnings };
|
|
21
|
+
}
|
|
22
|
+
export function createSkillWriteTool(opts) {
|
|
23
|
+
const { skillsDir } = opts;
|
|
24
|
+
return {
|
|
25
|
+
// Writes mutate disk + invalidate cache — not safe for parallel
|
|
26
|
+
// dispatch with another skill_write (two writes racing the cache
|
|
27
|
+
// invalidation could leave a stale entry). Reads are fine to overlap
|
|
28
|
+
// because the cache TTL absorbs the staleness.
|
|
29
|
+
parallelSafe: false,
|
|
30
|
+
schema: {
|
|
31
|
+
name: "skill_write",
|
|
32
|
+
description: "Author or update a skill manifest (and optional adjacent assets) " +
|
|
33
|
+
"inside the session's skills directory. Writes " +
|
|
34
|
+
"`<skillsDir>/<name>/skill.md` with the provided markdown content, " +
|
|
35
|
+
"plus any files listed in `files` under the same skill folder " +
|
|
36
|
+
"(e.g. `scripts/foo.py`, `templates/x.tex`, `references/api.md`). " +
|
|
37
|
+
"Folder layout is mandatory — progressive-disclosure assets sit " +
|
|
38
|
+
"next to the manifest. The catalog reloads on the NEXT turn " +
|
|
39
|
+
"(not the current one) — finish your current task, then the new " +
|
|
40
|
+
"skill is available via skill_view.\n\n" +
|
|
41
|
+
"Content conventions (clawgram-style):\n" +
|
|
42
|
+
" - First line: `# Title` (the display title; can be Korean or English).\n" +
|
|
43
|
+
" - Near the top: `> **Description**: <comma-separated trigger keywords>`. " +
|
|
44
|
+
"This drives skill activation — be specific, list the words a user would " +
|
|
45
|
+
"actually type.\n" +
|
|
46
|
+
" - Sections to include: 트리거 / 프로세스 / Gotchas. Gotchas is the " +
|
|
47
|
+
"most valuable section — accumulate failure cases + fixes over time.\n" +
|
|
48
|
+
" - Don't restate the obvious; focus on knowledge that changes behavior.\n\n" +
|
|
49
|
+
"Returns success with the manifest path + per-asset paths, or an " +
|
|
50
|
+
"error JSON when validation fails or any target already exists " +
|
|
51
|
+
"(pass `overwrite: true` to replace).",
|
|
52
|
+
input_schema: {
|
|
53
|
+
type: "object",
|
|
54
|
+
properties: {
|
|
55
|
+
name: {
|
|
56
|
+
type: "string",
|
|
57
|
+
description: "Skill identifier in kebab-case (lowercase, dashes between words, " +
|
|
58
|
+
"no leading/trailing dashes). Becomes the folder name; the loader " +
|
|
59
|
+
"uses it as the canonical name when no frontmatter `name:` is set.",
|
|
60
|
+
},
|
|
61
|
+
content: {
|
|
62
|
+
type: "string",
|
|
63
|
+
description: "Full markdown body of the skill. Must include `# Title` and " +
|
|
64
|
+
"`> **Description**: ...` near the top (a warning surfaces if either " +
|
|
65
|
+
"is missing). No YAML frontmatter required.",
|
|
66
|
+
},
|
|
67
|
+
files: {
|
|
68
|
+
type: "object",
|
|
69
|
+
description: "Optional map of `<relative-path>: <file-content>` for adjacent " +
|
|
70
|
+
"assets inside the skill folder. Paths are relative to " +
|
|
71
|
+
"`<skillsDir>/<name>/`, use forward slashes, must not contain `..` " +
|
|
72
|
+
"or absolute prefixes, and cannot equal `skill.md` (reserved for " +
|
|
73
|
+
"the manifest). Parent directories are created automatically. " +
|
|
74
|
+
"Example: `{\"scripts/run.sh\": \"#!/bin/bash\\n...\", " +
|
|
75
|
+
"\"templates/x.tex\": \"...\", \"references/api.md\": \"...\"}`",
|
|
76
|
+
additionalProperties: { type: "string" },
|
|
77
|
+
},
|
|
78
|
+
overwrite: {
|
|
79
|
+
type: "boolean",
|
|
80
|
+
description: "Replace existing files at the manifest path OR any `files` " +
|
|
81
|
+
"target. Default false; when false, any preexisting target aborts " +
|
|
82
|
+
"the whole call BEFORE writing anything.",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
required: ["name", "content"],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
async execute(input) {
|
|
89
|
+
const name = typeof input.name === "string" ? input.name.trim() : "";
|
|
90
|
+
const content = typeof input.content === "string" ? input.content : "";
|
|
91
|
+
const overwrite = input.overwrite === true;
|
|
92
|
+
const filesInput = input.files && typeof input.files === "object" && !Array.isArray(input.files)
|
|
93
|
+
? input.files
|
|
94
|
+
: null;
|
|
95
|
+
if (!name) {
|
|
96
|
+
return JSON.stringify({ error: "skill_write: missing 'name' argument" });
|
|
97
|
+
}
|
|
98
|
+
if (!NAME_RE.test(name)) {
|
|
99
|
+
return JSON.stringify({
|
|
100
|
+
error: `skill_write: invalid name '${name}' — must be kebab-case ` +
|
|
101
|
+
"(lowercase letters/digits, single dashes between segments, " +
|
|
102
|
+
"start with a letter).",
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (!content.trim()) {
|
|
106
|
+
return JSON.stringify({
|
|
107
|
+
error: "skill_write: 'content' is empty — provide the skill markdown body",
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
// Final path: <skillsDir>/<name>/skill.md. The skillsDir was resolved
|
|
111
|
+
// from (cwd, skillKey) at session start, so the agent's write
|
|
112
|
+
// automatically lands in its own profile.
|
|
113
|
+
const skillDir = join(skillsDir, name);
|
|
114
|
+
const skillFile = join(skillDir, "skill.md");
|
|
115
|
+
// ---- Phase 1: validate the entire write set BEFORE touching disk ----
|
|
116
|
+
// Up-front validation lets us reject a malformed batch as a unit
|
|
117
|
+
// (e.g. one bad relative path among ten files) instead of writing
|
|
118
|
+
// half the assets and then bailing.
|
|
119
|
+
const fileWrites = [];
|
|
120
|
+
if (filesInput) {
|
|
121
|
+
for (const [rel, raw] of Object.entries(filesInput)) {
|
|
122
|
+
if (typeof rel !== "string" || rel.trim() === "") {
|
|
123
|
+
return JSON.stringify({
|
|
124
|
+
error: `skill_write: 'files' has an empty key (entry value: ${typeof raw})`,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
if (typeof raw !== "string") {
|
|
128
|
+
return JSON.stringify({
|
|
129
|
+
error: `skill_write: 'files[${rel}]' must be a string, got ${typeof raw}`,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
const safetyErr = validateRelativePath(rel);
|
|
133
|
+
if (safetyErr) {
|
|
134
|
+
return JSON.stringify({
|
|
135
|
+
error: `skill_write: ${safetyErr} (entry '${rel}')`,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
if (rel === "skill.md") {
|
|
139
|
+
return JSON.stringify({
|
|
140
|
+
error: "skill_write: 'files' may not include 'skill.md' — pass the " +
|
|
141
|
+
"manifest body via the top-level `content` argument instead",
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
fileWrites.push({ rel, abs: join(skillDir, rel), body: raw });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Pre-check existing-target conflicts when overwrite=false. We do
|
|
148
|
+
// this AFTER validating shapes so a malformed entry surfaces first.
|
|
149
|
+
if (!overwrite) {
|
|
150
|
+
if (existsSync(skillFile)) {
|
|
151
|
+
return JSON.stringify({
|
|
152
|
+
error: `skill_write: '${skillFile}' already exists — pass overwrite: true to replace`,
|
|
153
|
+
path: skillFile,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
for (const f of fileWrites) {
|
|
157
|
+
if (existsSync(f.abs)) {
|
|
158
|
+
return JSON.stringify({
|
|
159
|
+
error: `skill_write: '${f.abs}' already exists — pass overwrite: true to replace`,
|
|
160
|
+
path: f.abs,
|
|
161
|
+
rel: f.rel,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// ---- Phase 2: write manifest + adjacent files ----
|
|
167
|
+
let bytesTotal = 0;
|
|
168
|
+
const writtenFiles = [];
|
|
169
|
+
try {
|
|
170
|
+
mkdirSync(skillDir, { recursive: true });
|
|
171
|
+
// Manifest first — ensure trailing newline.
|
|
172
|
+
const manifestBody = content.endsWith("\n") ? content : `${content}\n`;
|
|
173
|
+
writeFileSync(skillFile, manifestBody, "utf-8");
|
|
174
|
+
const manifestBytes = Buffer.byteLength(manifestBody, "utf-8");
|
|
175
|
+
bytesTotal += manifestBytes;
|
|
176
|
+
for (const f of fileWrites) {
|
|
177
|
+
mkdirSync(dirname(f.abs), { recursive: true });
|
|
178
|
+
writeFileSync(f.abs, f.body, "utf-8");
|
|
179
|
+
const b = Buffer.byteLength(f.body, "utf-8");
|
|
180
|
+
bytesTotal += b;
|
|
181
|
+
writtenFiles.push({ rel: f.rel, path: f.abs, bytes: b });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch (e) {
|
|
185
|
+
// Partial failure: the manifest may or may not be written, and
|
|
186
|
+
// some files may have landed. Report what succeeded so the agent
|
|
187
|
+
// can decide whether to re-try with overwrite or clean up by hand.
|
|
188
|
+
return JSON.stringify({
|
|
189
|
+
error: `skill_write: failed mid-write: ${e instanceof Error ? e.message : String(e)}`,
|
|
190
|
+
manifestPath: skillFile,
|
|
191
|
+
manifestWritten: existsSync(skillFile),
|
|
192
|
+
filesWritten: writtenFiles,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// Bust the loader cache so the next provider call (next turn) sees
|
|
196
|
+
// this skill in the catalog without waiting for the TTL.
|
|
197
|
+
invalidateSkillsCache();
|
|
198
|
+
const { warnings } = lintContent(content);
|
|
199
|
+
const result = {
|
|
200
|
+
ok: true,
|
|
201
|
+
path: skillFile,
|
|
202
|
+
skillDir,
|
|
203
|
+
name,
|
|
204
|
+
action: overwrite ? "overwritten" : "created",
|
|
205
|
+
bytes: bytesTotal,
|
|
206
|
+
note: "Catalog reloads on the NEXT turn — the new skill is not visible " +
|
|
207
|
+
"in the current turn's <available_skills> list. Call skill_view " +
|
|
208
|
+
"after the next user turn to verify activation.",
|
|
209
|
+
};
|
|
210
|
+
if (writtenFiles.length > 0)
|
|
211
|
+
result.files = writtenFiles;
|
|
212
|
+
if (warnings.length > 0)
|
|
213
|
+
result.warnings = warnings;
|
|
214
|
+
logger.info({
|
|
215
|
+
name,
|
|
216
|
+
path: skillFile,
|
|
217
|
+
action: result.action,
|
|
218
|
+
bytes: bytesTotal,
|
|
219
|
+
fileCount: writtenFiles.length,
|
|
220
|
+
warningCount: warnings.length,
|
|
221
|
+
}, "skill_write: skill manifest + assets persisted");
|
|
222
|
+
return JSON.stringify(result);
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Validate a relative path supplied via `files`. Returns an error string on
|
|
228
|
+
* failure, or `null` when the path is safe to use as `join(skillDir, rel)`.
|
|
229
|
+
*
|
|
230
|
+
* Rejected:
|
|
231
|
+
* - absolute paths (any drive prefix or leading `/`)
|
|
232
|
+
* - paths that normalize outside the skill folder (`..` escapes)
|
|
233
|
+
* - paths that resolve to "." (i.e. the skill folder itself)
|
|
234
|
+
* - paths with backslashes (force forward-slash to keep cross-platform
|
|
235
|
+
* behavior predictable; Windows hosts will translate on `join`)
|
|
236
|
+
*
|
|
237
|
+
* Note: we don't validate against a per-file regex — the model can write
|
|
238
|
+
* any filename the host filesystem accepts, including dotfiles. Only the
|
|
239
|
+
* traversal vector is the safety boundary.
|
|
240
|
+
*/
|
|
241
|
+
function validateRelativePath(rel) {
|
|
242
|
+
if (rel.includes("\\")) {
|
|
243
|
+
return `path '${rel}' must use forward slashes, not backslashes`;
|
|
244
|
+
}
|
|
245
|
+
if (isAbsolute(rel)) {
|
|
246
|
+
return `path '${rel}' must be relative to the skill folder, not absolute`;
|
|
247
|
+
}
|
|
248
|
+
const normalized = normalize(rel);
|
|
249
|
+
if (normalized === "." || normalized === "") {
|
|
250
|
+
return `path '${rel}' resolves to the skill folder itself`;
|
|
251
|
+
}
|
|
252
|
+
// The reliable cross-platform escape check: a `..` segment anywhere.
|
|
253
|
+
const segments = normalized.split(/[/\\]/);
|
|
254
|
+
if (segments.includes("..")) {
|
|
255
|
+
return `path '${rel}' escapes the skill folder via '..'`;
|
|
256
|
+
}
|
|
257
|
+
// Defensive: ensure relative() from "." still keeps us inside.
|
|
258
|
+
const back = relative(".", normalized);
|
|
259
|
+
if (back.startsWith("..")) {
|
|
260
|
+
return `path '${rel}' escapes the skill folder via '..'`;
|
|
261
|
+
}
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=skill_write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill_write.js","sourceRoot":"","sources":["../../../src/tools/builtin/skill_write.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { TaskStore } from "../../state/tasks.js";
|
|
2
|
+
import type { ToolHandler } from "../../tools/registry.js";
|
|
3
|
+
/**
|
|
4
|
+
* `TaskCreate` / `TaskUpdate` / `TaskList` / `TaskGet` builtins — the
|
|
5
|
+
* granular replacement for the v0.1.x `todo_write` snapshot-replace tool.
|
|
6
|
+
*
|
|
7
|
+
* Each tool covers a single CRUD verb so the model can mutate one task per
|
|
8
|
+
* call without round-tripping the whole list. The store enforces a single
|
|
9
|
+
* `in_progress` task at a time (TaskUpdate flips any prior in_progress to
|
|
10
|
+
* pending and surfaces the demoted id), and dependency edges
|
|
11
|
+
* (`blockedBy` / `blocks`) are kept bidirectionally consistent.
|
|
12
|
+
*
|
|
13
|
+
* The read side stays cheap: every per-turn `<system-reminder>` already
|
|
14
|
+
* renders the current list. `TaskList` exists for explicit refresh after
|
|
15
|
+
* a long stretch of tool work (sub-agent delegation, batch updates), and
|
|
16
|
+
* `TaskGet` returns the full entry — including description, owner, and
|
|
17
|
+
* metadata — which the reminder summary intentionally omits.
|
|
18
|
+
*
|
|
19
|
+
* Side-effecting tools (`TaskCreate`, `TaskUpdate`) are `parallelSafe: false`
|
|
20
|
+
* because two concurrent writes would race on the in-progress sweep and
|
|
21
|
+
* dependency-edge maintenance. Reads (`TaskList`, `TaskGet`) are safe to
|
|
22
|
+
* parallelise — they snapshot the in-memory map.
|
|
23
|
+
*/
|
|
24
|
+
export interface TaskToolsOptions {
|
|
25
|
+
/** Required. The per-session store. Built by maestroProvider via
|
|
26
|
+
* `getTaskStore(sessionId)` so the same instance is shared across
|
|
27
|
+
* every tool call in this turn. */
|
|
28
|
+
store: TaskStore;
|
|
29
|
+
}
|
|
30
|
+
export declare function createTaskCreateTool(opts: TaskToolsOptions): ToolHandler;
|
|
31
|
+
export declare function createTaskUpdateTool(opts: TaskToolsOptions): ToolHandler;
|
|
32
|
+
export declare function createTaskListTool(opts: TaskToolsOptions): ToolHandler;
|
|
33
|
+
export declare function createTaskGetTool(opts: TaskToolsOptions): ToolHandler;
|
|
34
|
+
//# sourceMappingURL=tasks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,SAAS,EAEV,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,gBAAgB;IAC/B;;wCAEoC;IACpC,KAAK,EAAE,SAAS,CAAC;CAClB;AA+BD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,CAgExE;AAQD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,CAsGxE;AAMD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,CAiCtE;AAMD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,CAiCrE"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
function summarize(t) {
|
|
2
|
+
const out = {
|
|
3
|
+
id: t.id,
|
|
4
|
+
subject: t.subject,
|
|
5
|
+
status: t.status,
|
|
6
|
+
blockedBy: t.blockedBy,
|
|
7
|
+
blocks: t.blocks,
|
|
8
|
+
};
|
|
9
|
+
if (t.activeForm)
|
|
10
|
+
out.activeForm = t.activeForm;
|
|
11
|
+
if (t.owner)
|
|
12
|
+
out.owner = t.owner;
|
|
13
|
+
return out;
|
|
14
|
+
}
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// TaskCreate
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
export function createTaskCreateTool(opts) {
|
|
19
|
+
const { store } = opts;
|
|
20
|
+
return {
|
|
21
|
+
parallelSafe: false,
|
|
22
|
+
schema: {
|
|
23
|
+
name: "TaskCreate",
|
|
24
|
+
description: "Create a single new task. Returns the freshly assigned id (numeric " +
|
|
25
|
+
"string like '1', '2', ...). The task starts in 'pending' status — " +
|
|
26
|
+
"transition it with TaskUpdate. Set up dependencies via TaskUpdate's " +
|
|
27
|
+
"`addBlockedBy` / `addBlocks` fields after the dependent tasks exist.",
|
|
28
|
+
input_schema: {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
subject: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: "Imperative title — what needs to be done. e.g. 'Read spec'.",
|
|
34
|
+
},
|
|
35
|
+
description: {
|
|
36
|
+
type: "string",
|
|
37
|
+
description: "Optional longer detail or acceptance criteria. Use this for context " +
|
|
38
|
+
"the subject line is too short to carry.",
|
|
39
|
+
},
|
|
40
|
+
activeForm: {
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "Optional present-continuous form for spinner/status display " +
|
|
43
|
+
"('Reading spec' vs the imperative 'Read spec'). Hosts that " +
|
|
44
|
+
"render a live task list show this while status is in_progress.",
|
|
45
|
+
},
|
|
46
|
+
owner: {
|
|
47
|
+
type: "string",
|
|
48
|
+
description: "Optional owner / agent name. Useful when delegating to sub-agents " +
|
|
49
|
+
"via the Agent tool so a glance at TaskList shows who's responsible.",
|
|
50
|
+
},
|
|
51
|
+
metadata: {
|
|
52
|
+
type: "object",
|
|
53
|
+
description: "Arbitrary host-controlled bag, round-tripped verbatim. The SDK " +
|
|
54
|
+
"neither reads nor interprets the shape.",
|
|
55
|
+
additionalProperties: true,
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
required: ["subject"],
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
async execute(input) {
|
|
62
|
+
const subject = typeof input.subject === "string" ? input.subject.trim() : "";
|
|
63
|
+
if (!subject) {
|
|
64
|
+
return JSON.stringify({ error: "TaskCreate: 'subject' must be a non-empty string" });
|
|
65
|
+
}
|
|
66
|
+
const create = { subject };
|
|
67
|
+
if (typeof input.description === "string")
|
|
68
|
+
create.description = input.description;
|
|
69
|
+
if (typeof input.activeForm === "string")
|
|
70
|
+
create.activeForm = input.activeForm;
|
|
71
|
+
if (typeof input.owner === "string")
|
|
72
|
+
create.owner = input.owner;
|
|
73
|
+
if (input.metadata && typeof input.metadata === "object" && !Array.isArray(input.metadata)) {
|
|
74
|
+
create.metadata = input.metadata;
|
|
75
|
+
}
|
|
76
|
+
const entry = store.create(create);
|
|
77
|
+
return JSON.stringify({ ok: true, id: entry.id, subject: entry.subject });
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// TaskUpdate
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
const VALID_STATUSES = new Set(["pending", "in_progress", "completed", "deleted"]);
|
|
85
|
+
export function createTaskUpdateTool(opts) {
|
|
86
|
+
const { store } = opts;
|
|
87
|
+
return {
|
|
88
|
+
parallelSafe: false,
|
|
89
|
+
schema: {
|
|
90
|
+
name: "TaskUpdate",
|
|
91
|
+
description: "Update a single existing task by id. Any subset of fields can change " +
|
|
92
|
+
"in one call (status, subject, description, activeForm, owner, " +
|
|
93
|
+
"metadata, dependency edges). Status transitions:\n" +
|
|
94
|
+
" - → 'in_progress': the store demotes any other in_progress task to " +
|
|
95
|
+
"'pending' (1-in-progress invariant) and reports the demoted id back.\n" +
|
|
96
|
+
" - → 'deleted': permanent. The task disappears from TaskList output " +
|
|
97
|
+
"but stays on disk for TaskGet forensics.\n" +
|
|
98
|
+
"Dependency edges are bidirectional — addBlockedBy: ['3'] on task 5 " +
|
|
99
|
+
"also adds '5' to task 3's blocks list. Self-loops and unknown ids " +
|
|
100
|
+
"are silently ignored.",
|
|
101
|
+
input_schema: {
|
|
102
|
+
type: "object",
|
|
103
|
+
properties: {
|
|
104
|
+
taskId: {
|
|
105
|
+
type: "string",
|
|
106
|
+
description: "Id of the task to mutate (as returned by TaskCreate).",
|
|
107
|
+
},
|
|
108
|
+
status: {
|
|
109
|
+
type: "string",
|
|
110
|
+
enum: ["pending", "in_progress", "completed", "deleted"],
|
|
111
|
+
description: "New status. Setting in_progress triggers the 1-in-progress sweep; " +
|
|
112
|
+
"setting deleted is permanent.",
|
|
113
|
+
},
|
|
114
|
+
subject: { type: "string", description: "New imperative title." },
|
|
115
|
+
description: { type: "string", description: "New long-form detail." },
|
|
116
|
+
activeForm: { type: "string", description: "New spinner / status display form." },
|
|
117
|
+
owner: { type: "string", description: "New owner / agent name." },
|
|
118
|
+
metadata: {
|
|
119
|
+
type: "object",
|
|
120
|
+
description: "New metadata bag (overwrites previous).",
|
|
121
|
+
additionalProperties: true,
|
|
122
|
+
},
|
|
123
|
+
addBlockedBy: {
|
|
124
|
+
type: "array",
|
|
125
|
+
items: { type: "string" },
|
|
126
|
+
description: "Task ids that must complete before this one can start. Edges " +
|
|
127
|
+
"are added bidirectionally on the blockers' `blocks` lists.",
|
|
128
|
+
},
|
|
129
|
+
addBlocks: {
|
|
130
|
+
type: "array",
|
|
131
|
+
items: { type: "string" },
|
|
132
|
+
description: "Task ids that this task blocks. Edges are added bidirectionally " +
|
|
133
|
+
"on the blocked tasks' `blockedBy` lists.",
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
required: ["taskId"],
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
async execute(input) {
|
|
140
|
+
const taskId = typeof input.taskId === "string" ? input.taskId.trim() : "";
|
|
141
|
+
if (!taskId) {
|
|
142
|
+
return JSON.stringify({ error: "TaskUpdate: 'taskId' must be a non-empty string" });
|
|
143
|
+
}
|
|
144
|
+
if (!store.get(taskId)) {
|
|
145
|
+
return JSON.stringify({ error: `TaskUpdate: no task with id '${taskId}'` });
|
|
146
|
+
}
|
|
147
|
+
const update = {};
|
|
148
|
+
if (typeof input.status === "string") {
|
|
149
|
+
if (!VALID_STATUSES.has(input.status)) {
|
|
150
|
+
return JSON.stringify({
|
|
151
|
+
error: `TaskUpdate: invalid status '${input.status}' — must be one of ` +
|
|
152
|
+
"pending, in_progress, completed, deleted",
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
update.status = input.status;
|
|
156
|
+
}
|
|
157
|
+
if (typeof input.subject === "string" && input.subject.trim()) {
|
|
158
|
+
update.subject = input.subject;
|
|
159
|
+
}
|
|
160
|
+
if (typeof input.description === "string")
|
|
161
|
+
update.description = input.description;
|
|
162
|
+
if (typeof input.activeForm === "string")
|
|
163
|
+
update.activeForm = input.activeForm;
|
|
164
|
+
if (typeof input.owner === "string")
|
|
165
|
+
update.owner = input.owner;
|
|
166
|
+
if (input.metadata && typeof input.metadata === "object" && !Array.isArray(input.metadata)) {
|
|
167
|
+
update.metadata = input.metadata;
|
|
168
|
+
}
|
|
169
|
+
if (Array.isArray(input.addBlockedBy)) {
|
|
170
|
+
update.addBlockedBy = input.addBlockedBy.filter((x) => typeof x === "string");
|
|
171
|
+
}
|
|
172
|
+
if (Array.isArray(input.addBlocks)) {
|
|
173
|
+
update.addBlocks = input.addBlocks.filter((x) => typeof x === "string");
|
|
174
|
+
}
|
|
175
|
+
const result = store.update(taskId, update);
|
|
176
|
+
const payload = {
|
|
177
|
+
ok: true,
|
|
178
|
+
task: summarize(result.task),
|
|
179
|
+
};
|
|
180
|
+
if (result.demotedId)
|
|
181
|
+
payload.demotedId = result.demotedId;
|
|
182
|
+
return JSON.stringify(payload);
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
// ---------------------------------------------------------------------------
|
|
187
|
+
// TaskList
|
|
188
|
+
// ---------------------------------------------------------------------------
|
|
189
|
+
export function createTaskListTool(opts) {
|
|
190
|
+
const { store } = opts;
|
|
191
|
+
return {
|
|
192
|
+
parallelSafe: true,
|
|
193
|
+
schema: {
|
|
194
|
+
name: "TaskList",
|
|
195
|
+
description: "Return all non-deleted tasks (compact form: id, subject, status, " +
|
|
196
|
+
"activeForm, owner, blockedBy, blocks). The per-turn system reminder " +
|
|
197
|
+
"already carries a summary — use TaskList when you need the full " +
|
|
198
|
+
"state programmatically (e.g. after a stretch of TaskUpdate calls " +
|
|
199
|
+
"or sub-agent delegation). Pass `includeDeleted: true` to also see " +
|
|
200
|
+
"tasks the model marked deleted earlier.",
|
|
201
|
+
input_schema: {
|
|
202
|
+
type: "object",
|
|
203
|
+
properties: {
|
|
204
|
+
includeDeleted: {
|
|
205
|
+
type: "boolean",
|
|
206
|
+
description: "When true, include tasks with status='deleted'. Default false.",
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
async execute(input) {
|
|
212
|
+
const includeDeleted = input.includeDeleted === true;
|
|
213
|
+
const list = includeDeleted ? store.listAll() : store.list();
|
|
214
|
+
return JSON.stringify({
|
|
215
|
+
ok: true,
|
|
216
|
+
count: list.length,
|
|
217
|
+
tasks: list.map(summarize),
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
// ---------------------------------------------------------------------------
|
|
223
|
+
// TaskGet
|
|
224
|
+
// ---------------------------------------------------------------------------
|
|
225
|
+
export function createTaskGetTool(opts) {
|
|
226
|
+
const { store } = opts;
|
|
227
|
+
return {
|
|
228
|
+
parallelSafe: true,
|
|
229
|
+
schema: {
|
|
230
|
+
name: "TaskGet",
|
|
231
|
+
description: "Fetch the full entry for a single task (every field including " +
|
|
232
|
+
"description, metadata, createdAt/updatedAt timestamps). Use this " +
|
|
233
|
+
"when the compact TaskList summary doesn't carry enough detail.",
|
|
234
|
+
input_schema: {
|
|
235
|
+
type: "object",
|
|
236
|
+
properties: {
|
|
237
|
+
taskId: {
|
|
238
|
+
type: "string",
|
|
239
|
+
description: "Id of the task to fetch.",
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
required: ["taskId"],
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
async execute(input) {
|
|
246
|
+
const taskId = typeof input.taskId === "string" ? input.taskId.trim() : "";
|
|
247
|
+
if (!taskId) {
|
|
248
|
+
return JSON.stringify({ error: "TaskGet: 'taskId' must be a non-empty string" });
|
|
249
|
+
}
|
|
250
|
+
const task = store.get(taskId);
|
|
251
|
+
if (!task) {
|
|
252
|
+
return JSON.stringify({ error: `TaskGet: no task with id '${taskId}'` });
|
|
253
|
+
}
|
|
254
|
+
return JSON.stringify({ ok: true, task });
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../../src/tools/builtin/tasks.ts"],"names":[],"mappings":"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"}
|