@dsh-plugin/dsh-loader 1.0.0 → 1.1.0-dev.32287576957

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 (74) hide show
  1. package/LICENSE +160 -0
  2. package/README.md +251 -226
  3. package/{README.zh-CN.md → README.zh_CN.md} +227 -202
  4. package/bin/dshloader.mjs +42 -42
  5. package/cordis.patch.yml +8 -8
  6. package/dist/adapters/dsh-1-x.d.ts +23 -0
  7. package/dist/adapters/dsh-1-x.js +223 -0
  8. package/dist/adapters/dsh-1-x.js.map +1 -0
  9. package/dist/adapters/index.d.ts +22 -0
  10. package/dist/adapters/index.js +57 -0
  11. package/dist/adapters/index.js.map +1 -0
  12. package/dist/api.d.ts +13 -0
  13. package/dist/api.js +46 -0
  14. package/dist/api.js.map +1 -0
  15. package/dist/client.d.ts +157 -0
  16. package/dist/client.js +295 -0
  17. package/dist/client.js.map +1 -0
  18. package/dist/index.d.ts +52 -0
  19. package/dist/index.js +89 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/registry.d.ts +35 -0
  22. package/dist/registry.js +229 -0
  23. package/dist/registry.js.map +1 -0
  24. package/dist/services/services.d.ts +4 -0
  25. package/dist/services/services.js +28 -0
  26. package/dist/services/services.js.map +1 -0
  27. package/dist/services/settings.d.ts +41 -0
  28. package/dist/services/settings.js +161 -0
  29. package/dist/services/settings.js.map +1 -0
  30. package/dist/services/web.d.ts +10 -0
  31. package/dist/services/web.js +63 -0
  32. package/dist/services/web.js.map +1 -0
  33. package/dist/setup.d.ts +32 -0
  34. package/dist/setup.js +119 -0
  35. package/dist/setup.js.map +1 -0
  36. package/dist/types.d.ts +111 -0
  37. package/dist/types.js +12 -0
  38. package/dist/types.js.map +1 -0
  39. package/dist/version.d.ts +2 -0
  40. package/{src → dist}/version.js +5 -5
  41. package/dist/version.js.map +1 -0
  42. package/lib/client.js +283 -0
  43. package/lib/client.js.map +1 -0
  44. package/package.json +75 -59
  45. package/src/stable/agent.d.ts +1 -1
  46. package/src/stable/agent.js +2 -2
  47. package/src/stable/llm.d.ts +1 -1
  48. package/src/stable/llm.js +2 -2
  49. package/src/stable/runtime.d.ts +1 -1
  50. package/src/stable/runtime.js +5 -5
  51. package/src/stable/schema-form.d.ts +1 -1
  52. package/src/stable/schema-form.js +2 -2
  53. package/src/stable/settings.d.ts +1 -1
  54. package/src/stable/settings.js +2 -2
  55. package/src/stable/tools.d.ts +1 -1
  56. package/src/stable/tools.js +5 -5
  57. package/src/stable/ui-primitives.d.ts +4 -4
  58. package/src/stable/ui-primitives.js +6 -6
  59. package/src/stable/ui-settings.d.ts +6 -6
  60. package/src/stable/ui-settings.js +4 -4
  61. package/src/stable/ui-slots.d.ts +1 -1
  62. package/src/stable/ui-slots.js +2 -2
  63. package/src/stable/web-react.d.ts +1 -1
  64. package/src/stable/web-react.js +2 -2
  65. package/src/adapters/dsh-1-x.js +0 -236
  66. package/src/adapters/index.js +0 -59
  67. package/src/api.js +0 -56
  68. package/src/client.js +0 -330
  69. package/src/index.js +0 -105
  70. package/src/registry.js +0 -242
  71. package/src/services/services.js +0 -28
  72. package/src/services/settings.js +0 -174
  73. package/src/services/web.js +0 -71
  74. package/src/setup.mjs +0 -125
@@ -0,0 +1,229 @@
1
+ /**
2
+ * Adapter registry + dsh version detection (design.md §3.1 / §3.2).
3
+ *
4
+ * Selection rules (mirrors design.md §3.1, five rules):
5
+ * 1. exact match — adapter.supports === version
6
+ * 2. range match — semver.satisfies(version, supports); when several
7
+ * ranges cover the version, pick the narrowest; ties
8
+ * broken by last-registered-wins.
9
+ * 3. nearest-low fallback — no exact/range hit, but some adapters only cover
10
+ * versions below the real one: pick the one whose
11
+ * upper bound is closest, mark mode 'fallback', warn.
12
+ * 4. version too old — real version is below every adapter's lower bound:
13
+ * throw UnsupportedDshVersionError with a "too old"
14
+ * message and the lowest supported version.
15
+ * 5. version too new / empty registry — throw UnsupportedDshVersionError with
16
+ * an "upgrade dshloader" message.
17
+ *
18
+ * Version detection priority (design.md §3.2):
19
+ * 1. DSHLOADER_DSH_VERSION env var (highest; for tests/CI override)
20
+ * 2. node_modules/@deepseek-ai/dsh/package.json#version
21
+ * 3. ctx.runtime?.version — reserved for the future, NOT consulted in v1.
22
+ * child_process `dsh --version` is deliberately NOT used (design.md §3.2).
23
+ */
24
+ import { readFileSync } from 'node:fs';
25
+ import { join, resolve, dirname } from 'node:path';
26
+ import { createRequire } from 'node:module';
27
+ import semver from 'semver';
28
+ import { LOG_PREFIX } from './version.js';
29
+ const require = createRequire(import.meta.url);
30
+ export class UnsupportedDshVersionError extends Error {
31
+ kind; // 'too-old' | 'too-new'
32
+ version;
33
+ minSupported;
34
+ constructor(message, opts = {}) {
35
+ super(message);
36
+ this.name = 'UnsupportedDshVersionError';
37
+ this.kind = opts.kind;
38
+ this.version = opts.version;
39
+ this.minSupported = opts.minSupported;
40
+ }
41
+ }
42
+ export class InvalidVersionError extends Error {
43
+ version;
44
+ constructor(message, opts = {}) {
45
+ super(message);
46
+ this.name = 'InvalidVersionError';
47
+ this.version = opts.version;
48
+ }
49
+ }
50
+ /**
51
+ * Resolve the installed dsh version.
52
+ *
53
+ * @returns semver version string, or undefined when unreachable
54
+ */
55
+ export function detectDshVersion(opts = {}) {
56
+ const env = opts.env ?? process.env;
57
+ const envVal = env.DSHLOADER_DSH_VERSION;
58
+ if (typeof envVal === 'string' && envVal.trim() !== '') {
59
+ return envVal.trim();
60
+ }
61
+ const candidates = [];
62
+ if (opts.dshPkgPath)
63
+ candidates.push(opts.dshPkgPath);
64
+ if (opts.profileDir) {
65
+ candidates.push(join(opts.profileDir, 'node_modules', '@deepseek-ai', 'dsh', 'package.json'));
66
+ }
67
+ // Resolve from the loader's own location (profile node_modules sits beside it).
68
+ try {
69
+ candidates.push(require.resolve('@deepseek-ai/dsh/package.json'));
70
+ }
71
+ catch { /* not installed — skip */ }
72
+ // Global node_modules — dsh is typically installed globally (the runtime
73
+ // that loads profiles, not a profile dependency). Derive from the Node.js
74
+ // executable: /opt/homebrew/bin/node → /opt/homebrew/lib/node_modules.
75
+ const globalRoot = resolve(dirname(process.execPath), '..', 'lib', 'node_modules');
76
+ candidates.push(join(globalRoot, '@deepseek-ai', 'dsh', 'package.json'));
77
+ // Walk up from cwd as a last resort.
78
+ let dir = process.cwd();
79
+ for (let i = 0; i < 8; i += 1) {
80
+ candidates.push(join(dir, 'node_modules', '@deepseek-ai', 'dsh', 'package.json'));
81
+ const parent = resolve(dir, '..');
82
+ if (parent === dir)
83
+ break;
84
+ dir = parent;
85
+ }
86
+ for (const path of candidates) {
87
+ try {
88
+ const pkg = JSON.parse(readFileSync(path, 'utf8'));
89
+ if (typeof pkg.version === 'string' && pkg.version.trim() !== '') {
90
+ return pkg.version.trim();
91
+ }
92
+ }
93
+ catch { /* try next */ }
94
+ }
95
+ return undefined;
96
+ }
97
+ /**
98
+ * Parse a semver range into { lower, upper } bounds. Each bound is
99
+ * { v: SemVer, inc: boolean } or null when unbounded on that side.
100
+ */
101
+ function rangeBounds(range) {
102
+ const r = new semver.Range(range);
103
+ let lower = null;
104
+ let upper = null;
105
+ for (const group of r.set) {
106
+ for (const c of group) {
107
+ const op = c.operator;
108
+ const v = c.semver; // parsed SemVer (c.value is the raw comparator string)
109
+ if (op === '' || op === '=') {
110
+ lower = { v, inc: true };
111
+ upper = { v, inc: true };
112
+ }
113
+ else if (op === '>') {
114
+ lower = { v, inc: false };
115
+ }
116
+ else if (op === '>=') {
117
+ lower = { v, inc: true };
118
+ }
119
+ else if (op === '<') {
120
+ upper = { v, inc: false };
121
+ }
122
+ else if (op === '<=') {
123
+ upper = { v, inc: true };
124
+ }
125
+ }
126
+ }
127
+ return { lower, upper };
128
+ }
129
+ /** True when every version the range covers is strictly below `version`. */
130
+ function isLowerCandidate(range, version) {
131
+ const { upper } = rangeBounds(range);
132
+ if (!upper)
133
+ return false; // unbounded above → can cover version, not a lower candidate
134
+ return upper.inc ? semver.gt(version, upper.v) : semver.gte(version, upper.v);
135
+ }
136
+ /** Lowest version that satisfies the range (semver.minVersion). */
137
+ function rangeMinVersion(range) {
138
+ const min = semver.minVersion(range);
139
+ return min ? min.version : null;
140
+ }
141
+ export class AdapterRegistry {
142
+ adapters;
143
+ constructor() {
144
+ this.adapters = [];
145
+ }
146
+ register(factory) {
147
+ if (!factory || typeof factory.supports !== 'string' || typeof factory.create !== 'function') {
148
+ throw new TypeError('AdapterFactory must expose { supports: string, create: function }');
149
+ }
150
+ this.adapters.push(factory);
151
+ return this;
152
+ }
153
+ select(version) {
154
+ if (!semver.valid(version)) {
155
+ throw new InvalidVersionError(`${LOG_PREFIX} cannot parse dsh version "${version}" as semver`, { version });
156
+ }
157
+ if (this.adapters.length === 0) {
158
+ throw new UnsupportedDshVersionError(`${LOG_PREFIX} no adapter registered for dsh ${version}; please upgrade @dsh-plugin/dsh-loader`, { kind: 'too-new', version });
159
+ }
160
+ // Rule 1 + 2: exact and range matches.
161
+ const matches = [];
162
+ for (const factory of this.adapters) {
163
+ if (factory.supports === version) {
164
+ matches.push({ factory, mode: 'exact' });
165
+ }
166
+ else if (semver.satisfies(version, factory.supports)) {
167
+ matches.push({ factory, mode: 'range' });
168
+ }
169
+ }
170
+ if (matches.length > 0) {
171
+ // Narrowest range wins; tie → last registered.
172
+ let best = matches[matches.length - 1];
173
+ for (let i = matches.length - 1; i >= 0; i -= 1) {
174
+ const candidate = matches[i];
175
+ const narrowest = matches.every((other, j) => {
176
+ if (i === j)
177
+ return true;
178
+ try {
179
+ return semver.subset(candidate.factory.supports, other.factory.supports);
180
+ }
181
+ catch {
182
+ return false;
183
+ }
184
+ });
185
+ if (narrowest) {
186
+ best = candidate;
187
+ break;
188
+ }
189
+ }
190
+ // Exact match always beats a range match on the same version.
191
+ const exact = matches.find((m) => m.mode === 'exact');
192
+ if (exact)
193
+ best = exact;
194
+ return { factory: best.factory, mode: best.mode };
195
+ }
196
+ // Rule 3: nearest-low fallback.
197
+ const lowers = this.adapters
198
+ .filter((f) => isLowerCandidate(f.supports, version))
199
+ .map((f) => {
200
+ const { upper } = rangeBounds(f.supports);
201
+ return { factory: f, upper };
202
+ });
203
+ if (lowers.length > 0) {
204
+ lowers.sort((a, b) => {
205
+ const cmp = semver.compare(b.upper.v, a.upper.v);
206
+ if (cmp !== 0)
207
+ return cmp;
208
+ // exclusive upper is "higher" than inclusive at the same version
209
+ return (b.upper.inc ? 0 : 1) - (a.upper.inc ? 0 : 1);
210
+ });
211
+ const chosen = lowers[0];
212
+ console.warn(`${LOG_PREFIX} no exact adapter for dsh ${version}; falling back to "${chosen.factory.name}" (supports ${chosen.factory.supports})`);
213
+ return { factory: chosen.factory, mode: 'fallback' };
214
+ }
215
+ // Rule 4 vs 5: too old vs too new.
216
+ const minVersions = this.adapters
217
+ .map((f) => rangeMinVersion(f.supports))
218
+ .filter((v) => v !== null)
219
+ .map((v) => semver.parse(v));
220
+ if (minVersions.length > 0) {
221
+ const lowest = minVersions.reduce((acc, v) => (semver.lt(v, acc) ? v : acc));
222
+ if (semver.lt(version, lowest)) {
223
+ throw new UnsupportedDshVersionError(`${LOG_PREFIX} current dsh version ${version} is too old; dshloader minimum supported is ${lowest.version}. Please upgrade dsh or use an older dshloader release.`, { kind: 'too-old', version, minSupported: lowest.version });
224
+ }
225
+ }
226
+ throw new UnsupportedDshVersionError(`${LOG_PREFIX} no adapter covers dsh ${version}; please upgrade @dsh-plugin/dsh-loader`, { kind: 'too-new', version });
227
+ }
228
+ }
229
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { CordisContext, ServicesAPI } from '../types.js';
2
+ export declare function createServicesAPI(opts: {
3
+ ctx: CordisContext;
4
+ }): ServicesAPI;
@@ -0,0 +1,28 @@
1
+ // Services stable API (design.md §3.3 / §4.1 `ctx.dshLoader.services`).
2
+ //
3
+ // Thin read/alias helpers over the cordis service registry. `alias()` is a
4
+ // low-level escape hatch for plugin authors who need a one-hop alias beyond
5
+ // what the selected adapter already provides; it never overwrites an existing
6
+ // service (mirrors the adapter safety rule in design.md §5.1).
7
+ import { LOG_PREFIX } from '../version.js';
8
+ export function createServicesAPI(opts) {
9
+ const { ctx } = opts;
10
+ return {
11
+ get(name) {
12
+ return ctx.get(name);
13
+ },
14
+ alias(from, to) {
15
+ if (ctx.get(from) !== undefined) {
16
+ console.warn(`${LOG_PREFIX} services.alias: "${from}" already exists, skip alias`);
17
+ return;
18
+ }
19
+ const target = ctx.get(to);
20
+ if (target === undefined) {
21
+ console.warn(`${LOG_PREFIX} services.alias: target "${to}" unavailable, cannot alias "${from}"`);
22
+ return;
23
+ }
24
+ ctx.reflect.provide(from, target);
25
+ },
26
+ };
27
+ }
28
+ //# sourceMappingURL=services.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services.js","sourceRoot":"","sources":["../../src/services/services.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,8EAA8E;AAC9E,+DAA+D;AAE/D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,UAAU,iBAAiB,CAAC,IAA4B;IAC5D,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACrB,OAAO;QACL,GAAG,CAAC,IAAI;YACN,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;QACD,KAAK,CAAC,IAAI,EAAE,EAAE;YACZ,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;gBAChC,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,qBAAqB,IAAI,8BAA8B,CAAC,CAAC;gBACnF,OAAO;YACT,CAAC;YACD,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC3B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,4BAA4B,EAAE,gCAAgC,IAAI,GAAG,CAAC,CAAC;gBACjG,OAAO;YACT,CAAC;YACD,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { CordisContext, SettingsAPI, SettingsResult, NamespaceView } from '../types.js';
2
+ /**
3
+ * Official browser-writable settings namespaces (dsh-host-apiproxy
4
+ * WEB_SETTINGS_NAMESPACES), as documented in dsh-upstream-fixes/README.md.
5
+ * Product namespaces and dynamic model-provider namespaces are not enumerable
6
+ * without dsh internals; callers may extend this set via `extraWhitelist`.
7
+ */
8
+ export declare const DEFAULT_WEB_SETTINGS_NAMESPACES: Set<string>;
9
+ /** A raw settings descriptor returned by the real settings service. */
10
+ interface SettingsDescriptor {
11
+ ns: string;
12
+ schema: any;
13
+ value: any;
14
+ base?: any;
15
+ user?: any;
16
+ applies?: any;
17
+ secrets?: {
18
+ path: string[];
19
+ set?: any;
20
+ }[];
21
+ revision?: any;
22
+ }
23
+ /**
24
+ * Shape a raw settings descriptor into the official NamespaceView wire shape
25
+ * (mirrors dsh-upstream-fixes/lib/index.js `namespaceView`).
26
+ */
27
+ export declare function toNamespaceView(descriptor: SettingsDescriptor): NamespaceView;
28
+ /**
29
+ * Map a thrown settings error into a SettingsResult, preserving the official
30
+ * `settings-conflict` / `settings-rejected` classification.
31
+ */
32
+ export declare function settingsErrorToResult(error: unknown, ns: string, method: string): SettingsResult;
33
+ /**
34
+ * Build the `ctx.dshLoader.settings` stable API.
35
+ */
36
+ export declare function createSettingsAPI(opts: {
37
+ ctx: CordisContext;
38
+ exposeAllNamespaces: boolean;
39
+ whitelist?: Set<string>;
40
+ }): SettingsAPI;
41
+ export {};
@@ -0,0 +1,161 @@
1
+ // Settings stable API (design.md §3.3.1 / §4.1 / §4.2).
2
+ //
3
+ // Two concerns are deliberately separated:
4
+ // 1. naming/shape differences — handled by proxying to ctx.get('settings').
5
+ // 2. access scope (security) — `exposeAllNamespaces` controls whether
6
+ // `describe` returns only the official browser whitelist namespaces
7
+ // (default, matches official behavior) or every registered namespace.
8
+ //
9
+ // Host-side writes always proxy through to the real settings service: host
10
+ // plugin code is already trusted (it runs in the dsh Node process and could
11
+ // call ctx.get('settings').update directly). The whitelist is a browser-side
12
+ // default-deny boundary owned by dsh-host-apiproxy; the browser path is
13
+ // covered separately by the client fetch interceptor (src/client.ts).
14
+ import { LOG_PREFIX } from '../version.js';
15
+ /**
16
+ * Official browser-writable settings namespaces (dsh-host-apiproxy
17
+ * WEB_SETTINGS_NAMESPACES), as documented in dsh-upstream-fixes/README.md.
18
+ * Product namespaces and dynamic model-provider namespaces are not enumerable
19
+ * without dsh internals; callers may extend this set via `extraWhitelist`.
20
+ */
21
+ export const DEFAULT_WEB_SETTINGS_NAMESPACES = new Set([
22
+ 'agent-loop',
23
+ 'shell',
24
+ 'locale',
25
+ 'permission',
26
+ 'ui-conversation',
27
+ 'ui-theme',
28
+ 'web-search-deepseek',
29
+ ]);
30
+ /**
31
+ * Shape a raw settings descriptor into the official NamespaceView wire shape
32
+ * (mirrors dsh-upstream-fixes/lib/index.js `namespaceView`).
33
+ */
34
+ export function toNamespaceView(descriptor) {
35
+ const view = {
36
+ ns: String(descriptor.ns),
37
+ schema: descriptor.schema,
38
+ value: descriptor.value,
39
+ ...(descriptor.base === undefined ? {} : { base: descriptor.base }),
40
+ ...(descriptor.user === undefined ? {} : { user: descriptor.user }),
41
+ applies: descriptor.applies,
42
+ secrets: (descriptor.secrets ?? []).map((s) => ({ path: [...s.path], set: s.set })),
43
+ revision: descriptor.revision,
44
+ };
45
+ return view;
46
+ }
47
+ /**
48
+ * Map a thrown settings error into a SettingsResult, preserving the official
49
+ * `settings-conflict` / `settings-rejected` classification.
50
+ */
51
+ export function settingsErrorToResult(error, ns, method) {
52
+ const isObject = error !== null && typeof error === 'object';
53
+ const isConflict = isObject && ('expected' in error || 'actual' in error);
54
+ if (isConflict) {
55
+ const err = error;
56
+ return {
57
+ ok: false,
58
+ code: 'settings-conflict',
59
+ message: err.message ?? String(error),
60
+ details: {
61
+ ns,
62
+ ...(err.expected === undefined ? {} : { expected: err.expected }),
63
+ ...(err.actual === undefined ? {} : { actual: err.actual }),
64
+ },
65
+ };
66
+ }
67
+ return {
68
+ ok: false,
69
+ code: 'settings-rejected',
70
+ message: error instanceof Error ? error.message : String(error),
71
+ details: { ns, method },
72
+ };
73
+ }
74
+ /**
75
+ * Build the `ctx.dshLoader.settings` stable API.
76
+ */
77
+ export function createSettingsAPI(opts) {
78
+ const { ctx, exposeAllNamespaces, whitelist } = opts;
79
+ const allowed = whitelist ?? DEFAULT_WEB_SETTINGS_NAMESPACES;
80
+ function getSettings() {
81
+ return ctx.get('settings');
82
+ }
83
+ function filterNamespaces(views) {
84
+ if (exposeAllNamespaces)
85
+ return views;
86
+ return views.filter((v) => allowed.has(String(v.ns)));
87
+ }
88
+ const api = {
89
+ exposeAllNamespaces: Boolean(exposeAllNamespaces),
90
+ /**
91
+ * Register a settings namespace. Proxies to the real settings service's
92
+ * `register(ns, schema, options)` and returns the owner scope
93
+ * ({ get, watch }) — the same shape the official service returns.
94
+ *
95
+ * Unlike describe/update/replace/mutate, register is NOT filtered by the
96
+ * whitelist: host plugin code is trusted and registering a namespace is
97
+ * a composition-time act, not a browser-facing read/write.
98
+ */
99
+ register(ns, schema, options) {
100
+ const settings = getSettings();
101
+ if (settings === undefined || typeof settings.register !== 'function') {
102
+ console.warn(`${LOG_PREFIX}:settings.register settings service unavailable`);
103
+ return undefined;
104
+ }
105
+ return settings.register(ns, schema, options);
106
+ },
107
+ describe(options = {}) {
108
+ const settings = getSettings();
109
+ if (settings === undefined || typeof settings.describe !== 'function') {
110
+ return [];
111
+ }
112
+ const redactSecrets = options.redactSecrets !== false;
113
+ const descriptors = settings.describe({ redactSecrets });
114
+ const views = (descriptors ?? []).map(toNamespaceView);
115
+ return filterNamespaces(views);
116
+ },
117
+ async _write(method, ns, section, expectedRevision) {
118
+ const settings = getSettings();
119
+ if (settings === undefined) {
120
+ return {
121
+ ok: false,
122
+ code: 'internal',
123
+ message: `${LOG_PREFIX}:settings.${method} settings service unavailable`,
124
+ details: { ns },
125
+ };
126
+ }
127
+ try {
128
+ if (method === 'update')
129
+ await settings.update(ns, section, expectedRevision);
130
+ else if (method === 'replace')
131
+ await settings.replace(ns, section, expectedRevision);
132
+ else
133
+ await settings.mutate(ns, section, expectedRevision);
134
+ }
135
+ catch (error) {
136
+ return settingsErrorToResult(error, ns, method);
137
+ }
138
+ const descriptor = settings.describe({ redactSecrets: true }).find((d) => String(d.ns) === String(ns));
139
+ if (descriptor === undefined) {
140
+ return {
141
+ ok: false,
142
+ code: 'internal',
143
+ message: `${LOG_PREFIX}:settings.${method} namespace disposed after write`,
144
+ details: { ns },
145
+ };
146
+ }
147
+ return { ok: true, value: toNamespaceView(descriptor) };
148
+ },
149
+ update(ns, section, expectedRevision) {
150
+ return api._write('update', ns, section, expectedRevision);
151
+ },
152
+ replace(ns, section, expectedRevision) {
153
+ return api._write('replace', ns, section, expectedRevision);
154
+ },
155
+ mutate(ns, ops, expectedRevision) {
156
+ return api._write('mutate', ns, ops, expectedRevision);
157
+ },
158
+ };
159
+ return api;
160
+ }
161
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/services/settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { CordisContext, WebAPI } from '../types.js';
2
+ export declare class DshLoaderWebError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ /**
6
+ * Build the `ctx.dshLoader.web` stable API.
7
+ */
8
+ export declare function createWebAPI(opts: {
9
+ ctx: CordisContext;
10
+ }): WebAPI;
@@ -0,0 +1,63 @@
1
+ // Web server stable API (design.md §3.3.2 / §4.1).
2
+ //
3
+ // Routes every registration through the real `webServer` (or `httpServer`
4
+ // alias) `register({ kind, ... })` call shape used by dsh 1.x, mirroring
5
+ // dsh-upstream-fixes/lib/index.js `registerRoutes`. Each method returns a
6
+ // dispose function that removes the registration when the underlying
7
+ // service supports it.
8
+ import { LOG_PREFIX } from '../version.js';
9
+ export class DshLoaderWebError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = 'DshLoaderWebError';
13
+ }
14
+ }
15
+ /** Resolve the active web server service (webServer preferred, httpServer alias next). */
16
+ function resolveWebServer(ctx) {
17
+ return ctx.get('webServer') ?? ctx.get('httpServer');
18
+ }
19
+ /**
20
+ * Build the `ctx.dshLoader.web` stable API.
21
+ */
22
+ export function createWebAPI(opts) {
23
+ const { ctx } = opts;
24
+ function server() {
25
+ const web = resolveWebServer(ctx);
26
+ if (web === undefined || typeof web.register !== 'function') {
27
+ throw new DshLoaderWebError(`${LOG_PREFIX}:web webServer service unavailable`);
28
+ }
29
+ return web;
30
+ }
31
+ return {
32
+ register(prefix, handler) {
33
+ const web = server();
34
+ return web.register({ kind: 'prefix', path: prefix, handler }) ?? (() => { });
35
+ },
36
+ get(path, handler) {
37
+ const web = server();
38
+ return web.register({ kind: 'route', method: 'GET', path, handler }) ?? (() => { });
39
+ },
40
+ post(path, handler) {
41
+ const web = server();
42
+ return web.register({ kind: 'route', method: 'POST', path, handler }) ?? (() => { });
43
+ },
44
+ use(middleware) {
45
+ const web = server();
46
+ return web.register({ kind: 'middleware', handler: middleware }) ?? (() => { });
47
+ },
48
+ /**
49
+ * Register a WebSocket upgrade route for an exact pathname.
50
+ * Proxies to `webServer.registerUpgrade({ path, handler })`.
51
+ *
52
+ * @returns dispose function that removes the upgrade route
53
+ */
54
+ registerUpgrade(route) {
55
+ const web = server();
56
+ if (typeof web.registerUpgrade !== 'function') {
57
+ throw new DshLoaderWebError(`${LOG_PREFIX}:web.registerUpgrade webServer does not support upgrade routes (registerUpgrade missing)`);
58
+ }
59
+ return web.registerUpgrade(route) ?? (() => { });
60
+ },
61
+ };
62
+ }
63
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/services/web.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,EAAE;AACF,0EAA0E;AAC1E,yEAAyE;AACzE,0EAA0E;AAC1E,qEAAqE;AACrE,uBAAuB;AACvB,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,0FAA0F;AAC1F,SAAS,gBAAgB,CAAC,GAAkB;IAC1C,OAAO,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAA4B;IACvD,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAErB,SAAS,MAAM;QACb,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,GAAG,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;YAC5D,MAAM,IAAI,iBAAiB,CAAC,GAAG,UAAU,oCAAoC,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,OAAO;QACL,QAAQ,CAAC,MAAM,EAAE,OAAO;YACtB,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC/E,CAAC;QACD,GAAG,CAAC,IAAI,EAAE,OAAO;YACf,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACrF,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,OAAO;YAChB,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACtF,CAAC;QACD,GAAG,CAAC,UAAU;YACZ,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACjF,CAAC;QACD;;;;;WAKG;QACH,eAAe,CAAC,KAAK;YACnB,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,IAAI,OAAO,GAAG,CAAC,eAAe,KAAK,UAAU,EAAE,CAAC;gBAC9C,MAAM,IAAI,iBAAiB,CACzB,GAAG,UAAU,0FAA0F,CACxG,CAAC;YACJ,CAAC;YACD,OAAO,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAClD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,32 @@
1
+ export declare function dshHome(): string;
2
+ export declare function profileDir(profileName: string): string;
3
+ /** Ensure dshloader is listed in the profile package.json dependencies. */
4
+ export declare function injectDependency(pkgPath: string): {
5
+ added: boolean;
6
+ manifest: any;
7
+ };
8
+ /** Ensure the dshloader insert entry exists in cordis.patch.yml (no reorder). */
9
+ export declare function injectPatch(patchPath: string): {
10
+ added: boolean;
11
+ text: string;
12
+ };
13
+ /**
14
+ * Run `dshloader setup <profile>`.
15
+ * @param profileName
16
+ * @returns
17
+ */
18
+ export declare function setupProfile(profileName: string): {
19
+ profileDir: string;
20
+ dependencyAdded: boolean;
21
+ patchAdded: boolean;
22
+ };
23
+ /** Best-effort dump-config validation. Returns { ok, output } (never throws). */
24
+ export declare function dumpConfig(profileName: string): {
25
+ ok: boolean;
26
+ output: string;
27
+ };
28
+ /** Print dshloader status for a profile (AC-OB-03, minimal). */
29
+ export declare function info(profileName?: string): {
30
+ loaderVersion: string;
31
+ dshVersion?: string;
32
+ };