openfox 2.0.129 → 2.0.131

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 (113) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +2 -0
  3. package/dist/CHANGELOG.md +44 -0
  4. package/dist/auth-D3WLIBTG.js +19 -0
  5. package/dist/{auto-config-454YE6KC.js → auto-config-5VSNLVNI.js} +6 -5
  6. package/dist/{backend-4YPEC3J2.js → backend-NDBY3DAQ.js} +4 -2
  7. package/dist/{chat-handler-TH6JBO6G.js → chat-handler-RAIMQU7F.js} +35 -35
  8. package/dist/{chunk-ISE55FOR.js → chunk-2AI7VYPN.js} +11 -1
  9. package/dist/{chunk-HO7A7TMF.js → chunk-55DGZIZ6.js} +15 -5
  10. package/dist/{chunk-L24A6GZ7.js → chunk-5AI3LHRQ.js} +85 -57
  11. package/dist/{chunk-ZFNBATE3.js → chunk-6EZDW4JS.js} +3 -2
  12. package/dist/{chunk-ZXWJ6JTL.js → chunk-6MUSEPV7.js} +1197 -225
  13. package/dist/{chunk-OHTBWA7L.js → chunk-6SUBBT2M.js} +13 -13
  14. package/dist/{chunk-6LX43YRA.js → chunk-7ET46SNE.js} +4 -4
  15. package/dist/{chunk-GIJUWPRQ.js → chunk-7JVBDBXE.js} +2 -2
  16. package/dist/{chunk-MYNNMV75.js → chunk-7LGMQ5KS.js} +54 -36
  17. package/dist/{chunk-ZIL6VKLU.js → chunk-BKMWZTNO.js} +3 -3
  18. package/dist/chunk-BMBOSVRM.js +7 -0
  19. package/dist/{auth-GTGIGX5X.js → chunk-CQGJ5RWB.js} +4 -4
  20. package/dist/{chunk-3B232XG4.js → chunk-DPFET73G.js} +2 -2
  21. package/dist/chunk-DQTN4B33.js +235 -0
  22. package/dist/{chunk-KBESUA3W.js → chunk-ELYHHEYL.js} +3 -3
  23. package/dist/{chunk-DABWCAXS.js → chunk-EUOWCVU6.js} +19 -6
  24. package/dist/{chunk-YJD5A375.js → chunk-FGNJMKDV.js} +5 -5
  25. package/dist/{chunk-ATWOXI52.js → chunk-HCYSGLY2.js} +1 -1
  26. package/dist/{chunk-OYBUJIC3.js → chunk-JU757HVI.js} +5 -1
  27. package/dist/{chunk-AQBRI7TM.js → chunk-KWAHD2JA.js} +13 -8
  28. package/dist/{chunk-N2Q3KYWM.js → chunk-LQKXJPKP.js} +8 -3
  29. package/dist/{chunk-EHFIUXWZ.js → chunk-LW6MMSTD.js} +2 -2
  30. package/dist/{chunk-ZIYETXOW.js → chunk-M5T4RDPJ.js} +4 -4
  31. package/dist/{chunk-66MG44TF.js → chunk-MGEYAYGU.js} +2 -2
  32. package/dist/{chunk-RV5G7QQU.js → chunk-MQMPIXON.js} +3 -3
  33. package/dist/{chunk-K2QKX4ZJ.js → chunk-OA2FURC3.js} +8 -2
  34. package/dist/{chunk-567L5OJ6.js → chunk-P57IBMK4.js} +2 -2
  35. package/dist/{chunk-P6GTPKE5.js → chunk-QJG5K3X2.js} +278 -16
  36. package/dist/{chunk-2COZT3YI.js → chunk-RQPHGBWI.js} +24 -24
  37. package/dist/chunk-SVALN5KE.js +394 -0
  38. package/dist/{session-status-6Q5B5PEN.js → chunk-T3S5MTMD.js} +2 -3
  39. package/dist/{chunk-7YP4O4XE.js → chunk-TACWRDDC.js} +3 -3
  40. package/dist/{chunk-7ZMOP5LS.js → chunk-TS5WKTFB.js} +18 -1
  41. package/dist/{chunk-PBFGJFGC.js → chunk-UV6IH6HK.js} +32 -10
  42. package/dist/{chunk-7RIEI2TE.js → chunk-WCM5ZW5N.js} +52 -17
  43. package/dist/{chunk-Y3BSBKHY.js → chunk-XE6UC5Z3.js} +2 -2
  44. package/dist/{chunk-26WS7AH6.js → chunk-Y6ZGHOKM.js} +39 -7
  45. package/dist/chunk-YNMP647F.js +24 -0
  46. package/dist/{chunk-H6YIVK67.js → chunk-ZCFQOC3C.js} +26 -6
  47. package/dist/{chunk-IJFKJ5D6.js → chunk-ZL4IAFF3.js} +4 -4
  48. package/dist/{chunk-JQMQ4DGC.js → chunk-ZVHUISW7.js} +76 -32
  49. package/dist/cli/dev.js +1 -1
  50. package/dist/cli/index.js +1 -1
  51. package/dist/client-E6QLHPHD.js +16 -0
  52. package/dist/{client-pure-GU2SV3DD.js → client-pure-FLKP6PTI.js} +2 -2
  53. package/dist/compactor-OEJAA2YP.js +32 -0
  54. package/dist/dynamic-context-Y555VDLA.js +52 -0
  55. package/dist/{events-GMHRX4LF.js → events-ZJPRGVL2.js} +9 -9
  56. package/dist/{folding-7K2GRPF4.js → folding-QRZOHY2I.js} +7 -7
  57. package/dist/http-client-P4XTKAZA.js +11 -0
  58. package/dist/{inspect-proxy-UKPU3Z64.js → inspect-proxy-A3OROWPG.js} +4 -4
  59. package/dist/launch-Y4H7FDU2.js +53 -0
  60. package/dist/{manager-NOKJQTTF.js → manager-TMBFBCQL.js} +5 -5
  61. package/dist/mcp-YU7AM3UV.js +120 -0
  62. package/dist/{model-catalog-ZLOWTQA7.js → model-catalog-2PCKTYGW.js} +2 -2
  63. package/dist/{oauth-provider-DGBC2YM6.js → oauth-provider-VHUS2KEG.js} +8 -2
  64. package/dist/orchestrator-SQN2SJ2A.js +64 -0
  65. package/dist/package.json +1 -1
  66. package/dist/{path-security-UDZ7UVWK.js → path-security-CBACXAMS.js} +13 -13
  67. package/dist/{platform-EMKWQTZX.js → platform-5LQXOZO3.js} +4 -4
  68. package/dist/plugins-registry.json +12 -0
  69. package/dist/{processor-7RDR675X.js → processor-MEHODYNE.js} +34 -34
  70. package/dist/{profiles-HXGJIPF2.js → profiles-EBCVFYG7.js} +2 -2
  71. package/dist/{project-creator-JF3YVQAH.js → project-creator-6AGQTNXB.js} +3 -3
  72. package/dist/{projects-TPSLCJP2.js → projects-5U37RUTL.js} +3 -3
  73. package/dist/{protocol-DMneA8mx.d.ts → protocol-BMUoqwYH.d.ts} +2 -1
  74. package/dist/{protocol-TS3GVTT3.js → protocol-Y7MRKRUO.js} +3 -3
  75. package/dist/provider/index.d.ts +4 -4
  76. package/dist/{provider-DXEICEIE.js → provider-6YRII4IV.js} +11 -11
  77. package/dist/{provider-manager-PU7RS2TK.js → provider-manager-URNJBK5Q.js} +11 -11
  78. package/dist/{registry-Z4GVYFTV.js → registry-CMSSZHDC.js} +5 -5
  79. package/dist/{serve-Z5ITDPCQ.js → serve-NPADSJG7.js} +45 -43
  80. package/dist/server/index.d.ts +28 -4
  81. package/dist/server/index.js +42 -40
  82. package/dist/server-5TY22HDN.js +56 -0
  83. package/dist/service-VPXGREXF.js +27 -0
  84. package/dist/{session-overrides-4WAD3X5Q.js → session-overrides-OECQYRDK.js} +7 -7
  85. package/dist/session-status-UFO5IFI7.js +10 -0
  86. package/dist/{sessions-D7VRCHQY.js → sessions-NMPX5ICI.js} +6 -6
  87. package/dist/{settings-VOWWO4VG.js → settings-MDCRNQBY.js} +3 -3
  88. package/dist/shared/index.d.ts +3 -3
  89. package/dist/shared/index.js +1 -1
  90. package/dist/skill-defaults/browser/SKILL.md +20 -1
  91. package/dist/{tasks-SE3DOPVP.js → tasks-MNPXK2S5.js} +14 -14
  92. package/dist/{tools-6XUSIJN2.js → tools-6BDT5YMT.js} +37 -37
  93. package/dist/{types-PAKlAzp9.d.ts → types-BIkpxjaj.d.ts} +11 -2
  94. package/dist/{types-BWuVnaBw.d.ts → types-CoY8Ka1C.d.ts} +1 -1
  95. package/dist/{update-EJUI6PSV.js → update-XKCOBE47.js} +2 -2
  96. package/dist/web/assets/{index-CGKd7WLQ.js → index-Bx5r3aJx.js} +88 -88
  97. package/dist/web/assets/{index-CbX8veVW.css → index-Y300llHY.css} +1 -1
  98. package/dist/web/index.html +2 -2
  99. package/dist/web/sw.js +1 -1
  100. package/dist/{workspace-6CUE26YA.js → workspace-LM646OHC.js} +4 -4
  101. package/package.json +1 -1
  102. package/plugins-registry.json +12 -0
  103. package/dist/chunk-HIRDDCPD.js +0 -7
  104. package/dist/chunk-PHP7PLFX.js +0 -151
  105. package/dist/chunk-RSB4AR2A.js +0 -108
  106. package/dist/client-RZGGDGUA.js +0 -16
  107. package/dist/compactor-WKFNTUXL.js +0 -32
  108. package/dist/dynamic-context-ZVE733UI.js +0 -28
  109. package/dist/http-client-ROVNSHF6.js +0 -11
  110. package/dist/launch-5ARSU7EM.js +0 -53
  111. package/dist/orchestrator-E6GIZGEN.js +0 -64
  112. package/dist/server-MUJ7EHEI.js +0 -56
  113. package/dist/service-INQWTYY2.js +0 -27
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  getProjectByWorkdir,
6
6
  updateProject
7
- } from "./chunk-3B232XG4.js";
7
+ } from "./chunk-DPFET73G.js";
8
8
  import {
9
9
  logger
10
10
  } from "./chunk-K44MW7JJ.js";
@@ -347,4 +347,4 @@ export {
347
347
  deleteWorkspace,
348
348
  isGitRepository
349
349
  };
350
- //# sourceMappingURL=chunk-Y3BSBKHY.js.map
350
+ //# sourceMappingURL=chunk-XE6UC5Z3.js.map
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  getEventStore
3
- } from "./chunk-YJD5A375.js";
3
+ } from "./chunk-FGNJMKDV.js";
4
4
  import {
5
5
  createChatPathConfirmationMessage
6
- } from "./chunk-567L5OJ6.js";
6
+ } from "./chunk-P57IBMK4.js";
7
7
  import {
8
8
  getPlatformShell
9
- } from "./chunk-66MG44TF.js";
9
+ } from "./chunk-MGEYAYGU.js";
10
10
 
11
11
  // src/server/tools/path-security.ts
12
12
  import { realpath } from "fs/promises";
@@ -351,8 +351,39 @@ function resolveRelativeTraversals(command, workdir) {
351
351
  flush();
352
352
  return [...new Set(out)];
353
353
  }
354
+ function maskHeredocs(command) {
355
+ if (!command.includes("<<")) return command;
356
+ const lines = command.split("\n");
357
+ const starts = [];
358
+ for (let i = 0; i < lines.length; i++) {
359
+ const m = lines[i].match(/<<\s*(-?)(['"]?)([A-Za-z_][A-Za-z0-9_]*)\2/);
360
+ if (m) {
361
+ starts.push({ line: i, delimiter: m[3], stripTabs: m[1] === "-" });
362
+ }
363
+ }
364
+ const maskSpans = [];
365
+ let searchFrom = 0;
366
+ for (const start of starts) {
367
+ if (start.line < searchFrom) continue;
368
+ let end = -1;
369
+ for (let j = start.line + 1; j < lines.length; j++) {
370
+ const candidate = start.stripTabs ? lines[j].replace(/^\t+/, "") : lines[j];
371
+ if (candidate === start.delimiter) {
372
+ end = j;
373
+ break;
374
+ }
375
+ }
376
+ if (end !== -1) {
377
+ maskSpans.push([start.line + 1, end]);
378
+ searchFrom = end + 1;
379
+ }
380
+ }
381
+ if (maskSpans.length === 0) return command;
382
+ return lines.map((line, idx) => maskSpans.some(([s, e]) => idx >= s && idx < e) ? " ".repeat(line.length) : line).join("\n");
383
+ }
354
384
  function maskCommandForPathScan(command) {
355
- let sanitized = command.replace(/https?:\/\/[^\s'"]+/g, " __URL__ ").replace(/ftp:\/\/[^\s'"]+/g, " __URL__ ");
385
+ let sanitized = maskHeredocs(command);
386
+ sanitized = sanitized.replace(/https?:\/\/[^\s'"]+/g, " __URL__ ").replace(/ftp:\/\/[^\s'"]+/g, " __URL__ ");
356
387
  sanitized = sanitized.replace(/(?<!\w)s\/[^/]*\/[^/]*\/[gip]*/g, " __SED__ ");
357
388
  sanitized = sanitized.replace(/(?<!\w)s\|[^|]*\|[^|]*\|[gip]*/g, " __SED__ ");
358
389
  sanitized = sanitized.replace(/(?<!\w)s:[^:]*:[^:]*:[gip]*/g, " __SED__ ");
@@ -446,15 +477,16 @@ function extractSensitivePathsFromCommand(command) {
446
477
  return [];
447
478
  }
448
479
  const paths = [];
480
+ const scanCommand = maskHeredocs(command);
449
481
  const quotedPattern = /["']([^"']+)["']/g;
450
482
  let match;
451
- while ((match = quotedPattern.exec(command)) !== null) {
483
+ while ((match = quotedPattern.exec(scanCommand)) !== null) {
452
484
  const content = match[1];
453
485
  if (isSensitivePath(content)) {
454
486
  paths.push(content);
455
487
  }
456
488
  }
457
- const unquoted = command.replace(/["'][^"']*["']/g, " ").replace(/[|&;><]/g, " ");
489
+ const unquoted = scanCommand.replace(/["'][^"']*["']/g, " ").replace(/[|&;><]/g, " ");
458
490
  const tokens = unquoted.split(/\s+/).filter(Boolean);
459
491
  for (const token of tokens) {
460
492
  if (token.startsWith("-")) continue;
@@ -750,4 +782,4 @@ export {
750
782
  getConfirmationSessionId,
751
783
  getPendingConfirmationsBySession
752
784
  };
753
- //# sourceMappingURL=chunk-26WS7AH6.js.map
785
+ //# sourceMappingURL=chunk-Y6ZGHOKM.js.map
@@ -0,0 +1,24 @@
1
+ // src/server/mcp/server/bootstrap.ts
2
+ var WILDCARD_HOSTS = /* @__PURE__ */ new Set(["0.0.0.0", "::", "*"]);
3
+ function normalizeHost(host) {
4
+ return WILDCARD_HOSTS.has(host) ? "127.0.0.1" : host;
5
+ }
6
+ function buildOpenFoxMcpBootstrap(input) {
7
+ if (input.authRequired && !input.sessionToken) {
8
+ throw new Error("Session token could not be computed \u2014 cannot bootstrap an authenticated MCP endpoint");
9
+ }
10
+ const config = {
11
+ name: "openfox",
12
+ transport: "http",
13
+ url: `http://${normalizeHost(input.host)}:${input.port}/mcp`
14
+ };
15
+ if (input.authRequired && input.sessionToken) {
16
+ config.headers = { Authorization: `Bearer ${input.sessionToken}` };
17
+ }
18
+ return config;
19
+ }
20
+
21
+ export {
22
+ buildOpenFoxMcpBootstrap
23
+ };
24
+ //# sourceMappingURL=chunk-YNMP647F.js.map
@@ -1,6 +1,3 @@
1
- import {
2
- parseDefaultModelSelection
3
- } from "./chunk-JQMQ4DGC.js";
4
1
  import {
5
2
  deleteItemFromDir,
6
3
  getDefaultIds,
@@ -9,12 +6,15 @@ import {
9
6
  pathExists,
10
7
  saveItemToDir
11
8
  } from "./chunk-OSXPQSLW.js";
9
+ import {
10
+ parseDefaultModelSelection
11
+ } from "./chunk-ZVHUISW7.js";
12
12
  import {
13
13
  getProject
14
- } from "./chunk-3B232XG4.js";
14
+ } from "./chunk-DPFET73G.js";
15
15
  import {
16
16
  getDatabase
17
- } from "./chunk-OYBUJIC3.js";
17
+ } from "./chunk-JU757HVI.js";
18
18
  import {
19
19
  logger
20
20
  } from "./chunk-K44MW7JJ.js";
@@ -212,6 +212,25 @@ async function loadAllWorkflows(configDir, projectDir) {
212
212
  }
213
213
  return Array.from(workflowMap.values());
214
214
  }
215
+ async function listAvailableWorkflows(configDir, projectDir) {
216
+ const [defaultWorkflows, userWorkflows, projectWorkflows] = await Promise.all([
217
+ loadDefaultWorkflows(),
218
+ loadUserWorkflows(configDir),
219
+ projectDir ? loadProjectWorkflows(projectDir) : Promise.resolve([])
220
+ ]);
221
+ const projectIds = new Set(projectWorkflows.map((w) => w.metadata.id));
222
+ const userIds = new Set(userWorkflows.map((w) => w.metadata.id));
223
+ const effective = [...defaultWorkflows, ...userWorkflows, ...projectWorkflows];
224
+ const byId = new Map(effective.map((w) => [w.metadata.id, w]));
225
+ return Array.from(byId.values()).map((workflow) => ({
226
+ id: workflow.metadata.id,
227
+ name: workflow.metadata.name,
228
+ description: workflow.metadata.description,
229
+ ...workflow.metadata.color ? { color: workflow.metadata.color } : {},
230
+ scope: projectIds.has(workflow.metadata.id) ? "project" : userIds.has(workflow.metadata.id) ? "user" : "builtin",
231
+ ...workflow.metadata.parameters ? { parameters: workflow.metadata.parameters } : {}
232
+ }));
233
+ }
215
234
  async function saveWorkflowToProject(projectDir, workflow) {
216
235
  await saveItemToDir(getProjectWorkflowsDir(projectDir), workflow, WORKFLOW_EXTENSION, jsonSerializer);
217
236
  }
@@ -1085,6 +1104,7 @@ export {
1085
1104
  loadUserWorkflows,
1086
1105
  loadProjectWorkflows,
1087
1106
  loadAllWorkflows,
1107
+ listAvailableWorkflows,
1088
1108
  saveWorkflowToProject,
1089
1109
  deleteProjectWorkflow,
1090
1110
  getDefaultWorkflowIds,
@@ -1099,4 +1119,4 @@ export {
1099
1119
  isTaskGateError,
1100
1120
  createTasksService
1101
1121
  };
1102
- //# sourceMappingURL=chunk-H6YIVK67.js.map
1122
+ //# sourceMappingURL=chunk-ZCFQOC3C.js.map
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  createMessageStartEvent
3
- } from "./chunk-6LX43YRA.js";
3
+ } from "./chunk-7ET46SNE.js";
4
4
  import {
5
5
  COMPACTION_PROMPT
6
- } from "./chunk-GIJUWPRQ.js";
6
+ } from "./chunk-7JVBDBXE.js";
7
7
  import {
8
8
  getCurrentWindowMessageOptions
9
- } from "./chunk-YJD5A375.js";
9
+ } from "./chunk-FGNJMKDV.js";
10
10
 
11
11
  // src/server/context/compactor.ts
12
12
  function appendCompactionPrompt(sessionId, append) {
@@ -36,4 +36,4 @@ export {
36
36
  COMPACTION_MAX_RATIO,
37
37
  shouldCompact
38
38
  };
39
- //# sourceMappingURL=chunk-IJFKJ5D6.js.map
39
+ //# sourceMappingURL=chunk-ZL4IAFF3.js.map
@@ -1,15 +1,17 @@
1
1
  import {
2
+ hasVisionEvidence,
2
3
  parseLmStudioModels
3
- } from "./chunk-K2QKX4ZJ.js";
4
+ } from "./chunk-OA2FURC3.js";
4
5
  import {
5
6
  createLLMClient
6
- } from "./chunk-P6GTPKE5.js";
7
+ } from "./chunk-QJG5K3X2.js";
7
8
  import {
8
9
  getModelProfile
9
- } from "./chunk-7ZMOP5LS.js";
10
+ } from "./chunk-TS5WKTFB.js";
10
11
  import {
12
+ detectBackendFromUrl,
11
13
  getBackendCapabilities
12
- } from "./chunk-PBFGJFGC.js";
14
+ } from "./chunk-UV6IH6HK.js";
13
15
  import {
14
16
  buildModelsUrl,
15
17
  ensureVersionPrefix,
@@ -17,11 +19,12 @@ import {
17
19
  } from "./chunk-HNCM3D7Y.js";
18
20
  import {
19
21
  resolveAttachmentsInMessages
20
- } from "./chunk-DABWCAXS.js";
22
+ } from "./chunk-EUOWCVU6.js";
21
23
  import {
22
24
  getCatalogEntry,
23
- resolveEffortForModel
24
- } from "./chunk-ISE55FOR.js";
25
+ resolveEffortForModel,
26
+ resolveModeModelId
27
+ } from "./chunk-2AI7VYPN.js";
25
28
  import {
26
29
  logger
27
30
  } from "./chunk-K44MW7JJ.js";
@@ -45,11 +48,12 @@ function createTransportLLMClient(provider, modelId, transport, reasoningEffort)
45
48
  };
46
49
  let profile = profileFor(model);
47
50
  void getBackendCapabilities(backend);
48
- const context = () => {
51
+ const context = (resolvedEffort) => {
49
52
  const configured = provider.models.find((item) => item.id === model);
53
+ const send = resolveModeModelId(configured?.modes, resolvedEffort, configured?.apiModelId, model);
50
54
  return {
51
55
  providerId: provider.id,
52
- model: configured?.apiModelId ?? model,
56
+ model: send.modelId,
53
57
  catalogModel: model,
54
58
  ...configured?.requestBody && { requestBody: configured.requestBody },
55
59
  ...provider.credentialRef && { credentialRef: provider.credentialRef }
@@ -69,10 +73,15 @@ function createTransportLLMClient(provider, modelId, transport, reasoningEffort)
69
73
  const resolveRequest = async (request) => {
70
74
  const supportsVision = request.modelSettings?.supportsVision ?? profile.supportsVision ?? false;
71
75
  const resolvedEffort = resolveEffort(request);
76
+ const configured = provider.models.find((item) => item.id === model);
77
+ const send = resolveModeModelId(configured?.modes, resolvedEffort, configured?.apiModelId, model);
72
78
  return {
73
- ...request,
74
- messages: await resolveAttachmentsInMessages(request.messages, supportsVision),
75
- ...resolvedEffort ? { reasoningEffort: resolvedEffort } : {}
79
+ request: {
80
+ ...request,
81
+ messages: await resolveAttachmentsInMessages(request.messages, supportsVision),
82
+ ...resolvedEffort && !send.suppressEffort ? { reasoningEffort: resolvedEffort } : {}
83
+ },
84
+ effort: resolvedEffort
76
85
  };
77
86
  };
78
87
  return {
@@ -87,9 +96,13 @@ function createTransportLLMClient(provider, modelId, transport, reasoningEffort)
87
96
  backend = next;
88
97
  },
89
98
  getReasoningEffort: () => resolveEffort({}),
90
- complete: async (request) => transport.complete(await resolveRequest(request), context()),
99
+ complete: async (request) => {
100
+ const resolved = await resolveRequest(request);
101
+ return transport.complete(resolved.request, context(resolved.effort));
102
+ },
91
103
  stream: async function* (request) {
92
- yield* transport.stream(await resolveRequest(request), context());
104
+ const resolved = await resolveRequest(request);
105
+ yield* transport.stream(resolved.request, context(resolved.effort));
93
106
  }
94
107
  };
95
108
  }
@@ -213,7 +226,8 @@ async function fetchModelsFromBackend(url, apiKey) {
213
226
  if (data.data && Array.isArray(data.data)) {
214
227
  return data.data.map((m) => ({
215
228
  id: m.id,
216
- contextWindow: m.max_model_len ?? void 0
229
+ contextWindow: m.max_model_len ?? m.context_length ?? void 0,
230
+ supportsVision: m.capabilities?.vision || m.input_modalities?.includes("image") ? true : void 0
217
231
  }));
218
232
  }
219
233
  return [];
@@ -226,6 +240,10 @@ function enrichWithProfileDefaults(model) {
226
240
  const profile = getModelProfile(model.id);
227
241
  return {
228
242
  ...model,
243
+ // Only fill supportsVision from the profile when the model lacks it —
244
+ // a backend-detected value (e.g. Ollama /api/show, a transport plugin's
245
+ // listModels) must win over the static profile default.
246
+ ...model.supportsVision !== void 0 ? {} : profile.supportsVision !== void 0 ? { supportsVision: profile.supportsVision } : {},
229
247
  defaultTemperature: profile.temperature,
230
248
  defaultTopP: profile.topP,
231
249
  ...profile.topK !== void 0 && { defaultTopK: profile.topK },
@@ -244,7 +262,15 @@ function enrichWithCatalogDefaults(model) {
244
262
  }
245
263
  function mergeModelsWithUserOverrides(backendModels, userModels, preserveMissingUserModels = true) {
246
264
  const normalizedUserIdMap = new Map(userModels.map((m) => [normalizeModelId(m.id), m]));
247
- const updatedModels = backendModels.map((backendModel) => {
265
+ const claimedByMergedModes = /* @__PURE__ */ new Set();
266
+ for (const userModel of userModels) {
267
+ if (!userModel.modes?.length) continue;
268
+ for (const mode of userModel.modes) {
269
+ if (mode.apiModelId) claimedByMergedModes.add(normalizeModelId(mode.apiModelId));
270
+ }
271
+ }
272
+ const filteredBackendModels = backendModels.filter((m) => !claimedByMergedModes.has(normalizeModelId(m.id)));
273
+ const updatedModels = filteredBackendModels.map((backendModel) => {
248
274
  const existingUserModel = normalizedUserIdMap.get(normalizeModelId(backendModel.id));
249
275
  if (existingUserModel) {
250
276
  return enrichWithProfileDefaults({ ...backendModel, ...existingUserModel, id: backendModel.id });
@@ -252,7 +278,7 @@ function mergeModelsWithUserOverrides(backendModels, userModels, preserveMissing
252
278
  return enrichWithProfileDefaults(backendModel);
253
279
  });
254
280
  if (preserveMissingUserModels) {
255
- const normalizedBackendIds = new Set(backendModels.map((m) => normalizeModelId(m.id)));
281
+ const normalizedBackendIds = new Set(filteredBackendModels.map((m) => normalizeModelId(m.id)));
256
282
  for (const userModel of userModels) {
257
283
  if (!normalizedBackendIds.has(normalizeModelId(userModel.id))) {
258
284
  updatedModels.push(enrichWithProfileDefaults(userModel));
@@ -286,6 +312,7 @@ async function fetchModelsWithContext(baseUrl, apiKey, backend) {
286
312
  return models.map((m) => ({
287
313
  id: m.id,
288
314
  contextWindow: m.contextWindow ?? 2e5,
315
+ ...m.supportsVision !== void 0 && { supportsVision: m.supportsVision },
289
316
  source: m.contextWindow ? "backend" : "default"
290
317
  }));
291
318
  }
@@ -315,10 +342,13 @@ async function fetchOllamaModelsWithContext(baseUrl, _apiKey) {
315
342
  });
316
343
  if (showResponse.ok) {
317
344
  const showData = await showResponse.json();
318
- const contextLength = showData.model_info?.llama?.context_length ?? showData.model_info?.context_length ?? 2e5;
345
+ const mi = showData.model_info;
346
+ const contextLength = mi?.llama?.context_length ?? mi?.context_length ?? 2e5;
347
+ const isVisionModel = hasVisionEvidence(mi ?? {});
319
348
  modelsWithContext.push({
320
349
  id: model.name,
321
350
  contextWindow: contextLength,
351
+ ...isVisionModel ? { supportsVision: true } : {},
322
352
  source: contextLength !== 2e5 ? "backend" : "default"
323
353
  });
324
354
  } else {
@@ -421,20 +451,31 @@ function createProviderManager(config, options = {}) {
421
451
  }
422
452
  function createConfigForProvider(provider, model, reasoningEffort) {
423
453
  const modelThinking = resolveModelThinkingConfig(provider, model, reasoningEffort);
454
+ const configureModel = provider.models.find((m) => m.id === model);
455
+ const send = resolveModeModelId(
456
+ configureModel?.modes,
457
+ modelThinking.reasoningEffort,
458
+ configureModel?.apiModelId,
459
+ model
460
+ );
424
461
  return {
425
462
  ...config,
426
463
  llm: {
427
464
  ...config.llm,
428
465
  baseUrl: ensureVersionPrefix(provider.url),
429
- model,
430
- backend: provider.backend,
466
+ model: send.modelId,
467
+ backend: resolveBackend(provider),
431
468
  ...provider.apiKey && { apiKey: provider.apiKey },
432
469
  ...provider.thinkingField && { thinkingField: provider.thinkingField },
433
470
  ...provider.sendReasoningInMessages !== void 0 ? { sendReasoningInMessages: provider.sendReasoningInMessages } : {},
434
- ...modelThinking.reasoningEffort && { reasoningEffort: modelThinking.reasoningEffort }
471
+ ...modelThinking.reasoningEffort && !send.suppressEffort && { reasoningEffort: modelThinking.reasoningEffort }
435
472
  }
436
473
  };
437
474
  }
475
+ function resolveBackend(provider) {
476
+ if (provider.backend !== "unknown") return provider.backend;
477
+ return detectBackendFromUrl(provider.url) ?? "unknown";
478
+ }
438
479
  function resolveTransportAdapter(provider) {
439
480
  if (provider.transportAdapter) return provider.transportAdapter;
440
481
  return void 0;
@@ -456,10 +497,7 @@ function createProviderManager(config, options = {}) {
456
497
  function createClientForProvider(provider, model, reasoningEffort) {
457
498
  const resolvedModel = resolveProviderModel(provider, model);
458
499
  const transport = options.adapters?.getTransport(resolveTransportAdapter(provider));
459
- return transport ? createTransportLLMClient(provider, resolvedModel, transport, reasoningEffort) : createLLMClient(
460
- createConfigForProvider(provider, resolvedModel, reasoningEffort),
461
- provider.backend
462
- );
500
+ return transport ? createTransportLLMClient(provider, resolvedModel, transport, reasoningEffort) : createLLMClient(createConfigForProvider(provider, resolvedModel, reasoningEffort), resolveBackend(provider));
463
501
  }
464
502
  async function fetchProviderModels(provider) {
465
503
  const transport = options.adapters?.getTransport(resolveTransportAdapter(provider));
@@ -469,7 +507,7 @@ function createProviderManager(config, options = {}) {
469
507
  ...provider.credentialRef && { credentialRef: provider.credentialRef }
470
508
  });
471
509
  }
472
- const backend = provider.backend;
510
+ const backend = resolveBackend(provider);
473
511
  return fetchModelsWithContext(provider.url, provider.apiKey, backend);
474
512
  }
475
513
  const { providerId: activeProviderId, model: activeModel } = parseDefaultModelSelection(defaultModelSelection);
@@ -727,6 +765,9 @@ function createProviderManager(config, options = {}) {
727
765
  id: modelId,
728
766
  contextWindow: settings.contextWindow ?? existingModel?.contextWindow ?? 2e5,
729
767
  source: "user",
768
+ ...existingModel?.name !== void 0 && { name: existingModel.name },
769
+ ...existingModel?.apiModelId !== void 0 && { apiModelId: existingModel.apiModelId },
770
+ ...existingModel?.modes !== void 0 && { modes: existingModel.modes },
730
771
  ...finalTemp !== void 0 && { temperature: finalTemp },
731
772
  ...finalTopP !== void 0 && { topP: finalTopP },
732
773
  ...finalTopK !== void 0 && { topK: finalTopK },
@@ -756,7 +797,7 @@ function createProviderManager(config, options = {}) {
756
797
  getModelSettings(providerId, modelId, mode = "thinking") {
757
798
  const provider = providers.find((p) => p.id === providerId);
758
799
  const model = provider?.models.find((m) => m.id === modelId);
759
- if (!model) return void 0;
800
+ if (!provider || !model) return void 0;
760
801
  const baseSettings = {};
761
802
  if (model["temperature"] !== void 0) baseSettings["temperature"] = model["temperature"];
762
803
  if (model["topP"] !== void 0) baseSettings["topP"] = model["topP"];
@@ -772,10 +813,13 @@ function createProviderManager(config, options = {}) {
772
813
  }
773
814
  const modeEnabled = mode === "thinking" ? model.thinkingEnabled : model.nonThinkingEnabled;
774
815
  if (modeEnabled) {
775
- return {
776
- ...baseSettings,
777
- chatTemplateKwargs: mode === "thinking" ? { enable_thinking: true } : { enable_thinking: false }
778
- };
816
+ const capabilities = getBackendCapabilities(resolveBackend(provider));
817
+ if (capabilities.supportsChatTemplateKwargs) {
818
+ return {
819
+ ...baseSettings,
820
+ chatTemplateKwargs: mode === "thinking" ? { enable_thinking: true } : { enable_thinking: false }
821
+ };
822
+ }
779
823
  }
780
824
  const fallbackRawQP = mode === "thinking" ? model.nonThinkingQueryParams : model.thinkingQueryParams;
781
825
  if (fallbackRawQP) {
@@ -851,4 +895,4 @@ export {
851
895
  parseDefaultModelSelection,
852
896
  createProviderManager
853
897
  };
854
- //# sourceMappingURL=chunk-JQMQ4DGC.js.map
898
+ //# sourceMappingURL=chunk-ZVHUISW7.js.map
package/dist/cli/dev.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runCli
4
- } from "../chunk-HO7A7TMF.js";
4
+ } from "../chunk-55DGZIZ6.js";
5
5
  import "../chunk-AGXJ5O63.js";
6
6
  import {
7
7
  logger
package/dist/cli/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runCli
4
- } from "../chunk-HO7A7TMF.js";
4
+ } from "../chunk-55DGZIZ6.js";
5
5
  import "../chunk-AGXJ5O63.js";
6
6
  import {
7
7
  logger
@@ -0,0 +1,16 @@
1
+ import {
2
+ createLLMClient
3
+ } from "./chunk-QJG5K3X2.js";
4
+ import "./chunk-TS5WKTFB.js";
5
+ import "./chunk-UV6IH6HK.js";
6
+ import "./chunk-HNCM3D7Y.js";
7
+ import "./chunk-EUOWCVU6.js";
8
+ import "./chunk-6EZDW4JS.js";
9
+ import "./chunk-LQKXJPKP.js";
10
+ import "./chunk-JU757HVI.js";
11
+ import "./chunk-K44MW7JJ.js";
12
+ import "./chunk-YLJ4XMA6.js";
13
+ export {
14
+ createLLMClient
15
+ };
16
+ //# sourceMappingURL=client-E6QLHPHD.js.map
@@ -8,7 +8,7 @@ import {
8
8
  mapFinishReason,
9
9
  parseToolArguments,
10
10
  resolveAttachmentsInMessages
11
- } from "./chunk-DABWCAXS.js";
11
+ } from "./chunk-EUOWCVU6.js";
12
12
  import "./chunk-YLJ4XMA6.js";
13
13
  export {
14
14
  buildModelParams,
@@ -21,4 +21,4 @@ export {
21
21
  parseToolArguments,
22
22
  resolveAttachmentsInMessages
23
23
  };
24
- //# sourceMappingURL=client-pure-GU2SV3DD.js.map
24
+ //# sourceMappingURL=client-pure-FLKP6PTI.js.map
@@ -0,0 +1,32 @@
1
+ import {
2
+ COMPACTION_HEADROOM_TOKENS,
3
+ COMPACTION_MAX_RATIO,
4
+ appendCompactionPrompt,
5
+ shouldCompact
6
+ } from "./chunk-ZL4IAFF3.js";
7
+ import "./chunk-7ET46SNE.js";
8
+ import "./chunk-7JVBDBXE.js";
9
+ import "./chunk-FGNJMKDV.js";
10
+ import "./chunk-M5T4RDPJ.js";
11
+ import "./chunk-KWAHD2JA.js";
12
+ import "./chunk-ELYHHEYL.js";
13
+ import "./chunk-OSXPQSLW.js";
14
+ import "./chunk-LCLH6ZUL.js";
15
+ import "./chunk-MGEYAYGU.js";
16
+ import "./chunk-J2GP3J3X.js";
17
+ import "./chunk-DPFET73G.js";
18
+ import "./chunk-TS5WKTFB.js";
19
+ import "./chunk-UV6IH6HK.js";
20
+ import "./chunk-EUOWCVU6.js";
21
+ import "./chunk-LQKXJPKP.js";
22
+ import "./chunk-JU757HVI.js";
23
+ import "./chunk-K44MW7JJ.js";
24
+ import "./chunk-CQGTEGKL.js";
25
+ import "./chunk-YLJ4XMA6.js";
26
+ export {
27
+ COMPACTION_HEADROOM_TOKENS,
28
+ COMPACTION_MAX_RATIO,
29
+ appendCompactionPrompt,
30
+ shouldCompact
31
+ };
32
+ //# sourceMappingURL=compactor-OEJAA2YP.js.map
@@ -0,0 +1,52 @@
1
+ import {
2
+ applyDynamicContext,
3
+ buildCachedPrompt,
4
+ checkToolChangesAndInject,
5
+ computeDynamicContextHash,
6
+ computePreviewToolDiff,
7
+ computeSessionHash,
8
+ computeToolDiff,
9
+ computeUnifiedDiff,
10
+ detectToolChanges,
11
+ getToolFingerprint,
12
+ getToolSetFingerprint,
13
+ getToolSignature,
14
+ injectContextDriftReminders,
15
+ injectContextDriftRemindersForSessions,
16
+ renderSystemPromptDiff,
17
+ renderToolChangeReminder
18
+ } from "./chunk-SVALN5KE.js";
19
+ import "./chunk-BKMWZTNO.js";
20
+ import "./chunk-7JVBDBXE.js";
21
+ import "./chunk-FGNJMKDV.js";
22
+ import "./chunk-M5T4RDPJ.js";
23
+ import "./chunk-KWAHD2JA.js";
24
+ import "./chunk-ELYHHEYL.js";
25
+ import "./chunk-OSXPQSLW.js";
26
+ import "./chunk-LCLH6ZUL.js";
27
+ import "./chunk-MGEYAYGU.js";
28
+ import "./chunk-DPFET73G.js";
29
+ import "./chunk-LQKXJPKP.js";
30
+ import "./chunk-JU757HVI.js";
31
+ import "./chunk-K44MW7JJ.js";
32
+ import "./chunk-CQGTEGKL.js";
33
+ import "./chunk-YLJ4XMA6.js";
34
+ export {
35
+ applyDynamicContext,
36
+ buildCachedPrompt,
37
+ checkToolChangesAndInject,
38
+ computeDynamicContextHash,
39
+ computePreviewToolDiff,
40
+ computeSessionHash,
41
+ computeToolDiff,
42
+ computeUnifiedDiff,
43
+ detectToolChanges,
44
+ getToolFingerprint,
45
+ getToolSetFingerprint,
46
+ getToolSignature,
47
+ injectContextDriftReminders,
48
+ injectContextDriftRemindersForSessions,
49
+ renderSystemPromptDiff,
50
+ renderToolChangeReminder
51
+ };
52
+ //# sourceMappingURL=dynamic-context-Y555VDLA.js.map
@@ -40,7 +40,7 @@ import {
40
40
  isStoredEvent,
41
41
  isTurnEvent,
42
42
  truncateSessionMessages
43
- } from "./chunk-YJD5A375.js";
43
+ } from "./chunk-FGNJMKDV.js";
44
44
  import {
45
45
  buildContextMessagesFromEventHistory,
46
46
  buildContextMessagesFromMessages,
@@ -57,14 +57,14 @@ import {
57
57
  foldTodos,
58
58
  foldTurnEventsToSnapshotMessages,
59
59
  getMessagesForWindow
60
- } from "./chunk-ZIYETXOW.js";
61
- import "./chunk-AQBRI7TM.js";
62
- import "./chunk-LCLH6ZUL.js";
63
- import "./chunk-KBESUA3W.js";
60
+ } from "./chunk-M5T4RDPJ.js";
61
+ import "./chunk-KWAHD2JA.js";
62
+ import "./chunk-ELYHHEYL.js";
64
63
  import "./chunk-OSXPQSLW.js";
65
- import "./chunk-3B232XG4.js";
66
- import "./chunk-N2Q3KYWM.js";
67
- import "./chunk-OYBUJIC3.js";
64
+ import "./chunk-LCLH6ZUL.js";
65
+ import "./chunk-DPFET73G.js";
66
+ import "./chunk-LQKXJPKP.js";
67
+ import "./chunk-JU757HVI.js";
68
68
  import "./chunk-K44MW7JJ.js";
69
69
  import "./chunk-CQGTEGKL.js";
70
70
  import "./chunk-YLJ4XMA6.js";
@@ -126,4 +126,4 @@ export {
126
126
  isTurnEvent,
127
127
  truncateSessionMessages
128
128
  };
129
- //# sourceMappingURL=events-GMHRX4LF.js.map
129
+ //# sourceMappingURL=events-ZJPRGVL2.js.map
@@ -26,13 +26,13 @@ import {
26
26
  spreadOptionalMessageFields,
27
27
  stripOrphanedToolCalls,
28
28
  trimSnapshotStreamingOutput
29
- } from "./chunk-ZIYETXOW.js";
30
- import "./chunk-LCLH6ZUL.js";
31
- import "./chunk-KBESUA3W.js";
29
+ } from "./chunk-M5T4RDPJ.js";
30
+ import "./chunk-ELYHHEYL.js";
32
31
  import "./chunk-OSXPQSLW.js";
33
- import "./chunk-3B232XG4.js";
34
- import "./chunk-N2Q3KYWM.js";
35
- import "./chunk-OYBUJIC3.js";
32
+ import "./chunk-LCLH6ZUL.js";
33
+ import "./chunk-DPFET73G.js";
34
+ import "./chunk-LQKXJPKP.js";
35
+ import "./chunk-JU757HVI.js";
36
36
  import "./chunk-K44MW7JJ.js";
37
37
  import "./chunk-CQGTEGKL.js";
38
38
  import "./chunk-YLJ4XMA6.js";
@@ -65,4 +65,4 @@ export {
65
65
  stripOrphanedToolCalls,
66
66
  trimSnapshotStreamingOutput
67
67
  };
68
- //# sourceMappingURL=folding-7K2GRPF4.js.map
68
+ //# sourceMappingURL=folding-QRZOHY2I.js.map