@mindstudio-ai/remy 0.1.35 → 0.1.36
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/headless.js +436 -209
- package/dist/index.js +450 -215
- package/dist/prompt/compiled/media-cdn.md +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2059,7 +2059,7 @@ var init_screenshot = __esm({
|
|
|
2059
2059
|
init_sidecar();
|
|
2060
2060
|
init_runCli();
|
|
2061
2061
|
init_logger();
|
|
2062
|
-
SCREENSHOT_ANALYSIS_PROMPT = "Describe everything visible on screen from top to bottom \u2014 every element, its position, its size relative to the viewport, its colors, its content. Be thorough and spatial. After the inventory, note anything that looks visually broken (overlapping elements, clipped text, misaligned components).";
|
|
2062
|
+
SCREENSHOT_ANALYSIS_PROMPT = "Describe everything visible on screen from top to bottom \u2014 every element, its position, its size relative to the viewport, its colors, its content. Be comprehensive, thorough, and spatial. After the inventory, note anything that looks visually broken (overlapping elements, clipped text, misaligned components). Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.";
|
|
2063
2063
|
}
|
|
2064
2064
|
});
|
|
2065
2065
|
|
|
@@ -2097,6 +2097,91 @@ var init_screenshot2 = __esm({
|
|
|
2097
2097
|
}
|
|
2098
2098
|
});
|
|
2099
2099
|
|
|
2100
|
+
// src/statusWatcher.ts
|
|
2101
|
+
function startStatusWatcher(config) {
|
|
2102
|
+
const { apiConfig, getContext, onStatus, interval = 3e3, signal } = config;
|
|
2103
|
+
let lastLabel = "";
|
|
2104
|
+
let inflight = false;
|
|
2105
|
+
let stopped = false;
|
|
2106
|
+
const url = `${apiConfig.baseUrl}/_internal/v2/agent/remy/generate-status`;
|
|
2107
|
+
async function tick() {
|
|
2108
|
+
if (stopped || signal?.aborted || inflight) {
|
|
2109
|
+
return;
|
|
2110
|
+
}
|
|
2111
|
+
inflight = true;
|
|
2112
|
+
try {
|
|
2113
|
+
const ctx = getContext();
|
|
2114
|
+
if (!ctx.assistantText && !ctx.lastToolName) {
|
|
2115
|
+
log.debug("Status watcher: no context, skipping");
|
|
2116
|
+
return;
|
|
2117
|
+
}
|
|
2118
|
+
log.debug("Status watcher: requesting label", {
|
|
2119
|
+
textLength: ctx.assistantText.length,
|
|
2120
|
+
lastToolName: ctx.lastToolName
|
|
2121
|
+
});
|
|
2122
|
+
const res = await fetch(url, {
|
|
2123
|
+
method: "POST",
|
|
2124
|
+
headers: {
|
|
2125
|
+
"Content-Type": "application/json",
|
|
2126
|
+
Authorization: `Bearer ${apiConfig.apiKey}`
|
|
2127
|
+
},
|
|
2128
|
+
body: JSON.stringify({
|
|
2129
|
+
assistantText: ctx.assistantText.slice(-500),
|
|
2130
|
+
lastToolName: ctx.lastToolName,
|
|
2131
|
+
lastToolResult: ctx.lastToolResult?.slice(-200),
|
|
2132
|
+
onboardingState: ctx.onboardingState,
|
|
2133
|
+
userMessage: ctx.userMessage?.slice(-200)
|
|
2134
|
+
}),
|
|
2135
|
+
signal
|
|
2136
|
+
});
|
|
2137
|
+
if (!res.ok) {
|
|
2138
|
+
log.debug("Status watcher: endpoint returned non-ok", {
|
|
2139
|
+
status: res.status
|
|
2140
|
+
});
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
2143
|
+
const data = await res.json();
|
|
2144
|
+
if (!data.label) {
|
|
2145
|
+
log.debug("Status watcher: no label in response");
|
|
2146
|
+
return;
|
|
2147
|
+
}
|
|
2148
|
+
if (data.label === lastLabel) {
|
|
2149
|
+
log.debug("Status watcher: duplicate label, skipping", {
|
|
2150
|
+
label: data.label
|
|
2151
|
+
});
|
|
2152
|
+
return;
|
|
2153
|
+
}
|
|
2154
|
+
lastLabel = data.label;
|
|
2155
|
+
if (stopped) {
|
|
2156
|
+
return;
|
|
2157
|
+
}
|
|
2158
|
+
log.debug("Status watcher: emitting", { label: data.label });
|
|
2159
|
+
onStatus(data.label);
|
|
2160
|
+
} catch (err) {
|
|
2161
|
+
log.debug("Status watcher: error", { error: err?.message ?? "unknown" });
|
|
2162
|
+
} finally {
|
|
2163
|
+
inflight = false;
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
const timer = setInterval(tick, interval);
|
|
2167
|
+
tick().catch(() => {
|
|
2168
|
+
});
|
|
2169
|
+
log.debug("Status watcher started", { interval });
|
|
2170
|
+
return {
|
|
2171
|
+
stop() {
|
|
2172
|
+
stopped = true;
|
|
2173
|
+
clearInterval(timer);
|
|
2174
|
+
log.debug("Status watcher stopped");
|
|
2175
|
+
}
|
|
2176
|
+
};
|
|
2177
|
+
}
|
|
2178
|
+
var init_statusWatcher = __esm({
|
|
2179
|
+
"src/statusWatcher.ts"() {
|
|
2180
|
+
"use strict";
|
|
2181
|
+
init_logger();
|
|
2182
|
+
}
|
|
2183
|
+
});
|
|
2184
|
+
|
|
2100
2185
|
// src/subagents/common/cleanMessages.ts
|
|
2101
2186
|
function cleanMessagesForApi(messages) {
|
|
2102
2187
|
return messages.map((msg) => {
|
|
@@ -2145,19 +2230,47 @@ async function runSubAgent(config) {
|
|
|
2145
2230
|
signal,
|
|
2146
2231
|
parentToolId,
|
|
2147
2232
|
onEvent,
|
|
2148
|
-
resolveExternalTool
|
|
2233
|
+
resolveExternalTool,
|
|
2234
|
+
toolRegistry
|
|
2149
2235
|
} = config;
|
|
2150
2236
|
const emit2 = (e) => {
|
|
2151
2237
|
onEvent({ ...e, parentToolId });
|
|
2152
2238
|
};
|
|
2153
2239
|
const messages = [{ role: "user", content: task }];
|
|
2240
|
+
function getPartialText(blocks) {
|
|
2241
|
+
return blocks.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
2242
|
+
}
|
|
2243
|
+
function abortResult(blocks) {
|
|
2244
|
+
if (signal?.reason === "graceful") {
|
|
2245
|
+
const partial = getPartialText(blocks);
|
|
2246
|
+
return {
|
|
2247
|
+
text: partial ? `[INTERRUPTED]
|
|
2248
|
+
|
|
2249
|
+
${partial}` : "[INTERRUPTED] Sub-agent was interrupted before producing output.",
|
|
2250
|
+
messages
|
|
2251
|
+
};
|
|
2252
|
+
}
|
|
2253
|
+
return { text: "Error: cancelled", messages };
|
|
2254
|
+
}
|
|
2255
|
+
let lastToolResult = "";
|
|
2154
2256
|
while (true) {
|
|
2155
2257
|
if (signal?.aborted) {
|
|
2156
|
-
return
|
|
2258
|
+
return abortResult([]);
|
|
2157
2259
|
}
|
|
2158
2260
|
const contentBlocks = [];
|
|
2159
2261
|
let thinkingStartedAt = 0;
|
|
2160
2262
|
let stopReason = "end_turn";
|
|
2263
|
+
let currentToolNames = "";
|
|
2264
|
+
const statusWatcher = startStatusWatcher({
|
|
2265
|
+
apiConfig,
|
|
2266
|
+
getContext: () => ({
|
|
2267
|
+
assistantText: getPartialText(contentBlocks),
|
|
2268
|
+
lastToolName: currentToolNames || void 0,
|
|
2269
|
+
lastToolResult: lastToolResult || void 0
|
|
2270
|
+
}),
|
|
2271
|
+
onStatus: (label) => emit2({ type: "status", message: label }),
|
|
2272
|
+
signal
|
|
2273
|
+
});
|
|
2161
2274
|
const fullSystem = `${system}
|
|
2162
2275
|
|
|
2163
2276
|
Current date/time: ${(/* @__PURE__ */ new Date()).toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC")}`;
|
|
@@ -2233,7 +2346,8 @@ Current date/time: ${(/* @__PURE__ */ new Date()).toISOString().replace("T", " "
|
|
|
2233
2346
|
}
|
|
2234
2347
|
}
|
|
2235
2348
|
if (signal?.aborted) {
|
|
2236
|
-
|
|
2349
|
+
statusWatcher.stop();
|
|
2350
|
+
return abortResult(contentBlocks);
|
|
2237
2351
|
}
|
|
2238
2352
|
messages.push({
|
|
2239
2353
|
role: "assistant",
|
|
@@ -2243,6 +2357,7 @@ Current date/time: ${(/* @__PURE__ */ new Date()).toISOString().replace("T", " "
|
|
|
2243
2357
|
(b) => b.type === "tool"
|
|
2244
2358
|
);
|
|
2245
2359
|
if (stopReason !== "tool_use" || toolCalls.length === 0) {
|
|
2360
|
+
statusWatcher.stop();
|
|
2246
2361
|
const text = contentBlocks.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
2247
2362
|
return { text, messages };
|
|
2248
2363
|
}
|
|
@@ -2251,46 +2366,82 @@ Current date/time: ${(/* @__PURE__ */ new Date()).toISOString().replace("T", " "
|
|
|
2251
2366
|
count: toolCalls.length,
|
|
2252
2367
|
tools: toolCalls.map((tc) => tc.name)
|
|
2253
2368
|
});
|
|
2369
|
+
currentToolNames = toolCalls.map((tc) => tc.name).join(", ");
|
|
2254
2370
|
const results = await Promise.all(
|
|
2255
2371
|
toolCalls.map(async (tc) => {
|
|
2256
2372
|
if (signal?.aborted) {
|
|
2257
2373
|
return { id: tc.id, result: "Error: cancelled", isError: true };
|
|
2258
2374
|
}
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2375
|
+
let settle;
|
|
2376
|
+
const resultPromise = new Promise((res) => {
|
|
2377
|
+
settle = (result, isError) => res({ id: tc.id, result, isError });
|
|
2378
|
+
});
|
|
2379
|
+
let toolAbort = new AbortController();
|
|
2380
|
+
const cascadeAbort = () => toolAbort.abort();
|
|
2381
|
+
signal?.addEventListener("abort", cascadeAbort, { once: true });
|
|
2382
|
+
let settled = false;
|
|
2383
|
+
const safeSettle = (result, isError) => {
|
|
2384
|
+
if (settled) {
|
|
2385
|
+
return;
|
|
2386
|
+
}
|
|
2387
|
+
settled = true;
|
|
2388
|
+
signal?.removeEventListener("abort", cascadeAbort);
|
|
2389
|
+
settle(result, isError);
|
|
2390
|
+
};
|
|
2391
|
+
const run = async (input) => {
|
|
2392
|
+
try {
|
|
2393
|
+
let result;
|
|
2394
|
+
if (externalTools.has(tc.name) && resolveExternalTool) {
|
|
2395
|
+
result = await resolveExternalTool(tc.id, tc.name, input);
|
|
2396
|
+
} else {
|
|
2397
|
+
const onLog = (line) => emit2({
|
|
2398
|
+
type: "tool_input_delta",
|
|
2399
|
+
id: tc.id,
|
|
2400
|
+
name: tc.name,
|
|
2401
|
+
result: line
|
|
2402
|
+
});
|
|
2403
|
+
result = await executeTool2(tc.name, input, tc.id, onLog);
|
|
2404
|
+
}
|
|
2405
|
+
safeSettle(result, result.startsWith("Error"));
|
|
2406
|
+
} catch (err) {
|
|
2407
|
+
safeSettle(`Error: ${err.message}`, true);
|
|
2408
|
+
}
|
|
2409
|
+
};
|
|
2410
|
+
const entry = {
|
|
2411
|
+
id: tc.id,
|
|
2412
|
+
name: tc.name,
|
|
2413
|
+
input: tc.input,
|
|
2414
|
+
parentToolId,
|
|
2415
|
+
abortController: toolAbort,
|
|
2416
|
+
startedAt: Date.now(),
|
|
2417
|
+
settle: safeSettle,
|
|
2418
|
+
rerun: (newInput) => {
|
|
2419
|
+
settled = false;
|
|
2420
|
+
toolAbort = new AbortController();
|
|
2421
|
+
signal?.addEventListener("abort", () => toolAbort.abort(), {
|
|
2422
|
+
once: true
|
|
2269
2423
|
});
|
|
2270
|
-
|
|
2424
|
+
entry.abortController = toolAbort;
|
|
2425
|
+
entry.input = newInput;
|
|
2426
|
+
run(newInput);
|
|
2271
2427
|
}
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
id: tc.id,
|
|
2286
|
-
name: tc.name,
|
|
2287
|
-
result: errorMsg,
|
|
2288
|
-
isError: true
|
|
2289
|
-
});
|
|
2290
|
-
return { id: tc.id, result: errorMsg, isError: true };
|
|
2291
|
-
}
|
|
2428
|
+
};
|
|
2429
|
+
toolRegistry?.register(entry);
|
|
2430
|
+
run(tc.input);
|
|
2431
|
+
const r = await resultPromise;
|
|
2432
|
+
toolRegistry?.unregister(tc.id);
|
|
2433
|
+
emit2({
|
|
2434
|
+
type: "tool_done",
|
|
2435
|
+
id: tc.id,
|
|
2436
|
+
name: tc.name,
|
|
2437
|
+
result: r.result,
|
|
2438
|
+
isError: r.isError
|
|
2439
|
+
});
|
|
2440
|
+
return r;
|
|
2292
2441
|
})
|
|
2293
2442
|
);
|
|
2443
|
+
statusWatcher.stop();
|
|
2444
|
+
lastToolResult = results.at(-1)?.result ?? "";
|
|
2294
2445
|
for (const r of results) {
|
|
2295
2446
|
const block = contentBlocks.find(
|
|
2296
2447
|
(b) => b.type === "tool" && b.id === r.id
|
|
@@ -2298,6 +2449,7 @@ Current date/time: ${(/* @__PURE__ */ new Date()).toISOString().replace("T", " "
|
|
|
2298
2449
|
if (block?.type === "tool") {
|
|
2299
2450
|
block.result = r.result;
|
|
2300
2451
|
block.isError = r.isError;
|
|
2452
|
+
block.completedAt = Date.now();
|
|
2301
2453
|
}
|
|
2302
2454
|
messages.push({
|
|
2303
2455
|
role: "user",
|
|
@@ -2313,6 +2465,7 @@ var init_runner = __esm({
|
|
|
2313
2465
|
"use strict";
|
|
2314
2466
|
init_api();
|
|
2315
2467
|
init_logger();
|
|
2468
|
+
init_statusWatcher();
|
|
2316
2469
|
init_cleanMessages();
|
|
2317
2470
|
}
|
|
2318
2471
|
});
|
|
@@ -2604,7 +2757,8 @@ var init_browserAutomation = __esm({
|
|
|
2604
2757
|
}
|
|
2605
2758
|
}
|
|
2606
2759
|
return result2;
|
|
2607
|
-
}
|
|
2760
|
+
},
|
|
2761
|
+
toolRegistry: context.toolRegistry
|
|
2608
2762
|
});
|
|
2609
2763
|
context.subAgentMessages?.set(context.toolCallId, result.messages);
|
|
2610
2764
|
return result.text;
|
|
@@ -2738,7 +2892,7 @@ Brief description of the types used on the page. If you can identify the actual
|
|
|
2738
2892
|
## Techniques
|
|
2739
2893
|
Identify the specific design moves that make this page interesting and unique, described in terms of how a designer with a technical background would write them down as notes in their notebook for inspiration. Focus only on the non-obvious, hard-to-think-of techniques \u2014 the things that make this page gallery-worthy. Skip basics like "high contrast CTA" or "generous whitespace" that any competent designer already knows.
|
|
2740
2894
|
|
|
2741
|
-
Respond only with
|
|
2895
|
+
Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.
|
|
2742
2896
|
`;
|
|
2743
2897
|
definition3 = {
|
|
2744
2898
|
name: "analyzeDesign",
|
|
@@ -2781,7 +2935,7 @@ var init_analyzeImage = __esm({
|
|
|
2781
2935
|
"src/subagents/designExpert/tools/analyzeImage.ts"() {
|
|
2782
2936
|
"use strict";
|
|
2783
2937
|
init_runCli();
|
|
2784
|
-
DEFAULT_PROMPT = "Describe everything visible in this image \u2014 every element, its position, its size relative to the frame, its colors, its content. Be thorough and spatial. After the inventory, note anything that looks visually broken (overlapping elements, clipped text, misaligned components).";
|
|
2938
|
+
DEFAULT_PROMPT = "Describe everything visible in this image \u2014 every element, its position, its size relative to the frame, its colors, its content. Be comprhensive, thorough and spatial. After the inventory, note anything that looks visually broken (overlapping elements, clipped text, misaligned components). Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.";
|
|
2785
2939
|
definition4 = {
|
|
2786
2940
|
name: "analyzeImage",
|
|
2787
2941
|
description: "Analyze an image by URL. Returns a detailed description of everything visible. Provide a custom prompt to ask a specific question instead of the default full description.",
|
|
@@ -2880,7 +3034,7 @@ async function seedreamGenerate(opts) {
|
|
|
2880
3034
|
);
|
|
2881
3035
|
try {
|
|
2882
3036
|
const parsed = JSON.parse(batchResult);
|
|
2883
|
-
imageUrls = parsed.
|
|
3037
|
+
imageUrls = parsed.map(
|
|
2884
3038
|
(r) => r.output?.imageUrl ?? `Error: ${r.error}`
|
|
2885
3039
|
);
|
|
2886
3040
|
} catch {
|
|
@@ -2920,7 +3074,7 @@ var init_seedream = __esm({
|
|
|
2920
3074
|
"src/subagents/designExpert/tools/_seedream.ts"() {
|
|
2921
3075
|
"use strict";
|
|
2922
3076
|
init_runCli();
|
|
2923
|
-
ANALYZE_PROMPT = "You are reviewing this image for a visual designer sourcing assets for a project. Describe: what the image depicts, the mood and color palette, how the lighting and composition work, whether there are any issues (unwanted text, artifacts, distortions), and how it could be used in a layout (hero background, feature section, card texture, etc). Be concise and practical.";
|
|
3077
|
+
ANALYZE_PROMPT = "You are reviewing this image for a visual designer sourcing assets for a project. Describe: what the image depicts, the mood and color palette, how the lighting and composition work, whether there are any issues (unwanted text, artifacts, distortions), and how it could be used in a layout (hero background, feature section, card texture, etc). Be concise and practical. Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.";
|
|
2924
3078
|
}
|
|
2925
3079
|
});
|
|
2926
3080
|
|
|
@@ -3345,7 +3499,8 @@ Visual design expert. Describe the situation and what you need \u2014 the agent
|
|
|
3345
3499
|
signal: context.signal,
|
|
3346
3500
|
parentToolId: context.toolCallId,
|
|
3347
3501
|
onEvent: context.onEvent,
|
|
3348
|
-
resolveExternalTool: context.resolveExternalTool
|
|
3502
|
+
resolveExternalTool: context.resolveExternalTool,
|
|
3503
|
+
toolRegistry: context.toolRegistry
|
|
3349
3504
|
});
|
|
3350
3505
|
context.subAgentMessages?.set(context.toolCallId, result.messages);
|
|
3351
3506
|
return result.text;
|
|
@@ -3660,7 +3815,8 @@ var init_productVision = __esm({
|
|
|
3660
3815
|
signal: context.signal,
|
|
3661
3816
|
parentToolId: context.toolCallId,
|
|
3662
3817
|
onEvent: context.onEvent,
|
|
3663
|
-
resolveExternalTool: context.resolveExternalTool
|
|
3818
|
+
resolveExternalTool: context.resolveExternalTool,
|
|
3819
|
+
toolRegistry: context.toolRegistry
|
|
3664
3820
|
});
|
|
3665
3821
|
context.subAgentMessages?.set(context.toolCallId, result.messages);
|
|
3666
3822
|
return result.text;
|
|
@@ -3814,7 +3970,8 @@ var init_codeSanityCheck = __esm({
|
|
|
3814
3970
|
signal: context.signal,
|
|
3815
3971
|
parentToolId: context.toolCallId,
|
|
3816
3972
|
onEvent: context.onEvent,
|
|
3817
|
-
resolveExternalTool: context.resolveExternalTool
|
|
3973
|
+
resolveExternalTool: context.resolveExternalTool,
|
|
3974
|
+
toolRegistry: context.toolRegistry
|
|
3818
3975
|
});
|
|
3819
3976
|
context.subAgentMessages?.set(context.toolCallId, result.messages);
|
|
3820
3977
|
return result.text;
|
|
@@ -4186,91 +4343,6 @@ var init_parsePartialJson = __esm({
|
|
|
4186
4343
|
}
|
|
4187
4344
|
});
|
|
4188
4345
|
|
|
4189
|
-
// src/statusWatcher.ts
|
|
4190
|
-
function startStatusWatcher(config) {
|
|
4191
|
-
const { apiConfig, getContext, onStatus, interval = 3e3, signal } = config;
|
|
4192
|
-
let lastLabel = "";
|
|
4193
|
-
let inflight = false;
|
|
4194
|
-
let stopped = false;
|
|
4195
|
-
const url = `${apiConfig.baseUrl}/_internal/v2/agent/remy/generate-status`;
|
|
4196
|
-
async function tick() {
|
|
4197
|
-
if (stopped || signal?.aborted || inflight) {
|
|
4198
|
-
return;
|
|
4199
|
-
}
|
|
4200
|
-
inflight = true;
|
|
4201
|
-
try {
|
|
4202
|
-
const ctx = getContext();
|
|
4203
|
-
if (!ctx.assistantText && !ctx.lastToolName) {
|
|
4204
|
-
log.debug("Status watcher: no context, skipping");
|
|
4205
|
-
return;
|
|
4206
|
-
}
|
|
4207
|
-
log.debug("Status watcher: requesting label", {
|
|
4208
|
-
textLength: ctx.assistantText.length,
|
|
4209
|
-
lastToolName: ctx.lastToolName
|
|
4210
|
-
});
|
|
4211
|
-
const res = await fetch(url, {
|
|
4212
|
-
method: "POST",
|
|
4213
|
-
headers: {
|
|
4214
|
-
"Content-Type": "application/json",
|
|
4215
|
-
Authorization: `Bearer ${apiConfig.apiKey}`
|
|
4216
|
-
},
|
|
4217
|
-
body: JSON.stringify({
|
|
4218
|
-
assistantText: ctx.assistantText.slice(-500),
|
|
4219
|
-
lastToolName: ctx.lastToolName,
|
|
4220
|
-
lastToolResult: ctx.lastToolResult?.slice(-200),
|
|
4221
|
-
onboardingState: ctx.onboardingState,
|
|
4222
|
-
userMessage: ctx.userMessage?.slice(-200)
|
|
4223
|
-
}),
|
|
4224
|
-
signal
|
|
4225
|
-
});
|
|
4226
|
-
if (!res.ok) {
|
|
4227
|
-
log.debug("Status watcher: endpoint returned non-ok", {
|
|
4228
|
-
status: res.status
|
|
4229
|
-
});
|
|
4230
|
-
return;
|
|
4231
|
-
}
|
|
4232
|
-
const data = await res.json();
|
|
4233
|
-
if (!data.label) {
|
|
4234
|
-
log.debug("Status watcher: no label in response");
|
|
4235
|
-
return;
|
|
4236
|
-
}
|
|
4237
|
-
if (data.label === lastLabel) {
|
|
4238
|
-
log.debug("Status watcher: duplicate label, skipping", {
|
|
4239
|
-
label: data.label
|
|
4240
|
-
});
|
|
4241
|
-
return;
|
|
4242
|
-
}
|
|
4243
|
-
lastLabel = data.label;
|
|
4244
|
-
if (stopped) {
|
|
4245
|
-
return;
|
|
4246
|
-
}
|
|
4247
|
-
log.debug("Status watcher: emitting", { label: data.label });
|
|
4248
|
-
onStatus(data.label);
|
|
4249
|
-
} catch (err) {
|
|
4250
|
-
log.debug("Status watcher: error", { error: err?.message ?? "unknown" });
|
|
4251
|
-
} finally {
|
|
4252
|
-
inflight = false;
|
|
4253
|
-
}
|
|
4254
|
-
}
|
|
4255
|
-
const timer = setInterval(tick, interval);
|
|
4256
|
-
tick().catch(() => {
|
|
4257
|
-
});
|
|
4258
|
-
log.debug("Status watcher started", { interval });
|
|
4259
|
-
return {
|
|
4260
|
-
stop() {
|
|
4261
|
-
stopped = true;
|
|
4262
|
-
clearInterval(timer);
|
|
4263
|
-
log.debug("Status watcher stopped");
|
|
4264
|
-
}
|
|
4265
|
-
};
|
|
4266
|
-
}
|
|
4267
|
-
var init_statusWatcher = __esm({
|
|
4268
|
-
"src/statusWatcher.ts"() {
|
|
4269
|
-
"use strict";
|
|
4270
|
-
init_logger();
|
|
4271
|
-
}
|
|
4272
|
-
});
|
|
4273
|
-
|
|
4274
4346
|
// src/errors.ts
|
|
4275
4347
|
function friendlyError(raw) {
|
|
4276
4348
|
for (const [pattern, message] of patterns) {
|
|
@@ -4327,7 +4399,8 @@ async function runTurn(params) {
|
|
|
4327
4399
|
signal,
|
|
4328
4400
|
onEvent,
|
|
4329
4401
|
resolveExternalTool,
|
|
4330
|
-
hidden
|
|
4402
|
+
hidden,
|
|
4403
|
+
toolRegistry
|
|
4331
4404
|
} = params;
|
|
4332
4405
|
const tools2 = getToolDefinitions(onboardingState);
|
|
4333
4406
|
log.info("Turn started", {
|
|
@@ -4380,6 +4453,20 @@ async function runTurn(params) {
|
|
|
4380
4453
|
let thinkingStartedAt = 0;
|
|
4381
4454
|
const toolInputAccumulators = /* @__PURE__ */ new Map();
|
|
4382
4455
|
let stopReason = "end_turn";
|
|
4456
|
+
let subAgentText = "";
|
|
4457
|
+
let currentToolNames = "";
|
|
4458
|
+
const statusWatcher = startStatusWatcher({
|
|
4459
|
+
apiConfig,
|
|
4460
|
+
getContext: () => ({
|
|
4461
|
+
assistantText: subAgentText || getTextContent(contentBlocks).slice(-500),
|
|
4462
|
+
lastToolName: currentToolNames || getToolCalls(contentBlocks).filter((tc) => !STATUS_EXCLUDED_TOOLS.has(tc.name)).at(-1)?.name || lastCompletedTools || void 0,
|
|
4463
|
+
lastToolResult: lastCompletedResult || void 0,
|
|
4464
|
+
onboardingState,
|
|
4465
|
+
userMessage
|
|
4466
|
+
}),
|
|
4467
|
+
onStatus: (label) => onEvent({ type: "status", message: label }),
|
|
4468
|
+
signal
|
|
4469
|
+
});
|
|
4383
4470
|
async function handlePartialInput(acc, id, name, partial) {
|
|
4384
4471
|
const tool = getToolByName(name);
|
|
4385
4472
|
if (!tool?.streaming) {
|
|
@@ -4443,18 +4530,6 @@ async function runTurn(params) {
|
|
|
4443
4530
|
onEvent({ type: "tool_input_delta", id, name, result: content });
|
|
4444
4531
|
}
|
|
4445
4532
|
}
|
|
4446
|
-
const statusWatcher = startStatusWatcher({
|
|
4447
|
-
apiConfig,
|
|
4448
|
-
getContext: () => ({
|
|
4449
|
-
assistantText: getTextContent(contentBlocks).slice(-500),
|
|
4450
|
-
lastToolName: getToolCalls(contentBlocks).filter((tc) => !STATUS_EXCLUDED_TOOLS.has(tc.name)).at(-1)?.name || lastCompletedTools || void 0,
|
|
4451
|
-
lastToolResult: lastCompletedResult || void 0,
|
|
4452
|
-
onboardingState,
|
|
4453
|
-
userMessage
|
|
4454
|
-
}),
|
|
4455
|
-
onStatus: (label) => onEvent({ type: "status", message: label }),
|
|
4456
|
-
signal
|
|
4457
|
-
});
|
|
4458
4533
|
try {
|
|
4459
4534
|
for await (const event of streamChatWithRetry(
|
|
4460
4535
|
{
|
|
@@ -4575,10 +4650,9 @@ async function runTurn(params) {
|
|
|
4575
4650
|
} else {
|
|
4576
4651
|
throw err;
|
|
4577
4652
|
}
|
|
4578
|
-
} finally {
|
|
4579
|
-
statusWatcher.stop();
|
|
4580
4653
|
}
|
|
4581
4654
|
if (signal?.aborted) {
|
|
4655
|
+
statusWatcher.stop();
|
|
4582
4656
|
if (contentBlocks.length > 0) {
|
|
4583
4657
|
contentBlocks.push({
|
|
4584
4658
|
type: "text",
|
|
@@ -4600,6 +4674,7 @@ async function runTurn(params) {
|
|
|
4600
4674
|
});
|
|
4601
4675
|
const toolCalls = getToolCalls(contentBlocks);
|
|
4602
4676
|
if (stopReason !== "tool_use" || toolCalls.length === 0) {
|
|
4677
|
+
statusWatcher.stop();
|
|
4603
4678
|
saveSession(state);
|
|
4604
4679
|
onEvent({ type: "turn_done" });
|
|
4605
4680
|
return;
|
|
@@ -4608,8 +4683,7 @@ async function runTurn(params) {
|
|
|
4608
4683
|
count: toolCalls.length,
|
|
4609
4684
|
tools: toolCalls.map((tc) => tc.name)
|
|
4610
4685
|
});
|
|
4611
|
-
|
|
4612
|
-
const origOnEvent = onEvent;
|
|
4686
|
+
currentToolNames = toolCalls.filter((tc) => !STATUS_EXCLUDED_TOOLS.has(tc.name)).map((tc) => tc.name).join(", ");
|
|
4613
4687
|
const wrappedOnEvent = (e) => {
|
|
4614
4688
|
if ("parentToolId" in e && e.parentToolId) {
|
|
4615
4689
|
if (e.type === "text") {
|
|
@@ -4618,86 +4692,103 @@ async function runTurn(params) {
|
|
|
4618
4692
|
subAgentText = `Using ${e.name}`;
|
|
4619
4693
|
}
|
|
4620
4694
|
}
|
|
4621
|
-
|
|
4695
|
+
onEvent(e);
|
|
4622
4696
|
};
|
|
4623
|
-
const toolStatusWatcher = startStatusWatcher({
|
|
4624
|
-
apiConfig,
|
|
4625
|
-
getContext: () => ({
|
|
4626
|
-
assistantText: subAgentText || getTextContent(contentBlocks).slice(-500),
|
|
4627
|
-
lastToolName: toolCalls.filter((tc) => !STATUS_EXCLUDED_TOOLS.has(tc.name)).map((tc) => tc.name).join(", ") || void 0,
|
|
4628
|
-
lastToolResult: lastCompletedResult || void 0,
|
|
4629
|
-
onboardingState,
|
|
4630
|
-
userMessage
|
|
4631
|
-
}),
|
|
4632
|
-
onStatus: (label) => origOnEvent({ type: "status", message: label }),
|
|
4633
|
-
signal
|
|
4634
|
-
});
|
|
4635
4697
|
const subAgentMessages = /* @__PURE__ */ new Map();
|
|
4636
4698
|
const results = await Promise.all(
|
|
4637
4699
|
toolCalls.map(async (tc) => {
|
|
4638
4700
|
if (signal?.aborted) {
|
|
4639
|
-
return {
|
|
4640
|
-
id: tc.id,
|
|
4641
|
-
result: "Error: cancelled",
|
|
4642
|
-
isError: true
|
|
4643
|
-
};
|
|
4701
|
+
return { id: tc.id, result: "Error: cancelled", isError: true };
|
|
4644
4702
|
}
|
|
4645
4703
|
const toolStart = Date.now();
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4704
|
+
let settle;
|
|
4705
|
+
const resultPromise = new Promise((res) => {
|
|
4706
|
+
settle = (result, isError) => res({ id: tc.id, result, isError });
|
|
4707
|
+
});
|
|
4708
|
+
let toolAbort = new AbortController();
|
|
4709
|
+
const cascadeAbort = () => toolAbort.abort();
|
|
4710
|
+
signal?.addEventListener("abort", cascadeAbort, { once: true });
|
|
4711
|
+
let settled = false;
|
|
4712
|
+
const safeSettle = (result, isError) => {
|
|
4713
|
+
if (settled) {
|
|
4714
|
+
return;
|
|
4715
|
+
}
|
|
4716
|
+
settled = true;
|
|
4717
|
+
signal?.removeEventListener("abort", cascadeAbort);
|
|
4718
|
+
settle(result, isError);
|
|
4719
|
+
};
|
|
4720
|
+
const run = async (input) => {
|
|
4721
|
+
try {
|
|
4722
|
+
let result;
|
|
4723
|
+
if (EXTERNAL_TOOLS.has(tc.name) && resolveExternalTool) {
|
|
4724
|
+
saveSession(state);
|
|
4725
|
+
log.info("Waiting for external tool result", {
|
|
4667
4726
|
name: tc.name,
|
|
4668
|
-
|
|
4669
|
-
})
|
|
4727
|
+
id: tc.id
|
|
4728
|
+
});
|
|
4729
|
+
result = await resolveExternalTool(tc.id, tc.name, input);
|
|
4730
|
+
} else {
|
|
4731
|
+
result = await executeTool(tc.name, input, {
|
|
4732
|
+
apiConfig,
|
|
4733
|
+
model,
|
|
4734
|
+
signal: toolAbort.signal,
|
|
4735
|
+
onEvent: wrappedOnEvent,
|
|
4736
|
+
resolveExternalTool,
|
|
4737
|
+
toolCallId: tc.id,
|
|
4738
|
+
subAgentMessages,
|
|
4739
|
+
toolRegistry,
|
|
4740
|
+
onLog: (line) => wrappedOnEvent({
|
|
4741
|
+
type: "tool_input_delta",
|
|
4742
|
+
id: tc.id,
|
|
4743
|
+
name: tc.name,
|
|
4744
|
+
result: line
|
|
4745
|
+
})
|
|
4746
|
+
});
|
|
4747
|
+
}
|
|
4748
|
+
safeSettle(result, result.startsWith("Error"));
|
|
4749
|
+
} catch (err) {
|
|
4750
|
+
safeSettle(`Error: ${err.message}`, true);
|
|
4751
|
+
}
|
|
4752
|
+
};
|
|
4753
|
+
const entry = {
|
|
4754
|
+
id: tc.id,
|
|
4755
|
+
name: tc.name,
|
|
4756
|
+
input: tc.input,
|
|
4757
|
+
abortController: toolAbort,
|
|
4758
|
+
startedAt: toolStart,
|
|
4759
|
+
settle: safeSettle,
|
|
4760
|
+
rerun: (newInput) => {
|
|
4761
|
+
settled = false;
|
|
4762
|
+
toolAbort = new AbortController();
|
|
4763
|
+
signal?.addEventListener("abort", () => toolAbort.abort(), {
|
|
4764
|
+
once: true
|
|
4670
4765
|
});
|
|
4766
|
+
entry.abortController = toolAbort;
|
|
4767
|
+
entry.input = newInput;
|
|
4768
|
+
run(newInput);
|
|
4671
4769
|
}
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
id: tc.id,
|
|
4692
|
-
name: tc.name,
|
|
4693
|
-
result: errorMsg,
|
|
4694
|
-
isError: true
|
|
4695
|
-
});
|
|
4696
|
-
return { id: tc.id, result: errorMsg, isError: true };
|
|
4697
|
-
}
|
|
4770
|
+
};
|
|
4771
|
+
toolRegistry?.register(entry);
|
|
4772
|
+
run(tc.input);
|
|
4773
|
+
const r = await resultPromise;
|
|
4774
|
+
toolRegistry?.unregister(tc.id);
|
|
4775
|
+
log.info("Tool completed", {
|
|
4776
|
+
name: tc.name,
|
|
4777
|
+
elapsed: `${Date.now() - toolStart}ms`,
|
|
4778
|
+
isError: r.isError,
|
|
4779
|
+
resultLength: r.result.length
|
|
4780
|
+
});
|
|
4781
|
+
onEvent({
|
|
4782
|
+
type: "tool_done",
|
|
4783
|
+
id: tc.id,
|
|
4784
|
+
name: tc.name,
|
|
4785
|
+
result: r.result,
|
|
4786
|
+
isError: r.isError
|
|
4787
|
+
});
|
|
4788
|
+
return r;
|
|
4698
4789
|
})
|
|
4699
4790
|
);
|
|
4700
|
-
|
|
4791
|
+
statusWatcher.stop();
|
|
4701
4792
|
for (const r of results) {
|
|
4702
4793
|
const block = contentBlocks.find(
|
|
4703
4794
|
(b) => b.type === "tool" && b.id === r.id
|
|
@@ -4705,6 +4796,7 @@ async function runTurn(params) {
|
|
|
4705
4796
|
if (block?.type === "tool") {
|
|
4706
4797
|
block.result = r.result;
|
|
4707
4798
|
block.isError = r.isError;
|
|
4799
|
+
block.completedAt = Date.now();
|
|
4708
4800
|
const msgs = subAgentMessages.get(r.id);
|
|
4709
4801
|
if (msgs) {
|
|
4710
4802
|
block.subAgentMessages = msgs;
|
|
@@ -5063,6 +5155,84 @@ var init_config = __esm({
|
|
|
5063
5155
|
}
|
|
5064
5156
|
});
|
|
5065
5157
|
|
|
5158
|
+
// src/toolRegistry.ts
|
|
5159
|
+
var ToolRegistry;
|
|
5160
|
+
var init_toolRegistry = __esm({
|
|
5161
|
+
"src/toolRegistry.ts"() {
|
|
5162
|
+
"use strict";
|
|
5163
|
+
ToolRegistry = class {
|
|
5164
|
+
entries = /* @__PURE__ */ new Map();
|
|
5165
|
+
onEvent;
|
|
5166
|
+
register(entry) {
|
|
5167
|
+
this.entries.set(entry.id, entry);
|
|
5168
|
+
}
|
|
5169
|
+
unregister(id) {
|
|
5170
|
+
this.entries.delete(id);
|
|
5171
|
+
}
|
|
5172
|
+
get(id) {
|
|
5173
|
+
return this.entries.get(id);
|
|
5174
|
+
}
|
|
5175
|
+
/**
|
|
5176
|
+
* Stop a running tool.
|
|
5177
|
+
*
|
|
5178
|
+
* - graceful: abort and settle with [INTERRUPTED] + partial result
|
|
5179
|
+
* - hard: abort and settle with a generic error
|
|
5180
|
+
*
|
|
5181
|
+
* Returns true if the tool was found and stopped.
|
|
5182
|
+
*/
|
|
5183
|
+
stop(id, mode) {
|
|
5184
|
+
const entry = this.entries.get(id);
|
|
5185
|
+
if (!entry) {
|
|
5186
|
+
return false;
|
|
5187
|
+
}
|
|
5188
|
+
entry.abortController.abort(mode);
|
|
5189
|
+
if (mode === "graceful") {
|
|
5190
|
+
const partial = entry.getPartialResult?.() ?? "";
|
|
5191
|
+
const result = partial ? `[INTERRUPTED]
|
|
5192
|
+
|
|
5193
|
+
${partial}` : "[INTERRUPTED] Tool execution was stopped.";
|
|
5194
|
+
entry.settle(result, false);
|
|
5195
|
+
} else {
|
|
5196
|
+
entry.settle("Error: tool was cancelled", true);
|
|
5197
|
+
}
|
|
5198
|
+
this.onEvent?.({
|
|
5199
|
+
type: "tool_stopped",
|
|
5200
|
+
id: entry.id,
|
|
5201
|
+
name: entry.name,
|
|
5202
|
+
mode,
|
|
5203
|
+
...entry.parentToolId && { parentToolId: entry.parentToolId }
|
|
5204
|
+
});
|
|
5205
|
+
this.entries.delete(id);
|
|
5206
|
+
return true;
|
|
5207
|
+
}
|
|
5208
|
+
/**
|
|
5209
|
+
* Restart a running tool with the same or patched input.
|
|
5210
|
+
* The original controllable promise stays pending and settles
|
|
5211
|
+
* when the new execution finishes.
|
|
5212
|
+
*
|
|
5213
|
+
* Returns true if the tool was found and restarted.
|
|
5214
|
+
*/
|
|
5215
|
+
restart(id, patchedInput) {
|
|
5216
|
+
const entry = this.entries.get(id);
|
|
5217
|
+
if (!entry) {
|
|
5218
|
+
return false;
|
|
5219
|
+
}
|
|
5220
|
+
entry.abortController.abort("restart");
|
|
5221
|
+
const newInput = patchedInput ? { ...entry.input, ...patchedInput } : entry.input;
|
|
5222
|
+
this.onEvent?.({
|
|
5223
|
+
type: "tool_restarted",
|
|
5224
|
+
id: entry.id,
|
|
5225
|
+
name: entry.name,
|
|
5226
|
+
input: newInput,
|
|
5227
|
+
...entry.parentToolId && { parentToolId: entry.parentToolId }
|
|
5228
|
+
});
|
|
5229
|
+
entry.rerun(newInput);
|
|
5230
|
+
return true;
|
|
5231
|
+
}
|
|
5232
|
+
};
|
|
5233
|
+
}
|
|
5234
|
+
});
|
|
5235
|
+
|
|
5066
5236
|
// src/headless.ts
|
|
5067
5237
|
var headless_exports = {};
|
|
5068
5238
|
__export(headless_exports, {
|
|
@@ -5134,6 +5304,7 @@ async function startHeadless(opts = {}) {
|
|
|
5134
5304
|
const EXTERNAL_TOOL_TIMEOUT_MS = 3e5;
|
|
5135
5305
|
const pendingTools = /* @__PURE__ */ new Map();
|
|
5136
5306
|
const earlyResults = /* @__PURE__ */ new Map();
|
|
5307
|
+
const toolRegistry = new ToolRegistry();
|
|
5137
5308
|
const USER_FACING_TOOLS = /* @__PURE__ */ new Set([
|
|
5138
5309
|
"promptUser",
|
|
5139
5310
|
"confirmDestructiveAction",
|
|
@@ -5238,14 +5409,46 @@ async function startHeadless(opts = {}) {
|
|
|
5238
5409
|
rid
|
|
5239
5410
|
);
|
|
5240
5411
|
return;
|
|
5412
|
+
case "tool_stopped":
|
|
5413
|
+
emit(
|
|
5414
|
+
"tool_stopped",
|
|
5415
|
+
{
|
|
5416
|
+
id: e.id,
|
|
5417
|
+
name: e.name,
|
|
5418
|
+
mode: e.mode,
|
|
5419
|
+
...e.parentToolId && { parentToolId: e.parentToolId }
|
|
5420
|
+
},
|
|
5421
|
+
rid
|
|
5422
|
+
);
|
|
5423
|
+
return;
|
|
5424
|
+
case "tool_restarted":
|
|
5425
|
+
emit(
|
|
5426
|
+
"tool_restarted",
|
|
5427
|
+
{
|
|
5428
|
+
id: e.id,
|
|
5429
|
+
name: e.name,
|
|
5430
|
+
input: e.input,
|
|
5431
|
+
...e.parentToolId && { parentToolId: e.parentToolId }
|
|
5432
|
+
},
|
|
5433
|
+
rid
|
|
5434
|
+
);
|
|
5435
|
+
return;
|
|
5241
5436
|
case "status":
|
|
5242
|
-
emit(
|
|
5437
|
+
emit(
|
|
5438
|
+
"status",
|
|
5439
|
+
{
|
|
5440
|
+
message: e.message,
|
|
5441
|
+
...e.parentToolId && { parentToolId: e.parentToolId }
|
|
5442
|
+
},
|
|
5443
|
+
rid
|
|
5444
|
+
);
|
|
5243
5445
|
return;
|
|
5244
5446
|
case "error":
|
|
5245
5447
|
emit("error", { error: e.error }, rid);
|
|
5246
5448
|
return;
|
|
5247
5449
|
}
|
|
5248
5450
|
}
|
|
5451
|
+
toolRegistry.onEvent = onEvent;
|
|
5249
5452
|
async function handleMessage(parsed, requestId) {
|
|
5250
5453
|
if (running) {
|
|
5251
5454
|
emit(
|
|
@@ -5297,7 +5500,8 @@ async function startHeadless(opts = {}) {
|
|
|
5297
5500
|
signal: currentAbort.signal,
|
|
5298
5501
|
onEvent,
|
|
5299
5502
|
resolveExternalTool,
|
|
5300
|
-
hidden: isCommand
|
|
5503
|
+
hidden: isCommand,
|
|
5504
|
+
toolRegistry
|
|
5301
5505
|
});
|
|
5302
5506
|
if (!completedEmitted) {
|
|
5303
5507
|
emit(
|
|
@@ -5351,6 +5555,36 @@ async function startHeadless(opts = {}) {
|
|
|
5351
5555
|
emit("completed", { success: true }, requestId);
|
|
5352
5556
|
return;
|
|
5353
5557
|
}
|
|
5558
|
+
if (action === "stop_tool") {
|
|
5559
|
+
const id = parsed.id;
|
|
5560
|
+
const mode = parsed.mode ?? "hard";
|
|
5561
|
+
const found = toolRegistry.stop(id, mode);
|
|
5562
|
+
if (found) {
|
|
5563
|
+
emit("completed", { success: true }, requestId);
|
|
5564
|
+
} else {
|
|
5565
|
+
emit(
|
|
5566
|
+
"completed",
|
|
5567
|
+
{ success: false, error: "Tool not found" },
|
|
5568
|
+
requestId
|
|
5569
|
+
);
|
|
5570
|
+
}
|
|
5571
|
+
return;
|
|
5572
|
+
}
|
|
5573
|
+
if (action === "restart_tool") {
|
|
5574
|
+
const id = parsed.id;
|
|
5575
|
+
const patchedInput = parsed.input;
|
|
5576
|
+
const found = toolRegistry.restart(id, patchedInput);
|
|
5577
|
+
if (found) {
|
|
5578
|
+
emit("completed", { success: true }, requestId);
|
|
5579
|
+
} else {
|
|
5580
|
+
emit(
|
|
5581
|
+
"completed",
|
|
5582
|
+
{ success: false, error: "Tool not found" },
|
|
5583
|
+
requestId
|
|
5584
|
+
);
|
|
5585
|
+
}
|
|
5586
|
+
return;
|
|
5587
|
+
}
|
|
5354
5588
|
if (action === "message") {
|
|
5355
5589
|
await handleMessage(parsed, requestId);
|
|
5356
5590
|
return;
|
|
@@ -5385,6 +5619,7 @@ var init_headless = __esm({
|
|
|
5385
5619
|
init_lsp();
|
|
5386
5620
|
init_agent();
|
|
5387
5621
|
init_session();
|
|
5622
|
+
init_toolRegistry();
|
|
5388
5623
|
}
|
|
5389
5624
|
});
|
|
5390
5625
|
|