verybot 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -0
- package/dist/aliases/store.d.ts +21 -0
- package/dist/aliases/store.js +148 -0
- package/dist/aliases/types.d.ts +6 -0
- package/dist/aliases/types.js +1 -0
- package/dist/brain/agent-registry.d.ts +96 -0
- package/dist/brain/agent-registry.js +141 -0
- package/dist/brain/agent.d.ts +167 -0
- package/dist/brain/agent.js +932 -0
- package/dist/brain/channel-store.d.ts +27 -0
- package/dist/brain/channel-store.js +78 -0
- package/dist/brain/compaction.d.ts +37 -0
- package/dist/brain/compaction.js +214 -0
- package/dist/brain/context.d.ts +43 -0
- package/dist/brain/context.js +139 -0
- package/dist/brain/delegation-store.d.ts +33 -0
- package/dist/brain/delegation-store.js +106 -0
- package/dist/brain/loop.d.ts +24 -0
- package/dist/brain/loop.js +318 -0
- package/dist/brain/mcp-adapter.d.ts +43 -0
- package/dist/brain/mcp-adapter.js +244 -0
- package/dist/brain/memory-extractor.d.ts +26 -0
- package/dist/brain/memory-extractor.js +82 -0
- package/dist/brain/providers.d.ts +14 -0
- package/dist/brain/providers.js +85 -0
- package/dist/brain/queue.d.ts +18 -0
- package/dist/brain/queue.js +111 -0
- package/dist/brain/run-tools.d.ts +50 -0
- package/dist/brain/run-tools.js +136 -0
- package/dist/brain/session-key.d.ts +23 -0
- package/dist/brain/session-key.js +41 -0
- package/dist/brain/session-state.d.ts +36 -0
- package/dist/brain/session-state.js +51 -0
- package/dist/brain/session-store.d.ts +50 -0
- package/dist/brain/session-store.js +207 -0
- package/dist/brain/session.d.ts +32 -0
- package/dist/brain/session.js +75 -0
- package/dist/brain/task-subscriber.d.ts +56 -0
- package/dist/brain/task-subscriber.js +317 -0
- package/dist/brain/user-content.d.ts +16 -0
- package/dist/brain/user-content.js +32 -0
- package/dist/brain/utils.d.ts +4 -0
- package/dist/brain/utils.js +26 -0
- package/dist/brain/worker-coordinator.d.ts +25 -0
- package/dist/brain/worker-coordinator.js +83 -0
- package/dist/channels/commands.d.ts +50 -0
- package/dist/channels/commands.js +132 -0
- package/dist/channels/discord/channel.d.ts +29 -0
- package/dist/channels/discord/channel.js +159 -0
- package/dist/channels/discord/markdown.d.ts +19 -0
- package/dist/channels/discord/markdown.js +62 -0
- package/dist/channels/manager.d.ts +29 -0
- package/dist/channels/manager.js +100 -0
- package/dist/channels/slack/channel.d.ts +37 -0
- package/dist/channels/slack/channel.js +227 -0
- package/dist/channels/slack/markdown.d.ts +19 -0
- package/dist/channels/slack/markdown.js +62 -0
- package/dist/channels/specs.d.ts +32 -0
- package/dist/channels/specs.js +99 -0
- package/dist/channels/telegram/channel.d.ts +29 -0
- package/dist/channels/telegram/channel.js +182 -0
- package/dist/channels/telegram/markdown.d.ts +17 -0
- package/dist/channels/telegram/markdown.js +66 -0
- package/dist/channels/types.d.ts +26 -0
- package/dist/channels/types.js +1 -0
- package/dist/channels/whatsapp/channel.d.ts +34 -0
- package/dist/channels/whatsapp/channel.js +276 -0
- package/dist/channels/whatsapp/markdown.d.ts +20 -0
- package/dist/channels/whatsapp/markdown.js +51 -0
- package/dist/cli/claude-login.d.ts +5 -0
- package/dist/cli/claude-login.js +47 -0
- package/dist/cli/config.d.ts +5 -0
- package/dist/cli/config.js +78 -0
- package/dist/cli/index.d.ts +11 -0
- package/dist/cli/index.js +96 -0
- package/dist/computer/browser/actions.d.ts +31 -0
- package/dist/computer/browser/actions.js +148 -0
- package/dist/computer/browser/context-manager.d.ts +28 -0
- package/dist/computer/browser/context-manager.js +78 -0
- package/dist/computer/browser/manager.d.ts +91 -0
- package/dist/computer/browser/manager.js +344 -0
- package/dist/computer/browser/profile-badge.d.ts +13 -0
- package/dist/computer/browser/profile-badge.js +67 -0
- package/dist/computer/browser/screenshot.d.ts +5 -0
- package/dist/computer/browser/screenshot.js +21 -0
- package/dist/computer/browser/snapshot.d.ts +30 -0
- package/dist/computer/browser/snapshot.js +242 -0
- package/dist/computer/browser/tools.d.ts +5 -0
- package/dist/computer/browser/tools.js +167 -0
- package/dist/computer/browser/types.d.ts +26 -0
- package/dist/computer/browser/types.js +1 -0
- package/dist/computer/desktop/adapter.d.ts +25 -0
- package/dist/computer/desktop/adapter.js +11 -0
- package/dist/computer/desktop/macos.d.ts +24 -0
- package/dist/computer/desktop/macos.js +223 -0
- package/dist/computer/desktop/tools.d.ts +25 -0
- package/dist/computer/desktop/tools.js +114 -0
- package/dist/config/agent-config.d.ts +55 -0
- package/dist/config/agent-config.js +16 -0
- package/dist/config/model-catalog.d.ts +22 -0
- package/dist/config/model-catalog.js +112 -0
- package/dist/config/model-spec.d.ts +8 -0
- package/dist/config/model-spec.js +66 -0
- package/dist/config/store.d.ts +25 -0
- package/dist/config/store.js +143 -0
- package/dist/config.d.ts +110 -0
- package/dist/config.js +259 -0
- package/dist/control-ui/assets/index-Cbl7G5Sc.css +1 -0
- package/dist/control-ui/assets/index-Cu1P4C62.js +266 -0
- package/dist/control-ui/assets/noto-sans-cyrillic-ext-wght-normal-DSNfmdVt.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-cyrillic-wght-normal-B2hlT84T.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-devanagari-wght-normal-Cv-Vwajv.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-greek-ext-wght-normal-12T8GTDR.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-greek-wght-normal-Ymb6dZNd.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-latin-ext-wght-normal-W1qJv59z.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-latin-wght-normal-BYSzYMf3.woff2 +0 -0
- package/dist/control-ui/assets/noto-sans-vietnamese-wght-normal-DLTJy58D.woff2 +0 -0
- package/dist/control-ui/index.html +14 -0
- package/dist/control-ui/vite.svg +1 -0
- package/dist/events.d.ts +2 -0
- package/dist/events.js +11 -0
- package/dist/gateway/broadcast.d.ts +5 -0
- package/dist/gateway/broadcast.js +33 -0
- package/dist/gateway/methods/aliases.d.ts +17 -0
- package/dist/gateway/methods/aliases.js +22 -0
- package/dist/gateway/methods/chat.d.ts +33 -0
- package/dist/gateway/methods/chat.js +37 -0
- package/dist/gateway/methods/config.d.ts +14 -0
- package/dist/gateway/methods/config.js +24 -0
- package/dist/gateway/methods/models.d.ts +10 -0
- package/dist/gateway/methods/models.js +14 -0
- package/dist/gateway/methods/playbooks.d.ts +45 -0
- package/dist/gateway/methods/playbooks.js +488 -0
- package/dist/gateway/methods/prompt-templates.d.ts +27 -0
- package/dist/gateway/methods/prompt-templates.js +106 -0
- package/dist/gateway/methods/scheduler.d.ts +62 -0
- package/dist/gateway/methods/scheduler.js +129 -0
- package/dist/gateway/methods/sessions.d.ts +44 -0
- package/dist/gateway/methods/sessions.js +111 -0
- package/dist/gateway/methods/system.d.ts +12 -0
- package/dist/gateway/methods/system.js +39 -0
- package/dist/gateway/methods/tasks.d.ts +40 -0
- package/dist/gateway/methods/tasks.js +151 -0
- package/dist/gateway/methods/teams.d.ts +69 -0
- package/dist/gateway/methods/teams.js +376 -0
- package/dist/gateway/methods/tools.d.ts +6 -0
- package/dist/gateway/methods/tools.js +7 -0
- package/dist/gateway/methods/whatsapp.d.ts +19 -0
- package/dist/gateway/methods/whatsapp.js +35 -0
- package/dist/gateway/rpc.d.ts +38 -0
- package/dist/gateway/rpc.js +79 -0
- package/dist/gateway/server.d.ts +9 -0
- package/dist/gateway/server.js +137 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +254 -0
- package/dist/integrations/github.d.ts +7 -0
- package/dist/integrations/github.js +133 -0
- package/dist/integrations/mcp.d.ts +7 -0
- package/dist/integrations/mcp.js +106 -0
- package/dist/integrations/registry.d.ts +47 -0
- package/dist/integrations/registry.js +332 -0
- package/dist/integrations/scanner.d.ts +10 -0
- package/dist/integrations/scanner.js +122 -0
- package/dist/integrations/twitter.d.ts +10 -0
- package/dist/integrations/twitter.js +120 -0
- package/dist/integrations/types.d.ts +72 -0
- package/dist/integrations/types.js +1 -0
- package/dist/logger.d.ts +16 -0
- package/dist/logger.js +104 -0
- package/dist/markdown/chunk.d.ts +9 -0
- package/dist/markdown/chunk.js +52 -0
- package/dist/markdown/ir.d.ts +37 -0
- package/dist/markdown/ir.js +529 -0
- package/dist/markdown/render.d.ts +22 -0
- package/dist/markdown/render.js +148 -0
- package/dist/markdown/table-render.d.ts +43 -0
- package/dist/markdown/table-render.js +219 -0
- package/dist/markdown/tables.d.ts +17 -0
- package/dist/markdown/tables.js +27 -0
- package/dist/memory/embedding.d.ts +16 -0
- package/dist/memory/embedding.js +66 -0
- package/dist/memory/explicit.d.ts +16 -0
- package/dist/memory/explicit.js +29 -0
- package/dist/memory/extractor.d.ts +13 -0
- package/dist/memory/extractor.js +82 -0
- package/dist/memory/search.d.ts +15 -0
- package/dist/memory/search.js +57 -0
- package/dist/memory/session-learning.d.ts +23 -0
- package/dist/memory/session-learning.js +55 -0
- package/dist/memory/store.d.ts +36 -0
- package/dist/memory/store.js +334 -0
- package/dist/memory/types.d.ts +9 -0
- package/dist/memory/types.js +2 -0
- package/dist/paths.d.ts +28 -0
- package/dist/paths.js +48 -0
- package/dist/prompt-templates/builtins/index.d.ts +4 -0
- package/dist/prompt-templates/builtins/index.js +5 -0
- package/dist/prompt-templates/builtins/planner.d.ts +4 -0
- package/dist/prompt-templates/builtins/planner.js +77 -0
- package/dist/prompt-templates/store.d.ts +45 -0
- package/dist/prompt-templates/store.js +224 -0
- package/dist/prompt-templates/types.d.ts +10 -0
- package/dist/prompt-templates/types.js +1 -0
- package/dist/scheduler/connected-channels.d.ts +24 -0
- package/dist/scheduler/connected-channels.js +57 -0
- package/dist/scheduler/scheduler.d.ts +22 -0
- package/dist/scheduler/scheduler.js +132 -0
- package/dist/scheduler/store.d.ts +27 -0
- package/dist/scheduler/store.js +205 -0
- package/dist/scheduler/types.d.ts +29 -0
- package/dist/scheduler/types.js +1 -0
- package/dist/security/command-validator.d.ts +22 -0
- package/dist/security/command-validator.js +160 -0
- package/dist/security/docker-sandbox.d.ts +48 -0
- package/dist/security/docker-sandbox.js +218 -0
- package/dist/security/env-filter.d.ts +8 -0
- package/dist/security/env-filter.js +41 -0
- package/dist/skills/loader.d.ts +33 -0
- package/dist/skills/loader.js +132 -0
- package/dist/skills/prompt.d.ts +6 -0
- package/dist/skills/prompt.js +17 -0
- package/dist/skills/read-tool.d.ts +7 -0
- package/dist/skills/read-tool.js +24 -0
- package/dist/skills/scanner.d.ts +6 -0
- package/dist/skills/scanner.js +73 -0
- package/dist/skills/types.d.ts +15 -0
- package/dist/skills/types.js +1 -0
- package/dist/tasks/inline-attachment-content.d.ts +9 -0
- package/dist/tasks/inline-attachment-content.js +64 -0
- package/dist/tasks/store.d.ts +112 -0
- package/dist/tasks/store.js +519 -0
- package/dist/tasks/types.d.ts +129 -0
- package/dist/tasks/types.js +80 -0
- package/dist/teams/status-config.d.ts +8 -0
- package/dist/teams/status-config.js +40 -0
- package/dist/teams/store.d.ts +111 -0
- package/dist/teams/store.js +671 -0
- package/dist/teams/types.d.ts +30 -0
- package/dist/teams/types.js +1 -0
- package/dist/tools/bash.d.ts +18 -0
- package/dist/tools/bash.js +64 -0
- package/dist/tools/channel-history.d.ts +10 -0
- package/dist/tools/channel-history.js +43 -0
- package/dist/tools/delegate.d.ts +20 -0
- package/dist/tools/delegate.js +299 -0
- package/dist/tools/fs.d.ts +4 -0
- package/dist/tools/fs.js +335 -0
- package/dist/tools/integration-toggle.d.ts +14 -0
- package/dist/tools/integration-toggle.js +47 -0
- package/dist/tools/memory.d.ts +13 -0
- package/dist/tools/memory.js +59 -0
- package/dist/tools/prompt-templates.d.ts +7 -0
- package/dist/tools/prompt-templates.js +133 -0
- package/dist/tools/registry.d.ts +6 -0
- package/dist/tools/registry.js +9 -0
- package/dist/tools/schedule.d.ts +8 -0
- package/dist/tools/schedule.js +219 -0
- package/dist/tools/speak.d.ts +10 -0
- package/dist/tools/speak.js +56 -0
- package/dist/tools/tasks.d.ts +67 -0
- package/dist/tools/tasks.js +288 -0
- package/dist/tools/teams.d.ts +22 -0
- package/dist/tools/teams.js +470 -0
- package/dist/tools/web-fetch.d.ts +3 -0
- package/dist/tools/web-fetch.js +22 -0
- package/dist/tts/edge.d.ts +10 -0
- package/dist/tts/edge.js +60 -0
- package/dist/tts/speak.d.ts +12 -0
- package/dist/tts/speak.js +81 -0
- package/dist/tts/transcribe.d.ts +5 -0
- package/dist/tts/transcribe.js +40 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +22 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +13 -0
- package/package.json +102 -0
- package/verybot.js +2 -0
package/dist/tools/fs.js
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { tool } from "ai";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { readFile, writeFile, mkdir, readdir } from "fs/promises";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import { dirname, resolve } from "path";
|
|
6
|
+
import { sanitizeEnv } from "../security/env-filter.js";
|
|
7
|
+
import { logger } from "../logger.js";
|
|
8
|
+
/* ------------------------------------------------------------------ */
|
|
9
|
+
/* Constants */
|
|
10
|
+
/* ------------------------------------------------------------------ */
|
|
11
|
+
const MAX_OUTPUT = 10_000;
|
|
12
|
+
const DEFAULT_LINE_LIMIT = 2_000;
|
|
13
|
+
const DEFAULT_SEARCH_LIMIT = 200;
|
|
14
|
+
const EXEC_TIMEOUT = 15_000;
|
|
15
|
+
/* ------------------------------------------------------------------ */
|
|
16
|
+
/* Helpers */
|
|
17
|
+
/* ------------------------------------------------------------------ */
|
|
18
|
+
function sliceLines(text, offset, limit) {
|
|
19
|
+
const lines = text.split("\n");
|
|
20
|
+
const start = Math.max(0, offset);
|
|
21
|
+
const end = Math.min(lines.length, start + limit);
|
|
22
|
+
return lines
|
|
23
|
+
.slice(start, end)
|
|
24
|
+
.map((line, i) => `${start + i + 1}\t${line}`)
|
|
25
|
+
.join("\n");
|
|
26
|
+
}
|
|
27
|
+
function truncate(text, max = MAX_OUTPUT) {
|
|
28
|
+
if (text.length <= max)
|
|
29
|
+
return text;
|
|
30
|
+
return text.slice(0, max) + "\n…[truncated]";
|
|
31
|
+
}
|
|
32
|
+
/** Truncate output to N lines (for limiting search results in JS). */
|
|
33
|
+
function truncateLines(text, maxLines) {
|
|
34
|
+
const lines = text.split("\n");
|
|
35
|
+
if (lines.length <= maxLines)
|
|
36
|
+
return text;
|
|
37
|
+
return lines.slice(0, maxLines).join("\n") + "\n…[truncated]";
|
|
38
|
+
}
|
|
39
|
+
let rgAvailable = null;
|
|
40
|
+
function isRipgrepAvailable() {
|
|
41
|
+
if (rgAvailable === null) {
|
|
42
|
+
try {
|
|
43
|
+
execSync("rg --version", { stdio: "ignore", timeout: 3_000 });
|
|
44
|
+
rgAvailable = true;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
rgAvailable = false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return rgAvailable;
|
|
51
|
+
}
|
|
52
|
+
function shellEscape(arg) {
|
|
53
|
+
if (arg.includes("\0")) {
|
|
54
|
+
throw new Error("Null bytes not allowed in shell arguments");
|
|
55
|
+
}
|
|
56
|
+
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
57
|
+
}
|
|
58
|
+
/* ------------------------------------------------------------------ */
|
|
59
|
+
/* Tools */
|
|
60
|
+
/* ------------------------------------------------------------------ */
|
|
61
|
+
const readTool = tool({
|
|
62
|
+
description: "Read a file from the filesystem. Returns numbered lines. " +
|
|
63
|
+
"Use offset/limit for large files.",
|
|
64
|
+
inputSchema: z.object({
|
|
65
|
+
path: z.string().describe("Absolute or relative file path"),
|
|
66
|
+
offset: z
|
|
67
|
+
.number()
|
|
68
|
+
.int()
|
|
69
|
+
.min(0)
|
|
70
|
+
.optional()
|
|
71
|
+
.describe("0-based line offset to start reading from"),
|
|
72
|
+
limit: z
|
|
73
|
+
.number()
|
|
74
|
+
.int()
|
|
75
|
+
.min(1)
|
|
76
|
+
.optional()
|
|
77
|
+
.describe("Max number of lines to return"),
|
|
78
|
+
}),
|
|
79
|
+
execute: async ({ path, offset, limit }) => {
|
|
80
|
+
try {
|
|
81
|
+
const content = await readFile(resolve(path), "utf-8");
|
|
82
|
+
const lineOffset = offset ?? 0;
|
|
83
|
+
const lineLimit = limit ?? DEFAULT_LINE_LIMIT;
|
|
84
|
+
return truncate(sliceLines(content, lineOffset, lineLimit));
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
88
|
+
logger.warn(`read failed: ${msg}`);
|
|
89
|
+
return `Error: ${msg}`;
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
const writeTool = tool({
|
|
94
|
+
description: "Write content to a file. Creates parent directories if needed. " +
|
|
95
|
+
"Overwrites existing files.",
|
|
96
|
+
inputSchema: z.object({
|
|
97
|
+
path: z.string().describe("Absolute or relative file path"),
|
|
98
|
+
content: z.string().describe("File content to write"),
|
|
99
|
+
}),
|
|
100
|
+
execute: async ({ path, content }) => {
|
|
101
|
+
try {
|
|
102
|
+
const resolved = resolve(path);
|
|
103
|
+
await mkdir(dirname(resolved), { recursive: true });
|
|
104
|
+
await writeFile(resolved, content, "utf-8");
|
|
105
|
+
return `Wrote ${content.split("\n").length} lines to ${resolved}`;
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
109
|
+
logger.warn(`write failed: ${msg}`);
|
|
110
|
+
return `Error: ${msg}`;
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
const editTool = tool({
|
|
115
|
+
description: "Edit a file by replacing an exact text match. " +
|
|
116
|
+
"oldText must appear exactly once in the file.",
|
|
117
|
+
inputSchema: z.object({
|
|
118
|
+
path: z.string().describe("Absolute or relative file path"),
|
|
119
|
+
oldText: z.string().min(1).describe("Exact text to find (must be unique in file)"),
|
|
120
|
+
newText: z.string().describe("Replacement text"),
|
|
121
|
+
}),
|
|
122
|
+
execute: async ({ path, oldText, newText }) => {
|
|
123
|
+
try {
|
|
124
|
+
const resolved = resolve(path);
|
|
125
|
+
const content = await readFile(resolved, "utf-8");
|
|
126
|
+
const occurrences = content.split(oldText).length - 1;
|
|
127
|
+
if (occurrences === 0) {
|
|
128
|
+
return "Error: oldText not found in file";
|
|
129
|
+
}
|
|
130
|
+
if (occurrences > 1) {
|
|
131
|
+
return `Error: oldText found ${occurrences} times — must be unique. Provide more surrounding context.`;
|
|
132
|
+
}
|
|
133
|
+
// Use function replacement to avoid special pattern interpretation ($&, $`, etc.)
|
|
134
|
+
const updated = content.replace(oldText, () => newText);
|
|
135
|
+
await writeFile(resolved, updated, "utf-8");
|
|
136
|
+
return `Edited ${resolved} — replaced 1 occurrence`;
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
140
|
+
logger.warn(`edit failed: ${msg}`);
|
|
141
|
+
return `Error: ${msg}`;
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
const grepTool = tool({
|
|
146
|
+
description: "Search file contents using ripgrep (rg) or grep. " +
|
|
147
|
+
"Returns matching lines with file paths and line numbers.",
|
|
148
|
+
inputSchema: z.object({
|
|
149
|
+
pattern: z.string().describe("Search pattern (regex unless literal=true)"),
|
|
150
|
+
path: z
|
|
151
|
+
.string()
|
|
152
|
+
.optional()
|
|
153
|
+
.describe("Directory or file to search (default: cwd)"),
|
|
154
|
+
glob: z
|
|
155
|
+
.string()
|
|
156
|
+
.optional()
|
|
157
|
+
.describe("File glob filter, e.g. '*.ts'"),
|
|
158
|
+
ignoreCase: z
|
|
159
|
+
.boolean()
|
|
160
|
+
.optional()
|
|
161
|
+
.describe("Case-insensitive search"),
|
|
162
|
+
literal: z
|
|
163
|
+
.boolean()
|
|
164
|
+
.optional()
|
|
165
|
+
.describe("Treat pattern as literal string, not regex"),
|
|
166
|
+
context: z
|
|
167
|
+
.number()
|
|
168
|
+
.int()
|
|
169
|
+
.min(0)
|
|
170
|
+
.optional()
|
|
171
|
+
.describe("Lines of context around each match"),
|
|
172
|
+
limit: z
|
|
173
|
+
.number()
|
|
174
|
+
.int()
|
|
175
|
+
.min(1)
|
|
176
|
+
.optional()
|
|
177
|
+
.describe("Max number of result lines to return"),
|
|
178
|
+
}),
|
|
179
|
+
execute: async ({ pattern, path, glob: fileGlob, ignoreCase, literal, context, limit }) => {
|
|
180
|
+
const searchPath = resolve(path ?? ".");
|
|
181
|
+
const maxLines = limit ?? DEFAULT_SEARCH_LIMIT;
|
|
182
|
+
try {
|
|
183
|
+
let cmd;
|
|
184
|
+
if (isRipgrepAvailable()) {
|
|
185
|
+
const args = ["rg", "--no-heading", "-n"];
|
|
186
|
+
if (ignoreCase)
|
|
187
|
+
args.push("-i");
|
|
188
|
+
if (literal)
|
|
189
|
+
args.push("-F");
|
|
190
|
+
if (context)
|
|
191
|
+
args.push("-C", String(context));
|
|
192
|
+
if (fileGlob)
|
|
193
|
+
args.push("--glob", fileGlob);
|
|
194
|
+
args.push("--", pattern, searchPath);
|
|
195
|
+
cmd = args.map(shellEscape).join(" ");
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
const args = ["grep", "-rn"];
|
|
199
|
+
if (ignoreCase)
|
|
200
|
+
args.push("-i");
|
|
201
|
+
if (literal)
|
|
202
|
+
args.push("-F");
|
|
203
|
+
if (context)
|
|
204
|
+
args.push("-C", String(context));
|
|
205
|
+
if (fileGlob)
|
|
206
|
+
args.push("--include", fileGlob);
|
|
207
|
+
args.push("--", pattern, searchPath);
|
|
208
|
+
cmd = args.map(shellEscape).join(" ");
|
|
209
|
+
}
|
|
210
|
+
const output = execSync(cmd, {
|
|
211
|
+
encoding: "utf-8",
|
|
212
|
+
timeout: EXEC_TIMEOUT,
|
|
213
|
+
maxBuffer: 2 * 1024 * 1024,
|
|
214
|
+
env: sanitizeEnv(),
|
|
215
|
+
});
|
|
216
|
+
return truncate(truncateLines(output || "No matches found", maxLines));
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
// grep/rg exit code 1 = no matches (not an error)
|
|
220
|
+
const code = err.status;
|
|
221
|
+
if (code === 1)
|
|
222
|
+
return "No matches found";
|
|
223
|
+
const stderr = err.stderr ?? "";
|
|
224
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
225
|
+
logger.warn(`grep failed: ${msg}`);
|
|
226
|
+
return `Error: ${stderr || msg}`.slice(0, MAX_OUTPUT);
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
const findTool = tool({
|
|
231
|
+
description: "Find files by name pattern. Uses the system `find` command. " +
|
|
232
|
+
"Returns matching file paths.",
|
|
233
|
+
inputSchema: z.object({
|
|
234
|
+
pattern: z
|
|
235
|
+
.string()
|
|
236
|
+
.describe("Filename glob pattern, e.g. '*.ts' or 'index.*'"),
|
|
237
|
+
path: z
|
|
238
|
+
.string()
|
|
239
|
+
.optional()
|
|
240
|
+
.describe("Directory to search in (default: cwd)"),
|
|
241
|
+
limit: z
|
|
242
|
+
.number()
|
|
243
|
+
.int()
|
|
244
|
+
.min(1)
|
|
245
|
+
.optional()
|
|
246
|
+
.describe("Max number of results"),
|
|
247
|
+
}),
|
|
248
|
+
execute: async ({ pattern, path, limit }) => {
|
|
249
|
+
const searchPath = resolve(path ?? ".");
|
|
250
|
+
const maxResults = limit ?? DEFAULT_SEARCH_LIMIT;
|
|
251
|
+
try {
|
|
252
|
+
const cmd = [
|
|
253
|
+
"find",
|
|
254
|
+
shellEscape(searchPath),
|
|
255
|
+
"-name",
|
|
256
|
+
shellEscape(pattern),
|
|
257
|
+
"-not",
|
|
258
|
+
"-path",
|
|
259
|
+
shellEscape("*/node_modules/*"),
|
|
260
|
+
"-not",
|
|
261
|
+
"-path",
|
|
262
|
+
shellEscape("*/.git/*"),
|
|
263
|
+
].join(" ");
|
|
264
|
+
const output = execSync(cmd, {
|
|
265
|
+
encoding: "utf-8",
|
|
266
|
+
timeout: EXEC_TIMEOUT,
|
|
267
|
+
maxBuffer: 2 * 1024 * 1024,
|
|
268
|
+
env: sanitizeEnv(),
|
|
269
|
+
});
|
|
270
|
+
return truncate(truncateLines(output || "No files found", maxResults));
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
274
|
+
logger.warn(`find failed: ${msg}`);
|
|
275
|
+
return `Error: ${msg}`.slice(0, MAX_OUTPUT);
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
const lsTool = tool({
|
|
280
|
+
description: "List directory contents with type indicators. " +
|
|
281
|
+
"Directories end with /, symlinks with @.",
|
|
282
|
+
inputSchema: z.object({
|
|
283
|
+
path: z
|
|
284
|
+
.string()
|
|
285
|
+
.optional()
|
|
286
|
+
.describe("Directory to list (default: cwd)"),
|
|
287
|
+
limit: z
|
|
288
|
+
.number()
|
|
289
|
+
.int()
|
|
290
|
+
.min(1)
|
|
291
|
+
.optional()
|
|
292
|
+
.describe("Max number of entries to return"),
|
|
293
|
+
}),
|
|
294
|
+
execute: async ({ path, limit }) => {
|
|
295
|
+
const dirPath = resolve(path ?? ".");
|
|
296
|
+
const maxEntries = limit ?? DEFAULT_SEARCH_LIMIT;
|
|
297
|
+
try {
|
|
298
|
+
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
299
|
+
const lines = entries.slice(0, maxEntries).map((entry) => {
|
|
300
|
+
if (entry.isDirectory())
|
|
301
|
+
return `${entry.name}/`;
|
|
302
|
+
if (entry.isSymbolicLink())
|
|
303
|
+
return `${entry.name}@`;
|
|
304
|
+
return entry.name;
|
|
305
|
+
});
|
|
306
|
+
if (entries.length > maxEntries) {
|
|
307
|
+
lines.push(`…and ${entries.length - maxEntries} more`);
|
|
308
|
+
}
|
|
309
|
+
return lines.join("\n") || "(empty directory)";
|
|
310
|
+
}
|
|
311
|
+
catch (err) {
|
|
312
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
313
|
+
logger.warn(`ls failed: ${msg}`);
|
|
314
|
+
return `Error: ${msg}`;
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
});
|
|
318
|
+
/* ------------------------------------------------------------------ */
|
|
319
|
+
/* Export */
|
|
320
|
+
/* ------------------------------------------------------------------ */
|
|
321
|
+
const SANDBOX_ERROR = "Error: This tool is disabled in sandbox mode. Use bash instead (cat, tee, grep, find, ls).";
|
|
322
|
+
function sandboxGuard(t) {
|
|
323
|
+
return { ...t, execute: async () => SANDBOX_ERROR };
|
|
324
|
+
}
|
|
325
|
+
export function createFsTools(opts) {
|
|
326
|
+
const wrap = opts?.sandboxed ? sandboxGuard : (t) => t;
|
|
327
|
+
return {
|
|
328
|
+
read: wrap(readTool),
|
|
329
|
+
write: wrap(writeTool),
|
|
330
|
+
edit: wrap(editTool),
|
|
331
|
+
grep: wrap(grepTool),
|
|
332
|
+
find: wrap(findTool),
|
|
333
|
+
ls: wrap(lsTool),
|
|
334
|
+
};
|
|
335
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IntegrationRegistry } from "../integrations/registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* Create enable_integration and disable_integration tools.
|
|
4
|
+
* These mutate the session's active integrations set so that
|
|
5
|
+
* subsequent runs include/exclude the integration tools.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createIntegrationToggleTools(registry: IntegrationRegistry, activeIntegrations: Set<string>): {
|
|
8
|
+
enable_integration: import("ai").Tool<{
|
|
9
|
+
name: string;
|
|
10
|
+
}, string>;
|
|
11
|
+
disable_integration: import("ai").Tool<{
|
|
12
|
+
name: string;
|
|
13
|
+
}, string>;
|
|
14
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { tool } from "ai";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
/**
|
|
4
|
+
* Create enable_integration and disable_integration tools.
|
|
5
|
+
* These mutate the session's active integrations set so that
|
|
6
|
+
* subsequent runs include/exclude the integration tools.
|
|
7
|
+
*/
|
|
8
|
+
export function createIntegrationToggleTools(registry, activeIntegrations) {
|
|
9
|
+
const available = registry.names;
|
|
10
|
+
const availableList = available.join(", ");
|
|
11
|
+
const enableIntegration = tool({
|
|
12
|
+
description: `Enable an integration for this session. Available: ${availableList}. ` +
|
|
13
|
+
`Once enabled, the integration's tools will be available in subsequent messages.`,
|
|
14
|
+
inputSchema: z.object({
|
|
15
|
+
name: z.string().describe("Integration name to enable"),
|
|
16
|
+
}),
|
|
17
|
+
execute: async ({ name }) => {
|
|
18
|
+
const normalized = name.toLowerCase();
|
|
19
|
+
if (!registry.has(normalized)) {
|
|
20
|
+
return `Unknown integration "${name}". Available: ${availableList}`;
|
|
21
|
+
}
|
|
22
|
+
if (activeIntegrations.has(normalized)) {
|
|
23
|
+
return `Integration "${normalized}" is already enabled.`;
|
|
24
|
+
}
|
|
25
|
+
activeIntegrations.add(normalized);
|
|
26
|
+
const integration = registry.get(normalized);
|
|
27
|
+
const toolNames = Object.keys(integration.tools.tools).join(", ");
|
|
28
|
+
return `Integration "${normalized}" enabled. Tools now available: ${toolNames}`;
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
const disableIntegration = tool({
|
|
32
|
+
description: `Disable an integration for this session. ` +
|
|
33
|
+
`Once disabled, the integration's tools will no longer be available.`,
|
|
34
|
+
inputSchema: z.object({
|
|
35
|
+
name: z.string().describe("Integration name to disable"),
|
|
36
|
+
}),
|
|
37
|
+
execute: async ({ name }) => {
|
|
38
|
+
const normalized = name.toLowerCase();
|
|
39
|
+
if (!activeIntegrations.has(normalized)) {
|
|
40
|
+
return `Integration "${normalized}" is not currently enabled.`;
|
|
41
|
+
}
|
|
42
|
+
activeIntegrations.delete(normalized);
|
|
43
|
+
return `Integration "${normalized}" disabled.`;
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
return { enable_integration: enableIntegration, disable_integration: disableIntegration };
|
|
47
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Tool } from "ai";
|
|
2
|
+
import type { MemoryStore } from "../memory/store.js";
|
|
3
|
+
import type { EmbeddingProvider } from "../memory/embedding.js";
|
|
4
|
+
/**
|
|
5
|
+
* Create a session-scoped memory_search tool.
|
|
6
|
+
* Called per-run so results are restricted to the current session's memories.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createMemorySearchTool(store: MemoryStore, embeddingProvider: EmbeddingProvider | null, maxResults: number, teamId?: string): Tool;
|
|
9
|
+
/**
|
|
10
|
+
* Create a session-scoped memory_save tool.
|
|
11
|
+
* Allows the agent to explicitly persist facts when the user asks to remember something.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createMemorySaveTool(store: MemoryStore, embeddingProvider: EmbeddingProvider | null, sessionKey: string, teamId?: string): Tool;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { tool } from "ai";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { searchMemory } from "../memory/search.js";
|
|
4
|
+
import { saveExplicitMemory } from "../memory/explicit.js";
|
|
5
|
+
/**
|
|
6
|
+
* Create a session-scoped memory_search tool.
|
|
7
|
+
* Called per-run so results are restricted to the current session's memories.
|
|
8
|
+
*/
|
|
9
|
+
export function createMemorySearchTool(store, embeddingProvider, maxResults, teamId) {
|
|
10
|
+
return tool({
|
|
11
|
+
description: "Search long-term memory for facts about this user. " +
|
|
12
|
+
"ALWAYS call BEFORE responding to personal questions (name, location, preferences, history). " +
|
|
13
|
+
"Call multiple times with different queries to gather all relevant facts. " +
|
|
14
|
+
"When in doubt, search — it is fast.",
|
|
15
|
+
inputSchema: z.object({
|
|
16
|
+
query: z
|
|
17
|
+
.string()
|
|
18
|
+
.describe("What to search for, e.g. 'favorite food' or 'project details'"),
|
|
19
|
+
}),
|
|
20
|
+
execute: async ({ query }) => {
|
|
21
|
+
const facts = await searchMemory(store, query, {
|
|
22
|
+
limit: maxResults,
|
|
23
|
+
embeddingProvider,
|
|
24
|
+
teamId,
|
|
25
|
+
});
|
|
26
|
+
if (facts.length === 0)
|
|
27
|
+
return "No relevant memories found.";
|
|
28
|
+
return facts.map((f, i) => `${i + 1}. ${f}`).join("\n");
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Create a session-scoped memory_save tool.
|
|
34
|
+
* Allows the agent to explicitly persist facts when the user asks to remember something.
|
|
35
|
+
*/
|
|
36
|
+
export function createMemorySaveTool(store, embeddingProvider, sessionKey, teamId) {
|
|
37
|
+
return tool({
|
|
38
|
+
description: "Save a fact about the user to long-term memory. Use this when the user " +
|
|
39
|
+
"explicitly asks you to remember something, or shares personal information " +
|
|
40
|
+
"they expect you to retain (name, location, preferences, etc.). " +
|
|
41
|
+
"Each call saves ONE atomic fact — call multiple times for multiple facts.",
|
|
42
|
+
inputSchema: z.object({
|
|
43
|
+
fact: z
|
|
44
|
+
.string()
|
|
45
|
+
.describe("A single factual statement to remember, e.g. 'User lives in Singapore' " +
|
|
46
|
+
"or 'User's favorite food is noodles'"),
|
|
47
|
+
}),
|
|
48
|
+
execute: async ({ fact }) => {
|
|
49
|
+
const { saved, fact: normalizedFact } = await saveExplicitMemory(store, embeddingProvider, {
|
|
50
|
+
fact,
|
|
51
|
+
source: sessionKey,
|
|
52
|
+
teamId,
|
|
53
|
+
});
|
|
54
|
+
return saved
|
|
55
|
+
? `Saved: "${normalizedFact}"`
|
|
56
|
+
: `Already known: "${normalizedFact}"`;
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ToolSet } from "ai";
|
|
2
|
+
import type { PromptTemplateStore } from "../prompt-templates/store.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates AI-facing tools for prompt template management.
|
|
5
|
+
* Lets the LLM list, read, create, and update prompt templates.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createPromptTemplateTools(store: PromptTemplateStore): ToolSet;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { tool } from "ai";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { emit } from "../events.js";
|
|
4
|
+
const VALID_ROLES = ["orchestrator", "worker"];
|
|
5
|
+
/**
|
|
6
|
+
* Creates AI-facing tools for prompt template management.
|
|
7
|
+
* Lets the LLM list, read, create, and update prompt templates.
|
|
8
|
+
*/
|
|
9
|
+
export function createPromptTemplateTools(store) {
|
|
10
|
+
const listTemplates = tool({
|
|
11
|
+
description: "List all prompt templates. Returns name, role, and whether each is built-in.",
|
|
12
|
+
inputSchema: z.object({}),
|
|
13
|
+
execute: async () => {
|
|
14
|
+
const templates = store.listPromptTemplates();
|
|
15
|
+
if (templates.length === 0)
|
|
16
|
+
return "No prompt templates found.";
|
|
17
|
+
return templates
|
|
18
|
+
.map((t) => `[${t.id}] ${t.name} (${t.role}${t.builtin ? ", builtin" : ""}) — ${t.description || "no description"}`)
|
|
19
|
+
.join("\n");
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
const getTemplate = tool({
|
|
23
|
+
description: "Read the full content of a prompt template by ID or name.",
|
|
24
|
+
inputSchema: z.object({
|
|
25
|
+
id: z.string().optional().describe("Template ID"),
|
|
26
|
+
name: z.string().optional().describe("Template name (used if id is not provided)"),
|
|
27
|
+
}),
|
|
28
|
+
execute: async ({ id, name }) => {
|
|
29
|
+
if (!id && !name)
|
|
30
|
+
return "Either id or name is required";
|
|
31
|
+
let tpl = id ? store.getPromptTemplateById(id) : null;
|
|
32
|
+
if (!tpl && name) {
|
|
33
|
+
const all = store.listPromptTemplates();
|
|
34
|
+
tpl = all.find((t) => t.name.toLowerCase() === name.toLowerCase()) ?? null;
|
|
35
|
+
}
|
|
36
|
+
if (!tpl)
|
|
37
|
+
return `Template not found: ${id ?? name}`;
|
|
38
|
+
return [
|
|
39
|
+
`**${tpl.name}** (${tpl.role}${tpl.builtin ? ", builtin" : ""})`,
|
|
40
|
+
tpl.description ? `Description: ${tpl.description}` : "",
|
|
41
|
+
`---`,
|
|
42
|
+
tpl.content,
|
|
43
|
+
].filter(Boolean).join("\n");
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
const createTemplate = tool({
|
|
47
|
+
description: "Create a new prompt template.",
|
|
48
|
+
inputSchema: z.object({
|
|
49
|
+
name: z.string().describe("Template name (must be unique)"),
|
|
50
|
+
description: z.string().optional().describe("Short description of the template"),
|
|
51
|
+
role: z.enum(VALID_ROLES).describe("Role: orchestrator or worker"),
|
|
52
|
+
content: z.string().max(50_000).describe("The prompt template content"),
|
|
53
|
+
}),
|
|
54
|
+
execute: async ({ name, description, role, content }) => {
|
|
55
|
+
try {
|
|
56
|
+
const tpl = store.createPromptTemplate({ name, description, role, content });
|
|
57
|
+
emit("promptTemplateChange", { action: "created", promptTemplate: tpl });
|
|
58
|
+
return `Template created: [${tpl.id}] ${tpl.name} (${tpl.role})`;
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
return `Failed to create template: ${err instanceof Error ? err.message : err}`;
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
const updateTemplate = tool({
|
|
66
|
+
description: "Update an existing prompt template. Cannot modify built-in templates.",
|
|
67
|
+
inputSchema: z.object({
|
|
68
|
+
id: z.string().describe("Template ID to update"),
|
|
69
|
+
name: z.string().optional().describe("New name"),
|
|
70
|
+
description: z.string().optional().describe("New description"),
|
|
71
|
+
role: z.enum(VALID_ROLES).optional().describe("New role"),
|
|
72
|
+
content: z.string().max(50_000).optional().describe("New content"),
|
|
73
|
+
}),
|
|
74
|
+
execute: async ({ id, name, description, role, content }) => {
|
|
75
|
+
try {
|
|
76
|
+
const tpl = store.updatePromptTemplate(id, { name, description, role, content });
|
|
77
|
+
if (!tpl)
|
|
78
|
+
return `Template not found: ${id}`;
|
|
79
|
+
emit("promptTemplateChange", { action: "updated", promptTemplate: tpl });
|
|
80
|
+
return `Template updated: [${tpl.id}] ${tpl.name} (${tpl.role})`;
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
return `Failed to update template: ${err instanceof Error ? err.message : err}`;
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
const forkTemplate = tool({
|
|
88
|
+
description: "Fork an existing prompt template into a new user-editable copy. Useful for built-in templates.",
|
|
89
|
+
inputSchema: z.object({
|
|
90
|
+
id: z.string().describe("Template ID to fork"),
|
|
91
|
+
name: z.string().optional().describe("Optional name for the forked template"),
|
|
92
|
+
description: z.string().optional().describe("Optional description override"),
|
|
93
|
+
}),
|
|
94
|
+
execute: async ({ id, name, description }) => {
|
|
95
|
+
try {
|
|
96
|
+
const tpl = store.forkPromptTemplate(id, { name, description });
|
|
97
|
+
if (!tpl)
|
|
98
|
+
return `Template not found: ${id}`;
|
|
99
|
+
emit("promptTemplateChange", { action: "created", promptTemplate: tpl });
|
|
100
|
+
return `Template forked: [${tpl.id}] ${tpl.name} (${tpl.role})`;
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
return `Failed to fork template: ${err instanceof Error ? err.message : err}`;
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
const deleteTemplate = tool({
|
|
108
|
+
description: "Delete a prompt template by ID. Cannot delete built-in templates.",
|
|
109
|
+
inputSchema: z.object({
|
|
110
|
+
id: z.string().describe("Template ID to delete"),
|
|
111
|
+
}),
|
|
112
|
+
execute: async ({ id }) => {
|
|
113
|
+
try {
|
|
114
|
+
const deleted = store.deletePromptTemplate(id);
|
|
115
|
+
if (!deleted)
|
|
116
|
+
return `Template not found: ${id}`;
|
|
117
|
+
emit("promptTemplateChange", { action: "deleted", id });
|
|
118
|
+
return `Template deleted: ${id}`;
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
return `Failed to delete template: ${err instanceof Error ? err.message : err}`;
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
prompt_template_list: listTemplates,
|
|
127
|
+
prompt_template_get: getTemplate,
|
|
128
|
+
prompt_template_create: createTemplate,
|
|
129
|
+
prompt_template_fork: forkTemplate,
|
|
130
|
+
prompt_template_update: updateTemplate,
|
|
131
|
+
prompt_template_delete: deleteTemplate,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ToolSet } from "ai";
|
|
2
|
+
import type { ScheduleStore } from "../scheduler/store.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create schedule management tools scoped to a team.
|
|
5
|
+
* These let the LLM create, list, delete, pause, resume schedules
|
|
6
|
+
* and set the team's timezone.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createScheduleTools(store: ScheduleStore, teamId: string, availableIntegrations: string[]): ToolSet;
|