@posthog/agent 1.22.0 → 1.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +3 -3
- package/README.md +3 -3
- package/dist/index.d.ts +11 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/src/adapters/claude/claude-adapter.d.ts +3 -3
- package/dist/src/adapters/claude/claude-adapter.d.ts.map +1 -1
- package/dist/src/adapters/claude/claude-adapter.js +156 -111
- package/dist/src/adapters/claude/claude-adapter.js.map +1 -1
- package/dist/src/adapters/claude/tool-mapper.d.ts +1 -1
- package/dist/src/adapters/claude/tool-mapper.d.ts.map +1 -1
- package/dist/src/adapters/claude/tool-mapper.js.map +1 -1
- package/dist/src/adapters/types.d.ts +1 -1
- package/dist/src/adapters/types.d.ts.map +1 -1
- package/dist/src/agent.d.ts +7 -7
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +143 -85
- package/dist/src/agent.js.map +1 -1
- package/dist/src/agents/execution.js.map +1 -1
- package/dist/src/agents/planning.js.map +1 -1
- package/dist/src/agents/research.js.map +1 -1
- package/dist/src/file-manager.d.ts +4 -4
- package/dist/src/file-manager.d.ts.map +1 -1
- package/dist/src/file-manager.js +59 -58
- package/dist/src/file-manager.js.map +1 -1
- package/dist/src/git-manager.d.ts +1 -1
- package/dist/src/git-manager.d.ts.map +1 -1
- package/dist/src/git-manager.js +93 -69
- package/dist/src/git-manager.js.map +1 -1
- package/dist/src/posthog-api.d.ts +2 -3
- package/dist/src/posthog-api.d.ts.map +1 -1
- package/dist/src/posthog-api.js +22 -22
- package/dist/src/posthog-api.js.map +1 -1
- package/dist/src/prompt-builder.d.ts +3 -3
- package/dist/src/prompt-builder.d.ts.map +1 -1
- package/dist/src/prompt-builder.js +123 -93
- package/dist/src/prompt-builder.js.map +1 -1
- package/dist/src/task-manager.d.ts +4 -4
- package/dist/src/task-manager.d.ts.map +1 -1
- package/dist/src/task-manager.js +19 -18
- package/dist/src/task-manager.js.map +1 -1
- package/dist/src/task-progress-reporter.d.ts +3 -4
- package/dist/src/task-progress-reporter.d.ts.map +1 -1
- package/dist/src/task-progress-reporter.js +59 -54
- package/dist/src/task-progress-reporter.js.map +1 -1
- package/dist/src/template-manager.d.ts +1 -1
- package/dist/src/template-manager.d.ts.map +1 -1
- package/dist/src/template-manager.js +30 -28
- package/dist/src/template-manager.js.map +1 -1
- package/dist/src/todo-manager.d.ts +3 -3
- package/dist/src/todo-manager.d.ts.map +1 -1
- package/dist/src/todo-manager.js +29 -24
- package/dist/src/todo-manager.js.map +1 -1
- package/dist/src/tools/registry.d.ts +1 -1
- package/dist/src/tools/registry.js +60 -60
- package/dist/src/tools/registry.js.map +1 -1
- package/dist/src/tools/types.d.ts +31 -31
- package/dist/src/types.d.ts +33 -33
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/logger.d.ts +4 -4
- package/dist/src/utils/logger.d.ts.map +1 -1
- package/dist/src/utils/logger.js +8 -8
- package/dist/src/utils/logger.js.map +1 -1
- package/dist/src/workflow/config.d.ts +1 -1
- package/dist/src/workflow/config.d.ts.map +1 -1
- package/dist/src/workflow/config.js +18 -18
- package/dist/src/workflow/config.js.map +1 -1
- package/dist/src/workflow/steps/build.d.ts +1 -1
- package/dist/src/workflow/steps/build.d.ts.map +1 -1
- package/dist/src/workflow/steps/build.js +46 -38
- package/dist/src/workflow/steps/build.js.map +1 -1
- package/dist/src/workflow/steps/finalize.d.ts +1 -1
- package/dist/src/workflow/steps/finalize.d.ts.map +1 -1
- package/dist/src/workflow/steps/finalize.js +54 -48
- package/dist/src/workflow/steps/finalize.js.map +1 -1
- package/dist/src/workflow/steps/plan.d.ts +1 -1
- package/dist/src/workflow/steps/plan.d.ts.map +1 -1
- package/dist/src/workflow/steps/plan.js +58 -46
- package/dist/src/workflow/steps/plan.js.map +1 -1
- package/dist/src/workflow/steps/research.d.ts +1 -1
- package/dist/src/workflow/steps/research.d.ts.map +1 -1
- package/dist/src/workflow/steps/research.js +68 -56
- package/dist/src/workflow/steps/research.js.map +1 -1
- package/dist/src/workflow/types.d.ts +12 -12
- package/dist/src/workflow/types.d.ts.map +1 -1
- package/dist/src/workflow/utils.d.ts +1 -1
- package/dist/src/workflow/utils.d.ts.map +1 -1
- package/dist/src/workflow/utils.js +7 -4
- package/dist/src/workflow/utils.js.map +1 -1
- package/package.json +8 -8
- package/src/adapters/claude/claude-adapter.ts +220 -168
- package/src/adapters/claude/tool-mapper.ts +2 -2
- package/src/adapters/types.ts +1 -1
- package/src/agent.ts +579 -444
- package/src/agents/execution.ts +1 -1
- package/src/agents/planning.ts +1 -1
- package/src/agents/research.ts +0 -1
- package/src/file-manager.ts +64 -63
- package/src/git-manager.ts +152 -87
- package/src/posthog-api.ts +122 -82
- package/src/prompt-builder.ts +180 -135
- package/src/task-manager.ts +38 -30
- package/src/task-progress-reporter.ts +70 -59
- package/src/template-manager.ts +98 -45
- package/src/todo-manager.ts +35 -30
- package/src/tools/registry.ts +62 -62
- package/src/tools/types.ts +36 -36
- package/src/types.ts +93 -71
- package/src/utils/logger.ts +62 -56
- package/src/workflow/config.ts +48 -48
- package/src/workflow/steps/build.ts +122 -113
- package/src/workflow/steps/finalize.ts +214 -182
- package/src/workflow/steps/plan.ts +151 -131
- package/src/workflow/steps/research.ts +205 -186
- package/src/workflow/types.ts +38 -36
- package/src/workflow/utils.ts +37 -34
- package/LICENSE +0 -33
package/src/template-manager.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { promises as fs
|
|
2
|
-
import {
|
|
3
|
-
import { fileURLToPath } from
|
|
1
|
+
import { existsSync, promises as fs } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
4
|
|
|
5
5
|
export interface TemplateVariables {
|
|
6
6
|
task_id: string;
|
|
@@ -21,39 +21,71 @@ export class TemplateManager {
|
|
|
21
21
|
// Exhaustive list of possible template locations
|
|
22
22
|
const candidateDirs = [
|
|
23
23
|
// Standard build output (dist/src/template-manager.js -> dist/templates)
|
|
24
|
-
join(__dirname,
|
|
24
|
+
join(__dirname, "..", "templates"),
|
|
25
25
|
|
|
26
26
|
// If preserveModules creates nested structure (dist/src/template-manager.js -> dist/src/templates)
|
|
27
|
-
join(__dirname,
|
|
27
|
+
join(__dirname, "templates"),
|
|
28
28
|
|
|
29
29
|
// Development scenarios (src/template-manager.ts -> src/templates)
|
|
30
|
-
join(__dirname,
|
|
30
|
+
join(__dirname, "..", "..", "src", "templates"),
|
|
31
31
|
|
|
32
32
|
// Package root templates directory
|
|
33
|
-
join(__dirname,
|
|
33
|
+
join(__dirname, "..", "..", "templates"),
|
|
34
34
|
|
|
35
35
|
// When node_modules symlink or installed (node_modules/@posthog/agent/dist/src/... -> node_modules/@posthog/agent/dist/templates)
|
|
36
|
-
join(__dirname,
|
|
36
|
+
join(__dirname, "..", "..", "dist", "templates"),
|
|
37
37
|
|
|
38
38
|
// When consumed from node_modules deep in tree
|
|
39
|
-
join(__dirname,
|
|
40
|
-
join(__dirname,
|
|
41
|
-
join(__dirname,
|
|
39
|
+
join(__dirname, "..", "..", "..", "templates"),
|
|
40
|
+
join(__dirname, "..", "..", "..", "dist", "templates"),
|
|
41
|
+
join(__dirname, "..", "..", "..", "src", "templates"),
|
|
42
42
|
|
|
43
43
|
// When bundled by Vite/Webpack (e.g., .vite/build/index.js -> node_modules/@posthog/agent/dist/templates)
|
|
44
44
|
// Try to find node_modules from current location
|
|
45
|
-
join(
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
join(
|
|
46
|
+
__dirname,
|
|
47
|
+
"..",
|
|
48
|
+
"node_modules",
|
|
49
|
+
"@posthog",
|
|
50
|
+
"agent",
|
|
51
|
+
"dist",
|
|
52
|
+
"templates",
|
|
53
|
+
),
|
|
54
|
+
join(
|
|
55
|
+
__dirname,
|
|
56
|
+
"..",
|
|
57
|
+
"..",
|
|
58
|
+
"node_modules",
|
|
59
|
+
"@posthog",
|
|
60
|
+
"agent",
|
|
61
|
+
"dist",
|
|
62
|
+
"templates",
|
|
63
|
+
),
|
|
64
|
+
join(
|
|
65
|
+
__dirname,
|
|
66
|
+
"..",
|
|
67
|
+
"..",
|
|
68
|
+
"..",
|
|
69
|
+
"node_modules",
|
|
70
|
+
"@posthog",
|
|
71
|
+
"agent",
|
|
72
|
+
"dist",
|
|
73
|
+
"templates",
|
|
74
|
+
),
|
|
48
75
|
];
|
|
49
76
|
|
|
50
77
|
const resolvedDir = candidateDirs.find((dir) => existsSync(dir));
|
|
51
78
|
|
|
52
79
|
if (!resolvedDir) {
|
|
53
|
-
console.error(
|
|
54
|
-
console.error(
|
|
55
|
-
console.error(
|
|
56
|
-
console.error(
|
|
80
|
+
console.error("[TemplateManager] Could not find templates directory.");
|
|
81
|
+
console.error("[TemplateManager] Current file:", __filename);
|
|
82
|
+
console.error("[TemplateManager] Current dir:", __dirname);
|
|
83
|
+
console.error(
|
|
84
|
+
"[TemplateManager] Tried:",
|
|
85
|
+
candidateDirs
|
|
86
|
+
.map((d) => `\n - ${d} (exists: ${existsSync(d)})`)
|
|
87
|
+
.join(""),
|
|
88
|
+
);
|
|
57
89
|
}
|
|
58
90
|
|
|
59
91
|
this.templatesDir = resolvedDir ?? candidateDirs[0];
|
|
@@ -62,74 +94,95 @@ export class TemplateManager {
|
|
|
62
94
|
private async loadTemplate(templateName: string): Promise<string> {
|
|
63
95
|
try {
|
|
64
96
|
const templatePath = join(this.templatesDir, templateName);
|
|
65
|
-
return await fs.readFile(templatePath,
|
|
97
|
+
return await fs.readFile(templatePath, "utf8");
|
|
66
98
|
} catch (error) {
|
|
67
|
-
throw new Error(
|
|
99
|
+
throw new Error(
|
|
100
|
+
`Failed to load template ${templateName} from ${this.templatesDir}: ${error}`,
|
|
101
|
+
);
|
|
68
102
|
}
|
|
69
103
|
}
|
|
70
104
|
|
|
71
|
-
private substituteVariables(
|
|
105
|
+
private substituteVariables(
|
|
106
|
+
template: string,
|
|
107
|
+
variables: TemplateVariables,
|
|
108
|
+
): string {
|
|
72
109
|
let result = template;
|
|
73
|
-
|
|
110
|
+
|
|
74
111
|
for (const [key, value] of Object.entries(variables)) {
|
|
75
112
|
if (value !== undefined) {
|
|
76
|
-
const placeholder = new RegExp(`{{${key}}}`,
|
|
113
|
+
const placeholder = new RegExp(`{{${key}}}`, "g");
|
|
77
114
|
result = result.replace(placeholder, value);
|
|
78
115
|
}
|
|
79
116
|
}
|
|
80
|
-
|
|
81
|
-
result = result.replace(/{{[^}]+}}/g,
|
|
82
|
-
|
|
117
|
+
|
|
118
|
+
result = result.replace(/{{[^}]+}}/g, "[PLACEHOLDER]");
|
|
119
|
+
|
|
83
120
|
return result;
|
|
84
121
|
}
|
|
85
122
|
|
|
86
123
|
async generatePlan(variables: TemplateVariables): Promise<string> {
|
|
87
|
-
const template = await this.loadTemplate(
|
|
124
|
+
const template = await this.loadTemplate("plan-template.md");
|
|
88
125
|
return this.substituteVariables(template, {
|
|
89
126
|
...variables,
|
|
90
|
-
date: variables.date || new Date().toISOString().split(
|
|
127
|
+
date: variables.date || new Date().toISOString().split("T")[0],
|
|
91
128
|
});
|
|
92
129
|
}
|
|
93
130
|
|
|
94
|
-
async generateCustomFile(
|
|
131
|
+
async generateCustomFile(
|
|
132
|
+
templateName: string,
|
|
133
|
+
variables: TemplateVariables,
|
|
134
|
+
): Promise<string> {
|
|
95
135
|
const template = await this.loadTemplate(templateName);
|
|
96
136
|
return this.substituteVariables(template, {
|
|
97
137
|
...variables,
|
|
98
|
-
date: variables.date || new Date().toISOString().split(
|
|
138
|
+
date: variables.date || new Date().toISOString().split("T")[0],
|
|
99
139
|
});
|
|
100
140
|
}
|
|
101
141
|
|
|
102
|
-
async createTaskStructure(
|
|
103
|
-
|
|
104
|
-
|
|
142
|
+
async createTaskStructure(
|
|
143
|
+
taskId: string,
|
|
144
|
+
taskTitle: string,
|
|
145
|
+
options?: {
|
|
146
|
+
includePlan?: boolean;
|
|
147
|
+
additionalFiles?: Array<{
|
|
148
|
+
name: string;
|
|
149
|
+
template?: string;
|
|
150
|
+
content?: string;
|
|
151
|
+
}>;
|
|
152
|
+
},
|
|
153
|
+
): Promise<
|
|
154
|
+
Array<{
|
|
155
|
+
name: string;
|
|
156
|
+
content: string;
|
|
157
|
+
type: "plan" | "context" | "reference" | "output";
|
|
158
|
+
}>
|
|
159
|
+
> {
|
|
160
|
+
const files: Array<{
|
|
105
161
|
name: string;
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const files: Array<{ name: string; content: string; type: 'plan' | 'context' | 'reference' | 'output' }> = [];
|
|
111
|
-
|
|
162
|
+
content: string;
|
|
163
|
+
type: "plan" | "context" | "reference" | "output";
|
|
164
|
+
}> = [];
|
|
165
|
+
|
|
112
166
|
const variables: TemplateVariables = {
|
|
113
167
|
task_id: taskId,
|
|
114
168
|
task_title: taskTitle,
|
|
115
|
-
date: new Date().toISOString().split(
|
|
169
|
+
date: new Date().toISOString().split("T")[0],
|
|
116
170
|
};
|
|
117
171
|
|
|
118
172
|
// Generate plan file if requested
|
|
119
173
|
if (options?.includePlan !== false) {
|
|
120
174
|
const planContent = await this.generatePlan(variables);
|
|
121
175
|
files.push({
|
|
122
|
-
name:
|
|
176
|
+
name: "plan.md",
|
|
123
177
|
content: planContent,
|
|
124
|
-
type:
|
|
178
|
+
type: "plan",
|
|
125
179
|
});
|
|
126
180
|
}
|
|
127
181
|
|
|
128
|
-
|
|
129
182
|
if (options?.additionalFiles) {
|
|
130
183
|
for (const file of options.additionalFiles) {
|
|
131
184
|
let content: string;
|
|
132
|
-
|
|
185
|
+
|
|
133
186
|
if (file.template) {
|
|
134
187
|
content = await this.generateCustomFile(file.template, variables);
|
|
135
188
|
} else if (file.content) {
|
|
@@ -141,7 +194,7 @@ export class TemplateManager {
|
|
|
141
194
|
files.push({
|
|
142
195
|
name: file.name,
|
|
143
196
|
content,
|
|
144
|
-
type: file.name.includes(
|
|
197
|
+
type: file.name.includes("context") ? "context" : "reference",
|
|
145
198
|
});
|
|
146
199
|
}
|
|
147
200
|
}
|
package/src/todo-manager.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { PostHogFileManager } from
|
|
2
|
-
import { Logger } from
|
|
1
|
+
import type { PostHogFileManager } from "./file-manager.js";
|
|
2
|
+
import { Logger } from "./utils/logger.js";
|
|
3
3
|
|
|
4
4
|
export interface TodoItem {
|
|
5
5
|
content: string;
|
|
6
|
-
status:
|
|
6
|
+
status: "pending" | "in_progress" | "completed";
|
|
7
7
|
activeForm: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -24,18 +24,19 @@ export class TodoManager {
|
|
|
24
24
|
|
|
25
25
|
constructor(fileManager: PostHogFileManager, logger?: Logger) {
|
|
26
26
|
this.fileManager = fileManager;
|
|
27
|
-
this.logger =
|
|
27
|
+
this.logger =
|
|
28
|
+
logger || new Logger({ debug: false, prefix: "[TodoManager]" });
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
async readTodos(taskId: string): Promise<TodoList | null> {
|
|
31
32
|
try {
|
|
32
|
-
const content = await this.fileManager.readTaskFile(taskId,
|
|
33
|
+
const content = await this.fileManager.readTaskFile(taskId, "todos.json");
|
|
33
34
|
if (!content) {
|
|
34
35
|
return null;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
const parsed = JSON.parse(content) as TodoList;
|
|
38
|
-
this.logger.debug(
|
|
39
|
+
this.logger.debug("Loaded todos", {
|
|
39
40
|
taskId,
|
|
40
41
|
total: parsed.metadata.total,
|
|
41
42
|
pending: parsed.metadata.pending,
|
|
@@ -45,7 +46,7 @@ export class TodoManager {
|
|
|
45
46
|
|
|
46
47
|
return parsed;
|
|
47
48
|
} catch (error) {
|
|
48
|
-
this.logger.debug(
|
|
49
|
+
this.logger.debug("Failed to read todos.json", {
|
|
49
50
|
taskId,
|
|
50
51
|
error: error instanceof Error ? error.message : String(error),
|
|
51
52
|
});
|
|
@@ -54,7 +55,7 @@ export class TodoManager {
|
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
async writeTodos(taskId: string, todos: TodoList): Promise<void> {
|
|
57
|
-
this.logger.debug(
|
|
58
|
+
this.logger.debug("Writing todos", {
|
|
58
59
|
taskId,
|
|
59
60
|
total: todos.metadata.total,
|
|
60
61
|
pending: todos.metadata.pending,
|
|
@@ -63,12 +64,12 @@ export class TodoManager {
|
|
|
63
64
|
});
|
|
64
65
|
|
|
65
66
|
await this.fileManager.writeTaskFile(taskId, {
|
|
66
|
-
name:
|
|
67
|
+
name: "todos.json",
|
|
67
68
|
content: JSON.stringify(todos, null, 2),
|
|
68
|
-
type:
|
|
69
|
+
type: "artifact",
|
|
69
70
|
});
|
|
70
71
|
|
|
71
|
-
this.logger.info(
|
|
72
|
+
this.logger.info("Todos saved", {
|
|
72
73
|
taskId,
|
|
73
74
|
total: todos.metadata.total,
|
|
74
75
|
completed: todos.metadata.completed,
|
|
@@ -81,9 +82,9 @@ export class TodoManager {
|
|
|
81
82
|
if (toolInput.todos && Array.isArray(toolInput.todos)) {
|
|
82
83
|
for (const todo of toolInput.todos) {
|
|
83
84
|
items.push({
|
|
84
|
-
content: todo.content ||
|
|
85
|
-
status: todo.status ||
|
|
86
|
-
activeForm: todo.activeForm || todo.content ||
|
|
85
|
+
content: todo.content || "",
|
|
86
|
+
status: todo.status || "pending",
|
|
87
|
+
activeForm: todo.activeForm || todo.content || "",
|
|
87
88
|
});
|
|
88
89
|
}
|
|
89
90
|
}
|
|
@@ -93,11 +94,11 @@ export class TodoManager {
|
|
|
93
94
|
return { items, metadata };
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
private calculateMetadata(items: TodoItem[]): TodoList[
|
|
97
|
+
private calculateMetadata(items: TodoItem[]): TodoList["metadata"] {
|
|
97
98
|
const total = items.length;
|
|
98
|
-
const pending = items.filter((t) => t.status ===
|
|
99
|
-
const in_progress = items.filter((t) => t.status ===
|
|
100
|
-
const completed = items.filter((t) => t.status ===
|
|
99
|
+
const pending = items.filter((t) => t.status === "pending").length;
|
|
100
|
+
const in_progress = items.filter((t) => t.status === "in_progress").length;
|
|
101
|
+
const completed = items.filter((t) => t.status === "completed").length;
|
|
101
102
|
|
|
102
103
|
return {
|
|
103
104
|
total,
|
|
@@ -111,43 +112,47 @@ export class TodoManager {
|
|
|
111
112
|
async getTodoContext(taskId: string): Promise<string> {
|
|
112
113
|
const todos = await this.readTodos(taskId);
|
|
113
114
|
if (!todos || todos.items.length === 0) {
|
|
114
|
-
return
|
|
115
|
+
return "";
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
const lines: string[] = [
|
|
118
|
-
lines.push(
|
|
118
|
+
const lines: string[] = ["## Previous Todo List\n"];
|
|
119
|
+
lines.push("You previously created the following todo list:\n");
|
|
119
120
|
|
|
120
121
|
for (const item of todos.items) {
|
|
121
122
|
const statusIcon =
|
|
122
|
-
item.status ===
|
|
123
|
+
item.status === "completed"
|
|
124
|
+
? "✓"
|
|
125
|
+
: item.status === "in_progress"
|
|
126
|
+
? "▶"
|
|
127
|
+
: "○";
|
|
123
128
|
lines.push(`${statusIcon} [${item.status}] ${item.content}`);
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
lines.push(
|
|
127
|
-
`\nProgress: ${todos.metadata.completed}/${todos.metadata.total} completed\n
|
|
132
|
+
`\nProgress: ${todos.metadata.completed}/${todos.metadata.total} completed\n`,
|
|
128
133
|
);
|
|
129
134
|
|
|
130
|
-
return lines.join(
|
|
135
|
+
return lines.join("\n");
|
|
131
136
|
}
|
|
132
137
|
|
|
133
138
|
// check for TodoWrite tool call and persist if found
|
|
134
139
|
async checkAndPersistFromMessage(
|
|
135
140
|
message: any,
|
|
136
|
-
taskId: string
|
|
141
|
+
taskId: string,
|
|
137
142
|
): Promise<TodoList | null> {
|
|
138
|
-
if (message.type !==
|
|
143
|
+
if (message.type !== "assistant" || !message.message?.content) {
|
|
139
144
|
return null;
|
|
140
145
|
}
|
|
141
146
|
|
|
142
147
|
for (const block of message.message.content) {
|
|
143
|
-
if (block.type ===
|
|
148
|
+
if (block.type === "tool_use" && block.name === "TodoWrite") {
|
|
144
149
|
try {
|
|
145
|
-
this.logger.info(
|
|
150
|
+
this.logger.info("TodoWrite detected, persisting todos", { taskId });
|
|
146
151
|
|
|
147
152
|
const todoList = this.parseTodoWriteInput(block.input);
|
|
148
153
|
await this.writeTodos(taskId, todoList);
|
|
149
154
|
|
|
150
|
-
this.logger.info(
|
|
155
|
+
this.logger.info("Persisted todos successfully", {
|
|
151
156
|
taskId,
|
|
152
157
|
total: todoList.metadata.total,
|
|
153
158
|
completed: todoList.metadata.completed,
|
|
@@ -155,7 +160,7 @@ export class TodoManager {
|
|
|
155
160
|
|
|
156
161
|
return todoList;
|
|
157
162
|
} catch (error) {
|
|
158
|
-
this.logger.error(
|
|
163
|
+
this.logger.error("Failed to persist todos", {
|
|
159
164
|
taskId,
|
|
160
165
|
error: error instanceof Error ? error.message : String(error),
|
|
161
166
|
});
|
package/src/tools/registry.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Tool } from
|
|
1
|
+
import type { Tool } from "./types.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Registry of all known tools with their metadata.
|
|
@@ -6,88 +6,88 @@ import type { Tool } from './types.js';
|
|
|
6
6
|
*/
|
|
7
7
|
const TOOL_DEFINITIONS: Record<string, Tool> = {
|
|
8
8
|
// Filesystem tools
|
|
9
|
-
|
|
10
|
-
name:
|
|
11
|
-
category:
|
|
12
|
-
description:
|
|
9
|
+
Read: {
|
|
10
|
+
name: "Read",
|
|
11
|
+
category: "filesystem",
|
|
12
|
+
description: "Read file contents from the filesystem",
|
|
13
13
|
},
|
|
14
|
-
|
|
15
|
-
name:
|
|
16
|
-
category:
|
|
17
|
-
description:
|
|
14
|
+
Write: {
|
|
15
|
+
name: "Write",
|
|
16
|
+
category: "filesystem",
|
|
17
|
+
description: "Write content to a file",
|
|
18
18
|
},
|
|
19
|
-
|
|
20
|
-
name:
|
|
21
|
-
category:
|
|
22
|
-
description:
|
|
19
|
+
Edit: {
|
|
20
|
+
name: "Edit",
|
|
21
|
+
category: "filesystem",
|
|
22
|
+
description: "Edit file with find and replace operations",
|
|
23
23
|
},
|
|
24
|
-
|
|
25
|
-
name:
|
|
26
|
-
category:
|
|
27
|
-
description:
|
|
24
|
+
Glob: {
|
|
25
|
+
name: "Glob",
|
|
26
|
+
category: "filesystem",
|
|
27
|
+
description: "Find files matching a pattern",
|
|
28
28
|
},
|
|
29
|
-
|
|
30
|
-
name:
|
|
31
|
-
category:
|
|
32
|
-
description:
|
|
29
|
+
NotebookEdit: {
|
|
30
|
+
name: "NotebookEdit",
|
|
31
|
+
category: "filesystem",
|
|
32
|
+
description: "Edit Jupyter notebook cells",
|
|
33
33
|
},
|
|
34
34
|
|
|
35
35
|
// Shell tools
|
|
36
|
-
|
|
37
|
-
name:
|
|
38
|
-
category:
|
|
39
|
-
description:
|
|
36
|
+
Bash: {
|
|
37
|
+
name: "Bash",
|
|
38
|
+
category: "shell",
|
|
39
|
+
description: "Execute bash commands",
|
|
40
40
|
},
|
|
41
|
-
|
|
42
|
-
name:
|
|
43
|
-
category:
|
|
44
|
-
description:
|
|
41
|
+
BashOutput: {
|
|
42
|
+
name: "BashOutput",
|
|
43
|
+
category: "shell",
|
|
44
|
+
description: "Read output from a background bash process",
|
|
45
45
|
},
|
|
46
|
-
|
|
47
|
-
name:
|
|
48
|
-
category:
|
|
49
|
-
description:
|
|
46
|
+
KillShell: {
|
|
47
|
+
name: "KillShell",
|
|
48
|
+
category: "shell",
|
|
49
|
+
description: "Terminate a background bash process",
|
|
50
50
|
},
|
|
51
51
|
|
|
52
52
|
// Web tools
|
|
53
|
-
|
|
54
|
-
name:
|
|
55
|
-
category:
|
|
56
|
-
description:
|
|
53
|
+
WebFetch: {
|
|
54
|
+
name: "WebFetch",
|
|
55
|
+
category: "web",
|
|
56
|
+
description: "Fetch content from a URL",
|
|
57
57
|
},
|
|
58
|
-
|
|
59
|
-
name:
|
|
60
|
-
category:
|
|
61
|
-
description:
|
|
58
|
+
WebSearch: {
|
|
59
|
+
name: "WebSearch",
|
|
60
|
+
category: "web",
|
|
61
|
+
description: "Search the web",
|
|
62
62
|
},
|
|
63
63
|
|
|
64
64
|
// Search tools
|
|
65
|
-
|
|
66
|
-
name:
|
|
67
|
-
category:
|
|
68
|
-
description:
|
|
65
|
+
Grep: {
|
|
66
|
+
name: "Grep",
|
|
67
|
+
category: "search",
|
|
68
|
+
description: "Search file contents using patterns",
|
|
69
69
|
},
|
|
70
70
|
|
|
71
71
|
// Assistant tools
|
|
72
|
-
|
|
73
|
-
name:
|
|
74
|
-
category:
|
|
75
|
-
description:
|
|
72
|
+
Task: {
|
|
73
|
+
name: "Task",
|
|
74
|
+
category: "assistant",
|
|
75
|
+
description: "Launch a specialized agent for a sub-task",
|
|
76
76
|
},
|
|
77
|
-
|
|
78
|
-
name:
|
|
79
|
-
category:
|
|
80
|
-
description:
|
|
77
|
+
TodoWrite: {
|
|
78
|
+
name: "TodoWrite",
|
|
79
|
+
category: "assistant",
|
|
80
|
+
description: "Manage task list and track progress",
|
|
81
81
|
},
|
|
82
|
-
|
|
83
|
-
name:
|
|
84
|
-
category:
|
|
85
|
-
description:
|
|
82
|
+
ExitPlanMode: {
|
|
83
|
+
name: "ExitPlanMode",
|
|
84
|
+
category: "assistant",
|
|
85
|
+
description: "Exit plan mode and present plan to user",
|
|
86
86
|
},
|
|
87
|
-
|
|
88
|
-
name:
|
|
89
|
-
category:
|
|
90
|
-
description:
|
|
87
|
+
SlashCommand: {
|
|
88
|
+
name: "SlashCommand",
|
|
89
|
+
category: "assistant",
|
|
90
|
+
description: "Execute a slash command",
|
|
91
91
|
},
|
|
92
92
|
};
|
|
93
93
|
|
|
@@ -123,7 +123,7 @@ export class ToolRegistry {
|
|
|
123
123
|
*/
|
|
124
124
|
getByCategory(category: string): Tool[] {
|
|
125
125
|
return Object.values(TOOL_DEFINITIONS).filter(
|
|
126
|
-
(tool) => tool.category === category
|
|
126
|
+
(tool) => tool.category === category,
|
|
127
127
|
);
|
|
128
128
|
}
|
|
129
129
|
}
|