@mastra/playground-ui 68.0.0-alpha.2 → 68.0.0-alpha.3
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/dist/KnowledgePageGraph.css +55 -0
- package/dist/{MarkdownRenderer-2GOXQJEv.js → MarkdownRenderer-CI30RqdB.js} +19 -6
- package/dist/MarkdownRenderer-CI30RqdB.js.map +1 -0
- package/dist/{MarkdownRenderer-CB8Z_CHc.cjs → MarkdownRenderer-y65WGBhC.cjs} +19 -6
- package/dist/MarkdownRenderer-y65WGBhC.cjs.map +1 -0
- package/dist/{activity-rJ1NQl_2.js → activity-C8Ql81WM.js} +2 -2
- package/dist/{activity-rJ1NQl_2.js.map → activity-C8Ql81WM.js.map} +1 -1
- package/dist/{activity-DyB5H3gF.cjs → activity-CcQZeDYi.cjs} +2 -2
- package/dist/{activity-DyB5H3gF.cjs.map → activity-CcQZeDYi.cjs.map} +1 -1
- package/dist/components/MarkdownRenderer.cjs.js +1 -1
- package/dist/components/MarkdownRenderer.es.js +1 -1
- package/dist/components/SavedViews.cjs.js +1 -1
- package/dist/components/SavedViews.es.js +1 -1
- package/dist/components/ai/activity.cjs.js +1 -1
- package/dist/components/ai/activity.es.js +1 -1
- package/dist/components/ai/plan.cjs.js +1 -1
- package/dist/components/ai/plan.es.js +1 -1
- package/dist/components/ai/tool-approval.cjs.js +1 -1
- package/dist/components/ai/tool-approval.es.js +1 -1
- package/dist/components/ai/tool-call.cjs.js +2 -2
- package/dist/components/ai/tool-call.es.js +2 -2
- package/dist/domains/chat/activity/activity-stretch-line.cjs.js +1 -1
- package/dist/domains/chat/activity/activity-stretch-line.es.js +1 -1
- package/dist/domains/chat/activity/components/activity-fold.cjs.js +1 -1
- package/dist/domains/chat/activity/components/activity-fold.es.js +1 -1
- package/dist/domains/chat/activity/components/activity-timed-trigger.cjs.js +1 -1
- package/dist/domains/chat/activity/components/activity-timed-trigger.es.js +1 -1
- package/dist/domains/chat/activity/components/calls-panel.cjs.js +1 -1
- package/dist/domains/chat/activity/components/calls-panel.es.js +1 -1
- package/dist/domains/chat/activity/components/stretch-content.cjs.js +1 -1
- package/dist/domains/chat/activity/components/stretch-content.es.js +1 -1
- package/dist/domains/chat/activity/components/stretch-thought.cjs.js +1 -1
- package/dist/domains/chat/activity/components/stretch-thought.es.js +1 -1
- package/dist/domains/chat/activity/model/activity-segments.cjs.js +1 -1
- package/dist/domains/chat/activity/model/activity-segments.es.js +1 -1
- package/dist/domains/chat/activity/model/activity-words.cjs.js +2 -2
- package/dist/domains/chat/activity/model/activity-words.es.js +2 -2
- package/dist/domains/chat/components/badge-wrapper.cjs.js +1 -1
- package/dist/domains/chat/components/badge-wrapper.es.js +1 -1
- package/dist/domains/chat/knowledge/knowledge-links.cjs.js +52 -6
- package/dist/domains/chat/knowledge/knowledge-links.cjs.js.map +1 -1
- package/dist/domains/chat/knowledge/knowledge-links.es.js +53 -9
- package/dist/domains/chat/knowledge/knowledge-links.es.js.map +1 -1
- package/dist/domains/chat/knowledge/pinned-knowledge-data.cjs.js +10 -3
- package/dist/domains/chat/knowledge/pinned-knowledge-data.cjs.js.map +1 -1
- package/dist/domains/chat/knowledge/pinned-knowledge-data.es.js +10 -3
- package/dist/domains/chat/knowledge/pinned-knowledge-data.es.js.map +1 -1
- package/dist/domains/chat/knowledge/pinned-knowledge.cjs.js +8 -3
- package/dist/domains/chat/knowledge/pinned-knowledge.cjs.js.map +1 -1
- package/dist/domains/chat/knowledge/pinned-knowledge.es.js +8 -3
- package/dist/domains/chat/knowledge/pinned-knowledge.es.js.map +1 -1
- package/dist/domains/chat/knowledge.cjs.js +2 -0
- package/dist/domains/chat/knowledge.es.js +2 -2
- package/dist/domains/chat/messages/message-row.cjs.js +3 -3
- package/dist/domains/chat/messages/message-row.es.js +3 -3
- package/dist/domains/chat/messages/notification-signal-notice.cjs.js +1 -1
- package/dist/domains/chat/messages/notification-signal-notice.es.js +1 -1
- package/dist/domains/chat/messages/reasoning-content.cjs.js +1 -1
- package/dist/domains/chat/messages/reasoning-content.es.js +1 -1
- package/dist/domains/chat/messages/renderers/message-text.cjs.js +35 -1
- package/dist/domains/chat/messages/renderers/message-text.cjs.js.map +1 -1
- package/dist/domains/chat/messages/renderers/message-text.es.js +36 -2
- package/dist/domains/chat/messages/renderers/message-text.es.js.map +1 -1
- package/dist/domains/chat/messages/renderers/reasoning-part-renderer.cjs.js +1 -1
- package/dist/domains/chat/messages/renderers/reasoning-part-renderer.es.js +1 -1
- package/dist/domains/chat/messages/signal-badge.cjs.js +1 -1
- package/dist/domains/chat/messages/signal-badge.es.js +1 -1
- package/dist/domains/chat/messages/skill-message.cjs.js +2 -2
- package/dist/domains/chat/messages/skill-message.es.js +2 -2
- package/dist/domains/chat/messages/system-reminder-badge.cjs.js +1 -1
- package/dist/domains/chat/messages/system-reminder-badge.es.js +1 -1
- package/dist/domains/chat/tools/badges/agent-badge-wrapper.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/agent-badge-wrapper.es.js +1 -1
- package/dist/domains/chat/tools/badges/agent-badge.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/agent-badge.es.js +1 -1
- package/dist/domains/chat/tools/badges/file-tree-badge.cjs.js +2 -2
- package/dist/domains/chat/tools/badges/file-tree-badge.es.js +2 -2
- package/dist/domains/chat/tools/badges/knowledge-body-range.cjs.js +80 -0
- package/dist/domains/chat/tools/badges/knowledge-body-range.cjs.js.map +1 -0
- package/dist/domains/chat/tools/badges/knowledge-body-range.d.ts +1 -0
- package/dist/domains/chat/tools/badges/knowledge-body-range.es.js +78 -0
- package/dist/domains/chat/tools/badges/knowledge-body-range.es.js.map +1 -0
- package/dist/domains/chat/tools/badges/knowledge-tool-badge.cjs.js +163 -13
- package/dist/domains/chat/tools/badges/knowledge-tool-badge.cjs.js.map +1 -1
- package/dist/domains/chat/tools/badges/knowledge-tool-badge.es.js +165 -15
- package/dist/domains/chat/tools/badges/knowledge-tool-badge.es.js.map +1 -1
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.cjs.js +51 -0
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.cjs.js.map +1 -0
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.d.ts +1 -0
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.es.js +49 -0
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.es.js.map +1 -0
- package/dist/domains/chat/tools/badges/mcp-task-chip.cjs.js +7 -2
- package/dist/domains/chat/tools/badges/mcp-task-chip.cjs.js.map +1 -1
- package/dist/domains/chat/tools/badges/mcp-task-chip.es.js +7 -2
- package/dist/domains/chat/tools/badges/mcp-task-chip.es.js.map +1 -1
- package/dist/domains/chat/tools/badges/observation-marker-badge.cjs.js +2 -2
- package/dist/domains/chat/tools/badges/observation-marker-badge.es.js +2 -2
- package/dist/domains/chat/tools/badges/observation-marker-details.cjs.js +2 -2
- package/dist/domains/chat/tools/badges/observation-marker-details.es.js +2 -2
- package/dist/domains/chat/tools/badges/observation-renderer.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/observation-renderer.es.js +1 -1
- package/dist/domains/chat/tools/badges/sandbox-execution-badge.cjs.js +2 -2
- package/dist/domains/chat/tools/badges/sandbox-execution-badge.es.js +2 -2
- package/dist/domains/chat/tools/badges/tool-approval-badge.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/tool-approval-badge.es.js +1 -1
- package/dist/domains/chat/tools/badges/tool-badge.cjs.js +9 -4
- package/dist/domains/chat/tools/badges/tool-badge.cjs.js.map +1 -1
- package/dist/domains/chat/tools/badges/tool-badge.es.js +9 -4
- package/dist/domains/chat/tools/badges/tool-badge.es.js.map +1 -1
- package/dist/domains/chat/tools/badges/use-deferred-input-request.cjs.js +81 -0
- package/dist/domains/chat/tools/badges/use-deferred-input-request.cjs.js.map +1 -0
- package/dist/domains/chat/tools/badges/use-deferred-input-request.d.ts +1 -0
- package/dist/domains/chat/tools/badges/use-deferred-input-request.es.js +77 -0
- package/dist/domains/chat/tools/badges/use-deferred-input-request.es.js.map +1 -0
- package/dist/domains/chat/tools/badges/use-mcp-task-progress.cjs.js +11 -2
- package/dist/domains/chat/tools/badges/use-mcp-task-progress.cjs.js.map +1 -1
- package/dist/domains/chat/tools/badges/use-mcp-task-progress.es.js +11 -2
- package/dist/domains/chat/tools/badges/use-mcp-task-progress.es.js.map +1 -1
- package/dist/domains/chat/tools/badges/workflow-badge.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/workflow-badge.es.js +1 -1
- package/dist/domains/chat/tools/mcp-input-request-tool.cjs.js +240 -0
- package/dist/domains/chat/tools/mcp-input-request-tool.cjs.js.map +1 -0
- package/dist/domains/chat/tools/mcp-input-request-tool.d.ts +1 -0
- package/dist/domains/chat/tools/mcp-input-request-tool.es.js +239 -0
- package/dist/domains/chat/tools/mcp-input-request-tool.es.js.map +1 -0
- package/dist/domains/chat/tools/mcp-input-request.cjs.js +40 -0
- package/dist/domains/chat/tools/mcp-input-request.cjs.js.map +1 -0
- package/dist/domains/chat/tools/mcp-input-request.d.ts +1 -0
- package/dist/domains/chat/tools/mcp-input-request.es.js +33 -0
- package/dist/domains/chat/tools/mcp-input-request.es.js.map +1 -0
- package/dist/domains/chat/tools/tool-card-kind.cjs.js +8 -3
- package/dist/domains/chat/tools/tool-card-kind.cjs.js.map +1 -1
- package/dist/domains/chat/tools/tool-card-kind.es.js +8 -4
- package/dist/domains/chat/tools/tool-card-kind.es.js.map +1 -1
- package/dist/domains/chat/tools/tool-card.cjs.js +1 -1
- package/dist/domains/chat/tools/tool-card.es.js +1 -1
- package/dist/domains/chat/tools/tool-groups.cjs.js +1 -1
- package/dist/domains/chat/tools/tool-groups.es.js +1 -1
- package/dist/domains/chat.cjs.js +5 -3
- package/dist/domains/chat.es.js +4 -4
- package/dist/domains/knowledge/components/KnowledgePageCard.cjs.js +48 -0
- package/dist/domains/knowledge/components/KnowledgePageCard.cjs.js.map +1 -0
- package/dist/domains/knowledge/components/KnowledgePageCard.d.ts +1 -0
- package/dist/domains/knowledge/components/KnowledgePageCard.es.js +47 -0
- package/dist/domains/knowledge/components/KnowledgePageCard.es.js.map +1 -0
- package/dist/domains/knowledge/components/KnowledgePageDetail.cjs.js +63 -5
- package/dist/domains/knowledge/components/KnowledgePageDetail.cjs.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageDetail.es.js +64 -6
- package/dist/domains/knowledge/components/KnowledgePageDetail.es.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageExplorer.cjs.js +485 -47
- package/dist/domains/knowledge/components/KnowledgePageExplorer.cjs.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageExplorer.es.js +487 -50
- package/dist/domains/knowledge/components/KnowledgePageExplorer.es.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageGraph.cjs.js +1051 -123
- package/dist/domains/knowledge/components/KnowledgePageGraph.cjs.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageGraph.es.js +1054 -126
- package/dist/domains/knowledge/components/KnowledgePageGraph.es.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageTree.cjs.js +75 -3
- package/dist/domains/knowledge/components/KnowledgePageTree.cjs.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageTree.es.js +76 -4
- package/dist/domains/knowledge/components/KnowledgePageTree.es.js.map +1 -1
- package/dist/domains/knowledge/lib/circleText.cjs.js +9 -0
- package/dist/domains/knowledge/lib/circleText.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/circleText.d.ts +1 -0
- package/dist/domains/knowledge/lib/circleText.es.js +8 -0
- package/dist/domains/knowledge/lib/circleText.es.js.map +1 -0
- package/dist/domains/knowledge/lib/fitViewport.cjs.js +82 -0
- package/dist/domains/knowledge/lib/fitViewport.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/fitViewport.d.ts +1 -0
- package/dist/domains/knowledge/lib/fitViewport.es.js +73 -0
- package/dist/domains/knowledge/lib/fitViewport.es.js.map +1 -0
- package/dist/domains/knowledge/lib/graphShape.cjs.js +524 -0
- package/dist/domains/knowledge/lib/graphShape.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/graphShape.d.ts +1 -0
- package/dist/domains/knowledge/lib/graphShape.es.js +499 -0
- package/dist/domains/knowledge/lib/graphShape.es.js.map +1 -0
- package/dist/domains/knowledge/lib/linkCountsText.cjs.js +11 -0
- package/dist/domains/knowledge/lib/linkCountsText.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/linkCountsText.d.ts +1 -0
- package/dist/domains/knowledge/lib/linkCountsText.es.js +10 -0
- package/dist/domains/knowledge/lib/linkCountsText.es.js.map +1 -0
- package/dist/domains/knowledge/lib/pageAddress.cjs.js +29 -0
- package/dist/domains/knowledge/lib/pageAddress.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/pageAddress.d.ts +1 -0
- package/dist/domains/knowledge/lib/pageAddress.es.js +27 -0
- package/dist/domains/knowledge/lib/pageAddress.es.js.map +1 -0
- package/dist/domains/knowledge/lib/pageGraph.cjs.js +11 -11
- package/dist/domains/knowledge/lib/pageGraph.cjs.js.map +1 -1
- package/dist/domains/knowledge/lib/pageGraph.es.js +11 -11
- package/dist/domains/knowledge/lib/pageGraph.es.js.map +1 -1
- package/dist/domains/knowledge/lib/pageRefs.cjs.js +69 -0
- package/dist/domains/knowledge/lib/pageRefs.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/pageRefs.d.ts +1 -0
- package/dist/domains/knowledge/lib/pageRefs.es.js +66 -0
- package/dist/domains/knowledge/lib/pageRefs.es.js.map +1 -0
- package/dist/domains/knowledge/lib/pageTree.cjs.js +5 -0
- package/dist/domains/knowledge/lib/pageTree.cjs.js.map +1 -1
- package/dist/domains/knowledge/lib/pageTree.es.js +5 -1
- package/dist/domains/knowledge/lib/pageTree.es.js.map +1 -1
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.cjs.js +82 -0
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.d.ts +1 -0
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.es.js +78 -0
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.es.js.map +1 -0
- package/dist/domains/knowledge/lib/tooltipSide.cjs.js +77 -0
- package/dist/domains/knowledge/lib/tooltipSide.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/tooltipSide.d.ts +1 -0
- package/dist/domains/knowledge/lib/tooltipSide.es.js +75 -0
- package/dist/domains/knowledge/lib/tooltipSide.es.js.map +1 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.cjs.js +65 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.d.ts +1 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.es.js +62 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.es.js.map +1 -0
- package/dist/domains/knowledge/lib/useStableWhile.cjs.js +15 -0
- package/dist/domains/knowledge/lib/useStableWhile.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/useStableWhile.d.ts +1 -0
- package/dist/domains/knowledge/lib/useStableWhile.es.js +14 -0
- package/dist/domains/knowledge/lib/useStableWhile.es.js.map +1 -0
- package/dist/domains/scores/components/trace-scores-list.cjs.js +2 -2
- package/dist/domains/scores/components/trace-scores-list.es.js +2 -2
- package/dist/domains/skills/skill-simple-form.cjs.js +1 -1
- package/dist/domains/skills/skill-simple-form.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-error-renderer.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-error-renderer.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-input-renderers.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-input-renderers.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-output-renderers.cjs.js +2 -2
- package/dist/domains/traces/components/span-payload/span-output-renderers.es.js +2 -2
- package/dist/domains/traces/components/span-payload/span-payload-messages.cjs.js +2 -2
- package/dist/domains/traces/components/span-payload/span-payload-messages.es.js +2 -2
- package/dist/domains/traces/components/span-payload/span-payload-primitives.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-primitives.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-processor.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-processor.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-tool.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-tool.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-processor-mutations.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-processor-mutations.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-tools-section.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-tools-section.es.js +1 -1
- package/dist/domains/traces/components/span-timeline-row.cjs.js +1 -1
- package/dist/domains/traces/components/span-timeline-row.es.js +1 -1
- package/dist/domains/traces/components/span-timing-hover-card.cjs.js +1 -1
- package/dist/domains/traces/components/span-timing-hover-card.es.js +1 -1
- package/dist/domains/traces/components/trace-data-panel-view.cjs.js +8 -2
- package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
- package/dist/domains/traces/components/trace-data-panel-view.es.js +8 -2
- package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
- package/dist/domains/traces/components/trace-error-cell.cjs.js +1 -1
- package/dist/domains/traces/components/trace-error-cell.es.js +1 -1
- package/dist/domains/workflows/runs/workflow-run-list.cjs.js +1 -1
- package/dist/domains/workflows/runs/workflow-run-list.es.js +1 -1
- package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js +2 -2
- package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js +2 -2
- package/dist/domains/workflows/workflow/use-workflow-trigger.cjs.js +3 -3
- package/dist/domains/workflows/workflow/use-workflow-trigger.es.js +3 -3
- package/dist/domains/workflows/workflow/workflow-input-data.cjs.js +1 -1
- package/dist/domains/workflows/workflow/workflow-input-data.es.js +1 -1
- package/dist/domains/workflows/workflow/workflow-suspended-steps.cjs.js +2 -2
- package/dist/domains/workflows/workflow/workflow-suspended-steps.es.js +2 -2
- package/dist/domains/workflows/workflow/workflow-time-travel-form.cjs.js +2 -2
- package/dist/domains/workflows/workflow/workflow-time-travel-form.es.js +2 -2
- package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js +1 -1
- package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js +1 -1
- package/dist/domains/workspace/components/workspace-markdown-preview.cjs.js +1 -1
- package/dist/domains/workspace/components/workspace-markdown-preview.es.js +1 -1
- package/dist/lib/form/dynamic-form.cjs.js +2 -2
- package/dist/lib/form/dynamic-form.es.js +2 -2
- package/dist/lib/form/json-draft.cjs.js +1 -1
- package/dist/lib/form/json-draft.es.js +1 -1
- package/dist/lib/form/zod-provider.cjs.js +1 -1
- package/dist/lib/form/zod-provider.es.js +1 -1
- package/dist/{span-payload-primitives-B3RdahsC.js → span-payload-primitives-CKKIAVPJ.js} +4 -4
- package/dist/{span-payload-primitives-B3RdahsC.js.map → span-payload-primitives-CKKIAVPJ.js.map} +1 -1
- package/dist/{span-payload-primitives-_2d-pAOD.cjs → span-payload-primitives-D4tHWN2W.cjs} +4 -4
- package/dist/{span-payload-primitives-_2d-pAOD.cjs.map → span-payload-primitives-D4tHWN2W.cjs.map} +1 -1
- package/dist/src/domains/chat/knowledge/knowledge-links.d.ts +32 -4
- package/dist/src/domains/chat/knowledge/pinned-knowledge-data.d.ts +2 -0
- package/dist/src/domains/chat/tools/badges/knowledge-body-range.d.ts +12 -0
- package/dist/src/domains/chat/tools/badges/knowledge-tool-badge.d.ts +5 -2
- package/dist/src/domains/chat/tools/badges/mcp-input-request-badge.d.ts +18 -0
- package/dist/src/domains/chat/tools/badges/tool-badge.d.ts +4 -1
- package/dist/src/domains/chat/tools/badges/use-deferred-input-request.d.ts +44 -0
- package/dist/src/domains/chat/tools/badges/use-mcp-task-progress.d.ts +6 -1
- package/dist/src/domains/chat/tools/mcp-input-request-tool.d.ts +18 -0
- package/dist/src/domains/chat/tools/mcp-input-request.d.ts +40 -0
- package/dist/src/domains/chat/tools/tool-card-kind.d.ts +4 -2
- package/dist/src/domains/chat/tools/tool-card.d.ts +1 -1
- package/dist/src/domains/knowledge/components/KnowledgePageCard.d.ts +23 -0
- package/dist/src/domains/knowledge/components/KnowledgePageExplorer.d.ts +29 -0
- package/dist/src/domains/knowledge/components/KnowledgePageGraph.d.ts +27 -1
- package/dist/src/domains/knowledge/components/KnowledgePageTree.d.ts +2 -1
- package/dist/src/domains/knowledge/lib/circleText.d.ts +2 -0
- package/dist/src/domains/knowledge/lib/fitViewport.d.ts +67 -0
- package/dist/src/domains/knowledge/lib/graphShape.d.ts +131 -0
- package/dist/src/domains/knowledge/lib/linkCountsText.d.ts +5 -0
- package/dist/src/domains/knowledge/lib/pageAddress.d.ts +5 -0
- package/dist/src/domains/knowledge/lib/pageGraph.d.ts +4 -4
- package/dist/src/domains/knowledge/lib/pageRefs.d.ts +15 -0
- package/dist/src/domains/knowledge/lib/pageTree.d.ts +2 -0
- package/dist/src/domains/knowledge/lib/remarkKnowledgeLinks.d.ts +13 -0
- package/dist/src/domains/knowledge/lib/tooltipSide.d.ts +40 -0
- package/dist/src/domains/knowledge/lib/useLeavingNodes.d.ts +14 -0
- package/dist/src/domains/knowledge/lib/useStableWhile.d.ts +5 -0
- package/dist/src/domains/knowledge/pageTypes.d.ts +6 -1
- package/dist/src/ds/components/MarkdownRenderer/markdown-renderer.d.ts +8 -1
- package/dist/src/ds/components/ai/tool-call/tool-phrases.d.ts +6 -0
- package/dist/style.css +69 -2
- package/dist/{tool-approval-1qiB4hhG.cjs → tool-approval-CJvPDL7D.cjs} +4 -4
- package/dist/{tool-approval-1qiB4hhG.cjs.map → tool-approval-CJvPDL7D.cjs.map} +1 -1
- package/dist/{tool-approval-B6MFcaKV.js → tool-approval-DyN11vFA.js} +4 -4
- package/dist/{tool-approval-B6MFcaKV.js.map → tool-approval-DyN11vFA.js.map} +1 -1
- package/dist/{tool-call-Bu66PkD-.cjs → tool-call-DBn14X-3.cjs} +9 -3
- package/dist/{tool-call-Bu66PkD-.cjs.map → tool-call-DBn14X-3.cjs.map} +1 -1
- package/dist/{tool-call-Ch9-jjXU.js → tool-call-Dsj43lvJ.js} +9 -3
- package/dist/{tool-call-Ch9-jjXU.js.map → tool-call-Dsj43lvJ.js.map} +1 -1
- package/dist/{tool-card-DrqPZfPQ.cjs → tool-card-rxhTDpk_.cjs} +164 -126
- package/dist/tool-card-rxhTDpk_.cjs.map +1 -0
- package/dist/{tool-card-sO6P2Qj4.js → tool-card-toDgoZzJ.js} +165 -127
- package/dist/tool-card-toDgoZzJ.js.map +1 -0
- package/dist/{tool-presentation-DvCsb_kz.js → tool-presentation-CvibOP1J.js} +6 -1
- package/dist/tool-presentation-CvibOP1J.js.map +1 -0
- package/dist/{tool-presentation-CQlDEwgS.cjs → tool-presentation-D6nzVruN.cjs} +6 -1
- package/dist/tool-presentation-D6nzVruN.cjs.map +1 -0
- package/package.json +10 -10
- package/dist/MarkdownRenderer-2GOXQJEv.js.map +0 -1
- package/dist/MarkdownRenderer-CB8Z_CHc.cjs.map +0 -1
- package/dist/domains/knowledge/lib/pageLayout.cjs.js +0 -49
- package/dist/domains/knowledge/lib/pageLayout.cjs.js.map +0 -1
- package/dist/domains/knowledge/lib/pageLayout.d.ts +0 -1
- package/dist/domains/knowledge/lib/pageLayout.es.js +0 -48
- package/dist/domains/knowledge/lib/pageLayout.es.js.map +0 -1
- package/dist/src/domains/knowledge/lib/pageLayout.d.ts +0 -24
- package/dist/tool-card-DrqPZfPQ.cjs.map +0 -1
- package/dist/tool-card-sO6P2Qj4.js.map +0 -1
- package/dist/tool-presentation-CQlDEwgS.cjs.map +0 -1
- package/dist/tool-presentation-DvCsb_kz.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-mcp-task-progress.es.js","names":[],"sources":["../../../../../src/domains/chat/tools/badges/use-mcp-task-progress.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport type { ActivityStatus } from '@/ds/components/ai/activity';\n\nexport type McpTaskStatus = 'working' | 'input_required' | 'completed' | 'failed' | 'cancelled';\n\n/** What `@mastra/mcp`'s client writes to a task-backed tool's output stream (`MCPTaskProgress`). */\nexport interface McpTaskProgress {\n type: 'mcp-task';\n taskId: string;\n status: McpTaskStatus;\n createdAt: string;\n serverName: string;\n}\n\nconst STATUSES: ReadonlySet<string> = new Set(['working', 'input_required', 'completed', 'failed', 'cancelled']);\n\nexport const isTerminalMcpTaskStatus = (status: McpTaskStatus) =>\n status === 'completed' || status === 'failed' || status === 'cancelled';\n\nfunction isMcpTaskProgress(value: unknown): value is McpTaskProgress {\n if (typeof value !== 'object' || value === null) return false;\n const entry = value as Record<string, unknown>;\n return (\n entry.type === 'mcp-task' &&\n typeof entry.taskId === 'string' &&\n typeof entry.createdAt === 'string' &&\n typeof entry.serverName === 'string' &&\n typeof entry.status === 'string' &&\n STATUSES.has(entry.status)\n );\n}\n\n/** While a tool call runs, its progress writes accumulate as the call's `result` array. */\nfunction latestProgress(result: unknown): McpTaskProgress | undefined {\n if (!Array.isArray(result)) return undefined;\n for (let index = result.length - 1; index >= 0; index--) {\n if (isMcpTaskProgress(result[index])) return result[index];\n }\n return undefined;\n}\n\nexport interface McpTaskView extends McpTaskProgress {\n /** When the card saw the task end; the elapsed time stops here. */\n endedAt?: number;\n}\n\n/**\n * The MCP task behind a tool call, if the call continued as one. The final result replaces the\n * progress writes, so the last one seen is kept for as long as the card is mounted; its terminal\n * status then comes from how the call ended. Progress isn't saved with the thread, so a reloaded\n * card has no task to show.\n *\n * A deferred call (one running as a Mastra background task) settles its part with a placeholder\n * long before the task ends, so its end is never inferred here: the background task says when.\n */\nexport function useMcpTaskProgress(\n result: unknown,\n status: ActivityStatus,\n { deferred = false }: { deferred?: boolean } = {},\n): McpTaskView | undefined {\n const live = latestProgress(result);\n const [seen, setSeen] = useState(live);\n if (live && (live.taskId !== seen?.taskId || live.status !== seen.status)) setSeen(live);\n\n const task = live ?? seen;\n const ended = task && !live && !deferred && status !== 'running';\n const taskStatus: McpTaskStatus | undefined = !task\n ? undefined\n : ended && !isTerminalMcpTaskStatus(task.status)\n ? status === 'error'\n ? 'failed'\n : 'completed'\n : task.status;\n const terminal = taskStatus !== undefined && isTerminalMcpTaskStatus(taskStatus);\n\n const [endedAt, setEndedAt] = useState<number>();\n useEffect(() => {\n if (terminal && endedAt === undefined) setEndedAt(Date.now());\n }, [terminal, endedAt]);\n\n return task && taskStatus ? { ...task, status: taskStatus, endedAt } : undefined;\n}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"use-mcp-task-progress.es.js","names":[],"sources":["../../../../../src/domains/chat/tools/badges/use-mcp-task-progress.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport type { McpInputRequestPayload } from '../mcp-input-request';\nimport type { ActivityStatus } from '@/ds/components/ai/activity';\n\nexport type McpTaskStatus = 'working' | 'input_required' | 'completed' | 'failed' | 'cancelled';\n\n/** What `@mastra/mcp`'s client writes to a task-backed tool's output stream (`MCPTaskProgress`). */\nexport interface McpTaskProgress {\n type: 'mcp-task';\n taskId: string;\n status: McpTaskStatus;\n createdAt: string;\n serverName: string;\n}\n\nconst STATUSES: ReadonlySet<string> = new Set(['working', 'input_required', 'completed', 'failed', 'cancelled']);\n\nexport const isTerminalMcpTaskStatus = (status: McpTaskStatus) =>\n status === 'completed' || status === 'failed' || status === 'cancelled';\n\nfunction isMcpTaskProgress(value: unknown): value is McpTaskProgress {\n if (typeof value !== 'object' || value === null) return false;\n const entry = value as Record<string, unknown>;\n return (\n entry.type === 'mcp-task' &&\n typeof entry.taskId === 'string' &&\n typeof entry.createdAt === 'string' &&\n typeof entry.serverName === 'string' &&\n typeof entry.status === 'string' &&\n STATUSES.has(entry.status)\n );\n}\n\n/** While a tool call runs, its progress writes accumulate as the call's `result` array. */\nfunction latestProgress(result: unknown): McpTaskProgress | undefined {\n if (!Array.isArray(result)) return undefined;\n for (let index = result.length - 1; index >= 0; index--) {\n if (isMcpTaskProgress(result[index])) return result[index];\n }\n return undefined;\n}\n\nexport interface McpTaskView extends McpTaskProgress {\n /** When the card saw the task end; the elapsed time stops here. */\n endedAt?: number;\n}\n\n/**\n * The MCP task behind a tool call, if the call continued as one. The final result replaces the\n * progress writes, so the last one seen is kept for as long as the card is mounted; its terminal\n * status then comes from how the call ended. Progress isn't saved with the thread, so a reloaded\n * card has no task to show.\n *\n * A deferred call (one running as a Mastra background task) settles its part with a placeholder\n * long before the task ends, so its end is never inferred here: the background task says when.\n *\n * While the call is suspended on the task's input request, the request names the task, so the chip\n * reads `input_required` even on a reloaded card with no progress.\n */\nexport function useMcpTaskProgress(\n result: unknown,\n status: ActivityStatus,\n { deferred = false, request }: { deferred?: boolean; request?: McpInputRequestPayload } = {},\n): McpTaskView | undefined {\n const live: McpTaskProgress | undefined = request\n ? {\n type: 'mcp-task',\n taskId: request.taskId,\n status: 'input_required',\n createdAt: request.createdAt,\n serverName: request.serverName,\n }\n : latestProgress(result);\n const [seen, setSeen] = useState(live);\n if (live && (live.taskId !== seen?.taskId || live.status !== seen.status)) setSeen(live);\n\n const task = live ?? seen;\n const ended = task && !live && !deferred && status !== 'running';\n const taskStatus: McpTaskStatus | undefined = !task\n ? undefined\n : ended && !isTerminalMcpTaskStatus(task.status)\n ? status === 'error'\n ? 'failed'\n : 'completed'\n : task.status;\n const terminal = taskStatus !== undefined && isTerminalMcpTaskStatus(taskStatus);\n\n const [endedAt, setEndedAt] = useState<number>();\n useEffect(() => {\n if (terminal && endedAt === undefined) setEndedAt(Date.now());\n }, [terminal, endedAt]);\n\n return task && taskStatus ? { ...task, status: taskStatus, endedAt } : undefined;\n}\n"],"mappings":";;AAeA,IAAM,2BAAgC,IAAI,IAAI;CAAC;CAAW;CAAkB;CAAa;CAAU;AAAW,CAAC;AAE/G,IAAa,2BAA2B,WACtC,WAAW,eAAe,WAAW,YAAY,WAAW;AAE9D,SAAS,kBAAkB,OAA0C;CACnE,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,QAAQ;CACd,OACE,MAAM,SAAS,cACf,OAAO,MAAM,WAAW,YACxB,OAAO,MAAM,cAAc,YAC3B,OAAO,MAAM,eAAe,YAC5B,OAAO,MAAM,WAAW,YACxB,SAAS,IAAI,MAAM,MAAM;AAE7B;;AAGA,SAAS,eAAe,QAA8C;CACpE,IAAI,CAAC,MAAM,QAAQ,MAAM,GAAG,OAAO,KAAA;CACnC,KAAK,IAAI,QAAQ,OAAO,SAAS,GAAG,SAAS,GAAG,SAC9C,IAAI,kBAAkB,OAAO,MAAM,GAAG,OAAO,OAAO;AAGxD;;;;;;;;;;;;;AAmBA,SAAgB,mBACd,QACA,QACA,EAAE,WAAW,OAAO,YAAsE,CAAC,GAClE;CACzB,MAAM,OAAoC,UACtC;EACE,MAAM;EACN,QAAQ,QAAQ;EAChB,QAAQ;EACR,WAAW,QAAQ;EACnB,YAAY,QAAQ;CACtB,IACA,eAAe,MAAM;CACzB,MAAM,CAAC,MAAM,WAAW,SAAS,IAAI;CACrC,IAAI,SAAS,KAAK,WAAW,MAAM,UAAU,KAAK,WAAW,KAAK,SAAS,QAAQ,IAAI;CAEvF,MAAM,OAAO,QAAQ;CAErB,MAAM,aAAwC,CAAC,OAC3C,KAAA,IAFU,QAAQ,CAAC,QAAQ,CAAC,YAAY,WAAW,aAG1C,CAAC,wBAAwB,KAAK,MAAM,IAC3C,WAAW,UACT,WACA,cACF,KAAK;CACX,MAAM,WAAW,eAAe,KAAA,KAAa,wBAAwB,UAAU;CAE/E,MAAM,CAAC,SAAS,cAAc,SAAiB;CAC/C,gBAAgB;EACd,IAAI,YAAY,YAAY,KAAA,GAAW,WAAW,KAAK,IAAI,CAAC;CAC9D,GAAG,CAAC,UAAU,OAAO,CAAC;CAEtB,OAAO,QAAQ,aAAa;EAAE,GAAG;EAAM,QAAQ;EAAY;CAAQ,IAAI,KAAA;AACzE"}
|
|
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
const require_lib_framework = require("../../../../lib/framework.cjs.js");
|
|
3
3
|
const require_Button = require("../../../../Button-DLcMcuUL.cjs");
|
|
4
4
|
const require_icons_WorkflowIcon = require("../../../../icons/WorkflowIcon.cjs.js");
|
|
5
|
-
const require_tool_call = require("../../../../tool-call-
|
|
5
|
+
const require_tool_call = require("../../../../tool-call-DBn14X-3.cjs");
|
|
6
6
|
const require_CodeEditor = require("../../../../CodeEditor-CLzs0yVc.cjs");
|
|
7
7
|
const require_domains_chat_components_loading_badge = require("../../components/loading-badge.cjs.js");
|
|
8
8
|
const require_domains_chat_components_network_choice_metadata_dialog = require("../../components/network-choice-metadata-dialog.cjs.js");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useLinkComponent } from "../../../../lib/framework.es.js";
|
|
2
2
|
import { t as Button } from "../../../../Button-CLXTbAY8.js";
|
|
3
3
|
import { WorkflowIcon as WorkflowIcon$1 } from "../../../../icons/WorkflowIcon.es.js";
|
|
4
|
-
import { c as ToolCallMono } from "../../../../tool-call-
|
|
4
|
+
import { c as ToolCallMono } from "../../../../tool-call-Dsj43lvJ.js";
|
|
5
5
|
import { t as CodeEditor } from "../../../../CodeEditor-COnz9c6B.js";
|
|
6
6
|
import { LoadingBadge } from "../../components/loading-badge.es.js";
|
|
7
7
|
import { NetworkChoiceMetadataDialogTrigger } from "../../components/network-choice-metadata-dialog.es.js";
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_Button = require("../../../Button-DLcMcuUL.cjs");
|
|
3
|
+
const require_Txt = require("../../../Txt-BnoSqxKE.cjs");
|
|
4
|
+
const require_CodeEditor = require("../../../CodeEditor-CLzs0yVc.cjs");
|
|
5
|
+
const require_Notice = require("../../../Notice-JZ7SW7q6.cjs");
|
|
6
|
+
const require_domains_chat_tools_mcp_input_request = require("./mcp-input-request.cjs.js");
|
|
7
|
+
const require_ask_user = require("../../../ask-user-C1p2PEYe.cjs");
|
|
8
|
+
const require_lib_form_dynamic_form = require("../../../lib/form/dynamic-form.cjs.js");
|
|
9
|
+
const require_lib_form_json_schema_to_zod_runtime = require("../../../lib/form/json-schema-to-zod-runtime.cjs.js");
|
|
10
|
+
let react = require("react");
|
|
11
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
12
|
+
let lucide_react = require("lucide-react");
|
|
13
|
+
// src/domains/chat/tools/mcp-input-request-tool.tsx
|
|
14
|
+
var ACTION_LABEL = {
|
|
15
|
+
accept: "Accepted",
|
|
16
|
+
decline: "Declined",
|
|
17
|
+
cancel: "Cancelled"
|
|
18
|
+
};
|
|
19
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20
|
+
var httpUrl = (value) => {
|
|
21
|
+
if (typeof value !== "string") return void 0;
|
|
22
|
+
try {
|
|
23
|
+
const url = new URL(value);
|
|
24
|
+
return url.protocol === "https:" || url.protocol === "http:" ? url.href : void 0;
|
|
25
|
+
} catch {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
/** More fields than any real question needs; a bigger form is not one Studio should draw. */
|
|
30
|
+
var MAX_FORM_FIELDS = 100;
|
|
31
|
+
var FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
32
|
+
"string",
|
|
33
|
+
"number",
|
|
34
|
+
"integer",
|
|
35
|
+
"boolean"
|
|
36
|
+
]);
|
|
37
|
+
var FIELD_KEYS = [
|
|
38
|
+
"type",
|
|
39
|
+
"title",
|
|
40
|
+
"description",
|
|
41
|
+
"default",
|
|
42
|
+
"enum",
|
|
43
|
+
"enumNames",
|
|
44
|
+
"format",
|
|
45
|
+
"minLength",
|
|
46
|
+
"maxLength",
|
|
47
|
+
"minimum",
|
|
48
|
+
"maximum"
|
|
49
|
+
];
|
|
50
|
+
var isStringList = (value) => Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
51
|
+
/**
|
|
52
|
+
* The MCP spec limits `requestedSchema` to a flat object of primitive fields. Keep only that shape, so a
|
|
53
|
+
* server can't hand Studio a deep or huge schema to convert; anything else isn't a form Studio draws.
|
|
54
|
+
*/
|
|
55
|
+
function formSchema(requested) {
|
|
56
|
+
const { type, properties, required } = requested;
|
|
57
|
+
if (type !== "object" || !isRecord(properties)) return void 0;
|
|
58
|
+
const entries = Object.entries(properties);
|
|
59
|
+
if (entries.length > MAX_FORM_FIELDS) return void 0;
|
|
60
|
+
const fields = {};
|
|
61
|
+
for (const [key, field] of entries) {
|
|
62
|
+
if (!isRecord(field) || typeof field.type !== "string" || !FIELD_TYPES.has(field.type)) return void 0;
|
|
63
|
+
if (field.enum !== void 0 && !isStringList(field.enum)) return void 0;
|
|
64
|
+
fields[key] = Object.fromEntries(FIELD_KEYS.filter((name) => field[name] !== void 0).map((name) => [name, field[name]]));
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
type: "object",
|
|
68
|
+
properties: fields,
|
|
69
|
+
...isStringList(required) ? { required } : {}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function viewRequest({ method, params }) {
|
|
73
|
+
const message = typeof params?.message === "string" ? params.message : void 0;
|
|
74
|
+
if (method !== "elicitation/create") return {
|
|
75
|
+
kind: "unsupported",
|
|
76
|
+
message
|
|
77
|
+
};
|
|
78
|
+
const url = params?.mode === "url" ? httpUrl(params.url) : void 0;
|
|
79
|
+
if (url) return {
|
|
80
|
+
kind: "url",
|
|
81
|
+
message,
|
|
82
|
+
url
|
|
83
|
+
};
|
|
84
|
+
const schema = params?.mode !== "url" && isRecord(params?.requestedSchema) ? formSchema(params.requestedSchema) : void 0;
|
|
85
|
+
if (schema) return {
|
|
86
|
+
kind: "form",
|
|
87
|
+
message,
|
|
88
|
+
schema
|
|
89
|
+
};
|
|
90
|
+
return {
|
|
91
|
+
kind: "unsupported",
|
|
92
|
+
message
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The questions an MCP server asked while a tool call's task waits. Every request key needs an answer
|
|
97
|
+
* before the call can continue, so answers are held until the last one is given, then sent together.
|
|
98
|
+
*/
|
|
99
|
+
function McpInputRequestTool({ payload, onSubmit, isSubmitting, error, readOnly, notice }) {
|
|
100
|
+
const [answers, setAnswers] = (0, react.useState)({});
|
|
101
|
+
const keys = Object.keys(payload.requests);
|
|
102
|
+
const tooLarge = (0, react.useMemo)(() => require_domains_chat_tools_mcp_input_request.inputRequestTooLarge(payload), [payload]);
|
|
103
|
+
const send = (inputResponses) => {
|
|
104
|
+
Promise.resolve(onSubmit({ inputResponses })).catch(() => setAnswers({}));
|
|
105
|
+
};
|
|
106
|
+
const answer = (key, response) => {
|
|
107
|
+
const next = {
|
|
108
|
+
...answers,
|
|
109
|
+
[key]: response
|
|
110
|
+
};
|
|
111
|
+
setAnswers(next);
|
|
112
|
+
if (!keys.every((requestKey) => next[requestKey])) return;
|
|
113
|
+
send(next);
|
|
114
|
+
};
|
|
115
|
+
const cancelAll = () => {
|
|
116
|
+
const next = Object.fromEntries(keys.map((key) => [key, { action: "cancel" }]));
|
|
117
|
+
setAnswers(next);
|
|
118
|
+
send(next);
|
|
119
|
+
};
|
|
120
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_ask_user.AskUserContainer, {
|
|
121
|
+
className: "mb-4",
|
|
122
|
+
"data-testid": "mcp-input-request",
|
|
123
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_ask_user.AskUserLabel, { children: [
|
|
124
|
+
payload.serverName,
|
|
125
|
+
" needs input to continue ",
|
|
126
|
+
payload.toolName
|
|
127
|
+
] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_ask_user.AskUserBody, {
|
|
128
|
+
className: "flex flex-col gap-4",
|
|
129
|
+
children: [
|
|
130
|
+
notice && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Notice.Notice, {
|
|
131
|
+
variant: "info",
|
|
132
|
+
children: notice
|
|
133
|
+
}),
|
|
134
|
+
tooLarge ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_Txt.Txt, {
|
|
135
|
+
tone: "muted",
|
|
136
|
+
children: [payload.serverName, " sent more than Studio can show here."]
|
|
137
|
+
}), !readOnly && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
138
|
+
className: "flex gap-2",
|
|
139
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.Button, {
|
|
140
|
+
type: "button",
|
|
141
|
+
variant: "ghost",
|
|
142
|
+
disabled: isSubmitting || Object.keys(answers).length > 0,
|
|
143
|
+
onClick: cancelAll,
|
|
144
|
+
children: "Cancel"
|
|
145
|
+
})
|
|
146
|
+
})] }) : Object.entries(payload.requests).map(([key, request]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InputRequest, {
|
|
147
|
+
requestKey: key,
|
|
148
|
+
request,
|
|
149
|
+
answered: answers[key]?.action,
|
|
150
|
+
disabled: readOnly || isSubmitting || answers[key] !== void 0,
|
|
151
|
+
readOnly,
|
|
152
|
+
onAnswer: (response) => answer(key, response)
|
|
153
|
+
}, key)),
|
|
154
|
+
error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Notice.Notice, {
|
|
155
|
+
variant: "destructive",
|
|
156
|
+
role: "alert",
|
|
157
|
+
children: error
|
|
158
|
+
})
|
|
159
|
+
]
|
|
160
|
+
})]
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
function InputRequest({ requestKey, request, answered, disabled, readOnly, onAnswer }) {
|
|
164
|
+
const view = (0, react.useMemo)(() => viewRequest(request), [request]);
|
|
165
|
+
const schema = (0, react.useMemo)(() => view.kind === "form" ? require_lib_form_json_schema_to_zod_runtime.jsonSchemaToZodRuntime(view.schema) : void 0, [view]);
|
|
166
|
+
const decline = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.Button, {
|
|
167
|
+
type: "button",
|
|
168
|
+
disabled,
|
|
169
|
+
onClick: () => onAnswer({ action: "decline" }),
|
|
170
|
+
children: "Decline"
|
|
171
|
+
});
|
|
172
|
+
const cancel = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.Button, {
|
|
173
|
+
type: "button",
|
|
174
|
+
variant: "ghost",
|
|
175
|
+
disabled,
|
|
176
|
+
onClick: () => onAnswer({ action: "cancel" }),
|
|
177
|
+
children: "Cancel"
|
|
178
|
+
});
|
|
179
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
180
|
+
"aria-label": `Input request ${requestKey}`,
|
|
181
|
+
className: "flex flex-col gap-3",
|
|
182
|
+
children: [view.message && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Txt.Txt, {
|
|
183
|
+
variant: "subheading",
|
|
184
|
+
tone: "ink",
|
|
185
|
+
children: view.message
|
|
186
|
+
}), answered ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Txt.Txt, {
|
|
187
|
+
tone: "muted",
|
|
188
|
+
children: ACTION_LABEL[answered]
|
|
189
|
+
}) : readOnly ? null : view.kind === "form" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_lib_form_dynamic_form.DynamicForm, {
|
|
190
|
+
schema,
|
|
191
|
+
onSubmit: (values) => onAnswer({
|
|
192
|
+
action: "accept",
|
|
193
|
+
content: isRecord(values) ? values : {}
|
|
194
|
+
}),
|
|
195
|
+
isSubmitLoading: disabled,
|
|
196
|
+
submitButtonLabel: "Accept",
|
|
197
|
+
submitButtonVariant: "primary",
|
|
198
|
+
submitActions: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [decline, cancel] })
|
|
199
|
+
}) : view.kind === "url" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
200
|
+
className: "flex flex-wrap items-center gap-2",
|
|
201
|
+
children: [
|
|
202
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.Button, {
|
|
203
|
+
variant: "link",
|
|
204
|
+
render: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
205
|
+
href: view.url,
|
|
206
|
+
target: "_blank",
|
|
207
|
+
rel: "noopener noreferrer"
|
|
208
|
+
}),
|
|
209
|
+
iconEnd: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ExternalLink, {}),
|
|
210
|
+
children: "Open link"
|
|
211
|
+
}),
|
|
212
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.Button, {
|
|
213
|
+
type: "button",
|
|
214
|
+
variant: "primary",
|
|
215
|
+
disabled,
|
|
216
|
+
onClick: () => onAnswer({ action: "accept" }),
|
|
217
|
+
children: "Done"
|
|
218
|
+
}),
|
|
219
|
+
cancel
|
|
220
|
+
]
|
|
221
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
222
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_Txt.Txt, {
|
|
223
|
+
tone: "muted",
|
|
224
|
+
children: [
|
|
225
|
+
"Studio can't answer a ",
|
|
226
|
+
request.method,
|
|
227
|
+
" request."
|
|
228
|
+
]
|
|
229
|
+
}),
|
|
230
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_CodeEditor.CodeEditor, { data: { ...request } }),
|
|
231
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
232
|
+
className: "flex gap-2",
|
|
233
|
+
children: cancel
|
|
234
|
+
})
|
|
235
|
+
] })]
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
exports.McpInputRequestTool = McpInputRequestTool;
|
|
239
|
+
|
|
240
|
+
//# sourceMappingURL=mcp-input-request-tool.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-input-request-tool.cjs.js","names":["useState","useMemo","inputRequestTooLarge","AskUserContainer","AskUserLabel","AskUserBody","Notice","_Fragment","Txt","Button","jsonSchemaToZodRuntime","DynamicForm","ExternalLink","CodeEditor"],"sources":["../../../../src/domains/chat/tools/mcp-input-request-tool.tsx"],"sourcesContent":["import { ExternalLink } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport type {\n McpInputAction,\n McpInputRequest,\n McpInputRequestPayload,\n McpInputResponse,\n McpInputResumeData,\n} from './mcp-input-request';\nimport { inputRequestTooLarge } from './mcp-input-request';\nimport { AskUserBody, AskUserContainer, AskUserLabel } from '@/ds/components/ai/ask-user';\nimport { Button } from '@/ds/components/Button';\nimport { CodeEditor } from '@/ds/components/CodeEditor';\nimport { Notice } from '@/ds/components/Notice';\nimport { Txt } from '@/ds/components/Txt';\nimport { DynamicForm } from '@/lib/form/dynamic-form';\nimport { jsonSchemaToZodRuntime } from '@/lib/form/json-schema-to-zod-runtime';\n\nexport interface McpInputRequestToolProps {\n payload: McpInputRequestPayload;\n /** Sends the answers; the request stays open (and answerable again) if the returned promise rejects. */\n onSubmit: (resumeData: McpInputResumeData) => void | Promise<unknown>;\n isSubmitting?: boolean;\n /** Why the last answer didn't go through. */\n error?: string;\n /** History view: show the question without answering it. */\n readOnly?: boolean;\n /** Why the request can't be answered here, shown with the questions. */\n notice?: string;\n}\n\nconst ACTION_LABEL: Record<McpInputAction, string> = {\n accept: 'Accepted',\n decline: 'Declined',\n cancel: 'Cancelled',\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\ntype RequestView =\n | { kind: 'form'; message?: string; schema: Record<string, unknown> }\n | { kind: 'url'; message?: string; url: string }\n | { kind: 'unsupported'; message?: string };\n\nconst httpUrl = (value: unknown): string | undefined => {\n if (typeof value !== 'string') return undefined;\n try {\n const url = new URL(value);\n return url.protocol === 'https:' || url.protocol === 'http:' ? url.href : undefined;\n } catch {\n return undefined;\n }\n};\n\n/** More fields than any real question needs; a bigger form is not one Studio should draw. */\nconst MAX_FORM_FIELDS = 100;\nconst FIELD_TYPES = new Set(['string', 'number', 'integer', 'boolean']);\n// Keywords the MCP spec allows on a requested field. `pattern` isn't one: a server-chosen regex would\n// run against every keystroke.\nconst FIELD_KEYS = [\n 'type',\n 'title',\n 'description',\n 'default',\n 'enum',\n 'enumNames',\n 'format',\n 'minLength',\n 'maxLength',\n 'minimum',\n 'maximum',\n];\n\nconst isStringList = (value: unknown): value is string[] =>\n Array.isArray(value) && value.every(item => typeof item === 'string');\n\n/**\n * The MCP spec limits `requestedSchema` to a flat object of primitive fields. Keep only that shape, so a\n * server can't hand Studio a deep or huge schema to convert; anything else isn't a form Studio draws.\n */\nfunction formSchema(requested: Record<string, unknown>): Record<string, unknown> | undefined {\n const { type, properties, required } = requested;\n if (type !== 'object' || !isRecord(properties)) return undefined;\n const entries = Object.entries(properties);\n if (entries.length > MAX_FORM_FIELDS) return undefined;\n const fields: Record<string, Record<string, unknown>> = {};\n for (const [key, field] of entries) {\n if (!isRecord(field) || typeof field.type !== 'string' || !FIELD_TYPES.has(field.type)) return undefined;\n if (field.enum !== undefined && !isStringList(field.enum)) return undefined;\n fields[key] = Object.fromEntries(\n FIELD_KEYS.filter(name => field[name] !== undefined).map(name => [name, field[name]]),\n );\n }\n return { type: 'object', properties: fields, ...(isStringList(required) ? { required } : {}) };\n}\n\nfunction viewRequest({ method, params }: McpInputRequest): RequestView {\n const message = typeof params?.message === 'string' ? params.message : undefined;\n if (method !== 'elicitation/create') return { kind: 'unsupported', message };\n // Only web links: a server-chosen `javascript:` URL must not become a clickable link.\n const url = params?.mode === 'url' ? httpUrl(params.url) : undefined;\n if (url) return { kind: 'url', message, url };\n const schema =\n params?.mode !== 'url' && isRecord(params?.requestedSchema) ? formSchema(params.requestedSchema) : undefined;\n if (schema) return { kind: 'form', message, schema };\n return { kind: 'unsupported', message };\n}\n\n/**\n * The questions an MCP server asked while a tool call's task waits. Every request key needs an answer\n * before the call can continue, so answers are held until the last one is given, then sent together.\n */\nexport function McpInputRequestTool({\n payload,\n onSubmit,\n isSubmitting,\n error,\n readOnly,\n notice,\n}: McpInputRequestToolProps) {\n const [answers, setAnswers] = useState<Record<string, McpInputResponse>>({});\n const keys = Object.keys(payload.requests);\n const tooLarge = useMemo(() => inputRequestTooLarge(payload), [payload]);\n\n const send = (inputResponses: Record<string, McpInputResponse>) => {\n void Promise.resolve(onSubmit({ inputResponses })).catch(() => setAnswers({}));\n };\n\n const answer = (key: string, response: McpInputResponse) => {\n const next = { ...answers, [key]: response };\n setAnswers(next);\n if (!keys.every(requestKey => next[requestKey])) return;\n send(next);\n };\n\n const cancelAll = () => {\n const next = Object.fromEntries(keys.map(key => [key, { action: 'cancel' as const }]));\n setAnswers(next);\n send(next);\n };\n\n return (\n <AskUserContainer className=\"mb-4\" data-testid=\"mcp-input-request\">\n <AskUserLabel>\n {payload.serverName} needs input to continue {payload.toolName}\n </AskUserLabel>\n <AskUserBody className=\"flex flex-col gap-4\">\n {notice && <Notice variant=\"info\">{notice}</Notice>}\n {tooLarge ? (\n <>\n <Txt tone=\"muted\">{payload.serverName} sent more than Studio can show here.</Txt>\n {!readOnly && (\n <div className=\"flex gap-2\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={isSubmitting || Object.keys(answers).length > 0}\n onClick={cancelAll}\n >\n Cancel\n </Button>\n </div>\n )}\n </>\n ) : (\n Object.entries(payload.requests).map(([key, request]) => (\n <InputRequest\n key={key}\n requestKey={key}\n request={request}\n answered={answers[key]?.action}\n disabled={readOnly || isSubmitting || answers[key] !== undefined}\n readOnly={readOnly}\n onAnswer={response => answer(key, response)}\n />\n ))\n )}\n {error && (\n <Notice variant=\"destructive\" role=\"alert\">\n {error}\n </Notice>\n )}\n </AskUserBody>\n </AskUserContainer>\n );\n}\n\nfunction InputRequest({\n requestKey,\n request,\n answered,\n disabled,\n readOnly,\n onAnswer,\n}: {\n requestKey: string;\n request: McpInputRequest;\n answered?: McpInputAction;\n disabled?: boolean;\n readOnly?: boolean;\n onAnswer: (response: McpInputResponse) => void;\n}) {\n const view = useMemo(() => viewRequest(request), [request]);\n const schema = useMemo(() => (view.kind === 'form' ? jsonSchemaToZodRuntime(view.schema) : undefined), [view]);\n\n const decline = (\n <Button type=\"button\" disabled={disabled} onClick={() => onAnswer({ action: 'decline' })}>\n Decline\n </Button>\n );\n const cancel = (\n <Button type=\"button\" variant=\"ghost\" disabled={disabled} onClick={() => onAnswer({ action: 'cancel' })}>\n Cancel\n </Button>\n );\n\n return (\n <section aria-label={`Input request ${requestKey}`} className=\"flex flex-col gap-3\">\n {view.message && (\n <Txt variant=\"subheading\" tone=\"ink\">\n {view.message}\n </Txt>\n )}\n {answered ? (\n <Txt tone=\"muted\">{ACTION_LABEL[answered]}</Txt>\n ) : readOnly ? null : view.kind === 'form' ? (\n <DynamicForm\n schema={schema}\n onSubmit={values => onAnswer({ action: 'accept', content: isRecord(values) ? values : {} })}\n isSubmitLoading={disabled}\n submitButtonLabel=\"Accept\"\n submitButtonVariant=\"primary\"\n submitActions={\n <>\n {decline}\n {cancel}\n </>\n }\n />\n ) : view.kind === 'url' ? (\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n variant=\"link\"\n render={<a href={view.url} target=\"_blank\" rel=\"noopener noreferrer\" />}\n iconEnd={<ExternalLink />}\n >\n Open link\n </Button>\n <Button type=\"button\" variant=\"primary\" disabled={disabled} onClick={() => onAnswer({ action: 'accept' })}>\n Done\n </Button>\n {cancel}\n </div>\n ) : (\n <>\n <Txt tone=\"muted\">Studio can't answer a {request.method} request.</Txt>\n <CodeEditor data={{ ...request }} />\n <div className=\"flex gap-2\">{cancel}</div>\n </>\n )}\n </section>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../../src/domains/chat/tools/mcp-input-request-tool';
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { t as Button } from "../../../Button-CLXTbAY8.js";
|
|
2
|
+
import { t as Txt } from "../../../Txt-BM6TVV_c.js";
|
|
3
|
+
import { t as CodeEditor } from "../../../CodeEditor-COnz9c6B.js";
|
|
4
|
+
import { t as Notice } from "../../../Notice-C-8oOZZF.js";
|
|
5
|
+
import { inputRequestTooLarge } from "./mcp-input-request.es.js";
|
|
6
|
+
import { c as AskUserBody, l as AskUserContainer, u as AskUserLabel } from "../../../ask-user-DPznrqGO.js";
|
|
7
|
+
import { DynamicForm } from "../../../lib/form/dynamic-form.es.js";
|
|
8
|
+
import { jsonSchemaToZodRuntime } from "../../../lib/form/json-schema-to-zod-runtime.es.js";
|
|
9
|
+
import { useMemo, useState } from "react";
|
|
10
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { ExternalLink } from "lucide-react";
|
|
12
|
+
// src/domains/chat/tools/mcp-input-request-tool.tsx
|
|
13
|
+
var ACTION_LABEL = {
|
|
14
|
+
accept: "Accepted",
|
|
15
|
+
decline: "Declined",
|
|
16
|
+
cancel: "Cancelled"
|
|
17
|
+
};
|
|
18
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19
|
+
var httpUrl = (value) => {
|
|
20
|
+
if (typeof value !== "string") return void 0;
|
|
21
|
+
try {
|
|
22
|
+
const url = new URL(value);
|
|
23
|
+
return url.protocol === "https:" || url.protocol === "http:" ? url.href : void 0;
|
|
24
|
+
} catch {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
/** More fields than any real question needs; a bigger form is not one Studio should draw. */
|
|
29
|
+
var MAX_FORM_FIELDS = 100;
|
|
30
|
+
var FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
31
|
+
"string",
|
|
32
|
+
"number",
|
|
33
|
+
"integer",
|
|
34
|
+
"boolean"
|
|
35
|
+
]);
|
|
36
|
+
var FIELD_KEYS = [
|
|
37
|
+
"type",
|
|
38
|
+
"title",
|
|
39
|
+
"description",
|
|
40
|
+
"default",
|
|
41
|
+
"enum",
|
|
42
|
+
"enumNames",
|
|
43
|
+
"format",
|
|
44
|
+
"minLength",
|
|
45
|
+
"maxLength",
|
|
46
|
+
"minimum",
|
|
47
|
+
"maximum"
|
|
48
|
+
];
|
|
49
|
+
var isStringList = (value) => Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
50
|
+
/**
|
|
51
|
+
* The MCP spec limits `requestedSchema` to a flat object of primitive fields. Keep only that shape, so a
|
|
52
|
+
* server can't hand Studio a deep or huge schema to convert; anything else isn't a form Studio draws.
|
|
53
|
+
*/
|
|
54
|
+
function formSchema(requested) {
|
|
55
|
+
const { type, properties, required } = requested;
|
|
56
|
+
if (type !== "object" || !isRecord(properties)) return void 0;
|
|
57
|
+
const entries = Object.entries(properties);
|
|
58
|
+
if (entries.length > MAX_FORM_FIELDS) return void 0;
|
|
59
|
+
const fields = {};
|
|
60
|
+
for (const [key, field] of entries) {
|
|
61
|
+
if (!isRecord(field) || typeof field.type !== "string" || !FIELD_TYPES.has(field.type)) return void 0;
|
|
62
|
+
if (field.enum !== void 0 && !isStringList(field.enum)) return void 0;
|
|
63
|
+
fields[key] = Object.fromEntries(FIELD_KEYS.filter((name) => field[name] !== void 0).map((name) => [name, field[name]]));
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
type: "object",
|
|
67
|
+
properties: fields,
|
|
68
|
+
...isStringList(required) ? { required } : {}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function viewRequest({ method, params }) {
|
|
72
|
+
const message = typeof params?.message === "string" ? params.message : void 0;
|
|
73
|
+
if (method !== "elicitation/create") return {
|
|
74
|
+
kind: "unsupported",
|
|
75
|
+
message
|
|
76
|
+
};
|
|
77
|
+
const url = params?.mode === "url" ? httpUrl(params.url) : void 0;
|
|
78
|
+
if (url) return {
|
|
79
|
+
kind: "url",
|
|
80
|
+
message,
|
|
81
|
+
url
|
|
82
|
+
};
|
|
83
|
+
const schema = params?.mode !== "url" && isRecord(params?.requestedSchema) ? formSchema(params.requestedSchema) : void 0;
|
|
84
|
+
if (schema) return {
|
|
85
|
+
kind: "form",
|
|
86
|
+
message,
|
|
87
|
+
schema
|
|
88
|
+
};
|
|
89
|
+
return {
|
|
90
|
+
kind: "unsupported",
|
|
91
|
+
message
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The questions an MCP server asked while a tool call's task waits. Every request key needs an answer
|
|
96
|
+
* before the call can continue, so answers are held until the last one is given, then sent together.
|
|
97
|
+
*/
|
|
98
|
+
function McpInputRequestTool({ payload, onSubmit, isSubmitting, error, readOnly, notice }) {
|
|
99
|
+
const [answers, setAnswers] = useState({});
|
|
100
|
+
const keys = Object.keys(payload.requests);
|
|
101
|
+
const tooLarge = useMemo(() => inputRequestTooLarge(payload), [payload]);
|
|
102
|
+
const send = (inputResponses) => {
|
|
103
|
+
Promise.resolve(onSubmit({ inputResponses })).catch(() => setAnswers({}));
|
|
104
|
+
};
|
|
105
|
+
const answer = (key, response) => {
|
|
106
|
+
const next = {
|
|
107
|
+
...answers,
|
|
108
|
+
[key]: response
|
|
109
|
+
};
|
|
110
|
+
setAnswers(next);
|
|
111
|
+
if (!keys.every((requestKey) => next[requestKey])) return;
|
|
112
|
+
send(next);
|
|
113
|
+
};
|
|
114
|
+
const cancelAll = () => {
|
|
115
|
+
const next = Object.fromEntries(keys.map((key) => [key, { action: "cancel" }]));
|
|
116
|
+
setAnswers(next);
|
|
117
|
+
send(next);
|
|
118
|
+
};
|
|
119
|
+
return /* @__PURE__ */ jsxs(AskUserContainer, {
|
|
120
|
+
className: "mb-4",
|
|
121
|
+
"data-testid": "mcp-input-request",
|
|
122
|
+
children: [/* @__PURE__ */ jsxs(AskUserLabel, { children: [
|
|
123
|
+
payload.serverName,
|
|
124
|
+
" needs input to continue ",
|
|
125
|
+
payload.toolName
|
|
126
|
+
] }), /* @__PURE__ */ jsxs(AskUserBody, {
|
|
127
|
+
className: "flex flex-col gap-4",
|
|
128
|
+
children: [
|
|
129
|
+
notice && /* @__PURE__ */ jsx(Notice, {
|
|
130
|
+
variant: "info",
|
|
131
|
+
children: notice
|
|
132
|
+
}),
|
|
133
|
+
tooLarge ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Txt, {
|
|
134
|
+
tone: "muted",
|
|
135
|
+
children: [payload.serverName, " sent more than Studio can show here."]
|
|
136
|
+
}), !readOnly && /* @__PURE__ */ jsx("div", {
|
|
137
|
+
className: "flex gap-2",
|
|
138
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
139
|
+
type: "button",
|
|
140
|
+
variant: "ghost",
|
|
141
|
+
disabled: isSubmitting || Object.keys(answers).length > 0,
|
|
142
|
+
onClick: cancelAll,
|
|
143
|
+
children: "Cancel"
|
|
144
|
+
})
|
|
145
|
+
})] }) : Object.entries(payload.requests).map(([key, request]) => /* @__PURE__ */ jsx(InputRequest, {
|
|
146
|
+
requestKey: key,
|
|
147
|
+
request,
|
|
148
|
+
answered: answers[key]?.action,
|
|
149
|
+
disabled: readOnly || isSubmitting || answers[key] !== void 0,
|
|
150
|
+
readOnly,
|
|
151
|
+
onAnswer: (response) => answer(key, response)
|
|
152
|
+
}, key)),
|
|
153
|
+
error && /* @__PURE__ */ jsx(Notice, {
|
|
154
|
+
variant: "destructive",
|
|
155
|
+
role: "alert",
|
|
156
|
+
children: error
|
|
157
|
+
})
|
|
158
|
+
]
|
|
159
|
+
})]
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
function InputRequest({ requestKey, request, answered, disabled, readOnly, onAnswer }) {
|
|
163
|
+
const view = useMemo(() => viewRequest(request), [request]);
|
|
164
|
+
const schema = useMemo(() => view.kind === "form" ? jsonSchemaToZodRuntime(view.schema) : void 0, [view]);
|
|
165
|
+
const decline = /* @__PURE__ */ jsx(Button, {
|
|
166
|
+
type: "button",
|
|
167
|
+
disabled,
|
|
168
|
+
onClick: () => onAnswer({ action: "decline" }),
|
|
169
|
+
children: "Decline"
|
|
170
|
+
});
|
|
171
|
+
const cancel = /* @__PURE__ */ jsx(Button, {
|
|
172
|
+
type: "button",
|
|
173
|
+
variant: "ghost",
|
|
174
|
+
disabled,
|
|
175
|
+
onClick: () => onAnswer({ action: "cancel" }),
|
|
176
|
+
children: "Cancel"
|
|
177
|
+
});
|
|
178
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
179
|
+
"aria-label": `Input request ${requestKey}`,
|
|
180
|
+
className: "flex flex-col gap-3",
|
|
181
|
+
children: [view.message && /* @__PURE__ */ jsx(Txt, {
|
|
182
|
+
variant: "subheading",
|
|
183
|
+
tone: "ink",
|
|
184
|
+
children: view.message
|
|
185
|
+
}), answered ? /* @__PURE__ */ jsx(Txt, {
|
|
186
|
+
tone: "muted",
|
|
187
|
+
children: ACTION_LABEL[answered]
|
|
188
|
+
}) : readOnly ? null : view.kind === "form" ? /* @__PURE__ */ jsx(DynamicForm, {
|
|
189
|
+
schema,
|
|
190
|
+
onSubmit: (values) => onAnswer({
|
|
191
|
+
action: "accept",
|
|
192
|
+
content: isRecord(values) ? values : {}
|
|
193
|
+
}),
|
|
194
|
+
isSubmitLoading: disabled,
|
|
195
|
+
submitButtonLabel: "Accept",
|
|
196
|
+
submitButtonVariant: "primary",
|
|
197
|
+
submitActions: /* @__PURE__ */ jsxs(Fragment$1, { children: [decline, cancel] })
|
|
198
|
+
}) : view.kind === "url" ? /* @__PURE__ */ jsxs("div", {
|
|
199
|
+
className: "flex flex-wrap items-center gap-2",
|
|
200
|
+
children: [
|
|
201
|
+
/* @__PURE__ */ jsx(Button, {
|
|
202
|
+
variant: "link",
|
|
203
|
+
render: /* @__PURE__ */ jsx("a", {
|
|
204
|
+
href: view.url,
|
|
205
|
+
target: "_blank",
|
|
206
|
+
rel: "noopener noreferrer"
|
|
207
|
+
}),
|
|
208
|
+
iconEnd: /* @__PURE__ */ jsx(ExternalLink, {}),
|
|
209
|
+
children: "Open link"
|
|
210
|
+
}),
|
|
211
|
+
/* @__PURE__ */ jsx(Button, {
|
|
212
|
+
type: "button",
|
|
213
|
+
variant: "primary",
|
|
214
|
+
disabled,
|
|
215
|
+
onClick: () => onAnswer({ action: "accept" }),
|
|
216
|
+
children: "Done"
|
|
217
|
+
}),
|
|
218
|
+
cancel
|
|
219
|
+
]
|
|
220
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
221
|
+
/* @__PURE__ */ jsxs(Txt, {
|
|
222
|
+
tone: "muted",
|
|
223
|
+
children: [
|
|
224
|
+
"Studio can't answer a ",
|
|
225
|
+
request.method,
|
|
226
|
+
" request."
|
|
227
|
+
]
|
|
228
|
+
}),
|
|
229
|
+
/* @__PURE__ */ jsx(CodeEditor, { data: { ...request } }),
|
|
230
|
+
/* @__PURE__ */ jsx("div", {
|
|
231
|
+
className: "flex gap-2",
|
|
232
|
+
children: cancel
|
|
233
|
+
})
|
|
234
|
+
] })]
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
export { McpInputRequestTool };
|
|
238
|
+
|
|
239
|
+
//# sourceMappingURL=mcp-input-request-tool.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-input-request-tool.es.js","names":["_Fragment"],"sources":["../../../../src/domains/chat/tools/mcp-input-request-tool.tsx"],"sourcesContent":["import { ExternalLink } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport type {\n McpInputAction,\n McpInputRequest,\n McpInputRequestPayload,\n McpInputResponse,\n McpInputResumeData,\n} from './mcp-input-request';\nimport { inputRequestTooLarge } from './mcp-input-request';\nimport { AskUserBody, AskUserContainer, AskUserLabel } from '@/ds/components/ai/ask-user';\nimport { Button } from '@/ds/components/Button';\nimport { CodeEditor } from '@/ds/components/CodeEditor';\nimport { Notice } from '@/ds/components/Notice';\nimport { Txt } from '@/ds/components/Txt';\nimport { DynamicForm } from '@/lib/form/dynamic-form';\nimport { jsonSchemaToZodRuntime } from '@/lib/form/json-schema-to-zod-runtime';\n\nexport interface McpInputRequestToolProps {\n payload: McpInputRequestPayload;\n /** Sends the answers; the request stays open (and answerable again) if the returned promise rejects. */\n onSubmit: (resumeData: McpInputResumeData) => void | Promise<unknown>;\n isSubmitting?: boolean;\n /** Why the last answer didn't go through. */\n error?: string;\n /** History view: show the question without answering it. */\n readOnly?: boolean;\n /** Why the request can't be answered here, shown with the questions. */\n notice?: string;\n}\n\nconst ACTION_LABEL: Record<McpInputAction, string> = {\n accept: 'Accepted',\n decline: 'Declined',\n cancel: 'Cancelled',\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\ntype RequestView =\n | { kind: 'form'; message?: string; schema: Record<string, unknown> }\n | { kind: 'url'; message?: string; url: string }\n | { kind: 'unsupported'; message?: string };\n\nconst httpUrl = (value: unknown): string | undefined => {\n if (typeof value !== 'string') return undefined;\n try {\n const url = new URL(value);\n return url.protocol === 'https:' || url.protocol === 'http:' ? url.href : undefined;\n } catch {\n return undefined;\n }\n};\n\n/** More fields than any real question needs; a bigger form is not one Studio should draw. */\nconst MAX_FORM_FIELDS = 100;\nconst FIELD_TYPES = new Set(['string', 'number', 'integer', 'boolean']);\n// Keywords the MCP spec allows on a requested field. `pattern` isn't one: a server-chosen regex would\n// run against every keystroke.\nconst FIELD_KEYS = [\n 'type',\n 'title',\n 'description',\n 'default',\n 'enum',\n 'enumNames',\n 'format',\n 'minLength',\n 'maxLength',\n 'minimum',\n 'maximum',\n];\n\nconst isStringList = (value: unknown): value is string[] =>\n Array.isArray(value) && value.every(item => typeof item === 'string');\n\n/**\n * The MCP spec limits `requestedSchema` to a flat object of primitive fields. Keep only that shape, so a\n * server can't hand Studio a deep or huge schema to convert; anything else isn't a form Studio draws.\n */\nfunction formSchema(requested: Record<string, unknown>): Record<string, unknown> | undefined {\n const { type, properties, required } = requested;\n if (type !== 'object' || !isRecord(properties)) return undefined;\n const entries = Object.entries(properties);\n if (entries.length > MAX_FORM_FIELDS) return undefined;\n const fields: Record<string, Record<string, unknown>> = {};\n for (const [key, field] of entries) {\n if (!isRecord(field) || typeof field.type !== 'string' || !FIELD_TYPES.has(field.type)) return undefined;\n if (field.enum !== undefined && !isStringList(field.enum)) return undefined;\n fields[key] = Object.fromEntries(\n FIELD_KEYS.filter(name => field[name] !== undefined).map(name => [name, field[name]]),\n );\n }\n return { type: 'object', properties: fields, ...(isStringList(required) ? { required } : {}) };\n}\n\nfunction viewRequest({ method, params }: McpInputRequest): RequestView {\n const message = typeof params?.message === 'string' ? params.message : undefined;\n if (method !== 'elicitation/create') return { kind: 'unsupported', message };\n // Only web links: a server-chosen `javascript:` URL must not become a clickable link.\n const url = params?.mode === 'url' ? httpUrl(params.url) : undefined;\n if (url) return { kind: 'url', message, url };\n const schema =\n params?.mode !== 'url' && isRecord(params?.requestedSchema) ? formSchema(params.requestedSchema) : undefined;\n if (schema) return { kind: 'form', message, schema };\n return { kind: 'unsupported', message };\n}\n\n/**\n * The questions an MCP server asked while a tool call's task waits. Every request key needs an answer\n * before the call can continue, so answers are held until the last one is given, then sent together.\n */\nexport function McpInputRequestTool({\n payload,\n onSubmit,\n isSubmitting,\n error,\n readOnly,\n notice,\n}: McpInputRequestToolProps) {\n const [answers, setAnswers] = useState<Record<string, McpInputResponse>>({});\n const keys = Object.keys(payload.requests);\n const tooLarge = useMemo(() => inputRequestTooLarge(payload), [payload]);\n\n const send = (inputResponses: Record<string, McpInputResponse>) => {\n void Promise.resolve(onSubmit({ inputResponses })).catch(() => setAnswers({}));\n };\n\n const answer = (key: string, response: McpInputResponse) => {\n const next = { ...answers, [key]: response };\n setAnswers(next);\n if (!keys.every(requestKey => next[requestKey])) return;\n send(next);\n };\n\n const cancelAll = () => {\n const next = Object.fromEntries(keys.map(key => [key, { action: 'cancel' as const }]));\n setAnswers(next);\n send(next);\n };\n\n return (\n <AskUserContainer className=\"mb-4\" data-testid=\"mcp-input-request\">\n <AskUserLabel>\n {payload.serverName} needs input to continue {payload.toolName}\n </AskUserLabel>\n <AskUserBody className=\"flex flex-col gap-4\">\n {notice && <Notice variant=\"info\">{notice}</Notice>}\n {tooLarge ? (\n <>\n <Txt tone=\"muted\">{payload.serverName} sent more than Studio can show here.</Txt>\n {!readOnly && (\n <div className=\"flex gap-2\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={isSubmitting || Object.keys(answers).length > 0}\n onClick={cancelAll}\n >\n Cancel\n </Button>\n </div>\n )}\n </>\n ) : (\n Object.entries(payload.requests).map(([key, request]) => (\n <InputRequest\n key={key}\n requestKey={key}\n request={request}\n answered={answers[key]?.action}\n disabled={readOnly || isSubmitting || answers[key] !== undefined}\n readOnly={readOnly}\n onAnswer={response => answer(key, response)}\n />\n ))\n )}\n {error && (\n <Notice variant=\"destructive\" role=\"alert\">\n {error}\n </Notice>\n )}\n </AskUserBody>\n </AskUserContainer>\n );\n}\n\nfunction InputRequest({\n requestKey,\n request,\n answered,\n disabled,\n readOnly,\n onAnswer,\n}: {\n requestKey: string;\n request: McpInputRequest;\n answered?: McpInputAction;\n disabled?: boolean;\n readOnly?: boolean;\n onAnswer: (response: McpInputResponse) => void;\n}) {\n const view = useMemo(() => viewRequest(request), [request]);\n const schema = useMemo(() => (view.kind === 'form' ? jsonSchemaToZodRuntime(view.schema) : undefined), [view]);\n\n const decline = (\n <Button type=\"button\" disabled={disabled} onClick={() => onAnswer({ action: 'decline' })}>\n Decline\n </Button>\n );\n const cancel = (\n <Button type=\"button\" variant=\"ghost\" disabled={disabled} onClick={() => onAnswer({ action: 'cancel' })}>\n Cancel\n </Button>\n );\n\n return (\n <section aria-label={`Input request ${requestKey}`} className=\"flex flex-col gap-3\">\n {view.message && (\n <Txt variant=\"subheading\" tone=\"ink\">\n {view.message}\n </Txt>\n )}\n {answered ? (\n <Txt tone=\"muted\">{ACTION_LABEL[answered]}</Txt>\n ) : readOnly ? null : view.kind === 'form' ? (\n <DynamicForm\n schema={schema}\n onSubmit={values => onAnswer({ action: 'accept', content: isRecord(values) ? values : {} })}\n isSubmitLoading={disabled}\n submitButtonLabel=\"Accept\"\n submitButtonVariant=\"primary\"\n submitActions={\n <>\n {decline}\n {cancel}\n </>\n }\n />\n ) : view.kind === 'url' ? (\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n variant=\"link\"\n render={<a href={view.url} target=\"_blank\" rel=\"noopener noreferrer\" />}\n iconEnd={<ExternalLink />}\n >\n Open link\n </Button>\n <Button type=\"button\" variant=\"primary\" disabled={disabled} onClick={() => onAnswer({ action: 'accept' })}>\n Done\n </Button>\n {cancel}\n </div>\n ) : (\n <>\n <Txt tone=\"muted\">Studio can't answer a {request.method} request.</Txt>\n <CodeEditor data={{ ...request }} />\n <div className=\"flex gap-2\">{cancel}</div>\n </>\n )}\n </section>\n );\n}\n"],"mappings":";;;;;;;;;;;;AA+BA,IAAM,eAA+C;CACnD,QAAQ;CACR,SAAS;CACT,QAAQ;AACV;AAEA,IAAM,YAAY,UAChB,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAOrE,IAAM,WAAW,UAAuC;CACtD,IAAI,OAAO,UAAU,UAAU,OAAO,KAAA;CACtC,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,KAAK;EACzB,OAAO,IAAI,aAAa,YAAY,IAAI,aAAa,UAAU,IAAI,OAAO,KAAA;CAC5E,QAAQ;EACN;CACF;AACF;;AAGA,IAAM,kBAAkB;AACxB,IAAM,8BAAc,IAAI,IAAI;CAAC;CAAU;CAAU;CAAW;AAAS,CAAC;AAGtE,IAAM,aAAa;CACjB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,IAAM,gBAAgB,UACpB,MAAM,QAAQ,KAAK,KAAK,MAAM,OAAM,SAAQ,OAAO,SAAS,QAAQ;;;;;AAMtE,SAAS,WAAW,WAAyE;CAC3F,MAAM,EAAE,MAAM,YAAY,aAAa;CACvC,IAAI,SAAS,YAAY,CAAC,SAAS,UAAU,GAAG,OAAO,KAAA;CACvD,MAAM,UAAU,OAAO,QAAQ,UAAU;CACzC,IAAI,QAAQ,SAAS,iBAAiB,OAAO,KAAA;CAC7C,MAAM,SAAkD,CAAC;CACzD,KAAK,MAAM,CAAC,KAAK,UAAU,SAAS;EAClC,IAAI,CAAC,SAAS,KAAK,KAAK,OAAO,MAAM,SAAS,YAAY,CAAC,YAAY,IAAI,MAAM,IAAI,GAAG,OAAO,KAAA;EAC/F,IAAI,MAAM,SAAS,KAAA,KAAa,CAAC,aAAa,MAAM,IAAI,GAAG,OAAO,KAAA;EAClE,OAAO,OAAO,OAAO,YACnB,WAAW,QAAO,SAAQ,MAAM,UAAU,KAAA,CAAS,CAAC,CAAC,KAAI,SAAQ,CAAC,MAAM,MAAM,KAAK,CAAC,CACtF;CACF;CACA,OAAO;EAAE,MAAM;EAAU,YAAY;EAAQ,GAAI,aAAa,QAAQ,IAAI,EAAE,SAAS,IAAI,CAAC;CAAG;AAC/F;AAEA,SAAS,YAAY,EAAE,QAAQ,UAAwC;CACrE,MAAM,UAAU,OAAO,QAAQ,YAAY,WAAW,OAAO,UAAU,KAAA;CACvE,IAAI,WAAW,sBAAsB,OAAO;EAAE,MAAM;EAAe;CAAQ;CAE3E,MAAM,MAAM,QAAQ,SAAS,QAAQ,QAAQ,OAAO,GAAG,IAAI,KAAA;CAC3D,IAAI,KAAK,OAAO;EAAE,MAAM;EAAO;EAAS;CAAI;CAC5C,MAAM,SACJ,QAAQ,SAAS,SAAS,SAAS,QAAQ,eAAe,IAAI,WAAW,OAAO,eAAe,IAAI,KAAA;CACrG,IAAI,QAAQ,OAAO;EAAE,MAAM;EAAQ;EAAS;CAAO;CACnD,OAAO;EAAE,MAAM;EAAe;CAAQ;AACxC;;;;;AAMA,SAAgB,oBAAoB,EAClC,SACA,UACA,cACA,OACA,UACA,UAC2B;CAC3B,MAAM,CAAC,SAAS,cAAc,SAA2C,CAAC,CAAC;CAC3E,MAAM,OAAO,OAAO,KAAK,QAAQ,QAAQ;CACzC,MAAM,WAAW,cAAc,qBAAqB,OAAO,GAAG,CAAC,OAAO,CAAC;CAEvE,MAAM,QAAQ,mBAAqD;EACjE,QAAa,QAAQ,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,YAAY,WAAW,CAAC,CAAC,CAAC;CAC/E;CAEA,MAAM,UAAU,KAAa,aAA+B;EAC1D,MAAM,OAAO;GAAE,GAAG;IAAU,MAAM;EAAS;EAC3C,WAAW,IAAI;EACf,IAAI,CAAC,KAAK,OAAM,eAAc,KAAK,WAAW,GAAG;EACjD,KAAK,IAAI;CACX;CAEA,MAAM,kBAAkB;EACtB,MAAM,OAAO,OAAO,YAAY,KAAK,KAAI,QAAO,CAAC,KAAK,EAAE,QAAQ,SAAkB,CAAC,CAAC,CAAC;EACrF,WAAW,IAAI;EACf,KAAK,IAAI;CACX;CAEA,OACE,qBAAC,kBAAD;EAAkB,WAAU;EAAO,eAAY;EAA/C,UAAA,CACE,qBAAC,cAAD,EAAA,UAAA;GACG,QAAQ;GAAW;GAA0B,QAAQ;EAC1C,EAAA,CAAA,GACd,qBAAC,aAAD;GAAa,WAAU;GAAvB,UAAA;IACG,UAAU,oBAAC,QAAD;KAAQ,SAAQ;KAAQ,UAAA;IAAe,CAAA;IACjD,WACC,qBAAAA,YAAA,EAAA,UAAA,CACE,qBAAC,KAAD;KAAK,MAAK;KAAV,UAAA,CAAmB,QAAQ,YAAW,uCAA0C;IAC/E,CAAA,GAAA,CAAC,YACA,oBAAC,OAAD;KAAK,WAAU;KACb,UAAA,oBAAC,QAAD;MACE,MAAK;MACL,SAAQ;MACR,UAAU,gBAAgB,OAAO,KAAK,OAAO,CAAC,CAAC,SAAS;MACxD,SAAS;MACV,UAAA;KAEO,CAAA;IACL,CAAA,CAEP,EAAA,CAAA,IAEF,OAAO,QAAQ,QAAQ,QAAQ,CAAC,CAAC,KAAK,CAAC,KAAK,aAC1C,oBAAC,cAAD;KAEE,YAAY;KACH;KACT,UAAU,QAAQ,IAAI,EAAE;KACxB,UAAU,YAAY,gBAAgB,QAAQ,SAAS,KAAA;KAC7C;KACV,WAAU,aAAY,OAAO,KAAK,QAAQ;IAC3C,GAPM,GAON,CACF;IAEF,SACC,oBAAC,QAAD;KAAQ,SAAQ;KAAc,MAAK;KAChC,UAAA;IACK,CAAA;GAEC;EACG,CAAA,CAAA;;AAEtB;AAEA,SAAS,aAAa,EACpB,YACA,SACA,UACA,UACA,UACA,YAQC;CACD,MAAM,OAAO,cAAc,YAAY,OAAO,GAAG,CAAC,OAAO,CAAC;CAC1D,MAAM,SAAS,cAAe,KAAK,SAAS,SAAS,uBAAuB,KAAK,MAAM,IAAI,KAAA,GAAY,CAAC,IAAI,CAAC;CAE7G,MAAM,UACJ,oBAAC,QAAD;EAAQ,MAAK;EAAmB;EAAU,eAAe,SAAS,EAAE,QAAQ,UAAU,CAAC;EAAG,UAAA;CAElF,CAAA;CAEV,MAAM,SACJ,oBAAC,QAAD;EAAQ,MAAK;EAAS,SAAQ;EAAkB;EAAU,eAAe,SAAS,EAAE,QAAQ,SAAS,CAAC;EAAG,UAAA;CAEjG,CAAA;CAGV,OACE,qBAAC,WAAD;EAAS,cAAY,iBAAiB;EAAc,WAAU;EAA9D,UAAA,CACG,KAAK,WACJ,oBAAC,KAAD;GAAK,SAAQ;GAAa,MAAK;GAC5B,UAAA,KAAK;EACH,CAAA,GAEN,WACC,oBAAC,KAAD;GAAK,MAAK;GAAS,UAAA,aAAa;EAAe,CAAA,IAC7C,WAAW,OAAO,KAAK,SAAS,SAClC,oBAAC,aAAD;GACU;GACR,WAAU,WAAU,SAAS;IAAE,QAAQ;IAAU,SAAS,SAAS,MAAM,IAAI,SAAS,CAAC;GAAE,CAAC;GAC1F,iBAAiB;GACjB,mBAAkB;GAClB,qBAAoB;GACpB,eACE,qBAAAA,YAAA,EAAA,UAAA,CACG,SACA,MACD,EAAA,CAAA;EAEL,CAAA,IACC,KAAK,SAAS,QAChB,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACE,oBAAC,QAAD;KACE,SAAQ;KACR,QAAQ,oBAAC,KAAD;MAAG,MAAM,KAAK;MAAK,QAAO;MAAS,KAAI;KAAuB,CAAA;KACtE,SAAS,oBAAC,cAAD,CAAe,CAAA;KACzB,UAAA;IAEO,CAAA;IACR,oBAAC,QAAD;KAAQ,MAAK;KAAS,SAAQ;KAAoB;KAAU,eAAe,SAAS,EAAE,QAAQ,SAAS,CAAC;KAAG,UAAA;IAEnG,CAAA;IACP;GACE;EAEL,CAAA,IAAA,qBAAAA,YAAA,EAAA,UAAA;GACE,qBAAC,KAAD;IAAK,MAAK;IAAV,UAAA;KAAkB;KAAuB,QAAQ;KAAO;IAAc;;GACtE,oBAAC,YAAD,EAAY,MAAM,EAAE,GAAG,QAAQ,EAAI,CAAA;GACnC,oBAAC,OAAD;IAAK,WAAU;IAAc,UAAA;GAAY,CAAA;EACzC,EAAA,CAAA,CAEG;;AAEb"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_domains_chat_messages_signal_data = require("../messages/signal-data.cjs.js");
|
|
3
|
+
// src/domains/chat/tools/mcp-input-request.ts
|
|
4
|
+
function isMcpInputRequest(payload) {
|
|
5
|
+
return require_domains_chat_messages_signal_data.isRecord(payload) && payload.type === "mcp-input-request" && typeof payload.serverName === "string" && typeof payload.toolName === "string" && typeof payload.taskId === "string" && typeof payload.createdAt === "string" && require_domains_chat_messages_signal_data.isRecord(payload.requests) && Object.values(payload.requests).every((request) => require_domains_chat_messages_signal_data.isRecord(request) && typeof request.method === "string");
|
|
6
|
+
}
|
|
7
|
+
/** More questions at once than any real task asks; the server decides these, so Studio bounds them. */
|
|
8
|
+
var MAX_INPUT_REQUESTS = 20;
|
|
9
|
+
var MAX_REQUEST_MESSAGE_LENGTH = 2e3;
|
|
10
|
+
var MAX_INPUT_REQUESTS_SIZE = 65536;
|
|
11
|
+
/** Whether the server sent more than Studio draws: too many questions, a huge message, or huge params. */
|
|
12
|
+
function inputRequestTooLarge(payload) {
|
|
13
|
+
const requests = Object.values(payload.requests);
|
|
14
|
+
if (requests.length > 20) return true;
|
|
15
|
+
if (requests.some((request) => typeof request.params?.message === "string" && request.params.message.length > 2e3)) return true;
|
|
16
|
+
return JSON.stringify(payload.requests).length > MAX_INPUT_REQUESTS_SIZE;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* This call's own suspension. Saved entries are keyed by call id, but a live run keys them by tool
|
|
20
|
+
* name (two calls of one tool share that key), so the entry's own `toolCallId` decides.
|
|
21
|
+
*/
|
|
22
|
+
function findSuspension(metadata, toolCallId) {
|
|
23
|
+
const suspensions = metadata?.suspendedTools;
|
|
24
|
+
if (!suspensions) return void 0;
|
|
25
|
+
return Object.values(suspensions).find((entry) => entry?.toolCallId === toolCallId);
|
|
26
|
+
}
|
|
27
|
+
/** The MCP input request this call is suspended on, if it is. */
|
|
28
|
+
function suspendedMcpInputRequest(metadata, toolCallId) {
|
|
29
|
+
const payload = findSuspension(metadata, toolCallId)?.suspendPayload;
|
|
30
|
+
return isMcpInputRequest(payload) ? payload : void 0;
|
|
31
|
+
}
|
|
32
|
+
exports.MAX_INPUT_REQUESTS = MAX_INPUT_REQUESTS;
|
|
33
|
+
exports.MAX_INPUT_REQUESTS_SIZE = MAX_INPUT_REQUESTS_SIZE;
|
|
34
|
+
exports.MAX_REQUEST_MESSAGE_LENGTH = MAX_REQUEST_MESSAGE_LENGTH;
|
|
35
|
+
exports.findSuspension = findSuspension;
|
|
36
|
+
exports.inputRequestTooLarge = inputRequestTooLarge;
|
|
37
|
+
exports.isMcpInputRequest = isMcpInputRequest;
|
|
38
|
+
exports.suspendedMcpInputRequest = suspendedMcpInputRequest;
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=mcp-input-request.cjs.js.map
|