@mastra/playground-ui 66.0.0 → 66.0.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dist/domains/traces/components/format-trace-thread-messages.cjs.js +52 -0
  2. package/dist/domains/traces/components/format-trace-thread-messages.cjs.js.map +1 -1
  3. package/dist/domains/traces/components/format-trace-thread-messages.es.js +51 -1
  4. package/dist/domains/traces/components/format-trace-thread-messages.es.js.map +1 -1
  5. package/dist/domains/traces/components/read-only-tool-call-provider.cjs.js +23 -0
  6. package/dist/domains/traces/components/read-only-tool-call-provider.cjs.js.map +1 -0
  7. package/dist/domains/traces/components/read-only-tool-call-provider.d.ts +1 -0
  8. package/dist/domains/traces/components/read-only-tool-call-provider.es.js +22 -0
  9. package/dist/domains/traces/components/read-only-tool-call-provider.es.js.map +1 -0
  10. package/dist/domains/traces/components/span-data-panel-view.cjs.js +123 -67
  11. package/dist/domains/traces/components/span-data-panel-view.cjs.js.map +1 -1
  12. package/dist/domains/traces/components/span-data-panel-view.es.js +131 -75
  13. package/dist/domains/traces/components/span-data-panel-view.es.js.map +1 -1
  14. package/dist/domains/traces/components/span-details-view.cjs.js +19 -11
  15. package/dist/domains/traces/components/span-details-view.cjs.js.map +1 -1
  16. package/dist/domains/traces/components/span-details-view.es.js +22 -14
  17. package/dist/domains/traces/components/span-details-view.es.js.map +1 -1
  18. package/dist/domains/traces/components/span-outcome.cjs.js +78 -0
  19. package/dist/domains/traces/components/span-outcome.cjs.js.map +1 -0
  20. package/dist/domains/traces/components/span-outcome.d.ts +1 -0
  21. package/dist/domains/traces/components/span-outcome.es.js +77 -0
  22. package/dist/domains/traces/components/span-outcome.es.js.map +1 -0
  23. package/dist/domains/traces/components/span-outcome.utils.cjs.js +360 -0
  24. package/dist/domains/traces/components/span-outcome.utils.cjs.js.map +1 -0
  25. package/dist/domains/traces/components/span-outcome.utils.d.ts +1 -0
  26. package/dist/domains/traces/components/span-outcome.utils.es.js +357 -0
  27. package/dist/domains/traces/components/span-outcome.utils.es.js.map +1 -0
  28. package/dist/domains/traces/components/span-payload/span-error-renderer.cjs.js +32 -15
  29. package/dist/domains/traces/components/span-payload/span-error-renderer.cjs.js.map +1 -1
  30. package/dist/domains/traces/components/span-payload/span-error-renderer.es.js +32 -16
  31. package/dist/domains/traces/components/span-payload/span-error-renderer.es.js.map +1 -1
  32. package/dist/domains/traces/components/span-payload/span-input-renderers.cjs.js +2 -2
  33. package/dist/domains/traces/components/span-payload/span-input-renderers.es.js +2 -2
  34. package/dist/domains/traces/components/span-payload/span-output-renderers.cjs.js +2 -10
  35. package/dist/domains/traces/components/span-payload/span-output-renderers.cjs.js.map +1 -1
  36. package/dist/domains/traces/components/span-payload/span-output-renderers.es.js +2 -10
  37. package/dist/domains/traces/components/span-payload/span-output-renderers.es.js.map +1 -1
  38. package/dist/domains/traces/components/span-payload/span-payload-json.cjs.js +22 -1
  39. package/dist/domains/traces/components/span-payload/span-payload-json.cjs.js.map +1 -1
  40. package/dist/domains/traces/components/span-payload/span-payload-json.es.js +22 -1
  41. package/dist/domains/traces/components/span-payload/span-payload-json.es.js.map +1 -1
  42. package/dist/domains/traces/components/span-payload/span-payload-messages.cjs.js +1 -1
  43. package/dist/domains/traces/components/span-payload/span-payload-messages.es.js +1 -1
  44. package/dist/domains/traces/components/span-payload/span-payload-primitives.cjs.js +1 -1
  45. package/dist/domains/traces/components/span-payload/span-payload-primitives.es.js +1 -1
  46. package/dist/domains/traces/components/span-payload/span-payload-processor.cjs.js +4 -7
  47. package/dist/domains/traces/components/span-payload/span-payload-processor.cjs.js.map +1 -1
  48. package/dist/domains/traces/components/span-payload/span-payload-processor.es.js +4 -7
  49. package/dist/domains/traces/components/span-payload/span-payload-processor.es.js.map +1 -1
  50. package/dist/domains/traces/components/span-payload/span-payload-registry.cjs.js +21 -19
  51. package/dist/domains/traces/components/span-payload/span-payload-registry.cjs.js.map +1 -1
  52. package/dist/domains/traces/components/span-payload/span-payload-registry.es.js +22 -20
  53. package/dist/domains/traces/components/span-payload/span-payload-registry.es.js.map +1 -1
  54. package/dist/domains/traces/components/span-payload/span-payload-section.cjs.js +62 -19
  55. package/dist/domains/traces/components/span-payload/span-payload-section.cjs.js.map +1 -1
  56. package/dist/domains/traces/components/span-payload/span-payload-section.es.js +62 -20
  57. package/dist/domains/traces/components/span-payload/span-payload-section.es.js.map +1 -1
  58. package/dist/domains/traces/components/span-payload/span-payload-tool.cjs.js +1 -1
  59. package/dist/domains/traces/components/span-payload/span-payload-tool.es.js +1 -1
  60. package/dist/domains/traces/components/span-payload/span-processor-attributes.cjs.js +51 -140
  61. package/dist/domains/traces/components/span-payload/span-processor-attributes.cjs.js.map +1 -1
  62. package/dist/domains/traces/components/span-payload/span-processor-attributes.es.js +54 -143
  63. package/dist/domains/traces/components/span-payload/span-processor-attributes.es.js.map +1 -1
  64. package/dist/domains/traces/components/span-payload/span-processor-mutations.cjs.js +99 -0
  65. package/dist/domains/traces/components/span-payload/span-processor-mutations.cjs.js.map +1 -0
  66. package/dist/domains/traces/components/span-payload/span-processor-mutations.d.ts +1 -0
  67. package/dist/domains/traces/components/span-payload/span-processor-mutations.es.js +98 -0
  68. package/dist/domains/traces/components/span-payload/span-processor-mutations.es.js.map +1 -0
  69. package/dist/domains/traces/components/span-payload/span-tools-section.cjs.js +48 -3
  70. package/dist/domains/traces/components/span-payload/span-tools-section.cjs.js.map +1 -1
  71. package/dist/domains/traces/components/span-payload/span-tools-section.es.js +48 -5
  72. package/dist/domains/traces/components/span-payload/span-tools-section.es.js.map +1 -1
  73. package/dist/domains/traces/components/span-payload.cjs.js +6 -1
  74. package/dist/domains/traces/components/span-payload.es.js +5 -4
  75. package/dist/domains/traces/components/thread-trace/thread-trace-spans.cjs.js +1 -1
  76. package/dist/domains/traces/components/thread-trace/thread-trace-spans.es.js +1 -1
  77. package/dist/domains/traces/components/trace-data-panel-view.cjs.js +1 -1
  78. package/dist/domains/traces/components/trace-data-panel-view.es.js +1 -1
  79. package/dist/domains/traces/components/trace-details-view.cjs.js +1 -1
  80. package/dist/domains/traces/components/trace-details-view.es.js +1 -1
  81. package/dist/domains/traces/components/trace-thread-item-view.cjs.js +26 -38
  82. package/dist/domains/traces/components/trace-thread-item-view.cjs.js.map +1 -1
  83. package/dist/domains/traces/components/trace-thread-item-view.es.js +26 -38
  84. package/dist/domains/traces/components/trace-thread-item-view.es.js.map +1 -1
  85. package/dist/domains/traces/components.cjs.js +7 -2
  86. package/dist/domains/traces/components.es.js +6 -5
  87. package/dist/domains/traces/hooks/use-trace-span-navigation.cjs.js +1 -1
  88. package/dist/domains/traces/hooks/use-trace-span-navigation.es.js +1 -1
  89. package/dist/domains/traces.cjs.js +7 -2
  90. package/dist/domains/traces.es.js +6 -5
  91. package/dist/{span-payload-primitives-Fi1kSYyM.js → span-payload-primitives-CNDSzk1Q.js} +2 -2
  92. package/dist/{span-payload-primitives-Fi1kSYyM.js.map → span-payload-primitives-CNDSzk1Q.js.map} +1 -1
  93. package/dist/{span-payload-primitives-rxerCV7Y.cjs → span-payload-primitives-DNhjpAtm.cjs} +2 -2
  94. package/dist/{span-payload-primitives-rxerCV7Y.cjs.map → span-payload-primitives-DNhjpAtm.cjs.map} +1 -1
  95. package/dist/src/domains/traces/components/format-trace-thread-messages.d.ts +14 -0
  96. package/dist/src/domains/traces/components/read-only-tool-call-provider.d.ts +5 -0
  97. package/dist/src/domains/traces/components/span-outcome.d.ts +15 -0
  98. package/dist/src/domains/traces/components/span-outcome.utils.d.ts +32 -0
  99. package/dist/src/domains/traces/components/span-payload/index.d.ts +4 -3
  100. package/dist/src/domains/traces/components/span-payload/span-error-renderer.d.ts +2 -0
  101. package/dist/src/domains/traces/components/span-payload/span-payload-json.d.ts +3 -1
  102. package/dist/src/domains/traces/components/span-payload/span-payload-processor.d.ts +1 -4
  103. package/dist/src/domains/traces/components/span-payload/span-payload-registry.d.ts +5 -14
  104. package/dist/src/domains/traces/components/span-payload/span-payload-section.d.ts +20 -1
  105. package/dist/src/domains/traces/components/span-payload/span-processor-attributes.d.ts +4 -4
  106. package/dist/src/domains/traces/components/span-payload/span-processor-mutations.d.ts +5 -0
  107. package/dist/src/domains/traces/components/span-payload/span-tools-section.d.ts +14 -2
  108. package/dist/style.css +22 -2
  109. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"span-payload-registry.cjs.js","names":["getSpanSignal","describeSpanInput","SpanType","describeProcessorPipeline"],"sources":["../../../../../src/domains/traces/components/span-payload/span-payload-registry.ts"],"sourcesContent":["import { SpanType, describeProcessorPipeline, describeSpanInput } from '@mastra/core/observability';\nimport type { ProcessorRunInputByPhase, ProcessorSpanPayload } from '@mastra/core/observability';\nimport type { ComponentType } from 'react';\nimport type { SpanRecord } from '../../types';\nimport { getSpanSignal } from '@/domains/traces/utils/span-signal';\nimport type { LinkComponentPaths } from '@/lib/framework';\n\ntype CoreSpanRecord = Parameters<typeof describeSpanInput>[0];\n\ntype Described = { type: string; value: unknown };\n\n/** A component per description tag, typed against the value that tag carries. */\nexport type PayloadRegistry<D extends Described> = {\n [T in D['type']]: ComponentType<{ value: Extract<D, { type: T }>['value'] }>;\n};\n\n/**\n * Picks the registry entry for `description.type`. The registry is exhaustive by type,\n * so the entry always exists; the cast only erases the per-tag prop refinement TS cannot\n * carry through an indexed lookup.\n */\nexport function pickRenderer<D extends Described>(\n registry: PayloadRegistry<D>,\n description: D,\n): ComponentType<{ value: D['value'] }> {\n return registry[description.type as D['type']] as ComponentType<{ value: D['value'] }>;\n}\n\n/**\n * The client-js span (API response: ISO-string dates, string-literal enums) is the core\n * span over the wire. `describeSpan*` only read `spanType`, `metadata`, `input`, `output`\n * and `error`, which are identical in both, so this is the one place the two types meet.\n */\nexport function asCoreSpan(span: SpanRecord): CoreSpanRecord {\n // oxlint-disable-next-line typescript/no-unnecessary-type-assertion -- Generated SDK and core span types differ once workspace declarations are built.\n return span as unknown as CoreSpanRecord;\n}\n\nexport const hasItems = (value: unknown): value is unknown[] => Array.isArray(value) && value.length > 0;\n\n/** Whether a span's input has a rendered preview, rather than only its raw JSON. */\nexport function hasSpanInputPreview(span: SpanRecord): boolean {\n return getSpanSignal(span) !== undefined || describeSpanInput(asCoreSpan(span))?.type !== 'json';\n}\n\nconst isEmptyObject = (value: unknown) =>\n typeof value === 'object' && value !== null && !Array.isArray(value) && Object.keys(value).length === 0;\n\n/**\n * Whether a processor ran the span. A processor can retype its span (memory\n * recall is a `memory_operation`), so the recorded phase counts as well as the type.\n */\nconst isProcessorSpan = (span: SpanRecord) =>\n span.spanType === SpanType.PROCESSOR_RUN || describeProcessorPipeline(asCoreSpan(span)) !== undefined;\n\n/**\n * The output to show, or `undefined` when `{}` only means \"nothing\": a processor\n * that returned nothing, or a chunk that streamed no content (e.g. encrypted reasoning).\n */\nexport function getSpanOutputPayload(span: SpanRecord): unknown {\n if (isEmptyObject(span.output) && (span.spanType === SpanType.MODEL_CHUNK || isProcessorSpan(span))) {\n return undefined;\n }\n return span.output;\n}\n\nconst isCount = (value: unknown): value is number => typeof value === 'number' && Number.isFinite(value);\n\nexport interface ProcessorRunContext {\n stepNumber?: number;\n retryCount?: number;\n /** The assistant message the step is producing, not the user message that started the run. */\n messageId?: string;\n}\n\n/**\n * Where in the generation the hook ran. The runner hands these values to every\n * hook, so they are recorded in `input`, but they describe the run rather than\n * what the processor read: Attributes shows them and the input preview skips them.\n * A key is present only when it holds a well-formed value, so a malformed one stays in the input.\n */\nexport function getProcessorRunContext(input: ProcessorSpanPayload<ProcessorRunInputByPhase>): ProcessorRunContext {\n const { data } = input;\n const stepNumber = 'stepNumber' in data ? data.stepNumber : undefined;\n const retryCount = 'retryCount' in data ? data.retryCount : undefined;\n const messageId = 'messageId' in data ? data.messageId : undefined;\n return {\n ...(isCount(stepNumber) ? { stepNumber } : {}),\n ...(isCount(retryCount) ? { retryCount } : {}),\n ...(typeof messageId === 'string' && messageId.length > 0 ? { messageId } : {}),\n };\n}\n\n/** A tool offered to the model, with the id the tool registry knows it by. */\n/** Who a tool hands the work to when an agent exposes a workflow or sub-agent as a tool. */\nexport interface DelegatedTool {\n kind: 'workflow' | 'agent';\n /** The key the agent registered it under, which the workflow and agent pages resolve. */\n key: string;\n}\n\nconst DELEGATED_TOOL = /^(workflow|agent)-(.+)$/;\n\n/**\n * The workflow or sub-agent behind a tool name, if it is one. Agents expose each\n * workflow they own as `workflow-<key>` and each sub-agent as `agent-<key>`.\n */\nexport function getDelegatedTool(toolName: string): DelegatedTool | undefined {\n const match = DELEGATED_TOOL.exec(toolName);\n if (!match?.[2]) return undefined;\n return { kind: match[1] === 'workflow' ? 'workflow' : 'agent', key: match[2] };\n}\n\n/** The page of the workflow or sub-agent behind a tool name, or `''` when it is neither. */\nexport function getDelegatedToolHref(paths: LinkComponentPaths, toolName: string): string {\n const delegated = getDelegatedTool(toolName);\n if (!delegated) return '';\n return delegated.kind === 'workflow' ? paths.workflowLink(delegated.key) : paths.agentLink(delegated.key);\n}\n\nexport interface SpanTool {\n id: string;\n description?: string;\n}\n\nexport interface SpanTools {\n tools: SpanTool[];\n /** The stored values the list was read from, for the JSON view. */\n raw: { tools: unknown; toolChoice?: unknown };\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst textOf = (value: unknown) => (typeof value === 'string' && value.length > 0 ? value : undefined);\n\n/** Processor spans record `{ id, name }`, model spans `{ name }`, agent runs bare names. */\nfunction toTool(value: unknown): SpanTool | undefined {\n if (typeof value === 'string') return value ? { id: value } : undefined;\n if (!isRecord(value)) return undefined;\n const id = textOf(value.id) ?? textOf(value.name);\n if (!id) return undefined;\n const description = textOf(value.description);\n return description ? { id, description } : { id };\n}\n\n/**\n * The tools a span offered the model. A processor span records them in its\n * input; model spans record definitions in attributes, agent runs only names.\n */\nexport function getSpanTools(span: SpanRecord): SpanTools | undefined {\n const input = describeSpanInput(asCoreSpan(span));\n const data: Record<string, unknown> = input?.type === 'processor' ? input.value.data : {};\n const attributes = span.attributes ?? {};\n const [tools, toolChoice] = hasItems(data.tools)\n ? [data.tools, data.toolChoice]\n : hasItems(attributes.tools)\n ? [attributes.tools, attributes.toolChoice]\n : [attributes.availableTools, attributes.toolChoice];\n if (!hasItems(tools)) return undefined;\n\n const list = tools.map(toTool).filter((tool): tool is SpanTool => tool !== undefined);\n if (list.length === 0) return undefined;\n return { tools: list, raw: toolChoice === undefined ? { tools } : { tools, toolChoice } };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"span-payload-registry.cjs.js","names":["getSpanSignal","describeSpanInput","describeSpanOutput","SpanType","describeProcessorPipeline"],"sources":["../../../../../src/domains/traces/components/span-payload/span-payload-registry.ts"],"sourcesContent":["import { SpanType, describeProcessorPipeline, describeSpanInput, describeSpanOutput } from '@mastra/core/observability';\nimport type { ProcessorRunInputByPhase, ProcessorSpanPayload } from '@mastra/core/observability';\nimport type { ComponentType } from 'react';\nimport type { SpanRecord } from '../../types';\nimport { getSpanSignal } from '@/domains/traces/utils/span-signal';\nimport type { LinkComponentPaths } from '@/lib/framework';\n\ntype CoreSpanRecord = Parameters<typeof describeSpanInput>[0];\n\ntype Described = { type: string; value: unknown };\n\n/** A component per description tag, typed against the value that tag carries. */\nexport type PayloadRegistry<D extends Described> = {\n [T in D['type']]: ComponentType<{ value: Extract<D, { type: T }>['value'] }>;\n};\n\n/**\n * Picks the registry entry for `description.type`. The registry is exhaustive by type,\n * so the entry always exists; the cast only erases the per-tag prop refinement TS cannot\n * carry through an indexed lookup.\n */\nexport function pickRenderer<D extends Described>(\n registry: PayloadRegistry<D>,\n description: D,\n): ComponentType<{ value: D['value'] }> {\n return registry[description.type as D['type']] as ComponentType<{ value: D['value'] }>;\n}\n\n/**\n * The client-js span (API response: ISO-string dates, string-literal enums) is the core\n * span over the wire. `describeSpan*` only read `spanType`, `metadata`, `input`, `output`\n * and `error`, which are identical in both, so this is the one place the two types meet.\n */\nexport function asCoreSpan(span: SpanRecord): CoreSpanRecord {\n // oxlint-disable-next-line typescript/no-unnecessary-type-assertion -- Generated SDK and core span types differ once workspace declarations are built.\n return span as unknown as CoreSpanRecord;\n}\n\nexport const hasItems = (value: unknown): value is unknown[] => Array.isArray(value) && value.length > 0;\n\n/** Whether a span's input has a rendered preview, rather than only its raw JSON. */\nexport function hasSpanInputPreview(span: SpanRecord): boolean {\n return getSpanSignal(span) !== undefined || describeSpanInput(asCoreSpan(span))?.type !== 'json';\n}\n\nconst hasText = (value: unknown) => typeof value === 'string' && value.length > 0;\n\n/**\n * Whether a span's output has a rendered preview, rather than only its raw JSON.\n * A model result that only asked for tools has nothing to preview: its calls are listed under Tool calls.\n */\nexport function hasSpanOutputPreview(span: SpanRecord): boolean {\n const description = describeSpanOutput(asCoreSpan(span));\n switch (description?.type) {\n case 'json':\n return false;\n case 'model-step-result': {\n const { text, object, steps } = description.value;\n return hasText(text) || object !== undefined || hasItems(steps);\n }\n case 'model-generation-result': {\n const { text, reasoningText, reasoning, object, sources, files, warnings } = description.value;\n return (\n hasText(text) ||\n typeof reasoningText === 'string' ||\n reasoning !== undefined ||\n object !== undefined ||\n hasItems(sources) ||\n hasItems(files) ||\n hasItems(warnings)\n );\n }\n default:\n return true;\n }\n}\n\nconst isEmptyObject = (value: unknown) =>\n typeof value === 'object' && value !== null && !Array.isArray(value) && Object.keys(value).length === 0;\n\n/**\n * Whether a processor ran the span. A processor can retype its span (memory\n * recall is a `memory_operation`), so the recorded phase counts as well as the type.\n */\nconst isProcessorSpan = (span: SpanRecord) =>\n span.spanType === SpanType.PROCESSOR_RUN || describeProcessorPipeline(asCoreSpan(span)) !== undefined;\n\n/**\n * The output to show, or `undefined` when `{}` only means \"nothing\": a processor\n * that returned nothing, or a chunk that streamed no content (e.g. encrypted reasoning).\n */\nexport function getSpanOutputPayload(span: SpanRecord): unknown {\n if (isEmptyObject(span.output) && (span.spanType === SpanType.MODEL_CHUNK || isProcessorSpan(span))) {\n return undefined;\n }\n return span.output;\n}\n\n/** A tool offered to the model, with the id the tool registry knows it by. */\n/** Who a tool hands the work to when an agent exposes a workflow or sub-agent as a tool. */\nexport interface DelegatedTool {\n kind: 'workflow' | 'agent';\n /** The key the agent registered it under, which the workflow and agent pages resolve. */\n key: string;\n}\n\nconst DELEGATED_TOOL = /^(workflow|agent)-(.+)$/;\n\n/**\n * The workflow or sub-agent behind a tool name, if it is one. Agents expose each\n * workflow they own as `workflow-<key>` and each sub-agent as `agent-<key>`.\n */\nexport function getDelegatedTool(toolName: string): DelegatedTool | undefined {\n const match = DELEGATED_TOOL.exec(toolName);\n if (!match?.[2]) return undefined;\n return { kind: match[1] === 'workflow' ? 'workflow' : 'agent', key: match[2] };\n}\n\n/** The page of the workflow or sub-agent behind a tool name, or `''` when it is neither. */\nexport function getDelegatedToolHref(paths: LinkComponentPaths, toolName: string): string {\n const delegated = getDelegatedTool(toolName);\n if (!delegated) return '';\n return delegated.kind === 'workflow' ? paths.workflowLink(delegated.key) : paths.agentLink(delegated.key);\n}\n\nexport interface SpanTool {\n id: string;\n description?: string;\n}\n\nexport interface SpanTools {\n tools: SpanTool[];\n /** The stored values the list was read from, for the JSON view. */\n raw: { tools: unknown; toolChoice?: unknown };\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst textOf = (value: unknown) => (typeof value === 'string' && value.length > 0 ? value : undefined);\n\n/** Processor spans record `{ id, name }`, model spans `{ name }`, agent runs bare names. */\nfunction toTool(value: unknown): SpanTool | undefined {\n if (typeof value === 'string') return value ? { id: value } : undefined;\n if (!isRecord(value)) return undefined;\n const id = textOf(value.id) ?? textOf(value.name);\n if (!id) return undefined;\n const description = textOf(value.description);\n return description ? { id, description } : { id };\n}\n\n/**\n * The tools a span offered the model. A processor span records them in its\n * input; model spans record definitions in attributes, agent runs only names.\n */\nexport function getSpanTools(span: SpanRecord): SpanTools | undefined {\n const input = describeSpanInput(asCoreSpan(span));\n const data: Record<string, unknown> = input?.type === 'processor' ? input.value.data : {};\n const attributes = span.attributes ?? {};\n const [tools, toolChoice] = hasItems(data.tools)\n ? [data.tools, data.toolChoice]\n : hasItems(attributes.tools)\n ? [attributes.tools, attributes.toolChoice]\n : [attributes.availableTools, attributes.toolChoice];\n if (!hasItems(tools)) return undefined;\n\n const list = tools.map(toTool).filter((tool): tool is SpanTool => tool !== undefined);\n if (list.length === 0) return undefined;\n return { tools: list, raw: toolChoice === undefined ? { tools } : { tools, toolChoice } };\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { getSpanSignal } from "../../utils/span-signal.es.js";
2
- import { SpanType, describeProcessorPipeline, describeSpanInput } from "@mastra/core/observability";
2
+ import { SpanType, describeProcessorPipeline, describeSpanInput, describeSpanOutput } from "@mastra/core/observability";
3
3
  // src/domains/traces/components/span-payload/span-payload-registry.ts
4
4
  /**
5
5
  * Picks the registry entry for `description.type`. The registry is exhaustive by type,
@@ -22,6 +22,26 @@ var hasItems = (value) => Array.isArray(value) && value.length > 0;
22
22
  function hasSpanInputPreview(span) {
23
23
  return getSpanSignal(span) !== void 0 || describeSpanInput(asCoreSpan(span))?.type !== "json";
24
24
  }
25
+ var hasText = (value) => typeof value === "string" && value.length > 0;
26
+ /**
27
+ * Whether a span's output has a rendered preview, rather than only its raw JSON.
28
+ * A model result that only asked for tools has nothing to preview: its calls are listed under Tool calls.
29
+ */
30
+ function hasSpanOutputPreview(span) {
31
+ const description = describeSpanOutput(asCoreSpan(span));
32
+ switch (description?.type) {
33
+ case "json": return false;
34
+ case "model-step-result": {
35
+ const { text, object, steps } = description.value;
36
+ return hasText(text) || object !== void 0 || hasItems(steps);
37
+ }
38
+ case "model-generation-result": {
39
+ const { text, reasoningText, reasoning, object, sources, files, warnings } = description.value;
40
+ return hasText(text) || typeof reasoningText === "string" || reasoning !== void 0 || object !== void 0 || hasItems(sources) || hasItems(files) || hasItems(warnings);
41
+ }
42
+ default: return true;
43
+ }
44
+ }
25
45
  var isEmptyObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.keys(value).length === 0;
26
46
  /**
27
47
  * Whether a processor ran the span. A processor can retype its span (memory
@@ -36,24 +56,6 @@ function getSpanOutputPayload(span) {
36
56
  if (isEmptyObject(span.output) && (span.spanType === SpanType.MODEL_CHUNK || isProcessorSpan(span))) return;
37
57
  return span.output;
38
58
  }
39
- var isCount = (value) => typeof value === "number" && Number.isFinite(value);
40
- /**
41
- * Where in the generation the hook ran. The runner hands these values to every
42
- * hook, so they are recorded in `input`, but they describe the run rather than
43
- * what the processor read: Attributes shows them and the input preview skips them.
44
- * A key is present only when it holds a well-formed value, so a malformed one stays in the input.
45
- */
46
- function getProcessorRunContext(input) {
47
- const { data } = input;
48
- const stepNumber = "stepNumber" in data ? data.stepNumber : void 0;
49
- const retryCount = "retryCount" in data ? data.retryCount : void 0;
50
- const messageId = "messageId" in data ? data.messageId : void 0;
51
- return {
52
- ...isCount(stepNumber) ? { stepNumber } : {},
53
- ...isCount(retryCount) ? { retryCount } : {},
54
- ...typeof messageId === "string" && messageId.length > 0 ? { messageId } : {}
55
- };
56
- }
57
59
  var DELEGATED_TOOL = /^(workflow|agent)-(.+)$/;
58
60
  /**
59
61
  * The workflow or sub-agent behind a tool name, if it is one. Agents expose each
@@ -107,6 +109,6 @@ function getSpanTools(span) {
107
109
  }
108
110
  };
109
111
  }
110
- export { asCoreSpan, getDelegatedTool, getDelegatedToolHref, getProcessorRunContext, getSpanOutputPayload, getSpanTools, hasItems, hasSpanInputPreview, pickRenderer };
112
+ export { asCoreSpan, getDelegatedTool, getDelegatedToolHref, getSpanOutputPayload, getSpanTools, hasItems, hasSpanInputPreview, hasSpanOutputPreview, pickRenderer };
111
113
 
112
114
  //# sourceMappingURL=span-payload-registry.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"span-payload-registry.es.js","names":[],"sources":["../../../../../src/domains/traces/components/span-payload/span-payload-registry.ts"],"sourcesContent":["import { SpanType, describeProcessorPipeline, describeSpanInput } from '@mastra/core/observability';\nimport type { ProcessorRunInputByPhase, ProcessorSpanPayload } from '@mastra/core/observability';\nimport type { ComponentType } from 'react';\nimport type { SpanRecord } from '../../types';\nimport { getSpanSignal } from '@/domains/traces/utils/span-signal';\nimport type { LinkComponentPaths } from '@/lib/framework';\n\ntype CoreSpanRecord = Parameters<typeof describeSpanInput>[0];\n\ntype Described = { type: string; value: unknown };\n\n/** A component per description tag, typed against the value that tag carries. */\nexport type PayloadRegistry<D extends Described> = {\n [T in D['type']]: ComponentType<{ value: Extract<D, { type: T }>['value'] }>;\n};\n\n/**\n * Picks the registry entry for `description.type`. The registry is exhaustive by type,\n * so the entry always exists; the cast only erases the per-tag prop refinement TS cannot\n * carry through an indexed lookup.\n */\nexport function pickRenderer<D extends Described>(\n registry: PayloadRegistry<D>,\n description: D,\n): ComponentType<{ value: D['value'] }> {\n return registry[description.type as D['type']] as ComponentType<{ value: D['value'] }>;\n}\n\n/**\n * The client-js span (API response: ISO-string dates, string-literal enums) is the core\n * span over the wire. `describeSpan*` only read `spanType`, `metadata`, `input`, `output`\n * and `error`, which are identical in both, so this is the one place the two types meet.\n */\nexport function asCoreSpan(span: SpanRecord): CoreSpanRecord {\n // oxlint-disable-next-line typescript/no-unnecessary-type-assertion -- Generated SDK and core span types differ once workspace declarations are built.\n return span as unknown as CoreSpanRecord;\n}\n\nexport const hasItems = (value: unknown): value is unknown[] => Array.isArray(value) && value.length > 0;\n\n/** Whether a span's input has a rendered preview, rather than only its raw JSON. */\nexport function hasSpanInputPreview(span: SpanRecord): boolean {\n return getSpanSignal(span) !== undefined || describeSpanInput(asCoreSpan(span))?.type !== 'json';\n}\n\nconst isEmptyObject = (value: unknown) =>\n typeof value === 'object' && value !== null && !Array.isArray(value) && Object.keys(value).length === 0;\n\n/**\n * Whether a processor ran the span. A processor can retype its span (memory\n * recall is a `memory_operation`), so the recorded phase counts as well as the type.\n */\nconst isProcessorSpan = (span: SpanRecord) =>\n span.spanType === SpanType.PROCESSOR_RUN || describeProcessorPipeline(asCoreSpan(span)) !== undefined;\n\n/**\n * The output to show, or `undefined` when `{}` only means \"nothing\": a processor\n * that returned nothing, or a chunk that streamed no content (e.g. encrypted reasoning).\n */\nexport function getSpanOutputPayload(span: SpanRecord): unknown {\n if (isEmptyObject(span.output) && (span.spanType === SpanType.MODEL_CHUNK || isProcessorSpan(span))) {\n return undefined;\n }\n return span.output;\n}\n\nconst isCount = (value: unknown): value is number => typeof value === 'number' && Number.isFinite(value);\n\nexport interface ProcessorRunContext {\n stepNumber?: number;\n retryCount?: number;\n /** The assistant message the step is producing, not the user message that started the run. */\n messageId?: string;\n}\n\n/**\n * Where in the generation the hook ran. The runner hands these values to every\n * hook, so they are recorded in `input`, but they describe the run rather than\n * what the processor read: Attributes shows them and the input preview skips them.\n * A key is present only when it holds a well-formed value, so a malformed one stays in the input.\n */\nexport function getProcessorRunContext(input: ProcessorSpanPayload<ProcessorRunInputByPhase>): ProcessorRunContext {\n const { data } = input;\n const stepNumber = 'stepNumber' in data ? data.stepNumber : undefined;\n const retryCount = 'retryCount' in data ? data.retryCount : undefined;\n const messageId = 'messageId' in data ? data.messageId : undefined;\n return {\n ...(isCount(stepNumber) ? { stepNumber } : {}),\n ...(isCount(retryCount) ? { retryCount } : {}),\n ...(typeof messageId === 'string' && messageId.length > 0 ? { messageId } : {}),\n };\n}\n\n/** A tool offered to the model, with the id the tool registry knows it by. */\n/** Who a tool hands the work to when an agent exposes a workflow or sub-agent as a tool. */\nexport interface DelegatedTool {\n kind: 'workflow' | 'agent';\n /** The key the agent registered it under, which the workflow and agent pages resolve. */\n key: string;\n}\n\nconst DELEGATED_TOOL = /^(workflow|agent)-(.+)$/;\n\n/**\n * The workflow or sub-agent behind a tool name, if it is one. Agents expose each\n * workflow they own as `workflow-<key>` and each sub-agent as `agent-<key>`.\n */\nexport function getDelegatedTool(toolName: string): DelegatedTool | undefined {\n const match = DELEGATED_TOOL.exec(toolName);\n if (!match?.[2]) return undefined;\n return { kind: match[1] === 'workflow' ? 'workflow' : 'agent', key: match[2] };\n}\n\n/** The page of the workflow or sub-agent behind a tool name, or `''` when it is neither. */\nexport function getDelegatedToolHref(paths: LinkComponentPaths, toolName: string): string {\n const delegated = getDelegatedTool(toolName);\n if (!delegated) return '';\n return delegated.kind === 'workflow' ? paths.workflowLink(delegated.key) : paths.agentLink(delegated.key);\n}\n\nexport interface SpanTool {\n id: string;\n description?: string;\n}\n\nexport interface SpanTools {\n tools: SpanTool[];\n /** The stored values the list was read from, for the JSON view. */\n raw: { tools: unknown; toolChoice?: unknown };\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst textOf = (value: unknown) => (typeof value === 'string' && value.length > 0 ? value : undefined);\n\n/** Processor spans record `{ id, name }`, model spans `{ name }`, agent runs bare names. */\nfunction toTool(value: unknown): SpanTool | undefined {\n if (typeof value === 'string') return value ? { id: value } : undefined;\n if (!isRecord(value)) return undefined;\n const id = textOf(value.id) ?? textOf(value.name);\n if (!id) return undefined;\n const description = textOf(value.description);\n return description ? { id, description } : { id };\n}\n\n/**\n * The tools a span offered the model. A processor span records them in its\n * input; model spans record definitions in attributes, agent runs only names.\n */\nexport function getSpanTools(span: SpanRecord): SpanTools | undefined {\n const input = describeSpanInput(asCoreSpan(span));\n const data: Record<string, unknown> = input?.type === 'processor' ? input.value.data : {};\n const attributes = span.attributes ?? {};\n const [tools, toolChoice] = hasItems(data.tools)\n ? [data.tools, data.toolChoice]\n : hasItems(attributes.tools)\n ? [attributes.tools, attributes.toolChoice]\n : [attributes.availableTools, attributes.toolChoice];\n if (!hasItems(tools)) return undefined;\n\n const list = tools.map(toTool).filter((tool): tool is SpanTool => tool !== undefined);\n if (list.length === 0) return undefined;\n return { tools: list, raw: toolChoice === undefined ? { tools } : { tools, toolChoice } };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"span-payload-registry.es.js","names":[],"sources":["../../../../../src/domains/traces/components/span-payload/span-payload-registry.ts"],"sourcesContent":["import { SpanType, describeProcessorPipeline, describeSpanInput, describeSpanOutput } from '@mastra/core/observability';\nimport type { ProcessorRunInputByPhase, ProcessorSpanPayload } from '@mastra/core/observability';\nimport type { ComponentType } from 'react';\nimport type { SpanRecord } from '../../types';\nimport { getSpanSignal } from '@/domains/traces/utils/span-signal';\nimport type { LinkComponentPaths } from '@/lib/framework';\n\ntype CoreSpanRecord = Parameters<typeof describeSpanInput>[0];\n\ntype Described = { type: string; value: unknown };\n\n/** A component per description tag, typed against the value that tag carries. */\nexport type PayloadRegistry<D extends Described> = {\n [T in D['type']]: ComponentType<{ value: Extract<D, { type: T }>['value'] }>;\n};\n\n/**\n * Picks the registry entry for `description.type`. The registry is exhaustive by type,\n * so the entry always exists; the cast only erases the per-tag prop refinement TS cannot\n * carry through an indexed lookup.\n */\nexport function pickRenderer<D extends Described>(\n registry: PayloadRegistry<D>,\n description: D,\n): ComponentType<{ value: D['value'] }> {\n return registry[description.type as D['type']] as ComponentType<{ value: D['value'] }>;\n}\n\n/**\n * The client-js span (API response: ISO-string dates, string-literal enums) is the core\n * span over the wire. `describeSpan*` only read `spanType`, `metadata`, `input`, `output`\n * and `error`, which are identical in both, so this is the one place the two types meet.\n */\nexport function asCoreSpan(span: SpanRecord): CoreSpanRecord {\n // oxlint-disable-next-line typescript/no-unnecessary-type-assertion -- Generated SDK and core span types differ once workspace declarations are built.\n return span as unknown as CoreSpanRecord;\n}\n\nexport const hasItems = (value: unknown): value is unknown[] => Array.isArray(value) && value.length > 0;\n\n/** Whether a span's input has a rendered preview, rather than only its raw JSON. */\nexport function hasSpanInputPreview(span: SpanRecord): boolean {\n return getSpanSignal(span) !== undefined || describeSpanInput(asCoreSpan(span))?.type !== 'json';\n}\n\nconst hasText = (value: unknown) => typeof value === 'string' && value.length > 0;\n\n/**\n * Whether a span's output has a rendered preview, rather than only its raw JSON.\n * A model result that only asked for tools has nothing to preview: its calls are listed under Tool calls.\n */\nexport function hasSpanOutputPreview(span: SpanRecord): boolean {\n const description = describeSpanOutput(asCoreSpan(span));\n switch (description?.type) {\n case 'json':\n return false;\n case 'model-step-result': {\n const { text, object, steps } = description.value;\n return hasText(text) || object !== undefined || hasItems(steps);\n }\n case 'model-generation-result': {\n const { text, reasoningText, reasoning, object, sources, files, warnings } = description.value;\n return (\n hasText(text) ||\n typeof reasoningText === 'string' ||\n reasoning !== undefined ||\n object !== undefined ||\n hasItems(sources) ||\n hasItems(files) ||\n hasItems(warnings)\n );\n }\n default:\n return true;\n }\n}\n\nconst isEmptyObject = (value: unknown) =>\n typeof value === 'object' && value !== null && !Array.isArray(value) && Object.keys(value).length === 0;\n\n/**\n * Whether a processor ran the span. A processor can retype its span (memory\n * recall is a `memory_operation`), so the recorded phase counts as well as the type.\n */\nconst isProcessorSpan = (span: SpanRecord) =>\n span.spanType === SpanType.PROCESSOR_RUN || describeProcessorPipeline(asCoreSpan(span)) !== undefined;\n\n/**\n * The output to show, or `undefined` when `{}` only means \"nothing\": a processor\n * that returned nothing, or a chunk that streamed no content (e.g. encrypted reasoning).\n */\nexport function getSpanOutputPayload(span: SpanRecord): unknown {\n if (isEmptyObject(span.output) && (span.spanType === SpanType.MODEL_CHUNK || isProcessorSpan(span))) {\n return undefined;\n }\n return span.output;\n}\n\n/** A tool offered to the model, with the id the tool registry knows it by. */\n/** Who a tool hands the work to when an agent exposes a workflow or sub-agent as a tool. */\nexport interface DelegatedTool {\n kind: 'workflow' | 'agent';\n /** The key the agent registered it under, which the workflow and agent pages resolve. */\n key: string;\n}\n\nconst DELEGATED_TOOL = /^(workflow|agent)-(.+)$/;\n\n/**\n * The workflow or sub-agent behind a tool name, if it is one. Agents expose each\n * workflow they own as `workflow-<key>` and each sub-agent as `agent-<key>`.\n */\nexport function getDelegatedTool(toolName: string): DelegatedTool | undefined {\n const match = DELEGATED_TOOL.exec(toolName);\n if (!match?.[2]) return undefined;\n return { kind: match[1] === 'workflow' ? 'workflow' : 'agent', key: match[2] };\n}\n\n/** The page of the workflow or sub-agent behind a tool name, or `''` when it is neither. */\nexport function getDelegatedToolHref(paths: LinkComponentPaths, toolName: string): string {\n const delegated = getDelegatedTool(toolName);\n if (!delegated) return '';\n return delegated.kind === 'workflow' ? paths.workflowLink(delegated.key) : paths.agentLink(delegated.key);\n}\n\nexport interface SpanTool {\n id: string;\n description?: string;\n}\n\nexport interface SpanTools {\n tools: SpanTool[];\n /** The stored values the list was read from, for the JSON view. */\n raw: { tools: unknown; toolChoice?: unknown };\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst textOf = (value: unknown) => (typeof value === 'string' && value.length > 0 ? value : undefined);\n\n/** Processor spans record `{ id, name }`, model spans `{ name }`, agent runs bare names. */\nfunction toTool(value: unknown): SpanTool | undefined {\n if (typeof value === 'string') return value ? { id: value } : undefined;\n if (!isRecord(value)) return undefined;\n const id = textOf(value.id) ?? textOf(value.name);\n if (!id) return undefined;\n const description = textOf(value.description);\n return description ? { id, description } : { id };\n}\n\n/**\n * The tools a span offered the model. A processor span records them in its\n * input; model spans record definitions in attributes, agent runs only names.\n */\nexport function getSpanTools(span: SpanRecord): SpanTools | undefined {\n const input = describeSpanInput(asCoreSpan(span));\n const data: Record<string, unknown> = input?.type === 'processor' ? input.value.data : {};\n const attributes = span.attributes ?? {};\n const [tools, toolChoice] = hasItems(data.tools)\n ? [data.tools, data.toolChoice]\n : hasItems(attributes.tools)\n ? [attributes.tools, attributes.toolChoice]\n : [attributes.availableTools, attributes.toolChoice];\n if (!hasItems(tools)) return undefined;\n\n const list = tools.map(toTool).filter((tool): tool is SpanTool => tool !== undefined);\n if (list.length === 0) return undefined;\n return { tools: list, raw: toolChoice === undefined ? { tools } : { tools, toolChoice } };\n}\n"],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_utils = require("../../../../utils-uDc1ofX1.cjs");
3
3
  const require_Button = require("../../../../Button-YQRflC47.cjs");
4
+ const require_components_Collapsible = require("../../../../components/Collapsible.cjs.js");
5
+ const require_components_DisclosureChevron = require("../../../../components/DisclosureChevron.cjs.js");
4
6
  const require_copy_button = require("../../../../copy-button-BYEFKNpo.cjs");
5
7
  const require_data_panel_section_heading = require("../../../../data-panel-section-heading-d9UnruDt.cjs");
6
8
  const require_components_CollapsibleBox = require("../../../../components/CollapsibleBox.cjs.js");
@@ -40,7 +42,7 @@ function ViewToggle({ view, onChange }) {
40
42
  * the same syntax highlighting while preserving the stored payload. Long content is
41
43
  * clipped with a fade and an Expand button, like the experiment comparison sections.
42
44
  */
43
- function SpanPayloadSection({ title, icon, raw, hasPreview = true, children, framed = true, layout = "panel", defaultView = "rich", className }) {
45
+ function SpanPayloadSection({ title, icon, raw, hasPreview = true, children, framed = true, layout = "panel", defaultView = "rich", emphasis = false, heading, clip = true, className }) {
44
46
  const [view, setView] = (0, react.useState)(defaultView);
45
47
  const box = require_components_CollapsibleBox.useCollapsibleBox();
46
48
  if (raw == null) return null;
@@ -48,20 +50,28 @@ function SpanPayloadSection({ title, icon, raw, hasPreview = true, children, fra
48
50
  const showJson = !hasRich || view === "raw";
49
51
  const content = showJson ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_domains_traces_components_span_payload_span_payload_json.SpanPayloadJson, {
50
52
  value: raw,
51
- bare: framed
53
+ bare: framed,
54
+ foldNested: true
52
55
  }) : children;
56
+ const shouldClip = clip && !showJson;
57
+ const clipped = (body) => shouldClip ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_CollapsibleBox.CollapsibleBox, {
58
+ state: box,
59
+ expandLabel: "Expand",
60
+ children: body
61
+ }) : body;
53
62
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
54
63
  "data-slot": "span-payload-section",
55
64
  "data-view": showJson ? "raw" : "rich",
56
- className: require_utils.cn("flex min-w-0 flex-col gap-2", className),
65
+ "data-emphasis": emphasis || void 0,
66
+ className: require_utils.cn("group/payload flex min-w-0 flex-col gap-2", className),
57
67
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
58
68
  className: "flex flex-wrap items-center justify-between gap-2",
59
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_data_panel_section_heading.DataPanelSectionHeading, {
69
+ children: [heading ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_data_panel_section_heading.DataPanelSectionHeading, {
60
70
  icon,
61
- className: layout === "details" ? "text-meta" : void 0,
71
+ className: require_utils.cn(layout === "details" && "text-meta", emphasis && "font-medium text-foreground [&>svg]:text-info-indicator"),
62
72
  children: title
63
73
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
64
- className: "ml-auto flex items-center gap-1",
74
+ className: "ml-auto flex items-center gap-1 group-focus-within/payload:opacity-100 group-hover/payload:opacity-100 motion-safe:transition-opacity pointer-fine:opacity-0",
65
75
  children: [hasRich && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewToggle, {
66
76
  view,
67
77
  onChange: setView
@@ -75,19 +85,11 @@ function SpanPayloadSection({ title, icon, raw, hasPreview = true, children, fra
75
85
  children: [framed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Card.Card, {
76
86
  "data-slot": "span-payload-card",
77
87
  className: "min-w-0 overflow-hidden",
78
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_CollapsibleBox.CollapsibleBox, {
79
- state: box,
80
- expandLabel: "Expand",
81
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Card.CardContent, {
82
- className: "[&_[data-slot=message]]:my-0",
83
- children: content
84
- })
85
- })
86
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_CollapsibleBox.CollapsibleBox, {
87
- state: box,
88
- expandLabel: "Expand",
89
- children: content
90
- }), box.isExpanded && box.isClipped && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
88
+ children: clipped(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Card.CardContent, {
89
+ className: "[&_[data-slot=message]]:my-0",
90
+ children: content
91
+ }))
92
+ }) : clipped(content), shouldClip && box.isExpanded && box.isClipped && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
91
93
  className: "flex justify-center pt-1",
92
94
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.Button, {
93
95
  size: "sm",
@@ -100,6 +102,47 @@ function SpanPayloadSection({ title, icon, raw, hasPreview = true, children, fra
100
102
  })]
101
103
  });
102
104
  }
105
+ /**
106
+ * A span payload that is only worth reading as stored, like metadata or attributes.
107
+ * Folded behind its heading by default, and shown in full as JSON once opened.
108
+ */
109
+ function SpanPayloadJsonSection({ title, icon, raw, layout = "panel" }) {
110
+ if (raw == null) return null;
111
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_components_Collapsible.Collapsible, {
112
+ "data-slot": "span-payload-section",
113
+ "data-view": "raw",
114
+ className: "group/payload flex min-w-0 flex-col gap-2",
115
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
116
+ className: "flex flex-wrap items-center justify-between gap-2",
117
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_components_Collapsible.CollapsibleTrigger, {
118
+ className: "flex items-center gap-1 rounded-sm",
119
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_DisclosureChevron.DisclosureChevron, {
120
+ direction: "right",
121
+ className: "size-3 text-placeholder"
122
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_data_panel_section_heading.DataPanelSectionHeading, {
123
+ icon,
124
+ className: require_utils.cn(layout === "details" && "text-meta"),
125
+ children: title
126
+ })]
127
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
128
+ className: "ml-auto flex items-center gap-1 group-focus-within/payload:opacity-100 group-hover/payload:opacity-100 motion-safe:transition-opacity pointer-fine:opacity-0",
129
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_copy_button.CopyButton, {
130
+ content: JSON.stringify(raw, null, 2),
131
+ variant: "ghost"
132
+ })
133
+ })]
134
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Collapsible.CollapsibleContent, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Card.Card, {
135
+ "data-slot": "span-payload-card",
136
+ className: "min-w-0 overflow-hidden",
137
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Card.CardContent, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_domains_traces_components_span_payload_span_payload_json.SpanPayloadJson, {
138
+ value: raw,
139
+ bare: true,
140
+ foldNested: true
141
+ }) })
142
+ }) })]
143
+ });
144
+ }
145
+ exports.SpanPayloadJsonSection = SpanPayloadJsonSection;
103
146
  exports.SpanPayloadSection = SpanPayloadSection;
104
147
 
105
148
  //# sourceMappingURL=span-payload-section.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"span-payload-section.cjs.js","names":["Button","Eye","Braces","useState","useCollapsibleBox","SpanPayloadJson","cn","DataPanelSectionHeading","CopyButton","Card","CollapsibleBox","CardContent","Minimize2"],"sources":["../../../../../src/domains/traces/components/span-payload/span-payload-section.tsx"],"sourcesContent":["import { Braces, Eye, Minimize2 } from 'lucide-react';\nimport { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { SpanPayloadJson } from './span-payload-json';\nimport { Button } from '@/ds/components/Button';\nimport { Card, CardContent } from '@/ds/components/Card';\nimport { CollapsibleBox, useCollapsibleBox } from '@/ds/components/CollapsibleBox';\nimport { CopyButton } from '@/ds/components/CopyButton';\nimport { DataPanelSectionHeading } from '@/ds/components/DataPanel/data-panel-section-heading';\nimport { cn } from '@/lib/utils';\n\nexport type SpanPayloadView = 'rich' | 'raw';\n\nexport interface SpanPayloadSectionProps {\n title: string;\n icon?: ReactNode;\n /** The payload as stored; shown as JSON in the Raw view. */\n raw: unknown;\n /** Whether a dedicated presentation exists rather than a JSON fallback. */\n hasPreview?: boolean;\n /**\n * The human-readable rendering. `null` when the payload has no rich form\n * (JSON fallback): the section then shows Raw only and hides the toggle.\n */\n children: ReactNode;\n /**\n * Wraps the content in a card, with the clipping inside it so the rounded frame stays intact.\n * Turn off for content that brings its own frame, like the error banner.\n */\n framed?: boolean;\n /** `panel` matches `DataPanel.CodeSection`; `details` matches `DataDetailsPanel.CodeSection`. */\n layout?: 'panel' | 'details';\n defaultView?: SpanPayloadView;\n className?: string;\n}\n\nfunction ViewToggle({ view, onChange }: { view: SpanPayloadView; onChange: (view: SpanPayloadView) => void }) {\n return (\n <div\n role=\"group\"\n aria-label=\"Payload view\"\n data-slot=\"span-payload-view-toggle\"\n className=\"flex items-center gap-1\"\n >\n <Button\n size=\"icon-sm\"\n variant={view === 'rich' ? 'subtle' : 'ghost'}\n aria-pressed={view === 'rich'}\n aria-label=\"Preview\"\n tooltip=\"Preview\"\n onClick={() => onChange('rich')}\n >\n <Eye />\n </Button>\n <Button\n size=\"icon-sm\"\n variant={view === 'raw' ? 'subtle' : 'ghost'}\n aria-pressed={view === 'raw'}\n aria-label=\"JSON\"\n tooltip=\"JSON\"\n onClick={() => onChange('raw')}\n >\n <Braces />\n </Button>\n </div>\n );\n}\n\n/**\n * A span payload section with Preview / JSON view toggles. All JSON views share\n * the same syntax highlighting while preserving the stored payload. Long content is\n * clipped with a fade and an Expand button, like the experiment comparison sections.\n */\nexport function SpanPayloadSection({\n title,\n icon,\n raw,\n hasPreview = true,\n children,\n framed = true,\n layout = 'panel',\n defaultView = 'rich',\n className,\n}: SpanPayloadSectionProps) {\n const [view, setView] = useState<SpanPayloadView>(defaultView);\n const box = useCollapsibleBox();\n if (raw == null) return null;\n\n const hasRich = hasPreview && children != null;\n const showJson = !hasRich || view === 'raw';\n const content = showJson ? <SpanPayloadJson value={raw} bare={framed} /> : children;\n\n return (\n <div\n data-slot=\"span-payload-section\"\n data-view={showJson ? 'raw' : 'rich'}\n className={cn('flex min-w-0 flex-col gap-2', className)}\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <DataPanelSectionHeading icon={icon} className={layout === 'details' ? 'text-meta' : undefined}>\n {title}\n </DataPanelSectionHeading>\n <div className=\"ml-auto flex items-center gap-1\">\n {hasRich && <ViewToggle view={view} onChange={setView} />}\n <CopyButton content={JSON.stringify(raw, null, 2)} variant=\"ghost\" />\n </div>\n </div>\n <div className=\"min-w-0\">\n {framed ? (\n <Card data-slot=\"span-payload-card\" className=\"min-w-0 overflow-hidden\">\n <CollapsibleBox state={box} expandLabel=\"Expand\">\n {/* Renderers space their children with gaps; a user bubble's chat margin would double the card's Y padding. */}\n <CardContent className=\"[&_[data-slot=message]]:my-0\">{content}</CardContent>\n </CollapsibleBox>\n </Card>\n ) : (\n <CollapsibleBox state={box} expandLabel=\"Expand\">\n {content}\n </CollapsibleBox>\n )}\n {box.isExpanded && box.isClipped && (\n <div className=\"flex justify-center pt-1\">\n <Button size=\"sm\" variant=\"ghost\" icon={<Minimize2 />} onClick={() => box.setExpanded(false)}>\n Collapse\n </Button>\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"span-payload-section.cjs.js","names":["Button","Eye","Braces","useState","useCollapsibleBox","SpanPayloadJson","CollapsibleBox","cn","DataPanelSectionHeading","CopyButton","Card","CardContent","Minimize2","Collapsible","CollapsibleTrigger","DisclosureChevron","CollapsibleContent"],"sources":["../../../../../src/domains/traces/components/span-payload/span-payload-section.tsx"],"sourcesContent":["import { Braces, Eye, Minimize2 } from 'lucide-react';\nimport { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { SpanPayloadJson } from './span-payload-json';\nimport { Button } from '@/ds/components/Button';\nimport { Card, CardContent } from '@/ds/components/Card';\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/ds/components/Collapsible';\nimport { CollapsibleBox, useCollapsibleBox } from '@/ds/components/CollapsibleBox';\nimport { CopyButton } from '@/ds/components/CopyButton';\nimport { DataPanelSectionHeading } from '@/ds/components/DataPanel/data-panel-section-heading';\nimport { DisclosureChevron } from '@/ds/components/DisclosureChevron';\nimport { cn } from '@/lib/utils';\n\nexport type SpanPayloadView = 'rich' | 'raw';\n\nexport interface SpanPayloadSectionProps {\n title: string;\n icon?: ReactNode;\n /** The payload as stored; shown as JSON in the Raw view. */\n raw: unknown;\n /** Whether a dedicated presentation exists rather than a JSON fallback. */\n hasPreview?: boolean;\n /**\n * The human-readable rendering. `null` when the payload has no rich form\n * (JSON fallback): the section then shows Raw only and hides the toggle.\n */\n children: ReactNode;\n /**\n * Wraps the content in a card, with the clipping inside it so the rounded frame stays intact.\n * Turn off for content that brings its own frame, like the error banner.\n */\n framed?: boolean;\n /** `panel` matches `DataPanel.CodeSection`; `details` matches `DataDetailsPanel.CodeSection`. */\n layout?: 'panel' | 'details';\n defaultView?: SpanPayloadView;\n /** Marks the section that proves what the span did, so it stands out from the payloads around it. */\n emphasis?: boolean;\n /** Replaces the title heading, e.g. with the sentence of the notice the section sits in. */\n heading?: ReactNode;\n /** Clips long content behind an Expand button. Turn off for content that folds on its own, like tool call rows. */\n clip?: boolean;\n className?: string;\n}\n\nfunction ViewToggle({ view, onChange }: { view: SpanPayloadView; onChange: (view: SpanPayloadView) => void }) {\n return (\n <div\n role=\"group\"\n aria-label=\"Payload view\"\n data-slot=\"span-payload-view-toggle\"\n className=\"flex items-center gap-1\"\n >\n <Button\n size=\"icon-sm\"\n variant={view === 'rich' ? 'subtle' : 'ghost'}\n aria-pressed={view === 'rich'}\n aria-label=\"Preview\"\n tooltip=\"Preview\"\n onClick={() => onChange('rich')}\n >\n <Eye />\n </Button>\n <Button\n size=\"icon-sm\"\n variant={view === 'raw' ? 'subtle' : 'ghost'}\n aria-pressed={view === 'raw'}\n aria-label=\"JSON\"\n tooltip=\"JSON\"\n onClick={() => onChange('raw')}\n >\n <Braces />\n </Button>\n </div>\n );\n}\n\n/**\n * A span payload section with Preview / JSON view toggles. All JSON views share\n * the same syntax highlighting while preserving the stored payload. Long content is\n * clipped with a fade and an Expand button, like the experiment comparison sections.\n */\nexport function SpanPayloadSection({\n title,\n icon,\n raw,\n hasPreview = true,\n children,\n framed = true,\n layout = 'panel',\n defaultView = 'rich',\n emphasis = false,\n heading,\n clip = true,\n className,\n}: SpanPayloadSectionProps) {\n const [view, setView] = useState<SpanPayloadView>(defaultView);\n const box = useCollapsibleBox();\n if (raw == null) return null;\n\n const hasRich = hasPreview && children != null;\n const showJson = !hasRich || view === 'raw';\n const content = showJson ? <SpanPayloadJson value={raw} bare={framed} foldNested /> : children;\n // JSON folds its nested values instead, so it never needs clipping.\n const shouldClip = clip && !showJson;\n const clipped = (body: ReactNode) =>\n shouldClip ? (\n <CollapsibleBox state={box} expandLabel=\"Expand\">\n {body}\n </CollapsibleBox>\n ) : (\n body\n );\n\n return (\n <div\n data-slot=\"span-payload-section\"\n data-view={showJson ? 'raw' : 'rich'}\n data-emphasis={emphasis || undefined}\n className={cn('group/payload flex min-w-0 flex-col gap-2', className)}\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n {heading ?? (\n <DataPanelSectionHeading\n icon={icon}\n className={cn(\n layout === 'details' && 'text-meta',\n emphasis && 'font-medium text-foreground [&>svg]:text-info-indicator',\n )}\n >\n {title}\n </DataPanelSectionHeading>\n )}\n {/* Revealed on hover or keyboard focus; `pointer-fine` only, since a touch screen has no hover. */}\n <div className=\"ml-auto flex items-center gap-1 group-focus-within/payload:opacity-100 group-hover/payload:opacity-100 motion-safe:transition-opacity pointer-fine:opacity-0\">\n {hasRich && <ViewToggle view={view} onChange={setView} />}\n <CopyButton content={JSON.stringify(raw, null, 2)} variant=\"ghost\" />\n </div>\n </div>\n <div className=\"min-w-0\">\n {framed ? (\n <Card data-slot=\"span-payload-card\" className=\"min-w-0 overflow-hidden\">\n {/* Renderers space their children with gaps; a user bubble's chat margin would double the card's Y padding. */}\n {clipped(<CardContent className=\"[&_[data-slot=message]]:my-0\">{content}</CardContent>)}\n </Card>\n ) : (\n clipped(content)\n )}\n {shouldClip && box.isExpanded && box.isClipped && (\n <div className=\"flex justify-center pt-1\">\n <Button size=\"sm\" variant=\"ghost\" icon={<Minimize2 />} onClick={() => box.setExpanded(false)}>\n Collapse\n </Button>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport interface SpanPayloadJsonSectionProps {\n title: string;\n icon?: ReactNode;\n /** The payload as stored; shown as JSON. */\n raw: unknown;\n /** `panel` matches `DataPanel.CodeSection`; `details` matches `DataDetailsPanel.CodeSection`. */\n layout?: 'panel' | 'details';\n}\n\n/**\n * A span payload that is only worth reading as stored, like metadata or attributes.\n * Folded behind its heading by default, and shown in full as JSON once opened.\n */\nexport function SpanPayloadJsonSection({ title, icon, raw, layout = 'panel' }: SpanPayloadJsonSectionProps) {\n if (raw == null) return null;\n\n return (\n <Collapsible data-slot=\"span-payload-section\" data-view=\"raw\" className=\"group/payload flex min-w-0 flex-col gap-2\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <CollapsibleTrigger className=\"flex items-center gap-1 rounded-sm\">\n <DisclosureChevron direction=\"right\" className=\"size-3 text-placeholder\" />\n <DataPanelSectionHeading icon={icon} className={cn(layout === 'details' && 'text-meta')}>\n {title}\n </DataPanelSectionHeading>\n </CollapsibleTrigger>\n {/* Revealed on hover or keyboard focus; `pointer-fine` only, since a touch screen has no hover. */}\n <div className=\"ml-auto flex items-center gap-1 group-focus-within/payload:opacity-100 group-hover/payload:opacity-100 motion-safe:transition-opacity pointer-fine:opacity-0\">\n <CopyButton content={JSON.stringify(raw, null, 2)} variant=\"ghost\" />\n </div>\n </div>\n <CollapsibleContent>\n <Card data-slot=\"span-payload-card\" className=\"min-w-0 overflow-hidden\">\n <CardContent>\n <SpanPayloadJson value={raw} bare foldNested />\n </CardContent>\n </Card>\n </CollapsibleContent>\n </Collapsible>\n );\n}\n"],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  import { t as cn } from "../../../../utils-DQx8TpNT.js";
2
2
  import { t as Button } from "../../../../Button-Bw1e3ONi.js";
3
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../../../../components/Collapsible.es.js";
4
+ import { DisclosureChevron } from "../../../../components/DisclosureChevron.es.js";
3
5
  import { t as CopyButton } from "../../../../copy-button-CF-X4iDj.js";
4
6
  import { t as DataPanelSectionHeading } from "../../../../data-panel-section-heading-X3tHNMV1.js";
5
7
  import { CollapsibleBox, useCollapsibleBox } from "../../../../components/CollapsibleBox.es.js";
@@ -39,7 +41,7 @@ function ViewToggle({ view, onChange }) {
39
41
  * the same syntax highlighting while preserving the stored payload. Long content is
40
42
  * clipped with a fade and an Expand button, like the experiment comparison sections.
41
43
  */
42
- function SpanPayloadSection({ title, icon, raw, hasPreview = true, children, framed = true, layout = "panel", defaultView = "rich", className }) {
44
+ function SpanPayloadSection({ title, icon, raw, hasPreview = true, children, framed = true, layout = "panel", defaultView = "rich", emphasis = false, heading, clip = true, className }) {
43
45
  const [view, setView] = useState(defaultView);
44
46
  const box = useCollapsibleBox();
45
47
  if (raw == null) return null;
@@ -47,20 +49,28 @@ function SpanPayloadSection({ title, icon, raw, hasPreview = true, children, fra
47
49
  const showJson = !hasRich || view === "raw";
48
50
  const content = showJson ? /* @__PURE__ */ jsx(SpanPayloadJson, {
49
51
  value: raw,
50
- bare: framed
52
+ bare: framed,
53
+ foldNested: true
51
54
  }) : children;
55
+ const shouldClip = clip && !showJson;
56
+ const clipped = (body) => shouldClip ? /* @__PURE__ */ jsx(CollapsibleBox, {
57
+ state: box,
58
+ expandLabel: "Expand",
59
+ children: body
60
+ }) : body;
52
61
  return /* @__PURE__ */ jsxs("div", {
53
62
  "data-slot": "span-payload-section",
54
63
  "data-view": showJson ? "raw" : "rich",
55
- className: cn("flex min-w-0 flex-col gap-2", className),
64
+ "data-emphasis": emphasis || void 0,
65
+ className: cn("group/payload flex min-w-0 flex-col gap-2", className),
56
66
  children: [/* @__PURE__ */ jsxs("div", {
57
67
  className: "flex flex-wrap items-center justify-between gap-2",
58
- children: [/* @__PURE__ */ jsx(DataPanelSectionHeading, {
68
+ children: [heading ?? /* @__PURE__ */ jsx(DataPanelSectionHeading, {
59
69
  icon,
60
- className: layout === "details" ? "text-meta" : void 0,
70
+ className: cn(layout === "details" && "text-meta", emphasis && "font-medium text-foreground [&>svg]:text-info-indicator"),
61
71
  children: title
62
72
  }), /* @__PURE__ */ jsxs("div", {
63
- className: "ml-auto flex items-center gap-1",
73
+ className: "ml-auto flex items-center gap-1 group-focus-within/payload:opacity-100 group-hover/payload:opacity-100 motion-safe:transition-opacity pointer-fine:opacity-0",
64
74
  children: [hasRich && /* @__PURE__ */ jsx(ViewToggle, {
65
75
  view,
66
76
  onChange: setView
@@ -74,19 +84,11 @@ function SpanPayloadSection({ title, icon, raw, hasPreview = true, children, fra
74
84
  children: [framed ? /* @__PURE__ */ jsx(Card, {
75
85
  "data-slot": "span-payload-card",
76
86
  className: "min-w-0 overflow-hidden",
77
- children: /* @__PURE__ */ jsx(CollapsibleBox, {
78
- state: box,
79
- expandLabel: "Expand",
80
- children: /* @__PURE__ */ jsx(CardContent, {
81
- className: "[&_[data-slot=message]]:my-0",
82
- children: content
83
- })
84
- })
85
- }) : /* @__PURE__ */ jsx(CollapsibleBox, {
86
- state: box,
87
- expandLabel: "Expand",
88
- children: content
89
- }), box.isExpanded && box.isClipped && /* @__PURE__ */ jsx("div", {
87
+ children: clipped(/* @__PURE__ */ jsx(CardContent, {
88
+ className: "[&_[data-slot=message]]:my-0",
89
+ children: content
90
+ }))
91
+ }) : clipped(content), shouldClip && box.isExpanded && box.isClipped && /* @__PURE__ */ jsx("div", {
90
92
  className: "flex justify-center pt-1",
91
93
  children: /* @__PURE__ */ jsx(Button, {
92
94
  size: "sm",
@@ -99,6 +101,46 @@ function SpanPayloadSection({ title, icon, raw, hasPreview = true, children, fra
99
101
  })]
100
102
  });
101
103
  }
102
- export { SpanPayloadSection };
104
+ /**
105
+ * A span payload that is only worth reading as stored, like metadata or attributes.
106
+ * Folded behind its heading by default, and shown in full as JSON once opened.
107
+ */
108
+ function SpanPayloadJsonSection({ title, icon, raw, layout = "panel" }) {
109
+ if (raw == null) return null;
110
+ return /* @__PURE__ */ jsxs(Collapsible, {
111
+ "data-slot": "span-payload-section",
112
+ "data-view": "raw",
113
+ className: "group/payload flex min-w-0 flex-col gap-2",
114
+ children: [/* @__PURE__ */ jsxs("div", {
115
+ className: "flex flex-wrap items-center justify-between gap-2",
116
+ children: [/* @__PURE__ */ jsxs(CollapsibleTrigger, {
117
+ className: "flex items-center gap-1 rounded-sm",
118
+ children: [/* @__PURE__ */ jsx(DisclosureChevron, {
119
+ direction: "right",
120
+ className: "size-3 text-placeholder"
121
+ }), /* @__PURE__ */ jsx(DataPanelSectionHeading, {
122
+ icon,
123
+ className: cn(layout === "details" && "text-meta"),
124
+ children: title
125
+ })]
126
+ }), /* @__PURE__ */ jsx("div", {
127
+ className: "ml-auto flex items-center gap-1 group-focus-within/payload:opacity-100 group-hover/payload:opacity-100 motion-safe:transition-opacity pointer-fine:opacity-0",
128
+ children: /* @__PURE__ */ jsx(CopyButton, {
129
+ content: JSON.stringify(raw, null, 2),
130
+ variant: "ghost"
131
+ })
132
+ })]
133
+ }), /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx(Card, {
134
+ "data-slot": "span-payload-card",
135
+ className: "min-w-0 overflow-hidden",
136
+ children: /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(SpanPayloadJson, {
137
+ value: raw,
138
+ bare: true,
139
+ foldNested: true
140
+ }) })
141
+ }) })]
142
+ });
143
+ }
144
+ export { SpanPayloadJsonSection, SpanPayloadSection };
103
145
 
104
146
  //# sourceMappingURL=span-payload-section.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"span-payload-section.es.js","names":[],"sources":["../../../../../src/domains/traces/components/span-payload/span-payload-section.tsx"],"sourcesContent":["import { Braces, Eye, Minimize2 } from 'lucide-react';\nimport { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { SpanPayloadJson } from './span-payload-json';\nimport { Button } from '@/ds/components/Button';\nimport { Card, CardContent } from '@/ds/components/Card';\nimport { CollapsibleBox, useCollapsibleBox } from '@/ds/components/CollapsibleBox';\nimport { CopyButton } from '@/ds/components/CopyButton';\nimport { DataPanelSectionHeading } from '@/ds/components/DataPanel/data-panel-section-heading';\nimport { cn } from '@/lib/utils';\n\nexport type SpanPayloadView = 'rich' | 'raw';\n\nexport interface SpanPayloadSectionProps {\n title: string;\n icon?: ReactNode;\n /** The payload as stored; shown as JSON in the Raw view. */\n raw: unknown;\n /** Whether a dedicated presentation exists rather than a JSON fallback. */\n hasPreview?: boolean;\n /**\n * The human-readable rendering. `null` when the payload has no rich form\n * (JSON fallback): the section then shows Raw only and hides the toggle.\n */\n children: ReactNode;\n /**\n * Wraps the content in a card, with the clipping inside it so the rounded frame stays intact.\n * Turn off for content that brings its own frame, like the error banner.\n */\n framed?: boolean;\n /** `panel` matches `DataPanel.CodeSection`; `details` matches `DataDetailsPanel.CodeSection`. */\n layout?: 'panel' | 'details';\n defaultView?: SpanPayloadView;\n className?: string;\n}\n\nfunction ViewToggle({ view, onChange }: { view: SpanPayloadView; onChange: (view: SpanPayloadView) => void }) {\n return (\n <div\n role=\"group\"\n aria-label=\"Payload view\"\n data-slot=\"span-payload-view-toggle\"\n className=\"flex items-center gap-1\"\n >\n <Button\n size=\"icon-sm\"\n variant={view === 'rich' ? 'subtle' : 'ghost'}\n aria-pressed={view === 'rich'}\n aria-label=\"Preview\"\n tooltip=\"Preview\"\n onClick={() => onChange('rich')}\n >\n <Eye />\n </Button>\n <Button\n size=\"icon-sm\"\n variant={view === 'raw' ? 'subtle' : 'ghost'}\n aria-pressed={view === 'raw'}\n aria-label=\"JSON\"\n tooltip=\"JSON\"\n onClick={() => onChange('raw')}\n >\n <Braces />\n </Button>\n </div>\n );\n}\n\n/**\n * A span payload section with Preview / JSON view toggles. All JSON views share\n * the same syntax highlighting while preserving the stored payload. Long content is\n * clipped with a fade and an Expand button, like the experiment comparison sections.\n */\nexport function SpanPayloadSection({\n title,\n icon,\n raw,\n hasPreview = true,\n children,\n framed = true,\n layout = 'panel',\n defaultView = 'rich',\n className,\n}: SpanPayloadSectionProps) {\n const [view, setView] = useState<SpanPayloadView>(defaultView);\n const box = useCollapsibleBox();\n if (raw == null) return null;\n\n const hasRich = hasPreview && children != null;\n const showJson = !hasRich || view === 'raw';\n const content = showJson ? <SpanPayloadJson value={raw} bare={framed} /> : children;\n\n return (\n <div\n data-slot=\"span-payload-section\"\n data-view={showJson ? 'raw' : 'rich'}\n className={cn('flex min-w-0 flex-col gap-2', className)}\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <DataPanelSectionHeading icon={icon} className={layout === 'details' ? 'text-meta' : undefined}>\n {title}\n </DataPanelSectionHeading>\n <div className=\"ml-auto flex items-center gap-1\">\n {hasRich && <ViewToggle view={view} onChange={setView} />}\n <CopyButton content={JSON.stringify(raw, null, 2)} variant=\"ghost\" />\n </div>\n </div>\n <div className=\"min-w-0\">\n {framed ? (\n <Card data-slot=\"span-payload-card\" className=\"min-w-0 overflow-hidden\">\n <CollapsibleBox state={box} expandLabel=\"Expand\">\n {/* Renderers space their children with gaps; a user bubble's chat margin would double the card's Y padding. */}\n <CardContent className=\"[&_[data-slot=message]]:my-0\">{content}</CardContent>\n </CollapsibleBox>\n </Card>\n ) : (\n <CollapsibleBox state={box} expandLabel=\"Expand\">\n {content}\n </CollapsibleBox>\n )}\n {box.isExpanded && box.isClipped && (\n <div className=\"flex justify-center pt-1\">\n <Button size=\"sm\" variant=\"ghost\" icon={<Minimize2 />} onClick={() => box.setExpanded(false)}>\n Collapse\n </Button>\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;AAoCA,SAAS,WAAW,EAAE,MAAM,YAAkF;CAC5G,OACE,qBAAC,OAAD;EACE,MAAK;EACL,cAAW;EACX,aAAU;EACV,WAAU;EAJZ,UAAA,CAME,oBAAC,QAAD;GACE,MAAK;GACL,SAAS,SAAS,SAAS,WAAW;GACtC,gBAAc,SAAS;GACvB,cAAW;GACX,SAAQ;GACR,eAAe,SAAS,MAAM;GAE9B,UAAA,oBAAC,KAAD,CAAM,CAAA;EACA,CAAA,GACR,oBAAC,QAAD;GACE,MAAK;GACL,SAAS,SAAS,QAAQ,WAAW;GACrC,gBAAc,SAAS;GACvB,cAAW;GACX,SAAQ;GACR,eAAe,SAAS,KAAK;GAE7B,UAAA,oBAAC,QAAD,CAAS,CAAA;EACH,CAAA,CACL;;AAET;;;;;;AAOA,SAAgB,mBAAmB,EACjC,OACA,MACA,KACA,aAAa,MACb,UACA,SAAS,MACT,SAAS,SACT,cAAc,QACd,aAC0B;CAC1B,MAAM,CAAC,MAAM,WAAW,SAA0B,WAAW;CAC7D,MAAM,MAAM,kBAAkB;CAC9B,IAAI,OAAO,MAAM,OAAO;CAExB,MAAM,UAAU,cAAc,YAAY;CAC1C,MAAM,WAAW,CAAC,WAAW,SAAS;CACtC,MAAM,UAAU,WAAW,oBAAC,iBAAD;EAAiB,OAAO;EAAK,MAAM;CAAS,CAAA,IAAI;CAE3E,OACE,qBAAC,OAAD;EACE,aAAU;EACV,aAAW,WAAW,QAAQ;EAC9B,WAAW,GAAG,+BAA+B,SAAS;EAHxD,UAAA,CAKE,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,oBAAC,yBAAD;IAA+B;IAAM,WAAW,WAAW,YAAY,cAAc,KAAA;IAClF,UAAA;GACsB,CAAA,GACzB,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACG,WAAW,oBAAC,YAAD;KAAkB;KAAM,UAAU;IAAU,CAAA,GACxD,oBAAC,YAAD;KAAY,SAAS,KAAK,UAAU,KAAK,MAAM,CAAC;KAAG,SAAQ;IAAS,CAAA,CACjE;GACF,CAAA,CAAA;EACL,CAAA,GAAA,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACG,SACC,oBAAC,MAAD;IAAM,aAAU;IAAoB,WAAU;IAC5C,UAAA,oBAAC,gBAAD;KAAgB,OAAO;KAAK,aAAY;KAEtC,UAAA,oBAAC,aAAD;MAAa,WAAU;MAAgC,UAAA;KAAqB,CAAA;IAC9D,CAAA;GACZ,CAAA,IAEN,oBAAC,gBAAD;IAAgB,OAAO;IAAK,aAAY;IACrC,UAAA;GACa,CAAA,GAEjB,IAAI,cAAc,IAAI,aACrB,oBAAC,OAAD;IAAK,WAAU;IACb,UAAA,oBAAC,QAAD;KAAQ,MAAK;KAAK,SAAQ;KAAQ,MAAM,oBAAC,WAAD,CAAY,CAAA;KAAG,eAAe,IAAI,YAAY,KAAK;KAAG,UAAA;IAEtF,CAAA;GACL,CAAA,CAEJ;EACF,CAAA,CAAA;;AAET"}
1
+ {"version":3,"file":"span-payload-section.es.js","names":[],"sources":["../../../../../src/domains/traces/components/span-payload/span-payload-section.tsx"],"sourcesContent":["import { Braces, Eye, Minimize2 } from 'lucide-react';\nimport { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { SpanPayloadJson } from './span-payload-json';\nimport { Button } from '@/ds/components/Button';\nimport { Card, CardContent } from '@/ds/components/Card';\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/ds/components/Collapsible';\nimport { CollapsibleBox, useCollapsibleBox } from '@/ds/components/CollapsibleBox';\nimport { CopyButton } from '@/ds/components/CopyButton';\nimport { DataPanelSectionHeading } from '@/ds/components/DataPanel/data-panel-section-heading';\nimport { DisclosureChevron } from '@/ds/components/DisclosureChevron';\nimport { cn } from '@/lib/utils';\n\nexport type SpanPayloadView = 'rich' | 'raw';\n\nexport interface SpanPayloadSectionProps {\n title: string;\n icon?: ReactNode;\n /** The payload as stored; shown as JSON in the Raw view. */\n raw: unknown;\n /** Whether a dedicated presentation exists rather than a JSON fallback. */\n hasPreview?: boolean;\n /**\n * The human-readable rendering. `null` when the payload has no rich form\n * (JSON fallback): the section then shows Raw only and hides the toggle.\n */\n children: ReactNode;\n /**\n * Wraps the content in a card, with the clipping inside it so the rounded frame stays intact.\n * Turn off for content that brings its own frame, like the error banner.\n */\n framed?: boolean;\n /** `panel` matches `DataPanel.CodeSection`; `details` matches `DataDetailsPanel.CodeSection`. */\n layout?: 'panel' | 'details';\n defaultView?: SpanPayloadView;\n /** Marks the section that proves what the span did, so it stands out from the payloads around it. */\n emphasis?: boolean;\n /** Replaces the title heading, e.g. with the sentence of the notice the section sits in. */\n heading?: ReactNode;\n /** Clips long content behind an Expand button. Turn off for content that folds on its own, like tool call rows. */\n clip?: boolean;\n className?: string;\n}\n\nfunction ViewToggle({ view, onChange }: { view: SpanPayloadView; onChange: (view: SpanPayloadView) => void }) {\n return (\n <div\n role=\"group\"\n aria-label=\"Payload view\"\n data-slot=\"span-payload-view-toggle\"\n className=\"flex items-center gap-1\"\n >\n <Button\n size=\"icon-sm\"\n variant={view === 'rich' ? 'subtle' : 'ghost'}\n aria-pressed={view === 'rich'}\n aria-label=\"Preview\"\n tooltip=\"Preview\"\n onClick={() => onChange('rich')}\n >\n <Eye />\n </Button>\n <Button\n size=\"icon-sm\"\n variant={view === 'raw' ? 'subtle' : 'ghost'}\n aria-pressed={view === 'raw'}\n aria-label=\"JSON\"\n tooltip=\"JSON\"\n onClick={() => onChange('raw')}\n >\n <Braces />\n </Button>\n </div>\n );\n}\n\n/**\n * A span payload section with Preview / JSON view toggles. All JSON views share\n * the same syntax highlighting while preserving the stored payload. Long content is\n * clipped with a fade and an Expand button, like the experiment comparison sections.\n */\nexport function SpanPayloadSection({\n title,\n icon,\n raw,\n hasPreview = true,\n children,\n framed = true,\n layout = 'panel',\n defaultView = 'rich',\n emphasis = false,\n heading,\n clip = true,\n className,\n}: SpanPayloadSectionProps) {\n const [view, setView] = useState<SpanPayloadView>(defaultView);\n const box = useCollapsibleBox();\n if (raw == null) return null;\n\n const hasRich = hasPreview && children != null;\n const showJson = !hasRich || view === 'raw';\n const content = showJson ? <SpanPayloadJson value={raw} bare={framed} foldNested /> : children;\n // JSON folds its nested values instead, so it never needs clipping.\n const shouldClip = clip && !showJson;\n const clipped = (body: ReactNode) =>\n shouldClip ? (\n <CollapsibleBox state={box} expandLabel=\"Expand\">\n {body}\n </CollapsibleBox>\n ) : (\n body\n );\n\n return (\n <div\n data-slot=\"span-payload-section\"\n data-view={showJson ? 'raw' : 'rich'}\n data-emphasis={emphasis || undefined}\n className={cn('group/payload flex min-w-0 flex-col gap-2', className)}\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n {heading ?? (\n <DataPanelSectionHeading\n icon={icon}\n className={cn(\n layout === 'details' && 'text-meta',\n emphasis && 'font-medium text-foreground [&>svg]:text-info-indicator',\n )}\n >\n {title}\n </DataPanelSectionHeading>\n )}\n {/* Revealed on hover or keyboard focus; `pointer-fine` only, since a touch screen has no hover. */}\n <div className=\"ml-auto flex items-center gap-1 group-focus-within/payload:opacity-100 group-hover/payload:opacity-100 motion-safe:transition-opacity pointer-fine:opacity-0\">\n {hasRich && <ViewToggle view={view} onChange={setView} />}\n <CopyButton content={JSON.stringify(raw, null, 2)} variant=\"ghost\" />\n </div>\n </div>\n <div className=\"min-w-0\">\n {framed ? (\n <Card data-slot=\"span-payload-card\" className=\"min-w-0 overflow-hidden\">\n {/* Renderers space their children with gaps; a user bubble's chat margin would double the card's Y padding. */}\n {clipped(<CardContent className=\"[&_[data-slot=message]]:my-0\">{content}</CardContent>)}\n </Card>\n ) : (\n clipped(content)\n )}\n {shouldClip && box.isExpanded && box.isClipped && (\n <div className=\"flex justify-center pt-1\">\n <Button size=\"sm\" variant=\"ghost\" icon={<Minimize2 />} onClick={() => box.setExpanded(false)}>\n Collapse\n </Button>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport interface SpanPayloadJsonSectionProps {\n title: string;\n icon?: ReactNode;\n /** The payload as stored; shown as JSON. */\n raw: unknown;\n /** `panel` matches `DataPanel.CodeSection`; `details` matches `DataDetailsPanel.CodeSection`. */\n layout?: 'panel' | 'details';\n}\n\n/**\n * A span payload that is only worth reading as stored, like metadata or attributes.\n * Folded behind its heading by default, and shown in full as JSON once opened.\n */\nexport function SpanPayloadJsonSection({ title, icon, raw, layout = 'panel' }: SpanPayloadJsonSectionProps) {\n if (raw == null) return null;\n\n return (\n <Collapsible data-slot=\"span-payload-section\" data-view=\"raw\" className=\"group/payload flex min-w-0 flex-col gap-2\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <CollapsibleTrigger className=\"flex items-center gap-1 rounded-sm\">\n <DisclosureChevron direction=\"right\" className=\"size-3 text-placeholder\" />\n <DataPanelSectionHeading icon={icon} className={cn(layout === 'details' && 'text-meta')}>\n {title}\n </DataPanelSectionHeading>\n </CollapsibleTrigger>\n {/* Revealed on hover or keyboard focus; `pointer-fine` only, since a touch screen has no hover. */}\n <div className=\"ml-auto flex items-center gap-1 group-focus-within/payload:opacity-100 group-hover/payload:opacity-100 motion-safe:transition-opacity pointer-fine:opacity-0\">\n <CopyButton content={JSON.stringify(raw, null, 2)} variant=\"ghost\" />\n </div>\n </div>\n <CollapsibleContent>\n <Card data-slot=\"span-payload-card\" className=\"min-w-0 overflow-hidden\">\n <CardContent>\n <SpanPayloadJson value={raw} bare foldNested />\n </CardContent>\n </Card>\n </CollapsibleContent>\n </Collapsible>\n );\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_span_payload_primitives = require("../../../../span-payload-primitives-rxerCV7Y.cjs");
2
+ const require_span_payload_primitives = require("../../../../span-payload-primitives-DNhjpAtm.cjs");
3
3
  exports.SpanPayloadTool = require_span_payload_primitives.SpanPayloadTool;
4
4
  exports.SpanToolNameValue = require_span_payload_primitives.SpanToolNameValue;
@@ -1 +1 @@
1
- export { c as SpanPayloadTool, l as SpanToolNameValue } from "../../../../span-payload-primitives-Fi1kSYyM.js";
1
+ export { c as SpanPayloadTool, l as SpanToolNameValue } from "../../../../span-payload-primitives-CNDSzk1Q.js";