@shipfox/client-logs 6.0.2 → 12.0.1
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +17 -0
- package/dist/components/agent-session-rows.d.ts +2 -1
- package/dist/components/agent-session-rows.d.ts.map +1 -1
- package/dist/components/agent-session-rows.js +64 -46
- package/dist/components/agent-session-rows.js.map +1 -1
- package/dist/components/log-view.js +18 -11
- package/dist/components/log-view.js.map +1 -1
- package/dist/core/log-model.d.ts +1 -0
- package/dist/core/log-model.d.ts.map +1 -1
- package/dist/core/log-model.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/components/agent-session-rows.tsx +33 -7
- package/src/components/log-view.stories.tsx +44 -0
- package/src/components/log-view.test.tsx +20 -1
- package/src/components/log-view.tsx +24 -11
- package/src/core/log-model.ts +8 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/vercel.json +1 -3
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
$ shipfox-swc
|
|
2
|
-
Successfully compiled: 13 files with swc (
|
|
2
|
+
Successfully compiled: 13 files with swc (251.76ms)
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @shipfox/client-logs
|
|
2
2
|
|
|
3
|
+
## 12.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 57e69d8: Preserve and display Claude tool-use summaries on their matching tool-call rows.
|
|
8
|
+
- Updated dependencies [57e69d8]
|
|
9
|
+
- @shipfox/api-logs-dto@10.2.0
|
|
10
|
+
|
|
11
|
+
## 11.0.0
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 38a4635: Names Claude tool-result rows from their matching tool calls and marks unmatched results explicitly.
|
|
16
|
+
- @shipfox/api-logs-dto@9.0.2
|
|
17
|
+
- @shipfox/client-api@6.0.1
|
|
18
|
+
- @shipfox/react-ui@0.3.7
|
|
19
|
+
|
|
3
20
|
## 6.0.2
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -2,7 +2,8 @@ import type { SessionViewRow } from '#core/log-model.js';
|
|
|
2
2
|
export interface AgentSessionRowsProps {
|
|
3
3
|
rows: readonly SessionViewRow[];
|
|
4
4
|
resolvedToolCallIds: ReadonlySet<string>;
|
|
5
|
+
toolCallNames: ReadonlyMap<string, string>;
|
|
5
6
|
indent: number;
|
|
6
7
|
}
|
|
7
|
-
export declare function AgentSessionRows({ rows, resolvedToolCallIds, indent }: AgentSessionRowsProps): import("react").JSX.Element[];
|
|
8
|
+
export declare function AgentSessionRows({ rows, resolvedToolCallIds, toolCallNames, indent, }: AgentSessionRowsProps): import("react").JSX.Element[];
|
|
8
9
|
//# sourceMappingURL=agent-session-rows.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-session-rows.d.ts","sourceRoot":"","sources":["../../src/components/agent-session-rows.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,cAAc,EAAqB,MAAM,oBAAoB,CAAC;AAO3E,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,SAAS,cAAc,EAAE,CAAC;IAChC,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"agent-session-rows.d.ts","sourceRoot":"","sources":["../../src/components/agent-session-rows.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,cAAc,EAAqB,MAAM,oBAAoB,CAAC;AAO3E,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,SAAS,cAAc,EAAE,CAAC;IAChC,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,mBAAmB,EACnB,aAAa,EACb,MAAM,GACP,EAAE,qBAAqB,iCAWvB"}
|
|
@@ -9,14 +9,15 @@ const PREVIEW_CHAR_LIMIT = 1200;
|
|
|
9
9
|
const WORD_SUMMARY_CHAR_LIMIT = 5000;
|
|
10
10
|
const WHITESPACE = /\s+/g;
|
|
11
11
|
const WORD_SEPARATOR = /\s+/;
|
|
12
|
-
export function AgentSessionRows({ rows, resolvedToolCallIds, indent }) {
|
|
12
|
+
export function AgentSessionRows({ rows, resolvedToolCallIds, toolCallNames, indent }) {
|
|
13
13
|
return rows.map((row, index)=>/*#__PURE__*/ _jsx(AgentSessionRowView, {
|
|
14
14
|
row: row,
|
|
15
15
|
resolvedToolCallIds: resolvedToolCallIds,
|
|
16
|
+
toolCallNames: toolCallNames,
|
|
16
17
|
indent: indent
|
|
17
18
|
}, `${row.kind}-${index}`));
|
|
18
19
|
}
|
|
19
|
-
function AgentSessionRowView({ row, resolvedToolCallIds, indent }) {
|
|
20
|
+
function AgentSessionRowView({ row, resolvedToolCallIds, toolCallNames, indent }) {
|
|
20
21
|
switch(row.kind){
|
|
21
22
|
case 'message':
|
|
22
23
|
return /*#__PURE__*/ _jsx(LogRow, {
|
|
@@ -91,7 +92,7 @@ function AgentSessionRowView({ row, resolvedToolCallIds, indent }) {
|
|
|
91
92
|
children: [
|
|
92
93
|
/*#__PURE__*/ _jsx(LogDisclosureTrigger, {
|
|
93
94
|
timestamp: new Date(row.timestamp),
|
|
94
|
-
summary: compactPreview(row.input),
|
|
95
|
+
summary: compactPreview(row.summary ?? row.input),
|
|
95
96
|
trailing: awaitingResult ? /*#__PURE__*/ _jsxs("span", {
|
|
96
97
|
className: "inline-flex items-center gap-4",
|
|
97
98
|
children: [
|
|
@@ -122,7 +123,21 @@ function AgentSessionRowView({ row, resolvedToolCallIds, indent }) {
|
|
|
122
123
|
})
|
|
123
124
|
}),
|
|
124
125
|
/*#__PURE__*/ _jsx(LogDisclosureContent, {
|
|
125
|
-
children: /*#__PURE__*/
|
|
126
|
+
children: row.summary != null ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
127
|
+
children: [
|
|
128
|
+
/*#__PURE__*/ _jsx(LogContent, {
|
|
129
|
+
children: /*#__PURE__*/ _jsx(PreviewText, {
|
|
130
|
+
text: row.summary
|
|
131
|
+
})
|
|
132
|
+
}),
|
|
133
|
+
/*#__PURE__*/ _jsx(LogContent, {
|
|
134
|
+
variant: "code",
|
|
135
|
+
children: /*#__PURE__*/ _jsx(PreviewText, {
|
|
136
|
+
text: row.input
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
]
|
|
140
|
+
}) : /*#__PURE__*/ _jsx(LogContent, {
|
|
126
141
|
variant: "code",
|
|
127
142
|
children: /*#__PURE__*/ _jsx(PreviewText, {
|
|
128
143
|
text: row.input
|
|
@@ -133,52 +148,55 @@ function AgentSessionRowView({ row, resolvedToolCallIds, indent }) {
|
|
|
133
148
|
});
|
|
134
149
|
}
|
|
135
150
|
case 'tool-result':
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
{
|
|
152
|
+
const toolName = row.toolName === 'tool' ? (row.toolCallId != null ? toolCallNames.get(row.toolCallId) : undefined) ?? '(unmatched)' : row.toolName;
|
|
153
|
+
return /*#__PURE__*/ _jsxs(LogDisclosure, {
|
|
154
|
+
indent: indent,
|
|
155
|
+
children: [
|
|
156
|
+
/*#__PURE__*/ _jsx(LogDisclosureTrigger, {
|
|
157
|
+
timestamp: new Date(row.timestamp),
|
|
158
|
+
summary: compactPreview(row.output),
|
|
159
|
+
trailing: /*#__PURE__*/ _jsxs("span", {
|
|
160
|
+
className: cn('inline-flex items-center gap-4', row.isError ? 'text-red-600 dark:text-red-400' : 'text-foreground-neutral-muted'),
|
|
161
|
+
children: [
|
|
162
|
+
/*#__PURE__*/ _jsx(Icon, {
|
|
163
|
+
name: row.isError ? 'closeCircleLine' : 'checkLine',
|
|
164
|
+
className: "size-12",
|
|
165
|
+
"aria-hidden": "true"
|
|
166
|
+
}),
|
|
167
|
+
row.isError ? 'error' : 'ok'
|
|
168
|
+
]
|
|
169
|
+
}),
|
|
170
|
+
children: /*#__PURE__*/ _jsxs("span", {
|
|
171
|
+
className: "inline-flex min-w-0 items-center gap-6",
|
|
172
|
+
children: [
|
|
173
|
+
/*#__PURE__*/ _jsx(Icon, {
|
|
174
|
+
name: "terminalWindowLine",
|
|
175
|
+
className: "size-14 flex-none",
|
|
176
|
+
"aria-hidden": "true"
|
|
177
|
+
}),
|
|
178
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
179
|
+
className: "truncate",
|
|
180
|
+
children: [
|
|
181
|
+
"result ",
|
|
182
|
+
toolName
|
|
183
|
+
]
|
|
184
|
+
})
|
|
185
|
+
]
|
|
186
|
+
})
|
|
152
187
|
}),
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
"aria-hidden": "true"
|
|
160
|
-
}),
|
|
161
|
-
/*#__PURE__*/ _jsxs("span", {
|
|
162
|
-
className: "truncate",
|
|
163
|
-
children: [
|
|
164
|
-
"result ",
|
|
165
|
-
row.toolName
|
|
166
|
-
]
|
|
188
|
+
/*#__PURE__*/ _jsx(LogDisclosureContent, {
|
|
189
|
+
children: /*#__PURE__*/ _jsx(LogContent, {
|
|
190
|
+
variant: "code",
|
|
191
|
+
className: cn(row.isError && 'text-red-600 dark:text-red-400'),
|
|
192
|
+
children: /*#__PURE__*/ _jsx(PreviewText, {
|
|
193
|
+
text: row.output
|
|
167
194
|
})
|
|
168
|
-
]
|
|
169
|
-
})
|
|
170
|
-
}),
|
|
171
|
-
/*#__PURE__*/ _jsx(LogDisclosureContent, {
|
|
172
|
-
children: /*#__PURE__*/ _jsx(LogContent, {
|
|
173
|
-
variant: "code",
|
|
174
|
-
className: cn(row.isError && 'text-red-600 dark:text-red-400'),
|
|
175
|
-
children: /*#__PURE__*/ _jsx(PreviewText, {
|
|
176
|
-
text: row.output
|
|
177
195
|
})
|
|
178
196
|
})
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
197
|
+
]
|
|
198
|
+
});
|
|
199
|
+
}
|
|
182
200
|
case 'lifecycle':
|
|
183
201
|
return /*#__PURE__*/ _jsx(LogRow, {
|
|
184
202
|
lineNumber: null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/agent-session-rows.tsx"],"sourcesContent":["'use client';\n\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {\n LogContent,\n LogDisclosure,\n LogDisclosureContent,\n LogDisclosureTrigger,\n LogRow,\n} from '@shipfox/react-ui/log';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {Fragment, useState} from 'react';\nimport type {SessionViewRow, SessionViewRowMeta} from '#core/log-model.js';\n\nconst PREVIEW_CHAR_LIMIT = 1200;\nconst WORD_SUMMARY_CHAR_LIMIT = 5000;\nconst WHITESPACE = /\\s+/g;\nconst WORD_SEPARATOR = /\\s+/;\n\nexport interface AgentSessionRowsProps {\n rows: readonly SessionViewRow[];\n resolvedToolCallIds: ReadonlySet<string>;\n indent: number;\n}\n\nexport function AgentSessionRows({rows, resolvedToolCallIds, indent}: AgentSessionRowsProps) {\n return rows.map((row, index) => (\n <AgentSessionRowView\n // biome-ignore lint/suspicious/noArrayIndexKey: session rows are immutable and never reordered, so the index is stable; content keys would balloon to megabyte strings and collide on repeated id-less tool calls.\n key={`${row.kind}-${index}`}\n row={row}\n resolvedToolCallIds={resolvedToolCallIds}\n indent={indent}\n />\n ));\n}\n\nfunction AgentSessionRowView({\n row,\n resolvedToolCallIds,\n indent,\n}: {\n row: SessionViewRow;\n resolvedToolCallIds: ReadonlySet<string>;\n indent: number;\n}) {\n switch (row.kind) {\n case 'message':\n return (\n <LogRow\n lineNumber={null}\n timestamp={new Date(row.timestamp)}\n indent={indent}\n tone={row.terminalFailure ? 'error' : 'default'}\n data-log-terminal-failure={row.terminalFailure ? 'true' : undefined}\n >\n <LogContent className=\"text-foreground-neutral-base\">\n <span className=\"flex min-w-0 items-start gap-8\">\n <MessageIcon role={row.role} terminalFailure={row.terminalFailure} />\n <span className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <span className=\"flex min-w-0 items-center gap-8\">\n <MessageRoleLabel label={row.label} terminalFailure={row.terminalFailure} />\n <RowMetadata meta={row.meta} className=\"ml-auto flex-none\" />\n </span>\n <span className=\"block min-w-0\">\n <PreviewText text={row.text} />\n </span>\n </span>\n </span>\n </LogContent>\n </LogRow>\n );\n case 'thinking':\n return (\n <LogDisclosure indent={indent}>\n <LogDisclosureTrigger\n summary={wordSummary(row.text)}\n timestamp={new Date(row.timestamp)}\n className=\"text-foreground-neutral-subtle\"\n >\n thinking\n </LogDisclosureTrigger>\n <LogDisclosureContent className=\"text-foreground-neutral-subtle\">\n <LogContent className=\"text-foreground-neutral-subtle\">\n <PreviewText text={row.text} />\n </LogContent>\n </LogDisclosureContent>\n </LogDisclosure>\n );\n case 'tool-call': {\n const awaitingResult = row.id != null && !resolvedToolCallIds.has(row.id);\n return (\n <LogDisclosure indent={indent}>\n <LogDisclosureTrigger\n timestamp={new Date(row.timestamp)}\n summary={compactPreview(row.input)}\n trailing={\n awaitingResult ? (\n <span className=\"inline-flex items-center gap-4\">\n <Icon\n name=\"loader4Line\"\n className=\"size-12 motion-safe:animate-spin\"\n aria-hidden=\"true\"\n />\n awaiting result\n </span>\n ) : null\n }\n >\n <span className=\"inline-flex min-w-0 items-center gap-6\">\n <Icon name=\"terminalBoxLine\" className=\"size-14 flex-none\" aria-hidden=\"true\" />\n <span className=\"truncate\">tool {row.name}</span>\n </span>\n </LogDisclosureTrigger>\n <LogDisclosureContent>\n <LogContent variant=\"code\">\n <PreviewText text={row.input} />\n </LogContent>\n </LogDisclosureContent>\n </LogDisclosure>\n );\n }\n case 'tool-result':\n return (\n <LogDisclosure indent={indent}>\n <LogDisclosureTrigger\n timestamp={new Date(row.timestamp)}\n summary={compactPreview(row.output)}\n trailing={\n <span\n className={cn(\n 'inline-flex items-center gap-4',\n row.isError ? 'text-red-600 dark:text-red-400' : 'text-foreground-neutral-muted',\n )}\n >\n <Icon\n name={row.isError ? 'closeCircleLine' : 'checkLine'}\n className=\"size-12\"\n aria-hidden=\"true\"\n />\n {row.isError ? 'error' : 'ok'}\n </span>\n }\n >\n <span className=\"inline-flex min-w-0 items-center gap-6\">\n <Icon name=\"terminalWindowLine\" className=\"size-14 flex-none\" aria-hidden=\"true\" />\n <span className=\"truncate\">result {row.toolName}</span>\n </span>\n </LogDisclosureTrigger>\n <LogDisclosureContent>\n <LogContent\n variant=\"code\"\n className={cn(row.isError && 'text-red-600 dark:text-red-400')}\n >\n <PreviewText text={row.output} />\n </LogContent>\n </LogDisclosureContent>\n </LogDisclosure>\n );\n case 'lifecycle':\n return (\n <LogRow\n lineNumber={null}\n timestamp={new Date(row.timestamp)}\n indent={indent}\n tone={row.tone}\n data-log-terminal-failure={row.terminalFailure ? 'true' : undefined}\n >\n <LogContent className=\"text-foreground-neutral-muted\">\n <span className=\"inline-flex w-full items-center gap-8\">\n <Icon name=\"informationLine\" className=\"size-14 flex-none\" aria-hidden=\"true\" />\n <span className=\"min-w-0\">\n <span className=\"font-medium\">{row.label}</span>\n {row.detail != null ? (\n <>\n {' · '}\n <span className=\"text-foreground-neutral-subtle\">{row.detail}</span>\n </>\n ) : null}\n </span>\n <span\n aria-hidden=\"true\"\n className=\"h-px flex-1 border-t border-dashed border-current opacity-30\"\n />\n <RowMetadata meta={row.meta} />\n </span>\n </LogContent>\n </LogRow>\n );\n case 'raw':\n return (\n <LogDisclosure indent={indent}>\n <LogDisclosureTrigger\n timestamp={new Date(row.timestamp)}\n summary={compactPreview(row.raw)}\n className=\"text-orange-600 dark:text-orange-400\"\n >\n <span className=\"inline-flex min-w-0 items-center gap-6\">\n <Icon name=\"errorWarningLine\" className=\"size-14 flex-none\" aria-hidden=\"true\" />\n <span className=\"truncate\">{row.label}</span>\n </span>\n </LogDisclosureTrigger>\n <LogDisclosureContent>\n <LogContent variant=\"code\">\n <PreviewText text={row.raw} />\n </LogContent>\n </LogDisclosureContent>\n </LogDisclosure>\n );\n default:\n return assertNever(row);\n }\n}\n\nfunction MessageIcon({role, terminalFailure}: {role: string; terminalFailure: boolean}) {\n const name = terminalFailure\n ? 'closeCircleLine'\n : role === 'user'\n ? 'userLine'\n : role === 'assistant'\n ? 'robot2Line'\n : 'message2Line';\n\n return (\n <Icon\n name={name}\n className={cn(\n 'mt-2 size-14 flex-none',\n terminalFailure ? 'text-red-600 dark:text-red-400' : 'text-foreground-neutral-muted',\n )}\n aria-hidden=\"true\"\n />\n );\n}\n\nfunction MessageRoleLabel({label, terminalFailure}: {label: string; terminalFailure: boolean}) {\n return (\n <span\n className={cn(\n 'min-w-0 font-code text-foreground-neutral-muted',\n terminalFailure && 'text-foreground-highlight-error',\n )}\n >\n <span className=\"truncate\">{label}</span>\n </span>\n );\n}\n\nfunction RowMetadata({meta, className}: {meta: readonly SessionViewRowMeta[]; className?: string}) {\n if (meta.length === 0) return null;\n\n const inlineMeta = meta.length === 1 && meta[0]?.inline !== false ? meta[0] : null;\n if (inlineMeta != null) {\n return (\n <span\n className={cn('font-code text-xs text-foreground-neutral-muted', className)}\n title={`${inlineMeta.label}: ${inlineMeta.value}`}\n >\n {inlineMeta.value}\n </span>\n );\n }\n\n return (\n <span className={className}>\n <MetadataTrigger meta={meta} />\n </span>\n );\n}\n\nfunction MetadataTrigger({meta}: {meta: readonly SessionViewRowMeta[]}) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex size-20 flex-none items-center justify-center rounded-4 text-foreground-neutral-muted opacity-60 transition-opacity hover:bg-background-components-hover hover:text-foreground-neutral-base hover:opacity-100 focus-visible:opacity-100 focus-visible:shadow-[inset_0_0_0_2px_var(--color-primary-500)] group-hover/log-row:opacity-100\"\n aria-label=\"Show message metadata\"\n >\n <Icon name=\"informationLine\" className=\"size-12\" aria-hidden=\"true\" />\n </button>\n </TooltipTrigger>\n <TooltipContent align=\"end\" variant=\"inverted\" className=\"max-w-360 px-8 py-6\">\n <span className=\"grid grid-cols-[max-content_minmax(0,1fr)] gap-x-8 gap-y-2 font-code text-xs\">\n {meta.map((item) => (\n <Fragment key={`${item.label}-${item.value}`}>\n <span className=\"text-foreground-contrast-secondary\">{item.label}</span>\n <span className=\"min-w-0 break-all text-foreground-contrast-primary\">\n {item.value}\n </span>\n </Fragment>\n ))}\n </span>\n </TooltipContent>\n </Tooltip>\n );\n}\n\nfunction PreviewText({text}: {text: string}) {\n const [expanded, setExpanded] = useState(false);\n const truncated = text.length > PREVIEW_CHAR_LIMIT;\n const visible = truncated && !expanded ? `${text.slice(0, PREVIEW_CHAR_LIMIT)}…` : text;\n\n return (\n <>\n {visible}\n {truncated ? (\n <button\n type=\"button\"\n aria-expanded={expanded}\n className=\"ml-8 inline-flex min-h-24 items-center rounded-4 px-6 font-display text-xs text-foreground-highlight-interactive focus-visible:shadow-[inset_0_0_0_2px_var(--color-primary-500)]\"\n onClick={() => setExpanded((value) => !value)}\n >\n {expanded ? 'show less' : 'show more'}\n </button>\n ) : null}\n </>\n );\n}\n\nfunction compactPreview(value: string): string {\n // Normalize only a bounded head: tool output can be megabytes, and this runs\n // per render for every disclosure trigger.\n const head = value.length > 200 ? value.slice(0, 200) : value;\n const singleLine = head.replace(WHITESPACE, ' ').trim();\n if (singleLine.length <= 80) return singleLine;\n return `${singleLine.slice(0, 80)}…`;\n}\n\nfunction wordSummary(value: string): string {\n const truncated = value.length > WORD_SUMMARY_CHAR_LIMIT;\n const head = truncated ? value.slice(0, WORD_SUMMARY_CHAR_LIMIT) : value;\n const count = head.trim().split(WORD_SEPARATOR).filter(Boolean).length;\n const marker = truncated ? '+' : '';\n return `${count}${marker} ${count === 1 ? 'word' : 'words'}`;\n}\n\nfunction assertNever(value: never): never {\n throw new Error(`unexpected agent session row: ${JSON.stringify(value)}`);\n}\n"],"names":["Icon","LogContent","LogDisclosure","LogDisclosureContent","LogDisclosureTrigger","LogRow","Tooltip","TooltipContent","TooltipTrigger","cn","Fragment","useState","PREVIEW_CHAR_LIMIT","WORD_SUMMARY_CHAR_LIMIT","WHITESPACE","WORD_SEPARATOR","AgentSessionRows","rows","resolvedToolCallIds","indent","map","row","index","AgentSessionRowView","kind","lineNumber","timestamp","Date","tone","terminalFailure","data-log-terminal-failure","undefined","className","span","MessageIcon","role","MessageRoleLabel","label","RowMetadata","meta","PreviewText","text","summary","wordSummary","awaitingResult","id","has","compactPreview","input","trailing","name","aria-hidden","variant","output","isError","toolName","detail","raw","assertNever","length","inlineMeta","inline","title","value","MetadataTrigger","asChild","button","type","aria-label","align","item","expanded","setExpanded","truncated","visible","slice","aria-expanded","onClick","head","singleLine","replace","trim","count","split","filter","Boolean","marker","Error","JSON","stringify"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/components/agent-session-rows.tsx"],"sourcesContent":["'use client';\n\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {\n LogContent,\n LogDisclosure,\n LogDisclosureContent,\n LogDisclosureTrigger,\n LogRow,\n} from '@shipfox/react-ui/log';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {Fragment, useState} from 'react';\nimport type {SessionViewRow, SessionViewRowMeta} from '#core/log-model.js';\n\nconst PREVIEW_CHAR_LIMIT = 1200;\nconst WORD_SUMMARY_CHAR_LIMIT = 5000;\nconst WHITESPACE = /\\s+/g;\nconst WORD_SEPARATOR = /\\s+/;\n\nexport interface AgentSessionRowsProps {\n rows: readonly SessionViewRow[];\n resolvedToolCallIds: ReadonlySet<string>;\n toolCallNames: ReadonlyMap<string, string>;\n indent: number;\n}\n\nexport function AgentSessionRows({\n rows,\n resolvedToolCallIds,\n toolCallNames,\n indent,\n}: AgentSessionRowsProps) {\n return rows.map((row, index) => (\n <AgentSessionRowView\n // biome-ignore lint/suspicious/noArrayIndexKey: session rows are immutable and never reordered, so the index is stable; content keys would balloon to megabyte strings and collide on repeated id-less tool calls.\n key={`${row.kind}-${index}`}\n row={row}\n resolvedToolCallIds={resolvedToolCallIds}\n toolCallNames={toolCallNames}\n indent={indent}\n />\n ));\n}\n\nfunction AgentSessionRowView({\n row,\n resolvedToolCallIds,\n toolCallNames,\n indent,\n}: {\n row: SessionViewRow;\n resolvedToolCallIds: ReadonlySet<string>;\n toolCallNames: ReadonlyMap<string, string>;\n indent: number;\n}) {\n switch (row.kind) {\n case 'message':\n return (\n <LogRow\n lineNumber={null}\n timestamp={new Date(row.timestamp)}\n indent={indent}\n tone={row.terminalFailure ? 'error' : 'default'}\n data-log-terminal-failure={row.terminalFailure ? 'true' : undefined}\n >\n <LogContent className=\"text-foreground-neutral-base\">\n <span className=\"flex min-w-0 items-start gap-8\">\n <MessageIcon role={row.role} terminalFailure={row.terminalFailure} />\n <span className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <span className=\"flex min-w-0 items-center gap-8\">\n <MessageRoleLabel label={row.label} terminalFailure={row.terminalFailure} />\n <RowMetadata meta={row.meta} className=\"ml-auto flex-none\" />\n </span>\n <span className=\"block min-w-0\">\n <PreviewText text={row.text} />\n </span>\n </span>\n </span>\n </LogContent>\n </LogRow>\n );\n case 'thinking':\n return (\n <LogDisclosure indent={indent}>\n <LogDisclosureTrigger\n summary={wordSummary(row.text)}\n timestamp={new Date(row.timestamp)}\n className=\"text-foreground-neutral-subtle\"\n >\n thinking\n </LogDisclosureTrigger>\n <LogDisclosureContent className=\"text-foreground-neutral-subtle\">\n <LogContent className=\"text-foreground-neutral-subtle\">\n <PreviewText text={row.text} />\n </LogContent>\n </LogDisclosureContent>\n </LogDisclosure>\n );\n case 'tool-call': {\n const awaitingResult = row.id != null && !resolvedToolCallIds.has(row.id);\n return (\n <LogDisclosure indent={indent}>\n <LogDisclosureTrigger\n timestamp={new Date(row.timestamp)}\n summary={compactPreview(row.summary ?? row.input)}\n trailing={\n awaitingResult ? (\n <span className=\"inline-flex items-center gap-4\">\n <Icon\n name=\"loader4Line\"\n className=\"size-12 motion-safe:animate-spin\"\n aria-hidden=\"true\"\n />\n awaiting result\n </span>\n ) : null\n }\n >\n <span className=\"inline-flex min-w-0 items-center gap-6\">\n <Icon name=\"terminalBoxLine\" className=\"size-14 flex-none\" aria-hidden=\"true\" />\n <span className=\"truncate\">tool {row.name}</span>\n </span>\n </LogDisclosureTrigger>\n <LogDisclosureContent>\n {row.summary != null ? (\n <>\n <LogContent>\n <PreviewText text={row.summary} />\n </LogContent>\n <LogContent variant=\"code\">\n <PreviewText text={row.input} />\n </LogContent>\n </>\n ) : (\n <LogContent variant=\"code\">\n <PreviewText text={row.input} />\n </LogContent>\n )}\n </LogDisclosureContent>\n </LogDisclosure>\n );\n }\n case 'tool-result': {\n const toolName =\n row.toolName === 'tool'\n ? ((row.toolCallId != null ? toolCallNames.get(row.toolCallId) : undefined) ??\n '(unmatched)')\n : row.toolName;\n return (\n <LogDisclosure indent={indent}>\n <LogDisclosureTrigger\n timestamp={new Date(row.timestamp)}\n summary={compactPreview(row.output)}\n trailing={\n <span\n className={cn(\n 'inline-flex items-center gap-4',\n row.isError ? 'text-red-600 dark:text-red-400' : 'text-foreground-neutral-muted',\n )}\n >\n <Icon\n name={row.isError ? 'closeCircleLine' : 'checkLine'}\n className=\"size-12\"\n aria-hidden=\"true\"\n />\n {row.isError ? 'error' : 'ok'}\n </span>\n }\n >\n <span className=\"inline-flex min-w-0 items-center gap-6\">\n <Icon name=\"terminalWindowLine\" className=\"size-14 flex-none\" aria-hidden=\"true\" />\n <span className=\"truncate\">result {toolName}</span>\n </span>\n </LogDisclosureTrigger>\n <LogDisclosureContent>\n <LogContent\n variant=\"code\"\n className={cn(row.isError && 'text-red-600 dark:text-red-400')}\n >\n <PreviewText text={row.output} />\n </LogContent>\n </LogDisclosureContent>\n </LogDisclosure>\n );\n }\n case 'lifecycle':\n return (\n <LogRow\n lineNumber={null}\n timestamp={new Date(row.timestamp)}\n indent={indent}\n tone={row.tone}\n data-log-terminal-failure={row.terminalFailure ? 'true' : undefined}\n >\n <LogContent className=\"text-foreground-neutral-muted\">\n <span className=\"inline-flex w-full items-center gap-8\">\n <Icon name=\"informationLine\" className=\"size-14 flex-none\" aria-hidden=\"true\" />\n <span className=\"min-w-0\">\n <span className=\"font-medium\">{row.label}</span>\n {row.detail != null ? (\n <>\n {' · '}\n <span className=\"text-foreground-neutral-subtle\">{row.detail}</span>\n </>\n ) : null}\n </span>\n <span\n aria-hidden=\"true\"\n className=\"h-px flex-1 border-t border-dashed border-current opacity-30\"\n />\n <RowMetadata meta={row.meta} />\n </span>\n </LogContent>\n </LogRow>\n );\n case 'raw':\n return (\n <LogDisclosure indent={indent}>\n <LogDisclosureTrigger\n timestamp={new Date(row.timestamp)}\n summary={compactPreview(row.raw)}\n className=\"text-orange-600 dark:text-orange-400\"\n >\n <span className=\"inline-flex min-w-0 items-center gap-6\">\n <Icon name=\"errorWarningLine\" className=\"size-14 flex-none\" aria-hidden=\"true\" />\n <span className=\"truncate\">{row.label}</span>\n </span>\n </LogDisclosureTrigger>\n <LogDisclosureContent>\n <LogContent variant=\"code\">\n <PreviewText text={row.raw} />\n </LogContent>\n </LogDisclosureContent>\n </LogDisclosure>\n );\n default:\n return assertNever(row);\n }\n}\n\nfunction MessageIcon({role, terminalFailure}: {role: string; terminalFailure: boolean}) {\n const name = terminalFailure\n ? 'closeCircleLine'\n : role === 'user'\n ? 'userLine'\n : role === 'assistant'\n ? 'robot2Line'\n : 'message2Line';\n\n return (\n <Icon\n name={name}\n className={cn(\n 'mt-2 size-14 flex-none',\n terminalFailure ? 'text-red-600 dark:text-red-400' : 'text-foreground-neutral-muted',\n )}\n aria-hidden=\"true\"\n />\n );\n}\n\nfunction MessageRoleLabel({label, terminalFailure}: {label: string; terminalFailure: boolean}) {\n return (\n <span\n className={cn(\n 'min-w-0 font-code text-foreground-neutral-muted',\n terminalFailure && 'text-foreground-highlight-error',\n )}\n >\n <span className=\"truncate\">{label}</span>\n </span>\n );\n}\n\nfunction RowMetadata({meta, className}: {meta: readonly SessionViewRowMeta[]; className?: string}) {\n if (meta.length === 0) return null;\n\n const inlineMeta = meta.length === 1 && meta[0]?.inline !== false ? meta[0] : null;\n if (inlineMeta != null) {\n return (\n <span\n className={cn('font-code text-xs text-foreground-neutral-muted', className)}\n title={`${inlineMeta.label}: ${inlineMeta.value}`}\n >\n {inlineMeta.value}\n </span>\n );\n }\n\n return (\n <span className={className}>\n <MetadataTrigger meta={meta} />\n </span>\n );\n}\n\nfunction MetadataTrigger({meta}: {meta: readonly SessionViewRowMeta[]}) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex size-20 flex-none items-center justify-center rounded-4 text-foreground-neutral-muted opacity-60 transition-opacity hover:bg-background-components-hover hover:text-foreground-neutral-base hover:opacity-100 focus-visible:opacity-100 focus-visible:shadow-[inset_0_0_0_2px_var(--color-primary-500)] group-hover/log-row:opacity-100\"\n aria-label=\"Show message metadata\"\n >\n <Icon name=\"informationLine\" className=\"size-12\" aria-hidden=\"true\" />\n </button>\n </TooltipTrigger>\n <TooltipContent align=\"end\" variant=\"inverted\" className=\"max-w-360 px-8 py-6\">\n <span className=\"grid grid-cols-[max-content_minmax(0,1fr)] gap-x-8 gap-y-2 font-code text-xs\">\n {meta.map((item) => (\n <Fragment key={`${item.label}-${item.value}`}>\n <span className=\"text-foreground-contrast-secondary\">{item.label}</span>\n <span className=\"min-w-0 break-all text-foreground-contrast-primary\">\n {item.value}\n </span>\n </Fragment>\n ))}\n </span>\n </TooltipContent>\n </Tooltip>\n );\n}\n\nfunction PreviewText({text}: {text: string}) {\n const [expanded, setExpanded] = useState(false);\n const truncated = text.length > PREVIEW_CHAR_LIMIT;\n const visible = truncated && !expanded ? `${text.slice(0, PREVIEW_CHAR_LIMIT)}…` : text;\n\n return (\n <>\n {visible}\n {truncated ? (\n <button\n type=\"button\"\n aria-expanded={expanded}\n className=\"ml-8 inline-flex min-h-24 items-center rounded-4 px-6 font-display text-xs text-foreground-highlight-interactive focus-visible:shadow-[inset_0_0_0_2px_var(--color-primary-500)]\"\n onClick={() => setExpanded((value) => !value)}\n >\n {expanded ? 'show less' : 'show more'}\n </button>\n ) : null}\n </>\n );\n}\n\nfunction compactPreview(value: string): string {\n // Normalize only a bounded head: tool output can be megabytes, and this runs\n // per render for every disclosure trigger.\n const head = value.length > 200 ? value.slice(0, 200) : value;\n const singleLine = head.replace(WHITESPACE, ' ').trim();\n if (singleLine.length <= 80) return singleLine;\n return `${singleLine.slice(0, 80)}…`;\n}\n\nfunction wordSummary(value: string): string {\n const truncated = value.length > WORD_SUMMARY_CHAR_LIMIT;\n const head = truncated ? value.slice(0, WORD_SUMMARY_CHAR_LIMIT) : value;\n const count = head.trim().split(WORD_SEPARATOR).filter(Boolean).length;\n const marker = truncated ? '+' : '';\n return `${count}${marker} ${count === 1 ? 'word' : 'words'}`;\n}\n\nfunction assertNever(value: never): never {\n throw new Error(`unexpected agent session row: ${JSON.stringify(value)}`);\n}\n"],"names":["Icon","LogContent","LogDisclosure","LogDisclosureContent","LogDisclosureTrigger","LogRow","Tooltip","TooltipContent","TooltipTrigger","cn","Fragment","useState","PREVIEW_CHAR_LIMIT","WORD_SUMMARY_CHAR_LIMIT","WHITESPACE","WORD_SEPARATOR","AgentSessionRows","rows","resolvedToolCallIds","toolCallNames","indent","map","row","index","AgentSessionRowView","kind","lineNumber","timestamp","Date","tone","terminalFailure","data-log-terminal-failure","undefined","className","span","MessageIcon","role","MessageRoleLabel","label","RowMetadata","meta","PreviewText","text","summary","wordSummary","awaitingResult","id","has","compactPreview","input","trailing","name","aria-hidden","variant","toolName","toolCallId","get","output","isError","detail","raw","assertNever","length","inlineMeta","inline","title","value","MetadataTrigger","asChild","button","type","aria-label","align","item","expanded","setExpanded","truncated","visible","slice","aria-expanded","onClick","head","singleLine","replace","trim","count","split","filter","Boolean","marker","Error","JSON","stringify"],"mappings":"AAAA;;AAEA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SACEC,UAAU,EACVC,aAAa,EACbC,oBAAoB,EACpBC,oBAAoB,EACpBC,MAAM,QACD,wBAAwB;AAC/B,SAAQC,OAAO,EAAEC,cAAc,EAAEC,cAAc,QAAO,4BAA4B;AAClF,SAAQC,EAAE,QAAO,0BAA0B;AAC3C,SAAQC,QAAQ,EAAEC,QAAQ,QAAO,QAAQ;AAGzC,MAAMC,qBAAqB;AAC3B,MAAMC,0BAA0B;AAChC,MAAMC,aAAa;AACnB,MAAMC,iBAAiB;AASvB,OAAO,SAASC,iBAAiB,EAC/BC,IAAI,EACJC,mBAAmB,EACnBC,aAAa,EACbC,MAAM,EACgB;IACtB,OAAOH,KAAKI,GAAG,CAAC,CAACC,KAAKC,sBACpB,KAACC;YAGCF,KAAKA;YACLJ,qBAAqBA;YACrBC,eAAeA;YACfC,QAAQA;WAJH,GAAGE,IAAIG,IAAI,CAAC,CAAC,EAAEF,OAAO;AAOjC;AAEA,SAASC,oBAAoB,EAC3BF,GAAG,EACHJ,mBAAmB,EACnBC,aAAa,EACbC,MAAM,EAMP;IACC,OAAQE,IAAIG,IAAI;QACd,KAAK;YACH,qBACE,KAACpB;gBACCqB,YAAY;gBACZC,WAAW,IAAIC,KAAKN,IAAIK,SAAS;gBACjCP,QAAQA;gBACRS,MAAMP,IAAIQ,eAAe,GAAG,UAAU;gBACtCC,6BAA2BT,IAAIQ,eAAe,GAAG,SAASE;0BAE1D,cAAA,KAAC/B;oBAAWgC,WAAU;8BACpB,cAAA,MAACC;wBAAKD,WAAU;;0CACd,KAACE;gCAAYC,MAAMd,IAAIc,IAAI;gCAAEN,iBAAiBR,IAAIQ,eAAe;;0CACjE,MAACI;gCAAKD,WAAU;;kDACd,MAACC;wCAAKD,WAAU;;0DACd,KAACI;gDAAiBC,OAAOhB,IAAIgB,KAAK;gDAAER,iBAAiBR,IAAIQ,eAAe;;0DACxE,KAACS;gDAAYC,MAAMlB,IAAIkB,IAAI;gDAAEP,WAAU;;;;kDAEzC,KAACC;wCAAKD,WAAU;kDACd,cAAA,KAACQ;4CAAYC,MAAMpB,IAAIoB,IAAI;;;;;;;;;QAOzC,KAAK;YACH,qBACE,MAACxC;gBAAckB,QAAQA;;kCACrB,KAAChB;wBACCuC,SAASC,YAAYtB,IAAIoB,IAAI;wBAC7Bf,WAAW,IAAIC,KAAKN,IAAIK,SAAS;wBACjCM,WAAU;kCACX;;kCAGD,KAAC9B;wBAAqB8B,WAAU;kCAC9B,cAAA,KAAChC;4BAAWgC,WAAU;sCACpB,cAAA,KAACQ;gCAAYC,MAAMpB,IAAIoB,IAAI;;;;;;QAKrC,KAAK;YAAa;gBAChB,MAAMG,iBAAiBvB,IAAIwB,EAAE,IAAI,QAAQ,CAAC5B,oBAAoB6B,GAAG,CAACzB,IAAIwB,EAAE;gBACxE,qBACE,MAAC5C;oBAAckB,QAAQA;;sCACrB,KAAChB;4BACCuB,WAAW,IAAIC,KAAKN,IAAIK,SAAS;4BACjCgB,SAASK,eAAe1B,IAAIqB,OAAO,IAAIrB,IAAI2B,KAAK;4BAChDC,UACEL,+BACE,MAACX;gCAAKD,WAAU;;kDACd,KAACjC;wCACCmD,MAAK;wCACLlB,WAAU;wCACVmB,eAAY;;oCACZ;;iCAGF;sCAGN,cAAA,MAAClB;gCAAKD,WAAU;;kDACd,KAACjC;wCAAKmD,MAAK;wCAAkBlB,WAAU;wCAAoBmB,eAAY;;kDACvE,MAAClB;wCAAKD,WAAU;;4CAAW;4CAAMX,IAAI6B,IAAI;;;;;;sCAG7C,KAAChD;sCACEmB,IAAIqB,OAAO,IAAI,qBACd;;kDACE,KAAC1C;kDACC,cAAA,KAACwC;4CAAYC,MAAMpB,IAAIqB,OAAO;;;kDAEhC,KAAC1C;wCAAWoD,SAAQ;kDAClB,cAAA,KAACZ;4CAAYC,MAAMpB,IAAI2B,KAAK;;;;+CAIhC,KAAChD;gCAAWoD,SAAQ;0CAClB,cAAA,KAACZ;oCAAYC,MAAMpB,IAAI2B,KAAK;;;;;;YAMxC;QACA,KAAK;YAAe;gBAClB,MAAMK,WACJhC,IAAIgC,QAAQ,KAAK,SACZ,AAAChC,CAAAA,IAAIiC,UAAU,IAAI,OAAOpC,cAAcqC,GAAG,CAAClC,IAAIiC,UAAU,IAAIvB,SAAQ,KACvE,gBACAV,IAAIgC,QAAQ;gBAClB,qBACE,MAACpD;oBAAckB,QAAQA;;sCACrB,KAAChB;4BACCuB,WAAW,IAAIC,KAAKN,IAAIK,SAAS;4BACjCgB,SAASK,eAAe1B,IAAImC,MAAM;4BAClCP,wBACE,MAAChB;gCACCD,WAAWxB,GACT,kCACAa,IAAIoC,OAAO,GAAG,mCAAmC;;kDAGnD,KAAC1D;wCACCmD,MAAM7B,IAAIoC,OAAO,GAAG,oBAAoB;wCACxCzB,WAAU;wCACVmB,eAAY;;oCAEb9B,IAAIoC,OAAO,GAAG,UAAU;;;sCAI7B,cAAA,MAACxB;gCAAKD,WAAU;;kDACd,KAACjC;wCAAKmD,MAAK;wCAAqBlB,WAAU;wCAAoBmB,eAAY;;kDAC1E,MAAClB;wCAAKD,WAAU;;4CAAW;4CAAQqB;;;;;;sCAGvC,KAACnD;sCACC,cAAA,KAACF;gCACCoD,SAAQ;gCACRpB,WAAWxB,GAAGa,IAAIoC,OAAO,IAAI;0CAE7B,cAAA,KAACjB;oCAAYC,MAAMpB,IAAImC,MAAM;;;;;;YAKvC;QACA,KAAK;YACH,qBACE,KAACpD;gBACCqB,YAAY;gBACZC,WAAW,IAAIC,KAAKN,IAAIK,SAAS;gBACjCP,QAAQA;gBACRS,MAAMP,IAAIO,IAAI;gBACdE,6BAA2BT,IAAIQ,eAAe,GAAG,SAASE;0BAE1D,cAAA,KAAC/B;oBAAWgC,WAAU;8BACpB,cAAA,MAACC;wBAAKD,WAAU;;0CACd,KAACjC;gCAAKmD,MAAK;gCAAkBlB,WAAU;gCAAoBmB,eAAY;;0CACvE,MAAClB;gCAAKD,WAAU;;kDACd,KAACC;wCAAKD,WAAU;kDAAeX,IAAIgB,KAAK;;oCACvChB,IAAIqC,MAAM,IAAI,qBACb;;4CACG;0DACD,KAACzB;gDAAKD,WAAU;0DAAkCX,IAAIqC,MAAM;;;yCAE5D;;;0CAEN,KAACzB;gCACCkB,eAAY;gCACZnB,WAAU;;0CAEZ,KAACM;gCAAYC,MAAMlB,IAAIkB,IAAI;;;;;;QAKrC,KAAK;YACH,qBACE,MAACtC;gBAAckB,QAAQA;;kCACrB,KAAChB;wBACCuB,WAAW,IAAIC,KAAKN,IAAIK,SAAS;wBACjCgB,SAASK,eAAe1B,IAAIsC,GAAG;wBAC/B3B,WAAU;kCAEV,cAAA,MAACC;4BAAKD,WAAU;;8CACd,KAACjC;oCAAKmD,MAAK;oCAAmBlB,WAAU;oCAAoBmB,eAAY;;8CACxE,KAAClB;oCAAKD,WAAU;8CAAYX,IAAIgB,KAAK;;;;;kCAGzC,KAACnC;kCACC,cAAA,KAACF;4BAAWoD,SAAQ;sCAClB,cAAA,KAACZ;gCAAYC,MAAMpB,IAAIsC,GAAG;;;;;;QAKpC;YACE,OAAOC,YAAYvC;IACvB;AACF;AAEA,SAASa,YAAY,EAACC,IAAI,EAAEN,eAAe,EAA2C;IACpF,MAAMqB,OAAOrB,kBACT,oBACAM,SAAS,SACP,aACAA,SAAS,cACP,eACA;IAER,qBACE,KAACpC;QACCmD,MAAMA;QACNlB,WAAWxB,GACT,0BACAqB,kBAAkB,mCAAmC;QAEvDsB,eAAY;;AAGlB;AAEA,SAASf,iBAAiB,EAACC,KAAK,EAAER,eAAe,EAA4C;IAC3F,qBACE,KAACI;QACCD,WAAWxB,GACT,mDACAqB,mBAAmB;kBAGrB,cAAA,KAACI;YAAKD,WAAU;sBAAYK;;;AAGlC;AAEA,SAASC,YAAY,EAACC,IAAI,EAAEP,SAAS,EAA4D;IAC/F,IAAIO,KAAKsB,MAAM,KAAK,GAAG,OAAO;IAE9B,MAAMC,aAAavB,KAAKsB,MAAM,KAAK,KAAKtB,IAAI,CAAC,EAAE,EAAEwB,WAAW,QAAQxB,IAAI,CAAC,EAAE,GAAG;IAC9E,IAAIuB,cAAc,MAAM;QACtB,qBACE,KAAC7B;YACCD,WAAWxB,GAAG,mDAAmDwB;YACjEgC,OAAO,GAAGF,WAAWzB,KAAK,CAAC,EAAE,EAAEyB,WAAWG,KAAK,EAAE;sBAEhDH,WAAWG,KAAK;;IAGvB;IAEA,qBACE,KAAChC;QAAKD,WAAWA;kBACf,cAAA,KAACkC;YAAgB3B,MAAMA;;;AAG7B;AAEA,SAAS2B,gBAAgB,EAAC3B,IAAI,EAAwC;IACpE,qBACE,MAAClC;;0BACC,KAACE;gBAAe4D,OAAO;0BACrB,cAAA,KAACC;oBACCC,MAAK;oBACLrC,WAAU;oBACVsC,cAAW;8BAEX,cAAA,KAACvE;wBAAKmD,MAAK;wBAAkBlB,WAAU;wBAAUmB,eAAY;;;;0BAGjE,KAAC7C;gBAAeiE,OAAM;gBAAMnB,SAAQ;gBAAWpB,WAAU;0BACvD,cAAA,KAACC;oBAAKD,WAAU;8BACbO,KAAKnB,GAAG,CAAC,CAACoD,qBACT,MAAC/D;;8CACC,KAACwB;oCAAKD,WAAU;8CAAsCwC,KAAKnC,KAAK;;8CAChE,KAACJ;oCAAKD,WAAU;8CACbwC,KAAKP,KAAK;;;2BAHA,GAAGO,KAAKnC,KAAK,CAAC,CAAC,EAAEmC,KAAKP,KAAK,EAAE;;;;;AAWxD;AAEA,SAASzB,YAAY,EAACC,IAAI,EAAiB;IACzC,MAAM,CAACgC,UAAUC,YAAY,GAAGhE,SAAS;IACzC,MAAMiE,YAAYlC,KAAKoB,MAAM,GAAGlD;IAChC,MAAMiE,UAAUD,aAAa,CAACF,WAAW,GAAGhC,KAAKoC,KAAK,CAAC,GAAGlE,oBAAoB,CAAC,CAAC,GAAG8B;IAEnF,qBACE;;YACGmC;YACAD,0BACC,KAACP;gBACCC,MAAK;gBACLS,iBAAeL;gBACfzC,WAAU;gBACV+C,SAAS,IAAML,YAAY,CAACT,QAAU,CAACA;0BAEtCQ,WAAW,cAAc;iBAE1B;;;AAGV;AAEA,SAAS1B,eAAekB,KAAa;IACnC,6EAA6E;IAC7E,2CAA2C;IAC3C,MAAMe,OAAOf,MAAMJ,MAAM,GAAG,MAAMI,MAAMY,KAAK,CAAC,GAAG,OAAOZ;IACxD,MAAMgB,aAAaD,KAAKE,OAAO,CAACrE,YAAY,KAAKsE,IAAI;IACrD,IAAIF,WAAWpB,MAAM,IAAI,IAAI,OAAOoB;IACpC,OAAO,GAAGA,WAAWJ,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;AACtC;AAEA,SAASlC,YAAYsB,KAAa;IAChC,MAAMU,YAAYV,MAAMJ,MAAM,GAAGjD;IACjC,MAAMoE,OAAOL,YAAYV,MAAMY,KAAK,CAAC,GAAGjE,2BAA2BqD;IACnE,MAAMmB,QAAQJ,KAAKG,IAAI,GAAGE,KAAK,CAACvE,gBAAgBwE,MAAM,CAACC,SAAS1B,MAAM;IACtE,MAAM2B,SAASb,YAAY,MAAM;IACjC,OAAO,GAAGS,QAAQI,OAAO,CAAC,EAAEJ,UAAU,IAAI,SAAS,SAAS;AAC9D;AAEA,SAASxB,YAAYK,KAAY;IAC/B,MAAM,IAAIwB,MAAM,CAAC,8BAA8B,EAAEC,KAAKC,SAAS,CAAC1B,QAAQ;AAC1E"}
|
|
@@ -14,7 +14,7 @@ export function LogView({ records, timestamps = 'off', wrap = false, showLineNum
|
|
|
14
14
|
const tree = useMemo(()=>buildLogTree(records), [
|
|
15
15
|
records
|
|
16
16
|
]);
|
|
17
|
-
const
|
|
17
|
+
const resolvedToolCalls = useMemo(()=>collectResolvedToolCalls(tree.nodes), [
|
|
18
18
|
tree.nodes
|
|
19
19
|
]);
|
|
20
20
|
const noOutputState = getNoOutputState(tree, emptyState);
|
|
@@ -53,7 +53,7 @@ export function LogView({ records, timestamps = 'off', wrap = false, showLineNum
|
|
|
53
53
|
noOutputState ? /*#__PURE__*/ _jsx(NoOutputRow, {
|
|
54
54
|
state: noOutputState
|
|
55
55
|
}) : null,
|
|
56
|
-
renderNodes(tree.nodes, 0, tree, defaultGroupsOpen,
|
|
56
|
+
renderNodes(tree.nodes, 0, tree, defaultGroupsOpen, resolvedToolCalls)
|
|
57
57
|
]
|
|
58
58
|
});
|
|
59
59
|
}
|
|
@@ -140,7 +140,7 @@ function NoOutputRow({ state }) {
|
|
|
140
140
|
})
|
|
141
141
|
});
|
|
142
142
|
}
|
|
143
|
-
function renderNodes(nodes, depth, tree, defaultGroupsOpen,
|
|
143
|
+
function renderNodes(nodes, depth, tree, defaultGroupsOpen, resolvedToolCalls) {
|
|
144
144
|
// `node.seq` is the stable, unique render key (see `LogNodeBase`): a concatenated
|
|
145
145
|
// multi-step/retry stream can repeat a `group_id` or a marker's `(type, ts)` at one
|
|
146
146
|
// level, which a key derived from those fields would collide on.
|
|
@@ -158,7 +158,7 @@ function renderNodes(nodes, depth, tree, defaultGroupsOpen, resolvedToolCallIds)
|
|
|
158
158
|
depth: depth,
|
|
159
159
|
terminated: tree.terminated,
|
|
160
160
|
defaultOpen: defaultGroupsOpen,
|
|
161
|
-
children: renderNodes(node.children, depth + 1, tree, defaultGroupsOpen,
|
|
161
|
+
children: renderNodes(node.children, depth + 1, tree, defaultGroupsOpen, resolvedToolCalls)
|
|
162
162
|
}, node.seq);
|
|
163
163
|
case 'marker':
|
|
164
164
|
return /*#__PURE__*/ _jsx(MarkerRow, {
|
|
@@ -170,7 +170,8 @@ function renderNodes(nodes, depth, tree, defaultGroupsOpen, resolvedToolCallIds)
|
|
|
170
170
|
rows: [
|
|
171
171
|
node.record.row
|
|
172
172
|
],
|
|
173
|
-
resolvedToolCallIds:
|
|
173
|
+
resolvedToolCallIds: resolvedToolCalls.ids,
|
|
174
|
+
toolCallNames: resolvedToolCalls.names,
|
|
174
175
|
indent: depth
|
|
175
176
|
}, node.seq);
|
|
176
177
|
default:
|
|
@@ -178,21 +179,27 @@ function renderNodes(nodes, depth, tree, defaultGroupsOpen, resolvedToolCallIds)
|
|
|
178
179
|
}
|
|
179
180
|
});
|
|
180
181
|
}
|
|
181
|
-
function
|
|
182
|
+
function collectResolvedToolCalls(nodes) {
|
|
182
183
|
const ids = new Set();
|
|
183
|
-
|
|
184
|
-
|
|
184
|
+
const names = new Map();
|
|
185
|
+
collectResolvedToolCallsInto(nodes, ids, names);
|
|
186
|
+
return {
|
|
187
|
+
ids,
|
|
188
|
+
names
|
|
189
|
+
};
|
|
185
190
|
}
|
|
186
|
-
function
|
|
191
|
+
function collectResolvedToolCallsInto(nodes, ids, names) {
|
|
187
192
|
for (const node of nodes){
|
|
188
193
|
switch(node.kind){
|
|
189
194
|
case 'session':
|
|
190
|
-
if (node.record.row.kind === 'tool-
|
|
195
|
+
if (node.record.row.kind === 'tool-call' && node.record.row.id != null) {
|
|
196
|
+
names.set(node.record.row.id, node.record.row.name);
|
|
197
|
+
} else if (node.record.row.kind === 'tool-result' && node.record.row.toolCallId != null) {
|
|
191
198
|
ids.add(node.record.row.toolCallId);
|
|
192
199
|
}
|
|
193
200
|
break;
|
|
194
201
|
case 'group':
|
|
195
|
-
|
|
202
|
+
collectResolvedToolCallsInto(node.children, ids, names);
|
|
196
203
|
break;
|
|
197
204
|
case 'output':
|
|
198
205
|
case 'marker':
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/log-view.tsx"],"sourcesContent":["'use client';\n\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {LogContent, LogRow, LogRows, type LogTimestampMode} from '@shipfox/react-ui/log';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {type ReactNode, type UIEventHandler, useEffect, useMemo, useRef} from 'react';\nimport type {LogRecord} from '#core/log-model.js';\nimport {\n assertNever,\n buildLogTree,\n type LogNode,\n type LogTree,\n type MarkerLogRecord,\n} from '#core/log-tree.js';\nimport {AgentSessionRows} from './agent-session-rows.js';\nimport {LogGroup} from './log-group.js';\nimport {OutputLogRow} from './output-log-row.js';\nimport {CappedMarker, EndMarker, GapMarker, RunnerLostMarker} from './system-markers.js';\n\nexport interface LogViewProps {\n records: readonly LogRecord[];\n timestamps?: LogTimestampMode;\n wrap?: boolean;\n showLineNumbers?: boolean;\n emptyState?: 'complete' | 'pending';\n defaultGroupsOpen?: boolean;\n anchorToFailure?: boolean;\n className?: string | undefined;\n onScroll?: UIEventHandler<HTMLDivElement> | undefined;\n}\n\nexport interface LogViewSkeletonProps\n extends Pick<LogViewProps, 'timestamps' | 'wrap' | 'showLineNumbers' | 'className'> {\n rows?: number;\n}\n\nexport function LogView({\n records,\n timestamps = 'off',\n wrap = false,\n showLineNumbers = true,\n emptyState = 'complete',\n defaultGroupsOpen = false,\n anchorToFailure = false,\n className,\n onScroll,\n}: LogViewProps) {\n const rowsRef = useRef<HTMLDivElement>(null);\n const tree = useMemo(() => buildLogTree(records), [records]);\n const resolvedToolCallIds = useMemo(() => collectResolvedToolCallIds(tree.nodes), [tree.nodes]);\n const noOutputState = getNoOutputState(tree, emptyState);\n const anchorRecordCount = records.length;\n\n useEffect(() => {\n if (!anchorToFailure) return;\n if (anchorRecordCount === 0) return;\n\n const frame = scheduleAnimationFrame(() => {\n const rows = rowsRef.current;\n if (!rows) return;\n\n const failure = rows.querySelector<HTMLElement>('[data-log-terminal-failure=\"true\"]');\n if (failure) {\n failure.scrollIntoView({block: 'center'});\n return;\n }\n\n rows.scrollTop = rows.scrollHeight;\n });\n\n return () => cancelScheduledFrame(frame);\n }, [anchorToFailure, anchorRecordCount]);\n\n return (\n <LogRows\n ref={rowsRef}\n timestamps={timestamps}\n wrap={wrap}\n showLineNumbers={showLineNumbers}\n className={className}\n onScroll={onScroll}\n {...(tree.originTs != null ? {timestampOrigin: new Date(tree.originTs)} : {})}\n >\n {noOutputState ? <NoOutputRow state={noOutputState} /> : null}\n {renderNodes(tree.nodes, 0, tree, defaultGroupsOpen, resolvedToolCallIds)}\n </LogRows>\n );\n}\n\nexport function LogViewSkeleton({\n rows = 5,\n timestamps = 'off',\n wrap = false,\n showLineNumbers = true,\n className,\n}: LogViewSkeletonProps) {\n const widths = ['w-[62%]', 'w-[44%]', 'w-[74%]', 'w-[36%]', 'w-[55%]'];\n const skeletonRows = getSkeletonRows(rows);\n\n return (\n <LogRows\n timestamps={timestamps}\n wrap={wrap}\n showLineNumbers={showLineNumbers}\n className={className}\n role=\"presentation\"\n aria-live=\"off\"\n aria-hidden=\"true\"\n >\n {skeletonRows.map((row) => (\n <LogRow key={row.id} lineNumber={row.lineNumber}>\n <Skeleton\n className={`my-4 h-12 ${widths[(row.lineNumber - 1) % widths.length] ?? 'w-[48%]'}`}\n />\n </LogRow>\n ))}\n </LogRows>\n );\n}\n\nfunction getSkeletonRows(rows: number): {id: string; lineNumber: number}[] {\n return Array.from({length: rows}, (_, index) => {\n const lineNumber = index + 1;\n return {id: `log-view-skeleton-row-${lineNumber}`, lineNumber};\n });\n}\n\nfunction getNoOutputState(\n tree: LogTree,\n emptyState: NonNullable<LogViewProps['emptyState']>,\n): LogViewProps['emptyState'] | null {\n if (tree.nodes.length === 0) return emptyState;\n\n if (tree.lineCount !== 0) return null;\n if (tree.nodes.length !== 1) return null;\n\n const [node] = tree.nodes;\n if (node?.kind === 'marker' && node.record.type === 'end') return 'complete';\n\n return null;\n}\n\nfunction NoOutputRow({state}: {state: NonNullable<LogViewProps['emptyState']>}) {\n const copy =\n state === 'pending'\n ? {\n title: 'No output yet',\n detail: 'New lines will appear here as the step writes them.',\n }\n : {\n title: 'Step produced no output',\n detail: 'This log stream closed without session entries or process output.',\n };\n\n return (\n <LogRow lineNumber={null}>\n <LogContent className=\"text-foreground-neutral-muted\">\n <span className=\"inline-flex min-w-0 items-center gap-8\">\n <Icon name=\"info\" className=\"size-14 flex-none\" aria-hidden=\"true\" />\n <span className=\"min-w-0\">\n <span className=\"font-medium\">{copy.title}</span>\n {' · '}\n <span className=\"text-foreground-neutral-subtle\">{copy.detail}</span>\n </span>\n </span>\n </LogContent>\n </LogRow>\n );\n}\n\nfunction renderNodes(\n nodes: readonly LogNode[],\n depth: number,\n tree: LogTree,\n defaultGroupsOpen: boolean,\n resolvedToolCallIds: ReadonlySet<string>,\n): ReactNode[] {\n // `node.seq` is the stable, unique render key (see `LogNodeBase`): a concatenated\n // multi-step/retry stream can repeat a `group_id` or a marker's `(type, ts)` at one\n // level, which a key derived from those fields would collide on.\n return nodes.map((node): ReactNode => {\n switch (node.kind) {\n case 'output':\n return (\n <OutputLogRow\n key={node.seq}\n record={node.record}\n lineNumber={node.lineNumber}\n indent={depth}\n />\n );\n case 'group':\n return (\n <LogGroup\n key={node.seq}\n node={node}\n depth={depth}\n terminated={tree.terminated}\n defaultOpen={defaultGroupsOpen}\n >\n {renderNodes(node.children, depth + 1, tree, defaultGroupsOpen, resolvedToolCallIds)}\n </LogGroup>\n );\n case 'marker':\n return <MarkerRow key={node.seq} record={node.record} tree={tree} />;\n case 'session':\n return (\n <AgentSessionRows\n key={node.seq}\n rows={[node.record.row]}\n resolvedToolCallIds={resolvedToolCallIds}\n indent={depth}\n />\n );\n default:\n return assertNever(node);\n }\n });\n}\n\nfunction collectResolvedToolCallIds(nodes: readonly LogNode[]): ReadonlySet<string> {\n const ids = new Set<string>();\n collectResolvedToolCallIdsInto(nodes, ids);\n return ids;\n}\n\nfunction collectResolvedToolCallIdsInto(nodes: readonly LogNode[], ids: Set<string>): void {\n for (const node of nodes) {\n switch (node.kind) {\n case 'session':\n if (node.record.row.kind === 'tool-result' && node.record.row.toolCallId != null) {\n ids.add(node.record.row.toolCallId);\n }\n break;\n case 'group':\n collectResolvedToolCallIdsInto(node.children, ids);\n break;\n case 'output':\n case 'marker':\n break;\n default:\n assertNever(node);\n }\n }\n}\n\nfunction scheduleAnimationFrame(callback: FrameRequestCallback): number {\n if (typeof globalThis.requestAnimationFrame === 'function') {\n return globalThis.requestAnimationFrame(callback);\n }\n return window.setTimeout(() => callback(Date.now()), 0);\n}\n\nfunction cancelScheduledFrame(frame: number) {\n if (typeof globalThis.cancelAnimationFrame === 'function') {\n globalThis.cancelAnimationFrame(frame);\n return;\n }\n window.clearTimeout(frame);\n}\n\nfunction MarkerRow({record, tree}: {record: MarkerLogRecord; tree: LogTree}): ReactNode {\n switch (record.type) {\n case 'end':\n return (\n <EndMarker\n record={record}\n lineCount={tree.lineCount}\n durationMs={tree.originTs != null ? record.ts - tree.originTs : null}\n />\n );\n case 'gap':\n return <GapMarker record={record} />;\n case 'capped':\n return <CappedMarker record={record} />;\n case 'runner_lost':\n return <RunnerLostMarker record={record} />;\n default:\n return assertNever(record);\n }\n}\n"],"names":["Icon","LogContent","LogRow","LogRows","Skeleton","useEffect","useMemo","useRef","assertNever","buildLogTree","AgentSessionRows","LogGroup","OutputLogRow","CappedMarker","EndMarker","GapMarker","RunnerLostMarker","LogView","records","timestamps","wrap","showLineNumbers","emptyState","defaultGroupsOpen","anchorToFailure","className","onScroll","rowsRef","tree","resolvedToolCallIds","collectResolvedToolCallIds","nodes","noOutputState","getNoOutputState","anchorRecordCount","length","frame","scheduleAnimationFrame","rows","current","failure","querySelector","scrollIntoView","block","scrollTop","scrollHeight","cancelScheduledFrame","ref","originTs","timestampOrigin","Date","NoOutputRow","state","renderNodes","LogViewSkeleton","widths","skeletonRows","getSkeletonRows","role","aria-live","aria-hidden","map","row","lineNumber","id","Array","from","_","index","lineCount","node","kind","record","type","copy","title","detail","span","name","depth","indent","seq","terminated","defaultOpen","children","MarkerRow","ids","Set","collectResolvedToolCallIdsInto","toolCallId","add","callback","globalThis","requestAnimationFrame","window","setTimeout","now","cancelAnimationFrame","clearTimeout","durationMs","ts"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/components/log-view.tsx"],"sourcesContent":["'use client';\n\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {LogContent, LogRow, LogRows, type LogTimestampMode} from '@shipfox/react-ui/log';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {type ReactNode, type UIEventHandler, useEffect, useMemo, useRef} from 'react';\nimport type {LogRecord} from '#core/log-model.js';\nimport {\n assertNever,\n buildLogTree,\n type LogNode,\n type LogTree,\n type MarkerLogRecord,\n} from '#core/log-tree.js';\nimport {AgentSessionRows} from './agent-session-rows.js';\nimport {LogGroup} from './log-group.js';\nimport {OutputLogRow} from './output-log-row.js';\nimport {CappedMarker, EndMarker, GapMarker, RunnerLostMarker} from './system-markers.js';\n\nexport interface LogViewProps {\n records: readonly LogRecord[];\n timestamps?: LogTimestampMode;\n wrap?: boolean;\n showLineNumbers?: boolean;\n emptyState?: 'complete' | 'pending';\n defaultGroupsOpen?: boolean;\n anchorToFailure?: boolean;\n className?: string | undefined;\n onScroll?: UIEventHandler<HTMLDivElement> | undefined;\n}\n\nexport interface LogViewSkeletonProps\n extends Pick<LogViewProps, 'timestamps' | 'wrap' | 'showLineNumbers' | 'className'> {\n rows?: number;\n}\n\nexport function LogView({\n records,\n timestamps = 'off',\n wrap = false,\n showLineNumbers = true,\n emptyState = 'complete',\n defaultGroupsOpen = false,\n anchorToFailure = false,\n className,\n onScroll,\n}: LogViewProps) {\n const rowsRef = useRef<HTMLDivElement>(null);\n const tree = useMemo(() => buildLogTree(records), [records]);\n const resolvedToolCalls = useMemo(() => collectResolvedToolCalls(tree.nodes), [tree.nodes]);\n const noOutputState = getNoOutputState(tree, emptyState);\n const anchorRecordCount = records.length;\n\n useEffect(() => {\n if (!anchorToFailure) return;\n if (anchorRecordCount === 0) return;\n\n const frame = scheduleAnimationFrame(() => {\n const rows = rowsRef.current;\n if (!rows) return;\n\n const failure = rows.querySelector<HTMLElement>('[data-log-terminal-failure=\"true\"]');\n if (failure) {\n failure.scrollIntoView({block: 'center'});\n return;\n }\n\n rows.scrollTop = rows.scrollHeight;\n });\n\n return () => cancelScheduledFrame(frame);\n }, [anchorToFailure, anchorRecordCount]);\n\n return (\n <LogRows\n ref={rowsRef}\n timestamps={timestamps}\n wrap={wrap}\n showLineNumbers={showLineNumbers}\n className={className}\n onScroll={onScroll}\n {...(tree.originTs != null ? {timestampOrigin: new Date(tree.originTs)} : {})}\n >\n {noOutputState ? <NoOutputRow state={noOutputState} /> : null}\n {renderNodes(tree.nodes, 0, tree, defaultGroupsOpen, resolvedToolCalls)}\n </LogRows>\n );\n}\n\nexport function LogViewSkeleton({\n rows = 5,\n timestamps = 'off',\n wrap = false,\n showLineNumbers = true,\n className,\n}: LogViewSkeletonProps) {\n const widths = ['w-[62%]', 'w-[44%]', 'w-[74%]', 'w-[36%]', 'w-[55%]'];\n const skeletonRows = getSkeletonRows(rows);\n\n return (\n <LogRows\n timestamps={timestamps}\n wrap={wrap}\n showLineNumbers={showLineNumbers}\n className={className}\n role=\"presentation\"\n aria-live=\"off\"\n aria-hidden=\"true\"\n >\n {skeletonRows.map((row) => (\n <LogRow key={row.id} lineNumber={row.lineNumber}>\n <Skeleton\n className={`my-4 h-12 ${widths[(row.lineNumber - 1) % widths.length] ?? 'w-[48%]'}`}\n />\n </LogRow>\n ))}\n </LogRows>\n );\n}\n\nfunction getSkeletonRows(rows: number): {id: string; lineNumber: number}[] {\n return Array.from({length: rows}, (_, index) => {\n const lineNumber = index + 1;\n return {id: `log-view-skeleton-row-${lineNumber}`, lineNumber};\n });\n}\n\nfunction getNoOutputState(\n tree: LogTree,\n emptyState: NonNullable<LogViewProps['emptyState']>,\n): LogViewProps['emptyState'] | null {\n if (tree.nodes.length === 0) return emptyState;\n\n if (tree.lineCount !== 0) return null;\n if (tree.nodes.length !== 1) return null;\n\n const [node] = tree.nodes;\n if (node?.kind === 'marker' && node.record.type === 'end') return 'complete';\n\n return null;\n}\n\nfunction NoOutputRow({state}: {state: NonNullable<LogViewProps['emptyState']>}) {\n const copy =\n state === 'pending'\n ? {\n title: 'No output yet',\n detail: 'New lines will appear here as the step writes them.',\n }\n : {\n title: 'Step produced no output',\n detail: 'This log stream closed without session entries or process output.',\n };\n\n return (\n <LogRow lineNumber={null}>\n <LogContent className=\"text-foreground-neutral-muted\">\n <span className=\"inline-flex min-w-0 items-center gap-8\">\n <Icon name=\"info\" className=\"size-14 flex-none\" aria-hidden=\"true\" />\n <span className=\"min-w-0\">\n <span className=\"font-medium\">{copy.title}</span>\n {' · '}\n <span className=\"text-foreground-neutral-subtle\">{copy.detail}</span>\n </span>\n </span>\n </LogContent>\n </LogRow>\n );\n}\n\nfunction renderNodes(\n nodes: readonly LogNode[],\n depth: number,\n tree: LogTree,\n defaultGroupsOpen: boolean,\n resolvedToolCalls: ResolvedToolCalls,\n): ReactNode[] {\n // `node.seq` is the stable, unique render key (see `LogNodeBase`): a concatenated\n // multi-step/retry stream can repeat a `group_id` or a marker's `(type, ts)` at one\n // level, which a key derived from those fields would collide on.\n return nodes.map((node): ReactNode => {\n switch (node.kind) {\n case 'output':\n return (\n <OutputLogRow\n key={node.seq}\n record={node.record}\n lineNumber={node.lineNumber}\n indent={depth}\n />\n );\n case 'group':\n return (\n <LogGroup\n key={node.seq}\n node={node}\n depth={depth}\n terminated={tree.terminated}\n defaultOpen={defaultGroupsOpen}\n >\n {renderNodes(node.children, depth + 1, tree, defaultGroupsOpen, resolvedToolCalls)}\n </LogGroup>\n );\n case 'marker':\n return <MarkerRow key={node.seq} record={node.record} tree={tree} />;\n case 'session':\n return (\n <AgentSessionRows\n key={node.seq}\n rows={[node.record.row]}\n resolvedToolCallIds={resolvedToolCalls.ids}\n toolCallNames={resolvedToolCalls.names}\n indent={depth}\n />\n );\n default:\n return assertNever(node);\n }\n });\n}\n\ninterface ResolvedToolCalls {\n ids: ReadonlySet<string>;\n names: ReadonlyMap<string, string>;\n}\n\nfunction collectResolvedToolCalls(nodes: readonly LogNode[]): ResolvedToolCalls {\n const ids = new Set<string>();\n const names = new Map<string, string>();\n collectResolvedToolCallsInto(nodes, ids, names);\n return {ids, names};\n}\n\nfunction collectResolvedToolCallsInto(\n nodes: readonly LogNode[],\n ids: Set<string>,\n names: Map<string, string>,\n): void {\n for (const node of nodes) {\n switch (node.kind) {\n case 'session':\n if (node.record.row.kind === 'tool-call' && node.record.row.id != null) {\n names.set(node.record.row.id, node.record.row.name);\n } else if (node.record.row.kind === 'tool-result' && node.record.row.toolCallId != null) {\n ids.add(node.record.row.toolCallId);\n }\n break;\n case 'group':\n collectResolvedToolCallsInto(node.children, ids, names);\n break;\n case 'output':\n case 'marker':\n break;\n default:\n assertNever(node);\n }\n }\n}\n\nfunction scheduleAnimationFrame(callback: FrameRequestCallback): number {\n if (typeof globalThis.requestAnimationFrame === 'function') {\n return globalThis.requestAnimationFrame(callback);\n }\n return window.setTimeout(() => callback(Date.now()), 0);\n}\n\nfunction cancelScheduledFrame(frame: number) {\n if (typeof globalThis.cancelAnimationFrame === 'function') {\n globalThis.cancelAnimationFrame(frame);\n return;\n }\n window.clearTimeout(frame);\n}\n\nfunction MarkerRow({record, tree}: {record: MarkerLogRecord; tree: LogTree}): ReactNode {\n switch (record.type) {\n case 'end':\n return (\n <EndMarker\n record={record}\n lineCount={tree.lineCount}\n durationMs={tree.originTs != null ? record.ts - tree.originTs : null}\n />\n );\n case 'gap':\n return <GapMarker record={record} />;\n case 'capped':\n return <CappedMarker record={record} />;\n case 'runner_lost':\n return <RunnerLostMarker record={record} />;\n default:\n return assertNever(record);\n }\n}\n"],"names":["Icon","LogContent","LogRow","LogRows","Skeleton","useEffect","useMemo","useRef","assertNever","buildLogTree","AgentSessionRows","LogGroup","OutputLogRow","CappedMarker","EndMarker","GapMarker","RunnerLostMarker","LogView","records","timestamps","wrap","showLineNumbers","emptyState","defaultGroupsOpen","anchorToFailure","className","onScroll","rowsRef","tree","resolvedToolCalls","collectResolvedToolCalls","nodes","noOutputState","getNoOutputState","anchorRecordCount","length","frame","scheduleAnimationFrame","rows","current","failure","querySelector","scrollIntoView","block","scrollTop","scrollHeight","cancelScheduledFrame","ref","originTs","timestampOrigin","Date","NoOutputRow","state","renderNodes","LogViewSkeleton","widths","skeletonRows","getSkeletonRows","role","aria-live","aria-hidden","map","row","lineNumber","id","Array","from","_","index","lineCount","node","kind","record","type","copy","title","detail","span","name","depth","indent","seq","terminated","defaultOpen","children","MarkerRow","resolvedToolCallIds","ids","toolCallNames","names","Set","Map","collectResolvedToolCallsInto","set","toolCallId","add","callback","globalThis","requestAnimationFrame","window","setTimeout","now","cancelAnimationFrame","clearTimeout","durationMs","ts"],"mappings":"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"}
|
package/dist/core/log-model.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-model.d.ts","sourceRoot":"","sources":["../../src/core/log-model.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC9B;AAED,MAAM,MAAM,cAAc,GACtB;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,OAAO,CAAC;CAC1B,GACD;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,GACnD;
|
|
1
|
+
{"version":3,"file":"log-model.d.ts","sourceRoot":"","sources":["../../src/core/log-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/log-model.ts"],"sourcesContent":["export interface SessionViewRowMeta {\n label: string;\n value: string;\n inline?: boolean | undefined;\n}\n\nexport type SessionViewRow =\n | {\n kind: 'message';\n timestamp: number;\n role: string;\n label: string;\n meta: readonly SessionViewRowMeta[];\n text: string;\n terminalFailure: boolean;\n }\n | {kind: 'thinking'; timestamp: number; text: string}\n | {kind: 'tool-call'
|
|
1
|
+
{"version":3,"sources":["../../src/core/log-model.ts"],"sourcesContent":["export interface SessionViewRowMeta {\n label: string;\n value: string;\n inline?: boolean | undefined;\n}\n\nexport type SessionViewRow =\n | {\n kind: 'message';\n timestamp: number;\n role: string;\n label: string;\n meta: readonly SessionViewRowMeta[];\n text: string;\n terminalFailure: boolean;\n }\n | {kind: 'thinking'; timestamp: number; text: string}\n | {\n kind: 'tool-call';\n timestamp: number;\n id: string | null;\n name: string;\n input: string;\n summary?: string | undefined;\n }\n | {\n kind: 'tool-result';\n timestamp: number;\n toolCallId: string | null;\n toolName: string;\n output: string;\n isError: boolean;\n }\n | {\n kind: 'lifecycle';\n timestamp: number;\n label: string;\n detail: string | null;\n meta: readonly SessionViewRowMeta[];\n tone: 'default' | 'warning' | 'error';\n terminalFailure: boolean;\n }\n | {kind: 'raw'; timestamp: number; label: string; raw: string};\n\ninterface LogRecordBase {\n v: 1;\n ts: number;\n}\n\nexport type LogRecord =\n | (LogRecordBase & {type: 'output'; stream: 'stdout' | 'stderr'; data: string})\n | (LogRecordBase & {\n type: 'group_start';\n groupId: string;\n parentGroupId: string | null;\n name: string;\n })\n | (LogRecordBase & {type: 'group_end'; groupId: string})\n | (LogRecordBase & {type: 'end'; totalBytes: number})\n | (LogRecordBase & {type: 'gap'; droppedBytes: number})\n | (LogRecordBase & {type: 'agent_session'; row: SessionViewRow})\n | (LogRecordBase & {type: 'capped'})\n | (LogRecordBase & {type: 'runner_lost'});\n\nexport type LogSource = 'inline' | 'presigned';\nexport type LogState = 'open' | 'closed' | 'compacted';\n\nexport interface InlineLogRead {\n mode: 'inline';\n ndjson: string;\n nextCursor: number;\n hasMore: boolean;\n state: 'open' | 'closed';\n truncated: boolean;\n}\n\nexport interface PresignedLogRead {\n mode: 'presigned';\n url: string;\n expiresAt: string;\n totalBytes: number;\n truncated: boolean;\n}\n"],"names":[],"mappings":"AA4EA,WAMC"}
|