@chengxianglibra/dsh-data-analysis 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/README.en.md +135 -0
  2. package/README.md +105 -98
  3. package/cordis.patch.yml +1 -1
  4. package/lib/bin/environment.js +8 -6
  5. package/lib/client/credentials/changes.js +74 -0
  6. package/lib/client/credentials/create-datasource.js +126 -22
  7. package/lib/client/credentials/credential-draft.js +42 -0
  8. package/lib/client/credentials/defaults.js +11 -0
  9. package/lib/client/credentials/descriptions.js +46 -0
  10. package/lib/client/credentials/install.js +209 -81
  11. package/lib/client/credentials/model.js +323 -51
  12. package/lib/client/credentials/report-publishing.js +96 -0
  13. package/lib/client/credentials/styles.js +13 -9
  14. package/lib/client/i18n/context.js +22 -0
  15. package/lib/client/i18n/copy.js +60 -0
  16. package/lib/client/i18n/credentials.js +475 -0
  17. package/lib/client/i18n/host.js +28 -0
  18. package/lib/client/i18n/navigation.js +41 -0
  19. package/lib/client/i18n/presentation.js +577 -0
  20. package/lib/client/i18n/python.js +36 -0
  21. package/lib/client/i18n/semantic.js +441 -0
  22. package/lib/client/i18n/settings.js +30 -0
  23. package/lib/client/input-context.js +21 -0
  24. package/lib/client/python-tool/card.js +35 -0
  25. package/lib/client/python-tool/execution-error.js +35 -0
  26. package/lib/client/python-tool/install.js +9 -0
  27. package/lib/client/python-tool/model.js +101 -0
  28. package/lib/client/right-tabs/install.js +535 -0
  29. package/lib/client/right-tabs/live-delivery.js +58 -0
  30. package/lib/client/right-tabs/navigation.js +47 -0
  31. package/lib/client/right-tabs/page.js +178 -0
  32. package/lib/client/right-tabs/styles.js +11 -0
  33. package/lib/client/rpc.js +5 -0
  34. package/lib/client/semantic-reference.js +10 -0
  35. package/lib/client/settings/card.js +90 -0
  36. package/lib/client/settings/install.js +10 -0
  37. package/lib/client/workspace-header-action.js +14 -1
  38. package/lib/client/workspace-shortcuts.js +26 -0
  39. package/lib/client.js +388 -242
  40. package/lib/compatibility.js +1 -1
  41. package/lib/datasource/authoring.js +43 -4
  42. package/lib/datasource/bridge-programs.js +23 -20
  43. package/lib/datasource/bridge.js +46 -3
  44. package/lib/datasource/changes-contract.js +41 -0
  45. package/lib/datasource/changes.js +49 -0
  46. package/lib/datasource/configure.js +39 -0
  47. package/lib/datasource/defaults.js +25 -0
  48. package/lib/datasource/index.js +2 -1
  49. package/lib/datasource/python-options.js +15 -0
  50. package/lib/datasource/python.js +119 -25
  51. package/lib/datasource/rpc.js +75 -13
  52. package/lib/datasource/service.js +286 -11
  53. package/lib/datasource/test.js +3 -2
  54. package/lib/disclosure/activation.js +19 -7
  55. package/lib/disclosure/execution-guidance.js +49 -0
  56. package/lib/disclosure/help.js +4 -1
  57. package/lib/environment/runtime.js +35 -34
  58. package/lib/environment/workspace.js +18 -1
  59. package/lib/lifecycle.js +33 -0
  60. package/lib/plugin-agents.js +154 -0
  61. package/lib/plugin.js +98 -172
  62. package/lib/presentation/asset.js +34 -0
  63. package/lib/presentation/assets/portable.js +14 -14
  64. package/lib/presentation/assets/static.js +344 -73
  65. package/lib/presentation/build/index.js +3 -2
  66. package/lib/presentation/commit.js +19 -12
  67. package/lib/presentation/contracts/asset-path.js +9 -0
  68. package/lib/presentation/contracts/catalog.js +62 -0
  69. package/lib/presentation/contracts/charts.js +0 -23
  70. package/lib/presentation/contracts/index.js +17 -5
  71. package/lib/presentation/contracts/types.js +1 -1
  72. package/lib/presentation/delivery.js +45 -30
  73. package/lib/presentation/export-html.js +214 -0
  74. package/lib/presentation/files.js +4 -5
  75. package/lib/presentation/projection/index.js +2 -1
  76. package/lib/presentation/projection/program.js +2 -9
  77. package/lib/presentation/projection/sql-code.js +13 -13
  78. package/lib/presentation/reports.js +114 -17
  79. package/lib/presentation/rpc.js +96 -58
  80. package/lib/presentation/tool.js +6 -10
  81. package/lib/report-publishing/adapters.js +111 -0
  82. package/lib/report-publishing/config.js +69 -0
  83. package/lib/report-publishing/service.js +180 -0
  84. package/lib/rpc.js +49 -0
  85. package/lib/semantic-browser/contracts.js +17 -0
  86. package/lib/semantic-browser/program.js +10 -0
  87. package/lib/semantic-browser/service.js +40 -6
  88. package/lib/semantic-reference/bridge.js +10 -1
  89. package/lib/semantic-reference/contracts.js +20 -6
  90. package/lib/semantic-reference/environment.js +56 -0
  91. package/lib/semantic-reference/labels.js +16 -0
  92. package/lib/semantic-reference/rpc.js +39 -18
  93. package/lib/semantic-reference/search.js +5 -4
  94. package/lib/semantic-reference/usage.js +12 -3
  95. package/lib/settings.js +21 -0
  96. package/lib/tool-lifecycle.js +22 -0
  97. package/lib/types/client/credentials/changes.d.ts +9 -0
  98. package/lib/types/client/credentials/create-datasource.d.ts +3 -1
  99. package/lib/types/client/credentials/credential-draft.d.ts +14 -0
  100. package/lib/types/client/credentials/defaults.d.ts +2 -0
  101. package/lib/types/client/credentials/descriptions.d.ts +1 -0
  102. package/lib/types/client/credentials/install.d.ts +19 -1
  103. package/lib/types/client/credentials/model.d.ts +31 -11
  104. package/lib/types/client/credentials/report-publishing.d.ts +5 -0
  105. package/lib/types/client/credentials/styles.d.ts +1 -1
  106. package/lib/types/client/i18n/context.d.ts +17 -0
  107. package/lib/types/client/i18n/copy.d.ts +821 -0
  108. package/lib/types/client/i18n/credentials.d.ts +475 -0
  109. package/lib/types/client/i18n/host.d.ts +17 -0
  110. package/lib/types/client/i18n/navigation.d.ts +41 -0
  111. package/lib/types/client/i18n/presentation.d.ts +577 -0
  112. package/lib/types/client/i18n/python.d.ts +19 -0
  113. package/lib/types/client/i18n/semantic.d.ts +441 -0
  114. package/lib/types/client/i18n/settings.d.ts +16 -0
  115. package/lib/types/client/input-context.d.ts +19 -0
  116. package/lib/types/client/presentation/ask-dsh.d.ts +4 -8
  117. package/lib/types/client/presentation/catalog-model.d.ts +24 -0
  118. package/lib/types/client/presentation/catalog.d.ts +20 -0
  119. package/lib/types/client/presentation/chart-tooltip.d.ts +2 -2
  120. package/lib/types/client/presentation/context-reference.d.ts +12 -0
  121. package/lib/types/client/presentation/copy-context.d.ts +2 -2
  122. package/lib/types/client/presentation/delivery-model.d.ts +27 -6
  123. package/lib/types/client/presentation/delivery.d.ts +8 -7
  124. package/lib/types/client/presentation/download.d.ts +2 -0
  125. package/lib/types/client/presentation/export-menu.d.ts +26 -0
  126. package/lib/types/client/presentation/export-view.d.ts +63 -0
  127. package/lib/types/client/presentation/host-entry.d.ts +8 -2
  128. package/lib/types/client/presentation/icons.d.ts +1 -1
  129. package/lib/types/client/presentation/model.d.ts +14 -15
  130. package/lib/types/client/presentation/reader.d.ts +15 -2
  131. package/lib/types/client/presentation/reference-source.d.ts +9 -0
  132. package/lib/types/client/presentation/source-code-model.d.ts +2 -1
  133. package/lib/types/client/presentation/source-code.d.ts +0 -5
  134. package/lib/types/client/presentation/source-dialog.d.ts +1 -2
  135. package/lib/types/client/presentation/sources.d.ts +5 -5
  136. package/lib/types/client/presentation/styles.d.ts +1 -1
  137. package/lib/types/client/presentation/table.d.ts +5 -1
  138. package/lib/types/client/python-tool/card.d.ts +2 -0
  139. package/lib/types/client/python-tool/execution-error.d.ts +3 -0
  140. package/lib/types/client/python-tool/install.d.ts +2 -0
  141. package/lib/types/client/python-tool/model.d.ts +20 -0
  142. package/lib/types/client/right-tabs/install.d.ts +18 -0
  143. package/lib/types/client/right-tabs/live-delivery.d.ts +8 -0
  144. package/lib/types/client/right-tabs/navigation.d.ts +17 -0
  145. package/lib/types/client/right-tabs/page.d.ts +36 -0
  146. package/lib/types/client/right-tabs/styles.d.ts +2 -0
  147. package/lib/types/client/rpc.d.ts +3 -0
  148. package/lib/types/client/semantic-reference.d.ts +4 -0
  149. package/lib/types/client/settings/card.d.ts +9 -0
  150. package/lib/types/client/settings/install.d.ts +2 -0
  151. package/lib/types/client/workspace-header-action.d.ts +1 -1
  152. package/lib/types/client/workspace-shortcuts.d.ts +15 -0
  153. package/lib/types/client.d.ts +5 -2
  154. package/lib/types/compatibility.d.ts +1 -1
  155. package/lib/types/datasource/authoring.d.ts +10 -0
  156. package/lib/types/datasource/bridge.d.ts +23 -2
  157. package/lib/types/datasource/changes-contract.d.ts +18 -0
  158. package/lib/types/datasource/changes.d.ts +15 -0
  159. package/lib/types/datasource/configure.d.ts +7 -0
  160. package/lib/types/datasource/defaults.d.ts +7 -0
  161. package/lib/types/datasource/index.d.ts +6 -1
  162. package/lib/types/datasource/python-options.d.ts +8 -0
  163. package/lib/types/datasource/python.d.ts +17 -2
  164. package/lib/types/datasource/rpc.d.ts +2 -1
  165. package/lib/types/datasource/service.d.ts +48 -5
  166. package/lib/types/datasource/test.d.ts +1 -1
  167. package/lib/types/disclosure/activation.d.ts +2 -1
  168. package/lib/types/disclosure/execution-guidance.d.ts +6 -0
  169. package/lib/types/disclosure/help.d.ts +1 -1
  170. package/lib/types/environment/types.d.ts +2 -1
  171. package/lib/types/environment/workspace.d.ts +1 -0
  172. package/lib/types/lifecycle.d.ts +8 -0
  173. package/lib/types/plugin-agents.d.ts +29 -0
  174. package/lib/types/plugin.d.ts +12 -28
  175. package/lib/types/presentation/asset.d.ts +6 -0
  176. package/lib/types/presentation/build/index.d.ts +7 -2
  177. package/lib/types/presentation/commit.d.ts +1 -1
  178. package/lib/types/presentation/contracts/asset-path.d.ts +2 -0
  179. package/lib/types/presentation/contracts/catalog.d.ts +27 -0
  180. package/lib/types/presentation/contracts/charts.d.ts +0 -2
  181. package/lib/types/presentation/contracts/types.d.ts +7 -4
  182. package/lib/types/presentation/delivery.d.ts +1 -1
  183. package/lib/types/presentation/export-html.d.ts +13 -0
  184. package/lib/types/presentation/reports.d.ts +6 -1
  185. package/lib/types/presentation/rpc.d.ts +3 -2
  186. package/lib/types/presentation/tool.d.ts +2 -2
  187. package/lib/types/report-publishing/adapters.d.ts +6 -0
  188. package/lib/types/report-publishing/config.d.ts +22 -0
  189. package/lib/types/report-publishing/service.d.ts +68 -0
  190. package/lib/types/rpc.d.ts +3 -0
  191. package/lib/types/semantic-browser/contracts.d.ts +7 -0
  192. package/lib/types/semantic-browser/service.d.ts +7 -1
  193. package/lib/types/semantic-reference/bridge.d.ts +1 -0
  194. package/lib/types/semantic-reference/contracts.d.ts +5 -2
  195. package/lib/types/semantic-reference/environment.d.ts +22 -0
  196. package/lib/types/semantic-reference/labels.d.ts +16 -0
  197. package/lib/types/semantic-reference/rpc.d.ts +1 -1
  198. package/lib/types/semantic-reference/search.d.ts +1 -1
  199. package/lib/types/settings.d.ts +14 -0
  200. package/lib/types/tool-lifecycle.d.ts +4 -0
  201. package/lib/types/workspace-identity.d.ts +6 -0
  202. package/lib/workspace-identity.js +9 -0
  203. package/package.json +93 -61
  204. package/python/presentation-kit/dist/dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl +0 -0
  205. package/skills/dsh-data-analysis-files/SKILL.md +44 -0
  206. package/skills/dsh-data-analysis-files/references/delivery.md +15 -0
  207. package/skills/dsh-data-analysis-files/references/examples.md +93 -0
  208. package/skills/dsh-data-analysis-presentation/SKILL.md +15 -15
  209. package/skills/dsh-data-analysis-presentation/references/examples/artifact.draft.json +13 -4
  210. package/skills/dsh-data-analysis-presentation/references/examples/charts.draft.json +3 -2
  211. package/skills/dsh-data-analysis-presentation/references/examples/comparison.draft.json +3 -2
  212. package/skills/dsh-data-analysis-presentation/references/examples/computed-sources.draft.json +12 -5
  213. package/skills/dsh-data-analysis-presentation/references/examples/computed.draft.json +3 -2
  214. package/skills/dsh-data-analysis-presentation/references/examples/interaction.draft.json +3 -2
  215. package/skills/dsh-data-analysis-presentation/references/examples/source-only.draft.json +12 -4
  216. package/skills/dsh-data-analysis-presentation/references/examples.md +3 -1
  217. package/skills/dsh-data-analysis-presentation/references/export-html.md +7 -0
  218. package/skills/dsh-data-analysis-presentation/references/interaction.md +1 -1
  219. package/skills/dsh-data-analysis-presentation/references/narrative.md +1 -1
  220. package/skills/dsh-data-analysis-presentation/references/publishing.md +3 -0
  221. package/skills/dsh-data-analysis-presentation/references/schema.md +29 -2
  222. package/lib/types/client/presentation/install.d.ts +0 -15
@@ -1,47 +1,68 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useRef, useState, useSyncExternalStore } from 'react';
3
- import { WorkspaceHeaderAction } from "../workspace-header-action.js";
3
+ import { useCopy } from "./../i18n/context.js";
4
+ import { localized } from "../i18n/host.js";
4
5
  import { CreateDatasource } from "./create-datasource.js";
5
6
  import { CredentialClientModel, credentialMessage } from "./model.js";
7
+ import { ReportPublishingCredentials } from "./report-publishing.js";
6
8
  import { credentialStyles } from "./styles.js";
7
9
  const statusLabels = {
8
- 'awaiting-input': '等待填写',
9
- executing: '正在保存或验证',
10
- 'awaiting-decision': '连接验证失败,等待处理',
11
- succeeded: '验证完成,原调用继续',
12
- 'handed-off': '已交给助手排查',
13
- 'call-ended': '原调用已结束',
14
- 'context-changed': '上下文已变化',
10
+ 'awaiting-input': 'marivo.credentials.awaiting-input',
11
+ executing: 'marivo.credentials.saving-or-validating-77',
12
+ 'awaiting-decision': 'marivo.credentials.connection-validation-failed-action-needed',
13
+ succeeded: 'marivo.credentials.validated-original-call-continues',
14
+ 'handed-off': 'marivo.credentials.handed-to-the-assistant-for-investigation',
15
+ 'call-ended': 'marivo.credentials.original-call-ended',
16
+ cancelled: 'marivo.credentials.configuration-request-cancelled',
17
+ 'context-changed': 'marivo.credentials.context-changed',
15
18
  };
16
- function Icon({ name, size = 18 }) {
17
- return (_jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [name === 'database' && (_jsxs(_Fragment, { children: [_jsx("ellipse", { cx: "12", cy: "5", rx: "8", ry: "3" }), _jsx("path", { d: "M4 5v14c0 4 16 4 16 0V5M4 12c0 4 16 4 16 0" })] })), name === 'lock' && (_jsxs(_Fragment, { children: [_jsx("rect", { x: "4", y: "10", width: "16", height: "11", rx: "2" }), _jsx("path", { d: "M8 10V7a4 4 0 0 1 8 0v3m-4 5v2" })] })), name === 'close' && _jsx("path", { d: "m6 6 12 12M6 18 18 6" }), name === 'refresh' && (_jsx("path", { d: "M20 7v5h-5M4 17v-5h5M6.1 6a8 8 0 0 1 13.4 3M4.5 15a8 8 0 0 0 13.4 3" })), name === 'check' && _jsx("path", { d: "m5 12 4 4L19 6" }), name === 'info' && (_jsxs(_Fragment, { children: [_jsx("circle", { cx: "12", cy: "12", r: "9" }), _jsx("path", { d: "M12 11v6m0-10v.01" })] }))] }));
19
+ export function CredentialIcon({ name, size = 18 }) {
20
+ return (_jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [name === 'database' && (_jsxs(_Fragment, { children: [_jsx("ellipse", { cx: "12", cy: "5", rx: "8", ry: "3" }), _jsx("path", { d: "M4 5v14c0 4 16 4 16 0V5M4 12c0 4 16 4 16 0" })] })), name === 'refresh' && (_jsx("path", { d: "M20 7v5h-5M4 17v-5h5M6.1 6a8 8 0 0 1 13.4 3M4.5 15a8 8 0 0 0 13.4 3" })), name === 'add' && _jsx("path", { d: "M12 5v14M5 12h14" }), name === 'edit' && _jsx("path", { d: "m16 3 5 5L9 20l-6 1 1-6L16 3ZM13 6l5 5" }), name === 'delete' && _jsx("path", { d: "M3 6h18M9 6V3h6v3M5 6l1 15h12l1-15M10 10v7m4-7v7" }), name === 'test' && (_jsx("path", { d: "M9 3h6M10 3v6l-6 10a1.3 1.3 0 0 0 1 2h14a1.3 1.3 0 0 0 1-2L14 9V3M7 15h10" })), name === 'check' && _jsx("path", { d: "m5 12 4 4L19 6" }), name === 'info' && (_jsxs(_Fragment, { children: [_jsx("circle", { cx: "12", cy: "12", r: "9" }), _jsx("path", { d: "M12 11v6m0-10v.01" })] }))] }));
18
21
  }
19
- function TestResult({ result, stale = false }) {
22
+ export function TestResult({ result, stale = false }) {
23
+ const t = useCopy();
20
24
  if (!result)
21
25
  return null;
22
- return (_jsxs("div", { className: "mc-result", "data-tone": stale ? 'stale' : result.ok ? 'success' : 'error', role: "status", children: [_jsxs("div", { className: "mc-result-title", children: [_jsx(Icon, { name: stale || !result.ok ? 'info' : 'check', size: 16 }), stale ? '配置已变化,请重新测试' : result.ok ? '连接测试成功' : '连接测试失败'] }), !result.ok && !stale && (_jsxs(_Fragment, { children: [_jsx("p", { children: result.failure?.message }), result.repair?.action && _jsx("p", { children: result.repair.action }), result.failure?.code && (_jsxs("details", { children: [_jsx("summary", { children: "\u67E5\u770B\u9519\u8BEF\u4EE3\u7801" }), _jsx("pre", { children: result.failure.code })] }))] }))] }));
26
+ return (_jsxs("div", { className: "mc-result", "data-tone": stale ? 'stale' : result.ok ? 'success' : 'error', role: "status", children: [_jsxs("div", { className: "mc-result-title", children: [_jsx(CredentialIcon, { name: stale || !result.ok ? 'info' : 'check', size: 16 }), stale
27
+ ? t('marivo.credentials.configuration-changed-test-again')
28
+ : result.ok
29
+ ? t('marivo.credentials.connection-test-succeeded')
30
+ : t('marivo.credentials.connection-test-failed')] }), !result.ok && !stale && (_jsxs(_Fragment, { children: [_jsx("p", { children: t(result.failure?.message) }), result.repair?.action && _jsx("p", { children: result.repair.action }), result.failure?.code && (_jsxs("details", { children: [_jsx("summary", { children: t('marivo.credentials.show-error-code') }), _jsx("pre", { children: result.failure.code })] }))] }))] }));
23
31
  }
24
32
  function OperationOutcome({ entry }) {
33
+ const t = useCopy();
25
34
  if (!entry)
26
35
  return null;
27
36
  const operation = entry.operation;
28
37
  const errors = operation?.errors ?? [];
38
+ if (operation?.action === 'delete-datasource')
39
+ return (_jsxs("div", { className: "mc-operation-note", "data-error": operation.status !== 'succeeded', role: "status", children: [_jsx("p", { children: operation.datasourceRemoved
40
+ ? t('marivo.credentials.datasource-value-was-deleted', { p0: entry.name })
41
+ : t('marivo.credentials.deletion-of-datasource-value-is-unconfirmed-refresh-the-list', {
42
+ p0: entry.name,
43
+ }) }), operation.datasourceRemoved && !operation.deleteCredentials && (_jsx("p", { children: t('marivo.credentials.associated-saved-credentials-were-retained') })), operation.deletedCredentials?.length > 0 && (_jsxs("p", { children: [t('marivo.credentials.deleted-credentials'), operation.deletedCredentials.join('、'), "\u3002"] })), operation.credentialDeleteFailures?.length > 0 && (_jsxs("p", { children: [t('marivo.credentials.credentials-that-could-not-be-deleted'), operation.credentialDeleteFailures.join('、'), "\u3002"] })), operation.status === 'cancelled' && (_jsx("p", { children: t('marivo.credentials.operation-cancelled-completed-deletions-remain-other-credentials-may-still') })), errors.length > 0 && _jsx("p", { children: errors.map(credentialMessage).join(' ') })] }));
29
44
  const unsuccessful = entry.error ||
30
45
  operation?.status === 'cancelled' ||
31
46
  operation?.status === 'failed' ||
32
47
  operation?.result?.ok === false;
33
48
  if (!unsuccessful && operation?.action !== 'delete')
34
49
  return null;
35
- return (_jsxs("div", { className: "mc-operation-note", "data-error": Boolean(entry.error || errors.length), role: "status", children: [entry.error && _jsx("p", { children: entry.error }), operation?.status === 'cancelled' && _jsx("p", { children: "\u672C\u6B21\u64CD\u4F5C\u5DF2\u53D6\u6D88\u3002" }), operation?.status === 'succeeded' && operation.action === 'delete' && (_jsx("p", { children: "\u5DF2\u5220\u9664\u4FDD\u5B58\u503C\uFF0C\u5F53\u524D\u914D\u7F6E\u72B6\u6001\u5DF2\u66F4\u65B0\u3002" })), errors.length > 0 && _jsx("p", { children: errors.map(credentialMessage).join(' ') }), operation?.status === 'failed' && errors.length === 0 && !operation.result && (_jsx("p", { children: "\u64CD\u4F5C\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5\u3002" })), unsuccessful && operation?.saved.length > 0 && _jsxs("p", { children: ["\u5DF2\u4FDD\u5B58\uFF1A", operation.saved.join('、'), "\u3002"] })] }));
50
+ return (_jsxs("div", { className: "mc-operation-note", "data-error": Boolean(entry.error || errors.length), role: "status", children: [entry.error && _jsx("p", { children: t(entry.error) }), operation?.status === 'cancelled' && (_jsx("p", { children: t('marivo.credentials.this-operation-was-cancelled') })), operation?.status === 'succeeded' && operation.action === 'delete' && (_jsx("p", { children: t('marivo.credentials.saved-value-deleted-configuration-status-updated') })), errors.length > 0 && _jsx("p", { children: errors.map(credentialMessage).join(' ') }), operation?.status === 'failed' && errors.length === 0 && !operation.result && (_jsx("p", { children: t('marivo.credentials.operation-incomplete-please-retry') })), unsuccessful && operation?.saved.length > 0 && (_jsxs("p", { children: [t('marivo.credentials.saved'), operation.saved.join('、'), "\u3002"] }))] }));
36
51
  }
37
- function DatasourceProperties({ context }) {
52
+ export function DatasourceProperties({ context }) {
53
+ const t = useCopy();
38
54
  const properties = Object.entries(context.properties ?? {});
39
- return (_jsxs("section", { className: "mc-properties", "aria-label": "\u6570\u636E\u6E90\u5C5E\u6027", children: [_jsx("h4", { className: "mc-section-heading", children: "\u6570\u636E\u6E90\u5C5E\u6027" }), _jsxs("dl", { className: "mc-property-list", children: [_jsxs("div", { className: "mc-property", children: [_jsx("dt", { children: "\u5F15\u64CE" }), _jsx("dd", { children: context.backend || '未提供' })] }), properties.map(([field, value]) => (_jsxs("div", { className: "mc-property", children: [_jsx("dt", { children: field }), _jsx("dd", { children: value !== null && typeof value === 'object' ? (_jsx("section", { className: "mc-property-json", tabIndex: 0, "aria-label": `${field} 配置值`, children: _jsx("pre", { children: JSON.stringify(value, null, 2) }) })) : (_jsx("span", { children: typeof value === 'string' && value !== '' ? value : JSON.stringify(value) })) })] }, field)))] })] }));
55
+ return (_jsxs("section", { className: "mc-properties", "aria-label": t('marivo.credentials.datasource-properties'), children: [_jsx("h4", { className: "mc-section-heading", children: t('marivo.credentials.datasource-properties') }), _jsxs("dl", { className: "mc-property-list", children: [_jsxs("div", { className: "mc-property", children: [_jsx("dt", { children: t('marivo.credentials.engine') }), _jsx("dd", { children: context.backend || t('marivo.credentials.not-provided') })] }), properties.map(([field, value]) => (_jsxs("div", { className: "mc-property", children: [_jsx("dt", { children: field }), _jsx("dd", { children: value !== null && typeof value === 'object' ? (_jsx("section", { className: "mc-property-json",
56
+ // biome-ignore lint/a11y/noNoninteractiveTabindex: Keyboard users must be able to scroll long JSON values.
57
+ tabIndex: 0, "aria-label": t('marivo.credentials.value-configuration-value', { p0: field }), children: _jsx("pre", { children: JSON.stringify(value, null, 2) }) })) : (_jsx("span", { children: typeof value === 'string' && value !== '' ? value : JSON.stringify(value) })) })] }, field)))] })] }));
40
58
  }
41
- function CredentialForm({ context, request, state, model, workspaceId }) {
59
+ function CredentialForm({ context, request, state, model, workspaceId, onEdit }) {
60
+ const t = useCopy();
42
61
  const [values, setValues] = useState({});
43
62
  const [editing, setEditing] = useState({});
44
63
  const [deleting, setDeleting] = useState('');
64
+ const [removingDatasource, setRemovingDatasource] = useState(false);
65
+ const [removeCredentials, setRemoveCredentials] = useState(false);
45
66
  const busy = request?.status === 'executing' ||
46
67
  state.operations.some((entry) => entry.handle.scope === context.token);
47
68
  const ended = request?.endedAt !== undefined;
@@ -57,6 +78,8 @@ function CredentialForm({ context, request, state, model, workspaceId }) {
57
78
  setValues({});
58
79
  setEditing({});
59
80
  setDeleting('');
81
+ setRemovingDatasource(false);
82
+ setRemoveCredentials(false);
60
83
  }, [context.token, context.version]);
61
84
  const saveReference = (ref) => {
62
85
  const changes = { [ref]: values[ref] };
@@ -70,91 +93,183 @@ function CredentialForm({ context, request, state, model, workspaceId }) {
70
93
  setEditing({});
71
94
  void model.start(context, request ? 'submit' : 'update', changes);
72
95
  };
73
- return (_jsxs("section", { className: "mc-form", "aria-label": `${context.name} 凭证配置`, children: [_jsxs("div", { className: "mc-form-body", children: [_jsxs("div", { className: "mc-detail-heading", children: [_jsxs("div", { children: [_jsx("p", { className: "mc-eyebrow", children: "\u6570\u636E\u6E90\u914D\u7F6E" }), _jsx("h3", { children: context.name })] }), _jsxs("span", { className: "mc-badge", "data-ready": ready, children: [ready && _jsx(Icon, { name: "check", size: 13 }), context.refs.length === 0
74
- ? '无需凭证'
75
- : ready
76
- ? '凭证已配齐'
77
- : `${configured} / ${context.refs.length} 项已配置`] })] }), request && (_jsxs("div", { className: "mc-request-status", role: "status", children: [_jsx("strong", { children: statusLabels[request.status] }), !ended && _jsx("p", { children: "\u9A8C\u8BC1\u6210\u529F\u540E\u7EE7\u7EED\u5F53\u524D\u4EFB\u52A1\u3002" }), (request.status === 'call-ended' || request.status === 'context-changed') && (_jsx("p", { children: "\u8BF7\u91CD\u65B0\u53D1\u8D77\u4EFB\u52A1\u3002" }))] })), _jsx(DatasourceProperties, { context: context }), _jsx("h4", { className: "mc-section-heading", children: "\u51ED\u8BC1" }), context.refs.length === 0 && (_jsx("p", { className: "mc-note", children: "\u8BE5\u6570\u636E\u6E90\u6CA1\u6709\u51ED\u8BC1\u5F15\u7528\uFF0C\u53EF\u76F4\u63A5\u6D4B\u8BD5\u8FDE\u63A5\u3002" })), context.refs.length > 0 && (_jsx("div", { className: "mc-fields", children: context.refs.map((ref) => {
96
+ return (_jsxs("section", { className: "mc-form", "aria-label": t('marivo.credentials.value-credential-configuration', { p0: context.name }), children: [_jsxs("div", { className: "mc-form-body", children: [_jsxs("div", { className: "mc-detail-heading mc-datasource-heading", children: [_jsx("p", { className: "mc-eyebrow", children: t('marivo.credentials.datasource-configuration') }), _jsxs("div", { className: "mc-name-row", children: [_jsx("h3", { children: context.name }), _jsxs("div", { className: "mc-heading-actions", children: [_jsxs("span", { className: "mc-badge", "data-ready": ready, children: [ready && _jsx(CredentialIcon, { name: "check", size: 13 }), context.refs.length === 0
97
+ ? t('marivo.credentials.no-credentials-required')
98
+ : ready
99
+ ? t('marivo.credentials.all-credentials-configured')
100
+ : t('marivo.credentials.value-value-configured', {
101
+ p0: configured,
102
+ p1: context.refs.length,
103
+ })] }), !ended && (_jsx("button", { className: "mc-icon-button", type: "button", title: t('marivo.credentials.edit-configuration'), "aria-label": t('marivo.credentials.edit-configuration'), disabled: busy, onClick: onEdit, children: _jsx(CredentialIcon, { name: "edit" }) })), !request && (_jsx("button", { className: "mc-icon-button mc-danger", type: "button", title: t('marivo.credentials.delete-datasource'), "aria-label": t('marivo.credentials.delete-datasource'), disabled: busy || state.loading, onClick: () => setRemovingDatasource(true), children: _jsx(CredentialIcon, { name: "delete" }) }))] })] })] }), removingDatasource && (_jsxs("fieldset", { className: "mc-confirm", "aria-label": t('marivo.credentials.confirm-datasource-deletion'), children: [_jsxs("p", { children: [t('marivo.credentials.confirm-datasource-deletion'), context.name, t('marivo.credentials.this-removes-the-datasource-definition-from-this-workspace-not')] }), context.refs.length > 0 && (_jsxs(_Fragment, { children: [_jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: removeCredentials, disabled: busy, onChange: (event) => setRemoveCredentials(event.target.checked) }), ' ', t('marivo.credentials.also-delete-associated-saved-credentials')] }), _jsxs("p", { children: [t('marivo.credentials.credential-references'), context.refs.join('、'), t('marivo.credentials.other-datasources-or-workspaces-may-share-these-credentials-and')] })] })), _jsx("button", { className: "mc-danger", type: "button", disabled: busy || state.loading, onClick: () => {
104
+ setRemovingDatasource(false);
105
+ void model.start(context, 'delete-datasource', {}, undefined, removeCredentials);
106
+ }, children: t('marivo.credentials.confirm-datasource-deletion') }), _jsx("button", { type: "button", disabled: busy, onClick: () => {
107
+ setRemovingDatasource(false);
108
+ setRemoveCredentials(false);
109
+ }, children: t('marivo.credentials.cancel') })] })), request && (_jsxs("div", { className: "mc-request-status", role: "status", children: [_jsx("strong", { children: t(statusLabels[request.status]) }), !ended && (_jsx("p", { children: t('marivo.credentials.continue-the-current-task-after-successful-validation') })), (request.status === 'call-ended' || request.status === 'context-changed') && (_jsx("p", { children: t('marivo.credentials.start-the-task-again') }))] })), _jsx(DatasourceProperties, { context: context }), _jsx("h4", { className: "mc-section-heading", children: t('marivo.credentials.credentials') }), context.refs.length === 0 && (_jsx("p", { className: "mc-note", children: t('marivo.credentials.this-datasource-has-no-credential-references-you-can-test') })), context.refs.length > 0 && (_jsx("div", { className: "mc-fields", children: context.refs.map((ref) => {
78
110
  const info = context.credentials[ref];
79
111
  const shared = state.datasources
80
112
  .filter((item) => item.refs.includes(ref))
81
113
  .map((item) => item.name);
82
- return (_jsxs("fieldset", { className: "mc-field", disabled: busy || ended, "aria-label": ref, children: [_jsxs("div", { className: "mc-field-header", children: [_jsxs("div", { className: "mc-field-title", children: [_jsx("h4", { children: ref }), _jsxs("p", { children: ["\u5B57\u6BB5\uFF1A", Object.entries(context.fields)
114
+ return (_jsxs("fieldset", { className: "mc-field", disabled: busy || ended, "aria-label": ref, children: [_jsxs("div", { className: "mc-field-header", children: [_jsxs("div", { className: "mc-field-title", children: [_jsx("h4", { children: ref }), _jsxs("p", { children: [t('marivo.credentials.field'), Object.entries(context.fields)
83
115
  .filter(([, value]) => value === ref)
84
116
  .map(([field]) => field)
85
- .join('、'), ' ', "\u00B7 \u6765\u6E90\uFF1A", info?.source ?? '无', !info?.writable && ' · 来源只读'] })] }), _jsxs("div", { className: "mc-field-actions", children: [_jsx("span", { className: "mc-badge", "data-ready": Boolean(info?.configured), children: info?.configured ? '已配置' : '未配置' }), info?.writable && info.configured && !editing[ref] && (_jsx("button", { type: "button", onClick: () => setEditing({ ...editing, [ref]: true }), children: "\u66F4\u6362" })), info?.writable && info.configured && editing[ref] && (_jsx("button", { type: "button", onClick: () => {
117
+ .join('、'), ' ', t('marivo.credentials.source'), info?.source ?? t('marivo.credentials.none'), !info?.writable && t('marivo.credentials.read-only-source')] })] }), _jsxs("div", { className: "mc-field-actions", children: [_jsx("span", { className: "mc-badge", "data-ready": Boolean(info?.configured), children: info?.configured
118
+ ? t('marivo.credentials.configured')
119
+ : t('marivo.credentials.not-configured') }), info?.writable && info.configured && !editing[ref] && (_jsx("button", { type: "button", onClick: () => setEditing({ ...editing, [ref]: true }), children: t('marivo.credentials.replace') })), info?.writable && info.configured && editing[ref] && (_jsx("button", { type: "button", onClick: () => {
86
120
  setValues({ ...values, [ref]: '' });
87
121
  setEditing({ ...editing, [ref]: false });
88
- }, children: "\u53D6\u6D88\u66F4\u6362" })), info?.writable && !request && info.configured && (_jsx("button", { className: "mc-quiet", type: "button", onClick: () => setDeleting(ref), children: "\u5220\u9664\u5DF2\u4FDD\u5B58\u503C" }))] })] }), info?.writable && (!info.configured || editing[ref]) && (_jsxs("label", { className: "mc-secret-input", children: ["\u65B0\u503C", _jsx("input", { type: "password", autoComplete: "new-password", placeholder: "\u8F93\u5165\u51ED\u8BC1\u503C", value: values[ref] ?? '', onChange: (event) => setValues({ ...values, [ref]: event.target.value }) }), !request && (_jsx("button", { type: "button", className: "mc-primary", disabled: !values[ref], onClick: () => saveReference(ref), children: info.configured ? '确认更换' : '新增凭证' }))] })), shared.length > 1 && (_jsxs("p", { className: "mc-field-note", children: ["\u4E0E ", shared.filter((name) => name !== context.name).join('、'), " \u5171\u4EAB\u6B64\u5F15\u7528"] })), deleting === ref && (_jsxs("div", { className: "mc-confirm", children: [_jsxs("p", { children: ["\u786E\u8BA4\u5220\u9664 ", ref, " \u7684\u5DF2\u4FDD\u5B58\u503C\uFF1F"] }), _jsx("button", { className: "mc-danger", type: "button", onClick: () => {
122
+ }, children: t('marivo.credentials.cancel-replacement') })), info?.writable && !request && info.configured && (_jsx("button", { className: "mc-danger", type: "button", onClick: () => setDeleting(ref), children: t('marivo.credentials.delete-saved-value') }))] })] }), info?.writable && (!info.configured || editing[ref]) && (_jsxs("label", { className: "mc-secret-input", children: [t('marivo.credentials.new-value'), _jsx("input", { type: "password", autoComplete: "new-password", placeholder: t('marivo.credentials.enter-credential-value-127'), value: values[ref] ?? '', onChange: (event) => setValues({ ...values, [ref]: event.target.value }) }), !request && (_jsx("button", { type: "button", className: "mc-primary", disabled: !values[ref], onClick: () => saveReference(ref), children: info.configured
123
+ ? t('marivo.credentials.confirm-replacement')
124
+ : t('marivo.credentials.add-credential') }))] })), shared.length > 1 && (_jsxs("p", { className: "mc-field-note", children: [t('marivo.credentials.and'), shared.filter((name) => name !== context.name).join('、'), ' ', t('marivo.credentials.share-this-reference')] })), deleting === ref && (_jsxs("div", { className: "mc-confirm", children: [_jsxs("p", { children: [t('marivo.credentials.confirm-deletion-of'), ref, " ", t('marivo.credentials.the-saved-value')] }), _jsx("button", { className: "mc-danger", type: "button", onClick: () => {
89
125
  setDeleting('');
90
126
  void model.start(context, 'delete', {}, ref);
91
- }, children: "\u786E\u8BA4\u5220\u9664\u5DF2\u4FDD\u5B58\u503C" }), _jsx("button", { type: "button", onClick: () => setDeleting(''), children: "\u4FDD\u7559" })] }))] }, ref));
92
- }) })), _jsxs("div", { className: "mc-test", children: [_jsxs("div", { className: "mc-test-heading", children: [_jsx("h4", { children: "\u8FDE\u63A5\u72B6\u6001" }), latestTest?.at !== undefined && (_jsxs("time", { dateTime: new Date(latestTest.at).toISOString(), children: ["\u4E0A\u6B21\u6D4B\u8BD5\uFF1A", new Date(latestTest.at).toLocaleString()] }))] }), latestResult ? (_jsx(TestResult, { result: latestResult, stale: !request?.failure && latestTest?.stale })) : (_jsx("p", { className: "mc-empty-test", children: "\u5C1A\u672A\u6D4B\u8BD5\u8FDE\u63A5\u3002" })), _jsx(OperationOutcome, { entry: outcome })] })] }), !ended && (_jsxs("div", { className: "mc-form-footer", children: [request && (_jsx("button", { className: "mc-primary", type: "button", disabled: busy, onClick: submit, children: "\u63D0\u4EA4\u51ED\u8BC1\u5E76\u7EE7\u7EED" })), _jsx("button", { type: "button", disabled: busy, onClick: () => void model.start(context, request ? 'submit' : 'test'), children: request ? '使用已有配置验证并继续' : '测试连接' }), request?.failure && (_jsx("button", { type: "button", disabled: busy, onClick: () => void model.start(context, 'diagnose'), children: "\u4EA4\u7ED9\u52A9\u624B\u6392\u67E5" })), request ? (_jsx("button", { className: "mc-quiet mc-cancel", type: "button", onClick: () => void model.cancelRequest(request.id), children: "\u53D6\u6D88\u672C\u8F6E" })) : (busy && (_jsx("button", { className: "mc-quiet mc-cancel", type: "button", onClick: () => void model.cancelOperation(context.token), children: "\u53D6\u6D88\u64CD\u4F5C" })))] })), ended && (_jsxs("div", { className: "mc-form-footer", children: [_jsx("button", { type: "button", onClick: () => model.show(workspaceId), children: "\u8FD4\u56DE\u6570\u636E\u6E90\u7BA1\u7406" }), _jsx("button", { className: "mc-quiet", type: "button", onClick: () => model.close(), children: "\u5B8C\u6210" })] }))] }));
127
+ }, children: t('marivo.credentials.confirm-saved-value-deletion') }), _jsx("button", { type: "button", onClick: () => setDeleting(''), children: t('marivo.credentials.keep') })] }))] }, ref));
128
+ }) })), _jsxs("div", { className: "mc-test", children: [_jsxs("div", { className: "mc-test-heading", children: [_jsx("h4", { children: t('marivo.credentials.connection-status') }), _jsxs("div", { className: "mc-heading-actions", children: [latestTest?.at !== undefined && (_jsxs("time", { dateTime: new Date(latestTest.at).toISOString(), children: [t('marivo.credentials.last-test'), new Date(latestTest.at).toLocaleString()] })), !request && (_jsx("button", { className: "mc-icon-button", type: "button", title: t('marivo.credentials.test-connection'), "aria-label": t('marivo.credentials.test-connection'), disabled: busy, onClick: () => void model.start(context, 'test'), children: _jsx(CredentialIcon, { name: "test" }) }))] })] }), latestResult ? (_jsx(TestResult, { result: latestResult, stale: !request?.failure && latestTest?.stale })) : (_jsx("p", { className: "mc-empty-test", children: t('marivo.credentials.connection-has-not-been-tested') })), outcome?.operation?.action !== 'delete-datasource' && (_jsx(OperationOutcome, { entry: outcome }))] })] }), !ended && (request || busy) && (_jsxs("div", { className: "mc-form-footer", children: [request && (_jsx("button", { className: "mc-primary", type: "button", disabled: busy, onClick: submit, children: t('marivo.credentials.submit-credentials-and-continue') })), request && (_jsx("button", { type: "button", disabled: busy, onClick: () => void model.start(context, 'submit'), children: t('marivo.credentials.validate-existing-configuration-and-continue') })), request?.failure && (_jsx("button", { type: "button", disabled: busy, onClick: () => void model.start(context, 'diagnose'), children: t('marivo.credentials.ask-the-assistant-to-investigate') })), request ? (_jsx("button", { className: "mc-quiet mc-cancel", type: "button", onClick: () => void model.cancelRequest(request.id), children: t('marivo.credentials.cancel-this-round') })) : (busy && (_jsx("button", { className: "mc-quiet mc-cancel", type: "button", onClick: () => void model.cancelOperation(context.token), children: t('marivo.credentials.cancel-operation') })))] })), ended && (_jsx("div", { className: "mc-form-footer", children: _jsx("button", { type: "button", onClick: () => model.show(workspaceId), children: t('marivo.credentials.back-to-datasource-management') }) }))] }));
93
129
  }
94
- function CredentialPanel({ model, workspaces }) {
130
+ export function CredentialPanel({ model, workspaces, onRefresh }) {
131
+ const t = useCopy();
95
132
  const state = useSyncExternalStore(model.subscribe, model.getSnapshot);
96
- const dialog = useRef(null);
97
133
  const columns = useRef(null);
134
+ const navigation = useRef(null);
98
135
  const main = useRef(null);
99
136
  const [creating, setCreating] = useState(false);
137
+ const [editingName, setEditingName] = useState('');
138
+ const [requestError, setRequestError] = useState('');
139
+ const [requestChoice, setRequestChoice] = useState('create');
100
140
  // biome-ignore lint/correctness/useExhaustiveDependencies: Switching context discards the creation form.
101
- useEffect(() => setCreating(false), [state.open, state.workspaceId, state.requestId]);
102
141
  useEffect(() => {
103
- if (state.open)
104
- dialog.current?.showModal();
105
- else
106
- dialog.current?.close();
107
- }, [state.open]);
142
+ setCreating(false);
143
+ setEditingName('');
144
+ setRequestError('');
145
+ setRequestChoice('create');
146
+ }, [state.open, state.workspaceId, state.requestId]);
108
147
  const request = state.requests.find((item) => item.id === state.requestId);
148
+ // biome-ignore lint/correctness/useExhaustiveDependencies: Open the initial form once per request occurrence; live watch updates must preserve user navigation.
149
+ useEffect(() => {
150
+ if (!request?.configuration || request.context || request.endedAt !== undefined)
151
+ return;
152
+ setCreating(true);
153
+ setEditingName(request.configuration.mode === 'edit' ? request.configuration.name : '');
154
+ }, [request?.id, state.open]);
155
+ useEffect(() => {
156
+ if (request?.endedAt === undefined)
157
+ return;
158
+ setCreating(false);
159
+ setEditingName('');
160
+ }, [request?.endedAt]);
109
161
  const pending = state.requests.filter((item) => item.endedAt === undefined && item.sessionId === state.sessionId);
110
- const context = request?.context ?? state.datasources.find((item) => item.token === state.selected);
162
+ const context = request
163
+ ? request.context
164
+ : state.datasources.find((item) => item.token === state.selected);
111
165
  // biome-ignore lint/correctness/useExhaustiveDependencies: A different detail or creation page starts at the top of its content.
112
166
  useEffect(() => {
113
- if (main.current)
167
+ if (main.current) {
114
168
  main.current.scrollTop = 0;
169
+ const page = main.current.closest('.rt-page');
170
+ if (page)
171
+ page.scrollTop = 0;
172
+ }
115
173
  if (columns.current)
116
174
  columns.current.scrollTop = 0;
175
+ const list = navigation.current;
176
+ const selected = list?.querySelector('[aria-pressed="true"]');
177
+ if (selected) {
178
+ const bounds = selected.getBoundingClientRect();
179
+ const viewport = list.getBoundingClientRect();
180
+ if (bounds.left < viewport.left)
181
+ list.scrollLeft += bounds.left - viewport.left;
182
+ else if (bounds.right > viewport.right)
183
+ list.scrollLeft += bounds.right - viewport.right;
184
+ }
117
185
  }, [creating, context?.token]);
118
186
  const workspaceId = request
119
187
  ? (workspaces.find((item) => item.sessionIds.includes(request.sessionId))?.workspaceId ?? '')
120
188
  : state.workspaceId;
121
- const datasources = request ? [request.context] : state.datasources;
189
+ const datasources = request ? (request.context ? [request.context] : []) : state.datasources;
122
190
  const operations = state.operations.filter((entry) => entry.workspaceId === workspaceId);
123
191
  const activeOperation = operations.find((entry) => entry.handle.id === state.handle?.id)?.operation;
124
192
  if (!state.open)
125
193
  return null;
126
- return (_jsxs("dialog", { ref: dialog, className: "mc-dialog", onCancel: (event) => {
127
- event.preventDefault();
128
- model.close();
129
- }, "aria-labelledby": "marivo-credentials-title", children: [_jsx("style", { children: credentialStyles }), _jsxs("div", { className: "mc-shell", children: [_jsxs("header", { className: "mc-header", children: [_jsx("div", { className: "mc-header-mark", children: _jsx(Icon, { name: "lock", size: 22 }) }), _jsxs("div", { className: "mc-header-copy", children: [_jsx("h2", { id: "marivo-credentials-title", children: "\u6570\u636E\u6E90\u4E0E\u51ED\u8BC1" }), _jsx("p", { children: "\u914D\u7F6E\u8BBF\u95EE\u51ED\u8BC1\uFF0C\u6D4B\u8BD5\u6570\u636E\u6E90\u8FDE\u63A5\u3002" })] }), _jsx("button", { className: "mc-close", type: "button", "aria-label": "\u6536\u8D77", title: "\u6536\u8D77", onClick: () => model.close(), children: _jsx(Icon, { name: "close", size: 20 }) })] }), pending.length > 0 && (_jsxs("div", { className: "mc-requests", children: [_jsx("span", { children: "\u672C\u4F1A\u8BDD\u5F85\u529E" }), pending.map((item) => (_jsxs("button", { type: "button", onClick: () => model.openRequest(item.id), children: [item.context.name, " \u00B7 ", statusLabels[item.status]] }, item.id))), request && (_jsx("button", { className: "mc-quiet", type: "button", onClick: () => model.show(workspaceId), children: "\u6570\u636E\u6E90\u7BA1\u7406" }))] })), _jsxs("div", { className: "mc-columns", ref: columns, children: [_jsxs("aside", { className: "mc-nav", "aria-label": "\u6570\u636E\u6E90\u5BFC\u822A", children: [!request && (_jsx("button", { type: "button", disabled: !workspaceId || state.loading, onClick: () => setCreating(true), children: "\u65B0\u589E\u6570\u636E\u6E90" })), _jsxs("div", { children: [_jsxs("div", { className: "mc-nav-heading", children: [_jsx("h3", { children: request ? '请求的数据源' : `数据源 · ${datasources.length}` }), _jsx("button", { className: "mc-quiet", type: "button", "aria-label": "\u5237\u65B0\u72B6\u6001", title: "\u5237\u65B0\u72B6\u6001", disabled: state.loading || !workspaceId, onClick: () => void model.selectWorkspace(workspaceId), children: _jsx(Icon, { name: "refresh", size: 16 }) })] }), _jsx("ul", { className: "mc-datasources", children: datasources.map((item) => {
130
- const count = item.refs.filter((ref) => item.credentials[ref]?.configured).length;
131
- const ready = count === item.refs.length;
132
- const running = state.operations.some((entry) => entry.handle.scope === item.token);
133
- return (_jsx("li", { children: _jsxs("button", { className: "mc-datasource", type: "button", "aria-label": `选择数据源 ${item.name}`, "aria-pressed": context?.token === item.token, onClick: () => {
134
- if (request)
135
- model.openRequest(request.id);
136
- else {
137
- setCreating(false);
138
- model.select(item.token);
139
- }
140
- }, children: [_jsx(Icon, { name: "database" }), _jsxs("span", { className: "mc-datasource-copy", children: [_jsx("span", { className: "mc-datasource-name", children: item.name }), _jsxs("span", { className: "mc-datasource-status", children: [_jsx("span", { className: "mc-dot", "data-ready": ready }), running
141
- ? '正在处理…'
142
- : item.refs.length === 0
143
- ? '无需凭证'
144
- : ready
145
- ? '凭证已配齐'
146
- : `${count} / ${item.refs.length} 项已配置`] })] })] }) }, item.token));
147
- }) })] })] }), _jsxs("main", { className: "mc-main", ref: main, children: [state.error && (_jsx("p", { role: "alert", className: "mc-alert", children: state.error })), state.loading && (_jsx("p", { className: "mc-loading", role: "status", children: "\u6B63\u5728\u8BFB\u53D6\u6570\u636E\u6E90\u4E0E\u51ED\u8BC1\u72B6\u6001\u2026" })), !creating && !state.loading && !context && !state.error && (_jsxs("div", { className: "mc-empty", children: [_jsx(Icon, { name: "database", size: 32 }), _jsx("h3", { children: !state.workspaceId
148
- ? '当前会话未绑定 Workspace'
194
+ return (_jsxs("section", { className: "mc-panel", "aria-label": t('marivo.credentials.datasources-and-credentials'), children: [_jsx("style", { children: credentialStyles }), _jsxs("div", { className: "rt-heading-row", children: [_jsx("h2", { className: "rt-heading", children: t('marivo.credentials.datasources-and-credentials') }), _jsxs("div", { className: "mc-heading-actions", children: [!request && (_jsx("button", { className: "mc-icon-button", type: "button", title: t('marivo.credentials.add-datasource'), "aria-label": t('marivo.credentials.add-datasource'), disabled: !workspaceId || state.loading, onClick: () => {
195
+ setEditingName('');
196
+ setCreating(true);
197
+ }, children: _jsx(CredentialIcon, { name: "add" }) })), _jsx("button", { className: "mc-icon-button", type: "button", title: t('marivo.credentials.refresh-datasources'), "aria-label": t('marivo.credentials.refresh-datasources'), disabled: state.loading, onClick: onRefresh ?? (() => void model.refreshDatasources()), children: _jsx(CredentialIcon, { name: "refresh" }) })] })] }), _jsx("p", { className: "rt-caption", children: workspaces.find((item) => item.workspaceId === workspaceId)?.title ?? workspaceId }), _jsxs("div", { className: "mc-shell", children: [(pending.length > 0 || request) && (_jsxs("div", { className: "mc-requests", children: [_jsx("span", { children: pending.length
198
+ ? t('marivo.credentials.requests-in-this-session')
199
+ : t('marivo.credentials.configuration-result') }), pending.map((item) => (_jsxs("button", { type: "button", onClick: () => model.openRequest(item.id), children: [item.context?.name ??
200
+ item.configuration?.name ??
201
+ t('marivo.credentials.add-datasource'), ' ', "\u00B7 ", t(statusLabels[item.status])] }, item.id))), request && (_jsx("button", { className: "mc-quiet", type: "button", onClick: () => model.show(workspaceId), children: t('marivo.credentials.datasource-management') }))] })), _jsxs("div", { className: "mc-columns", ref: columns, children: [!request && (_jsx("aside", { className: "mc-nav", "aria-label": t('marivo.credentials.datasource-navigation'), children: _jsxs("div", { children: [_jsx("div", { className: "mc-nav-heading", children: _jsx("h3", { children: request
202
+ ? t('marivo.credentials.requested-datasource')
203
+ : t('marivo.credentials.datasource-value', { p0: datasources.length }) }) }), _jsx("ul", { className: "mc-datasources", ref: navigation, children: datasources.map((item) => {
204
+ const count = item.refs.filter((ref) => item.credentials[ref]?.configured).length;
205
+ const ready = count === item.refs.length;
206
+ const running = state.operations.some((entry) => entry.handle.scope === item.token);
207
+ return (_jsx("li", { children: _jsxs("button", { className: "mc-datasource", type: "button", "aria-label": t('marivo.credentials.select-datasource-value', {
208
+ p0: item.name,
209
+ }), "aria-pressed": !creating && context?.token === item.token, onClick: () => {
210
+ if (request)
211
+ model.openRequest(request.id);
212
+ else {
213
+ setCreating(false);
214
+ model.select(item.token);
215
+ }
216
+ }, children: [_jsx(CredentialIcon, { name: "database" }), _jsxs("span", { className: "mc-datasource-copy", children: [_jsx("span", { className: "mc-datasource-name", children: item.name }), _jsxs("span", { className: "mc-datasource-status", children: [_jsx("span", { className: "mc-dot", "data-ready": ready }), running
217
+ ? t('marivo.credentials.processing')
218
+ : item.refs.length === 0
219
+ ? t('marivo.credentials.no-credentials-required')
220
+ : ready
221
+ ? t('marivo.credentials.all-credentials-configured')
222
+ : t('marivo.credentials.value-value-configured', {
223
+ p0: count,
224
+ p1: item.refs.length,
225
+ })] })] })] }) }, item.token));
226
+ }) })] }) })), _jsxs("main", { className: "mc-main", ref: main, children: [Object.values(state.outcomes)
227
+ .filter((entry) => entry.workspaceId === workspaceId &&
228
+ entry.operation?.action === 'delete-datasource')
229
+ .map((entry) => (_jsxs("div", { className: "mc-request-status", children: [_jsx(OperationOutcome, { entry: entry }), _jsx("button", { type: "button", onClick: () => model.dismissOutcome(entry.handle.scope), children: t('marivo.credentials.dismiss-deletion-result') })] }, entry.handle.id))), state.error && (_jsx("p", { role: "alert", className: "mc-alert", children: t(state.error) })), state.loading && (_jsx("p", { className: "mc-loading", role: "status", children: t('marivo.credentials.loading-datasources-and-credential-status') })), !request && !creating && !state.loading && !context && !state.error && (_jsxs("div", { className: "mc-empty", children: [_jsx(CredentialIcon, { name: "database", size: 32 }), _jsx("h3", { children: !state.workspaceId
230
+ ? t('marivo.credentials.this-session-is-not-bound-to-a-workspace')
149
231
  : state.datasources.length === 0
150
- ? '暂无数据源'
151
- : '选择一个数据源' }), _jsx("p", { children: !state.workspaceId
152
- ? '请返回会话后重试。'
232
+ ? t('marivo.credentials.no-datasources')
233
+ : t('marivo.credentials.select-a-datasource') }), _jsx("p", { children: !state.workspaceId
234
+ ? t('marivo.credentials.return-to-the-session-and-retry')
153
235
  : state.datasources.length === 0
154
- ? '该 Workspace 没有已定义的数据源。'
155
- : '查看凭证配置与最近一次连接测试。' })] })), creating && (_jsx(CreateDatasource, { model: model, workspaceId: workspaceId, close: () => setCreating(false) }, workspaceId)), !creating && context && (_jsx(CredentialForm, { context: context, request: request, state: state, model: model, workspaceId: workspaceId }, context.token)), operations.length > 0 && (_jsxs("section", { className: "mc-activity", "aria-label": "\u8FDB\u884C\u4E2D\u7684\u51ED\u8BC1\u64CD\u4F5C", children: [_jsxs("p", { className: "mc-activity-heading", children: ["\u8FDB\u884C\u4E2D \u00B7 ", operations.length] }), _jsx("div", { className: "mc-activity-list", children: operations.map((entry) => (_jsxs("button", { type: "button", "aria-pressed": state.handle?.id === entry.handle.id, onClick: () => model.selectOperation(entry.handle.id), children: [entry.name, " \u00B7 \u5904\u7406\u4E2D"] }, entry.handle.id))) }), activeOperation?.status === 'running' && (_jsxs("div", { className: "mc-progress", children: [_jsxs("p", { children: [state.operations.find((entry) => entry.handle.id === state.handle?.id)?.name, ' ', "\u00B7 ", activeOperation.phase === 'saving' ? '正在保存' : '正在验证连接'] }), _jsx("button", { type: "button", onClick: () => void model.cancelOperation(), children: "\u53D6\u6D88\u6B64\u64CD\u4F5C" }), activeOperation.saved.length > 0 && (_jsxs("p", { children: ["\u5DF2\u4FDD\u5B58\uFF1A", activeOperation.saved.join('、'), "\u3002"] }))] }))] }))] })] })] })] }));
236
+ ? t('marivo.credentials.this-workspace-has-no-defined-datasources')
237
+ : t('marivo.credentials.view-credential-configuration-and-the-latest-connection-test') })] })), request?.configuration && (_jsxs("section", { className: "mc-request-status", "aria-label": t('marivo.credentials.configuration-request'), children: [_jsxs("div", { className: "mc-request-heading", children: [_jsx("h3", { children: t('marivo.credentials.configure-a-datasource-to-continue') }), _jsx("span", { className: "mc-badge", role: "status", children: t(statusLabels[request.status]) }), request.endedAt === undefined && (_jsx("button", { className: "mc-quiet", type: "button", onClick: () => void model.cancelRequest(request.id), children: t('marivo.credentials.cancel-configuration-request') }))] }), _jsxs("details", { className: "mc-request-reason", children: [_jsx("summary", { children: t('marivo.credentials.show-assistant-request-details') }), _jsx("p", { children: t(request.configuration.reason) })] }), requestError && _jsx("p", { role: "alert", children: t(requestError) }), request.endedAt === undefined && request.status !== 'executing' && (_jsxs(_Fragment, { children: [request.configuration.mode === 'create' && !context && (_jsxs(_Fragment, { children: [_jsxs("fieldset", { className: "mc-request-choice", "aria-label": t('marivo.credentials.configuration-method'), children: [_jsx("button", { type: "button", "aria-pressed": requestChoice === 'create', onClick: () => {
238
+ setRequestChoice('create');
239
+ setCreating(true);
240
+ setEditingName('');
241
+ setRequestError('');
242
+ }, children: t('marivo.credentials.add-datasource') }), _jsx("button", { type: "button", "aria-pressed": requestChoice === 'existing', onClick: () => {
243
+ setRequestChoice('existing');
244
+ setCreating(false);
245
+ setEditingName('');
246
+ setRequestError('');
247
+ }, children: t('marivo.credentials.use-an-existing-datasource') })] }), requestChoice === 'existing' && (_jsxs("div", { className: "mc-existing-source", children: [_jsx("p", { children: t('marivo.credentials.if-an-existing-connection-can-access-the-target-table') }), _jsxs("label", { className: "mc-secret-input", children: [t('marivo.credentials.select-an-existing-datasource'), _jsxs("select", { "aria-label": t('marivo.credentials.select-an-existing-datasource'), value: "", onChange: async (event) => {
248
+ if (!event.target.value)
249
+ return;
250
+ try {
251
+ await model.selectConfiguration(workspaceId, request.id, event.target.value);
252
+ setCreating(false);
253
+ setEditingName('');
254
+ }
255
+ catch (error) {
256
+ setRequestError(error.message);
257
+ }
258
+ }, children: [_jsx("option", { value: "", children: t('marivo.credentials.please-select') }), state.datasources.map((item) => (_jsx("option", { value: item.name, children: item.name }, item.name)))] })] }), state.datasources.length === 0 && (_jsx("p", { children: t('marivo.credentials.no-reusable-datasource-is-available-switch-to-add-datasource') }))] }))] })), !creating &&
259
+ !context &&
260
+ (request.configuration.mode === 'edit' || requestChoice === 'create') && (_jsx("button", { type: "button", onClick: () => {
261
+ setCreating(true);
262
+ setEditingName(request.configuration.name ?? '');
263
+ }, children: t('marivo.credentials.open-configuration-form') }))] }))] })), creating && request?.endedAt === undefined && (_jsx(CreateDatasource, { name: editingName || undefined, requestId: request?.configuration ? request.id : undefined, model: model, workspaceId: workspaceId, close: () => setCreating(false) }, `${workspaceId}/${editingName}/${request?.id ?? ''}`)), !creating && context && (_jsx(CredentialForm, { context: context, request: request, state: state, model: model, workspaceId: workspaceId, onEdit: () => {
264
+ setEditingName(context.name);
265
+ setCreating(true);
266
+ } }, context.token)), operations.length > 0 && (_jsxs("section", { className: "mc-activity", "aria-label": t('marivo.credentials.credential-operations-in-progress'), children: [_jsxs("p", { className: "mc-activity-heading", children: [t('marivo.credentials.in-progress'), operations.length] }), _jsx("div", { className: "mc-activity-list", children: operations.map((entry) => (_jsxs("button", { type: "button", "aria-pressed": state.handle?.id === entry.handle.id, onClick: () => model.selectOperation(entry.handle.id), children: [entry.name, " ", t('marivo.credentials.processing-177')] }, entry.handle.id))) }), activeOperation?.status === 'running' && (_jsxs("div", { className: "mc-progress", children: [_jsxs("p", { children: [state.operations.find((entry) => entry.handle.id === state.handle?.id)?.name, ' ', "\u00B7", ' ', activeOperation.phase === 'removing'
267
+ ? t('marivo.credentials.deleting')
268
+ : activeOperation.phase === 'saving'
269
+ ? t('marivo.credentials.saving')
270
+ : t('marivo.credentials.validating-connection')] }), _jsx("button", { type: "button", onClick: () => void model.cancelOperation(), children: t('marivo.credentials.cancel-this-operation') }), activeOperation.saved.length > 0 && (_jsxs("p", { children: [t('marivo.credentials.saved'), activeOperation.saved.join('、'), "\u3002"] }))] }))] }))] })] })] }), !request && workspaceId && (_jsx(ReportPublishingCredentials, { model: model, workspaceId: workspaceId }, workspaceId))] }));
156
271
  }
157
- export function installCredentials(ctx, rpc) {
272
+ export function installCredentials(ctx, rpc, changes) {
158
273
  let storage;
159
274
  try {
160
275
  storage = window.sessionStorage;
@@ -162,30 +277,43 @@ export function installCredentials(ctx, rpc) {
162
277
  catch {
163
278
  /* optional query-handle persistence */
164
279
  }
165
- const model = new CredentialClientModel(rpc, storage);
280
+ const model = new CredentialClientModel(rpc, storage, changes);
166
281
  model.recover();
167
282
  ctx.effect(() => () => model.dispose(), 'dsh-data-analysis: credential client lifecycle');
168
283
  ctx.on('connection/reset', () => model.reset());
169
- ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register({ name: 'conversation.session.header.actions', id: 'marivo-credentials', order: 100 }, function Entry({ sessionId, useWorkspaces }) {
170
- const workspaces = useWorkspaces((state) => state.items);
171
- const selected = workspaces.find((item) => item.sessionIds.includes(sessionId))?.workspaceId ?? '';
172
- return (_jsx(WorkspaceHeaderAction, { label: "\u6570\u636E\u6E90\u4E0E\u51ED\u8BC1", icon: "credentials", disabled: !selected, title: selected ? '数据源与凭证' : '当前会话未绑定工作区,无法打开数据源与凭证', onClick: () => {
173
- if (selected)
174
- model.show(selected);
175
- } }));
176
- }));
177
- ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register({ name: 'conversation.session.header.actions', id: 'marivo-credential-requests', order: 120 }, function Pending({ sessionId }) {
284
+ ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register({
285
+ locale: 'marivo.navigation',
286
+ name: 'conversation.session.header.actions',
287
+ id: 'marivo-credential-requests',
288
+ order: 120,
289
+ }, localized(ctx, function Pending({ sessionId }) {
290
+ const t = useCopy();
178
291
  const state = useSyncExternalStore(model.subscribe, model.getSnapshot);
179
292
  const request = state.requests.find((item) => item.sessionId === sessionId && item.endedAt === undefined);
180
- return request ? (_jsx("button", { className: "mc-pending-entry", type: "button", onClick: () => model.openRequest(request.id), children: "\u7B49\u5F85\u914D\u7F6E\u51ED\u8BC1" })) : null;
181
- }));
182
- ctx.slots.inject('shell.overlay', () => ctx.slots.register({ name: 'shell.overlay', id: 'marivo-credentials' }, function Overlay({ useSessions, useWorkspaces }) {
293
+ return request ? (_jsx("button", { className: "mc-pending-entry", style: {
294
+ flex: 'none',
295
+ whiteSpace: 'nowrap',
296
+ fontSize: 12,
297
+ padding: '4px 6px',
298
+ border: '1px solid currentColor',
299
+ borderRadius: 7,
300
+ background: 'transparent',
301
+ color: 'inherit',
302
+ cursor: 'pointer',
303
+ }, "aria-label": request.configuration
304
+ ? t('marivo.credentials.awaiting-datasource-configuration')
305
+ : t('marivo.credentials.awaiting-credentials'), title: request.configuration
306
+ ? t('marivo.credentials.awaiting-datasource-configuration')
307
+ : t('marivo.credentials.awaiting-credentials'), type: "button", onClick: () => model.openRequest(request.id), children: t('marivo.credentials.configuration-needed') })) : null;
308
+ })));
309
+ ctx.slots.inject('shell.overlay', () => ctx.slots.register({ locale: 'marivo.navigation', name: 'shell.overlay', id: 'marivo-credential-observer' }, localized(ctx, function Observer({ useSessions, useWorkspaces }) {
183
310
  const sessionId = useSessions((state) => state.current) ?? '';
184
311
  const workspaces = useWorkspaces((state) => state.items);
185
312
  const currentWorkspace = workspaces.find((item) => item.sessionIds.includes(sessionId))?.workspaceId ?? '';
186
313
  useEffect(() => model.session(sessionId), [sessionId]);
187
314
  // biome-ignore lint/correctness/useExhaustiveDependencies: Workspace reassignment must dismiss old content.
188
315
  useEffect(() => model.close(), [currentWorkspace]);
189
- return _jsx(CredentialPanel, { model: model, workspaces: workspaces });
190
- }));
316
+ return null;
317
+ })));
318
+ return model;
191
319
  }