@steerable/agent-ui 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/dist/cards/ActionSegmentCard.d.ts +18 -0
  2. package/dist/cards/ActionSegmentCard.d.ts.map +1 -0
  3. package/dist/cards/ActionSegmentCard.js +26 -0
  4. package/dist/cards/ActionSegmentCard.js.map +1 -0
  5. package/dist/cards/AnalysisDocumentCard.d.ts +33 -0
  6. package/dist/cards/AnalysisDocumentCard.d.ts.map +1 -0
  7. package/dist/cards/AnalysisDocumentCard.js +11 -0
  8. package/dist/cards/AnalysisDocumentCard.js.map +1 -0
  9. package/dist/cards/AskUserQuestionsCard.d.ts +43 -0
  10. package/dist/cards/AskUserQuestionsCard.d.ts.map +1 -0
  11. package/dist/cards/AskUserQuestionsCard.js +171 -0
  12. package/dist/cards/AskUserQuestionsCard.js.map +1 -0
  13. package/dist/cards/CoverageReportCard.d.ts +41 -0
  14. package/dist/cards/CoverageReportCard.d.ts.map +1 -0
  15. package/dist/cards/CoverageReportCard.js +55 -0
  16. package/dist/cards/CoverageReportCard.js.map +1 -0
  17. package/dist/cards/OrchestrationPlanCard.d.ts +60 -0
  18. package/dist/cards/OrchestrationPlanCard.d.ts.map +1 -0
  19. package/dist/cards/OrchestrationPlanCard.js +103 -0
  20. package/dist/cards/OrchestrationPlanCard.js.map +1 -0
  21. package/dist/cards/PlanSelectorCard.d.ts +40 -0
  22. package/dist/cards/PlanSelectorCard.d.ts.map +1 -0
  23. package/dist/cards/PlanSelectorCard.js +106 -0
  24. package/dist/cards/PlanSelectorCard.js.map +1 -0
  25. package/dist/cards/PlanStepsCard.d.ts +18 -0
  26. package/dist/cards/PlanStepsCard.d.ts.map +1 -0
  27. package/dist/cards/PlanStepsCard.js +25 -0
  28. package/dist/cards/PlanStepsCard.js.map +1 -0
  29. package/dist/cards/QuizCard.d.ts +44 -0
  30. package/dist/cards/QuizCard.d.ts.map +1 -0
  31. package/dist/cards/QuizCard.js +113 -0
  32. package/dist/cards/QuizCard.js.map +1 -0
  33. package/dist/cards/ResearchPlanCard.d.ts +23 -0
  34. package/dist/cards/ResearchPlanCard.d.ts.map +1 -0
  35. package/dist/cards/ResearchPlanCard.js +50 -0
  36. package/dist/cards/ResearchPlanCard.js.map +1 -0
  37. package/dist/cards/SearchSourcesCard.d.ts +29 -0
  38. package/dist/cards/SearchSourcesCard.d.ts.map +1 -0
  39. package/dist/cards/SearchSourcesCard.js +83 -0
  40. package/dist/cards/SearchSourcesCard.js.map +1 -0
  41. package/dist/cards/SuggestedRepliesCard.d.ts +18 -0
  42. package/dist/cards/SuggestedRepliesCard.d.ts.map +1 -0
  43. package/dist/cards/SuggestedRepliesCard.js +14 -0
  44. package/dist/cards/SuggestedRepliesCard.js.map +1 -0
  45. package/dist/cards/SummaryMessageCard.d.ts +40 -0
  46. package/dist/cards/SummaryMessageCard.d.ts.map +1 -0
  47. package/dist/cards/SummaryMessageCard.js +56 -0
  48. package/dist/cards/SummaryMessageCard.js.map +1 -0
  49. package/dist/cards/ThinkingProcessCard.d.ts +46 -0
  50. package/dist/cards/ThinkingProcessCard.d.ts.map +1 -0
  51. package/dist/cards/ThinkingProcessCard.js +79 -0
  52. package/dist/cards/ThinkingProcessCard.js.map +1 -0
  53. package/dist/cards/ToolExecutionCard.d.ts +21 -0
  54. package/dist/cards/ToolExecutionCard.d.ts.map +1 -0
  55. package/dist/cards/ToolExecutionCard.js +65 -0
  56. package/dist/cards/ToolExecutionCard.js.map +1 -0
  57. package/dist/cards/icons.d.ts +38 -0
  58. package/dist/cards/icons.d.ts.map +1 -0
  59. package/dist/cards/icons.js +87 -0
  60. package/dist/cards/icons.js.map +1 -0
  61. package/dist/cards/index.d.ts +38 -0
  62. package/dist/cards/index.d.ts.map +1 -0
  63. package/dist/cards/index.js +24 -0
  64. package/dist/cards/index.js.map +1 -0
  65. package/dist/cards/types.d.ts +24 -0
  66. package/dist/cards/types.d.ts.map +1 -0
  67. package/dist/cards/types.js +7 -0
  68. package/dist/cards/types.js.map +1 -0
  69. package/dist/components/AgentSelector.d.ts +23 -0
  70. package/dist/components/AgentSelector.d.ts.map +1 -0
  71. package/dist/components/AgentSelector.js +63 -0
  72. package/dist/components/AgentSelector.js.map +1 -0
  73. package/dist/components/AgentSelector.stories.d.ts +12 -0
  74. package/dist/components/AgentSelector.stories.d.ts.map +1 -0
  75. package/dist/components/AgentSelector.stories.js +95 -0
  76. package/dist/components/AgentSelector.stories.js.map +1 -0
  77. package/dist/components/ChatPanel.d.ts +138 -21
  78. package/dist/components/ChatPanel.d.ts.map +1 -1
  79. package/dist/components/ChatPanel.js +181 -26
  80. package/dist/components/ChatPanel.js.map +1 -1
  81. package/dist/components/index.d.ts +3 -1
  82. package/dist/components/index.d.ts.map +1 -1
  83. package/dist/components/index.js +1 -0
  84. package/dist/components/index.js.map +1 -1
  85. package/dist/hooks/useChatStream.d.ts +15 -0
  86. package/dist/hooks/useChatStream.d.ts.map +1 -1
  87. package/dist/hooks/useChatStream.js +13 -1
  88. package/dist/hooks/useChatStream.js.map +1 -1
  89. package/dist/index.d.ts +2 -0
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +5 -0
  92. package/dist/index.js.map +1 -1
  93. package/dist/state/ChatSessionProvider.d.ts +59 -0
  94. package/dist/state/ChatSessionProvider.d.ts.map +1 -0
  95. package/dist/state/ChatSessionProvider.js +71 -0
  96. package/dist/state/ChatSessionProvider.js.map +1 -0
  97. package/dist/state/MockChatStreamTransport.d.ts +54 -0
  98. package/dist/state/MockChatStreamTransport.d.ts.map +1 -0
  99. package/dist/state/MockChatStreamTransport.js +86 -0
  100. package/dist/state/MockChatStreamTransport.js.map +1 -0
  101. package/dist/state/MockChatStreamTransport.stories.d.ts +13 -0
  102. package/dist/state/MockChatStreamTransport.stories.d.ts.map +1 -0
  103. package/dist/state/MockChatStreamTransport.stories.js +60 -0
  104. package/dist/state/MockChatStreamTransport.stories.js.map +1 -0
  105. package/dist/state/bridgeLegacySSE.d.ts +42 -0
  106. package/dist/state/bridgeLegacySSE.d.ts.map +1 -0
  107. package/dist/state/bridgeLegacySSE.js +102 -0
  108. package/dist/state/bridgeLegacySSE.js.map +1 -0
  109. package/dist/state/index.d.ts +32 -0
  110. package/dist/state/index.d.ts.map +1 -0
  111. package/dist/state/index.js +24 -0
  112. package/dist/state/index.js.map +1 -0
  113. package/dist/state/parseSSE.d.ts +50 -0
  114. package/dist/state/parseSSE.d.ts.map +1 -0
  115. package/dist/state/parseSSE.js +112 -0
  116. package/dist/state/parseSSE.js.map +1 -0
  117. package/dist/state/useChatComposer.d.ts +51 -0
  118. package/dist/state/useChatComposer.d.ts.map +1 -0
  119. package/dist/state/useChatComposer.js +82 -0
  120. package/dist/state/useChatComposer.js.map +1 -0
  121. package/dist/state/useChatList.d.ts +73 -0
  122. package/dist/state/useChatList.d.ts.map +1 -0
  123. package/dist/state/useChatList.js +161 -0
  124. package/dist/state/useChatList.js.map +1 -0
  125. package/dist/state/useChatSession.d.ts +29 -0
  126. package/dist/state/useChatSession.d.ts.map +1 -0
  127. package/dist/state/useChatSession.js +37 -0
  128. package/dist/state/useChatSession.js.map +1 -0
  129. package/dist/state/useScrollLock.d.ts +35 -0
  130. package/dist/state/useScrollLock.d.ts.map +1 -0
  131. package/dist/state/useScrollLock.js +74 -0
  132. package/dist/state/useScrollLock.js.map +1 -0
  133. package/dist/state/useToolCallStream.d.ts +38 -0
  134. package/dist/state/useToolCallStream.d.ts.map +1 -0
  135. package/dist/state/useToolCallStream.js +74 -0
  136. package/dist/state/useToolCallStream.js.map +1 -0
  137. package/package.json +11 -3
  138. package/src/cards/ActionSegmentCard.tsx +60 -0
  139. package/src/cards/AnalysisDocumentCard.tsx +81 -0
  140. package/src/cards/AskUserQuestionsCard.tsx +354 -0
  141. package/src/cards/CoverageReportCard.tsx +215 -0
  142. package/src/cards/OrchestrationPlanCard.tsx +328 -0
  143. package/src/cards/PlanSelectorCard.tsx +312 -0
  144. package/src/cards/PlanStepsCard.tsx +52 -0
  145. package/src/cards/QuizCard.tsx +309 -0
  146. package/src/cards/ResearchPlanCard.tsx +169 -0
  147. package/src/cards/SearchSourcesCard.tsx +244 -0
  148. package/src/cards/SuggestedRepliesCard.tsx +48 -0
  149. package/src/cards/SummaryMessageCard.tsx +145 -0
  150. package/src/cards/ThinkingProcessCard.tsx +155 -0
  151. package/src/cards/ToolExecutionCard.tsx +152 -0
  152. package/src/cards/cards.test.tsx +492 -0
  153. package/src/cards/icons.tsx +249 -0
  154. package/src/cards/index.ts +53 -0
  155. package/src/cards/types.ts +27 -0
  156. package/src/components/AgentSelector.stories.tsx +113 -0
  157. package/src/components/AgentSelector.test.tsx +70 -0
  158. package/src/components/AgentSelector.tsx +147 -0
  159. package/src/components/ChatPanel.test.tsx +130 -0
  160. package/src/components/ChatPanel.tsx +612 -138
  161. package/src/components/index.ts +13 -1
  162. package/src/hooks/useChatStream.test.ts +78 -0
  163. package/src/hooks/useChatStream.ts +32 -1
  164. package/src/index.ts +43 -0
  165. package/src/state/ChatSessionProvider.test.tsx +85 -0
  166. package/src/state/ChatSessionProvider.tsx +98 -0
  167. package/src/state/MockChatStreamTransport.stories.tsx +95 -0
  168. package/src/state/MockChatStreamTransport.test.ts +163 -0
  169. package/src/state/MockChatStreamTransport.ts +123 -0
  170. package/src/state/bridgeLegacySSE.test.ts +134 -0
  171. package/src/state/bridgeLegacySSE.ts +134 -0
  172. package/src/state/index.ts +82 -0
  173. package/src/state/parseSSE.test.ts +123 -0
  174. package/src/state/parseSSE.ts +123 -0
  175. package/src/state/useChatComposer.test.ts +145 -0
  176. package/src/state/useChatComposer.ts +117 -0
  177. package/src/state/useChatList.test.ts +135 -0
  178. package/src/state/useChatList.ts +220 -0
  179. package/src/state/useChatSession.test.ts +61 -0
  180. package/src/state/useChatSession.ts +64 -0
  181. package/src/state/useScrollLock.test.ts +99 -0
  182. package/src/state/useScrollLock.ts +105 -0
  183. package/src/state/useToolCallStream.test.ts +86 -0
  184. package/src/state/useToolCallStream.ts +110 -0
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `<ActionSegmentCard />`
3
+ *
4
+ * Horizontal strip of inline tool / action invocations within a single
5
+ * assistant message. Each segment is rendered with `<ToolExecutionCard />` so
6
+ * the visual behaviour matches the standalone tool-execution card.
7
+ */
8
+ import * as React from 'react';
9
+ import type { ActionSegmentPayload } from '@steerable/agent-protocol';
10
+ export interface ActionSegmentCardProps {
11
+ payload: ActionSegmentPayload;
12
+ className?: string;
13
+ renderArgs?: (args: unknown) => React.ReactNode;
14
+ renderOutput?: (output: unknown) => React.ReactNode;
15
+ }
16
+ export declare const ActionSegmentCard: React.FC<ActionSegmentCardProps>;
17
+ export default ActionSegmentCard;
18
+ //# sourceMappingURL=ActionSegmentCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionSegmentCard.d.ts","sourceRoot":"","sources":["../../src/cards/ActionSegmentCard.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,oBAAoB,EAAwB,MAAM,2BAA2B,CAAC;AAG5F,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC;IAChD,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC;CACrD;AAoBD,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAqB9D,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { ToolExecutionCard } from './ToolExecutionCard.js';
3
+ function segmentToTool(segment) {
4
+ return {
5
+ id: segment.id,
6
+ name: segment.kind,
7
+ status: segment.status,
8
+ summary: segment.label ?? null,
9
+ args: segment.args,
10
+ output: segment.output,
11
+ error: segment.error ?? null,
12
+ durationMs: segment.startedAt && segment.finishedAt
13
+ ? Math.max(0, Date.parse(segment.finishedAt) - Date.parse(segment.startedAt))
14
+ : null,
15
+ icon: null,
16
+ expandable: true,
17
+ };
18
+ }
19
+ export const ActionSegmentCard = ({ payload, className, renderArgs, renderOutput, }) => {
20
+ const segments = payload.segments ?? [];
21
+ if (segments.length === 0)
22
+ return null;
23
+ return (_jsx("div", { className: ['steerable-action-segment space-y-1.5', className].filter(Boolean).join(' '), children: segments.map((s) => (_jsx(ToolExecutionCard, { payload: segmentToTool(s), renderArgs: renderArgs, renderOutput: renderOutput }, s.id))) }));
24
+ };
25
+ export default ActionSegmentCard;
26
+ //# sourceMappingURL=ActionSegmentCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionSegmentCard.js","sourceRoot":"","sources":["../../src/cards/ActionSegmentCard.tsx"],"names":[],"mappings":";AASA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAS3D,SAAS,aAAa,CAAC,OAAiD;IACtE,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI;QAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI;QAC5B,UAAU,EACR,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,UAAU;YACrC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC7E,CAAC,CAAC,IAAI;QACV,IAAI,EAAE,IAAI;QACV,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAqC,CAAC,EAClE,OAAO,EACP,SAAS,EACT,UAAU,EACV,YAAY,GACb,EAAE,EAAE;IACH,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;IACxC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,OAAO,CACL,cAAK,SAAS,EAAE,CAAC,sCAAsC,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,YAC1F,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACnB,KAAC,iBAAiB,IAEhB,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EACzB,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,YAAY,IAHrB,CAAC,CAAC,EAAE,CAIT,CACH,CAAC,GACE,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * `<AnalysisDocumentCard />`
3
+ *
4
+ * Long-form markdown document card.
5
+ *
6
+ * The framework deliberately does not pull in `react-markdown` / `remark-gfm` /
7
+ * `github-markdown-css` -- the consumer must pass a `renderMarkdown` slot (or
8
+ * a `Markdown` child) to do the actual rendering. Default fallback is a `<pre>`
9
+ * block.
10
+ *
11
+ * Header variants:
12
+ * - `inline` (default): title sits inline with the document icon.
13
+ * - `strip`: title becomes a `bg-muted/50` strip on top, with the icon hidden.
14
+ *
15
+ * Footer slot lets host apps attach an actions bar (deeppath uses this for
16
+ * "转化为行动 / 保存到笔记 / 保存为 PDF / 深入研究 / 复制 / 模型 + 时间").
17
+ */
18
+ import * as React from 'react';
19
+ import type { AnalysisDocumentPayload } from '@steerable/agent-protocol';
20
+ import { type RenderSlotResult } from './types.js';
21
+ export type AnalysisDocumentHeaderVariant = 'inline' | 'strip';
22
+ export interface AnalysisDocumentCardProps {
23
+ payload: AnalysisDocumentPayload;
24
+ isComplete?: boolean;
25
+ renderMarkdown?: (body: string) => RenderSlotResult;
26
+ renderFooter?: () => RenderSlotResult;
27
+ className?: string;
28
+ bodyClassName?: string;
29
+ headerVariant?: AnalysisDocumentHeaderVariant;
30
+ }
31
+ export declare const AnalysisDocumentCard: React.FC<AnalysisDocumentCardProps>;
32
+ export default AnalysisDocumentCard;
33
+ //# sourceMappingURL=AnalysisDocumentCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalysisDocumentCard.d.ts","sourceRoot":"","sources":["../../src/cards/AnalysisDocumentCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEzE,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhE,MAAM,MAAM,6BAA6B,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE/D,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,uBAAuB,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,gBAAgB,CAAC;IACpD,YAAY,CAAC,EAAE,MAAM,gBAAgB,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,6BAA6B,CAAC;CAC/C;AAED,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CA4CpE,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { BookIcon } from './icons.js';
3
+ import { asReactNode } from './types.js';
4
+ export const AnalysisDocumentCard = ({ payload, renderMarkdown, renderFooter, className, bodyClassName, headerVariant = 'inline', }) => {
5
+ return (_jsxs("article", { className: [
6
+ 'steerable-analysis-document overflow-hidden rounded-lg border border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-card-bg,#fff)] text-sm text-[var(--agent-foreground,#111827)]',
7
+ className,
8
+ ].filter(Boolean).join(' '), children: [payload.title && headerVariant === 'strip' ? (_jsx("div", { className: "border-b border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-muted,#f3f4f6)]/50 px-4 py-2", children: _jsx("span", { className: "block truncate text-xs font-medium text-[var(--agent-muted-foreground,#6b7280)]", children: payload.title }) })) : (_jsxs("header", { className: "mb-3 flex items-center gap-2 border-b border-[var(--agent-border,#e5e7eb)] px-4 pt-3 pb-2", children: [_jsx(BookIcon, { size: 14, className: "text-[var(--agent-muted-foreground,#6b7280)]" }), _jsx("h3", { className: "text-sm font-medium", children: payload.title || '分析报告' }), payload.modelId && (_jsx("span", { className: "ml-auto rounded-full bg-[var(--agent-muted,#f3f4f6)] px-2 py-0.5 text-[10px] uppercase tracking-wider text-[var(--agent-muted-foreground,#6b7280)]", children: payload.modelId }))] })), _jsx("div", { className: ['p-4', bodyClassName].filter(Boolean).join(' '), children: renderMarkdown ? (asReactNode(renderMarkdown(payload.body))) : (_jsx("pre", { className: "whitespace-pre-wrap break-words font-sans", children: payload.body })) }), renderFooter && asReactNode(renderFooter())] }));
9
+ };
10
+ export default AnalysisDocumentCard;
11
+ //# sourceMappingURL=AnalysisDocumentCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalysisDocumentCard.js","sourceRoot":"","sources":["../../src/cards/AnalysisDocumentCard.tsx"],"names":[],"mappings":";AAmBA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAyB,MAAM,YAAY,CAAC;AAchE,MAAM,CAAC,MAAM,oBAAoB,GAAwC,CAAC,EACxE,OAAO,EACP,cAAc,EACd,YAAY,EACZ,SAAS,EACT,aAAa,EACb,aAAa,GAAG,QAAQ,GACzB,EAAE,EAAE;IACH,OAAO,CACL,mBACE,SAAS,EAAE;YACT,kLAAkL;YAClL,SAAS;SACV,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,aAE1B,OAAO,CAAC,KAAK,IAAI,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,CAC5C,cAAK,SAAS,EAAC,4FAA4F,YACzG,eAAM,SAAS,EAAC,iFAAiF,YAC9F,OAAO,CAAC,KAAK,GACT,GACH,CACP,CAAC,CAAC,CAAC,CACF,kBAAQ,SAAS,EAAC,2FAA2F,aAC3G,KAAC,QAAQ,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,8CAA8C,GAAG,EAC/E,aAAI,SAAS,EAAC,qBAAqB,YAAE,OAAO,CAAC,KAAK,IAAI,MAAM,GAAM,EACjE,OAAO,CAAC,OAAO,IAAI,CAClB,eAAM,SAAS,EAAC,oJAAoJ,YACjK,OAAO,CAAC,OAAO,GACX,CACR,IACM,CACV,EAED,cAAK,SAAS,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,YAC7D,cAAc,CAAC,CAAC,CAAC,CAChB,WAAW,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAC1C,CAAC,CAAC,CAAC,CACF,cAAK,SAAS,EAAC,2CAA2C,YAAE,OAAO,CAAC,IAAI,GAAO,CAChF,GACG,EAEL,YAAY,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC,IACpC,CACX,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * `<AskUserQuestionsCard />`
3
+ *
4
+ * Mid-run interrupt: the agent has paused and is asking the user to answer a
5
+ * structured set of questions before continuing. Supports select / text /
6
+ * password question types with optional multi-select and an opt-in "custom
7
+ * text" escape per question.
8
+ *
9
+ * Submission is controlled: the parent passes `onSubmit(answers)` and may
10
+ * re-emit the same card with `payload.answers` filled in to flip the UI into
11
+ * read-only review mode.
12
+ *
13
+ * Features:
14
+ * - `allowCustomText`: each `select` question gets a "自定义" pill that
15
+ * flips it into a free-form input (deeppath relies on this for
16
+ * "the option I want is not listed").
17
+ * - `onAutoContinue` + `autoContinueLabel`: surfaces an escape button in the
18
+ * intro row ("交给我决定") that delegates the decision back to the agent.
19
+ * - `requireAllAnswered`: disables the submit button until every question
20
+ * has a non-empty answer.
21
+ * - Localisable strings: `submitLabel`, `multiSelectLabel`, `customLabel`,
22
+ * `bottomHint`.
23
+ */
24
+ import * as React from 'react';
25
+ import type { AskUserQuestionsPayload } from '@steerable/agent-protocol';
26
+ type AnswerValue = string | string[];
27
+ export interface AskUserQuestionsCardProps {
28
+ payload: AskUserQuestionsPayload;
29
+ isComplete?: boolean;
30
+ onSubmit?: (answers: Record<string, AnswerValue>) => void;
31
+ onAutoContinue?: () => void;
32
+ className?: string;
33
+ allowCustomText?: boolean;
34
+ requireAllAnswered?: boolean;
35
+ submitLabel?: React.ReactNode;
36
+ multiSelectLabel?: React.ReactNode;
37
+ customLabel?: React.ReactNode;
38
+ autoContinueLabel?: React.ReactNode;
39
+ bottomHint?: React.ReactNode;
40
+ }
41
+ export declare const AskUserQuestionsCard: React.FC<AskUserQuestionsCardProps>;
42
+ export default AskUserQuestionsCard;
43
+ //# sourceMappingURL=AskUserQuestionsCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AskUserQuestionsCard.d.ts","sourceRoot":"","sources":["../../src/cards/AskUserQuestionsCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAQzE,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAGrC,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,uBAAuB,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,KAAK,IAAI,CAAC;IAC1D,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,gBAAgB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,iBAAiB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACpC,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B;AAWD,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CAoSpE,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,171 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * `<AskUserQuestionsCard />`
4
+ *
5
+ * Mid-run interrupt: the agent has paused and is asking the user to answer a
6
+ * structured set of questions before continuing. Supports select / text /
7
+ * password question types with optional multi-select and an opt-in "custom
8
+ * text" escape per question.
9
+ *
10
+ * Submission is controlled: the parent passes `onSubmit(answers)` and may
11
+ * re-emit the same card with `payload.answers` filled in to flip the UI into
12
+ * read-only review mode.
13
+ *
14
+ * Features:
15
+ * - `allowCustomText`: each `select` question gets a "自定义" pill that
16
+ * flips it into a free-form input (deeppath relies on this for
17
+ * "the option I want is not listed").
18
+ * - `onAutoContinue` + `autoContinueLabel`: surfaces an escape button in the
19
+ * intro row ("交给我决定") that delegates the decision back to the agent.
20
+ * - `requireAllAnswered`: disables the submit button until every question
21
+ * has a non-empty answer.
22
+ * - Localisable strings: `submitLabel`, `multiSelectLabel`, `customLabel`,
23
+ * `bottomHint`.
24
+ */
25
+ import * as React from 'react';
26
+ import { MessageQuestionIcon, CheckIcon, LoaderIcon, PencilIcon, } from './icons.js';
27
+ function emptyAnswerFor(q) {
28
+ if (q.multiSelect)
29
+ return [];
30
+ return '';
31
+ }
32
+ function isInputOnly(q) {
33
+ return q.type === 'text' || q.type === 'password';
34
+ }
35
+ export const AskUserQuestionsCard = ({ payload, isComplete, onSubmit, onAutoContinue, className, allowCustomText = false, requireAllAnswered = false, submitLabel = '提交', multiSelectLabel = '(可多选)', customLabel = '自定义', autoContinueLabel = '交给我决定', bottomHint, }) => {
36
+ const isReadOnly = Boolean(isComplete || payload.answers);
37
+ const initial = React.useMemo(() => {
38
+ const seed = {};
39
+ const custom = {};
40
+ const text = {};
41
+ for (const q of payload.questions ?? []) {
42
+ const fromBackend = payload.answers?.[q.id];
43
+ if (fromBackend === undefined) {
44
+ seed[q.id] = emptyAnswerFor(q);
45
+ continue;
46
+ }
47
+ if (isInputOnly(q)) {
48
+ text[q.id] = typeof fromBackend === 'string' ? fromBackend : '';
49
+ seed[q.id] = fromBackend;
50
+ continue;
51
+ }
52
+ const options = q.options ?? [];
53
+ if (Array.isArray(fromBackend)) {
54
+ const allInOptions = fromBackend.every((a) => options.includes(a));
55
+ if (allInOptions) {
56
+ seed[q.id] = fromBackend;
57
+ }
58
+ else {
59
+ custom[q.id] = true;
60
+ text[q.id] = fromBackend.join('、');
61
+ seed[q.id] = fromBackend;
62
+ }
63
+ }
64
+ else {
65
+ if (options.includes(fromBackend)) {
66
+ seed[q.id] = fromBackend;
67
+ }
68
+ else {
69
+ custom[q.id] = true;
70
+ text[q.id] = fromBackend;
71
+ seed[q.id] = fromBackend;
72
+ }
73
+ }
74
+ }
75
+ return { seed, custom, text };
76
+ }, [payload.questions, payload.answers]);
77
+ const [draft, setDraft] = React.useState(initial.seed);
78
+ const [customMode, setCustomMode] = React.useState(initial.custom);
79
+ const [customText, setCustomText] = React.useState(initial.text);
80
+ const [submitting, setSubmitting] = React.useState(false);
81
+ React.useEffect(() => {
82
+ setDraft(initial.seed);
83
+ setCustomMode(initial.custom);
84
+ setCustomText(initial.text);
85
+ }, [initial]);
86
+ const toggleMulti = (qId, opt) => setDraft((p) => {
87
+ const cur = (p[qId] ?? []);
88
+ return { ...p, [qId]: cur.includes(opt) ? cur.filter((v) => v !== opt) : [...cur, opt] };
89
+ });
90
+ const setSingle = (qId, value) => setDraft((p) => ({ ...p, [qId]: value }));
91
+ const enterCustom = (qId) => {
92
+ setCustomMode((p) => ({ ...p, [qId]: true }));
93
+ setDraft((p) => {
94
+ const next = { ...p };
95
+ delete next[qId];
96
+ return next;
97
+ });
98
+ };
99
+ const cancelCustom = (qId) => {
100
+ setCustomMode((p) => ({ ...p, [qId]: false }));
101
+ setCustomText((p) => {
102
+ const next = { ...p };
103
+ delete next[qId];
104
+ return next;
105
+ });
106
+ };
107
+ const answerForQuestion = React.useCallback((q) => {
108
+ if (isInputOnly(q))
109
+ return (customText[q.id] || '').trim();
110
+ if (allowCustomText && customMode[q.id])
111
+ return (customText[q.id] || '').trim();
112
+ const val = draft[q.id];
113
+ if (Array.isArray(val))
114
+ return val.length > 0 ? val.join('、') : '';
115
+ return val || '';
116
+ }, [allowCustomText, customMode, customText, draft]);
117
+ const allAnswered = React.useMemo(() => (payload.questions ?? []).every((q) => answerForQuestion(q).length > 0), [payload.questions, answerForQuestion]);
118
+ const handleSubmit = async () => {
119
+ if (!onSubmit)
120
+ return;
121
+ if (requireAllAnswered && !allAnswered)
122
+ return;
123
+ setSubmitting(true);
124
+ try {
125
+ const out = {};
126
+ for (const q of payload.questions ?? []) {
127
+ if (isInputOnly(q) || (allowCustomText && customMode[q.id])) {
128
+ out[q.id] = (customText[q.id] || '').trim();
129
+ }
130
+ else {
131
+ out[q.id] = draft[q.id] ?? emptyAnswerFor(q);
132
+ }
133
+ }
134
+ onSubmit(out);
135
+ }
136
+ finally {
137
+ setSubmitting(false);
138
+ }
139
+ };
140
+ return (_jsx("div", { className: [
141
+ 'steerable-ask-user overflow-hidden rounded-lg border border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-card-bg,#fff)] text-sm text-[var(--agent-foreground,#111827)]',
142
+ className,
143
+ ].filter(Boolean).join(' '), children: _jsxs("div", { className: "space-y-4 p-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "flex flex-1 items-start gap-2", children: [!payload.intro && (_jsx(MessageQuestionIcon, { size: 14, className: "mt-0.5 text-[var(--agent-muted-foreground,#6b7280)]" })), payload.intro ? (_jsx("p", { className: "flex-1 text-sm", children: payload.intro })) : (_jsx("span", { className: "font-medium", children: "\u9700\u8981\u4F60\u7684\u8F93\u5165" }))] }), !isReadOnly && onAutoContinue && (_jsxs("button", { type: "button", onClick: onAutoContinue, className: "inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-card-bg,#fff)] px-3 py-1 text-xs font-medium text-[var(--agent-foreground,#111827)] transition-all duration-200 hover:bg-[var(--agent-muted,#f3f4f6)]", children: [_jsx(CheckIcon, { size: 12 }), autoContinueLabel] }))] }), _jsx("ol", { className: "space-y-3", children: (payload.questions ?? []).map((q, idx) => {
144
+ const value = draft[q.id];
145
+ const inputOnly = isInputOnly(q);
146
+ const isCustom = allowCustomText && customMode[q.id];
147
+ return (_jsxs("li", { className: "space-y-2", children: [_jsxs("p", { className: "text-sm font-medium", children: [idx + 1, ". ", q.text, !inputOnly && q.multiSelect && (_jsx("span", { className: "ml-1.5 text-xs font-normal text-[var(--agent-muted-foreground,#6b7280)]", children: multiSelectLabel }))] }), inputOnly && (_jsx("input", { type: q.type === 'password' ? 'password' : 'text', disabled: isReadOnly, placeholder: q.placeholder || (q.type === 'password' ? '输入密码' : '输入你的回答...'), value: customText[q.id] || '', onChange: (e) => setCustomText((p) => ({ ...p, [q.id]: e.target.value })), className: "w-full rounded-lg border border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-background,#fff)] px-3 py-1.5 text-xs text-[var(--agent-foreground,#111827)] outline-none placeholder:text-[var(--agent-muted-foreground,#6b7280)] focus:border-[var(--agent-primary,#18181b)] focus:ring-1 focus:ring-[var(--agent-primary,#18181b)] disabled:cursor-not-allowed disabled:opacity-60" })), !inputOnly && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-wrap gap-2", children: [(q.options ?? []).map((opt) => {
148
+ const selected = !isCustom &&
149
+ (q.multiSelect
150
+ ? (Array.isArray(value) ? value : []).includes(opt)
151
+ : value === opt);
152
+ return (_jsxs("button", { type: "button", disabled: isReadOnly, onClick: () => q.multiSelect ? toggleMulti(q.id, opt) : setSingle(q.id, opt), className: [
153
+ 'rounded-full border px-3 py-1.5 text-xs font-medium transition-all duration-200',
154
+ selected
155
+ ? 'border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-muted,#f3f4f6)] text-[var(--agent-foreground,#111827)] ring-1 ring-[var(--agent-border,#e5e7eb)]'
156
+ : 'border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-card-bg,#fff)] text-[var(--agent-muted-foreground,#6b7280)] hover:bg-[var(--agent-muted,#f3f4f6)] hover:text-[var(--agent-foreground,#111827)]',
157
+ isReadOnly ? 'cursor-not-allowed opacity-60' : 'cursor-pointer',
158
+ ].join(' '), children: [q.multiSelect && selected && (_jsx(CheckIcon, { size: 10, className: "-ml-0.5 mr-1 inline" })), opt] }, opt));
159
+ }), allowCustomText && !isCustom && (_jsx("button", { type: "button", disabled: isReadOnly, onClick: () => enterCustom(q.id), className: [
160
+ 'rounded-full border border-dashed border-[var(--agent-border,#e5e7eb)] px-3 py-1.5 text-xs font-medium text-[var(--agent-muted-foreground,#6b7280)] transition-all duration-200 hover:bg-[var(--agent-muted,#f3f4f6)] hover:text-[var(--agent-foreground,#111827)]',
161
+ isReadOnly ? 'cursor-not-allowed opacity-60' : 'cursor-pointer',
162
+ ].join(' '), children: _jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx(PencilIcon, { size: 12 }), customLabel] }) }))] }), isCustom && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("input", { type: "text", disabled: isReadOnly, placeholder: "\u8F93\u5165\u4F60\u7684\u56DE\u7B54...", value: customText[q.id] || '', onChange: (e) => setCustomText((p) => ({ ...p, [q.id]: e.target.value })), className: "flex-1 rounded-lg border border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-background,#fff)] px-3 py-1.5 text-xs text-[var(--agent-foreground,#111827)] outline-none placeholder:text-[var(--agent-muted-foreground,#6b7280)] focus:border-[var(--agent-primary,#18181b)] focus:ring-1 focus:ring-[var(--agent-primary,#18181b)] disabled:cursor-not-allowed disabled:opacity-60" }), _jsx("button", { type: "button", disabled: isReadOnly, onClick: () => cancelCustom(q.id), className: "text-xs text-[var(--agent-muted-foreground,#6b7280)] transition-colors duration-200 hover:text-[var(--agent-foreground,#111827)]", children: "\u53D6\u6D88" })] }))] }))] }, q.id));
163
+ }) }), payload.outro && (_jsx("p", { className: "text-xs text-[var(--agent-muted-foreground,#6b7280)] whitespace-pre-line", children: payload.outro })), !isReadOnly && onSubmit && (_jsxs("div", { className: "flex items-center justify-between pt-1", children: [_jsx("span", { className: "text-xs text-[var(--agent-muted-foreground,#6b7280)]", children: bottomHint }), _jsxs("button", { type: "button", onClick: handleSubmit, disabled: submitting || (requireAllAnswered && !allAnswered), className: [
164
+ 'inline-flex items-center gap-1.5 rounded-full px-4 py-1.5 text-xs font-medium transition-all duration-200',
165
+ submitting || (requireAllAnswered && !allAnswered)
166
+ ? 'cursor-not-allowed bg-[var(--agent-muted,#f3f4f6)] text-[var(--agent-muted-foreground,#6b7280)]'
167
+ : 'bg-[var(--agent-primary,#18181b)] text-[var(--agent-primary-foreground,#fff)] shadow-sm hover:opacity-90',
168
+ ].join(' '), children: [submitting ? _jsx(LoaderIcon, { size: 10, className: "animate-spin" }) : _jsx(CheckIcon, { size: 12 }), submitLabel] })] }))] }) }));
169
+ };
170
+ export default AskUserQuestionsCard;
171
+ //# sourceMappingURL=AskUserQuestionsCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AskUserQuestionsCard.js","sourceRoot":"","sources":["../../src/cards/AskUserQuestionsCard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * `<CoverageReportCard />`
3
+ *
4
+ * Renders mastery / coverage of a knowledge graph: overall numbers, section
5
+ * progress bars, and a list of weak knowledge points with recommendations.
6
+ * Offers a "practice weak points" action (optionally with multi-select) when
7
+ * `payload.actions.allowRemediateQuiz` is set.
8
+ *
9
+ * Configurable bits:
10
+ * - `progressMetric` ('mastery' default, or 'coverage') controls which value
11
+ * fills the per-section progress bar.
12
+ * - `allowWeakPointSelection` turns the weak-points list into checkboxes;
13
+ * `onRemediate` then receives the explicit selected ids (or all ids if
14
+ * nothing is checked).
15
+ * - `renderSectionStats(section)` slot lets consumers attach an info line
16
+ * under each progress bar (e.g. "已学 5/12 · 已测 3 · 已掌握 2").
17
+ * - `remediateDisabled` + `remediateLabel` + `remediateHint` let the host
18
+ * surface submission state (e.g. "已提交补救请求").
19
+ * - `emptyWeakPointsLabel` shows a positive empty state when there are no
20
+ * weak points to display.
21
+ */
22
+ import * as React from 'react';
23
+ import type { CoverageReportPayload } from '@steerable/agent-protocol';
24
+ import { type RenderSlotResult } from './types.js';
25
+ type Section = NonNullable<CoverageReportPayload['sections']>[number];
26
+ export interface CoverageReportCardProps {
27
+ payload: CoverageReportPayload;
28
+ isComplete?: boolean;
29
+ onRemediate?: (selectedIds: string[]) => void;
30
+ className?: string;
31
+ progressMetric?: 'coverage' | 'mastery';
32
+ allowWeakPointSelection?: boolean;
33
+ remediateDisabled?: boolean;
34
+ remediateLabel?: string;
35
+ remediateHint?: React.ReactNode;
36
+ emptyWeakPointsLabel?: React.ReactNode;
37
+ renderSectionStats?: (section: Section) => RenderSlotResult;
38
+ }
39
+ export declare const CoverageReportCard: React.FC<CoverageReportCardProps>;
40
+ export default CoverageReportCard;
41
+ //# sourceMappingURL=CoverageReportCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoverageReportCard.d.ts","sourceRoot":"","sources":["../../src/cards/CoverageReportCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhE,KAAK,OAAO,GAAG,WAAW,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,qBAAqB,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACxC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,oBAAoB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,gBAAgB,CAAC;CAC7D;AAQD,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAoKhE,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * `<CoverageReportCard />`
4
+ *
5
+ * Renders mastery / coverage of a knowledge graph: overall numbers, section
6
+ * progress bars, and a list of weak knowledge points with recommendations.
7
+ * Offers a "practice weak points" action (optionally with multi-select) when
8
+ * `payload.actions.allowRemediateQuiz` is set.
9
+ *
10
+ * Configurable bits:
11
+ * - `progressMetric` ('mastery' default, or 'coverage') controls which value
12
+ * fills the per-section progress bar.
13
+ * - `allowWeakPointSelection` turns the weak-points list into checkboxes;
14
+ * `onRemediate` then receives the explicit selected ids (or all ids if
15
+ * nothing is checked).
16
+ * - `renderSectionStats(section)` slot lets consumers attach an info line
17
+ * under each progress bar (e.g. "已学 5/12 · 已测 3 · 已掌握 2").
18
+ * - `remediateDisabled` + `remediateLabel` + `remediateHint` let the host
19
+ * surface submission state (e.g. "已提交补救请求").
20
+ * - `emptyWeakPointsLabel` shows a positive empty state when there are no
21
+ * weak points to display.
22
+ */
23
+ import * as React from 'react';
24
+ import { ChartIcon, CheckIcon, AlertIcon } from './icons.js';
25
+ import { asReactNode } from './types.js';
26
+ function pct(v) {
27
+ const safe = Number.isFinite(v ?? NaN) ? v : 0;
28
+ const c = Math.max(0, Math.min(1, safe));
29
+ return `${Math.round(c * 100)}%`;
30
+ }
31
+ export const CoverageReportCard = ({ payload, isComplete, onRemediate, className, progressMetric = 'mastery', allowWeakPointSelection = false, remediateDisabled = false, remediateLabel, remediateHint, emptyWeakPointsLabel, renderSectionStats, }) => {
32
+ const sections = payload.sections ?? [];
33
+ const weakPoints = payload.weakPoints ?? [];
34
+ const [selected, setSelected] = React.useState([]);
35
+ const toggle = (id) => setSelected((prev) => (prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]));
36
+ const handleClick = () => {
37
+ if (!onRemediate || remediateDisabled)
38
+ return;
39
+ const ids = allowWeakPointSelection && selected.length > 0
40
+ ? selected
41
+ : weakPoints.map((wp) => wp.id);
42
+ onRemediate(ids);
43
+ };
44
+ return (_jsx("div", { className: [
45
+ 'steerable-coverage-report rounded-lg border border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-card-bg,#fff)] text-sm text-[var(--agent-foreground,#111827)]',
46
+ className,
47
+ ].filter(Boolean).join(' '), children: _jsxs("div", { className: "space-y-3 p-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ChartIcon, { size: 14, className: "text-blue-500" }), _jsx("span", { className: "font-medium", children: payload.title }), isComplete && _jsx(CheckIcon, { size: 12, className: "text-emerald-600" })] }), _jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsxs("div", { className: "rounded-md border border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-background,#fff)] p-2", children: [_jsx("p", { className: "text-[11px] text-[var(--agent-muted-foreground,#6b7280)]", children: "\u6574\u4F53\u8986\u76D6\u7387" }), _jsx("p", { className: "text-base font-semibold", children: pct(payload.overallCoverage) })] }), _jsxs("div", { className: "rounded-md border border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-background,#fff)] p-2", children: [_jsx("p", { className: "text-[11px] text-[var(--agent-muted-foreground,#6b7280)]", children: "\u6574\u4F53\u638C\u63E1\u7387" }), _jsx("p", { className: "text-base font-semibold", children: pct(payload.overallMastery) })] })] }), payload.summary && (_jsx("p", { className: "text-xs text-[var(--agent-muted-foreground,#6b7280)] whitespace-pre-line", children: payload.summary })), _jsx("div", { className: "space-y-2", children: sections.map((section) => {
48
+ const fill = progressMetric === 'coverage' ? section.coverage : section.mastery;
49
+ return (_jsxs("div", { className: "rounded-md border border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-background,#fff)] p-2", children: [_jsxs("div", { className: "mb-1 flex items-center justify-between", children: [_jsx("span", { className: "text-sm font-medium", children: section.name }), _jsxs("span", { className: "text-xs text-[var(--agent-muted-foreground,#6b7280)]", children: ["\u8986\u76D6 ", pct(section.coverage), " \u00B7 \u638C\u63E1 ", pct(section.mastery)] })] }), _jsx("div", { className: "h-2 w-full overflow-hidden rounded-full bg-[var(--agent-muted,#f3f4f6)]", children: _jsx("div", { className: progressMetric === 'coverage'
50
+ ? 'h-full bg-[var(--agent-primary,#18181b)] transition-all duration-200'
51
+ : 'h-full bg-emerald-500 transition-all duration-200', style: { width: pct(fill) }, "aria-hidden": true }) }), renderSectionStats && (_jsx("div", { className: "mt-1 text-[11px] text-[var(--agent-muted-foreground,#6b7280)]", children: asReactNode(renderSectionStats(section)) }))] }, section.id));
52
+ }) }), _jsxs("div", { className: "space-y-2 rounded-md border border-[var(--agent-border,#e5e7eb)] bg-[var(--agent-background,#fff)] p-2", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-xs font-medium text-amber-600 dark:text-amber-400", children: [_jsx(AlertIcon, { size: 12 }), "\u8584\u5F31\u77E5\u8BC6\u70B9"] }), weakPoints.length === 0 ? (emptyWeakPointsLabel ? (_jsxs("div", { className: "inline-flex items-center gap-1.5 text-xs text-green-600 dark:text-green-400", children: [_jsx(CheckIcon, { size: 12 }), emptyWeakPointsLabel] })) : null) : allowWeakPointSelection ? (_jsx("div", { className: "space-y-1.5", children: weakPoints.map((point) => (_jsxs("label", { className: "flex cursor-pointer items-start gap-2", children: [_jsx("input", { type: "checkbox", className: "mt-0.5 h-4 w-4", checked: selected.includes(point.id), onChange: () => toggle(point.id), disabled: remediateDisabled }), _jsxs("div", { className: "min-w-0 text-xs", children: [_jsxs("p", { className: "font-medium", children: [point.name, point.sectionName ? ` · ${point.sectionName}` : ''] }), _jsxs("p", { className: "text-[var(--agent-muted-foreground,#6b7280)]", children: ["\u6B63\u786E\u7387 ", pct(point.accuracy), " \u00B7 ", point.recommendation] })] })] }, point.id))) })) : (_jsx("ul", { className: "space-y-1 text-xs", children: weakPoints.map((wp) => (_jsxs("li", { children: [_jsx("span", { className: "font-medium", children: wp.name }), wp.sectionName && (_jsxs("span", { className: "ml-1 text-[var(--agent-muted-foreground,#6b7280)]", children: ["\u00B7 ", wp.sectionName] })), _jsxs("span", { className: "ml-1 text-[var(--agent-muted-foreground,#6b7280)]", children: ["\u00B7 \u6B63\u786E\u7387 ", pct(wp.accuracy)] }), _jsx("p", { className: "text-[var(--agent-muted-foreground,#6b7280)]", children: wp.recommendation })] }, wp.id))) }))] }), payload.actions?.allowRemediateQuiz && onRemediate && weakPoints.length > 0 && (_jsxs("div", { className: "flex items-center justify-between pt-1", children: [_jsx("span", { className: "text-xs text-[var(--agent-muted-foreground,#6b7280)]", children: remediateHint }), _jsx("button", { type: "button", onClick: handleClick, disabled: remediateDisabled, className: "inline-flex h-[28px] items-center rounded-full bg-[var(--agent-primary,#18181b)] px-3 text-xs font-medium text-[var(--agent-primary-foreground,#fff)] transition-all duration-200 hover:opacity-90 disabled:opacity-50", children: remediateLabel || payload.actions.remediateActionLabel || '为薄弱点出题' })] }))] }) }));
53
+ };
54
+ export default CoverageReportCard;
55
+ //# sourceMappingURL=CoverageReportCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoverageReportCard.js","sourceRoot":"","sources":["../../src/cards/CoverageReportCard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * `<OrchestrationPlanCard />`
3
+ *
4
+ * The visible surface of an otherwise invisible Coordinator agent. Renders
5
+ * one row per worker task with a status dot driven by `taskStatuses` (a map
6
+ * the parent computes off sibling assistant bubbles tagged with the same
7
+ * orchestrationGroupId + orchestrationTaskId).
8
+ *
9
+ * Three top-level shells are supported via mutually-exclusive flags so the
10
+ * Coordinator can express its lifecycle without forcing the caller to render
11
+ * three different components:
12
+ * - `loading` + optional `loadingHint` — Coordinator is still planning.
13
+ * - `failed` + optional `failure` — planning errored.
14
+ * - default — `payload.tasks` are rendered.
15
+ *
16
+ * Slots:
17
+ * - `renderAbove` / `renderBelowHeader` — out-of-flow rails for badges and
18
+ * context-load lines that deeppath wants to ride along.
19
+ * - `renderTaskRow(task, status)` — full row override (deeppath uses
20
+ * it to draw the per-agent colored chip + monospaced task id + right-
21
+ * aligned status label).
22
+ * - `headerLabel`, `headerSecondary` — override the default
23
+ * "编排计划 · N 个子任务" header label/subline.
24
+ * - `hideMode`, `hideHeaderCounts` — drop the optional header chips
25
+ * when the host UI does not want them (deeppath hides both).
26
+ * - controlled `expanded` + `onExpandedChange`.
27
+ */
28
+ import * as React from 'react';
29
+ import type { OrchestrationPlanPayload } from '@steerable/agent-protocol';
30
+ import { type RenderSlotResult } from './types.js';
31
+ export type OrchestrationTaskStatus = 'pending' | 'running' | 'ok' | 'skipped' | 'failed' | 'ask_user_paused';
32
+ export type OrchestrationTask = OrchestrationPlanPayload['tasks'][number];
33
+ export interface OrchestrationPlanCardProps {
34
+ payload: OrchestrationPlanPayload;
35
+ /** Status of each task, keyed by `payload.tasks[i].id`. Missing → pending. */
36
+ taskStatuses?: Record<string, OrchestrationTaskStatus>;
37
+ /** Lookup of agentId → display name; falls back to the raw id. */
38
+ agentNameFor?: (agentId: string) => string;
39
+ className?: string;
40
+ defaultExpanded?: boolean;
41
+ expanded?: boolean;
42
+ onExpandedChange?: (next: boolean) => void;
43
+ loading?: boolean;
44
+ loadingHint?: React.ReactNode;
45
+ failed?: boolean;
46
+ failure?: React.ReactNode;
47
+ headerLabel?: React.ReactNode;
48
+ headerSecondary?: React.ReactNode;
49
+ hideMode?: boolean;
50
+ hideHeaderCounts?: boolean;
51
+ renderAbove?: () => RenderSlotResult;
52
+ renderBelowHeader?: () => RenderSlotResult;
53
+ renderTaskRow?: (task: OrchestrationTask, status: OrchestrationTaskStatus) => RenderSlotResult;
54
+ }
55
+ declare const STATUS_LABEL: Record<OrchestrationTaskStatus, string>;
56
+ declare const DOT_CLASS: Record<OrchestrationTaskStatus, string>;
57
+ export declare const OrchestrationPlanCard: React.FC<OrchestrationPlanCardProps>;
58
+ export { STATUS_LABEL as ORCHESTRATION_STATUS_LABEL, DOT_CLASS as ORCHESTRATION_DOT_CLASS };
59
+ export default OrchestrationPlanCard;
60
+ //# sourceMappingURL=OrchestrationPlanCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrchestrationPlanCard.d.ts","sourceRoot":"","sources":["../../src/cards/OrchestrationPlanCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAQ1E,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhE,MAAM,MAAM,uBAAuB,GAC/B,SAAS,GACT,SAAS,GACT,IAAI,GACJ,SAAS,GACT,QAAQ,GACR,iBAAiB,CAAC;AAEtB,MAAM,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,wBAAwB,CAAC;IAClC,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;IACvD,kEAAkE;IAClE,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAG3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAG1B,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAG3B,WAAW,CAAC,EAAE,MAAM,gBAAgB,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,gBAAgB,CAAC;IAG3C,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,uBAAuB,KAAK,gBAAgB,CAAC;CAChG;AAED,QAAA,MAAM,YAAY,EAAE,MAAM,CAAC,uBAAuB,EAAE,MAAM,CAOzD,CAAC;AAEF,QAAA,MAAM,SAAS,EAAE,MAAM,CAAC,uBAAuB,EAAE,MAAM,CAOtD,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAkOtE,CAAC;AAEF,OAAO,EAAE,YAAY,IAAI,0BAA0B,EAAE,SAAS,IAAI,uBAAuB,EAAE,CAAC;AAE5F,eAAe,qBAAqB,CAAC"}