@chengxianglibra/dsh-data-analysis 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. package/README.md +139 -53
  2. package/cordis.patch.yml +1 -1
  3. package/lib/bin/environment.js +9 -7
  4. package/lib/bin/presentation-lint.js +21 -0
  5. package/lib/bridges.js +2 -2
  6. package/lib/client/credentials/changes.js +74 -0
  7. package/lib/client/credentials/create-datasource.js +171 -0
  8. package/lib/client/credentials/credential-draft.js +42 -0
  9. package/lib/client/credentials/defaults.js +11 -0
  10. package/lib/client/credentials/descriptions.js +46 -0
  11. package/lib/client/credentials/install.js +319 -0
  12. package/lib/client/credentials/model.js +766 -0
  13. package/lib/client/credentials/report-publishing.js +96 -0
  14. package/lib/client/credentials/styles.js +21 -0
  15. package/lib/client/i18n/context.js +22 -0
  16. package/lib/client/i18n/copy.js +57 -0
  17. package/lib/client/i18n/credentials.js +475 -0
  18. package/lib/client/i18n/host.js +27 -0
  19. package/lib/client/i18n/navigation.js +41 -0
  20. package/lib/client/i18n/presentation.js +577 -0
  21. package/lib/client/i18n/python.js +36 -0
  22. package/lib/client/i18n/semantic.js +441 -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/workspace-header-action.js +24 -0
  36. package/lib/client/workspace-shortcuts.js +26 -0
  37. package/lib/client.js +1250 -730
  38. package/lib/compatibility.js +2 -2
  39. package/lib/datasource/authoring.js +109 -0
  40. package/lib/datasource/bridge-programs.js +42 -27
  41. package/lib/datasource/bridge.js +144 -9
  42. package/lib/datasource/changes-contract.js +41 -0
  43. package/lib/datasource/changes.js +49 -0
  44. package/lib/datasource/configure.js +39 -0
  45. package/lib/datasource/defaults.js +25 -0
  46. package/lib/datasource/index.js +4 -2
  47. package/lib/datasource/python-options.js +21 -0
  48. package/lib/datasource/python.js +206 -0
  49. package/lib/datasource/resolver-program.js +112 -0
  50. package/lib/datasource/rpc.js +150 -0
  51. package/lib/datasource/service.js +962 -0
  52. package/lib/datasource/shell-env.js +2 -333
  53. package/lib/datasource/test.js +25 -51
  54. package/lib/disclosure/activation.js +19 -7
  55. package/lib/disclosure/execution-guidance.js +52 -0
  56. package/lib/disclosure/help.js +4 -1
  57. package/lib/environment/binding.js +54 -9
  58. package/lib/environment/runtime.js +120 -108
  59. package/lib/environment/subprocess.js +6 -1
  60. package/lib/environment/summary.js +3 -3
  61. package/lib/environment/workspace.js +23 -1
  62. package/lib/index.js +1 -1
  63. package/lib/lifecycle.js +33 -0
  64. package/lib/plugin-agents.js +154 -0
  65. package/lib/plugin.js +172 -133
  66. package/lib/presentation/asset.js +34 -0
  67. package/lib/presentation/assets/portable.js +606 -0
  68. package/lib/presentation/assets/static.js +1216 -0
  69. package/lib/presentation/build/index.js +72 -0
  70. package/lib/presentation/commit.js +163 -0
  71. package/lib/presentation/contracts/asset-path.js +9 -0
  72. package/lib/presentation/contracts/catalog.js +62 -0
  73. package/lib/presentation/contracts/charts.js +453 -0
  74. package/lib/presentation/contracts/editing.js +58 -0
  75. package/lib/presentation/contracts/index.js +663 -0
  76. package/lib/presentation/contracts/interaction.js +62 -0
  77. package/lib/presentation/contracts/types.js +15 -0
  78. package/lib/presentation/contracts/values.js +28 -0
  79. package/lib/presentation/delivery.js +71 -0
  80. package/lib/presentation/export-html.js +214 -0
  81. package/lib/presentation/files.js +82 -0
  82. package/lib/presentation/index.js +6 -0
  83. package/lib/presentation/lint.js +46 -0
  84. package/lib/presentation/projection/files.js +85 -0
  85. package/lib/presentation/projection/index.js +196 -0
  86. package/lib/presentation/projection/program.js +137 -0
  87. package/lib/presentation/projection/sql-code.js +79 -0
  88. package/lib/presentation/receipt.js +34 -0
  89. package/lib/presentation/reports.js +219 -0
  90. package/lib/presentation/rpc.js +186 -0
  91. package/lib/presentation/tool.js +118 -0
  92. package/lib/python-execution-contracts.js +1 -0
  93. package/lib/python-execution.js +232 -0
  94. package/lib/report-publishing/adapters.js +111 -0
  95. package/lib/report-publishing/config.js +69 -0
  96. package/lib/report-publishing/service.js +180 -0
  97. package/lib/rpc.js +49 -0
  98. package/lib/semantic-browser/contracts.js +97 -0
  99. package/lib/semantic-browser/definition.js +64 -0
  100. package/lib/semantic-browser/program.js +129 -0
  101. package/lib/semantic-browser/service.js +106 -0
  102. package/lib/semantic-reference/bridge.js +127 -0
  103. package/lib/semantic-reference/contracts.js +127 -0
  104. package/lib/semantic-reference/environment.js +56 -0
  105. package/lib/semantic-reference/index.js +3 -0
  106. package/lib/semantic-reference/labels.js +16 -0
  107. package/lib/semantic-reference/rpc.js +143 -0
  108. package/lib/semantic-reference/search.js +95 -0
  109. package/lib/semantic-reference/usage.js +152 -0
  110. package/lib/tool-lifecycle.js +22 -0
  111. package/lib/types/bridges.d.ts +2 -2
  112. package/lib/types/client/credentials/changes.d.ts +9 -0
  113. package/lib/types/client/credentials/create-datasource.d.ts +7 -0
  114. package/lib/types/client/credentials/credential-draft.d.ts +14 -0
  115. package/lib/types/client/credentials/defaults.d.ts +2 -0
  116. package/lib/types/client/credentials/descriptions.d.ts +1 -0
  117. package/lib/types/client/credentials/install.d.ts +19 -0
  118. package/lib/types/client/credentials/model.d.ts +79 -0
  119. package/lib/types/client/credentials/report-publishing.d.ts +5 -0
  120. package/lib/types/client/credentials/styles.d.ts +1 -0
  121. package/lib/types/client/i18n/context.d.ts +17 -0
  122. package/lib/types/client/i18n/copy.d.ts +806 -0
  123. package/lib/types/client/i18n/credentials.d.ts +475 -0
  124. package/lib/types/client/i18n/host.d.ts +16 -0
  125. package/lib/types/client/i18n/navigation.d.ts +41 -0
  126. package/lib/types/client/i18n/presentation.d.ts +577 -0
  127. package/lib/types/client/i18n/python.d.ts +19 -0
  128. package/lib/types/client/i18n/semantic.d.ts +441 -0
  129. package/lib/types/client/input-context.d.ts +19 -0
  130. package/lib/types/client/presentation/ask-dsh.d.ts +5 -0
  131. package/lib/types/client/presentation/catalog-model.d.ts +24 -0
  132. package/lib/types/client/presentation/catalog.d.ts +20 -0
  133. package/lib/types/client/presentation/chart-explorer.d.ts +12 -0
  134. package/lib/types/client/presentation/chart-geometry.d.ts +30 -0
  135. package/lib/types/client/presentation/chart-renderer.d.ts +10 -0
  136. package/lib/types/client/presentation/chart-specials.d.ts +10 -0
  137. package/lib/types/client/presentation/chart-styles.d.ts +1 -0
  138. package/lib/types/client/presentation/chart-tooltip.d.ts +13 -0
  139. package/lib/types/client/presentation/chart-view.d.ts +23 -0
  140. package/lib/types/client/presentation/context-reference.d.ts +12 -0
  141. package/lib/types/client/presentation/copy-context.d.ts +5 -0
  142. package/lib/types/client/presentation/delivery-model.d.ts +75 -0
  143. package/lib/types/client/presentation/delivery.d.ts +78 -0
  144. package/lib/types/client/presentation/download.d.ts +2 -0
  145. package/lib/types/client/presentation/editor-controls.d.ts +12 -0
  146. package/lib/types/client/presentation/export-menu.d.ts +26 -0
  147. package/lib/types/client/presentation/export-view.d.ts +63 -0
  148. package/lib/types/client/presentation/global-filters.d.ts +6 -0
  149. package/lib/types/client/presentation/host-entry.d.ts +18 -0
  150. package/lib/types/client/presentation/icons.d.ts +4 -0
  151. package/lib/types/client/presentation/markdown.d.ts +5 -0
  152. package/lib/types/client/presentation/model.d.ts +61 -0
  153. package/lib/types/client/presentation/reader.d.ts +24 -0
  154. package/lib/types/client/presentation/reference-source.d.ts +9 -0
  155. package/lib/types/client/presentation/source-code-model.d.ts +17 -0
  156. package/lib/types/client/presentation/source-code.d.ts +6 -0
  157. package/lib/types/client/presentation/source-dialog.d.ts +12 -0
  158. package/lib/types/client/presentation/source-facts.d.ts +20 -0
  159. package/lib/types/client/presentation/source-format.d.ts +5 -0
  160. package/lib/types/client/presentation/source-highlight.d.ts +7 -0
  161. package/lib/types/client/presentation/sources.d.ts +13 -0
  162. package/lib/types/client/presentation/styles.d.ts +1 -0
  163. package/lib/types/client/presentation/table.d.ts +16 -0
  164. package/lib/types/client/presentation/use-element-width.d.ts +5 -0
  165. package/lib/types/client/python-tool/card.d.ts +2 -0
  166. package/lib/types/client/python-tool/execution-error.d.ts +3 -0
  167. package/lib/types/client/python-tool/install.d.ts +2 -0
  168. package/lib/types/client/python-tool/model.d.ts +20 -0
  169. package/lib/types/client/right-tabs/install.d.ts +18 -0
  170. package/lib/types/client/right-tabs/live-delivery.d.ts +8 -0
  171. package/lib/types/client/right-tabs/navigation.d.ts +17 -0
  172. package/lib/types/client/right-tabs/page.d.ts +36 -0
  173. package/lib/types/client/right-tabs/styles.d.ts +2 -0
  174. package/lib/types/client/rpc.d.ts +3 -0
  175. package/lib/types/client/semantic-reference.d.ts +4 -0
  176. package/lib/types/client/workspace-header-action.d.ts +7 -0
  177. package/lib/types/client/workspace-shortcuts.d.ts +15 -0
  178. package/lib/types/client.d.ts +9 -124
  179. package/lib/types/compatibility.d.ts +3 -3
  180. package/lib/types/datasource/authoring.d.ts +35 -0
  181. package/lib/types/datasource/bridge.d.ts +43 -4
  182. package/lib/types/datasource/changes-contract.d.ts +18 -0
  183. package/lib/types/datasource/changes.d.ts +15 -0
  184. package/lib/types/datasource/configure.d.ts +7 -0
  185. package/lib/types/datasource/defaults.d.ts +7 -0
  186. package/lib/types/datasource/index.d.ts +8 -5
  187. package/lib/types/datasource/python-options.d.ts +9 -0
  188. package/lib/types/datasource/python.d.ts +19 -0
  189. package/lib/types/datasource/resolver-program.d.ts +6 -0
  190. package/lib/types/datasource/rpc.d.ts +5 -0
  191. package/lib/types/datasource/service.d.ts +155 -0
  192. package/lib/types/datasource/shell-env.d.ts +0 -29
  193. package/lib/types/datasource/test.d.ts +6 -29
  194. package/lib/types/disclosure/activation.d.ts +2 -1
  195. package/lib/types/disclosure/execution-guidance.d.ts +6 -0
  196. package/lib/types/disclosure/help.d.ts +1 -1
  197. package/lib/types/environment/binding.d.ts +5 -1
  198. package/lib/types/environment/errors.d.ts +1 -1
  199. package/lib/types/environment/runtime.d.ts +5 -5
  200. package/lib/types/environment/types.d.ts +15 -3
  201. package/lib/types/environment/workspace.d.ts +1 -0
  202. package/lib/types/index.d.ts +1 -1
  203. package/lib/types/lifecycle.d.ts +8 -0
  204. package/lib/types/plugin-agents.d.ts +27 -0
  205. package/lib/types/plugin.d.ts +14 -24
  206. package/lib/types/presentation/asset.d.ts +6 -0
  207. package/lib/types/presentation/build/index.d.ts +16 -0
  208. package/lib/types/presentation/commit.d.ts +4 -0
  209. package/lib/types/presentation/contracts/asset-path.d.ts +2 -0
  210. package/lib/types/presentation/contracts/catalog.d.ts +27 -0
  211. package/lib/types/presentation/contracts/charts.d.ts +11 -0
  212. package/lib/types/presentation/contracts/editing.d.ts +8 -0
  213. package/lib/types/presentation/contracts/index.d.ts +11 -0
  214. package/lib/types/presentation/contracts/interaction.d.ts +8 -0
  215. package/lib/types/presentation/contracts/types.d.ts +255 -0
  216. package/lib/types/presentation/contracts/values.d.ts +9 -0
  217. package/lib/types/presentation/delivery.d.ts +3 -0
  218. package/lib/types/presentation/export-html.d.ts +13 -0
  219. package/lib/types/presentation/files.d.ts +7 -0
  220. package/lib/types/presentation/index.d.ts +6 -0
  221. package/lib/types/presentation/lint.d.ts +13 -0
  222. package/lib/types/presentation/projection/files.d.ts +2 -0
  223. package/lib/types/presentation/projection/index.d.ts +20 -0
  224. package/lib/types/presentation/projection/program.d.ts +2 -0
  225. package/lib/types/presentation/projection/sql-code.d.ts +2 -0
  226. package/lib/types/presentation/receipt.d.ts +14 -0
  227. package/lib/types/presentation/reports.d.ts +10 -0
  228. package/lib/types/presentation/rpc.d.ts +25 -0
  229. package/lib/types/presentation/tool.d.ts +12 -0
  230. package/lib/types/python-execution-contracts.d.ts +10 -0
  231. package/lib/types/python-execution.d.ts +10 -0
  232. package/lib/types/report-publishing/adapters.d.ts +6 -0
  233. package/lib/types/report-publishing/config.d.ts +22 -0
  234. package/lib/types/report-publishing/service.d.ts +68 -0
  235. package/lib/types/rpc.d.ts +3 -0
  236. package/lib/types/semantic-browser/contracts.d.ts +47 -0
  237. package/lib/types/semantic-browser/definition.d.ts +20 -0
  238. package/lib/types/semantic-browser/program.d.ts +2 -0
  239. package/lib/types/semantic-browser/service.d.ts +26 -0
  240. package/lib/types/semantic-reference/bridge.d.ts +12 -0
  241. package/lib/types/semantic-reference/contracts.d.ts +54 -0
  242. package/lib/types/semantic-reference/environment.d.ts +22 -0
  243. package/lib/types/semantic-reference/index.d.ts +3 -0
  244. package/lib/types/semantic-reference/labels.d.ts +16 -0
  245. package/lib/types/semantic-reference/rpc.d.ts +15 -0
  246. package/lib/types/semantic-reference/search.d.ts +10 -0
  247. package/lib/types/semantic-reference/usage.d.ts +43 -0
  248. package/lib/types/tool-lifecycle.d.ts +4 -0
  249. package/lib/types/workspace-identity.d.ts +6 -0
  250. package/lib/workspace-identity.js +9 -0
  251. package/package.json +99 -53
  252. package/python/presentation-kit/dist/dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl +0 -0
  253. package/skills/dsh-data-analysis-files/SKILL.md +32 -0
  254. package/skills/dsh-data-analysis-files/references/examples.md +93 -0
  255. package/skills/dsh-data-analysis-presentation/SKILL.md +28 -0
  256. package/skills/dsh-data-analysis-presentation/references/chart-examples.md +18 -0
  257. package/skills/dsh-data-analysis-presentation/references/charts.md +55 -0
  258. package/skills/dsh-data-analysis-presentation/references/examples/artifact.draft.json +36 -0
  259. package/skills/dsh-data-analysis-presentation/references/examples/charts-bins.dataset.json +33 -0
  260. package/skills/dsh-data-analysis-presentation/references/examples/charts-boxes.dataset.json +45 -0
  261. package/skills/dsh-data-analysis-presentation/references/examples/charts-composition.dataset.json +33 -0
  262. package/skills/dsh-data-analysis-presentation/references/examples/charts-funnel.dataset.json +27 -0
  263. package/skills/dsh-data-analysis-presentation/references/examples/charts-precision.dataset.json +21 -0
  264. package/skills/dsh-data-analysis-presentation/references/examples/charts-series.dataset.json +58 -0
  265. package/skills/dsh-data-analysis-presentation/references/examples/charts-shares.dataset.json +33 -0
  266. package/skills/dsh-data-analysis-presentation/references/examples/charts-waterfall.dataset.json +44 -0
  267. package/skills/dsh-data-analysis-presentation/references/examples/charts.draft.json +393 -0
  268. package/skills/dsh-data-analysis-presentation/references/examples/comparison-selected.dataset.json +24 -0
  269. package/skills/dsh-data-analysis-presentation/references/examples/comparison-summary.dataset.json +22 -0
  270. package/skills/dsh-data-analysis-presentation/references/examples/comparison.dataset.json +18 -0
  271. package/skills/dsh-data-analysis-presentation/references/examples/comparison.draft.json +80 -0
  272. package/skills/dsh-data-analysis-presentation/references/examples/computed-sources.draft.json +42 -0
  273. package/skills/dsh-data-analysis-presentation/references/examples/computed.dataset.json +12 -0
  274. package/skills/dsh-data-analysis-presentation/references/examples/computed.draft.json +58 -0
  275. package/skills/dsh-data-analysis-presentation/references/examples/interaction-detail.dataset.json +30 -0
  276. package/skills/dsh-data-analysis-presentation/references/examples/interaction-summary.dataset.json +22 -0
  277. package/skills/dsh-data-analysis-presentation/references/examples/interaction.draft.json +279 -0
  278. package/skills/dsh-data-analysis-presentation/references/examples/source-only.draft.json +27 -0
  279. package/skills/dsh-data-analysis-presentation/references/examples/write-charts.py +73 -0
  280. package/skills/dsh-data-analysis-presentation/references/examples/write-comparison.py +42 -0
  281. package/skills/dsh-data-analysis-presentation/references/examples/write-computed.py +21 -0
  282. package/skills/dsh-data-analysis-presentation/references/examples/write-interaction.py +33 -0
  283. package/skills/dsh-data-analysis-presentation/references/examples.md +44 -0
  284. package/skills/dsh-data-analysis-presentation/references/export-html.md +7 -0
  285. package/skills/dsh-data-analysis-presentation/references/interaction.md +56 -0
  286. package/skills/dsh-data-analysis-presentation/references/narrative.md +37 -0
  287. package/skills/dsh-data-analysis-presentation/references/publishing.md +3 -0
  288. package/skills/dsh-data-analysis-presentation/references/schema.md +162 -0
  289. package/lib/datasource/access.js +0 -60
  290. package/lib/datasource/credentials.js +0 -24
  291. package/lib/evidence/bridge-program.js +0 -153
  292. package/lib/evidence/bridge.js +0 -166
  293. package/lib/evidence/index.js +0 -2
  294. package/lib/evidence/sources.js +0 -263
  295. package/lib/types/datasource/access.d.ts +0 -27
  296. package/lib/types/evidence/bridge.d.ts +0 -40
  297. package/lib/types/evidence/index.d.ts +0 -4
  298. package/lib/types/evidence/sources.d.ts +0 -57
  299. package/python/report-kit/dist/dsh_data_analysis_report_kit-3.0.0-py3-none-any.whl +0 -0
  300. package/skills/dsh-data-analysis-report/SKILL.md +0 -57
  301. package/skills/dsh-data-analysis-report/assets/marivo-artifact.js +0 -113
  302. package/skills/dsh-data-analysis-report/assets/marivo-session-dag.js +0 -1201
  303. package/skills/dsh-data-analysis-report/assets/report-data.js +0 -449
@@ -1,13 +1,6 @@
1
- import { randomBytes } from 'node:crypto';
2
- import { credentialRef, isCredentialRefName, } from '@deepseek-ai/dsh-credentials';
1
+ import { isCredentialRefName } from '@deepseek-ai/dsh-credentials';
3
2
  import { MarivoEnvironmentError } from "../environment/index.js";
4
- import { resolveMarivoDatasourceBridge, } from "./bridge.js";
5
3
  export const MARIVO_CREDENTIAL_STORAGE_PREFIX = 'DSH_DATA_ANALYSIS_CREDENTIAL_';
6
- export const MARIVO_CREDENTIAL_LEASE_PREFIX = '# dsh-marivo-credential-lease:';
7
- export const DEFAULT_MARIVO_CREDENTIAL_LEASE_TTL_MS = 30 * 60_000;
8
- export const DEFAULT_MARIVO_CREDENTIAL_LEASE_MAX_USES = 64;
9
- const TOKEN_PATTERN = /^[A-Za-z0-9_-]{43}$/;
10
- const SHELL_TOOL_NAMES = new Set(['bash', 'pwsh']);
11
4
  const HOST_SHELL_ENVIRONMENT_NAMES = new Set([
12
5
  'DSH_HOME',
13
6
  'DSH_SESSION_ID',
@@ -56,331 +49,7 @@ export function marivoCredentialStorageRef(ref) {
56
49
  .join('');
57
50
  return `${MARIVO_CREDENTIAL_STORAGE_PREFIX}${encoded}`;
58
51
  }
59
- function credentialBindings(refs) {
60
- return Object.freeze([...new Set(refs)].map((environmentRef) => ({
61
- environmentRef,
62
- storageRef: marivoCredentialStorageRef(environmentRef),
63
- })));
64
- }
65
- function bashPrelude(token, bindings) {
66
- return [
67
- `${MARIVO_CREDENTIAL_LEASE_PREFIX}${token}`,
68
- ...bindings.flatMap(({ environmentRef, storageRef }) => [
69
- `export ${environmentRef}="\${${storageRef}}"`,
70
- `unset ${storageRef}`,
71
- ]),
72
- 'export MARIVO_PERSIST_CREDENTIALS=0',
73
- ].join('\n');
74
- }
75
- function pwshPrelude(token, bindings) {
76
- return [
77
- `${MARIVO_CREDENTIAL_LEASE_PREFIX}${token}`,
78
- ...bindings.flatMap(({ environmentRef, storageRef }) => [
79
- `$env:${environmentRef} = $env:${storageRef}`,
80
- `Remove-Item Env:${storageRef}`,
81
- ]),
82
- "$env:MARIVO_PERSIST_CREDENTIALS = '0'",
83
- ].join('\n');
84
- }
85
- function leaseFailure(code, message, details = {}) {
86
- return new MarivoEnvironmentError(code, message, details);
87
- }
88
- function commandArguments(execution) {
89
- return typeof execution.arguments === 'object' &&
90
- execution.arguments !== null &&
91
- !Array.isArray(execution.arguments)
92
- ? execution.arguments
93
- : undefined;
94
- }
95
- function hasCredentialStorageRefAt(command, offset, caseInsensitive) {
96
- const candidate = caseInsensitive ? command.slice(offset).toUpperCase() : command.slice(offset);
97
- if (!candidate.startsWith(MARIVO_CREDENTIAL_STORAGE_PREFIX))
98
- return false;
99
- let cursor = MARIVO_CREDENTIAL_STORAGE_PREFIX.length;
100
- const firstHex = cursor;
101
- while (cursor < candidate.length && /[A-F0-9]/.test(candidate[cursor] ?? ''))
102
- cursor++;
103
- return (cursor > firstHex &&
104
- (cursor === candidate.length || !/[A-Z0-9_]/i.test(candidate[cursor] ?? '')));
105
- }
106
- function isBashCommentStart(command, offset) {
107
- if (offset === 0)
108
- return true;
109
- return /[\s;&|()]/.test(command[offset - 1] ?? '');
110
- }
111
- function containsCredentialDereference(execution) {
112
- const command = commandArguments(execution)?.command;
113
- if (typeof command !== 'string')
114
- return false;
115
- const pwsh = execution.name === 'pwsh';
116
- let quote;
117
- let comment = false;
118
- for (let index = 0; index < command.length; index++) {
119
- const character = command[index];
120
- if (comment) {
121
- if (character === '\n' || character === '\r')
122
- comment = false;
123
- continue;
124
- }
125
- if (quote === "'") {
126
- if (character === "'") {
127
- if (pwsh && command[index + 1] === "'")
128
- index++;
129
- else
130
- quote = undefined;
131
- }
132
- continue;
133
- }
134
- if (character === (pwsh ? '`' : '\\')) {
135
- index++;
136
- continue;
137
- }
138
- if (character === '#' && quote === undefined && (pwsh || isBashCommentStart(command, index))) {
139
- comment = true;
140
- continue;
141
- }
142
- if (character === "'" && quote === undefined) {
143
- quote = "'";
144
- continue;
145
- }
146
- if (character === '"') {
147
- quote = quote === '"' ? undefined : '"';
148
- continue;
149
- }
150
- if (character !== '$')
151
- continue;
152
- if (pwsh) {
153
- if (command.slice(index + 1, index + 5).toLowerCase() === 'env:' &&
154
- hasCredentialStorageRefAt(command, index + 5, true)) {
155
- return true;
156
- }
157
- if (command.slice(index + 1, index + 6).toLowerCase() === '{env:' &&
158
- hasCredentialStorageRefAt(command, index + 6, true)) {
159
- return true;
160
- }
161
- continue;
162
- }
163
- const refOffset = command[index + 1] === '{' ? index + 2 : index + 1;
164
- if (hasCredentialStorageRefAt(command, refOffset, false))
165
- return true;
166
- }
167
- return false;
168
- }
169
- function leaseToken(execution) {
170
- const command = commandArguments(execution)?.command;
171
- if (typeof command !== 'string')
172
- return undefined;
173
- const firstLine = command.split(/\r?\n/, 1)[0] ?? '';
174
- const candidate = firstLine.startsWith(MARIVO_CREDENTIAL_LEASE_PREFIX)
175
- ? firstLine.slice(MARIVO_CREDENTIAL_LEASE_PREFIX.length)
176
- : undefined;
177
- if (candidate !== undefined && TOKEN_PATTERN.test(candidate))
178
- return candidate;
179
- if (firstLine.includes('dsh-marivo-credential-')) {
180
- throw leaseFailure('shell-credential-lease-invalid', 'Marivo shell credential lease marker is malformed or unsupported');
181
- }
182
- return undefined;
183
- }
184
- function isHarnessPersistentShell(agent, name) {
185
- const definition = agent.ctx.tools.get(name, agent);
186
- return definition?.output.schema.type === 'string';
187
- }
188
52
  export function assertMarivoCredentialReferences(refs) {
189
- for (const ref of refs) {
53
+ for (const ref of refs)
190
54
  marivoCredentialStorageRef(ref);
191
- }
192
- }
193
- /** Own bounded leases and expose credential values only to each admitted Shell execution. */
194
- export class MarivoShellCredentialLeases {
195
- #ctx;
196
- #credentials;
197
- #ttlMs;
198
- #maxUses;
199
- #leases = new Map();
200
- #executionValues = new Map();
201
- #contributors = new Map();
202
- #disposed = false;
203
- constructor(ctx, credentials, options = {}) {
204
- const ttlMs = options.ttlMs ?? DEFAULT_MARIVO_CREDENTIAL_LEASE_TTL_MS;
205
- const maxUses = options.maxUses ?? DEFAULT_MARIVO_CREDENTIAL_LEASE_MAX_USES;
206
- if (!Number.isSafeInteger(ttlMs) ||
207
- ttlMs < 1 ||
208
- ttlMs > DEFAULT_MARIVO_CREDENTIAL_LEASE_TTL_MS) {
209
- throw new TypeError(`Marivo shell credential lease ttlMs must be an integer from 1 to ${DEFAULT_MARIVO_CREDENTIAL_LEASE_TTL_MS}`);
210
- }
211
- if (!Number.isSafeInteger(maxUses) ||
212
- maxUses < 1 ||
213
- maxUses > DEFAULT_MARIVO_CREDENTIAL_LEASE_MAX_USES) {
214
- throw new TypeError(`Marivo shell credential lease maxUses must be an integer from 1 to ${DEFAULT_MARIVO_CREDENTIAL_LEASE_MAX_USES}`);
215
- }
216
- this.#ctx = ctx;
217
- this.#credentials = credentials;
218
- this.#ttlMs = ttlMs;
219
- this.#maxUses = maxUses;
220
- }
221
- #ensureContributor(ref) {
222
- if (this.#disposed)
223
- throw new Error('Marivo shell credential leases are disposed');
224
- if (this.#contributors.has(ref))
225
- return;
226
- const dispose = shellEnvironmentRegistry(this.#ctx).register({
227
- name: `dsh-data-analysis:credential:${ref}`,
228
- variables: {
229
- [ref]: {
230
- description: 'Marivo datasource credential authorized for this Shell execution.',
231
- },
232
- },
233
- resolve: (execution) => {
234
- const value = this.#executionValues.get(execution)?.values.get(ref);
235
- return value === undefined ? {} : { [ref]: value };
236
- },
237
- });
238
- this.#contributors.set(ref, dispose);
239
- }
240
- #purgeExpired(now) {
241
- for (const [token, lease] of this.#leases) {
242
- if (lease.expiresAt <= now)
243
- this.#leases.delete(token);
244
- }
245
- }
246
- revokeLease(agent, bridge, datasourceName) {
247
- for (const [token, lease] of this.#leases) {
248
- if (lease.agent === agent &&
249
- lease.workspaceFingerprint === bridge.binding.fingerprint &&
250
- lease.datasourceName === datasourceName) {
251
- this.#leases.delete(token);
252
- }
253
- }
254
- }
255
- issueLease(agent, bridge, datasourceName, refs) {
256
- if (this.#disposed)
257
- throw new Error('Marivo shell credential leases are disposed');
258
- const now = Date.now();
259
- this.#purgeExpired(now);
260
- this.revokeLease(agent, bridge, datasourceName);
261
- assertMarivoCredentialReferences(refs);
262
- const bindings = credentialBindings(refs);
263
- for (const binding of bindings)
264
- this.#ensureContributor(binding.storageRef);
265
- const token = randomBytes(32).toString('base64url');
266
- this.#leases.set(token, {
267
- agent,
268
- workspaceFingerprint: bridge.binding.fingerprint,
269
- datasourceName,
270
- bindings,
271
- expiresAt: now + this.#ttlMs,
272
- remainingUses: this.#maxUses,
273
- });
274
- return {
275
- token,
276
- expires_in_ms: this.#ttlMs,
277
- max_uses: this.#maxUses,
278
- usage: 'bounded-foreground-shell-lease',
279
- bash_prelude: bashPrelude(token, bindings),
280
- pwsh_prelude: pwshPrelude(token, bindings),
281
- };
282
- }
283
- async #claim(agent, bridgeSource, execution, token) {
284
- const lease = this.#leases.get(token);
285
- if (lease === undefined) {
286
- throw leaseFailure('shell-credential-lease-invalid', 'Marivo shell credential lease is unknown; call marivo_datasource_access again');
287
- }
288
- if (lease.expiresAt <= Date.now()) {
289
- this.#leases.delete(token);
290
- throw leaseFailure('shell-credential-lease-expired', 'Marivo shell credential lease has expired; call marivo_datasource_access again', { datasourceName: lease.datasourceName });
291
- }
292
- if (execution.agent !== agent || lease.agent !== agent) {
293
- throw leaseFailure('shell-credential-lease-scope-mismatch', 'Marivo shell credential lease belongs to another Agent');
294
- }
295
- const bridge = await resolveMarivoDatasourceBridge(bridgeSource);
296
- if (this.#leases.get(token) !== lease) {
297
- throw leaseFailure('shell-credential-lease-invalid', 'Marivo shell credential lease was revoked; call marivo_datasource_access again');
298
- }
299
- if (lease.workspaceFingerprint !== bridge.binding.fingerprint) {
300
- throw leaseFailure('shell-credential-lease-scope-mismatch', 'Marivo shell credential lease belongs to another Workspace binding');
301
- }
302
- if (lease.expiresAt <= Date.now()) {
303
- this.#leases.delete(token);
304
- throw leaseFailure('shell-credential-lease-expired', 'Marivo shell credential lease has expired; call marivo_datasource_access again', { datasourceName: lease.datasourceName });
305
- }
306
- const args = commandArguments(execution);
307
- if (args?.run_in_background === true) {
308
- throw leaseFailure('shell-credential-injection-unsupported', 'Marivo shell credential leases cannot be used by background Shell executions', { tool: execution.name });
309
- }
310
- if (isHarnessPersistentShell(agent, execution.name)) {
311
- throw leaseFailure('shell-credential-injection-unsupported', `Marivo shell credential leases cannot be used by persistent ${execution.name}`, { tool: execution.name });
312
- }
313
- if (lease.remainingUses < 1) {
314
- this.#leases.delete(token);
315
- throw leaseFailure('shell-credential-lease-exhausted', 'Marivo shell credential lease is exhausted; call marivo_datasource_access again', { datasourceName: lease.datasourceName });
316
- }
317
- lease.remainingUses--;
318
- const values = new Map();
319
- for (const binding of lease.bindings) {
320
- execution.signal.throwIfAborted();
321
- let resolved;
322
- try {
323
- resolved = await this.#credentials.resolve(credentialRef(binding.storageRef));
324
- }
325
- catch {
326
- throw leaseFailure('shell-credential-lease-resolve-failed', 'A credential authorized by the Marivo shell lease could not be resolved', { datasourceName: lease.datasourceName, ref: binding.environmentRef });
327
- }
328
- if (resolved === undefined) {
329
- throw leaseFailure('shell-credential-lease-resolve-failed', 'A credential authorized by the Marivo shell lease is no longer configured', { datasourceName: lease.datasourceName, ref: binding.environmentRef });
330
- }
331
- values.set(binding.storageRef, resolved.value);
332
- }
333
- this.#executionValues.set(execution, { agent, values });
334
- }
335
- async prepareExecution(agent, bridgeSource, execution) {
336
- if (this.#disposed)
337
- throw new Error('Marivo shell credential leases are disposed');
338
- const token = leaseToken(execution);
339
- if (token === undefined) {
340
- if (containsCredentialDereference(execution)) {
341
- throw leaseFailure('shell-credential-lease-invalid', 'Marivo shell credential reference is not authorized because the exact prelude lease marker is missing. Call marivo_datasource_access again, copy the exact prelude, and use a foreground Shell execution', { tool: execution.name });
342
- }
343
- return false;
344
- }
345
- await this.#claim(agent, bridgeSource, execution, token);
346
- return true;
347
- }
348
- installAgent(agent, bridgeSource) {
349
- const stopPreExecute = agent.ctx.on('tools/pre-execute', async (execution, next) => {
350
- if (execution.agent === agent && SHELL_TOOL_NAMES.has(execution.name)) {
351
- await this.prepareExecution(agent, bridgeSource, execution);
352
- }
353
- return next();
354
- });
355
- const stopResult = agent.ctx.on('tools/result', (execution) => {
356
- if (execution.agent === agent)
357
- this.#executionValues.delete(execution);
358
- });
359
- let active = true;
360
- return () => {
361
- if (!active)
362
- return;
363
- active = false;
364
- stopPreExecute();
365
- stopResult();
366
- for (const [token, lease] of this.#leases) {
367
- if (lease.agent === agent)
368
- this.#leases.delete(token);
369
- }
370
- for (const [execution, snapshot] of this.#executionValues) {
371
- if (snapshot.agent === agent)
372
- this.#executionValues.delete(execution);
373
- }
374
- };
375
- }
376
- dispose() {
377
- if (this.#disposed)
378
- return;
379
- this.#disposed = true;
380
- this.#leases.clear();
381
- this.#executionValues.clear();
382
- for (const dispose of this.#contributors.values())
383
- dispose();
384
- this.#contributors.clear();
385
- }
386
55
  }
@@ -1,65 +1,39 @@
1
1
  import { defineTool } from '@deepseek-ai/dsh-tools';
2
- import { resolveMarivoDatasourceBridge, } from "./bridge.js";
3
- import { inspectMarivoDatasourceCredentials } from "./credentials.js";
2
+ import { registerMarivoTool } from "../tool-lifecycle.js";
3
+ import { resolveMarivoDatasourceBridge } from "./bridge.js";
4
4
  export const MARIVO_DATASOURCE_TEST_TOOL_NAME = 'marivo_datasource_test';
5
- function datasourceName(value) {
6
- if (typeof value !== 'string' || value.trim() === '' || value.length > 256) {
7
- throw new TypeError('marivo_datasource_test name must be a non-empty string of at most 256 characters');
8
- }
9
- return value;
10
- }
11
- function renderValue(value) {
12
- if (value.status === 'needs-credentials')
13
- return JSON.stringify(value);
14
- if (value.status === 'ok') {
15
- return `Marivo datasource ${value.name} connection test succeeded${value.latency_ms === null ? '' : ` in ${value.latency_ms} ms`}.`;
16
- }
17
- return JSON.stringify(value);
18
- }
19
- /** Build the scoped datasource connection-test Tool. */
20
- export function createMarivoDatasourceTestTool(bridgeSource, credentials, options) {
5
+ export function createMarivoDatasourceTestTool(source, service) {
21
6
  return defineTool({
22
7
  name: MARIVO_DATASOURCE_TEST_TOOL_NAME,
23
- description: 'Test one configured Marivo datasource connection. Missing datasource environment references are requested through the DSH credential service.',
8
+ description: 'Test a Marivo datasource through Host credentials. Missing credentials wait for the Web form while this call remains alive; configured connection failures return directly.',
24
9
  parameters: {
25
- name: {
26
- type: 'string',
27
- required: true,
28
- description: 'Configured Marivo datasource name.',
29
- },
10
+ name: { type: 'string', required: true, description: 'Configured datasource name.' },
30
11
  },
31
12
  output: {
32
13
  schema: { type: 'json' },
33
- render: (_args, value) => [
34
- { type: 'text', text: renderValue(value) },
35
- ],
14
+ render: (_args, value) => [{ type: 'text', text: JSON.stringify(value) }],
36
15
  },
37
- timeoutMs: 65_000,
38
16
  async execute(args, exec) {
39
- const name = datasourceName(args.name);
40
- const bridge = await resolveMarivoDatasourceBridge(bridgeSource);
41
- options.revokeShellLease(bridge, name);
42
- const described = await bridge.describe(name, exec.signal);
43
- const overlay = {};
44
- const missing = await inspectMarivoDatasourceCredentials(described.refs, credentials, exec.signal, (ref, value) => {
45
- overlay[ref] = value;
46
- });
47
- if (missing.length > 0)
48
- return { status: 'needs-credentials', name: described.name, refs: missing };
49
- const tested = await bridge.test(name, overlay, exec.signal);
50
- if (tested.ok) {
51
- return { status: 'ok', name: tested.name, latency_ms: tested.latency_ms };
52
- }
53
- return {
54
- status: 'failed',
55
- name: tested.name,
56
- latency_ms: tested.latency_ms,
57
- failure: tested.failure,
58
- repair: tested.repair,
59
- };
17
+ if (!args.name.trim() || args.name.length > 256)
18
+ throw new Error('Invalid datasource name');
19
+ return datasourceToolValue(await service.track(service.prepare('test', exec, () => resolveMarivoDatasourceBridge(source), args.name)));
60
20
  },
61
21
  });
62
22
  }
63
- export function registerMarivoDatasourceTestTool(ctx, bridgeSource, credentials, options) {
64
- return ctx.tools.register(createMarivoDatasourceTestTool(bridgeSource, credentials, options));
23
+ export function registerMarivoDatasourceTestTool(ctx, source, service) {
24
+ return registerMarivoTool(ctx, createMarivoDatasourceTestTool(source, service));
25
+ }
26
+ /** Preserve the datasource tools' public status family; raw Marivo results stay inside the service. */
27
+ export function datasourceToolValue(result) {
28
+ if (!('ok' in result))
29
+ return JSON.parse(JSON.stringify(result));
30
+ return JSON.parse(JSON.stringify(result.ok
31
+ ? { status: 'ok', name: result.name, latency_ms: result.latency_ms }
32
+ : {
33
+ status: 'failed',
34
+ name: result.name,
35
+ latency_ms: result.latency_ms,
36
+ failure: result.failure,
37
+ repair: result.repair,
38
+ }));
65
39
  }
@@ -1,5 +1,6 @@
1
1
  import { createUserMessage } from '@deepseek-ai/dsh-llm';
2
2
  import { scopeParentOf } from '@deepseek-ai/dsh-scope';
3
+ import { finishCleanup, PendingTasks } from "../lifecycle.js";
3
4
  import { MARIVO_HELP_TOOL_NAME, readMarivoHelpTargets, registerMarivoHelpTool, renderMarivoHelpValue, resolveMarivoHelpBridge, } from "./help.js";
4
5
  const SKILL_TOOL_NAME = 'skill';
5
6
  export const MARIVO_ROOT_HELP_TARGETS = Object.freeze({
@@ -119,6 +120,8 @@ export class MarivoDisclosureController {
119
120
  #visibleHelp = new Map();
120
121
  #lifecycleAbort = new AbortController();
121
122
  #disposers = [];
123
+ #tasks = new PendingTasks();
124
+ #closing;
122
125
  #disposed = false;
123
126
  #telemetry = { activations: [], rootHelp: [], failures: [] };
124
127
  constructor(agent, bridgeSource, options = {}) {
@@ -181,7 +184,10 @@ export class MarivoDisclosureController {
181
184
  return 'already-visible';
182
185
  return visible === undefined ? 'delivered' : 'replacement';
183
186
  }
184
- async prepareStep(messages, signal) {
187
+ prepareStep(messages, signal) {
188
+ return this.#tasks.track(this.#prepareStep(messages, signal));
189
+ }
190
+ async #prepareStep(messages, signal) {
185
191
  if (this.#disposed)
186
192
  throw this.#lifecycleAbort.signal.reason;
187
193
  this.#observeExplicitInvocations(messages);
@@ -273,13 +279,16 @@ export class MarivoDisclosureController {
273
279
  return;
274
280
  this.#disposed = true;
275
281
  this.#lifecycleAbort.abort(new Error('Marivo disclosure controller disposed'));
276
- for (const disposer of this.#disposers.reverse())
277
- disposer();
282
+ this.#closing = finishCleanup([...this.#disposers.reverse(), () => this.#tasks.drain()]);
278
283
  this.#disposers = [];
279
284
  this.#activeSkills.clear();
280
285
  this.#pendingSkills.clear();
281
286
  this.#visibleHelp.clear();
282
287
  }
288
+ close() {
289
+ this.dispose();
290
+ return this.#closing;
291
+ }
283
292
  #inheritedSkillToolVisible() {
284
293
  const inheritedSkillTool = this.agent.ctx.tools.get(SKILL_TOOL_NAME, scopeParentOf(this.agent));
285
294
  return (inheritedSkillTool !== undefined &&
@@ -294,7 +303,7 @@ export class MarivoDisclosureController {
294
303
  }
295
304
  }
296
305
  #restoreActiveSkills() {
297
- for (const event of this.agent.session.events) {
306
+ for (const event of this.agent.session.snapshotEvents()) {
298
307
  if (event.type !== 'user/message')
299
308
  continue;
300
309
  const disclosure = rootHelpSource(event.data.source);
@@ -309,7 +318,7 @@ export class MarivoDisclosureController {
309
318
  #refreshVisibleHelp(messages) {
310
319
  this.#visibleHelp.clear();
311
320
  const visible = new Set(this.agent.session.surface.nodes);
312
- for (const event of this.agent.session.events) {
321
+ for (const event of this.agent.session.snapshotEvents()) {
313
322
  if (!visible.has(event.seq))
314
323
  continue;
315
324
  if (event.type === 'user/message') {
@@ -340,7 +349,9 @@ export class MarivoDisclosureController {
340
349
  }
341
350
  }
342
351
  #hasHistoricalDisclosure(skill) {
343
- return this.agent.session.events.some((event) => event.type === 'user/message' && rootHelpSource(event.data.source)?.skill === skill);
352
+ return this.agent.session
353
+ .snapshotEvents()
354
+ .some((event) => event.type === 'user/message' && rootHelpSource(event.data.source)?.skill === skill);
344
355
  }
345
356
  }
346
357
  /** Install skill-triggered Marivo live-help disclosure for one Agent scope. */
@@ -356,9 +367,10 @@ export function installMarivoDisclosure(_ctx, agent, bridgeSource, options = {})
356
367
  if (decision.kind === 'reject')
357
368
  return decision;
358
369
  const injections = await controller.prepareStep(decision.messages, signal);
370
+ signal.throwIfAborted();
359
371
  return injections.length === 0
360
372
  ? decision
361
- : { kind: 'enter', messages: [...decision.messages, ...injections] };
373
+ : { ...decision, messages: [...decision.messages, ...injections] };
362
374
  }, true));
363
375
  return controller;
364
376
  }
@@ -0,0 +1,52 @@
1
+ import { createUserMessage } from '@deepseek-ai/dsh-llm';
2
+ export const MARIVO_DATASOURCE_CREDENTIAL_PROMPT = [
3
+ 'When a requested table has no usable configured datasource, call marivo_datasource_configure with mode=create and a brief reason. For a datasource needing connection configuration repair, use mode=edit and its exact name. The user configures it in the owning Web right tab; do not request secrets in chat or write connection configuration on the user behalf. Only status=ok allows continuing: rediscover the datasource and verify the requested table and read access before analysis. Other statuses are not connection success. A provided local file may be analyzed directly when appropriate; do not invent a remote datasource requirement.',
4
+ 'DSH Credentials owns Marivo datasource secrets. Never request values in chat, read credential files or ~/.marivo/secrets.toml, or write secrets to scripts, arguments, environment variables, reports or logs.',
5
+ 'Use marivo_datasource_test after datasource changes, credential rotation, connection failures, or explicit user requests. Missing credentials wait for the Web form only while the original call remains alive.',
6
+ 'Execute analysis, metadata inspection and semantic data reads through marivo_python. Declare all exact Marivo datasource names this execution may access, including datasources without passwords. Local file analysis with pandas or native DuckDB uses datasources: [] when no Marivo datasource is accessed.',
7
+ 'marivo_python waits for all missing credentials and validates the bound Workspace and datasource identities before taking one fresh snapshot and starting user code once. Configured credentials need no extra connection test. Ordinary Shell receives no datasource secret.',
8
+ 'marivo_python installs credential_scope before user code. When using Marivo Session/reader objects, create or resume them inside that execution, and close Sessions in finally. Do not replace the resolver, read SecretValue contents, or bypass Host scope with environment/cache configuration.',
9
+ "Each marivo_python call uses a separate process. Closing releases that process's Session resources; it does not end the analytical question or delete durable Artifacts. When continuing a persisted Marivo analysis, reuse its Session identity across calls.",
10
+ 'Configured credentials do not imply a valid connection or query permissions. Preserve real failures; never automatically replay a script with possible side effects.',
11
+ 'Session lifetime pattern inside one marivo_python call (create/resume using current Runtime Help):\nsession = ...\ntry:\n ... # analysis using this Session\nfinally:\n session.close()',
12
+ ].join('\n');
13
+ export const MARIVO_ANALYSIS_CLOSEOUT_PROMPT = [
14
+ 'Analysis semantics and execution contracts come from the activated Runtime Skill and current Help.',
15
+ 'Before completing any analysis, including a text-only answer, check each user question and each requested comparison scope against its evidence. Keep incomplete branches explicit; preserve comparison sides, direction and denominator. Match conclusion strength to evidence, and reflect limitations in the claims themselves.',
16
+ ].join(' ');
17
+ /** Bridge rules activated after system prompt assembly, without changing their wording. */
18
+ function executionGuidanceSupplement(before, after) {
19
+ const rules = [];
20
+ if (before.length === 0 && after.length > 0)
21
+ rules.push(MARIVO_DATASOURCE_CREDENTIAL_PROMPT);
22
+ if (!before.includes('marivo-analysis') && after.includes('marivo-analysis'))
23
+ rules.push(MARIVO_ANALYSIS_CLOSEOUT_PROMPT);
24
+ if (rules.length === 0)
25
+ return [];
26
+ return [
27
+ createUserMessage({
28
+ content: [
29
+ {
30
+ type: 'text',
31
+ text: ['<marivo_execution_guidance>', ...rules, '</marivo_execution_guidance>'].join('\n\n'),
32
+ },
33
+ ],
34
+ source: { kind: 'plugin', plugin: 'dsh-data-analysis' },
35
+ }),
36
+ ];
37
+ }
38
+ /** Full-plugin seam: requires its execution tools, credentials service and system sections. */
39
+ export function installMarivoExecutionGuidance(agent, controller) {
40
+ return agent.ctx.on('agent/pre-step', async ({ signal }, next) => {
41
+ // Prepend after Help installation to wrap its successful disclosure decision.
42
+ const previouslyActive = controller.activeSkills;
43
+ const decision = await next();
44
+ if (decision.kind === 'reject')
45
+ return decision;
46
+ signal.throwIfAborted();
47
+ const guidance = executionGuidanceSupplement(previouslyActive, controller.activeSkills);
48
+ return guidance.length === 0
49
+ ? decision
50
+ : { ...decision, messages: [...decision.messages, ...guidance] };
51
+ }, true);
52
+ }
@@ -1,5 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { defineTool } from '@deepseek-ai/dsh-tools';
3
+ import { registerMarivoTool } from "../tool-lifecycle.js";
3
4
  import { MarivoHelpError, resolveMarivoHelpBridge, } from "./bridge.js";
4
5
  export { MarivoHelpError, resolveMarivoHelpBridge } from "./bridge.js";
5
6
  export const MARIVO_HELP_TOOL_NAME = 'marivo_help';
@@ -203,12 +204,14 @@ export function createMarivoHelpTool(bridgeSource, limitOverrides = {}, resolveD
203
204
  },
204
205
  timeoutMs: limits.toolTimeoutMs,
205
206
  async execute(args, exec) {
207
+ exec.signal.throwIfAborted();
206
208
  const bridge = await resolveMarivoHelpBridge(bridgeSource);
207
209
  const internal = await readMarivoHelpTargets(bridge, args.targets, {
208
210
  limits,
209
211
  signal: exec.signal,
210
212
  resolveDelivery,
211
213
  });
214
+ exec.signal.throwIfAborted();
212
215
  const value = {
213
216
  environment: { version: internal.environment.version },
214
217
  targets: internal.targets,
@@ -223,5 +226,5 @@ export function createMarivoHelpTool(bridgeSource, limitOverrides = {}, resolveD
223
226
  }
224
227
  /** Register the focused Help Tool; skill-triggered root disclosure is composed separately. */
225
228
  export function registerMarivoHelpTool(ctx, bridgeSource, limits = {}, resolveDelivery) {
226
- return ctx.tools.register(createMarivoHelpTool(bridgeSource, limits, resolveDelivery));
229
+ return registerMarivoTool(ctx, createMarivoHelpTool(bridgeSource, limits, resolveDelivery));
227
230
  }