@townco/agent 0.1.83 → 0.1.85

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 (36) hide show
  1. package/dist/acp-server/adapter.js +140 -43
  2. package/dist/acp-server/http.js +55 -0
  3. package/dist/acp-server/session-storage.d.ts +31 -6
  4. package/dist/acp-server/session-storage.js +60 -1
  5. package/dist/definition/index.d.ts +2 -4
  6. package/dist/definition/index.js +1 -2
  7. package/dist/runner/agent-runner.d.ts +2 -3
  8. package/dist/runner/hooks/executor.d.ts +5 -2
  9. package/dist/runner/hooks/executor.js +26 -2
  10. package/dist/runner/hooks/predefined/document-context-extractor/chunk-manager.d.ts +37 -0
  11. package/dist/runner/hooks/predefined/document-context-extractor/chunk-manager.js +134 -0
  12. package/dist/runner/hooks/predefined/document-context-extractor/content-extractor.d.ts +20 -0
  13. package/dist/runner/hooks/predefined/document-context-extractor/content-extractor.js +171 -0
  14. package/dist/runner/hooks/predefined/document-context-extractor/extraction-state.d.ts +57 -0
  15. package/dist/runner/hooks/predefined/document-context-extractor/extraction-state.js +126 -0
  16. package/dist/runner/hooks/predefined/document-context-extractor/index.d.ts +22 -0
  17. package/dist/runner/hooks/predefined/document-context-extractor/index.js +338 -0
  18. package/dist/runner/hooks/predefined/document-context-extractor/relevance-scorer.d.ts +19 -0
  19. package/dist/runner/hooks/predefined/document-context-extractor/relevance-scorer.js +156 -0
  20. package/dist/runner/hooks/predefined/document-context-extractor/types.d.ts +130 -0
  21. package/dist/runner/hooks/predefined/document-context-extractor/types.js +8 -0
  22. package/dist/runner/hooks/predefined/tool-response-compactor.d.ts +0 -4
  23. package/dist/runner/hooks/predefined/tool-response-compactor.js +101 -222
  24. package/dist/runner/hooks/types.d.ts +18 -12
  25. package/dist/runner/langchain/index.js +64 -11
  26. package/dist/runner/langchain/tools/artifacts.js +6 -9
  27. package/dist/runner/langchain/tools/document_extract.d.ts +26 -0
  28. package/dist/runner/langchain/tools/document_extract.js +135 -0
  29. package/dist/runner/tools.d.ts +2 -2
  30. package/dist/runner/tools.js +1 -0
  31. package/dist/templates/index.d.ts +1 -2
  32. package/dist/tsconfig.tsbuildinfo +1 -1
  33. package/dist/utils/context-size-calculator.d.ts +1 -10
  34. package/dist/utils/context-size-calculator.js +1 -12
  35. package/package.json +6 -6
  36. package/templates/index.ts +1 -2
@@ -177,9 +177,6 @@ async function deleteFromSupabase(storageKey) {
177
177
  throw new Error(`Failed to delete from Supabase Storage: ${error.message}`);
178
178
  }
179
179
  }
180
- /**
181
- * List files in Supabase Storage with optional prefix and recursion
182
- */
183
180
  async function listFilesInSupabase(sessionId, relativePath, recursive = false) {
184
181
  const supabase = getSupabaseClient();
185
182
  const bucket = getBucketName();
@@ -426,9 +423,6 @@ const artifactsUrl = tool(async ({ session_id, path, expires_in = 3600, }) => {
426
423
  .describe("Expiration time in seconds (1-31536000). Default: 3600 (1 hour)"),
427
424
  }),
428
425
  });
429
- // ============================================================================
430
- // Tool Metadata
431
- // ============================================================================
432
426
  // Add metadata for UI display
433
427
  artifactsCp.prettyName = "Copy Artifact";
434
428
  artifactsCp.icon = "Upload";
@@ -437,20 +431,23 @@ artifactsCp.verbiage = {
437
431
  past: "Copied artifact to {destination}",
438
432
  paramKey: "destination",
439
433
  };
440
- artifactsDel.prettyName = "Delete Artifact";
434
+ artifactsDel.prettyName =
435
+ "Delete Artifact";
441
436
  artifactsDel.icon = "Trash";
442
437
  artifactsDel.verbiage = {
443
438
  active: "Deleting artifact {path}",
444
439
  past: "Deleted artifact {path}",
445
440
  paramKey: "path",
446
441
  };
447
- artifactsLs.prettyName = "List Artifacts";
442
+ artifactsLs.prettyName =
443
+ "List Artifacts";
448
444
  artifactsLs.icon = "List";
449
445
  artifactsLs.verbiage = {
450
446
  active: "Listing artifacts",
451
447
  past: "Listed artifacts",
452
448
  };
453
- artifactsUrl.prettyName = "Generate Artifact URL";
449
+ artifactsUrl.prettyName =
450
+ "Generate Artifact URL";
454
451
  artifactsUrl.icon = "Link";
455
452
  artifactsUrl.verbiage = {
456
453
  active: "Generating URL for {path}",
@@ -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
+ file_path: string;
23
+ query: string;
24
+ session_id?: string | undefined;
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
+ }
@@ -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<{
@@ -10,6 +10,7 @@ export const zBuiltInToolType = z.union([
10
10
  z.literal("generate_image"),
11
11
  z.literal("town_generate_image"),
12
12
  z.literal("browser"),
13
+ z.literal("document_extract"),
13
14
  ]);
14
15
  /** Custom tool schema (loaded from module path). */
15
16
  const zCustomTool = z.object({
@@ -31,8 +31,7 @@ export interface TemplateVars {
31
31
  } | {
32
32
  type: "tool_response";
33
33
  setting?: {
34
- maxContextThreshold?: number | undefined;
35
- responseTruncationThreshold?: number | undefined;
34
+ maxTokensSize?: number | undefined;
36
35
  } | undefined;
37
36
  callback: string;
38
37
  }> | undefined;