lonny-agent 0.2.3 → 0.2.6
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 +326 -326
- package/dist/agent/index.js +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/llm.d.ts +4 -0
- package/dist/agent/llm.d.ts.map +1 -1
- package/dist/agent/project.d.ts +26 -0
- package/dist/agent/project.d.ts.map +1 -0
- package/dist/agent/project.js +303 -0
- package/dist/agent/project.js.map +1 -0
- package/dist/agent/prompt-builder.d.ts +1 -1
- package/dist/agent/prompt-builder.d.ts.map +1 -1
- package/dist/agent/prompt-builder.js +22 -13
- package/dist/agent/prompt-builder.js.map +1 -1
- package/dist/agent/providers/anthropic.d.ts.map +1 -1
- package/dist/agent/providers/anthropic.js +20 -2
- package/dist/agent/providers/anthropic.js.map +1 -1
- package/dist/agent/providers/google.d.ts.map +1 -1
- package/dist/agent/providers/google.js +1 -1
- package/dist/agent/providers/google.js.map +1 -1
- package/dist/agent/providers/ollama.d.ts.map +1 -1
- package/dist/agent/providers/ollama.js +2 -1
- package/dist/agent/providers/ollama.js.map +1 -1
- package/dist/agent/providers/openai.d.ts.map +1 -1
- package/dist/agent/providers/openai.js +63 -3
- package/dist/agent/providers/openai.js.map +1 -1
- package/dist/agent/session.d.ts +8 -2
- package/dist/agent/session.d.ts.map +1 -1
- package/dist/agent/session.js +250 -153
- package/dist/agent/session.js.map +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +7 -1
- package/dist/config/index.js.map +1 -1
- package/dist/tools/__tests__/bash.test.js +1 -1
- package/dist/tools/__tests__/bash.test.js.map +1 -1
- package/dist/tools/__tests__/edit.test.js +875 -371
- package/dist/tools/__tests__/edit.test.js.map +1 -1
- package/dist/tools/__tests__/grep.test.js +32 -0
- package/dist/tools/__tests__/grep.test.js.map +1 -1
- package/dist/tools/__tests__/sed.test.d.ts +2 -0
- package/dist/tools/__tests__/sed.test.d.ts.map +1 -0
- package/dist/tools/__tests__/sed.test.js +228 -0
- package/dist/tools/__tests__/sed.test.js.map +1 -0
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +83 -10
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.d.ts +58 -0
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +366 -149
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +54 -30
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/read.d.ts +6 -0
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +42 -15
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/registry.d.ts +0 -6
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +2 -33
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/sed.d.ts +4 -0
- package/dist/tools/sed.d.ts.map +1 -0
- package/dist/tools/sed.js +121 -0
- package/dist/tools/sed.js.map +1 -0
- package/dist/tools/write_plan.d.ts +1 -1
- package/dist/tools/write_plan.d.ts.map +1 -1
- package/dist/tools/write_plan.js +14 -4
- package/dist/tools/write_plan.js.map +1 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +5 -4
- package/dist/tui/index.js.map +1 -1
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +30 -7
- package/dist/web/index.js.map +1 -1
- package/dist/web/public/app.js +5 -855
- package/dist/web/public/confirm.js +70 -0
- package/dist/web/public/index.html +121 -120
- package/dist/web/public/input.js +107 -0
- package/dist/web/public/messages.js +395 -0
- package/dist/web/public/sidebar.js +82 -0
- package/dist/web/public/state.js +72 -0
- package/dist/web/public/style.css +996 -949
- package/dist/web/public/utils.js +37 -0
- package/dist/web/public/websocket.js +267 -0
- package/dist/web/public/ws.js +19 -0
- package/dist/web/session-bridge.d.ts.map +1 -1
- package/dist/web/session-bridge.js +3 -7
- package/dist/web/session-bridge.js.map +1 -1
- package/package.json +55 -54
- package/scripts/copy-native.mjs +24 -0
- package/scripts/copy-web.mjs +15 -0
- package/src/agent/index.ts +25 -25
- package/src/agent/llm.ts +4 -0
- package/src/agent/project.ts +366 -0
- package/src/agent/prompt-builder.ts +23 -13
- package/src/agent/providers/anthropic.ts +179 -172
- package/src/agent/providers/google.ts +210 -211
- package/src/agent/providers/ollama.ts +186 -182
- package/src/agent/providers/openai.ts +73 -5
- package/src/agent/session.ts +275 -153
- package/src/config/index.ts +342 -335
- package/src/tools/__tests__/bash.test.ts +1 -1
- package/src/tools/__tests__/edit.test.ts +981 -385
- package/src/tools/__tests__/grep.test.ts +35 -0
- package/src/tools/bash.ts +97 -11
- package/src/tools/edit.ts +414 -154
- package/src/tools/git.ts +76 -76
- package/src/tools/grep.ts +57 -30
- package/src/tools/read.ts +61 -25
- package/src/tools/registry.ts +231 -265
- package/src/tools/write_plan.ts +21 -5
- package/src/tui/index.ts +786 -785
- package/src/web/index.ts +29 -7
- package/src/web/public/app.js +5 -855
- package/src/web/public/confirm.js +70 -0
- package/src/web/public/index.html +121 -120
- package/src/web/public/input.js +107 -0
- package/src/web/public/messages.js +395 -0
- package/src/web/public/sidebar.js +82 -0
- package/src/web/public/state.js +72 -0
- package/src/web/public/style.css +996 -949
- package/src/web/public/utils.js +37 -0
- package/src/web/public/websocket.js +267 -0
- package/src/web/public/ws.js +19 -0
- package/src/web/session-bridge.ts +193 -194
- package/.kilo/plans/1780064105789-mighty-pixel.md +0 -171
- package/.kilo/plans/1780293725888-quick-wizard.md +0 -62
- package/.lonny/plan-web-cwd-status.md +0 -38
- package/src/tools/exec.ts +0 -348
package/src/tools/exec.ts
DELETED
|
@@ -1,348 +0,0 @@
|
|
|
1
|
-
import * as vm from 'node:vm'
|
|
2
|
-
import { fmtErr } from './errors.js'
|
|
3
|
-
import type { Tool, ToolDefinition, ToolResult } from './types.js'
|
|
4
|
-
|
|
5
|
-
// ── Types ────────────────────────────────────────────────────────────────────
|
|
6
|
-
|
|
7
|
-
interface ExecPragma {
|
|
8
|
-
timeout_ms?: number
|
|
9
|
-
yield_time_ms?: number
|
|
10
|
-
max_output_tokens?: number
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface ExecContext {
|
|
14
|
-
tools: Record<string, (input: unknown) => Promise<string>>
|
|
15
|
-
store: Map<string, unknown>
|
|
16
|
-
output: string[]
|
|
17
|
-
notified: boolean
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const PRAGMA_PREFIX = '// @exec:'
|
|
21
|
-
const DEFAULT_TIMEOUT_MS = 30_000
|
|
22
|
-
|
|
23
|
-
// ── Pragma parsing ──────────────────────────────────────────────────────────
|
|
24
|
-
|
|
25
|
-
function parsePragma(input: string): { code: string; pragma: ExecPragma } {
|
|
26
|
-
const lines = input.split('\n')
|
|
27
|
-
const firstLine = lines[0]?.trim() ?? ''
|
|
28
|
-
const pragma: ExecPragma = {}
|
|
29
|
-
|
|
30
|
-
if (firstLine.startsWith(PRAGMA_PREFIX)) {
|
|
31
|
-
const jsonStr = firstLine.slice(PRAGMA_PREFIX.length).trim()
|
|
32
|
-
if (jsonStr) {
|
|
33
|
-
try {
|
|
34
|
-
const parsed = JSON.parse(jsonStr) as ExecPragma
|
|
35
|
-
// Validate fields
|
|
36
|
-
for (const key of Object.keys(parsed)) {
|
|
37
|
-
if (!['timeout_ms', 'yield_time_ms', 'max_output_tokens'].includes(key)) {
|
|
38
|
-
throw new Error(
|
|
39
|
-
`exec pragma only supports \`timeout_ms\`, \`yield_time_ms\`, and \`max_output_tokens\`; got \`${key}\``,
|
|
40
|
-
)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
if (parsed.timeout_ms !== undefined) {
|
|
44
|
-
if (!Number.isSafeInteger(parsed.timeout_ms) || parsed.timeout_ms < 0) {
|
|
45
|
-
throw new Error('exec pragma field `timeout_ms` must be a non-negative safe integer')
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (parsed.yield_time_ms !== undefined) {
|
|
49
|
-
if (!Number.isSafeInteger(parsed.yield_time_ms) || parsed.yield_time_ms < 0) {
|
|
50
|
-
throw new Error('exec pragma field `yield_time_ms` must be a non-negative safe integer')
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
if (parsed.max_output_tokens !== undefined) {
|
|
54
|
-
if (!Number.isSafeInteger(parsed.max_output_tokens) || parsed.max_output_tokens < 0) {
|
|
55
|
-
throw new Error(
|
|
56
|
-
'exec pragma field `max_output_tokens` must be a non-negative safe integer',
|
|
57
|
-
)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
Object.assign(pragma, parsed)
|
|
61
|
-
} catch (err) {
|
|
62
|
-
throw new Error(`exec pragma parse error: ${fmtErr(err)}`)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return { code: lines.slice(1).join('\n').trim(), pragma }
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return { code: input, pragma }
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// ── TypeScript type rendering ────────────────────────────────────────────────
|
|
72
|
-
|
|
73
|
-
function renderTsType(param: Record<string, unknown>, depth = 0): string {
|
|
74
|
-
const indent = ' '.repeat(depth + 1)
|
|
75
|
-
const closeIndent = ' '.repeat(depth)
|
|
76
|
-
|
|
77
|
-
if (param.type === 'string') return 'string'
|
|
78
|
-
if (param.type === 'number' || param.type === 'integer') return 'number'
|
|
79
|
-
if (param.type === 'boolean') return 'boolean'
|
|
80
|
-
if (param.type === 'array') {
|
|
81
|
-
if (param.items) return `Array<${renderTsType(param.items as Record<string, unknown>, depth)}>`
|
|
82
|
-
return 'unknown[]'
|
|
83
|
-
}
|
|
84
|
-
if (param.type === 'object' || (param.properties as Record<string, unknown> | undefined)) {
|
|
85
|
-
const props = param.properties as Record<string, Record<string, unknown>> | undefined
|
|
86
|
-
const additionalProps = param.additionalProperties
|
|
87
|
-
if (!props && !additionalProps) return 'Record<string, unknown>'
|
|
88
|
-
|
|
89
|
-
const lines: string[] = ['{']
|
|
90
|
-
if (props) {
|
|
91
|
-
for (const [key, value] of Object.entries(props)) {
|
|
92
|
-
const isRequired =
|
|
93
|
-
Array.isArray(param.required) && (param.required as string[]).includes(key)
|
|
94
|
-
const opt = isRequired ? '' : '?'
|
|
95
|
-
const desc = value.description ? ` // ${value.description}` : ''
|
|
96
|
-
const valType = renderTsType(value, depth + 1)
|
|
97
|
-
lines.push(`${indent}${JSON.stringify(key)}${opt}: ${valType};${desc}`)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
if (additionalProps && additionalProps !== false) {
|
|
101
|
-
const valType =
|
|
102
|
-
typeof additionalProps === 'object'
|
|
103
|
-
? renderTsType(additionalProps as Record<string, unknown>, depth + 1)
|
|
104
|
-
: 'unknown'
|
|
105
|
-
lines.push(`${indent}[key: string]: ${valType};`)
|
|
106
|
-
}
|
|
107
|
-
lines.push(`${closeIndent}}`)
|
|
108
|
-
return lines.join('\n')
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return 'unknown'
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function renderToolDeclaration(tool: ToolDefinition): string {
|
|
115
|
-
const params = tool.parameters
|
|
116
|
-
const hasParams = params && Object.keys(params).length > 0
|
|
117
|
-
const paramType = hasParams
|
|
118
|
-
? renderTsType({
|
|
119
|
-
type: 'object',
|
|
120
|
-
properties: params,
|
|
121
|
-
required: Object.entries(params)
|
|
122
|
-
.filter(([_, v]) => v.required)
|
|
123
|
-
.map(([k]) => k),
|
|
124
|
-
} as unknown as Record<string, unknown>)
|
|
125
|
-
: '{}'
|
|
126
|
-
|
|
127
|
-
return `${tool.name}(args: ${paramType}): Promise<string>;`
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// ── Build the exec tool description with TypeScript declarations ────────────
|
|
131
|
-
|
|
132
|
-
function buildExecDescription(toolDefs: ToolDefinition[]): string {
|
|
133
|
-
const toolDeclarations = toolDefs
|
|
134
|
-
.filter(t => t.name !== 'exec')
|
|
135
|
-
.map(t => ` ${renderToolDeclaration(t)}`)
|
|
136
|
-
.join('\n')
|
|
137
|
-
|
|
138
|
-
return `Run JavaScript code to orchestrate/compose tool calls.
|
|
139
|
-
- Evaluates the provided JavaScript code in a fresh V8 sandbox as an async function.
|
|
140
|
-
- All tools are available on the global \`tools\` object, for example \`await tools.read({paths: ["file.ts"]})\`.
|
|
141
|
-
- Tool methods take an object as their input argument and return a string.
|
|
142
|
-
- Runs raw JavaScript — no \`require\`, no file system, no network access, no \`console\` (use \`text()\` instead).
|
|
143
|
-
- Accepts raw JavaScript source text, not JSON, quoted strings, or markdown code fences.
|
|
144
|
-
- You may optionally start the tool input with a first-line pragma like \`// @exec: {"timeout_ms": 30000, "max_output_tokens": 1000}\`.
|
|
145
|
-
- \`timeout_ms\` sets the maximum execution time (default: 30000).
|
|
146
|
-
- \`max_output_tokens\` sets the token budget for results (approximate character limit).
|
|
147
|
-
|
|
148
|
-
Global helpers:
|
|
149
|
-
- \`text(value)\`: Appends a string to the output. Non-string values are stringified.
|
|
150
|
-
- \`exit()\`: Immediately ends the current script successfully.
|
|
151
|
-
- \`store(key, value)\`: Stores a value under a string key for later \`exec\` calls in the same session.
|
|
152
|
-
- \`load(key)\`: Returns the stored value, or \`undefined\` if missing.
|
|
153
|
-
|
|
154
|
-
Available tool declarations:
|
|
155
|
-
\`\`\`ts
|
|
156
|
-
declare const tools: {
|
|
157
|
-
${toolDeclarations}
|
|
158
|
-
};
|
|
159
|
-
\`\`\``
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// ── Exec tool factory ───────────────────────────────────────────────────────
|
|
163
|
-
|
|
164
|
-
export function createExecTool(getTools: () => Tool[]): Tool {
|
|
165
|
-
// Shared store across exec calls in the same session
|
|
166
|
-
const sharedStore = new Map<string, unknown>()
|
|
167
|
-
|
|
168
|
-
return {
|
|
169
|
-
definition: {
|
|
170
|
-
name: 'exec',
|
|
171
|
-
description: 'Run JavaScript code to orchestrate tool calls in a sandboxed V8 isolate.',
|
|
172
|
-
parameters: {
|
|
173
|
-
code: {
|
|
174
|
-
type: 'string',
|
|
175
|
-
description:
|
|
176
|
-
'JavaScript source code to execute. Optionally starts with // @exec: {"timeout_ms": 30000} pragma.',
|
|
177
|
-
required: true,
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
async execute(input: Record<string, unknown>): Promise<ToolResult> {
|
|
182
|
-
const rawCode = input.code as string
|
|
183
|
-
if (!rawCode || typeof rawCode !== 'string') {
|
|
184
|
-
return {
|
|
185
|
-
success: false,
|
|
186
|
-
output: '',
|
|
187
|
-
error: 'exec expects a `code` string parameter with JavaScript source text.',
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Parse pragma
|
|
192
|
-
let code: string
|
|
193
|
-
let pragma: ExecPragma
|
|
194
|
-
try {
|
|
195
|
-
const parsed = parsePragma(rawCode)
|
|
196
|
-
code = parsed.code
|
|
197
|
-
pragma = parsed.pragma
|
|
198
|
-
} catch (err) {
|
|
199
|
-
return { success: false, output: '', error: fmtErr(err) }
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (!code.trim()) {
|
|
203
|
-
return {
|
|
204
|
-
success: false,
|
|
205
|
-
output: '',
|
|
206
|
-
error: 'exec expects non-empty JavaScript source text.',
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Build context
|
|
211
|
-
const ctx: ExecContext = {
|
|
212
|
-
tools: {},
|
|
213
|
-
store: sharedStore,
|
|
214
|
-
output: [],
|
|
215
|
-
notified: false,
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Wrap each registered tool as an async function available in the sandbox
|
|
219
|
-
const allTools = getTools()
|
|
220
|
-
for (const tool of allTools) {
|
|
221
|
-
if (tool.definition.name === 'exec') continue // don't expose exec itself
|
|
222
|
-
ctx.tools[tool.definition.name] = async (toolInput: unknown): Promise<string> => {
|
|
223
|
-
const result = await tool.execute((toolInput ?? {}) as Record<string, unknown>)
|
|
224
|
-
if (!result.success) {
|
|
225
|
-
throw new Error(`Tool "${tool.definition.name}" failed: ${result.error}`)
|
|
226
|
-
}
|
|
227
|
-
return result.output
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Wrap the code in an async function that receives the context
|
|
232
|
-
const wrappedCode = `
|
|
233
|
-
(async () => {
|
|
234
|
-
const tools = context.tools;
|
|
235
|
-
const store = context.store;
|
|
236
|
-
const output = context.output;
|
|
237
|
-
|
|
238
|
-
function text(value) {
|
|
239
|
-
if (value === null || value === undefined) output.push(String(value));
|
|
240
|
-
else if (typeof value === 'object') output.push(JSON.stringify(value));
|
|
241
|
-
else output.push(String(value));
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
function exit() {
|
|
245
|
-
context.done = true;
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function store(key, value) {
|
|
250
|
-
context.store.set(key, value);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function load(key) {
|
|
254
|
-
return context.store.get(key);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
${code}
|
|
258
|
-
})()
|
|
259
|
-
`
|
|
260
|
-
|
|
261
|
-
// Create sandbox context
|
|
262
|
-
const sandbox = {
|
|
263
|
-
context: ctx,
|
|
264
|
-
setTimeout: setTimeout.bind(globalThis),
|
|
265
|
-
clearTimeout: clearTimeout.bind(globalThis),
|
|
266
|
-
console: {
|
|
267
|
-
log: (...args: unknown[]) => ctx.output.push(args.map(a => String(a)).join(' ')),
|
|
268
|
-
error: (...args: unknown[]) =>
|
|
269
|
-
ctx.output.push(`ERROR: ${args.map(a => String(a)).join(' ')}`),
|
|
270
|
-
warn: (...args: unknown[]) =>
|
|
271
|
-
ctx.output.push(`WARN: ${args.map(a => String(a)).join(' ')}`),
|
|
272
|
-
info: (...args: unknown[]) => ctx.output.push(args.map(a => String(a)).join(' ')),
|
|
273
|
-
},
|
|
274
|
-
// Safe globals
|
|
275
|
-
Array,
|
|
276
|
-
Object,
|
|
277
|
-
String,
|
|
278
|
-
Number,
|
|
279
|
-
Boolean,
|
|
280
|
-
Date,
|
|
281
|
-
Math,
|
|
282
|
-
JSON,
|
|
283
|
-
RegExp,
|
|
284
|
-
Map,
|
|
285
|
-
Set,
|
|
286
|
-
Promise,
|
|
287
|
-
Error,
|
|
288
|
-
TypeError,
|
|
289
|
-
RangeError,
|
|
290
|
-
SyntaxError,
|
|
291
|
-
ReferenceError,
|
|
292
|
-
parseInt,
|
|
293
|
-
parseFloat,
|
|
294
|
-
isNaN,
|
|
295
|
-
isFinite,
|
|
296
|
-
encodeURI,
|
|
297
|
-
decodeURI,
|
|
298
|
-
encodeURIComponent,
|
|
299
|
-
decodeURIComponent,
|
|
300
|
-
// TextEncoder/Decoder for buffer handling
|
|
301
|
-
TextEncoder,
|
|
302
|
-
TextDecoder,
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
const timeout = pragma.timeout_ms ?? DEFAULT_TIMEOUT_MS
|
|
306
|
-
const maxOutputTokens = pragma.max_output_tokens ?? 10_000
|
|
307
|
-
const maxChars = maxOutputTokens * 4 // rough estimate
|
|
308
|
-
|
|
309
|
-
try {
|
|
310
|
-
const script = new vm.Script(wrappedCode, {
|
|
311
|
-
filename: 'exec-sandbox.js',
|
|
312
|
-
})
|
|
313
|
-
|
|
314
|
-
const vmContext = vm.createContext(sandbox)
|
|
315
|
-
await script.runInContext(vmContext, {
|
|
316
|
-
timeout: timeout,
|
|
317
|
-
breakOnSigint: true,
|
|
318
|
-
})
|
|
319
|
-
|
|
320
|
-
let output = ctx.output.join('')
|
|
321
|
-
if (output.length > maxChars) {
|
|
322
|
-
output = `${output.slice(0, maxChars)}\n\n... (output truncated)`
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
return { success: true, output: output || '(exec completed with no output)' }
|
|
326
|
-
} catch (err) {
|
|
327
|
-
const msg = fmtErr(err)
|
|
328
|
-
if (msg.includes('timed out') || msg.includes('timeout')) {
|
|
329
|
-
return {
|
|
330
|
-
success: false,
|
|
331
|
-
output: ctx.output.join(''),
|
|
332
|
-
error: `exec timed out after ${timeout}ms`,
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
return {
|
|
336
|
-
success: false,
|
|
337
|
-
output: ctx.output.join(''),
|
|
338
|
-
error: `exec error: ${msg}`,
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
},
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/** Rebuild the exec tool definition (called when tools change) */
|
|
346
|
-
export function updateExecToolDefinition(execTool: Tool, toolDefs: ToolDefinition[]): void {
|
|
347
|
-
execTool.definition.description = buildExecDescription(toolDefs)
|
|
348
|
-
}
|