@khorsheed/dsh-local-agent-dsh 0.2.0-rc.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.
- package/CHANGELOG.md +16 -0
- package/README.en.md +23 -136
- package/README.i18n.yaml +2 -2
- package/README.md +23 -136
- package/lib/client.js +155 -83
- package/lib/{dsh-cli-provider-UhWvivte.js → dsh-cli-provider-B7s3zH0m.js} +108 -27
- package/lib/dsh-cli-provider-DYRuRpVz.js +1920 -0
- package/lib/dsh-cli-provider.js +1 -1
- package/lib/index.js +40 -27
- package/lib/provision.js +327 -152
- package/lib/types/client/SettingsCard.d.ts +41 -13
- package/lib/types/client/SettingsCard.js +22 -6
- package/lib/types/client/icons.d.ts +1 -1
- package/lib/types/client/index.d.ts +5 -27
- package/lib/types/client/index.js +87 -44
- package/lib/types/client/locales.js +2 -2
- package/lib/types/dsh-cli-provider.js +82 -47
- package/lib/types/index.d.ts +9 -1
- package/lib/types/index.js +35 -21
- package/lib/types/live-driver.js +72 -54
- package/lib/types/model-catalog.d.ts +1 -0
- package/lib/types/model-catalog.js +9 -4
- package/lib/types/model-launch.d.ts +14 -0
- package/lib/types/model-launch.js +58 -0
- package/lib/types/provision.d.ts +166 -119
- package/lib/types/provision.js +376 -166
- package/lib/types/session-mirror.d.ts +55 -0
- package/lib/types/session-mirror.js +155 -1
- package/locale/en.json +2 -2
- package/locale/zh.json +2 -2
- package/package.json +27 -25
- package/lib/invariant.js +0 -33
- package/lib/types/invariant.d.ts +0 -16
- package/lib/types/invariant.js +0 -37
package/lib/types/provision.d.ts
CHANGED
|
@@ -5,29 +5,38 @@
|
|
|
5
5
|
* `<scoped home>/profiles/<name>` — a manifest listing the official
|
|
6
6
|
* `@deepseek-ai/dsh-base` layer, the family headless composition as the
|
|
7
7
|
* profile's own patch layer (copied verbatim from the headless bundle's
|
|
8
|
-
* `cordis.patch.yml`), and
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* `cordis.patch.yml`), and `@khorsheed/dsh-local-agent-dsh-headless` in
|
|
9
|
+
* the sub-profile's node_modules (the loader resolves the patch's insert
|
|
10
|
+
* rows through it) — a copy of the bundle for the host profile, a symlink
|
|
11
|
+
* for the `-unit` twin and for the pinned single-profile form (see
|
|
12
|
+
* `HeadlessBundleMount`).
|
|
11
13
|
* Everything else the boot needs (dsh-base and its whole dependency graph,
|
|
12
14
|
* cordis, the healed `profiles/node_modules` fallback) is resolved from the
|
|
13
15
|
* dsh installation anchor automatically, so provisioning costs no pnpm
|
|
14
16
|
* install.
|
|
15
17
|
*
|
|
16
|
-
* A sub-profile may additionally
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
18
|
+
* A sub-profile may additionally compose an AGENT PRESET (host 0.2.0's
|
|
19
|
+
* declarative form): the bundle package that declares the preset — an
|
|
20
|
+
* `@deepseek-ai/dsh-agent-preset` row in its own bundle patch — joins the
|
|
21
|
+
* manifest's bundle list, and one appended patch layer inserts
|
|
22
|
+
* `@deepseek-ai/dsh-agent-preset-registry` with that preset as its
|
|
23
|
+
* `default`. Without it the sub-dsh's model-facing rows come from the host
|
|
24
|
+
* plane and the agent reads them off the global layer — which is why "the
|
|
25
|
+
* same harness under two presets" was not a thing a condition could ask for.
|
|
26
|
+
* With it, the scope directory IS the capability face: two scopes naming two
|
|
27
|
+
* presets are two subjects, and the difference is files a person can read.
|
|
23
28
|
*
|
|
24
|
-
* Where the preset
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
29
|
+
* Where the preset PACKAGE lives is the scope's business too. The scope keeps
|
|
30
|
+
* its own copy at `<scoped home>/preset-packages/<id>` and the sub-profile
|
|
31
|
+
* resolves it through a RELATIVE symlink in its own `node_modules`, so the
|
|
32
|
+
* package is found identically on the host and inside an evaluation unit
|
|
33
|
+
* (which bind-mounts the scope, and nothing else). The copy comes from the
|
|
34
|
+
* evaluation instance's own installation of the same package, which is also
|
|
35
|
+
* what the instance's capability catalog measures. `provisionDshScope` below
|
|
36
|
+
* is the entry that makes the copy, records what the scope composes in a
|
|
37
|
+
* file of its own, and composes it. (0.1.x wrote a roster row for
|
|
38
|
+
* `@deepseek-ai/dsh-agent-presets` and a `<scoped home>/.agent-presets/<id>`
|
|
39
|
+
* directory instead; 0.2.0 ships neither the roster nor the directory scan.)
|
|
31
40
|
*
|
|
32
41
|
* It may also carry a PERMISSION BOUNDARY: one appended patch layer pinning
|
|
33
42
|
* `sandbox-policy`'s mode and `user-approval`'s policy to one of dsh's own
|
|
@@ -36,7 +45,7 @@
|
|
|
36
45
|
* sub-dsh on a developer's machine and the wrong one inside an evaluation
|
|
37
46
|
* unit, where the container IS the boundary and nobody is there to answer an
|
|
38
47
|
* approval prompt. The layer is a FILE in the scope directory for the same
|
|
39
|
-
* reason the
|
|
48
|
+
* reason the preset layer is: a scoped home bind-mounted into a unit carries its
|
|
40
49
|
* own boundary with it, and the value never has to ride the spawn env (where
|
|
41
50
|
* every name enters the unit's composite fingerprint) or be baked into an
|
|
42
51
|
* image.
|
|
@@ -52,31 +61,22 @@
|
|
|
52
61
|
*/
|
|
53
62
|
/** Default name of the sub-dsh profile under the scoped home. */
|
|
54
63
|
export declare const DEFAULT_SUB_PROFILE_NAME = "headless-local-agent-dsh";
|
|
55
|
-
/** One preset root the sub-profile's roster scans. */
|
|
56
|
-
export interface DshSubProfilePresetRoot {
|
|
57
|
-
/** Directory holding preset sub-directories; a leading `~` is expanded by the roster. */
|
|
58
|
-
path: string;
|
|
59
|
-
/** Trust level; the roster defaults it to `user`. */
|
|
60
|
-
trust?: 'system' | 'user';
|
|
61
|
-
}
|
|
62
64
|
/**
|
|
63
|
-
* The preset
|
|
65
|
+
* The agent preset a sub-profile composes.
|
|
64
66
|
*
|
|
65
|
-
* `id` is the preset every sub-dsh session of this scope
|
|
66
|
-
*
|
|
67
|
-
* `@deepseek-ai/dsh-agent-
|
|
68
|
-
*
|
|
69
|
-
*
|
|
67
|
+
* `id` is the preset every sub-dsh session of this scope joins — the
|
|
68
|
+
* registry row's `default`. `package` is the bundle package that DECLARES it
|
|
69
|
+
* (an `@deepseek-ai/dsh-agent-preset` row in its bundle patch): it joins the
|
|
70
|
+
* sub-profile's bundle list and resolves from the sub-profile's own
|
|
71
|
+
* `node_modules`, where provisioning links the scope's copy of it. Absent
|
|
72
|
+
* `package` writes the registry row alone, for an id the sub-dsh's own
|
|
73
|
+
* installation already declares.
|
|
70
74
|
*/
|
|
71
75
|
export interface DshSubProfilePreset {
|
|
72
|
-
/** The preset id the sub-dsh composes (`[a-z0-9][a-z0-9-]
|
|
76
|
+
/** The preset id the sub-dsh composes (`[a-z0-9][a-z0-9-]*`). */
|
|
73
77
|
id: string;
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
-
/** Keep the roster's bundled presets (default true, the roster's own default). */
|
|
77
|
-
includeShippedRoot?: boolean;
|
|
78
|
-
/** Keep `<scoped home>/.agent-presets` (default true, the roster's own default). */
|
|
79
|
-
includeUserRoot?: boolean;
|
|
78
|
+
/** The bundle package declaring that preset. */
|
|
79
|
+
package?: string;
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
82
|
* A sub-dsh permission preset: dsh's own three-word vocabulary, spelled the
|
|
@@ -87,6 +87,8 @@ export interface DshSubProfilePreset {
|
|
|
87
87
|
export type DshSubProfilePermissions = 'read-only' | 'workspace-write' | 'danger-full-access';
|
|
88
88
|
/** Config the provisioning step reads. */
|
|
89
89
|
export interface DshSubProfileConfig {
|
|
90
|
+
/** Local launches only: read a per-process model snapshot from the private launch environment. */
|
|
91
|
+
inheritModelConfiguration?: boolean;
|
|
90
92
|
/** Sub-dsh profile name under the scoped home. */
|
|
91
93
|
profileName?: string;
|
|
92
94
|
/**
|
|
@@ -96,9 +98,19 @@ export interface DshSubProfileConfig {
|
|
|
96
98
|
*/
|
|
97
99
|
headlessBundleDir?: string;
|
|
98
100
|
/**
|
|
99
|
-
*
|
|
101
|
+
* The headless bundle directory as an evaluation UNIT sees it (the image's
|
|
102
|
+
* own install, `/opt/dsh-headless/node_modules/@khorsheed/dsh-local-agent-dsh-headless`
|
|
103
|
+
* on the dataset image). Present, provisioning writes a second sub-profile,
|
|
104
|
+
* `<profileName>-unit`, identical but for that symlink target, and
|
|
105
|
+
* container rounds launch it — so the host profile can link the bundle THIS
|
|
106
|
+
* instance resolves (its own host line) while the unit keeps the image's.
|
|
107
|
+
* Absent, both kinds of round share one profile, as before this existed.
|
|
108
|
+
*/
|
|
109
|
+
unitHeadlessBundleDir?: string;
|
|
110
|
+
/**
|
|
111
|
+
* Compose an agent preset into the sub-profile. Absent leaves the
|
|
100
112
|
* sub-profile exactly as every scope had it before this field existed: no
|
|
101
|
-
*
|
|
113
|
+
* registry row, and the agent reading the global layer.
|
|
102
114
|
*/
|
|
103
115
|
preset?: DshSubProfilePreset;
|
|
104
116
|
/**
|
|
@@ -110,22 +122,23 @@ export interface DshSubProfileConfig {
|
|
|
110
122
|
permissions?: DshSubProfilePermissions;
|
|
111
123
|
}
|
|
112
124
|
/**
|
|
113
|
-
* The
|
|
125
|
+
* The registry package the registry row names.
|
|
114
126
|
*
|
|
115
127
|
* Deliberately NOT symlinked into the sub-profile the way the headless bundle
|
|
116
128
|
* is. The headless bundle is a `@khorsheed` package the dsh installation does
|
|
117
|
-
* not carry, so it must be linked in from the plugin installation; the
|
|
118
|
-
* is an OFFICIAL package, already in the installation anchor's
|
|
119
|
-
* `@deepseek-ai/dsh-base`. Linking a second copy would give it
|
|
120
|
-
* `@deepseek-ai/cordis` — and cordis does service lookup and type
|
|
121
|
-
* instance identity, so the symptom would be silently missing
|
|
122
|
-
* than an error
|
|
123
|
-
*
|
|
124
|
-
* roster gets the loader's own "cannot resolve" message, which names the
|
|
129
|
+
* not carry, so it must be linked in from the plugin installation; the
|
|
130
|
+
* registry is an OFFICIAL package, already in the installation anchor's
|
|
131
|
+
* closure beside `@deepseek-ai/dsh-base`. Linking a second copy would give it
|
|
132
|
+
* a second `@deepseek-ai/cordis` — and cordis does service lookup and type
|
|
133
|
+
* checks by instance identity, so the symptom would be silently missing
|
|
134
|
+
* services rather than an error. A deployment whose anchor genuinely lacks the
|
|
135
|
+
* registry gets the loader's own "cannot resolve" message, which names the
|
|
125
136
|
* module better than provisioning could.
|
|
126
137
|
*/
|
|
127
|
-
export declare const
|
|
128
|
-
/**
|
|
138
|
+
export declare const PRESET_REGISTRY_MODULE = "@deepseek-ai/dsh-agent-preset-registry";
|
|
139
|
+
/** The declarative preset row a preset bundle package carries in its patch. */
|
|
140
|
+
export declare const PRESET_ROW_MODULE = "@deepseek-ai/dsh-agent-preset";
|
|
141
|
+
/** A preset id doubles as a directory name inside the scope. */
|
|
129
142
|
export declare const SUB_PROFILE_PRESET_ID_RE: RegExp;
|
|
130
143
|
/**
|
|
131
144
|
* Resolve the family headless bundle's directory. The bundle is a declared
|
|
@@ -136,25 +149,31 @@ export declare const SUB_PROFILE_PRESET_ID_RE: RegExp;
|
|
|
136
149
|
*/
|
|
137
150
|
export declare function resolveHeadlessBundleDir(config?: DshSubProfileConfig): string;
|
|
138
151
|
/**
|
|
139
|
-
* The
|
|
152
|
+
* The preset layer appended to the sub-profile's patch, or `''` when the
|
|
140
153
|
* sub-profile composes no preset.
|
|
141
154
|
*
|
|
155
|
+
* One insert of the 0.2.0 preset registry with the preset as its `default`:
|
|
156
|
+
* every sub-dsh session that names no preset joins this one (the headless
|
|
157
|
+
* agent loader mounts it through the registry's `mount`). The preset's own
|
|
158
|
+
* declaration rides the bundle layer — the package that declares it is in
|
|
159
|
+
* the manifest's bundle list — so this layer never repeats the composition.
|
|
160
|
+
*
|
|
142
161
|
* It is a SEPARATE patch operation appended after the headless bundle's own
|
|
143
162
|
* list, which is what keeps the two independent: an upgraded headless bundle
|
|
144
|
-
* rewrites its half and the
|
|
163
|
+
* rewrites its half and the preset survives, and dropping the preset drops
|
|
145
164
|
* exactly these lines.
|
|
146
|
-
* @param preset - the
|
|
165
|
+
* @param preset - the preset to compose, or undefined for none.
|
|
147
166
|
* @returns the YAML text to append (already newline-terminated), or `''`.
|
|
148
167
|
*/
|
|
149
|
-
export declare function
|
|
168
|
+
export declare function presetRegistryLayer(preset: DshSubProfilePreset | undefined): string;
|
|
150
169
|
/**
|
|
151
170
|
* The preset id a provisioned sub-profile's patch composes, read back from
|
|
152
|
-
* the file. The
|
|
171
|
+
* the file. The preset layer is generated, so it is also parseable: a lock
|
|
153
172
|
* check or a status surface can answer "which preset does this scope run?"
|
|
154
173
|
* without booting the sub-dsh.
|
|
155
174
|
* @param homeDir - the harness scoped home.
|
|
156
175
|
* @param profileName - the sub-profile name (default {@link DEFAULT_SUB_PROFILE_NAME}).
|
|
157
|
-
* @returns the preset id, or undefined when the sub-profile composes no
|
|
176
|
+
* @returns the preset id, or undefined when the sub-profile composes no preset.
|
|
158
177
|
*/
|
|
159
178
|
export declare function readSubProfilePreset(homeDir: string, profileName?: string): string | undefined;
|
|
160
179
|
/**
|
|
@@ -193,40 +212,59 @@ export declare function permissionBoundaryLayer(permissions: DshSubProfilePermis
|
|
|
193
212
|
* @returns the pinned mode, or undefined when the sub-profile pins none.
|
|
194
213
|
*/
|
|
195
214
|
export declare function readSubProfilePermissions(homeDir: string, profileName?: string): DshSubProfilePermissions | undefined;
|
|
215
|
+
/** Suffix of the evaluation-unit twin of a sub-profile (see `unitHeadlessBundleDir`). */
|
|
216
|
+
export declare const UNIT_PROFILE_SUFFIX = "-unit";
|
|
217
|
+
/**
|
|
218
|
+
* The profile name an evaluation UNIT launches for this config: the
|
|
219
|
+
* `-unit` twin when one is configured, else the one sub-profile.
|
|
220
|
+
* @param config - provisioning config.
|
|
221
|
+
* @returns the profile name a container round passes to `--profile`.
|
|
222
|
+
*/
|
|
223
|
+
export declare function unitSubProfileName(config?: DshSubProfileConfig): string;
|
|
196
224
|
/**
|
|
197
225
|
* Provision (idempotently) the sub-dsh headless profile in the harness
|
|
198
226
|
* scoped home: manifest, the headless patch as the profile's own patch
|
|
199
|
-
* layer, and the bundle symlink
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
227
|
+
* layer, and the headless bundle (a copy; a symlink in the `-unit` twin or under a lone `headlessBundleDir` pin) — plus, when a preset package is composed,
|
|
228
|
+
* the relative link resolving it from the scope's own copy, and, when
|
|
229
|
+
* `unitHeadlessBundleDir` is configured, the `-unit` twin a container round
|
|
230
|
+
* launches. A file whose content already matches is left untouched, so
|
|
231
|
+
* re-running after a restart is a no-op; a drifted file (an upgraded headless
|
|
232
|
+
* bundle, or a profile provisioned by an earlier scheme) is rewritten, which
|
|
233
|
+
* heals it before the sub-dsh boots.
|
|
204
234
|
* @param homeDir - the `dsh` harness's scoped home (its `$DSH_HOME` root).
|
|
205
235
|
* @param config - profile naming and bundle-dir overrides.
|
|
206
|
-
* @returns the absolute sub-profile directory.
|
|
236
|
+
* @returns the absolute (host) sub-profile directory.
|
|
207
237
|
*/
|
|
208
238
|
export declare function provisionDshSubProfile(homeDir: string, config?: DshSubProfileConfig): string;
|
|
209
239
|
/**
|
|
210
|
-
*
|
|
211
|
-
*
|
|
240
|
+
* Where a scope keeps its own copy of each preset PACKAGE it composes:
|
|
241
|
+
* `<scoped home>/preset-packages/<id>`. (0.1.x used `.agent-presets/<id>`,
|
|
242
|
+
* the directory roster's derived user root; 0.2.0 has no directory scan.)
|
|
212
243
|
*/
|
|
213
|
-
export declare const
|
|
244
|
+
export declare const SCOPE_PRESET_PACKAGES_DIR = "preset-packages";
|
|
245
|
+
/**
|
|
246
|
+
* The scope's copy of one preset package.
|
|
247
|
+
* @param homeDir - the harness scoped home.
|
|
248
|
+
* @param id - the preset id.
|
|
249
|
+
* @returns the directory, whether or not it exists.
|
|
250
|
+
*/
|
|
251
|
+
export declare function scopePresetPackageDir(homeDir: string, id: string): string;
|
|
214
252
|
/**
|
|
215
253
|
* The scope's own declaration of what its sub-profile composes.
|
|
216
254
|
*
|
|
217
255
|
* A FILE in the scope directory, for the third time and the same reason as
|
|
218
|
-
* the
|
|
256
|
+
* the preset layer and the permission boundary: a scoped home bind-mounted
|
|
219
257
|
* into an evaluation unit carries its own composition with it, and nothing
|
|
220
258
|
* has to ride the spawn env or be baked into an image.
|
|
221
259
|
*
|
|
222
260
|
* It exists because the plugin's own `config` is instance-global — one
|
|
223
261
|
* deployment, one answer — while a preset is a property of the SUBJECT. Two
|
|
224
|
-
* scopes
|
|
225
|
-
* to build it was to hand-append the
|
|
262
|
+
* scopes composing two presets was therefore unexpressible, and the only way
|
|
263
|
+
* to build it was to hand-append the preset layer to each scope's patch. That
|
|
226
264
|
* hand edit does not survive: this module regenerates the patch WHOLE, and
|
|
227
265
|
* the registry re-provisions a scope the first time anything names it in a
|
|
228
|
-
* fresh host process — so the
|
|
229
|
-
* and the next read-back reports a scope that
|
|
266
|
+
* fresh host process — so the layer silently disappears on the next restart,
|
|
267
|
+
* and the next read-back reports a scope that composes nothing.
|
|
230
268
|
*/
|
|
231
269
|
export declare const SCOPE_SUB_PROFILE_FILENAME = "sub-profile.json";
|
|
232
270
|
/** What {@link SCOPE_SUB_PROFILE_FILENAME} may say. */
|
|
@@ -254,127 +292,136 @@ export declare function readScopeSubProfile(homeDir: string): DshScopeSubProfile
|
|
|
254
292
|
*/
|
|
255
293
|
export declare function writeScopeSubProfile(homeDir: string, declaration: DshScopeSubProfile): void;
|
|
256
294
|
/**
|
|
257
|
-
* Every absolute filesystem path a preset
|
|
295
|
+
* Every absolute filesystem path a preset bundle patch names.
|
|
258
296
|
*
|
|
259
297
|
* An absolute path is the one thing in a composition that cannot be true in
|
|
260
298
|
* two places at once, and a preset used as an evaluation factor is copied:
|
|
261
|
-
* it is read on the host from the
|
|
299
|
+
* it is read on the host from the instance's installation, again from the
|
|
262
300
|
* scope's own copy, and a third time inside a unit where the scope is bound
|
|
263
301
|
* at a different mount point. `skill-filesystem` resolves each
|
|
264
302
|
* `customSkillDirs` entry with `resolve()`, so an absolute entry is taken as
|
|
265
303
|
* written and a bare relative one resolves against the process's cwd —
|
|
266
304
|
* neither travels.
|
|
267
305
|
*
|
|
268
|
-
* What does travel is the
|
|
269
|
-
* `
|
|
306
|
+
* What does travel is resolving the package's own directory through the
|
|
307
|
+
* loader's `baseUrl` (the declaring profile's root), the form the official
|
|
308
|
+
* web-app presets use:
|
|
270
309
|
*
|
|
271
310
|
* ```yaml
|
|
272
311
|
* customSkillDirs:
|
|
273
|
-
* - !!js "process.getBuiltinModule('node:
|
|
312
|
+
* - !!js "process.getBuiltinModule('node:path').join(process.getBuiltinModule('node:path').dirname(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('<pkg>/package.json')), 'skills')"
|
|
274
313
|
* ```
|
|
275
314
|
*
|
|
276
|
-
* `baseUrl` is the composition's own directory (the include rewrites it), so
|
|
277
|
-
* the root resolves wherever the preset is installed.
|
|
278
|
-
*
|
|
279
315
|
* Unparsable YAML reports NO findings: the loader is the authority on whether
|
|
280
316
|
* a composition loads, and refusing a preset because this reader could not
|
|
281
317
|
* parse it would be this module overruling it.
|
|
282
|
-
* @param text - the
|
|
318
|
+
* @param text - the bundle patch content.
|
|
283
319
|
* @returns the offending literals, in document order, deduplicated.
|
|
284
320
|
*/
|
|
285
321
|
export declare function compositionAbsolutePaths(text: string): string[];
|
|
286
322
|
/**
|
|
287
|
-
* Whether two preset directories are the same directory, byte for
|
|
323
|
+
* Whether two preset package directories are the same directory, byte for
|
|
324
|
+
* byte.
|
|
288
325
|
*
|
|
289
326
|
* This is the whole claim the evaluation rests on: a capability face carries
|
|
290
327
|
* no filesystem path, so the fingerprint taken against the deployment's copy
|
|
291
328
|
* describes the scope's copy exactly when the two hold the same bytes.
|
|
292
|
-
* @param a - one preset directory.
|
|
329
|
+
* @param a - one preset package directory.
|
|
293
330
|
* @param b - the other.
|
|
294
331
|
* @returns true when both hold the same files with the same contents.
|
|
295
332
|
*/
|
|
296
333
|
export declare function presetTreesEqual(a: string, b: string): boolean;
|
|
334
|
+
/** One installed bundle package that declares a preset. */
|
|
335
|
+
export interface DshPresetPackage {
|
|
336
|
+
/** The package name (what the sub-profile manifest lists). */
|
|
337
|
+
name: string;
|
|
338
|
+
/** The package directory, symlinks resolved. */
|
|
339
|
+
dir: string;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Find the bundle package, among a profile's direct dependencies, whose
|
|
343
|
+
* bundle patch declares preset `id`.
|
|
344
|
+
*
|
|
345
|
+
* This is how the 0.2.0 host itself learns the preset: a profile's direct
|
|
346
|
+
* `dsh.bundle`-declaring dependency mounts its patch, and the patch's
|
|
347
|
+
* `@deepseek-ai/dsh-agent-preset` row registers the id. Reading the same files
|
|
348
|
+
* is what lets a scope copy exactly the package the evaluation instance's
|
|
349
|
+
* capability catalog measures.
|
|
350
|
+
* @param profileDir - the instance profile directory (holding `package.json`).
|
|
351
|
+
* @param id - the preset id.
|
|
352
|
+
* @returns the declaring package, or undefined when none (or more than one) declares it.
|
|
353
|
+
*/
|
|
354
|
+
export declare function findPresetPackage(profileDir: string, id: string): DshPresetPackage | undefined;
|
|
297
355
|
/** What {@link snapshotScopePreset} did. */
|
|
298
356
|
export interface DshScopePresetSnapshot {
|
|
299
|
-
/** The scope's copy of the preset
|
|
357
|
+
/** The scope's copy of the preset package. */
|
|
300
358
|
dir: string;
|
|
359
|
+
/** The package name the copy carries. */
|
|
360
|
+
packageName: string;
|
|
301
361
|
/** Whether that copy is byte-for-byte the deployment's own. */
|
|
302
362
|
matchesSource: boolean;
|
|
303
363
|
/** Whether this call wrote it. */
|
|
304
364
|
copied: boolean;
|
|
305
365
|
}
|
|
306
366
|
/**
|
|
307
|
-
* Give one scope its own copy of a preset, from the
|
|
367
|
+
* Give one scope its own copy of a preset package, from the evaluation
|
|
368
|
+
* instance's own installation of it.
|
|
308
369
|
*
|
|
309
|
-
* The copy is what makes a preset reachable on BOTH paths. The
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
* one directory, because the unit binds the scope. A roster pointed at the
|
|
314
|
-
* deployment's root instead resolves on the host and names a path the unit
|
|
315
|
-
* does not have.
|
|
370
|
+
* The copy is what makes a preset reachable on BOTH paths. The sub-profile
|
|
371
|
+
* resolves the package through a relative link to
|
|
372
|
+
* `<scope>/preset-packages/<id>`, which is one directory on the host and
|
|
373
|
+
* inside an evaluation unit, because the unit binds the scope.
|
|
316
374
|
*
|
|
317
375
|
* `refresh` is the difference between provisioning a condition and healing a
|
|
318
|
-
* scope. A deliberate provision re-syncs from the
|
|
376
|
+
* scope. A deliberate provision re-syncs from the instance's copy, because
|
|
319
377
|
* that is the moment a new lock is minted and an edited preset should be
|
|
320
378
|
* picked up. Every other provisioning leaves an existing copy alone: nothing
|
|
321
|
-
* may move the subject under a run
|
|
379
|
+
* may move the subject under a run — and a healing call whose instance no
|
|
380
|
+
* longer carries the package keeps the copy, reporting `matchesSource: false`.
|
|
322
381
|
* @param homeDir - the harness scoped home.
|
|
323
|
-
* @param
|
|
324
|
-
* @param id - the preset id
|
|
382
|
+
* @param instanceProfileDir - the instance profile directory, or undefined when unknown.
|
|
383
|
+
* @param id - the preset id.
|
|
325
384
|
* @param options - `refresh` re-syncs an existing copy.
|
|
326
385
|
* @returns where the copy is and whether it matches the source.
|
|
327
|
-
* @throws when
|
|
386
|
+
* @throws when no copy can be made: no installed package declares the id, or it is not a usable preset package.
|
|
328
387
|
*/
|
|
329
|
-
export declare function snapshotScopePreset(homeDir: string,
|
|
388
|
+
export declare function snapshotScopePreset(homeDir: string, instanceProfileDir: string | undefined, id: string, options?: {
|
|
330
389
|
refresh?: boolean;
|
|
331
390
|
}): DshScopePresetSnapshot;
|
|
332
|
-
/**
|
|
333
|
-
* The deployment's own preset root, when the caller names no other.
|
|
334
|
-
*
|
|
335
|
-
* The roster's own derivation, repeated here because the provisioning paths
|
|
336
|
-
* that heal a scope (a host round, a live runtime) have no settings service
|
|
337
|
-
* in reach: a non-blank `$DSH_HOME`, else the `~/.dsh` installation default
|
|
338
|
-
* (the precedence of `resolveDshHome` in `@deepseek-ai/dsh-home-paths` —
|
|
339
|
-
* the default was once hardcoded to `.dsh-official`, pointing a desktop
|
|
340
|
-
* instance at another instance's home; 2026-09-30).
|
|
341
|
-
*/
|
|
342
|
-
export declare function defaultPresetRoot(): string;
|
|
343
391
|
/** Per-scope inputs {@link provisionDshScope} takes. */
|
|
344
392
|
export interface DshScopeProvisionOptions {
|
|
345
393
|
/**
|
|
346
394
|
* The preset this scope composes. Present, it is authoritative: it is
|
|
347
395
|
* persisted into the scope's own declaration and its copy is re-synced from
|
|
348
|
-
* the
|
|
396
|
+
* the instance's installation. Absent, the scope's declaration decides.
|
|
349
397
|
*/
|
|
350
398
|
preset?: string;
|
|
351
|
-
/**
|
|
352
|
-
|
|
399
|
+
/**
|
|
400
|
+
* The evaluation instance's own profile directory, whose direct
|
|
401
|
+
* dependencies are searched for the package declaring the preset.
|
|
402
|
+
*/
|
|
403
|
+
instanceProfileDir?: string;
|
|
353
404
|
}
|
|
354
405
|
/** What {@link provisionDshScope} left in the scope. */
|
|
355
406
|
export interface DshScopeProvisioned {
|
|
356
407
|
/** The sub-profile directory. */
|
|
357
408
|
profileDir: string;
|
|
358
|
-
/** The preset the sub-profile now
|
|
409
|
+
/** The preset the sub-profile now composes, when it composes one. */
|
|
359
410
|
preset?: string;
|
|
360
|
-
/** The scope's own copy of that preset, when it keeps one. */
|
|
411
|
+
/** The scope's own copy of that preset package, when it keeps one. */
|
|
361
412
|
presetSnapshot?: {
|
|
362
413
|
matchesSource: boolean;
|
|
363
414
|
};
|
|
364
415
|
}
|
|
365
416
|
/**
|
|
366
|
-
* Provision one scope: its own preset copy, its declaration, and the
|
|
367
|
-
* sub-profile that
|
|
417
|
+
* Provision one scope: its own preset package copy, its declaration, and the
|
|
418
|
+
* sub-profile that composes it.
|
|
368
419
|
*
|
|
369
420
|
* The preset resolves in one order, and the order is the decision: the
|
|
370
421
|
* CALLER's explicit request, then the SCOPE's own declaration, then the
|
|
371
422
|
* deployment's plugin config. The first is how a condition says which subject
|
|
372
423
|
* this scope is; the second is how that survives a restart; the third is the
|
|
373
424
|
* deployment-wide answer every scope had before either existed.
|
|
374
|
-
*
|
|
375
|
-
* A scope-owned preset rosters with NO `roots`. The roster's derived user
|
|
376
|
-
* root is exactly the scope's copy on both paths, so leaving the roots alone
|
|
377
|
-
* is what gives the host and the unit one resolution rule instead of two.
|
|
378
425
|
* @param homeDir - the harness scoped home.
|
|
379
426
|
* @param config - the deployment's sub-profile config.
|
|
380
427
|
* @param options - per-scope inputs.
|