@link-assistant/agent 0.0.9 → 0.0.12

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 (104) hide show
  1. package/EXAMPLES.md +36 -0
  2. package/MODELS.md +72 -24
  3. package/README.md +59 -2
  4. package/TOOLS.md +20 -0
  5. package/package.json +35 -2
  6. package/src/agent/agent.ts +68 -54
  7. package/src/auth/claude-oauth.ts +426 -0
  8. package/src/auth/index.ts +28 -26
  9. package/src/auth/plugins.ts +876 -0
  10. package/src/bun/index.ts +53 -43
  11. package/src/bus/global.ts +5 -5
  12. package/src/bus/index.ts +59 -53
  13. package/src/cli/bootstrap.js +12 -12
  14. package/src/cli/bootstrap.ts +6 -6
  15. package/src/cli/cmd/agent.ts +97 -92
  16. package/src/cli/cmd/auth.ts +469 -0
  17. package/src/cli/cmd/cmd.ts +2 -2
  18. package/src/cli/cmd/export.ts +41 -41
  19. package/src/cli/cmd/mcp.ts +144 -119
  20. package/src/cli/cmd/models.ts +30 -29
  21. package/src/cli/cmd/run.ts +269 -213
  22. package/src/cli/cmd/stats.ts +185 -146
  23. package/src/cli/error.ts +17 -13
  24. package/src/cli/ui.ts +39 -24
  25. package/src/command/index.ts +26 -26
  26. package/src/config/config.ts +528 -288
  27. package/src/config/markdown.ts +15 -15
  28. package/src/file/ripgrep.ts +201 -169
  29. package/src/file/time.ts +21 -18
  30. package/src/file/watcher.ts +51 -42
  31. package/src/file.ts +1 -1
  32. package/src/flag/flag.ts +26 -11
  33. package/src/format/formatter.ts +206 -162
  34. package/src/format/index.ts +61 -61
  35. package/src/global/index.ts +21 -21
  36. package/src/id/id.ts +47 -33
  37. package/src/index.js +346 -199
  38. package/src/json-standard/index.ts +67 -51
  39. package/src/mcp/index.ts +135 -128
  40. package/src/patch/index.ts +336 -267
  41. package/src/project/bootstrap.ts +15 -15
  42. package/src/project/instance.ts +43 -36
  43. package/src/project/project.ts +47 -47
  44. package/src/project/state.ts +37 -33
  45. package/src/provider/models-macro.ts +5 -5
  46. package/src/provider/models.ts +32 -32
  47. package/src/provider/opencode.js +19 -19
  48. package/src/provider/provider.ts +518 -277
  49. package/src/provider/transform.ts +143 -102
  50. package/src/server/project.ts +21 -21
  51. package/src/server/server.ts +111 -105
  52. package/src/session/agent.js +66 -60
  53. package/src/session/compaction.ts +136 -111
  54. package/src/session/index.ts +189 -156
  55. package/src/session/message-v2.ts +312 -268
  56. package/src/session/message.ts +73 -57
  57. package/src/session/processor.ts +180 -166
  58. package/src/session/prompt.ts +678 -533
  59. package/src/session/retry.ts +26 -23
  60. package/src/session/revert.ts +76 -62
  61. package/src/session/status.ts +26 -26
  62. package/src/session/summary.ts +97 -76
  63. package/src/session/system.ts +77 -63
  64. package/src/session/todo.ts +22 -16
  65. package/src/snapshot/index.ts +92 -76
  66. package/src/storage/storage.ts +157 -120
  67. package/src/tool/bash.ts +116 -106
  68. package/src/tool/batch.ts +73 -59
  69. package/src/tool/codesearch.ts +60 -53
  70. package/src/tool/edit.ts +319 -263
  71. package/src/tool/glob.ts +32 -28
  72. package/src/tool/grep.ts +72 -53
  73. package/src/tool/invalid.ts +7 -7
  74. package/src/tool/ls.ts +77 -64
  75. package/src/tool/multiedit.ts +30 -21
  76. package/src/tool/patch.ts +121 -94
  77. package/src/tool/read.ts +140 -122
  78. package/src/tool/registry.ts +38 -38
  79. package/src/tool/task.ts +93 -60
  80. package/src/tool/todo.ts +16 -16
  81. package/src/tool/tool.ts +45 -36
  82. package/src/tool/webfetch.ts +97 -74
  83. package/src/tool/websearch.ts +78 -64
  84. package/src/tool/write.ts +21 -15
  85. package/src/util/binary.ts +27 -19
  86. package/src/util/context.ts +8 -8
  87. package/src/util/defer.ts +7 -5
  88. package/src/util/error.ts +24 -19
  89. package/src/util/eventloop.ts +16 -10
  90. package/src/util/filesystem.ts +37 -33
  91. package/src/util/fn.ts +11 -8
  92. package/src/util/iife.ts +1 -1
  93. package/src/util/keybind.ts +44 -44
  94. package/src/util/lazy.ts +7 -7
  95. package/src/util/locale.ts +20 -16
  96. package/src/util/lock.ts +43 -38
  97. package/src/util/log.ts +95 -85
  98. package/src/util/queue.ts +8 -8
  99. package/src/util/rpc.ts +35 -23
  100. package/src/util/scrap.ts +4 -4
  101. package/src/util/signal.ts +5 -5
  102. package/src/util/timeout.ts +6 -6
  103. package/src/util/token.ts +2 -2
  104. package/src/util/wildcard.ts +38 -27
package/src/tool/bash.ts CHANGED
@@ -1,67 +1,75 @@
1
- import z from "zod"
2
- import { spawn } from "child_process"
3
- import { Tool } from "./tool"
4
- import DESCRIPTION from "./bash.txt"
5
- import { Log } from "../util/log"
6
- import { Instance } from "../project/instance"
7
- import { lazy } from "../util/lazy"
8
- import { Language } from "web-tree-sitter"
9
- import { $ } from "bun"
10
- import { Filesystem } from "../util/filesystem"
11
- import { fileURLToPath } from "url"
12
-
13
- const MAX_OUTPUT_LENGTH = 30_000
14
- const DEFAULT_TIMEOUT = 1 * 60 * 1000
15
- const MAX_TIMEOUT = 10 * 60 * 1000
16
- const SIGKILL_TIMEOUT_MS = 200
17
-
18
- export const log = Log.create({ service: "bash-tool" })
1
+ import z from 'zod';
2
+ import { spawn } from 'child_process';
3
+ import { Tool } from './tool';
4
+ import DESCRIPTION from './bash.txt';
5
+ import { Log } from '../util/log';
6
+ import { Instance } from '../project/instance';
7
+ import { lazy } from '../util/lazy';
8
+ import { Language } from 'web-tree-sitter';
9
+ import { $ } from 'bun';
10
+ import { Filesystem } from '../util/filesystem';
11
+ import { fileURLToPath } from 'url';
12
+
13
+ const MAX_OUTPUT_LENGTH = 30_000;
14
+ const DEFAULT_TIMEOUT = 1 * 60 * 1000;
15
+ const MAX_TIMEOUT = 10 * 60 * 1000;
16
+ const SIGKILL_TIMEOUT_MS = 200;
17
+
18
+ export const log = Log.create({ service: 'bash-tool' });
19
19
 
20
20
  const resolveWasm = (asset: string) => {
21
- if (asset.startsWith("file://")) return fileURLToPath(asset)
22
- if (asset.startsWith("/") || /^[a-z]:/i.test(asset)) return asset
23
- const url = new URL(asset, import.meta.url)
24
- return fileURLToPath(url)
25
- }
21
+ if (asset.startsWith('file://')) return fileURLToPath(asset);
22
+ if (asset.startsWith('/') || /^[a-z]:/i.test(asset)) return asset;
23
+ const url = new URL(asset, import.meta.url);
24
+ return fileURLToPath(url);
25
+ };
26
26
 
27
27
  const parser = lazy(async () => {
28
- const { Parser } = await import("web-tree-sitter")
29
- const { default: treeWasm } = await import("web-tree-sitter/tree-sitter.wasm" as string, {
30
- with: { type: "wasm" },
31
- })
32
- const treePath = resolveWasm(treeWasm)
28
+ const { Parser } = await import('web-tree-sitter');
29
+ const { default: treeWasm } = await import(
30
+ 'web-tree-sitter/tree-sitter.wasm' as string,
31
+ {
32
+ with: { type: 'wasm' },
33
+ }
34
+ );
35
+ const treePath = resolveWasm(treeWasm);
33
36
  await Parser.init({
34
37
  locateFile() {
35
- return treePath
38
+ return treePath;
36
39
  },
37
- })
38
- const { default: bashWasm } = await import("tree-sitter-bash/tree-sitter-bash.wasm" as string, {
39
- with: { type: "wasm" },
40
- })
41
- const bashPath = resolveWasm(bashWasm)
42
- const bashLanguage = await Language.load(bashPath)
43
- const p = new Parser()
44
- p.setLanguage(bashLanguage)
45
- return p
46
- })
47
-
48
- export const BashTool = Tool.define("bash", {
40
+ });
41
+ const { default: bashWasm } = await import(
42
+ 'tree-sitter-bash/tree-sitter-bash.wasm' as string,
43
+ {
44
+ with: { type: 'wasm' },
45
+ }
46
+ );
47
+ const bashPath = resolveWasm(bashWasm);
48
+ const bashLanguage = await Language.load(bashPath);
49
+ const p = new Parser();
50
+ p.setLanguage(bashLanguage);
51
+ return p;
52
+ });
53
+
54
+ export const BashTool = Tool.define('bash', {
49
55
  description: DESCRIPTION,
50
56
  parameters: z.object({
51
- command: z.string().describe("The command to execute"),
52
- timeout: z.number().describe("Optional timeout in milliseconds").optional(),
57
+ command: z.string().describe('The command to execute'),
58
+ timeout: z.number().describe('Optional timeout in milliseconds').optional(),
53
59
  description: z
54
60
  .string()
55
61
  .describe(
56
- "Clear, concise description of what this command does in 5-10 words. Examples:\nInput: ls\nOutput: Lists files in current directory\n\nInput: git status\nOutput: Shows working tree status\n\nInput: npm install\nOutput: Installs package dependencies\n\nInput: mkdir foo\nOutput: Creates directory 'foo'",
62
+ "Clear, concise description of what this command does in 5-10 words. Examples:\nInput: ls\nOutput: Lists files in current directory\n\nInput: git status\nOutput: Shows working tree status\n\nInput: npm install\nOutput: Installs package dependencies\n\nInput: mkdir foo\nOutput: Creates directory 'foo'"
57
63
  )
58
64
  .optional(),
59
65
  }),
60
66
  async execute(params, ctx) {
61
67
  if (params.timeout !== undefined && params.timeout < 0) {
62
- throw new Error(`Invalid timeout value: ${params.timeout}. Timeout must be a positive number.`)
68
+ throw new Error(
69
+ `Invalid timeout value: ${params.timeout}. Timeout must be a positive number.`
70
+ );
63
71
  }
64
- const timeout = Math.min(params.timeout ?? DEFAULT_TIMEOUT, MAX_TIMEOUT)
72
+ const timeout = Math.min(params.timeout ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);
65
73
 
66
74
  // No restrictions - unrestricted command execution
67
75
  const proc = spawn(params.command, {
@@ -70,114 +78,116 @@ export const BashTool = Tool.define("bash", {
70
78
  env: {
71
79
  ...process.env,
72
80
  },
73
- stdio: ["ignore", "pipe", "pipe"],
74
- detached: process.platform !== "win32",
75
- })
81
+ stdio: ['ignore', 'pipe', 'pipe'],
82
+ detached: process.platform !== 'win32',
83
+ });
76
84
 
77
- let output = ""
85
+ let output = '';
78
86
 
79
87
  // Initialize metadata with empty output
80
88
  ctx.metadata({
81
89
  metadata: {
82
- output: "",
90
+ output: '',
83
91
  description: params.description,
84
92
  },
85
- })
93
+ });
86
94
 
87
95
  const append = (chunk: Buffer) => {
88
- output += chunk.toString()
96
+ output += chunk.toString();
89
97
  ctx.metadata({
90
98
  metadata: {
91
99
  output,
92
100
  description: params.description,
93
101
  },
94
- })
95
- }
102
+ });
103
+ };
96
104
 
97
- proc.stdout?.on("data", append)
98
- proc.stderr?.on("data", append)
105
+ proc.stdout?.on('data', append);
106
+ proc.stderr?.on('data', append);
99
107
 
100
- let timedOut = false
101
- let aborted = false
102
- let exited = false
108
+ let timedOut = false;
109
+ let aborted = false;
110
+ let exited = false;
103
111
 
104
112
  const killTree = async () => {
105
- const pid = proc.pid
113
+ const pid = proc.pid;
106
114
  if (!pid || exited) {
107
- return
115
+ return;
108
116
  }
109
117
 
110
- if (process.platform === "win32") {
118
+ if (process.platform === 'win32') {
111
119
  await new Promise<void>((resolve) => {
112
- const killer = spawn("taskkill", ["/pid", String(pid), "/f", "/t"], { stdio: "ignore" })
113
- killer.once("exit", resolve)
114
- killer.once("error", resolve)
115
- })
116
- return
120
+ const killer = spawn('taskkill', ['/pid', String(pid), '/f', '/t'], {
121
+ stdio: 'ignore',
122
+ });
123
+ killer.once('exit', resolve);
124
+ killer.once('error', resolve);
125
+ });
126
+ return;
117
127
  }
118
128
 
119
129
  try {
120
- process.kill(-pid, "SIGTERM")
121
- await Bun.sleep(SIGKILL_TIMEOUT_MS)
130
+ process.kill(-pid, 'SIGTERM');
131
+ await Bun.sleep(SIGKILL_TIMEOUT_MS);
122
132
  if (!exited) {
123
- process.kill(-pid, "SIGKILL")
133
+ process.kill(-pid, 'SIGKILL');
124
134
  }
125
135
  } catch (_e) {
126
- proc.kill("SIGTERM")
127
- await Bun.sleep(SIGKILL_TIMEOUT_MS)
136
+ proc.kill('SIGTERM');
137
+ await Bun.sleep(SIGKILL_TIMEOUT_MS);
128
138
  if (!exited) {
129
- proc.kill("SIGKILL")
139
+ proc.kill('SIGKILL');
130
140
  }
131
141
  }
132
- }
142
+ };
133
143
 
134
144
  if (ctx.abort.aborted) {
135
- aborted = true
136
- await killTree()
145
+ aborted = true;
146
+ await killTree();
137
147
  }
138
148
 
139
149
  const abortHandler = () => {
140
- aborted = true
141
- void killTree()
142
- }
150
+ aborted = true;
151
+ void killTree();
152
+ };
143
153
 
144
- ctx.abort.addEventListener("abort", abortHandler, { once: true })
154
+ ctx.abort.addEventListener('abort', abortHandler, { once: true });
145
155
 
146
156
  const timeoutTimer = setTimeout(() => {
147
- timedOut = true
148
- void killTree()
149
- }, timeout)
157
+ timedOut = true;
158
+ void killTree();
159
+ }, timeout);
150
160
 
151
161
  await new Promise<void>((resolve, reject) => {
152
162
  const cleanup = () => {
153
- clearTimeout(timeoutTimer)
154
- ctx.abort.removeEventListener("abort", abortHandler)
155
- }
156
-
157
- proc.once("exit", () => {
158
- exited = true
159
- cleanup()
160
- resolve()
161
- })
162
-
163
- proc.once("error", (error) => {
164
- exited = true
165
- cleanup()
166
- reject(error)
167
- })
168
- })
163
+ clearTimeout(timeoutTimer);
164
+ ctx.abort.removeEventListener('abort', abortHandler);
165
+ };
166
+
167
+ proc.once('exit', () => {
168
+ exited = true;
169
+ cleanup();
170
+ resolve();
171
+ });
172
+
173
+ proc.once('error', (error) => {
174
+ exited = true;
175
+ cleanup();
176
+ reject(error);
177
+ });
178
+ });
169
179
 
170
180
  if (output.length > MAX_OUTPUT_LENGTH) {
171
- output = output.slice(0, MAX_OUTPUT_LENGTH)
172
- output += "\n\n(Output was truncated due to length limit)"
181
+ output = output.slice(0, MAX_OUTPUT_LENGTH);
182
+ output += '\n\n(Output was truncated due to length limit)';
173
183
  }
174
184
 
175
185
  if (timedOut) {
176
- output += `\n\n(Command timed out after ${timeout} ms)`
186
+ output += `\n\n(Command timed out after ${timeout} ms)`;
177
187
  }
178
188
 
179
189
  if (aborted) {
180
- output += "\n\n(Command was aborted)"
190
+ output += '\n\n(Command was aborted)';
181
191
  }
182
192
 
183
193
  return {
@@ -188,6 +198,6 @@ export const BashTool = Tool.define("bash", {
188
198
  description: params.description,
189
199
  },
190
200
  output,
191
- }
201
+ };
192
202
  },
193
- })
203
+ });
package/src/tool/batch.ts CHANGED
@@ -1,90 +1,100 @@
1
- import z from "zod"
2
- import { Tool } from "./tool"
3
- import DESCRIPTION from "./batch.txt"
1
+ import z from 'zod';
2
+ import { Tool } from './tool';
3
+ import DESCRIPTION from './batch.txt';
4
4
 
5
- const DISALLOWED = new Set(["batch", "edit", "todoread"])
6
- const FILTERED_FROM_SUGGESTIONS = new Set(["invalid", "patch", ...DISALLOWED])
5
+ const DISALLOWED = new Set(['batch', 'edit', 'todoread']);
6
+ const FILTERED_FROM_SUGGESTIONS = new Set(['invalid', 'patch', ...DISALLOWED]);
7
7
 
8
- export const BatchTool = Tool.define("batch", async () => {
8
+ export const BatchTool = Tool.define('batch', async () => {
9
9
  return {
10
10
  description: DESCRIPTION,
11
11
  parameters: z.object({
12
12
  tool_calls: z
13
13
  .array(
14
14
  z.object({
15
- tool: z.string().describe("The name of the tool to execute"),
16
- parameters: z.object({}).loose().describe("Parameters for the tool"),
17
- }),
15
+ tool: z.string().describe('The name of the tool to execute'),
16
+ parameters: z
17
+ .object({})
18
+ .loose()
19
+ .describe('Parameters for the tool'),
20
+ })
18
21
  )
19
- .min(1, "Provide at least one tool call")
20
- .describe("Array of tool calls to execute in parallel"),
22
+ .min(1, 'Provide at least one tool call')
23
+ .describe('Array of tool calls to execute in parallel'),
21
24
  }),
22
25
  formatValidationError(error) {
23
26
  const formattedErrors = error.issues
24
27
  .map((issue) => {
25
- const path = issue.path.length > 0 ? issue.path.join(".") : "root"
26
- return ` - ${path}: ${issue.message}`
28
+ const path = issue.path.length > 0 ? issue.path.join('.') : 'root';
29
+ return ` - ${path}: ${issue.message}`;
27
30
  })
28
- .join("\n")
31
+ .join('\n');
29
32
 
30
- return `Invalid parameters for tool 'batch':\n${formattedErrors}\n\nExpected payload format:\n [{"tool": "tool_name", "parameters": {...}}, {...}]`
33
+ return `Invalid parameters for tool 'batch':\n${formattedErrors}\n\nExpected payload format:\n [{"tool": "tool_name", "parameters": {...}}, {...}]`;
31
34
  },
32
35
  async execute(params, ctx) {
33
- const { Session } = await import("../session")
34
- const { Identifier } = await import("../id/id")
36
+ const { Session } = await import('../session');
37
+ const { Identifier } = await import('../id/id');
35
38
 
36
- const toolCalls = params.tool_calls.slice(0, 10)
37
- const discardedCalls = params.tool_calls.slice(10)
39
+ const toolCalls = params.tool_calls.slice(0, 10);
40
+ const discardedCalls = params.tool_calls.slice(10);
38
41
 
39
- const { ToolRegistry } = await import("./registry")
40
- const availableTools = await ToolRegistry.tools("", "")
41
- const toolMap = new Map(availableTools.map((t) => [t.id, t]))
42
+ const { ToolRegistry } = await import('./registry');
43
+ const availableTools = await ToolRegistry.tools('', '');
44
+ const toolMap = new Map(availableTools.map((t) => [t.id, t]));
42
45
 
43
46
  const executeCall = async (call: (typeof toolCalls)[0]) => {
44
- const callStartTime = Date.now()
45
- const partID = Identifier.ascending("part")
47
+ const callStartTime = Date.now();
48
+ const partID = Identifier.ascending('part');
46
49
 
47
50
  try {
48
51
  if (DISALLOWED.has(call.tool)) {
49
52
  throw new Error(
50
- `Tool '${call.tool}' is not allowed in batch. Disallowed tools: ${Array.from(DISALLOWED).join(", ")}`,
51
- )
53
+ `Tool '${call.tool}' is not allowed in batch. Disallowed tools: ${Array.from(DISALLOWED).join(', ')}`
54
+ );
52
55
  }
53
56
 
54
- const tool = toolMap.get(call.tool)
57
+ const tool = toolMap.get(call.tool);
55
58
  if (!tool) {
56
- const availableToolsList = Array.from(toolMap.keys()).filter((name) => !FILTERED_FROM_SUGGESTIONS.has(name))
57
- throw new Error(`Tool '${call.tool}' not found. Available tools: ${availableToolsList.join(", ")}`)
59
+ const availableToolsList = Array.from(toolMap.keys()).filter(
60
+ (name) => !FILTERED_FROM_SUGGESTIONS.has(name)
61
+ );
62
+ throw new Error(
63
+ `Tool '${call.tool}' not found. Available tools: ${availableToolsList.join(', ')}`
64
+ );
58
65
  }
59
- const validatedParams = tool.parameters.parse(call.parameters)
66
+ const validatedParams = tool.parameters.parse(call.parameters);
60
67
 
61
68
  await Session.updatePart({
62
69
  id: partID,
63
70
  messageID: ctx.messageID,
64
71
  sessionID: ctx.sessionID,
65
- type: "tool",
72
+ type: 'tool',
66
73
  tool: call.tool,
67
74
  callID: partID,
68
75
  state: {
69
- status: "running",
76
+ status: 'running',
70
77
  input: call.parameters,
71
78
  time: {
72
79
  start: callStartTime,
73
80
  },
74
81
  },
75
- })
82
+ });
76
83
 
77
- const result = await tool.execute(validatedParams, { ...ctx, callID: partID })
84
+ const result = await tool.execute(validatedParams, {
85
+ ...ctx,
86
+ callID: partID,
87
+ });
78
88
 
79
89
  await Session.updatePart({
80
90
  id: partID,
81
91
  messageID: ctx.messageID,
82
92
  sessionID: ctx.sessionID,
83
- type: "tool",
93
+ type: 'tool',
84
94
  tool: call.tool,
85
95
  callID: partID,
86
96
  state: {
87
- status: "completed",
97
+ status: 'completed',
88
98
  input: call.parameters,
89
99
  output: result.output,
90
100
  title: result.title,
@@ -95,19 +105,19 @@ export const BatchTool = Tool.define("batch", async () => {
95
105
  end: Date.now(),
96
106
  },
97
107
  },
98
- })
108
+ });
99
109
 
100
- return { success: true as const, tool: call.tool, result }
110
+ return { success: true as const, tool: call.tool, result };
101
111
  } catch (error) {
102
112
  await Session.updatePart({
103
113
  id: partID,
104
114
  messageID: ctx.messageID,
105
115
  sessionID: ctx.sessionID,
106
- type: "tool",
116
+ type: 'tool',
107
117
  tool: call.tool,
108
118
  callID: partID,
109
119
  state: {
110
- status: "error",
120
+ status: 'error',
111
121
  input: call.parameters,
112
122
  error: error instanceof Error ? error.message : String(error),
113
123
  time: {
@@ -115,51 +125,55 @@ export const BatchTool = Tool.define("batch", async () => {
115
125
  end: Date.now(),
116
126
  },
117
127
  },
118
- })
128
+ });
119
129
 
120
- return { success: false as const, tool: call.tool, error }
130
+ return { success: false as const, tool: call.tool, error };
121
131
  }
122
- }
132
+ };
123
133
 
124
- const results = await Promise.all(toolCalls.map((call) => executeCall(call)))
134
+ const results = await Promise.all(
135
+ toolCalls.map((call) => executeCall(call))
136
+ );
125
137
 
126
138
  // Add discarded calls as errors
127
- const now = Date.now()
139
+ const now = Date.now();
128
140
  for (const call of discardedCalls) {
129
- const partID = Identifier.ascending("part")
141
+ const partID = Identifier.ascending('part');
130
142
  await Session.updatePart({
131
143
  id: partID,
132
144
  messageID: ctx.messageID,
133
145
  sessionID: ctx.sessionID,
134
- type: "tool",
146
+ type: 'tool',
135
147
  tool: call.tool,
136
148
  callID: partID,
137
149
  state: {
138
- status: "error",
150
+ status: 'error',
139
151
  input: call.parameters,
140
- error: "Maximum of 10 tools allowed in batch",
152
+ error: 'Maximum of 10 tools allowed in batch',
141
153
  time: { start: now, end: now },
142
154
  },
143
- })
155
+ });
144
156
  results.push({
145
157
  success: false as const,
146
158
  tool: call.tool,
147
- error: new Error("Maximum of 10 tools allowed in batch"),
148
- })
159
+ error: new Error('Maximum of 10 tools allowed in batch'),
160
+ });
149
161
  }
150
162
 
151
- const successfulCalls = results.filter((r) => r.success).length
152
- const failedCalls = results.length - successfulCalls
163
+ const successfulCalls = results.filter((r) => r.success).length;
164
+ const failedCalls = results.length - successfulCalls;
153
165
 
154
166
  const outputMessage =
155
167
  failedCalls > 0
156
168
  ? `Executed ${successfulCalls}/${results.length} tools successfully. ${failedCalls} failed.`
157
- : `All ${successfulCalls} tools executed successfully.\n\nKeep using the batch tool for optimal performance in your next response!`
169
+ : `All ${successfulCalls} tools executed successfully.\n\nKeep using the batch tool for optimal performance in your next response!`;
158
170
 
159
171
  return {
160
172
  title: `Batch execution (${successfulCalls}/${results.length} successful)`,
161
173
  output: outputMessage,
162
- attachments: results.filter((result) => result.success).flatMap((r) => r.result.attachments ?? []),
174
+ attachments: results
175
+ .filter((result) => result.success)
176
+ .flatMap((r) => r.result.attachments ?? []),
163
177
  metadata: {
164
178
  totalCalls: results.length,
165
179
  successful: successfulCalls,
@@ -167,7 +181,7 @@ export const BatchTool = Tool.define("batch", async () => {
167
181
  tools: params.tool_calls.map((c) => c.tool),
168
182
  details: results.map((r) => ({ tool: r.tool, success: r.success })),
169
183
  },
170
- }
184
+ };
171
185
  },
172
- }
173
- })
186
+ };
187
+ });