@chengxianglibra/dsh-data-analysis 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48,6 +48,7 @@ function parsePackageManifest(value) {
48
48
  contracts: Object.freeze({
49
49
  runtimeInstallation: requiredLiteral(contracts.runtimeInstallation, 'dsh-data-analysis-runtime/v3', 'package compatibility contracts.runtimeInstallation'),
50
50
  subprocessPolicy: requiredLiteral(contracts.subprocessPolicy, 'direct-argv-inherited-env-snapshot-overlay-v2', 'package compatibility contracts.subprocessPolicy'),
51
+ integration: requiredLiteral(contracts.integration, 'dsh-data-analysis-integration/v1', 'package compatibility contracts.integration'),
51
52
  }),
52
53
  }),
53
54
  });
@@ -1,10 +1,13 @@
1
1
  import { z } from 'zod';
2
2
  import { CredentialServiceError } from "./service.js";
3
+ import { marivoCredentialStorageRef } from "./shell-env.js";
3
4
  /** Validate against this Workspace's live Runtime; never include config values in errors. */
4
- export function withDatasourceDefaults(schema, configured) {
5
- if (configured === undefined)
5
+ export function withDatasourceDefaults(schema, configured, managed) {
6
+ if (configured === undefined && managed === undefined)
6
7
  return schema;
7
- const parsed = z.record(z.string(), z.record(z.string(), z.json())).safeParse(configured);
8
+ const parsed = z
9
+ .record(z.string(), z.record(z.string(), z.json()))
10
+ .safeParse(configured === undefined ? {} : configured);
8
11
  if (!parsed.success)
9
12
  throw new CredentialServiceError('datasource-defaults-invalid');
10
13
  for (const [backend, values] of Object.entries(parsed.data)) {
@@ -21,5 +24,24 @@ export function withDatasourceDefaults(schema, configured) {
21
24
  throw new CredentialServiceError('datasource-defaults-type-invalid');
22
25
  }
23
26
  }
24
- return { ...schema, creationDefaults: parsed.data };
27
+ const combined = Object.fromEntries(Object.entries(parsed.data).map(([backend, values]) => [backend, { ...values }]));
28
+ if (managed !== undefined) {
29
+ const references = z.record(z.string(), z.record(z.string(), z.string())).safeParse(managed);
30
+ if (!references.success)
31
+ throw new CredentialServiceError('datasource-defaults-invalid');
32
+ for (const [backend, fields] of Object.entries(references.data)) {
33
+ const definition = schema.backends.find((item) => item.name === backend);
34
+ if (!definition)
35
+ throw new CredentialServiceError('datasource-defaults-backend-invalid');
36
+ for (const [name, reference] of Object.entries(fields)) {
37
+ if (!name.endsWith('_env') || !definition.fields.some((field) => field.name === name))
38
+ throw new CredentialServiceError('datasource-defaults-field-invalid');
39
+ marivoCredentialStorageRef(reference);
40
+ if (Object.hasOwn(combined[backend] ?? {}, name))
41
+ throw new CredentialServiceError('datasource-defaults-credential-forbidden');
42
+ }
43
+ combined[backend] = { ...combined[backend], ...fields };
44
+ }
45
+ }
46
+ return { ...schema, creationDefaults: combined };
25
47
  }
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { registerPluginRpc } from "../rpc.js";
3
- import { withDatasourceDefaults } from "./defaults.js";
3
+ import { withDatasourceDefaults, } from "./defaults.js";
4
4
  import { CREDENTIAL_CHANNEL, credentialError } from "./service.js";
5
5
  const text = z.string().min(1).max(256);
6
6
  const handle = { generation: z.string().uuid(), id: z.string().uuid(), scope: z.string().uuid() };
@@ -15,7 +15,7 @@ const mutation = z
15
15
  changes: z.record(text, z.string().min(1).max(65536)).optional(),
16
16
  })
17
17
  .strict();
18
- export function registerCredentialRpc(connection, service, workspace, datasourceDefaults) {
18
+ export function registerCredentialRpc(connection, service, workspace, datasourceDefaults, managedCredentialDefaults) {
19
19
  const unregister = registerPluginRpc(connection, CREDENTIAL_CHANNEL, [
20
20
  'overview',
21
21
  'authoring',
@@ -53,7 +53,7 @@ export function registerCredentialRpc(connection, service, workspace, datasource
53
53
  generation: service.generation,
54
54
  ...(input.mode === 'edit'
55
55
  ? schema
56
- : withDatasourceDefaults(schema, datasourceDefaults)),
56
+ : withDatasourceDefaults(schema, datasourceDefaults, managedCredentialDefaults)),
57
57
  };
58
58
  }
59
59
  else if (endpoint === 'configuration') {
@@ -527,6 +527,8 @@ export async function ensureSharedMarivoRuntime(config = {}, options = {}) {
527
527
  const existing = await validatedExisting(runtimeRoot, configuredPython, options.environment, timeoutMs, presentationKitWheel);
528
528
  if (existing !== undefined)
529
529
  return existing;
530
+ if (options.existingOnly)
531
+ throw new MarivoEnvironmentError('shared-runtime-installation-required', 'A valid shared Marivo Runtime installation is required');
530
532
  await mkdir(path.dirname(runtimeRoot), { recursive: true });
531
533
  const lockPath = `${runtimeRoot}.install-lock`;
532
534
  const release = await acquireLock(lockPath, timeoutMs, options.waitIntervalMs ?? 100);
@@ -31,9 +31,11 @@ export class MarivoWorkspaceEnvironmentManager {
31
31
  #disposed = false;
32
32
  #closing;
33
33
  runtime;
34
+ onBound;
34
35
  #bindings = new Map();
35
- constructor(runtime) {
36
+ constructor(runtime, onBound) {
36
37
  this.runtime = runtime;
38
+ this.onBound = onBound;
37
39
  }
38
40
  resolve(projectRoot) {
39
41
  return this.#tasks.track(this.#resolve(projectRoot));
@@ -54,6 +56,16 @@ export class MarivoWorkspaceEnvironmentManager {
54
56
  version: this.runtime.presentationKitVersion,
55
57
  packagePath: this.runtime.presentationKitPackagePath,
56
58
  },
59
+ })
60
+ .then(async (environment) => {
61
+ if (this.#disposed)
62
+ throw new Error('Marivo Workspace manager disposed');
63
+ await this.onBound?.(environment);
64
+ return environment;
65
+ })
66
+ .catch((error) => {
67
+ this.#bindings.delete(canonicalRoot);
68
+ throw error;
57
69
  });
58
70
  this.#bindings.set(canonicalRoot, binding);
59
71
  }
@@ -0,0 +1,5 @@
1
+ /** Public extension seam. The version denotes this shape, not a specific consumer. */
2
+ export const INTEGRATION_CONTRACT_VERSION = 'dsh-data-analysis-integration/v1';
3
+ export { withDatasourceDefaults } from "./datasource/defaults.js";
4
+ export { applyWithIntegration } from "./plugin.js";
5
+ export { registerPluginRpc } from "./rpc.js";
package/lib/plugin.js CHANGED
@@ -70,6 +70,10 @@ function configuredProjectRoot(config, agent) {
70
70
  }
71
71
  /** Ensure the shared Runtime once, mount its skills, then bind each Workspace lazily. */
72
72
  export async function apply(ctx, config = {}) {
73
+ return applyWithIntegration(ctx, config);
74
+ }
75
+ /** Compose an extension at the public seam while retaining the ordinary plugin behavior. */
76
+ export async function applyWithIntegration(ctx, config = {}, integration = {}) {
73
77
  const publishingConfig = resolvePublishingConfig(config.reportPublishing);
74
78
  const pythonOptions = currentPythonOptions(config);
75
79
  const pythonExecutable = config.pythonExecutable ?? process.env.DSH_DATA_ANALYSIS_PYTHON;
@@ -82,7 +86,7 @@ export async function apply(ctx, config = {}) {
82
86
  ...(config.installTimeoutMs === undefined ? {} : { installTimeoutMs: config.installTimeoutMs }),
83
87
  });
84
88
  const disposeRuntimeShellEnvironment = registerMarivoRuntimeShellEnvironment(ctx, runtime.pythonExecutable);
85
- const manager = new MarivoWorkspaceEnvironmentManager(runtime);
89
+ const manager = new MarivoWorkspaceEnvironmentManager(runtime, integration.onWorkspaceBound);
86
90
  const bindings = new WeakMap();
87
91
  const resolveEnvironment = (agent) => {
88
92
  const root = configuredProjectRoot(config, agent);
@@ -93,7 +97,7 @@ export async function apply(ctx, config = {}) {
93
97
  bindings.set(agent, { root, environment });
94
98
  return environment;
95
99
  };
96
- const credentialService = new MarivoCredentialService(ctx.credentials, config.credentialInteraction);
100
+ const credentialService = new MarivoCredentialService(integration.datasourceCredentials ?? ctx.credentials, config.credentialInteraction);
97
101
  const credentialNotifications = new CredentialChangesService(ctx, credentialService);
98
102
  let unregisterChanges;
99
103
  const disposeChanges = async () => {
@@ -188,7 +192,7 @@ export async function apply(ctx, config = {}) {
188
192
  root)
189
193
  throw new Error('Workspace changed');
190
194
  return new MarivoDatasourceBridge(environment);
191
- }, config.datasourceDefaults);
195
+ }, config.datasourceDefaults, integration.managedCredentialDefaults);
192
196
  let lastDiagnostic = -Infinity;
193
197
  const usage = new SemanticReferenceUsage(ctx.storageDomain, Date.now, () => {
194
198
  if (Date.now() - lastDiagnostic >= 30_000) {
@@ -3,6 +3,7 @@ import { installRightTabs } from './client/right-tabs/install.tsx';
3
3
  export { marivoPresentationDeliveryDefinition, parsePresentationDurableContent, presentationDeliveryFromEvent, presentationsForNode, } from './client/presentation/delivery.ts';
4
4
  export { PresentationDeliveryModel } from './client/presentation/delivery-model.ts';
5
5
  export { HostPresentationReader } from './client/presentation/host-entry.tsx';
6
+ export { createPluginRpc } from './client/rpc.ts';
6
7
  export declare const inject: string[];
7
8
  export declare function apply(ctx: Context, options?: {
8
9
  diagnostics?: boolean;
@@ -12,6 +12,7 @@ export interface DshDataAnalysisCompatibility {
12
12
  readonly contracts: {
13
13
  readonly runtimeInstallation: 'dsh-data-analysis-runtime/v3';
14
14
  readonly subprocessPolicy: 'direct-argv-inherited-env-snapshot-overlay-v2';
15
+ readonly integration: 'dsh-data-analysis-integration/v1';
15
16
  };
16
17
  }
17
18
  /** The package semver and the compatibility contract shipped in this exact installation. */
@@ -1,7 +1,8 @@
1
1
  import type { DatasourceAuthoring } from './authoring.ts';
2
2
  export type DatasourceDefaults = Record<string, Record<string, unknown>>;
3
+ export type ManagedCredentialDefaults = Record<string, Record<string, string>>;
3
4
  export type DatasourceAuthoringView = DatasourceAuthoring & {
4
5
  creationDefaults?: DatasourceDefaults;
5
6
  };
6
7
  /** Validate against this Workspace's live Runtime; never include config values in errors. */
7
- export declare function withDatasourceDefaults(schema: DatasourceAuthoring, configured: unknown): DatasourceAuthoringView;
8
+ export declare function withDatasourceDefaults(schema: DatasourceAuthoring, configured: unknown, managed?: ManagedCredentialDefaults): DatasourceAuthoringView;
@@ -1,5 +1,5 @@
1
1
  import type { HostConnectionHandle } from '@deepseek-ai/dsh-client-connection';
2
2
  import type { MarivoDatasourceBridgePort } from './bridge.ts';
3
- import { type DatasourceDefaults } from './defaults.ts';
3
+ import { type DatasourceDefaults, type ManagedCredentialDefaults } from './defaults.ts';
4
4
  import { type MarivoCredentialService } from './service.ts';
5
- export declare function registerCredentialRpc(connection: HostConnectionHandle, service: MarivoCredentialService, workspace: (id: string) => Promise<MarivoDatasourceBridgePort>, datasourceDefaults?: DatasourceDefaults): () => Promise<void>;
5
+ export declare function registerCredentialRpc(connection: HostConnectionHandle, service: MarivoCredentialService, workspace: (id: string) => Promise<MarivoDatasourceBridgePort>, datasourceDefaults?: DatasourceDefaults, managedCredentialDefaults?: ManagedCredentialDefaults): () => Promise<void>;
@@ -1,4 +1,4 @@
1
- export type EnvironmentFailureCode = 'project-root-invalid' | 'python-path-relative' | 'python-unavailable' | 'shared-runtime-config-invalid' | 'shared-runtime-lock-timeout' | 'shared-runtime-install-failed' | 'shared-runtime-identity-mismatch' | 'shared-runtime-version-unsupported' | 'shared-runtime-pandas-unsupported' | 'shared-runtime-presentation-kit-unsupported' | 'shared-runtime-presentation-kit-wheel-invalid' | 'shared-runtime-presentation-kit-wheel-unavailable' | 'shared-runtime-package-unavailable' | 'shared-runtime-skills-invalid' | 'subprocess-start-failed' | 'subprocess-timeout' | 'subprocess-cancelled' | 'subprocess-output-limit' | 'subprocess-output-invalid' | 'subprocess-failed' | 'datasource-credential-ref-invalid' | 'datasource-credential-resolve-failed' | 'shell-credential-lease-invalid' | 'shell-credential-lease-expired' | 'shell-credential-lease-exhausted' | 'shell-credential-lease-scope-mismatch' | 'shell-credential-lease-resolve-failed' | 'shell-credential-injection-unsupported' | 'doctor-json-invalid' | 'doctor-admission-failed' | 'binding-identity-mismatch' | 'binding-failed';
1
+ export type EnvironmentFailureCode = 'project-root-invalid' | 'python-path-relative' | 'python-unavailable' | 'shared-runtime-config-invalid' | 'shared-runtime-installation-required' | 'shared-runtime-lock-timeout' | 'shared-runtime-install-failed' | 'shared-runtime-identity-mismatch' | 'shared-runtime-version-unsupported' | 'shared-runtime-pandas-unsupported' | 'shared-runtime-presentation-kit-unsupported' | 'shared-runtime-presentation-kit-wheel-invalid' | 'shared-runtime-presentation-kit-wheel-unavailable' | 'shared-runtime-package-unavailable' | 'shared-runtime-skills-invalid' | 'subprocess-start-failed' | 'subprocess-timeout' | 'subprocess-cancelled' | 'subprocess-output-limit' | 'subprocess-output-invalid' | 'subprocess-failed' | 'datasource-credential-ref-invalid' | 'datasource-credential-resolve-failed' | 'shell-credential-lease-invalid' | 'shell-credential-lease-expired' | 'shell-credential-lease-exhausted' | 'shell-credential-lease-scope-mismatch' | 'shell-credential-lease-resolve-failed' | 'shell-credential-injection-unsupported' | 'doctor-json-invalid' | 'doctor-admission-failed' | 'binding-identity-mismatch' | 'binding-failed';
2
2
  /** Stable failure envelope for config, subprocess, doctor, and identity errors. */
3
3
  export declare class MarivoEnvironmentError extends Error {
4
4
  readonly code: EnvironmentFailureCode;
@@ -7,6 +7,8 @@ export declare const PRESENTATION_KIT_PANDAS_RANGE = ">=2.2.0,<3.0.0";
7
7
  export declare const PRESENTATION_KIT_WHEEL_FILENAME = "dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl";
8
8
  export declare const DEFAULT_SHARED_RUNTIME_INSTALL_TIMEOUT_MS = 600000;
9
9
  interface RuntimeInstallOptions {
10
+ /** Validate an existing installation without creating directories or acquiring an install lock. */
11
+ existingOnly?: boolean;
10
12
  environment?: NodeJS.ProcessEnv;
11
13
  waitIntervalMs?: number;
12
14
  /** Test/build seam; production always resolves the wheel distributed beside the plugin. */
@@ -4,7 +4,8 @@ import type { SharedMarivoRuntime } from './types.ts';
4
4
  export declare class MarivoWorkspaceEnvironmentManager {
5
5
  #private;
6
6
  readonly runtime: SharedMarivoRuntime;
7
- constructor(runtime: SharedMarivoRuntime);
7
+ readonly onBound?: (environment: MarivoEnvironment) => Promise<void>;
8
+ constructor(runtime: SharedMarivoRuntime, onBound?: (environment: MarivoEnvironment) => Promise<void>);
8
9
  resolve(projectRoot: string): Promise<MarivoEnvironment>;
9
10
  close(): Promise<void>;
10
11
  dispose(): void;
@@ -0,0 +1,16 @@
1
+ import type { ManagedCredentialDefaults } from './datasource/defaults.ts';
2
+ import type { CredentialStore } from './datasource/service.ts';
3
+ import type { MarivoEnvironment } from './environment/index.ts';
4
+ /** Public extension seam. The version denotes this shape, not a specific consumer. */
5
+ export declare const INTEGRATION_CONTRACT_VERSION: "dsh-data-analysis-integration/v1";
6
+ export interface MarivoIntegrationV1 {
7
+ /** Runs once after a Workspace binds, before its environment is returned. */
8
+ readonly onWorkspaceBound?: (environment: MarivoEnvironment) => Promise<void>;
9
+ /** Harness-managed store used only by datasource operations. */
10
+ readonly datasourceCredentials?: CredentialStore;
11
+ /** Credential reference names, validated against the live Workspace Runtime schema. */
12
+ readonly managedCredentialDefaults?: ManagedCredentialDefaults;
13
+ }
14
+ export { withDatasourceDefaults } from './datasource/defaults.ts';
15
+ export { applyWithIntegration } from './plugin.ts';
16
+ export { registerPluginRpc } from './rpc.ts';
@@ -5,6 +5,7 @@ export { resolvePresentationWorkspace } from './workspace-identity.ts';
5
5
  import type { Context } from '@deepseek-ai/cordis';
6
6
  import z from '@deepseek-ai/schemastery';
7
7
  import type { DatasourceDefaults } from './datasource/defaults.ts';
8
+ import type { MarivoIntegrationV1 } from './integration.ts';
8
9
  export { MARIVO_DATASOURCE_CREDENTIAL_PROMPT } from './disclosure/execution-guidance.ts';
9
10
  /** Cordis plugin name used by loader diagnostics and lifecycle logs. */
10
11
  export declare const name = "dsh-data-analysis";
@@ -51,3 +52,5 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
51
52
  }>>, "plain">;
52
53
  /** Ensure the shared Runtime once, mount its skills, then bind each Workspace lazily. */
53
54
  export declare function apply(ctx: Context, config?: Config): Promise<() => Promise<void>>;
55
+ /** Compose an extension at the public seam while retaining the ordinary plugin behavior. */
56
+ export declare function applyWithIntegration(ctx: Context, config?: Config, integration?: MarivoIntegrationV1): Promise<() => Promise<void>>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chengxianglibra/dsh-data-analysis",
3
3
  "description": "Marivo runtime, live Help, secure datasource execution and presentation delivery for DeepSeek Harness",
4
- "version": "0.2.2",
4
+ "version": "0.2.3",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/chengxianglibra/dsh-data-analysis.git",
@@ -31,6 +31,14 @@
31
31
  "types": "./lib/types/client.d.ts",
32
32
  "default": "./lib/client.js"
33
33
  },
34
+ "./client-composition": {
35
+ "types": "./lib/types/client.d.ts",
36
+ "default": "./lib/client-composition.js"
37
+ },
38
+ "./integration": {
39
+ "types": "./lib/types/integration.d.ts",
40
+ "default": "./lib/integration.js"
41
+ },
34
42
  "./environment": {
35
43
  "types": "./lib/types/environment/index.d.ts",
36
44
  "default": "./lib/environment/index.js"
@@ -82,7 +90,8 @@
82
90
  },
83
91
  "contracts": {
84
92
  "runtimeInstallation": "dsh-data-analysis-runtime/v3",
85
- "subprocessPolicy": "direct-argv-inherited-env-snapshot-overlay-v2"
93
+ "subprocessPolicy": "direct-argv-inherited-env-snapshot-overlay-v2",
94
+ "integration": "dsh-data-analysis-integration/v1"
86
95
  }
87
96
  },
88
97
  "dsh": {