openfox 2.0.75 → 2.0.77

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 (63) hide show
  1. package/README.md +5 -2
  2. package/dist/{chat-handler-QLMBYRDY.js → chat-handler-FNRKORKP.js} +16 -16
  3. package/dist/{chunk-CJ2AJ7HU.js → chunk-3TQN25OM.js} +3 -3
  4. package/dist/{chunk-KEVRZWL3.js → chunk-46RORSKU.js} +2 -2
  5. package/dist/{chunk-S7O77CVO.js → chunk-4QHDQP2N.js} +2 -2
  6. package/dist/{chunk-I4RWK2L2.js → chunk-7QXRQ5ZL.js} +3 -3
  7. package/dist/{chunk-MIJX54CG.js → chunk-BX3VJP2D.js} +167 -89
  8. package/dist/{chunk-LKUAKQZY.js → chunk-CI5BWHW7.js} +8 -8
  9. package/dist/{chunk-OHGQILRF.js → chunk-CJDYSUU5.js} +3 -3
  10. package/dist/{chunk-LUG5QTFC.js → chunk-CPTC2MD5.js} +3 -3
  11. package/dist/{chunk-E5LLEO3C.js → chunk-DH3SSBZN.js} +2 -2
  12. package/dist/{chunk-UV3EMWL4.js → chunk-LXFLRM7M.js} +2 -2
  13. package/dist/{chunk-YFFP4DR4.js → chunk-NGJ5XJ7D.js} +2 -2
  14. package/dist/chunk-NUXS5OQB.js +7 -0
  15. package/dist/{chunk-LTFB2WWE.js → chunk-OBQPXUXI.js} +2 -2
  16. package/dist/{chunk-EZK7CGJ7.js → chunk-RMXPVQP4.js} +315 -45
  17. package/dist/{chunk-J3VQBVGO.js → chunk-VMYDUZWI.js} +8 -8
  18. package/dist/{chunk-UN26GIQG.js → chunk-VPFUXGMM.js} +6 -1
  19. package/dist/{chunk-6XOA2WPU.js → chunk-WL2WEJAK.js} +6 -3
  20. package/dist/{chunk-XWBNYU2L.js → chunk-XNCHOD2X.js} +5 -4
  21. package/dist/{chunk-6ZMGWDOD.js → chunk-YDV7RIQ6.js} +143 -109
  22. package/dist/{chunk-WGAAQASA.js → chunk-YFVSSMA3.js} +3 -2
  23. package/dist/{chunk-QNKXZH3Z.js → chunk-YMFCFMMB.js} +2 -2
  24. package/dist/{chunk-PJQW6TYI.js → chunk-YPHLCRFP.js} +7 -7
  25. package/dist/cli/dev.js +1 -1
  26. package/dist/cli/index.js +1 -1
  27. package/dist/{client-SC6X65GY.js → client-V5DZRO2D.js} +3 -3
  28. package/dist/{client-pure-NMLDKRDN.js → client-pure-5YE5WFJP.js} +2 -2
  29. package/dist/{compactor-AERNYEMP.js → compactor-BJXFE5PL.js} +8 -8
  30. package/dist/{config-EUMVEFHU.js → config-MD74ETY5.js} +2 -2
  31. package/dist/{events-X353XCPN.js → events-FLWRLM6V.js} +3 -3
  32. package/dist/{inspect-proxy-PHVZBZUO.js → inspect-proxy-JHZV34QR.js} +4 -4
  33. package/dist/{manager-5GILDCVD.js → manager-OPMCSYN2.js} +5 -5
  34. package/dist/{orchestrator-BIFTALBG.js → orchestrator-67BZJEOO.js} +15 -15
  35. package/dist/package.json +3 -1
  36. package/dist/{path-security-3FAIPJSV.js → path-security-ZROWNL22.js} +4 -4
  37. package/dist/{platform-XQ7BS3KQ.js → platform-QGXO3CNR.js} +4 -4
  38. package/dist/plugins-registry.json +6 -0
  39. package/dist/{processor-MQ47QSDR.js → processor-BCOSEMZK.js} +16 -16
  40. package/dist/{project-creator-FQRBN3RG.js → project-creator-C22J43BC.js} +3 -3
  41. package/dist/{projects-LHRNCUGW.js → projects-WSVINK2C.js} +3 -3
  42. package/dist/{protocol-Sr6Jr4ZS.d.ts → protocol-Ceapo3jt.d.ts} +1 -1
  43. package/dist/provider/index.d.ts +4 -4
  44. package/dist/{provider-OJUCZ5RN.js → provider-PI3RDDE4.js} +6 -6
  45. package/dist/{provider-manager-MAKXSL6L.js → provider-manager-PD3BXUHY.js} +4 -4
  46. package/dist/{serve-UD27KOL2.js → serve-BD44GN7N.js} +21 -21
  47. package/dist/server/index.d.ts +3 -3
  48. package/dist/server/index.js +20 -20
  49. package/dist/{server-TJ3PP5EW.js → server-OLRW27DH.js} +17 -17
  50. package/dist/{settings-PFXRYXZU.js → settings-7XDMSPIC.js} +3 -3
  51. package/dist/shared/index.d.ts +3 -3
  52. package/dist/{tools-RZ464GUJ.js → tools-T7S45DOQ.js} +14 -14
  53. package/dist/{types-C4cG9CtC.d.ts → types-DABVUbUu.d.ts} +1 -0
  54. package/dist/{types-DSZhFA8O.d.ts → types-pssMT-oY.d.ts} +1 -1
  55. package/dist/{update-MWIZH4P2.js → update-56VZOLQJ.js} +2 -2
  56. package/dist/{update-server-MYYQUNZX.js → update-server-V6GJ43WH.js} +2 -2
  57. package/dist/web/assets/index-BuUd6IgK.js +305 -0
  58. package/dist/web/index.html +1 -1
  59. package/dist/web/sw.js +1 -1
  60. package/package.json +3 -1
  61. package/plugins-registry.json +6 -0
  62. package/dist/chunk-6COWK53A.js +0 -7
  63. package/dist/web/assets/index-Bn4hwZeP.js +0 -305
@@ -9,7 +9,7 @@ import {
9
9
  loadAllAgentsDefault,
10
10
  processEventsForConversation,
11
11
  runTopLevelAgentLoop
12
- } from "./chunk-6ZMGWDOD.js";
12
+ } from "./chunk-YDV7RIQ6.js";
13
13
  import {
14
14
  TurnMetrics,
15
15
  buildAgentReminder,
@@ -17,16 +17,16 @@ import {
17
17
  buildTopLevelSystemPrompt,
18
18
  createChatDoneEvent,
19
19
  createMessageStartEvent
20
- } from "./chunk-XWBNYU2L.js";
20
+ } from "./chunk-XNCHOD2X.js";
21
21
  import {
22
22
  PathAccessDeniedError
23
- } from "./chunk-KEVRZWL3.js";
23
+ } from "./chunk-46RORSKU.js";
24
24
  import {
25
25
  getCurrentContextWindowId,
26
26
  getCurrentWindowMessageOptions,
27
27
  getEventStore,
28
28
  getRuntimeConfig
29
- } from "./chunk-YFFP4DR4.js";
29
+ } from "./chunk-NGJ5XJ7D.js";
30
30
  import {
31
31
  buildSnapshotFromSessionState
32
32
  } from "./chunk-DJASQ2ZB.js";
@@ -66,7 +66,7 @@ function resolveAgentDef(sessionManager, sessionId) {
66
66
  }
67
67
  async function buildCachedPrompt(sessionManager, sessionId, agentDef) {
68
68
  const { instructionContent, skills } = await loadSessionContext(sessionManager, sessionId);
69
- const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-RZ464GUJ.js");
69
+ const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-T7S45DOQ.js");
70
70
  const tools = getToolRegistryForAgent2(agentDef).definitions;
71
71
  const toolFingerprint = getToolFingerprint(tools);
72
72
  const allAgents = await loadAllAgentsDefault();
@@ -79,7 +79,7 @@ async function buildCachedPrompt(sessionManager, sessionId, agentDef) {
79
79
  async function computeSessionHash(sessionManager, sessionId) {
80
80
  const { instructionContent, skills } = await loadSessionContext(sessionManager, sessionId);
81
81
  const agentDef = await resolveAgentDef(sessionManager, sessionId);
82
- const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-RZ464GUJ.js");
82
+ const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-T7S45DOQ.js");
83
83
  const tools = getToolRegistryForAgent2(agentDef).definitions;
84
84
  const toolFingerprint = getToolFingerprint(tools);
85
85
  return computeDynamicContextHash(instructionContent, skills, toolFingerprint);
@@ -97,7 +97,7 @@ async function applyDynamicContext(sessionManager, sessionId) {
97
97
 
98
98
  // src/server/chat/orchestrator.ts
99
99
  async function buildRetryPatterns() {
100
- const { getSetting, SETTINGS_KEYS } = await import("./settings-PFXRYXZU.js");
100
+ const { getSetting, SETTINGS_KEYS } = await import("./settings-7XDMSPIC.js");
101
101
  const raw = getSetting(SETTINGS_KEYS.RETRY_PATTERNS);
102
102
  if (!raw) {
103
103
  const oldXmlProtection = getSetting("llm.disableXmlProtection");
@@ -359,4 +359,4 @@ export {
359
359
  runChatTurn,
360
360
  runAgentTurn
361
361
  };
362
- //# sourceMappingURL=chunk-J3VQBVGO.js.map
362
+ //# sourceMappingURL=chunk-VMYDUZWI.js.map
@@ -8,6 +8,10 @@ function buildUpdatedServerConfig(patch, existing, persistedCfg) {
8
8
  const mergedEnv = patch.env !== void 0 ? patch.env : transportChanged ? void 0 : existing.config.env;
9
9
  const mergedUrl = patch.url !== void 0 ? patch.url : transportChanged ? void 0 : existing.config.url;
10
10
  const mergedHeaders = patch.headers !== void 0 ? patch.headers : transportChanged ? void 0 : existing.config.headers;
11
+ const mergedTimeout = patch.timeout !== void 0 ? patch.timeout : existing.config.timeout;
12
+ if (patch.timeout !== void 0 && (typeof patch.timeout !== "number" || patch.timeout <= 0)) {
13
+ return { serverCfg: {}, error: "timeout must be a positive number" };
14
+ }
11
15
  if (resolvedTransport === "http" && !mergedUrl) {
12
16
  return { serverCfg: {}, error: "url is required for http transport" };
13
17
  }
@@ -21,6 +25,7 @@ function buildUpdatedServerConfig(patch, existing, persistedCfg) {
21
25
  ...mergedEnv && Object.keys(mergedEnv).length > 0 ? { env: mergedEnv } : {},
22
26
  ...mergedUrl ? { url: mergedUrl } : {},
23
27
  ...mergedHeaders && Object.keys(mergedHeaders).length > 0 ? { headers: mergedHeaders } : {},
28
+ ...mergedTimeout !== void 0 ? { timeout: mergedTimeout } : {},
24
29
  ...persistedCfg?.disabledTools && persistedCfg.disabledTools.length > 0 ? { disabledTools: persistedCfg.disabledTools } : {},
25
30
  ...persistedCfg?.cachedTools && persistedCfg.cachedTools.length > 0 ? { cachedTools: persistedCfg.cachedTools } : {}
26
31
  };
@@ -51,4 +56,4 @@ export {
51
56
  buildUpdatedServerConfig,
52
57
  applyMcpServerUpdate
53
58
  };
54
- //# sourceMappingURL=chunk-UN26GIQG.js.map
59
+ //# sourceMappingURL=chunk-VPFUXGMM.js.map
@@ -13,7 +13,7 @@ import {
13
13
  getThinking,
14
14
  mapFinishReason,
15
15
  parseToolArguments
16
- } from "./chunk-EZK7CGJ7.js";
16
+ } from "./chunk-RMXPVQP4.js";
17
17
  import {
18
18
  LLMError,
19
19
  OpenAIHttpClient
@@ -94,7 +94,10 @@ function createLLMClient(config, initialBackend = "unknown") {
94
94
  const content = message.content ?? "";
95
95
  const thinkingContent = getThinking(message, thinkingField) ?? "";
96
96
  const toolCalls = message.tool_calls?.map((tc) => {
97
- const { arguments: args, parseError } = parseToolArguments(tc.function.arguments, { id: tc.id, name: tc.function.name });
97
+ const { arguments: args, parseError } = parseToolArguments(tc.function.arguments, {
98
+ id: tc.id,
99
+ name: tc.function.name
100
+ });
98
101
  return { id: tc.id, name: tc.function.name, arguments: args, ...parseError ? { parseError } : {} };
99
102
  });
100
103
  return {
@@ -265,4 +268,4 @@ function createLLMClient(config, initialBackend = "unknown") {
265
268
  export {
266
269
  createLLMClient
267
270
  };
268
- //# sourceMappingURL=chunk-6XOA2WPU.js.map
271
+ //# sourceMappingURL=chunk-WL2WEJAK.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getPlatformShell
3
- } from "./chunk-S7O77CVO.js";
3
+ } from "./chunk-4QHDQP2N.js";
4
4
  import {
5
5
  streamWithSegments
6
6
  } from "./chunk-J2GP3J3X.js";
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-YHEQTVFV.js";
13
13
  import {
14
14
  buildModelParams
15
- } from "./chunk-EZK7CGJ7.js";
15
+ } from "./chunk-RMXPVQP4.js";
16
16
  import {
17
17
  logger
18
18
  } from "./chunk-K44MW7JJ.js";
@@ -419,13 +419,14 @@ async function* streamLLMPure(options) {
419
419
  const fullName = toolNames.get(value.index);
420
420
  if (!seenToolIndices.has(value.index) && fullName) {
421
421
  seenToolIndices.add(value.index);
422
+ const displayName = options.subAgentAliases?.has(fullName) ? "call_sub_agent" : fullName;
422
423
  const accumulatedArgs = toolArgs.get(value.index);
423
424
  yield {
424
425
  type: "tool.preparing",
425
426
  data: {
426
427
  messageId,
427
428
  index: value.index,
428
- name: fullName,
429
+ name: displayName,
429
430
  ...accumulatedArgs ? { arguments: accumulatedArgs } : {}
430
431
  }
431
432
  };
@@ -678,4 +679,4 @@ export {
678
679
  createChatDoneEvent,
679
680
  consumeStreamGenerator
680
681
  };
681
- //# sourceMappingURL=chunk-XWBNYU2L.js.map
682
+ //# sourceMappingURL=chunk-XNCHOD2X.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-NWO6GRYE.js";
4
4
  import {
5
5
  applyMcpServerUpdate
6
- } from "./chunk-UN26GIQG.js";
6
+ } from "./chunk-VPFUXGMM.js";
7
7
  import {
8
8
  getGitBranch,
9
9
  listWorkspaces
@@ -24,13 +24,13 @@ import {
24
24
  createToolCallEvent,
25
25
  createToolResultEvent,
26
26
  streamLLMPure
27
- } from "./chunk-XWBNYU2L.js";
27
+ } from "./chunk-XNCHOD2X.js";
28
28
  import {
29
29
  startInspectProxy
30
- } from "./chunk-E5LLEO3C.js";
30
+ } from "./chunk-DH3SSBZN.js";
31
31
  import {
32
32
  getProject
33
- } from "./chunk-UV3EMWL4.js";
33
+ } from "./chunk-LXFLRM7M.js";
34
34
  import {
35
35
  checkAborted,
36
36
  createProcess,
@@ -41,13 +41,13 @@ import {
41
41
  spawnShellProcess,
42
42
  startProcessCommand,
43
43
  stopProcess
44
- } from "./chunk-LTFB2WWE.js";
44
+ } from "./chunk-OBQPXUXI.js";
45
45
  import {
46
46
  SETTINGS_KEYS,
47
47
  deleteSetting,
48
48
  getSetting,
49
49
  setSetting
50
- } from "./chunk-QNKXZH3Z.js";
50
+ } from "./chunk-YMFCFMMB.js";
51
51
  import {
52
52
  getMaxPerSession,
53
53
  getSessionProcessCount,
@@ -58,13 +58,13 @@ import {
58
58
  extractAbsolutePathsFromCommand,
59
59
  extractSensitivePathsFromCommand,
60
60
  requestPathAccess
61
- } from "./chunk-KEVRZWL3.js";
61
+ } from "./chunk-46RORSKU.js";
62
62
  import {
63
63
  getCurrentContextWindowId,
64
64
  getCurrentWindowMessageOptions,
65
65
  getEventStore,
66
66
  getRuntimeConfig
67
- } from "./chunk-YFFP4DR4.js";
67
+ } from "./chunk-NGJ5XJ7D.js";
68
68
  import {
69
69
  buildContextMessagesFromEventHistory,
70
70
  foldContextState,
@@ -86,18 +86,22 @@ import {
86
86
  } from "./chunk-V4IE7HJY.js";
87
87
  import {
88
88
  OUTPUT_LIMITS,
89
+ cacheSet,
90
+ contentHash,
91
+ decodeDataUrl,
92
+ extractPdfContent,
89
93
  extractPdfText,
90
94
  formatPdfErrorMessage,
91
95
  isPdfBuffer,
92
96
  processPdfContent
93
- } from "./chunk-EZK7CGJ7.js";
97
+ } from "./chunk-RMXPVQP4.js";
94
98
  import {
95
99
  logger
96
100
  } from "./chunk-K44MW7JJ.js";
97
101
  import {
98
102
  loadGlobalConfig,
99
103
  saveGlobalConfig
100
- } from "./chunk-WGAAQASA.js";
104
+ } from "./chunk-YFVSSMA3.js";
101
105
  import {
102
106
  getGlobalConfigDir
103
107
  } from "./chunk-CQGTEGKL.js";
@@ -2107,6 +2111,21 @@ function createToolProgressHandler(append, messageId, callId, _sessionId) {
2107
2111
  // src/server/chat/execute-tools.ts
2108
2112
  import stripAnsi2 from "strip-ansi";
2109
2113
  var INTERRUPTED_ERROR = "Tool execution was interrupted by user";
2114
+ function extractSubAgentPrompt(args) {
2115
+ return args["prompt"] || args["query"] || args["task"] || "";
2116
+ }
2117
+ async function transformSubAgentAliases(toolCalls, toolRegistry) {
2118
+ const hasCallSubAgent = toolRegistry.tools.some((t) => t.name === "call_sub_agent");
2119
+ if (!hasCallSubAgent) return;
2120
+ const agents = await loadAllAgentsDefault();
2121
+ for (const tc of toolCalls) {
2122
+ const agentDef = findAgentById(tc.name, agents);
2123
+ if (!agentDef?.metadata.subagent) continue;
2124
+ const prompt = extractSubAgentPrompt(tc.arguments);
2125
+ tc.name = "call_sub_agent";
2126
+ tc.arguments = { subAgentType: agentDef.metadata.id, prompt };
2127
+ }
2128
+ }
2110
2129
  function createInterruptedResult(startTime) {
2111
2130
  return {
2112
2131
  success: false,
@@ -2123,6 +2142,7 @@ async function executeTools(assistantMsgId, toolCalls, ctx, append) {
2123
2142
  if (ctx.signal?.aborted) {
2124
2143
  throw new Error("Aborted");
2125
2144
  }
2145
+ await transformSubAgentAliases(toolCalls, ctx.toolRegistry);
2126
2146
  for (const toolCall of toolCalls) {
2127
2147
  append(createToolCallEvent(assistantMsgId, toolCall));
2128
2148
  }
@@ -2428,6 +2448,8 @@ ${CONTINUE_PROMPT}` : CONTINUE_PROMPT;
2428
2448
  const requestedMaxTokens = modelSettings.maxTokens ?? 16384;
2429
2449
  modelSettings = { ...modelSettings, maxTokens: Math.min(requestedMaxTokens, availableForOutput) };
2430
2450
  }
2451
+ const allAgents = await loadAllAgentsDefault();
2452
+ const subAgentAliases = new Set(getSubAgents(allAgents).map((a) => a.metadata.id));
2431
2453
  const streamGen = streamLLMPure({
2432
2454
  messageId: assistantMsgId,
2433
2455
  systemPrompt: assembledRequest.systemPrompt,
@@ -2436,6 +2458,7 @@ ${CONTINUE_PROMPT}` : CONTINUE_PROMPT;
2436
2458
  tools: assembledRequest.tools,
2437
2459
  toolChoice: "auto",
2438
2460
  signal,
2461
+ subAgentAliases,
2439
2462
  ...config.retryPatterns ? { retryPatterns: config.retryPatterns } : {},
2440
2463
  ...modelSettings && { modelSettings }
2441
2464
  });
@@ -2494,7 +2517,7 @@ ${CONTINUE_PROMPT}` : CONTINUE_PROMPT;
2494
2517
  sessionManager.setCurrentContextSize(sessionId, result.usage.promptTokens, config.subAgentMetadata?.subAgentId);
2495
2518
  if (!compacting) {
2496
2519
  const contextState2 = sessionManager.getContextState(sessionId);
2497
- const { shouldCompact, appendCompactionPrompt } = await import("./compactor-AERNYEMP.js");
2520
+ const { shouldCompact, appendCompactionPrompt } = await import("./compactor-BJXFE5PL.js");
2498
2521
  if (shouldCompact(contextState2.currentTokens, contextState2.maxTokens, runtimeConfig.context.compactionThreshold)) {
2499
2522
  appendCompactionPrompt(sessionId, append);
2500
2523
  compacting = true;
@@ -2851,10 +2874,9 @@ async function describeImageFromDataUrl(dataUrl, visionModel, options) {
2851
2874
  }
2852
2875
 
2853
2876
  // src/server/context/image-processor.ts
2854
- import { createHash as createHash2 } from "crypto";
2855
2877
  async function loadVisionModelFromGlobalConfig() {
2856
2878
  try {
2857
- const { loadGlobalConfig: loadGlobalConfig2, getVisionFallback } = await import("./config-EUMVEFHU.js");
2879
+ const { loadGlobalConfig: loadGlobalConfig2, getVisionFallback } = await import("./config-MD74ETY5.js");
2858
2880
  const runtimeConfig = getRuntimeConfig();
2859
2881
  const mode = runtimeConfig.mode ?? "production";
2860
2882
  const globalConfig = await loadGlobalConfig2(mode);
@@ -2872,12 +2894,12 @@ async function loadVisionModelFromGlobalConfig() {
2872
2894
  return void 0;
2873
2895
  }
2874
2896
  var descriptionCache = /* @__PURE__ */ new Map();
2875
- function contentHash(data) {
2876
- return createHash2("sha256").update(data).digest("hex").slice(0, 16);
2877
- }
2878
2897
  function isImageAttachment(att) {
2879
2898
  return att.mimeType.startsWith("image/");
2880
2899
  }
2900
+ function isPdfAttachment(att) {
2901
+ return att.mimeType === "application/pdf";
2902
+ }
2881
2903
  function hasImageMetadata(result) {
2882
2904
  const meta = result.metadata;
2883
2905
  if (!meta) return false;
@@ -2885,46 +2907,17 @@ function hasImageMetadata(result) {
2885
2907
  const mimeType = meta["mimeType"];
2886
2908
  return typeof dataUrl === "string" && typeof mimeType === "string" && mimeType.startsWith("image/");
2887
2909
  }
2888
- async function describeAttachment(att, messageId, options, descriptions) {
2889
- const cacheKey = contentHash(att.data);
2890
- if (descriptionCache.has(cacheKey)) {
2891
- const cached = descriptionCache.get(cacheKey);
2892
- descriptions.set(att.id, cached);
2893
- return cached;
2894
- }
2895
- if (options.visionModel) {
2896
- const startData = {
2897
- messageId,
2898
- attachmentId: att.id
2899
- };
2900
- if (att.filename !== void 0) {
2901
- startData.filename = att.filename;
2902
- }
2903
- options.onEvent?.({ type: "vision_fallback.start", data: startData });
2904
- const description = await describeImageFromDataUrl(att.data, options.visionModel, {
2905
- context: att.filename ? `File: ${att.filename}` : void 0,
2906
- signal: options.signal
2907
- });
2908
- descriptionCache.set(cacheKey, description);
2909
- descriptions.set(att.id, description);
2910
- options.onEvent?.({ type: "vision_fallback.done", data: { messageId, attachmentId: att.id, description } });
2911
- return description;
2912
- }
2913
- const placeholder = `[Image: ${att.filename || "image"}]`;
2914
- descriptions.set(att.id, placeholder);
2915
- return placeholder;
2916
- }
2917
- async function describeToolResultImage(dataUrl, filename, toolCallId, messageId, options, descriptions) {
2910
+ async function describeImageDataUrl(dataUrl, attachmentId, messageId, options, descriptions, filename) {
2918
2911
  const cacheKey = contentHash(dataUrl);
2919
2912
  if (descriptionCache.has(cacheKey)) {
2920
2913
  const cached = descriptionCache.get(cacheKey);
2921
- descriptions.set(toolCallId, cached);
2914
+ descriptions.set(attachmentId, cached);
2922
2915
  return cached;
2923
2916
  }
2924
2917
  if (options.visionModel) {
2925
2918
  const startData = {
2926
2919
  messageId,
2927
- attachmentId: toolCallId
2920
+ attachmentId
2928
2921
  };
2929
2922
  if (filename !== void 0) {
2930
2923
  startData.filename = filename;
@@ -2934,18 +2927,61 @@ async function describeToolResultImage(dataUrl, filename, toolCallId, messageId,
2934
2927
  context: filename ? `File: ${filename}` : void 0,
2935
2928
  signal: options.signal
2936
2929
  });
2937
- descriptionCache.set(cacheKey, description);
2938
- descriptions.set(toolCallId, description);
2939
- options.onEvent?.({
2940
- type: "vision_fallback.done",
2941
- data: { messageId, attachmentId: toolCallId, description }
2942
- });
2930
+ cacheSet(descriptionCache, cacheKey, description);
2931
+ descriptions.set(attachmentId, description);
2932
+ options.onEvent?.({ type: "vision_fallback.done", data: { messageId, attachmentId, description } });
2943
2933
  return description;
2944
2934
  }
2945
- const placeholder = `[Image: ${filename || "image"}]`;
2946
- descriptions.set(toolCallId, placeholder);
2935
+ const placeholder = filename ? `[Image: ${filename}]` : "[Image]";
2936
+ descriptions.set(attachmentId, placeholder);
2947
2937
  return placeholder;
2948
2938
  }
2939
+ async function describeAttachment(att, messageId, options, descriptions) {
2940
+ return describeImageDataUrl(att.data, att.id, messageId, options, descriptions, att.filename);
2941
+ }
2942
+ async function describePdfAttachment(att, messageId, options, descriptions) {
2943
+ const hasVision = !!options.visionModel;
2944
+ const cacheKey = `pdf:${hasVision}:${contentHash(att.data)}`;
2945
+ const filenameLabel = att.filename || "document.pdf";
2946
+ if (descriptionCache.has(cacheKey)) {
2947
+ const cached = descriptionCache.get(cacheKey);
2948
+ const output2 = `[PDF: ${filenameLabel}]${cached}`;
2949
+ descriptions.set(att.id, output2);
2950
+ return output2;
2951
+ }
2952
+ const buffer = decodeDataUrl(att.data);
2953
+ if (!buffer) {
2954
+ const fallback = `[PDF: ${filenameLabel}] (could not decode)`;
2955
+ cacheSet(descriptionCache, cacheKey, fallback);
2956
+ descriptions.set(att.id, fallback);
2957
+ return fallback;
2958
+ }
2959
+ let blocks;
2960
+ try {
2961
+ const result = await extractPdfContent(buffer);
2962
+ blocks = result.blocks;
2963
+ } catch {
2964
+ const errorText = `[PDF: ${filenameLabel}] (could not extract content)`;
2965
+ descriptions.set(att.id, errorText);
2966
+ return errorText;
2967
+ }
2968
+ let body = "";
2969
+ let imageIndex = 0;
2970
+ for (const block of blocks) {
2971
+ if (block.type === "text" && block.content) {
2972
+ body += "\n\n" + block.content;
2973
+ } else if (block.type === "image" && block.dataUrl) {
2974
+ const imgAttachmentId = `${att.id}/image-${imageIndex}`;
2975
+ const description = await describeImageDataUrl(block.dataUrl, imgAttachmentId, messageId, options, descriptions);
2976
+ body += "\n\n" + description;
2977
+ imageIndex++;
2978
+ }
2979
+ }
2980
+ const output = `[PDF: ${filenameLabel}]${body}`;
2981
+ cacheSet(descriptionCache, cacheKey, body);
2982
+ descriptions.set(att.id, output);
2983
+ return output;
2984
+ }
2949
2985
  async function processContextImages(events, options) {
2950
2986
  if (options.modelSupportsVision) {
2951
2987
  return { events, descriptions: /* @__PURE__ */ new Map() };
@@ -2956,9 +2992,8 @@ async function processContextImages(events, options) {
2956
2992
  if (event.type === "message.start") {
2957
2993
  const data = event.data;
2958
2994
  if (!data.attachments || data.attachments.length === 0) continue;
2959
- const imageAtts = data.attachments.filter(isImageAttachment);
2960
- if (imageAtts.length === 0) continue;
2961
2995
  let enriched = false;
2996
+ const imageAtts = data.attachments.filter(isImageAttachment);
2962
2997
  for (const att of imageAtts) {
2963
2998
  if (att.description) {
2964
2999
  descriptions.set(att.id, att.description);
@@ -2968,6 +3003,16 @@ async function processContextImages(events, options) {
2968
3003
  att.description = description;
2969
3004
  enriched = true;
2970
3005
  }
3006
+ const pdfAtts = data.attachments.filter(isPdfAttachment);
3007
+ for (const att of pdfAtts) {
3008
+ if (att.pdfContent) {
3009
+ descriptions.set(att.id, att.pdfContent);
3010
+ continue;
3011
+ }
3012
+ const pdfContent = await describePdfAttachment(att, data.messageId, options, descriptions);
3013
+ att.pdfContent = pdfContent;
3014
+ enriched = true;
3015
+ }
2971
3016
  if (enriched && options.persistEvent) {
2972
3017
  options.persistEvent(event.sessionId, event.seq, data);
2973
3018
  }
@@ -2982,13 +3027,13 @@ async function processContextImages(events, options) {
2982
3027
  }
2983
3028
  const dataUrl = meta["dataUrl"];
2984
3029
  const path = meta["path"];
2985
- const description = await describeToolResultImage(
3030
+ const description = await describeImageDataUrl(
2986
3031
  dataUrl,
2987
- path,
2988
3032
  data.toolCallId,
2989
3033
  data.messageId,
2990
3034
  options,
2991
- descriptions
3035
+ descriptions,
3036
+ path
2992
3037
  );
2993
3038
  meta["description"] = description;
2994
3039
  if (options.persistEvent) {
@@ -3000,16 +3045,24 @@ async function processContextImages(events, options) {
3000
3045
  let enriched = false;
3001
3046
  for (const message of snapshot.messages) {
3002
3047
  if (message.role === "user" && message.attachments && message.attachments.length > 0) {
3003
- const imageAtts = message.attachments.filter(isImageAttachment);
3004
- if (imageAtts.length === 0) continue;
3005
- for (const att of imageAtts) {
3006
- if (att.description) {
3007
- descriptions.set(att.id, att.description);
3008
- continue;
3048
+ for (const att of message.attachments) {
3049
+ if (isImageAttachment(att)) {
3050
+ if (att.description) {
3051
+ descriptions.set(att.id, att.description);
3052
+ continue;
3053
+ }
3054
+ const description = await describeAttachment(att, message.id, options, descriptions);
3055
+ att.description = description;
3056
+ enriched = true;
3057
+ } else if (isPdfAttachment(att)) {
3058
+ if (att.pdfContent) {
3059
+ descriptions.set(att.id, att.pdfContent);
3060
+ continue;
3061
+ }
3062
+ const pdfContent = await describePdfAttachment(att, message.id, options, descriptions);
3063
+ att.pdfContent = pdfContent;
3064
+ enriched = true;
3009
3065
  }
3010
- const description = await describeAttachment(att, message.id, options, descriptions);
3011
- att.description = description;
3012
- enriched = true;
3013
3066
  }
3014
3067
  }
3015
3068
  if (message.role === "assistant" && message.toolCalls) {
@@ -3022,13 +3075,13 @@ async function processContextImages(events, options) {
3022
3075
  }
3023
3076
  const dataUrl = meta["dataUrl"];
3024
3077
  const path = meta["path"];
3025
- const description = await describeToolResultImage(
3078
+ const description = await describeImageDataUrl(
3026
3079
  dataUrl,
3027
- path,
3028
3080
  toolCall.id,
3029
3081
  message.id,
3030
3082
  options,
3031
- descriptions
3083
+ descriptions,
3084
+ path
3032
3085
  );
3033
3086
  meta["description"] = description;
3034
3087
  enriched = true;
@@ -3399,7 +3452,7 @@ var callSubAgentTool = {
3399
3452
  };
3400
3453
  }
3401
3454
  try {
3402
- const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-RZ464GUJ.js");
3455
+ const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-T7S45DOQ.js");
3403
3456
  const toolRegistry = getToolRegistryForAgent2(agentDef);
3404
3457
  const turnMetrics = new TurnMetrics();
3405
3458
  const result = await executeSubAgent({
@@ -4369,6 +4422,10 @@ var mcpConfigTool = createTool(
4369
4422
  enabled: {
4370
4423
  type: "boolean",
4371
4424
  description: "Whether the tool should be enabled (required for: toggle-tool)"
4425
+ },
4426
+ timeout: {
4427
+ type: "number",
4428
+ description: "Timeout in seconds for MCP tool calls (optional)"
4372
4429
  }
4373
4430
  },
4374
4431
  required: ["action"]
@@ -4398,7 +4455,7 @@ var mcpConfigTool = createTool(
4398
4455
  mcpNotifyChanged?.(sessionId);
4399
4456
  }
4400
4457
  async function rebuildTools() {
4401
- const { setMcpTools: setMcpTools2 } = await import("./tools-RZ464GUJ.js");
4458
+ const { setMcpTools: setMcpTools2 } = await import("./tools-T7S45DOQ.js");
4402
4459
  const mcpTools = createMcpTools(mcpManagerForTools);
4403
4460
  setMcpTools2(mcpTools);
4404
4461
  }
@@ -4435,13 +4492,17 @@ var mcpConfigTool = createTool(
4435
4492
  } else if (!args.command) {
4436
4493
  return helpers.error("command is required for stdio transport");
4437
4494
  }
4495
+ if (args.timeout !== void 0 && (typeof args.timeout !== "number" || args.timeout <= 0)) {
4496
+ return helpers.error("timeout must be a positive number");
4497
+ }
4438
4498
  const serverCfg = {
4439
4499
  transport: args.transport ?? "stdio",
4440
4500
  ...args.command ? { command: args.command } : {},
4441
4501
  ...args.args && args.args.length > 0 ? { args: args.args } : {},
4442
4502
  ...args.env && Object.keys(args.env).length > 0 ? { env: args.env } : {},
4443
4503
  ...args.url ? { url: args.url } : {},
4444
- ...args.headers && Object.keys(args.headers).length > 0 ? { headers: args.headers } : {}
4504
+ ...args.headers && Object.keys(args.headers).length > 0 ? { headers: args.headers } : {},
4505
+ ...args.timeout !== void 0 ? { timeout: args.timeout } : {}
4445
4506
  };
4446
4507
  await persistAndRebuild((mcpServers) => {
4447
4508
  mcpServers[args.name] = serverCfg;
@@ -4466,7 +4527,8 @@ var mcpConfigTool = createTool(
4466
4527
  ...args.args !== void 0 ? { args: args.args } : {},
4467
4528
  ...args.env !== void 0 ? { env: args.env } : {},
4468
4529
  ...args.url !== void 0 ? { url: args.url } : {},
4469
- ...args.headers !== void 0 ? { headers: args.headers } : {}
4530
+ ...args.headers !== void 0 ? { headers: args.headers } : {},
4531
+ ...args.timeout !== void 0 ? { timeout: args.timeout } : {}
4470
4532
  };
4471
4533
  const { error: updateError } = await applyMcpServerUpdate({
4472
4534
  name: args.name,
@@ -4484,7 +4546,9 @@ var mcpConfigTool = createTool(
4484
4546
  notifyContextChanged(context.sessionId);
4485
4547
  const server = mcpManagerForTools.getServer(args.name);
4486
4548
  const toolCount = server?.tools.length ?? 0;
4487
- return helpers.success(`Updated MCP server "${args.name}" (${toolCount} tools discovered). ${APPLY_PROMPT_MESSAGE}`);
4549
+ return helpers.success(
4550
+ `Updated MCP server "${args.name}" (${toolCount} tools discovered). ${APPLY_PROMPT_MESSAGE}`
4551
+ );
4488
4552
  }
4489
4553
  if (args.action === "remove") {
4490
4554
  if (!args.name) return helpers.error("Missing required field: name");
@@ -4828,39 +4892,11 @@ function validateToolAction(toolName, action, permissions) {
4828
4892
  }
4829
4893
  return void 0;
4830
4894
  }
4831
- function extractSubAgentPrompt(args) {
4832
- return args["prompt"] || args["query"] || args["task"] || "";
4833
- }
4834
4895
  function createRegistryFromTools(tools, allowedTools, toolPermissions, agentId, isSubAgent) {
4835
4896
  const toolMap = /* @__PURE__ */ new Map();
4836
4897
  for (const tool of tools) {
4837
4898
  toolMap.set(tool.name, tool);
4838
4899
  }
4839
- async function trySubAgentAlias(name, args, context) {
4840
- if (!toolMap.has("call_sub_agent")) {
4841
- return null;
4842
- }
4843
- try {
4844
- const agents = await loadAllAgentsDefault();
4845
- const agentDef = findAgentById(name, agents);
4846
- if (!agentDef?.metadata.subagent) {
4847
- return null;
4848
- }
4849
- const prompt = extractSubAgentPrompt(args);
4850
- logger.info("Sub-agent alias transformation", {
4851
- from: name,
4852
- to: "call_sub_agent",
4853
- subAgentType: name
4854
- });
4855
- return callSubAgentTool.execute({ subAgentType: name, prompt }, context);
4856
- } catch (err) {
4857
- logger.warn("Sub-agent alias resolution failed", {
4858
- tool: name,
4859
- error: err instanceof Error ? err.message : String(err)
4860
- });
4861
- return null;
4862
- }
4863
- }
4864
4900
  return {
4865
4901
  tools,
4866
4902
  definitions: tools.map((t) => t.definition),
@@ -4936,8 +4972,6 @@ function createRegistryFromTools(tools, allowedTools, toolPermissions, agentId,
4936
4972
  };
4937
4973
  }
4938
4974
  }
4939
- const aliasResult = await trySubAgentAlias(name, args, context);
4940
- if (aliasResult) return aliasResult;
4941
4975
  return {
4942
4976
  success: false,
4943
4977
  error: `Unknown tool: ${name}. Available tools: ${tools.map((t) => t.name).join(", ")}`,
@@ -5074,4 +5108,4 @@ export {
5074
5108
  getToolRegistryForAgent,
5075
5109
  createToolRegistry
5076
5110
  };
5077
- //# sourceMappingURL=chunk-6ZMGWDOD.js.map
5111
+ //# sourceMappingURL=chunk-YDV7RIQ6.js.map
@@ -104,7 +104,8 @@ var mcpServerSchema = z.object({
104
104
  url: z.string().optional(),
105
105
  headers: z.record(z.string(), z.string()).optional(),
106
106
  disabledTools: z.array(z.string()).optional(),
107
- cachedTools: z.array(cachedToolSchema).optional()
107
+ cachedTools: z.array(cachedToolSchema).optional(),
108
+ timeout: z.number().positive().optional()
108
109
  });
109
110
  var llmConfigSchema = z.object({
110
111
  timeout: z.number().optional(),
@@ -313,4 +314,4 @@ export {
313
314
  removeProvider,
314
315
  activateProvider
315
316
  };
316
- //# sourceMappingURL=chunk-WGAAQASA.js.map
317
+ //# sourceMappingURL=chunk-YFVSSMA3.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getDatabase
3
- } from "./chunk-I4RWK2L2.js";
3
+ } from "./chunk-7QXRQ5ZL.js";
4
4
 
5
5
  // src/server/db/settings.ts
6
6
  var SETTINGS_KEYS = {
@@ -101,4 +101,4 @@ export {
101
101
  deleteSetting,
102
102
  getAllSettings
103
103
  };
104
- //# sourceMappingURL=chunk-QNKXZH3Z.js.map
104
+ //# sourceMappingURL=chunk-YMFCFMMB.js.map