@tutti-os/agent-gui 0.0.44 → 0.0.46

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 (49) 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 +154 -69
  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-BAQTM6VS.js} +15 -6
  11. package/dist/chunk-BAQTM6VS.js.map +1 -0
  12. package/dist/{chunk-ZORA4UAT.js → chunk-D6IYEVDT.js} +2 -2
  13. package/dist/chunk-EIC7XS3C.js +71 -0
  14. package/dist/chunk-EIC7XS3C.js.map +1 -0
  15. package/dist/chunk-FJG2EH4V.js +317 -0
  16. package/dist/chunk-FJG2EH4V.js.map +1 -0
  17. package/dist/{chunk-64OSXJRE.js → chunk-FRG36S6N.js} +26 -7
  18. package/dist/chunk-FRG36S6N.js.map +1 -0
  19. package/dist/{chunk-J4MU53PH.js → chunk-NZ2BGOJU.js} +2 -2
  20. package/dist/chunk-OL54R6OL.js +99 -0
  21. package/dist/chunk-OL54R6OL.js.map +1 -0
  22. package/dist/{chunk-ZTQKIJ5J.js → chunk-QT45WUPQ.js} +71 -20
  23. package/dist/chunk-QT45WUPQ.js.map +1 -0
  24. package/dist/{chunk-IGXC7NRW.js → chunk-VFQR7AZI.js} +10 -63
  25. package/dist/chunk-VFQR7AZI.js.map +1 -0
  26. package/dist/{chunk-SF2PE7M6.js → chunk-ZJ7OSY4T.js} +4 -4
  27. package/dist/context-mention-palette/index.js +7 -6
  28. package/dist/i18n/index.d.ts +2 -2
  29. package/dist/i18n/index.js +2 -1
  30. package/dist/index.d.ts +1 -5
  31. package/dist/index.js +321 -245
  32. package/dist/index.js.map +1 -1
  33. package/dist/uiSettings-BQS9r2eo.d.ts +6 -0
  34. package/dist/workbench/contribution.js +1 -1
  35. package/dist/workbench/index.d.ts +3 -0
  36. package/dist/workbench/index.js +13 -2
  37. package/dist/workbench/sessionTitle.d.ts +28 -0
  38. package/dist/workbench/sessionTitle.js +14 -0
  39. package/dist/workbench/sessionTitle.js.map +1 -0
  40. package/dist/workspace-agent-generated-files.js +3 -2
  41. package/package.json +21 -14
  42. package/dist/chunk-25VZHG6G.js.map +0 -1
  43. package/dist/chunk-64OSXJRE.js.map +0 -1
  44. package/dist/chunk-GMLK2EFU.js.map +0 -1
  45. package/dist/chunk-IGXC7NRW.js.map +0 -1
  46. package/dist/chunk-ZTQKIJ5J.js.map +0 -1
  47. /package/dist/{chunk-ZORA4UAT.js.map → chunk-D6IYEVDT.js.map} +0 -0
  48. /package/dist/{chunk-J4MU53PH.js.map → chunk-NZ2BGOJU.js.map} +0 -0
  49. /package/dist/{chunk-SF2PE7M6.js.map → chunk-ZJ7OSY4T.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-BAQTM6VS.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-ZJ7OSY4T.js";
66
76
  import {
67
77
  WORKSPACE_AGENT_ACTIVITY_RUNTIME_SESSION_ORIGIN,
68
78
  buildWorkspaceAgentActivityListViewModel,
@@ -72,24 +82,25 @@ 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 {
97
+ AGENT_RICH_TEXT_CARET_ANCHOR,
87
98
  exitAgentFileMentionSuggestion,
88
99
  formatAgentMentionMarkdown,
89
100
  mentionItemToAttrs,
90
101
  normalizeAgentSessionMentionTitle,
91
102
  parseMentionItemFromHref
92
- } from "./chunk-64OSXJRE.js";
103
+ } from "./chunk-FRG36S6N.js";
93
104
  import "./chunk-Y35GDLP2.js";
94
105
  import {
95
106
  AgentActivityHostProvider,
@@ -108,9 +119,7 @@ import "./chunk-TYGL25EL.js";
108
119
  import {
109
120
  AGENT_CONTEXT_MENTION_PROVIDER_IDS
110
121
  } from "./chunk-JM24HADP.js";
111
- import {
112
- normalizeAgentTitleText
113
- } from "./chunk-GCBDIQDX.js";
122
+ import "./chunk-GCBDIQDX.js";
114
123
  import {
115
124
  AgentGuiI18nProvider,
116
125
  agentGuiI18nModule,
@@ -118,7 +127,8 @@ import {
118
127
  getActiveUiLanguage,
119
128
  translate,
120
129
  useTranslation
121
- } from "./chunk-IGXC7NRW.js";
130
+ } from "./chunk-EIC7XS3C.js";
131
+ import "./chunk-VFQR7AZI.js";
122
132
  import "./chunk-LUGELG5V.js";
123
133
  import "./chunk-PJP5BUU6.js";
124
134
 
@@ -2040,6 +2050,7 @@ function WorkspaceNodeWindow({
2040
2050
  const renderedChildren = typeof children === "function" ? children(renderedFrame) : children;
2041
2051
  const rootStyle = appearance === "embedded" ? {
2042
2052
  "--node-header-padding-x": "16px",
2053
+ "--node-header-traffic-light-title-offset": "64px",
2043
2054
  ...resolvedStyle,
2044
2055
  width: "100%",
2045
2056
  height: "100%",
@@ -2051,6 +2062,7 @@ function WorkspaceNodeWindow({
2051
2062
  WebkitBackdropFilter: "none"
2052
2063
  } : {
2053
2064
  "--node-header-padding-x": "16px",
2065
+ "--node-header-traffic-light-title-offset": "64px",
2054
2066
  ...resolvedStyle,
2055
2067
  background: "transparent",
2056
2068
  border: "1px solid var(--node-window-border)",
@@ -2087,7 +2099,7 @@ function WorkspaceNodeWindow({
2087
2099
  hideHeader ? null : customHeader ? customHeader : /* @__PURE__ */ jsxs3(
2088
2100
  "header",
2089
2101
  {
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",
2102
+ 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
2103
  style: {
2092
2104
  borderBottomColor: "var(--node-header-border)",
2093
2105
  background: "var(--node-header-surface)"
@@ -2106,7 +2118,7 @@ function WorkspaceNodeWindow({
2106
2118
  /* @__PURE__ */ jsxs3(
2107
2119
  "div",
2108
2120
  {
2109
- className: "workspace-node-window__controls nodrag absolute left-4 top-1/2 inline-flex -translate-y-1/2 items-center gap-2",
2121
+ 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
2122
  "data-workspace-node-window-controls": "true",
2111
2123
  children: [
2112
2124
  /* @__PURE__ */ jsx10(
@@ -2141,7 +2153,7 @@ function WorkspaceNodeWindow({
2141
2153
  /* @__PURE__ */ jsxs3(
2142
2154
  "div",
2143
2155
  {
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",
2156
+ 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
2157
  "data-workspace-node-window-title": "true",
2146
2158
  title,
2147
2159
  children: [
@@ -2228,16 +2240,17 @@ function WorkspaceNodeTrafficLightButton({
2228
2240
  event.stopPropagation();
2229
2241
  onClick();
2230
2242
  };
2243
+ const iconName = tone === "maximize" ? pressed ? "unfullscreen" : "fullscreen" : tone;
2231
2244
  return /* @__PURE__ */ jsx10(
2232
2245
  "button",
2233
2246
  {
2234
2247
  "aria-label": ariaLabel,
2235
2248
  "aria-pressed": pressed,
2236
2249
  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]"
2250
+ "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)]",
2251
+ tone === "close" && "group-hover/traffic-lights:before:bg-[#ff5f57] group-focus-within/traffic-lights:before:bg-[#ff5f57]",
2252
+ tone === "minimize" && "group-hover/traffic-lights:before:bg-[#ffbd2e] group-focus-within/traffic-lights:before:bg-[#ffbd2e]",
2253
+ tone === "maximize" && "group-hover/traffic-lights:before:bg-[#28c840] group-focus-within/traffic-lights:before:bg-[#28c840]"
2241
2254
  ),
2242
2255
  "data-window-header": "top",
2243
2256
  "data-workspace-node-window-traffic-light": tone,
@@ -2246,10 +2259,42 @@ function WorkspaceNodeTrafficLightButton({
2246
2259
  type: "button",
2247
2260
  onClick: handleClick,
2248
2261
  onDoubleClick: (event) => event.stopPropagation(),
2249
- onPointerDown: (event) => event.stopPropagation()
2262
+ onPointerDown: (event) => event.stopPropagation(),
2263
+ children: /* @__PURE__ */ jsx10(
2264
+ WorkspaceNodeWindowTrafficLightIcon,
2265
+ {
2266
+ "aria-hidden": "true",
2267
+ 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",
2268
+ "data-workspace-node-window-traffic-light-icon": iconName,
2269
+ iconName
2270
+ }
2271
+ )
2250
2272
  }
2251
2273
  );
2252
2274
  }
2275
+ function WorkspaceNodeWindowTrafficLightIcon({
2276
+ className,
2277
+ iconName,
2278
+ ...props
2279
+ }) {
2280
+ return /* @__PURE__ */ jsx10(
2281
+ "svg",
2282
+ {
2283
+ ...props,
2284
+ className,
2285
+ fill: "currentColor",
2286
+ viewBox: "0 0 24 24",
2287
+ xmlns: "http://www.w3.org/2000/svg",
2288
+ children: /* @__PURE__ */ jsx10("path", { d: trafficLightIconPathByName[iconName] })
2289
+ }
2290
+ );
2291
+ }
2292
+ var trafficLightIconPathByName = {
2293
+ 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",
2294
+ 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",
2295
+ 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",
2296
+ 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"
2297
+ };
2253
2298
 
2254
2299
  // agent-gui/agentGuiNode/controller/useAgentGUINodeController.ts
2255
2300
  import {
@@ -2363,141 +2408,6 @@ var DEFAULT_AGENT_SETTINGS = {
2363
2408
  hideWorktreeMismatchDropWarning: false
2364
2409
  };
2365
2410
 
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
2411
  // agent-gui/agentGuiNode/model/agentGuiConversationProjectResolver.ts
2502
2412
  import { resolveWorkspaceUserProjectDisplayLabel } from "@tutti-os/workspace-user-project/core";
2503
2413
  var AGENT_GUI_CONVERSATION_PROJECT_SUMMARY_CACHE_LIMIT = 512;
@@ -2960,10 +2870,7 @@ function firstUserMessageTitleFromTimelineItems(timelineItems) {
2960
2870
  return userMessage ? timelineItemText(userMessage) : "";
2961
2871
  }
2962
2872
  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) : "";
2873
+ return firstAgentGUIUserMessageTitle(messages);
2967
2874
  }
2968
2875
  function workspaceAgentMessagesFromTimelineItems(timelineItems) {
2969
2876
  return timelineItems.map((item, index) => {
@@ -2993,38 +2900,6 @@ function workspaceAgentMessagesFromTimelineItems(timelineItems) {
2993
2900
  };
2994
2901
  });
2995
2902
  }
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
2903
  function timelineItemRole(item) {
3029
2904
  const role = item.role?.trim().toLowerCase();
3030
2905
  if (role === "user") {
@@ -3579,7 +3454,7 @@ function projectWorkspaceAgentMessagesToTimelineItems(messages) {
3579
3454
  actorType: "agent",
3580
3455
  itemType: "message.assistant_thinking",
3581
3456
  role: "assistant_thinking",
3582
- content: messageText2(message),
3457
+ content: messageText(message),
3583
3458
  occurredAtUnixMs
3584
3459
  });
3585
3460
  }
@@ -3593,7 +3468,7 @@ function projectWorkspaceAgentMessagesToTimelineItems(messages) {
3593
3468
  actorType: "user",
3594
3469
  itemType: "message.user",
3595
3470
  role: "user",
3596
- content: messageText2(message),
3471
+ content: messageText(message),
3597
3472
  occurredAtUnixMs
3598
3473
  });
3599
3474
  }
@@ -3607,7 +3482,7 @@ function projectWorkspaceAgentMessagesToTimelineItems(messages) {
3607
3482
  actorType: "agent",
3608
3483
  itemType: "message.assistant",
3609
3484
  role: "assistant",
3610
- content: messageText2(message),
3485
+ content: messageText(message),
3611
3486
  occurredAtUnixMs
3612
3487
  });
3613
3488
  }
@@ -3734,7 +3609,7 @@ function toolCallItemType(status) {
3734
3609
  return "call";
3735
3610
  }
3736
3611
  }
3737
- function messageText2(message) {
3612
+ function messageText(message) {
3738
3613
  const payload = normalizedPayload(message.payload);
3739
3614
  const title = messagePayloadString(message, "title");
3740
3615
  return firstNonEmptyString(
@@ -3748,7 +3623,7 @@ function messageText2(message) {
3748
3623
  }
3749
3624
  function statusMessageText(message) {
3750
3625
  const title = messagePayloadString(message, "title") ?? "";
3751
- const text = messageText2(message);
3626
+ const text = messageText(message);
3752
3627
  if (title && text && title !== text) {
3753
3628
  return `${title}
3754
3629
 
@@ -7434,8 +7309,31 @@ function sessionHasRenderableMessages(input) {
7434
7309
  const sessionView = getAgentSessionView(
7435
7310
  input.sessionViewRef(normalizedAgentSessionId)
7436
7311
  );
7312
+ if (sessionViewHasUnhydratedOlderDetailMessages({
7313
+ agentSessionId: normalizedAgentSessionId,
7314
+ detailMessages: sessionView?.detailMessages ?? [],
7315
+ hasLoadedInitialMessages: input.hasLoadedInitialMessages === true,
7316
+ hasOlderMessages: sessionView?.hasOlderMessages ?? false,
7317
+ oldestLoadedVersion: sessionView?.oldestLoadedVersion ?? null,
7318
+ snapshotMessagesById: input.snapshotMessagesById
7319
+ })) {
7320
+ return false;
7321
+ }
7437
7322
  return (sessionView?.detailMessages?.length ?? 0) > 0 || (sessionView?.overlayMessages?.length ?? 0) > 0;
7438
7323
  }
7324
+ function sessionViewHasUnhydratedOlderDetailMessages(input) {
7325
+ if (input.hasLoadedInitialMessages || input.hasOlderMessages || input.detailMessages.length === 0) {
7326
+ return false;
7327
+ }
7328
+ const oldestLoadedVersion = input.oldestLoadedVersion ?? minFiniteMessageVersion(input.detailMessages);
7329
+ if (oldestLoadedVersion === null) {
7330
+ return false;
7331
+ }
7332
+ const snapshotOldestVersion = minFiniteMessageVersion(
7333
+ input.snapshotMessagesById[input.agentSessionId] ?? []
7334
+ );
7335
+ return oldestLoadedVersion > 1 || snapshotOldestVersion !== null && snapshotOldestVersion < oldestLoadedVersion;
7336
+ }
7439
7337
  function filterMessagesForDetailWindowOverlay(input) {
7440
7338
  if (input.localMessages.length === 0) {
7441
7339
  return [];
@@ -9425,6 +9323,9 @@ function useAgentGUINodeController({
9425
9323
  if (previous !== normalized) {
9426
9324
  const hasCachedMessages = sessionHasRenderableMessages({
9427
9325
  agentSessionId: normalized,
9326
+ hasLoadedInitialMessages: selectedConversationInitialMessagesLoadedIdsRef.current.has(
9327
+ normalized
9328
+ ),
9428
9329
  sessionViewRef,
9429
9330
  snapshotMessagesById: agentActivitySnapshotRef.current.sessionMessagesById
9430
9331
  });
@@ -10396,6 +10297,9 @@ function useAgentGUINodeController({
10396
10297
  );
10397
10298
  const hasRenderableMessages = sessionHasRenderableMessages({
10398
10299
  agentSessionId: normalizedAgentSessionId,
10300
+ hasLoadedInitialMessages: selectedConversationInitialMessagesLoadedIdsRef.current.has(
10301
+ normalizedAgentSessionId
10302
+ ),
10399
10303
  sessionViewRef,
10400
10304
  snapshotMessagesById: agentActivitySnapshotRef.current.sessionMessagesById
10401
10305
  });
@@ -10646,8 +10550,9 @@ function useAgentGUINodeController({
10646
10550
  if (nextMessages.length === 0) {
10647
10551
  return;
10648
10552
  }
10649
- const currentMessages = getAgentSessionView(sessionViewRef(agentSessionId))?.overlayMessages ?? [];
10650
- const currentDetailMessages = getAgentSessionView(sessionViewRef(agentSessionId))?.detailMessages ?? [];
10553
+ const currentView = getAgentSessionView(sessionViewRef(agentSessionId));
10554
+ const currentMessages = currentView?.overlayMessages ?? [];
10555
+ const currentDetailMessages = currentView?.detailMessages ?? [];
10651
10556
  const currentDurableDetailMessages = currentDetailMessages.filter(
10652
10557
  (message) => !isWorkspaceAgentActivityOptimisticMessage(message)
10653
10558
  );
@@ -10671,7 +10576,19 @@ function useAgentGUINodeController({
10671
10576
  if (durableDetailWindowMessages.length > 0) {
10672
10577
  mergeAgentSessionViewDetailMessages(
10673
10578
  sessionViewRef(agentSessionId),
10674
- durableDetailWindowMessages
10579
+ durableDetailWindowMessages,
10580
+ {
10581
+ hasOlderMessages: currentView?.hasOlderMessages === true || sessionViewHasUnhydratedOlderDetailMessages({
10582
+ agentSessionId,
10583
+ detailMessages: nextDetailMessages,
10584
+ hasLoadedInitialMessages: selectedConversationInitialMessagesLoadedIdsRef.current.has(
10585
+ agentSessionId
10586
+ ),
10587
+ hasOlderMessages: currentView?.hasOlderMessages ?? false,
10588
+ oldestLoadedVersion: minFiniteMessageVersion(nextDetailMessages),
10589
+ snapshotMessagesById: agentActivitySnapshot.sessionMessagesById
10590
+ })
10591
+ }
10675
10592
  );
10676
10593
  }
10677
10594
  const durableMessages = nextDetailMessages.length > 0 ? nextDetailMessages : durableSnapshotMessages;
@@ -15767,7 +15684,7 @@ import {
15767
15684
  } from "@tutti-os/ui-system";
15768
15685
 
15769
15686
  // agent-gui/agentGuiNode/AgentComposer.tsx
15770
- import { AddIcon, Select as Select2, SelectTrigger as SelectTrigger2 } from "@tutti-os/ui-system";
15687
+ import { AddIcon, Button as Button3, Select as Select2, SelectTrigger as SelectTrigger2 } from "@tutti-os/ui-system";
15771
15688
  import { ListChecks as ListChecks2, Target as Target3, X } from "lucide-react";
15772
15689
  import {
15773
15690
  createMentionPaletteStateAdapter,
@@ -16535,6 +16452,7 @@ var styles3 = {
16535
16452
  shell: "agent-gui-node__shell",
16536
16453
  timeline: "agent-gui-node__timeline",
16537
16454
  timelineCentered: "agent-gui-node__timeline-centered",
16455
+ timelineScrolledFromTop: "agent-gui-node__timeline--scrolled-from-top",
16538
16456
  transcriptSkeleton: "agent-gui-node__transcript-skeleton",
16539
16457
  transcriptSkeletonBubble: "agent-gui-node__transcript-skeleton-bubble",
16540
16458
  transcriptSkeletonLine: "agent-gui-node__transcript-skeleton-line",
@@ -17797,7 +17715,11 @@ import {
17797
17715
  } from "react";
17798
17716
  import { createPortal } from "react-dom";
17799
17717
  import { Extension } from "@tiptap/core";
17800
- import { Plugin, PluginKey } from "@tiptap/pm/state";
17718
+ import {
17719
+ Plugin,
17720
+ PluginKey,
17721
+ TextSelection
17722
+ } from "@tiptap/pm/state";
17801
17723
  import { Decoration, DecorationSet } from "@tiptap/pm/view";
17802
17724
  import { EditorContent, useEditor } from "@tiptap/react";
17803
17725
 
@@ -17825,19 +17747,23 @@ function referenceMentionPath(item) {
17825
17747
  }
17826
17748
  return path;
17827
17749
  }
17828
- function createAgentMentionContent(items) {
17750
+ function createAgentMentionContent(items, options = {}) {
17829
17751
  return items.flatMap((item, index) => [
17830
- ...index > 0 ? [{ type: "text", text: " " }] : [],
17752
+ ...index === 0 && options.prefixCaretAnchor ? [
17753
+ { type: "text", text: AGENT_RICH_TEXT_CARET_ANCHOR }
17754
+ ] : index > 0 ? [{ type: "text", text: " " }] : [],
17831
17755
  { type: "agentFileMention", attrs: mentionItemToAttrs(item) },
17832
17756
  { type: "text", text: " " }
17833
17757
  ]);
17834
17758
  }
17835
- function createAgentFileMentionContent(items) {
17759
+ function createAgentFileMentionContent(items, options = {}) {
17836
17760
  return items.flatMap((item, index) => {
17837
17761
  const path = referenceMentionPath(item);
17838
17762
  const name = item.displayName?.trim() || basename(path);
17839
17763
  return [
17840
- ...index > 0 ? [{ type: "text", text: " " }] : [],
17764
+ ...index === 0 && options.prefixCaretAnchor ? [
17765
+ { type: "text", text: AGENT_RICH_TEXT_CARET_ANCHOR }
17766
+ ] : index > 0 ? [{ type: "text", text: " " }] : [],
17841
17767
  {
17842
17768
  type: "agentFileMention",
17843
17769
  attrs: {
@@ -17998,8 +17924,11 @@ function fileToBase64(file) {
17998
17924
 
17999
17925
  // agent-gui/agentGuiNode/agentRichText/AgentRichTextEditor.tsx
18000
17926
  import { jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
18001
- function buildWorkspaceFileMentionDropContent(entries) {
18002
- return entries.flatMap((entry) => [
17927
+ function buildWorkspaceFileMentionDropContent(entries, options = {}) {
17928
+ return entries.flatMap((entry, index) => [
17929
+ ...index === 0 && options.prefixCaretAnchor ? [
17930
+ { type: "text", text: AGENT_RICH_TEXT_CARET_ANCHOR }
17931
+ ] : [],
18003
17932
  {
18004
17933
  type: "agentFileMention",
18005
17934
  attrs: {
@@ -18013,6 +17942,79 @@ function buildWorkspaceFileMentionDropContent(entries) {
18013
17942
  { type: "text", text: " " }
18014
17943
  ]);
18015
17944
  }
17945
+ function isPromptVisualLineStart(editor, position) {
17946
+ if (position <= 1) {
17947
+ return true;
17948
+ }
17949
+ return editor.state.doc.textBetween(
17950
+ Math.max(1, position - 1),
17951
+ position,
17952
+ "\n",
17953
+ "\n"
17954
+ ) === "\n";
17955
+ }
17956
+ function findCaretAnchorBeforeAtomicRun(doc, position) {
17957
+ let anchorPosition = null;
17958
+ doc.descendants((node, nodePosition) => {
17959
+ if (nodePosition >= position) {
17960
+ return false;
17961
+ }
17962
+ if (node.isText) {
17963
+ const text = node.text ?? "";
17964
+ for (let offset = 0; offset < text.length; offset += 1) {
17965
+ const characterPosition = nodePosition + offset;
17966
+ if (characterPosition >= position) {
17967
+ return false;
17968
+ }
17969
+ if (text[offset] === AGENT_RICH_TEXT_CARET_ANCHOR) {
17970
+ anchorPosition = characterPosition;
17971
+ continue;
17972
+ }
17973
+ if (anchorPosition !== null) {
17974
+ anchorPosition = null;
17975
+ }
17976
+ }
17977
+ return true;
17978
+ }
17979
+ if (node.type.name === "agentFileMention") {
17980
+ return false;
17981
+ }
17982
+ if (node.isInline && anchorPosition !== null) {
17983
+ anchorPosition = null;
17984
+ }
17985
+ return true;
17986
+ });
17987
+ return anchorPosition;
17988
+ }
17989
+ function moveSelectionOverCaretAnchor(state, dispatch, key) {
17990
+ const { doc, selection } = state;
17991
+ if (!selection.empty) {
17992
+ return false;
17993
+ }
17994
+ const position = selection.from;
17995
+ if (key === "ArrowLeft") {
17996
+ const anchorPosition = findCaretAnchorBeforeAtomicRun(doc, position);
17997
+ if (anchorPosition === null) {
17998
+ return false;
17999
+ }
18000
+ dispatch(state.tr.setSelection(TextSelection.create(doc, anchorPosition)));
18001
+ return true;
18002
+ }
18003
+ if (key === "ArrowRight" && position < doc.content.size && doc.textBetween(position, position + 1) === AGENT_RICH_TEXT_CARET_ANCHOR) {
18004
+ const afterAnchor = position + 1;
18005
+ const mentionAfterAnchor = doc.resolve(afterAnchor).nodeAfter;
18006
+ dispatch(
18007
+ state.tr.setSelection(
18008
+ TextSelection.create(
18009
+ doc,
18010
+ afterAnchor + (mentionAfterAnchor?.type.name === "agentFileMention" ? mentionAfterAnchor.nodeSize : 0)
18011
+ )
18012
+ )
18013
+ );
18014
+ return true;
18015
+ }
18016
+ return false;
18017
+ }
18016
18018
  function createAgentRichTextPlaceholderExtension(getPlaceholder) {
18017
18019
  return Extension.create({
18018
18020
  name: "agentRichTextPlaceholder",
@@ -18040,6 +18042,34 @@ function createAgentRichTextPlaceholderExtension(getPlaceholder) {
18040
18042
  }
18041
18043
  });
18042
18044
  }
18045
+ function createAgentRichTextCaretAnchorExtension() {
18046
+ return Extension.create({
18047
+ name: "agentRichTextCaretAnchor",
18048
+ addProseMirrorPlugins() {
18049
+ return [
18050
+ new Plugin({
18051
+ key: new PluginKey("agentRichTextCaretAnchor"),
18052
+ props: {
18053
+ handleKeyDown(view, event) {
18054
+ if (event.key !== "ArrowLeft" && event.key !== "ArrowRight" || event.shiftKey || event.metaKey || event.ctrlKey || event.altKey) {
18055
+ return false;
18056
+ }
18057
+ if (moveSelectionOverCaretAnchor(
18058
+ view.state,
18059
+ (transaction) => view.dispatch(transaction),
18060
+ event.key
18061
+ )) {
18062
+ event.preventDefault();
18063
+ return true;
18064
+ }
18065
+ return false;
18066
+ }
18067
+ }
18068
+ })
18069
+ ];
18070
+ }
18071
+ });
18072
+ }
18043
18073
  function scrollEditorSelectionIntoView(editor) {
18044
18074
  const scrollContainer = editor.view.dom;
18045
18075
  if (!(scrollContainer instanceof HTMLElement)) {
@@ -18277,6 +18307,7 @@ var AgentRichTextEditor = forwardRef3(function AgentRichTextEditor2({
18277
18307
  { skills: availableSkillsRef.current },
18278
18308
  { capabilities: availableCapabilitiesRef.current }
18279
18309
  ),
18310
+ createAgentRichTextCaretAnchorExtension(),
18280
18311
  createAgentRichTextPlaceholderExtension(() => placeholderRef.current)
18281
18312
  ],
18282
18313
  [enableFileMentionSuggestions]
@@ -18520,7 +18551,12 @@ var AgentRichTextEditor = forwardRef3(function AgentRichTextEditor2({
18520
18551
  const insertPosition = coordinatePosition ?? (Number.isInteger(fallbackSelectionPosition) ? fallbackSelectionPosition : null) ?? currentEditor.state.doc.content.size;
18521
18552
  currentEditor.chain().focus().insertContentAt(
18522
18553
  insertPosition,
18523
- buildWorkspaceFileMentionDropContent(entries)
18554
+ buildWorkspaceFileMentionDropContent(entries, {
18555
+ prefixCaretAnchor: isPromptVisualLineStart(
18556
+ currentEditor,
18557
+ insertPosition
18558
+ )
18559
+ })
18524
18560
  ).run();
18525
18561
  return true;
18526
18562
  }
@@ -18553,6 +18589,18 @@ var AgentRichTextEditor = forwardRef3(function AgentRichTextEditor2({
18553
18589
  event.stopPropagation();
18554
18590
  return;
18555
18591
  }
18592
+ if ((event.key === "ArrowLeft" || event.key === "ArrowRight") && !event.shiftKey && !event.metaKey && !event.ctrlKey && !event.altKey) {
18593
+ const currentEditor = editorRef.current;
18594
+ if (currentEditor && !currentEditor.isDestroyed && moveSelectionOverCaretAnchor(
18595
+ currentEditor.state,
18596
+ (transaction) => currentEditor.view.dispatch(transaction),
18597
+ event.key
18598
+ )) {
18599
+ event.preventDefault();
18600
+ event.stopPropagation();
18601
+ return;
18602
+ }
18603
+ }
18556
18604
  if (event.key === "Enter" && (event.metaKey || event.ctrlKey) && !event.shiftKey && !event.altKey) {
18557
18605
  event.preventDefault();
18558
18606
  event.stopPropagation();
@@ -18637,14 +18685,28 @@ var AgentRichTextEditor = forwardRef3(function AgentRichTextEditor2({
18637
18685
  if (!currentEditor || currentEditor.isDestroyed || items.length === 0) {
18638
18686
  return;
18639
18687
  }
18640
- currentEditor.chain().focus().insertContent(createAgentFileMentionContent(items)).run();
18688
+ currentEditor.chain().focus().insertContent(
18689
+ createAgentFileMentionContent(items, {
18690
+ prefixCaretAnchor: isPromptVisualLineStart(
18691
+ currentEditor,
18692
+ currentEditor.state.selection.from
18693
+ )
18694
+ })
18695
+ ).run();
18641
18696
  },
18642
18697
  insertMentionItems(items) {
18643
18698
  const currentEditor = editorRef.current;
18644
18699
  if (!currentEditor || currentEditor.isDestroyed || items.length === 0) {
18645
18700
  return;
18646
18701
  }
18647
- currentEditor.chain().focus().insertContent(createAgentMentionContent(items)).run();
18702
+ currentEditor.chain().focus().insertContent(
18703
+ createAgentMentionContent(items, {
18704
+ prefixCaretAnchor: isPromptVisualLineStart(
18705
+ currentEditor,
18706
+ currentEditor.state.selection.from
18707
+ )
18708
+ })
18709
+ ).run();
18648
18710
  },
18649
18711
  replaceTextBeforeSelection(length, text) {
18650
18712
  const currentEditor = editorRef.current;
@@ -19527,10 +19589,13 @@ var ComposerFloatingMenuSurface = forwardRef4(function ComposerFloatingMenuSurfa
19527
19589
  import { jsx as jsx27, jsxs as jsxs15 } from "react/jsx-runtime";
19528
19590
  var USAGE_POPOVER_HOVER_DELAY_MS = 120;
19529
19591
  var DOCK_COMPOSER_INPUT_MIN_HEIGHT = 56;
19530
- var DOCK_COMPOSER_INPUT_MAX_HEIGHT = 120;
19592
+ var DOCK_COMPOSER_TEXT_LINE_HEIGHT = 24;
19593
+ var DOCK_COMPOSER_MAX_VISIBLE_TEXT_LINES = 3.5;
19594
+ var DOCK_COMPOSER_INPUT_TEXT_CHROME_HEIGHT = 26;
19595
+ var DOCK_COMPOSER_TEXT_VIEWPORT_MAX_HEIGHT = DOCK_COMPOSER_TEXT_LINE_HEIGHT * DOCK_COMPOSER_MAX_VISIBLE_TEXT_LINES;
19596
+ var DOCK_COMPOSER_INPUT_MAX_HEIGHT = DOCK_COMPOSER_INPUT_TEXT_CHROME_HEIGHT + DOCK_COMPOSER_TEXT_VIEWPORT_MAX_HEIGHT;
19531
19597
  var DOCK_COMPOSER_INPUT_BORDER_HEIGHT = 2;
19532
19598
  var DOCK_COMPOSER_INPUT_PADDING_BLOCK_HEIGHT = 24;
19533
- var DOCK_COMPOSER_INPUT_TEXT_CHROME_HEIGHT = 26;
19534
19599
  function agentUsageChipLevel(percentUsed) {
19535
19600
  if (percentUsed >= USAGE_CRITICAL_PERCENT) {
19536
19601
  return "critical";
@@ -19689,12 +19754,14 @@ function AgentUsageChip({
19689
19754
  }
19690
19755
  ) : null,
19691
19756
  compactSupported && onCompact ? /* @__PURE__ */ jsx27(
19692
- "button",
19757
+ Button3,
19693
19758
  {
19694
19759
  type: "button",
19695
19760
  "data-testid": "agent-gui-compact-button",
19696
19761
  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]",
19762
+ className: "nodrag w-full font-medium [-webkit-app-region:no-drag]",
19763
+ size: "sm",
19764
+ variant: "secondary",
19698
19765
  onClick: onCompact,
19699
19766
  children: labels.usageCompactAction
19700
19767
  }
@@ -21287,7 +21354,10 @@ function AgentComposer({
21287
21354
  "--agent-gui-composer-attachment-height": `${dockComposerAttachmentHeight}px`,
21288
21355
  "--agent-gui-composer-input-height": `${dockComposerInputHeight}px`,
21289
21356
  "--agent-gui-composer-input-max-height": `${dockComposerInputMaxHeight}px`,
21290
- "--agent-gui-composer-text-height": `${dockComposerTextHeight}px`
21357
+ "--agent-gui-composer-text-height": `${dockComposerTextHeight}px`,
21358
+ "--agent-gui-composer-text-line-height": `${DOCK_COMPOSER_TEXT_LINE_HEIGHT}px`,
21359
+ "--agent-gui-composer-text-max-visible-lines": `${DOCK_COMPOSER_MAX_VISIBLE_TEXT_LINES}`,
21360
+ "--agent-gui-composer-text-viewport-height": `${DOCK_COMPOSER_TEXT_VIEWPORT_MAX_HEIGHT}px`
21291
21361
  },
21292
21362
  [
21293
21363
  dockComposerAttachmentHeight,
@@ -22555,13 +22625,13 @@ import { createRichTextMentionHref as createRichTextMentionHref2 } from "@tutti-
22555
22625
  import { Fragment as Fragment8, jsx as jsx30, jsxs as jsxs17 } from "react/jsx-runtime";
22556
22626
  var AGENT_GUI_STICK_TO_BOTTOM_THRESHOLD_PX = 24;
22557
22627
  var AGENT_GUI_TOP_HISTORY_PREFETCH_THRESHOLD_PX = 240;
22628
+ var AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX = 1;
22558
22629
  var AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE = 5;
22559
22630
  var AGENT_GUI_TIMELINE_SCROLL_AREA_CONTENT_STYLE = {
22560
22631
  width: "100%",
22561
22632
  minWidth: "100%",
22562
22633
  display: "grid",
22563
- gridTemplateColumns: "minmax(0, min(100%, var(--agent-gui-detail-flow-max-width)))",
22564
- justifyContent: "center",
22634
+ gridTemplateColumns: "minmax(0, 1fr)",
22565
22635
  gap: "24px"
22566
22636
  };
22567
22637
  var EMPTY_WORKSPACE_APP_ICONS3 = [];
@@ -22747,19 +22817,11 @@ function resolveActiveConversationBusyStatus(input) {
22747
22817
  }
22748
22818
  return null;
22749
22819
  }
22750
- function conversationDisplayTitle(conversation, labels) {
22751
- return resolveAgentGUIConversationDisplayTitle(
22752
- conversation,
22753
- labels.fallbackAgentTitle
22754
- );
22755
- }
22756
22820
  function conversationPlainTitle(conversation, labels, uiLanguage) {
22757
- return formatAgentSessionMentionText(
22758
- conversationDisplayTitle(conversation, labels),
22759
- {
22760
- language: uiLanguage
22761
- }
22762
- );
22821
+ return formatAgentGUIConversationPlainTitle(conversation, {
22822
+ fallbackAgentLabel: labels.fallbackAgentTitle,
22823
+ language: uiLanguage
22824
+ });
22763
22825
  }
22764
22826
  function AgentGUINodeView({
22765
22827
  viewModel,
@@ -23386,6 +23448,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23386
23448
  const bottomDockRef = useRef13(null);
23387
23449
  const timelineScrollAnchorRef = useRef13(null);
23388
23450
  const pendingPrependScrollAnchorRef = useRef13(null);
23451
+ const [isTimelineScrolledToTop, setIsTimelineScrolledToTop] = useState12(true);
23389
23452
  const [
23390
23453
  bottomDockDismissedPromptRequestId,
23391
23454
  setBottomDockDismissedPromptRequestId
@@ -24037,6 +24100,8 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24037
24100
  const activeConversationId = viewModel.activeConversationId;
24038
24101
  if (!activeConversationId) {
24039
24102
  timelineScrollAnchorRef.current = null;
24103
+ pendingPrependScrollAnchorRef.current = null;
24104
+ setIsTimelineScrolledToTop(true);
24040
24105
  return;
24041
24106
  }
24042
24107
  const maxScrollTop = Math.max(
@@ -24079,6 +24144,9 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24079
24144
  scrollTop: nextScrollTop,
24080
24145
  clientHeight: timeline.clientHeight
24081
24146
  };
24147
+ setIsTimelineScrolledToTop(
24148
+ nextScrollTop <= AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX
24149
+ );
24082
24150
  }, [
24083
24151
  conversation,
24084
24152
  showTimelineSkeleton,
@@ -24137,6 +24205,9 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24137
24205
  scrollTop: maxScrollTop,
24138
24206
  clientHeight: timeline.clientHeight
24139
24207
  };
24208
+ setIsTimelineScrolledToTop(
24209
+ maxScrollTop <= AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX
24210
+ );
24140
24211
  });
24141
24212
  };
24142
24213
  syncBottomDockSpace();
@@ -24171,17 +24242,21 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24171
24242
  return;
24172
24243
  }
24173
24244
  const captureScrollAnchor = () => {
24245
+ const scrollTop = timeline.scrollTop;
24174
24246
  timelineScrollAnchorRef.current = {
24175
24247
  conversationId: activeConversationId,
24176
24248
  scrollHeight: timeline.scrollHeight,
24177
- scrollTop: timeline.scrollTop,
24249
+ scrollTop,
24178
24250
  clientHeight: timeline.clientHeight
24179
24251
  };
24180
- if (viewModel.hasOlderMessages && !viewModel.isLoadingOlderMessages && timeline.scrollTop <= AGENT_GUI_TOP_HISTORY_PREFETCH_THRESHOLD_PX) {
24252
+ setIsTimelineScrolledToTop(
24253
+ scrollTop <= AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX
24254
+ );
24255
+ if (viewModel.hasOlderMessages && !viewModel.isLoadingOlderMessages && scrollTop <= AGENT_GUI_TOP_HISTORY_PREFETCH_THRESHOLD_PX) {
24181
24256
  pendingPrependScrollAnchorRef.current = {
24182
24257
  conversationId: activeConversationId,
24183
24258
  scrollHeight: timeline.scrollHeight,
24184
- scrollTop: timeline.scrollTop
24259
+ scrollTop
24185
24260
  };
24186
24261
  actions.loadOlderConversationMessages();
24187
24262
  }
@@ -24251,7 +24326,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24251
24326
  className: "min-h-0 flex-1 [&_[data-orientation=vertical][data-slot=scroll-area-scrollbar]]:opacity-100",
24252
24327
  viewportRef: timelineRef,
24253
24328
  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(),
24329
+ 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
24330
  viewportContentStyle: AGENT_GUI_TIMELINE_SCROLL_AREA_CONTENT_STYLE,
24256
24331
  children: !hasActiveConversation ? /* @__PURE__ */ jsx30(
24257
24332
  AgentGUIEmptyHeroPane,
@@ -24926,7 +25001,7 @@ var AgentGUIConversationRailPane = memo(
24926
25001
  })
24927
25002
  }
24928
25003
  ),
24929
- /* @__PURE__ */ jsx30("div", { className: "shrink-0 border-t border-[var(--border-1)] px-2 py-1.5", children: /* @__PURE__ */ jsxs17(Popover, { children: [
25004
+ /* @__PURE__ */ jsx30("div", { className: "shrink-0 px-2 py-1.5", children: /* @__PURE__ */ jsxs17(Popover, { children: [
24930
25005
  /* @__PURE__ */ jsx30(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs17(
24931
25006
  Button,
24932
25007
  {
@@ -26579,13 +26654,10 @@ var AgentGUINode = memo2(function AgentGUINode2({
26579
26654
  const displayProviderLabel = viewModel.activeConversation ? resolveAgentGUIProviderDisplayLabel(activeProvider, fallbackAgentTitle) : selectedProviderTargetLabel;
26580
26655
  const windowAgentTitle = viewModel.activeConversation ? getAgentHostManagedToolchainAgentByName(activeProvider)?.label ?? displayProviderLabel : displayProviderLabel;
26581
26656
  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;
26657
+ const activeConversationWindowTitle = viewModel.activeConversation ? formatAgentGUIConversationPlainTitle(viewModel.activeConversation, {
26658
+ fallbackAgentLabel: fallbackAgentTitle,
26659
+ language: locale
26660
+ }) : null;
26589
26661
  const labels = useMemo11(
26590
26662
  () => ({
26591
26663
  initialPlaceholder: t("agentHost.agentGui.initialPlaceholder", {
@@ -26932,8 +27004,12 @@ var AgentGUINode = memo2(function AgentGUINode2({
26932
27004
  "agentHost.agentGui.slashPaletteConnectorsGroup"
26933
27005
  ),
26934
27006
  slashPaletteMcpGroup: t("agentHost.agentGui.slashPaletteMcpGroup"),
26935
- slashCommandCompactLabel: t("agentHost.agentGui.slashCommandCompactLabel"),
26936
- slashCommandContextLabel: t("agentHost.agentGui.slashCommandContextLabel"),
27007
+ slashCommandCompactLabel: t(
27008
+ "agentHost.agentGui.slashCommandCompactLabel"
27009
+ ),
27010
+ slashCommandContextLabel: t(
27011
+ "agentHost.agentGui.slashCommandContextLabel"
27012
+ ),
26937
27013
  slashCommandFastLabel: t("agentHost.agentGui.slashCommandFastLabel"),
26938
27014
  slashCommandGoalLabel: t("agentHost.agentGui.slashCommandGoalLabel"),
26939
27015
  slashCommandInitLabel: t("agentHost.agentGui.slashCommandInitLabel"),