@tutti-os/agent-gui 0.0.44 → 0.0.45

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 (47) hide show
  1. package/dist/agent-conversation/index.js +5 -4
  2. package/dist/agent-conversation/index.js.map +1 -1
  3. package/dist/agent-message-center/index.js +17 -11
  4. package/dist/agent-message-center/index.js.map +1 -1
  5. package/dist/app/renderer/agentactivity.css +99 -54
  6. package/dist/{chunk-GMLK2EFU.js → chunk-62QOR3TC.js} +4 -97
  7. package/dist/chunk-62QOR3TC.js.map +1 -0
  8. package/dist/{chunk-5UD2YEBX.js → chunk-AMNXH4DJ.js} +47 -14
  9. package/dist/{chunk-5UD2YEBX.js.map → chunk-AMNXH4DJ.js.map} +1 -1
  10. package/dist/{chunk-25VZHG6G.js → chunk-CZ7PS3DU.js} +4 -4
  11. package/dist/{chunk-ZORA4UAT.js → chunk-D6IYEVDT.js} +2 -2
  12. package/dist/chunk-EIC7XS3C.js +71 -0
  13. package/dist/chunk-EIC7XS3C.js.map +1 -0
  14. package/dist/chunk-FJG2EH4V.js +317 -0
  15. package/dist/chunk-FJG2EH4V.js.map +1 -0
  16. package/dist/{chunk-J4MU53PH.js → chunk-NZ2BGOJU.js} +2 -2
  17. package/dist/chunk-OL54R6OL.js +99 -0
  18. package/dist/chunk-OL54R6OL.js.map +1 -0
  19. package/dist/{chunk-ZTQKIJ5J.js → chunk-QT45WUPQ.js} +71 -20
  20. package/dist/chunk-QT45WUPQ.js.map +1 -0
  21. package/dist/{chunk-SF2PE7M6.js → chunk-UGV6JTWM.js} +4 -4
  22. package/dist/{chunk-IGXC7NRW.js → chunk-VFQR7AZI.js} +10 -63
  23. package/dist/chunk-VFQR7AZI.js.map +1 -0
  24. package/dist/{chunk-64OSXJRE.js → chunk-ZG3WZSMV.js} +2 -2
  25. package/dist/context-mention-palette/index.js +7 -6
  26. package/dist/i18n/index.d.ts +2 -2
  27. package/dist/i18n/index.js +2 -1
  28. package/dist/index.d.ts +1 -5
  29. package/dist/index.js +157 -232
  30. package/dist/index.js.map +1 -1
  31. package/dist/uiSettings-BQS9r2eo.d.ts +6 -0
  32. package/dist/workbench/contribution.js +1 -1
  33. package/dist/workbench/index.d.ts +3 -0
  34. package/dist/workbench/index.js +13 -2
  35. package/dist/workbench/sessionTitle.d.ts +28 -0
  36. package/dist/workbench/sessionTitle.js +14 -0
  37. package/dist/workbench/sessionTitle.js.map +1 -0
  38. package/dist/workspace-agent-generated-files.js +3 -2
  39. package/package.json +19 -12
  40. package/dist/chunk-GMLK2EFU.js.map +0 -1
  41. package/dist/chunk-IGXC7NRW.js.map +0 -1
  42. package/dist/chunk-ZTQKIJ5J.js.map +0 -1
  43. /package/dist/{chunk-25VZHG6G.js.map → chunk-CZ7PS3DU.js.map} +0 -0
  44. /package/dist/{chunk-ZORA4UAT.js.map → chunk-D6IYEVDT.js.map} +0 -0
  45. /package/dist/{chunk-J4MU53PH.js.map → chunk-NZ2BGOJU.js.map} +0 -0
  46. /package/dist/{chunk-SF2PE7M6.js.map → chunk-UGV6JTWM.js.map} +0 -0
  47. /package/dist/{chunk-64OSXJRE.js.map → chunk-ZG3WZSMV.js.map} +0 -0
package/dist/index.js CHANGED
@@ -21,9 +21,8 @@ import {
21
21
  } from "./chunk-4K22O34C.js";
22
22
  import {
23
23
  AgentInteractivePromptSurface,
24
- approvalOptionDisplayLabel,
25
- formatAgentSessionMentionText
26
- } from "./chunk-GMLK2EFU.js";
24
+ approvalOptionDisplayLabel
25
+ } from "./chunk-62QOR3TC.js";
27
26
  import {
28
27
  PLAN_IMPLEMENTATION_ACTION_FEEDBACK,
29
28
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
@@ -32,6 +31,17 @@ import {
32
31
  planDecisionOps,
33
32
  planImplementationPromptFromPlanTurn
34
33
  } from "./chunk-MKHDRIGN.js";
34
+ import {
35
+ AGENT_PROVIDER_LABEL,
36
+ firstAgentGUIUserMessageTitle,
37
+ formatAgentGUIConversationPlainTitle,
38
+ normalizeAgentGUIProviderIdentity,
39
+ resolveAgentGUIConversationTitle,
40
+ resolveAgentGUIDockConversationTitle,
41
+ resolveAgentGUIExplicitConversationTitle,
42
+ resolveAgentGUIProviderDisplayLabel,
43
+ resolveAgentGUIProviderIdentity
44
+ } from "./chunk-FJG2EH4V.js";
35
45
  import {
36
46
  AgentConversationFlow,
37
47
  Button,
@@ -48,13 +58,13 @@ import {
48
58
  skillDescriptionForDisplay,
49
59
  skillTriggerForPrefix,
50
60
  useProjectedAgentConversation
51
- } from "./chunk-25VZHG6G.js";
61
+ } from "./chunk-CZ7PS3DU.js";
52
62
  import {
53
63
  AgentMessageMarkdown,
54
64
  ZoomableImage,
55
65
  cn,
56
66
  resolveWorkspaceLinkAction
57
- } from "./chunk-ZTQKIJ5J.js";
67
+ } from "./chunk-QT45WUPQ.js";
58
68
  import {
59
69
  AGENT_MENTION_FILTER_TAB_ORDER,
60
70
  AgentFileMentionPalette,
@@ -62,7 +72,7 @@ import {
62
72
  DEFAULT_AGENT_MENTION_FILTER,
63
73
  agentMentionItemKey,
64
74
  preloadAgentMentionBrowse
65
- } from "./chunk-SF2PE7M6.js";
75
+ } from "./chunk-UGV6JTWM.js";
66
76
  import {
67
77
  WORKSPACE_AGENT_ACTIVITY_RUNTIME_SESSION_ORIGIN,
68
78
  buildWorkspaceAgentActivityListViewModel,
@@ -72,24 +82,24 @@ import {
72
82
  isWorkspaceAgentUntitledTask,
73
83
  mergeWorkspaceAgentActivityDurableAndOverlayMessages,
74
84
  selectWorkspaceAgentActivityOverlayMessages
75
- } from "./chunk-ZORA4UAT.js";
85
+ } from "./chunk-D6IYEVDT.js";
76
86
  import {
77
87
  MANAGED_AGENT_ICON_FALLBACK_URL,
78
88
  MANAGED_AGENT_ICON_URLS,
79
89
  Spinner,
80
90
  normalizeManagedAgentProvider
81
- } from "./chunk-J4MU53PH.js";
82
- import "./chunk-MTFSQWZ6.js";
91
+ } from "./chunk-NZ2BGOJU.js";
83
92
  import {
84
93
  resolveWorkspaceAgentSessionSortTimeUnixMs
85
94
  } from "./chunk-IBIMGLCD.js";
95
+ import "./chunk-MTFSQWZ6.js";
86
96
  import {
87
97
  exitAgentFileMentionSuggestion,
88
98
  formatAgentMentionMarkdown,
89
99
  mentionItemToAttrs,
90
100
  normalizeAgentSessionMentionTitle,
91
101
  parseMentionItemFromHref
92
- } from "./chunk-64OSXJRE.js";
102
+ } from "./chunk-ZG3WZSMV.js";
93
103
  import "./chunk-Y35GDLP2.js";
94
104
  import {
95
105
  AgentActivityHostProvider,
@@ -108,9 +118,7 @@ import "./chunk-TYGL25EL.js";
108
118
  import {
109
119
  AGENT_CONTEXT_MENTION_PROVIDER_IDS
110
120
  } from "./chunk-JM24HADP.js";
111
- import {
112
- normalizeAgentTitleText
113
- } from "./chunk-GCBDIQDX.js";
121
+ import "./chunk-GCBDIQDX.js";
114
122
  import {
115
123
  AgentGuiI18nProvider,
116
124
  agentGuiI18nModule,
@@ -118,7 +126,8 @@ import {
118
126
  getActiveUiLanguage,
119
127
  translate,
120
128
  useTranslation
121
- } from "./chunk-IGXC7NRW.js";
129
+ } from "./chunk-EIC7XS3C.js";
130
+ import "./chunk-VFQR7AZI.js";
122
131
  import "./chunk-LUGELG5V.js";
123
132
  import "./chunk-PJP5BUU6.js";
124
133
 
@@ -2040,6 +2049,7 @@ function WorkspaceNodeWindow({
2040
2049
  const renderedChildren = typeof children === "function" ? children(renderedFrame) : children;
2041
2050
  const rootStyle = appearance === "embedded" ? {
2042
2051
  "--node-header-padding-x": "16px",
2052
+ "--node-header-traffic-light-title-offset": "64px",
2043
2053
  ...resolvedStyle,
2044
2054
  width: "100%",
2045
2055
  height: "100%",
@@ -2051,6 +2061,7 @@ function WorkspaceNodeWindow({
2051
2061
  WebkitBackdropFilter: "none"
2052
2062
  } : {
2053
2063
  "--node-header-padding-x": "16px",
2064
+ "--node-header-traffic-light-title-offset": "64px",
2054
2065
  ...resolvedStyle,
2055
2066
  background: "transparent",
2056
2067
  border: "1px solid var(--node-window-border)",
@@ -2087,7 +2098,7 @@ function WorkspaceNodeWindow({
2087
2098
  hideHeader ? null : customHeader ? customHeader : /* @__PURE__ */ jsxs3(
2088
2099
  "header",
2089
2100
  {
2090
- className: "workspace-node-window__header relative flex h-[var(--node-header-height)] min-h-[var(--node-header-height)] cursor-grab items-center gap-2 border-b border-[var(--node-header-border)] bg-[var(--node-header-surface)] px-2 pl-[var(--node-header-padding-x)] active:cursor-grabbing",
2101
+ className: "workspace-node-window__header relative flex h-[var(--node-header-height)] min-h-[var(--node-header-height)] cursor-grab items-center gap-2 border-b border-[var(--node-header-border)] bg-[var(--node-header-surface)] px-2 pl-[calc(var(--node-header-padding-x)+var(--node-header-traffic-light-title-offset))] active:cursor-grabbing",
2091
2102
  style: {
2092
2103
  borderBottomColor: "var(--node-header-border)",
2093
2104
  background: "var(--node-header-surface)"
@@ -2106,7 +2117,7 @@ function WorkspaceNodeWindow({
2106
2117
  /* @__PURE__ */ jsxs3(
2107
2118
  "div",
2108
2119
  {
2109
- className: "workspace-node-window__controls nodrag absolute left-4 top-1/2 inline-flex -translate-y-1/2 items-center gap-2",
2120
+ className: "workspace-node-window__controls nodrag group/traffic-lights absolute left-4 top-1/2 inline-flex -translate-y-1/2 items-center gap-2",
2110
2121
  "data-workspace-node-window-controls": "true",
2111
2122
  children: [
2112
2123
  /* @__PURE__ */ jsx10(
@@ -2141,7 +2152,7 @@ function WorkspaceNodeWindow({
2141
2152
  /* @__PURE__ */ jsxs3(
2142
2153
  "div",
2143
2154
  {
2144
- className: "workspace-node-window__title ml-[64px] flex min-w-0 max-w-[280px] flex-1 items-center gap-2 text-[15px] leading-5 font-semibold text-foreground",
2155
+ className: "workspace-node-window__title flex min-w-0 max-w-[280px] flex-1 items-center gap-2 text-[15px] leading-5 font-semibold text-foreground",
2145
2156
  "data-workspace-node-window-title": "true",
2146
2157
  title,
2147
2158
  children: [
@@ -2228,16 +2239,17 @@ function WorkspaceNodeTrafficLightButton({
2228
2239
  event.stopPropagation();
2229
2240
  onClick();
2230
2241
  };
2242
+ const iconName = tone === "maximize" ? pressed ? "unfullscreen" : "fullscreen" : tone;
2231
2243
  return /* @__PURE__ */ jsx10(
2232
2244
  "button",
2233
2245
  {
2234
2246
  "aria-label": ariaLabel,
2235
2247
  "aria-pressed": pressed,
2236
2248
  className: cn(
2237
- "relative -m-1 inline-flex size-5 shrink-0 cursor-pointer rounded-full border-0 bg-transparent p-0 opacity-[0.78] outline-none transition-opacity duration-150 before:absolute before:inset-1 before:rounded-full before:bg-[color-mix(in_srgb,var(--text-tertiary)_72%,transparent)] before:content-[''] hover:opacity-100 focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-[var(--accent)] focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--node-header-surface)]",
2238
- tone === "close" && "hover:before:bg-[#ff5f57] focus-visible:before:bg-[#ff5f57]",
2239
- tone === "minimize" && "hover:before:bg-[#ffbd2e] focus-visible:before:bg-[#ffbd2e]",
2240
- tone === "maximize" && "hover:before:bg-[#28c840] focus-visible:before:bg-[#28c840]"
2249
+ "relative -m-1 inline-flex size-5 shrink-0 cursor-pointer rounded-full border-0 bg-transparent p-0 opacity-[0.78] outline-none transition-opacity duration-150 before:absolute before:inset-1 before:rounded-full before:bg-[color-mix(in_srgb,var(--text-tertiary)_72%,transparent)] before:content-[''] group-hover/traffic-lights:opacity-100 group-focus-within/traffic-lights:opacity-100 focus-visible:ring-2 focus-visible:ring-[var(--accent)] focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--node-header-surface)]",
2250
+ tone === "close" && "group-hover/traffic-lights:before:bg-[#ff5f57] group-focus-within/traffic-lights:before:bg-[#ff5f57]",
2251
+ tone === "minimize" && "group-hover/traffic-lights:before:bg-[#ffbd2e] group-focus-within/traffic-lights:before:bg-[#ffbd2e]",
2252
+ tone === "maximize" && "group-hover/traffic-lights:before:bg-[#28c840] group-focus-within/traffic-lights:before:bg-[#28c840]"
2241
2253
  ),
2242
2254
  "data-window-header": "top",
2243
2255
  "data-workspace-node-window-traffic-light": tone,
@@ -2246,10 +2258,42 @@ function WorkspaceNodeTrafficLightButton({
2246
2258
  type: "button",
2247
2259
  onClick: handleClick,
2248
2260
  onDoubleClick: (event) => event.stopPropagation(),
2249
- onPointerDown: (event) => event.stopPropagation()
2261
+ onPointerDown: (event) => event.stopPropagation(),
2262
+ children: /* @__PURE__ */ jsx10(
2263
+ WorkspaceNodeWindowTrafficLightIcon,
2264
+ {
2265
+ "aria-hidden": "true",
2266
+ className: "pointer-events-none absolute inset-[5px] z-[1] size-[10px] text-[color-mix(in_srgb,#000_68%,transparent)] opacity-0 transition-opacity duration-150 group-hover/traffic-lights:opacity-100 group-focus-within/traffic-lights:opacity-100",
2267
+ "data-workspace-node-window-traffic-light-icon": iconName,
2268
+ iconName
2269
+ }
2270
+ )
2271
+ }
2272
+ );
2273
+ }
2274
+ function WorkspaceNodeWindowTrafficLightIcon({
2275
+ className,
2276
+ iconName,
2277
+ ...props
2278
+ }) {
2279
+ return /* @__PURE__ */ jsx10(
2280
+ "svg",
2281
+ {
2282
+ ...props,
2283
+ className,
2284
+ fill: "currentColor",
2285
+ viewBox: "0 0 24 24",
2286
+ xmlns: "http://www.w3.org/2000/svg",
2287
+ children: /* @__PURE__ */ jsx10("path", { d: trafficLightIconPathByName[iconName] })
2250
2288
  }
2251
2289
  );
2252
2290
  }
2291
+ var trafficLightIconPathByName = {
2292
+ close: "M16.9395 4.93953C17.5253 4.35374 18.4748 4.35374 19.0606 4.93953C19.6463 5.52532 19.6464 6.47486 19.0606 7.06062L14.1212 12.0001L19.0606 16.9395C19.6463 17.5253 19.6464 18.4749 19.0606 19.0606C18.4749 19.6464 17.5253 19.6463 16.9395 19.0606L12.0001 14.1212L7.06062 19.0606C6.47486 19.6464 5.52532 19.6463 4.93953 19.0606C4.35374 18.4748 4.35374 17.5253 4.93953 16.9395L9.87898 12.0001L4.93953 7.06062C4.35374 6.47484 4.35374 5.52532 4.93953 4.93953C5.52532 4.35374 6.47484 4.35374 7.06062 4.93953L12.0001 9.87898L16.9395 4.93953Z",
2293
+ fullscreen: "M18.1465 7.85352C18.4615 7.53861 18.9999 7.76165 19 8.20703V18.5C19 18.7761 18.7761 19 18.5 19H8.20703C7.76165 18.9999 7.53861 18.4615 7.85352 18.1465L18.1465 7.85352ZM15.793 5C16.2384 5.00006 16.4614 5.53855 16.1465 5.85352L5.85352 16.1465C5.53855 16.4614 5.00006 16.2384 5 15.793V5.5C5 5.22386 5.22386 5 5.5 5H15.793Z",
2294
+ minimize: "M5 10.5H19C19.8284 10.5 20.5 11.1716 20.5 12C20.5 12.8284 19.8284 13.5 19 13.5H5C4.17157 13.5 3.5 12.8284 3.5 12C3.5 11.1716 4.17157 10.5 5 10.5Z",
2295
+ 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"
2296
+ };
2253
2297
 
2254
2298
  // agent-gui/agentGuiNode/controller/useAgentGUINodeController.ts
2255
2299
  import {
@@ -2363,141 +2407,6 @@ var DEFAULT_AGENT_SETTINGS = {
2363
2407
  hideWorktreeMismatchDropWarning: false
2364
2408
  };
2365
2409
 
2366
- // contexts/settings/domain/agentSettings.providerMeta.ts
2367
- var AGENT_PROVIDER_LABEL = {
2368
- "claude-code": "Claude Code",
2369
- codex: "Codex",
2370
- nexight: "Nexight",
2371
- opencode: "OpenCode",
2372
- gemini: "Gemini CLI",
2373
- openclaw: "OpenClaw",
2374
- hermes: "Hermes Agent"
2375
- };
2376
-
2377
- // agent-gui/agentGuiNode/model/agentGuiProviderIdentity.ts
2378
- function normalizeAgentGUIProviderIdentity(provider) {
2379
- switch (provider?.trim().toLowerCase() ?? "") {
2380
- case "claude-code":
2381
- case "claude":
2382
- case "claude code":
2383
- return "claude-code";
2384
- case "codex":
2385
- return "codex";
2386
- case "nexight":
2387
- case "tutti":
2388
- return "nexight";
2389
- case "gemini":
2390
- return "gemini";
2391
- case "hermes":
2392
- return "hermes";
2393
- case "openclaw":
2394
- return "openclaw";
2395
- default:
2396
- return "unknown";
2397
- }
2398
- }
2399
- function resolveAgentGUIProviderIdentity(input) {
2400
- const candidates = [
2401
- input.sessionProvider,
2402
- input.workspaceSessionProvider,
2403
- input.conversationProvider,
2404
- timelineProviderHint(input.timelineItems ?? [])
2405
- ];
2406
- for (const candidate of candidates) {
2407
- const normalized = normalizeAgentGUIProviderIdentity(candidate);
2408
- if (normalized !== "unknown") {
2409
- return normalized;
2410
- }
2411
- }
2412
- return "unknown";
2413
- }
2414
- function resolveAgentGUIConversationTitle(title, provider) {
2415
- const normalizedTitle = stripAgentGUITitleTrailingPeriod(
2416
- normalizeAgentTitleText(title)
2417
- );
2418
- if (normalizedTitle) {
2419
- return {
2420
- title: normalizedTitle,
2421
- titleFallback: null
2422
- };
2423
- }
2424
- if (provider === "unknown") {
2425
- return {
2426
- title: "",
2427
- titleFallback: "generic-agent"
2428
- };
2429
- }
2430
- return {
2431
- title: AGENT_PROVIDER_LABEL[provider],
2432
- titleFallback: null
2433
- };
2434
- }
2435
- function resolveAgentGUIConversationDisplayTitle(input, fallbackAgentLabel) {
2436
- if (input.title) {
2437
- return stripAgentGUITitleTrailingPeriod(
2438
- normalizeAgentTitleText(input.title)
2439
- );
2440
- }
2441
- if (input.titleFallback === "generic-agent") {
2442
- return stripAgentGUITitleTrailingPeriod(fallbackAgentLabel);
2443
- }
2444
- return "";
2445
- }
2446
- function resolveAgentGUIDockConversationTitle(input) {
2447
- return resolveAgentGUIExplicitConversationTitle(input);
2448
- }
2449
- function resolveAgentGUIExplicitConversationTitle(input) {
2450
- if (input.titleFallback) {
2451
- return null;
2452
- }
2453
- const title = stripAgentGUITitleTrailingPeriod(
2454
- normalizeAgentTitleText(input.title)
2455
- );
2456
- if (!title) {
2457
- return null;
2458
- }
2459
- if (isWorkspaceAgentUntitledTask(title)) {
2460
- return null;
2461
- }
2462
- if (input.provider !== "unknown" && title === AGENT_PROVIDER_LABEL[input.provider]) {
2463
- return null;
2464
- }
2465
- return title;
2466
- }
2467
- function resolveAgentGUIProviderDisplayLabel(provider, fallbackAgentLabel) {
2468
- const resolvedProvider = normalizeAgentGUIProviderIdentity(provider);
2469
- if (resolvedProvider === "unknown") {
2470
- return fallbackAgentLabel;
2471
- }
2472
- return AGENT_PROVIDER_LABEL[resolvedProvider];
2473
- }
2474
- function stripAgentGUITitleTrailingPeriod(title) {
2475
- return title.trimEnd().replace(/[.。]+$/u, "").trimEnd();
2476
- }
2477
- function timelineProviderHint(timelineItems) {
2478
- for (const item of timelineItems) {
2479
- if (isUserTimelineItem(item)) {
2480
- continue;
2481
- }
2482
- const normalized = normalizeAgentGUIProviderIdentity(item.actorId);
2483
- if (normalized !== "unknown") {
2484
- return normalized;
2485
- }
2486
- }
2487
- return null;
2488
- }
2489
- function isUserTimelineItem(item) {
2490
- const role = item.role?.trim().toLowerCase();
2491
- if (role === "user") {
2492
- return true;
2493
- }
2494
- const actorType = item.actorType.trim().toLowerCase();
2495
- if (actorType === "user") {
2496
- return true;
2497
- }
2498
- return item.itemType.trim().toLowerCase() === "message.user";
2499
- }
2500
-
2501
2410
  // agent-gui/agentGuiNode/model/agentGuiConversationProjectResolver.ts
2502
2411
  import { resolveWorkspaceUserProjectDisplayLabel } from "@tutti-os/workspace-user-project/core";
2503
2412
  var AGENT_GUI_CONVERSATION_PROJECT_SUMMARY_CACHE_LIMIT = 512;
@@ -2960,10 +2869,7 @@ function firstUserMessageTitleFromTimelineItems(timelineItems) {
2960
2869
  return userMessage ? timelineItemText(userMessage) : "";
2961
2870
  }
2962
2871
  function firstUserMessageTitleFromMessages(messages) {
2963
- const userMessage = [...messages].filter(
2964
- (message) => messageRole(message) === "user" && messageText(message).length > 0
2965
- ).sort(compareMessagesAscending)[0];
2966
- return userMessage ? messageText(userMessage) : "";
2872
+ return firstAgentGUIUserMessageTitle(messages);
2967
2873
  }
2968
2874
  function workspaceAgentMessagesFromTimelineItems(timelineItems) {
2969
2875
  return timelineItems.map((item, index) => {
@@ -2993,38 +2899,6 @@ function workspaceAgentMessagesFromTimelineItems(timelineItems) {
2993
2899
  };
2994
2900
  });
2995
2901
  }
2996
- function messageRole(message) {
2997
- const role = message.role?.trim().toLowerCase();
2998
- if (role === "user") {
2999
- return "user";
3000
- }
3001
- if (role === "assistant" || role === "agent") {
3002
- return "agent";
3003
- }
3004
- const kind = message.kind.trim().toLowerCase();
3005
- if (kind === "message.user") {
3006
- return "user";
3007
- }
3008
- if (kind === "message.assistant" || kind === "message.agent") {
3009
- return "agent";
3010
- }
3011
- return null;
3012
- }
3013
- function messageText(message) {
3014
- const payloadDisplayPrompt = typeof message.payload?.displayPrompt === "string" ? message.payload.displayPrompt : "";
3015
- const payloadContent = typeof message.payload?.content === "string" ? message.payload.content : "";
3016
- const payloadText = typeof message.payload?.text === "string" ? message.payload.text : "";
3017
- return (payloadDisplayPrompt || payloadText || payloadContent).replace(/\s+/g, " ").trim();
3018
- }
3019
- function compareMessagesAscending(left, right) {
3020
- const leftTime = left.occurredAtUnixMs ?? left.completedAtUnixMs ?? left.startedAtUnixMs ?? 0;
3021
- const rightTime = right.occurredAtUnixMs ?? right.completedAtUnixMs ?? right.startedAtUnixMs ?? 0;
3022
- const timeDiff = leftTime - rightTime;
3023
- if (timeDiff !== 0) {
3024
- return timeDiff;
3025
- }
3026
- return (left.id ?? 0) - (right.id ?? 0) || left.messageId.localeCompare(right.messageId);
3027
- }
3028
2902
  function timelineItemRole(item) {
3029
2903
  const role = item.role?.trim().toLowerCase();
3030
2904
  if (role === "user") {
@@ -3579,7 +3453,7 @@ function projectWorkspaceAgentMessagesToTimelineItems(messages) {
3579
3453
  actorType: "agent",
3580
3454
  itemType: "message.assistant_thinking",
3581
3455
  role: "assistant_thinking",
3582
- content: messageText2(message),
3456
+ content: messageText(message),
3583
3457
  occurredAtUnixMs
3584
3458
  });
3585
3459
  }
@@ -3593,7 +3467,7 @@ function projectWorkspaceAgentMessagesToTimelineItems(messages) {
3593
3467
  actorType: "user",
3594
3468
  itemType: "message.user",
3595
3469
  role: "user",
3596
- content: messageText2(message),
3470
+ content: messageText(message),
3597
3471
  occurredAtUnixMs
3598
3472
  });
3599
3473
  }
@@ -3607,7 +3481,7 @@ function projectWorkspaceAgentMessagesToTimelineItems(messages) {
3607
3481
  actorType: "agent",
3608
3482
  itemType: "message.assistant",
3609
3483
  role: "assistant",
3610
- content: messageText2(message),
3484
+ content: messageText(message),
3611
3485
  occurredAtUnixMs
3612
3486
  });
3613
3487
  }
@@ -3734,7 +3608,7 @@ function toolCallItemType(status) {
3734
3608
  return "call";
3735
3609
  }
3736
3610
  }
3737
- function messageText2(message) {
3611
+ function messageText(message) {
3738
3612
  const payload = normalizedPayload(message.payload);
3739
3613
  const title = messagePayloadString(message, "title");
3740
3614
  return firstNonEmptyString(
@@ -3748,7 +3622,7 @@ function messageText2(message) {
3748
3622
  }
3749
3623
  function statusMessageText(message) {
3750
3624
  const title = messagePayloadString(message, "title") ?? "";
3751
- const text = messageText2(message);
3625
+ const text = messageText(message);
3752
3626
  if (title && text && title !== text) {
3753
3627
  return `${title}
3754
3628
 
@@ -7434,8 +7308,31 @@ function sessionHasRenderableMessages(input) {
7434
7308
  const sessionView = getAgentSessionView(
7435
7309
  input.sessionViewRef(normalizedAgentSessionId)
7436
7310
  );
7311
+ if (sessionViewHasUnhydratedOlderDetailMessages({
7312
+ agentSessionId: normalizedAgentSessionId,
7313
+ detailMessages: sessionView?.detailMessages ?? [],
7314
+ hasLoadedInitialMessages: input.hasLoadedInitialMessages === true,
7315
+ hasOlderMessages: sessionView?.hasOlderMessages ?? false,
7316
+ oldestLoadedVersion: sessionView?.oldestLoadedVersion ?? null,
7317
+ snapshotMessagesById: input.snapshotMessagesById
7318
+ })) {
7319
+ return false;
7320
+ }
7437
7321
  return (sessionView?.detailMessages?.length ?? 0) > 0 || (sessionView?.overlayMessages?.length ?? 0) > 0;
7438
7322
  }
7323
+ function sessionViewHasUnhydratedOlderDetailMessages(input) {
7324
+ if (input.hasLoadedInitialMessages || input.hasOlderMessages || input.detailMessages.length === 0) {
7325
+ return false;
7326
+ }
7327
+ const oldestLoadedVersion = input.oldestLoadedVersion ?? minFiniteMessageVersion(input.detailMessages);
7328
+ if (oldestLoadedVersion === null) {
7329
+ return false;
7330
+ }
7331
+ const snapshotOldestVersion = minFiniteMessageVersion(
7332
+ input.snapshotMessagesById[input.agentSessionId] ?? []
7333
+ );
7334
+ return oldestLoadedVersion > 1 || snapshotOldestVersion !== null && snapshotOldestVersion < oldestLoadedVersion;
7335
+ }
7439
7336
  function filterMessagesForDetailWindowOverlay(input) {
7440
7337
  if (input.localMessages.length === 0) {
7441
7338
  return [];
@@ -9425,6 +9322,9 @@ function useAgentGUINodeController({
9425
9322
  if (previous !== normalized) {
9426
9323
  const hasCachedMessages = sessionHasRenderableMessages({
9427
9324
  agentSessionId: normalized,
9325
+ hasLoadedInitialMessages: selectedConversationInitialMessagesLoadedIdsRef.current.has(
9326
+ normalized
9327
+ ),
9428
9328
  sessionViewRef,
9429
9329
  snapshotMessagesById: agentActivitySnapshotRef.current.sessionMessagesById
9430
9330
  });
@@ -10396,6 +10296,9 @@ function useAgentGUINodeController({
10396
10296
  );
10397
10297
  const hasRenderableMessages = sessionHasRenderableMessages({
10398
10298
  agentSessionId: normalizedAgentSessionId,
10299
+ hasLoadedInitialMessages: selectedConversationInitialMessagesLoadedIdsRef.current.has(
10300
+ normalizedAgentSessionId
10301
+ ),
10399
10302
  sessionViewRef,
10400
10303
  snapshotMessagesById: agentActivitySnapshotRef.current.sessionMessagesById
10401
10304
  });
@@ -10646,8 +10549,9 @@ function useAgentGUINodeController({
10646
10549
  if (nextMessages.length === 0) {
10647
10550
  return;
10648
10551
  }
10649
- const currentMessages = getAgentSessionView(sessionViewRef(agentSessionId))?.overlayMessages ?? [];
10650
- const currentDetailMessages = getAgentSessionView(sessionViewRef(agentSessionId))?.detailMessages ?? [];
10552
+ const currentView = getAgentSessionView(sessionViewRef(agentSessionId));
10553
+ const currentMessages = currentView?.overlayMessages ?? [];
10554
+ const currentDetailMessages = currentView?.detailMessages ?? [];
10651
10555
  const currentDurableDetailMessages = currentDetailMessages.filter(
10652
10556
  (message) => !isWorkspaceAgentActivityOptimisticMessage(message)
10653
10557
  );
@@ -10671,7 +10575,19 @@ function useAgentGUINodeController({
10671
10575
  if (durableDetailWindowMessages.length > 0) {
10672
10576
  mergeAgentSessionViewDetailMessages(
10673
10577
  sessionViewRef(agentSessionId),
10674
- durableDetailWindowMessages
10578
+ durableDetailWindowMessages,
10579
+ {
10580
+ hasOlderMessages: currentView?.hasOlderMessages === true || sessionViewHasUnhydratedOlderDetailMessages({
10581
+ agentSessionId,
10582
+ detailMessages: nextDetailMessages,
10583
+ hasLoadedInitialMessages: selectedConversationInitialMessagesLoadedIdsRef.current.has(
10584
+ agentSessionId
10585
+ ),
10586
+ hasOlderMessages: currentView?.hasOlderMessages ?? false,
10587
+ oldestLoadedVersion: minFiniteMessageVersion(nextDetailMessages),
10588
+ snapshotMessagesById: agentActivitySnapshot.sessionMessagesById
10589
+ })
10590
+ }
10675
10591
  );
10676
10592
  }
10677
10593
  const durableMessages = nextDetailMessages.length > 0 ? nextDetailMessages : durableSnapshotMessages;
@@ -15767,7 +15683,7 @@ import {
15767
15683
  } from "@tutti-os/ui-system";
15768
15684
 
15769
15685
  // agent-gui/agentGuiNode/AgentComposer.tsx
15770
- import { AddIcon, Select as Select2, SelectTrigger as SelectTrigger2 } from "@tutti-os/ui-system";
15686
+ import { AddIcon, Button as Button3, Select as Select2, SelectTrigger as SelectTrigger2 } from "@tutti-os/ui-system";
15771
15687
  import { ListChecks as ListChecks2, Target as Target3, X } from "lucide-react";
15772
15688
  import {
15773
15689
  createMentionPaletteStateAdapter,
@@ -16535,6 +16451,7 @@ var styles3 = {
16535
16451
  shell: "agent-gui-node__shell",
16536
16452
  timeline: "agent-gui-node__timeline",
16537
16453
  timelineCentered: "agent-gui-node__timeline-centered",
16454
+ timelineScrolledFromTop: "agent-gui-node__timeline--scrolled-from-top",
16538
16455
  transcriptSkeleton: "agent-gui-node__transcript-skeleton",
16539
16456
  transcriptSkeletonBubble: "agent-gui-node__transcript-skeleton-bubble",
16540
16457
  transcriptSkeletonLine: "agent-gui-node__transcript-skeleton-line",
@@ -19689,12 +19606,14 @@ function AgentUsageChip({
19689
19606
  }
19690
19607
  ) : null,
19691
19608
  compactSupported && onCompact ? /* @__PURE__ */ jsx27(
19692
- "button",
19609
+ Button3,
19693
19610
  {
19694
19611
  type: "button",
19695
19612
  "data-testid": "agent-gui-compact-button",
19696
19613
  disabled: compactDisabled,
19697
- className: "nodrag inline-flex items-center justify-center rounded-[6px] bg-[var(--transparency-block)] px-2 py-1 text-[12px] font-medium text-[var(--text-primary)] transition-colors hover:bg-[var(--transparency-hover)] focus-visible:bg-[var(--transparency-hover)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-45 disabled:hover:bg-[var(--transparency-block)] [-webkit-app-region:no-drag]",
19614
+ className: "nodrag w-full font-medium [-webkit-app-region:no-drag]",
19615
+ size: "sm",
19616
+ variant: "secondary",
19698
19617
  onClick: onCompact,
19699
19618
  children: labels.usageCompactAction
19700
19619
  }
@@ -22555,13 +22474,13 @@ import { createRichTextMentionHref as createRichTextMentionHref2 } from "@tutti-
22555
22474
  import { Fragment as Fragment8, jsx as jsx30, jsxs as jsxs17 } from "react/jsx-runtime";
22556
22475
  var AGENT_GUI_STICK_TO_BOTTOM_THRESHOLD_PX = 24;
22557
22476
  var AGENT_GUI_TOP_HISTORY_PREFETCH_THRESHOLD_PX = 240;
22477
+ var AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX = 1;
22558
22478
  var AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE = 5;
22559
22479
  var AGENT_GUI_TIMELINE_SCROLL_AREA_CONTENT_STYLE = {
22560
22480
  width: "100%",
22561
22481
  minWidth: "100%",
22562
22482
  display: "grid",
22563
- gridTemplateColumns: "minmax(0, min(100%, var(--agent-gui-detail-flow-max-width)))",
22564
- justifyContent: "center",
22483
+ gridTemplateColumns: "minmax(0, 1fr)",
22565
22484
  gap: "24px"
22566
22485
  };
22567
22486
  var EMPTY_WORKSPACE_APP_ICONS3 = [];
@@ -22747,19 +22666,11 @@ function resolveActiveConversationBusyStatus(input) {
22747
22666
  }
22748
22667
  return null;
22749
22668
  }
22750
- function conversationDisplayTitle(conversation, labels) {
22751
- return resolveAgentGUIConversationDisplayTitle(
22752
- conversation,
22753
- labels.fallbackAgentTitle
22754
- );
22755
- }
22756
22669
  function conversationPlainTitle(conversation, labels, uiLanguage) {
22757
- return formatAgentSessionMentionText(
22758
- conversationDisplayTitle(conversation, labels),
22759
- {
22760
- language: uiLanguage
22761
- }
22762
- );
22670
+ return formatAgentGUIConversationPlainTitle(conversation, {
22671
+ fallbackAgentLabel: labels.fallbackAgentTitle,
22672
+ language: uiLanguage
22673
+ });
22763
22674
  }
22764
22675
  function AgentGUINodeView({
22765
22676
  viewModel,
@@ -23386,6 +23297,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23386
23297
  const bottomDockRef = useRef13(null);
23387
23298
  const timelineScrollAnchorRef = useRef13(null);
23388
23299
  const pendingPrependScrollAnchorRef = useRef13(null);
23300
+ const [isTimelineScrolledToTop, setIsTimelineScrolledToTop] = useState12(true);
23389
23301
  const [
23390
23302
  bottomDockDismissedPromptRequestId,
23391
23303
  setBottomDockDismissedPromptRequestId
@@ -24037,6 +23949,8 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24037
23949
  const activeConversationId = viewModel.activeConversationId;
24038
23950
  if (!activeConversationId) {
24039
23951
  timelineScrollAnchorRef.current = null;
23952
+ pendingPrependScrollAnchorRef.current = null;
23953
+ setIsTimelineScrolledToTop(true);
24040
23954
  return;
24041
23955
  }
24042
23956
  const maxScrollTop = Math.max(
@@ -24079,6 +23993,9 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24079
23993
  scrollTop: nextScrollTop,
24080
23994
  clientHeight: timeline.clientHeight
24081
23995
  };
23996
+ setIsTimelineScrolledToTop(
23997
+ nextScrollTop <= AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX
23998
+ );
24082
23999
  }, [
24083
24000
  conversation,
24084
24001
  showTimelineSkeleton,
@@ -24137,6 +24054,9 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24137
24054
  scrollTop: maxScrollTop,
24138
24055
  clientHeight: timeline.clientHeight
24139
24056
  };
24057
+ setIsTimelineScrolledToTop(
24058
+ maxScrollTop <= AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX
24059
+ );
24140
24060
  });
24141
24061
  };
24142
24062
  syncBottomDockSpace();
@@ -24171,17 +24091,21 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24171
24091
  return;
24172
24092
  }
24173
24093
  const captureScrollAnchor = () => {
24094
+ const scrollTop = timeline.scrollTop;
24174
24095
  timelineScrollAnchorRef.current = {
24175
24096
  conversationId: activeConversationId,
24176
24097
  scrollHeight: timeline.scrollHeight,
24177
- scrollTop: timeline.scrollTop,
24098
+ scrollTop,
24178
24099
  clientHeight: timeline.clientHeight
24179
24100
  };
24180
- if (viewModel.hasOlderMessages && !viewModel.isLoadingOlderMessages && timeline.scrollTop <= AGENT_GUI_TOP_HISTORY_PREFETCH_THRESHOLD_PX) {
24101
+ setIsTimelineScrolledToTop(
24102
+ scrollTop <= AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX
24103
+ );
24104
+ if (viewModel.hasOlderMessages && !viewModel.isLoadingOlderMessages && scrollTop <= AGENT_GUI_TOP_HISTORY_PREFETCH_THRESHOLD_PX) {
24181
24105
  pendingPrependScrollAnchorRef.current = {
24182
24106
  conversationId: activeConversationId,
24183
24107
  scrollHeight: timeline.scrollHeight,
24184
- scrollTop: timeline.scrollTop
24108
+ scrollTop
24185
24109
  };
24186
24110
  actions.loadOlderConversationMessages();
24187
24111
  }
@@ -24251,7 +24175,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24251
24175
  className: "min-h-0 flex-1 [&_[data-orientation=vertical][data-slot=scroll-area-scrollbar]]:opacity-100",
24252
24176
  viewportRef: timelineRef,
24253
24177
  viewportTestId: "agent-gui-timeline",
24254
- viewportClassName: `${AgentGUINode_styles_default.timeline} ${hasActiveConversation ? AgentGUINode_styles_default.timelineWithComposer : AgentGUINode_styles_default.timelineCentered} ${showUnavailableChatEmpty ? AgentGUINode_styles_default.timelineUnavailableChatEmpty : ""}`.trim(),
24178
+ viewportClassName: `${AgentGUINode_styles_default.timeline} ${hasActiveConversation ? AgentGUINode_styles_default.timelineWithComposer : AgentGUINode_styles_default.timelineCentered} ${!isTimelineScrolledToTop ? AgentGUINode_styles_default.timelineScrolledFromTop : ""} ${showUnavailableChatEmpty ? AgentGUINode_styles_default.timelineUnavailableChatEmpty : ""}`.trim(),
24255
24179
  viewportContentStyle: AGENT_GUI_TIMELINE_SCROLL_AREA_CONTENT_STYLE,
24256
24180
  children: !hasActiveConversation ? /* @__PURE__ */ jsx30(
24257
24181
  AgentGUIEmptyHeroPane,
@@ -24926,7 +24850,7 @@ var AgentGUIConversationRailPane = memo(
24926
24850
  })
24927
24851
  }
24928
24852
  ),
24929
- /* @__PURE__ */ jsx30("div", { className: "shrink-0 border-t border-[var(--border-1)] px-2 py-1.5", children: /* @__PURE__ */ jsxs17(Popover, { children: [
24853
+ /* @__PURE__ */ jsx30("div", { className: "shrink-0 px-2 py-1.5", children: /* @__PURE__ */ jsxs17(Popover, { children: [
24930
24854
  /* @__PURE__ */ jsx30(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs17(
24931
24855
  Button,
24932
24856
  {
@@ -26579,13 +26503,10 @@ var AgentGUINode = memo2(function AgentGUINode2({
26579
26503
  const displayProviderLabel = viewModel.activeConversation ? resolveAgentGUIProviderDisplayLabel(activeProvider, fallbackAgentTitle) : selectedProviderTargetLabel;
26580
26504
  const windowAgentTitle = viewModel.activeConversation ? getAgentHostManagedToolchainAgentByName(activeProvider)?.label ?? displayProviderLabel : displayProviderLabel;
26581
26505
  const activeConversationDockTitle = viewModel.activeConversation ? resolveAgentGUIDockConversationTitle(viewModel.activeConversation) : null;
26582
- const activeConversationWindowTitle = viewModel.activeConversation ? formatAgentSessionMentionText(
26583
- resolveAgentGUIConversationDisplayTitle(
26584
- viewModel.activeConversation,
26585
- fallbackAgentTitle
26586
- ),
26587
- { language: locale }
26588
- ) : null;
26506
+ const activeConversationWindowTitle = viewModel.activeConversation ? formatAgentGUIConversationPlainTitle(viewModel.activeConversation, {
26507
+ fallbackAgentLabel: fallbackAgentTitle,
26508
+ language: locale
26509
+ }) : null;
26589
26510
  const labels = useMemo11(
26590
26511
  () => ({
26591
26512
  initialPlaceholder: t("agentHost.agentGui.initialPlaceholder", {
@@ -26932,8 +26853,12 @@ var AgentGUINode = memo2(function AgentGUINode2({
26932
26853
  "agentHost.agentGui.slashPaletteConnectorsGroup"
26933
26854
  ),
26934
26855
  slashPaletteMcpGroup: t("agentHost.agentGui.slashPaletteMcpGroup"),
26935
- slashCommandCompactLabel: t("agentHost.agentGui.slashCommandCompactLabel"),
26936
- slashCommandContextLabel: t("agentHost.agentGui.slashCommandContextLabel"),
26856
+ slashCommandCompactLabel: t(
26857
+ "agentHost.agentGui.slashCommandCompactLabel"
26858
+ ),
26859
+ slashCommandContextLabel: t(
26860
+ "agentHost.agentGui.slashCommandContextLabel"
26861
+ ),
26937
26862
  slashCommandFastLabel: t("agentHost.agentGui.slashCommandFastLabel"),
26938
26863
  slashCommandGoalLabel: t("agentHost.agentGui.slashCommandGoalLabel"),
26939
26864
  slashCommandInitLabel: t("agentHost.agentGui.slashCommandInitLabel"),