@dsh-plugin/dsh-loader 1.1.0-dev.32287576957 → 1.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.
Files changed (62) hide show
  1. package/dist/adapters/dsh-1-x.js +4 -0
  2. package/dist/adapters/dsh-1-x.js.map +1 -1
  3. package/dist/api.d.ts +2 -0
  4. package/dist/api.js +18 -2
  5. package/dist/api.js.map +1 -1
  6. package/dist/client.d.ts +0 -1
  7. package/dist/client.js +13 -3
  8. package/dist/client.js.map +1 -1
  9. package/dist/index.js +7 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/patch.d.ts +112 -0
  12. package/dist/patch.js +179 -0
  13. package/dist/patch.js.map +1 -0
  14. package/dist/services/dsh-symbols.d.ts +70 -0
  15. package/dist/services/dsh-symbols.js +82 -0
  16. package/dist/services/dsh-symbols.js.map +1 -0
  17. package/dist/services/llm.d.ts +30 -0
  18. package/dist/services/llm.js +35 -0
  19. package/dist/services/llm.js.map +1 -0
  20. package/dist/services/registry.d.ts +144 -0
  21. package/dist/services/registry.js +209 -0
  22. package/dist/services/registry.js.map +1 -0
  23. package/dist/services/settings.d.ts +6 -0
  24. package/dist/services/settings.js +29 -1
  25. package/dist/services/settings.js.map +1 -1
  26. package/dist/services/web.js +20 -4
  27. package/dist/services/web.js.map +1 -1
  28. package/dist/setup.js +17 -1
  29. package/dist/setup.js.map +1 -1
  30. package/dist/types.d.ts +55 -0
  31. package/dist/version.d.ts +1 -1
  32. package/dist/version.js +1 -1
  33. package/lib/client.js +2775 -4
  34. package/lib/client.js.map +1 -1
  35. package/lib/types/adapters/dsh-1-x.d.ts +23 -0
  36. package/lib/types/adapters/index.d.ts +22 -0
  37. package/lib/types/client-ui.d.ts +40 -0
  38. package/lib/types/client.d.ts +156 -0
  39. package/lib/types/patch.d.ts +112 -0
  40. package/lib/types/registry.d.ts +35 -0
  41. package/lib/types/services/dsh-symbols.d.ts +70 -0
  42. package/lib/types/services/llm.d.ts +30 -0
  43. package/lib/types/services/registry.d.ts +144 -0
  44. package/lib/types/services/settings.d.ts +47 -0
  45. package/lib/types/types.d.ts +166 -0
  46. package/lib/types/ui/anchors.d.ts +56 -0
  47. package/lib/types/ui/components.d.ts +159 -0
  48. package/lib/types/ui/icons.d.ts +142 -0
  49. package/lib/types/ui/index.d.ts +30 -0
  50. package/lib/types/ui/menu.d.ts +104 -0
  51. package/lib/types/ui/slots.d.ts +152 -0
  52. package/lib/types/ui/style.d.ts +97 -0
  53. package/lib/types/version.d.ts +2 -0
  54. package/package.json +42 -9
  55. package/src/stable/compaction-basic.d.ts +1 -0
  56. package/src/stable/compaction-basic.js +5 -0
  57. package/src/stable/credentials.d.ts +1 -0
  58. package/src/stable/credentials.js +5 -0
  59. package/src/stable/subagent.d.ts +1 -0
  60. package/src/stable/subagent.js +5 -0
  61. package/src/stable/timeout.d.ts +1 -0
  62. package/src/stable/timeout.js +5 -0
@@ -0,0 +1,23 @@
1
+ import type { CordisContext, HostAdapterConfig } from '../types.js';
2
+ export declare const supports = ">=0.1.0-rc.1 <2.0.0";
3
+ export declare const name = "dsh-1-x";
4
+ export declare const BRIDGE_PREFIX = "/api/dshloader";
5
+ export declare const hostPackageAliases: Record<string, string>;
6
+ /**
7
+ * Install a Module._resolveFilename hook that maps old package names to
8
+ * new ones for CJS require() calls. Returns a dispose function that
9
+ * removes the hook.
10
+ */
11
+ export declare function installHostPackageAliases(aliases: Record<string, string>): Promise<() => void>;
12
+ /**
13
+ * @param ctx cordis context
14
+ * @param config
15
+ */
16
+ export declare function create(ctx: CordisContext, config?: HostAdapterConfig): HostAdapterType;
17
+ interface HostAdapterType {
18
+ supports: string;
19
+ name: string;
20
+ apply: () => Promise<void>;
21
+ dispose: () => void;
22
+ }
23
+ export {};
@@ -0,0 +1,22 @@
1
+ import type { AdapterFactory } from '../types.js';
2
+ import type { AdapterRegistry } from '../registry.js';
3
+ /** All host adapter factories, in registration order. */
4
+ export declare const hostAdapters: AdapterFactory[];
5
+ /** Register every built-in host adapter onto a registry. */
6
+ export declare function registerHostAdapters(registry: AdapterRegistry): AdapterRegistry;
7
+ export declare const clientAdapters: {
8
+ supports: string;
9
+ name: string;
10
+ moduleAliases: {
11
+ '@deepseek-ai/dsh-client-runtime/src/client/sessions/context-provenance.ts': string;
12
+ 'dsh/runtime/context-provenance': string;
13
+ };
14
+ packageAliases: {
15
+ '@dsh-plugin/dsh-loader/ui-primitives': string;
16
+ '@dsh-plugin/dsh-loader/ui-slots': string;
17
+ '@dsh-plugin/dsh-loader/web-react': string;
18
+ '@dsh-plugin/dsh-loader/schema-form': string;
19
+ '@dsh-plugin/dsh-loader/ui-settings': string;
20
+ '@dsh-plugin/dsh-loader/runtime': string;
21
+ };
22
+ }[];
@@ -0,0 +1,40 @@
1
+ import { type DshLoaderUi } from './ui/index.js';
2
+ export * from './ui/index.js';
3
+ export { createClientAPI, installClient, installSettingsFetchInterceptor, ModuleNotFoundError, } from './client.js';
4
+ /** cordis plugin name (matches the npm package name and the bundle id). */
5
+ export declare const name = "@dsh-plugin/dsh-loader";
6
+ /** dshloader consumes no cordis service; it only provides. */
7
+ export declare const inject: string[];
8
+ /**
9
+ * The UI facade for callers that reach dshloader through the module table rather
10
+ * than `window.__dshLoader__`.
11
+ *
12
+ * @returns the facade, or `undefined` before the client plugin has applied.
13
+ */
14
+ export declare function getUi(): DshLoaderUi | undefined;
15
+ /**
16
+ * The cordis client service name dshloader publishes its UI facade under.
17
+ *
18
+ * Consumers should declare `inject: ['dshLoaderUi']` and read `ctx.dshLoaderUi`:
19
+ * cordis then activates them only after dshloader's client half has applied,
20
+ * which is the only ordering guarantee available on the browser side.
21
+ * `dsh.client.immediately` guarantees the bundle's factory is REGISTERED early,
22
+ * not that its `apply` has run — so a plugin that reads
23
+ * `window.__dshLoader__.ui` without injecting can observe `undefined`.
24
+ */
25
+ export declare const UI_SERVICE = "dshLoaderUi";
26
+ /** Minimal cordis client context surface this entry touches. */
27
+ interface ClientContextLike {
28
+ get?: (name: string) => unknown;
29
+ effect?: (fn: () => unknown) => unknown;
30
+ provide?: (name: string, value: unknown) => unknown;
31
+ }
32
+ /**
33
+ * cordis client-plugin entry.
34
+ *
35
+ * Mounts the infrastructure first (so the `__ModuleLoader__` wrapper is in place
36
+ * before any sibling bundle materialises), then the UI facade, then publishes it
37
+ * both as the `dshLoaderUi` cordis service (ordered access) and on
38
+ * `window.__dshLoader__.ui` (ad-hoc access from non-cordis code).
39
+ */
40
+ export declare function apply(ctx: ClientContextLike): void;
@@ -0,0 +1,156 @@
1
+ /** Browser-only globals dshloader relies on (typed loosely so the module compiles without DOM lib). */
2
+ type FetchImpl = (input: any, init?: any) => Promise<{
3
+ clone(): {
4
+ json(): any;
5
+ };
6
+ json(): any;
7
+ }>;
8
+ interface DshLoaderWindowLike {
9
+ fetch: FetchImpl;
10
+ location?: {
11
+ origin?: string;
12
+ };
13
+ Response?: new (body?: string, init?: {
14
+ status?: number;
15
+ headers?: Record<string, string>;
16
+ }) => any;
17
+ __ModuleLoader__?: {
18
+ load(handoff: {
19
+ id: string;
20
+ factory: (require: (spec: string) => any) => any;
21
+ }): unknown;
22
+ };
23
+ __DSHLOADER_VERSION__?: string;
24
+ __DSHLOADER_CONFIG__?: {
25
+ exposeAllNamespaces?: boolean;
26
+ };
27
+ __dshNativeRequire__?: (spec: string) => any;
28
+ __dshLoader__?: unknown;
29
+ }
30
+ declare global {
31
+ }
32
+ export declare class ModuleNotFoundError extends Error {
33
+ specifier: string;
34
+ constructor(specifier: string);
35
+ }
36
+ interface CreateClientAPIOpts {
37
+ dshVersion?: string;
38
+ adapterVersion?: string;
39
+ moduleAliases?: Record<string, string>;
40
+ packageAliases?: Map<string, string> | Record<string, string>;
41
+ requireImpl?: (spec: string) => any;
42
+ fetchBridge?: {
43
+ describe: () => Promise<any>;
44
+ write: (mode: string, payload: object) => Promise<any>;
45
+ };
46
+ clientCtx?: {
47
+ get?: (name: string) => any;
48
+ };
49
+ }
50
+ /**
51
+ * Build the `window.__dshLoader__` API object.
52
+ */
53
+ export declare function createClientAPI(opts?: CreateClientAPIOpts): {
54
+ version: string;
55
+ dshVersion: string | undefined;
56
+ adapterVersion: string | undefined;
57
+ require(specifier: string): any;
58
+ registerModuleAlias(alias: string, target: string): void;
59
+ /**
60
+ * Register a package-name alias for the client module loader's
61
+ * require(). When a plugin's bundle calls require('@old/pkg-name'),
62
+ * the loader's wrapped require remaps it to '@new/pkg-name' before
63
+ * hitting the module table. This lets dsh rename client packages
64
+ * across versions without forcing plugin bundles to rebuild.
65
+ */
66
+ registerPackageAlias(oldName: string, newName: string): void;
67
+ /**
68
+ * Read a client-side cordis service by name.
69
+ * Proxies to `clientCtx.get(name)` — the same ctx.get plugins use
70
+ * inside their client `apply(ctx)`, but exposed through the stable
71
+ * dshloader surface so plugins don't depend on the cordis context
72
+ * shape directly.
73
+ *
74
+ * Only available when dshloader's client apply() received a ctx
75
+ * (cordis client boot). Returns undefined when ctx is not wired.
76
+ */
77
+ services: {
78
+ get(name: string): any;
79
+ };
80
+ rpc: {
81
+ settings: {
82
+ describe: () => Promise<any>;
83
+ update: (ns: string, section: unknown) => Promise<any>;
84
+ replace: (ns: string, section: unknown) => Promise<any>;
85
+ mutate: (ns: string, ops: unknown) => Promise<any>;
86
+ };
87
+ } | undefined;
88
+ };
89
+ interface InstallClientOpts {
90
+ window?: DshLoaderWindowLike;
91
+ dshVersion?: string;
92
+ exposeAllNamespaces?: boolean;
93
+ requireImpl?: (spec: string) => any;
94
+ hostBridgePrefix?: string;
95
+ packageAliases?: Record<string, string>;
96
+ clientCtx?: {
97
+ get?: (name: string) => any;
98
+ };
99
+ }
100
+ /**
101
+ * Install dshloader into a browser-like environment.
102
+ */
103
+ export declare function installClient(opts?: InstallClientOpts): {
104
+ version: string;
105
+ dshVersion: string | undefined;
106
+ adapterVersion: string | undefined;
107
+ require(specifier: string): any;
108
+ registerModuleAlias(alias: string, target: string): void;
109
+ /**
110
+ * Register a package-name alias for the client module loader's
111
+ * require(). When a plugin's bundle calls require('@old/pkg-name'),
112
+ * the loader's wrapped require remaps it to '@new/pkg-name' before
113
+ * hitting the module table. This lets dsh rename client packages
114
+ * across versions without forcing plugin bundles to rebuild.
115
+ */
116
+ registerPackageAlias(oldName: string, newName: string): void;
117
+ /**
118
+ * Read a client-side cordis service by name.
119
+ * Proxies to `clientCtx.get(name)` — the same ctx.get plugins use
120
+ * inside their client `apply(ctx)`, but exposed through the stable
121
+ * dshloader surface so plugins don't depend on the cordis context
122
+ * shape directly.
123
+ *
124
+ * Only available when dshloader's client apply() received a ctx
125
+ * (cordis client boot). Returns undefined when ctx is not wired.
126
+ */
127
+ services: {
128
+ get(name: string): any;
129
+ };
130
+ rpc: {
131
+ settings: {
132
+ describe: () => Promise<any>;
133
+ update: (ns: string, section: unknown) => Promise<any>;
134
+ replace: (ns: string, section: unknown) => Promise<any>;
135
+ mutate: (ns: string, ops: unknown) => Promise<any>;
136
+ };
137
+ } | undefined;
138
+ } | undefined;
139
+ /**
140
+ * Fetch interceptor for settings namespace whitelist bypass (fix 5, path 2).
141
+ * Mirrors dsh-upstream-fixes/lib/client.js (127-223).
142
+ *
143
+ * - /api/settings.describe: merge non-whitelisted namespaces from the host
144
+ * bridge into the official response (rpcId/official fields preserved).
145
+ * - /api/settings.{update,mutate,replace}: route writes for namespaces the
146
+ * official proxy does NOT expose through the host bridge, and rebuild the
147
+ * response envelope as `{ type: 'server-response', rpcId, result }` so the
148
+ * official client can correlate the response with the request.
149
+ */
150
+ export declare function installSettingsFetchInterceptor(win: DshLoaderWindowLike, bridgePrefix?: string): () => void;
151
+ export declare const name = "@dsh-plugin/dsh-loader";
152
+ export declare const inject: string[];
153
+ export declare function apply(ctx: {
154
+ get?: (name: string) => any;
155
+ }): void;
156
+ export {};
@@ -0,0 +1,112 @@
1
+ /**
2
+ * The dshloader PATCH protocol (`ctx.dshLoader.patch` / `__dshLoader__.patch`).
3
+ *
4
+ * Monkey-patching a host method or global is the only way to intervene in
5
+ * behaviour dsh exposes no extension point for. Three plugins in this family
6
+ * each hand-rolled the protocol and they did NOT agree:
7
+ *
8
+ * - dsh-loader's own `Module._resolveFilename` hook → identity-checked restore
9
+ * - dsh-network-settings' `globalThis.fetch` wrapper → identity-checked restore
10
+ * - dsh-better-sidebar's `workspaces.openPath` wrap → UNCONDITIONAL restore
11
+ *
12
+ * The last one silently destroys a later plugin's wrapper when it disposes
13
+ * first, even though its own comment promised the opposite. This module is the
14
+ * single correct implementation; every patch site delegates here.
15
+ *
16
+ * The five guarantees:
17
+ *
18
+ * 1. RAW original — each patch captures EXACTLY the value present when it
19
+ * installed (another plugin's wrapper when one is already there) and
20
+ * restores that value verbatim, never a bound copy. This is what lets a
21
+ * chain of wrappers survive disposal in any order.
22
+ * 2. Identity-checked restore — disposal only reverts the slot when it still
23
+ * holds OUR wrapper. If somebody patched on top afterwards, we leave the
24
+ * chain alone (reverting would delete their wrapper).
25
+ * 3. Re-apply safety — re-applying the same `id` recovers the true original
26
+ * first, so HMR / repeated `apply()` can never nest a wrapper in itself.
27
+ * This holds while our patch is the OUTERMOST one; if a foreign patch was
28
+ * layered on top in between, re-applying chains instead (un-nesting a
29
+ * middle wrapper is not possible without rebuilding the whole chain).
30
+ * 4. Cross-instance durability — slot bookkeeping lives in a WeakMap parked on
31
+ * `globalThis` under a `Symbol.for` key, so a reloaded module instance still
32
+ * sees the original captured by its predecessor. Targets are never mutated.
33
+ * 5. Loud misuse — patching a non-function method, or a missing target, throws
34
+ * instead of silently no-op'ing.
35
+ *
36
+ * Pure and environment-agnostic: no DOM, no Node builtins, so the same module
37
+ * serves the host half and the browser half.
38
+ *
39
+ * @module @dsh-plugin/dsh-loader/patch
40
+ */
41
+ /** A live patch, disposed through {@link PatchHandle.dispose}. */
42
+ export interface PatchHandle {
43
+ /** Remove this patch when the slot still carries its wrapper (idempotent). */
44
+ dispose(): void;
45
+ /** Whether the target slot still carries this patch's wrapper. */
46
+ readonly active: boolean;
47
+ /** The raw value captured before any dshloader patch touched the slot. */
48
+ readonly original: unknown;
49
+ }
50
+ /** Options shared by every patch entry point. */
51
+ export interface PatchOptions {
52
+ /**
53
+ * Stable patch id. Re-applying the same id on the same slot recovers the
54
+ * true original before re-wrapping (guarantee 3), so HMR cannot nest
55
+ * wrappers. Defaults to `'anonymous'` — pass a real id (`'<plugin>:<what>'`)
56
+ * for any patch that can be re-applied.
57
+ */
58
+ id?: string;
59
+ }
60
+ /**
61
+ * Patch one slot of `target`. The low-level primitive behind
62
+ * {@link PatchAPI.method} and {@link PatchAPI.global}.
63
+ *
64
+ * @param target - object owning the slot (a service instance, `globalThis`, …).
65
+ * @param key - property key to wrap.
66
+ * @param wrap - receives the value currently in the slot (the previous wrapper
67
+ * when another patch is already installed — chaining is intended) and returns
68
+ * the replacement.
69
+ * @param options - see {@link PatchOptions}.
70
+ * @returns the handle whose `dispose()` reverts this patch.
71
+ */
72
+ export declare function patchSlot<T = unknown>(target: object, key: PropertyKey, wrap: (original: T) => T, options?: PatchOptions): PatchHandle;
73
+ /** Whether a dshloader patch is currently installed on `target[key]`. */
74
+ export declare function isPatched(target: object, key: PropertyKey): boolean;
75
+ /** The patch id currently installed on `target[key]`, or `undefined`. */
76
+ export declare function patchIdOf(target: object, key: PropertyKey): string | undefined;
77
+ /** The stable `patch` facade exposed on the host and browser APIs. */
78
+ export interface PatchAPI {
79
+ /**
80
+ * Wrap a method of a service / object.
81
+ *
82
+ * ```ts
83
+ * const handle = ctx.dshLoader.patch.method(
84
+ * workspaces, 'openPath',
85
+ * original => (path: string) => takeover(path) ?? original.call(workspaces, path),
86
+ * { id: 'better-sidebar:openPath' },
87
+ * )
88
+ * ```
89
+ */
90
+ method<T extends object, K extends keyof T>(target: T, key: K, wrap: (original: T[K]) => T[K], options?: PatchOptions): PatchHandle;
91
+ /**
92
+ * Wrap a global function such as `fetch`. Defaults to `globalThis`; pass
93
+ * `scope` for `window` or a test double.
94
+ *
95
+ * ```ts
96
+ * ctx.dshLoader.patch.global('fetch',
97
+ * original => (input, init) => original(rewrite(input), init),
98
+ * { id: 'network-settings:fetch' })
99
+ * ```
100
+ */
101
+ global<T = unknown>(key: PropertyKey, wrap: (original: T) => T, options?: PatchOptions & {
102
+ scope?: object;
103
+ }): PatchHandle;
104
+ /** Low-level primitive; `method`/`global` are thin wrappers over it. */
105
+ slot<T = unknown>(target: object, key: PropertyKey, wrap: (original: T) => T, options?: PatchOptions): PatchHandle;
106
+ /** Whether a dshloader patch currently occupies `target[key]`. */
107
+ isPatched(target: object, key: PropertyKey): boolean;
108
+ /** The patch id currently occupying `target[key]`, if any. */
109
+ patchIdOf(target: object, key: PropertyKey): string | undefined;
110
+ }
111
+ /** Build the `patch` facade. Stateless — all bookkeeping is in the global registry. */
112
+ export declare function createPatchAPI(): PatchAPI;
@@ -0,0 +1,35 @@
1
+ import type { AdapterFactory, AdapterSelection } from './types.js';
2
+ interface DshVersionOptions {
3
+ profileDir?: string;
4
+ dshPkgPath?: string;
5
+ env?: typeof process.env;
6
+ }
7
+ export declare class UnsupportedDshVersionError extends Error {
8
+ kind?: string;
9
+ version?: string;
10
+ minSupported?: string | null;
11
+ constructor(message: string, opts?: {
12
+ kind?: string;
13
+ version?: string;
14
+ minSupported?: string | null;
15
+ });
16
+ }
17
+ export declare class InvalidVersionError extends Error {
18
+ version?: string;
19
+ constructor(message: string, opts?: {
20
+ version?: string;
21
+ });
22
+ }
23
+ /**
24
+ * Resolve the installed dsh version.
25
+ *
26
+ * @returns semver version string, or undefined when unreachable
27
+ */
28
+ export declare function detectDshVersion(opts?: DshVersionOptions): string | undefined;
29
+ export declare class AdapterRegistry {
30
+ adapters: AdapterFactory[];
31
+ constructor();
32
+ register(factory: AdapterFactory): this;
33
+ select(version: string): AdapterSelection;
34
+ }
35
+ export {};
@@ -0,0 +1,70 @@
1
+ /** Node's `setTimeout` ceiling (2^31 - 1), used when dsh-timeout is unavailable. */
2
+ export declare const NODE_MAX_TIMER_DELAY_MS = 2147483647;
3
+ /** The raw modules this facade forwards to, as resolved at boot. */
4
+ export interface DshSymbolModules {
5
+ tools?: {
6
+ defineTool?: unknown;
7
+ ToolArgsError?: unknown;
8
+ };
9
+ timeout?: {
10
+ deadline?: unknown;
11
+ MAX_TIMER_DELAY_MS?: number;
12
+ };
13
+ credentials?: {
14
+ credentialRef?: unknown;
15
+ };
16
+ subagent?: {
17
+ delegationDepthOf?: unknown;
18
+ };
19
+ compaction?: {
20
+ BasicCompactionEngine?: unknown;
21
+ };
22
+ llm?: {
23
+ BlockAssembler?: unknown;
24
+ };
25
+ }
26
+ /**
27
+ * Module-level dsh symbols, grouped by owning package.
28
+ *
29
+ * Types are deliberately loose (`any`-shaped call signatures): pinning dsh's
30
+ * internal shapes here would defeat the shim's purpose, exactly as
31
+ * `src/types.ts` explains for the service surfaces.
32
+ */
33
+ export interface DshSymbolsAPI {
34
+ tools: {
35
+ /** `defineTool(definition)` — build a tool definition dsh's registry accepts. */
36
+ defineTool<T>(definition: T): T;
37
+ /** `ToolArgsError` — the error class dsh expects for invalid tool arguments. */
38
+ readonly ToolArgsError: new (messages: string[]) => Error;
39
+ };
40
+ timeout: {
41
+ /** `deadline(...)` — dsh's cancellation-aware deadline helper. */
42
+ deadline<T>(...args: any[]): T;
43
+ /** dsh's timer ceiling; falls back to Node's own 2^31-1 when unavailable. */
44
+ readonly MAX_TIMER_DELAY_MS: number;
45
+ };
46
+ credentials: {
47
+ /** `credentialRef(ref)` — brand a raw reference for `credentials.resolve`. */
48
+ credentialRef(ref: unknown): unknown;
49
+ };
50
+ subagent: {
51
+ /** `delegationDepthOf(agent)` — how deep a delegated agent sits. */
52
+ delegationDepthOf(agent: unknown): number;
53
+ };
54
+ compaction: {
55
+ /**
56
+ * `BasicCompactionEngine` — the base class a plugin subclasses to override
57
+ * `summarize`. Throws when unavailable, because a subclass declaration has
58
+ * no meaningful fallback.
59
+ */
60
+ readonly BasicCompactionEngine: new (...args: any[]) => any;
61
+ };
62
+ llm: {
63
+ /** `BlockAssembler` — dsh's streaming content-block assembler. */
64
+ readonly BlockAssembler: new (...args: any[]) => any;
65
+ };
66
+ }
67
+ /** Build the `ctx.dshLoader.dsh` facade over boot-resolved modules. */
68
+ export declare function createDshSymbolsAPI(opts: {
69
+ modules?: DshSymbolModules;
70
+ }): DshSymbolsAPI;
@@ -0,0 +1,30 @@
1
+ /** The `@deepseek-ai/dsh-llm` surface the facades forward to. */
2
+ export interface LlmModule {
3
+ createUserMessage?: (input: unknown) => unknown;
4
+ deepFreeze?: <T>(value: T) => T;
5
+ /** Streaming content-block assembler; surfaced through `dshLoader.dsh.llm`. */
6
+ BlockAssembler?: unknown;
7
+ }
8
+ /** The `llm` facade exposed on the host API. */
9
+ export interface LlmAPI {
10
+ /**
11
+ * Build one identified, frozen user-role message.
12
+ *
13
+ * @param input - complete content and source for a new user message.
14
+ * @returns the immutable message.
15
+ * @throws when `@deepseek-ai/dsh-llm` is unavailable — callers building a
16
+ * message have no meaningful fallback, so this fails loudly rather than
17
+ * handing back something the agent loop would reject.
18
+ */
19
+ createUserMessage(input: unknown): unknown;
20
+ /**
21
+ * Deep-freeze a value with dsh's own helper (so frozen-ness matches what the
22
+ * runtime expects). Falls back to `Object.freeze` on the top level when the
23
+ * module is unavailable.
24
+ */
25
+ deepFreeze<T>(value: T): T;
26
+ }
27
+ /** Build the `ctx.dshLoader.llm` facade. */
28
+ export declare function createLlmAPI(opts: {
29
+ module?: LlmModule;
30
+ }): LlmAPI;
@@ -0,0 +1,144 @@
1
+ import type { CordisContext } from '../types.js';
2
+ /** A live tool definition as the tools registry holds it (shape kept loose on purpose). */
3
+ export interface ToolDefinitionLike {
4
+ name?: string;
5
+ description?: string;
6
+ parameters?: Record<string, unknown>;
7
+ execute?: (args: Record<string, unknown>, exec: unknown) => Promise<unknown>;
8
+ [key: string]: unknown;
9
+ }
10
+ /** One permission preset row as the `permissionPresets` table stores it. */
11
+ export interface PermissionPresetLike {
12
+ sandbox: string;
13
+ approval: string;
14
+ name?: string;
15
+ description?: string;
16
+ [key: string]: unknown;
17
+ }
18
+ /** The optional dsh modules the facades need, resolved once at boot. */
19
+ export interface RegistryModules {
20
+ /** `@deepseek-ai/dsh-sandbox` — for `ESCALATION_TARGETS`. */
21
+ sandbox?: {
22
+ ESCALATION_TARGETS?: readonly string[];
23
+ };
24
+ /** `@deepseek-ai/dsh-permission-presets` — for `effectivePermissionPreset`. */
25
+ permissionPresets?: {
26
+ effectivePermissionPreset?: (events: readonly unknown[]) => string | undefined;
27
+ };
28
+ /**
29
+ * `@deepseek-ai/dsh-settings` — the settings facade DELEGATES to these rather
30
+ * than reimplementing them. `installSettingsSection` in particular carries
31
+ * real upstream behaviour (register `base` from the composition entry, point
32
+ * the source thunk at the resolved scope, fall back to the entry when the
33
+ * service goes away, all riding the scoped fiber); copying that into a shim
34
+ * would be a bug farm.
35
+ */
36
+ settings?: {
37
+ installSettingsSection?: (ctx: unknown, ns: unknown, schema: unknown, entry: unknown, hooks: unknown) => void;
38
+ settingsNamespace?: (id: string) => unknown;
39
+ SettingsConflictError?: new (...args: never[]) => Error;
40
+ };
41
+ /**
42
+ * `@deepseek-ai/dsh-llm` — message-construction helpers are MODULE-level
43
+ * exports, not service methods, so `services.get('llm')` cannot reach them.
44
+ */
45
+ llm?: import('./llm.js').LlmModule;
46
+ /** `@deepseek-ai/dsh-tools` — `defineTool` / `ToolArgsError` are module-level. */
47
+ tools?: {
48
+ defineTool?: unknown;
49
+ ToolArgsError?: unknown;
50
+ };
51
+ /** `@deepseek-ai/dsh-timeout` — `deadline` / `MAX_TIMER_DELAY_MS`. */
52
+ timeout?: {
53
+ deadline?: unknown;
54
+ MAX_TIMER_DELAY_MS?: number;
55
+ };
56
+ /** `@deepseek-ai/dsh-credentials` — `credentialRef`. */
57
+ credentials?: {
58
+ credentialRef?: unknown;
59
+ };
60
+ /** `@deepseek-ai/dsh-subagent` — `delegationDepthOf`. */
61
+ subagent?: {
62
+ delegationDepthOf?: unknown;
63
+ };
64
+ /** `@deepseek-ai/dsh-compaction-basic` — the `BasicCompactionEngine` base class. */
65
+ compaction?: {
66
+ BasicCompactionEngine?: unknown;
67
+ };
68
+ }
69
+ /**
70
+ * Load the optional dsh modules the facades proxy.
71
+ *
72
+ * The specifiers are held in variables so TypeScript does not try to resolve
73
+ * them at build time: dshloader declares no `@deepseek-ai/*` dependency, and
74
+ * these packages only exist in the dsh runtime that loads the profile.
75
+ *
76
+ * @returns whatever resolved; a missing module simply stays `undefined`.
77
+ */
78
+ export declare function preloadRegistryModules(): Promise<RegistryModules>;
79
+ /** Tool-registry accessors. */
80
+ export interface ToolsRegistryAPI {
81
+ /** Every registered tool definition; `[]` when the registry shape is unreachable. */
82
+ list(): ToolDefinitionLike[];
83
+ /** One definition by tool name. */
84
+ get(name: string): ToolDefinitionLike | undefined;
85
+ /**
86
+ * Run `patcher` over every registered definition now and after every
87
+ * `tools/change`, so load order between this plugin and the tool plugins does
88
+ * not matter.
89
+ *
90
+ * A definition is handed to a given `id` at most once (a non-enumerable
91
+ * `Symbol.for` marker on the definition), which is what stops a `tools/change`
92
+ * storm from wrapping `execute` again and again.
93
+ *
94
+ * @param patcher - mutates one live definition; throwing is contained and logged.
95
+ * @param options.id - stable patch id, used for the once-per-definition marker.
96
+ * @returns a disposer that stops the replay (already-applied patches stay).
97
+ */
98
+ patchAll(patcher: (def: ToolDefinitionLike) => void, options: {
99
+ id: string;
100
+ }): () => void;
101
+ }
102
+ /** Sandbox-registry accessors. */
103
+ export interface SandboxRegistryAPI {
104
+ /** The escalation modes escalation tools advertise; `[]` when unreachable. */
105
+ escalationTargets(): readonly string[];
106
+ /**
107
+ * Advertise one extra escalation mode (idempotent).
108
+ * @returns a disposer removing the mode again; a no-op when unreachable.
109
+ */
110
+ addEscalationTarget(mode: string): () => void;
111
+ }
112
+ /** Permission-preset registry accessors. */
113
+ export interface PermissionPresetsRegistryAPI {
114
+ /** The live preset table, or `undefined` when the service is absent. */
115
+ table(): Record<string, PermissionPresetLike> | undefined;
116
+ /**
117
+ * Define a preset unless the key already exists (declaration in a
118
+ * `cordis.patch.yml` layer wins).
119
+ * @returns a disposer removing only a preset this call actually added.
120
+ */
121
+ define(key: string, preset: PermissionPresetLike): () => void;
122
+ /**
123
+ * Fold a session's effective permission-preset key from its event log.
124
+ * @returns the preset key, or `undefined` when the helper is unavailable.
125
+ */
126
+ effective(events: readonly unknown[]): string | undefined;
127
+ }
128
+ /** The `registry` facade exposed on the host API. */
129
+ export interface RegistryAPI {
130
+ tools: ToolsRegistryAPI;
131
+ sandbox: SandboxRegistryAPI;
132
+ permissionPresets: PermissionPresetsRegistryAPI;
133
+ }
134
+ /**
135
+ * Build the `ctx.dshLoader.registry` facade.
136
+ *
137
+ * @param opts.ctx - the cordis context (services are read lazily, never cached,
138
+ * so a service arriving later is still picked up).
139
+ * @param opts.modules - optional dsh modules from {@link preloadRegistryModules}.
140
+ */
141
+ export declare function createRegistryAPI(opts: {
142
+ ctx: CordisContext;
143
+ modules?: RegistryModules;
144
+ }): RegistryAPI;