codebase-cli 2.0.0-pre.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/LICENSE +21 -0
- package/README.md +266 -0
- package/bin/codebase +2 -0
- package/dist/agent/agent.js +198 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/config.js +117 -0
- package/dist/agent/config.js.map +1 -0
- package/dist/agent/events.js +153 -0
- package/dist/agent/events.js.map +1 -0
- package/dist/agent/router.js +35 -0
- package/dist/agent/router.js.map +1 -0
- package/dist/agent/system-prompt.js +21 -0
- package/dist/agent/system-prompt.js.map +1 -0
- package/dist/auth/cli.js +138 -0
- package/dist/auth/cli.js.map +1 -0
- package/dist/auth/credentials.js +105 -0
- package/dist/auth/credentials.js.map +1 -0
- package/dist/auth/flow.js +222 -0
- package/dist/auth/flow.js.map +1 -0
- package/dist/auth/pkce.js +46 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/cli.js +69 -0
- package/dist/cli.js.map +1 -0
- package/dist/clipboard/copy.js +106 -0
- package/dist/clipboard/copy.js.map +1 -0
- package/dist/commands/builtins.js +203 -0
- package/dist/commands/builtins.js.map +1 -0
- package/dist/commands/registry.js +65 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/commands/types.js +2 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/compaction/engine.js +209 -0
- package/dist/compaction/engine.js.map +1 -0
- package/dist/compaction/tokens.js +79 -0
- package/dist/compaction/tokens.js.map +1 -0
- package/dist/compaction/types.js +2 -0
- package/dist/compaction/types.js.map +1 -0
- package/dist/diagnostics/checkers.js +211 -0
- package/dist/diagnostics/checkers.js.map +1 -0
- package/dist/diagnostics/engine.js +71 -0
- package/dist/diagnostics/engine.js.map +1 -0
- package/dist/diagnostics/types.js +2 -0
- package/dist/diagnostics/types.js.map +1 -0
- package/dist/dotenv/loader.js +115 -0
- package/dist/dotenv/loader.js.map +1 -0
- package/dist/glue/client.js +47 -0
- package/dist/glue/client.js.map +1 -0
- package/dist/glue/intent.js +78 -0
- package/dist/glue/intent.js.map +1 -0
- package/dist/glue/narration.js +55 -0
- package/dist/glue/narration.js.map +1 -0
- package/dist/headless/run.js +89 -0
- package/dist/headless/run.js.map +1 -0
- package/dist/hooks/manager.js +158 -0
- package/dist/hooks/manager.js.map +1 -0
- package/dist/hooks/runner.js +70 -0
- package/dist/hooks/runner.js.map +1 -0
- package/dist/hooks/types.js +2 -0
- package/dist/hooks/types.js.map +1 -0
- package/dist/memory/inject.js +12 -0
- package/dist/memory/inject.js.map +1 -0
- package/dist/memory/store.js +178 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/types.js +10 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/permissions/store.js +172 -0
- package/dist/permissions/store.js.map +1 -0
- package/dist/plan/flow.js +214 -0
- package/dist/plan/flow.js.map +1 -0
- package/dist/plan/prompts.js +69 -0
- package/dist/plan/prompts.js.map +1 -0
- package/dist/plan/store.js +37 -0
- package/dist/plan/store.js.map +1 -0
- package/dist/plan/types.js +3 -0
- package/dist/plan/types.js.map +1 -0
- package/dist/sessions/store.js +105 -0
- package/dist/sessions/store.js.map +1 -0
- package/dist/skills/loader.js +41 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/platform-loader.js +63 -0
- package/dist/skills/platform-loader.js.map +1 -0
- package/dist/skills/types.js +21 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/tools/ask-user.js +61 -0
- package/dist/tools/ask-user.js.map +1 -0
- package/dist/tools/dispatch-agent.js +178 -0
- package/dist/tools/dispatch-agent.js.map +1 -0
- package/dist/tools/edit-file.js +80 -0
- package/dist/tools/edit-file.js.map +1 -0
- package/dist/tools/errors.js +89 -0
- package/dist/tools/errors.js.map +1 -0
- package/dist/tools/file-ops.js +136 -0
- package/dist/tools/file-ops.js.map +1 -0
- package/dist/tools/file-state-cache.js +92 -0
- package/dist/tools/file-state-cache.js.map +1 -0
- package/dist/tools/git/branch.js +84 -0
- package/dist/tools/git/branch.js.map +1 -0
- package/dist/tools/git/commit.js +83 -0
- package/dist/tools/git/commit.js.map +1 -0
- package/dist/tools/git/diff.js +72 -0
- package/dist/tools/git/diff.js.map +1 -0
- package/dist/tools/git/git-helpers.js +58 -0
- package/dist/tools/git/git-helpers.js.map +1 -0
- package/dist/tools/git/log.js +70 -0
- package/dist/tools/git/log.js.map +1 -0
- package/dist/tools/git/status.js +97 -0
- package/dist/tools/git/status.js.map +1 -0
- package/dist/tools/git/worktree.js +132 -0
- package/dist/tools/git/worktree.js.map +1 -0
- package/dist/tools/glob.js +128 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.js +199 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/list-files.js +120 -0
- package/dist/tools/list-files.js.map +1 -0
- package/dist/tools/memory-tools.js +127 -0
- package/dist/tools/memory-tools.js.map +1 -0
- package/dist/tools/multi-edit.js +87 -0
- package/dist/tools/multi-edit.js.map +1 -0
- package/dist/tools/notebook-edit.js +147 -0
- package/dist/tools/notebook-edit.js.map +1 -0
- package/dist/tools/permission.js +168 -0
- package/dist/tools/permission.js.map +1 -0
- package/dist/tools/plan-mode.js +76 -0
- package/dist/tools/plan-mode.js.map +1 -0
- package/dist/tools/read-file.js +135 -0
- package/dist/tools/read-file.js.map +1 -0
- package/dist/tools/registry.js +52 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/shell.js +216 -0
- package/dist/tools/shell.js.map +1 -0
- package/dist/tools/task-store.js +70 -0
- package/dist/tools/task-store.js.map +1 -0
- package/dist/tools/tasks.js +131 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/web-fetch.js +152 -0
- package/dist/tools/web-fetch.js.map +1 -0
- package/dist/tools/web-search.js +169 -0
- package/dist/tools/web-search.js.map +1 -0
- package/dist/tools/write-file.js +70 -0
- package/dist/tools/write-file.js.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/App.js +216 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/Input.js +90 -0
- package/dist/ui/Input.js.map +1 -0
- package/dist/ui/Message.js +89 -0
- package/dist/ui/Message.js.map +1 -0
- package/dist/ui/MessageList.js +35 -0
- package/dist/ui/MessageList.js.map +1 -0
- package/dist/ui/Permission.js +39 -0
- package/dist/ui/Permission.js.map +1 -0
- package/dist/ui/Status.js +34 -0
- package/dist/ui/Status.js.map +1 -0
- package/dist/ui/TaskPanel.js +43 -0
- package/dist/ui/TaskPanel.js.map +1 -0
- package/dist/ui/Throbber.js +20 -0
- package/dist/ui/Throbber.js.map +1 -0
- package/dist/ui/ToolPanel.js +83 -0
- package/dist/ui/ToolPanel.js.map +1 -0
- package/dist/ui/UserQuery.js +38 -0
- package/dist/ui/UserQuery.js.map +1 -0
- package/dist/ui/input-state.js +210 -0
- package/dist/ui/input-state.js.map +1 -0
- package/dist/ui/wrap.js +30 -0
- package/dist/ui/wrap.js.map +1 -0
- package/dist/user-queries/store.js +60 -0
- package/dist/user-queries/store.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/tools/shell.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-agent-instance task store. Holds the in-flight checklist the model
|
|
3
|
+
* uses to plan multi-step work. UI listeners receive a snapshot of the
|
|
4
|
+
* full list on every mutation so they can re-render.
|
|
5
|
+
*/
|
|
6
|
+
export class TaskStore {
|
|
7
|
+
tasks = new Map();
|
|
8
|
+
listeners = new Set();
|
|
9
|
+
counter = 0;
|
|
10
|
+
create(input) {
|
|
11
|
+
const id = `task-${++this.counter}`;
|
|
12
|
+
const now = Date.now();
|
|
13
|
+
const task = {
|
|
14
|
+
id,
|
|
15
|
+
title: input.title,
|
|
16
|
+
description: input.description ?? null,
|
|
17
|
+
activeForm: input.activeForm ?? null,
|
|
18
|
+
status: "pending",
|
|
19
|
+
createdAt: now,
|
|
20
|
+
updatedAt: now,
|
|
21
|
+
};
|
|
22
|
+
this.tasks.set(id, task);
|
|
23
|
+
this.emit();
|
|
24
|
+
return task;
|
|
25
|
+
}
|
|
26
|
+
update(id, patch) {
|
|
27
|
+
const existing = this.tasks.get(id);
|
|
28
|
+
if (!existing) {
|
|
29
|
+
throw new Error(`Task ${id} not found.`);
|
|
30
|
+
}
|
|
31
|
+
const next = {
|
|
32
|
+
...existing,
|
|
33
|
+
title: patch.title ?? existing.title,
|
|
34
|
+
description: patch.description !== undefined ? patch.description : existing.description,
|
|
35
|
+
activeForm: patch.activeForm !== undefined ? patch.activeForm : existing.activeForm,
|
|
36
|
+
status: patch.status ?? existing.status,
|
|
37
|
+
updatedAt: Date.now(),
|
|
38
|
+
};
|
|
39
|
+
this.tasks.set(id, next);
|
|
40
|
+
this.emit();
|
|
41
|
+
return next;
|
|
42
|
+
}
|
|
43
|
+
get(id) {
|
|
44
|
+
return this.tasks.get(id);
|
|
45
|
+
}
|
|
46
|
+
list(filter) {
|
|
47
|
+
const all = Array.from(this.tasks.values());
|
|
48
|
+
if (filter?.status)
|
|
49
|
+
return all.filter((t) => t.status === filter.status);
|
|
50
|
+
return all;
|
|
51
|
+
}
|
|
52
|
+
clear() {
|
|
53
|
+
this.tasks.clear();
|
|
54
|
+
this.counter = 0;
|
|
55
|
+
this.emit();
|
|
56
|
+
}
|
|
57
|
+
subscribe(listener) {
|
|
58
|
+
this.listeners.add(listener);
|
|
59
|
+
return () => {
|
|
60
|
+
this.listeners.delete(listener);
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
emit() {
|
|
64
|
+
const snapshot = this.list();
|
|
65
|
+
for (const listener of this.listeners) {
|
|
66
|
+
listener(snapshot);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=task-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-store.js","sourceRoot":"","sources":["../../src/tools/task-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
const StatusSchema = Type.Union([
|
|
3
|
+
Type.Literal("pending"),
|
|
4
|
+
Type.Literal("in_progress"),
|
|
5
|
+
Type.Literal("completed"),
|
|
6
|
+
Type.Literal("cancelled"),
|
|
7
|
+
]);
|
|
8
|
+
// ─── create_task ─────────────────────────────────────────────
|
|
9
|
+
const CreateParams = Type.Object({
|
|
10
|
+
title: Type.String({
|
|
11
|
+
minLength: 1,
|
|
12
|
+
maxLength: 200,
|
|
13
|
+
description: "Short task name. Imperative form (e.g. 'Add OAuth refresh token').",
|
|
14
|
+
}),
|
|
15
|
+
description: Type.Optional(Type.String({ description: "Free-form longer description." })),
|
|
16
|
+
active_form: Type.Optional(Type.String({
|
|
17
|
+
description: "Verb-ing form for live display while task is in progress (e.g. 'Adding OAuth refresh token').",
|
|
18
|
+
})),
|
|
19
|
+
});
|
|
20
|
+
export function createCreateTask(ctx) {
|
|
21
|
+
return {
|
|
22
|
+
name: "create_task",
|
|
23
|
+
label: "New task",
|
|
24
|
+
description: "Add a task to the agent's checklist. Returns the task with an assigned id. Status starts as 'pending'.",
|
|
25
|
+
parameters: CreateParams,
|
|
26
|
+
executionMode: "sequential",
|
|
27
|
+
execute: async (_id, params) => {
|
|
28
|
+
const task = ctx.tasks.create({
|
|
29
|
+
title: params.title,
|
|
30
|
+
description: params.description ?? null,
|
|
31
|
+
activeForm: params.active_form ?? null,
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
content: [{ type: "text", text: `Created ${task.id}: ${task.title}` }],
|
|
35
|
+
details: task,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// ─── update_task ─────────────────────────────────────────────
|
|
41
|
+
const UpdateParams = Type.Object({
|
|
42
|
+
id: Type.String({ description: "Task id returned from create_task (e.g. 'task-3')." }),
|
|
43
|
+
status: Type.Optional(Type.Union([StatusSchema], {
|
|
44
|
+
description: "New status: pending | in_progress | completed | cancelled.",
|
|
45
|
+
})),
|
|
46
|
+
title: Type.Optional(Type.String({ minLength: 1, maxLength: 200 })),
|
|
47
|
+
description: Type.Optional(Type.String()),
|
|
48
|
+
active_form: Type.Optional(Type.String()),
|
|
49
|
+
});
|
|
50
|
+
export function createUpdateTask(ctx) {
|
|
51
|
+
return {
|
|
52
|
+
name: "update_task",
|
|
53
|
+
label: "Update task",
|
|
54
|
+
description: "Change a task's status or fields. Move tasks to 'in_progress' when you start them and 'completed' when done.",
|
|
55
|
+
parameters: UpdateParams,
|
|
56
|
+
executionMode: "sequential",
|
|
57
|
+
execute: async (_id, params) => {
|
|
58
|
+
const task = ctx.tasks.update(params.id, {
|
|
59
|
+
status: params.status,
|
|
60
|
+
title: params.title,
|
|
61
|
+
description: params.description,
|
|
62
|
+
activeForm: params.active_form,
|
|
63
|
+
});
|
|
64
|
+
return {
|
|
65
|
+
content: [{ type: "text", text: `${task.id} → ${task.status}: ${task.title}` }],
|
|
66
|
+
details: task,
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// ─── list_tasks ──────────────────────────────────────────────
|
|
72
|
+
const ListParams = Type.Object({
|
|
73
|
+
status: Type.Optional(Type.Union([StatusSchema], {
|
|
74
|
+
description: "Filter to one status. Omit to see all tasks.",
|
|
75
|
+
})),
|
|
76
|
+
});
|
|
77
|
+
export function createListTasks(ctx) {
|
|
78
|
+
return {
|
|
79
|
+
name: "list_tasks",
|
|
80
|
+
label: "Tasks",
|
|
81
|
+
description: "List all tasks, optionally filtered by status.",
|
|
82
|
+
parameters: ListParams,
|
|
83
|
+
executionMode: "parallel",
|
|
84
|
+
execute: async (_id, params) => {
|
|
85
|
+
const filter = {};
|
|
86
|
+
if (params.status)
|
|
87
|
+
filter.status = params.status;
|
|
88
|
+
const tasks = ctx.tasks.list(filter);
|
|
89
|
+
const text = tasks.length === 0
|
|
90
|
+
? params.status
|
|
91
|
+
? `No tasks with status ${params.status}.`
|
|
92
|
+
: "No tasks."
|
|
93
|
+
: tasks.map(formatLine).join("\n");
|
|
94
|
+
return {
|
|
95
|
+
content: [{ type: "text", text }],
|
|
96
|
+
details: { tasks, count: tasks.length },
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// ─── get_task ────────────────────────────────────────────────
|
|
102
|
+
const GetParams = Type.Object({
|
|
103
|
+
id: Type.String({ description: "Task id." }),
|
|
104
|
+
});
|
|
105
|
+
export function createGetTask(ctx) {
|
|
106
|
+
return {
|
|
107
|
+
name: "get_task",
|
|
108
|
+
label: "Get task",
|
|
109
|
+
description: "Fetch a single task by id. Errors if the id is unknown.",
|
|
110
|
+
parameters: GetParams,
|
|
111
|
+
executionMode: "parallel",
|
|
112
|
+
execute: async (_id, params) => {
|
|
113
|
+
const task = ctx.tasks.get(params.id);
|
|
114
|
+
if (!task)
|
|
115
|
+
throw new Error(`Task ${params.id} not found.`);
|
|
116
|
+
return {
|
|
117
|
+
content: [{ type: "text", text: formatLine(task) }],
|
|
118
|
+
details: task,
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function formatLine(task) {
|
|
124
|
+
const tag = task.status === "in_progress" ? "▶" : task.status === "completed" ? "✓" : task.status === "cancelled" ? "✗" : "○";
|
|
125
|
+
return `${tag} ${task.id} ${task.title}${task.description ? ` — ${task.description}` : ""}`;
|
|
126
|
+
}
|
|
127
|
+
// ─── factory bundle ──────────────────────────────────────────
|
|
128
|
+
export function createTaskTools(ctx) {
|
|
129
|
+
return [createCreateTask(ctx), createUpdateTask(ctx), createListTasks(ctx), createGetTask(ctx)];
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/tools/tasks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
const Params = Type.Object({
|
|
3
|
+
url: Type.String({
|
|
4
|
+
description: "Absolute http(s) URL.",
|
|
5
|
+
}),
|
|
6
|
+
method: Type.Optional(Type.Union([Type.Literal("GET"), Type.Literal("HEAD")], {
|
|
7
|
+
description: "GET (default) or HEAD.",
|
|
8
|
+
})),
|
|
9
|
+
headers: Type.Optional(Type.Record(Type.String(), Type.String(), {
|
|
10
|
+
description: "Extra request headers (e.g. Authorization, User-Agent).",
|
|
11
|
+
})),
|
|
12
|
+
timeout_ms: Type.Optional(Type.Integer({
|
|
13
|
+
minimum: 100,
|
|
14
|
+
maximum: 60_000,
|
|
15
|
+
description: "Abort after this many ms. Default 15000, max 60000.",
|
|
16
|
+
})),
|
|
17
|
+
max_bytes: Type.Optional(Type.Integer({
|
|
18
|
+
minimum: 1024,
|
|
19
|
+
maximum: 1_000_000,
|
|
20
|
+
description: "Cap on bytes returned. Default 100000, max 1000000.",
|
|
21
|
+
})),
|
|
22
|
+
});
|
|
23
|
+
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
24
|
+
const DEFAULT_MAX_BYTES = 100_000;
|
|
25
|
+
const DESCRIPTION = `Fetch an http(s) URL and return the response body as text.
|
|
26
|
+
|
|
27
|
+
Behavior:
|
|
28
|
+
- GET by default; HEAD for header-only checks.
|
|
29
|
+
- Default timeout 15s (max 60s); aborts cleanly on the agent's abort signal.
|
|
30
|
+
- Body is decoded as UTF-8 and capped at 100 KB by default; truncation reported in details.
|
|
31
|
+
- Redirects are followed automatically. The final URL is reported in details.
|
|
32
|
+
- Errors (DNS, connect, TLS) bubble up with the underlying message — they do not retry.
|
|
33
|
+
|
|
34
|
+
Use this for documentation/spec lookups when you have a URL. For discovery use web_search.`;
|
|
35
|
+
export function createWebFetch(_ctx) {
|
|
36
|
+
return {
|
|
37
|
+
name: "web_fetch",
|
|
38
|
+
label: "Fetch",
|
|
39
|
+
description: DESCRIPTION,
|
|
40
|
+
parameters: Params,
|
|
41
|
+
executionMode: "parallel",
|
|
42
|
+
execute: async (_id, params, signal) => {
|
|
43
|
+
validateUrl(params.url);
|
|
44
|
+
const method = params.method ?? "GET";
|
|
45
|
+
const timeoutMs = params.timeout_ms ?? DEFAULT_TIMEOUT_MS;
|
|
46
|
+
const maxBytes = params.max_bytes ?? DEFAULT_MAX_BYTES;
|
|
47
|
+
const startedAt = Date.now();
|
|
48
|
+
const controller = new AbortController();
|
|
49
|
+
const onUpstreamAbort = () => controller.abort();
|
|
50
|
+
signal?.addEventListener("abort", onUpstreamAbort);
|
|
51
|
+
const timer = setTimeout(() => controller.abort(new Error("timeout")), timeoutMs);
|
|
52
|
+
let response;
|
|
53
|
+
try {
|
|
54
|
+
response = await fetch(params.url, {
|
|
55
|
+
method,
|
|
56
|
+
headers: params.headers,
|
|
57
|
+
redirect: "follow",
|
|
58
|
+
signal: controller.signal,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
clearTimeout(timer);
|
|
63
|
+
signal?.removeEventListener("abort", onUpstreamAbort);
|
|
64
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
65
|
+
if (reason.toLowerCase().includes("timeout")) {
|
|
66
|
+
throw new Error(`web_fetch timed out after ${Math.round(timeoutMs / 1000)}s.`);
|
|
67
|
+
}
|
|
68
|
+
throw new Error(`web_fetch failed: ${reason}`);
|
|
69
|
+
}
|
|
70
|
+
let body = "";
|
|
71
|
+
let truncated = false;
|
|
72
|
+
let bytes = 0;
|
|
73
|
+
if (method === "GET" && response.body) {
|
|
74
|
+
const reader = response.body.getReader();
|
|
75
|
+
const chunks = [];
|
|
76
|
+
try {
|
|
77
|
+
while (true) {
|
|
78
|
+
const { done, value } = await reader.read();
|
|
79
|
+
if (done)
|
|
80
|
+
break;
|
|
81
|
+
bytes += value.byteLength;
|
|
82
|
+
if (bytes > maxBytes) {
|
|
83
|
+
truncated = true;
|
|
84
|
+
const room = maxBytes - (bytes - value.byteLength);
|
|
85
|
+
if (room > 0)
|
|
86
|
+
chunks.push(value.subarray(0, room));
|
|
87
|
+
controller.abort();
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
chunks.push(value);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
try {
|
|
95
|
+
reader.releaseLock();
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// already released
|
|
99
|
+
}
|
|
100
|
+
clearTimeout(timer);
|
|
101
|
+
signal?.removeEventListener("abort", onUpstreamAbort);
|
|
102
|
+
}
|
|
103
|
+
body = Buffer.concat(chunks.map((c) => Buffer.from(c))).toString("utf8");
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
clearTimeout(timer);
|
|
107
|
+
signal?.removeEventListener("abort", onUpstreamAbort);
|
|
108
|
+
}
|
|
109
|
+
const durationMs = Date.now() - startedAt;
|
|
110
|
+
const contentType = response.headers.get("content-type");
|
|
111
|
+
const summary = formatSummary(params.url, response, contentType, bytes, truncated, durationMs, body);
|
|
112
|
+
return {
|
|
113
|
+
content: [{ type: "text", text: summary }],
|
|
114
|
+
details: {
|
|
115
|
+
url: params.url,
|
|
116
|
+
finalUrl: response.url,
|
|
117
|
+
status: response.status,
|
|
118
|
+
statusText: response.statusText,
|
|
119
|
+
contentType,
|
|
120
|
+
bytes,
|
|
121
|
+
truncated,
|
|
122
|
+
durationMs,
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function validateUrl(raw) {
|
|
129
|
+
let parsed;
|
|
130
|
+
try {
|
|
131
|
+
parsed = new URL(raw);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
throw new Error(`Invalid URL: ${raw}`);
|
|
135
|
+
}
|
|
136
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
137
|
+
throw new Error(`URL must be http or https; got ${parsed.protocol}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function formatSummary(url, response, contentType, bytes, truncated, durationMs, body) {
|
|
141
|
+
const lines = [];
|
|
142
|
+
const finalUrl = response.url && response.url !== url ? `\nFinal: ${response.url}` : "";
|
|
143
|
+
lines.push(`${response.status} ${response.statusText} (${durationMs}ms, ${bytes} bytes${truncated ? ", truncated" : ""})${finalUrl}`);
|
|
144
|
+
if (contentType)
|
|
145
|
+
lines.push(`Content-Type: ${contentType}`);
|
|
146
|
+
if (body) {
|
|
147
|
+
lines.push("");
|
|
148
|
+
lines.push(body);
|
|
149
|
+
}
|
|
150
|
+
return lines.join("\n");
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=web-fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-fetch.js","sourceRoot":"","sources":["../../src/tools/web-fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
const Params = Type.Object({
|
|
3
|
+
query: Type.String({
|
|
4
|
+
minLength: 1,
|
|
5
|
+
maxLength: 500,
|
|
6
|
+
description: "Search query.",
|
|
7
|
+
}),
|
|
8
|
+
max_results: Type.Optional(Type.Integer({
|
|
9
|
+
minimum: 1,
|
|
10
|
+
maximum: 20,
|
|
11
|
+
description: "Number of results to return. Default 5, max 20.",
|
|
12
|
+
})),
|
|
13
|
+
timeout_ms: Type.Optional(Type.Integer({
|
|
14
|
+
minimum: 500,
|
|
15
|
+
maximum: 60_000,
|
|
16
|
+
description: "Abort the search after this many ms. Default 15000.",
|
|
17
|
+
})),
|
|
18
|
+
});
|
|
19
|
+
const DEFAULT_RESULTS = 5;
|
|
20
|
+
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
21
|
+
const DESCRIPTION = `Search the web. Returns title + url + snippet for each result, formatted so the model can pick a URL and pass it to web_fetch.
|
|
22
|
+
|
|
23
|
+
Provider auto-detected from env (highest-priority match wins):
|
|
24
|
+
- TAVILY_API_KEY → Tavily (recommended; free tier available)
|
|
25
|
+
- BRAVE_API_KEY → Brave Search
|
|
26
|
+
- SEARXNG_URL → self-hosted SearXNG instance
|
|
27
|
+
|
|
28
|
+
If none are set, this tool errors with onboarding instructions instead of attempting an unauthenticated fallback. Default 5 results, max 20.`;
|
|
29
|
+
export function createWebSearch(_ctx) {
|
|
30
|
+
return {
|
|
31
|
+
name: "web_search",
|
|
32
|
+
label: "Search",
|
|
33
|
+
description: DESCRIPTION,
|
|
34
|
+
parameters: Params,
|
|
35
|
+
executionMode: "parallel",
|
|
36
|
+
execute: async (_id, params, signal) => {
|
|
37
|
+
const provider = pickProvider(process.env);
|
|
38
|
+
const max = params.max_results ?? DEFAULT_RESULTS;
|
|
39
|
+
const timeout = params.timeout_ms ?? DEFAULT_TIMEOUT_MS;
|
|
40
|
+
const controller = new AbortController();
|
|
41
|
+
const onUpstreamAbort = () => controller.abort();
|
|
42
|
+
signal?.addEventListener("abort", onUpstreamAbort);
|
|
43
|
+
const timer = setTimeout(() => controller.abort(new Error("timeout")), timeout);
|
|
44
|
+
const startedAt = Date.now();
|
|
45
|
+
let results;
|
|
46
|
+
try {
|
|
47
|
+
results = await provider.search(params.query, max, controller.signal);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
51
|
+
if (controller.signal.aborted && !signal?.aborted) {
|
|
52
|
+
throw new Error(`web_search timed out after ${Math.round(timeout / 1000)}s.`);
|
|
53
|
+
}
|
|
54
|
+
throw new Error(`web_search (${provider.name}) failed: ${reason}`);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
clearTimeout(timer);
|
|
58
|
+
signal?.removeEventListener("abort", onUpstreamAbort);
|
|
59
|
+
}
|
|
60
|
+
const durationMs = Date.now() - startedAt;
|
|
61
|
+
return {
|
|
62
|
+
content: [{ type: "text", text: formatResults(provider.name, params.query, results) }],
|
|
63
|
+
details: { query: params.query, provider: provider.name, results, durationMs },
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export function pickProvider(env) {
|
|
69
|
+
if (env.TAVILY_API_KEY) {
|
|
70
|
+
return tavilyProvider(env.TAVILY_API_KEY, env.TAVILY_BASE_URL);
|
|
71
|
+
}
|
|
72
|
+
if (env.BRAVE_API_KEY) {
|
|
73
|
+
return braveProvider(env.BRAVE_API_KEY, env.BRAVE_BASE_URL);
|
|
74
|
+
}
|
|
75
|
+
if (env.SEARXNG_URL) {
|
|
76
|
+
return searxngProvider(env.SEARXNG_URL);
|
|
77
|
+
}
|
|
78
|
+
throw new Error("web_search has no provider configured. Set one of TAVILY_API_KEY (recommended), BRAVE_API_KEY, " +
|
|
79
|
+
"or SEARXNG_URL. Tavily offers a free tier at https://tavily.com.");
|
|
80
|
+
}
|
|
81
|
+
function tavilyProvider(apiKey, baseUrl) {
|
|
82
|
+
const url = `${baseUrl ?? "https://api.tavily.com"}/search`;
|
|
83
|
+
return {
|
|
84
|
+
name: "tavily",
|
|
85
|
+
search: async (query, max, signal) => {
|
|
86
|
+
const res = await fetch(url, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: { "Content-Type": "application/json" },
|
|
89
|
+
body: JSON.stringify({
|
|
90
|
+
api_key: apiKey,
|
|
91
|
+
query,
|
|
92
|
+
max_results: max,
|
|
93
|
+
search_depth: "basic",
|
|
94
|
+
include_answer: false,
|
|
95
|
+
}),
|
|
96
|
+
signal,
|
|
97
|
+
});
|
|
98
|
+
if (!res.ok)
|
|
99
|
+
throw new Error(`tavily ${res.status} ${res.statusText}`);
|
|
100
|
+
const json = (await res.json());
|
|
101
|
+
return (json.results ?? []).map((r) => ({
|
|
102
|
+
title: r.title,
|
|
103
|
+
url: r.url,
|
|
104
|
+
snippet: r.content,
|
|
105
|
+
}));
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function braveProvider(apiKey, baseUrl) {
|
|
110
|
+
const url = baseUrl ?? "https://api.search.brave.com/res/v1/web/search";
|
|
111
|
+
return {
|
|
112
|
+
name: "brave",
|
|
113
|
+
search: async (query, max, signal) => {
|
|
114
|
+
const u = new URL(url);
|
|
115
|
+
u.searchParams.set("q", query);
|
|
116
|
+
u.searchParams.set("count", String(max));
|
|
117
|
+
const res = await fetch(u, {
|
|
118
|
+
headers: { "X-Subscription-Token": apiKey, Accept: "application/json" },
|
|
119
|
+
signal,
|
|
120
|
+
});
|
|
121
|
+
if (!res.ok)
|
|
122
|
+
throw new Error(`brave ${res.status} ${res.statusText}`);
|
|
123
|
+
const json = (await res.json());
|
|
124
|
+
return (json.web?.results ?? []).map((r) => ({
|
|
125
|
+
title: r.title,
|
|
126
|
+
url: r.url,
|
|
127
|
+
snippet: r.description,
|
|
128
|
+
}));
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function searxngProvider(baseUrl) {
|
|
133
|
+
const root = baseUrl.replace(/\/+$/, "");
|
|
134
|
+
return {
|
|
135
|
+
name: "searxng",
|
|
136
|
+
search: async (query, max, signal) => {
|
|
137
|
+
const u = new URL(`${root}/search`);
|
|
138
|
+
u.searchParams.set("q", query);
|
|
139
|
+
u.searchParams.set("format", "json");
|
|
140
|
+
const res = await fetch(u, { signal });
|
|
141
|
+
if (!res.ok)
|
|
142
|
+
throw new Error(`searxng ${res.status} ${res.statusText}`);
|
|
143
|
+
const json = (await res.json());
|
|
144
|
+
return (json.results ?? []).slice(0, max).map((r) => ({
|
|
145
|
+
title: r.title,
|
|
146
|
+
url: r.url,
|
|
147
|
+
snippet: r.content ?? "",
|
|
148
|
+
}));
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function formatResults(provider, query, results) {
|
|
153
|
+
if (results.length === 0) {
|
|
154
|
+
return `No results for "${query}" via ${provider}.`;
|
|
155
|
+
}
|
|
156
|
+
const lines = [`${results.length} results from ${provider} for "${query}":`, ""];
|
|
157
|
+
for (let i = 0; i < results.length; i++) {
|
|
158
|
+
const r = results[i];
|
|
159
|
+
lines.push(`${i + 1}. ${r.title}`);
|
|
160
|
+
lines.push(` ${r.url}`);
|
|
161
|
+
if (r.snippet) {
|
|
162
|
+
const trimmed = r.snippet.length > 300 ? `${r.snippet.slice(0, 300)}…` : r.snippet;
|
|
163
|
+
lines.push(` ${trimmed}`);
|
|
164
|
+
}
|
|
165
|
+
lines.push("");
|
|
166
|
+
}
|
|
167
|
+
return lines.join("\n").trimEnd();
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=web-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search.js","sourceRoot":"","sources":["../../src/tools/web-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { statSync } from "node:fs";
|
|
2
|
+
import { Type } from "typebox";
|
|
3
|
+
import { atomicWrite, detectEol, pathExists, resolveInsideCwd, validateForOverwrite } from "./file-ops.js";
|
|
4
|
+
const Params = Type.Object({
|
|
5
|
+
path: Type.String({
|
|
6
|
+
description: "File path (absolute or relative to the project root). Parent directories are created automatically.",
|
|
7
|
+
}),
|
|
8
|
+
content: Type.String({
|
|
9
|
+
description: "File contents. Line endings in the content are normalized to the file's existing style on overwrite.",
|
|
10
|
+
}),
|
|
11
|
+
});
|
|
12
|
+
const DESCRIPTION = `Create a new file or overwrite an existing one.
|
|
13
|
+
|
|
14
|
+
Hard rules:
|
|
15
|
+
- To OVERWRITE an existing file, you must read it with read_file first in the current turn. Otherwise this errors with "not read first".
|
|
16
|
+
- If the file changed on disk between the last read and this write, this errors with "file unexpectedly modified" — read it again.
|
|
17
|
+
- To CREATE a new file, no prior read is required. Parent directories are created.
|
|
18
|
+
- On overwrite, BOM and line endings are preserved from the original file. On create, the encoding follows the supplied content (LF inferred from content; BOM inferred from a leading 0xEF 0xBB 0xBF in the supplied bytes).
|
|
19
|
+
- File permissions are preserved on overwrite; new files default to 0644.
|
|
20
|
+
|
|
21
|
+
Use edit_file when you only need to change part of a file — it's safer because it won't accidentally truncate context the model didn't fully read.`;
|
|
22
|
+
export function createWriteFile(ctx) {
|
|
23
|
+
return {
|
|
24
|
+
name: "write_file",
|
|
25
|
+
label: "Write",
|
|
26
|
+
description: DESCRIPTION,
|
|
27
|
+
parameters: Params,
|
|
28
|
+
executionMode: "sequential",
|
|
29
|
+
execute: async (_toolCallId, params) => {
|
|
30
|
+
const absPath = resolveInsideCwd(ctx.cwd, params.path);
|
|
31
|
+
const exists = pathExists(absPath);
|
|
32
|
+
let hasBOM = false;
|
|
33
|
+
let eol = detectEol(params.content);
|
|
34
|
+
let mode = 0o644;
|
|
35
|
+
if (exists) {
|
|
36
|
+
const snap = validateForOverwrite(absPath, ctx.fileStateCache);
|
|
37
|
+
hasBOM = snap.hasBOM;
|
|
38
|
+
eol = snap.eol;
|
|
39
|
+
mode = statSync(absPath).mode & 0o777;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
// Bare-bytes hint: a new file's content may already start with BOM characters.
|
|
43
|
+
if (params.content.charCodeAt(0) === 0xfeff) {
|
|
44
|
+
hasBOM = true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const written = atomicWrite(absPath, params.content, { hasBOM, eol, mode });
|
|
48
|
+
ctx.fileStateCache.record({
|
|
49
|
+
path: absPath,
|
|
50
|
+
content: params.content.charCodeAt(0) === 0xfeff ? params.content.slice(1) : params.content,
|
|
51
|
+
mtimeMs: written.mtimeMs,
|
|
52
|
+
size: written.size,
|
|
53
|
+
hasBOM,
|
|
54
|
+
eol,
|
|
55
|
+
isPartialView: false,
|
|
56
|
+
storedAt: Date.now(),
|
|
57
|
+
});
|
|
58
|
+
return {
|
|
59
|
+
content: [
|
|
60
|
+
{
|
|
61
|
+
type: "text",
|
|
62
|
+
text: exists ? `Overwrote ${params.path} (${written.size} bytes).` : `Created ${params.path}.`,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
details: { path: absPath, created: !exists, bytes: written.size },
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=write-file.js.map
|