@sparkelf/dsh-dataops-managed 0.3.3 → 0.3.4

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.
@@ -0,0 +1,64 @@
1
+ /** Model configuration one workspace publishes and another adopts. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ /** Profile entry id whose Config holds the model providers. */
4
+ export declare const MODEL_SETTINGS_NAMESPACE = "llm-pi-ai";
5
+ /** One provider profile as the settings document holds it. */
6
+ type ProviderProfile = Record<string, unknown>;
7
+ /** Model configuration read from, or written to, the local settings document. */
8
+ export interface ModelSettingsSnapshot {
9
+ /** Providers keyed by provider id. */
10
+ providers: Record<string, ProviderProfile>;
11
+ /** Revision the read observed; a write must present it back. */
12
+ revision: number | undefined;
13
+ }
14
+ /**
15
+ * Read the models this workspace currently holds.
16
+ *
17
+ * A missing section is an empty result rather than an error: a fresh workspace has never
18
+ * opened the models page, and that is the normal state for the first user to arrive.
19
+ * @param ctx - DSH Host context carrying the settings service.
20
+ * @returns Provider profiles and the revision the read observed.
21
+ */
22
+ export declare function readModels(ctx: Context): ModelSettingsSnapshot;
23
+ /**
24
+ * Collect every model id a workspace holds, grouped by provider.
25
+ * @param providers - Provider profiles to walk.
26
+ * @returns Model ids offered by each provider.
27
+ */
28
+ export declare function modelIdsByProvider(providers: Record<string, ProviderProfile>): Record<string, string[]>;
29
+ /**
30
+ * Narrow published providers to the models their publisher offers.
31
+ *
32
+ * The publisher decides which of its models other users may use; a model it kept private is
33
+ * dropped here, so it is never written into a reader's settings at all.
34
+ * @param providers - Published provider profiles.
35
+ * @param sharedModelIds - Model ids the publisher offers.
36
+ * @returns Providers holding only the offered models.
37
+ */
38
+ export declare function selectSharedModels(providers: Record<string, ProviderProfile>, sharedModelIds: readonly string[]): Record<string, ProviderProfile>;
39
+ /**
40
+ * Merge adopted provider profiles into the ones a workspace already holds.
41
+ *
42
+ * A provider the user already has keeps its own models and gains the adopted ones that are
43
+ * missing, so adopting never removes a model the user configured. The user's own entry for a
44
+ * model wins on conflict: that is what keeps a local edit from being overwritten.
45
+ * @param local - Providers the workspace holds now.
46
+ * @param adopted - Providers the publisher offers.
47
+ * @returns Providers to write, and whether anything changed.
48
+ */
49
+ export declare function mergeProviders(local: Record<string, ProviderProfile>, adopted: Record<string, ProviderProfile>): {
50
+ providers: Record<string, ProviderProfile>;
51
+ changed: boolean;
52
+ };
53
+ /**
54
+ * Write provider profiles into this workspace's settings.
55
+ *
56
+ * The write presents the revision the read observed. A settings service that has moved on
57
+ * refuses it with its own conflict error, which the caller surfaces rather than retrying:
58
+ * silently overwriting a concurrent edit is exactly what this feature must not do.
59
+ * @param ctx - DSH Host context carrying the settings service.
60
+ * @param providers - Providers to store.
61
+ * @param revision - Revision from the read this write is based on.
62
+ */
63
+ export declare function writeModels(ctx: Context, providers: Record<string, ProviderProfile>, revision: number | undefined): Promise<void>;
64
+ export {};
@@ -0,0 +1,145 @@
1
+ /** Adopt, publish, and stop following the model configuration another workspace offers. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ /** This plugin's own profile entry id, which owns the sync state. */
4
+ export declare const SYNC_NAMESPACE = "dataops-managed";
5
+ /** Whether this workspace follows the publisher, or keeps what its user wrote. */
6
+ export type FollowState = 'following' | 'detached';
7
+ /** What this workspace remembers between runs. */
8
+ export interface SyncState {
9
+ /** The user here chose their own models, so adoption stops for them. */
10
+ detached: boolean;
11
+ /** Model ids adoption last wrote, so a later edit can be told apart from one of them. */
12
+ adoptedModelIds: string[];
13
+ /** Model ids the administrator keeps private; every other model is offered by default. */
14
+ privateModelIds: string[];
15
+ }
16
+ /** Read and write this workspace's sync state. */
17
+ export interface SyncStateStore {
18
+ /** @returns The stored state, or defaults before anything was stored. */
19
+ read(): SyncState;
20
+ /** @param next - State to store. */
21
+ write(next: SyncState): Promise<void>;
22
+ }
23
+ /** Configuration the host half receives from the profile. */
24
+ export interface SyncConfig {
25
+ /** DataOps browser/API origin reachable from the DSH Host. */
26
+ baseUrl: string;
27
+ /** DSH credential reference holding the current DataOps access JWT. */
28
+ credentialRef: string;
29
+ }
30
+ /** What the settings UI reads to describe the current state. */
31
+ export interface SyncStatus {
32
+ /** Whether this workspace currently follows a publisher. */
33
+ followState: FollowState;
34
+ /** Whether an administrator currently offers models to this workspace. */
35
+ publisherSharing: boolean;
36
+ /** How many models this workspace adopts from the publisher. */
37
+ adoptedCount: number;
38
+ /** Model ids the administrator keeps private. */
39
+ privateModelIds: string[];
40
+ /** Publication time reported by the publisher, when one is sharing. */
41
+ publishedAt: string | null;
42
+ /** Whether the current user may change what this workspace shares. */
43
+ canPublish: boolean;
44
+ /** Models this workspace holds, and whether each is offered to other users. */
45
+ models: {
46
+ id: string;
47
+ shared: boolean;
48
+ }[];
49
+ }
50
+ /**
51
+ * Own the model-sync state one workspace keeps.
52
+ *
53
+ * The state lives in this workspace rather than in DataOps, because whether a user has written
54
+ * their own models is a fact about this workspace. Keeping it here is also what makes the
55
+ * promise hold across restarts: a user who chose their own models is not adopted again.
56
+ */
57
+ export declare class ModelSync {
58
+ private readonly ctx;
59
+ private readonly config;
60
+ private readonly store;
61
+ constructor(ctx: Context, config: SyncConfig, store: SyncStateStore);
62
+ /**
63
+ * Read the DataOps JWT this workspace is currently authorized with.
64
+ * @returns The token, or undefined when the workspace has no session yet.
65
+ */
66
+ private token;
67
+ /** The DataOps API origin this workspace reports to. */
68
+ private apiBase;
69
+ /**
70
+ * Fetch the publication this workspace may adopt.
71
+ * @returns The published snapshot, or undefined when the workspace is not authorized.
72
+ */
73
+ private fetchPublished;
74
+ /**
75
+ * The models this workspace offers to others.
76
+ *
77
+ * Every model is offered unless the administrator marked it private, which is what makes a
78
+ * newly added model shared without an extra step.
79
+ * @param providers - Providers this workspace holds.
80
+ * @param privateModelIds - Model ids kept private.
81
+ * @returns Model ids to offer.
82
+ */
83
+ private offeredModelIds;
84
+ /**
85
+ * Report this workspace's models to DataOps as a publication.
86
+ *
87
+ * Called when an administrator turns sharing on, or edits their models while it is on. The
88
+ * workspace stays the owner of the configuration; DataOps stores only this copy.
89
+ * @param sharingEnabled - Whether sharing is on.
90
+ */
91
+ publish(sharingEnabled: boolean): Promise<void>;
92
+ /**
93
+ * Read the current user's own publication state and whether they may change it.
94
+ *
95
+ * The permission rule lives in DataOps; the browser only displays what this reports, so
96
+ * nothing in the page decides who is an administrator.
97
+ * @returns The state, or null when the workspace is not authorized.
98
+ */
99
+ readOwnState(): Promise<{
100
+ sharingEnabled: boolean;
101
+ canPublish: boolean;
102
+ } | null>;
103
+ /**
104
+ * Record which models the administrator keeps private.
105
+ * @param privateModelIds - Model ids not offered to other users.
106
+ * @param sharingEnabled - Whether sharing is on, so the change reaches readers now.
107
+ */
108
+ setPrivateModels(privateModelIds: readonly string[], sharingEnabled: boolean): Promise<void>;
109
+ /**
110
+ * Adopt the published models into this workspace.
111
+ *
112
+ * Does nothing when the user here writes their own models, which is what keeps a local edit
113
+ * from being replaced by the publisher's version. Otherwise it merges: models the workspace
114
+ * lacks are added, and a model it already holds is left exactly as it is.
115
+ * @returns Adopted provider profiles, or null when nothing was adopted.
116
+ */
117
+ adopt(): Promise<Record<string, Record<string, unknown>> | null>;
118
+ /**
119
+ * Whether this workspace holds models adoption did not put there.
120
+ *
121
+ * A model the workspace has now and adoption did not write is the user's own, so adopting
122
+ * again would discard their work. An empty record means adoption never ran here, and the
123
+ * first pass must not read the workspace's existing models as an edit.
124
+ * @param current - Providers the workspace holds now.
125
+ * @param adoptedModelIds - Model ids adoption last wrote.
126
+ * @returns True when the workspace holds something adoption did not write.
127
+ */
128
+ private editedSinceAdoption;
129
+ /**
130
+ * Stop following the publisher and keep what this workspace holds now.
131
+ *
132
+ * A user who chose their own models must not be pulled back, so this choice is stored and
133
+ * survives the next start.
134
+ */
135
+ detach(): Promise<void>;
136
+ /**
137
+ * Follow the publisher again, adopting its models on the next pass.
138
+ */
139
+ resumeFollowing(): Promise<void>;
140
+ /**
141
+ * Describe the current state for the settings UI.
142
+ * @returns The sync state, whether the viewer may publish, and their own models.
143
+ */
144
+ status(): Promise<SyncStatus>;
145
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sparkelf/dsh-dataops-managed",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "DataOps JWT intake and credential-backed MCP tools for managed DeepSeek Harness workspaces.",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -42,6 +42,11 @@
42
42
  "README.md",
43
43
  "LICENSE"
44
44
  ],
45
+ "scripts": {
46
+ "build": "rm -rf lib && tsc -p tsconfig.build.json && tsdown",
47
+ "bundle": "tsdown",
48
+ "prepack": "pnpm run build"
49
+ },
45
50
  "engines": {
46
51
  "node": "^22.19.0 || >=24.0.0"
47
52
  },
@@ -56,41 +61,39 @@
56
61
  },
57
62
  "peerDependencies": {
58
63
  "@deepseek-ai/cordis": "^4.0.4",
59
- "@deepseek-ai/dsh-credentials": "0.1.7-rc.2",
60
- "@deepseek-ai/dsh-host-webserver": "0.1.7-rc.2",
61
64
  "@deepseek-ai/dsh-client-locale": "0.1.7-rc.2",
65
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.2",
62
66
  "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.2",
67
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.2",
63
68
  "@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.2",
69
+ "@deepseek-ai/dsh-client-ui-sidebar": "0.1.7-rc.2",
64
70
  "@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.2",
71
+ "@deepseek-ai/dsh-credentials": "0.1.7-rc.2",
72
+ "@deepseek-ai/dsh-host-webserver": "0.1.7-rc.2",
73
+ "@deepseek-ai/dsh-settings": "0.1.7-rc.2",
65
74
  "@deepseek-ai/dsh-tools": "0.1.7-rc.2",
66
75
  "@deepseek-ai/schemastery": ">=3.18.1",
67
76
  "@sparkelf/dsh-plugin-mcp-credentials": ">=0.1.0-rc.14",
68
- "react": ">=18.2.0 <20",
69
- "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.2",
70
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.2",
71
- "@deepseek-ai/dsh-client-ui-sidebar": "0.1.7-rc.2"
77
+ "react": ">=18.2.0 <20"
72
78
  },
73
79
  "devDependencies": {
74
80
  "@deepseek-ai/cordis": "4.0.4",
75
- "@deepseek-ai/dsh-credentials": "0.1.7-rc.2",
76
- "@deepseek-ai/dsh-host-webserver": "0.1.7-rc.2",
77
81
  "@deepseek-ai/dsh-client-locale": "0.1.7-rc.2",
82
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.2",
78
83
  "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.2",
84
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.2",
79
85
  "@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.2",
86
+ "@deepseek-ai/dsh-client-ui-sidebar": "0.1.7-rc.2",
80
87
  "@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.2",
88
+ "@deepseek-ai/dsh-credentials": "0.1.7-rc.2",
89
+ "@deepseek-ai/dsh-host-webserver": "0.1.7-rc.2",
90
+ "@deepseek-ai/dsh-settings": "0.1.7-rc.2",
81
91
  "@deepseek-ai/dsh-tools": "0.1.7-rc.2",
82
92
  "@deepseek-ai/schemastery": "3.18.2",
83
93
  "@sparkelf/dsh-plugin-mcp-credentials": "0.1.0-rc.14",
84
94
  "@types/react": "~18.3.1",
85
95
  "lightningcss": "^1.32.0",
86
96
  "react": "^18.2.0",
87
- "tsdown": "^0.22.2",
88
- "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.2",
89
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.2",
90
- "@deepseek-ai/dsh-client-ui-sidebar": "0.1.7-rc.2"
91
- },
92
- "scripts": {
93
- "build": "rm -rf lib && tsc -p tsconfig.build.json && tsdown",
94
- "bundle": "tsdown"
97
+ "tsdown": "^0.22.2"
95
98
  }
96
- }
99
+ }