maestro-agent-sdk 0.1.4 → 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 +197 -10
- package/dist/agents/contracts.d.ts +10 -0
- package/dist/agents/contracts.d.ts.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -5
- package/dist/index.js.map +1 -1
- package/dist/memory/reminder.d.ts +9 -9
- package/dist/memory/reminder.d.ts.map +1 -1
- package/dist/memory/reminder.js +21 -15
- package/dist/memory/reminder.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 +136 -22
- 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.js +3 -3
- 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/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/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/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
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export type TaskStatus = "pending" | "in_progress" | "completed" | "deleted";
|
|
2
|
+
export interface TaskEntry {
|
|
3
|
+
/** Auto-assigned numeric string ("1", "2", ...). Stable across re-saves. */
|
|
4
|
+
id: string;
|
|
5
|
+
/** Imperative title — what needs to be done. ("Read spec", "Implement loader"). */
|
|
6
|
+
subject: string;
|
|
7
|
+
/** Optional longer detail / acceptance criteria. */
|
|
8
|
+
description?: string;
|
|
9
|
+
/** Optional present-continuous form for spinner / status display
|
|
10
|
+
* ("Reading spec" vs the imperative "Read spec"). */
|
|
11
|
+
activeForm?: string;
|
|
12
|
+
status: TaskStatus;
|
|
13
|
+
/** Task ids this task depends on. Cannot start until each is `completed`. */
|
|
14
|
+
blockedBy: string[];
|
|
15
|
+
/** Task ids that depend on this one. Maintained in sync with `blockedBy`
|
|
16
|
+
* on the other side — never edit directly. */
|
|
17
|
+
blocks: string[];
|
|
18
|
+
/** Optional owner / agent name. Surfaces in TaskList for multi-agent runs. */
|
|
19
|
+
owner?: string;
|
|
20
|
+
/** Arbitrary host-controlled bag. Round-tripped verbatim. */
|
|
21
|
+
metadata?: Record<string, unknown>;
|
|
22
|
+
createdAt: string;
|
|
23
|
+
updatedAt: string;
|
|
24
|
+
}
|
|
25
|
+
export interface CreateInput {
|
|
26
|
+
subject: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
activeForm?: string;
|
|
29
|
+
owner?: string;
|
|
30
|
+
metadata?: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
export interface UpdateInput {
|
|
33
|
+
status?: TaskStatus;
|
|
34
|
+
subject?: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
activeForm?: string;
|
|
37
|
+
owner?: string;
|
|
38
|
+
metadata?: Record<string, unknown>;
|
|
39
|
+
/** Add these task ids to this task's `blockedBy` list (and update the
|
|
40
|
+
* other side's `blocks`). Unknown ids are silently ignored. */
|
|
41
|
+
addBlockedBy?: string[];
|
|
42
|
+
/** Add these task ids to this task's `blocks` list (and update the
|
|
43
|
+
* other side's `blockedBy`). */
|
|
44
|
+
addBlocks?: string[];
|
|
45
|
+
}
|
|
46
|
+
export interface UpdateResult {
|
|
47
|
+
task: TaskEntry;
|
|
48
|
+
/** When the update flipped an existing in_progress task to pending to
|
|
49
|
+
* enforce the 1-in-progress invariant, this is the demoted id. */
|
|
50
|
+
demotedId?: string;
|
|
51
|
+
}
|
|
52
|
+
export declare class TaskStore {
|
|
53
|
+
private readonly path;
|
|
54
|
+
private tasks;
|
|
55
|
+
private nextCounter;
|
|
56
|
+
constructor(path: string);
|
|
57
|
+
/** Snapshot of every non-deleted task in insertion order. Caller must not
|
|
58
|
+
* mutate the array. Use `listAll()` to include deleted entries. */
|
|
59
|
+
list(): readonly TaskEntry[];
|
|
60
|
+
/** Like `list()` but includes deleted entries — for forensic queries. */
|
|
61
|
+
listAll(): readonly TaskEntry[];
|
|
62
|
+
/** Look up by id. Returns null if no such task exists. */
|
|
63
|
+
get(id: string): TaskEntry | null;
|
|
64
|
+
/** True when the live list (non-deleted) is empty. */
|
|
65
|
+
isEmpty(): boolean;
|
|
66
|
+
/** Create a new task. Returns the freshly persisted entry. */
|
|
67
|
+
create(input: CreateInput): TaskEntry;
|
|
68
|
+
/**
|
|
69
|
+
* Update a task. Throws if no such task exists.
|
|
70
|
+
*
|
|
71
|
+
* Status transitions:
|
|
72
|
+
* - Anything → `in_progress` runs the 1-in-progress sweep, demoting
|
|
73
|
+
* any previously-in_progress task to `pending` and returning its id.
|
|
74
|
+
* - Anything → `deleted` is permanent; the task stays on disk for
|
|
75
|
+
* forensic queries but disappears from `list()`.
|
|
76
|
+
*
|
|
77
|
+
* Dependency edges are bidirectional: setting `addBlockedBy: ["3"]` on
|
|
78
|
+
* task 5 also pushes "5" onto task 3's `blocks` array. Self-loops and
|
|
79
|
+
* unknown ids are silently ignored.
|
|
80
|
+
*/
|
|
81
|
+
update(id: string, input: UpdateInput): UpdateResult;
|
|
82
|
+
/** Drop the on-disk file (both new and legacy). Called by
|
|
83
|
+
* `deleteMaestroSession` via `dropTaskStore`. */
|
|
84
|
+
unlinkFile(): void;
|
|
85
|
+
/** Test-only: snapshot the path the store is backed by. */
|
|
86
|
+
__path(): string;
|
|
87
|
+
private nextId;
|
|
88
|
+
/** Path of the legacy `.todos.json` file for this session. */
|
|
89
|
+
private legacyPath;
|
|
90
|
+
private hydrate;
|
|
91
|
+
private hydrateFromV2;
|
|
92
|
+
private hydrateFromLegacy;
|
|
93
|
+
/** Recover the counter from existing IDs when the file lacked the field. */
|
|
94
|
+
private deriveCounter;
|
|
95
|
+
private persist;
|
|
96
|
+
}
|
|
97
|
+
/** Resolve the absolute tasks-file path for a session. Mirrors
|
|
98
|
+
* `maestroSessionPath` but with `.tasks.json` instead of `.jsonl`. */
|
|
99
|
+
export declare function tasksPathFor(sessionId: string): string;
|
|
100
|
+
export declare function getTaskStore(sessionId: string): TaskStore;
|
|
101
|
+
/** Drop a session's store + unlink its on-disk file (both new and legacy). */
|
|
102
|
+
export declare function dropTaskStore(sessionId: string): void;
|
|
103
|
+
/** Test-only. Reset every store. */
|
|
104
|
+
export declare function __resetAllStores(): void;
|
|
105
|
+
/** Test-only. Count of currently-tracked sessions. */
|
|
106
|
+
export declare function __storeCount(): number;
|
|
107
|
+
//# sourceMappingURL=tasks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/state/tasks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { logger } from "../platform/logger.js";
|
|
5
|
+
/**
|
|
6
|
+
* Per-session task store backing the `TaskCreate` / `TaskUpdate` / `TaskList`
|
|
7
|
+
* / `TaskGet` builtin family.
|
|
8
|
+
*
|
|
9
|
+
* The Task* family replaced the v0.1.x `TodoWrite` snapshot-replace model
|
|
10
|
+
* with granular CRUD: each call mutates a single task (or queries the
|
|
11
|
+
* list) instead of overwriting the whole snapshot. The motivation is
|
|
12
|
+
* forward-compat with richer surfaces — task dependencies (`blocks` /
|
|
13
|
+
* `blockedBy`), owners (sub-agent assignment), per-task metadata, and
|
|
14
|
+
* long-running plans where round-tripping the entire list every turn is
|
|
15
|
+
* wasteful.
|
|
16
|
+
*
|
|
17
|
+
* Persistence: one JSON file at `~/.maestro/sessions/<sid>.tasks.json` —
|
|
18
|
+
* a snapshot of `{ version, nextCounter, tasks }`, atomically written.
|
|
19
|
+
* Schema version is stamped so future migrations stay cheap.
|
|
20
|
+
*
|
|
21
|
+
* Backward compatibility: when no `.tasks.json` exists but a legacy
|
|
22
|
+
* `.todos.json` is present (written by the pre-Task SDK), we auto-migrate
|
|
23
|
+
* on first hydrate — old todos become tasks with `content` → `subject`
|
|
24
|
+
* and the `task-N` prefix stripped to the bare counter. No deps are
|
|
25
|
+
* synthesized; the migration is lossless on the fields that survived the
|
|
26
|
+
* model. The legacy file is left in place for one release as a safety
|
|
27
|
+
* net; `dropTaskStore` unlinks both.
|
|
28
|
+
*
|
|
29
|
+
* Lifecycle:
|
|
30
|
+
* - `getTaskStore(sid)` lazy-creates the store and hydrates from disk
|
|
31
|
+
* (preferring `.tasks.json`, falling back to `.todos.json`).
|
|
32
|
+
* - `dropTaskStore(sid)` is called from `deleteMaestroSession` and
|
|
33
|
+
* `cleanupStaleMaestroSessions` so the module-level map can't outlive
|
|
34
|
+
* its sessions.
|
|
35
|
+
*
|
|
36
|
+
* Invariants enforced inside the store:
|
|
37
|
+
* - IDs are auto-assigned as numeric strings ("1", "2", "3"). Numeric
|
|
38
|
+
* ids are short, easy to refer back to in prose, and match Claude
|
|
39
|
+
* Code's TaskCreate return shape.
|
|
40
|
+
* - At most one task is `in_progress` at a time. `markInProgress`
|
|
41
|
+
* flips any prior in_progress entry back to `pending` and returns
|
|
42
|
+
* the demoted id so the caller can surface it.
|
|
43
|
+
* - `status: "deleted"` is permanent — TaskList / TaskGet filter
|
|
44
|
+
* deleted entries by default. The on-disk record stays so a future
|
|
45
|
+
* TaskGet by id can still surface "this task was deleted at T".
|
|
46
|
+
* - Dependency edges are bidirectional: setting `addBlockedBy: ["3"]`
|
|
47
|
+
* on task 5 also adds "5" to task 3's `blocks` array. The store
|
|
48
|
+
* enforces consistency on every mutation.
|
|
49
|
+
*/
|
|
50
|
+
/** Mirror of `maestroSessionsDir()` from session-store.ts — inlined here to
|
|
51
|
+
* avoid a circular import (session-store.ts needs to call `dropTaskStore`
|
|
52
|
+
* for cleanup). Two single-line copies are cheaper than extracting a shared
|
|
53
|
+
* util file for one path. */
|
|
54
|
+
function sessionsDir() {
|
|
55
|
+
return join(homedir(), ".maestro", "sessions");
|
|
56
|
+
}
|
|
57
|
+
export class TaskStore {
|
|
58
|
+
path;
|
|
59
|
+
tasks = new Map();
|
|
60
|
+
nextCounter = 1;
|
|
61
|
+
constructor(path) {
|
|
62
|
+
this.path = path;
|
|
63
|
+
this.hydrate();
|
|
64
|
+
}
|
|
65
|
+
/** Snapshot of every non-deleted task in insertion order. Caller must not
|
|
66
|
+
* mutate the array. Use `listAll()` to include deleted entries. */
|
|
67
|
+
list() {
|
|
68
|
+
const out = [];
|
|
69
|
+
for (const t of this.tasks.values()) {
|
|
70
|
+
if (t.status !== "deleted")
|
|
71
|
+
out.push(t);
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
/** Like `list()` but includes deleted entries — for forensic queries. */
|
|
76
|
+
listAll() {
|
|
77
|
+
return [...this.tasks.values()];
|
|
78
|
+
}
|
|
79
|
+
/** Look up by id. Returns null if no such task exists. */
|
|
80
|
+
get(id) {
|
|
81
|
+
return this.tasks.get(id) ?? null;
|
|
82
|
+
}
|
|
83
|
+
/** True when the live list (non-deleted) is empty. */
|
|
84
|
+
isEmpty() {
|
|
85
|
+
for (const t of this.tasks.values()) {
|
|
86
|
+
if (t.status !== "deleted")
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
/** Create a new task. Returns the freshly persisted entry. */
|
|
92
|
+
create(input) {
|
|
93
|
+
const now = new Date().toISOString();
|
|
94
|
+
const id = this.nextId();
|
|
95
|
+
const entry = {
|
|
96
|
+
id,
|
|
97
|
+
subject: input.subject,
|
|
98
|
+
status: "pending",
|
|
99
|
+
blockedBy: [],
|
|
100
|
+
blocks: [],
|
|
101
|
+
createdAt: now,
|
|
102
|
+
updatedAt: now,
|
|
103
|
+
};
|
|
104
|
+
if (input.description !== undefined)
|
|
105
|
+
entry.description = input.description;
|
|
106
|
+
if (input.activeForm !== undefined)
|
|
107
|
+
entry.activeForm = input.activeForm;
|
|
108
|
+
if (input.owner !== undefined)
|
|
109
|
+
entry.owner = input.owner;
|
|
110
|
+
if (input.metadata !== undefined)
|
|
111
|
+
entry.metadata = input.metadata;
|
|
112
|
+
this.tasks.set(id, entry);
|
|
113
|
+
this.persist();
|
|
114
|
+
return entry;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Update a task. Throws if no such task exists.
|
|
118
|
+
*
|
|
119
|
+
* Status transitions:
|
|
120
|
+
* - Anything → `in_progress` runs the 1-in-progress sweep, demoting
|
|
121
|
+
* any previously-in_progress task to `pending` and returning its id.
|
|
122
|
+
* - Anything → `deleted` is permanent; the task stays on disk for
|
|
123
|
+
* forensic queries but disappears from `list()`.
|
|
124
|
+
*
|
|
125
|
+
* Dependency edges are bidirectional: setting `addBlockedBy: ["3"]` on
|
|
126
|
+
* task 5 also pushes "5" onto task 3's `blocks` array. Self-loops and
|
|
127
|
+
* unknown ids are silently ignored.
|
|
128
|
+
*/
|
|
129
|
+
update(id, input) {
|
|
130
|
+
const entry = this.tasks.get(id);
|
|
131
|
+
if (!entry) {
|
|
132
|
+
throw new Error(`TaskStore.update: no task with id '${id}'`);
|
|
133
|
+
}
|
|
134
|
+
const now = new Date().toISOString();
|
|
135
|
+
let demotedId;
|
|
136
|
+
if (input.status !== undefined && input.status !== entry.status) {
|
|
137
|
+
if (input.status === "in_progress") {
|
|
138
|
+
// Demote any other in_progress task first.
|
|
139
|
+
for (const other of this.tasks.values()) {
|
|
140
|
+
if (other.id !== id && other.status === "in_progress") {
|
|
141
|
+
other.status = "pending";
|
|
142
|
+
other.updatedAt = now;
|
|
143
|
+
demotedId = other.id;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
entry.status = input.status;
|
|
148
|
+
}
|
|
149
|
+
if (input.subject !== undefined)
|
|
150
|
+
entry.subject = input.subject;
|
|
151
|
+
if (input.description !== undefined)
|
|
152
|
+
entry.description = input.description;
|
|
153
|
+
if (input.activeForm !== undefined)
|
|
154
|
+
entry.activeForm = input.activeForm;
|
|
155
|
+
if (input.owner !== undefined)
|
|
156
|
+
entry.owner = input.owner;
|
|
157
|
+
if (input.metadata !== undefined)
|
|
158
|
+
entry.metadata = input.metadata;
|
|
159
|
+
if (input.addBlockedBy && input.addBlockedBy.length > 0) {
|
|
160
|
+
for (const blockerId of input.addBlockedBy) {
|
|
161
|
+
if (blockerId === id)
|
|
162
|
+
continue;
|
|
163
|
+
const blocker = this.tasks.get(blockerId);
|
|
164
|
+
if (!blocker)
|
|
165
|
+
continue;
|
|
166
|
+
if (!entry.blockedBy.includes(blockerId))
|
|
167
|
+
entry.blockedBy.push(blockerId);
|
|
168
|
+
if (!blocker.blocks.includes(id))
|
|
169
|
+
blocker.blocks.push(id);
|
|
170
|
+
blocker.updatedAt = now;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (input.addBlocks && input.addBlocks.length > 0) {
|
|
174
|
+
for (const blockedId of input.addBlocks) {
|
|
175
|
+
if (blockedId === id)
|
|
176
|
+
continue;
|
|
177
|
+
const blocked = this.tasks.get(blockedId);
|
|
178
|
+
if (!blocked)
|
|
179
|
+
continue;
|
|
180
|
+
if (!entry.blocks.includes(blockedId))
|
|
181
|
+
entry.blocks.push(blockedId);
|
|
182
|
+
if (!blocked.blockedBy.includes(id))
|
|
183
|
+
blocked.blockedBy.push(id);
|
|
184
|
+
blocked.updatedAt = now;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
entry.updatedAt = now;
|
|
188
|
+
this.persist();
|
|
189
|
+
return demotedId !== undefined ? { task: entry, demotedId } : { task: entry };
|
|
190
|
+
}
|
|
191
|
+
/** Drop the on-disk file (both new and legacy). Called by
|
|
192
|
+
* `deleteMaestroSession` via `dropTaskStore`. */
|
|
193
|
+
unlinkFile() {
|
|
194
|
+
for (const p of [this.path, this.legacyPath()]) {
|
|
195
|
+
try {
|
|
196
|
+
unlinkSync(p);
|
|
197
|
+
}
|
|
198
|
+
catch (e) {
|
|
199
|
+
if (e?.code !== "ENOENT") {
|
|
200
|
+
logger.warn({ err: e, path: p }, "TaskStore.unlinkFile failed");
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/** Test-only: snapshot the path the store is backed by. */
|
|
206
|
+
__path() {
|
|
207
|
+
return this.path;
|
|
208
|
+
}
|
|
209
|
+
// --- internals ---------------------------------------------------------
|
|
210
|
+
nextId() {
|
|
211
|
+
const id = String(this.nextCounter);
|
|
212
|
+
this.nextCounter++;
|
|
213
|
+
return id;
|
|
214
|
+
}
|
|
215
|
+
/** Path of the legacy `.todos.json` file for this session. */
|
|
216
|
+
legacyPath() {
|
|
217
|
+
return this.path.replace(/\.tasks\.json$/, ".todos.json");
|
|
218
|
+
}
|
|
219
|
+
hydrate() {
|
|
220
|
+
if (existsSync(this.path)) {
|
|
221
|
+
this.hydrateFromV2();
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const legacy = this.legacyPath();
|
|
225
|
+
if (existsSync(legacy)) {
|
|
226
|
+
this.hydrateFromLegacy(legacy);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
// Fresh session — nothing to load.
|
|
230
|
+
}
|
|
231
|
+
hydrateFromV2() {
|
|
232
|
+
try {
|
|
233
|
+
const raw = readFileSync(this.path, "utf8");
|
|
234
|
+
const parsed = JSON.parse(raw);
|
|
235
|
+
if (parsed.version !== 2 || !Array.isArray(parsed.tasks)) {
|
|
236
|
+
logger.warn({ path: this.path }, "TaskStore.hydrate: unsupported schema, ignoring");
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
for (const t of parsed.tasks) {
|
|
240
|
+
if (isWellFormedEntry(t))
|
|
241
|
+
this.tasks.set(t.id, t);
|
|
242
|
+
}
|
|
243
|
+
this.nextCounter = Math.max(1, parsed.nextCounter ?? this.deriveCounter());
|
|
244
|
+
}
|
|
245
|
+
catch (e) {
|
|
246
|
+
logger.warn({ err: e, path: this.path }, "TaskStore.hydrate: parse failed, starting empty");
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
hydrateFromLegacy(legacyPath) {
|
|
250
|
+
try {
|
|
251
|
+
const raw = readFileSync(legacyPath, "utf8");
|
|
252
|
+
const parsed = JSON.parse(raw);
|
|
253
|
+
if (parsed.version !== 1 || !Array.isArray(parsed.todos)) {
|
|
254
|
+
logger.warn({ path: legacyPath }, "TaskStore.hydrate: legacy schema malformed, ignoring");
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const now = new Date().toISOString();
|
|
258
|
+
let maxNumericId = 0;
|
|
259
|
+
for (const old of parsed.todos) {
|
|
260
|
+
if (typeof old.id !== "string" || typeof old.content !== "string")
|
|
261
|
+
continue;
|
|
262
|
+
const status = old.status === "pending" || old.status === "in_progress" || old.status === "completed"
|
|
263
|
+
? old.status
|
|
264
|
+
: "pending";
|
|
265
|
+
// Strip "task-" prefix if present so the migrated id is just the number.
|
|
266
|
+
const numericId = old.id.replace(/^task-/, "");
|
|
267
|
+
const n = Number.parseInt(numericId, 10);
|
|
268
|
+
if (Number.isFinite(n) && n > maxNumericId)
|
|
269
|
+
maxNumericId = n;
|
|
270
|
+
const migrated = {
|
|
271
|
+
id: numericId || this.nextId(),
|
|
272
|
+
subject: old.content,
|
|
273
|
+
status,
|
|
274
|
+
blockedBy: [],
|
|
275
|
+
blocks: [],
|
|
276
|
+
createdAt: now,
|
|
277
|
+
updatedAt: now,
|
|
278
|
+
};
|
|
279
|
+
if (old.activeForm)
|
|
280
|
+
migrated.activeForm = old.activeForm;
|
|
281
|
+
this.tasks.set(migrated.id, migrated);
|
|
282
|
+
}
|
|
283
|
+
this.nextCounter = Math.max(parsed.nextCounter ?? 1, maxNumericId + 1);
|
|
284
|
+
// Persist immediately as v2 so the next hydrate prefers the new path.
|
|
285
|
+
this.persist();
|
|
286
|
+
logger.info({ from: legacyPath, to: this.path, migrated: this.tasks.size }, "TaskStore: migrated legacy todos file to tasks v2");
|
|
287
|
+
}
|
|
288
|
+
catch (e) {
|
|
289
|
+
logger.warn({ err: e, path: legacyPath }, "TaskStore.hydrate: legacy parse failed, starting empty");
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/** Recover the counter from existing IDs when the file lacked the field. */
|
|
293
|
+
deriveCounter() {
|
|
294
|
+
let max = 0;
|
|
295
|
+
for (const t of this.tasks.values()) {
|
|
296
|
+
const n = Number.parseInt(t.id, 10);
|
|
297
|
+
if (Number.isFinite(n) && n > max)
|
|
298
|
+
max = n;
|
|
299
|
+
}
|
|
300
|
+
return max + 1;
|
|
301
|
+
}
|
|
302
|
+
persist() {
|
|
303
|
+
const file = {
|
|
304
|
+
version: 2,
|
|
305
|
+
nextCounter: this.nextCounter,
|
|
306
|
+
tasks: [...this.tasks.values()],
|
|
307
|
+
};
|
|
308
|
+
writeAtomic(this.path, file);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/** Atomic write: tmp → rename. Same pattern as skills/usage.ts and the
|
|
312
|
+
* legacy todos store. */
|
|
313
|
+
function writeAtomic(path, contents) {
|
|
314
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
315
|
+
const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
|
|
316
|
+
writeFileSync(tmp, JSON.stringify(contents, null, 2));
|
|
317
|
+
renameSync(tmp, path);
|
|
318
|
+
}
|
|
319
|
+
function isWellFormedEntry(v) {
|
|
320
|
+
if (!v || typeof v !== "object")
|
|
321
|
+
return false;
|
|
322
|
+
const o = v;
|
|
323
|
+
if (typeof o.id !== "string" || typeof o.subject !== "string")
|
|
324
|
+
return false;
|
|
325
|
+
if (!isStatus(o.status))
|
|
326
|
+
return false;
|
|
327
|
+
if (!Array.isArray(o.blockedBy) || !o.blockedBy.every((x) => typeof x === "string"))
|
|
328
|
+
return false;
|
|
329
|
+
if (!Array.isArray(o.blocks) || !o.blocks.every((x) => typeof x === "string"))
|
|
330
|
+
return false;
|
|
331
|
+
if (typeof o.createdAt !== "string" || typeof o.updatedAt !== "string")
|
|
332
|
+
return false;
|
|
333
|
+
if (o.description !== undefined && typeof o.description !== "string")
|
|
334
|
+
return false;
|
|
335
|
+
if (o.activeForm !== undefined && typeof o.activeForm !== "string")
|
|
336
|
+
return false;
|
|
337
|
+
if (o.owner !== undefined && typeof o.owner !== "string")
|
|
338
|
+
return false;
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
function isStatus(v) {
|
|
342
|
+
return v === "pending" || v === "in_progress" || v === "completed" || v === "deleted";
|
|
343
|
+
}
|
|
344
|
+
/** Resolve the absolute tasks-file path for a session. Mirrors
|
|
345
|
+
* `maestroSessionPath` but with `.tasks.json` instead of `.jsonl`. */
|
|
346
|
+
export function tasksPathFor(sessionId) {
|
|
347
|
+
return join(sessionsDir(), `${sessionId}.tasks.json`);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Module-level registry — same pattern as `file-state.ts` / the legacy
|
|
351
|
+
* todos store.
|
|
352
|
+
*
|
|
353
|
+
* Cleanup is wired into `deleteMaestroSession` and
|
|
354
|
+
* `cleanupStaleMaestroSessions` so the map can't outlive its sessions.
|
|
355
|
+
*/
|
|
356
|
+
const stores = new Map();
|
|
357
|
+
export function getTaskStore(sessionId) {
|
|
358
|
+
let s = stores.get(sessionId);
|
|
359
|
+
if (!s) {
|
|
360
|
+
s = new TaskStore(tasksPathFor(sessionId));
|
|
361
|
+
stores.set(sessionId, s);
|
|
362
|
+
}
|
|
363
|
+
return s;
|
|
364
|
+
}
|
|
365
|
+
/** Drop a session's store + unlink its on-disk file (both new and legacy). */
|
|
366
|
+
export function dropTaskStore(sessionId) {
|
|
367
|
+
const s = stores.get(sessionId);
|
|
368
|
+
if (s) {
|
|
369
|
+
s.unlinkFile();
|
|
370
|
+
stores.delete(sessionId);
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
// Best-effort cleanup of orphan files even when no store is hydrated —
|
|
374
|
+
// matches the old `dropTodoStore` behaviour so cleanupStaleMaestroSessions
|
|
375
|
+
// can clear .tasks.json / .todos.json siblings of a JSONL it's removing.
|
|
376
|
+
const newPath = tasksPathFor(sessionId);
|
|
377
|
+
const legacyPath = newPath.replace(/\.tasks\.json$/, ".todos.json");
|
|
378
|
+
for (const p of [newPath, legacyPath]) {
|
|
379
|
+
try {
|
|
380
|
+
unlinkSync(p);
|
|
381
|
+
}
|
|
382
|
+
catch (e) {
|
|
383
|
+
if (e?.code !== "ENOENT") {
|
|
384
|
+
logger.warn({ err: e, path: p }, "dropTaskStore: orphan unlink failed");
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/** Test-only. Reset every store. */
|
|
391
|
+
export function __resetAllStores() {
|
|
392
|
+
stores.clear();
|
|
393
|
+
}
|
|
394
|
+
/** Test-only. Count of currently-tracked sessions. */
|
|
395
|
+
export function __storeCount() {
|
|
396
|
+
return stores.size;
|
|
397
|
+
}
|
|
398
|
+
//# sourceMappingURL=tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/state/tasks.ts"],"names":[],"mappings":"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"}
|
|
@@ -67,7 +67,7 @@ export interface RunSubAgentResult {
|
|
|
67
67
|
* Cleanup contract (load-bearing):
|
|
68
68
|
* - Clean drain or thrown error → `deleteMaestroSession(subSessionId)`
|
|
69
69
|
* in the finally block. Frees the JSONL + file-state tracker + (any)
|
|
70
|
-
*
|
|
70
|
+
* task store for this sub-session.
|
|
71
71
|
* - Abort → leave JSONL on disk. The 30-day TTL sweep will eventually
|
|
72
72
|
* clear it; meanwhile it's available for postmortem.
|
|
73
73
|
*/
|
package/dist/sub-agent/runner.js
CHANGED
|
@@ -54,8 +54,8 @@ function loadOverlay(kind) {
|
|
|
54
54
|
* `explore` — Read + WebFetch + skill_view only. NO bash, write, edit —
|
|
55
55
|
* the role is read-only by construction.
|
|
56
56
|
*
|
|
57
|
-
* Neither registers `Agent` (recursion cap) or
|
|
58
|
-
* don't plan iteratively).
|
|
57
|
+
* Neither registers `Agent` (recursion cap) or the Task* family
|
|
58
|
+
* (sub-agents don't plan iteratively).
|
|
59
59
|
*/
|
|
60
60
|
function buildToolRegistry(kind, subSessionId, skills, abortSignal) {
|
|
61
61
|
void abortSignal; // reserved for future bash abort wiring
|
|
@@ -85,7 +85,7 @@ function buildToolRegistry(kind, subSessionId, skills, abortSignal) {
|
|
|
85
85
|
* Cleanup contract (load-bearing):
|
|
86
86
|
* - Clean drain or thrown error → `deleteMaestroSession(subSessionId)`
|
|
87
87
|
* in the finally block. Frees the JSONL + file-state tracker + (any)
|
|
88
|
-
*
|
|
88
|
+
* task store for this sub-session.
|
|
89
89
|
* - Abort → leave JSONL on disk. The 30-day TTL sweep will eventually
|
|
90
90
|
* clear it; meanwhile it's available for postmortem.
|
|
91
91
|
*/
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ToolHandler } from "../../tools/registry.js";
|
|
2
|
+
export declare const globTool: ToolHandler;
|
|
3
|
+
/**
|
|
4
|
+
* Compile a shell-style glob to a regex that matches the entire relative
|
|
5
|
+
* path (anchored at both ends).
|
|
6
|
+
*
|
|
7
|
+
* Handled tokens:
|
|
8
|
+
* `**\/` → `(?:.*\/)?` — zero or more path segments (greedy across `/`)
|
|
9
|
+
* `**` → `.*` — anything including `/`
|
|
10
|
+
* `*` → `[^/]*` — anything except `/` within one segment
|
|
11
|
+
* `?` → `[^/]` — single char within one segment
|
|
12
|
+
*
|
|
13
|
+
* Other regex metacharacters are escaped so literals like `.` in `foo.ts`
|
|
14
|
+
* don't accidentally turn into "any char".
|
|
15
|
+
*/
|
|
16
|
+
export declare function compileGlob(pattern: string): RegExp;
|
|
17
|
+
//# sourceMappingURL=glob.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/glob.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAuCpD,eAAO,MAAM,QAAQ,EAAE,WAmJtB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA+BnD"}
|