@tutti-os/agent-gui 0.0.94 → 0.0.95

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 (153) hide show
  1. package/README.md +48 -32
  2. package/dist/AgentGUI-CwBLYtv-.d.ts +992 -0
  3. package/dist/agent-conversation/index.d.ts +5 -7
  4. package/dist/agent-conversation/index.js +12 -8
  5. package/dist/agent-conversation/index.js.map +1 -1
  6. package/dist/agent-env/index.d.ts +10 -36
  7. package/dist/agent-env/index.js +1 -56
  8. package/dist/agent-env/index.js.map +1 -1
  9. package/dist/agent-gui.d.ts +21 -0
  10. package/dist/agent-gui.js +39 -0
  11. package/dist/agent-message-center/index.d.ts +145 -124
  12. package/dist/agent-message-center/index.js +1374 -1316
  13. package/dist/agent-message-center/index.js.map +1 -1
  14. package/dist/{agentConversationVM-Cl4G0Lln.d.ts → agentConversationVM-C335TR6S.d.ts} +112 -7
  15. package/dist/agentFileMentionContracts-Czvz6YMI.d.ts +107 -0
  16. package/dist/{agentGuiNodeTypes-CAioPXK9.d.ts → agentGuiNodeTypes-DppADPHW.d.ts} +96 -148
  17. package/dist/agentPlanPromptDispatch-C7cCMjve.d.ts +37 -0
  18. package/dist/agents.d.ts +13 -0
  19. package/dist/agents.js +13 -0
  20. package/dist/app/renderer/agentactivity.css +126 -80
  21. package/dist/app/renderer/assets/icons/agent-vinyls/tutti-vinyl.png +0 -0
  22. package/dist/app/renderer/assets/icons/open-link-lined.svg +4 -0
  23. package/dist/{chunk-P72YLKC6.js → chunk-3R2D4E57.js} +3127 -3398
  24. package/dist/chunk-3R2D4E57.js.map +1 -0
  25. package/dist/chunk-4YG7YK7S.js +23 -0
  26. package/dist/chunk-4YG7YK7S.js.map +1 -0
  27. package/dist/chunk-5X7YDOC6.js +42 -0
  28. package/dist/chunk-5X7YDOC6.js.map +1 -0
  29. package/dist/{chunk-IBIMGLCD.js → chunk-7J4K6WKB.js} +1 -1
  30. package/dist/chunk-7J4K6WKB.js.map +1 -0
  31. package/dist/{chunk-BXVPOGYK.js → chunk-7PFDA2HQ.js} +505 -504
  32. package/dist/chunk-7PFDA2HQ.js.map +1 -0
  33. package/dist/{chunk-AWAIUYG4.js → chunk-7RDD3EWP.js} +513 -555
  34. package/dist/chunk-7RDD3EWP.js.map +1 -0
  35. package/dist/{chunk-UBDPV34P.js → chunk-AOS2VWU6.js} +1355 -1305
  36. package/dist/chunk-AOS2VWU6.js.map +1 -0
  37. package/dist/{chunk-E5FOXRUM.js → chunk-BFNJKTDV.js} +295 -255
  38. package/dist/chunk-BFNJKTDV.js.map +1 -0
  39. package/dist/{chunk-5FE7M42A.js → chunk-BIHBXWK5.js} +2 -2
  40. package/dist/{chunk-7BUYFVRI.js → chunk-C5FV4UGI.js} +2921 -2944
  41. package/dist/chunk-C5FV4UGI.js.map +1 -0
  42. package/dist/{chunk-SCLLP5DO.js → chunk-CRO2MV2Y.js} +36 -46
  43. package/dist/chunk-CRO2MV2Y.js.map +1 -0
  44. package/dist/chunk-FGLQZ6I4.js +9 -0
  45. package/dist/chunk-FGLQZ6I4.js.map +1 -0
  46. package/dist/chunk-H6IQ63DQ.js +14 -0
  47. package/dist/chunk-H6IQ63DQ.js.map +1 -0
  48. package/dist/{chunk-IGY4ASUF.js → chunk-JX2SIXNL.js} +1293 -1702
  49. package/dist/chunk-JX2SIXNL.js.map +1 -0
  50. package/dist/chunk-KAL4XZMA.js +231 -0
  51. package/dist/chunk-KAL4XZMA.js.map +1 -0
  52. package/dist/chunk-KJQERFKX.js +259 -0
  53. package/dist/chunk-KJQERFKX.js.map +1 -0
  54. package/dist/chunk-LQVXBT65.js +491 -0
  55. package/dist/chunk-LQVXBT65.js.map +1 -0
  56. package/dist/{chunk-554VG7ZW.js → chunk-NITOD7WF.js} +2 -2
  57. package/dist/{chunk-7LMJXF4R.js → chunk-NJAZ7LQM.js} +20 -16
  58. package/dist/chunk-NJAZ7LQM.js.map +1 -0
  59. package/dist/chunk-NX3CZJXW.js +25 -0
  60. package/dist/chunk-NX3CZJXW.js.map +1 -0
  61. package/dist/chunk-O6W72SEP.js +93 -0
  62. package/dist/chunk-O6W72SEP.js.map +1 -0
  63. package/dist/chunk-RY6GIO3K.js +31700 -0
  64. package/dist/chunk-RY6GIO3K.js.map +1 -0
  65. package/dist/{chunk-XDV4ZRVK.js → chunk-UGVI47X6.js} +98 -37
  66. package/dist/chunk-UGVI47X6.js.map +1 -0
  67. package/dist/{chunk-XW4CVBUH.js → chunk-UQJPV6HP.js} +18 -11
  68. package/dist/chunk-UQJPV6HP.js.map +1 -0
  69. package/dist/{chunk-GAPTLVII.js → chunk-VF22EG3F.js} +1 -1
  70. package/dist/{chunk-GAPTLVII.js.map → chunk-VF22EG3F.js.map} +1 -1
  71. package/dist/{chunk-45FF4DQU.js → chunk-WEDMAVX2.js} +22 -24
  72. package/dist/chunk-WEDMAVX2.js.map +1 -0
  73. package/dist/{chunk-MATIJPGF.js → chunk-XMO45GKA.js} +531 -401
  74. package/dist/chunk-XMO45GKA.js.map +1 -0
  75. package/dist/{chunk-ZUW4B5AT.js → chunk-YE25HN6T.js} +6 -9
  76. package/dist/chunk-YE25HN6T.js.map +1 -0
  77. package/dist/context-mention-palette/index.d.ts +3 -2
  78. package/dist/context-mention-palette/index.js +19 -14
  79. package/dist/custom-mention.d.ts +44 -0
  80. package/dist/custom-mention.js +17 -0
  81. package/dist/custom-mention.js.map +1 -0
  82. package/dist/dock-icons.d.ts +6 -0
  83. package/dist/dock-icons.js +11 -0
  84. package/dist/dock-icons.js.map +1 -0
  85. package/dist/i18n/index.d.ts +850 -841
  86. package/dist/i18n/index.js +2 -2
  87. package/dist/index.d.ts +52 -1061
  88. package/dist/index.js +72 -35530
  89. package/dist/index.js.map +1 -1
  90. package/dist/mention-search.d.ts +226 -0
  91. package/dist/mention-search.js +29 -0
  92. package/dist/mention-search.js.map +1 -0
  93. package/dist/open-link-lined-JWEKUKME.svg +4 -0
  94. package/dist/provider-icons.d.ts +6 -0
  95. package/dist/provider-icons.js +12 -0
  96. package/dist/provider-icons.js.map +1 -0
  97. package/dist/provider-identity.d.ts +9 -0
  98. package/dist/provider-identity.js +21 -0
  99. package/dist/provider-identity.js.map +1 -0
  100. package/dist/runtime-BBNdWgDU.d.ts +10 -0
  101. package/dist/{types-PLFZ8SBX.d.ts → types-DX2bxgB8.d.ts} +28 -83
  102. package/dist/workbench/contribution.d.ts +32 -40
  103. package/dist/workbench/contribution.js +10 -6
  104. package/dist/workbench/index.d.ts +3 -2
  105. package/dist/workbench/index.js +24 -20
  106. package/dist/workbench/launch.d.ts +2 -5
  107. package/dist/workbench/launch.js +4 -3
  108. package/dist/workbench/providerCatalog.js +2 -1
  109. package/dist/workbench/sessionTitle.d.ts +4 -3
  110. package/dist/workbench/sessionTitle.js +4 -3
  111. package/dist/workbench/state.d.ts +1 -1
  112. package/dist/workbench/state.js +3 -2
  113. package/dist/workbench/types.d.ts +0 -3
  114. package/dist/workbench/types.js +1 -1
  115. package/dist/workspace-agent-generated-files.d.ts +20 -2
  116. package/dist/workspace-agent-generated-files.js +7 -6
  117. package/dist/workspaceAgentActivityListTypes-C7gPWYiA.d.ts +71 -0
  118. package/package.json +63 -26
  119. package/dist/AgentMentionSearchController-DD_WOred.d.ts +0 -241
  120. package/dist/AgentMessageMarkdown-DeYPURtF.d.ts +0 -7
  121. package/dist/chunk-45FF4DQU.js.map +0 -1
  122. package/dist/chunk-4HP6V2YA.js +0 -207
  123. package/dist/chunk-4HP6V2YA.js.map +0 -1
  124. package/dist/chunk-7BUYFVRI.js.map +0 -1
  125. package/dist/chunk-7LMJXF4R.js.map +0 -1
  126. package/dist/chunk-AWAIUYG4.js.map +0 -1
  127. package/dist/chunk-BXVPOGYK.js.map +0 -1
  128. package/dist/chunk-E5FOXRUM.js.map +0 -1
  129. package/dist/chunk-IBIMGLCD.js.map +0 -1
  130. package/dist/chunk-IGY4ASUF.js.map +0 -1
  131. package/dist/chunk-LR4FA5X6.js +0 -368
  132. package/dist/chunk-LR4FA5X6.js.map +0 -1
  133. package/dist/chunk-MATIJPGF.js.map +0 -1
  134. package/dist/chunk-MKHDRIGN.js +0 -71
  135. package/dist/chunk-MKHDRIGN.js.map +0 -1
  136. package/dist/chunk-P72YLKC6.js.map +0 -1
  137. package/dist/chunk-SCLLP5DO.js.map +0 -1
  138. package/dist/chunk-UBDPV34P.js.map +0 -1
  139. package/dist/chunk-VAKFNNKT.js +0 -410
  140. package/dist/chunk-VAKFNNKT.js.map +0 -1
  141. package/dist/chunk-XDV4ZRVK.js.map +0 -1
  142. package/dist/chunk-XW4CVBUH.js.map +0 -1
  143. package/dist/chunk-ZUW4B5AT.js.map +0 -1
  144. package/dist/plan-decision-ops.d.ts +0 -70
  145. package/dist/plan-decision-ops.js +0 -19
  146. package/dist/queued-prompt-runtime.d.ts +0 -115
  147. package/dist/queued-prompt-runtime.js +0 -9
  148. package/dist/workspaceAgentActivityListViewModel-BzV-cf0D.d.ts +0 -340
  149. package/dist/workspaceLinkActions-DS9LWqzI.d.ts +0 -74
  150. /package/dist/{plan-decision-ops.js.map → agent-gui.js.map} +0 -0
  151. /package/dist/{queued-prompt-runtime.js.map → agents.js.map} +0 -0
  152. /package/dist/{chunk-5FE7M42A.js.map → chunk-BIHBXWK5.js.map} +0 -0
  153. /package/dist/{chunk-554VG7ZW.js.map → chunk-NITOD7WF.js.map} +0 -0
@@ -1,3 +1,10 @@
1
+ import {
2
+ agentGuiWorkbenchDockIdentityFromIdentifier,
3
+ agentGuiWorkbenchProviderFromIdentifier,
4
+ agentGuiWorkbenchTypeId,
5
+ agentGuiWorkbenchUnifiedDockEntryId,
6
+ createAgentGuiWorkbenchLaunchDescriptor
7
+ } from "./chunk-NJAZ7LQM.js";
1
8
  import {
2
9
  agentGuiWorkbenchProviderFromInstanceId,
3
10
  agentGuiWorkbenchProviderFromInstanceIdOrNull,
@@ -5,38 +12,31 @@ import {
5
12
  migrateLegacyAgentGuiWorkbenchState,
6
13
  normalizeAgentGuiWorkbenchNodeState,
7
14
  normalizeAgentGuiWorkbenchState
8
- } from "./chunk-45FF4DQU.js";
9
- import {
10
- agentGuiWorkbenchDockIdentityFromIdentifier,
11
- agentGuiWorkbenchProviderFromIdentifier,
12
- agentGuiWorkbenchTypeId,
13
- agentGuiWorkbenchUnifiedDockEntryId,
14
- createAgentGuiWorkbenchLaunchDescriptor
15
- } from "./chunk-7LMJXF4R.js";
15
+ } from "./chunk-WEDMAVX2.js";
16
16
  import {
17
17
  agentGuiWorkbenchDefaultDockProviders,
18
18
  isAgentGuiWorkbenchProvider,
19
19
  resolveAgentGuiWorkbenchProviderLabel
20
- } from "./chunk-XW4CVBUH.js";
20
+ } from "./chunk-UQJPV6HP.js";
21
+ import {
22
+ normalizeAgentGUIAgents,
23
+ projectAgentGUIAgentsToInternalTargets
24
+ } from "./chunk-O6W72SEP.js";
25
+ import {
26
+ agentGuiDockIconUrls
27
+ } from "./chunk-4YG7YK7S.js";
28
+ import {
29
+ normalizeManagedAgentProvider
30
+ } from "./chunk-H6IQ63DQ.js";
21
31
  import {
22
- claudeRoundedUrl,
23
- codexRoundedUrl,
24
- cursorColorfulUrl,
25
- cursorRoundedUrl,
26
- hermesRoundedUrl,
27
- manageAgentClaudeCodeUrl,
28
- manageAgentTuttiUrl,
29
- normalizeManagedAgentProvider,
30
- openclawRoundedUrl,
31
- opencodeRoundedUrl,
32
- tuttiAgentRoundedUrl
33
- } from "./chunk-XDV4ZRVK.js";
32
+ resolveAgentGUIProviderCatalogIdentity
33
+ } from "./chunk-KJQERFKX.js";
34
+ import {
35
+ resolveProviderIconAsset
36
+ } from "./chunk-UGVI47X6.js";
34
37
 
35
38
  // workbench/contribution.ts
36
- import { createElement as createElement2 } from "react";
37
- import {
38
- getWorkbenchLayoutFrame
39
- } from "@tutti-os/workbench-surface";
39
+ import { createElement as createElement3 } from "react";
40
40
 
41
41
  // agent-gui/agentGuiNode/model/agentGuiRailLayout.ts
42
42
  function clamp(value, min, max) {
@@ -118,66 +118,18 @@ function resolveAgentGUIExpandedWindowFrame(input) {
118
118
  };
119
119
  }
120
120
 
121
- // dockIcons.ts
122
- var agentGuiDockIconUrl = codexRoundedUrl;
123
- var agentGuiDockIconUrls = {
124
- "claude-code": manageAgentClaudeCodeUrl,
125
- codex: codexRoundedUrl,
126
- cursor: cursorRoundedUrl,
127
- hermes: hermesRoundedUrl,
128
- nexight: manageAgentTuttiUrl,
129
- openclaw: openclawRoundedUrl,
130
- opencode: opencodeRoundedUrl,
131
- "tutti-agent": tuttiAgentRoundedUrl
132
- };
133
-
134
- // app/renderer/assets/icons/agents/claudecode-flat-filled.svg
135
- var claudecode_flat_filled_default = "./claudecode-flat-filled-NHO4JCVK.svg";
136
-
137
- // app/renderer/assets/icons/agents/codex-flat-filled.svg
138
- var codex_flat_filled_default = "./codex-flat-filled-WYHCF5VR.svg";
139
-
140
- // app/renderer/assets/icons/agents/cursor-flat-filled.svg
141
- var cursor_flat_filled_default = "./cursor-flat-filled-CL7N3BTZ.svg";
142
-
143
- // app/renderer/assets/icons/agents/opencode-flat-filled.svg
144
- var opencode_flat_filled_default = "./opencode-flat-filled-CYAJPX45.svg";
145
-
146
- // app/renderer/assets/icons/agents/tutti-flat-filled.svg
147
- var tutti_flat_filled_default = "./tutti-flat-filled-K32QBTZE.svg";
148
-
149
121
  // agentGuiSessionProviderIconUrls.ts
150
122
  function resolveAgentGuiSessionProviderIconUrl(provider) {
151
- switch (normalizeManagedAgentProvider(provider)) {
152
- case "claude-code":
153
- return claudeRoundedUrl;
154
- case "codex":
155
- return codexRoundedUrl;
156
- case "cursor":
157
- return cursorColorfulUrl;
158
- case "opencode":
159
- return opencodeRoundedUrl;
160
- case "tutti":
161
- return manageAgentTuttiUrl;
162
- default:
163
- return null;
164
- }
123
+ const identity = resolveAgentGUIProviderCatalogIdentity(
124
+ normalizeManagedAgentProvider(provider)
125
+ );
126
+ return resolveProviderIconAsset(identity?.iconKey, "sessionColorful");
165
127
  }
166
128
  function resolveAgentGuiSessionProviderFlatIconUrl(provider) {
167
- switch (normalizeManagedAgentProvider(provider)) {
168
- case "claude-code":
169
- return claudecode_flat_filled_default;
170
- case "codex":
171
- return codex_flat_filled_default;
172
- case "cursor":
173
- return cursor_flat_filled_default;
174
- case "opencode":
175
- return opencode_flat_filled_default;
176
- case "tutti":
177
- return tutti_flat_filled_default;
178
- default:
179
- return null;
180
- }
129
+ const identity = resolveAgentGUIProviderCatalogIdentity(
130
+ normalizeManagedAgentProvider(provider)
131
+ );
132
+ return resolveProviderIconAsset(identity?.iconKey, "sessionFlat");
181
133
  }
182
134
 
183
135
  // workbench/bodyRenderErrorRegistry.ts
@@ -227,7 +179,6 @@ import {
227
179
  createElement,
228
180
  useState
229
181
  } from "react";
230
- import { ExternalLink } from "lucide-react";
231
182
  import {
232
183
  Button,
233
184
  PanelIcon,
@@ -238,6 +189,11 @@ import {
238
189
  cn
239
190
  } from "@tutti-os/ui-system";
240
191
  import { CreateChatIcon } from "@tutti-os/ui-system/icons";
192
+
193
+ // app/renderer/assets/icons/open-link-lined.svg
194
+ var open_link_lined_default = "./open-link-lined-JWEKUKME.svg";
195
+
196
+ // workbench/header.ts
241
197
  var headerChromeIconButtonClassName = "agent-gui-workbench-header__icon-button";
242
198
  var conversationRailToggleButtonClassName = "agent-gui-workbench-header__icon-button agent-gui-workbench-header__rail-toggle";
243
199
  var detachedWindowButtonClassName = "agent-gui-workbench-header__icon-button agent-gui-workbench-header__detached-window";
@@ -261,6 +217,7 @@ function AgentGuiWorkbenchHeader({
261
217
  onOpenDetachedWindow,
262
218
  onToggleConversationRail,
263
219
  showAppTitle = true,
220
+ showConversationRailToggle = true,
264
221
  showWindowControls = true,
265
222
  title: _title,
266
223
  windowActions,
@@ -354,48 +311,16 @@ function AgentGuiWorkbenchHeader({
354
311
  label: copy.openDetachedWindow ?? "Open in detached window",
355
312
  onOpenDetachedWindow
356
313
  }) : null,
357
- createElement(
358
- Button,
359
- {
360
- "aria-label": toggleLabel,
361
- className: conversationRailToggleButtonClassName,
362
- "data-agent-gui-conversation-rail-auto-collapsed": isConversationRailAutoCollapsed ? "true" : void 0,
363
- "data-agent-gui-conversation-rail-collapsed": isConversationRailCollapsed ? "true" : void 0,
364
- "data-testid": "agent-gui-toggle-conversation-rail",
365
- size: "icon-sm",
366
- title: toggleLabel,
367
- type: "button",
368
- variant: "ghost",
369
- onClick: (event) => {
370
- event.stopPropagation();
371
- onToggleConversationRail(!isConversationRailCollapsed);
372
- },
373
- onDoubleClick: (event) => event.stopPropagation(),
374
- onPointerDown: (event) => event.stopPropagation()
375
- },
376
- createElement(PanelIcon, { className: headerChromeIconClassName })
377
- ),
378
- isConversationRailCollapsed && onCreateConversation ? createElement(
379
- Button,
380
- {
381
- "aria-label": copy.newConversation,
382
- className: headerChromeIconButtonClassName,
383
- size: "icon-sm",
384
- title: copy.newConversation,
385
- type: "button",
386
- variant: "ghost",
387
- onClick: (event) => {
388
- event.stopPropagation();
389
- onCreateConversation();
390
- },
391
- onDoubleClick: (event) => event.stopPropagation(),
392
- onPointerDown: (event) => event.stopPropagation()
393
- },
394
- createElement(CreateChatIcon, {
395
- "aria-hidden": true,
396
- className: headerChromeIconClassName
397
- })
398
- ) : null,
314
+ showConversationRailToggle ? createConversationRailToggleButton({
315
+ isAutoCollapsed: isConversationRailAutoCollapsed,
316
+ isCollapsed: isConversationRailCollapsed,
317
+ label: toggleLabel,
318
+ onToggleConversationRail
319
+ }) : null,
320
+ isConversationRailCollapsed && onCreateConversation ? createNewConversationButton({
321
+ label: copy.newConversation,
322
+ onCreateConversation
323
+ }) : null,
399
324
  isConversationRailCollapsed && sessionTitle ? createElement(
400
325
  "span",
401
326
  {
@@ -456,6 +381,43 @@ function AgentGuiWorkbenchHeader({
456
381
  ) : null
457
382
  );
458
383
  }
384
+ function createConversationRailToggleButton({
385
+ isAutoCollapsed,
386
+ isCollapsed,
387
+ label,
388
+ onToggleConversationRail
389
+ }) {
390
+ const button = createElement(
391
+ Button,
392
+ {
393
+ "aria-label": label,
394
+ className: conversationRailToggleButtonClassName,
395
+ "data-agent-gui-conversation-rail-auto-collapsed": isAutoCollapsed ? "true" : void 0,
396
+ "data-agent-gui-conversation-rail-collapsed": isCollapsed ? "true" : void 0,
397
+ "data-testid": "agent-gui-toggle-conversation-rail",
398
+ size: "icon-sm",
399
+ type: "button",
400
+ variant: "ghost",
401
+ onClick: (event) => {
402
+ event.stopPropagation();
403
+ onToggleConversationRail(!isCollapsed);
404
+ },
405
+ onDoubleClick: (event) => event.stopPropagation(),
406
+ onPointerDown: (event) => event.stopPropagation()
407
+ },
408
+ createElement(PanelIcon, { className: headerChromeIconClassName })
409
+ );
410
+ return createElement(TooltipProvider, {
411
+ children: createElement(
412
+ Tooltip,
413
+ null,
414
+ createElement(TooltipTrigger, { asChild: true }, button),
415
+ createElement(TooltipContent, { side: "bottom" }, label)
416
+ ),
417
+ delayDuration: 250,
418
+ skipDelayDuration: 0
419
+ });
420
+ }
459
421
  function createDetachedWindowButton({
460
422
  label,
461
423
  onOpenDetachedWindow
@@ -476,7 +438,55 @@ function createDetachedWindowButton({
476
438
  onDoubleClick: (event) => event.stopPropagation(),
477
439
  onPointerDown: (event) => event.stopPropagation()
478
440
  },
479
- createElement(ExternalLink, {
441
+ createElement("span", {
442
+ "aria-hidden": true,
443
+ className: headerChromeIconClassName,
444
+ "data-agent-gui-icon": "open-link-lined",
445
+ style: {
446
+ backgroundColor: "currentColor",
447
+ display: "block",
448
+ WebkitMaskImage: `url("${open_link_lined_default}")`,
449
+ WebkitMaskPosition: "center",
450
+ WebkitMaskRepeat: "no-repeat",
451
+ WebkitMaskSize: "contain",
452
+ maskImage: `url("${open_link_lined_default}")`,
453
+ maskPosition: "center",
454
+ maskRepeat: "no-repeat",
455
+ maskSize: "contain"
456
+ }
457
+ })
458
+ );
459
+ return createElement(TooltipProvider, {
460
+ children: createElement(
461
+ Tooltip,
462
+ null,
463
+ createElement(TooltipTrigger, { asChild: true }, button),
464
+ createElement(TooltipContent, { side: "bottom" }, label)
465
+ ),
466
+ delayDuration: 250,
467
+ skipDelayDuration: 0
468
+ });
469
+ }
470
+ function createNewConversationButton({
471
+ label,
472
+ onCreateConversation
473
+ }) {
474
+ const button = createElement(
475
+ Button,
476
+ {
477
+ "aria-label": label,
478
+ className: headerChromeIconButtonClassName,
479
+ size: "icon-sm",
480
+ type: "button",
481
+ variant: "ghost",
482
+ onClick: (event) => {
483
+ event.stopPropagation();
484
+ onCreateConversation();
485
+ },
486
+ onDoubleClick: (event) => event.stopPropagation(),
487
+ onPointerDown: (event) => event.stopPropagation()
488
+ },
489
+ createElement(CreateChatIcon, {
480
490
  "aria-hidden": true,
481
491
  className: headerChromeIconClassName
482
492
  })
@@ -588,93 +598,11 @@ var trafficLightIconPathByName = {
588
598
  unfullscreen: "M20.793 12C21.2384 12.0001 21.4614 12.5386 21.1465 12.8536L12.8536 21.1465C12.5386 21.4614 12.0001 21.2384 12.0001 20.793V12.5C12.0001 12.2239 12.2239 12 12.5001 12H20.793ZM11.1465 2.85356C11.4615 2.53864 12 2.76166 12.0001 3.20708V11.5C12 11.7761 11.7762 12 11.5001 12H3.20708C2.76166 12 2.53864 11.4615 2.85357 11.1465L11.1465 2.85356Z"
589
599
  };
590
600
 
591
- // agents.ts
592
- function normalizeAgentGUIAgents(agents) {
593
- const normalized = [];
594
- const seenAgentTargetIds = /* @__PURE__ */ new Set();
595
- for (const agent of agents ?? []) {
596
- const agentTargetId = agent.agentTargetId.trim();
597
- const name = agent.name.trim();
598
- const iconUrl = agent.iconUrl.trim();
599
- if (!agentTargetId || !name || !iconUrl || seenAgentTargetIds.has(agentTargetId)) {
600
- continue;
601
- }
602
- seenAgentTargetIds.add(agentTargetId);
603
- const ownerName = agent.owner?.name?.trim() ?? "";
604
- const ownerAvatarUrl = agent.owner?.avatarUrl?.trim() ?? "";
605
- const reason = agent.availability.reason?.trim() ?? "";
606
- normalized.push({
607
- agentTargetId,
608
- name,
609
- iconUrl,
610
- ...agent.description?.trim() ? { description: agent.description.trim() } : {},
611
- ...ownerName || ownerAvatarUrl ? {
612
- owner: {
613
- ...ownerName ? { name: ownerName } : {},
614
- ...ownerAvatarUrl ? { avatarUrl: ownerAvatarUrl } : {}
615
- }
616
- } : {},
617
- availability: {
618
- status: normalizeAgentGUIAgentAvailabilityStatus(
619
- agent.availability.status
620
- ),
621
- ...reason ? { reason } : {},
622
- ...agent.availability.pendingAction ? { pendingAction: agent.availability.pendingAction } : {}
623
- },
624
- provider: agent.provider
625
- });
626
- }
627
- return normalized;
628
- }
629
- function agentGUIAgentIsReady(agent) {
630
- return agent.availability.status === "ready";
631
- }
632
- function resolveAgentGUISelectedDirectoryAgent(input) {
633
- const explicitAgentTargetId = input.agentTargetId?.trim() || input.defaultAgentTargetId?.trim() || "";
634
- if (explicitAgentTargetId) {
635
- return input.agents.find(
636
- (agent) => agent.agentTargetId === explicitAgentTargetId
637
- ) ?? null;
638
- }
639
- return input.agents.find((agent) => agentGUIAgentIsReady(agent)) ?? input.agents[0] ?? null;
640
- }
641
- function projectAgentGUIAgentsToInternalTargets(agents) {
642
- return agents.map((agent) => ({
643
- targetId: agent.agentTargetId,
644
- agentTargetId: agent.agentTargetId,
645
- provider: agent.provider,
646
- ref: {
647
- kind: "agent-directory",
648
- provider: agent.provider,
649
- agentTargetId: agent.agentTargetId
650
- },
651
- label: agent.name,
652
- ...agent.description ? { description: agent.description } : {},
653
- iconUrl: agent.iconUrl,
654
- ...agent.owner?.avatarUrl ? {
655
- badge: {
656
- iconUrl: agent.owner.avatarUrl,
657
- ...agent.owner.name ? { label: agent.owner.name } : {}
658
- }
659
- } : {},
660
- ...agent.owner?.name ? { ownerLabel: agent.owner.name } : {},
661
- ...agent.availability.status !== "ready" ? { disabled: true } : {},
662
- ...agent.availability.reason ? { unavailableReason: agent.availability.reason } : {}
663
- }));
664
- }
665
- function normalizeAgentGUIAgentAvailabilityStatus(status) {
666
- switch (status) {
667
- case "ready":
668
- case "checking":
669
- case "coming_soon":
670
- case "not_installed":
671
- case "auth_required":
672
- case "unavailable":
673
- return status;
674
- }
675
- }
676
-
677
- // workbench/contribution.ts
601
+ // workbench/contributionDock.tsx
602
+ import { createElement as createElement2 } from "react";
603
+ import {
604
+ getWorkbenchLayoutFrame
605
+ } from "@tutti-os/workbench-surface";
678
606
  var agentGuiWorkbenchDefaultNodeFrame = {
679
607
  height: 560,
680
608
  width: 1040,
@@ -692,13 +620,10 @@ var agentGuiWorkbenchUnifiedDockTileProviders = [
692
620
  "tutti-agent",
693
621
  "hermes"
694
622
  ];
695
- var AGENT_GUI_WORKBENCH_CONVERSATION_RAIL_TOGGLE_EVENT = "tutti:agent-gui-workbench-conversation-rail-toggle";
696
- var AGENT_GUI_WORKBENCH_NEW_CONVERSATION_EVENT = "tutti:agent-gui-workbench-new-conversation";
697
- var AGENT_GUI_WORKBENCH_OPEN_EXTERNAL_IMPORT_EVENT = "tutti:agent-gui-workbench-open-external-import";
698
623
  var agentGuiWorkbenchDefaultCopy = {
699
- collapseConversationRail: "Collapse conversation rail",
624
+ collapseConversationRail: "Hide sidebar",
700
625
  close: "Close",
701
- expandConversationRail: "Expand conversation rail",
626
+ expandConversationRail: "Show sidebar",
702
627
  fallbackAgentLabel: "Agent",
703
628
  maximize: "Maximize",
704
629
  minimize: "Minimize",
@@ -707,293 +632,26 @@ var agentGuiWorkbenchDefaultCopy = {
707
632
  openDetachedWindow: "Open in detached window",
708
633
  restore: "Restore"
709
634
  };
710
- function createAgentGuiWorkbenchContribution(input) {
711
- const nodeStateSource = createAgentGuiWorkbenchNodeStateSource({
712
- workspaceId: input.workspaceId
713
- });
714
- const frame = input.frame ?? agentGuiWorkbenchDefaultNodeFrame;
715
- const copy = resolveAgentGuiWorkbenchContributionCopy(input.copy);
716
- return {
717
- dockEntries: buildAgentGuiDockEntries({
718
- defaultProvider: input.defaultProvider,
719
- defaultAgentTargetId: input.defaultAgentTargetId,
720
- dockIconUrls: input.dockIconUrls,
721
- label: copy.nodeTitle,
722
- providerAvailability: input.providerAvailability,
723
- agentsLoading: input.agentsLoading,
724
- renderPreview: input.renderPreview,
725
- resolveDockPopupIdentity: input.resolveDockPopupIdentity,
726
- resolveDockPopupTitle: input.resolveDockPopupTitle,
727
- sectionId: input.dockSectionId ?? "agents",
728
- agents: input.agents,
729
- unifiedDockIconUrl: input.unifiedDockIconUrl
730
- }),
731
- externalStateSource: nodeStateSource.externalStateSource,
732
- id: input.id ?? "workspace-agent-gui",
733
- nodes: [
734
- {
735
- frame,
736
- instance: { mode: "multi" },
737
- onBodyRenderErrorChange: ({ hasError, node }) => {
738
- setAgentGuiWorkbenchBodyRenderError(node.id, hasError);
739
- },
740
- renderBody: (context) => input.renderBody(
741
- context,
742
- {
743
- nodeTypeId: agentGuiWorkbenchTypeId,
744
- onStateChange: (state) => {
745
- nodeStateSource.writeNodeState({
746
- instanceId: context.instanceId,
747
- nodeId: context.node.id,
748
- state,
749
- typeId: agentGuiWorkbenchTypeId
750
- });
751
- },
752
- provider: providerFromActivation(context.activation) ?? agentGuiWorkbenchProviderFromInstanceId(context.instanceId)
753
- }
754
- ),
755
- renderHeader: ({
756
- activation,
757
- dragHandleProps,
758
- displayMode,
759
- externalNodeState,
760
- instanceId,
761
- isFocused,
762
- node,
763
- surfaceSize,
764
- windowActions
765
- }) => {
766
- const provider = providerFromActivation(activation) ?? agentGuiWorkbenchProviderFromInstanceId(instanceId);
767
- const headerTitle = copy.nodeTitle;
768
- const rawWorkbenchState = externalNodeState ?? node.data.runtimeNodeState;
769
- const migratedWorkbenchState = migrateLegacyAgentGuiWorkbenchState(rawWorkbenchState);
770
- const workbenchState = normalizeAgentGuiWorkbenchState(
771
- migratedWorkbenchState
772
- );
773
- const nodeState = normalizeAgentGuiWorkbenchNodeState(
774
- migratedWorkbenchState,
775
- provider
776
- );
777
- const isConversationRailAutoCollapsed = shouldAutoCollapseAgentGUIConversationRail(node.frame.width);
778
- const isConversationRailCollapsed = nodeState.conversationRailCollapsed === true || isConversationRailAutoCollapsed;
779
- const conversationRailWidthPx = clampAgentGUIConversationRailWidthPx(
780
- nodeState.conversationRailWidthPx,
781
- node.frame.width
782
- );
783
- const conversationIdentity = input.resolveDockPopupIdentity?.(workbenchState) ?? null;
784
- const conversationTitle = conversationIdentity?.title ?? input.resolveDockPopupTitle?.(workbenchState) ?? workbenchState.lastActiveConversationTitle ?? null;
785
- const iconProvider = providerFromActivation(activation) ?? agentGuiWorkbenchProviderFromInstanceIdOrNull(instanceId);
786
- const conversationIconFallbackUrl = iconProvider ? resolveAgentGuiSessionProviderIconUrl(iconProvider) ?? resolveAgentGuiWorkbenchProviderIconUrl({
787
- dockIconUrls: input.dockIconUrls,
788
- provider: iconProvider
789
- }) : null;
790
- const conversationIconUrl = conversationIdentity?.iconUrl ?? conversationIconFallbackUrl;
791
- const persistConversationRailCollapsed = (collapsed) => {
792
- nodeStateSource.writeNodeState({
793
- instanceId,
794
- nodeId: node.id,
795
- state: {
796
- ...workbenchState,
797
- conversationRailCollapsed: collapsed
798
- },
799
- typeId: agentGuiWorkbenchTypeId
800
- });
801
- };
802
- const announceConversationRailCollapsed = (collapsed) => {
803
- window.dispatchEvent(
804
- new CustomEvent(
805
- AGENT_GUI_WORKBENCH_CONVERSATION_RAIL_TOGGLE_EVENT,
806
- {
807
- detail: {
808
- conversationRailCollapsed: collapsed,
809
- instanceId
810
- }
811
- }
812
- )
813
- );
814
- };
815
- const announceNewConversation = () => {
816
- window.dispatchEvent(
817
- new CustomEvent(
818
- AGENT_GUI_WORKBENCH_NEW_CONVERSATION_EVENT,
819
- {
820
- detail: {
821
- instanceId
822
- }
823
- }
824
- )
825
- );
826
- };
827
- return createElement2(AgentGuiWorkbenchHeader, {
828
- copy,
829
- conversationIconUrl,
830
- conversationIconFallbackUrl,
831
- conversationTitle,
832
- conversationRailWidthPx,
833
- displayMode,
834
- isConversationRailAutoCollapsed,
835
- isConversationRailCollapsed,
836
- nodeId: node.id,
837
- providerRailWidthPx: agentGuiWorkbenchProviderRailWidthPx,
838
- title: headerTitle,
839
- windowActions: {
840
- close: windowActions.close,
841
- minimize: windowActions.minimize,
842
- toggleDisplayMode: windowActions.toggleDisplayMode
843
- },
844
- ...dragHandleProps,
845
- onCreateConversation: announceNewConversation,
846
- onOpenDetachedWindow: input.onOpenDetachedWindow ? () => {
847
- void input.onOpenDetachedWindow?.({
848
- agentSessionId: workbenchState.lastActiveAgentSessionId,
849
- agentTargetId: nodeState.agentTargetId,
850
- agents: input.agents ?? void 0,
851
- provider,
852
- workspaceId: input.workspaceId
853
- });
854
- } : void 0,
855
- onPointerDown: (event) => {
856
- dragHandleProps.onPointerDown?.(event);
857
- if (!isFocused) {
858
- windowActions.focus();
859
- }
860
- },
861
- onToggleConversationRail: (nextCollapsed) => {
862
- announceConversationRailCollapsed(nextCollapsed);
863
- if (isConversationRailCollapsed && nextCollapsed === false && node.displayMode !== "fullscreen") {
864
- const expandedFrame = resolveAgentGUIExpandedWindowFrame({
865
- conversationRailWidthPx: nodeState.conversationRailWidthPx,
866
- desktopSize: surfaceSize,
867
- height: node.frame.height,
868
- position: {
869
- x: node.frame.x,
870
- y: node.frame.y
871
- },
872
- width: node.frame.width
873
- });
874
- windowActions.resize({
875
- ...node.frame,
876
- height: expandedFrame.size.height,
877
- width: expandedFrame.size.width,
878
- x: expandedFrame.position.x,
879
- y: expandedFrame.position.y
880
- });
881
- }
882
- persistConversationRailCollapsed(nextCollapsed);
883
- }
884
- });
885
- },
886
- title: copy.nodeTitle,
887
- typeId: agentGuiWorkbenchTypeId,
888
- window: {
889
- closable: true,
890
- defaultOpen: false,
891
- minimizedDock: {
892
- kind: "component",
893
- providePreview: (item) => createAgentGuiWorkbenchPreviewContent({
894
- item,
895
- renderPreview: input.renderMinimizedPreview,
896
- resolveDockPopupTitle: input.resolveDockPopupTitle
897
- })
898
- },
899
- minimizable: true
900
- }
901
- }
902
- ],
903
- onLaunchRequest: (request) => {
904
- if (request.typeId !== agentGuiWorkbenchTypeId) {
905
- return null;
906
- }
907
- const launchPayload = resolveAgentGuiWorkbenchLaunchPayload(request, {
908
- resolveDockLaunchPayload: input.resolveDockLaunchPayload
909
- });
910
- const {
911
- activation,
912
- dockEntryId,
913
- instanceId: descriptorInstanceId,
914
- openInNewWindow,
915
- reuseDockEntryNode,
916
- reuseExistingSessionNode,
917
- targetAgentSessionId
918
- } = createAgentGuiWorkbenchLaunchDescriptor({
919
- ...request,
920
- payload: launchPayload
921
- });
922
- const existingInstanceId = targetAgentSessionId && reuseExistingSessionNode ? nodeStateSource.findInstanceIdByAgentSessionId(targetAgentSessionId) : null;
923
- const instanceId = existingInstanceId ?? descriptorInstanceId;
924
- const title = copy.nodeTitle;
925
- const launchTarget = agentTargetLaunchPayloadFromRequest(launchPayload);
926
- const launchAgentTargetId = launchTarget.agentTargetId;
927
- if (targetAgentSessionId) {
928
- const previousState = nodeStateSource.readNodeState({
929
- instanceId,
930
- typeId: agentGuiWorkbenchTypeId
931
- });
932
- nodeStateSource.writeNodeState({
933
- instanceId,
934
- state: {
935
- ...normalizeAgentGuiWorkbenchState(previousState),
936
- ...targetAgentSessionId ? { lastActiveAgentSessionId: targetAgentSessionId } : {},
937
- agentTargetId: launchAgentTargetId ?? null
938
- },
939
- typeId: agentGuiWorkbenchTypeId
940
- });
941
- } else if (launchAgentTargetId) {
942
- const previousState = nodeStateSource.readNodeState({
943
- instanceId,
944
- typeId: agentGuiWorkbenchTypeId
945
- });
946
- nodeStateSource.writeNodeState({
947
- instanceId,
948
- state: {
949
- ...normalizeAgentGuiWorkbenchState(previousState),
950
- lastActiveAgentSessionId: null,
951
- agentTargetId: launchAgentTargetId
952
- },
953
- typeId: agentGuiWorkbenchTypeId
954
- });
955
- }
956
- const defaultFrame = resolveAgentGuiWorkbenchDefaultLaunchFrame({
957
- frame,
958
- request
959
- });
960
- return {
961
- activation,
962
- ...openInNewWindow ? { cascadeOffset: agentGuiWorkbenchNewWindowCascadeOffset } : {},
963
- defaultFrame,
964
- dockEntryId,
965
- framePolicy: !openInNewWindow && isAgentGuiWorkbenchCompactVisibleFrame(defaultFrame, frame) ? "absolute" : "cascade-same-type-centered",
966
- instanceId,
967
- // Reusing the window already showing this specific conversation
968
- // (e.g. clicking a completion notification) should just focus it,
969
- // not reset it back to the default size/position.
970
- preserveExistingNodeFrame: existingInstanceId !== null,
971
- reuseDockEntryNode,
972
- title,
973
- typeId: agentGuiWorkbenchTypeId
974
- };
975
- }
976
- };
977
- }
978
- function buildAgentGuiDockEntries(input) {
979
- const sectionId = input.sectionId ?? "agents";
980
- const launchPayload = resolveAgentGuiUnifiedDockLaunchPayload(input);
981
- const provider = launchPayload.provider;
982
- const unifiedTileIconUrls = resolveAgentGuiUnifiedDockTileIconUrls(
983
- input.dockIconUrls
984
- );
985
- return [
986
- createAgentGuiWorkbenchDockEntry({
987
- aggregateProviders: agentGuiWorkbenchDefaultDockProviders,
988
- icon: input.unifiedDockIconUrl ? createAgentGuiWorkbenchUnifiedDockIcon({
989
- iconUrl: input.unifiedDockIconUrl
990
- }) : createAgentGuiWorkbenchLaunchpadStyleDockIcon({
991
- tileIconUrls: unifiedTileIconUrls
992
- }),
993
- label: input.label ?? agentGuiWorkbenchDefaultCopy.nodeTitle,
994
- launchPayload,
995
- order: 0,
996
- provider,
635
+ function buildAgentGuiDockEntries(input) {
636
+ const sectionId = input.sectionId ?? "agents";
637
+ const launchPayload = resolveAgentGuiUnifiedDockLaunchPayload(input);
638
+ const provider = launchPayload.provider;
639
+ const unifiedTileIconUrls = resolveAgentGuiUnifiedDockTileIconUrls(
640
+ input.dockIconUrls
641
+ );
642
+ return [
643
+ createAgentGuiWorkbenchDockEntry({
644
+ agentDirectory: input.agentDirectory,
645
+ aggregateProviders: agentGuiWorkbenchDefaultDockProviders,
646
+ icon: input.unifiedDockIconUrl ? createAgentGuiWorkbenchUnifiedDockIcon({
647
+ iconUrl: input.unifiedDockIconUrl
648
+ }) : createAgentGuiWorkbenchLaunchpadStyleDockIcon({
649
+ tileIconUrls: unifiedTileIconUrls
650
+ }),
651
+ label: input.label ?? agentGuiWorkbenchDefaultCopy.nodeTitle,
652
+ launchPayload,
653
+ order: 0,
654
+ provider,
997
655
  renderPreview: input.renderPreview,
998
656
  resolveDockPopupIdentity: input.resolveDockPopupIdentity,
999
657
  resolveDockPopupTitle: input.resolveDockPopupTitle,
@@ -1007,7 +665,7 @@ function resolveAgentGuiUnifiedDockLaunchPayload(input) {
1007
665
  if (target) {
1008
666
  return {
1009
667
  provider: target.provider,
1010
- agentTargetId: target.agentTargetId
668
+ agentTargetId: target.agentTargetId ?? target.targetId
1011
669
  };
1012
670
  }
1013
671
  return {
@@ -1050,11 +708,6 @@ function createAgentGuiWorkbenchDockEntry(input) {
1050
708
  label: input.label,
1051
709
  launchBehavior: "enabled",
1052
710
  launchPayload: input.launchPayload ?? { provider: input.provider },
1053
- // A normal dock launch reuses the node already showing this provider/target
1054
- // (its instanceId is target-keyed). The popup's explicit "New window" action
1055
- // must instead always open a fresh window, so hand it a payload that flags
1056
- // openInNewWindow — the launch descriptor then derives a unique panel
1057
- // instanceId and cascades the new window off the existing one.
1058
711
  newWindowLaunchPayload: {
1059
712
  ...input.launchPayload ?? { provider: input.provider },
1060
713
  openInNewWindow: true
@@ -1063,6 +716,9 @@ function createAgentGuiWorkbenchDockEntry(input) {
1063
716
  if (node.data.typeId !== agentGuiWorkbenchTypeId) {
1064
717
  return false;
1065
718
  }
719
+ if (input.aggregateProviders && (agentGuiWorkbenchDockIdentityFromIdentifier(node.data.instanceId)?.kind === "unifiedAggregate" || agentGuiWorkbenchDockIdentityFromIdentifier(node.data.dockEntryId)?.kind === "unifiedAggregate")) {
720
+ return true;
721
+ }
1066
722
  const provider = resolveAgentGuiWorkbenchProviderFromNodeIdentityOrNull(node);
1067
723
  if (!provider) {
1068
724
  return false;
@@ -1071,6 +727,7 @@ function createAgentGuiWorkbenchDockEntry(input) {
1071
727
  },
1072
728
  order: input.order,
1073
729
  providePopupItemPreview: (item) => input.renderPreview ? createAgentGuiWorkbenchPreviewContent({
730
+ agentDirectory: input.agentDirectory,
1074
731
  item,
1075
732
  label: input.label,
1076
733
  provider: input.provider,
@@ -1155,45 +812,56 @@ function providerFromActivation(activation) {
1155
812
  return providerFromState(payload);
1156
813
  }
1157
814
  function resolveAgentGuiWorkbenchLaunchPayload(request, input) {
1158
- if (request.reason !== "dock" || agentGuiWorkbenchDockIdentityFromIdentifier(request.dockEntryId)?.kind !== "unifiedAggregate" || !isEmptyAgentGuiWorkbenchDockLaunchPayload(request.payload)) {
815
+ if (hasAgentSessionId(request.payload)) {
1159
816
  return request.payload;
1160
817
  }
1161
- const resolved = input.resolveDockLaunchPayload?.({
1162
- dockEntryId: request.dockEntryId,
1163
- payload: request.payload,
1164
- reason: request.reason
1165
- }) ?? request.payload;
1166
- if (isOpenInNewWindowLaunchPayload(request.payload) && resolved && typeof resolved === "object" && !Array.isArray(resolved)) {
1167
- return { ...resolved, openInNewWindow: true };
818
+ const snapshot = input.agentDirectory.getSnapshot();
819
+ const agents = normalizeAgentGUIAgents(snapshot.agents);
820
+ const payload = isRecord(request.payload) ? request.payload : {};
821
+ const isUnifiedDockLaunch = request.reason === "dock" && agentGuiWorkbenchDockIdentityFromIdentifier(request.dockEntryId)?.kind === "unifiedAggregate";
822
+ const explicitAgentTargetId = isUnifiedDockLaunch ? null : readTrimmedString(payload.agentTargetId);
823
+ if (explicitAgentTargetId) {
824
+ const explicitAgent = agents.find(
825
+ (agent) => agent.agentTargetId === explicitAgentTargetId && agent.availability.status === "ready"
826
+ );
827
+ if (!explicitAgent || !isAgentGuiWorkbenchProvider(explicitAgent.provider)) {
828
+ return null;
829
+ }
830
+ return {
831
+ ...payload,
832
+ agentTargetId: explicitAgent.agentTargetId,
833
+ provider: explicitAgent.provider
834
+ };
835
+ }
836
+ const requestedProvider = providerFromState(payload);
837
+ const resolved = resolveAgentGuiUnifiedDockLaunchPayload({
838
+ agentDirectory: input.agentDirectory,
839
+ defaultProvider: requestedProvider ?? input.defaultProvider,
840
+ providerAvailability: input.providerAvailability
841
+ });
842
+ if (!resolved.agentTargetId) {
843
+ return null;
1168
844
  }
1169
- return resolved;
845
+ return { ...payload, ...resolved };
1170
846
  }
1171
- function isOpenInNewWindowLaunchPayload(payload) {
1172
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
847
+ function hasAgentSessionId(payload) {
848
+ if (!isRecord(payload)) {
1173
849
  return false;
1174
850
  }
1175
- return payload.openInNewWindow === true;
851
+ return readTrimmedString(payload.agentSessionId) !== null;
1176
852
  }
1177
- function isEmptyAgentGuiWorkbenchDockLaunchPayload(payload) {
1178
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
1179
- return true;
1180
- }
1181
- const typed = payload;
1182
- return typeof typed.agentSessionId !== "string" && typeof typed.draftPrompt !== "string";
853
+ function isRecord(value) {
854
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
855
+ }
856
+ function readTrimmedString(value) {
857
+ return typeof value === "string" && value.trim() ? value.trim() : null;
1183
858
  }
1184
859
  function resolveUnifiedAgentGuiDockTarget(input) {
1185
- const targets = normalizeAgentGUIAgents(input.agents).filter(
1186
- (target) => isAgentGuiWorkbenchProvider(target.provider) && isUnifiedAgentGuiDockProvider(target.provider) && target.availability.status === "ready" && isAgentGuiProviderAvailable(target.provider, input.providerAvailability)
860
+ const targets = projectAgentGUIAgentsToInternalTargets(
861
+ normalizeAgentGUIAgents(input.agentDirectory.getSnapshot().agents)
862
+ ).filter(
863
+ (target) => isAgentGuiWorkbenchProvider(target.provider) && isUnifiedAgentGuiDockProvider(target.provider) && target.disabled !== true && isAgentGuiProviderAvailable(target.provider, input.providerAvailability)
1187
864
  );
1188
- const defaultAgentTargetId = input.defaultAgentTargetId?.trim();
1189
- if (defaultAgentTargetId) {
1190
- const explicitTarget = targets.find(
1191
- (target) => target.agentTargetId === defaultAgentTargetId
1192
- );
1193
- if (explicitTarget) {
1194
- return explicitTarget;
1195
- }
1196
- }
1197
865
  if (input.defaultProvider && isUnifiedAgentGuiDockProvider(input.defaultProvider) && isAgentGuiProviderAvailable(
1198
866
  input.defaultProvider,
1199
867
  input.providerAvailability
@@ -1229,8 +897,8 @@ function isUnifiedAgentGuiDockProvider(provider) {
1229
897
  );
1230
898
  }
1231
899
  function preferredAgentGuiDockTargetForProvider(targets, provider) {
1232
- const agents = targets.filter((target) => target.provider === provider);
1233
- return agents[0] ?? null;
900
+ const agentTargets = targets.filter((target) => target.provider === provider);
901
+ return agentTargets[0] ?? null;
1234
902
  }
1235
903
  function isAgentGuiProviderAvailable(provider, availability) {
1236
904
  const value = availability?.[provider];
@@ -1248,15 +916,16 @@ function isAgentGuiProviderAvailable(provider, availability) {
1248
916
  }
1249
917
  return value.status === "ready" || value.status === "available";
1250
918
  }
1251
- function agentTargetLaunchPayloadFromRequest(payload) {
919
+ function providerTargetLaunchPayloadFromRequest(payload, _expectedProvider) {
1252
920
  if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
1253
921
  return {
1254
922
  agentTargetId: null
1255
923
  };
1256
924
  }
1257
925
  const agentTargetId = payload.agentTargetId;
926
+ const providerTargetId = payload.providerTargetId;
1258
927
  return {
1259
- agentTargetId: typeof agentTargetId === "string" && agentTargetId.trim() ? agentTargetId.trim() : null
928
+ agentTargetId: typeof agentTargetId === "string" && agentTargetId.trim() ? agentTargetId.trim() : typeof providerTargetId === "string" && providerTargetId.trim() ? providerTargetId.trim() : null
1260
929
  };
1261
930
  }
1262
931
  function createAgentGuiWorkbenchPreviewContent(input) {
@@ -1272,6 +941,7 @@ function createAgentGuiWorkbenchPreviewContent(input) {
1272
941
  element: input.renderPreview(
1273
942
  createAgentGuiWorkbenchPreviewBodyContext(input.item),
1274
943
  {
944
+ agentDirectory: input.agentDirectory,
1275
945
  nodeTypeId: agentGuiWorkbenchTypeId,
1276
946
  onStateChange: () => void 0,
1277
947
  provider
@@ -1301,7 +971,301 @@ function createAgentGuiWorkbenchPreviewBodyContext(input) {
1301
971
  };
1302
972
  }
1303
973
 
974
+ // workbench/contribution.ts
975
+ var AGENT_GUI_WORKBENCH_CONVERSATION_RAIL_TOGGLE_EVENT = "tutti:agent-gui-workbench-conversation-rail-toggle";
976
+ var AGENT_GUI_WORKBENCH_NEW_CONVERSATION_EVENT = "tutti:agent-gui-workbench-new-conversation";
977
+ var AGENT_GUI_WORKBENCH_OPEN_EXTERNAL_IMPORT_EVENT = "tutti:agent-gui-workbench-open-external-import";
978
+ function createAgentGuiWorkbenchContribution(input) {
979
+ const nodeStateSource = createAgentGuiWorkbenchNodeStateSource({
980
+ workspaceId: input.workspaceId
981
+ });
982
+ const frame = input.frame ?? agentGuiWorkbenchDefaultNodeFrame;
983
+ const copy = resolveAgentGuiWorkbenchContributionCopy(input.copy);
984
+ return {
985
+ dockEntries: buildAgentGuiDockEntries({
986
+ agentDirectory: input.agentDirectory,
987
+ defaultProvider: input.defaultProvider,
988
+ dockIconUrls: input.dockIconUrls,
989
+ label: copy.nodeTitle,
990
+ providerAvailability: input.providerAvailability,
991
+ renderPreview: input.renderPreview,
992
+ resolveDockPopupIdentity: input.resolveDockPopupIdentity,
993
+ resolveDockPopupTitle: input.resolveDockPopupTitle,
994
+ sectionId: input.dockSectionId ?? "agents",
995
+ unifiedDockIconUrl: input.unifiedDockIconUrl
996
+ }),
997
+ externalStateSource: nodeStateSource.externalStateSource,
998
+ id: input.id ?? "workspace-agent-gui",
999
+ nodes: [
1000
+ {
1001
+ frame,
1002
+ instance: { mode: "multi" },
1003
+ onBodyRenderErrorChange: ({ hasError, node }) => {
1004
+ setAgentGuiWorkbenchBodyRenderError(node.id, hasError);
1005
+ },
1006
+ renderBody: (context) => input.renderBody(
1007
+ context,
1008
+ {
1009
+ agentDirectory: input.agentDirectory,
1010
+ nodeTypeId: agentGuiWorkbenchTypeId,
1011
+ onStateChange: (state) => {
1012
+ nodeStateSource.writeNodeState({
1013
+ instanceId: context.instanceId,
1014
+ nodeId: context.node.id,
1015
+ state,
1016
+ typeId: agentGuiWorkbenchTypeId
1017
+ });
1018
+ },
1019
+ provider: providerFromActivation(context.activation) ?? agentGuiWorkbenchProviderFromInstanceId(context.instanceId)
1020
+ }
1021
+ ),
1022
+ renderHeader: ({
1023
+ activation,
1024
+ dragHandleProps,
1025
+ displayMode,
1026
+ externalNodeState,
1027
+ instanceId,
1028
+ isFocused,
1029
+ node,
1030
+ surfaceSize,
1031
+ windowActions
1032
+ }) => {
1033
+ const provider = providerFromActivation(activation) ?? agentGuiWorkbenchProviderFromInstanceId(instanceId);
1034
+ const headerTitle = copy.nodeTitle;
1035
+ const rawWorkbenchState = externalNodeState ?? node.data.runtimeNodeState;
1036
+ const migratedWorkbenchState = migrateLegacyAgentGuiWorkbenchState(rawWorkbenchState);
1037
+ const workbenchState = normalizeAgentGuiWorkbenchState(
1038
+ migratedWorkbenchState
1039
+ );
1040
+ const nodeState = normalizeAgentGuiWorkbenchNodeState(
1041
+ migratedWorkbenchState,
1042
+ provider
1043
+ );
1044
+ const isConversationRailAutoCollapsed = shouldAutoCollapseAgentGUIConversationRail(node.frame.width);
1045
+ const isConversationRailCollapsed = nodeState.conversationRailCollapsed === true || isConversationRailAutoCollapsed;
1046
+ const conversationRailWidthPx = clampAgentGUIConversationRailWidthPx(
1047
+ nodeState.conversationRailWidthPx,
1048
+ node.frame.width
1049
+ );
1050
+ const conversationIdentity = input.resolveDockPopupIdentity?.(workbenchState) ?? null;
1051
+ const conversationTitle = conversationIdentity?.title ?? input.resolveDockPopupTitle?.(workbenchState) ?? null;
1052
+ const iconProvider = providerFromActivation(activation) ?? agentGuiWorkbenchProviderFromInstanceIdOrNull(instanceId);
1053
+ const conversationIconFallbackUrl = iconProvider ? resolveAgentGuiSessionProviderIconUrl(iconProvider) ?? resolveAgentGuiWorkbenchProviderIconUrl({
1054
+ dockIconUrls: input.dockIconUrls,
1055
+ provider: iconProvider
1056
+ }) : null;
1057
+ const conversationIconUrl = conversationIdentity?.iconUrl ?? conversationIconFallbackUrl;
1058
+ const persistConversationRailCollapsed = (collapsed) => {
1059
+ nodeStateSource.writeNodeState({
1060
+ instanceId,
1061
+ nodeId: node.id,
1062
+ state: {
1063
+ ...workbenchState,
1064
+ conversationRailCollapsed: collapsed
1065
+ },
1066
+ typeId: agentGuiWorkbenchTypeId
1067
+ });
1068
+ };
1069
+ const announceConversationRailCollapsed = (collapsed) => {
1070
+ window.dispatchEvent(
1071
+ new CustomEvent(
1072
+ AGENT_GUI_WORKBENCH_CONVERSATION_RAIL_TOGGLE_EVENT,
1073
+ {
1074
+ detail: {
1075
+ conversationRailCollapsed: collapsed,
1076
+ instanceId
1077
+ }
1078
+ }
1079
+ )
1080
+ );
1081
+ };
1082
+ const announceNewConversation = () => {
1083
+ window.dispatchEvent(
1084
+ new CustomEvent(
1085
+ AGENT_GUI_WORKBENCH_NEW_CONVERSATION_EVENT,
1086
+ {
1087
+ detail: {
1088
+ instanceId
1089
+ }
1090
+ }
1091
+ )
1092
+ );
1093
+ };
1094
+ return createElement3(AgentGuiWorkbenchHeader, {
1095
+ copy,
1096
+ conversationIconUrl,
1097
+ conversationIconFallbackUrl,
1098
+ conversationTitle,
1099
+ conversationRailWidthPx,
1100
+ displayMode,
1101
+ isConversationRailAutoCollapsed,
1102
+ isConversationRailCollapsed,
1103
+ nodeId: node.id,
1104
+ providerRailWidthPx: agentGuiWorkbenchProviderRailWidthPx,
1105
+ title: headerTitle,
1106
+ windowActions: {
1107
+ close: windowActions.close,
1108
+ minimize: windowActions.minimize,
1109
+ toggleDisplayMode: windowActions.toggleDisplayMode
1110
+ },
1111
+ ...dragHandleProps,
1112
+ onCreateConversation: announceNewConversation,
1113
+ onOpenDetachedWindow: input.onOpenDetachedWindow ? () => {
1114
+ void input.onOpenDetachedWindow?.({
1115
+ agentSessionId: workbenchState.lastActiveAgentSessionId,
1116
+ agentTargetId: nodeState.agentTargetId,
1117
+ provider,
1118
+ workspaceId: input.workspaceId
1119
+ });
1120
+ } : void 0,
1121
+ onPointerDown: (event) => {
1122
+ dragHandleProps.onPointerDown?.(event);
1123
+ if (!isFocused) {
1124
+ windowActions.focus();
1125
+ }
1126
+ },
1127
+ onToggleConversationRail: (nextCollapsed) => {
1128
+ announceConversationRailCollapsed(nextCollapsed);
1129
+ if (isConversationRailCollapsed && nextCollapsed === false && node.displayMode !== "fullscreen") {
1130
+ const expandedFrame = resolveAgentGUIExpandedWindowFrame({
1131
+ conversationRailWidthPx: nodeState.conversationRailWidthPx,
1132
+ desktopSize: surfaceSize,
1133
+ height: node.frame.height,
1134
+ position: {
1135
+ x: node.frame.x,
1136
+ y: node.frame.y
1137
+ },
1138
+ width: node.frame.width
1139
+ });
1140
+ windowActions.resize({
1141
+ ...node.frame,
1142
+ height: expandedFrame.size.height,
1143
+ width: expandedFrame.size.width,
1144
+ x: expandedFrame.position.x,
1145
+ y: expandedFrame.position.y
1146
+ });
1147
+ }
1148
+ persistConversationRailCollapsed(nextCollapsed);
1149
+ }
1150
+ });
1151
+ },
1152
+ title: copy.nodeTitle,
1153
+ typeId: agentGuiWorkbenchTypeId,
1154
+ window: {
1155
+ closable: true,
1156
+ defaultOpen: false,
1157
+ minimizedDock: {
1158
+ kind: "component",
1159
+ providePreview: (item) => createAgentGuiWorkbenchPreviewContent({
1160
+ agentDirectory: input.agentDirectory,
1161
+ item,
1162
+ renderPreview: input.renderMinimizedPreview,
1163
+ resolveDockPopupTitle: input.resolveDockPopupTitle
1164
+ })
1165
+ },
1166
+ minimizable: true
1167
+ }
1168
+ }
1169
+ ],
1170
+ onLaunchRequest: (request) => {
1171
+ if (request.typeId !== agentGuiWorkbenchTypeId) {
1172
+ return null;
1173
+ }
1174
+ const launchPayload = resolveAgentGuiWorkbenchLaunchPayload(request, {
1175
+ agentDirectory: input.agentDirectory,
1176
+ defaultProvider: input.defaultProvider,
1177
+ providerAvailability: input.providerAvailability
1178
+ });
1179
+ if (!hasAgentSessionId2(launchPayload) && !providerTargetLaunchPayloadFromRequest(
1180
+ launchPayload,
1181
+ providerFromState(launchPayload) ?? "codex"
1182
+ ).agentTargetId) {
1183
+ return null;
1184
+ }
1185
+ if (!providerFromState(launchPayload) && !agentGuiWorkbenchProviderFromIdentifier(request.dockEntryId)) {
1186
+ return null;
1187
+ }
1188
+ const {
1189
+ activation,
1190
+ dockEntryId,
1191
+ instanceId: descriptorInstanceId,
1192
+ openInNewWindow,
1193
+ provider,
1194
+ reuseDockEntryNode,
1195
+ reuseExistingSessionNode,
1196
+ targetAgentSessionId
1197
+ } = createAgentGuiWorkbenchLaunchDescriptor({
1198
+ ...request,
1199
+ payload: launchPayload
1200
+ });
1201
+ const existingInstanceId = targetAgentSessionId && reuseExistingSessionNode ? nodeStateSource.findInstanceIdByAgentSessionId(targetAgentSessionId) : null;
1202
+ const instanceId = existingInstanceId ?? descriptorInstanceId;
1203
+ const title = copy.nodeTitle;
1204
+ const providerTarget = providerTargetLaunchPayloadFromRequest(
1205
+ launchPayload,
1206
+ provider
1207
+ );
1208
+ const launchAgentTargetId = providerTarget.agentTargetId;
1209
+ if (targetAgentSessionId) {
1210
+ const previousState = nodeStateSource.readNodeState({
1211
+ instanceId,
1212
+ typeId: agentGuiWorkbenchTypeId
1213
+ });
1214
+ nodeStateSource.writeNodeState({
1215
+ instanceId,
1216
+ state: {
1217
+ ...normalizeAgentGuiWorkbenchState(previousState),
1218
+ ...targetAgentSessionId ? { lastActiveAgentSessionId: targetAgentSessionId } : {},
1219
+ agentTargetId: launchAgentTargetId ?? null
1220
+ },
1221
+ typeId: agentGuiWorkbenchTypeId
1222
+ });
1223
+ } else if (providerTarget.agentTargetId) {
1224
+ const previousState = nodeStateSource.readNodeState({
1225
+ instanceId,
1226
+ typeId: agentGuiWorkbenchTypeId
1227
+ });
1228
+ nodeStateSource.writeNodeState({
1229
+ instanceId,
1230
+ state: {
1231
+ ...normalizeAgentGuiWorkbenchState(previousState),
1232
+ lastActiveAgentSessionId: null,
1233
+ agentTargetId: providerTarget.agentTargetId
1234
+ },
1235
+ typeId: agentGuiWorkbenchTypeId
1236
+ });
1237
+ }
1238
+ const defaultFrame = resolveAgentGuiWorkbenchDefaultLaunchFrame({
1239
+ frame,
1240
+ request
1241
+ });
1242
+ return {
1243
+ activation,
1244
+ ...openInNewWindow ? { cascadeOffset: agentGuiWorkbenchNewWindowCascadeOffset } : {},
1245
+ defaultFrame,
1246
+ dockEntryId,
1247
+ framePolicy: !openInNewWindow && isAgentGuiWorkbenchCompactVisibleFrame(defaultFrame, frame) ? "absolute" : "cascade-same-type-centered",
1248
+ instanceId,
1249
+ // Reusing the window already showing this specific conversation
1250
+ // (e.g. clicking a completion notification) should just focus it,
1251
+ // not reset it back to the default size/position.
1252
+ preserveExistingNodeFrame: existingInstanceId !== null,
1253
+ reuseDockEntryNode,
1254
+ title,
1255
+ typeId: agentGuiWorkbenchTypeId
1256
+ };
1257
+ }
1258
+ };
1259
+ }
1260
+ function hasAgentSessionId2(payload) {
1261
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
1262
+ return false;
1263
+ }
1264
+ return typeof payload.agentSessionId === "string" && payload.agentSessionId.trim().length > 0;
1265
+ }
1266
+
1304
1267
  export {
1268
+ resolveAgentGuiSessionProviderFlatIconUrl,
1305
1269
  AGENT_GUI_CONVERSATION_RAIL_MIN_WIDTH_PX,
1306
1270
  AGENT_GUI_DETAIL_MIN_WIDTH_PX,
1307
1271
  AGENT_GUI_COLLAPSED_MIN_WIDTH_PX,
@@ -1310,27 +1274,21 @@ export {
1310
1274
  clampAgentGUIConversationRailWidthPx,
1311
1275
  resolveNextAgentGUIConversationRailWidthPx,
1312
1276
  resolveAgentGUIExpandedWindowFrame,
1313
- agentGuiDockIconUrl,
1314
- agentGuiDockIconUrls,
1315
- resolveAgentGuiSessionProviderFlatIconUrl,
1316
1277
  AgentGuiWorkbenchHeader,
1317
- normalizeAgentGUIAgents,
1318
- resolveAgentGUISelectedDirectoryAgent,
1319
- projectAgentGUIAgentsToInternalTargets,
1320
1278
  agentGuiWorkbenchDefaultNodeFrame,
1321
1279
  agentGuiWorkbenchDefaultUsableWidthRatio,
1322
1280
  agentGuiWorkbenchDefaultUsableHeightRatio,
1323
1281
  agentGuiWorkbenchCompactVisibleAreaRatio,
1324
1282
  agentGuiWorkbenchNewWindowCascadeOffset,
1325
1283
  agentGuiWorkbenchProviderRailWidthPx,
1326
- AGENT_GUI_WORKBENCH_CONVERSATION_RAIL_TOGGLE_EVENT,
1327
- AGENT_GUI_WORKBENCH_NEW_CONVERSATION_EVENT,
1328
- AGENT_GUI_WORKBENCH_OPEN_EXTERNAL_IMPORT_EVENT,
1329
1284
  agentGuiWorkbenchDefaultCopy,
1330
- createAgentGuiWorkbenchContribution,
1331
1285
  buildAgentGuiDockEntries,
1332
1286
  resolveAgentGuiUnifiedDockLaunchPayload,
1333
1287
  resolveAgentGuiWorkbenchDefaultLaunchFrame,
1334
- resolveAgentGuiWorkbenchContributionCopy
1288
+ resolveAgentGuiWorkbenchContributionCopy,
1289
+ AGENT_GUI_WORKBENCH_CONVERSATION_RAIL_TOGGLE_EVENT,
1290
+ AGENT_GUI_WORKBENCH_NEW_CONVERSATION_EVENT,
1291
+ AGENT_GUI_WORKBENCH_OPEN_EXTERNAL_IMPORT_EVENT,
1292
+ createAgentGuiWorkbenchContribution
1335
1293
  };
1336
- //# sourceMappingURL=chunk-AWAIUYG4.js.map
1294
+ //# sourceMappingURL=chunk-7RDD3EWP.js.map