@tutti-os/agent-gui 0.0.233 → 0.0.235

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 (87) hide show
  1. package/README.md +49 -0
  2. package/dist/{AgentRichTextReadonly-U3XUJYCW.js → AgentRichTextReadonly-CCELQPHE.js} +5 -5
  3. package/dist/agent-conversation/index.d.ts +17 -4
  4. package/dist/agent-conversation/index.js +13 -9
  5. package/dist/agent-conversation/index.js.map +1 -1
  6. package/dist/agent-gui.d.ts +19 -3
  7. package/dist/agent-gui.js +22 -16
  8. package/dist/agent-message-center/index.d.ts +1 -1
  9. package/dist/agent-message-center/index.js +10 -7
  10. package/dist/agent-message-center/index.js.map +1 -1
  11. package/dist/{agentGuiNodeTypes-DW7T--Y8.d.ts → agentGuiNodeTypes-Dgl7kQHA.d.ts} +2 -2
  12. package/dist/agents.d.ts +1 -1
  13. package/dist/app/renderer/agentactivity.css +17 -0
  14. package/dist/{chunk-M6WEFXPL.js → chunk-2MCNNB2P.js} +2 -24
  15. package/dist/chunk-2MCNNB2P.js.map +1 -0
  16. package/dist/{chunk-CQFT3MI5.js → chunk-3YYI6RXA.js} +7 -5
  17. package/dist/{chunk-CQFT3MI5.js.map → chunk-3YYI6RXA.js.map} +1 -1
  18. package/dist/{chunk-EDP4D42H.js → chunk-45KN5Z5F.js} +877 -871
  19. package/dist/chunk-45KN5Z5F.js.map +1 -0
  20. package/dist/{chunk-T57ZZWTC.js → chunk-4HAG3FOY.js} +2 -2
  21. package/dist/{chunk-ZBI6R46N.js → chunk-5DN5N2XS.js} +2 -2
  22. package/dist/{chunk-BCBB4HOV.js → chunk-634MNSI5.js} +2 -2
  23. package/dist/chunk-A4KKC324.js +4768 -0
  24. package/dist/chunk-A4KKC324.js.map +1 -0
  25. package/dist/chunk-ALAGL6VL.js +48 -0
  26. package/dist/chunk-ALAGL6VL.js.map +1 -0
  27. package/dist/{chunk-2STAUA73.js → chunk-AYTUAZE3.js} +5 -2
  28. package/dist/chunk-AYTUAZE3.js.map +1 -0
  29. package/dist/{chunk-SWO67UWQ.js → chunk-CZOZBUIM.js} +7 -7
  30. package/dist/{chunk-SWO67UWQ.js.map → chunk-CZOZBUIM.js.map} +1 -1
  31. package/dist/{chunk-2L2LVSOD.js → chunk-EHNPHZE4.js} +881 -5812
  32. package/dist/chunk-EHNPHZE4.js.map +1 -0
  33. package/dist/{chunk-N5356722.js → chunk-EKQ7UX2B.js} +13 -319
  34. package/dist/chunk-EKQ7UX2B.js.map +1 -0
  35. package/dist/{chunk-ZXEICU6J.js → chunk-KK7YXPTS.js} +3 -1
  36. package/dist/chunk-KK7YXPTS.js.map +1 -0
  37. package/dist/{chunk-WGCDSA7P.js → chunk-MBM7PJIF.js} +27 -506
  38. package/dist/chunk-MBM7PJIF.js.map +1 -0
  39. package/dist/chunk-RMC2MGL4.js +557 -0
  40. package/dist/chunk-RMC2MGL4.js.map +1 -0
  41. package/dist/{chunk-JA6XAKKE.js → chunk-TWF6JXPC.js} +2 -2
  42. package/dist/{chunk-7AYFKNLD.js → chunk-TWMV6YTX.js} +4 -4
  43. package/dist/chunk-VV3YIU5W.js +25 -0
  44. package/dist/chunk-VV3YIU5W.js.map +1 -0
  45. package/dist/{chunk-GLVENTN6.js → chunk-WXLO33YP.js} +2 -2
  46. package/dist/chunk-XWPHTXEM.js +529 -0
  47. package/dist/chunk-XWPHTXEM.js.map +1 -0
  48. package/dist/chunk-YEXRTXTE.js +315 -0
  49. package/dist/chunk-YEXRTXTE.js.map +1 -0
  50. package/dist/{chunk-WMJDOMG6.js → chunk-ZELGKLW5.js} +4 -4
  51. package/dist/composer-projection.d.ts +37 -0
  52. package/dist/composer-projection.js +21 -0
  53. package/dist/composer-projection.js.map +1 -0
  54. package/dist/context-mention-palette/index.js +9 -7
  55. package/dist/conversation-projection.d.ts +551 -0
  56. package/dist/conversation-projection.js +42 -0
  57. package/dist/conversation-projection.js.map +1 -0
  58. package/dist/conversation-rail-projection.js +3 -3
  59. package/dist/i18n/index.d.ts +2 -0
  60. package/dist/i18n/index.js +2 -2
  61. package/dist/index.d.ts +32 -13
  62. package/dist/index.js +22 -16
  63. package/dist/index.js.map +1 -1
  64. package/dist/mention-search.js +7 -5
  65. package/dist/{types-CHAMK2g7.d.ts → types-DtXXsISB.d.ts} +1 -1
  66. package/dist/workbench/contribution.js +4 -4
  67. package/dist/workbench/index.js +4 -4
  68. package/dist/workbench/sessionTitle.js +3 -3
  69. package/dist/workspace-agent-generated-files.d.ts +1 -12
  70. package/dist/workspaceAgentActivityListTypes-BUKNyMbh.d.ts +48 -0
  71. package/dist/{workspaceLinkActions-CzsbvGmC.d.ts → workspaceLinkActions-DxyzMy10.d.ts} +13 -12
  72. package/package.json +29 -15
  73. package/dist/chunk-2L2LVSOD.js.map +0 -1
  74. package/dist/chunk-2STAUA73.js.map +0 -1
  75. package/dist/chunk-EDP4D42H.js.map +0 -1
  76. package/dist/chunk-M6WEFXPL.js.map +0 -1
  77. package/dist/chunk-N5356722.js.map +0 -1
  78. package/dist/chunk-WGCDSA7P.js.map +0 -1
  79. package/dist/chunk-ZXEICU6J.js.map +0 -1
  80. /package/dist/{AgentRichTextReadonly-U3XUJYCW.js.map → AgentRichTextReadonly-CCELQPHE.js.map} +0 -0
  81. /package/dist/{chunk-T57ZZWTC.js.map → chunk-4HAG3FOY.js.map} +0 -0
  82. /package/dist/{chunk-ZBI6R46N.js.map → chunk-5DN5N2XS.js.map} +0 -0
  83. /package/dist/{chunk-BCBB4HOV.js.map → chunk-634MNSI5.js.map} +0 -0
  84. /package/dist/{chunk-JA6XAKKE.js.map → chunk-TWF6JXPC.js.map} +0 -0
  85. /package/dist/{chunk-7AYFKNLD.js.map → chunk-TWMV6YTX.js.map} +0 -0
  86. /package/dist/{chunk-GLVENTN6.js.map → chunk-WXLO33YP.js.map} +0 -0
  87. /package/dist/{chunk-WMJDOMG6.js.map → chunk-ZELGKLW5.js.map} +0 -0
@@ -1,3 +1,14 @@
1
+ import {
2
+ decodeWorkspaceLinkPath,
3
+ isDirectAgentGeneratedMediaPath,
4
+ isInsideOrEqualWorkspaceFilePath,
5
+ isUrlLikeWorkspaceFilePath,
6
+ normalizeWorkspaceFilePath,
7
+ resolveAgentSessionMentionLinkAction,
8
+ resolveWorkspaceFilePathCandidate,
9
+ resolveWorkspaceUrlLinkAction,
10
+ workspaceFilePathBasename
11
+ } from "./chunk-XWPHTXEM.js";
1
12
  import {
2
13
  cn,
3
14
  readParsedDocumentCache,
@@ -7,14 +18,14 @@ import {
7
18
  import {
8
19
  getOptionalAgentHostApi,
9
20
  useOptionalAgentHostApi
10
- } from "./chunk-M6WEFXPL.js";
21
+ } from "./chunk-2MCNNB2P.js";
11
22
  import {
12
23
  managedAgentRoundedIconUrl
13
24
  } from "./chunk-3X5VDG6T.js";
14
25
  import {
15
26
  translate,
16
27
  useTranslation
17
- } from "./chunk-GLVENTN6.js";
28
+ } from "./chunk-WXLO33YP.js";
18
29
  import {
19
30
  resolveAgentWorkspaceFileVisualKind
20
31
  } from "./chunk-5BJYO6X3.js";
@@ -22,243 +33,6 @@ import {
22
33
  getAgentCustomMentionKind
23
34
  } from "./chunk-D2JUDUYY.js";
24
35
 
25
- // shared/agentMcpToolTarget.ts
26
- function extractAgentMcpToolTarget({
27
- input: rawInput,
28
- metadata: rawMetadata,
29
- payload: rawPayload,
30
- toolName
31
- }) {
32
- const payload = objectValue(rawPayload);
33
- const input = objectValue(rawInput) ?? objectValue(payload?.input);
34
- const metadata = objectValue(rawMetadata) ?? objectValue(payload?.metadata);
35
- const toolCall = objectValue(input?.toolCall);
36
- const toolCallRawInput = objectValue(toolCall?.rawInput);
37
- const request = objectValue(input?.request) ?? objectValue(toolCall?.request);
38
- const requestMeta = objectValue(request?._meta);
39
- const parsedToolName = parseMcpToolName(
40
- firstString(toolName, stringValue(metadata?.toolName))
41
- );
42
- const server = firstString(
43
- stringValue(metadata?.server),
44
- stringValue(metadata?.serverName),
45
- stringValue(metadata?.mcpServer),
46
- stringValue(input?.server),
47
- stringValue(input?.server_name),
48
- stringValue(input?.serverName),
49
- stringValue(input?.mcpServer),
50
- stringValue(toolCall?.server),
51
- stringValue(toolCall?.server_name),
52
- stringValue(toolCall?.serverName),
53
- stringValue(toolCallRawInput?.server),
54
- stringValue(toolCallRawInput?.server_name),
55
- stringValue(toolCallRawInput?.serverName),
56
- parsedToolName?.server
57
- );
58
- const tool = firstString(
59
- stringValue(metadata?.toolName),
60
- stringValue(metadata?.tool),
61
- stringValue(input?.tool),
62
- stringValue(input?.toolName),
63
- stringValue(toolCall?.tool),
64
- stringValue(toolCall?.toolName),
65
- stringValue(toolCallRawInput?.tool),
66
- stringValue(toolCallRawInput?.toolName),
67
- parsedToolName?.tool
68
- );
69
- if (!server || !tool) {
70
- return null;
71
- }
72
- return {
73
- server,
74
- tool,
75
- displayName: formatAgentMcpToolTarget({ server, tool }),
76
- instruction: firstString(
77
- formatToolParamsDisplay(requestMeta?.tool_params_display),
78
- formatObjectInstruction(requestMeta?.tool_params),
79
- formatObjectInstruction(input?.arguments),
80
- formatObjectInstruction(toolCallRawInput?.arguments)
81
- ) ?? null
82
- };
83
- }
84
- function formatAgentMcpToolTarget({
85
- server,
86
- tool
87
- }) {
88
- return `${server} / ${tool}`;
89
- }
90
- function parseMcpToolName(value) {
91
- const match = value?.match(/^mcp__([^_]+(?:_[^_]+)*)__(.+)$/i);
92
- if (!match) {
93
- return null;
94
- }
95
- const server = match[1]?.replace(/_/gu, "-").trim();
96
- const tool = match[2]?.trim();
97
- return server && tool ? { server, tool } : null;
98
- }
99
- function firstString(...values) {
100
- return values.find((value) => value !== null && value !== void 0) ?? null;
101
- }
102
- function formatToolParamsDisplay(value) {
103
- if (!Array.isArray(value)) {
104
- return null;
105
- }
106
- const parts = value.flatMap((entry) => {
107
- const record = objectValue(entry);
108
- const name = stringValue(record?.display_name) ?? stringValue(record?.displayName) ?? stringValue(record?.name);
109
- const rawValue = record?.value;
110
- const formattedValue = formatInstructionValue(rawValue);
111
- return name && formattedValue ? [`${name}: ${formattedValue}`] : [];
112
- });
113
- return parts.length > 0 ? parts.join(", ") : null;
114
- }
115
- function formatObjectInstruction(value) {
116
- const record = objectValue(value);
117
- if (!record) {
118
- return stringValue(value);
119
- }
120
- const parts = Object.entries(record).flatMap(([key, rawValue]) => {
121
- const formattedValue = formatInstructionValue(rawValue);
122
- return formattedValue ? [`${key}: ${formattedValue}`] : [];
123
- });
124
- return parts.length > 0 ? parts.join(", ") : null;
125
- }
126
- function formatInstructionValue(value) {
127
- if (typeof value === "string") {
128
- return stringValue(value);
129
- }
130
- if (typeof value === "number" || typeof value === "boolean" || value === null) {
131
- return String(value);
132
- }
133
- if (Array.isArray(value)) {
134
- const parts = value.flatMap((entry) => {
135
- const formattedValue = formatInstructionValue(entry);
136
- return formattedValue ? [formattedValue] : [];
137
- });
138
- return parts.length > 0 ? parts.join(", ") : null;
139
- }
140
- if (objectValue(value)) {
141
- return stableJsonValue(value);
142
- }
143
- return null;
144
- }
145
- function stableJsonValue(value) {
146
- try {
147
- return JSON.stringify(value);
148
- } catch {
149
- return null;
150
- }
151
- }
152
- function stringValue(value) {
153
- return typeof value === "string" && value.trim() ? value.trim() : null;
154
- }
155
- function objectValue(value) {
156
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
157
- }
158
-
159
- // shared/agentConversation/agentApprovalPurpose.ts
160
- function normalizeAgentApprovalPurpose(value) {
161
- return value === "edit-files" ? value : null;
162
- }
163
-
164
- // shared/agentConversation/exitPlanOptions.ts
165
- var EXIT_PLAN_KEEP_PLANNING_OPTION_ID = "plan";
166
- function isExitPlanSwitchModeInput(input) {
167
- const record = recordValue(input);
168
- const toolCall = recordValue(record.toolCall);
169
- if (normalizeToken(stringValue2(toolCall.kind)) !== "switchmode") {
170
- return false;
171
- }
172
- return collectRawOptions(record).some(
173
- (option) => normalizeToken(rawOptionId(option)) === EXIT_PLAN_KEEP_PLANNING_OPTION_ID
174
- );
175
- }
176
- function extractExitPlanModeOptions(input, payload) {
177
- const sources = payload === void 0 ? [recordValue(input)] : [recordValue(input), recordValue(payload)];
178
- return sources.flatMap(collectRawOptions).flatMap((option) => {
179
- const id = rawOptionId(option);
180
- if (!id || normalizeToken(id) === EXIT_PLAN_KEEP_PLANNING_OPTION_ID) {
181
- return [];
182
- }
183
- return [
184
- {
185
- id,
186
- label: stringValue2(option.name) ?? stringValue2(option.label) ?? stringValue2(option.title) ?? stringValue2(option.kind) ?? id,
187
- kind: stringValue2(option.kind) ?? id,
188
- ...stringValue2(option.description) ? { description: stringValue2(option.description) } : {}
189
- }
190
- ];
191
- });
192
- }
193
- function extractExitPlanKeepPlanningOptionId(input, payload) {
194
- const sources = payload === void 0 ? [recordValue(input)] : [recordValue(input), recordValue(payload)];
195
- for (const option of sources.flatMap(collectRawOptions)) {
196
- const id = rawOptionId(option);
197
- if (id && normalizeToken(id) === EXIT_PLAN_KEEP_PLANNING_OPTION_ID) {
198
- return id;
199
- }
200
- }
201
- return null;
202
- }
203
- function collectRawOptions(record) {
204
- return arrayValue(record.options).map(recordValue);
205
- }
206
- function rawOptionId(option) {
207
- return stringValue2(option.optionId) ?? stringValue2(option.id) ?? stringValue2(option.kind) ?? "";
208
- }
209
- function normalizeToken(value) {
210
- return (value ?? "").replace(/[_\s-]+/g, "").trim().toLowerCase();
211
- }
212
- function stringValue2(value) {
213
- return typeof value === "string" && value.trim() ? value.trim() : null;
214
- }
215
- function recordValue(value) {
216
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
217
- }
218
- function arrayValue(value) {
219
- return Array.isArray(value) ? value : [];
220
- }
221
-
222
- // shared/agentConversation/askUserQuestions.ts
223
- function normalizeAskUserQuestions(rawQuestions) {
224
- return arrayValue2(rawQuestions).flatMap((value, index) => {
225
- const question = objectValue2(value);
226
- if (!question) {
227
- return [];
228
- }
229
- return [
230
- {
231
- id: stringValue3(question.id) ?? `question-${index + 1}`,
232
- header: stringValue3(question.header) ?? `Question ${index + 1}`,
233
- question: stringValue3(question.question) ?? stringValue3(question.header) ?? `Question ${index + 1}`,
234
- options: arrayValue2(question.options).flatMap((optionValue) => {
235
- const option = objectValue2(optionValue);
236
- const label = stringValue3(option?.label);
237
- if (!label) {
238
- return [];
239
- }
240
- return [
241
- {
242
- label,
243
- description: stringValue3(option?.description) ?? ""
244
- }
245
- ];
246
- }),
247
- multiSelect: Boolean(question.multiSelect)
248
- }
249
- ];
250
- });
251
- }
252
- function stringValue3(value) {
253
- return typeof value === "string" && value.trim() ? value.trim() : null;
254
- }
255
- function objectValue2(value) {
256
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
257
- }
258
- function arrayValue2(value) {
259
- return Array.isArray(value) ? value : [];
260
- }
261
-
262
36
  // shared/AgentMessageMarkdown.tsx
263
37
  import {
264
38
  useCallback as useCallback4,
@@ -276,104 +50,9 @@ import { resolveWorkspaceFileExtension } from "@tutti-os/workspace-file-preview"
276
50
  import { MentionPill } from "@tutti-os/ui-system/components";
277
51
  import { useResolvedRichTextMention } from "@tutti-os/ui-rich-text/editor";
278
52
 
279
- // shared/utils/websiteUrl.ts
280
- var ALLOWED_WEBSITE_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
281
- var LIKELY_HOST_PATTERN = /^(localhost|(\d{1,3}\.){3}\d{1,3}|(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,})(?::\d{1,5})?(?:[/?#][^\s]*)?$/i;
282
- var EXPLICIT_PROTOCOL_PATTERN = /^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//;
283
- var LOOPBACK_HOST_PATTERN = /^(localhost|127(?:\.\d{1,3}){3})(?::\d{1,5})?(?:[/?#][^\s]*)?$/i;
284
- function defaultSchemeForHostInput(value) {
285
- return LOOPBACK_HOST_PATTERN.test(value) ? "http" : "https";
286
- }
287
- function resolveWebsiteNavigationUrl(rawUrl) {
288
- const trimmed = rawUrl.trim();
289
- if (trimmed.length === 0) {
290
- return { url: null, error: null };
291
- }
292
- if (EXPLICIT_PROTOCOL_PATTERN.test(trimmed)) {
293
- try {
294
- const parsed = new URL(trimmed);
295
- if (!ALLOWED_WEBSITE_PROTOCOLS.has(parsed.protocol)) {
296
- return { url: null, error: `Unsupported protocol: ${parsed.protocol}` };
297
- }
298
- return { url: parsed.toString(), error: null };
299
- } catch {
300
- return { url: null, error: "Invalid URL" };
301
- }
302
- }
303
- if (!LIKELY_HOST_PATTERN.test(trimmed)) {
304
- return { url: null, error: "Invalid URL" };
305
- }
306
- try {
307
- const parsed = new URL(
308
- `${defaultSchemeForHostInput(trimmed)}://${trimmed}`
309
- );
310
- return { url: parsed.toString(), error: null };
311
- } catch {
312
- return { url: null, error: "Invalid URL" };
313
- }
314
- }
315
-
316
53
  // actions/workspaceLinkActions.ts
317
54
  import { parseRichTextMentionHref } from "@tutti-os/ui-rich-text/core";
318
- var URL_LIKE_LINK_PATTERN = /^[a-zA-Z][a-zA-Z\d+.-]*:|^#/;
319
55
  var LOCAL_ASSET_ROOT = "/var/cache/tsh/local-assets";
320
- function resolveWorkspaceFilePathCandidate({
321
- path,
322
- workspaceRoot,
323
- basePath
324
- }) {
325
- const rawPath = decodeWorkspaceLinkPath(path.trim());
326
- if (!rawPath || isUrlLikeWorkspaceFilePath(rawPath) || isUncWorkspaceFilePath(rawPath)) {
327
- return null;
328
- }
329
- const normalizedPath = normalizeWorkspaceFilePath(rawPath);
330
- if (isUnsupportedSpecialWorkspaceFilePath(normalizedPath)) {
331
- return null;
332
- }
333
- if (isStagedLocalAssetPath(normalizedPath)) {
334
- return null;
335
- }
336
- if (isHomeRelativeWorkspaceFilePath(normalizedPath)) {
337
- const directoryPath = dirnameForHomeRelativePath(normalizedPath);
338
- return {
339
- path: normalizedPath,
340
- directoryPath,
341
- workspaceRoot: normalizeWorkspaceFilePath(workspaceRoot?.trim() ?? "") || directoryPath
342
- };
343
- }
344
- if (isAbsoluteLocalPath(normalizedPath) && (isDirectAgentGeneratedMediaPath(normalizedPath) || isDirectWorkspaceAppDataPath(normalizedPath))) {
345
- const directoryPath = dirname(normalizedPath);
346
- return {
347
- path: normalizedPath,
348
- directoryPath,
349
- workspaceRoot: normalizeWorkspaceFilePath(workspaceRoot?.trim() ?? "") || directoryPath
350
- };
351
- }
352
- const selectedRoot = normalizeWorkspaceFilePath(workspaceRoot?.trim() ?? "");
353
- const sessionRoot = normalizeWorkspaceFilePath(basePath?.trim() ?? "");
354
- const root = selectedRoot || sessionRoot;
355
- if (!root) {
356
- return null;
357
- }
358
- if (isAbsoluteLocalPath(normalizedPath)) {
359
- const directoryPath = dirname(normalizedPath);
360
- return {
361
- path: normalizedPath,
362
- directoryPath,
363
- workspaceRoot: root
364
- };
365
- }
366
- const base = normalizeWorkspaceFilePath(basePath?.trim() || root);
367
- const resolvedPath = isAbsoluteLocalPath(normalizedPath) ? normalizedPath : normalizeWorkspaceFilePath(`${base}/${normalizedPath}`);
368
- if (!isInsideOrEqual(resolvedPath, root) && !isDirectAgentGeneratedMediaPath(resolvedPath)) {
369
- return null;
370
- }
371
- return {
372
- path: resolvedPath,
373
- directoryPath: resolvedPath === root ? root : dirname(resolvedPath),
374
- workspaceRoot: root
375
- };
376
- }
377
56
  function resolveWorkspaceFileLinkAction({
378
57
  path,
379
58
  workspaceRoot,
@@ -405,7 +84,7 @@ function resolveLocalAssetPreviewLinkAction({
405
84
  return null;
406
85
  }
407
86
  const resolvedPath = normalizeWorkspaceFilePath(rawPath);
408
- if (resolvedPath === LOCAL_ASSET_ROOT || !isInsideOrEqual(resolvedPath, LOCAL_ASSET_ROOT)) {
87
+ if (resolvedPath === LOCAL_ASSET_ROOT || !isInsideOrEqualWorkspaceFilePath(resolvedPath, LOCAL_ASSET_ROOT)) {
409
88
  return null;
410
89
  }
411
90
  if (resolvedPath.endsWith(".metadata.json")) {
@@ -414,21 +93,7 @@ function resolveLocalAssetPreviewLinkAction({
414
93
  return {
415
94
  type: "open-local-asset-preview",
416
95
  path: resolvedPath,
417
- name: basename(resolvedPath),
418
- source
419
- };
420
- }
421
- function resolveWorkspaceUrlLinkAction({
422
- url,
423
- source
424
- }) {
425
- const resolved = resolveWebsiteNavigationUrl(url);
426
- if (!resolved.url || resolved.error) {
427
- return null;
428
- }
429
- return {
430
- type: "open-url",
431
- url: resolved.url,
96
+ name: workspaceFilePathBasename(resolvedPath),
432
97
  source
433
98
  };
434
99
  }
@@ -452,21 +117,18 @@ function resolveWorkspaceMentionLinkAction({
452
117
  source
453
118
  };
454
119
  }
120
+ const agentSessionAction = resolveAgentSessionMentionLinkAction({
121
+ href,
122
+ source
123
+ });
124
+ if (agentSessionAction) {
125
+ return agentSessionAction;
126
+ }
455
127
  const workspaceId = mention.scope?.workspaceId?.trim() || "";
456
128
  const targetId = mention.entityId.trim();
457
129
  if (!workspaceId || !targetId) {
458
130
  return null;
459
131
  }
460
- if (mention.providerId === "agent-session") {
461
- const agentTargetId = mention.scope?.agentTargetId?.trim() || null;
462
- return {
463
- type: "open-agent-session",
464
- workspaceId,
465
- agentSessionId: targetId,
466
- ...agentTargetId ? { agentTargetId } : {},
467
- source
468
- };
469
- }
470
132
  if (mention.providerId === "workspace-issue") {
471
133
  const mode = parseWorkspaceIssueMentionMode(mention.scope?.mode ?? null);
472
134
  const outputDir = mention.scope?.outputDir?.trim() || "";
@@ -529,140 +191,6 @@ function resolveWorkspaceLinkAction({
529
191
  source
530
192
  }) ?? resolveWorkspaceUrlLinkAction({ url: href, source });
531
193
  }
532
- function normalizeWorkspaceFilePath(path) {
533
- const normalizedPath = path.trim().replaceAll("\\", "/");
534
- const drive = /^[A-Za-z]:/.exec(normalizedPath)?.[0] ?? "";
535
- const startsWithSlash = normalizedPath.startsWith("/");
536
- const pathBody = drive ? normalizedPath.slice(drive.length) : startsWithSlash ? normalizedPath.slice(1) : normalizedPath;
537
- const parts = [];
538
- for (const part of pathBody.split("/")) {
539
- if (!part || part === ".") {
540
- continue;
541
- }
542
- if (part === "..") {
543
- parts.pop();
544
- continue;
545
- }
546
- parts.push(part);
547
- }
548
- if (drive) {
549
- return parts.length > 0 ? `${drive}/${parts.join("/")}` : `${drive}/`;
550
- }
551
- if (startsWithSlash) {
552
- return parts.length > 0 ? `/${parts.join("/")}` : "/";
553
- }
554
- return parts.join("/");
555
- }
556
- function isUrlLikeWorkspaceFilePath(path) {
557
- if (path.startsWith("#")) {
558
- return true;
559
- }
560
- if (isWindowsAbsolutePath(path.trim().replaceAll("\\", "/"))) {
561
- return false;
562
- }
563
- return URL_LIKE_LINK_PATTERN.test(path);
564
- }
565
- function isAbsoluteLocalPath(path) {
566
- return path.startsWith("/") || isWindowsAbsolutePath(path);
567
- }
568
- function isHomeRelativeWorkspaceFilePath(path) {
569
- return path === "~" || path.startsWith("~/");
570
- }
571
- function dirnameForHomeRelativePath(path) {
572
- return path === "~" ? "~" : dirname(path);
573
- }
574
- function isWindowsAbsolutePath(path) {
575
- return /^[A-Za-z]:\//.test(path);
576
- }
577
- function isUncWorkspaceFilePath(path) {
578
- return /^(?:\\\\|\/\/)[^/\\]+[/\\][^/\\]+/.test(path);
579
- }
580
- function isUnsupportedSpecialWorkspaceFilePath(path) {
581
- const comparisonPath = cleanWorkspaceFilePathForComparison(path);
582
- return comparisonPath === "/dev/null" || comparisonPath.split("/").some((segment) => {
583
- const normalized = segment.trim().replace(/[. ]+$/g, "");
584
- const deviceName = normalized.split(".", 1)[0]?.toUpperCase();
585
- return deviceName === "NUL";
586
- });
587
- }
588
- function cleanWorkspaceFilePathForComparison(path) {
589
- const normalized = path.replace(/\/+/g, "/");
590
- const parts = [];
591
- for (const part of normalized.split("/")) {
592
- if (!part || part === ".") {
593
- continue;
594
- }
595
- if (part === "..") {
596
- parts.pop();
597
- continue;
598
- }
599
- parts.push(part);
600
- }
601
- return normalized.startsWith("/") ? `/${parts.join("/")}` : parts.join("/");
602
- }
603
- function decodeWorkspaceLinkPath(path) {
604
- if (!path.includes("%")) {
605
- return path;
606
- }
607
- try {
608
- return decodeURI(path);
609
- } catch {
610
- return path;
611
- }
612
- }
613
- function dirname(path) {
614
- const index = path.lastIndexOf("/");
615
- if (index <= 0) {
616
- return "/";
617
- }
618
- return path.slice(0, index);
619
- }
620
- function basename(path) {
621
- return path.split("/").filter(Boolean).at(-1) ?? path;
622
- }
623
- function isInsideOrEqual(path, root) {
624
- if (root === "/") {
625
- return path.startsWith("/");
626
- }
627
- const comparison = isWindowsAbsolutePath(root) || isWindowsAbsolutePath(path) ? { path: path.toLowerCase(), root: root.toLowerCase() } : { path, root };
628
- return comparison.path === comparison.root || comparison.path.startsWith(`${comparison.root}/`);
629
- }
630
- function isStagedLocalAssetPath(path) {
631
- return path !== LOCAL_ASSET_ROOT && isInsideOrEqual(path, LOCAL_ASSET_ROOT);
632
- }
633
- function isDirectAgentGeneratedMediaPath(path) {
634
- if (!isAbsoluteLocalPath(path)) {
635
- return false;
636
- }
637
- const statePath = getTuttiStatePathSegments(path);
638
- if (!statePath) {
639
- return false;
640
- }
641
- if (statePath[1] !== "agent" || statePath[2] !== "runs" || !statePath.includes("generated_images") && !statePath.includes("generated_videos")) {
642
- return false;
643
- }
644
- return /\.(?:png|jpe?g|gif|webp|bmp|mp4|webm)$/i.test(path);
645
- }
646
- function isDirectWorkspaceAppDataPath(path) {
647
- if (!isAbsoluteLocalPath(path)) {
648
- return false;
649
- }
650
- const statePath = getTuttiStatePathSegments(path);
651
- if (!statePath) {
652
- return false;
653
- }
654
- return statePath[1] === "apps" && statePath[2] === "workspaces" && statePath.length > 5;
655
- }
656
- function getTuttiStatePathSegments(path) {
657
- const segments = path.split("/").filter(Boolean);
658
- const stateRootIndex = segments.findIndex(
659
- (segment) => segment === ".tutti" || segment === ".tutti-dev"
660
- );
661
- if (stateRootIndex < 0) {
662
- return null;
663
- }
664
- return segments.slice(stateRootIndex);
665
- }
666
194
 
667
195
  // shared/streamingMarkdownTailStabilizer.ts
668
196
  var DEFAULT_MAX_TAIL_CHARS = 4096;
@@ -1117,7 +645,7 @@ function isHomeRelativePath(path) {
1117
645
  const candidate = path.trim();
1118
646
  return candidate.length > 0 && !/\s/.test(candidate) && (candidate === "~" || candidate.startsWith("~/") || candidate.startsWith("~\\"));
1119
647
  }
1120
- function isWindowsAbsolutePath2(path) {
648
+ function isWindowsAbsolutePath(path) {
1121
649
  const candidate = path.trim();
1122
650
  return /^[A-Za-z]:[\\/]/.test(candidate) && !/\s/.test(candidate);
1123
651
  }
@@ -1126,7 +654,7 @@ function isExplicitWorkspaceFilePath(path) {
1126
654
  if (!candidate || candidate.includes("://")) {
1127
655
  return false;
1128
656
  }
1129
- return isLocalAbsolutePath(candidate) || isHomeRelativePath(candidate) || isWindowsAbsolutePath2(candidate);
657
+ return isLocalAbsolutePath(candidate) || isHomeRelativePath(candidate) || isWindowsAbsolutePath(candidate);
1130
658
  }
1131
659
  function isClickableMarkdownHref(href) {
1132
660
  const target = href.trim();
@@ -3147,8 +2675,8 @@ function resolveWorkspaceFileMentionEntryKind(path, label, explicitKind) {
3147
2675
  if (resolveWorkspaceFileExtension(path)) {
3148
2676
  return "file";
3149
2677
  }
3150
- const basename2 = basenameWorkspacePath2(path);
3151
- return basename2 === label ? "directory" : "file";
2678
+ const basename = basenameWorkspacePath2(path);
2679
+ return basename === label ? "directory" : "file";
3152
2680
  }
3153
2681
  function parseWorkspaceFileMentionLink(href, rawLabel) {
3154
2682
  const label = rawLabel.trim();
@@ -3745,13 +3273,6 @@ var styles = {
3745
3273
  var AgentGUIConversation_styles_default = styles;
3746
3274
 
3747
3275
  export {
3748
- extractAgentMcpToolTarget,
3749
- normalizeAgentApprovalPurpose,
3750
- isExitPlanSwitchModeInput,
3751
- extractExitPlanModeOptions,
3752
- extractExitPlanKeepPlanningOptionId,
3753
- normalizeAskUserQuestions,
3754
- resolveWorkspaceFilePathCandidate,
3755
3276
  resolveWorkspaceFileLinkAction,
3756
3277
  resolveWorkspaceLinkAction,
3757
3278
  blobToBase64,
@@ -3761,4 +3282,4 @@ export {
3761
3282
  AgentMessageMarkdown,
3762
3283
  CustomScrollArea
3763
3284
  };
3764
- //# sourceMappingURL=chunk-WGCDSA7P.js.map
3285
+ //# sourceMappingURL=chunk-MBM7PJIF.js.map