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.
Files changed (102) hide show
  1. package/README.md +216 -20
  2. package/dist/agents/contracts.d.ts +10 -0
  3. package/dist/agents/contracts.d.ts.map +1 -1
  4. package/dist/agents/rollout/shared.d.ts +4 -4
  5. package/dist/agents/rollout/shared.js +4 -4
  6. package/dist/core/loop.d.ts.map +1 -1
  7. package/dist/core/loop.js +9 -8
  8. package/dist/core/loop.js.map +1 -1
  9. package/dist/index.d.ts +8 -7
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +8 -7
  12. package/dist/index.js.map +1 -1
  13. package/dist/memory/compressor.d.ts +8 -5
  14. package/dist/memory/compressor.d.ts.map +1 -1
  15. package/dist/memory/compressor.js +10 -4
  16. package/dist/memory/compressor.js.map +1 -1
  17. package/dist/memory/reminder.d.ts +11 -12
  18. package/dist/memory/reminder.d.ts.map +1 -1
  19. package/dist/memory/reminder.js +22 -32
  20. package/dist/memory/reminder.js.map +1 -1
  21. package/dist/platform/config.d.ts +0 -2
  22. package/dist/platform/config.d.ts.map +1 -1
  23. package/dist/platform/config.js +9 -18
  24. package/dist/platform/config.js.map +1 -1
  25. package/dist/platform/version.d.ts +13 -0
  26. package/dist/platform/version.d.ts.map +1 -0
  27. package/dist/platform/version.js +13 -0
  28. package/dist/platform/version.js.map +1 -0
  29. package/dist/provider.d.ts +62 -0
  30. package/dist/provider.d.ts.map +1 -1
  31. package/dist/provider.js +137 -30
  32. package/dist/provider.js.map +1 -1
  33. package/dist/registry.d.ts.map +1 -1
  34. package/dist/registry.js +16 -1
  35. package/dist/registry.js.map +1 -1
  36. package/dist/session-store.d.ts +95 -4
  37. package/dist/session-store.d.ts.map +1 -1
  38. package/dist/session-store.js +144 -13
  39. package/dist/session-store.js.map +1 -1
  40. package/dist/skills/curator.d.ts +8 -6
  41. package/dist/skills/curator.d.ts.map +1 -1
  42. package/dist/skills/curator.js +13 -7
  43. package/dist/skills/curator.js.map +1 -1
  44. package/dist/skills/loader.d.ts +45 -20
  45. package/dist/skills/loader.d.ts.map +1 -1
  46. package/dist/skills/loader.js +56 -11
  47. package/dist/skills/loader.js.map +1 -1
  48. package/dist/state/tasks.d.ts +107 -0
  49. package/dist/state/tasks.d.ts.map +1 -0
  50. package/dist/state/tasks.js +398 -0
  51. package/dist/state/tasks.js.map +1 -0
  52. package/dist/sub-agent/runner.d.ts +1 -1
  53. package/dist/sub-agent/runner.d.ts.map +1 -1
  54. package/dist/sub-agent/runner.js +3 -5
  55. package/dist/sub-agent/runner.js.map +1 -1
  56. package/dist/tools/builtin/edit.d.ts.map +1 -1
  57. package/dist/tools/builtin/edit.js +0 -4
  58. package/dist/tools/builtin/edit.js.map +1 -1
  59. package/dist/tools/builtin/glob.d.ts +17 -0
  60. package/dist/tools/builtin/glob.d.ts.map +1 -0
  61. package/dist/tools/builtin/glob.js +235 -0
  62. package/dist/tools/builtin/glob.js.map +1 -0
  63. package/dist/tools/builtin/grep.d.ts +3 -0
  64. package/dist/tools/builtin/grep.d.ts.map +1 -0
  65. package/dist/tools/builtin/grep.js +272 -0
  66. package/dist/tools/builtin/grep.js.map +1 -0
  67. package/dist/tools/builtin/read.d.ts.map +1 -1
  68. package/dist/tools/builtin/read.js +0 -4
  69. package/dist/tools/builtin/read.js.map +1 -1
  70. package/dist/tools/builtin/skill_write.d.ts +53 -0
  71. package/dist/tools/builtin/skill_write.d.ts.map +1 -0
  72. package/dist/tools/builtin/skill_write.js +264 -0
  73. package/dist/tools/builtin/skill_write.js.map +1 -0
  74. package/dist/tools/builtin/tasks.d.ts +34 -0
  75. package/dist/tools/builtin/tasks.d.ts.map +1 -0
  76. package/dist/tools/builtin/tasks.js +258 -0
  77. package/dist/tools/builtin/tasks.js.map +1 -0
  78. package/dist/tools/builtin/write.d.ts +4 -10
  79. package/dist/tools/builtin/write.d.ts.map +1 -1
  80. package/dist/tools/builtin/write.js.map +1 -1
  81. package/dist/tools/file-state.d.ts +1 -1
  82. package/dist/tools/file-state.js +1 -1
  83. package/dist/tools/registry.d.ts +1 -1
  84. package/dist/types.d.ts +64 -0
  85. package/dist/types.d.ts.map +1 -1
  86. package/package.json +1 -1
  87. package/dist/state/todos.d.ts +0 -95
  88. package/dist/state/todos.d.ts.map +0 -1
  89. package/dist/state/todos.js +0 -198
  90. package/dist/state/todos.js.map +0 -1
  91. package/dist/tools/builtin/sandbox.d.ts +0 -16
  92. package/dist/tools/builtin/sandbox.d.ts.map +0 -1
  93. package/dist/tools/builtin/sandbox.js +0 -59
  94. package/dist/tools/builtin/sandbox.js.map +0 -1
  95. package/dist/tools/builtin/todo_write.d.ts +0 -29
  96. package/dist/tools/builtin/todo_write.d.ts.map +0 -1
  97. package/dist/tools/builtin/todo_write.js +0 -96
  98. package/dist/tools/builtin/todo_write.js.map +0 -1
  99. package/dist/tools/hooks/sandbox-fs.d.ts +0 -25
  100. package/dist/tools/hooks/sandbox-fs.d.ts.map +0 -1
  101. package/dist/tools/hooks/sandbox-fs.js +0 -48
  102. package/dist/tools/hooks/sandbox-fs.js.map +0 -1
@@ -1,9 +1,5 @@
1
1
  import type { FileStateTracker } from "../../tools/file-state.js";
2
2
  import type { ToolHandler } from "../../tools/registry.js";
3
- /**
4
- * NOTE: filesystem sandboxing now lives in the `sandbox-fs` PreToolUse hook.
5
- * Standalone callers (tests, scripts) without the registry get NO sandbox.
6
- */
7
3
  /**
8
4
  * Write builtin — claude SDK `Write` tool parity for maestro.
9
5
  *
@@ -13,12 +9,10 @@ import type { ToolHandler } from "../../tools/registry.js";
13
9
  * additive writes should use the bash tool with `>>` for now (Phase 5 may add
14
10
  * a separate `Edit` builtin that handles the read-modify-write cycle).
15
11
  *
16
- * Path safety: absolute path is enforced. The write is NOT sandboxed under
17
- * the workspace dir here the host's permission system (PreToolUse hooks
18
- * via `ToolRegistry`, or the optional `createSandboxFsHook`) plus the agent
19
- * loop's abort plumbing are the authoritative guardrails. A stricter check
20
- * can land later without breaking the schema (the model only sees the public
21
- * fields).
12
+ * Path safety: absolute path is enforced. Any further restriction (workspace
13
+ * allowlist, owner check, etc.) is the host's job register a PreToolUse
14
+ * hook via `ToolRegistry.use()` and inspect `ctx.input.file_path` there.
15
+ * The agent loop's abort plumbing remains the authoritative cancel path.
22
16
  */
23
17
  export interface WriteToolOptions {
24
18
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/write.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;GAGG;AAEH;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED,wBAAgB,eAAe,CAAC,IAAI,GAAE,gBAAqB,GAAG,WAAW,CAkExE;AAED,mDAAmD;AACnD,eAAO,MAAM,SAAS,EAAE,WAA+B,CAAC"}
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/write.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED,wBAAgB,eAAe,CAAC,IAAI,GAAE,gBAAqB,GAAG,WAAW,CAkExE;AAED,mDAAmD;AACnD,eAAO,MAAM,SAAS,EAAE,WAA+B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/tools/builtin/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAqChD,MAAM,UAAU,eAAe,CAAC,OAAyB,EAAE;IACzD,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACzB,OAAO;QACL,MAAM,EAAE;YACN,IAAI,EAAE,OAAO;YACb,WAAW,EACT,sEAAsE;gBACtE,uEAAuE;gBACvE,qEAAqE;YACvE,YAAY,EAAE;gBACZ,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,SAAS,EAAE;wBACT,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,+DAA+D;qBAC7E;oBACD,OAAO,EAAE;wBACP,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,kDAAkD;qBAChE;iBACF;gBACD,QAAQ,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC;aACnC;SACF;QACD,KAAK,CAAC,OAAO,CAAC,KAAK;YACjB,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5E,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,qCAAqC,EAAE,CAAC,CAAC;YAC1E,CAAC;YACD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC1B,OAAO,IAAI,CAAC,SAAS,CAAC;oBACpB,KAAK,EAAE,2CAA2C,QAAQ,GAAG;iBAC9D,CAAC,CAAC;YACL,CAAC;YACD,mEAAmE;YACnE,0EAA0E;YAC1E,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC7D,IAAI,OAAO;oBAAE,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YACzD,CAAC;YACD,uEAAuE;YACvE,kEAAkE;YAClE,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACtC,OAAO,IAAI,CAAC,SAAS,CAAC;oBACpB,KAAK,EAAE,0CAA0C,OAAO,KAAK,CAAC,OAAO,EAAE;iBACxE,CAAC,CAAC;YACL,CAAC;YACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;YAE9B,IAAI,CAAC;gBACH,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClD,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAC5C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,IAAI,CAAC,SAAS,CAAC;oBACpB,KAAK,EAAE,kBAAkB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;iBACtE,CAAC,CAAC;YACL,CAAC;YAED,qEAAqE;YACrE,uDAAuD;YACvD,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;YAE1B,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAClD,OAAO,iBAAiB,QAAQ,KAAK,KAAK,SAAS,CAAC;QACtD,CAAC;KACF,CAAC;AACJ,CAAC;AAED,mDAAmD;AACnD,MAAM,CAAC,MAAM,SAAS,GAAgB,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/tools/builtin/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AA8BhD,MAAM,UAAU,eAAe,CAAC,OAAyB,EAAE;IACzD,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACzB,OAAO;QACL,MAAM,EAAE;YACN,IAAI,EAAE,OAAO;YACb,WAAW,EACT,sEAAsE;gBACtE,uEAAuE;gBACvE,qEAAqE;YACvE,YAAY,EAAE;gBACZ,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,SAAS,EAAE;wBACT,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,+DAA+D;qBAC7E;oBACD,OAAO,EAAE;wBACP,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,kDAAkD;qBAChE;iBACF;gBACD,QAAQ,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC;aACnC;SACF;QACD,KAAK,CAAC,OAAO,CAAC,KAAK;YACjB,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5E,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,qCAAqC,EAAE,CAAC,CAAC;YAC1E,CAAC;YACD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC1B,OAAO,IAAI,CAAC,SAAS,CAAC;oBACpB,KAAK,EAAE,2CAA2C,QAAQ,GAAG;iBAC9D,CAAC,CAAC;YACL,CAAC;YACD,mEAAmE;YACnE,0EAA0E;YAC1E,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC7D,IAAI,OAAO;oBAAE,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YACzD,CAAC;YACD,uEAAuE;YACvE,kEAAkE;YAClE,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACtC,OAAO,IAAI,CAAC,SAAS,CAAC;oBACpB,KAAK,EAAE,0CAA0C,OAAO,KAAK,CAAC,OAAO,EAAE;iBACxE,CAAC,CAAC;YACL,CAAC;YACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;YAE9B,IAAI,CAAC;gBACH,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClD,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAC5C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,IAAI,CAAC,SAAS,CAAC;oBACpB,KAAK,EAAE,kBAAkB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;iBACtE,CAAC,CAAC;YACL,CAAC;YAED,qEAAqE;YACrE,uDAAuD;YACvD,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;YAE1B,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAClD,OAAO,iBAAiB,QAAQ,KAAK,KAAK,SAAS,CAAC;QACtD,CAAC;KACF,CAAC;AACJ,CAAC;AAED,mDAAmD;AACnD,MAAM,CAAC,MAAM,SAAS,GAAgB,eAAe,EAAE,CAAC"}
@@ -63,7 +63,7 @@ export declare class FileStateTracker {
63
63
  /**
64
64
  * Check whether `absPath` may be Edit/Write'd. Returns null on allow,
65
65
  * or a string error on deny — callers stringify into `{error}` so the
66
- * model sees the same shape as sandbox / arg-validation rejections.
66
+ * model sees the same shape as arg-validation rejections.
67
67
  *
68
68
  * Three reject paths:
69
69
  * - "no_read": never Read this session. Forces the model to Read first.
@@ -29,7 +29,7 @@ export class FileStateTracker {
29
29
  /**
30
30
  * Check whether `absPath` may be Edit/Write'd. Returns null on allow,
31
31
  * or a string error on deny — callers stringify into `{error}` so the
32
- * model sees the same shape as sandbox / arg-validation rejections.
32
+ * model sees the same shape as arg-validation rejections.
33
33
  *
34
34
  * Three reject paths:
35
35
  * - "no_read": never Read this session. Forces the model to Read first.
@@ -8,7 +8,7 @@ import type { ProviderToolSchema } from "../providers/base.js";
8
8
  *
9
9
  * Phase 2 adds a hook chain around `dispatch` (PreToolUse / PostToolUse)
10
10
  * matching Claude Code's settings.json hook surface. Hooks centralize
11
- * policy that would otherwise be sprinkled across tools — sandbox gates,
11
+ * policy that would otherwise be sprinkled across tools — path allowlists,
12
12
  * automatic redaction, telemetry.
13
13
  */
14
14
  /**
package/dist/types.d.ts CHANGED
@@ -84,6 +84,24 @@ export interface AgentQueryOptions {
84
84
  agent: AgentKind;
85
85
  prompt: string;
86
86
  sessionId?: string | null;
87
+ /**
88
+ * Working-directory hint for this session.
89
+ *
90
+ * The SDK uses this for two narrow purposes:
91
+ * 1. `mkdir -p` so the path exists when subsequent host code stats it
92
+ * (e.g. resume flows that read files from the session's expected root).
93
+ * 2. Stamp it into the rollout `_meta` header (since v0.1.5) so a future
94
+ * indexer / forensic sweep can attribute the on-disk JSONL to a project.
95
+ *
96
+ * Note: the SDK loop itself does **not** chdir, and the built-in tools
97
+ * (Read/Write/Edit) require absolute paths regardless of this value. The
98
+ * Bash tool's `cwd` is per-call input from the model, NOT auto-injected
99
+ * from this field. Future minor versions may evolve tools to respect this
100
+ * hint, but today it is treated as metadata.
101
+ *
102
+ * Pass the canonical project / workspace path the host wants associated
103
+ * with this session.
104
+ */
87
105
  cwd: string;
88
106
  systemPrompt: string;
89
107
  userId?: string;
@@ -106,5 +124,51 @@ export interface AgentQueryOptions {
106
124
  mcpExtra?: Record<string, unknown>;
107
125
  isCron?: boolean;
108
126
  silent?: boolean;
127
+ /**
128
+ * Named skill profile within the per-cwd `.skills/` directory. The SDK
129
+ * resolves the skill catalog source as:
130
+ *
131
+ * - `<cwd>/.skills/<skillKey>/` when set
132
+ * - `<cwd>/.skills/<MAESTRO_DEFAULT_SKILL_KEY>/` when omitted (literally
133
+ * `<cwd>/.skills/default/` — the constant is exported so hosts can
134
+ * reference it symbolically).
135
+ *
136
+ * Every skill lives under a named key — the SDK never loads from the
137
+ * `.skills/` root directly. This keeps the layout uniform so a caller
138
+ * scanning the filesystem can answer "which profiles exist?" with one
139
+ * `readdir`.
140
+ *
141
+ * Use case: one workspace, multiple disjoint skill sets. A topic /
142
+ * session passes a key (e.g. "legal", "coding"); the agent's catalog
143
+ * is whatever lives under that subdirectory. New skills the agent
144
+ * writes during the session naturally land in the same subdir — the
145
+ * keyed dir IS the loader root, so created skills stay scoped to the
146
+ * key without extra plumbing.
147
+ *
148
+ * This is the only knob the SDK exposes for skill-source routing —
149
+ * `(cwd, skillKey)` is a deterministic pair, so two sessions with the
150
+ * same pair load the same catalog and there's no env-var / explicit-
151
+ * dir precedence chain to reason about.
152
+ */
153
+ skillKey?: string;
154
+ /**
155
+ * Whitelist of skill names this call may surface. When provided, the
156
+ * loaded catalog is filtered down to entries whose `name` matches one
157
+ * of the listed values BEFORE curation, index rendering, and
158
+ * `skill_view` registration. Unknown names in the list are silently
159
+ * ignored (no error) so a host can safely pass a superset.
160
+ *
161
+ * Omit (or pass `undefined`) to allow every loaded skill — the default
162
+ * pre-0.1.5 behavior.
163
+ */
164
+ allowedSkills?: string[];
165
+ /**
166
+ * Opaque host-controlled bag persisted alongside the session as part of
167
+ * the rollout `_meta` header. The SDK reads and writes this verbatim and
168
+ * never interprets its shape — useful for round-tripping `topicId`,
169
+ * `groupId`, or any other host-side identifiers that should follow the
170
+ * session across persistence.
171
+ */
172
+ sessionMetadata?: Record<string, unknown>;
109
173
  }
110
174
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maestro-agent-sdk",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Embeddable, provider-agnostic TypeScript agent SDK — pluggable providers, built-in tools, skills, memory, and MCP.",
5
5
  "license": "MIT",
6
6
  "author": "Yeonwoo Jeong <aadd4020@gmail.com>",
@@ -1,95 +0,0 @@
1
- /**
2
- * Per-session todo list backing TodoWrite.
3
- *
4
- * The model gets a single `todo_write` tool to upsert / mutate the list. There
5
- * is no `todo_list` tool — read-side surfaces via the per-turn system
6
- * reminder, which keeps the model from juggling two near-identical tools
7
- * (and saves a per-turn round-trip for what is fundamentally a snapshot view).
8
- *
9
- * Persistence: one JSON file at `~/.maestro/sessions/<sid>.todos.json` — a
10
- * snapshot of the current list, atomically written. Not JSONL: `todo_write`
11
- * semantically OVERWRITES the list each call, so an append-only stream
12
- * would accumulate dead entries the loader has to filter. A single JSON
13
- * snapshot matches the actual semantics and is cheaper to read.
14
- *
15
- * Lifecycle:
16
- * - `getTodoStore(sid)` lazy-creates the store and hydrates from disk if
17
- * a prior turn wrote one.
18
- * - `dropTodoStore(sid)` is called from `deleteMaestroSession` and
19
- * `cleanupStaleMaestroSessions` (same pattern as `file-state.ts`) so the
20
- * module-level map can't outlive its sessions.
21
- *
22
- * Invariants enforced at upsert time:
23
- * - At most one entry is `in_progress`. Setting a second one to
24
- * `in_progress` flips any prior one to `pending` and warns the caller
25
- * via the tool result. Mirrors Claude Code's TodoWrite contract.
26
- * - IDs are auto-assigned (`task-1`, `task-2`, …) when omitted. Short IDs
27
- * so the model can refer back to them in prose without bloat.
28
- */
29
- export type TodoStatus = "pending" | "in_progress" | "completed";
30
- export interface TodoEntry {
31
- id: string;
32
- content: string;
33
- status: TodoStatus;
34
- /** Optional present-continuous form for spinner/status display
35
- * ("Reading config" vs the imperative "Read config"). */
36
- activeForm?: string;
37
- }
38
- export interface TodoUpsert {
39
- id?: string;
40
- content: string;
41
- status: TodoStatus;
42
- activeForm?: string;
43
- }
44
- export interface UpsertResult {
45
- todos: TodoEntry[];
46
- /** Set when the upsert had to flip a prior in_progress to pending to
47
- * enforce the 1-in-progress invariant. The tool surfaces this in its
48
- * result so the model knows the previously-active item was bumped. */
49
- demotedId?: string;
50
- }
51
- export declare class TodoStore {
52
- private readonly path;
53
- private todos;
54
- private nextCounter;
55
- constructor(path: string);
56
- /** Read the current list. Caller must not mutate. */
57
- list(): readonly TodoEntry[];
58
- /** True when the list is empty (no in-flight or pending work). */
59
- isEmpty(): boolean;
60
- /**
61
- * Replace / upsert the entire list. Entries with an `id` that matches an
62
- * existing one update that entry; entries without an id (or with an id
63
- * not in the current list) become new entries with an auto-assigned id.
64
- *
65
- * The shape mirrors Claude Code's TodoWrite: the model passes a complete
66
- * snapshot of "what I want the list to look like now," and we reconcile.
67
- * That means an existing id NOT included in the incoming snapshot is
68
- * dropped — TodoWrite is a snapshot replace, not a partial update.
69
- *
70
- * Returns `{todos, demotedId?}` so the tool can tell the model exactly
71
- * what landed (incl. any in-progress demotion).
72
- */
73
- upsert(incoming: TodoUpsert[]): UpsertResult;
74
- /** Drop the on-disk file. Called by deleteMaestroSession via dropTodoStore. */
75
- unlinkFile(): void;
76
- /** Test-only: snapshot the path the store is backed by. */
77
- __path(): string;
78
- private nextId;
79
- private hydrate;
80
- /** Recover the counter from existing IDs when the file lacked the field
81
- * (defensive — recent hydrate writes always include it). */
82
- private deriveCounter;
83
- private persist;
84
- }
85
- /** Resolve the absolute todos-file path for a session. Mirrors
86
- * `maestroSessionPath` but with `.todos.json` instead of `.jsonl`. */
87
- export declare function todosPathFor(sessionId: string): string;
88
- export declare function getTodoStore(sessionId: string): TodoStore;
89
- /** Drop a session's store + unlink its on-disk file. */
90
- export declare function dropTodoStore(sessionId: string): void;
91
- /** Test-only. Reset every store. */
92
- export declare function __resetAllStores(): void;
93
- /** Test-only. Count of currently-tracked sessions. */
94
- export declare function __storeCount(): number;
95
- //# sourceMappingURL=todos.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"todos.d.ts","sourceRoot":"","sources":["../../src/state/todos.ts"],"names":[],"mappings":"AAoBA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;AAEjE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,UAAU,CAAC;IACnB;8DAC0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AASD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB;;2EAEuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,SAAS;IAIR,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,WAAW,CAAK;gBAEK,IAAI,EAAE,MAAM;IAIzC,qDAAqD;IACrD,IAAI,IAAI,SAAS,SAAS,EAAE;IAI5B,kEAAkE;IAClE,OAAO,IAAI,OAAO;IAIlB;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,YAAY;IAwC5C,+EAA+E;IAC/E,UAAU,IAAI,IAAI;IAUlB,2DAA2D;IAC3D,MAAM,IAAI,MAAM;IAMhB,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,OAAO;IAgBf;iEAC6D;IAC7D,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,OAAO;CAQhB;AAqBD;uEACuE;AACvE,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAeD,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAOzD;AAED,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAMrD;AAED,oCAAoC;AACpC,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED,sDAAsD;AACtD,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
@@ -1,198 +0,0 @@
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
- /** Mirror of `maestroSessionsDir()` from session-store.ts — inlined here to
6
- * avoid a circular import (session-store.ts needs to call
7
- * `dropTodoStore` for cleanup). Two single-line copies are cheaper than
8
- * extracting a shared util file for one path. */
9
- function sessionsDir() {
10
- return join(homedir(), ".maestro", "sessions");
11
- }
12
- export class TodoStore {
13
- path;
14
- todos = [];
15
- nextCounter = 1;
16
- constructor(path) {
17
- this.path = path;
18
- this.hydrate();
19
- }
20
- /** Read the current list. Caller must not mutate. */
21
- list() {
22
- return this.todos;
23
- }
24
- /** True when the list is empty (no in-flight or pending work). */
25
- isEmpty() {
26
- return this.todos.length === 0;
27
- }
28
- /**
29
- * Replace / upsert the entire list. Entries with an `id` that matches an
30
- * existing one update that entry; entries without an id (or with an id
31
- * not in the current list) become new entries with an auto-assigned id.
32
- *
33
- * The shape mirrors Claude Code's TodoWrite: the model passes a complete
34
- * snapshot of "what I want the list to look like now," and we reconcile.
35
- * That means an existing id NOT included in the incoming snapshot is
36
- * dropped — TodoWrite is a snapshot replace, not a partial update.
37
- *
38
- * Returns `{todos, demotedId?}` so the tool can tell the model exactly
39
- * what landed (incl. any in-progress demotion).
40
- */
41
- upsert(incoming) {
42
- const out = [];
43
- let demotedId;
44
- // First pass: build the new list, assigning IDs to entries that need
45
- // them. We do this BEFORE the 1-in-progress sweep so the auto-IDs are
46
- // available for the warning message.
47
- for (const item of incoming) {
48
- const id = item.id?.trim() || this.nextId();
49
- out.push({
50
- id,
51
- content: item.content,
52
- status: item.status,
53
- ...(item.activeForm ? { activeForm: item.activeForm } : {}),
54
- });
55
- }
56
- // Second pass: enforce 1-in-progress. Walk in incoming order; the LAST
57
- // in_progress wins (mirrors how a model batch-updates and the final
58
- // entry expresses current intent). Earlier in_progress entries are
59
- // flipped to pending and surfaced via `demotedId`.
60
- let lastInProgressIdx = -1;
61
- for (let i = 0; i < out.length; i++) {
62
- if (out[i].status === "in_progress")
63
- lastInProgressIdx = i;
64
- }
65
- if (lastInProgressIdx >= 0) {
66
- for (let i = 0; i < out.length; i++) {
67
- if (i === lastInProgressIdx)
68
- continue;
69
- if (out[i].status === "in_progress") {
70
- out[i] = { ...out[i], status: "pending" };
71
- demotedId = out[i].id;
72
- }
73
- }
74
- }
75
- this.todos = out;
76
- this.persist();
77
- return demotedId !== undefined ? { todos: out, demotedId } : { todos: out };
78
- }
79
- /** Drop the on-disk file. Called by deleteMaestroSession via dropTodoStore. */
80
- unlinkFile() {
81
- try {
82
- unlinkSync(this.path);
83
- }
84
- catch (e) {
85
- if (e?.code !== "ENOENT") {
86
- logger.warn({ err: e, path: this.path }, "TodoStore.unlinkFile failed");
87
- }
88
- }
89
- }
90
- /** Test-only: snapshot the path the store is backed by. */
91
- __path() {
92
- return this.path;
93
- }
94
- // --- internals ---------------------------------------------------------
95
- nextId() {
96
- const id = `task-${this.nextCounter}`;
97
- this.nextCounter++;
98
- return id;
99
- }
100
- hydrate() {
101
- if (!existsSync(this.path))
102
- return;
103
- try {
104
- const raw = readFileSync(this.path, "utf8");
105
- const parsed = JSON.parse(raw);
106
- if (parsed.version !== 1 || !Array.isArray(parsed.todos)) {
107
- logger.warn({ path: this.path }, "TodoStore.hydrate: unsupported schema, ignoring");
108
- return;
109
- }
110
- this.todos = parsed.todos.filter(isWellFormedEntry);
111
- this.nextCounter = Math.max(1, parsed.nextCounter ?? this.deriveCounter());
112
- }
113
- catch (e) {
114
- logger.warn({ err: e, path: this.path }, "TodoStore.hydrate: parse failed, starting empty");
115
- }
116
- }
117
- /** Recover the counter from existing IDs when the file lacked the field
118
- * (defensive — recent hydrate writes always include it). */
119
- deriveCounter() {
120
- let max = 0;
121
- for (const t of this.todos) {
122
- const m = /^task-(\d+)$/.exec(t.id);
123
- if (m)
124
- max = Math.max(max, Number.parseInt(m[1], 10));
125
- }
126
- return max + 1;
127
- }
128
- persist() {
129
- const file = {
130
- version: 1,
131
- nextCounter: this.nextCounter,
132
- todos: this.todos,
133
- };
134
- writeAtomic(this.path, file);
135
- }
136
- }
137
- /** Atomic write: tmp → rename. Same pattern as skills/usage.ts. */
138
- function writeAtomic(path, contents) {
139
- mkdirSync(dirname(path), { recursive: true });
140
- const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
141
- writeFileSync(tmp, JSON.stringify(contents, null, 2));
142
- renameSync(tmp, path);
143
- }
144
- function isWellFormedEntry(v) {
145
- if (!v || typeof v !== "object")
146
- return false;
147
- const o = v;
148
- if (typeof o.id !== "string" || typeof o.content !== "string")
149
- return false;
150
- if (o.status !== "pending" && o.status !== "in_progress" && o.status !== "completed") {
151
- return false;
152
- }
153
- if (o.activeForm !== undefined && typeof o.activeForm !== "string")
154
- return false;
155
- return true;
156
- }
157
- /** Resolve the absolute todos-file path for a session. Mirrors
158
- * `maestroSessionPath` but with `.todos.json` instead of `.jsonl`. */
159
- export function todosPathFor(sessionId) {
160
- return join(sessionsDir(), `${sessionId}.todos.json`);
161
- }
162
- /**
163
- * Module-level registry — same pattern as `file-state.ts`.
164
- *
165
- * The maestroProvider rebuilds tools each turn but the sessionId persists
166
- * across turns. A registry-local store would re-hydrate every turn (cheap
167
- * but wasteful); a module-level cache keeps the in-memory list hot.
168
- *
169
- * Cleanup is wired into `deleteMaestroSession` and
170
- * `cleanupStaleMaestroSessions` (see session-store.ts) so the map can't
171
- * outlive its sessions.
172
- */
173
- const stores = new Map();
174
- export function getTodoStore(sessionId) {
175
- let s = stores.get(sessionId);
176
- if (!s) {
177
- s = new TodoStore(todosPathFor(sessionId));
178
- stores.set(sessionId, s);
179
- }
180
- return s;
181
- }
182
- /** Drop a session's store + unlink its on-disk file. */
183
- export function dropTodoStore(sessionId) {
184
- const s = stores.get(sessionId);
185
- if (s) {
186
- s.unlinkFile();
187
- stores.delete(sessionId);
188
- }
189
- }
190
- /** Test-only. Reset every store. */
191
- export function __resetAllStores() {
192
- stores.clear();
193
- }
194
- /** Test-only. Count of currently-tracked sessions. */
195
- export function __storeCount() {
196
- return stores.size;
197
- }
198
- //# sourceMappingURL=todos.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"todos.js","sourceRoot":"","sources":["../../src/state/todos.ts"],"names":[],"mappings":"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"}
@@ -1,16 +0,0 @@
1
- /**
2
- * Check whether `filePath` is allowed by the sandbox. Returns null on allow,
3
- * or an error message string on deny. Callers stringify the error into a
4
- * `{error}` payload so the model sees a structured rejection.
5
- *
6
- * The path is normalized (`..` collapsed) but symlinks are NOT followed.
7
- * Caller is responsible for ensuring `filePath` is already absolute — the
8
- * Read/Write/Edit tools enforce that at the top of `execute`.
9
- */
10
- export declare function checkFilesystemAccess(filePath: string): string | null;
11
- /** Whether the sandbox is currently active. Default is OFF; the operator
12
- * opts in by exporting `MAESTRO_FS_SANDBOX_ENABLED=1`. Read each call so a
13
- * test can toggle it without restarting the process. */
14
- export declare function isSandboxEnabled(): boolean;
15
- export declare const __ENV_ENABLED = "MAESTRO_FS_SANDBOX_ENABLED";
16
- //# sourceMappingURL=sandbox.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/sandbox.ts"],"names":[],"mappings":"AA+BA;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYrE;AAED;;yDAEyD;AACzD,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED,eAAO,MAAM,aAAa,+BAAc,CAAC"}
@@ -1,59 +0,0 @@
1
- import { resolve as resolvePath } from "node:path";
2
- import { WORKSPACE_DIR } from "../../platform/config.js";
3
- /**
4
- * Maestro builtin filesystem sandbox.
5
- *
6
- * Optional gate Read/Write/Edit (and any PreToolUse hook that consults it)
7
- * can use to constrain file access to `${WORKSPACE_DIR}`. Default is
8
- * **disabled** — claude/codex providers grant unconstrained FS access via
9
- * `bypassPermissions` / `danger-full-access`, and forcing a stricter posture
10
- * on maestro alone silently breaks any workflow that legitimately reaches
11
- * outside the workspace (reading `~/.config`, writing into a sibling repo,
12
- * etc.). The single-tenant Mac deployments maestro targets trust the model
13
- * with the whole UID anyway.
14
- *
15
- * Opt-in: set `MAESTRO_FS_SANDBOX_ENABLED=1` to enforce. Only paths under
16
- * `${WORKSPACE_DIR}` (defaults to `~/maestro-workspace`, override via
17
- * `MAESTRO_WORKSPACE_DIR`) are allowed when enabled; system paths
18
- * (`~/.ssh`, `/etc`, `/usr`, sibling project clones, etc.) are rejected.
19
- * Useful for multi-tenant or hardened setups where the model should not be
20
- * trusted with arbitrary FS access.
21
- *
22
- * Symlink note: we resolve `..` segments via `path.resolve` but do NOT
23
- * follow symlinks (no `realpathSync`) — a symlink inside the workspace
24
- * pointing OUT is still considered inside (the link target is what gets
25
- * written/read, and the user explicitly placed that link there). Tightening
26
- * this is a follow-up if it ever matters.
27
- */
28
- const ENV_ENABLED = "MAESTRO_FS_SANDBOX_ENABLED";
29
- /**
30
- * Check whether `filePath` is allowed by the sandbox. Returns null on allow,
31
- * or an error message string on deny. Callers stringify the error into a
32
- * `{error}` payload so the model sees a structured rejection.
33
- *
34
- * The path is normalized (`..` collapsed) but symlinks are NOT followed.
35
- * Caller is responsible for ensuring `filePath` is already absolute — the
36
- * Read/Write/Edit tools enforce that at the top of `execute`.
37
- */
38
- export function checkFilesystemAccess(filePath) {
39
- if (!isSandboxEnabled())
40
- return null;
41
- const resolved = resolvePath(filePath);
42
- // Allow path === root and any descendant. The separator suffix avoids
43
- // `WORKSPACE_DIR-sibling` style false-allows.
44
- if (resolved === WORKSPACE_DIR)
45
- return null;
46
- const prefix = WORKSPACE_DIR.endsWith("/") ? WORKSPACE_DIR : `${WORKSPACE_DIR}/`;
47
- if (resolved.startsWith(prefix))
48
- return null;
49
- return (`Sandbox: path '${filePath}' is outside the workspace root (${WORKSPACE_DIR}). ` +
50
- `Unset ${ENV_ENABLED} or scope the operation under the workspace.`);
51
- }
52
- /** Whether the sandbox is currently active. Default is OFF; the operator
53
- * opts in by exporting `MAESTRO_FS_SANDBOX_ENABLED=1`. Read each call so a
54
- * test can toggle it without restarting the process. */
55
- export function isSandboxEnabled() {
56
- return process.env[ENV_ENABLED] === "1";
57
- }
58
- export const __ENV_ENABLED = ENV_ENABLED;
59
- //# sourceMappingURL=sandbox.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../../src/tools/builtin/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,WAAW,GAAG,4BAA4B,CAAC;AAEjD;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,IAAI,CAAC,gBAAgB,EAAE;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACvC,sEAAsE;IACtE,8CAA8C;IAC9C,IAAI,QAAQ,KAAK,aAAa;QAAE,OAAO,IAAI,CAAC;IAC5C,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,GAAG,CAAC;IACjF,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,CACL,kBAAkB,QAAQ,oCAAoC,aAAa,KAAK;QAChF,SAAS,WAAW,8CAA8C,CACnE,CAAC;AACJ,CAAC;AAED;;yDAEyD;AACzD,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC"}
@@ -1,29 +0,0 @@
1
- import type { TodoStore } from "../../state/todos.js";
2
- import type { ToolHandler } from "../../tools/registry.js";
3
- /**
4
- * `todo_write` builtin — TodoWrite-style task tracking for maestro.
5
- *
6
- * One tool, snapshot-replace semantics: the model passes the COMPLETE list
7
- * it wants in place, and the store reconciles (upsert by id, drop entries
8
- * absent from the snapshot, auto-assign ids on new items).
9
- *
10
- * Claude Code parity:
11
- * - No separate `todo_list`. Read-side surfaces via the per-turn system
12
- * reminder, which renders the current list each turn — no extra
13
- * round-trip + no decision surface for "which tool do I call?".
14
- * - 1-in-progress invariant. The LAST `in_progress` in the incoming
15
- * snapshot wins; earlier in_progress entries are flipped to `pending`
16
- * and the demoted id is reported back so the model knows.
17
- *
18
- * Side-effecting: every call mutates the store + persists to disk.
19
- * `parallelSafe: false` is the right default — running two `todo_write`
20
- * calls in parallel would race the snapshot.
21
- */
22
- export interface TodoWriteToolOptions {
23
- /** Required. The per-session store. Built by maestroProvider via
24
- * `getTodoStore(sessionId)` so the same instance is shared across
25
- * every tool call in this turn. */
26
- store: TodoStore;
27
- }
28
- export declare function createTodoWriteTool(opts: TodoWriteToolOptions): ToolHandler;
29
- //# sourceMappingURL=todo_write.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"todo_write.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/todo_write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,eAAe,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,oBAAoB;IACnC;;wCAEoC;IACpC,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,GAAG,WAAW,CA+E3E"}