dsh-turn-outline 0.2.5
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.
- package/LICENSE +21 -0
- package/README.en.md +132 -0
- package/README.md +132 -0
- package/cordis.patch.yml +3 -0
- package/lib/client.js +1865 -0
- package/lib/client.js.map +7 -0
- package/lib/index.js +305 -0
- package/lib/index.js.map +7 -0
- package/package.json +86 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/client/index.tsx", "../src/client/styles.ts", "../src/client/TrailTab.tsx", "../src/trail-model.ts", "../src/client/locales.ts", "../src/client/useTrail.ts", "../src/client/trail-jump.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Client half of dsh-turn-outline: register the \u300C\u8F6E\u6B21\u8F68\u8FF9\u300Dtab with\n * dsh-better-sidebar (optional peer \u2014 inert without it) and inject the\n * token-driven stylesheet once.\n *\n * Bundle purity: `dsh-better-sidebar` is never value-imported \u2014 the tab is\n * registered through `ctx.betterSidebar` at runtime; `react` resolves from\n * the client module system seed; `@deepseek-ai/dsh-client-ui-primitives` is\n * required lazily with a glyph fallback so the panel works without it.\n */\nimport * as React from 'react'\nimport { trailCss } from './styles'\nimport { TrailTab } from './TrailTab'\n\n/** Icon primitives with an exact list glyph fallback (not a dropdown arrow). */\nconst primitives = (() => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require('@deepseek-ai/dsh-client-ui-primitives')\n } catch {\n return null\n }\n})()\n\nfunction listIcon(): React.ReactNode {\n const path = React.createElement('path', {\n d: 'M3 3.5h10M3 8h10M3 12.5h6',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: '1.5',\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n })\n return React.createElement('svg', { viewBox: '0 0 16 16', width: '14', height: '14', 'aria-hidden': true }, path)\n}\n\n/**\n * Tab glyph. Prefer a ui-primitives BRANCH icon (IconBranchOutline16 \u2014 a\n * flow/path) so the\u300C\u8F6E\u6B21\u8F68\u8FF9\u300Dtab reads as a trail of turns, not a dropdown\n * arrow; fall back to our own three-line list glyph.\n */\nfunction tabIcon(size: number): React.ReactNode {\n const IconList = primitives !== null && typeof primitives.IconBranchOutline16 === 'function'\n ? primitives.IconBranchOutline16\n : null\n if (IconList !== null) return React.createElement(IconList, { size })\n return listIcon()\n}\n\nexport const inject = ['sessions', 'betterSidebar']\n\nexport function apply(ctx: {\n get(name: string): unknown\n effect<T>(fn: () => T): T\n}): void {\n const style = document.createElement('style')\n style.dataset.plugin = 'dsh-turn-outline'\n style.textContent = trailCss\n document.head.appendChild(style)\n // cordis ctx.effect(fn) RUNS fn to register and treats its RETURN VALUE as\n // the cleanup. A single arrow executes style.remove() immediately (the\n // injected <style> is deleted on the spot \u2192 styles never apply). Double\n // arrow returns the cleanup so the sheet survives (matches conversation-\n // outline, the working reference).\n ctx.effect(() => () => style.remove())\n\n const betterSidebar = ctx.get('betterSidebar')\n if (\n betterSidebar === undefined || betterSidebar === null\n || typeof (betterSidebar as { registerTab?: unknown }).registerTab !== 'function'\n ) {\n // No better-sidebar: stay inert (the plan's no-op path).\n return\n }\n\n ctx.effect(() => (betterSidebar as { registerTab(descriptor: unknown): () => void }).registerTab({\n id: 'turn-outline',\n title: () => (typeof navigator !== 'undefined' && navigator.language.toLowerCase().startsWith('zh')\n ? '\u8F6E\u6B21\u8F68\u8FF9'\n : 'Turn Outline'),\n icon: (size: number) => tabIcon(size),\n order: 46,\n single: true,\n component: (props: {\n ctx: { get(name: string): unknown }\n store?: unknown\n scope: { sessionId: string; cwd?: string }\n tab: { id: string }\n visible: boolean\n }) => React.createElement(TrailTab, {\n ctx: props.ctx,\n scope: props.scope,\n visible: props.visible === true,\n tab: props.tab,\n }),\n }))\n}\n", "/**\n * styles.ts \u2014 DSH-native, token-driven CSS for the trail panel, injected once\n * by the client entry. The design language mirrors the upstream DSH trajectory\n * surface: a monochrome \"ink\" chrome (label tiers + hairline separators +\n * interactive hover washes), flat turn rows instead of cards, a 2px turn rail\n * for the located turn, semantic accent dots (success/warn/neutral) instead of\n * a per-tool rainbow, and monospace tool names/args. Every expanded-body row\n * shares one anatomy \u2014 a 6px semantic dot + a narrow name column + content \u2014\n * so input, output and tool rows read as one grid; the dot carries the whole\n * color channel (category for tools, red for failures).\n * All colors/fonts consume\n * DSW alias tokens (auto light/dark/skin); fallbacks mirror the native dark\n * values so a missing token never falls back to a foreign look.\n *\n * Radius scale (native): 2px micro tag \u00B7 4px chip/step hover \u00B7 6px buttons \u00B7\n * 8px floating surfaces. No 999px pills. Class names are prefixed `ttl-` and\n * are OUR contract (never matched against DSH internals).\n */\nexport const trailCss = `\n.ttl-root {\n box-sizing: border-box;\n position: relative;\n height: 100%;\n min-width: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--dsw-alias-bg-layer-1, #232324);\n color: var(--dsw-alias-label-primary, #f9fafb);\n font-family: var(--dsw-font-family, -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", \"Helvetica Neue\", Helvetica, Arial, sans-serif);\n font-size: 12px;\n line-height: 18px;\n container: trail-tab / inline-size;\n}\n\n/* \u2500\u2500 Header (36px, hairline) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.ttl-header {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n gap: 8px;\n flex: none;\n height: 36px;\n padding: 0 8px 0 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(255, 255, 255, 0.06));\n}\n.ttl-title {\n flex: none;\n min-width: 0;\n max-width: 55%;\n margin: 0;\n font-size: 13px;\n font-weight: 500;\n line-height: 20px;\n color: var(--dsw-alias-label-primary, #f9fafb);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ttl-count {\n flex: none;\n color: var(--dsw-alias-label-tertiary, #adb2b8);\n font-size: 12px;\n line-height: 18px;\n font-variant-numeric: tabular-nums;\n}\n.ttl-headerSpacer { flex: 1; min-width: 0; }\n/* Follow-latest: native ghost button + status dot (no checkbox pill). */\n.ttl-toggle {\n box-sizing: border-box;\n flex: none;\n height: 24px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 0 8px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary, #cfd3d6);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n white-space: nowrap;\n}\n.ttl-toggle:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(255, 255, 255, 0.08));\n color: var(--dsw-alias-label-primary, #f9fafb);\n}\n.ttl-toggleDot {\n flex: none;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: transparent;\n box-shadow: inset 0 0 0 1px var(--dsw-alias-label-tertiary, #adb2b8);\n}\n.ttl-toggle[aria-pressed=\"true\"] { color: var(--dsw-alias-label-primary, #f9fafb); }\n.ttl-toggle[aria-pressed=\"true\"] .ttl-toggleDot {\n background: var(--dsw-alias-state-success-primary, #22c55e);\n box-shadow: none;\n}\n\n/* \u2500\u2500 Filter row (flat text chips + semantic dots) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.ttl-filterRow {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n flex-wrap: nowrap;\n gap: 2px;\n flex: none;\n padding: 4px 8px;\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(255, 255, 255, 0.06));\n overflow-x: auto;\n scrollbar-width: thin;\n scrollbar-color: var(--dsw-alias-scrollbar-bg-l2, #545557) transparent;\n}\n.ttl-filterRow::-webkit-scrollbar { height: 4px; }\n.ttl-filterRow::-webkit-scrollbar-thumb {\n background: var(--dsw-alias-scrollbar-bg-l2, #545557);\n border-radius: 2px;\n}\n.ttl-chip {\n box-sizing: border-box;\n flex: none;\n height: 22px;\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 0 8px;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--dsw-alias-label-secondary, #cfd3d6);\n font: inherit;\n font-size: 12px;\n line-height: 16px;\n white-space: nowrap;\n cursor: pointer;\n}\n.ttl-chip:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(255, 255, 255, 0.08));\n color: var(--dsw-alias-label-primary, #f9fafb);\n}\n/* Active chip = business-blue TEXT on the hover wash (native detailTab). */\n.ttl-chip[aria-pressed=\"true\"] {\n background: var(--dsw-alias-interactive-bg-hover, rgba(255, 255, 255, 0.08));\n color: var(--dsw-alias-state-business-primary, #4176e6);\n}\n.ttl-chipNum {\n color: var(--dsw-alias-label-tertiary, #adb2b8);\n font-variant-numeric: tabular-nums;\n font-weight: 400;\n}\n.ttl-chip[aria-pressed=\"true\"] .ttl-chipNum { color: inherit; opacity: 0.72; }\n.ttl-chipDot {\n flex: none;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n}\n.ttl-dot-success { background: var(--dsw-alias-state-success-primary, #22c55e); }\n.ttl-dot-warn { background: var(--dsw-alias-state-warn-primary, #f59e0b); }\n.ttl-dot-neutral { background: var(--dsw-alias-label-tertiary, #adb2b8); }\n.ttl-moreChip { color: var(--dsw-alias-label-tertiary, #adb2b8); }\n.ttl-moreArrow {\n flex: none;\n display: inline-flex;\n transition: transform 120ms var(--ds-ease-in-out, ease);\n}\n.ttl-moreArrowOpen { transform: rotate(180deg); }\n/* \"More\" dropdown: native elevated menu (layer-2 + hairline + 8px + shadow). */\n.ttl-toolDropdown {\n box-sizing: border-box;\n position: absolute;\n z-index: 9;\n top: 64px;\n left: 8px;\n display: flex;\n flex-wrap: wrap;\n gap: 2px;\n width: max-content;\n max-width: calc(100% - 16px);\n max-height: 180px;\n overflow-y: auto;\n padding: 6px;\n border: 1px solid var(--dsw-alias-border-l2, rgba(255, 255, 255, 0.12));\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-2, #2c2c2e);\n box-shadow: 0 4px 16px var(--dsw-alias-bg-mask-1, rgba(0, 0, 0, 0.24));\n scrollbar-width: thin;\n scrollbar-color: var(--dsw-alias-scrollbar-bg-l2, #545557) transparent;\n}\n\n/* \u2500\u2500 Turn list (flat rows, hairline separators) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.ttl-list {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: 0 8px 8px;\n scrollbar-width: thin;\n scrollbar-color: var(--dsw-alias-scrollbar-bg-l2, #545557) transparent;\n}\n.ttl-list::-webkit-scrollbar { width: 6px; }\n.ttl-list::-webkit-scrollbar-thumb {\n background: var(--dsw-alias-scrollbar-bg-l2, #545557);\n border-radius: 3px;\n}\n.ttl-status {\n margin: 14px;\n color: var(--dsw-alias-label-tertiary, #adb2b8);\n font-size: 12px;\n line-height: 18px;\n}\n.ttl-error {\n margin: 14px;\n color: var(--dsw-alias-state-error-primary, #f25a5a);\n font-size: 12px;\n line-height: 18px;\n}\n\n/* \u2500\u2500 Turn row (no card; 2px rail marks the located turn) \u2500\u2500\u2500 */\n.ttl-turnRow {\n position: relative;\n border-top: 1px solid var(--dsw-alias-border-l1, rgba(255, 255, 255, 0.06));\n background: transparent;\n}\n.ttl-turnRow:first-child { border-top: none; }\n.ttl-turnRow[data-active=\"true\"]::before {\n content: \"\";\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 2px;\n background: color-mix(in srgb, var(--dsw-static-blue-500, #3b82f6) 22%, var(--dsw-alias-bg-layer-1, #232324));\n}\n.ttl-turnRow[data-active=\"true\"][data-error=\"true\"]::before {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary, #f25a5a) 22%, var(--dsw-alias-bg-layer-1, #232324));\n}\n.ttl-turnHead {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n gap: 0;\n min-height: 32px;\n padding: 0 6px 0 10px;\n}\n.ttl-turnHead:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(255, 255, 255, 0.08));\n}\n.ttl-turnToggle {\n box-sizing: border-box;\n min-width: 0;\n flex: 1;\n display: flex;\n align-items: center;\n gap: 7px;\n padding: 4px 0;\n border: none;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n.ttl-chevron {\n flex: none;\n color: var(--dsw-alias-label-tertiary, #adb2b8);\n transition: transform 120ms var(--ds-ease-in-out, ease);\n}\n.ttl-chevronOpen { transform: rotate(90deg); }\n/* \"\u8F6E\u6B21 N\": native turnLabel-style micro tag (mono, module bg, 2px radius). */\n.ttl-turnTag {\n box-sizing: border-box;\n flex: none;\n padding: 1px 5px;\n border-radius: 2px;\n background: var(--dsw-alias-bg-module-platform, #353638);\n color: var(--dsw-alias-label-tertiary, #adb2b8);\n font-family: var(--ds-font-family-code, \"SF Mono\", \"JetBrains Mono\", \"Fira Code\", Consolas, \"Liberation Mono\", Menlo, Courier, \"PingFang SC\", \"Microsoft YaHei\", monospace);\n font-size: 10px;\n font-weight: 500;\n line-height: 12px;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n user-select: none;\n}\n.ttl-turnRow[data-active=\"true\"] .ttl-turnTag {\n color: color-mix(in srgb, var(--dsw-static-blue-500, #3b82f6) 55%, var(--dsw-alias-label-tertiary, #adb2b8));\n background: color-mix(in srgb, var(--dsw-static-blue-500, #3b82f6) 14%, var(--dsw-alias-bg-layer-1, #232324));\n}\n.ttl-turnPreview {\n flex: 1;\n min-width: 0;\n color: var(--dsw-alias-label-secondary, #cfd3d6);\n font-size: 12px;\n line-height: 18px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ttl-turnMeta {\n flex: none;\n display: flex;\n align-items: center;\n gap: 6px;\n margin-left: 8px;\n}\n/* Step count: a bare tabular number (never a colored badge). */\n.ttl-stepsNum {\n flex: none;\n color: var(--dsw-alias-label-tertiary, #adb2b8);\n font-size: 11px;\n line-height: 16px;\n font-variant-numeric: tabular-nums;\n}\n.ttl-errorDot {\n flex: none;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--dsw-alias-state-error-primary, #f25a5a);\n}\n.ttl-locateBtn {\n box-sizing: border-box;\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-tertiary, #adb2b8);\n cursor: pointer;\n padding: 0;\n}\n.ttl-locateBtn:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(255, 255, 255, 0.08));\n color: var(--dsw-alias-label-primary, #f9fafb);\n}\n\n/* \u2500\u2500 Expanded body (transparent, indented under the rail) \u2500\u2500 */\n.ttl-turnBody {\n box-sizing: border-box;\n padding: 2px 6px 6px 34px;\n background: transparent;\n}\n/* \u2500\u2500 Unified row anatomy: [semantic dot] + [name] + [content] \u2500\u2500\n * One skeleton for every row. The 6px dot carries the whole color channel\n * (blue = user input, violet = assistant output, green/amber/neutral = tool\n * category matching the filter chips' dots, red = failure \u2014 replacing \u2717/\u2713),\n * the name names the row (monospace for tools), content follows. The name\n * column has a narrow 30px min-width: common short names (bash/edit/read,\n * \u8F93\u5165/\u8F93\u51FA) align without dead space; long names just push content. */\n.ttl-row {\n box-sizing: border-box;\n width: 100%;\n display: flex;\n align-items: flex-start;\n gap: 7px;\n padding: 3px 6px;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--dsw-alias-label-primary, #f9fafb);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n text-align: left;\n cursor: pointer;\n}\n.ttl-row:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(255, 255, 255, 0.08));\n}\n.ttl-rowDot {\n flex: none;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n margin-top: 6px;\n}\n.ttl-dot-blue {\n background: var(--dsw-alias-state-business-primary, #4176e6);\n}\n.ttl-dot-violet {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary-new-colorprimary-new-color, #5686fe) 60%, var(--dsw-alias-state-error-secondary, #f25a5a));\n}\n.ttl-dot-red {\n background: var(--dsw-alias-state-error-primary, #f25a5a);\n}\n.ttl-rowName {\n flex: none;\n min-width: 30px;\n max-width: 40%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--dsw-alias-label-secondary, #cfd3d6);\n}\n.ttl-rowNameMono {\n font-family: var(--ds-font-family-code, \"SF Mono\", \"JetBrains Mono\", \"Fira Code\", Consolas, \"Liberation Mono\", Menlo, Courier, \"PingFang SC\", \"Microsoft YaHei\", monospace);\n}\n.ttl-rowText {\n flex: 1;\n min-width: 0;\n color: var(--dsw-alias-label-primary, #f9fafb);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 3;\n line-clamp: 3;\n overflow: hidden;\n}\n.ttl-rowText2 {\n -webkit-line-clamp: 2;\n line-clamp: 2;\n}\n.ttl-rowTextMuted { color: var(--dsw-alias-label-tertiary, #adb2b8); }\n.ttl-rowArgs {\n flex: 1;\n min-width: 0;\n font-family: var(--ds-font-family-code, \"SF Mono\", \"JetBrains Mono\", \"Fira Code\", Consolas, \"Liberation Mono\", Menlo, Courier, \"PingFang SC\", \"Microsoft YaHei\", monospace);\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary, #cfd3d6);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n/* Error rows read red across dot and payload. */\n.ttl-row[data-step-kind=\"error\"] .ttl-rowArgs {\n color: var(--dsw-alias-state-error-primary, #f25a5a);\n}\n.ttl-emptyInline {\n padding: 6px 8px;\n color: var(--dsw-alias-label-tertiary, #adb2b8);\n font-size: 11px;\n line-height: 16px;\n}\n.ttl-showEarlier {\n box-sizing: border-box;\n width: 100%;\n height: 26px;\n margin: 2px 0 4px;\n padding: 0 8px;\n border: none;\n border-bottom: 1px dashed var(--dsw-alias-border-l2, rgba(255, 255, 255, 0.12));\n border-radius: 0;\n background: transparent;\n color: var(--dsw-alias-label-tertiary, #adb2b8);\n font: inherit;\n font-size: 11px;\n line-height: 16px;\n text-align: left;\n cursor: pointer;\n}\n.ttl-showEarlier:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(255, 255, 255, 0.08));\n color: var(--dsw-alias-label-secondary, #cfd3d6);\n}\n/* \u2500\u2500 Status bar / jump feedback \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.ttl-statusBar {\n box-sizing: border-box;\n flex: none;\n display: flex;\n align-items: center;\n gap: 8px;\n min-height: 30px;\n padding: 0 14px;\n border-top: 1px solid var(--dsw-alias-border-l1, rgba(255, 255, 255, 0.06));\n color: var(--dsw-alias-label-tertiary, #adb2b8);\n font-size: 12px;\n line-height: 18px;\n}\n.ttl-spin {\n display: inline-flex;\n color: var(--dsw-alias-state-business-primary, #4176e6);\n animation: ttl-spin 1s linear infinite;\n}\n@keyframes ttl-spin { to { transform: rotate(360deg); } }\n.ttl-jumpBanner {\n position: absolute;\n top: 8px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 8;\n display: flex;\n align-items: center;\n gap: 7px;\n max-width: 90%;\n padding: 5px 10px;\n border: 1px solid var(--dsw-alias-border-l2, rgba(255, 255, 255, 0.12));\n border-radius: 8px;\n background: var(--dsw-alias-button-floating-fill, #2c2c2e);\n color: var(--dsw-alias-label-primary, #f9fafb);\n font-size: 12px;\n font-weight: 400;\n line-height: 18px;\n white-space: nowrap;\n box-shadow: 0 4px 16px var(--dsw-alias-bg-mask-1, rgba(0, 0, 0, 0.24));\n}\n.ttl-toBottom {\n position: absolute;\n right: 12px;\n bottom: 12px;\n z-index: 5;\n box-sizing: border-box;\n height: 28px;\n padding: 0 12px;\n border: 1px solid var(--dsw-alias-border-l2, rgba(255, 255, 255, 0.12));\n border-radius: 8px;\n background: var(--dsw-alias-button-floating-fill, #2c2c2e);\n color: var(--dsw-alias-label-secondary, #cfd3d6);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n}\n.ttl-toBottom:hover {\n background: var(--dsw-alias-interactive-bg-hover-solid, #353638);\n color: var(--dsw-alias-label-primary, #f9fafb);\n}\n\n/* \u2500\u2500 Jump highlight flash (on the main conversation) \u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.ttl-flash { animation: ttl-flash 1.6s ease-out; }\n@keyframes ttl-flash {\n 0% { box-shadow: 0 0 0 3px var(--dsw-alias-state-business-primary, #4176e6); }\n 100% { box-shadow: 0 0 0 0 rgba(0, 0, 0, 0); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .ttl-spin { animation: none; }\n}\n`\n", "/**\n * TrailTab.tsx \u2014 the \u300C\u8F6E\u6B21\u8F68\u8FF9\u300Dpanel as a compact vertical turn timeline,\n * styled in the DSH-native design language (ink chrome, hairline separators,\n * flat rows \u2014 see styles.ts): a one-line header per turn (chevron + \"\u8F6E\u6B21 N\"\n * micro tag + input preview + bare tabular step count), an expanded flat list\n * of unified rows \u2014 [semantic dot] + [name] + [content] where the dot carries\n * the color channel (blue=input, violet=output, green/amber/neutral=tool\n * category, red=failure) \u2014 filter chips with matching category dots,\n * follow-latest auto-scroll, and click-to-locate (jump back into the main\n * conversation).\n *\n * Rendering cost model (v0.2.1): foldTurns ran over the WHOLE log and rebuilt\n * every TrailTurn object per poll, so every row re-rendered and index-based\n * keys + tail truncation remounted rows on each burst. Now:\n * - useTrail reuses closed TrailTurn objects (identity stable) \u2014 each poll\n * only the open turn's object changes;\n * - rows are keyed by event seq (stable), so appended steps reconcile in\n * place instead of shifting every key;\n * - each turn renders as a memoized TurnRow, so closed turns are skipped\n * entirely on the hot path.\n */\nimport * as React from 'react'\nimport type { TurnItem, TrailTurn, TrailStep, SessionEventLike } from '../trail-model'\nimport { stepsOf } from '../trail-model'\nimport { detectLang, t, type Lang } from './locales'\nimport { fetchTrailEvents, useTrail, type SessionsServiceLike } from './useTrail'\nimport { jumpToItem, type JumpTarget, type SessionFace } from './trail-jump'\n\nexport interface TrailTabProps {\n /** cordis client context (used only for ctx.get('sessions')). */\n ctx?: { get(name: string): unknown }\n scope: { sessionId: string; cwd?: string }\n visible: boolean\n tab: { id: string }\n /** test seam: override the events transport. */\n fetchEventsOverride?: (sessionId: string, afterSeq: number) => Promise<{ events: SessionEventLike[]; hasMore?: boolean }>\n}\n\ntype StepFilter = 'all' | 'failed' | string\n\nfunction sessionsOf(ctx: TrailTabProps['ctx']): SessionsServiceLike | undefined {\n if (ctx === undefined || typeof ctx.get !== 'function') return undefined\n const service = ctx.get('sessions')\n return service !== undefined && service !== null && typeof (service as { binding?: unknown }).binding === 'function'\n ? service as SessionsServiceLike\n : undefined\n}\n\nfunction turnByIdentity(turn: TrailTurn): string {\n return turn.turn !== null ? `turn:${turn.turn}` : `input:${turn.anchorSeq}`\n}\n\n/** Compact big counts: 1500 \u2192 \"1.5k\", 2200 \u2192 \"2.2k\", 384 \u2192 \"384\". */\nfunction formatCount(n: number): string {\n if (n < 1000) return String(n)\n const k = n / 1000\n return `${k >= 10 ? String(Math.round(k)) : String(Math.round(k * 10) / 10)}k`\n}\n\n/** Max step/items rows mounted per expanded turn (bounds the DOM). */\nconst STEP_CAP = 250\n\n/** Full tooltip text cap (server already trims to TEXT_CAP; belt and braces). */\nconst TITLE_CAP = 512\n\nfunction clipTitle(value: string): string {\n return value.length > TITLE_CAP ? `${value.slice(0, TITLE_CAP)}\u2026` : value\n}\n\n/** Semantic dot tone for a tool name (native-restrained: 3 tones + neutral). */\nfunction toolDotClass(name: string): 'success' | 'warn' | 'neutral' {\n const n = name.toLowerCase()\n if (n.includes('edit') || n.includes('write') || n.includes('patch')) return 'warn'\n if (n.includes('bash') || n.includes('command') || n.includes('exec') || n.includes('run')) return 'success'\n return 'neutral'\n}\n\n/** Stable per-item key: event seq (never shifts when new steps arrive). */\nfunction keyOfItem(item: TurnItem): string {\n return `seq:${item.kind === 'tool' ? item.step.seq : item.seq}`\n}\n\n/** The fold item a click targets (seq + kind + call id). */\nfunction targetFor(item: TurnItem): JumpTarget {\n if (item.kind === 'tool') {\n return {\n seq: item.step.seq,\n kind: item.step.kind === 'error' ? 'error' : 'tool',\n ...(item.step.callId !== null ? { callId: item.step.callId } : {}),\n }\n }\n return { seq: item.seq, kind: item.kind }\n}\n\ninterface TurnRowProps {\n turn: TrailTurn\n /** Position in the CURRENT visible list (drives default-latest semantics). */\n index: number\n expanded: boolean\n active: boolean\n showFull: boolean\n filter: StepFilter\n isToolFilter: boolean\n lang: Lang\n onToggle: (id: string) => void\n onShowEarlier: (id: string) => void\n onJump: (target: JumpTarget, turn: TrailTurn) => void\n}\n\nconst TurnRow = React.memo(function TurnRow(props: TurnRowProps): React.ReactElement {\n const { turn, index, expanded, active, showFull, filter, isToolFilter, lang, onToggle, onShowEarlier, onJump } = props\n const id = turnByIdentity(turn)\n\n const stepMatches = (step: TrailStep): boolean => {\n if (filter === 'all') return true\n if (filter === 'failed') return step.kind === 'error'\n return step.kind === 'tool' && step.name === filter\n }\n\n const items = turn.items.filter((item) => {\n if (item.kind === 'tool') return stepMatches(item.step)\n if (item.kind === 'input') return false\n return !isToolFilter\n })\n const turnTag = (t(lang, 'turnPrefix') as (n: number) => string)(turn.turn ?? index + 1)\n const preview = turn.inputPreview\n const hasError = turn.hasError\n /** The turn's user input; rendered as the first row of the expanded body. */\n const inputItem = turn.items.find((item): item is Extract<TurnItem, { kind: 'input' }> => item.kind === 'input')\n\n /** Unified row anatomy: [semantic dot] + [name] + [content]. */\n const dot = (tone: string): React.ReactElement => (\n <span className={`ttl-rowDot ttl-dot-${tone}`} aria-hidden=\"true\" />\n )\n const name = (label: string, mono: boolean): React.ReactElement => (\n <span className={`ttl-rowName${mono ? ' ttl-rowNameMono' : ''}`}>{label}</span>\n )\n\n /** First row of the expanded body: full input (3-line clamp), click = locate. */\n const renderInputRow = (item: Extract<TurnItem, { kind: 'input' }>): React.ReactElement => (\n <button\n type=\"button\"\n className=\"ttl-row\"\n data-testid=\"ttl-item-input\"\n title={clipTitle(item.text)}\n onClick={() => { onJump({ seq: item.seq, kind: 'input' }, turn) }}\n >\n {dot('blue')}\n {name(t(lang, 'input') as string, false)}\n <span className=\"ttl-rowText\">{item.text}</span>\n </button>\n )\n\n const renderStep = (step: TrailStep, key: string): React.ReactElement => {\n const isError = step.kind === 'error'\n const text = isError ? step.error : step.argsPreview\n const tone = isError ? 'red' : toolDotClass(step.name)\n return (\n <button\n type=\"button\"\n className=\"ttl-row\"\n key={key}\n data-testid=\"ttl-step\"\n data-step-kind={step.kind}\n title={text}\n onClick={() => { onJump(targetFor({ kind: 'tool', step }), turn) }}\n >\n {dot(tone)}\n {name(step.name, true)}\n <span className=\"ttl-rowArgs\">{text}</span>\n </button>\n )\n }\n\n const renderItem = (item: TurnItem, key: string): React.ReactElement | null => {\n if (item.kind === 'tool') return renderStep(item.step, key)\n if (item.kind === 'input') return null // shown as the body's first row\n if (item.kind === 'output') {\n return (\n <button\n type=\"button\"\n key={key}\n className=\"ttl-row\"\n data-testid=\"ttl-item-output\"\n title={clipTitle(item.text)}\n onClick={() => { onJump(targetFor(item), turn) }}\n >\n {dot('violet')}\n {name(t(lang, 'output') as string, false)}\n <span className=\"ttl-rowText ttl-rowText2\">{item.text}</span>\n </button>\n )\n }\n return (\n <button\n type=\"button\"\n key={key}\n className=\"ttl-row\"\n data-testid=\"ttl-item-compaction\"\n title={clipTitle(item.preview)}\n onClick={() => { onJump(targetFor(item), turn) }}\n >\n {dot('neutral')}\n {name(t(lang, 'compactionTag') as string, false)}\n <span className=\"ttl-rowText ttl-rowText2 ttl-rowTextMuted\">{item.preview}</span>\n </button>\n )\n }\n\n return (\n <section\n className=\"ttl-turnRow\"\n data-testid=\"ttl-turn\"\n data-collapsed={expanded ? 'false' : 'true'}\n data-active={active ? 'true' : undefined}\n data-error={hasError ? 'true' : undefined}\n >\n <div className=\"ttl-turnHead\">\n <button\n type=\"button\"\n className=\"ttl-turnToggle\"\n aria-expanded={expanded}\n onClick={() => { onToggle(id) }}\n >\n <span className={`ttl-chevron${expanded ? ' ttl-chevronOpen' : ''}`}>{chevronIcon()}</span>\n <span className=\"ttl-turnTag\" data-testid=\"ttl-turn-tag\">{turnTag}</span>\n {preview.length > 0\n ? <span className=\"ttl-turnPreview\" title={clipTitle(preview)}>{preview}</span>\n : null}\n </button>\n <span className=\"ttl-turnMeta\">\n {hasError ? <span className=\"ttl-errorDot\" data-testid=\"ttl-error-dot\" title={t(lang, 'error') as string} /> : null}\n <span\n className=\"ttl-stepsNum\"\n data-testid=\"ttl-steps-count\"\n title={t(lang, 'stepsLabel') as string}\n >{formatCount(turn.stepsCount)}</span>\n <button\n type=\"button\"\n className=\"ttl-locateBtn\"\n data-testid=\"ttl-locate\"\n title={t(lang, 'locate') as string}\n onClick={() => { onJump({ seq: turn.anchorSeq, kind: 'input' }, turn) }}\n >{targetIcon()}</button>\n </span>\n </div>\n {expanded\n ? (() => {\n // Bound the expanded body so a turn with thousands of steps\n // doesn't mount thousands of rows (and re-render them every\n // throttled update). Show the most recent STEP_CAP items plus a\n // \"show earlier\" affordance. Keys are seq-based, so appended\n // steps reconcile in place (rows keep their DOM nodes).\n const truncated = items.length > STEP_CAP && !showFull\n const shownItems = truncated ? items.slice(items.length - STEP_CAP) : items\n const hiddenCount = items.length - shownItems.length\n return (\n <div className=\"ttl-turnBody\">\n {filter === 'all' && inputItem !== undefined ? renderInputRow(inputItem) : null}\n {hiddenCount > 0\n ? <button\n type=\"button\"\n className=\"ttl-showEarlier\"\n data-testid=\"ttl-show-earlier\"\n onClick={() => { onShowEarlier(id) }}\n >{(t(lang, 'showEarlierSteps') as (n: number) => string)(hiddenCount)}</button>\n : null}\n {items.length === 0\n ? <div className=\"ttl-emptyInline\">{t(lang, 'emptyFiltered') as string}</div>\n : shownItems.map((item) => renderItem(item, keyOfItem(item)))}\n </div>\n )\n })()\n : null}\n </section>\n )\n})\n\nexport function TrailTab(props: TrailTabProps): React.ReactElement | null {\n const lang: Lang = detectLang()\n const sessionId = props.scope?.sessionId ?? ''\n const visible = props.visible === true\n const sessionsService = React.useMemo(() => sessionsOf(props.ctx), [props.ctx])\n const fetchEvents = React.useMemo(\n () => props.fetchEventsOverride !== undefined\n ? props.fetchEventsOverride\n : (sid: string, afterSeq: number) => fetchTrailEvents(sid, afterSeq),\n [props.fetchEventsOverride],\n )\n\n const { turns, stats, status, error, refresh } = useTrail(sessionId, visible, fetchEvents, sessionsService)\n\n const [filter, setFilter] = React.useState<StepFilter>('all')\n const [expandedTurns, setExpandedTurns] = React.useState<Set<string> | null>(null)\n const [jumping, setJumping] = React.useState<number | null>(null)\n const [jumpPages, setJumpPages] = React.useState(0)\n const [jumpMessage, setJumpMessage] = React.useState<string | null>(null)\n const [activeTurnId, setActiveTurnId] = React.useState<string | null>(null)\n const [followLatest, setFollowLatest] = React.useState(true)\n const [followPaused, setFollowPaused] = React.useState(false)\n const [moreToolsOpen, setMoreToolsOpen] = React.useState(false)\n const [showFullTurn, setShowFullTurn] = React.useState<Set<string>>(new Set())\n const listRef = React.useRef<HTMLDivElement | null>(null)\n const jumpingRef = React.useRef(false)\n\n // \u2500\u2500 Follow-latest auto-scroll (rAF-coalesced; no forced reflow per burst) \u2500\n const onScroll = React.useCallback((): void => {\n const el = listRef.current\n if (el === null) return\n const nearBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 32\n setFollowPaused(!nearBottom)\n }, [])\n\n React.useEffect(() => {\n if (!followLatest || followPaused) return undefined\n const el = listRef.current\n if (el === null) return undefined\n if (typeof window.requestAnimationFrame === 'function') {\n const raf = window.requestAnimationFrame(() => { el.scrollTop = el.scrollHeight })\n return () => window.cancelAnimationFrame(raf)\n }\n const timeout = window.setTimeout(() => { el.scrollTop = el.scrollHeight }, 0)\n return () => window.clearTimeout(timeout)\n }, [turns, followLatest, followPaused])\n\n const scrollToBottom = React.useCallback((): void => {\n const el = listRef.current\n if (el === null) return\n el.scrollTop = el.scrollHeight\n setFollowPaused(false)\n }, [])\n\n // \u2500\u2500 Expansion helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const latestIdRef = React.useRef('')\n React.useEffect(() => {\n latestIdRef.current = turns.length > 0 ? turnByIdentity(turns[turns.length - 1]) : ''\n }, [turns])\n\n const isTurnExpanded = React.useCallback((id: string, index: number): boolean => {\n if (expandedTurns === null) return index === turns.length - 1\n return expandedTurns.has(id)\n }, [expandedTurns, turns.length])\n\n const toggleTurn = React.useCallback((id: string): void => {\n setExpandedTurns((current) => {\n if (current === null) {\n // Default state = only the latest turn expanded. Materialize THAT\n // single set, then toggle just the clicked turn \u2014 never \"expand\n // every other turn\" (that inverted the default on first click).\n const latestId = latestIdRef.current\n const next = new Set<string>()\n if (latestId.length > 0) next.add(latestId)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n return next\n }\n const next = new Set(current)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n return next\n })\n }, [])\n\n const toggleShowFull = React.useCallback((id: string): void => {\n setShowFullTurn((current) => {\n const next = new Set(current)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n return next\n })\n }, [])\n\n // \u2500\u2500 Locate (jump) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const sessionForJump = React.useMemo<SessionFace | null>(() => {\n if (sessionsService === undefined) return null\n const binding = sessionsService.binding(sessionId)\n const session = binding !== undefined && binding.session !== undefined ? binding.session : undefined\n if (session === undefined) return null\n const face = session as unknown as { loadOlder?: unknown; getSnapshot?: unknown }\n if (typeof face.loadOlder !== 'function' || typeof face.getSnapshot !== 'function') return null\n return session as unknown as SessionFace\n }, [sessionsService, sessionId])\n\n const doJump = React.useCallback(async (target: JumpTarget, turn: TrailTurn): Promise<void> => {\n if (jumpingRef.current) return // ignore re-entry while a jump is in flight\n setActiveTurnId(turnByIdentity(turn))\n if (sessionForJump === null) {\n setJumpMessage(t(lang, 'jumpFailed') as string)\n return\n }\n jumpingRef.current = true\n setJumping(target.seq)\n setJumpPages(0)\n setJumpMessage(null)\n const outcome = await jumpToItem(sessionForJump, target, {\n document: window.document,\n onProgress: (pages) => setJumpPages(pages),\n })\n jumpingRef.current = false\n setJumping(null)\n if (outcome.ok) {\n setJumpMessage(t(lang, outcome.mode === 'trajectory' ? 'jumpTrajectory' : 'jumpDone') as string)\n } else {\n setJumpMessage(t(lang, 'jumpFailed') as string)\n }\n }, [sessionForJump, lang])\n\n // \u2500\u2500 Filtered rendering helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const stepMatches = (step: TrailStep): boolean => {\n if (filter === 'all') return true\n if (filter === 'failed') return step.kind === 'error'\n return step.kind === 'tool' && step.name === filter\n }\n\n const visibleTurns = React.useMemo(\n () => (filter === 'all' || filter === 'failed' ? turns : turns.filter((turn) => stepsOf(turn).some((step) => stepMatches(step)))),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [turns, filter],\n )\n\n const toolChips = stats.tools.slice(0, 4)\n const hasMoreTools = stats.tools.length > 4\n const isToolFilter = filter !== 'all' && filter !== 'failed'\n\n if (!visible) return null\n\n // \u2500\u2500 Render pieces \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const chipButton = (value: StepFilter, label: string, count: number, dot?: 'success' | 'warn' | 'neutral'): React.ReactElement => (\n <button\n type=\"button\"\n key={value}\n className=\"ttl-chip\"\n aria-pressed={filter === value ? 'true' : 'false'}\n data-testid={`ttl-chip-${value}`}\n onClick={() => { setFilter((current) => (current === value ? 'all' : value)) }}\n >\n {dot ? <span className={`ttl-chipDot ttl-dot-${dot}`} aria-hidden=\"true\" /> : null}\n <span>{label}</span>\n {count > 0 ? <span className=\"ttl-chipNum\">{String(count)}</span> : null}\n </button>\n )\n\n const header = (\n <div className=\"ttl-header\">\n <h2 className=\"ttl-title\">{t(lang, 'tabTitle') as string}</h2>\n <span className=\"ttl-count\" data-testid=\"ttl-count\">{(t(lang, 'turnsCount') as (n: number) => string)(turns.length)}</span>\n <span className=\"ttl-headerSpacer\" />\n <button\n type=\"button\"\n className=\"ttl-toggle\"\n aria-pressed={followLatest ? 'true' : 'false'}\n data-testid=\"ttl-follow-toggle\"\n onClick={() => { setFollowLatest((current) => !current) }}\n >\n <span className=\"ttl-toggleDot\" aria-hidden=\"true\" />\n {t(lang, 'followLatest') as string}\n </button>\n </div>\n )\n\n const chips = (\n <>\n <div className=\"ttl-filterRow\" role=\"group\" data-testid=\"ttl-chips\">\n {chipButton('all', t(lang, 'filterAll') as string, stats.total)}\n {stats.failed > 0 ? chipButton('failed', t(lang, 'filterFailed') as string, stats.failed) : null}\n {toolChips.map((tool) => chipButton(tool.name, tool.name, tool.count, toolDotClass(tool.name)))}\n {hasMoreTools\n ? <button\n type=\"button\"\n key=\"more\"\n className=\"ttl-chip ttl-moreChip\"\n aria-expanded={moreToolsOpen ? 'true' : 'false'}\n data-testid=\"ttl-chip-more\"\n onClick={() => { setMoreToolsOpen((current) => !current) }}\n >\n {t(lang, moreToolsOpen ? 'filterCollapse' : 'filterMore') as string}\n <span className={`ttl-moreArrow${moreToolsOpen ? ' ttl-moreArrowOpen' : ''}`}>{chevronIcon()}</span>\n </button>\n : null}\n </div>\n {moreToolsOpen && hasMoreTools\n ? <div className=\"ttl-toolDropdown\" data-testid=\"ttl-tool-dropdown\">\n {stats.tools.map((tool) => chipButton(tool.name, tool.name, tool.count, toolDotClass(tool.name)))}\n </div>\n : null}\n </>\n )\n\n let body: React.ReactElement\n if (status === 'loading') {\n body = <div className=\"ttl-status\" data-testid=\"ttl-status\">{t(lang, 'loading') as string}</div>\n } else if (status === 'error' && turns.length === 0) {\n body = (\n <div>\n <div className=\"ttl-error\" data-testid=\"ttl-error\">{error ?? t(lang, 'loadFailed') as string}</div>\n <div className=\"ttl-filterRow\">\n <button type=\"button\" className=\"ttl-chip\" onClick={refresh} data-testid=\"ttl-retry\">{t(lang, 'retry') as string}</button>\n </div>\n </div>\n )\n } else if (turns.length === 0) {\n body = <div className=\"ttl-status\" data-testid=\"ttl-empty\">{t(lang, 'emptyNoTurns') as string}</div>\n } else if (visibleTurns.length === 0) {\n body = (\n <div className=\"ttl-status\" data-testid=\"ttl-empty-filtered\">\n {t(lang, 'emptyFiltered') as string}\n <button type=\"button\" className=\"ttl-chip\" style={{ marginLeft: 8 }} onClick={() => { setFilter('all') }}>{t(lang, 'clearFilter') as string}</button>\n </div>\n )\n } else {\n body = (\n <div className=\"ttl-list\" ref={listRef} onScroll={onScroll} data-testid=\"ttl-list\">\n {visibleTurns.map((turn, index) => (\n <TurnRow\n key={turnByIdentity(turn)}\n turn={turn}\n index={index}\n expanded={isTurnExpanded(turnByIdentity(turn), index)}\n active={activeTurnId === turnByIdentity(turn)}\n showFull={showFullTurn.has(turnByIdentity(turn))}\n filter={filter}\n isToolFilter={isToolFilter}\n lang={lang}\n onToggle={toggleTurn}\n onShowEarlier={toggleShowFull}\n onJump={doJump}\n />\n ))}\n </div>\n )\n }\n\n const statusBar = jumping !== null || jumpMessage !== null\n ? (\n <div className=\"ttl-statusBar\" data-testid=\"ttl-statusbar\">\n {jumping !== null ? <span className=\"ttl-spin\">{spinnerIcon()}</span> : null}\n <span>\n {jumping !== null ? `${(t(lang, 'jumpProgress') as (n: number) => string)(jumpPages)} ` : ''}\n {jumpMessage ?? ''}\n </span>\n </div>\n )\n : null\n\n return (\n <div className=\"ttl-root\" role=\"complementary\" aria-label={t(lang, 'tabTitle') as string} data-testid=\"ttl-root\">\n {header}\n {chips}\n {body}\n {statusBar}\n {jumping !== null\n ? <div className=\"ttl-jumpBanner\" data-testid=\"ttl-jump-banner\" role=\"status\">\n <span className=\"ttl-spin\">{spinnerIcon()}</span>\n {(t(lang, 'jumpProgress') as (n: number) => string)(jumpPages)}\n </div>\n : null}\n {followPaused && turns.length > 0\n ? <button type=\"button\" className=\"ttl-toBottom\" data-testid=\"ttl-to-bottom\" onClick={scrollToBottom}>{t(lang, 'newUpdates') as string}</button>\n : null}\n </div>\n )\n}\n\nfunction chevronIcon(): React.ReactElement {\n return (\n <svg viewBox=\"0 0 16 16\" width=\"12\" height=\"12\" aria-hidden=\"true\">\n <path d=\"M6 4l4 4-4 4\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\nfunction spinnerIcon(): React.ReactElement {\n return (\n <svg viewBox=\"0 0 16 16\" width=\"12\" height=\"12\" aria-hidden=\"true\">\n <path d=\"M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2.5v3h-3\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n )\n}\n\nfunction targetIcon(): React.ReactElement {\n return (\n <svg viewBox=\"0 0 16 16\" width=\"13\" height=\"13\" aria-hidden=\"true\">\n <circle cx=\"8\" cy=\"8\" r=\"5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <circle cx=\"8\" cy=\"8\" r=\"1.6\" fill=\"currentColor\" />\n </svg>\n )\n}\n", "/**\n * trail-model.ts \u2014 pure event \u2192 turn folding for dsh-turn-outline.\n *\n * Framework-agnostic (no React / DOM / Node): a single foldTurns() maps a\n * session event stream onto per-user-turn summaries:\n *\n * turn boundary = `turn/start .. turn/end` (the `data.turn` number is the\n * turn identity \u2014 stable under parallel steps / steering).\n * input = first `user/message` with source.kind === 'user'.\n * context rows = `steering` / `context` user messages (kept as grey rows).\n * tool steps = `tool/call` (+ `tool/result` error rows).\n * tool groups = consecutive tool/call steps (>=2) merged, broken by an\n * assistant output, an error, a compaction, a user\n * message or a turn end.\n * output = `assistant/message` text (last text block wins).\n * compaction = `compaction/summary` shown as a checkpoint row.\n * command/run = ignored (mirrors the trajectory view).\n *\n * Fallback mode: a stream with NO turn/start events folds on\n * `user/message` boundaries, so the panel still works for odd logs.\n *\n * Field asymmetry (verified against DSH 0.1.1-rc.2):\n * user/message text lives in data.content (block array or bare string),\n * assistant/message text lives in data.message.content.\n */\n\nexport interface SessionEventLike {\n type: string\n seq: number\n time?: number\n data?: Record<string, unknown> | null\n}\n\nexport type TurnItem =\n | { kind: 'input'; seq: number; text: string; preview: string }\n | { kind: 'tool'; step: TrailStep }\n | { kind: 'output'; seq: number; text: string; preview: string }\n | { kind: 'compaction'; seq: number; preview: string }\n\nexport interface TrailStep {\n kind: 'tool' | 'error'\n seq: number\n name: string\n argsPreview: string\n callId: string | null\n error: string\n}\n\nexport interface TrailTurn {\n index: number\n turn: number | null\n /** The seq a jump targets: the user input, else the first item. */\n anchorSeq: number\n inputPreview: string\n outputPreview: string\n status: 'pending' | 'running' | 'done' | 'error'\n startedAt?: number\n endedAt?: number\n items: TurnItem[]\n stepsCount: number\n /** Number of injected system-reminders / steering for this turn (not rendered). */\n contextCount: number\n hasError: boolean\n}\n\n/** Aggregated step statistics (kept incrementally, not re-derived per pull). */\nexport interface TrailStats {\n total: number\n failed: number\n tools: Array<{ name: string; count: number }>\n}\n\n/** Preview length for one-line summaries. */\nexport const PREVIEW_MAX = 120\n\n/** Flatten every tool/error step of a turn. */\nexport function stepsOf(turn: TrailTurn): TrailStep[] {\n const out: TrailStep[] = []\n for (const item of turn.items) {\n if (item.kind === 'tool') out.push(item.step)\n }\n return out\n}\n\nexport function compact(value: string, max = PREVIEW_MAX): string {\n const oneLine = value.replace(/\\s+/g, ' ').trim()\n if (oneLine.length <= max) return oneLine\n return `${oneLine.slice(0, max - 1).trimEnd()}\u2026`\n}\n\n/** Extract text from a content block array (first non-empty text block). */\nexport function contentPreview(blocks: unknown): string {\n if (typeof blocks === 'string') return compact(blocks)\n if (!Array.isArray(blocks)) return ''\n for (const block of blocks) {\n if (\n block !== null && typeof block === 'object'\n && (block as { type?: unknown }).type === 'text'\n && typeof (block as { text?: unknown }).text === 'string'\n && (block as { text: string }).text.trim().length > 0\n ) {\n return compact((block as { text: string }).text)\n }\n }\n return ''\n}\n\n/** Last text block of an assistant message content array. */\nexport function lastTextBlock(blocks: unknown): string {\n if (typeof blocks === 'string') return blocks\n if (!Array.isArray(blocks)) return ''\n let last = ''\n for (const block of blocks) {\n if (\n block !== null && typeof block === 'object'\n && (block as { type?: unknown }).type === 'text'\n && typeof (block as { text?: unknown }).text === 'string'\n && (block as { text: string }).text.trim().length > 0\n ) {\n last = (block as { text: string }).text\n }\n }\n return last\n}\n\nfunction objectData(event: SessionEventLike): Record<string, unknown> {\n return event.data !== null && typeof event.data === 'object' ? event.data : {}\n}\n\n/** source.kind: 'user' | 'steering' | 'context' | 'plugin' | ... */\nfunction sourceKindOf(event: SessionEventLike, data: Record<string, unknown>): string | undefined {\n const message = data.message !== null && typeof data.message === 'object' ? data.message : {}\n const source = message !== null && typeof (message as { source?: unknown }).source === 'object'\n ? (message as { source: { kind?: unknown } }).source\n : (data.source !== null && typeof data.source === 'object'\n ? (data.source as { kind?: unknown })\n : null)\n if (source !== null && typeof source.kind === 'string') return source.kind\n return undefined\n}\n\nexport function toolCallIdOf(data: Record<string, unknown>): string | null {\n if (typeof data.callId === 'string' && data.callId.length > 0) return data.callId\n const message = data.message !== null && typeof data.message === 'object' ? data.message : {}\n const source = message !== null && typeof (message as { source?: unknown }).source === 'object'\n ? (message as { source: { callId?: unknown } }).source\n : null\n if (source !== null && typeof source.callId === 'string' && source.callId.length > 0) {\n return source.callId\n }\n return null\n}\n\ninterface Builder {\n turn: number | null\n startSeq: number | null\n endSeq: number | null\n input: string\n inputSeq: number | null\n output: string\n outputSeq: number | null\n items: TurnItem[]\n steps: TrailStep[]\n contexts: Array<{ seq: number; text: string; preview: string }>\n hasError: boolean\n startedAt?: number\n endedAt?: number\n /** Turn-mode order position (set by TrailFolder); tracks frozen slots. */\n position?: number\n}\n\nfunction newBuilder(turn: number | null): Builder {\n return {\n turn,\n startSeq: null,\n endSeq: null,\n input: '',\n inputSeq: null,\n output: '',\n outputSeq: null,\n items: [],\n steps: [],\n contexts: [],\n hasError: false,\n }\n}\n\nfunction appendItem(builder: Builder, item: TurnItem): void {\n builder.items.push(item)\n if (item.kind === 'tool') {\n builder.steps.push(item.step)\n if (item.step.kind === 'error') builder.hasError = true\n }\n}\n\nfunction finishBuilder(builder: Builder, index: number, boundarySeq: number): TrailTurn {\n const anchorSeq = builder.inputSeq !== null ? builder.inputSeq : boundarySeq\n const status: TrailTurn['status'] = builder.hasError\n ? 'error'\n : builder.endSeq === null\n ? (builder.items.length > 0 ? 'running' : 'pending')\n : 'done'\n return {\n index,\n turn: builder.turn,\n anchorSeq,\n inputPreview: compact(builder.input),\n outputPreview: compact(builder.output),\n status,\n ...(builder.startedAt !== undefined ? { startedAt: builder.startedAt } : {}),\n ...(builder.endedAt !== undefined ? { endedAt: builder.endedAt } : {}),\n items: builder.items,\n stepsCount: builder.steps.length,\n contextCount: builder.contexts.length,\n hasError: builder.hasError,\n }\n}\n\n/** First seq-bearing entry of an item list (used as a fallback boundary). */\nfunction firstItemSeq(items: TurnItem[]): number {\n for (const item of items) {\n if (item.kind === 'tool') return item.step.seq\n return item.seq\n }\n return 0\n}\n\n/**\n * Fold an event stream onto TrailTurn[].\n * @param events - session events ordered by seq.\n * @returns the folded turns in stream order.\n */\nexport function foldTurns(events: readonly SessionEventLike[]): TrailTurn[] {\n const out: TrailTurn[] = []\n if (!Array.isArray(events) || events.length === 0) return out\n\n const hasTurnEvents = events.some((event) => (\n event !== null && typeof event === 'object'\n && typeof (event as { type?: unknown }).type === 'string'\n && (event as { type: string }).type === 'turn/start'\n ))\n if (!hasTurnEvents) return foldByUserBoundaries(events)\n\n const index = new Map<number, Builder>()\n const order: number[] = []\n const pendingUser: Array<{ seq: number; text: string }> = []\n let current: Builder | null = null\n\n const builderOf = (turn: number): Builder => {\n let builder = index.get(turn)\n if (builder === undefined) {\n builder = newBuilder(turn)\n index.set(turn, builder)\n order.push(turn)\n }\n return builder\n }\n\n for (const event of events) {\n if (event === null || typeof event !== 'object' || typeof event.type !== 'string') continue\n const data = objectData(event)\n const seq = typeof event.seq === 'number' ? event.seq : 0\n const time = typeof event.time === 'number' ? event.time : undefined\n\n switch (event.type) {\n case 'turn/start': {\n const raw = data.turn\n if (typeof raw === 'number') {\n const builder = builderOf(raw)\n if (builder.startSeq === null) builder.startSeq = seq\n if (builder.startedAt === undefined) builder.startedAt = time\n for (const pending of pendingUser.splice(0)) {\n builder.input = pending.text\n builder.inputSeq = pending.seq\n builder.items.unshift({ kind: 'input', seq: pending.seq, text: pending.text, preview: compact(pending.text) })\n }\n current = builder\n }\n break\n }\n case 'turn/end': {\n const raw = data.turn\n const target = typeof raw === 'number' ? builderOf(raw) : current\n if (target !== null) {\n target.endSeq = seq\n target.endedAt = time\n current = null\n }\n break\n }\n case 'user/message': {\n const preview = contentPreview(data.content)\n if (preview.length === 0) break\n const kind = sourceKindOf(event, data)\n const text = typeof data.content === 'string'\n ? data.content\n : (typeof data.message === 'object' && data.message !== null\n && typeof (data.message as { content?: unknown }).content === 'string'\n ? (data.message as { content: string }).content\n : preview)\n if (kind === 'user') {\n if (current === null) {\n pendingUser.push({ seq, text })\n } else {\n current.input = text\n current.inputSeq = seq\n appendItem(current, { kind: 'input', seq, text, preview })\n }\n } else if (current !== null) {\n current.contexts.push({ seq, text, preview })\n }\n break\n }\n case 'assistant/message': {\n const message = data.message !== null && typeof data.message === 'object' ? data.message : {}\n const content = typeof (message as { content?: unknown }).content !== 'undefined'\n ? (message as { content: unknown }).content\n : data.content\n const text = lastTextBlock(content)\n if (text.length === 0) break\n if (current !== null) {\n current.output = text\n current.outputSeq = seq\n appendItem(current, { kind: 'output', seq, text, preview: compact(text) })\n }\n break\n }\n case 'tool/call': {\n if (current === null) break\n const name = typeof data.name === 'string' && data.name.length > 0 ? data.name : 'tool'\n const args = typeof data.arguments === 'string' && data.arguments.length > 0 ? data.arguments : ''\n const step: TrailStep = {\n kind: 'tool',\n seq,\n name,\n argsPreview: compact(args),\n callId: toolCallIdOf(data),\n error: '',\n }\n appendItem(current, { kind: 'tool', step })\n break\n }\n case 'tool/result': {\n const error = (data.error !== null && typeof data.error === 'object' ? data.error : null) as {\n name?: unknown\n code?: unknown\n } | null\n if (error === null) break\n if (current === null) break\n const name = typeof error.name === 'string' && error.name.length > 0 ? error.name : 'tool'\n const detail = typeof error.code === 'string' && error.code.length > 0 ? ` \u00B7 ${error.code}` : ''\n const step: TrailStep = {\n kind: 'error',\n seq,\n name,\n argsPreview: '',\n callId: toolCallIdOf(data),\n error: compact(`${name}${detail}`),\n }\n appendItem(current, { kind: 'tool', step })\n break\n }\n case 'compaction/summary': {\n const preview = contentPreview(data.summary)\n if (preview.length === 0) break\n if (current !== null) appendItem(current, { kind: 'compaction', seq, preview })\n break\n }\n default:\n // command/run and anything else: ignored.\n break\n }\n }\n\n let counter = 0\n for (const turn of order) {\n const builder = index.get(turn)\n if (builder === undefined) continue\n const boundarySeq = builder.startSeq !== null ? builder.startSeq : (builder.inputSeq ?? firstItemSeq(builder.items))\n out.push(finishBuilder(builder, counter, boundarySeq))\n counter += 1\n }\n // Trailing user messages that never found a turn.\n for (const pending of pendingUser) {\n const builder = newBuilder(null)\n builder.input = pending.text\n builder.inputSeq = pending.seq\n appendItem(builder, { kind: 'input', seq: pending.seq, text: pending.text, preview: compact(pending.text) })\n out.push(finishBuilder(builder, counter, pending.seq))\n counter += 1\n }\n return out\n}\n\n/** Fallback: fold on user/message boundaries when no turn/start exists. */\nexport function foldByUserBoundaries(events: readonly SessionEventLike[]): TrailTurn[] {\n const out: TrailTurn[] = []\n let builder: Builder | null = null\n let counter = 0\n\n const close = (): void => {\n if (builder === null) return\n const boundarySeq = builder.inputSeq !== null ? builder.inputSeq : builder.startSeq ?? 0\n out.push(finishBuilder(builder, counter, boundarySeq))\n counter += 1\n builder = null\n }\n\n for (const event of events) {\n if (event === null || typeof event !== 'object' || typeof event.type !== 'string') continue\n const data = objectData(event)\n const seq = typeof event.seq === 'number' ? event.seq : 0\n const time = typeof event.time === 'number' ? event.time : undefined\n\n if (event.type === 'user/message') {\n const kind = sourceKindOf(event, data)\n if (kind !== 'user') continue\n close()\n const text = typeof data.content === 'string' ? data.content : contentPreview(data.content)\n if (text.length === 0) continue\n builder = newBuilder(null)\n builder.startSeq = seq\n builder.startedAt = time\n builder.input = text\n builder.inputSeq = seq\n appendItem(builder, { kind: 'input', seq, text, preview: compact(text) })\n continue\n }\n if (builder === null) continue\n if (event.type === 'assistant/message') {\n const message = data.message !== null && typeof data.message === 'object' ? data.message : {}\n const text = lastTextBlock((message as { content?: unknown }).content ?? data.content)\n if (text.length === 0) continue\n builder.output = text\n builder.outputSeq = seq\n appendItem(builder, { kind: 'output', seq, text, preview: compact(text) })\n continue\n }\n if (event.type === 'tool/call') {\n const name = typeof data.name === 'string' && data.name.length > 0 ? data.name : 'tool'\n const args = typeof data.arguments === 'string' && data.arguments.length > 0 ? data.arguments : ''\n const step: TrailStep = {\n kind: 'tool',\n seq,\n name,\n argsPreview: compact(args),\n callId: toolCallIdOf(data),\n error: '',\n }\n // appendItem records the step once (in items AND steps); a redundant\n // direct steps.push here would double-count stepsCount.\n appendItem(builder, { kind: 'tool', step })\n continue\n }\n if (event.type === 'tool/result') {\n const error = (data.error !== null && typeof data.error === 'object' ? data.error : null) as {\n name?: unknown\n code?: unknown\n } | null\n if (error === null) continue\n const name = typeof error.name === 'string' && error.name.length > 0 ? error.name : 'tool'\n const detail = typeof error.code === 'string' && error.code.length > 0 ? ` \u00B7 ${error.code}` : ''\n const step: TrailStep = {\n kind: 'error',\n seq,\n name,\n argsPreview: '',\n callId: toolCallIdOf(data),\n error: compact(`${name}${detail}`),\n }\n appendItem(builder, { kind: 'tool', step })\n continue\n }\n }\n close()\n return out\n}\n\n// \u2500\u2500 Incremental folding \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Materialize the open user-mode turn (fallback folding) at its list index. */\nfunction finishUserTurn(builder: Builder, index: number): TrailTurn {\n const boundarySeq = builder.inputSeq !== null ? builder.inputSeq : builder.startSeq ?? 0\n return finishBuilder(builder, index, boundarySeq)\n}\n\n/**\n * TrailFolder \u2014 incremental variant of foldTurns for live (append-only) event\n * streams. Events are consumed ONCE via push(); snapshot() materializes the\n * current turn list. The key property for rendering cost:\n *\n * closed turns are materialized once and REUSED (object identity is stable\n * across snapshots), so React.memo row components skip them; only the open\n * turn and the trailing state re-materialize per push burst \u2014 O(delta) work\n * per pull instead of a full O(n) re-fold of the whole log.\n *\n * Semantics mirror foldTurns(events) exactly for any stream \u2014 including the\n * user-boundary fallback mode and the mode flip when the first turn/start\n * arrives after fallback turns were already folded (the flip reconstructs\n * what a from-scratch turn-mode fold would hold: only pending user inputs\n * survive; pre-turn outputs/steps are dropped, matching turn-mode replay):\n * - mode 'unknown': no boundary seen yet \u2014 every fold mode would drop the\n * events, so they are dropped.\n * - mode 'turn': turn/start boundaries (foldTurns' primary mode).\n * - mode 'user': no turn/start anywhere yet (foldByUserBoundaries).\n *\n * push() additionally skips events whose seq is not strictly greater than the\n * last consumed seq, which makes the folder idempotent against duplicate or\n * re-sent pages from the transport.\n */\nexport class TrailFolder {\n private mode: 'unknown' | 'turn' | 'user' = 'unknown'\n\n // turn-mode state\n private readonly builders = new Map<number, Builder>()\n private readonly order: number[] = []\n private readonly frozen: Array<TrailTurn | null> = []\n private readonly pendingUser: Array<{ seq: number; text: string }> = []\n private current: Builder | null = null\n\n // user-mode state\n private readonly userClosed: TrailTurn[] = []\n private userActive: Builder | null = null\n private userActiveTurn: TrailTurn | null = null\n private userCounter = 0\n\n private lastSeq = -1\n private total = 0\n private failed = 0\n private readonly byTool = new Map<string, number>()\n\n /** Highest event seq consumed so far (duplicates / re-pages are skipped). */\n get latestSeq(): number {\n return this.lastSeq\n }\n\n push(event: SessionEventLike): void {\n if (event === null || typeof event !== 'object' || typeof event.type !== 'string') return\n const seq = typeof event.seq === 'number' ? event.seq : Number.NaN\n if (!Number.isFinite(seq) || seq <= this.lastSeq) return\n const data = objectData(event)\n const time = typeof event.time === 'number' ? event.time : undefined\n this.lastSeq = seq\n\n if (this.mode === 'turn') {\n this.applyTurnEvent(event.type, data, seq, time)\n return\n }\n if (this.mode === 'user') {\n if (event.type === 'turn/start' && typeof data.turn === 'number') {\n this.flipToTurnMode()\n this.applyTurnEvent(event.type, data, seq, time)\n } else {\n this.applyUserEvent(event.type, data, seq, time)\n }\n return\n }\n // mode 'unknown': commit on the first mode-discriminating event.\n if (event.type === 'turn/start' && typeof data.turn === 'number') {\n this.mode = 'turn'\n this.applyTurnEvent(event.type, data, seq, time)\n return\n }\n if (event.type === 'user/message' && sourceKindOf(event, data) === 'user') {\n this.mode = 'user'\n this.applyUserEvent(event.type, data, seq, time)\n return\n }\n // No boundary yet: both fold modes would drop this event (no open turn).\n }\n\n /** The current turn list; closed turns keep their object identity. */\n snapshot(): TrailTurn[] {\n if (this.mode === 'unknown') return []\n if (this.mode === 'user') {\n const out = this.userClosed.slice()\n if (this.userActive !== null) {\n if (this.userActiveTurn === null) {\n this.userActiveTurn = finishUserTurn(this.userActive, this.userClosed.length)\n }\n out.push(this.userActiveTurn)\n }\n return out\n }\n const out: TrailTurn[] = []\n for (let i = 0; i < this.order.length; i += 1) {\n const materialized = this.frozen[i]\n if (materialized !== null) {\n out.push(materialized)\n continue\n }\n const builder = this.builders.get(this.order[i])\n if (builder === undefined) continue\n out.push(this.materializeTurn(builder, i))\n }\n // Trailing user messages that never found a turn.\n let counter = this.order.length\n for (const pending of this.pendingUser) {\n const builder = newBuilder(null)\n builder.input = pending.text\n builder.inputSeq = pending.seq\n appendItem(builder, { kind: 'input', seq: pending.seq, text: pending.text, preview: compact(pending.text) })\n out.push(finishBuilder(builder, counter, pending.seq))\n counter += 1\n }\n return out\n }\n\n /** Incrementally maintained step statistics (total / failed / by-tool). */\n stats(): TrailStats {\n const tools = [...this.byTool.entries()]\n .sort((a, b) => b[1] - a[1])\n .map(([name, count]) => ({ name, count }))\n return { total: this.total, failed: this.failed, tools }\n }\n\n // \u2500\u2500 turn-mode application (mirrors foldTurns' switch verbatim) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private builderOf(turn: number): Builder {\n let builder = this.builders.get(turn)\n if (builder === undefined) {\n builder = newBuilder(turn)\n builder.position = this.order.length\n this.builders.set(turn, builder)\n this.order.push(turn)\n this.frozen.push(null)\n }\n return builder\n }\n\n private markDirty(builder: Builder): void {\n if (this.mode === 'user') {\n if (builder === this.userActive) this.userActiveTurn = null\n return\n }\n const position = builder.position\n if (position !== undefined && position >= 0 && position < this.frozen.length) {\n this.frozen[position] = null\n }\n }\n\n private addStep(builder: Builder, item: TurnItem & { kind: 'tool' }): void {\n appendItem(builder, item)\n this.total += 1\n if (item.step.kind === 'error') this.failed += 1\n else this.byTool.set(item.step.name, (this.byTool.get(item.step.name) ?? 0) + 1)\n this.markDirty(builder)\n }\n\n private materializeTurn(builder: Builder, position: number): TrailTurn {\n const boundarySeq = builder.startSeq !== null ? builder.startSeq : (builder.inputSeq ?? firstItemSeq(builder.items))\n const materialized = finishBuilder(builder, position, boundarySeq)\n this.frozen[position] = materialized\n return materialized\n }\n\n private applyTurnEvent(type: string, data: Record<string, unknown>, seq: number, time?: number): void {\n switch (type) {\n case 'turn/start': {\n const raw = data.turn\n if (typeof raw !== 'number') break\n const builder = this.builderOf(raw)\n if (builder.startSeq === null) builder.startSeq = seq\n if (builder.startedAt === undefined) builder.startedAt = time\n for (const pending of this.pendingUser.splice(0)) {\n builder.input = pending.text\n builder.inputSeq = pending.seq\n builder.items.unshift({ kind: 'input', seq: pending.seq, text: pending.text, preview: compact(pending.text) })\n }\n this.current = builder\n this.markDirty(builder)\n break\n }\n case 'turn/end': {\n const raw = data.turn\n const target = typeof raw === 'number' ? this.builderOf(raw) : this.current\n if (target !== null) {\n target.endSeq = seq\n target.endedAt = time\n this.current = null\n this.markDirty(target)\n }\n break\n }\n case 'user/message': {\n const preview = contentPreview(data.content)\n if (preview.length === 0) break\n const kind = sourceKindOf({ type, seq, data }, data)\n const text = typeof data.content === 'string'\n ? data.content\n : (typeof data.message === 'object' && data.message !== null\n && typeof (data.message as { content?: unknown }).content === 'string'\n ? (data.message as { content: string }).content\n : preview)\n if (kind === 'user') {\n if (this.current === null) {\n this.pendingUser.push({ seq, text })\n } else {\n this.current.input = text\n this.current.inputSeq = seq\n appendItem(this.current, { kind: 'input', seq, text, preview })\n this.markDirty(this.current)\n }\n } else if (this.current !== null) {\n this.current.contexts.push({ seq, text, preview })\n this.markDirty(this.current)\n }\n break\n }\n case 'assistant/message': {\n const message = data.message !== null && typeof data.message === 'object' ? data.message : {}\n const content = typeof (message as { content?: unknown }).content !== 'undefined'\n ? (message as { content: unknown }).content\n : data.content\n const text = lastTextBlock(content)\n if (text.length === 0) break\n if (this.current !== null) {\n this.current.output = text\n this.current.outputSeq = seq\n appendItem(this.current, { kind: 'output', seq, text, preview: compact(text) })\n this.markDirty(this.current)\n }\n break\n }\n case 'tool/call': {\n if (this.current === null) break\n const name = typeof data.name === 'string' && data.name.length > 0 ? data.name : 'tool'\n const args = typeof data.arguments === 'string' && data.arguments.length > 0 ? data.arguments : ''\n const step: TrailStep = {\n kind: 'tool',\n seq,\n name,\n argsPreview: compact(args),\n callId: toolCallIdOf(data),\n error: '',\n }\n this.addStep(this.current, { kind: 'tool', step })\n break\n }\n case 'tool/result': {\n const error = (data.error !== null && typeof data.error === 'object' ? data.error : null) as {\n name?: unknown\n code?: unknown\n } | null\n if (error === null) break\n if (this.current === null) break\n const name = typeof error.name === 'string' && error.name.length > 0 ? error.name : 'tool'\n const detail = typeof error.code === 'string' && error.code.length > 0 ? ` \u00B7 ${error.code}` : ''\n const step: TrailStep = {\n kind: 'error',\n seq,\n name,\n argsPreview: '',\n callId: toolCallIdOf(data),\n error: compact(`${name}${detail}`),\n }\n this.addStep(this.current, { kind: 'tool', step })\n break\n }\n case 'compaction/summary': {\n const preview = contentPreview(data.summary)\n if (preview.length === 0) break\n if (this.current !== null) {\n appendItem(this.current, { kind: 'compaction', seq, preview })\n this.markDirty(this.current)\n }\n break\n }\n default:\n // command/run and anything else: ignored (mirrors the trajectory view).\n break\n }\n }\n\n // \u2500\u2500 user-mode application (mirrors foldByUserBoundaries verbatim) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private closeUserTurn(): void {\n if (this.userActive === null) return\n this.userClosed.push(finishUserTurn(this.userActive, this.userCounter))\n this.userCounter += 1\n this.userActive = null\n this.userActiveTurn = null\n }\n\n private applyUserEvent(type: string, data: Record<string, unknown>, seq: number, time?: number): void {\n if (type === 'user/message') {\n const kind = sourceKindOf({ type, seq, data }, data)\n if (kind !== 'user') return\n this.closeUserTurn()\n const text = typeof data.content === 'string' ? data.content : contentPreview(data.content)\n if (text.length === 0) return\n const builder = newBuilder(null)\n builder.startSeq = seq\n builder.startedAt = time\n builder.input = text\n builder.inputSeq = seq\n appendItem(builder, { kind: 'input', seq, text, preview: compact(text) })\n this.userActive = builder\n this.userActiveTurn = null\n return\n }\n if (this.userActive === null) return\n if (type === 'assistant/message') {\n const message = data.message !== null && typeof data.message === 'object' ? data.message : {}\n const text = lastTextBlock((message as { content?: unknown }).content ?? data.content)\n if (text.length === 0) return\n this.userActive.output = text\n this.userActive.outputSeq = seq\n appendItem(this.userActive, { kind: 'output', seq, text, preview: compact(text) })\n this.userActiveTurn = null\n return\n }\n if (type === 'tool/call') {\n const name = typeof data.name === 'string' && data.name.length > 0 ? data.name : 'tool'\n const args = typeof data.arguments === 'string' && data.arguments.length > 0 ? data.arguments : ''\n const step: TrailStep = {\n kind: 'tool',\n seq,\n name,\n argsPreview: compact(args),\n callId: toolCallIdOf(data),\n error: '',\n }\n this.addStep(this.userActive, { kind: 'tool', step })\n return\n }\n if (type === 'tool/result') {\n const error = (data.error !== null && typeof data.error === 'object' ? data.error : null) as {\n name?: unknown\n code?: unknown\n } | null\n if (error === null) return\n const name = typeof error.name === 'string' && error.name.length > 0 ? error.name : 'tool'\n const detail = typeof error.code === 'string' && error.code.length > 0 ? ` \u00B7 ${error.code}` : ''\n const step: TrailStep = {\n kind: 'error',\n seq,\n name,\n argsPreview: '',\n callId: toolCallIdOf(data),\n error: compact(`${name}${detail}`),\n }\n this.addStep(this.userActive, { kind: 'tool', step })\n return\n }\n // compaction & anything else: foldByUserBoundaries ignores them.\n }\n\n /**\n * A turn/start arrived after user-boundary turns were folded. Reconstruct\n * what a from-scratch turn-mode fold of the consumed prefix would hold:\n * every user input becomes a pending input (in arrival order), and the\n * pre-turn outputs / tool steps are dropped \u2014 turn-mode replay attaches\n * nothing while no turn is open. Statistics reset accordingly.\n */\n private flipToTurnMode(): void {\n const pending: Array<{ seq: number; text: string }> = []\n const take = (turn: TrailTurn): void => {\n for (const item of turn.items) {\n if (item.kind === 'input') {\n pending.push({ seq: item.seq, text: item.text })\n return\n }\n }\n }\n for (const turn of this.userClosed) take(turn)\n // Read the active builder directly: it may never have been snapshot()'d.\n if (this.userActive !== null && this.userActive.inputSeq !== null) {\n pending.push({ seq: this.userActive.inputSeq, text: this.userActive.input })\n }\n this.userClosed.length = 0\n this.userActive = null\n this.userActiveTurn = null\n this.userCounter = 0\n this.pendingUser.length = 0\n this.pendingUser.push(...pending)\n this.total = 0\n this.failed = 0\n this.byTool.clear()\n this.mode = 'turn'\n }\n}\n", "/**\n * locales.ts \u2014 zh/en dictionaries for the trail panel, following the\n * browser language (matching conversation-outline's i18n approach).\n */\n\nexport type Lang = 'zh' | 'en'\n\nexport function detectLang(): Lang {\n if (typeof navigator === 'undefined') return 'en'\n const raw = navigator.language ?? ''\n return raw.toLowerCase().startsWith('zh') ? 'zh' : 'en'\n}\n\nexport interface Dict {\n tabTitle: string\n turnsCount: (n: number) => string\n followLatest: string\n followPaused: string\n newUpdates: string\n filterAll: string\n filterFailed: string\n filterMore: string\n clearFilter: string\n emptyNoTurns: string\n emptyFiltered: string\n loadFailed: string\n loading: string\n retry: string\n stepsCount: (n: number) => string\n toolCalls: (n: number) => string\n input: string\n output: string\n context: string\n contextCount: (n: number) => string\n compaction: string\n /** Short compaction label for the row tag column. */\n compactionTag: string\n jumpProgress: (n: number) => string\n jumpDone: string\n jumpFailed: string\n jumpTrajectory: string\n previewExpand: string\n previewClose: string\n previewTitle: (label: string) => string\n copyTurn: string\n copied: string\n running: string\n error: string\n turnPrefix: (n: number) => string\n expandAll: string\n collapseAll: string\n locate: string\n stepsLabel: string\n filterCollapse: string\n showEarlierSteps: (n: number) => string\n}\n\nconst zh: Dict = {\n tabTitle: '\u8F6E\u6B21\u8F68\u8FF9',\n turnsCount: (n) => `${n} \u8F6E`,\n followLatest: '\u8DDF\u968F\u6700\u65B0',\n followPaused: '\u5DF2\u6682\u505C\u8DDF\u968F',\n newUpdates: '\u6709\u65B0\u66F4\u65B0 \u2193',\n filterAll: '\u5168\u90E8',\n filterFailed: '\u5931\u8D25',\n filterMore: '\u66F4\u591A',\n clearFilter: '\u6E05\u7A7A\u7B5B\u9009',\n emptyNoTurns: '\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u8F6E\u6B21',\n emptyFiltered: '\u6CA1\u6709\u7B26\u5408\u7B5B\u9009\u7684\u6B65\u9AA4',\n loadFailed: '\u4F1A\u8BDD\u6570\u636E\u52A0\u8F7D\u5931\u8D25',\n loading: '\u6B63\u5728\u52A0\u8F7D\u4F1A\u8BDD\u6570\u636E\u2026',\n retry: '\u91CD\u8BD5',\n stepsCount: (n) => `${n} \u6B65\u9AA4`,\n toolCalls: (n) => `${n} \u6B21\u8C03\u7528`,\n input: '\u8F93\u5165',\n output: '\u8F93\u51FA',\n context: '\u4E0A\u4E0B\u6587',\n contextCount: (n) => `${n} \u6761`,\n compaction: '\u538B\u7F29\u68C0\u67E5\u70B9',\n compactionTag: '\u538B\u7F29',\n jumpProgress: (n) => `\u6B63\u5728\u5B9A\u4F4D\u66F4\u65E9\u7684\u5BF9\u8BDD\uFF08\u5DF2\u52A0\u8F7D ${n} \u9875\uFF09\u2026`,\n jumpDone: '\u5DF2\u5B9A\u4F4D',\n jumpFailed: '\u65E0\u6CD5\u5B9A\u4F4D\u8BE5\u6D88\u606F',\n jumpTrajectory: '\u5DF2\u5728\u8F68\u8FF9\u89C6\u56FE\u5B9A\u4F4D',\n previewExpand: '\u5C55\u5F00',\n previewClose: '\u5173\u95ED',\n previewTitle: (label) => label,\n copyTurn: '\u590D\u5236\u672C\u8F6E',\n copied: '\u5DF2\u590D\u5236',\n running: '\u8FDB\u884C\u4E2D',\n error: '\u9519\u8BEF',\n turnPrefix: (n) => `\u8F6E\u6B21 ${n}`,\n expandAll: '\u5C55\u5F00\u5168\u90E8',\n collapseAll: '\u5168\u90E8\u6298\u53E0',\n locate: '\u5B9A\u4F4D',\n stepsLabel: '\u5DE5\u5177\u6B65\u9AA4\u6570',\n filterCollapse: '\u6536\u8D77',\n showEarlierSteps: (n) => `\u663E\u793A\u66F4\u65E9 ${n} \u6761`,\n}\n\nconst en: Dict = {\n tabTitle: 'Turn Outline',\n turnsCount: (n) => `${n} turns`,\n followLatest: 'Follow latest',\n followPaused: 'Follow paused',\n newUpdates: 'New updates \u2193',\n filterAll: 'All',\n filterFailed: 'Failed',\n filterMore: 'More',\n clearFilter: 'Clear filter',\n emptyNoTurns: 'No turns in this session yet',\n emptyFiltered: 'No steps match the filter',\n loadFailed: 'Failed to load session data',\n loading: 'Loading session data\u2026',\n retry: 'Retry',\n stepsCount: (n) => `${n} steps`,\n toolCalls: (n) => `${n} calls`,\n input: 'Input',\n output: 'Output',\n context: 'Context',\n contextCount: (n) => `${n} items`,\n compaction: 'Compaction checkpoint',\n compactionTag: 'Fold',\n jumpProgress: (n) => `Locating earlier conversation (loaded ${n} page${n === 1 ? '' : 's'})\u2026`,\n jumpDone: 'Located',\n jumpFailed: 'Could not locate that message',\n jumpTrajectory: 'Located in the trajectory view',\n previewExpand: 'Expand',\n previewClose: 'Close',\n previewTitle: (label) => label,\n copyTurn: 'Copy turn',\n copied: 'Copied',\n running: 'running',\n error: 'error',\n turnPrefix: (n) => `Turn ${n}`,\n expandAll: 'Expand all',\n collapseAll: 'Collapse all',\n locate: 'Locate',\n stepsLabel: 'tool steps',\n filterCollapse: 'Collapse',\n showEarlierSteps: (n) => `Show ${n} earlier`,\n}\n\nconst dicts: Record<Lang, Dict> = { zh, en }\n\nexport function t(lang: Lang, key: keyof Dict): string | number | ((...args: never[]) => unknown) {\n return dicts[lang][key]\n}\n", "/**\n * useTrail.ts \u2014 subscription-driven session-event hook for the trail panel.\n *\n * Refreshing strategy (v0.2+): no timer polling. Pull once on activation,\n * then subscribe to the client `sessions` binding snapshot; any snapshot\n * change (running flip, new steps, older pages) re-pulls the delta. The tab's\n * `visible` gate pauses the subscription entirely.\n *\n * Incremental folding (v0.2.1): incoming events are pushed ONCE into a\n * TrailFolder instead of re-folding the whole accumulated array on every\n * pull. Closed turns keep their object identity across snapshots, so\n * memoized row components skip re-rendering; each throttled pull costs\n * O(delta) folding + O(page) appends instead of a full O(n) re-fold.\n * Duplicate / re-sent pages are dropped by the folder's seq watermark.\n */\nimport * as React from 'react'\nimport type { SessionEventLike } from '../trail-model'\nimport { TrailFolder, type TrailStats, type TrailTurn } from '../trail-model'\n\nexport interface FetchEventsResult {\n events: SessionEventLike[]\n /** True when the server held more events back (page); re-pull to drain. */\n hasMore?: boolean\n}\n\nexport type FetchEvents = (sessionId: string, afterSeq: number) => Promise<FetchEventsResult>\n\nexport interface SessionsServiceLike {\n binding(sessionId: string): {\n session?: SessionFaceLike\n } | undefined\n}\n\nexport interface SessionFaceLike {\n subscribe(listener: () => void): () => void\n getSnapshot(): { running?: boolean } | null\n}\n\nexport type TrailStatus = 'idle' | 'loading' | 'ready' | 'error'\n\nexport interface TrailState {\n turns: TrailTurn[]\n stats: TrailStats\n status: TrailStatus\n error: string | null\n refresh: () => void\n}\n\n/** Cap on drained pages per pull (each page \u2264 PAGE_SIZE events). */\nconst MAX_PULL_PAGES = 64\n\n/** Default transport: POST the /turntrail/api/events route. */\nexport function fetchTrailEvents(sessionId: string, afterSeq: number, base?: string): Promise<FetchEventsResult> {\n const url = new URL('/turntrail/api/events', base ?? window.location.origin)\n return fetch(url.toString(), {\n method: 'POST',\n headers: { 'content-type': 'application/json', accept: 'application/json' },\n body: JSON.stringify({ sessionId, afterSeq }),\n }).then(async (response) => {\n const data = (await response.json()) as { events?: SessionEventLike[]; hasMore?: boolean; error?: string }\n if (!response.ok || data === null || typeof data !== 'object' || !Array.isArray(data.events)) {\n throw new Error(data !== null && typeof data === 'object' && typeof data.error === 'string'\n ? data.error\n : `HTTP ${response.status}`)\n }\n return { events: data.events, hasMore: data.hasMore === true }\n })\n}\n\nconst EMPTY: TrailTurn[] = []\nconst EMPTY_STATS: TrailStats = { total: 0, failed: 0, tools: [] }\n\nexport function useTrail(\n sessionId: string,\n visible: boolean,\n fetchEvents: FetchEvents,\n sessionsService?: SessionsServiceLike,\n): TrailState {\n const [turns, setTurns] = React.useState<TrailTurn[]>(EMPTY)\n const [stats, setStats] = React.useState<TrailStats>(EMPTY_STATS)\n const [status, setStatus] = React.useState<TrailStatus>('idle')\n const [error, setError] = React.useState<string | null>(null)\n const folderRef = React.useRef<TrailFolder | null>(null)\n const seqRef = React.useRef(0)\n const sessionIdRef = React.useRef(sessionId)\n const fetchRef = React.useRef(fetchEvents)\n const requestGen = React.useRef(0)\n // Throttle the subscription-driven refresh. During live generation DSH emits\n // many events; a network round-trip + fold + re-render on EVERY event\n // hammers the (shared) main thread. Coalesce a burst into one update.\n const lastPullAt = React.useRef(0)\n const throttleTimer = React.useRef<number | null>(null)\n\n React.useEffect(() => { fetchRef.current = fetchEvents }, [fetchEvents])\n\n // Cancel any pending throttled pull on teardown.\n React.useEffect(() => () => {\n if (throttleTimer.current !== null) window.clearTimeout(throttleTimer.current)\n }, [])\n\n const pull = React.useCallback(async (): Promise<void> => {\n const generation = ++requestGen.current\n const sid = sessionIdRef.current\n try {\n // Drain possibly-paginated pages until the server log is current.\n for (let page = 0; page < MAX_PULL_PAGES; page += 1) {\n const { events, hasMore } = await fetchRef.current(sid, seqRef.current)\n if (generation !== requestGen.current || sid !== sessionIdRef.current) return\n if (events.length > 0) {\n let folder = folderRef.current\n if (folder === null) folder = folderRef.current = new TrailFolder()\n let anyPushed = false\n for (const event of events) {\n const before = folder.latestSeq\n folder.push(event)\n if (folder.latestSeq !== before) anyPushed = true\n }\n if (anyPushed) {\n const last = events[events.length - 1]\n if (typeof last.seq === 'number' && last.seq > seqRef.current) seqRef.current = last.seq\n setTurns(folder.snapshot())\n setStats(folder.stats())\n }\n }\n if (hasMore !== true || events.length === 0) break\n }\n setError(null)\n setStatus('ready')\n } catch (reason) {\n if (generation !== requestGen.current) return\n setError(reason instanceof Error ? reason.message : String(reason))\n setStatus((current) => (current === 'ready' ? current : 'error'))\n }\n }, [])\n\n const refresh = React.useCallback(() => { void pull() }, [pull])\n\n /**\n * Throttled pull for the subscription path: at most one run per MIN_GAP ms,\n * trailing catch-up so the last event of a burst is never dropped.\n */\n const schedulePull = React.useCallback((): void => {\n const MIN_GAP = 120\n const now = Date.now()\n const since = now - lastPullAt.current\n if (since >= MIN_GAP) {\n lastPullAt.current = now\n void pull()\n return\n }\n if (throttleTimer.current !== null) return\n throttleTimer.current = window.setTimeout(() => {\n throttleTimer.current = null\n lastPullAt.current = Date.now()\n void pull()\n }, MIN_GAP - since)\n }, [pull])\n\n // Session switch: reset the accumulator.\n React.useEffect(() => {\n sessionIdRef.current = sessionId\n folderRef.current = null\n seqRef.current = 0\n setTurns(EMPTY)\n setStats(EMPTY_STATS)\n setError(null)\n setStatus(sessionId.length > 0 ? 'loading' : 'idle')\n }, [sessionId])\n\n // Activation + subscription-driven refresh (paused while invisible).\n React.useEffect(() => {\n if (sessionId.length === 0 || !visible) return undefined\n void pull()\n const binding = sessionsService?.binding(sessionId)\n const session = binding !== undefined && binding.session !== undefined ? binding.session : undefined\n if (session === undefined || typeof session.subscribe !== 'function') return undefined\n return session.subscribe(() => { schedulePull() })\n }, [sessionId, visible, pull, schedulePull, sessionsService])\n\n return { turns, stats, status, error, refresh }\n}\n", "/**\n * trail-jump.ts \u2014 structured jump-back into the main conversation, via the\n * client `sessions` service (no DOM text matching, no \"load older\" button\n * hacking).\n *\n * chat view: session.loadOlder() loop \u2192 snapshot.chat.nodes (Map,\n * keyed by node key, each with anchorSeq) \u2192 find the node\n * nearest to the target seq \u2192 `[data-chat-anchor-key]`\n * row \u2192 scrollIntoView + flash.\n * trajectory view: snapshot.views.get('trajectory') \u2192 { eventNodes,\n * requests } mapped to `[data-trajectory-row-key]` rows;\n * collapsed summaries are expanded first.\n *\n * All dependencies (session face, document) are injected so the module stays\n * unit-testable.\n */\n\n/** A fold item the user clicked \u2014 anything with a seq. */\nexport interface JumpTarget {\n seq: number\n kind: 'user' | 'assistant' | 'tool' | 'error' | 'compaction' | 'context' | 'input' | 'output'\n callId?: string\n turn?: number\n step?: number\n}\n\nexport interface ChatNodeLike {\n key: string\n anchorSeq: number\n visibility?: string\n kind?: string\n turn?: number\n step?: number\n callId?: string\n}\n\nexport interface SessionSnapshotLike {\n hasMore?: boolean\n chat?: {\n nodes?: {\n values(): Iterable<ChatNodeLike>\n }\n }\n views?: {\n get(kind: string): unknown\n }\n}\n\nexport interface SessionFace {\n loadOlder(): Promise<unknown>\n getSnapshot(): SessionSnapshotLike\n}\n\nexport interface DocumentLike {\n querySelectorAll(selector: string): ArrayLike<{ dataset: Record<string, string>; click?(): void; scrollIntoView(opts?: unknown): void }>\n querySelector(selector: string): { scrollIntoView(opts?: unknown): void; dataset?: Record<string, string>; classList?: { add(name: string): void } } | null\n}\n\nexport interface JumpOptions {\n document: DocumentLike\n guard?: number\n onProgress?: (pages: number) => void\n}\n\nexport type JumpOutcome =\n | { ok: true; mode: 'chat' | 'trajectory' }\n | { ok: false; error: string }\n\n/** Whether the chat view lists a seq inside its current render window. */\nexport function hasSeqInWindow(snapshot: SessionSnapshotLike, seq: number): boolean {\n const store = snapshot.chat?.nodes\n if (store === undefined || typeof store.values !== 'function') return false\n let min = Number.POSITIVE_INFINITY\n let max = Number.NEGATIVE_INFINITY\n for (const node of store.values()) {\n if (node === null || typeof node !== 'object' || typeof node.anchorSeq !== 'number') continue\n if (node.anchorSeq < min) min = node.anchorSeq\n if (node.anchorSeq > max) max = node.anchorSeq\n }\n return min <= seq && seq <= max\n}\n\n/**\n * Find the visible node nearest to a seq (exact \u2192 next \u2192 prev). Hidden\n * nodes (e.g. an injected system-reminder) are skipped, so a hidden input\n * falls back to the next visible row naturally.\n */\nexport function findNodeForSeq(snapshot: SessionSnapshotLike, seq: number): ChatNodeLike | null {\n const store = snapshot.chat?.nodes\n if (store === undefined || typeof store.values !== 'function') return null\n let exact: ChatNodeLike | null = null\n let next: ChatNodeLike | null = null\n let prev: ChatNodeLike | null = null\n for (const node of store.values()) {\n if (node === null || typeof node !== 'object' || node.visibility === 'hidden') continue\n const anchor = node.anchorSeq\n if (typeof anchor !== 'number') continue\n if (Math.abs(anchor - seq) < 0.5) {\n if (exact === null) exact = node\n continue\n }\n if (anchor >= seq && (next === null || anchor < next.anchorSeq)) next = node\n if (anchor <= seq && (prev === null || anchor > prev.anchorSeq)) prev = node\n }\n return exact !== null ? exact : next !== null ? next : prev\n}\n\nfunction isTrajectoryViewActive(document: DocumentLike): boolean {\n return document.querySelector('[data-trajectory-scroll]') !== null\n}\n\n/** trajectory view \u2192 a stable `data-trajectory-row-key` value (or null). */\nexport function trajectoryRecordIdFor(item: JumpTarget, snapshot: SessionSnapshotLike): string | null {\n const views = snapshot.views\n if (views === undefined || typeof views.get !== 'function') return null\n const trajectory = views.get('trajectory')\n if (trajectory === null || typeof trajectory !== 'object') return null\n const view = trajectory as { eventNodes?: unknown[]; requests?: unknown[] }\n const nodes = Array.isArray(view.eventNodes) ? view.eventNodes : []\n const requests = Array.isArray(view.requests) ? view.requests : []\n const nodeWithKind = (kinds: string[], seq: number): { seq?: number; kind?: string; turn?: number; step?: number; callId?: string } | undefined => {\n const matches = nodes.filter((node): node is Record<string, unknown> => (\n node !== null && typeof node === 'object'\n && kinds.includes(String((node as { kind?: unknown }).kind))\n && typeof (node as { seq?: unknown }).seq === 'number'\n ))\n return (matches.find((node) => node.seq === seq)\n ?? matches.filter((node) => (node.seq as number) >= seq).sort((a, b) => (a.seq as number) - (b.seq as number))[0]) as\n { seq?: number; kind?: string; turn?: number; step?: number; callId?: string } | undefined\n }\n\n if (item.kind === 'user' || item.kind === 'context' || item.kind === 'input') {\n const target = nodeWithKind(['user', 'steering', 'context'], item.seq)\n if (target === undefined || typeof target.seq !== 'number') return null\n const rowKind = target.kind === 'steering' ? 'user' : target.kind\n return `${rowKind}\\u0000seq\\u0000${target.seq}`\n }\n if (item.kind === 'assistant' || item.kind === 'output') {\n const target = nodeWithKind(['assistant'], item.seq)\n if (target === undefined || typeof target.turn !== 'number' || typeof target.step !== 'number') return null\n return `assistant\\u0000${target.turn}\\u0000${target.step}`\n }\n if (item.kind === 'tool' || item.kind === 'error') {\n if (typeof item.callId === 'string' && item.callId.length > 0) return `tool\\u0000call\\u0000${item.callId}`\n const target = nodeWithKind(['tool-result'], item.seq)\n if (target === undefined || typeof target.callId !== 'string') return null\n return `tool\\u0000call\\u0000${target.callId}`\n }\n if (item.kind === 'compaction') {\n const compactions: Array<{ purpose?: unknown; startSeq?: number; resultSeq?: number }> = []\n for (const request of requests) {\n if (request === null || typeof request !== 'object') continue\n const record = request as { purpose?: unknown; startSeq?: unknown; resultSeq?: unknown }\n if (record.purpose === 'compaction' && typeof record.startSeq === 'number') {\n compactions.push({ purpose: record.purpose, startSeq: record.startSeq, resultSeq: typeof record.resultSeq === 'number' ? record.resultSeq : undefined })\n }\n }\n const target = compactions.find((request) => request.resultSeq === item.seq)\n ?? compactions.filter((request) => (request.resultSeq ?? -1) >= item.seq)\n .sort((a, b) => (a.resultSeq ?? -1) - (b.resultSeq ?? -1))[0]\n if (target === undefined) return null\n return `compacted\\u0000seq\\u0000${target.startSeq}`\n }\n return null\n}\n\nfunction findTrajectoryRow(document: DocumentLike, key: string): { dataset: Record<string, string>; click?(): void; scrollIntoView(opts?: unknown): void } | null {\n const encoded = encodeURIComponent(key)\n const rows = document.querySelectorAll('tr[data-trajectory-row-key]')\n for (let index = 0; index < rows.length; index += 1) {\n const row = rows[index]\n const value = row.dataset !== undefined ? row.dataset.trajectoryRowKey : undefined\n if (value === encoded || value === key) return row\n }\n return null\n}\n\nfunction findTrajectoryRowBySeq(document: DocumentLike, item: JumpTarget): { dataset: Record<string, string>; click?(): void; scrollIntoView(opts?: unknown): void } | null {\n const rows = document.querySelectorAll('tr[data-trajectory-row-key]')\n for (let index = 0; index < rows.length; index += 1) {\n const row = rows[index]\n const raw = row.dataset.trajectoryRowKey ?? ''\n let id = ''\n try {\n id = decodeURIComponent(raw)\n } catch {\n continue\n }\n if (id.includes(`\\u0000seq\\u0000${item.seq}`)) return row\n if (typeof item.callId === 'string' && id.includes(`\\u0000call\\u0000${item.callId}`)) return row\n }\n return null\n}\n\nfunction expandCollapsedSummaries(document: DocumentLike): void {\n const rows = document.querySelectorAll('tr[data-collapsed-summary]')\n for (let index = 0; index < rows.length; index += 1) {\n const row = rows[index]\n if (typeof row.click === 'function') row.click()\n }\n}\n\nfunction waitForNextFrame(): Promise<void> {\n return new Promise((resolve) => {\n if (typeof requestAnimationFrame === 'function') {\n requestAnimationFrame(() => resolve())\n } else {\n resolve()\n }\n })\n}\n\n/**\n * Jump to the nearest rendered row for a fold item. Returns the outcome and\n * reports paging progress through onProgress.\n */\nexport async function jumpToItem(\n session: SessionFace,\n item: JumpTarget,\n options: JumpOptions,\n): Promise<JumpOutcome> {\n const guard = Number.isFinite(Number(options.guard)) && (options.guard ?? 0) > 0\n ? Math.min(500, Math.max(1, Math.floor(options.guard ?? 200)))\n : 200\n const document = options.document\n\n try {\n let snapshot = session.getSnapshot()\n const trajectoryActive = isTrajectoryViewActive(document)\n\n if (trajectoryActive) {\n let key = trajectoryRecordIdFor(item, snapshot)\n let row = key === null ? null : findTrajectoryRow(document, key)\n let pages = 0\n if (row === null && snapshot.hasMore === true) {\n while (snapshot.hasMore === true && pages < guard) {\n await session.loadOlder()\n snapshot = session.getSnapshot()\n pages += 1\n options.onProgress?.(pages)\n }\n key = trajectoryRecordIdFor(item, snapshot)\n row = key === null ? null : findTrajectoryRow(document, key)\n }\n if (row === null) {\n expandCollapsedSummaries(document)\n await waitForNextFrame()\n row = key === null ? null : findTrajectoryRow(document, key)\n }\n if (row === null) {\n row = findTrajectoryRowBySeq(document, item)\n }\n if (row === null) return { ok: false, error: 'trajectory-row-not-rendered' }\n row.scrollIntoView({ behavior: 'smooth', block: 'center' })\n return { ok: true, mode: 'trajectory' }\n }\n\n // Chat view: load older pages until the target is in the window.\n let pages = 0\n while (snapshot.hasMore === true && !hasSeqInWindow(snapshot, item.seq) && pages < guard) {\n await session.loadOlder()\n snapshot = session.getSnapshot()\n pages += 1\n options.onProgress?.(pages)\n }\n const node = findNodeForSeq(snapshot, item.seq)\n if (node === null) return { ok: false, error: 'seq-not-rendered' }\n // After loadOlder() the session data updates immediately, but the chat\n // DOM commits a tick later \u2014 give the freshly loaded row a few frames to\n // mount before declaring failure. (Without this the FIRST attempt used to\n // report \"cannot locate\" and the user had to click a second time.)\n const selector = `[data-chat-anchor-key=\"${cssEscape(node.key)}\"]`\n let row = document.querySelector(selector)\n let retries = 0\n while (row === null && retries < 6) {\n await waitForNextFrame()\n row = document.querySelector(selector)\n retries += 1\n }\n if (row === null) return { ok: false, error: 'row-not-in-chat-view' }\n row.scrollIntoView({ behavior: 'smooth', block: 'center' })\n if (row.classList !== undefined && typeof row.classList.add === 'function') {\n row.classList.add('ttl-flash')\n }\n return { ok: true, mode: 'chat' }\n } catch (reason) {\n return { ok: false, error: reason instanceof Error ? reason.message : String(reason) }\n }\n}\n\nfunction cssEscape(value: string): string {\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') return CSS.escape(value)\n return value.replace(/[\"\\\\]/g, '\\\\$&')\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,IAAAA,SAAuB;;;ACQhB,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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",
|
|
6
|
+
"names": ["React", "React", "out", "document", "row", "pages", "TurnRow", "next"]
|
|
7
|
+
}
|