botholomew 0.16.3 → 0.17.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/README.md +46 -41
- package/package.json +3 -8
- package/src/chat/agent.ts +37 -40
- package/src/chat/session.ts +8 -8
- package/src/cli.ts +0 -2
- package/src/commands/capabilities.ts +32 -32
- package/src/commands/context.ts +124 -223
- package/src/commands/mcpx.ts +1 -1
- package/src/commands/nuke.ts +44 -15
- package/src/commands/prepare.ts +17 -13
- package/src/config/loader.ts +1 -8
- package/src/constants.ts +16 -32
- package/src/init/index.ts +11 -14
- package/src/mem/client.ts +17 -0
- package/src/{context → prompts}/capabilities.ts +11 -7
- package/src/schedules/store.ts +1 -1
- package/src/tasks/store.ts +1 -1
- package/src/threads/store.ts +1 -1
- package/src/tools/capabilities/refresh.ts +1 -1
- package/src/tools/membot/adapter.ts +111 -0
- package/src/tools/membot/copy.ts +59 -0
- package/src/tools/membot/count_lines.ts +53 -0
- package/src/tools/membot/edit.ts +72 -0
- package/src/tools/membot/exists.ts +54 -0
- package/src/tools/membot/index.ts +26 -0
- package/src/tools/{context → membot}/pipe.ts +34 -32
- package/src/tools/registry.ts +6 -37
- package/src/tools/tool.ts +6 -8
- package/src/tui/App.tsx +3 -4
- package/src/tui/components/ContextPanel.tsx +109 -226
- package/src/tui/components/HelpPanel.tsx +2 -2
- package/src/tui/components/MessageList.tsx +0 -1
- package/src/tui/components/StatusBar.tsx +0 -6
- package/src/tui/components/ThreadPanel.tsx +8 -7
- package/src/tui/wrapDetail.ts +11 -0
- package/src/worker/heartbeat.ts +0 -20
- package/src/worker/index.ts +11 -11
- package/src/worker/llm.ts +7 -9
- package/src/worker/prompt.ts +25 -13
- package/src/worker/spawn.ts +1 -1
- package/src/worker/tick.ts +10 -9
- package/src/commands/db.ts +0 -119
- package/src/commands/with-db.ts +0 -22
- package/src/context/chunker.ts +0 -275
- package/src/context/embedder-impl.ts +0 -100
- package/src/context/embedder.ts +0 -9
- package/src/context/fetcher-errors.ts +0 -8
- package/src/context/fetcher.ts +0 -515
- package/src/context/locks.ts +0 -146
- package/src/context/markdown-converter.ts +0 -186
- package/src/context/reindex.ts +0 -198
- package/src/context/store.ts +0 -841
- package/src/context/url-utils.ts +0 -25
- package/src/db/connection.ts +0 -255
- package/src/db/doctor.ts +0 -235
- package/src/db/embeddings.ts +0 -317
- package/src/db/query.ts +0 -56
- package/src/db/schema.ts +0 -93
- package/src/db/sql/1-core_tables.sql +0 -53
- package/src/db/sql/10-dedupe_context_items.sql +0 -26
- package/src/db/sql/11-rebuild_hnsw.sql +0 -8
- package/src/db/sql/12-workers.sql +0 -66
- package/src/db/sql/13-drive-paths.sql +0 -47
- package/src/db/sql/14-drop_hnsw_index.sql +0 -8
- package/src/db/sql/15-fts_index.sql +0 -8
- package/src/db/sql/16-source_url.sql +0 -7
- package/src/db/sql/17-worker_log_path.sql +0 -3
- package/src/db/sql/18-reset_embeddings_for_local.sql +0 -39
- package/src/db/sql/19-disk_backed_index.sql +0 -36
- package/src/db/sql/2-logging_tables.sql +0 -24
- package/src/db/sql/20-drop_db_tables_for_files.sql +0 -19
- package/src/db/sql/3-daemon_state.sql +0 -5
- package/src/db/sql/4-unique_context_path.sql +0 -1
- package/src/db/sql/5-reset_embeddings_for_openai.sql +0 -1
- package/src/db/sql/6-vss_index.sql +0 -7
- package/src/db/sql/7-drop_embeddings_fk.sql +0 -23
- package/src/db/sql/8-task_output.sql +0 -1
- package/src/db/sql/9-source-type.sql +0 -1
- package/src/tools/context/read-large-result.ts +0 -33
- package/src/tools/dir/create.ts +0 -47
- package/src/tools/dir/size.ts +0 -77
- package/src/tools/dir/tree.ts +0 -124
- package/src/tools/file/copy.ts +0 -73
- package/src/tools/file/count-lines.ts +0 -54
- package/src/tools/file/delete.ts +0 -83
- package/src/tools/file/edit.ts +0 -76
- package/src/tools/file/exists.ts +0 -33
- package/src/tools/file/info.ts +0 -66
- package/src/tools/file/move.ts +0 -66
- package/src/tools/file/read.ts +0 -67
- package/src/tools/file/write.ts +0 -58
- package/src/tools/search/fuse.ts +0 -96
- package/src/tools/search/index.ts +0 -127
- package/src/tools/search/regexp.ts +0 -82
- package/src/tools/search/semantic.ts +0 -167
- /package/src/{db → utils}/uuid.ts +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { isHelpfulError } from "membot";
|
|
1
2
|
import { z } from "zod";
|
|
2
|
-
import { PathConflictError, writeContextFile } from "../../context/store.ts";
|
|
3
3
|
import { getTool, type ToolDefinition } from "../tool.ts";
|
|
4
4
|
|
|
5
5
|
const PREVIEW_CHARS = 200;
|
|
6
6
|
const ERROR_MESSAGE_CAP = 2000;
|
|
7
|
-
const TOOL_NAME = "
|
|
7
|
+
const TOOL_NAME = "membot_pipe";
|
|
8
8
|
|
|
9
9
|
function truncate(s: string, cap: number): string {
|
|
10
10
|
if (s.length <= cap) return s;
|
|
@@ -15,29 +15,28 @@ const inputSchema = z.object({
|
|
|
15
15
|
tool_name: z
|
|
16
16
|
.string()
|
|
17
17
|
.describe(
|
|
18
|
-
"Name of the tool to dispatch. Its full output is
|
|
18
|
+
"Name of the tool to dispatch. Its full output is captured and written to membot under `logical_path`; you (the LLM) only see the storage acknowledgment, never the raw bytes.",
|
|
19
19
|
),
|
|
20
20
|
tool_input: z
|
|
21
21
|
.record(z.string(), z.unknown())
|
|
22
22
|
.describe(
|
|
23
23
|
"Arguments to pass to the inner tool (same shape as a normal call).",
|
|
24
24
|
),
|
|
25
|
-
|
|
25
|
+
logical_path: z
|
|
26
26
|
.string()
|
|
27
27
|
.describe(
|
|
28
|
-
"
|
|
28
|
+
"Destination logical_path under which to store the captured output (e.g. 'gdoc/quarterly-plan.md'). Creates a new version on every call.",
|
|
29
29
|
),
|
|
30
|
-
|
|
31
|
-
.
|
|
30
|
+
change_note: z
|
|
31
|
+
.string()
|
|
32
32
|
.optional()
|
|
33
|
-
.describe(
|
|
34
|
-
"What to do if a file already exists at this path. Defaults to 'error'. Pass 'overwrite' to replace.",
|
|
35
|
-
),
|
|
33
|
+
.describe("Free-text note attached to the new version."),
|
|
36
34
|
});
|
|
37
35
|
|
|
38
36
|
const outputSchema = z.object({
|
|
39
37
|
is_error: z.boolean(),
|
|
40
|
-
|
|
38
|
+
logical_path: z.string().optional(),
|
|
39
|
+
version_id: z.string().optional(),
|
|
41
40
|
bytes_written: z.number().optional(),
|
|
42
41
|
preview: z
|
|
43
42
|
.string()
|
|
@@ -52,18 +51,19 @@ const outputSchema = z.object({
|
|
|
52
51
|
"forbidden_tool",
|
|
53
52
|
"invalid_input",
|
|
54
53
|
"inner_tool_error",
|
|
55
|
-
"
|
|
54
|
+
"write_failed",
|
|
55
|
+
"internal_error",
|
|
56
56
|
])
|
|
57
57
|
.optional(),
|
|
58
58
|
message: z.string().optional(),
|
|
59
59
|
next_action_hint: z.string().optional(),
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
-
export const
|
|
62
|
+
export const membotPipeTool = {
|
|
63
63
|
name: TOOL_NAME,
|
|
64
64
|
description:
|
|
65
|
-
"[[ bash equivalent command: cmd > file ]] Run another tool and pipe its full output directly into a
|
|
66
|
-
group: "
|
|
65
|
+
"[[ bash equivalent command: cmd > file ]] Run another tool and pipe its full output directly into a membot logical_path, without the result flowing through the conversation. Use this when you need a large tool output (Google Docs via mcp_exec, web fetches, search dumps) captured for later inspection but you do NOT need to read the bytes yourself. You'll only see the storage ack (logical_path, version_id, short preview).",
|
|
66
|
+
group: "membot",
|
|
67
67
|
inputSchema,
|
|
68
68
|
outputSchema,
|
|
69
69
|
execute: async (input, ctx) => {
|
|
@@ -82,9 +82,9 @@ export const pipeToContextTool = {
|
|
|
82
82
|
return {
|
|
83
83
|
is_error: true,
|
|
84
84
|
error_type: "forbidden_tool",
|
|
85
|
-
message: `Tool "${inner.name}" cannot be piped (terminal tools and
|
|
85
|
+
message: `Tool "${inner.name}" cannot be piped (terminal tools and ${TOOL_NAME} itself are not allowed).`,
|
|
86
86
|
next_action_hint:
|
|
87
|
-
"Pipe a non-terminal tool (
|
|
87
|
+
"Pipe a non-terminal tool (mcp_exec, membot_read, etc.) instead.",
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -143,30 +143,32 @@ export const pipeToContextTool = {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
try {
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
);
|
|
146
|
+
const written = await ctx.mem.write({
|
|
147
|
+
logical_path: input.logical_path,
|
|
148
|
+
content: innerOutput,
|
|
149
|
+
change_note: input.change_note,
|
|
150
|
+
});
|
|
152
151
|
return {
|
|
153
152
|
is_error: false,
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
logical_path: written.logical_path,
|
|
154
|
+
version_id: written.version_id,
|
|
155
|
+
bytes_written: written.size_bytes,
|
|
156
156
|
preview: innerOutput.slice(0, PREVIEW_CHARS),
|
|
157
157
|
};
|
|
158
158
|
} catch (err) {
|
|
159
|
-
if (err
|
|
159
|
+
if (isHelpfulError(err)) {
|
|
160
160
|
return {
|
|
161
161
|
is_error: true,
|
|
162
|
-
error_type: "
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
next_action_hint:
|
|
166
|
-
"Retry with on_conflict='overwrite' to replace, or pick a different path.",
|
|
162
|
+
error_type: "write_failed",
|
|
163
|
+
message: `Inner tool ran, but write to ${input.logical_path} failed: ${err.message}`,
|
|
164
|
+
next_action_hint: err.hint,
|
|
167
165
|
};
|
|
168
166
|
}
|
|
169
|
-
|
|
167
|
+
return {
|
|
168
|
+
is_error: true,
|
|
169
|
+
error_type: "internal_error",
|
|
170
|
+
message: err instanceof Error ? err.message : String(err),
|
|
171
|
+
};
|
|
170
172
|
}
|
|
171
173
|
},
|
|
172
174
|
} satisfies ToolDefinition<typeof inputSchema, typeof outputSchema>;
|
package/src/tools/registry.ts
CHANGED
|
@@ -1,27 +1,12 @@
|
|
|
1
1
|
// Capabilities tools
|
|
2
2
|
import { capabilitiesRefreshTool } from "./capabilities/refresh.ts";
|
|
3
|
-
// Context tools
|
|
4
|
-
import { pipeToContextTool } from "./context/pipe.ts";
|
|
5
|
-
import { readLargeResultTool } from "./context/read-large-result.ts";
|
|
6
|
-
// Context — directory operations
|
|
7
|
-
import { contextCreateDirTool } from "./dir/create.ts";
|
|
8
|
-
import { contextDirSizeTool } from "./dir/size.ts";
|
|
9
|
-
import { contextTreeTool } from "./dir/tree.ts";
|
|
10
|
-
// Context — file operations
|
|
11
|
-
import { contextCopyTool } from "./file/copy.ts";
|
|
12
|
-
import { contextCountLinesTool } from "./file/count-lines.ts";
|
|
13
|
-
import { contextDeleteTool } from "./file/delete.ts";
|
|
14
|
-
import { contextEditTool } from "./file/edit.ts";
|
|
15
|
-
import { contextExistsTool } from "./file/exists.ts";
|
|
16
|
-
import { contextInfoTool } from "./file/info.ts";
|
|
17
|
-
import { contextMoveTool } from "./file/move.ts";
|
|
18
|
-
import { contextReadTool } from "./file/read.ts";
|
|
19
|
-
import { contextWriteTool } from "./file/write.ts";
|
|
20
3
|
// MCP tools
|
|
21
4
|
import { mcpExecTool } from "./mcp/exec.ts";
|
|
22
5
|
import { mcpInfoTool } from "./mcp/info.ts";
|
|
23
6
|
import { mcpListToolsTool } from "./mcp/list-tools.ts";
|
|
24
7
|
import { mcpSearchTool } from "./mcp/search.ts";
|
|
8
|
+
// Membot tools (knowledge store)
|
|
9
|
+
import { registerMembotTools } from "./membot/index.ts";
|
|
25
10
|
// Prompt tools
|
|
26
11
|
import { promptCreateTool } from "./prompt/create.ts";
|
|
27
12
|
import { promptDeleteTool } from "./prompt/delete.ts";
|
|
@@ -32,8 +17,6 @@ import { promptReadTool } from "./prompt/read.ts";
|
|
|
32
17
|
import { createScheduleTool } from "./schedule/create.ts";
|
|
33
18
|
import { scheduleEditTool } from "./schedule/edit.ts";
|
|
34
19
|
import { listSchedulesTool } from "./schedule/list.ts";
|
|
35
|
-
// Search tools
|
|
36
|
-
import { searchTool } from "./search/index.ts";
|
|
37
20
|
// Skill tools
|
|
38
21
|
import { skillDeleteTool } from "./skill/delete.ts";
|
|
39
22
|
import { skillEditTool } from "./skill/edit.ts";
|
|
@@ -73,26 +56,15 @@ export function registerAllTools(): void {
|
|
|
73
56
|
registerTool(listTasksTool);
|
|
74
57
|
registerTool(viewTaskTool);
|
|
75
58
|
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
registerTool(contextReadTool);
|
|
81
|
-
registerTool(contextWriteTool);
|
|
82
|
-
registerTool(contextEditTool);
|
|
83
|
-
registerTool(contextDeleteTool);
|
|
84
|
-
registerTool(contextCopyTool);
|
|
85
|
-
registerTool(contextMoveTool);
|
|
86
|
-
registerTool(contextInfoTool);
|
|
87
|
-
registerTool(contextExistsTool);
|
|
88
|
-
registerTool(contextCountLinesTool);
|
|
59
|
+
// Knowledge store (membot) — add/read/write/edit/search/versions/refresh etc.
|
|
60
|
+
registerMembotTools();
|
|
61
|
+
|
|
62
|
+
// Prompts
|
|
89
63
|
registerTool(promptListTool);
|
|
90
64
|
registerTool(promptReadTool);
|
|
91
65
|
registerTool(promptCreateTool);
|
|
92
66
|
registerTool(promptEditTool);
|
|
93
67
|
registerTool(promptDeleteTool);
|
|
94
|
-
registerTool(readLargeResultTool);
|
|
95
|
-
registerTool(pipeToContextTool);
|
|
96
68
|
|
|
97
69
|
// Capabilities
|
|
98
70
|
registerTool(capabilitiesRefreshTool);
|
|
@@ -102,9 +74,6 @@ export function registerAllTools(): void {
|
|
|
102
74
|
registerTool(scheduleEditTool);
|
|
103
75
|
registerTool(listSchedulesTool);
|
|
104
76
|
|
|
105
|
-
// Search
|
|
106
|
-
registerTool(searchTool);
|
|
107
|
-
|
|
108
77
|
// Skill
|
|
109
78
|
registerTool(skillListTool);
|
|
110
79
|
registerTool(skillReadTool);
|
package/src/tools/tool.ts
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import type { Tool as AnthropicTool } from "@anthropic-ai/sdk/resources/messages";
|
|
2
2
|
import type { McpxClient } from "@evantahler/mcpx";
|
|
3
|
+
import type { MembotClient } from "membot";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
import type { BotholomewConfig } from "../config/schemas.ts";
|
|
5
|
-
import type { DbConnection } from "../db/connection.ts";
|
|
6
6
|
|
|
7
7
|
export interface ToolContext {
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* Per-process membot client. Backs every `membot_*` tool. Membot manages
|
|
10
|
+
* its own DuckDB connection lifecycle internally (lazy claim, release
|
|
11
|
+
* between operations), so tools just call `ctx.mem.<op>(...)` directly —
|
|
12
|
+
* no per-call open/close needed.
|
|
13
13
|
*/
|
|
14
|
-
|
|
15
|
-
/** Path to the DuckDB file. Use with `withDb` for long-running tools. */
|
|
16
|
-
dbPath: string;
|
|
14
|
+
mem: MembotClient;
|
|
17
15
|
projectDir: string;
|
|
18
16
|
config: Required<BotholomewConfig>;
|
|
19
17
|
mcpxClient: McpxClient | null;
|
package/src/tui/App.tsx
CHANGED
|
@@ -186,18 +186,17 @@ function AppInner({
|
|
|
186
186
|
setUsage,
|
|
187
187
|
});
|
|
188
188
|
|
|
189
|
-
const
|
|
189
|
+
const sessionReady = sessionRef.current != null;
|
|
190
190
|
const inputBarHeader = useMemo(
|
|
191
191
|
() =>
|
|
192
|
-
|
|
192
|
+
sessionReady ? (
|
|
193
193
|
<StatusBar
|
|
194
194
|
projectDir={projectDir}
|
|
195
|
-
dbPath={sessionDbPath}
|
|
196
195
|
chatTitle={chatTitle}
|
|
197
196
|
onWorkerStatusChange={setWorkerRunning}
|
|
198
197
|
/>
|
|
199
198
|
) : null,
|
|
200
|
-
[projectDir,
|
|
199
|
+
[projectDir, sessionReady, chatTitle],
|
|
201
200
|
);
|
|
202
201
|
|
|
203
202
|
const allToolCalls = useMemo(
|