@truefoundry/trueforge-ui 0.3.0-rc.1 → 0.3.0-rc.2

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 (92) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +7 -0
  3. package/dist/{AgentCodeSnippets-NZOFJE57.js → AgentCodeSnippets-637HQUXD.js} +7 -7
  4. package/dist/AgentMetricChart-4FYECRIN.js +15 -0
  5. package/dist/{AgentOverview-EEBHJC32.js → AgentOverview-3FJ5EE6N.js} +7 -7
  6. package/dist/{AgentSessionEventTimeline-26Z6IB3B.js → AgentSessionEventTimeline-VELWUYPR.js} +18 -9
  7. package/dist/AgentSessionEventTimeline-VELWUYPR.js.map +1 -0
  8. package/dist/{AgentSessionEventTimelineChart-CGCU7WBK.js → AgentSessionEventTimelineChart-CUKETHWM.js} +140 -53
  9. package/dist/AgentSessionEventTimelineChart-CUKETHWM.js.map +1 -0
  10. package/dist/{AgentSessions-3MPDZASK.js → AgentSessions-T7MOGOTZ.js} +8 -8
  11. package/dist/{ConnectorSettings-MXFRWWR6.js → ConnectorSettings-ESZ2RSRG.js} +18 -22
  12. package/dist/ConnectorSettings-ESZ2RSRG.js.map +1 -0
  13. package/dist/{DockLayout-LM4AFMFY.js → DockLayout-NLFNU6F2.js} +10 -10
  14. package/dist/{DrawerLayout-JR3O6RRB.js → DrawerLayout-PR3SMKA6.js} +12 -12
  15. package/dist/DrawerLayout-PR3SMKA6.js.map +1 -0
  16. package/dist/{ModelSettings-G7IFNC2Y.js → ModelSettings-LYW64IRR.js} +19 -25
  17. package/dist/ModelSettings-LYW64IRR.js.map +1 -0
  18. package/dist/OpenUiFenceBlock-JEPNPJ7U.js +9 -0
  19. package/dist/{SandboxSettings-NXAANMAX.js → SandboxSettings-DF64LHYI.js} +15 -19
  20. package/dist/SandboxSettings-DF64LHYI.js.map +1 -0
  21. package/dist/SchedulesPage-WQU4H25F.js +15 -0
  22. package/dist/{SettingsBuilder-L34IQ56S.js → SettingsBuilder-LSXK2VN4.js} +8 -8
  23. package/dist/{ShellRouteSync-CEBETGEJ.js → ShellRouteSync-B22IAV2W.js} +19 -9
  24. package/dist/ShellRouteSync-B22IAV2W.js.map +1 -0
  25. package/dist/{SidebarLayout-A2HJPPHS.js → SidebarLayout-XW6LXB7R.js} +17 -16
  26. package/dist/SidebarLayout-XW6LXB7R.js.map +1 -0
  27. package/dist/{SkillSettings-FGGMSUNO.js → SkillSettings-64VXUO6J.js} +13 -16
  28. package/dist/SkillSettings-64VXUO6J.js.map +1 -0
  29. package/dist/{TrueForgeUIWithRouter-MZVJWJMB.js → TrueForgeUIWithRouter-3TSLV22Q.js} +9 -9
  30. package/dist/{WidgetLayout-6QM45OQQ.js → WidgetLayout-Q5P7PYSJ.js} +10 -10
  31. package/dist/{chunk-ZKNUMH2M.js → chunk-5I2COQNL.js} +2 -2
  32. package/dist/chunk-BWHOZFIV.js +587 -0
  33. package/dist/chunk-BWHOZFIV.js.map +1 -0
  34. package/dist/{chunk-U7KURWW3.js → chunk-FQK2XVVE.js} +66 -26
  35. package/dist/chunk-FQK2XVVE.js.map +1 -0
  36. package/dist/{chunk-M62XY4NC.js → chunk-G2TUAD65.js} +6 -6
  37. package/dist/{chunk-M62XY4NC.js.map → chunk-G2TUAD65.js.map} +1 -1
  38. package/dist/{chunk-6O6FWUDW.js → chunk-GXYAOAK5.js} +23 -42
  39. package/dist/chunk-GXYAOAK5.js.map +1 -0
  40. package/dist/{chunk-XAU7QFG3.js → chunk-H6WTY5PM.js} +60 -38
  41. package/dist/chunk-H6WTY5PM.js.map +1 -0
  42. package/dist/{chunk-FJW36PD7.js → chunk-I3AL54MA.js} +10 -10
  43. package/dist/{chunk-FJW36PD7.js.map → chunk-I3AL54MA.js.map} +1 -1
  44. package/dist/{chunk-CYHJDKFB.js → chunk-LGRHHFHN.js} +16 -11
  45. package/dist/{chunk-CYHJDKFB.js.map → chunk-LGRHHFHN.js.map} +1 -1
  46. package/dist/{chunk-2XPPBEYF.js → chunk-NHHSZB5N.js} +2 -2
  47. package/dist/{chunk-WVE3F724.js → chunk-SQGT43Z3.js} +3 -3
  48. package/dist/{chunk-MPNSO7E6.js → chunk-VJ7BZGAF.js} +2 -2
  49. package/dist/{chunk-DMMZSZTN.js → chunk-VUMGMGKZ.js} +13 -13
  50. package/dist/chunk-VUMGMGKZ.js.map +1 -0
  51. package/dist/{chunk-ZTMKFZQ3.js → chunk-YQO2NMJ3.js} +447 -320
  52. package/dist/chunk-YQO2NMJ3.js.map +1 -0
  53. package/dist/index.d.ts +27 -7
  54. package/dist/index.js +13 -11
  55. package/dist/index.js.map +1 -1
  56. package/dist/plugins/trueforge-agent-server-adapter/index.js +2 -1
  57. package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
  58. package/dist/styles.css +1 -1
  59. package/package.json +3 -3
  60. package/dist/AgentMetricChart-JPU3MFQ2.js +0 -15
  61. package/dist/AgentSessionEventTimeline-26Z6IB3B.js.map +0 -1
  62. package/dist/AgentSessionEventTimelineChart-CGCU7WBK.js.map +0 -1
  63. package/dist/ConnectorSettings-MXFRWWR6.js.map +0 -1
  64. package/dist/DrawerLayout-JR3O6RRB.js.map +0 -1
  65. package/dist/ModelSettings-G7IFNC2Y.js.map +0 -1
  66. package/dist/OpenUiFenceBlock-2TV5TQ6P.js +0 -9
  67. package/dist/SandboxSettings-NXAANMAX.js.map +0 -1
  68. package/dist/SchedulesPage-KKLUDO6B.js +0 -15
  69. package/dist/ShellRouteSync-CEBETGEJ.js.map +0 -1
  70. package/dist/SidebarLayout-A2HJPPHS.js.map +0 -1
  71. package/dist/SkillSettings-FGGMSUNO.js.map +0 -1
  72. package/dist/chunk-6O6FWUDW.js.map +0 -1
  73. package/dist/chunk-7Z2C2K7F.js +0 -578
  74. package/dist/chunk-7Z2C2K7F.js.map +0 -1
  75. package/dist/chunk-DMMZSZTN.js.map +0 -1
  76. package/dist/chunk-U7KURWW3.js.map +0 -1
  77. package/dist/chunk-XAU7QFG3.js.map +0 -1
  78. package/dist/chunk-ZTMKFZQ3.js.map +0 -1
  79. /package/dist/{AgentCodeSnippets-NZOFJE57.js.map → AgentCodeSnippets-637HQUXD.js.map} +0 -0
  80. /package/dist/{AgentMetricChart-JPU3MFQ2.js.map → AgentMetricChart-4FYECRIN.js.map} +0 -0
  81. /package/dist/{AgentOverview-EEBHJC32.js.map → AgentOverview-3FJ5EE6N.js.map} +0 -0
  82. /package/dist/{AgentSessions-3MPDZASK.js.map → AgentSessions-T7MOGOTZ.js.map} +0 -0
  83. /package/dist/{DockLayout-LM4AFMFY.js.map → DockLayout-NLFNU6F2.js.map} +0 -0
  84. /package/dist/{OpenUiFenceBlock-2TV5TQ6P.js.map → OpenUiFenceBlock-JEPNPJ7U.js.map} +0 -0
  85. /package/dist/{SchedulesPage-KKLUDO6B.js.map → SchedulesPage-WQU4H25F.js.map} +0 -0
  86. /package/dist/{SettingsBuilder-L34IQ56S.js.map → SettingsBuilder-LSXK2VN4.js.map} +0 -0
  87. /package/dist/{TrueForgeUIWithRouter-MZVJWJMB.js.map → TrueForgeUIWithRouter-3TSLV22Q.js.map} +0 -0
  88. /package/dist/{WidgetLayout-6QM45OQQ.js.map → WidgetLayout-Q5P7PYSJ.js.map} +0 -0
  89. /package/dist/{chunk-ZKNUMH2M.js.map → chunk-5I2COQNL.js.map} +0 -0
  90. /package/dist/{chunk-2XPPBEYF.js.map → chunk-NHHSZB5N.js.map} +0 -0
  91. /package/dist/{chunk-WVE3F724.js.map → chunk-SQGT43Z3.js.map} +0 -0
  92. /package/dist/{chunk-MPNSO7E6.js.map → chunk-VJ7BZGAF.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0-rc.2
4
+
5
+ ### Minor Changes
6
+
7
+ - 04d2ee6: Add a `sidebarText` semantic token for sidebar nav labels, refresh trueforge sidebar colors, set trueforge base `radius` to `0.375rem` (6px), and set sidebar / thread-list control corners to `0.75rem` (12px).
8
+
9
+ Expose design-system `Button` (`Button.Primary` / `.Secondary` / `.Ghost` / `.Destructive`). `ButtonVariant` is now `primary | secondary | ghost | destructive` (`default` renamed to `primary`; `outline` removed — use `secondary`). Button sizes are `large` (default) and `small` (`icon` for icon-only).
10
+
11
+ ### Patch Changes
12
+
13
+ - 2a0ae4c: Show connector catalog logos in the composer Tools picker, matching the Connectors settings page.
14
+ - 2a0ae4c: Align AttachmentCard with assistant-ui's default square thumbnail, filename tooltip, and overlay remove control.
15
+ - fe6a14b: Improve session timelines with sub-agent wait states, grouped point-event markers, clean linear ticks, and readable summary durations.
16
+ - d5b479d: Clamp optional sessions/schedules chrome and unregister `/sessions`, `/schedules`, and `/library/:agentId` when those server ports are omitted, matching the Settings Lego gate.
17
+ - 5d72138: Keep `npx @truefoundry/trueforge` working on native Windows: import Kysely migrations with `pathToFileURL`, and keep sandbox guest paths POSIX. Source development stays Unix/WSL; CI also runs unit and SQLite store tests on Windows.
18
+ - Updated dependencies [a000b47]
19
+ - Updated dependencies [0ec8dc6]
20
+ - Updated dependencies [11865b4]
21
+ - @truefoundry/trueforge-sdk@0.1.4-rc.2
22
+
3
23
  ## 0.3.0-rc.1
4
24
 
5
25
  ### Minor Changes
package/README.md CHANGED
@@ -550,6 +550,7 @@ type AgentUIServer = AgentChatServer &
550
550
  catalog?: CatalogServer;
551
551
  sessions?: AgentSessionsServer;
552
552
  metrics?: AgentMetricsServer;
553
+ schedules?: ScheduleServer;
553
554
  };
554
555
  ```
555
556
 
@@ -557,8 +558,14 @@ type AgentUIServer = AgentChatServer &
557
558
  | -------------------- | ------------------------------------------------------------------- |
558
559
  | `AgentChatServer` | Sessions, turns, streaming, draft `AgentSpec` sync |
559
560
  | `AgentBuilderServer` | `getModels` / `getSkills` / `getMcp` / `searchAgents` / `saveAgent` |
561
+ | `catalog` | Settings CRUD (models / connectors / optional skills & sandbox) |
562
+ | `sessions` | Agent details + sessions browser (`/sessions`, `/library/:agentId`) |
563
+ | `schedules` | Schedules page (`/schedules`) |
560
564
  | `AgentMetricsServer` | Agent meter aggregates, chart definitions, and chart data |
561
565
 
566
+ Omit an optional port to hide its chrome and unregister its routes (same gate as the
567
+ Settings button for `catalog`).
568
+
562
569
  **Zero-config TrueFoundry** — see [Getting started](#getting-started). The SDK calls `createTrueFoundryAgentUIServer` for you.
563
570
 
564
571
  **Zero-config TrueForge (Harness)** — see [Getting started](#getting-started).
@@ -1,17 +1,17 @@
1
1
  "use client";
2
2
  import {
3
3
  useSlot
4
- } from "./chunk-ZTMKFZQ3.js";
5
- import "./chunk-2XPPBEYF.js";
4
+ } from "./chunk-YQO2NMJ3.js";
5
+ import "./chunk-NHHSZB5N.js";
6
6
  import {
7
7
  Icon
8
- } from "./chunk-XAU7QFG3.js";
9
- import "./chunk-U7KURWW3.js";
8
+ } from "./chunk-H6WTY5PM.js";
9
+ import "./chunk-FQK2XVVE.js";
10
10
  import "./chunk-M6MHLVSO.js";
11
- import "./chunk-MPNSO7E6.js";
11
+ import "./chunk-VJ7BZGAF.js";
12
12
  import {
13
13
  cn
14
- } from "./chunk-7Z2C2K7F.js";
14
+ } from "./chunk-BWHOZFIV.js";
15
15
 
16
16
  // src/atoms/agent-details/AgentCodeSnippets.tsx
17
17
  import { useEffect, useState } from "react";
@@ -71,4 +71,4 @@ function AgentCodeSnippets({ snippets }) {
71
71
  export {
72
72
  AgentCodeSnippets as default
73
73
  };
74
- //# sourceMappingURL=AgentCodeSnippets-NZOFJE57.js.map
74
+ //# sourceMappingURL=AgentCodeSnippets-637HQUXD.js.map
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import {
3
+ AgentMetricChart
4
+ } from "./chunk-5I2COQNL.js";
5
+ import "./chunk-YQO2NMJ3.js";
6
+ import "./chunk-NHHSZB5N.js";
7
+ import "./chunk-H6WTY5PM.js";
8
+ import "./chunk-FQK2XVVE.js";
9
+ import "./chunk-M6MHLVSO.js";
10
+ import "./chunk-VJ7BZGAF.js";
11
+ import "./chunk-BWHOZFIV.js";
12
+ export {
13
+ AgentMetricChart
14
+ };
15
+ //# sourceMappingURL=AgentMetricChart-4FYECRIN.js.map
@@ -1,17 +1,17 @@
1
1
  "use client";
2
2
  import {
3
3
  useSlot
4
- } from "./chunk-ZTMKFZQ3.js";
5
- import "./chunk-2XPPBEYF.js";
4
+ } from "./chunk-YQO2NMJ3.js";
5
+ import "./chunk-NHHSZB5N.js";
6
6
  import {
7
7
  Icon
8
- } from "./chunk-XAU7QFG3.js";
9
- import "./chunk-U7KURWW3.js";
8
+ } from "./chunk-H6WTY5PM.js";
9
+ import "./chunk-FQK2XVVE.js";
10
10
  import "./chunk-M6MHLVSO.js";
11
- import "./chunk-MPNSO7E6.js";
11
+ import "./chunk-VJ7BZGAF.js";
12
12
  import {
13
13
  cn
14
- } from "./chunk-7Z2C2K7F.js";
14
+ } from "./chunk-BWHOZFIV.js";
15
15
 
16
16
  // src/atoms/agent-details/AgentOverview.tsx
17
17
  import { useState } from "react";
@@ -164,4 +164,4 @@ function AgentOverview({ detail }) {
164
164
  export {
165
165
  AgentOverview as default
166
166
  };
167
- //# sourceMappingURL=AgentOverview-EEBHJC32.js.map
167
+ //# sourceMappingURL=AgentOverview-3FJ5EE6N.js.map
@@ -1,22 +1,25 @@
1
1
  "use client";
2
2
  import {
3
3
  SESSION_EVENT_TYPES,
4
- useSlot
5
- } from "./chunk-ZTMKFZQ3.js";
6
- import "./chunk-2XPPBEYF.js";
7
- import "./chunk-XAU7QFG3.js";
8
- import "./chunk-U7KURWW3.js";
4
+ getSessionEventColor,
5
+ useSlot,
6
+ useThemeMode
7
+ } from "./chunk-YQO2NMJ3.js";
8
+ import "./chunk-NHHSZB5N.js";
9
+ import "./chunk-H6WTY5PM.js";
10
+ import "./chunk-FQK2XVVE.js";
9
11
  import "./chunk-M6MHLVSO.js";
10
- import "./chunk-MPNSO7E6.js";
12
+ import "./chunk-VJ7BZGAF.js";
11
13
  import {
12
14
  cn
13
- } from "./chunk-7Z2C2K7F.js";
15
+ } from "./chunk-BWHOZFIV.js";
14
16
 
15
17
  // src/atoms/agent-details/AgentSessionEventTimeline.tsx
16
18
  import { useCallback, useMemo, useState } from "react";
17
19
  import { jsx, jsxs } from "react/jsx-runtime";
18
20
  function AgentSessionEventTimeline({ turns, segments, onSelectTurn }) {
19
21
  const AgentSessionEventTimelineChart = useSlot("AgentSessionEventTimelineChart");
22
+ const isDark = useThemeMode() === "dark";
20
23
  const [hiddenTypes, setHiddenTypes] = useState(() => /* @__PURE__ */ new Set());
21
24
  const availableEventTypes = useMemo(() => {
22
25
  const available = new Set(segments.map((segment) => segment.type));
@@ -52,7 +55,13 @@ function AgentSessionEventTimeline({ turns, segments, onSelectTurn }) {
52
55
  ),
53
56
  onClick: () => handleToggleType(eventType.id),
54
57
  children: [
55
- /* @__PURE__ */ jsx("span", { className: "size-2 rounded-sm", style: { backgroundColor: eventType.color } }),
58
+ /* @__PURE__ */ jsx(
59
+ "span",
60
+ {
61
+ className: "size-2 rounded-sm",
62
+ style: { backgroundColor: getSessionEventColor(eventType.id, isDark) }
63
+ }
64
+ ),
56
65
  eventType.label
57
66
  ]
58
67
  },
@@ -76,4 +85,4 @@ function AgentSessionEventTimeline({ turns, segments, onSelectTurn }) {
76
85
  export {
77
86
  AgentSessionEventTimeline
78
87
  };
79
- //# sourceMappingURL=AgentSessionEventTimeline-26Z6IB3B.js.map
88
+ //# sourceMappingURL=AgentSessionEventTimeline-VELWUYPR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/atoms/agent-details/AgentSessionEventTimeline.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useMemo, useState, type ComponentType } from 'react';\n\nimport { useSlot, useThemeMode } from '../../theme/SlotsProvider.js';\nimport { getSessionEventColor, SESSION_EVENT_TYPES, type SessionEventType } from '../../utils/sessionEventTimeline.js';\nimport { cn } from '../lib/cn.js';\nimport type { AgentSessionEventTimelineProps } from './types.js';\n\nexport function AgentSessionEventTimeline({ turns, segments, onSelectTurn }: AgentSessionEventTimelineProps) {\n const AgentSessionEventTimelineChart = useSlot('AgentSessionEventTimelineChart');\n const isDark = useThemeMode() === 'dark';\n const [hiddenTypes, setHiddenTypes] = useState<Set<SessionEventType>>(() => new Set());\n\n const availableEventTypes = useMemo(() => {\n const available = new Set(segments.map(segment => segment.type));\n return SESSION_EVENT_TYPES.filter(eventType => available.has(eventType.id));\n }, [segments]);\n\n const handleToggleType = useCallback((type: SessionEventType) => {\n setHiddenTypes(previous => {\n const next = new Set(previous);\n if (next.has(type)) next.delete(type);\n else next.add(type);\n return next;\n });\n }, []);\n\n if (segments.length === 0) return null;\n\n return (\n <div className=\"w-full\" data-slot=\"agent-session-event-timeline\">\n <div\n className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2\"\n data-slot=\"agent-session-event-types\"\n >\n <span className=\"text-xs font-medium uppercase text-text-secondary\">Event types</span>\n <div className=\"flex flex-wrap items-center gap-1\">\n {availableEventTypes.map(eventType => {\n const isVisible = !hiddenTypes.has(eventType.id);\n return (\n <button\n key={eventType.id}\n type=\"button\"\n aria-pressed={isVisible}\n className={cn(\n 'flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs font-medium',\n isVisible ? 'border-border text-text-primary' : 'border-transparent text-text-secondary opacity-80',\n )}\n onClick={() => handleToggleType(eventType.id)}\n >\n <span\n className=\"size-2 rounded-sm\"\n style={{ backgroundColor: getSessionEventColor(eventType.id, isDark) }}\n />\n {eventType.label}\n </button>\n );\n })}\n </div>\n </div>\n <div className=\"w-full py-2\">\n <AgentSessionEventTimelineChart\n turns={turns}\n segments={segments}\n hiddenTypes={hiddenTypes}\n onSelectTurn={onSelectTurn}\n />\n </div>\n </div>\n );\n}\n\ndeclare module '../../theme/SlotsProvider.js' {\n interface AtomSlots {\n AgentSessionEventTimeline: ComponentType<AgentSessionEventTimelineProps>;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAEA,SAAS,aAAa,SAAS,gBAAoC;AAkC3D,cAKM,YALN;AA3BD,SAAS,0BAA0B,EAAE,OAAO,UAAU,aAAa,GAAmC;AAC3G,QAAM,iCAAiC,QAAQ,gCAAgC;AAC/E,QAAM,SAAS,aAAa,MAAM;AAClC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAgC,MAAM,oBAAI,IAAI,CAAC;AAErF,QAAM,sBAAsB,QAAQ,MAAM;AACxC,UAAM,YAAY,IAAI,IAAI,SAAS,IAAI,aAAW,QAAQ,IAAI,CAAC;AAC/D,WAAO,oBAAoB,OAAO,eAAa,UAAU,IAAI,UAAU,EAAE,CAAC;AAAA,EAC5E,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,mBAAmB,YAAY,CAAC,SAA2B;AAC/D,mBAAe,cAAY;AACzB,YAAM,OAAO,IAAI,IAAI,QAAQ;AAC7B,UAAI,KAAK,IAAI,IAAI,EAAG,MAAK,OAAO,IAAI;AAAA,UAC/B,MAAK,IAAI,IAAI;AAClB,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,MAAI,SAAS,WAAW,EAAG,QAAO;AAElC,SACE,qBAAC,SAAI,WAAU,UAAS,aAAU,gCAChC;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,aAAU;AAAA,QAEV;AAAA,8BAAC,UAAK,WAAU,qDAAoD,yBAAW;AAAA,UAC/E,oBAAC,SAAI,WAAU,qCACZ,8BAAoB,IAAI,eAAa;AACpC,kBAAM,YAAY,CAAC,YAAY,IAAI,UAAU,EAAE;AAC/C,mBACE;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAK;AAAA,gBACL,gBAAc;AAAA,gBACd,WAAW;AAAA,kBACT;AAAA,kBACA,YAAY,oCAAoC;AAAA,gBAClD;AAAA,gBACA,SAAS,MAAM,iBAAiB,UAAU,EAAE;AAAA,gBAE5C;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,WAAU;AAAA,sBACV,OAAO,EAAE,iBAAiB,qBAAqB,UAAU,IAAI,MAAM,EAAE;AAAA;AAAA,kBACvE;AAAA,kBACC,UAAU;AAAA;AAAA;AAAA,cAbN,UAAU;AAAA,YAcjB;AAAA,UAEJ,CAAC,GACH;AAAA;AAAA;AAAA,IACF;AAAA,IACA,oBAAC,SAAI,WAAU,eACb;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF,GACF;AAAA,KACF;AAEJ;","names":[]}
@@ -7,6 +7,7 @@ import {
7
7
  buildTimelineAxisTicks,
8
8
  formatCostUsd,
9
9
  formatDurationMs,
10
+ formatTimelineAxisDuration,
10
11
  formatTimelineDuration,
11
12
  formatTokenCount,
12
13
  getActiveTimelineMs,
@@ -19,26 +20,31 @@ import {
19
20
  getTimelineHoverTargetId,
20
21
  getTimelineLayout,
21
22
  getTimelineRange,
23
+ groupCoincidentTimelineMarkers,
22
24
  groupOverlappingToolCalls,
23
25
  pickLongestNonOverlappingSegments,
26
+ roundDurationMsToSecond,
24
27
  useThemeMode
25
- } from "./chunk-ZTMKFZQ3.js";
26
- import "./chunk-2XPPBEYF.js";
27
- import "./chunk-XAU7QFG3.js";
28
- import "./chunk-U7KURWW3.js";
28
+ } from "./chunk-YQO2NMJ3.js";
29
+ import "./chunk-NHHSZB5N.js";
30
+ import "./chunk-H6WTY5PM.js";
31
+ import "./chunk-FQK2XVVE.js";
29
32
  import "./chunk-M6MHLVSO.js";
30
- import "./chunk-MPNSO7E6.js";
31
- import "./chunk-7Z2C2K7F.js";
33
+ import "./chunk-VJ7BZGAF.js";
34
+ import "./chunk-BWHOZFIV.js";
32
35
 
33
36
  // src/atoms/agent-details/AgentSessionEventTimelineChart.tsx
34
37
  import {
38
+ BarController,
35
39
  BarElement,
36
40
  Chart as ChartJS,
37
41
  LinearScale,
42
+ PointElement,
43
+ ScatterController,
38
44
  Tooltip
39
45
  } from "chart.js";
40
46
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
41
- import { Bar } from "react-chartjs-2";
47
+ import { Chart } from "react-chartjs-2";
42
48
 
43
49
  // src/atoms/agent-details/AgentSessionTimelineTooltip.tsx
44
50
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -70,6 +76,7 @@ function SessionTurnTooltip({
70
76
  durationMs,
71
77
  segments
72
78
  }) {
79
+ const isDark = useThemeMode() === "dark";
73
80
  return /* @__PURE__ */ jsxs("div", { className: "max-h-72 w-72 max-w-full overflow-auto text-xs text-text-primary", children: [
74
81
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
75
82
  /* @__PURE__ */ jsx("span", { className: "font-semibold", children: `Turn ${turnNumber}` }),
@@ -86,7 +93,7 @@ function SessionTurnTooltip({
86
93
  "span",
87
94
  {
88
95
  className: "size-1.5 shrink-0 rounded-full",
89
- style: { backgroundColor: getSessionEventColor(segment.type) }
96
+ style: { backgroundColor: getSessionEventColor(segment.type, isDark) }
90
97
  }
91
98
  ),
92
99
  /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: label }),
@@ -107,6 +114,27 @@ function SessionToolCallGroupTooltip({ group }) {
107
114
  ] }, segment.id)) })
108
115
  ] });
109
116
  }
117
+ function SessionMarkerGroupTooltip({ group }) {
118
+ const isDark = useThemeMode() === "dark";
119
+ const singleSegment = group.segments.length === 1 ? group.segments[0] : void 0;
120
+ if (singleSegment != null) return /* @__PURE__ */ jsx(SessionEventTooltip, { segment: singleSegment });
121
+ return /* @__PURE__ */ jsxs("div", { className: "max-h-72 w-80 max-w-full overflow-auto text-xs", children: [
122
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-text-secondary", children: "Events" }),
123
+ /* @__PURE__ */ jsx("div", { className: "mt-1.5 border-t border-border pt-1.5", children: group.segments.map((segment) => /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-start gap-1.5 py-0.5", children: [
124
+ /* @__PURE__ */ jsx(
125
+ "span",
126
+ {
127
+ className: "mt-1 size-1.5 shrink-0 rounded-full",
128
+ style: { backgroundColor: getSessionEventColor(segment.type, isDark) }
129
+ }
130
+ ),
131
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
132
+ /* @__PURE__ */ jsx("div", { className: "font-medium text-text-secondary", children: getSessionEventTooltipHeading(segment.type) }),
133
+ /* @__PURE__ */ jsx("div", { className: "wrap-break-word font-medium text-text-primary", children: segment.description.trim() || segment.title })
134
+ ] })
135
+ ] }, segment.id)) })
136
+ ] });
137
+ }
110
138
  function SessionSubAgentGroupTooltip({ group }) {
111
139
  return /* @__PURE__ */ jsxs("div", { className: "max-h-72 w-80 max-w-full overflow-auto text-xs", children: [
112
140
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
@@ -114,29 +142,30 @@ function SessionSubAgentGroupTooltip({ group }) {
114
142
  /* @__PURE__ */ jsx("span", { className: "tabular-nums text-text-secondary", children: formatTimelineDuration(group.endMs - group.startMs) })
115
143
  ] }),
116
144
  /* @__PURE__ */ jsx("div", { className: "mt-1.5 border-t border-border pt-1.5", children: group.segments.map((segment, index) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 py-0.5", children: [
117
- /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate font-medium text-text-primary", children: `Sub-agent ${index + 1}: ${segment.description || segment.title}` }),
118
- /* @__PURE__ */ jsx("span", { className: "shrink-0 tabular-nums text-text-secondary", children: formatTimelineDuration(segment.endMs - segment.startMs) })
145
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate font-medium text-text-primary", children: group.segments.length === 1 ? segment.description || segment.title : `Sub-agent ${index + 1}: ${segment.description || segment.title}` }),
146
+ group.segments.length === 1 ? null : /* @__PURE__ */ jsx("span", { className: "shrink-0 tabular-nums text-text-secondary", children: formatTimelineDuration(segment.endMs - segment.startMs) })
119
147
  ] }, segment.id)) })
120
148
  ] });
121
149
  }
122
150
 
123
151
  // src/atoms/agent-details/AgentSessionEventTimelineChart.tsx
124
152
  import { jsx as jsx2 } from "react/jsx-runtime";
125
- ChartJS.register(LinearScale, BarElement, Tooltip);
153
+ ChartJS.register(BarController, BarElement, LinearScale, PointElement, ScatterController, Tooltip);
126
154
  var MARKER_PX = 4;
127
155
  var TURN_GAP_PX = 12;
128
156
  var END_PAD_PX = 12;
129
157
  var BAR_RADIUS_PX = 2;
130
158
  var ROW_GAP_PX = 8;
159
+ var MARKER_EVENT_GAP_PX = 2;
131
160
  var OVERHEAD_PX = 30;
132
- function rowCenters(heights, gap) {
161
+ function rowCenters({ heights, gaps }) {
133
162
  const centers = [];
134
163
  let offset = 0;
135
- for (const height of heights) {
164
+ heights.forEach((height, index) => {
136
165
  centers.push(offset + height / 2);
137
- offset += height + gap;
138
- }
139
- return { centers, band: Math.max(0, offset - gap) };
166
+ offset += height + (gaps[index] ?? 0);
167
+ });
168
+ return { centers, band: offset };
140
169
  }
141
170
  function eventOrder(type) {
142
171
  if (type === "sub_agent") return 0;
@@ -159,8 +188,8 @@ function AgentSessionEventTimelineChart({
159
188
  const isDark = mode === "dark";
160
189
  const axis = isDark ? "#8c8c92" : "#71717a";
161
190
  const grid = isDark ? "#27272a" : "#e4e4e7";
162
- const turnFill = isDark ? "#3f3f46" : "#e4e4e7";
163
- const turnHover = isDark ? "#52525b" : "#d4d4d8";
191
+ const turnFill = isDark ? "#3f3f46" : "#E0ECFD";
192
+ const turnHover = isDark ? "#52525b" : "#E0ECFD";
164
193
  const wrapperRef = useRef(null);
165
194
  const [widthPx, setWidthPx] = useState(0);
166
195
  const [overheadPx, setOverheadPx] = useState(OVERHEAD_PX);
@@ -199,17 +228,22 @@ function AgentSessionEventTimelineChart({
199
228
  window.removeEventListener("resize", refreshTooltipAnchor);
200
229
  };
201
230
  }, [refreshTooltipAnchor, tooltipTarget]);
202
- const activeTotalMs = Math.max(1, ...segments.map((segment) => segment.endMs));
231
+ const segmentTotalMs = Math.max(0, ...segments.map((segment) => segment.endMs));
232
+ const activeTotalMs = Math.max(1, roundDurationMsToSecond(segmentTotalMs));
203
233
  const { turnStartsMs, turnOrdinals, turnRanges } = useMemo(() => getTimelineLayout(segments), [segments]);
204
- const gapCount = Math.max(0, turnStartsMs.length - 1);
234
+ const activeTurnStartsMs = useMemo(
235
+ () => turnStartsMs.filter((startMs, index) => index === 0 || startMs <= activeTotalMs),
236
+ [activeTotalMs, turnStartsMs]
237
+ );
238
+ const gapCount = Math.max(0, activeTurnStartsMs.length - 1);
205
239
  const scaleWidthPx = Math.max(widthPx / 2, widthPx - TURN_GAP_PX * gapCount - END_PAD_PX);
206
240
  const msPerPx = activeTotalMs / Math.max(1, scaleWidthPx);
207
241
  const turnGapMs = TURN_GAP_PX * msPerPx;
208
242
  const totalMs = activeTotalMs + gapCount * turnGapMs;
209
243
  const timelineMaxMs = totalMs + END_PAD_PX * msPerPx;
210
244
  const timelineGaps = useMemo(
211
- () => turnStartsMs.slice(1).map((startMs, index) => ({ startMs: startMs + index * turnGapMs, endMs: startMs + (index + 1) * turnGapMs })),
212
- [turnGapMs, turnStartsMs]
245
+ () => activeTurnStartsMs.slice(1).map((startMs, index) => ({ startMs: startMs + index * turnGapMs, endMs: startMs + (index + 1) * turnGapMs })),
246
+ [activeTurnStartsMs, turnGapMs]
213
247
  );
214
248
  const visibleSegments = useMemo(
215
249
  () => segments.flatMap((segment) => {
@@ -219,6 +253,8 @@ function AgentSessionEventTimelineChart({
219
253
  }),
220
254
  [hiddenTypes, segments, turnGapMs, turnOrdinals]
221
255
  );
256
+ const markerGroups = useMemo(() => groupCoincidentTimelineMarkers(visibleSegments), [visibleSegments]);
257
+ const durationSegments = useMemo(() => visibleSegments.filter((segment) => !segment.isMarker), [visibleSegments]);
222
258
  const turnBars = useMemo(
223
259
  () => turnRanges.length < 2 ? [] : turnRanges.map((range) => ({
224
260
  ...range,
@@ -230,8 +266,8 @@ function AgentSessionEventTimelineChart({
230
266
  [msPerPx, turnGapMs, turnRanges]
231
267
  );
232
268
  const subAgentSegments = useMemo(
233
- () => visibleSegments.filter((segment) => segment.type === "sub_agent"),
234
- [visibleSegments]
269
+ () => durationSegments.filter((segment) => segment.type === "sub_agent"),
270
+ [durationSegments]
235
271
  );
236
272
  const mainSubAgents = useMemo(() => pickLongestNonOverlappingSegments(subAgentSegments), [subAgentSegments]);
237
273
  const subAgentGroups = useMemo(
@@ -239,15 +275,15 @@ function AgentSessionEventTimelineChart({
239
275
  [mainSubAgents, subAgentSegments]
240
276
  );
241
277
  const subAgentLanes = useMemo(
242
- () => getSubAgentLanes({ subAgentSegments, threadSegments: visibleSegments, minWidthMs: MARKER_PX * msPerPx }),
243
- [msPerPx, subAgentSegments, visibleSegments]
278
+ () => getSubAgentLanes({ subAgentSegments, threadSegments: durationSegments, minWidthMs: MARKER_PX * msPerPx }),
279
+ [durationSegments, msPerPx, subAgentSegments]
244
280
  );
245
281
  const mainCandidates = useMemo(() => {
246
282
  const kept = new Set(mainSubAgents.map((segment) => segment.id));
247
- return visibleSegments.filter(
283
+ return durationSegments.filter(
248
284
  (segment) => segment.threadId === MAIN_THREAD_ID || segment.type === "sub_agent" && kept.has(segment.id)
249
285
  );
250
- }, [mainSubAgents, visibleSegments]);
286
+ }, [durationSegments, mainSubAgents]);
251
287
  const toolCallGroups = useMemo(
252
288
  () => groupOverlappingToolCalls(mainCandidates.filter((segment) => segment.type === "tool_call")).filter(
253
289
  (group) => group.segments.length > 1
@@ -264,14 +300,20 @@ function AgentSessionEventTimelineChart({
264
300
  );
265
301
  const laneCount = subAgentLanes.reduce((count, lane) => Math.max(count, lane.lane + 1), 0);
266
302
  const hasTurnRow = turnBars.length > 0;
267
- const eventRow = hasTurnRow ? 1 : 0;
268
- const { centers, band } = useMemo(
269
- () => rowCenters([...hasTurnRow ? [16] : [], 28, ...Array.from({ length: laneCount }, () => 12)], ROW_GAP_PX),
270
- [hasTurnRow, laneCount]
271
- );
303
+ const markerRow = hasTurnRow ? 1 : 0;
304
+ const eventRow = markerRow + 1;
305
+ const { centers, band } = useMemo(() => {
306
+ const heights = [...hasTurnRow ? [16] : [], 10, 28, ...Array.from({ length: laneCount }, () => 12)];
307
+ const gaps = heights.map((_, index) => {
308
+ if (index === heights.length - 1) return 0;
309
+ return index === markerRow ? MARKER_EVENT_GAP_PX : ROW_GAP_PX;
310
+ });
311
+ return rowCenters({ heights, gaps });
312
+ }, [hasTurnRow, laneCount, markerRow]);
272
313
  const chartTargets = useMemo(
273
314
  () => [
274
315
  ...turnBars.map((bar) => ({ type: TIMELINE_TYPE.turn, bar })),
316
+ ...markerGroups.map((group) => ({ type: TIMELINE_TYPE.markerGroup, group })),
275
317
  ...subAgentLanes.flatMap(
276
318
  (lane) => lane.segments.map((segment) => ({ type: TIMELINE_TYPE.event, segment }))
277
319
  ),
@@ -282,7 +324,7 @@ function AgentSessionEventTimelineChart({
282
324
  }),
283
325
  ...toolCallGroups.map((group) => ({ type: TIMELINE_TYPE.toolCallGroup, group }))
284
326
  ],
285
- [mainEventSegments, subAgentGroups, subAgentLanes, toolCallGroups, turnBars]
327
+ [mainEventSegments, markerGroups, subAgentGroups, subAgentLanes, toolCallGroups, turnBars]
286
328
  );
287
329
  const barDataset = ({
288
330
  label,
@@ -321,14 +363,31 @@ function AgentSessionEventTimelineChart({
321
363
  thickness: 16
322
364
  })
323
365
  ),
366
+ ...markerGroups.map((group) => {
367
+ const type = group.segments.length === 1 ? group.segments[0]?.type : "system";
368
+ const color = getSessionEventColor(type ?? "system", isDark);
369
+ return {
370
+ type: "scatter",
371
+ label: group.segments.map((segment) => getSessionEventLabel(segment.type)).join(", "),
372
+ data: [{ x: group.startMs, y: centers[markerRow] ?? 0 }],
373
+ pointStyle: "rectRot",
374
+ pointRadius: 5,
375
+ pointHoverRadius: 6,
376
+ clip: false,
377
+ backgroundColor: color,
378
+ hoverBackgroundColor: getSessionEventHoverColor(type ?? "system", isDark),
379
+ borderWidth: 0,
380
+ order: 0
381
+ };
382
+ }),
324
383
  ...subAgentLanes.flatMap(
325
384
  (lane) => lane.segments.map(
326
385
  (segment) => barDataset({
327
386
  label: `${getSessionEventLabel(segment.type)}: ${segment.title}`,
328
387
  range: segment,
329
388
  y: centers[eventRow + 1 + lane.lane] ?? 0,
330
- color: getSessionEventColor(segment.type),
331
- hover: getSessionEventHoverColor(segment.type),
389
+ color: getSessionEventColor(segment.type, isDark),
390
+ hover: getSessionEventHoverColor(segment.type, isDark),
332
391
  thickness: 12,
333
392
  order: eventOrder(segment.type),
334
393
  inflateAmount: 0.5
@@ -340,8 +399,8 @@ function AgentSessionEventTimelineChart({
340
399
  label: `${getSessionEventLabel(segment.type)}: ${segment.title}`,
341
400
  range: segment,
342
401
  y: centers[eventRow] ?? 0,
343
- color: getSessionEventColor(segment.type),
344
- hover: getSessionEventHoverColor(segment.type),
402
+ color: getSessionEventColor(segment.type, isDark),
403
+ hover: getSessionEventHoverColor(segment.type, isDark),
345
404
  thickness: 28,
346
405
  order: eventOrder(segment.type),
347
406
  inflateAmount: 0.5
@@ -352,8 +411,8 @@ function AgentSessionEventTimelineChart({
352
411
  label: "Parallel tool calls",
353
412
  range: group,
354
413
  y: centers[eventRow] ?? 0,
355
- color: getSessionEventColor("tool_call"),
356
- hover: getSessionEventHoverColor("tool_call"),
414
+ color: getSessionEventColor("tool_call", isDark),
415
+ hover: getSessionEventHoverColor("tool_call", isDark),
357
416
  thickness: 28,
358
417
  order: eventOrder("tool_call"),
359
418
  inflateAmount: 0.5
@@ -361,7 +420,19 @@ function AgentSessionEventTimelineChart({
361
420
  )
362
421
  ]
363
422
  }),
364
- [centers, eventRow, mainEventSegments, subAgentLanes, toolCallGroups, turnBars, turnFill, turnHover]
423
+ [
424
+ centers,
425
+ eventRow,
426
+ isDark,
427
+ mainEventSegments,
428
+ markerGroups,
429
+ markerRow,
430
+ subAgentLanes,
431
+ toolCallGroups,
432
+ turnBars,
433
+ turnFill,
434
+ turnHover
435
+ ]
365
436
  );
366
437
  const turnLabelPlugin = useMemo(
367
438
  () => ({
@@ -436,21 +507,16 @@ function AgentSessionEventTimelineChart({
436
507
  grid: { color: grid },
437
508
  border: { color: grid },
438
509
  afterBuildTicks: (scale) => {
439
- scale.ticks = buildTimelineAxisTicks({
440
- ticks: scale.ticks,
441
- totalMs,
442
- timelineMaxMs
443
- });
510
+ scale.ticks = buildTimelineAxisTicks({ activeTotalMs, turnStartsMs: activeTurnStartsMs, turnGapMs });
444
511
  },
445
512
  ticks: {
446
513
  color: axis,
447
514
  autoSkip: false,
448
- includeBounds: true,
515
+ includeBounds: false,
449
516
  maxTicksLimit: 9,
450
- stepSize: timelineMaxMs / 8,
451
517
  callback: (value) => {
452
518
  const timelineMs = Number(value);
453
- return timelineMs <= totalMs ? formatTimelineDuration(getActiveTimelineMs(timelineMs, timelineGaps)) : "";
519
+ return timelineMs <= totalMs ? formatTimelineAxisDuration(getActiveTimelineMs(timelineMs, timelineGaps)) : "";
454
520
  }
455
521
  }
456
522
  },
@@ -465,7 +531,20 @@ function AgentSessionEventTimelineChart({
465
531
  }
466
532
  }
467
533
  }),
468
- [axis, band, chartTargets, grid, onSelectTurn, refreshTooltipAnchor, timelineGaps, timelineMaxMs, totalMs]
534
+ [
535
+ activeTotalMs,
536
+ activeTurnStartsMs,
537
+ axis,
538
+ band,
539
+ chartTargets,
540
+ grid,
541
+ onSelectTurn,
542
+ refreshTooltipAnchor,
543
+ timelineGaps,
544
+ timelineMaxMs,
545
+ totalMs,
546
+ turnGapMs
547
+ ]
469
548
  );
470
549
  const tooltipTurn = tooltipTarget?.type === TIMELINE_TYPE.turn ? turns[tooltipTarget.bar.turnIndex] : void 0;
471
550
  const containerStyle = useMemo(() => ({ height: band + overheadPx }), [band, overheadPx]);
@@ -483,7 +562,7 @@ function AgentSessionEventTimelineChart({
483
562
  segment: tooltipTarget.segment,
484
563
  subAgentLabel: tooltipTarget.segment.type === "sub_agent" ? void 0 : subAgentLanes.find((lane) => lane.threadId === tooltipTarget.segment.threadId)?.track.description
485
564
  }
486
- ) : tooltipTarget?.type === TIMELINE_TYPE.toolCallGroup ? /* @__PURE__ */ jsx2(SessionToolCallGroupTooltip, { group: tooltipTarget.group }) : tooltipTarget?.type === TIMELINE_TYPE.subAgentGroup ? /* @__PURE__ */ jsx2(SessionSubAgentGroupTooltip, { group: tooltipTarget.group }) : null;
565
+ ) : tooltipTarget?.type === TIMELINE_TYPE.toolCallGroup ? /* @__PURE__ */ jsx2(SessionToolCallGroupTooltip, { group: tooltipTarget.group }) : tooltipTarget?.type === TIMELINE_TYPE.markerGroup ? /* @__PURE__ */ jsx2(SessionMarkerGroupTooltip, { group: tooltipTarget.group }) : tooltipTarget?.type === TIMELINE_TYPE.subAgentGroup ? /* @__PURE__ */ jsx2(SessionSubAgentGroupTooltip, { group: tooltipTarget.group }) : null;
487
566
  return /* @__PURE__ */ jsx2("div", { ref: wrapperRef, className: "w-full", "data-slot": "agent-session-event-timeline-chart", children: /* @__PURE__ */ jsx2(
488
567
  LightTooltip,
489
568
  {
@@ -494,11 +573,19 @@ function AgentSessionEventTimelineChart({
494
573
  open: tooltipTarget != null && tooltipContent != null,
495
574
  className: "max-w-[min(25rem,calc(100vw-1rem))] whitespace-normal",
496
575
  anchor: tooltipAnchor,
497
- children: /* @__PURE__ */ jsx2("div", { className: "w-full", style: containerStyle, onMouseLeave: clearTooltip, children: /* @__PURE__ */ jsx2(Bar, { data: chartData, options: chartOptions, plugins: [turnLabelPlugin, overheadPlugin] }) })
576
+ children: /* @__PURE__ */ jsx2("div", { className: "w-full", style: containerStyle, onMouseLeave: clearTooltip, children: /* @__PURE__ */ jsx2(
577
+ Chart,
578
+ {
579
+ type: "bar",
580
+ data: chartData,
581
+ options: chartOptions,
582
+ plugins: [turnLabelPlugin, overheadPlugin]
583
+ }
584
+ ) })
498
585
  }
499
586
  ) });
500
587
  }
501
588
  export {
502
589
  AgentSessionEventTimelineChart
503
590
  };
504
- //# sourceMappingURL=AgentSessionEventTimelineChart-CGCU7WBK.js.map
591
+ //# sourceMappingURL=AgentSessionEventTimelineChart-CUKETHWM.js.map