@burtson-labs/host-kit 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +55 -0
  3. package/dist/backgroundTasks.d.ts +113 -0
  4. package/dist/backgroundTasks.d.ts.map +1 -0
  5. package/dist/backgroundTasks.js +137 -0
  6. package/dist/backgroundTasks.js.map +1 -0
  7. package/dist/checkpoints.d.ts +99 -0
  8. package/dist/checkpoints.d.ts.map +1 -0
  9. package/dist/checkpoints.js +227 -0
  10. package/dist/checkpoints.js.map +1 -0
  11. package/dist/hooks.d.ts +51 -0
  12. package/dist/hooks.d.ts.map +1 -0
  13. package/dist/hooks.js +152 -0
  14. package/dist/hooks.js.map +1 -0
  15. package/dist/index.d.ts +19 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +95 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/insights.d.ts +398 -0
  20. package/dist/insights.d.ts.map +1 -0
  21. package/dist/insights.js +1933 -0
  22. package/dist/insights.js.map +1 -0
  23. package/dist/mcp.d.ts +60 -0
  24. package/dist/mcp.d.ts.map +1 -0
  25. package/dist/mcp.js +281 -0
  26. package/dist/mcp.js.map +1 -0
  27. package/dist/mcpConnectors.d.ts +108 -0
  28. package/dist/mcpConnectors.d.ts.map +1 -0
  29. package/dist/mcpConnectors.js +217 -0
  30. package/dist/mcpConnectors.js.map +1 -0
  31. package/dist/mcpToolCache.d.ts +43 -0
  32. package/dist/mcpToolCache.d.ts.map +1 -0
  33. package/dist/mcpToolCache.js +150 -0
  34. package/dist/mcpToolCache.js.map +1 -0
  35. package/dist/mcpTrust.d.ts +22 -0
  36. package/dist/mcpTrust.d.ts.map +1 -0
  37. package/dist/mcpTrust.js +104 -0
  38. package/dist/mcpTrust.js.map +1 -0
  39. package/dist/memory.d.ts +38 -0
  40. package/dist/memory.d.ts.map +1 -0
  41. package/dist/memory.js +151 -0
  42. package/dist/memory.js.map +1 -0
  43. package/dist/memoryIndex.d.ts +38 -0
  44. package/dist/memoryIndex.d.ts.map +1 -0
  45. package/dist/memoryIndex.js +142 -0
  46. package/dist/memoryIndex.js.map +1 -0
  47. package/dist/mentions.d.ts +33 -0
  48. package/dist/mentions.d.ts.map +1 -0
  49. package/dist/mentions.js +126 -0
  50. package/dist/mentions.js.map +1 -0
  51. package/dist/ollamaModels.d.ts +36 -0
  52. package/dist/ollamaModels.d.ts.map +1 -0
  53. package/dist/ollamaModels.js +83 -0
  54. package/dist/ollamaModels.js.map +1 -0
  55. package/dist/permissions.d.ts +72 -0
  56. package/dist/permissions.d.ts.map +1 -0
  57. package/dist/permissions.js +271 -0
  58. package/dist/permissions.js.map +1 -0
  59. package/dist/tools/extraTools.d.ts +80 -0
  60. package/dist/tools/extraTools.d.ts.map +1 -0
  61. package/dist/tools/extraTools.js +471 -0
  62. package/dist/tools/extraTools.js.map +1 -0
  63. package/dist/tools/readMemoryTool.d.ts +3 -0
  64. package/dist/tools/readMemoryTool.d.ts.map +1 -0
  65. package/dist/tools/readMemoryTool.js +115 -0
  66. package/dist/tools/readMemoryTool.js.map +1 -0
  67. package/dist/tools/taskTool.d.ts +119 -0
  68. package/dist/tools/taskTool.d.ts.map +1 -0
  69. package/dist/tools/taskTool.js +466 -0
  70. package/dist/tools/taskTool.js.map +1 -0
  71. package/dist/tools/testRunTool.d.ts +59 -0
  72. package/dist/tools/testRunTool.d.ts.map +1 -0
  73. package/dist/tools/testRunTool.js +308 -0
  74. package/dist/tools/testRunTool.js.map +1 -0
  75. package/dist/turnLog.d.ts +89 -0
  76. package/dist/turnLog.d.ts.map +1 -0
  77. package/dist/turnLog.js +469 -0
  78. package/dist/turnLog.js.map +1 -0
  79. package/package.json +35 -0
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Permission policy for tool execution.
3
+ *
4
+ * Hosts (CLI, VS Code extension) consult the policy BEFORE a tool runs.
5
+ * The policy returns one of:
6
+ * - 'allow' : proceed without prompting
7
+ * - 'ask' : prompt the user (host decides how — modal, [y/N], etc.)
8
+ * - 'deny' : abort, model sees a blocked-tool result
9
+ *
10
+ * Patterns can target a tool by name ("write_file") or a tool+arg filter
11
+ * ("write_file:src/**", "run_command:npm test*"). Glob matching uses the
12
+ * same minimal engine as host-kit/mentions — *, **, ?, and {a,b}.
13
+ *
14
+ * Config shape in .bandit/settings.json:
15
+ *
16
+ * {
17
+ * "permissions": {
18
+ * "allow": ["read_file", "list_files", "search_code", "write_file:docs/**"],
19
+ * "deny": ["run_command:rm *"],
20
+ * "ask": ["write_file", "run_command"]
21
+ * }
22
+ * }
23
+ *
24
+ * Evaluation order: deny > allow > ask > default.
25
+ * Default for dangerous tools (write_file, apply_edit, replace_range, run_command) is 'ask'.
26
+ * Default for read-only tools is 'allow'.
27
+ */
28
+ export type PermissionDecision = 'allow' | 'ask' | 'deny';
29
+ export interface PermissionPolicy {
30
+ allow: string[];
31
+ deny: string[];
32
+ ask: string[];
33
+ }
34
+ export declare const emptyPolicy: () => PermissionPolicy;
35
+ /**
36
+ * Merge two policies. Used to combine workspace settings with session
37
+ * overrides (e.g. the user's "always allow for this session" choices).
38
+ */
39
+ export declare function mergePolicies(a: PermissionPolicy, b: PermissionPolicy): PermissionPolicy;
40
+ /**
41
+ * Evaluate the policy for a tool invocation. Returns the decision.
42
+ *
43
+ * @param toolName Tool being invoked (e.g. "write_file")
44
+ * @param primary The first meaningful param value (path, cmd, url…)
45
+ * used for fine-grained pattern matching. Empty
46
+ * string if unknown.
47
+ * @param policy Merged workspace + session policy.
48
+ * @param primaryFull Optional fuller representation of the invocation
49
+ * used for pattern matching alongside `primary`.
50
+ * For `run_command` the host should pass the full
51
+ * command line ("git push origin main") so glob
52
+ * patterns like `run_command:git *` and
53
+ * `run_command:rm *` work intuitively. When
54
+ * omitted (default) only `primary` is consulted —
55
+ * preserves the original semantics for callers
56
+ * that don't need the wider match.
57
+ */
58
+ export declare function evaluatePermission(toolName: string, primary: string, policy: PermissionPolicy, primaryFull?: string): PermissionDecision;
59
+ /**
60
+ * In-memory store for session-level "always allow" choices. Hosts instantiate
61
+ * one per conversation so approvals reset when the user starts fresh.
62
+ */
63
+ export declare class SessionPermissionStore {
64
+ private readonly allow;
65
+ /** Remember an "always allow for this session" choice. */
66
+ grant(toolName: string, primary?: string): void;
67
+ /** Returns a policy fragment reflecting session grants only. */
68
+ toPolicy(): PermissionPolicy;
69
+ clear(): void;
70
+ size(): number;
71
+ }
72
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AAE1D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AA0FD,eAAO,MAAM,WAAW,QAAO,gBAAsD,CAAC;AAEtF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,CAMxF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,EACxB,WAAW,CAAC,EAAE,MAAM,GACnB,kBAAkB,CAepB;AA2ED;;;GAGG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAE3C,0DAA0D;IAC1D,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAI/C,gEAAgE;IAChE,QAAQ,IAAI,gBAAgB;IAI5B,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,MAAM;CAGf"}
@@ -0,0 +1,271 @@
1
+ "use strict";
2
+ /**
3
+ * Permission policy for tool execution.
4
+ *
5
+ * Hosts (CLI, VS Code extension) consult the policy BEFORE a tool runs.
6
+ * The policy returns one of:
7
+ * - 'allow' : proceed without prompting
8
+ * - 'ask' : prompt the user (host decides how — modal, [y/N], etc.)
9
+ * - 'deny' : abort, model sees a blocked-tool result
10
+ *
11
+ * Patterns can target a tool by name ("write_file") or a tool+arg filter
12
+ * ("write_file:src/**", "run_command:npm test*"). Glob matching uses the
13
+ * same minimal engine as host-kit/mentions — *, **, ?, and {a,b}.
14
+ *
15
+ * Config shape in .bandit/settings.json:
16
+ *
17
+ * {
18
+ * "permissions": {
19
+ * "allow": ["read_file", "list_files", "search_code", "write_file:docs/**"],
20
+ * "deny": ["run_command:rm *"],
21
+ * "ask": ["write_file", "run_command"]
22
+ * }
23
+ * }
24
+ *
25
+ * Evaluation order: deny > allow > ask > default.
26
+ * Default for dangerous tools (write_file, apply_edit, replace_range, run_command) is 'ask'.
27
+ * Default for read-only tools is 'allow'.
28
+ */
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.SessionPermissionStore = exports.emptyPolicy = void 0;
31
+ exports.mergePolicies = mergePolicies;
32
+ exports.evaluatePermission = evaluatePermission;
33
+ /** Tools that mutate state or execute code and therefore require ask-by-default. */
34
+ const DANGEROUS_TOOLS = new Set(['write_file', 'apply_edit', 'replace_range', 'apply_patch', 'run_command']);
35
+ /**
36
+ * Mutating-tool name patterns used to gate MCP-bridged tools that
37
+ * aren't in the static DANGEROUS_TOOLS set. Catches tools whose names
38
+ * imply they change state outside Bandit's process — Gmail filters,
39
+ * Calendar events, Drive files, etc. — so the user sees a permission
40
+ * card before the agent silently archives 200 emails or creates a
41
+ * filter that auto-trashes mail.
42
+ *
43
+ * Captured 2026-05-25: bandit-logic ran createFilter +
44
+ * modifyMessageLabels + trashMessage without any permission prompt
45
+ * because they're all MCP-bridged tools and the evaluator defaulted
46
+ * to 'allow' for anything not in DANGEROUS_TOOLS. The user had no
47
+ * idea the inbox was being changed until after the fact.
48
+ *
49
+ * Read-only patterns (list*, get*, search*, read*) are deliberately
50
+ * NOT in this list — auto-allowing those keeps the agent able to
51
+ * browse without prompt-spam. The principle: ask before write,
52
+ * allow read by default.
53
+ */
54
+ const MUTATING_PATTERNS = [
55
+ /^create[A-Z_]/, // createFilter, createLabel, createEvent, createFolder, create_event
56
+ /^update[A-Z_]/, // updateDraft, updateEvent, updateSpreadsheet
57
+ /^modify[A-Z_]/, // modifyMessageLabels, modify_message_labels
58
+ /^delete[A-Z_]/, // deleteEvent, deleteFile, deleteFilter
59
+ /^remove[A-Z_]/, // removeLabel, removeMember
60
+ /^trash[A-Z_]/, // trashMessage
61
+ /^archive[A-Z_]/, // archiveMessage
62
+ /^move[A-Z_]/, // moveFile, moveMessage
63
+ /^send[A-Z_]/, // sendEmail, sendDraft, sendMessage
64
+ /^post[A-Z_]/, // postMessage, postComment
65
+ /^add[A-Z_]/, // addComment, addMember (catches additive mutations too)
66
+ /^insert[A-Z_]/, // insertText, insertEvent
67
+ /^replace[A-Z_]/, // replaceTableRowData, findAndReplace
68
+ /^rename[A-Z_]/, // renameSheet, renameTab, renameFile
69
+ /^duplicate[A-Z_]/, // duplicateSheet
70
+ /^batch[A-Z_]/, // batchWrite, batchUpdate
71
+ /^write[A-Z_]/, // writeSpreadsheet
72
+ /^append[A-Z_]/, // appendTableRows, appendToGoogleDoc, appendSpreadsheetRows
73
+ /^clear[A-Z_]/, // clearSpreadsheetRange
74
+ /^copy[A-Z_]/, // copyFile, copySheetTo (creates a new resource)
75
+ /^upload[A-Z_]/, // uploadFile
76
+ /^revoke[A-Z_]/, // revokeAccess
77
+ /^grant[A-Z_]/, // grantPermission
78
+ /^triage[A-Z_]/, // triageInbox (writes label/state)
79
+ /^apply[A-Z_]/, // applyTextStyle, applyParagraphStyle (modifies docs)
80
+ /^set[A-Z_]/, // setCellBorders, setRowHeights, setColumnWidths
81
+ /^protect[A-Z_]/, // protectRange
82
+ /^group[A-Z_]/, // groupRows
83
+ /^ungroup[A-Z_]/, // ungroupAllRows
84
+ /^freeze[A-Z_]/, // freezeRowsAndColumns
85
+ /^auto[Rr]esize/, // autoResizeColumns / autoResizeRows
86
+ /^reply[A-Z_]/, // replyToComment, replyToSheetsComment
87
+ /^cancel[A-Z_]/, // cancelEvent
88
+ /^quick[Aa]dd/, // quickAddEvent
89
+ ];
90
+ /**
91
+ * Strip the MCP namespace prefix (e.g. "burtson-labs.createFilter" →
92
+ * "createFilter") before pattern-testing. Tools registered via
93
+ * mcpToolToAgentTool get a "<server>.<tool>" naming convention; the
94
+ * mutating-verb test operates on the tool name itself.
95
+ */
96
+ function stripMcpNamespace(toolName) {
97
+ const dotIdx = toolName.indexOf('.');
98
+ if (dotIdx > 0)
99
+ return toolName.slice(dotIdx + 1);
100
+ // mcp__server__tool naming convention (alternate)
101
+ const underIdx = toolName.indexOf('__');
102
+ if (underIdx > 0 && toolName.startsWith('mcp__')) {
103
+ const after = toolName.slice(underIdx + 2);
104
+ const next = after.indexOf('__');
105
+ return next > 0 ? after.slice(next + 2) : after;
106
+ }
107
+ return toolName;
108
+ }
109
+ /**
110
+ * Does this tool's name look like a mutating operation?
111
+ * Used as the default-ask gate for MCP-bridged tools that aren't
112
+ * declared in the in-tree DANGEROUS_TOOLS set.
113
+ */
114
+ function looksMutating(toolName) {
115
+ const bareName = stripMcpNamespace(toolName);
116
+ return MUTATING_PATTERNS.some((re) => re.test(bareName));
117
+ }
118
+ const emptyPolicy = () => ({ allow: [], deny: [], ask: [] });
119
+ exports.emptyPolicy = emptyPolicy;
120
+ /**
121
+ * Merge two policies. Used to combine workspace settings with session
122
+ * overrides (e.g. the user's "always allow for this session" choices).
123
+ */
124
+ function mergePolicies(a, b) {
125
+ return {
126
+ allow: [...new Set([...a.allow, ...b.allow])],
127
+ deny: [...new Set([...a.deny, ...b.deny])],
128
+ ask: [...new Set([...a.ask, ...b.ask])]
129
+ };
130
+ }
131
+ /**
132
+ * Evaluate the policy for a tool invocation. Returns the decision.
133
+ *
134
+ * @param toolName Tool being invoked (e.g. "write_file")
135
+ * @param primary The first meaningful param value (path, cmd, url…)
136
+ * used for fine-grained pattern matching. Empty
137
+ * string if unknown.
138
+ * @param policy Merged workspace + session policy.
139
+ * @param primaryFull Optional fuller representation of the invocation
140
+ * used for pattern matching alongside `primary`.
141
+ * For `run_command` the host should pass the full
142
+ * command line ("git push origin main") so glob
143
+ * patterns like `run_command:git *` and
144
+ * `run_command:rm *` work intuitively. When
145
+ * omitted (default) only `primary` is consulted —
146
+ * preserves the original semantics for callers
147
+ * that don't need the wider match.
148
+ */
149
+ function evaluatePermission(toolName, primary, policy, primaryFull) {
150
+ // Deny has highest precedence — explicit deny wins over explicit allow.
151
+ if (matchesAny(toolName, primary, policy.deny, primaryFull))
152
+ return 'deny';
153
+ if (matchesAny(toolName, primary, policy.allow, primaryFull))
154
+ return 'allow';
155
+ if (matchesAny(toolName, primary, policy.ask, primaryFull))
156
+ return 'ask';
157
+ // Default: dangerous tools require explicit permission, read-only are OK.
158
+ // MCP-bridged tools whose names imply they mutate external state
159
+ // (createFilter, trashMessage, modifyMessageLabels, sendEmail, etc.)
160
+ // also default to 'ask' — without this, every MCP tool gets auto-
161
+ // allowed and the user has no chance to stop the agent before it
162
+ // archives 200 emails or creates a forwarding rule.
163
+ if (DANGEROUS_TOOLS.has(toolName))
164
+ return 'ask';
165
+ if (looksMutating(toolName))
166
+ return 'ask';
167
+ return 'allow';
168
+ }
169
+ function matchesAny(toolName, primary, patterns, primaryFull) {
170
+ for (const raw of patterns) {
171
+ const pattern = raw.trim();
172
+ if (!pattern)
173
+ continue;
174
+ const colon = pattern.indexOf(':');
175
+ if (colon === -1) {
176
+ // Tool-only pattern: matches every invocation of that tool.
177
+ if (pattern === toolName)
178
+ return true;
179
+ continue;
180
+ }
181
+ const toolPart = pattern.slice(0, colon);
182
+ const argPart = pattern.slice(colon + 1);
183
+ if (toolPart !== toolName)
184
+ continue;
185
+ // Try the wider form first when provided — this is what makes
186
+ // patterns like `run_command:git *` and `run_command:rm *` work
187
+ // (matching against "git push origin main", not just "git"). Fall
188
+ // back to the narrow primary for grants stored at binary-only
189
+ // scope and for non-run_command tools where primaryFull is
190
+ // identical to primary.
191
+ if (primaryFull && globMatch(argPart, primaryFull))
192
+ return true;
193
+ if (globMatch(argPart, primary))
194
+ return true;
195
+ }
196
+ return false;
197
+ }
198
+ /**
199
+ * Permission-pattern glob matcher.
200
+ *
201
+ * Unlike path-glob matchers, this one treats `*` as greedy (matching slashes
202
+ * too) because permission patterns target heterogeneous inputs (commands,
203
+ * URLs, paths) and users don't expect `/` to be segmenting. Keep `**` as an
204
+ * alias for `*` for user convenience so both "write_file:src/**" and
205
+ * "run_command:rm *" behave intuitively.
206
+ */
207
+ function globMatch(pattern, input) {
208
+ const regex = globToRegex(pattern);
209
+ return regex.test(input);
210
+ }
211
+ function globToRegex(glob) {
212
+ let out = '^';
213
+ for (let i = 0; i < glob.length; i++) {
214
+ const ch = glob[i];
215
+ if (ch === '*') {
216
+ if (glob[i + 1] === '*') {
217
+ i++;
218
+ }
219
+ out += '.*';
220
+ }
221
+ else if (ch === '?') {
222
+ out += '.';
223
+ }
224
+ else if (ch === '{') {
225
+ const end = glob.indexOf('}', i);
226
+ if (end === -1) {
227
+ out += '\\{';
228
+ continue;
229
+ }
230
+ const opts = glob.slice(i + 1, end).split(',').map(escapeRegex).join('|');
231
+ out += `(?:${opts})`;
232
+ i = end;
233
+ }
234
+ else if (/[.+^$()|\\]/.test(ch)) {
235
+ out += '\\' + ch;
236
+ }
237
+ else {
238
+ out += ch;
239
+ }
240
+ }
241
+ out += '$';
242
+ return new RegExp(out);
243
+ }
244
+ function escapeRegex(s) {
245
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
246
+ }
247
+ /**
248
+ * In-memory store for session-level "always allow" choices. Hosts instantiate
249
+ * one per conversation so approvals reset when the user starts fresh.
250
+ */
251
+ class SessionPermissionStore {
252
+ constructor() {
253
+ this.allow = new Set();
254
+ }
255
+ /** Remember an "always allow for this session" choice. */
256
+ grant(toolName, primary) {
257
+ this.allow.add(primary ? `${toolName}:${primary}` : toolName);
258
+ }
259
+ /** Returns a policy fragment reflecting session grants only. */
260
+ toPolicy() {
261
+ return { allow: [...this.allow], deny: [], ask: [] };
262
+ }
263
+ clear() {
264
+ this.allow.clear();
265
+ }
266
+ size() {
267
+ return this.allow.size;
268
+ }
269
+ }
270
+ exports.SessionPermissionStore = SessionPermissionStore;
271
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Extra tools layered onto the core ToolRegistry for the CLI host:
3
+ * - todo_write: in-agent todo tracking, persisted in-memory for the session
4
+ * - web_fetch: GET a URL and return a trimmed text body
5
+ * - web_search: query a search API (Tavily), return ranked snippets
6
+ */
7
+ import type { AgentTool } from '@burtson-labs/agent-core';
8
+ interface TodoItem {
9
+ id: number;
10
+ status: 'pending' | 'in_progress' | 'done';
11
+ content: string;
12
+ }
13
+ export declare class TodoStore {
14
+ private items;
15
+ private nextId;
16
+ snapshot(): TodoItem[];
17
+ render(): string;
18
+ /**
19
+ * Accepts a JSON array of { content, status? } to replace the list, or a
20
+ * single string 'content' for append. Simple to be forgiving of small models.
21
+ */
22
+ upsert(raw: string): string;
23
+ /**
24
+ * A short progress summary the tool returns so the model reads a
25
+ * clear "update succeeded, here's what's left" signal instead of
26
+ * interpreting the echoed list as a reset. The trailing nudge is
27
+ * deliberately blunt — bandit-core-1 and similar small models have
28
+ * been observed to claim completion without invoking the write
29
+ * tool, and this helper is the most direct place to remind the
30
+ * model of the expectation between tool calls.
31
+ */
32
+ summary(): string;
33
+ }
34
+ export declare function buildTodoWriteTool(store: TodoStore): AgentTool;
35
+ /**
36
+ * `remember` tool — persists a single fact to the workspace's BANDIT.md
37
+ * so it survives across sessions. Use case: the user says "remember
38
+ * that all my repos live in ~/Documents/GitHub" and wants the next
39
+ * Bandit session to know that without being re-told.
40
+ *
41
+ * Why a dedicated tool instead of asking the model to apply_edit
42
+ * BANDIT.md directly: small models (gemma4:e4b, qwen 4B) hallucinated
43
+ * the existing file contents when invited to edit it, and even on
44
+ * larger models the apply_edit dance for "append a bullet" was
45
+ * comically inefficient (4-5 turns minimum). This is one tool call
46
+ * with a single string parameter — same shape as todo_write.
47
+ *
48
+ * on the CLI: user said "you should add to your
49
+ * memory where my repos are", model used `todo_write` thinking it was
50
+ * the persistence mechanism, nothing actually landed on disk and the
51
+ * next session knew nothing.
52
+ */
53
+ export declare function buildRememberTool(): AgentTool;
54
+ export declare function isPrivateHost(hostname: string): Promise<boolean>;
55
+ export declare function buildWebFetchTool(): AgentTool;
56
+ export interface WebSearchToolOptions {
57
+ /** Tavily API key. Falls back to env var TAVILY_API_KEY when omitted.
58
+ * When neither is set, the tool returns a configuration error
59
+ * (model can fall back to web_fetch with a known URL). */
60
+ apiKey?: string;
61
+ /** Override the search endpoint. Default: https://api.tavily.com/search */
62
+ endpoint?: string;
63
+ }
64
+ /**
65
+ * Build a `web_search` tool backed by Tavily (purpose-built for LLM
66
+ * agents — returns ranked snippets, not raw HTML). When TAVILY_API_KEY
67
+ * is unset the tool returns a clear configuration error so the model
68
+ * can fall back to other tools (web_fetch with a known URL, ask the
69
+ * user, etc.) instead of hallucinating results.
70
+ *
71
+ * Why Tavily over scraping or Google CSE:
72
+ * - Generous free tier (1k req/mo at time of writing)
73
+ * - Single API call returns ranked snippets ready for the model
74
+ * - No CAPTCHA / rate-limit roulette like search-result scraping
75
+ * - Optional `answer` field gives the model an LLM-summarized answer
76
+ * directly when one fits the query
77
+ */
78
+ export declare function buildWebSearchTool(options?: WebSearchToolOptions): AgentTool;
79
+ export {};
80
+ //# sourceMappingURL=extraTools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraTools.d.ts","sourceRoot":"","sources":["../../src/tools/extraTools.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAoC,MAAM,0BAA0B,CAAC;AAG5F,UAAU,QAAQ;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;CACjB;AAiBD,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,MAAM,CAAK;IAEnB,QAAQ,IAAI,QAAQ,EAAE;IAItB,MAAM,IAAI,MAAM;IAUhB;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IA6D3B;;;;;;;;OAQG;IACH,OAAO,IAAI,MAAM;CAiBlB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CA8C9D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,IAAI,SAAS,CAmB7C;AAuCD,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAwBtE;AAED,wBAAgB,iBAAiB,IAAI,SAAS,CA4C7C;AAgBD,MAAM,WAAW,oBAAoB;IACnC;;8DAE0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAeD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,oBAAyB,GAAG,SAAS,CAsFhF"}