@townco/agent 0.1.84 → 0.1.87
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/dist/acp-server/adapter.d.ts +0 -8
- package/dist/definition/index.d.ts +0 -2
- package/dist/definition/index.js +0 -1
- package/dist/runner/agent-runner.d.ts +1 -2
- package/dist/runner/hooks/executor.d.ts +4 -8
- package/dist/runner/hooks/executor.js +9 -1
- package/dist/runner/hooks/predefined/document-context-extractor/chunk-manager.d.ts +37 -0
- package/dist/runner/hooks/predefined/document-context-extractor/chunk-manager.js +134 -0
- package/dist/runner/hooks/predefined/document-context-extractor/content-extractor.d.ts +20 -0
- package/dist/runner/hooks/predefined/document-context-extractor/content-extractor.js +171 -0
- package/dist/runner/hooks/predefined/document-context-extractor/extraction-state.d.ts +57 -0
- package/dist/runner/hooks/predefined/document-context-extractor/extraction-state.js +126 -0
- package/dist/runner/hooks/predefined/document-context-extractor/index.d.ts +22 -0
- package/dist/runner/hooks/predefined/document-context-extractor/index.js +338 -0
- package/dist/runner/hooks/predefined/document-context-extractor/relevance-scorer.d.ts +19 -0
- package/dist/runner/hooks/predefined/document-context-extractor/relevance-scorer.js +156 -0
- package/dist/runner/hooks/predefined/document-context-extractor/types.d.ts +130 -0
- package/dist/runner/hooks/predefined/document-context-extractor/types.js +8 -0
- package/dist/runner/hooks/predefined/tool-response-compactor.js +77 -212
- package/dist/runner/hooks/types.d.ts +15 -8
- package/dist/runner/index.d.ts +51 -2
- package/dist/runner/langchain/index.js +27 -0
- package/dist/runner/langchain/tools/artifacts.d.ts +6 -6
- package/dist/runner/langchain/tools/artifacts.js +98 -93
- package/dist/runner/langchain/tools/browser.d.ts +9 -9
- package/dist/runner/langchain/tools/document_extract.d.ts +26 -0
- package/dist/runner/langchain/tools/document_extract.js +135 -0
- package/dist/runner/langchain/tools/filesystem.d.ts +3 -3
- package/dist/runner/langchain/tools/generate_image.d.ts +8 -8
- package/dist/runner/langchain/tools/todo.d.ts +10 -10
- package/dist/runner/tools.d.ts +2 -2
- package/dist/runner/tools.js +1 -0
- package/dist/scaffold/project-scaffold.js +4 -4
- package/dist/templates/index.d.ts +0 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -13
- package/templates/index.ts +0 -1
|
@@ -11,19 +11,11 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import * as fs from "node:fs/promises";
|
|
13
13
|
import * as path from "node:path";
|
|
14
|
-
import {
|
|
14
|
+
import { createClient } from "@townco/apiclient";
|
|
15
|
+
import { getShedAuth } from "@townco/core/auth";
|
|
15
16
|
import { tool } from "langchain";
|
|
16
17
|
import { z } from "zod";
|
|
17
18
|
// ============================================================================
|
|
18
|
-
// Supabase Client and Bucket Configuration
|
|
19
|
-
// ============================================================================
|
|
20
|
-
function getSupabaseClient() {
|
|
21
|
-
return createSecretKeyClient();
|
|
22
|
-
}
|
|
23
|
-
function getBucketName() {
|
|
24
|
-
return "town-builder-artifacts";
|
|
25
|
-
}
|
|
26
|
-
// ============================================================================
|
|
27
19
|
// Storage Key Prefix Logic
|
|
28
20
|
// ============================================================================
|
|
29
21
|
/**
|
|
@@ -99,21 +91,26 @@ function validateStoragePath(path) {
|
|
|
99
91
|
throw new Error("Storage path cannot be empty");
|
|
100
92
|
}
|
|
101
93
|
}
|
|
102
|
-
function validateExpiration(expiresIn) {
|
|
103
|
-
// Supabase supports up to 365 days (31536000 seconds)
|
|
104
|
-
if (expiresIn < 1 || expiresIn > 31536000) {
|
|
105
|
-
throw new Error(`URL expiration must be between 1 and 31536000 seconds (365 days). Got: ${expiresIn}`);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
94
|
// ============================================================================
|
|
109
95
|
// Supabase Storage Operation Helpers
|
|
110
96
|
// ============================================================================
|
|
111
97
|
/**
|
|
112
|
-
* Upload a file to Supabase Storage
|
|
98
|
+
* Upload a file to Supabase Storage using signed URL
|
|
113
99
|
*/
|
|
114
100
|
async function uploadToSupabase(storageKey, localPath) {
|
|
115
|
-
const
|
|
116
|
-
|
|
101
|
+
const auth = getShedAuth();
|
|
102
|
+
if (auth === null)
|
|
103
|
+
throw new Error(`agent/artifacts: could not fetch shed auth`);
|
|
104
|
+
const { shedUrl, accessToken } = auth;
|
|
105
|
+
// Get signed upload URL from server
|
|
106
|
+
const signedUrl = await createClient({
|
|
107
|
+
shedUrl,
|
|
108
|
+
accessToken,
|
|
109
|
+
}).getArtifactUrl.query({
|
|
110
|
+
kind: "user",
|
|
111
|
+
key: storageKey,
|
|
112
|
+
upload: true,
|
|
113
|
+
});
|
|
117
114
|
// Read file content
|
|
118
115
|
const fileContent = await fs.readFile(localPath);
|
|
119
116
|
// Determine content type based on file extension
|
|
@@ -133,91 +130,92 @@ async function uploadToSupabase(storageKey, localPath) {
|
|
|
133
130
|
".zip": "application/zip",
|
|
134
131
|
};
|
|
135
132
|
const contentType = contentTypeMap[ext] || "application/octet-stream";
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
133
|
+
// Upload using signed URL
|
|
134
|
+
const response = await fetch(signedUrl, {
|
|
135
|
+
method: "PUT",
|
|
136
|
+
body: fileContent,
|
|
137
|
+
headers: {
|
|
138
|
+
"Content-Type": contentType,
|
|
139
|
+
},
|
|
141
140
|
});
|
|
142
|
-
if (
|
|
143
|
-
throw new Error(`Failed to upload to Supabase Storage: ${
|
|
141
|
+
if (!response.ok) {
|
|
142
|
+
throw new Error(`Failed to upload to Supabase Storage: ${response.status} ${response.statusText}`);
|
|
144
143
|
}
|
|
145
144
|
}
|
|
146
145
|
/**
|
|
147
|
-
* Download a file from Supabase Storage
|
|
146
|
+
* Download a file from Supabase Storage using signed URL
|
|
148
147
|
*/
|
|
149
148
|
async function downloadFromSupabase(storageKey, localPath) {
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
149
|
+
const auth = getShedAuth();
|
|
150
|
+
if (auth === null)
|
|
151
|
+
throw new Error(`agent/artifacts: could not fetch shed auth`);
|
|
152
|
+
const { shedUrl, accessToken } = auth;
|
|
153
|
+
// Get signed download URL from server
|
|
154
|
+
const signedUrl = await createClient({
|
|
155
|
+
shedUrl,
|
|
156
|
+
accessToken,
|
|
157
|
+
}).getArtifactUrl.query({
|
|
158
|
+
kind: "user",
|
|
159
|
+
key: storageKey,
|
|
160
|
+
upload: false,
|
|
161
|
+
});
|
|
162
|
+
// Download file using signed URL
|
|
163
|
+
const response = await fetch(signedUrl);
|
|
164
|
+
if (!response.ok) {
|
|
165
|
+
throw new Error(`Failed to download from Supabase Storage: ${response.status} ${response.statusText}`);
|
|
157
166
|
}
|
|
167
|
+
const data = await response.arrayBuffer();
|
|
158
168
|
if (!data) {
|
|
159
169
|
throw new Error("Supabase Storage response body is empty");
|
|
160
170
|
}
|
|
161
171
|
// Ensure parent directory exists
|
|
162
172
|
const dir = path.dirname(localPath);
|
|
163
173
|
await fs.mkdir(dir, { recursive: true });
|
|
164
|
-
// Convert
|
|
165
|
-
const
|
|
166
|
-
const buffer = Buffer.from(arrayBuffer);
|
|
174
|
+
// Convert ArrayBuffer to Buffer and write
|
|
175
|
+
const buffer = Buffer.from(data);
|
|
167
176
|
await fs.writeFile(localPath, buffer);
|
|
168
177
|
}
|
|
169
178
|
/**
|
|
170
179
|
* Delete a file from Supabase Storage
|
|
171
180
|
*/
|
|
172
181
|
async function deleteFromSupabase(storageKey) {
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
182
|
+
const auth = getShedAuth();
|
|
183
|
+
if (auth === null)
|
|
184
|
+
throw new Error(`agent/artifacts: could not fetch shed auth`);
|
|
185
|
+
const { shedUrl, accessToken } = auth;
|
|
186
|
+
// Call the delete API endpoint
|
|
187
|
+
await createClient({ shedUrl, accessToken }).deleteArtifact.mutate({
|
|
188
|
+
kind: "user",
|
|
189
|
+
key: storageKey,
|
|
190
|
+
});
|
|
179
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* List files in Supabase Storage with optional prefix and recursion
|
|
194
|
+
*/
|
|
180
195
|
async function listFilesInSupabase(sessionId, relativePath, recursive = false) {
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
? undefined
|
|
191
|
-
: {
|
|
192
|
-
limit: 100,
|
|
193
|
-
offset: 0,
|
|
194
|
-
sortBy: { column: "name", order: "asc" },
|
|
195
|
-
};
|
|
196
|
-
const { data, error } = await supabase.storage
|
|
197
|
-
.from(bucket)
|
|
198
|
-
.list(basePath, options);
|
|
199
|
-
if (error) {
|
|
200
|
-
throw new Error(`Failed to list files in Supabase Storage: ${error.message}`);
|
|
201
|
-
}
|
|
202
|
-
return data || [];
|
|
196
|
+
const auth = getShedAuth();
|
|
197
|
+
if (auth === null)
|
|
198
|
+
throw new Error(`agent/artifacts: could not fetch shed auth`);
|
|
199
|
+
const { shedUrl, accessToken } = auth;
|
|
200
|
+
return await createClient({ shedUrl, accessToken }).listArtifacts.query({
|
|
201
|
+
kind: "user",
|
|
202
|
+
key: buildStorageKey(sessionId, relativePath ?? ""),
|
|
203
|
+
recursive,
|
|
204
|
+
});
|
|
203
205
|
}
|
|
204
206
|
/**
|
|
205
207
|
* Generate a signed URL for a Supabase Storage object
|
|
206
208
|
*/
|
|
207
|
-
async
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
throw new Error("Signed URL not returned from Supabase Storage");
|
|
218
|
-
}
|
|
219
|
-
return data.signedUrl;
|
|
220
|
-
}
|
|
209
|
+
const generateSignedUrl = async (storageKey) => {
|
|
210
|
+
const shedAuth = getShedAuth();
|
|
211
|
+
if (shedAuth === null)
|
|
212
|
+
throw new Error("agent/artifacts: could not fetch shed auth");
|
|
213
|
+
const { accessToken, shedUrl } = shedAuth;
|
|
214
|
+
return await createClient({ shedUrl, accessToken }).getArtifactUrl.query({
|
|
215
|
+
kind: "user",
|
|
216
|
+
key: storageKey,
|
|
217
|
+
});
|
|
218
|
+
};
|
|
221
219
|
// ============================================================================
|
|
222
220
|
// Error Handling Helpers
|
|
223
221
|
// ============================================================================
|
|
@@ -391,17 +389,12 @@ const artifactsLs = tool(async ({ session_id, path, recursive = false, }) => {
|
|
|
391
389
|
/**
|
|
392
390
|
* Tool 4: artifacts_url - Generate signed URL
|
|
393
391
|
*/
|
|
394
|
-
const artifactsUrl = tool(async ({ session_id, path,
|
|
392
|
+
const artifactsUrl = tool(async ({ session_id, path, }) => {
|
|
395
393
|
try {
|
|
396
394
|
validateStoragePath(path);
|
|
397
|
-
validateExpiration(expires_in);
|
|
398
395
|
const storageKey = buildStorageKey(session_id, path);
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
const expiryStr = expiryHours >= 1
|
|
402
|
-
? `${expiryHours.toFixed(1)} hour(s)`
|
|
403
|
-
: `${expires_in} second(s)`;
|
|
404
|
-
return `Signed URL for ${path} (expires in ${expiryStr}):\n${url}`;
|
|
396
|
+
const _url = await generateSignedUrl(storageKey);
|
|
397
|
+
return `Signed URL for ${path}`;
|
|
405
398
|
}
|
|
406
399
|
catch (error) {
|
|
407
400
|
return handleStorageError(error, `Failed to generate URL for ${path}`);
|
|
@@ -423,32 +416,44 @@ const artifactsUrl = tool(async ({ session_id, path, expires_in = 3600, }) => {
|
|
|
423
416
|
.describe("Expiration time in seconds (1-31536000). Default: 3600 (1 hour)"),
|
|
424
417
|
}),
|
|
425
418
|
});
|
|
419
|
+
// ============================================================================
|
|
420
|
+
// Tool Metadata
|
|
421
|
+
// ============================================================================
|
|
426
422
|
// Add metadata for UI display
|
|
423
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata assignment to tool objects
|
|
427
424
|
artifactsCp.prettyName = "Copy Artifact";
|
|
425
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata assignment to tool objects
|
|
428
426
|
artifactsCp.icon = "Upload";
|
|
427
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata assignment to tool objects
|
|
429
428
|
artifactsCp.verbiage = {
|
|
430
429
|
active: "Copying artifact to {destination}",
|
|
431
430
|
past: "Copied artifact to {destination}",
|
|
432
431
|
paramKey: "destination",
|
|
433
432
|
};
|
|
434
|
-
|
|
435
|
-
|
|
433
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata assignment to tool objects
|
|
434
|
+
artifactsDel.prettyName = "Delete Artifact";
|
|
435
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata assignment to tool objects
|
|
436
436
|
artifactsDel.icon = "Trash";
|
|
437
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata assignment to tool objects
|
|
437
438
|
artifactsDel.verbiage = {
|
|
438
439
|
active: "Deleting artifact {path}",
|
|
439
440
|
past: "Deleted artifact {path}",
|
|
440
441
|
paramKey: "path",
|
|
441
442
|
};
|
|
442
|
-
|
|
443
|
-
|
|
443
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata assignment to tool objects
|
|
444
|
+
artifactsLs.prettyName = "List Artifacts";
|
|
445
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata assignment to tool objects
|
|
444
446
|
artifactsLs.icon = "List";
|
|
447
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata assignment to tool objects
|
|
445
448
|
artifactsLs.verbiage = {
|
|
446
449
|
active: "Listing artifacts",
|
|
447
450
|
past: "Listed artifacts",
|
|
448
451
|
};
|
|
449
|
-
|
|
450
|
-
|
|
452
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata assignment to tool objects
|
|
453
|
+
artifactsUrl.prettyName = "Generate Artifact URL";
|
|
454
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata assignment to tool objects
|
|
451
455
|
artifactsUrl.icon = "Link";
|
|
456
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata assignment to tool objects
|
|
452
457
|
artifactsUrl.verbiage = {
|
|
453
458
|
active: "Generating URL for {path}",
|
|
454
459
|
past: "Generated URL for {path}",
|
|
@@ -40,16 +40,16 @@ interface BrowserCloseResult {
|
|
|
40
40
|
export declare function makeBrowserTools(): readonly [import("langchain").DynamicStructuredTool<z.ZodObject<{
|
|
41
41
|
url: z.ZodString;
|
|
42
42
|
waitUntil: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
43
|
-
load: "load";
|
|
44
43
|
domcontentloaded: "domcontentloaded";
|
|
44
|
+
load: "load";
|
|
45
45
|
networkidle: "networkidle";
|
|
46
46
|
}>>>;
|
|
47
47
|
}, z.core.$strip>, {
|
|
48
48
|
url: string;
|
|
49
|
-
waitUntil: "
|
|
49
|
+
waitUntil: "domcontentloaded" | "load" | "networkidle";
|
|
50
50
|
}, {
|
|
51
51
|
url: string;
|
|
52
|
-
waitUntil?: "
|
|
52
|
+
waitUntil?: "domcontentloaded" | "load" | "networkidle" | undefined;
|
|
53
53
|
}, BrowserNavigateResult>, import("langchain").DynamicStructuredTool<z.ZodObject<{
|
|
54
54
|
fullPage: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
55
55
|
selector: z.ZodOptional<z.ZodString>;
|
|
@@ -62,28 +62,28 @@ export declare function makeBrowserTools(): readonly [import("langchain").Dynami
|
|
|
62
62
|
}, BrowserScreenshotResult>, import("langchain").DynamicStructuredTool<z.ZodObject<{
|
|
63
63
|
selector: z.ZodOptional<z.ZodString>;
|
|
64
64
|
extractType: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
65
|
-
text: "text";
|
|
66
65
|
html: "html";
|
|
66
|
+
text: "text";
|
|
67
67
|
}>>>;
|
|
68
68
|
}, z.core.$strip>, {
|
|
69
|
-
extractType: "text" | "html";
|
|
70
69
|
selector?: string | undefined;
|
|
70
|
+
extractType: "html" | "text";
|
|
71
71
|
}, {
|
|
72
72
|
selector?: string | undefined;
|
|
73
|
-
extractType?: "
|
|
73
|
+
extractType?: "html" | "text" | undefined;
|
|
74
74
|
}, BrowserExtractResult>, import("langchain").DynamicStructuredTool<z.ZodObject<{
|
|
75
75
|
selector: z.ZodString;
|
|
76
76
|
button: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
77
77
|
left: "left";
|
|
78
|
-
right: "right";
|
|
79
78
|
middle: "middle";
|
|
79
|
+
right: "right";
|
|
80
80
|
}>>>;
|
|
81
81
|
}, z.core.$strip>, {
|
|
82
82
|
selector: string;
|
|
83
|
-
button: "left" | "
|
|
83
|
+
button: "left" | "middle" | "right";
|
|
84
84
|
}, {
|
|
85
85
|
selector: string;
|
|
86
|
-
button?: "left" | "
|
|
86
|
+
button?: "left" | "middle" | "right" | undefined;
|
|
87
87
|
}, BrowserClickResult>, import("langchain").DynamicStructuredTool<z.ZodObject<{
|
|
88
88
|
selector: z.ZodString;
|
|
89
89
|
text: z.ZodString;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document extraction tool for extracting relevant information from large files
|
|
3
|
+
*
|
|
4
|
+
* Uses the document context extractor to intelligently extract relevant
|
|
5
|
+
* information from large documents based on a query/requirements description.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
/**
|
|
9
|
+
* Factory function to create the document extract tool
|
|
10
|
+
*/
|
|
11
|
+
export declare function makeDocumentExtractTool(): import("langchain").DynamicStructuredTool<z.ZodObject<{
|
|
12
|
+
session_id: z.ZodOptional<z.ZodString>;
|
|
13
|
+
file_path: z.ZodString;
|
|
14
|
+
query: z.ZodString;
|
|
15
|
+
target_tokens: z.ZodOptional<z.ZodNumber>;
|
|
16
|
+
}, z.core.$strip>, {
|
|
17
|
+
session_id: string;
|
|
18
|
+
file_path: string;
|
|
19
|
+
query: string;
|
|
20
|
+
target_tokens?: number;
|
|
21
|
+
}, {
|
|
22
|
+
session_id?: string | undefined;
|
|
23
|
+
file_path: string;
|
|
24
|
+
query: string;
|
|
25
|
+
target_tokens?: number | undefined;
|
|
26
|
+
}, string>;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document extraction tool for extracting relevant information from large files
|
|
3
|
+
*
|
|
4
|
+
* Uses the document context extractor to intelligently extract relevant
|
|
5
|
+
* information from large documents based on a query/requirements description.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "node:fs/promises";
|
|
8
|
+
import { tool } from "langchain";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { createLogger } from "../../../logger.js";
|
|
11
|
+
import { countTokens } from "../../../utils/token-counter.js";
|
|
12
|
+
import { extractDocumentContext } from "../../hooks/predefined/document-context-extractor/index.js";
|
|
13
|
+
const logger = createLogger("document-extract-tool");
|
|
14
|
+
// Minimum document size (in tokens) to use extraction
|
|
15
|
+
// Smaller documents are returned as-is
|
|
16
|
+
const MIN_EXTRACTION_THRESHOLD = 10000;
|
|
17
|
+
// Default target size for extraction output
|
|
18
|
+
const DEFAULT_TARGET_TOKENS = 20000;
|
|
19
|
+
/**
|
|
20
|
+
* Document extraction tool
|
|
21
|
+
*
|
|
22
|
+
* Reads a file and extracts relevant information based on the provided query.
|
|
23
|
+
* For large documents, uses intelligent chunking and relevance scoring.
|
|
24
|
+
* Small documents are returned as-is.
|
|
25
|
+
*/
|
|
26
|
+
const documentExtract = tool(async ({ session_id, file_path, query, target_tokens, }) => {
|
|
27
|
+
try {
|
|
28
|
+
// Read the file content
|
|
29
|
+
const content = await fs.readFile(file_path, "utf-8");
|
|
30
|
+
// Try to parse as JSON, otherwise treat as plain text
|
|
31
|
+
let parsedContent;
|
|
32
|
+
try {
|
|
33
|
+
parsedContent = JSON.parse(content);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Not JSON, wrap as text object
|
|
37
|
+
parsedContent = { content };
|
|
38
|
+
}
|
|
39
|
+
// Count tokens in the document
|
|
40
|
+
const documentTokens = countTokens(content);
|
|
41
|
+
logger.info("Document extraction requested", {
|
|
42
|
+
filePath: file_path,
|
|
43
|
+
documentTokens,
|
|
44
|
+
query: query.substring(0, 100),
|
|
45
|
+
sessionId: session_id,
|
|
46
|
+
});
|
|
47
|
+
// If document is small enough, return as-is
|
|
48
|
+
if (documentTokens <= MIN_EXTRACTION_THRESHOLD) {
|
|
49
|
+
logger.info("Document below extraction threshold, returning as-is", {
|
|
50
|
+
documentTokens,
|
|
51
|
+
threshold: MIN_EXTRACTION_THRESHOLD,
|
|
52
|
+
});
|
|
53
|
+
return content;
|
|
54
|
+
}
|
|
55
|
+
// Use document context extractor for large documents
|
|
56
|
+
const targetSize = target_tokens ?? DEFAULT_TARGET_TOKENS;
|
|
57
|
+
const result = await extractDocumentContext(parsedContent, "document_extract", // toolName
|
|
58
|
+
`extract-${Date.now()}`, // toolCallId
|
|
59
|
+
{ file_path, query }, // toolInput
|
|
60
|
+
query, // conversationContext (use query as context)
|
|
61
|
+
targetSize, session_id, undefined);
|
|
62
|
+
if (result.success && result.extractedData) {
|
|
63
|
+
logger.info("Document extraction successful", {
|
|
64
|
+
originalTokens: result.metadata.originalTokens,
|
|
65
|
+
extractedTokens: result.extractedTokens,
|
|
66
|
+
chunksProcessed: result.metadata.chunksProcessed,
|
|
67
|
+
chunksExtractedFrom: result.metadata.chunksExtractedFrom,
|
|
68
|
+
});
|
|
69
|
+
// Return extracted content as formatted string
|
|
70
|
+
return JSON.stringify(result.extractedData, null, 2);
|
|
71
|
+
}
|
|
72
|
+
// Extraction failed
|
|
73
|
+
logger.error("Document extraction failed", {
|
|
74
|
+
error: result.error,
|
|
75
|
+
phase: result.metadata.phase,
|
|
76
|
+
});
|
|
77
|
+
return `Error: Failed to extract from document: ${result.error}`;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
81
|
+
logger.error("Document extract tool error", {
|
|
82
|
+
filePath: file_path,
|
|
83
|
+
error: errorMessage,
|
|
84
|
+
});
|
|
85
|
+
// Check for common errors
|
|
86
|
+
if (errorMessage.includes("ENOENT") ||
|
|
87
|
+
errorMessage.includes("no such file")) {
|
|
88
|
+
return `Error: File not found at path: ${file_path}`;
|
|
89
|
+
}
|
|
90
|
+
if (errorMessage.includes("EACCES")) {
|
|
91
|
+
return `Error: Permission denied reading file: ${file_path}`;
|
|
92
|
+
}
|
|
93
|
+
return `Error: ${errorMessage}`;
|
|
94
|
+
}
|
|
95
|
+
}, {
|
|
96
|
+
name: "document_extract",
|
|
97
|
+
description: "Extract relevant information from a large document file based on a query. " +
|
|
98
|
+
"Use this tool when you need to find specific information in a large file " +
|
|
99
|
+
"(e.g., JSON data, logs, API responses) that would be too large to process directly. " +
|
|
100
|
+
"The tool intelligently identifies and extracts the most relevant portions of the document. " +
|
|
101
|
+
"For small files (under 10,000 tokens), returns the full content.",
|
|
102
|
+
schema: z.object({
|
|
103
|
+
session_id: z
|
|
104
|
+
.string()
|
|
105
|
+
.optional()
|
|
106
|
+
.describe("INTERNAL USE ONLY - Auto-injected by system"),
|
|
107
|
+
file_path: z
|
|
108
|
+
.string()
|
|
109
|
+
.describe("Absolute path to the file to extract from (e.g., '/tmp/data.json')"),
|
|
110
|
+
query: z
|
|
111
|
+
.string()
|
|
112
|
+
.describe("Description of what information to extract from the document. " +
|
|
113
|
+
"Be specific about what you're looking for."),
|
|
114
|
+
target_tokens: z
|
|
115
|
+
.number()
|
|
116
|
+
.optional()
|
|
117
|
+
.describe("Target size for extracted output in tokens (default: 20000). " +
|
|
118
|
+
"Use smaller values if you need a more concise summary."),
|
|
119
|
+
}),
|
|
120
|
+
});
|
|
121
|
+
// Add metadata for UI display
|
|
122
|
+
documentExtract.prettyName =
|
|
123
|
+
"Extract from Document";
|
|
124
|
+
documentExtract.icon = "FileSearch";
|
|
125
|
+
documentExtract.verbiage = {
|
|
126
|
+
active: "Extracting relevant information from {file_path}",
|
|
127
|
+
past: "Extracted relevant information from {file_path}",
|
|
128
|
+
paramKey: "file_path",
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Factory function to create the document extract tool
|
|
132
|
+
*/
|
|
133
|
+
export function makeDocumentExtractTool() {
|
|
134
|
+
return documentExtract;
|
|
135
|
+
}
|
|
@@ -9,8 +9,8 @@ export declare function makeFilesystemTools(): readonly [import("langchain").Dyn
|
|
|
9
9
|
glob: z.ZodOptional<z.ZodString>;
|
|
10
10
|
output_mode: z.ZodOptional<z.ZodEnum<{
|
|
11
11
|
content: "content";
|
|
12
|
-
files_with_matches: "files_with_matches";
|
|
13
12
|
count: "count";
|
|
13
|
+
files_with_matches: "files_with_matches";
|
|
14
14
|
}>>;
|
|
15
15
|
"-B": z.ZodOptional<z.ZodNumber>;
|
|
16
16
|
"-A": z.ZodOptional<z.ZodNumber>;
|
|
@@ -24,7 +24,7 @@ export declare function makeFilesystemTools(): readonly [import("langchain").Dyn
|
|
|
24
24
|
pattern: string;
|
|
25
25
|
path?: string | undefined;
|
|
26
26
|
glob?: string | undefined;
|
|
27
|
-
output_mode?: "content" | "
|
|
27
|
+
output_mode?: "content" | "count" | "files_with_matches" | undefined;
|
|
28
28
|
"-B"?: number | undefined;
|
|
29
29
|
"-A"?: number | undefined;
|
|
30
30
|
"-C"?: number | undefined;
|
|
@@ -37,7 +37,7 @@ export declare function makeFilesystemTools(): readonly [import("langchain").Dyn
|
|
|
37
37
|
pattern: string;
|
|
38
38
|
path?: string | undefined;
|
|
39
39
|
glob?: string | undefined;
|
|
40
|
-
output_mode?: "content" | "
|
|
40
|
+
output_mode?: "content" | "count" | "files_with_matches" | undefined;
|
|
41
41
|
"-B"?: number | undefined;
|
|
42
42
|
"-A"?: number | undefined;
|
|
43
43
|
"-C"?: number | undefined;
|
|
@@ -12,36 +12,36 @@ interface GenerateImageResult {
|
|
|
12
12
|
export declare function makeGenerateImageTool(): import("langchain").DynamicStructuredTool<z.ZodObject<{
|
|
13
13
|
prompt: z.ZodString;
|
|
14
14
|
aspectRatio: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
15
|
+
"16:9": "16:9";
|
|
15
16
|
"1:1": "1:1";
|
|
16
17
|
"3:4": "3:4";
|
|
17
18
|
"4:3": "4:3";
|
|
18
|
-
"9:16": "9:16";
|
|
19
|
-
"16:9": "16:9";
|
|
20
19
|
"5:4": "5:4";
|
|
20
|
+
"9:16": "9:16";
|
|
21
21
|
}>>>;
|
|
22
22
|
}, z.core.$strip>, {
|
|
23
23
|
prompt: string;
|
|
24
|
-
aspectRatio: "1:1" | "3:4" | "4:3" | "
|
|
24
|
+
aspectRatio: "16:9" | "1:1" | "3:4" | "4:3" | "5:4" | "9:16";
|
|
25
25
|
}, {
|
|
26
26
|
prompt: string;
|
|
27
|
-
aspectRatio?: "1:1" | "3:4" | "4:3" | "
|
|
27
|
+
aspectRatio?: "16:9" | "1:1" | "3:4" | "4:3" | "5:4" | "9:16" | undefined;
|
|
28
28
|
}, GenerateImageResult>;
|
|
29
29
|
/** Create generate image tool using Town proxy */
|
|
30
30
|
export declare function makeTownGenerateImageTool(): import("langchain").DynamicStructuredTool<z.ZodObject<{
|
|
31
31
|
prompt: z.ZodString;
|
|
32
32
|
aspectRatio: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
33
|
+
"16:9": "16:9";
|
|
33
34
|
"1:1": "1:1";
|
|
34
35
|
"3:4": "3:4";
|
|
35
36
|
"4:3": "4:3";
|
|
36
|
-
"9:16": "9:16";
|
|
37
|
-
"16:9": "16:9";
|
|
38
37
|
"5:4": "5:4";
|
|
38
|
+
"9:16": "9:16";
|
|
39
39
|
}>>>;
|
|
40
40
|
}, z.core.$strip>, {
|
|
41
41
|
prompt: string;
|
|
42
|
-
aspectRatio: "1:1" | "3:4" | "4:3" | "
|
|
42
|
+
aspectRatio: "16:9" | "1:1" | "3:4" | "4:3" | "5:4" | "9:16";
|
|
43
43
|
}, {
|
|
44
44
|
prompt: string;
|
|
45
|
-
aspectRatio?: "1:1" | "3:4" | "4:3" | "
|
|
45
|
+
aspectRatio?: "16:9" | "1:1" | "3:4" | "4:3" | "5:4" | "9:16" | undefined;
|
|
46
46
|
}, GenerateImageResult>;
|
|
47
47
|
export {};
|
|
@@ -3,9 +3,9 @@ export declare const TODO_WRITE_TOOL_NAME = "todo_write";
|
|
|
3
3
|
export declare const todoItemSchema: z.ZodObject<{
|
|
4
4
|
content: z.ZodString;
|
|
5
5
|
status: z.ZodEnum<{
|
|
6
|
-
pending: "pending";
|
|
7
|
-
in_progress: "in_progress";
|
|
8
6
|
completed: "completed";
|
|
7
|
+
in_progress: "in_progress";
|
|
8
|
+
pending: "pending";
|
|
9
9
|
}>;
|
|
10
10
|
activeForm: z.ZodString;
|
|
11
11
|
}, z.core.$strip>;
|
|
@@ -13,22 +13,22 @@ export declare function makeTodoWriteTool(): import("langchain").DynamicStructur
|
|
|
13
13
|
todos: z.ZodArray<z.ZodObject<{
|
|
14
14
|
content: z.ZodString;
|
|
15
15
|
status: z.ZodEnum<{
|
|
16
|
-
pending: "pending";
|
|
17
|
-
in_progress: "in_progress";
|
|
18
16
|
completed: "completed";
|
|
17
|
+
in_progress: "in_progress";
|
|
18
|
+
pending: "pending";
|
|
19
19
|
}>;
|
|
20
20
|
activeForm: z.ZodString;
|
|
21
21
|
}, z.core.$strip>>;
|
|
22
22
|
}, z.core.$strip>, {
|
|
23
23
|
todos: {
|
|
24
24
|
content: string;
|
|
25
|
-
status: "
|
|
25
|
+
status: "completed" | "in_progress" | "pending";
|
|
26
26
|
activeForm: string;
|
|
27
27
|
}[];
|
|
28
28
|
}, {
|
|
29
29
|
todos: {
|
|
30
30
|
content: string;
|
|
31
|
-
status: "
|
|
31
|
+
status: "completed" | "in_progress" | "pending";
|
|
32
32
|
activeForm: string;
|
|
33
33
|
}[];
|
|
34
34
|
}, string>;
|
|
@@ -36,22 +36,22 @@ export declare const todoWrite: import("langchain").DynamicStructuredTool<z.ZodO
|
|
|
36
36
|
todos: z.ZodArray<z.ZodObject<{
|
|
37
37
|
content: z.ZodString;
|
|
38
38
|
status: z.ZodEnum<{
|
|
39
|
-
pending: "pending";
|
|
40
|
-
in_progress: "in_progress";
|
|
41
39
|
completed: "completed";
|
|
40
|
+
in_progress: "in_progress";
|
|
41
|
+
pending: "pending";
|
|
42
42
|
}>;
|
|
43
43
|
activeForm: z.ZodString;
|
|
44
44
|
}, z.core.$strip>>;
|
|
45
45
|
}, z.core.$strip>, {
|
|
46
46
|
todos: {
|
|
47
47
|
content: string;
|
|
48
|
-
status: "
|
|
48
|
+
status: "completed" | "in_progress" | "pending";
|
|
49
49
|
activeForm: string;
|
|
50
50
|
}[];
|
|
51
51
|
}, {
|
|
52
52
|
todos: {
|
|
53
53
|
content: string;
|
|
54
|
-
status: "
|
|
54
|
+
status: "completed" | "in_progress" | "pending";
|
|
55
55
|
activeForm: string;
|
|
56
56
|
}[];
|
|
57
57
|
}, string>;
|
package/dist/runner/tools.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
/** Built-in tool types. */
|
|
3
|
-
export declare const zBuiltInToolType: z.ZodUnion<readonly [z.ZodLiteral<"artifacts">, z.ZodLiteral<"todo_write">, z.ZodLiteral<"get_weather">, z.ZodLiteral<"web_search">, z.ZodLiteral<"town_web_search">, z.ZodLiteral<"filesystem">, z.ZodLiteral<"generate_image">, z.ZodLiteral<"town_generate_image">, z.ZodLiteral<"browser">]>;
|
|
3
|
+
export declare const zBuiltInToolType: z.ZodUnion<readonly [z.ZodLiteral<"artifacts">, z.ZodLiteral<"todo_write">, z.ZodLiteral<"get_weather">, z.ZodLiteral<"web_search">, z.ZodLiteral<"town_web_search">, z.ZodLiteral<"filesystem">, z.ZodLiteral<"generate_image">, z.ZodLiteral<"town_generate_image">, z.ZodLiteral<"browser">, z.ZodLiteral<"document_extract">]>;
|
|
4
4
|
/** Subagent configuration schema for Task tools. */
|
|
5
5
|
export declare const zSubagentConfig: z.ZodObject<{
|
|
6
6
|
agentName: z.ZodString;
|
|
@@ -23,7 +23,7 @@ declare const zDirectTool: z.ZodObject<{
|
|
|
23
23
|
}, z.core.$strip>>>;
|
|
24
24
|
}, z.core.$strip>;
|
|
25
25
|
/** Tool type - can be a built-in tool string or custom tool object. */
|
|
26
|
-
export declare const zToolType: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"artifacts">, z.ZodLiteral<"todo_write">, z.ZodLiteral<"get_weather">, z.ZodLiteral<"web_search">, z.ZodLiteral<"town_web_search">, z.ZodLiteral<"filesystem">, z.ZodLiteral<"generate_image">, z.ZodLiteral<"town_generate_image">, z.ZodLiteral<"browser">]>, z.ZodObject<{
|
|
26
|
+
export declare const zToolType: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"artifacts">, z.ZodLiteral<"todo_write">, z.ZodLiteral<"get_weather">, z.ZodLiteral<"web_search">, z.ZodLiteral<"town_web_search">, z.ZodLiteral<"filesystem">, z.ZodLiteral<"generate_image">, z.ZodLiteral<"town_generate_image">, z.ZodLiteral<"browser">, z.ZodLiteral<"document_extract">]>, z.ZodObject<{
|
|
27
27
|
type: z.ZodLiteral<"custom">;
|
|
28
28
|
modulePath: z.ZodString;
|
|
29
29
|
}, z.core.$strip>, z.ZodObject<{
|