botholomew 0.18.3 → 0.18.5
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/package.json
CHANGED
package/src/tools/registry.ts
CHANGED
|
@@ -40,6 +40,7 @@ import { searchThreadsTool } from "./thread/search.ts";
|
|
|
40
40
|
import { viewThreadTool } from "./thread/view.ts";
|
|
41
41
|
import { registerTool } from "./tool.ts";
|
|
42
42
|
// Util tools
|
|
43
|
+
import { readLargeResultTool } from "./util/read_large_result.ts";
|
|
43
44
|
import { sleepTool } from "./util/sleep.ts";
|
|
44
45
|
// Worker tools
|
|
45
46
|
import { spawnWorkerTool } from "./worker/spawn.ts";
|
|
@@ -95,6 +96,7 @@ export function registerAllTools(): void {
|
|
|
95
96
|
|
|
96
97
|
// Util
|
|
97
98
|
registerTool(sleepTool);
|
|
99
|
+
registerTool(readLargeResultTool);
|
|
98
100
|
|
|
99
101
|
// Worker
|
|
100
102
|
registerTool(spawnWorkerTool);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import {
|
|
3
|
+
PAGE_SIZE_CHARS,
|
|
4
|
+
peekLargeResult,
|
|
5
|
+
readLargeResultPage,
|
|
6
|
+
} from "../../worker/large-results.ts";
|
|
7
|
+
import type { ToolDefinition } from "../tool.ts";
|
|
8
|
+
|
|
9
|
+
const ID_PATTERN = /^lr_\d+$/;
|
|
10
|
+
|
|
11
|
+
const inputSchema = z.object({
|
|
12
|
+
id: z
|
|
13
|
+
.string()
|
|
14
|
+
.regex(ID_PATTERN)
|
|
15
|
+
.describe(
|
|
16
|
+
'Large-result id from the "Paginated for LLM" stub, e.g. "lr_1".',
|
|
17
|
+
),
|
|
18
|
+
page: z
|
|
19
|
+
.number()
|
|
20
|
+
.int()
|
|
21
|
+
.min(1)
|
|
22
|
+
.default(1)
|
|
23
|
+
.describe(
|
|
24
|
+
`1-based page number. Each page is ~${PAGE_SIZE_CHARS} chars. Start at 1; the response includes total_pages so you know when to stop.`,
|
|
25
|
+
),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const outputSchema = z.object({
|
|
29
|
+
content: z.string(),
|
|
30
|
+
id: z.string(),
|
|
31
|
+
page: z.number(),
|
|
32
|
+
total_pages: z.number(),
|
|
33
|
+
total_chars: z.number(),
|
|
34
|
+
is_error: z.boolean(),
|
|
35
|
+
error_type: z.string().optional(),
|
|
36
|
+
next_action_hint: z.string().optional(),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export const readLargeResultTool = {
|
|
40
|
+
name: "read_large_result",
|
|
41
|
+
description: `[[ bash equivalent command: sed -n '<page>p' ]] Read one page of a large tool result that was cached because its inline payload exceeded the response budget. Use the id from the "Paginated for LLM" stub. Pages are 1-based and ~${PAGE_SIZE_CHARS} chars each; loop from page=1 to total_pages.`,
|
|
42
|
+
group: "util",
|
|
43
|
+
inputSchema,
|
|
44
|
+
outputSchema,
|
|
45
|
+
execute: async (input, _ctx): Promise<z.infer<typeof outputSchema>> => {
|
|
46
|
+
const meta = peekLargeResult(input.id);
|
|
47
|
+
if (!meta) {
|
|
48
|
+
return {
|
|
49
|
+
content: "",
|
|
50
|
+
id: input.id,
|
|
51
|
+
page: input.page,
|
|
52
|
+
total_pages: 0,
|
|
53
|
+
total_chars: 0,
|
|
54
|
+
is_error: true,
|
|
55
|
+
error_type: "unknown_id",
|
|
56
|
+
next_action_hint:
|
|
57
|
+
"Large-result entries live only for the current worker tick or chat session and are cleared between worker tasks. Re-run the originating tool to regenerate the result.",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const result = readLargeResultPage(input.id, input.page);
|
|
62
|
+
if (!result) {
|
|
63
|
+
return {
|
|
64
|
+
content: "",
|
|
65
|
+
id: input.id,
|
|
66
|
+
page: input.page,
|
|
67
|
+
total_pages: meta.totalPages,
|
|
68
|
+
total_chars: meta.totalChars,
|
|
69
|
+
is_error: true,
|
|
70
|
+
error_type: "page_out_of_range",
|
|
71
|
+
next_action_hint: `page=${input.page} is past the end. Valid pages are 1–${meta.totalPages}.`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
content: result.content,
|
|
77
|
+
id: input.id,
|
|
78
|
+
page: result.page,
|
|
79
|
+
total_pages: result.totalPages,
|
|
80
|
+
total_chars: meta.totalChars,
|
|
81
|
+
is_error: false,
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
} satisfies ToolDefinition<typeof inputSchema, typeof outputSchema>;
|
|
@@ -123,6 +123,13 @@ export function useMessageQueue({
|
|
|
123
123
|
try {
|
|
124
124
|
await sendMessage(sessionRef.current, entry.content, {
|
|
125
125
|
onToken: (token) => {
|
|
126
|
+
// Mirror the text→tool flush in onToolStart: when text begins
|
|
127
|
+
// streaming after one or more completed tool calls, push the
|
|
128
|
+
// pending tools into Static so the dynamic frame doesn't
|
|
129
|
+
// re-reconcile their boxes on every token flush.
|
|
130
|
+
if (!currentText && pendingToolCalls.length > 0) {
|
|
131
|
+
finalizeSegment();
|
|
132
|
+
}
|
|
126
133
|
currentText += token;
|
|
127
134
|
const now = Date.now();
|
|
128
135
|
if (now - lastStreamFlush >= 50) {
|
|
@@ -52,6 +52,19 @@ export function readLargeResultPage(
|
|
|
52
52
|
return { content, page, totalPages: entry.totalPages };
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/** Inspect a stored result without consuming a page. Returns null if unknown. */
|
|
56
|
+
export function peekLargeResult(
|
|
57
|
+
id: string,
|
|
58
|
+
): { toolName: string; totalChars: number; totalPages: number } | null {
|
|
59
|
+
const entry = store.get(id);
|
|
60
|
+
if (!entry) return null;
|
|
61
|
+
return {
|
|
62
|
+
toolName: entry.toolName,
|
|
63
|
+
totalChars: entry.totalChars,
|
|
64
|
+
totalPages: entry.totalPages,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
55
68
|
/** Build the inline stub that replaces the full result in the conversation */
|
|
56
69
|
export function buildResultStub(
|
|
57
70
|
id: string,
|
|
@@ -67,7 +80,7 @@ export function buildResultStub(
|
|
|
67
80
|
preview,
|
|
68
81
|
preview.length < content.length ? "..." : "",
|
|
69
82
|
"",
|
|
70
|
-
`Use read_large_result with id="${id}"
|
|
83
|
+
`Use read_large_result with id="${id}" and page=<n> (1–${totalPages}) to read it in ~${PAGE_SIZE_CHARS}-char pages.`,
|
|
71
84
|
].join("\n");
|
|
72
85
|
}
|
|
73
86
|
|