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