nolo-cli 0.147.0-alpha.2 → 0.149.0-alpha.1

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 (102) hide show
  1. package/{_executeModel-3OCR5R5P.js → _executeModel-OW3H7ICR.js} +29 -28
  2. package/{action-3ZOODRBC.js → action-GI44T4DR.js} +6 -6
  3. package/{addContentAction-IJHG2ZV7.js → addContentAction-B2DRF7P6.js} +5 -5
  4. package/{addDialogAgentAction-RLPSTAQ2.js → addDialogAgentAction-2P2FLTLD.js} +4 -4
  5. package/{agentDeleteCommand-6OGADD24.js → agentDeleteCommand-7IDWF6E3.js} +14 -13
  6. package/{agentEmailCommands-OAPYGNYC.js → agentEmailCommands-A6XBQZBN.js} +31 -30
  7. package/{agentListCommands-FRJZOOEG.js → agentListCommands-IW3GQVUP.js} +16 -15
  8. package/{agentMachineCommands-OWLOV5WO.js → agentMachineCommands-DQPUIMAC.js} +14 -13
  9. package/{agentProviderCommands-TWB6E5WD.js → agentProviderCommands-YK2BIIXZ.js} +1 -1
  10. package/{agentRecordCommands-BW7HM6VH.js → agentRecordCommands-VCA76W6B.js} +31 -30
  11. package/{agentRunCommand-O2F3NU2H.js → agentRunCommand-YNLDKVR7.js} +31 -30
  12. package/{agentRuntimeLocal-QQCDFR7B.js → agentRuntimeLocal-AK2QVJHY.js} +12 -11
  13. package/{agentSlice-ZOCKW66S.js → agentSlice-O4RUQUMT.js} +5 -5
  14. package/{appDeleteCommands-OGKQC2AM.js → appDeleteCommands-N3XEVVYC.js} +15 -14
  15. package/{appDeployCommands-Y2FV4JML.js → appDeployCommands-AWFIXYVW.js} +15 -14
  16. package/{appDeployStatusCommands-FNML5SUV.js → appDeployStatusCommands-CZRON2FO.js} +15 -14
  17. package/{appGetCommands-4FOY7W5E.js → appGetCommands-XQIUY4TD.js} +15 -14
  18. package/{appListCommands-E5SF6SIY.js → appListCommands-NNG4H36Y.js} +15 -14
  19. package/{chatQueueReduxAdapter-DFZ6QB4K.js → chatQueueReduxAdapter-TJRMXMYA.js} +11 -11
  20. package/{chunk-27VHPPII.js → chunk-36KZDDO5.js} +6 -6
  21. package/{chunk-KRC6GI2Q.js → chunk-3DAVPNFT.js} +2 -2
  22. package/{chunk-T76D3OYX.js → chunk-3SV7RM24.js} +1 -1
  23. package/{chunk-O7WXJIUI.js → chunk-4H22P2JV.js} +11 -9
  24. package/{chunk-M2YBIBBS.js → chunk-5TEEECZM.js} +1 -1
  25. package/{chunk-Z7IZQF56.js → chunk-6FGTMQCL.js} +1 -1
  26. package/{chunk-ETZWFV6M.js → chunk-7CHC4W22.js} +1 -1
  27. package/{chunk-PZ3HKBET.js → chunk-ACQD6YI2.js} +19 -19
  28. package/{chunk-ZSPC3ZTC.js → chunk-AKG5W4LG.js} +1 -1
  29. package/{chunk-CCOXTK3I.js → chunk-ALFH24P3.js} +26 -0
  30. package/{chunk-7NANRWL4.js → chunk-ALGORS6Y.js} +1 -1
  31. package/chunk-ATLTFRYJ.js +411 -0
  32. package/{chunk-HNRASX3X.js → chunk-CPUFH46E.js} +1 -1
  33. package/{chunk-GMVELWJG.js → chunk-CU3QB4HW.js} +2 -2
  34. package/{chunk-LQ6P2MFG.js → chunk-DXHL7G2L.js} +14 -14
  35. package/{chunk-2EE5UD3N.js → chunk-DY7ANLKG.js} +1 -1
  36. package/{chunk-I44MDY73.js → chunk-GOH6RW6F.js} +3 -3
  37. package/chunk-HTVYCXBP.js +681 -0
  38. package/{chunk-QALRKMHF.js → chunk-HYZIYH2H.js} +5 -5
  39. package/{chunk-EFZKILX6.js → chunk-IAESIMK7.js} +1 -1
  40. package/{chunk-OXGHM2WW.js → chunk-ID7LNBWR.js} +27 -257
  41. package/{chunk-HLUYTEBY.js → chunk-K2CSUCHJ.js} +1 -1
  42. package/{chunk-JORF7I7F.js → chunk-MST6R3E4.js} +3 -3
  43. package/{chunk-QJLEMM2V.js → chunk-O2OWEFII.js} +1 -1
  44. package/{chunk-724HIKHT.js → chunk-OHOVNO7I.js} +4 -127
  45. package/{chunk-P4CRULYJ.js → chunk-OMRJYNCI.js} +3 -3
  46. package/chunk-PQWU42UQ.js +132 -0
  47. package/{chunk-JQ4LUB5I.js → chunk-PZZTFEKK.js} +1 -1
  48. package/{chunk-QIH323EV.js → chunk-QXGPFY6J.js} +1 -1
  49. package/{chunk-B7ANJQWZ.js → chunk-RSEEDUMS.js} +2 -2
  50. package/{chunk-ELYEQNUI.js → chunk-RYZINGPM.js} +3 -3
  51. package/{chunk-AATZZAZE.js → chunk-SLLGJZDT.js} +1 -1
  52. package/{chunk-3IYMTWYZ.js → chunk-SONWNI3L.js} +2 -2
  53. package/chunk-TB3MIBRC.js +1716 -0
  54. package/{chunk-2B74TU77.js → chunk-TXH4IWJL.js} +3 -3
  55. package/{chunk-UC3Q7X3J.js → chunk-TZZ2WRBL.js} +5 -5
  56. package/{chunk-36HTQWBD.js → chunk-UASIEDKM.js} +3 -3
  57. package/{chunk-BJUDYFV5.js → chunk-UQNS32WZ.js} +1 -1
  58. package/{chunk-AUXHZ2M5.js → chunk-WIWM4FE3.js} +1 -1
  59. package/{chunk-YU2THNST.js → chunk-XISEYOGH.js} +1 -1
  60. package/{chunk-BFLSOVHN.js → chunk-XYJSY4KG.js} +16 -14
  61. package/{chunk-NU4DCNMR.js → chunk-YAQJJDC2.js} +4 -571
  62. package/{chunk-D76D3RTR.js → chunk-Z4CSIXYP.js} +2 -2
  63. package/{chunk-BCJPO6SE.js → chunk-ZUEK6A6C.js} +10 -10
  64. package/{commandRegistry-OPVCVVOQ.js → commandRegistry-2KBOXZQC.js} +42 -42
  65. package/{contentThunks-IWXWFN6P.js → contentThunks-BDIQRZR6.js} +12 -12
  66. package/{createAgentAutomationAction-ROWX5ZPK.js → createAgentAutomationAction-5UGTB26P.js} +12 -12
  67. package/{createDialogAction-WLVAITHA.js → createDialogAction-B7VGVEVU.js} +13 -13
  68. package/{createPageAction-DAJL6GES.js → createPageAction-CDLDKPRM.js} +12 -12
  69. package/{dbSlice-HFPIJT5P.js → dbSlice-DQ32LYTJ.js} +4 -4
  70. package/{deleteFile-UEAD5A5Z.js → deleteFile-NX6QHCWZ.js} +2 -2
  71. package/{dialogCommands-KSPH6QOU.js → dialogCommands-G7YBVAMC.js} +15 -14
  72. package/{dialogSlice-WW75BKLO.js → dialogSlice-N3YB65G5.js} +11 -11
  73. package/{docCreateCommands-B64BLZVJ.js → docCreateCommands-ZSLGVBZT.js} +14 -13
  74. package/{docDeleteCommands-UX2GXKUT.js → docDeleteCommands-5N4GVZBG.js} +15 -14
  75. package/{docReadCommands-5A6GF3XL.js → docReadCommands-YJSAA7AV.js} +14 -13
  76. package/{docStore-2SADZYLX.js → docStore-E3CEOV5Q.js} +5 -5
  77. package/{docUpdateCommands-UTBGZPSR.js → docUpdateCommands-WEMLSW6W.js} +14 -13
  78. package/{handleSendMessageAction-2M57WHLO.js → handleSendMessageAction-DQAD5ERJ.js} +440 -106
  79. package/index.js +3 -3
  80. package/{machineCommands-7JUTOZP2.js → machineCommands-HAP75VSG.js} +30 -29
  81. package/{machineWsRunDispatch-6EETR3RV.js → machineWsRunDispatch-L32G7C4P.js} +30 -29
  82. package/{memberThunks-SKFZ37VS.js → memberThunks-5ZXPR63F.js} +5 -5
  83. package/package.json +1 -1
  84. package/{providerPresetApply-XTEXOH7X.js → providerPresetApply-DD6NGWW6.js} +1 -1
  85. package/{providerRegistry-ADYDSLKR.js → providerRegistry-XDRLMYGJ.js} +1 -1
  86. package/{read-IEJLLUXY.js → read-EPTJRAEF.js} +2 -2
  87. package/{readDocTool-4SPYCP2Y.js → readDocTool-W4NDXNEX.js} +1 -1
  88. package/{readlineWorkspace-LBLAGNGM.js → readlineWorkspace-7BC66QSX.js} +34 -33
  89. package/{removeDialogAgentAction-R4RTGM2S.js → removeDialogAgentAction-OSYNZRX7.js} +6 -6
  90. package/{runAgentClientLoop-RPEULJFS.js → runAgentClientLoop-6E6UC3CE.js} +30 -28
  91. package/{setDialogExtraReferencesAction-NU2VZ7JZ.js → setDialogExtraReferencesAction-M32UYNCG.js} +5 -5
  92. package/{setPrimaryDialogAgentAction-VUY2FRVL.js → setPrimaryDialogAgentAction-WZ7KI3YA.js} +6 -6
  93. package/{settingSlice-CNE75ISY.js → settingSlice-Q6EKL7EQ.js} +5 -5
  94. package/{spaceCommands-HZUAGZXH.js → spaceCommands-UJOVU4XI.js} +14 -13
  95. package/{streamAgentChatTurn-D5POCPVX.js → streamAgentChatTurn-3UXPYFNX.js} +71 -1268
  96. package/{switchDialogAgentAction-JC27CP72.js → switchDialogAgentAction-GMR7WN3P.js} +4 -4
  97. package/{tools-I6D2B2G6.js → tools-MKYDMWA4.js} +21 -21
  98. package/{tuiSummaryLlmCaller-RVW6CJSK.js → tuiSummaryLlmCaller-3YFNHCTW.js} +7 -7
  99. package/{updateDialogTitleAction-7YZ7FNAK.js → updateDialogTitleAction-UPFV7TDT.js} +12 -12
  100. package/chunk-BJ3KD73I.js +0 -155
  101. package/chunk-JK5XW3NO.js +0 -108
  102. package/chunk-YYKMFBK7.js +0 -306
@@ -4,8 +4,11 @@ import {
4
4
  import {
5
5
  buildForegroundTurnAdmissionFetchInit,
6
6
  consumeAgentRunStream,
7
- projectDesktopToolUiContent
8
- } from "./chunk-YYKMFBK7.js";
7
+ mergeAgentToolsWithRuntime,
8
+ projectDesktopToolUiContent,
9
+ resolveTurnToolContext
10
+ } from "./chunk-TB3MIBRC.js";
11
+ import "./chunk-O2OWEFII.js";
9
12
  import {
10
13
  CONTEXT_OVERFLOW_ACTIONS,
11
14
  CONTEXT_TOO_LARGE_ACTIONS,
@@ -13,14 +16,20 @@ import {
13
16
  } from "./chunk-OCZKATRC.js";
14
17
  import {
15
18
  performServerProxyFetchWithRetry
16
- } from "./chunk-JK5XW3NO.js";
19
+ } from "./chunk-HTVYCXBP.js";
17
20
  import {
18
21
  createSSEParser,
19
22
  resolveAgentRequiredPackIds,
20
23
  waitForAbortableDelay
21
- } from "./chunk-BJ3KD73I.js";
24
+ } from "./chunk-ATLTFRYJ.js";
22
25
  import "./chunk-NF64D32W.js";
23
26
  import "./chunk-3L2WKC3W.js";
27
+ import "./chunk-TXH4IWJL.js";
28
+ import "./chunk-XPRWFQQK.js";
29
+ import "./chunk-UQNS32WZ.js";
30
+ import "./chunk-MEYIRKDN.js";
31
+ import "./chunk-36KZDDO5.js";
32
+ import "./chunk-ZJ7UHBJS.js";
24
33
  import {
25
34
  initMsgs,
26
35
  messageStreamEnd,
@@ -32,14 +41,14 @@ import {
32
41
  setMessages,
33
42
  setStreamingMessageId,
34
43
  updateToolMessage
35
- } from "./chunk-PZ3HKBET.js";
44
+ } from "./chunk-ACQD6YI2.js";
36
45
  import "./chunk-523DITKR.js";
37
46
  import "./chunk-YYLHWIW6.js";
38
47
  import "./chunk-6O4IK4V2.js";
39
48
  import {
40
49
  streamAgentChatTurn
41
- } from "./chunk-UC3Q7X3J.js";
42
- import "./chunk-D76D3RTR.js";
50
+ } from "./chunk-TZZ2WRBL.js";
51
+ import "./chunk-Z4CSIXYP.js";
43
52
  import "./chunk-5RGU3J7P.js";
44
53
  import "./chunk-M76ECQRD.js";
45
54
  import {
@@ -49,6 +58,8 @@ import {
49
58
  } from "./chunk-B6SAMB33.js";
50
59
  import "./chunk-YDH3FDFQ.js";
51
60
  import "./chunk-MX574M24.js";
61
+ import "./chunk-4DPP773Q.js";
62
+ import "./chunk-VIDPVFP3.js";
52
63
  import "./chunk-AGGIDPCZ.js";
53
64
  import "./chunk-B2XUQXQX.js";
54
65
  import {
@@ -56,8 +67,9 @@ import {
56
67
  } from "./chunk-6TPOEJMQ.js";
57
68
  import "./chunk-AUDNYVRC.js";
58
69
  import "./chunk-KHCLMKZZ.js";
59
- import "./chunk-ZSPC3ZTC.js";
60
- import "./chunk-ELYEQNUI.js";
70
+ import "./chunk-PQWU42UQ.js";
71
+ import "./chunk-AKG5W4LG.js";
72
+ import "./chunk-RYZINGPM.js";
61
73
  import "./chunk-PSCNXBYA.js";
62
74
  import "./chunk-L36OWPP3.js";
63
75
  import "./chunk-BYXBJQAS.js";
@@ -66,9 +78,11 @@ import "./chunk-7KVZ5LDQ.js";
66
78
  import "./chunk-HNMXYYJR.js";
67
79
  import "./chunk-3BXNTXYI.js";
68
80
  import "./chunk-W7XHHYWM.js";
69
- import "./chunk-B7ANJQWZ.js";
81
+ import "./chunk-RSEEDUMS.js";
70
82
  import "./chunk-UAD2WT54.js";
71
83
  import "./chunk-ZWQUWF6W.js";
84
+ import "./chunk-HDLLCBRF.js";
85
+ import "./chunk-4VJAC32I.js";
72
86
  import {
73
87
  canonicalizeToolName
74
88
  } from "./chunk-XUWRURDF.js";
@@ -79,22 +93,22 @@ import {
79
93
  } from "./chunk-Y3PMXGLH.js";
80
94
  import {
81
95
  selectCurrentServer
82
- } from "./chunk-3IYMTWYZ.js";
96
+ } from "./chunk-SONWNI3L.js";
83
97
  import "./chunk-Y5GCAMGP.js";
84
98
  import "./chunk-QDSINZM3.js";
85
99
  import "./chunk-KX6YBIHG.js";
86
100
  import {
87
101
  readAndWait,
88
102
  selectById
89
- } from "./chunk-QALRKMHF.js";
90
- import "./chunk-ETZWFV6M.js";
103
+ } from "./chunk-HYZIYH2H.js";
104
+ import "./chunk-7CHC4W22.js";
91
105
  import {
92
106
  createDialogMessageKeyAndId
93
107
  } from "./chunk-3AH7LNUB.js";
94
108
  import "./chunk-WWC7I6TA.js";
95
109
  import "./chunk-QSJ3HFEF.js";
96
- import "./chunk-EFZKILX6.js";
97
- import "./chunk-AUXHZ2M5.js";
110
+ import "./chunk-IAESIMK7.js";
111
+ import "./chunk-WIWM4FE3.js";
98
112
  import {
99
113
  getIsDesktopApp
100
114
  } from "./chunk-QOKAKDPE.js";
@@ -117,13 +131,8 @@ import "./chunk-CF7PE763.js";
117
131
  import "./chunk-G3SUCT4W.js";
118
132
  import "./chunk-4VNS5WPM.js";
119
133
 
120
- // packages/ai/agent/serverOwnedWebForegroundEligibility.ts
121
- var DURABLE_WEB_FOREGROUND_TOOL_NAMES = /* @__PURE__ */ new Set([
122
- "ask_user",
123
- "exa_search",
124
- "fetchWebpage"
125
- ]);
126
- function readToolName(value) {
134
+ // packages/ai/tools/effectiveToolSurface.ts
135
+ function readEffectiveToolName(value) {
127
136
  if (typeof value === "string") {
128
137
  const name2 = canonicalizeToolName(value.trim());
129
138
  return name2 || null;
@@ -134,12 +143,28 @@ function readToolName(value) {
134
143
  const name = canonicalizeToolName(candidate.trim());
135
144
  return name || null;
136
145
  }
137
- function configuredToolNames(agent) {
138
- const values = [];
139
- if (Array.isArray(agent.tools)) values.push(...agent.tools);
140
- if (Array.isArray(agent.toolNames)) values.push(...agent.toolNames);
146
+ function valuesOf(iterable) {
147
+ return iterable ? [...iterable] : [];
148
+ }
149
+ function resolveEffectiveToolSurface(input) {
150
+ const agent = input.agent ?? {};
151
+ const byName = /* @__PURE__ */ new Map();
152
+ const add = (values, source) => {
153
+ for (const value of values) {
154
+ const name = readEffectiveToolName(value);
155
+ if (!name) continue;
156
+ let sources = byName.get(name);
157
+ if (!sources) {
158
+ sources = /* @__PURE__ */ new Set();
159
+ byName.set(name, sources);
160
+ }
161
+ sources.add(source);
162
+ }
163
+ };
164
+ add(Array.isArray(agent.tools) ? agent.tools : [], "explicit");
165
+ add(Array.isArray(agent.toolNames) ? agent.toolNames : [], "explicit");
141
166
  const requiredPackIds = resolveAgentRequiredPackIds(agent);
142
- values.push(...expandEnabledPacks(requiredPackIds));
167
+ add(expandEnabledPacks(requiredPackIds), "required-pack");
143
168
  const policies = [
144
169
  agent.runtimeToolPolicy,
145
170
  agent.runtimeBinding?.runtimeToolPolicy,
@@ -147,38 +172,152 @@ function configuredToolNames(agent) {
147
172
  ];
148
173
  for (const policy of policies) {
149
174
  if (!policy || typeof policy !== "object") continue;
150
- if (Array.isArray(policy.agentTools)) values.push(...policy.agentTools);
151
- if (Array.isArray(policy.runtimeTools)) values.push(...policy.runtimeTools);
175
+ add(Array.isArray(policy.agentTools) ? policy.agentTools : [], "runtime-policy");
176
+ add(Array.isArray(policy.runtimeTools) ? policy.runtimeTools : [], "runtime-policy");
152
177
  }
153
- return [...new Set(values.map(readToolName).filter((name) => !!name))];
154
- }
155
- function hasSupportedDurableToolSurface(agent) {
156
- const policies = [
157
- agent.runtimeToolPolicy,
158
- agent.runtimeBinding?.runtimeToolPolicy,
159
- agent.runtimeBinding?.runtimeToolPolicySnapshot
178
+ add(Array.isArray(agent.referencedTools) ? agent.referencedTools : [], "reference");
179
+ add(valuesOf(input.referencedToolNames), "reference");
180
+ add(valuesOf(input.mentionedToolNames), "mention");
181
+ add(valuesOf(input.hostInjectedToolNames), "host-injected");
182
+ add(valuesOf(input.runtimeExtraToolNames), "runtime-extra");
183
+ const disabled = new Set(
184
+ (Array.isArray(agent.disabledTools) ? agent.disabledTools : []).map(readEffectiveToolName).filter((name) => !!name)
185
+ );
186
+ for (const name of disabled) byName.delete(name);
187
+ const entries = [...byName.entries()].map(
188
+ ([name, sources]) => ({ name, sources: [...sources] })
189
+ );
190
+ const requestedSources = /* @__PURE__ */ new Set([
191
+ "explicit",
192
+ "required-pack",
193
+ "runtime-policy",
194
+ "reference",
195
+ "mention",
196
+ "runtime-extra"
197
+ ]);
198
+ const requestedNames = entries.filter((entry) => entry.sources.some((source) => requestedSources.has(source))).map((entry) => entry.name);
199
+ const hostInjectedNames = entries.filter((entry) => entry.sources.includes("host-injected")).map((entry) => entry.name);
200
+ const shellEnabled = policies.some(
201
+ (policy) => policy && typeof policy === "object" && policy.shell?.enabled === true
202
+ );
203
+ const workspaceModes = [
204
+ ...new Set(
205
+ policies.map(
206
+ (policy) => policy && typeof policy === "object" && typeof policy.workspace?.mode === "string" ? policy.workspace.mode.trim() : ""
207
+ ).filter(Boolean)
208
+ )
160
209
  ];
161
- if (policies.some(
162
- (policy) => policy && typeof policy === "object" && (policy.shell?.enabled === true || policy.workspace?.mode === "lease")
163
- )) {
210
+ return {
211
+ names: entries.map((entry) => entry.name),
212
+ entries,
213
+ requestedNames,
214
+ hostInjectedNames,
215
+ shellEnabled,
216
+ workspaceModes,
217
+ workspaceLease: workspaceModes.includes("lease")
218
+ };
219
+ }
220
+
221
+ // packages/ai/agent/serverOwnedWebForegroundEligibility.ts
222
+ var DURABLE_WEB_FOREGROUND_INTERACTIVE_TOOL_NAMES = /* @__PURE__ */ new Set([
223
+ "ask_user"
224
+ ]);
225
+ var DURABLE_WEB_FOREGROUND_READ_ONLY_TOOL_NAMES = /* @__PURE__ */ new Set([
226
+ // Network read-only tools.
227
+ "exa_search",
228
+ "fetchWebpage",
229
+ // Dialog search backed by the server workspace executor.
230
+ "searchDialogMessages",
231
+ // Nolo workspace read/query tools.
232
+ "listDialogs",
233
+ "readDialog",
234
+ "queryDialogsBySubjectRef",
235
+ "listAgents",
236
+ "readAgent",
237
+ "listSpaces",
238
+ "readSpace",
239
+ "readDoc",
240
+ "readSkillDoc",
241
+ "listTables",
242
+ "queryTableRows"
243
+ ]);
244
+ var DURABLE_WEB_FOREGROUND_TOOL_NAMES = /* @__PURE__ */ new Set([
245
+ ...DURABLE_WEB_FOREGROUND_INTERACTIVE_TOOL_NAMES,
246
+ ...DURABLE_WEB_FOREGROUND_READ_ONLY_TOOL_NAMES
247
+ ]);
248
+ var AUDITED_WEB_FOREGROUND_HOST_BASELINE_TOOL_NAMES = /* @__PURE__ */ new Set([
249
+ // TOOL_PACKS.CORE
250
+ "read",
251
+ "readFile",
252
+ "createDoc",
253
+ "updateDoc",
254
+ "search_workspace",
255
+ "updateSelf",
256
+ "ask_user",
257
+ "createAgentAutomation",
258
+ "updateAgentAutomation",
259
+ "deleteAgentAutomation",
260
+ "notifyUser",
261
+ // ALWAYS_ON_PACK_IDS: long-term-memory + skills
262
+ "queryMemory",
263
+ "rememberMemory",
264
+ "deleteMemory",
265
+ "loadSkill",
266
+ "readSkillDoc",
267
+ // Default system capabilities
268
+ "exa_search",
269
+ "fetchWebpage",
270
+ "setTodoList",
271
+ "startAgentRun",
272
+ "controlAgentRun",
273
+ "listAgents"
274
+ ]);
275
+ function isDurableRequestedToolName(name) {
276
+ return typeof name === "string" && DURABLE_WEB_FOREGROUND_TOOL_NAMES.has(canonicalizeToolName(name));
277
+ }
278
+ function hasSupportedDurableToolSurface(agent, suppliedSurface) {
279
+ const surface = suppliedSurface ?? resolveEffectiveToolSurface({
280
+ agent
281
+ });
282
+ if (surface.shellEnabled || surface.workspaceLease) return false;
283
+ if (!surface.requestedNames.every(isDurableRequestedToolName)) {
164
284
  return false;
165
285
  }
166
- const names = configuredToolNames(agent);
167
- return names.length === 0 || names.every((name) => DURABLE_WEB_FOREGROUND_TOOL_NAMES.has(name));
286
+ return surface.hostInjectedNames.every(
287
+ (name) => AUDITED_WEB_FOREGROUND_HOST_BASELINE_TOOL_NAMES.has(canonicalizeToolName(name))
288
+ );
168
289
  }
169
290
  function shouldUseServerOwnedWebForegroundTurn(input) {
170
291
  if (input.surface !== "web") return false;
171
292
  if (input.isDesktopApp) return false;
172
293
  if (!input.currentServer?.trim() || !input.token?.trim()) return false;
173
294
  if (typeof input.userInput !== "string" || !input.userInput.trim()) return false;
295
+ if (input.turnToolContext) {
296
+ if (!input.turnToolContext.complete) return false;
297
+ if (input.turnToolContext.unresolvedReasons?.length) return false;
298
+ if (!input.effectiveToolSurface) {
299
+ const lateBound = [
300
+ ...input.turnToolContext.referencedToolNames,
301
+ ...input.turnToolContext.mentionedToolNames
302
+ ];
303
+ if (lateBound.some((name) => !isDurableRequestedToolName(name))) {
304
+ return false;
305
+ }
306
+ }
307
+ }
174
308
  const agent = input.agentConfig;
175
309
  if (!agent) return false;
176
310
  if (agent.useServerProxy === false) return false;
177
311
  if (agent.apiSource === "cli") return false;
178
312
  if (agent.runtimeBinding?.machineId) return false;
179
- if (!hasSupportedDurableToolSurface(agent)) return false;
313
+ if (!hasSupportedDurableToolSurface(agent, input.effectiveToolSurface)) return false;
180
314
  const runtimeOptions = input.runtimeOptions;
181
- if (runtimeOptions?.extraTools?.length) return false;
315
+ if (runtimeOptions?.extraTools?.length) {
316
+ if (!input.effectiveToolSurface) return false;
317
+ if (runtimeOptions.extraTools.some((name) => !isDurableRequestedToolName(name))) {
318
+ return false;
319
+ }
320
+ }
182
321
  if (runtimeOptions?.editingTarget) return false;
183
322
  if (runtimeOptions?.imageConfigOverride) return false;
184
323
  if (runtimeOptions?.quickChatModelOverride) return false;
@@ -331,19 +470,55 @@ function createServerOwnedToolProjection(args) {
331
470
  }
332
471
 
333
472
  // packages/ai/agent/serverOwnedWebForegroundHandoff.ts
473
+ function normalizeComparableText(value) {
474
+ if (typeof value === "string") {
475
+ return value.replace(/\r\n/g, "\n").trimEnd();
476
+ }
477
+ if (!Array.isArray(value)) return "";
478
+ return value.flatMap((part) => {
479
+ if (!part || typeof part !== "object") return [];
480
+ const record = part;
481
+ if (record.type === "text" && typeof record.text === "string") {
482
+ return [record.text];
483
+ }
484
+ return [];
485
+ }).join("").replace(/\r\n/g, "\n").trimEnd();
486
+ }
334
487
  function assistantText(message) {
335
- return typeof message.content === "string" ? message.content : "";
488
+ return normalizeComparableText(message.content);
336
489
  }
337
- function findNewCanonicalAssistant(messages, initialMessageIds, transientId, expectedText) {
490
+ function assistantThinking(message) {
491
+ const value = typeof message.thinkContent === "string" ? message.thinkContent : typeof message.reasoning_content === "string" ? message.reasoning_content : "";
492
+ return normalizeComparableText(value);
493
+ }
494
+ function assistantAgentKey(message) {
495
+ const value = message.agentKey ?? message.cybotKey;
496
+ return typeof value === "string" ? value : "";
497
+ }
498
+ function findNewCanonicalAssistant(messages, initialMessageIds, transientId, expectedText, expectedThinking, expectedAgentKey) {
338
499
  const transient = messages.find((message) => message?.id === transientId);
339
- const completedText = expectedText || (transient ? assistantText(transient) : "");
340
- for (const message of messages) {
341
- if (!message?.id || message.id === transientId) continue;
342
- if (initialMessageIds.has(message.id)) continue;
343
- if (message.role !== "assistant") continue;
344
- if (message.isStreaming) continue;
345
- if (completedText && assistantText(message) !== completedText) continue;
346
- return message;
500
+ const completedText = normalizeComparableText(
501
+ expectedText !== void 0 ? expectedText : transient ? assistantText(transient) : ""
502
+ );
503
+ const completedThinking = normalizeComparableText(
504
+ expectedThinking !== void 0 ? expectedThinking : transient ? assistantThinking(transient) : ""
505
+ );
506
+ const candidates = messages.filter((message) => {
507
+ if (!message?.id || message.id === transientId) return false;
508
+ if (initialMessageIds.has(message.id)) return false;
509
+ if (message.role !== "assistant") return false;
510
+ if (message.isStreaming) return false;
511
+ if (completedText) return assistantText(message) === completedText;
512
+ if (completedThinking) return assistantThinking(message) === completedThinking;
513
+ return false;
514
+ });
515
+ if (candidates.length === 0) return null;
516
+ if (candidates.length === 1) return candidates[0] ?? null;
517
+ if (expectedAgentKey) {
518
+ const agentMatches = candidates.filter(
519
+ (message) => assistantAgentKey(message) === expectedAgentKey
520
+ );
521
+ if (agentMatches.length === 1) return agentMatches[0] ?? null;
347
522
  }
348
523
  return null;
349
524
  }
@@ -356,7 +531,9 @@ async function waitForNewCanonicalAssistant(args) {
356
531
  args.readMessages(),
357
532
  args.initialMessageIds,
358
533
  args.transientId,
359
- args.expectedText
534
+ args.expectedText,
535
+ args.expectedThinking,
536
+ args.expectedAgentKey
360
537
  );
361
538
  if (canonical) return canonical;
362
539
  if (Date.now() >= deadline) return null;
@@ -364,18 +541,106 @@ async function waitForNewCanonicalAssistant(args) {
364
541
  }
365
542
  }
366
543
 
544
+ // packages/ai/agent/serverOwnedWebEffectiveToolSurface.ts
545
+ function resolveServerOwnedWebEffectiveToolSurface(args) {
546
+ const referencedToolNames = args.turnToolContext?.referencedToolNames ?? [];
547
+ const mentionedToolNames = args.turnToolContext?.mentionedToolNames ?? [];
548
+ const requested = resolveEffectiveToolSurface({
549
+ agent: args.agentConfig,
550
+ referencedToolNames,
551
+ mentionedToolNames,
552
+ runtimeExtraToolNames: args.runtimeOptions?.extraTools ?? []
553
+ });
554
+ const mergedAgent = mergeAgentToolsWithRuntime(
555
+ args.agentConfig,
556
+ referencedToolNames,
557
+ mentionedToolNames,
558
+ args.runtimeOptions ?? void 0,
559
+ args.state
560
+ );
561
+ const rawNames = (Array.isArray(mergedAgent.tools) ? mergedAgent.tools : []).map(readEffectiveToolName).filter((name) => typeof name === "string" && !!name);
562
+ const finalNames = Array.from(new Set(rawNames));
563
+ const finalSet = new Set(finalNames);
564
+ const requestedSet = new Set(requested.requestedNames);
565
+ const requestedNames = requested.requestedNames.filter((name) => finalSet.has(name));
566
+ const hostInjectedNames = finalNames.filter((name) => !requestedSet.has(name));
567
+ const hostResolved = resolveEffectiveToolSurface({
568
+ agent: args.agentConfig,
569
+ referencedToolNames,
570
+ mentionedToolNames,
571
+ hostInjectedToolNames: hostInjectedNames,
572
+ runtimeExtraToolNames: args.runtimeOptions?.extraTools ?? []
573
+ });
574
+ const entryByName = new Map(hostResolved.entries.map((entry) => [entry.name, entry]));
575
+ const entries = finalNames.flatMap((name) => {
576
+ const entry = entryByName.get(name);
577
+ return entry ? [entry] : [];
578
+ });
579
+ return {
580
+ names: finalNames,
581
+ entries,
582
+ requestedNames,
583
+ hostInjectedNames,
584
+ shellEnabled: hostResolved.shellEnabled,
585
+ workspaceModes: hostResolved.workspaceModes,
586
+ workspaceLease: hostResolved.workspaceLease
587
+ };
588
+ }
589
+
590
+ // packages/ai/agent/serverOwnedAssistantStream.ts
591
+ var EMPTY_SERVER_OWNED_ASSISTANT_STREAM = {
592
+ text: "",
593
+ thinking: "",
594
+ segmentText: "",
595
+ segmentThinking: ""
596
+ };
597
+ function applyServerOwnedAssistantStreamPayload(state, payload) {
598
+ if (payload?.type === "thinking" && typeof payload.content === "string") {
599
+ return {
600
+ ...state,
601
+ thinking: state.thinking + payload.content,
602
+ segmentThinking: state.segmentThinking + payload.content
603
+ };
604
+ }
605
+ if (payload?.type === "text" && typeof payload.content === "string") {
606
+ return {
607
+ ...state,
608
+ text: state.text + payload.content,
609
+ segmentText: state.segmentText + payload.content
610
+ };
611
+ }
612
+ if (payload?.type === "assistant_tool_calls") {
613
+ if (!state.segmentText && !state.segmentThinking) return state;
614
+ return {
615
+ ...state,
616
+ segmentText: "",
617
+ segmentThinking: ""
618
+ };
619
+ }
620
+ return state;
621
+ }
622
+
367
623
  // packages/ai/agent/serverOwnedWebForegroundTurn.ts
624
+ function resolveServerOwnedWebAllowedToolNames(toolNames) {
625
+ return Array.from(
626
+ new Set(
627
+ toolNames.filter((name) => typeof name === "string").map((name) => canonicalizeToolName(name)).filter((name) => DURABLE_WEB_FOREGROUND_TOOL_NAMES.has(name))
628
+ )
629
+ );
630
+ }
368
631
  function detectServerOwnedCandidateSurface() {
369
632
  return typeof window !== "undefined" && typeof document !== "undefined" ? "web" : "non-web";
370
633
  }
371
634
  async function canRunServerOwnedWebForegroundTurn(args, thunk) {
372
635
  try {
636
+ let state;
373
637
  let currentServer;
374
638
  let token;
375
639
  try {
376
- const state = thunk.getState();
640
+ state = thunk.getState();
377
641
  currentServer = selectCurrentServer(state);
378
- token = selectIdentityToken(state);
642
+ const rawToken = selectIdentityToken(state);
643
+ token = typeof rawToken === "string" ? rawToken : void 0;
379
644
  } catch {
380
645
  return { eligible: false };
381
646
  }
@@ -383,23 +648,47 @@ async function canRunServerOwnedWebForegroundTurn(args, thunk) {
383
648
  let agentConfig = args.agentConfig ?? void 0;
384
649
  if (!agentConfig) {
385
650
  try {
386
- const { readAndWait: readAndWait2 } = await import("./dbSlice-HFPIJT5P.js");
651
+ const { readAndWait: readAndWait2 } = await import("./dbSlice-DQ32LYTJ.js");
387
652
  agentConfig = await thunk.dispatch(readAndWait2(args.agentKey)).unwrap();
388
653
  } catch {
389
654
  return { eligible: false };
390
655
  }
391
656
  }
657
+ if (!agentConfig) return { eligible: false };
658
+ const turnToolContext = await resolveTurnToolContext({
659
+ agentConfig,
660
+ dialogConfig: args.dialogConfig,
661
+ userInput: args.userInput,
662
+ state,
663
+ dispatch: thunk.dispatch,
664
+ runtimeOptions: args.runtimeOptions
665
+ });
666
+ const effectiveToolSurface = resolveServerOwnedWebEffectiveToolSurface({
667
+ agentConfig,
668
+ runtimeOptions: args.runtimeOptions,
669
+ state,
670
+ turnToolContext
671
+ });
672
+ const eligible = shouldUseServerOwnedWebForegroundTurn({
673
+ surface: detectServerOwnedCandidateSurface(),
674
+ agentConfig,
675
+ effectiveToolSurface,
676
+ turnToolContext,
677
+ userInput: args.userInput,
678
+ runtimeOptions: args.runtimeOptions,
679
+ currentServer,
680
+ token,
681
+ isDesktopApp: getIsDesktopApp()
682
+ });
683
+ if (!eligible) {
684
+ return { eligible: false, agentConfig };
685
+ }
392
686
  return {
393
- eligible: shouldUseServerOwnedWebForegroundTurn({
394
- surface: detectServerOwnedCandidateSurface(),
395
- agentConfig,
396
- userInput: args.userInput,
397
- runtimeOptions: args.runtimeOptions,
398
- currentServer,
399
- token,
400
- isDesktopApp: getIsDesktopApp()
401
- }),
402
- agentConfig
687
+ eligible: true,
688
+ agentConfig: {
689
+ ...agentConfig,
690
+ tools: resolveServerOwnedWebAllowedToolNames(effectiveToolSurface.names)
691
+ }
403
692
  };
404
693
  } catch {
405
694
  return { eligible: false };
@@ -428,8 +717,9 @@ async function runServerOwnedWebForegroundTurn(args, thunk) {
428
717
  const { key: transientKey, messageId: transientId } = createDialogMessageKeyAndId(dialogId);
429
718
  const controller = new AbortController();
430
719
  const loopKey = `server-owned:${dialogId}:${transientId}`;
431
- let accumulated = "";
720
+ let assistantStream = EMPTY_SERVER_OWNED_ASSISTANT_STREAM;
432
721
  let sawDone = false;
722
+ let clientControllerReleased = false;
433
723
  const toolProjection = createServerOwnedToolProjection({
434
724
  dialogId,
435
725
  dispatch: thunk.dispatch,
@@ -441,18 +731,68 @@ async function runServerOwnedWebForegroundTurn(args, thunk) {
441
731
  supportedToolNames: DURABLE_WEB_FOREGROUND_TOOL_NAMES,
442
732
  keepReadOnlyUntilCanonical: ["ask_user"]
443
733
  });
734
+ const projectAssistant = () => {
735
+ thunk.dispatch(
736
+ messageStreaming({
737
+ id: transientId,
738
+ dialogId,
739
+ dbKey: transientKey,
740
+ role: "assistant",
741
+ content: assistantStream.text,
742
+ thinkContent: assistantStream.thinking,
743
+ cybotKey: args.agentKey,
744
+ agentKey: args.agentKey,
745
+ userId
746
+ })
747
+ );
748
+ };
749
+ const releaseClientController = () => {
750
+ if (clientControllerReleased) return;
751
+ clientControllerReleased = true;
752
+ thunk.dispatch(removeActiveController({ messageId: loopKey, dialogKey }));
753
+ };
754
+ const finishTransientImmediately = () => {
755
+ const transient = selectAllMsgs(thunk.getState(), dialogId).find((message) => message?.id === transientId);
756
+ if (transient) {
757
+ thunk.dispatch(
758
+ setMessages({
759
+ dialogId,
760
+ messages: [{
761
+ ...transient,
762
+ content: assistantStream.text,
763
+ thinkContent: assistantStream.thinking,
764
+ isStreaming: false
765
+ }]
766
+ })
767
+ );
768
+ }
769
+ setStreamingMessageId(dialogId, null);
770
+ };
771
+ const removeTransientWhenCanonicalArrives = () => {
772
+ void waitForNewCanonicalAssistant({
773
+ readMessages: () => selectAllMsgs(thunk.getState(), dialogId),
774
+ initialMessageIds,
775
+ transientId,
776
+ // The server persists a new assistant trace segment after every tool
777
+ // boundary. Fingerprint only the final segment here; the live transient
778
+ // intentionally keeps the concatenated presentation until canonical rows
779
+ // replace it.
780
+ expectedText: assistantStream.segmentText,
781
+ expectedThinking: assistantStream.segmentThinking,
782
+ expectedAgentKey: args.agentKey,
783
+ timeoutMs: 6e4,
784
+ pollMs: 100
785
+ }).then((canonical) => {
786
+ if (!canonical) return;
787
+ toolProjection.cleanup();
788
+ thunk.dispatch(removeTransientMessage({ id: transientId, dialogId }));
789
+ }).catch(() => {
790
+ });
791
+ };
444
792
  thunk.dispatch(addActiveController({ messageId: loopKey, controller, dialogKey }));
445
- thunk.dispatch(
446
- messageStreaming({
447
- id: transientId,
448
- dialogId,
449
- dbKey: transientKey,
450
- role: "assistant",
451
- content: "",
452
- cybotKey: args.agentKey,
453
- agentKey: args.agentKey,
454
- userId
455
- })
793
+ projectAssistant();
794
+ const allowedToolNames = resolveServerOwnedWebAllowedToolNames(
795
+ Array.isArray(args.agentConfig.tools) ? args.agentConfig.tools : []
456
796
  );
457
797
  const body = JSON.stringify({
458
798
  agentKey: args.agentKey,
@@ -472,6 +812,11 @@ async function runServerOwnedWebForegroundTurn(args, thunk) {
472
812
  "client-user-prepersisted",
473
813
  "durable-tool-cards"
474
814
  ],
815
+ // This is the exact post-filter surface produced during admission, not a
816
+ // global durable superset. Server-private defaults and machine tools are
817
+ // injected before this constraint, then intersected back to this turn's
818
+ // admitted names. Direct run() callers are sanitized again above.
819
+ allowedToolNames,
475
820
  ...args.dialogConfig.agentMode === "auto" ? { dialogAgentMode: "auto" } : { dialogAgentMode: "fixed" }
476
821
  },
477
822
  ...args.runtimeOptions ? { runtimeOptions: args.runtimeOptions } : {},
@@ -526,20 +871,13 @@ async function runServerOwnedWebForegroundTurn(args, thunk) {
526
871
  return { reject: payload.message || "Agent execution failed" };
527
872
  }
528
873
  toolProjection.handlePayload(payload);
529
- if (payload?.type === "text" && typeof payload.content === "string") {
530
- accumulated += payload.content;
531
- thunk.dispatch(
532
- messageStreaming({
533
- id: transientId,
534
- dialogId,
535
- dbKey: transientKey,
536
- role: "assistant",
537
- content: accumulated,
538
- cybotKey: args.agentKey,
539
- agentKey: args.agentKey,
540
- userId
541
- })
542
- );
874
+ const nextAssistantStream = applyServerOwnedAssistantStreamPayload(
875
+ assistantStream,
876
+ payload
877
+ );
878
+ if (nextAssistantStream !== assistantStream) {
879
+ assistantStream = nextAssistantStream;
880
+ projectAssistant();
543
881
  }
544
882
  }
545
883
  });
@@ -547,6 +885,7 @@ async function runServerOwnedWebForegroundTurn(args, thunk) {
547
885
  if (outcome.outcome === "rejected") throw new Error(outcome.message);
548
886
  if (!outcome.sawDone) return { serverOwned: true, detached: true };
549
887
  sawDone = true;
888
+ finishTransientImmediately();
550
889
  let canonicalVisible = false;
551
890
  try {
552
891
  await thunk.dispatch(initMsgs({ dialogId })).unwrap();
@@ -554,7 +893,11 @@ async function runServerOwnedWebForegroundTurn(args, thunk) {
554
893
  readMessages: () => selectAllMsgs(thunk.getState(), dialogId),
555
894
  initialMessageIds,
556
895
  transientId,
557
- expectedText: accumulated
896
+ expectedText: assistantStream.segmentText,
897
+ expectedThinking: assistantStream.segmentThinking,
898
+ expectedAgentKey: args.agentKey,
899
+ timeoutMs: 350,
900
+ pollMs: 25
558
901
  });
559
902
  } catch (error) {
560
903
  console.warn("[chat] server-owned canonical handoff refresh failed", {
@@ -567,24 +910,15 @@ async function runServerOwnedWebForegroundTurn(args, thunk) {
567
910
  thunk.dispatch(removeTransientMessage({ id: transientId, dialogId }));
568
911
  } else {
569
912
  toolProjection.cleanup();
570
- const transient = selectAllMsgs(thunk.getState(), dialogId).find((message) => message?.id === transientId);
571
- if (transient) {
572
- thunk.dispatch(
573
- setMessages({
574
- dialogId,
575
- messages: [{ ...transient, isStreaming: false }]
576
- })
577
- );
578
- }
579
- setStreamingMessageId(dialogId, null);
913
+ removeTransientWhenCanonicalArrives();
580
914
  console.warn(
581
- "[chat] server-owned canonical message not visible after done; keeping transient projection",
915
+ "[chat] server-owned canonical message not visible after done; keeping finished transient until canonical arrives",
582
916
  { dialogId, transientId }
583
917
  );
584
918
  }
585
919
  return { serverOwned: true };
586
920
  } finally {
587
- thunk.dispatch(removeActiveController({ messageId: loopKey, dialogKey }));
921
+ releaseClientController();
588
922
  if (!sawDone) {
589
923
  toolProjection.cleanup();
590
924
  thunk.dispatch(removeTransientMessage({ id: transientId, dialogId }));