@chengxianglibra/dsh-data-analysis 0.2.0 → 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 (35) hide show
  1. package/README.en.md +135 -0
  2. package/README.md +50 -80
  3. package/lib/client/credentials/install.js +2 -2
  4. package/lib/client/i18n/copy.js +4 -1
  5. package/lib/client/i18n/host.js +1 -0
  6. package/lib/client/i18n/settings.js +30 -0
  7. package/lib/client/settings/card.js +90 -0
  8. package/lib/client/settings/install.js +10 -0
  9. package/lib/client.js +85 -62
  10. package/lib/datasource/configure.js +1 -1
  11. package/lib/datasource/python-options.js +1 -7
  12. package/lib/datasource/python.js +9 -6
  13. package/lib/datasource/test.js +1 -1
  14. package/lib/disclosure/execution-guidance.js +5 -8
  15. package/lib/plugin-agents.js +2 -2
  16. package/lib/plugin.js +6 -2
  17. package/lib/presentation/assets/portable.js +1 -1
  18. package/lib/presentation/assets/static.js +47 -47
  19. package/lib/settings.js +21 -0
  20. package/lib/types/client/i18n/copy.d.ts +15 -0
  21. package/lib/types/client/i18n/host.d.ts +1 -0
  22. package/lib/types/client/i18n/settings.d.ts +16 -0
  23. package/lib/types/client/settings/card.d.ts +9 -0
  24. package/lib/types/client/settings/install.d.ts +2 -0
  25. package/lib/types/client.d.ts +2 -2
  26. package/lib/types/datasource/python-options.d.ts +1 -2
  27. package/lib/types/datasource/python.d.ts +2 -2
  28. package/lib/types/plugin-agents.d.ts +2 -0
  29. package/lib/types/settings.d.ts +14 -0
  30. package/package.json +15 -5
  31. package/python/presentation-kit/dist/dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl +0 -0
  32. package/skills/dsh-data-analysis-files/SKILL.md +22 -10
  33. package/skills/dsh-data-analysis-files/references/delivery.md +15 -0
  34. package/skills/dsh-data-analysis-presentation/SKILL.md +15 -19
  35. package/skills/dsh-data-analysis-presentation/references/schema.md +4 -1
@@ -5,7 +5,7 @@ export const MARIVO_DATASOURCE_CONFIGURE_TOOL_NAME = 'marivo_datasource_configur
5
5
  export function createMarivoDatasourceConfigureTool(source, service) {
6
6
  return defineTool({
7
7
  name: MARIVO_DATASOURCE_CONFIGURE_TOOL_NAME,
8
- description: 'Ask the user to create/select or edit a datasource in the owning Web session right tab. Waits until the user saves and tests successfully, cancels, or hands off a failure. Never pass credentials or configuration values. After success, rediscover the datasource and verify the requested table before analysis.',
8
+ description: 'When a requested remote table has no usable configured datasource, use mode=create to let the user create/select one; repair connection configuration with mode=edit and its exact name. The user configures it in the owning Web session right tab; never write connection configuration on their behalf or pass credentials or configuration values. Waits for successful save and connection test, cancellation or failure. Only status=ok permits continuation: rediscover the datasource and verify the requested table and read access before analysis. Success already includes a connection test; do not repeat it unless configuration or credentials change, a connection fails, or the user requests one. Local files need no remote datasource setup.',
9
9
  parameters: {
10
10
  mode: {
11
11
  type: 'string',
@@ -1,5 +1,4 @@
1
1
  export const DEFAULT_PYTHON_TIMEOUT_MS = 120_000;
2
- export const DEFAULT_PYTHON_MAX_TIMEOUT_MS = 600_000;
3
2
  const MAX_TIMER_DELAY_MS = 2_147_483_647;
4
3
  /** Do not echo rejected inputs: tool arguments and configuration are not trusted diagnostics. */
5
4
  export function pythonTimeout(value, name) {
@@ -12,10 +11,5 @@ export function pythonTimeout(value, name) {
12
11
  }
13
12
  export function resolvePythonOptions(options) {
14
13
  const pythonTimeoutMs = pythonTimeout(options.pythonTimeoutMs === undefined ? DEFAULT_PYTHON_TIMEOUT_MS : options.pythonTimeoutMs, 'pythonTimeoutMs');
15
- const pythonMaxTimeoutMs = pythonTimeout(options.pythonMaxTimeoutMs === undefined
16
- ? DEFAULT_PYTHON_MAX_TIMEOUT_MS
17
- : options.pythonMaxTimeoutMs, 'pythonMaxTimeoutMs');
18
- if (pythonTimeoutMs > pythonMaxTimeoutMs)
19
- throw new Error('pythonTimeoutMs must not exceed pythonMaxTimeoutMs');
20
- return { pythonTimeoutMs, pythonMaxTimeoutMs };
14
+ return { pythonTimeoutMs };
21
15
  }
@@ -4,7 +4,7 @@ import { defineTool } from '@deepseek-ai/dsh-tools';
4
4
  import { savePythonExecution } from "../python-execution.js";
5
5
  import { registerMarivoTool } from "../tool-lifecycle.js";
6
6
  import { resolveMarivoDatasourceBridge } from "./bridge.js";
7
- import { pythonTimeout, resolvePythonOptions } from "./python-options.js";
7
+ import { pythonTimeout, resolvePythonOptions, } from "./python-options.js";
8
8
  import { PYTHON_LAUNCHER, PYTHON_WORKER } from "./resolver-program.js";
9
9
  import { CredentialServiceError, } from "./service.js";
10
10
  import { datasourceToolValue } from "./test.js";
@@ -33,10 +33,11 @@ function quote(value) {
33
33
  : `'${value.replaceAll("'", "'\\''")}'`;
34
34
  }
35
35
  export function registerMarivoPythonTool(ctx, source, service, options = {}) {
36
- const limits = resolvePythonOptions(options);
36
+ const readOptions = typeof options === 'function' ? options : () => options;
37
+ resolvePythonOptions(readOptions());
37
38
  return registerMarivoTool(ctx, defineTool({
38
39
  name: 'marivo_python',
39
- description: 'Execute foreground Python in the bound Runtime and Workspace, including local pandas and native DuckDB file analysis. This call waits for missing credentials for every listed Marivo datasource before starting Python once; configured credentials do not trigger a connection test. When using Marivo Sessions or readers, create/resume them inside this execution and close Sessions in finally. No background execution or secret environment variables. Nonzero exits are reported without replay. Successful execution saves the exact submitted code and returns codeRef; explicitly associate it with presentation datasets through draft codeRefs. A codeCaptureError does not change the execution outcome and must not trigger replay. The execution summary reports adapter phase, outcome and effective Shell budget, not query progress or saved Artifacts. Credential waiting precedes the Shell budget; outer Code Mode deadlines and cancellation still apply. Timeout does not confirm remote query cancellation or absence of saved results.',
40
+ description: 'Execute foreground Python in the bound Runtime and Workspace, including local pandas and native DuckDB file analysis. Waits for missing credentials for every declared datasource before starting code once; no automatic connection test or execution replay. No background execution or secret environment variables. Success returns codeRef for the submitted code; associate it with presentation datasets through draft codeRefs when needed. codeCaptureError leaves the execution outcome unchanged; do not rerun to recover the code record. Inspect execution phase, outcome and nextAction after failure; timeout does not prove remote query cancellation or absence of saved results.',
40
41
  parameters: {
41
42
  code: {
42
43
  type: 'string',
@@ -51,7 +52,7 @@ export function registerMarivoPythonTool(ctx, source, service, options = {}) {
51
52
  },
52
53
  timeoutMs: {
53
54
  type: 'number',
54
- description: `Optional foreground Shell timeout in milliseconds, a positive integer at most 2147483647. Defaults to ${limits.pythonTimeoutMs}; capped at ${limits.pythonMaxTimeoutMs} and then by Harness Shell. Outer Code Mode deadlines remain independent.`,
55
+ description: 'Optional foreground Shell timeout in milliseconds, a positive integer at most 2147483647. Defaults to the current plugin pythonTimeoutMs setting. Credential waiting precedes this budget; Harness Shell limits, outer Code Mode deadlines and cancellation remain independent.',
55
56
  },
56
57
  },
57
58
  output: {
@@ -83,7 +84,9 @@ export function registerMarivoPythonTool(ctx, source, service, options = {}) {
83
84
  };
84
85
  try {
85
86
  try {
86
- requestedTimeoutMs = pythonTimeout(args.timeoutMs === undefined ? limits.pythonTimeoutMs : args.timeoutMs, 'timeoutMs');
87
+ requestedTimeoutMs = pythonTimeout(args.timeoutMs === undefined
88
+ ? resolvePythonOptions(readOptions()).pythonTimeoutMs
89
+ : args.timeoutMs, 'timeoutMs');
87
90
  }
88
91
  catch {
89
92
  rejectInput('timeoutMs must be a positive integer no greater than 2147483647');
@@ -112,7 +115,7 @@ export function registerMarivoPythonTool(ctx, source, service, options = {}) {
112
115
  const spec = shell.resolve({
113
116
  command: `${process.platform === 'win32' ? '& ' : ''}${quote(binding.pythonExecutable)} -c ${quote(PYTHON_LAUNCHER)}`,
114
117
  workdir: binding.projectRoot,
115
- timeoutMs: Math.min(requestedTimeoutMs, limits.pythonMaxTimeoutMs),
118
+ timeoutMs: requestedTimeoutMs,
116
119
  signal: prepared.signal,
117
120
  stdin: JSON.stringify({
118
121
  identity: binding,
@@ -5,7 +5,7 @@ export const MARIVO_DATASOURCE_TEST_TOOL_NAME = 'marivo_datasource_test';
5
5
  export function createMarivoDatasourceTestTool(source, service) {
6
6
  return defineTool({
7
7
  name: MARIVO_DATASOURCE_TEST_TOOL_NAME,
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.',
8
+ description: 'Test a Marivo datasource through Host credentials after datasource changes, credential rotation, connection failures, or explicit user requests. Normal analysis with configured credentials needs no preliminary test; successful marivo_datasource_configure already tested that configuration. Missing credentials wait for the Web form only while this call remains alive; configured connection failures return directly. Only status=ok proves this connection test succeeded; verify the requested table and read access separately.',
9
9
  parameters: {
10
10
  name: { type: 'string', required: true, description: 'Configured datasource name.' },
11
11
  },
@@ -1,14 +1,11 @@
1
1
  import { createUserMessage } from '@deepseek-ai/dsh-llm';
2
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.',
3
+ 'These are Host execution and credential rules; Marivo API and semantic contracts come from the bound Runtime Skill and live Help.',
4
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()',
5
+ 'Use marivo_datasource_configure for missing datasource setup or connection configuration repair; the user owns configuration in the Web form. Use marivo_datasource_test for connection checks under its tool contract. Configured credentials alone do not prove connection or read access.',
6
+ 'Execute analysis, metadata inspection and semantic data reads through marivo_python in the bound Runtime and Workspace. Declare all exact Marivo datasource names this execution may access, including datasources without passwords; use datasources: [] for local pandas or native DuckDB without Marivo datasource access.',
7
+ 'Each marivo_python call is a separate process. Create/resume Marivo Sessions inside the call, close them in finally, and retain the persisted Session identity when continuing the same analysis. Closing process resources does not delete durable Artifacts. Do not replace the credential resolver, read SecretValue contents, or bypass Host scope with environment/cache configuration.',
8
+ 'Preserve real failures. After uncertain execution, inspect existing effects before retrying; never automatically replay a script with possible side effects.',
12
9
  ].join('\n');
13
10
  export const MARIVO_ANALYSIS_CLOSEOUT_PROMPT = [
14
11
  'Analysis semantics and execution contracts come from the activated Runtime Skill and current Help.',
@@ -12,7 +12,7 @@ import { registerMarivoExportHtmlTool } from "./presentation/export-html.js";
12
12
  import { installMarivoPresentationCodeDelivery, registerMarivoPresentTool, } from "./presentation/index.js";
13
13
  import { registerReportPublishTool } from "./report-publishing/adapters.js";
14
14
  import { resolvePresentationWorkspace } from "./workspace-identity.js";
15
- const PRESENTATION_PROMPT = 'Answer ordinary factual questions in text. For analysis of provided data files, load dsh-data-analysis-files; local pandas or native DuckDB work needs no Marivo semantic setup. For charts, tables, reports, dashboards or a readable source presentation, load dsh-data-analysis-presentation and deliver through marivo_present. When the user requests an offline HTML file, export the saved report with marivo_export_html, then call native present with the returned path before the final response. Use the Runtime skills and live Help when the task needs Marivo analysis or semantic authoring; existing data can be presented directly.';
15
+ const PRESENTATION_PROMPT = 'Match delivery to the user request. Ordinary answers and simple comparison tables can stay in chat. For analysis of attachments or Workspace data files, including short chat comparisons, first load dsh-data-analysis-files; requested CSV, JSON or PNG files use native present. For interactive charts or tables, saved reports, dashboards, report updates or visual source panels, load dsh-data-analysis-presentation and use marivo_present; that Skill also covers report export and publication when requested. Existing results can be presented directly. Use the Runtime skills and live Help for Marivo analysis or semantic authoring; local pandas or native DuckDB file analysis needs no Marivo semantic setup. When analysis reveals a reusable business definition or semantic gap, follow the relevant Skill to assess reuse or handoff to marivo-semantic, limited to what the current task needs or the user has authorized; stop when that scope is answered or its blockers are explicit.';
16
16
  /**
17
17
  * Install one already-bound environment into every live or subsequently published Agent scope.
18
18
  * Installation is transactional for existing Agents and is disposed with the Cordis plugin.
@@ -87,7 +87,7 @@ export function createMarivoAgentInstallation(ctx, environmentOrResolver, option
87
87
  controller.addDisposer(installMarivoExecutionGuidance(agent, controller));
88
88
  controller.addDisposer(registerMarivoDatasourceTestTool(agent.ctx, datasourceSource, credentialService));
89
89
  controller.addDisposer(registerMarivoDatasourceConfigureTool(agent.ctx, datasourceSource, credentialService));
90
- controller.addDisposer(registerMarivoPythonTool(agent.ctx, datasourceSource, credentialService, pythonOptions));
90
+ controller.addDisposer(registerMarivoPythonTool(agent.ctx, datasourceSource, credentialService, options.pythonOptionsSource ?? pythonOptions));
91
91
  controller.addDisposer(() => credentialService.disposeAgent(agent));
92
92
  controller.addDisposer(registerMarivoPresentTool(agent.ctx, presentationSource, agent.session));
93
93
  controller.addDisposer(registerMarivoExportHtmlTool(agent.ctx, () => resolvePresentationWorkspace(ctx, String(agent.session.id)), agent.session));
package/lib/plugin.js CHANGED
@@ -5,6 +5,7 @@ import { createMarivoAgentInstallation } from "./plugin-agents.js";
5
5
  import { registerPublishingCredentials } from "./report-publishing/adapters.js";
6
6
  import { resolvePublishingConfig } from "./report-publishing/config.js";
7
7
  import { ReportPublishingService } from "./report-publishing/service.js";
8
+ import { installPythonSettings } from "./settings.js";
8
9
  import { resolvePresentationWorkspace } from "./workspace-identity.js";
9
10
  export { installMarivoPlugin } from "./plugin-agents.js";
10
11
  export { resolvePresentationWorkspace } from "./workspace-identity.js";
@@ -16,7 +17,7 @@ import { apply as installSkillFilesystem } from '@deepseek-ai/dsh-skill-filesyst
16
17
  import { WorkspaceId } from '@deepseek-ai/dsh-workspace';
17
18
  import z from '@deepseek-ai/schemastery';
18
19
  import { MarivoDatasourceBridge } from "./datasource/bridge.js";
19
- import { DEFAULT_PYTHON_MAX_TIMEOUT_MS, DEFAULT_PYTHON_TIMEOUT_MS, resolvePythonOptions, } from "./datasource/python-options.js";
20
+ import { DEFAULT_PYTHON_TIMEOUT_MS, resolvePythonOptions, } from "./datasource/python-options.js";
20
21
  import { registerCredentialRpc } from "./datasource/rpc.js";
21
22
  import { MarivoCredentialService } from "./datasource/service.js";
22
23
  import { registerMarivoRuntimeShellEnvironment } from "./datasource/shell-env.js";
@@ -47,7 +48,6 @@ export const Config = z.object({
47
48
  datasourceDefaults: z.any(),
48
49
  reportPublishing: z.any(),
49
50
  pythonTimeoutMs: z.number().default(DEFAULT_PYTHON_TIMEOUT_MS),
50
- pythonMaxTimeoutMs: z.number().default(DEFAULT_PYTHON_MAX_TIMEOUT_MS),
51
51
  credentialInteraction: z.union(['web', 'none']).default('web'),
52
52
  projectRoot: z.string(),
53
53
  pythonExecutable: z.string(),
@@ -100,6 +100,7 @@ export async function apply(ctx, config = {}) {
100
100
  let disposePresentation;
101
101
  let referenceService;
102
102
  let agentInstallation;
103
+ let pythonSettings;
103
104
  let closing;
104
105
  const browserService = new SemanticBrowserService({
105
106
  getWorkspace: (id) => ctx.workspaceRegistry.get(WorkspaceId(id)),
@@ -111,6 +112,7 @@ export async function apply(ctx, config = {}) {
111
112
  return closing;
112
113
  closing = finishCleanup([
113
114
  () => agentInstallation?.close(),
115
+ () => pythonSettings?.dispose(),
114
116
  () => disposeCredentials?.(),
115
117
  disposeChanges,
116
118
  () => disposePublishing?.(),
@@ -132,6 +134,7 @@ export async function apply(ctx, config = {}) {
132
134
  return closing;
133
135
  };
134
136
  try {
137
+ pythonSettings = installPythonSettings(ctx, pythonOptions);
135
138
  unregisterChanges = ctx.typert.register(credentialChangesHost);
136
139
  installSkillFilesystem(ctx, {
137
140
  providerName: 'dsh-data-analysis-marivo',
@@ -160,6 +163,7 @@ export async function apply(ctx, config = {}) {
160
163
  disposePublishing = registerPublishingCredentials(ctx.connection, reportPublishing, (id) => Boolean(ctx.workspaceRegistry.get(WorkspaceId(id))));
161
164
  agentInstallation = createMarivoAgentInstallation(ctx, resolveEnvironment, {
162
165
  ...pythonOptions,
166
+ pythonOptionsSource: pythonSettings.get,
163
167
  helpBridgeSource: helpBridge,
164
168
  ...(publishingConfig ? { reportPublishing } : {}),
165
169
  credentialService,