openfox 2.0.129 → 2.0.130

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 (101) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +2 -0
  3. package/dist/CHANGELOG.md +32 -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-4WCKNCQV.js} +32 -32
  8. package/dist/chunk-25DAVVTP.js +395 -0
  9. package/dist/{chunk-ISE55FOR.js → chunk-2AI7VYPN.js} +11 -1
  10. package/dist/{chunk-2COZT3YI.js → chunk-2OMXXCJJ.js} +24 -24
  11. package/dist/{chunk-OHTBWA7L.js → chunk-35GQEIH2.js} +13 -13
  12. package/dist/{chunk-N2Q3KYWM.js → chunk-3DZSHRXE.js} +7 -2
  13. package/dist/chunk-3OBZ55SX.js +7 -0
  14. package/dist/{chunk-ZIL6VKLU.js → chunk-64N4CZFT.js} +2 -2
  15. package/dist/{chunk-66MG44TF.js → chunk-6QZVAOSA.js} +2 -2
  16. package/dist/{chunk-6LX43YRA.js → chunk-7ET46SNE.js} +4 -4
  17. package/dist/{chunk-YJD5A375.js → chunk-AYCB32NI.js} +5 -5
  18. package/dist/{chunk-GIJUWPRQ.js → chunk-CGCEAKG5.js} +2 -2
  19. package/dist/{auth-GTGIGX5X.js → chunk-CQGJ5RWB.js} +4 -4
  20. package/dist/{chunk-JQMQ4DGC.js → chunk-CYQUM42E.js} +76 -32
  21. package/dist/{chunk-P6GTPKE5.js → chunk-DHDIKVRT.js} +278 -16
  22. package/dist/{chunk-ZXWJ6JTL.js → chunk-DI5GTIAU.js} +1154 -196
  23. package/dist/chunk-DQTN4B33.js +235 -0
  24. package/dist/{chunk-RV5G7QQU.js → chunk-DQTXXHD2.js} +3 -3
  25. package/dist/{chunk-MYNNMV75.js → chunk-DYIDDGMN.js} +54 -36
  26. package/dist/{chunk-DABWCAXS.js → chunk-EUOWCVU6.js} +19 -6
  27. package/dist/{chunk-7RIEI2TE.js → chunk-EVVWDRM5.js} +45 -16
  28. package/dist/{chunk-ATWOXI52.js → chunk-HCYSGLY2.js} +1 -1
  29. package/dist/{chunk-KBESUA3W.js → chunk-JHA2SPCU.js} +2 -2
  30. package/dist/{chunk-ZIYETXOW.js → chunk-JKRMMNUR.js} +4 -4
  31. package/dist/{chunk-H6YIVK67.js → chunk-JSONBGSY.js} +24 -4
  32. package/dist/{chunk-HO7A7TMF.js → chunk-KHKRHGA6.js} +15 -5
  33. package/dist/{chunk-K2QKX4ZJ.js → chunk-OA2FURC3.js} +8 -2
  34. package/dist/{chunk-ZFNBATE3.js → chunk-OXMOKQPW.js} +3 -2
  35. package/dist/{chunk-567L5OJ6.js → chunk-P57IBMK4.js} +2 -2
  36. package/dist/{session-status-6Q5B5PEN.js → chunk-T3S5MTMD.js} +2 -3
  37. package/dist/{chunk-7ZMOP5LS.js → chunk-TS5WKTFB.js} +18 -1
  38. package/dist/{chunk-PBFGJFGC.js → chunk-UV6IH6HK.js} +32 -10
  39. package/dist/{chunk-26WS7AH6.js → chunk-VJNA5AOB.js} +39 -7
  40. package/dist/{chunk-IJFKJ5D6.js → chunk-VUIXQ6X4.js} +4 -4
  41. package/dist/{chunk-L24A6GZ7.js → chunk-X24XN2M2.js} +84 -56
  42. package/dist/{chunk-AQBRI7TM.js → chunk-X3FHIDLT.js} +2 -2
  43. package/dist/chunk-YNMP647F.js +24 -0
  44. package/dist/{chunk-7YP4O4XE.js → chunk-ZRCRGPGT.js} +2 -2
  45. package/dist/cli/dev.js +1 -1
  46. package/dist/cli/index.js +1 -1
  47. package/dist/client-26RSMUAX.js +16 -0
  48. package/dist/{client-pure-GU2SV3DD.js → client-pure-FLKP6PTI.js} +2 -2
  49. package/dist/{compactor-WKFNTUXL.js → compactor-HYBSSFKP.js} +14 -14
  50. package/dist/dynamic-context-2VLACYK4.js +50 -0
  51. package/dist/{events-GMHRX4LF.js → events-D33QXGSX.js} +7 -7
  52. package/dist/{folding-7K2GRPF4.js → folding-QOKBKUU6.js} +5 -5
  53. package/dist/{http-client-ROVNSHF6.js → http-client-MGAJTGPR.js} +3 -3
  54. package/dist/launch-KFENN5GS.js +53 -0
  55. package/dist/{manager-NOKJQTTF.js → manager-VRHX7BVI.js} +4 -4
  56. package/dist/mcp-YU7AM3UV.js +120 -0
  57. package/dist/{model-catalog-ZLOWTQA7.js → model-catalog-2PCKTYGW.js} +2 -2
  58. package/dist/{oauth-provider-DGBC2YM6.js → oauth-provider-VHUS2KEG.js} +8 -2
  59. package/dist/{orchestrator-E6GIZGEN.js → orchestrator-PLTAEOMR.js} +30 -30
  60. package/dist/package.json +1 -1
  61. package/dist/{path-security-UDZ7UVWK.js → path-security-4WQJGU3Z.js} +11 -11
  62. package/dist/{platform-EMKWQTZX.js → platform-MWWJ6OKV.js} +3 -3
  63. package/dist/plugins-registry.json +12 -0
  64. package/dist/{processor-7RDR675X.js → processor-K4WHZKE6.js} +31 -31
  65. package/dist/{profiles-HXGJIPF2.js → profiles-EBCVFYG7.js} +2 -2
  66. package/dist/{protocol-DMneA8mx.d.ts → protocol-BMUoqwYH.d.ts} +2 -1
  67. package/dist/{protocol-TS3GVTT3.js → protocol-Y7MRKRUO.js} +3 -3
  68. package/dist/provider/index.d.ts +4 -4
  69. package/dist/{provider-DXEICEIE.js → provider-CVM33XHW.js} +10 -10
  70. package/dist/{provider-manager-PU7RS2TK.js → provider-manager-7NL5EQLG.js} +10 -10
  71. package/dist/{registry-Z4GVYFTV.js → registry-KFFZFIZT.js} +3 -3
  72. package/dist/{serve-Z5ITDPCQ.js → serve-KQAPXO5X.js} +42 -40
  73. package/dist/server/index.d.ts +18 -3
  74. package/dist/server/index.js +39 -37
  75. package/dist/server-RPKVKMDD.js +56 -0
  76. package/dist/{service-INQWTYY2.js → service-7TLOSFAO.js} +12 -12
  77. package/dist/{session-overrides-4WAD3X5Q.js → session-overrides-U573CU2V.js} +5 -5
  78. package/dist/session-status-UFO5IFI7.js +10 -0
  79. package/dist/{sessions-D7VRCHQY.js → sessions-LUVWWRFO.js} +4 -4
  80. package/dist/{settings-VOWWO4VG.js → settings-LMAMF2X7.js} +2 -2
  81. package/dist/shared/index.d.ts +3 -3
  82. package/dist/shared/index.js +1 -1
  83. package/dist/skill-defaults/browser/SKILL.md +20 -1
  84. package/dist/{tasks-SE3DOPVP.js → tasks-FA6Z52H2.js} +12 -12
  85. package/dist/{tools-6XUSIJN2.js → tools-SSPC3UQZ.js} +34 -34
  86. package/dist/{types-PAKlAzp9.d.ts → types-BIkpxjaj.d.ts} +11 -2
  87. package/dist/{types-BWuVnaBw.d.ts → types-CoY8Ka1C.d.ts} +1 -1
  88. package/dist/{update-EJUI6PSV.js → update-QRGK67DB.js} +2 -2
  89. package/dist/web/assets/{index-CGKd7WLQ.js → index-0PVQNOfW.js} +88 -88
  90. package/dist/web/assets/{index-CbX8veVW.css → index-Ds94aclE.css} +1 -1
  91. package/dist/web/index.html +2 -2
  92. package/dist/web/sw.js +1 -1
  93. package/package.json +1 -1
  94. package/plugins-registry.json +12 -0
  95. package/dist/chunk-HIRDDCPD.js +0 -7
  96. package/dist/chunk-PHP7PLFX.js +0 -151
  97. package/dist/chunk-RSB4AR2A.js +0 -108
  98. package/dist/client-RZGGDGUA.js +0 -16
  99. package/dist/dynamic-context-ZVE733UI.js +0 -28
  100. package/dist/launch-5ARSU7EM.js +0 -53
  101. package/dist/server-MUJ7EHEI.js +0 -56
package/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.130 - 2026-08-28
4
+
5
+ ### Features
6
+
7
+ - **Drive OpenFox sessions from any MCP client** — a built-in MCP server exposes `openfox_*` tools to run agents, manage sessions and workflows, plus an `openfox mcp` command that prints a paste-ready client config
8
+ - **Merge multi-mode model variants into a single model** — OmniRoute-style families (`*-low/-medium/-high`) collapse into one model with mode chips, mapped to the right provider ID per effort
9
+ - **Agent sees tool and prompt changes instantly** — system-reminder diffs are injected at the point of contention mid-session
10
+ - **Header icons collapse into a mobile menu** — cleaner navigation on small screens
11
+ - **New plugin registry entries** — openfox-openrouter-free and openfox-opencode-free
12
+
13
+ ### Enhancements
14
+
15
+ - **Full reasoning-effort control on OpenAI gpt-5** — tools and effort work together via the Responses API, no more forced "none"
16
+ - **Vision-capable models get an eye indicator** — auto-detected from the backend and shown across the model lists
17
+ - **MCP tool changes previewed in the system prompt** — the preview lists exactly which tools were added/removed
18
+ - **OAuth authorize completes instantly in the UI** — the callback tab notifies the app via BroadcastChannel, no paste-back needed
19
+
20
+ ### Bug Fixes
21
+
22
+ - **OpenAI provider no longer fails LLM calls** — gpt-5.x uses max_completion_tokens, thinking no longer sends chat_template_kwargs, and api.openai.com/anthropic.com providers auto-detect their backend without a re-save
23
+ - **OpenCode Go Responses-API models now work** — gpt-5.6-luna, grok-4.6 and muse-spark route to /v1/responses instead of the rejecting chat endpoint
24
+ - **Responses routing is backend-aware** — vLLM, Ollama and friends never hit /v1/responses
25
+ - **Session list no longer shrinks after delete/rename/favorite** — reloads are scoped to the active project
26
+ - **Session history defaults to a 300-message limit** — fresh installs no longer send unlimited history; explicit 0 stays opt-in unlimited
27
+ - **Logout actually logs out** — clears the token, closes the WebSocket and stops auto-reconnect
28
+ - **MCP OAuth reconnects no longer clobber pending authorizations** — background probes use in-memory state; stale client registrations are auto-detected and cleared
29
+ - **MCP server list refreshes reliably in the UI** — the tools tab updates immediately after server changes
30
+ - **Sub-agent window no longer shows the main session's compaction badge** — and no longer overlaps on narrow panes
31
+ - **No more false path confirmations from heredoc bodies** — path extraction ignores heredocs
32
+ - **Removed fake provider-defaults fields** — dead thinking/non-thinking params are gone, pointing to the real per-model settings
33
+ - **Merged mode-chip models survive catalog refresh** — no re-expanding after a re-fetch
34
+
3
35
  ## 2.0.129 - 2026-08-25
4
36
 
5
37
  ### Features
package/README.md CHANGED
@@ -100,6 +100,8 @@ Restart OpenFox after installing or updating a plugin.
100
100
  - To authenticate with a Github copilot account, you can install the [`openfox-github-copilot`](https://github.com/JamesDAdams/openfox-github-copilot) plugin.
101
101
  - To authenticate with a Google Antigravity account, you can install the [`openfox-google-antigravity`](https://github.com/JamesDAdams/openfox-google-antigravity) plugin.
102
102
  - To authenticate with an X (xAI) SuperGrok subscription, you can install the [`openfox-xai-supergrok`](https://github.com/Olgean-Group/openfox-xai-supergrok) plugin.
103
+ - To use free OpenRouter models, you can install the [`openfox-openrouter-free`](https://github.com/JamesDAdams/openfox-openrouter-free) plugin.
104
+ - To use free OpenCode models, you can install the [`openfox-opencode-free`](https://github.com/JamesDAdams/openfox-opencode-free) plugin.
103
105
 
104
106
  ## Screenshots
105
107
 
package/dist/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.130 - 2026-08-28
4
+
5
+ ### Features
6
+
7
+ - **Drive OpenFox sessions from any MCP client** — a built-in MCP server exposes `openfox_*` tools to run agents, manage sessions and workflows, plus an `openfox mcp` command that prints a paste-ready client config
8
+ - **Merge multi-mode model variants into a single model** — OmniRoute-style families (`*-low/-medium/-high`) collapse into one model with mode chips, mapped to the right provider ID per effort
9
+ - **Agent sees tool and prompt changes instantly** — system-reminder diffs are injected at the point of contention mid-session
10
+ - **Header icons collapse into a mobile menu** — cleaner navigation on small screens
11
+ - **New plugin registry entries** — openfox-openrouter-free and openfox-opencode-free
12
+
13
+ ### Enhancements
14
+
15
+ - **Full reasoning-effort control on OpenAI gpt-5** — tools and effort work together via the Responses API, no more forced "none"
16
+ - **Vision-capable models get an eye indicator** — auto-detected from the backend and shown across the model lists
17
+ - **MCP tool changes previewed in the system prompt** — the preview lists exactly which tools were added/removed
18
+ - **OAuth authorize completes instantly in the UI** — the callback tab notifies the app via BroadcastChannel, no paste-back needed
19
+
20
+ ### Bug Fixes
21
+
22
+ - **OpenAI provider no longer fails LLM calls** — gpt-5.x uses max_completion_tokens, thinking no longer sends chat_template_kwargs, and api.openai.com/anthropic.com providers auto-detect their backend without a re-save
23
+ - **OpenCode Go Responses-API models now work** — gpt-5.6-luna, grok-4.6 and muse-spark route to /v1/responses instead of the rejecting chat endpoint
24
+ - **Responses routing is backend-aware** — vLLM, Ollama and friends never hit /v1/responses
25
+ - **Session list no longer shrinks after delete/rename/favorite** — reloads are scoped to the active project
26
+ - **Session history defaults to a 300-message limit** — fresh installs no longer send unlimited history; explicit 0 stays opt-in unlimited
27
+ - **Logout actually logs out** — clears the token, closes the WebSocket and stops auto-reconnect
28
+ - **MCP OAuth reconnects no longer clobber pending authorizations** — background probes use in-memory state; stale client registrations are auto-detected and cleared
29
+ - **MCP server list refreshes reliably in the UI** — the tools tab updates immediately after server changes
30
+ - **Sub-agent window no longer shows the main session's compaction badge** — and no longer overlaps on narrow panes
31
+ - **No more false path confirmations from heredoc bodies** — path extraction ignores heredocs
32
+ - **Removed fake provider-defaults fields** — dead thinking/non-thinking params are gone, pointing to the real per-model settings
33
+ - **Merged mode-chip models survive catalog refresh** — no re-expanding after a re-fetch
34
+
3
35
  ## 2.0.129 - 2026-08-25
4
36
 
5
37
  ### Features
@@ -0,0 +1,19 @@
1
+ import {
2
+ authConfigExists,
3
+ encryptPassword,
4
+ hashPassword,
5
+ loadAuthConfig,
6
+ saveAuthConfig,
7
+ verifyPassword
8
+ } from "./chunk-CQGJ5RWB.js";
9
+ import "./chunk-CQGTEGKL.js";
10
+ import "./chunk-YLJ4XMA6.js";
11
+ export {
12
+ authConfigExists,
13
+ encryptPassword,
14
+ hashPassword,
15
+ loadAuthConfig,
16
+ saveAuthConfig,
17
+ verifyPassword
18
+ };
19
+ //# sourceMappingURL=auth-D3WLIBTG.js.map
@@ -1,12 +1,13 @@
1
1
  import {
2
- findLmStudioModel
3
- } from "./chunk-K2QKX4ZJ.js";
2
+ findLmStudioModel,
3
+ hasVisionEvidence
4
+ } from "./chunk-OA2FURC3.js";
4
5
  import {
5
6
  ensureVersionPrefix
6
7
  } from "./chunk-HNCM3D7Y.js";
7
8
  import {
8
9
  getCatalogEntry
9
- } from "./chunk-ISE55FOR.js";
10
+ } from "./chunk-2AI7VYPN.js";
10
11
  import {
11
12
  logger
12
13
  } from "./chunk-K44MW7JJ.js";
@@ -99,7 +100,7 @@ async function detectOllamaInfo(baseUrl, modelId) {
99
100
  const mi = data.model_info ?? {};
100
101
  const ctxKey = Object.keys(mi).find((k) => k.endsWith(".context_length") || k === "context_length");
101
102
  const ctxLen = ctxKey ? Number(mi[ctxKey]) : void 0;
102
- const supportsVision = !!mi["vision_start_token_id"] || Object.keys(mi).some((k) => k.includes(".vision."));
103
+ const supportsVision = hasVisionEvidence(mi);
103
104
  if (ctxLen && !isNaN(ctxLen)) {
104
105
  return { contextWindow: ctxLen, source: "backend", supportsVision };
105
106
  }
@@ -307,4 +308,4 @@ async function autoConfig(input) {
307
308
  export {
308
309
  autoConfig
309
310
  };
310
- //# sourceMappingURL=auto-config-454YE6KC.js.map
311
+ //# sourceMappingURL=auto-config-5VSNLVNI.js.map
@@ -1,10 +1,12 @@
1
1
  import {
2
+ detectBackendFromUrl,
2
3
  getBackendCapabilities,
3
4
  getBackendDisplayName
4
- } from "./chunk-PBFGJFGC.js";
5
+ } from "./chunk-UV6IH6HK.js";
5
6
  import "./chunk-YLJ4XMA6.js";
6
7
  export {
8
+ detectBackendFromUrl,
7
9
  getBackendCapabilities,
8
10
  getBackendDisplayName
9
11
  };
10
- //# sourceMappingURL=backend-4YPEC3J2.js.map
12
+ //# sourceMappingURL=backend-NDBY3DAQ.js.map
@@ -2,55 +2,55 @@ import {
2
2
  buildRunChatTurnParams,
3
3
  finalizeTurnCompletion,
4
4
  generateSessionNameForSession
5
- } from "./chunk-OHTBWA7L.js";
5
+ } from "./chunk-35GQEIH2.js";
6
6
  import {
7
7
  runChatTurn
8
- } from "./chunk-7RIEI2TE.js";
9
- import "./chunk-L24A6GZ7.js";
10
- import "./chunk-PHP7PLFX.js";
11
- import "./chunk-ZIL6VKLU.js";
12
- import "./chunk-6LX43YRA.js";
13
- import "./chunk-GIJUWPRQ.js";
8
+ } from "./chunk-EVVWDRM5.js";
9
+ import "./chunk-X24XN2M2.js";
10
+ import "./chunk-Y3BSBKHY.js";
11
+ import "./chunk-J7GAZGZT.js";
12
+ import "./chunk-JSONBGSY.js";
13
+ import "./chunk-ZRCRGPGT.js";
14
+ import "./chunk-7ET46SNE.js";
14
15
  import "./chunk-EHFIUXWZ.js";
15
- import "./chunk-RV5G7QQU.js";
16
+ import "./chunk-DQTXXHD2.js";
16
17
  import "./chunk-I72ACQ6R.js";
17
18
  import "./chunk-JE7LW7Y6.js";
18
19
  import "./chunk-OAN4BXEW.js";
19
- import "./chunk-Y3BSBKHY.js";
20
- import "./chunk-J7GAZGZT.js";
21
- import "./chunk-H6YIVK67.js";
22
- import "./chunk-7YP4O4XE.js";
23
- import "./chunk-26WS7AH6.js";
20
+ import "./chunk-25DAVVTP.js";
21
+ import "./chunk-64N4CZFT.js";
22
+ import "./chunk-CGCEAKG5.js";
23
+ import "./chunk-JURM3RPZ.js";
24
+ import "./chunk-VJNA5AOB.js";
24
25
  import {
25
26
  getEventStore
26
- } from "./chunk-YJD5A375.js";
27
- import "./chunk-ZIYETXOW.js";
28
- import "./chunk-AQBRI7TM.js";
27
+ } from "./chunk-AYCB32NI.js";
28
+ import "./chunk-JKRMMNUR.js";
29
+ import "./chunk-X3FHIDLT.js";
30
+ import "./chunk-JHA2SPCU.js";
31
+ import "./chunk-OSXPQSLW.js";
29
32
  import {
30
33
  createChatMessageMessage,
31
34
  createPhaseChangedMessage,
32
35
  createSessionRunningMessage
33
- } from "./chunk-567L5OJ6.js";
34
- import "./chunk-66MG44TF.js";
35
- import "./chunk-JURM3RPZ.js";
36
+ } from "./chunk-P57IBMK4.js";
36
37
  import "./chunk-LCLH6ZUL.js";
37
- import "./chunk-JQMQ4DGC.js";
38
- import "./chunk-K2QKX4ZJ.js";
38
+ import "./chunk-6QZVAOSA.js";
39
+ import "./chunk-CYQUM42E.js";
40
+ import "./chunk-OA2FURC3.js";
39
41
  import "./chunk-J2GP3J3X.js";
40
- import "./chunk-KBESUA3W.js";
41
- import "./chunk-OSXPQSLW.js";
42
42
  import "./chunk-3B232XG4.js";
43
- import "./chunk-P6GTPKE5.js";
44
- import "./chunk-7ZMOP5LS.js";
45
- import "./chunk-PBFGJFGC.js";
43
+ import "./chunk-DHDIKVRT.js";
44
+ import "./chunk-TS5WKTFB.js";
45
+ import "./chunk-UV6IH6HK.js";
46
46
  import "./chunk-HNCM3D7Y.js";
47
- import "./chunk-DABWCAXS.js";
48
- import "./chunk-ZFNBATE3.js";
49
- import "./chunk-N2Q3KYWM.js";
47
+ import "./chunk-EUOWCVU6.js";
48
+ import "./chunk-OXMOKQPW.js";
49
+ import "./chunk-3DZSHRXE.js";
50
50
  import "./chunk-OYBUJIC3.js";
51
- import "./chunk-ISE55FOR.js";
51
+ import "./chunk-2AI7VYPN.js";
52
52
  import "./chunk-K44MW7JJ.js";
53
- import "./chunk-ATWOXI52.js";
53
+ import "./chunk-HCYSGLY2.js";
54
54
  import "./chunk-R5FAEKXQ.js";
55
55
  import "./chunk-CQGTEGKL.js";
56
56
  import "./chunk-YLJ4XMA6.js";
@@ -174,4 +174,4 @@ export {
174
174
  startChatSession,
175
175
  stopSessionExecution
176
176
  };
177
- //# sourceMappingURL=chat-handler-TH6JBO6G.js.map
177
+ //# sourceMappingURL=chat-handler-4WCKNCQV.js.map
@@ -0,0 +1,395 @@
1
+ import {
2
+ getAllInstructions,
3
+ getEnabledSkillMetadata
4
+ } from "./chunk-64N4CZFT.js";
5
+ import {
6
+ buildTopLevelSystemPrompt
7
+ } from "./chunk-CGCEAKG5.js";
8
+ import {
9
+ getCurrentContextWindowId,
10
+ getEventStore
11
+ } from "./chunk-AYCB32NI.js";
12
+ import {
13
+ findAgentById,
14
+ getRuntimeConfig,
15
+ getSubAgents,
16
+ loadAllAgentsDefault,
17
+ resolveDefaultAgentId
18
+ } from "./chunk-JHA2SPCU.js";
19
+ import {
20
+ logger
21
+ } from "./chunk-K44MW7JJ.js";
22
+ import {
23
+ getGlobalConfigDir
24
+ } from "./chunk-CQGTEGKL.js";
25
+
26
+ // src/server/chat/dynamic-context.ts
27
+ import { createHash, randomUUID } from "crypto";
28
+ function computeUnifiedDiff(oldText, newText) {
29
+ const oldLines = oldText.length === 0 ? [] : oldText.split("\n");
30
+ const newLines = newText.length === 0 ? [] : newText.split("\n");
31
+ const result = [];
32
+ if (oldText === newText) {
33
+ return oldLines.map((line) => ({ type: "unchanged", content: line }));
34
+ }
35
+ const lcs = /* @__PURE__ */ new Map();
36
+ for (let i2 = 0; i2 <= oldLines.length; i2++) {
37
+ lcs.set(i2, /* @__PURE__ */ new Map());
38
+ for (let j2 = 0; j2 <= newLines.length; j2++) {
39
+ lcs.get(i2).set(j2, 0);
40
+ }
41
+ }
42
+ for (let i2 = 1; i2 <= oldLines.length; i2++) {
43
+ for (let j2 = 1; j2 <= newLines.length; j2++) {
44
+ const oldLine = oldLines[i2 - 1];
45
+ const newLine = newLines[j2 - 1];
46
+ if (oldLine === newLine) {
47
+ lcs.get(i2).set(j2, (lcs.get(i2 - 1).get(j2 - 1) ?? 0) + 1);
48
+ } else {
49
+ const up = lcs.get(i2 - 1).get(j2) ?? 0;
50
+ const left = lcs.get(i2).get(j2 - 1) ?? 0;
51
+ lcs.get(i2).set(j2, Math.max(up, left));
52
+ }
53
+ }
54
+ }
55
+ let i = oldLines.length;
56
+ let j = newLines.length;
57
+ while (i > 0 || j > 0) {
58
+ const oldLine = oldLines[i - 1] ?? "";
59
+ const newLine = newLines[j - 1] ?? "";
60
+ if (i > 0 && j > 0 && oldLine === newLine) {
61
+ result.unshift({ type: "unchanged", content: oldLine });
62
+ i--;
63
+ j--;
64
+ } else if (i > 0 && j > 0) {
65
+ const lcsIM1J = lcs.get(i - 1)?.get(j) ?? 0;
66
+ const lcsIJM1 = lcs.get(i)?.get(j - 1) ?? 0;
67
+ if (lcsIM1J > lcsIJM1) {
68
+ result.unshift({ type: "removed", content: oldLine });
69
+ i--;
70
+ } else {
71
+ result.unshift({ type: "added", content: newLine });
72
+ j--;
73
+ }
74
+ } else if (i > 0) {
75
+ result.unshift({ type: "removed", content: oldLine });
76
+ i--;
77
+ } else {
78
+ result.unshift({ type: "added", content: newLine });
79
+ j--;
80
+ }
81
+ }
82
+ return result;
83
+ }
84
+ function computeDynamicContextHash(instructionContent, skills, toolFingerprint, modelName) {
85
+ const dynamicInputs = JSON.stringify({
86
+ instructions: instructionContent,
87
+ skills: skills.map((s) => s.id).sort(),
88
+ ...toolFingerprint ? { tools: toolFingerprint } : {},
89
+ ...modelName ? { model: modelName } : {}
90
+ });
91
+ return createHash("sha256").update(dynamicInputs).digest("hex");
92
+ }
93
+ function getToolFingerprint(tools) {
94
+ return tools.map((t) => `${t.function.name}:${JSON.stringify(t.function.parameters)}`).sort().join("|");
95
+ }
96
+ function computeToolDiff(oldTools, newTools) {
97
+ const oldNames = oldTools.map((t) => t.function.name).sort();
98
+ const newNames = newTools.map((t) => t.function.name).sort();
99
+ const oldSet = new Set(oldNames);
100
+ const newSet = new Set(newNames);
101
+ const result = [];
102
+ for (const name of oldNames) {
103
+ if (!newSet.has(name)) result.push({ type: "removed", content: name });
104
+ }
105
+ for (const name of newNames) {
106
+ if (!oldSet.has(name)) result.push({ type: "added", content: name });
107
+ }
108
+ return result;
109
+ }
110
+ function computePreviewToolDiff(oldCachedTools, unfilteredTools, newTools) {
111
+ const baseline = oldCachedTools && oldCachedTools.length > 0 ? oldCachedTools : unfilteredTools;
112
+ return computeToolDiff(baseline, newTools);
113
+ }
114
+ var MAX_DESCRIPTION_LENGTH = 80;
115
+ function getToolSignature(tool) {
116
+ const fn = tool.function;
117
+ return `${fn.name}:${fn.description ?? ""}:${JSON.stringify(fn.parameters)}`;
118
+ }
119
+ function detectToolChanges(liveTools, cachedTools) {
120
+ const liveByName = new Map(liveTools.map((t) => [t.function.name, t]));
121
+ const cachedByName = new Map(cachedTools.map((t) => [t.function.name, t]));
122
+ const added = [];
123
+ const removed = [];
124
+ const changed = [];
125
+ for (const name of liveByName.keys()) {
126
+ const liveTool = liveByName.get(name);
127
+ const cachedTool = cachedByName.get(name);
128
+ if (!cachedTool) {
129
+ const properties = liveTool.function.parameters?.["properties"];
130
+ added.push({
131
+ name,
132
+ description: liveTool.function.description,
133
+ params: Object.keys(properties ?? {})
134
+ });
135
+ } else if (getToolSignature(liveTool) !== getToolSignature(cachedTool)) {
136
+ changed.push(name);
137
+ }
138
+ }
139
+ for (const name of cachedByName.keys()) {
140
+ if (!liveByName.has(name)) removed.push(name);
141
+ }
142
+ added.sort((a, b) => a.name.localeCompare(b.name));
143
+ removed.sort();
144
+ changed.sort();
145
+ return { added, removed, changed };
146
+ }
147
+ function hasToolChanges(changes) {
148
+ return changes.added.length > 0 || changes.removed.length > 0 || changes.changed.length > 0;
149
+ }
150
+ function truncateDescription(description) {
151
+ if (!description) return void 0;
152
+ const trimmed = description.replace(/\s+/g, " ").trim();
153
+ if (trimmed.length <= MAX_DESCRIPTION_LENGTH) return trimmed;
154
+ return trimmed.slice(0, MAX_DESCRIPTION_LENGTH - 1) + "\u2026";
155
+ }
156
+ function formatAddedTool(tool) {
157
+ const description = truncateDescription(tool.description);
158
+ const params = tool.params.length > 0 ? ` (params: ${tool.params.join(", ")})` : "";
159
+ return description ? `${tool.name} \u2014 ${description}${params}` : `${tool.name}${params}`;
160
+ }
161
+ function renderToolChangeReminder(changes) {
162
+ if (!hasToolChanges(changes)) return null;
163
+ const sections = [];
164
+ if (changes.added.length > 0) {
165
+ sections.push(`Added:
166
+ ${changes.added.map(formatAddedTool).join("\n")}`);
167
+ }
168
+ if (changes.removed.length > 0) {
169
+ sections.push(`Removed:
170
+ ${changes.removed.join("\n")}`);
171
+ }
172
+ if (changes.changed.length > 0) {
173
+ sections.push(`Changed:
174
+ ${changes.changed.join("\n")}`);
175
+ }
176
+ return `<system-reminder>
177
+ The available tools have changed since your last turn:
178
+ ${sections.join(
179
+ "\n"
180
+ )}
181
+ </system-reminder>`;
182
+ }
183
+ var MAX_PROMPT_DIFF_LINES = 40;
184
+ var MAX_PROMPT_DIFF_LINE_LENGTH = 200;
185
+ function renderSystemPromptDiff(oldPrompt, newPrompt) {
186
+ const diff = computeUnifiedDiff(oldPrompt, newPrompt);
187
+ const changedLines = diff.filter((line) => line.type !== "unchanged");
188
+ if (changedLines.length === 0) return null;
189
+ const visible = changedLines.slice(0, MAX_PROMPT_DIFF_LINES);
190
+ const lines = visible.map((line) => {
191
+ const marker = line.type === "added" ? "+" : "-";
192
+ const content = line.content.length > MAX_PROMPT_DIFF_LINE_LENGTH ? line.content.slice(0, MAX_PROMPT_DIFF_LINE_LENGTH) + "\u2026" : line.content;
193
+ return `${marker} ${content}`;
194
+ });
195
+ const omitted = changedLines.length - visible.length;
196
+ if (omitted > 0) {
197
+ lines.push(`\u2026 ${omitted} more line${omitted === 1 ? "" : "s"} omitted`);
198
+ }
199
+ return `<system-reminder>
200
+ Your system prompt has changed:
201
+ ${lines.join("\n")}
202
+ </system-reminder>`;
203
+ }
204
+ function injectSystemReminder(sessionId, append, content, type, name) {
205
+ const currentWindowId = getCurrentContextWindowId(sessionId);
206
+ const reminderMsgId = randomUUID();
207
+ append({
208
+ type: "message.start",
209
+ data: {
210
+ messageId: reminderMsgId,
211
+ role: "user",
212
+ content,
213
+ ...currentWindowId ? { contextWindowId: currentWindowId } : {},
214
+ isSystemGenerated: true,
215
+ messageKind: "auto-prompt",
216
+ metadata: { type, name, color: "#6b7280", kind: "reminder" }
217
+ }
218
+ });
219
+ append({
220
+ type: "message.done",
221
+ data: { messageId: reminderMsgId }
222
+ });
223
+ }
224
+ async function injectDriftReminders(sessionManager, sessionId, agentDef, options, append) {
225
+ const cached = sessionManager.getCachedPrompt(sessionId);
226
+ if (!cached) {
227
+ return { injectedToolReminder: false, injectedPromptReminder: false };
228
+ }
229
+ const { getToolRegistryForAgent } = await import("./tools-SSPC3UQZ.js");
230
+ const liveTools = getToolRegistryForAgent(agentDef, sessionId).definitions;
231
+ let injectedToolReminder = false;
232
+ let injectedPromptReminder = false;
233
+ const changes = detectToolChanges(liveTools, cached.tools);
234
+ if (hasToolChanges(changes)) {
235
+ const reminder = renderToolChangeReminder(changes);
236
+ if (reminder) {
237
+ injectSystemReminder(sessionId, append, reminder, "tools", "Tools");
238
+ injectedToolReminder = true;
239
+ }
240
+ const newHash = computeDynamicContextHash(
241
+ options.instructionContent,
242
+ options.skills,
243
+ getToolFingerprint(liveTools),
244
+ options.modelName
245
+ );
246
+ sessionManager.setCachedPrompt(sessionId, cached.systemPrompt, liveTools, newHash);
247
+ }
248
+ const livePromptHash = computeDynamicContextHash(
249
+ options.instructionContent,
250
+ options.skills,
251
+ void 0,
252
+ options.modelName
253
+ );
254
+ const announcedPromptHash = sessionManager.getAnnouncedPromptHash(sessionId) ?? cached.hash;
255
+ if (announcedPromptHash !== livePromptHash) {
256
+ const reminder = renderSystemPromptDiff(cached.systemPrompt, options.buildNewSystemPrompt());
257
+ if (reminder) {
258
+ injectSystemReminder(sessionId, append, reminder, "system-prompt", "System Prompt");
259
+ injectedPromptReminder = true;
260
+ }
261
+ sessionManager.setAnnouncedPromptHash(sessionId, livePromptHash);
262
+ }
263
+ return { injectedToolReminder, injectedPromptReminder };
264
+ }
265
+ async function checkToolChangesAndInject(sessionManager, sessionId, agentDef, options, append) {
266
+ return injectDriftReminders(sessionManager, sessionId, agentDef, options, append);
267
+ }
268
+ function createEventStoreAppend(sessionId) {
269
+ return (event) => {
270
+ try {
271
+ getEventStore().append(sessionId, event);
272
+ } catch {
273
+ }
274
+ };
275
+ }
276
+ function resolveConcreteModelName(sessionManager, sessionId, agentId) {
277
+ const effective = sessionManager.resolveEffectiveProviderModel(sessionId, agentId);
278
+ if (effective.providerId && effective.model) {
279
+ const pm = sessionManager.getProviderManager();
280
+ const resolvedModel = pm.resolveModel(effective.providerId, effective.model);
281
+ const effectiveModel = resolvedModel ?? effective.model;
282
+ const client = pm.createClient(effective.providerId, effectiveModel, effective.reasoningEffort);
283
+ if (client) return client.getModel();
284
+ }
285
+ return sessionManager.getProviderManager().getCurrentModel() ?? "";
286
+ }
287
+ async function injectContextDriftReminders(sessionManager, sessionId, append) {
288
+ try {
289
+ const allAgents = await loadAllAgentsDefault(sessionManager.getProjectWorkdir(sessionId));
290
+ const session = sessionManager.requireSession(sessionId);
291
+ const agentDef = findAgentById(session.mode, allAgents) ?? findAgentById(resolveDefaultAgentId(), allAgents);
292
+ const { instructionContent, skills } = await loadSessionContext(sessionManager, sessionId);
293
+ const subAgentDefs = getSubAgents(allAgents);
294
+ const modelName = resolveConcreteModelName(sessionManager, sessionId, agentDef.metadata.id);
295
+ return await injectDriftReminders(
296
+ sessionManager,
297
+ sessionId,
298
+ agentDef,
299
+ {
300
+ modelName,
301
+ instructionContent: instructionContent ?? "",
302
+ skills,
303
+ buildNewSystemPrompt: () => buildTopLevelSystemPrompt(session.workdir, instructionContent || void 0, skills, subAgentDefs, modelName)
304
+ },
305
+ append ?? createEventStoreAppend(sessionId)
306
+ );
307
+ } catch (error) {
308
+ logger.warn("injectContextDriftReminders failed", {
309
+ sessionId,
310
+ error: error instanceof Error ? error.message : String(error)
311
+ });
312
+ return { injectedToolReminder: false, injectedPromptReminder: false };
313
+ }
314
+ }
315
+ async function injectContextDriftRemindersForSessions(sessionManager, sessionIds) {
316
+ for (const sessionId of sessionIds) {
317
+ await injectContextDriftReminders(sessionManager, sessionId);
318
+ }
319
+ }
320
+ async function loadSessionContext(sessionManager, sessionId) {
321
+ const session = sessionManager.requireSession(sessionId);
322
+ const { content: instructionContent } = await getAllInstructions(session.workdir, session.projectId);
323
+ const runtimeConfig = getRuntimeConfig();
324
+ const configDir = getGlobalConfigDir(runtimeConfig.mode ?? "production");
325
+ const skills = await getEnabledSkillMetadata(configDir, sessionManager.getProjectWorkdir(sessionId));
326
+ return { instructionContent: instructionContent ?? "", skills };
327
+ }
328
+ function resolveAgentDef(sessionManager, sessionId) {
329
+ return loadAllAgentsDefault(sessionManager.getProjectWorkdir(sessionId)).then((allAgents) => {
330
+ const session = sessionManager.requireSession(sessionId);
331
+ return findAgentById(session.mode, allAgents) ?? findAgentById(resolveDefaultAgentId(), allAgents);
332
+ });
333
+ }
334
+ async function buildCachedPrompt(sessionManager, sessionId, agentDef, modelName) {
335
+ const { instructionContent, skills } = await loadSessionContext(sessionManager, sessionId);
336
+ const { getToolRegistryForAgent } = await import("./tools-SSPC3UQZ.js");
337
+ const tools = getToolRegistryForAgent(agentDef, sessionId).definitions;
338
+ const toolFingerprint = getToolFingerprint(tools);
339
+ const allAgents = await loadAllAgentsDefault(sessionManager.getProjectWorkdir(sessionId));
340
+ const subAgentDefs = getSubAgents(allAgents);
341
+ const session = sessionManager.requireSession(sessionId);
342
+ const systemPrompt = buildTopLevelSystemPrompt(
343
+ session.workdir,
344
+ instructionContent || void 0,
345
+ skills,
346
+ subAgentDefs,
347
+ modelName
348
+ );
349
+ const hash = computeDynamicContextHash(instructionContent, skills, toolFingerprint, modelName);
350
+ const promptHash = computeDynamicContextHash(instructionContent, skills, void 0, modelName);
351
+ return { systemPrompt, tools, hash, promptHash };
352
+ }
353
+ async function computeSessionHash(sessionManager, sessionId, modelName) {
354
+ const { instructionContent, skills } = await loadSessionContext(sessionManager, sessionId);
355
+ const agentDef = await resolveAgentDef(sessionManager, sessionId);
356
+ const { getToolRegistryForAgent } = await import("./tools-SSPC3UQZ.js");
357
+ const tools = getToolRegistryForAgent(agentDef, sessionId).definitions;
358
+ const toolFingerprint = getToolFingerprint(tools);
359
+ return computeDynamicContextHash(instructionContent, skills, toolFingerprint, modelName);
360
+ }
361
+ async function applyDynamicContext(sessionManager, sessionId, modelName) {
362
+ const session = sessionManager.requireSession(sessionId);
363
+ const allAgents = await loadAllAgentsDefault(sessionManager.getProjectWorkdir(sessionId));
364
+ const agentDef = findAgentById(session.mode, allAgents) ?? findAgentById(resolveDefaultAgentId(), allAgents);
365
+ const { systemPrompt, tools, hash, promptHash } = await buildCachedPrompt(
366
+ sessionManager,
367
+ sessionId,
368
+ agentDef,
369
+ modelName
370
+ );
371
+ sessionManager.setCachedPrompt(sessionId, systemPrompt, tools, hash);
372
+ sessionManager.setAnnouncedPromptHash(sessionId, promptHash);
373
+ sessionManager.setDynamicContextChanged(sessionId, false);
374
+ sessionManager.clearDebugDump(sessionId);
375
+ logger.debug("applyDynamicContext done", { sessionId, hash, toolCount: tools.length });
376
+ }
377
+
378
+ export {
379
+ computeUnifiedDiff,
380
+ computeDynamicContextHash,
381
+ getToolFingerprint,
382
+ computeToolDiff,
383
+ computePreviewToolDiff,
384
+ getToolSignature,
385
+ detectToolChanges,
386
+ renderToolChangeReminder,
387
+ renderSystemPromptDiff,
388
+ checkToolChangesAndInject,
389
+ injectContextDriftReminders,
390
+ injectContextDriftRemindersForSessions,
391
+ buildCachedPrompt,
392
+ computeSessionHash,
393
+ applyDynamicContext
394
+ };
395
+ //# sourceMappingURL=chunk-25DAVVTP.js.map
@@ -22,6 +22,15 @@ function resolveEffortForModel({
22
22
  if (override) return override;
23
23
  return defaultEffort && reasoningEfforts.includes(defaultEffort) ? defaultEffort : void 0;
24
24
  }
25
+ var MODE_SUFFIXES = ["low", "medium", "high", "xhigh", "max"];
26
+ var MODE_SUFFIX_REGEX = new RegExp(`-(${MODE_SUFFIXES.join("|")})$`);
27
+ function resolveModeModelId(modes, effort, fallbackApiModelId, modelId) {
28
+ const modeEntry = modes?.find((mode) => mode.level === effort);
29
+ if (modeEntry) {
30
+ return { modelId: modeEntry.apiModelId, suppressEffort: true };
31
+ }
32
+ return { modelId: fallbackApiModelId ?? modelId, suppressEffort: false };
33
+ }
25
34
 
26
35
  // src/server/providers/model-catalog.ts
27
36
  var CATALOG = [
@@ -83,7 +92,8 @@ export {
83
92
  REASONING_EFFORT_VALUES,
84
93
  isReasoningEffortValue,
85
94
  resolveEffortForModel,
95
+ resolveModeModelId,
86
96
  getCatalogEntry,
87
97
  getCatalogDefaultEffort
88
98
  };
89
- //# sourceMappingURL=chunk-ISE55FOR.js.map
99
+ //# sourceMappingURL=chunk-2AI7VYPN.js.map