@tiphareth/dsh-hardssh 0.1.2
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/README.md +50 -0
- package/cordis.patch.yml +26 -0
- package/lib/client.js +17780 -0
- package/lib/environment-BL1jddfB.js +449 -0
- package/lib/fs.js +478 -0
- package/lib/index.js +6758 -0
- package/lib/subprocess.js +600 -0
- package/lib/switch-fs-CAJpFY9C.js +193 -0
- package/lib/switch-fs-RrZtG2gv.js +210 -0
- package/lib/types/backend.d.ts +108 -0
- package/lib/types/base/capability.d.ts +107 -0
- package/lib/types/base/index.d.ts +18 -0
- package/lib/types/base/ledger-router.d.ts +48 -0
- package/lib/types/base/ledger.d.ts +82 -0
- package/lib/types/base/model.d.ts +108 -0
- package/lib/types/base/namespace.d.ts +57 -0
- package/lib/types/base/plugin.d.ts +102 -0
- package/lib/types/base/registry.d.ts +60 -0
- package/lib/types/base/router.d.ts +40 -0
- package/lib/types/client/api.d.ts +85 -0
- package/lib/types/client/directory-flow.d.ts +82 -0
- package/lib/types/client/icons.d.ts +19 -0
- package/lib/types/client/index.d.ts +34 -0
- package/lib/types/client/locales.d.ts +104 -0
- package/lib/types/client/manager-button.d.ts +32 -0
- package/lib/types/client/migrate.d.ts +20 -0
- package/lib/types/client/ssh/api.d.ts +89 -0
- package/lib/types/client/ssh/apply.d.ts +23 -0
- package/lib/types/client/ssh/locales.d.ts +156 -0
- package/lib/types/client/ssh/mount.d.ts +13 -0
- package/lib/types/client/ssh/panel/ClusterTab.d.ts +8 -0
- package/lib/types/client/ssh/panel/HostFingerprintDialog.d.ts +16 -0
- package/lib/types/client/ssh/panel/HostFormDialog.d.ts +13 -0
- package/lib/types/client/ssh/panel/HostsTab.d.ts +10 -0
- package/lib/types/client/ssh/panel/SessionSecretDialog.d.ts +16 -0
- package/lib/types/client/ssh/panel/SshPanel.d.ts +14 -0
- package/lib/types/client/ssh/panel/TerminalTab.d.ts +12 -0
- package/lib/types/client/ssh/panel/TransferTab.d.ts +8 -0
- package/lib/types/client/ssh/panel/TunnelsTab.d.ts +8 -0
- package/lib/types/client/ssh/panel/controller.d.ts +23 -0
- package/lib/types/client/ssh/panel/helpers.d.ts +15 -0
- package/lib/types/client/ssh/panel/xterm.css.d.ts +3 -0
- package/lib/types/client/ssh/sidebar-entry.d.ts +25 -0
- package/lib/types/client/state.d.ts +32 -0
- package/lib/types/client/text.d.ts +11 -0
- package/lib/types/client/workspace-badges.d.ts +38 -0
- package/lib/types/client/workspace-gate.d.ts +15 -0
- package/lib/types/client-http.d.ts +15 -0
- package/lib/types/core.d.ts +43 -0
- package/lib/types/fs.d.ts +36 -0
- package/lib/types/host-http.d.ts +25 -0
- package/lib/types/index.d.ts +53 -0
- package/lib/types/ledger.d.ts +132 -0
- package/lib/types/protocol.d.ts +101 -0
- package/lib/types/providers/index.d.ts +19 -0
- package/lib/types/providers/local/provider.d.ts +58 -0
- package/lib/types/providers/ssh/provider.d.ts +112 -0
- package/lib/types/remote/environment.d.ts +29 -0
- package/lib/types/remote/output.d.ts +38 -0
- package/lib/types/remote/remote-fs.d.ts +69 -0
- package/lib/types/remote/remote-process.d.ts +41 -0
- package/lib/types/remote/remote-subprocess.d.ts +31 -0
- package/lib/types/remote/remote-terminal.d.ts +41 -0
- package/lib/types/remote-runner.d.ts +83 -0
- package/lib/types/remote-search.d.ts +50 -0
- package/lib/types/routes.d.ts +24 -0
- package/lib/types/runtime/workspace-core.d.ts +59 -0
- package/lib/types/seam-state.d.ts +69 -0
- package/lib/types/shell.d.ts +8 -0
- package/lib/types/ssh/connection/lease.d.ts +16 -0
- package/lib/types/ssh/connection/pool.d.ts +57 -0
- package/lib/types/ssh/engine.d.ts +434 -0
- package/lib/types/ssh/exec/output.d.ts +31 -0
- package/lib/types/ssh/known-hosts.d.ts +89 -0
- package/lib/types/ssh/plugin.d.ts +57 -0
- package/lib/types/ssh/protocol.d.ts +236 -0
- package/lib/types/ssh/routes.d.ts +44 -0
- package/lib/types/ssh/store.d.ts +107 -0
- package/lib/types/ssh/tools.d.ts +35 -0
- package/lib/types/ssh/transfer/progress.d.ts +14 -0
- package/lib/types/ssh/vault.d.ts +110 -0
- package/lib/types/subprocess.d.ts +32 -0
- package/lib/types/switch/switch-fs.d.ts +88 -0
- package/lib/types/switch/switch-subprocess.d.ts +34 -0
- package/lib/types/tools.d.ts +12 -0
- package/package.json +134 -0
- package/src/backend.ts +624 -0
- package/src/base/capability.ts +86 -0
- package/src/base/index.ts +18 -0
- package/src/base/ledger-router.ts +128 -0
- package/src/base/ledger.ts +299 -0
- package/src/base/model.ts +118 -0
- package/src/base/namespace.ts +102 -0
- package/src/base/plugin.ts +170 -0
- package/src/base/registry.ts +109 -0
- package/src/base/router.ts +43 -0
- package/src/client/api.ts +196 -0
- package/src/client/css-modules.d.ts +5 -0
- package/src/client/directory-flow.tsx +482 -0
- package/src/client/icons.tsx +50 -0
- package/src/client/index.ts +210 -0
- package/src/client/locales.ts +105 -0
- package/src/client/manager-button.tsx +269 -0
- package/src/client/migrate.ts +109 -0
- package/src/client/ssh/api.ts +411 -0
- package/src/client/ssh/apply.ts +50 -0
- package/src/client/ssh/locales.ts +322 -0
- package/src/client/ssh/mount.tsx +83 -0
- package/src/client/ssh/panel/ClusterTab.tsx +123 -0
- package/src/client/ssh/panel/HostFingerprintDialog.tsx +82 -0
- package/src/client/ssh/panel/HostFormDialog.tsx +228 -0
- package/src/client/ssh/panel/HostsTab.tsx +236 -0
- package/src/client/ssh/panel/SessionSecretDialog.tsx +80 -0
- package/src/client/ssh/panel/SshPanel.tsx +77 -0
- package/src/client/ssh/panel/TerminalTab.tsx +176 -0
- package/src/client/ssh/panel/TransferTab.tsx +232 -0
- package/src/client/ssh/panel/TunnelsTab.tsx +177 -0
- package/src/client/ssh/panel/controller.ts +48 -0
- package/src/client/ssh/panel/helpers.ts +26 -0
- package/src/client/ssh/panel/panel.module.css +1006 -0
- package/src/client/ssh/panel/xterm.css.ts +2 -0
- package/src/client/ssh/sidebar-entry.ts +123 -0
- package/src/client/state.ts +99 -0
- package/src/client/text.ts +22 -0
- package/src/client/workspace-badges.ts +96 -0
- package/src/client/workspace-gate.ts +225 -0
- package/src/client/workspace.module.css +283 -0
- package/src/client-http.ts +45 -0
- package/src/core.ts +47 -0
- package/src/fs.ts +85 -0
- package/src/host-http.ts +74 -0
- package/src/index.ts +244 -0
- package/src/ledger.ts +416 -0
- package/src/protocol.ts +114 -0
- package/src/providers/index.ts +34 -0
- package/src/providers/local/provider.ts +179 -0
- package/src/providers/ssh/provider.ts +274 -0
- package/src/remote/environment.ts +123 -0
- package/src/remote/output.ts +142 -0
- package/src/remote/remote-fs.ts +532 -0
- package/src/remote/remote-process.ts +203 -0
- package/src/remote/remote-subprocess.ts +159 -0
- package/src/remote/remote-terminal.ts +141 -0
- package/src/remote-runner.ts +201 -0
- package/src/remote-search.ts +163 -0
- package/src/routes.ts +395 -0
- package/src/runtime/workspace-core.ts +154 -0
- package/src/seam-state.ts +185 -0
- package/src/shell.ts +10 -0
- package/src/ssh/connection/lease.ts +17 -0
- package/src/ssh/connection/pool.ts +275 -0
- package/src/ssh/engine.ts +1761 -0
- package/src/ssh/exec/output.ts +70 -0
- package/src/ssh/known-hosts.ts +214 -0
- package/src/ssh/plugin.ts +184 -0
- package/src/ssh/protocol.ts +227 -0
- package/src/ssh/routes.ts +892 -0
- package/src/ssh/store.ts +544 -0
- package/src/ssh/tools.ts +402 -0
- package/src/ssh/transfer/progress.ts +75 -0
- package/src/ssh/vault.ts +477 -0
- package/src/subprocess.ts +71 -0
- package/src/switch/switch-fs.ts +253 -0
- package/src/switch/switch-subprocess.ts +59 -0
- package/src/tools.ts +221 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sidebar entry injection.
|
|
3
|
+
*
|
|
4
|
+
* dsh's sidebar shell exposes no slot an external plugin can register into,
|
|
5
|
+
* so — following the task-board precedent of DOM-level extension — the entry
|
|
6
|
+
* row is injected between the shell's New Session button and the workspace
|
|
7
|
+
* browser. The injection self-heals: a MutationObserver watches the sidebar
|
|
8
|
+
* root and re-inserts the row whenever a React re-render displaces it
|
|
9
|
+
* (re-insertion happens in the same frame, before paint, so no flicker).
|
|
10
|
+
*
|
|
11
|
+
* The row is plain DOM (no React tree) so it can never disturb the shell's
|
|
12
|
+
* reconciliation; the panel view it toggles is a separate React root mounted
|
|
13
|
+
* in the center column (see mount.tsx).
|
|
14
|
+
*/
|
|
15
|
+
import type { PanelController } from './panel/controller.ts';
|
|
16
|
+
/** Stable data attribute identifying the injected entry row. */
|
|
17
|
+
export declare const ENTRY_SELECTOR = "[data-dsh-ssh-entry]";
|
|
18
|
+
/**
|
|
19
|
+
* Mount the sidebar entry, waiting for the shell to render and self-healing
|
|
20
|
+
* on later React re-renders.
|
|
21
|
+
* @param controller - the panel controller the entry toggles.
|
|
22
|
+
* @returns disposer removing the entry and its observers.
|
|
23
|
+
*/
|
|
24
|
+
export declare function mountSidebarEntry(controller: PanelController): () => void;
|
|
25
|
+
//# sourceMappingURL=sidebar-entry.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side SSH workspace state: the list of SSH-bound workspaces plus a
|
|
3
|
+
* light poll (3s) keeping it fresh. The snapshot is replaced only on
|
|
4
|
+
* successful fetches, so React's useSyncExternalStore sees stable references
|
|
5
|
+
* between polls. There is NO global local/remote mode anymore — a session's
|
|
6
|
+
* execution world is decided host-side by its cwd (an anchor path of an SSH
|
|
7
|
+
* workspace routes remote); this client state only drives the management UI
|
|
8
|
+
* (list / create / delete) and the sidebar title annotations.
|
|
9
|
+
*/
|
|
10
|
+
import type { SshWorkspaceRecord } from '../protocol.ts';
|
|
11
|
+
import type { WorkspaceApi } from './api.ts';
|
|
12
|
+
export interface WorkspaceManagerState {
|
|
13
|
+
/** SSH-bound workspaces, in creation order. */
|
|
14
|
+
workspaces: SshWorkspaceRecord[];
|
|
15
|
+
/** Whether the last load failed (keeps the previous list). */
|
|
16
|
+
error: string | null;
|
|
17
|
+
}
|
|
18
|
+
export declare class WorkspaceManager {
|
|
19
|
+
private readonly api;
|
|
20
|
+
private state;
|
|
21
|
+
private readonly listeners;
|
|
22
|
+
private timer;
|
|
23
|
+
constructor(api: WorkspaceApi);
|
|
24
|
+
getSnapshot(): WorkspaceManagerState;
|
|
25
|
+
subscribe(listener: () => void): () => void;
|
|
26
|
+
private emit;
|
|
27
|
+
refresh(): Promise<void>;
|
|
28
|
+
start(): void;
|
|
29
|
+
stop(): void;
|
|
30
|
+
remove(id: string): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny localization helper: resolves the active dictionary (zh when the
|
|
3
|
+
* document language starts with zh, else en). The dictionary is swapped by
|
|
4
|
+
* the plugin's apply() on <html lang> changes.
|
|
5
|
+
*/
|
|
6
|
+
import { type WorkspaceKey } from './locales.ts';
|
|
7
|
+
/** Switch the active dictionary (called by the client entry on lang change). */
|
|
8
|
+
export declare function setLanguage(zhMode: boolean): void;
|
|
9
|
+
/** Resolve one copy key (supports %s / %d substitution). */
|
|
10
|
+
export declare function tt(key: WorkspaceKey, ...args: Array<string | number>): string;
|
|
11
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sidebar workspace-row augmentation: labels every host workspace row whose
|
|
3
|
+
* title matches an SSH-bound workspace with a compact remote badge
|
|
4
|
+
* (`alias @ remoteRoot`), so a glance tells a local workspace from a remote
|
|
5
|
+
* one. Pure DOM-level extension (the sidebar shell exposes no slot for row
|
|
6
|
+
* decoration), following the dsh-ssh sidebar-entry precedent: a
|
|
7
|
+
* MutationObserver self-heals when React re-renders displace the injected
|
|
8
|
+
* badge.
|
|
9
|
+
*
|
|
10
|
+
* The row title alone matches: SSH-bound workspace titles are unique enough
|
|
11
|
+
* in practice (the ledger title is what the row shows). A title match against
|
|
12
|
+
* `~/.dsh/ssh-workspaces/<id>` anchors also works when the host picks that
|
|
13
|
+
* default title.
|
|
14
|
+
*
|
|
15
|
+
* @module dsh-hardssh/client/workspace-badges
|
|
16
|
+
*/
|
|
17
|
+
/** Render a small remote badge element. The cloud icon marks "remote";
|
|
18
|
+
* connected servers render in DeepSeek blue, disconnected stay gray. The
|
|
19
|
+
* tooltip shows the REMOTE directory plus the server, e.g.
|
|
20
|
+
* `/data/app (prod-01)`. */
|
|
21
|
+
export declare function makeBadge(alias: string, remoteRoot: string, connected: boolean): HTMLElement;
|
|
22
|
+
/**
|
|
23
|
+
* Mount the row-decoration pass. Queries the sidebar for project rows and
|
|
24
|
+
* appends a remote badge when the row's title belongs to an SSH workspace.
|
|
25
|
+
* Badges of aliases in `connected` render blue, others gray. Self-heals via
|
|
26
|
+
* MutationObserver on the sidebar container (rows re-render on
|
|
27
|
+
* session/workspace changes).
|
|
28
|
+
* @param workspaces - the SSH workspace records (id/title/alias/remoteRoot).
|
|
29
|
+
* @param connected - aliases with a live pooled connection (badge coloring).
|
|
30
|
+
* @returns disposer.
|
|
31
|
+
*/
|
|
32
|
+
export declare function mountWorkspaceBadges(workspaces: Array<{
|
|
33
|
+
id: string;
|
|
34
|
+
title: string;
|
|
35
|
+
alias: string;
|
|
36
|
+
remoteRoot: string;
|
|
37
|
+
}>, connected?: ReadonlySet<string>): () => void;
|
|
38
|
+
//# sourceMappingURL=workspace-badges.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SshApi } from './ssh/api.ts';
|
|
2
|
+
/** Silent prompt-only connection gate (no row / banner) for flows that
|
|
3
|
+
* surface their own errors (e.g. the directory browser). */
|
|
4
|
+
export declare function connectHost(api: SshApi, alias: string): Promise<boolean>;
|
|
5
|
+
/**
|
|
6
|
+
* Mount the click gate over every sidebar workspace row whose title belongs
|
|
7
|
+
* to an SSH-bound workspace. Self-heals via MutationObserver. Returns a
|
|
8
|
+
* disposer that removes listeners and injected state.
|
|
9
|
+
*/
|
|
10
|
+
export declare function mountWorkspaceGates(workspaces: Array<{
|
|
11
|
+
id: string;
|
|
12
|
+
title: string;
|
|
13
|
+
alias: string;
|
|
14
|
+
}>, api: SshApi): () => void;
|
|
15
|
+
//# sourceMappingURL=workspace-gate.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-side HTTP helpers for the dsh-hardssh route clients.
|
|
3
|
+
* Plain fetch / same-origin — bundled inline into the client bundle.
|
|
4
|
+
*/
|
|
5
|
+
/** Error carrying the route's JSON error message and stable code/status. */
|
|
6
|
+
export declare class HttpApiError extends Error {
|
|
7
|
+
readonly code?: string | undefined;
|
|
8
|
+
readonly status?: number | undefined;
|
|
9
|
+
constructor(message: string, code?: string | undefined, status?: number | undefined);
|
|
10
|
+
}
|
|
11
|
+
/** Query-string helper (skips undefined and empty values). */
|
|
12
|
+
export declare function buildQuery(params: Record<string, string | number | undefined>): string;
|
|
13
|
+
/** Parse a JSON response or throw an HttpApiError (code/status preserved). */
|
|
14
|
+
export declare function readJson<T>(response: Response): Promise<T>;
|
|
15
|
+
//# sourceMappingURL=client-http.d.ts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shared workspace core: the host store, the SSH engine, and the
|
|
3
|
+
* workspace ledger, provided as `ctx.hardsshCore` by the main plugin row so
|
|
4
|
+
* the two switch rows (fs / subprocess) resolve one instance each.
|
|
5
|
+
*/
|
|
6
|
+
import type { SshEngine } from './ssh/engine.ts';
|
|
7
|
+
import type { SshHostEntry, SshHostSummary } from './ssh/protocol.ts';
|
|
8
|
+
import type { SshWorkspaceLedger } from './ledger.ts';
|
|
9
|
+
import type { RemoteWorkspaceRunner } from './remote-runner.ts';
|
|
10
|
+
import type { WorkspaceSeamState } from './seam-state.ts';
|
|
11
|
+
/** Read-only host-store surface exposed on the core (the write paths live in
|
|
12
|
+
* the SSH routes, which get the full store). Avoids coupling the core type
|
|
13
|
+
* to either the plaintext HostStore or the vault-backed SecureHostStore. */
|
|
14
|
+
export interface HostStoreView {
|
|
15
|
+
readonly path: string;
|
|
16
|
+
list(): SshHostEntry[];
|
|
17
|
+
find(alias: string): SshHostEntry | undefined;
|
|
18
|
+
summarize(entry: SshHostEntry): SshHostSummary;
|
|
19
|
+
}
|
|
20
|
+
/** One process-wide core shared by every dsh-hardssh row. */
|
|
21
|
+
export interface HardsshCore {
|
|
22
|
+
hosts: HostStoreView;
|
|
23
|
+
engine: SshEngine;
|
|
24
|
+
/** The SSH-bound workspace ledger (anchor dir -> remote dir). */
|
|
25
|
+
ledger: SshWorkspaceLedger;
|
|
26
|
+
/** The shared seam state: ledger-derived routing snapshot + per-record
|
|
27
|
+
* fs/subprocess instances, consumed by the fs/subprocess switch rows. */
|
|
28
|
+
seams: WorkspaceSeamState;
|
|
29
|
+
/** Remote-workspace runner: resolve local anchor paths to remote channels
|
|
30
|
+
* (git / files / commands) so other plugins (dsh-workbench-tiphareth) can
|
|
31
|
+
* operate SSH-bound workspaces transparently. Optional in older builds. */
|
|
32
|
+
resolveRemote?: RemoteWorkspaceRunner['resolveRemote'];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* @deprecated Use HardsshCore. Kept as a source-compatible migration alias.
|
|
36
|
+
*/
|
|
37
|
+
export type EasysshCore = HardsshCore;
|
|
38
|
+
declare module '@deepseek-ai/cordis' {
|
|
39
|
+
interface Context {
|
|
40
|
+
hardsshCore: HardsshCore;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `ctx.fs` switch row: provides the workspace-routing filesystem facade in
|
|
3
|
+
* the host scope. The local backend (the deployment's sandboxed filesystem) is
|
|
4
|
+
* mounted in an isolated child scope so its own `ctx.fs` provide never
|
|
5
|
+
* collides. Routing and per-record remote backends are owned by the SHARED
|
|
6
|
+
* seam state (hardsshCore.seams): the row only binds its per-record backend
|
|
7
|
+
* factory and reads the state on every call. Every SSH-bound workspace record
|
|
8
|
+
* gets its OWN remote backend instance bound to that record's alias + remote
|
|
9
|
+
* root; the facade routes each call by the session cwd — an anchor path of an
|
|
10
|
+
* SSH workspace routes remote, everything else stays local. The facade
|
|
11
|
+
* auto-provides `fs` here because the `fs-sandbox` row is disabled by the
|
|
12
|
+
* profile patch.
|
|
13
|
+
*
|
|
14
|
+
* The seam state re-applies the ledger snapshot synchronously on every
|
|
15
|
+
* commit, so creating or removing an SSH workspace takes effect without a
|
|
16
|
+
* plugin restart and the fs/subprocess seams can never disagree. Before the
|
|
17
|
+
* initial ledger load finishes, routing degrades to local with a one-time
|
|
18
|
+
* warning for anchor-root paths.
|
|
19
|
+
*
|
|
20
|
+
* @module dsh-hardssh/fs
|
|
21
|
+
*/
|
|
22
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
23
|
+
import type { HardsshCore } from './core.ts';
|
|
24
|
+
declare module '@deepseek-ai/cordis' {
|
|
25
|
+
interface Context {
|
|
26
|
+
hardsshCore: HardsshCore;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** Stable cordis plugin name. */
|
|
30
|
+
export declare const name = "hardssh-fs";
|
|
31
|
+
/** Services required: the shared workspace core (mode store + engine) and the
|
|
32
|
+
* sandbox policy the local backend (`SandboxedFileSystem`) consumes. */
|
|
33
|
+
export declare const inject: string[];
|
|
34
|
+
/** Mount the switching filesystem facade. */
|
|
35
|
+
export declare function apply(ctx: Context): void;
|
|
36
|
+
//# sourceMappingURL=fs.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-side HTTP route helpers for the dsh-hardssh route family.
|
|
3
|
+
* HOST-ONLY: these import node:http types and must never end up in the
|
|
4
|
+
* client bundle (the client half never imports this module).
|
|
5
|
+
*/
|
|
6
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
7
|
+
/** One JSON response. */
|
|
8
|
+
export declare function writeJson(res: ServerResponse, status: number, body: unknown): void;
|
|
9
|
+
/** URL query helper (first value, decoded). */
|
|
10
|
+
export declare function queryParam(url: URL, name: string): string | undefined;
|
|
11
|
+
/** Loopback literal check plus browser same-origin markers (mirrors dsh-ssh). */
|
|
12
|
+
export declare function isLoopbackRequest(request: IncomingMessage): boolean;
|
|
13
|
+
export type ReadJsonBodyResult = {
|
|
14
|
+
ok: true;
|
|
15
|
+
body: Record<string, unknown>;
|
|
16
|
+
} | {
|
|
17
|
+
ok: false;
|
|
18
|
+
reason: 'too-large' | 'malformed' | 'not-object';
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Read a JSON request body with a hard byte cap. Discriminative result so
|
|
22
|
+
* the caller keeps its own error mapping (silent undefined vs 400/413).
|
|
23
|
+
*/
|
|
24
|
+
export declare function readJsonBody(req: IncomingMessage, maxBytes: number): Promise<ReadJsonBodyResult>;
|
|
25
|
+
//# sourceMappingURL=host-http.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-hardssh — host half. Owns the local⇄remote mode store, the
|
|
3
|
+
* /api/dsh-hardssh route family (loopback-only), the remote_* agent
|
|
4
|
+
* tools, a model-facing announcement section, the shared workspace core
|
|
5
|
+
* (`ctx.hardsshCore`, including the shared seam state the fs/subprocess
|
|
6
|
+
* switch rows consume), and — since the legacy dsh-ssh package was merged
|
|
7
|
+
* in — the SSH operations capability (host manager, ssh_* tools, /api/dsh-ssh,
|
|
8
|
+
* web terminal). In SSH mode the model's ordinary read/write/edit/bash tools
|
|
9
|
+
* run transparently on the remote host through those switch rows. File
|
|
10
|
+
* operations and SSH operations ride ONE shared SshEngine/HostStore over
|
|
11
|
+
* ~/.dsh/dsh-ssh.json (a single connection pool; SSH ops and workspaces
|
|
12
|
+
* invalidate together on config change). The browser half (./client) renders
|
|
13
|
+
* the header buttons, the SSH config dialog, the left workspace panel, and
|
|
14
|
+
* the SSH host-manager surfaces.
|
|
15
|
+
*
|
|
16
|
+
* The announcement section is rendered PER SESSION from the ledger facts
|
|
17
|
+
* (which workspace this session's cwd binds to), never from path-string
|
|
18
|
+
* heuristics; and a global tool guard blocks glob/grep/pwsh calls in
|
|
19
|
+
* SSH-bound sessions with a clear error instead of letting them fail with
|
|
20
|
+
* "No such file or directory" on the remote host.
|
|
21
|
+
*/
|
|
22
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
23
|
+
import z from '@deepseek-ai/schemastery';
|
|
24
|
+
/** Stable cordis plugin name. */
|
|
25
|
+
export declare const name = "hardssh";
|
|
26
|
+
/**
|
|
27
|
+
* Services required before the workspace surfaces can mount. `webServer` is
|
|
28
|
+
* deliberately NOT here: headless profiles lack it, and a hard inject would
|
|
29
|
+
* block the whole load tree — routes register through the dynamic
|
|
30
|
+
* ctx.inject(['webServer'], …) below (DSH 插件规范 §4.2).
|
|
31
|
+
*/
|
|
32
|
+
export declare const inject: string[];
|
|
33
|
+
/** Plugin config (schemastery; optional fields use .default, never .optional). */
|
|
34
|
+
export interface Config {
|
|
35
|
+
/** Master switch (default on). Disabling requires reverting the profile seam patch. */
|
|
36
|
+
enabled: boolean;
|
|
37
|
+
/** Whether the model-facing announcement section is mounted. */
|
|
38
|
+
announceToAgent: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Secret storage mode: 'none' (default, VSCode Remote-SSH style: passwords
|
|
41
|
+
* never persisted, prompted once per session) or 'vault' (encrypted at
|
|
42
|
+
* rest, for unattended agents). Mirrors the dsh-ssh settings namespace.
|
|
43
|
+
*/
|
|
44
|
+
secretStorage: 'none' | 'vault';
|
|
45
|
+
}
|
|
46
|
+
export declare const Config: z<Config>;
|
|
47
|
+
/**
|
|
48
|
+
* Mount the mode store, routes, tools, announcement, guard, and the shared core.
|
|
49
|
+
* @param ctx - host plugin context carrying tools/systemPrompt (webServer optional).
|
|
50
|
+
* @param config - resolved plugin config (schema defaults applied by the loader).
|
|
51
|
+
*/
|
|
52
|
+
export declare function apply(ctx: Context, config?: Config): void;
|
|
53
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSH-bound workspace ledger: the mapping from a LOCAL ANCHOR directory (the
|
|
3
|
+
* host-visible workspace path, which sessions use as their cwd) to a REMOTE
|
|
4
|
+
* directory on an SSH host. Persisted as JSON next to dsh-ssh.json so the
|
|
5
|
+
* fs/subprocess seams can route a session whose cwd is an anchor to the
|
|
6
|
+
* remote execution world, and everything else stays local.
|
|
7
|
+
*
|
|
8
|
+
* A ledger record is created through the GUI (pick a host, browse a remote
|
|
9
|
+
* dir, give it a title). The host-side anchor directory is auto-created
|
|
10
|
+
* under ~/.dsh/ssh-workspaces/<id>/; the host workspace registry owns it as
|
|
11
|
+
* a normal local workspace, so session creation/listing/persistence keep
|
|
12
|
+
* working untouched.
|
|
13
|
+
*
|
|
14
|
+
* Mutations are serialized through a per-instance queue and committed as:
|
|
15
|
+
* write temp file → atomic rename → swap memory/index → bump revision →
|
|
16
|
+
* notify subscribers. A persistence failure leaves observable state
|
|
17
|
+
* unchanged and never publishes an event.
|
|
18
|
+
*
|
|
19
|
+
* @module dsh-hardssh/ledger
|
|
20
|
+
*/
|
|
21
|
+
import type { SshWorkspaceRecord } from './protocol.ts';
|
|
22
|
+
/** One committed snapshot of the ledger. */
|
|
23
|
+
export interface LedgerSnapshot {
|
|
24
|
+
revision: number;
|
|
25
|
+
records: readonly SshWorkspaceRecord[];
|
|
26
|
+
}
|
|
27
|
+
/** One committed mutation, delivered to subscribers. */
|
|
28
|
+
export type LedgerChange = {
|
|
29
|
+
type: 'created';
|
|
30
|
+
revision: number;
|
|
31
|
+
record: SshWorkspaceRecord;
|
|
32
|
+
} | {
|
|
33
|
+
type: 'renamed';
|
|
34
|
+
revision: number;
|
|
35
|
+
before: SshWorkspaceRecord;
|
|
36
|
+
record: SshWorkspaceRecord;
|
|
37
|
+
} | {
|
|
38
|
+
type: 'removed';
|
|
39
|
+
revision: number;
|
|
40
|
+
record: SshWorkspaceRecord;
|
|
41
|
+
};
|
|
42
|
+
export type LedgerListener = (change: LedgerChange) => void;
|
|
43
|
+
/** Ledger file location: ~/.dsh/dsh-hardssh-workspaces.json. */
|
|
44
|
+
export declare function ledgerPath(): string;
|
|
45
|
+
/**
|
|
46
|
+
* Normalize a remote POSIX root: keep '/' as '/', collapse repeated
|
|
47
|
+
* separators and dot segments, reject relative paths and NUL.
|
|
48
|
+
*/
|
|
49
|
+
export declare function normalizeRemoteRoot(raw: string): string;
|
|
50
|
+
/** Anchor roots: ~/.dsh/ssh-workspaces/<id>/ — visible in the sidebar as
|
|
51
|
+
* ordinary host workspaces (and thus selectable for sessions). */
|
|
52
|
+
export declare function anchorRoot(): string;
|
|
53
|
+
/** The anchor directory for one id. */
|
|
54
|
+
export declare function anchorPathFor(id: string): string;
|
|
55
|
+
/** Default record title when the user gives none. */
|
|
56
|
+
export declare function defaultTitle(remoteRoot: string, alias: string): string;
|
|
57
|
+
/**
|
|
58
|
+
* Normalize a local anchor path for comparison: Windows anchors are
|
|
59
|
+
* case-insensitive with mixed separators; POSIX anchors stay case-sensitive.
|
|
60
|
+
*/
|
|
61
|
+
export declare function normalizeAnchorPath(path: string): string;
|
|
62
|
+
/** True when candidate equals anchor or is one of its descendants. Lexical
|
|
63
|
+
* comparison over already-resolved paths; deliberately no fs access. */
|
|
64
|
+
export declare function isPathUnderAnchor(anchor: string, candidate: string): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* The in-memory ledger. Loaded lazily on first access; every mutation writes
|
|
67
|
+
* through durably (atomic rename) and is serialized through a per-instance
|
|
68
|
+
* queue. A synchronous anchor index is maintained from the latest committed
|
|
69
|
+
* records so host seams can resolve a cwd/root without awaiting I/O.
|
|
70
|
+
*/
|
|
71
|
+
export declare class SshWorkspaceLedger {
|
|
72
|
+
private readonly fileOverride?;
|
|
73
|
+
private readonly anchorOverride?;
|
|
74
|
+
private records;
|
|
75
|
+
private loadPromise;
|
|
76
|
+
private anchorIndex;
|
|
77
|
+
private mutationTail;
|
|
78
|
+
private currentRevision;
|
|
79
|
+
private readonly listeners;
|
|
80
|
+
/** Overridable file location (tests isolate per instance). */
|
|
81
|
+
constructor(fileOverride?: string | undefined, anchorOverride?: string | undefined);
|
|
82
|
+
private file;
|
|
83
|
+
private anchors;
|
|
84
|
+
private anchorFor;
|
|
85
|
+
/** Load the ledger once (missing/unreadable/malformed file -> empty ledger). */
|
|
86
|
+
private ensureLoaded;
|
|
87
|
+
private readRecords;
|
|
88
|
+
/** Rebuild the synchronous anchor index from the current records. */
|
|
89
|
+
private reindex;
|
|
90
|
+
/** Persist a proposed record array without touching observable state. */
|
|
91
|
+
private save;
|
|
92
|
+
/** Serialize one mutation; a rejected earlier mutation never poisons later ones. */
|
|
93
|
+
private enqueueMutation;
|
|
94
|
+
/** Commit a computed next state: swap memory, bump revision, notify. */
|
|
95
|
+
private commit;
|
|
96
|
+
private emit;
|
|
97
|
+
/** Load the ledger (compat; returns detached copies). */
|
|
98
|
+
load(): Promise<SshWorkspaceRecord[]>;
|
|
99
|
+
/** All records, in creation order (detached copies). */
|
|
100
|
+
list(): Promise<SshWorkspaceRecord[]>;
|
|
101
|
+
/** Current detached snapshot. */
|
|
102
|
+
snapshot(): Promise<LedgerSnapshot>;
|
|
103
|
+
/** Current in-process snapshot, synchronously (empty before first load).
|
|
104
|
+
* The returned records are the live immutable objects — callers must not
|
|
105
|
+
* mutate them (commits always replace the array wholesale). */
|
|
106
|
+
snapshotSync(): LedgerSnapshot;
|
|
107
|
+
/** Current in-process revision (restarts at 0 on process restart). */
|
|
108
|
+
revision(): number;
|
|
109
|
+
/** Subscribe to committed mutations (no initial event). Returns a disposer. */
|
|
110
|
+
subscribe(listener: LedgerListener): () => void;
|
|
111
|
+
/** Look up by id. */
|
|
112
|
+
get(id: string): Promise<SshWorkspaceRecord | undefined>;
|
|
113
|
+
/** Look up by LOCAL anchor path (resolved). Returns the record whose
|
|
114
|
+
* anchor owns the path (the anchor itself or any descendant). */
|
|
115
|
+
findByAnchor(path: string): Promise<SshWorkspaceRecord | undefined>;
|
|
116
|
+
/** Synchronous anchor lookup (uses the in-memory index). */
|
|
117
|
+
findByAnchorSync(path: string): SshWorkspaceRecord | undefined;
|
|
118
|
+
/** Create a record: materialize the anchor, then persist+commit. */
|
|
119
|
+
create(input: {
|
|
120
|
+
title: string;
|
|
121
|
+
alias: string;
|
|
122
|
+
remoteRoot: string;
|
|
123
|
+
}): Promise<SshWorkspaceRecord>;
|
|
124
|
+
/** Rename a record (display title only). */
|
|
125
|
+
rename(id: string, title: string): Promise<SshWorkspaceRecord | undefined>;
|
|
126
|
+
/** Remove a record. The anchor directory is left in place (a host
|
|
127
|
+
* workspace may still reference it; the caller decides on deletion). */
|
|
128
|
+
remove(id: string): Promise<boolean>;
|
|
129
|
+
/** The anchor root shared by every record (for UI hints). */
|
|
130
|
+
anchorsRoot(): string;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=ledger.d.ts.map
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire contract between the host half (routes.ts) and the browser half
|
|
3
|
+
* (client/api.ts). Pure types only — imported by both halves, bundled into
|
|
4
|
+
* each, no runtime identity to share.
|
|
5
|
+
*/
|
|
6
|
+
/** The two workspace modes of the plugin. */
|
|
7
|
+
export type WorkspaceMode = 'local' | 'remote';
|
|
8
|
+
/** The plugin's mode state (host-owned singleton). */
|
|
9
|
+
export interface WorkspaceState {
|
|
10
|
+
/** Current mode: local = this machine, remote = an SSH host. */
|
|
11
|
+
mode: WorkspaceMode;
|
|
12
|
+
/** Active SSH host alias (kept while in local mode so the toggle can return). */
|
|
13
|
+
alias?: string;
|
|
14
|
+
/** Resolved absolute remote root (the workspace gate prefix). */
|
|
15
|
+
remoteRoot?: string;
|
|
16
|
+
/** Human label of the remote root ('~' when the default home was resolved). */
|
|
17
|
+
remoteRootLabel?: string;
|
|
18
|
+
}
|
|
19
|
+
/** One directory entry (both backends normalize to this shape). */
|
|
20
|
+
export interface WorkspaceEntry {
|
|
21
|
+
name: string;
|
|
22
|
+
type: 'dir' | 'file' | 'other';
|
|
23
|
+
size: number;
|
|
24
|
+
mtimeMs: number;
|
|
25
|
+
}
|
|
26
|
+
/** Directory listing response. */
|
|
27
|
+
export interface DirListing {
|
|
28
|
+
/** The listed absolute path. */
|
|
29
|
+
path: string;
|
|
30
|
+
entries: WorkspaceEntry[];
|
|
31
|
+
}
|
|
32
|
+
/** File read response (text only; binary/oversize is rejected with an error). */
|
|
33
|
+
export interface FileRead {
|
|
34
|
+
path: string;
|
|
35
|
+
content: string;
|
|
36
|
+
size: number;
|
|
37
|
+
mtime: number;
|
|
38
|
+
}
|
|
39
|
+
/** File write response (new mtime for the UI's conflict tracking). */
|
|
40
|
+
export interface FileWriteResult {
|
|
41
|
+
mtime: number;
|
|
42
|
+
}
|
|
43
|
+
/** One filename-search hit. */
|
|
44
|
+
export interface SearchHit {
|
|
45
|
+
/** Absolute path. */
|
|
46
|
+
path: string;
|
|
47
|
+
/** Path relative to the search root. */
|
|
48
|
+
rel: string;
|
|
49
|
+
isDir: boolean;
|
|
50
|
+
}
|
|
51
|
+
/** Filename-search response. */
|
|
52
|
+
export interface SearchView {
|
|
53
|
+
query: string;
|
|
54
|
+
hits: SearchHit[];
|
|
55
|
+
truncated: boolean;
|
|
56
|
+
}
|
|
57
|
+
/** JSON error body used by every route. */
|
|
58
|
+
export interface ApiErrorBody {
|
|
59
|
+
error: string;
|
|
60
|
+
}
|
|
61
|
+
/** Route paths the client calls (shared literals). */
|
|
62
|
+
export declare const WORKSPACE_API_BASE: "/api/dsh-hardssh";
|
|
63
|
+
export declare const WORKSPACE_API: {
|
|
64
|
+
readonly state: string;
|
|
65
|
+
readonly tree: string;
|
|
66
|
+
readonly file: string;
|
|
67
|
+
readonly search: string;
|
|
68
|
+
readonly sshWorkspaces: string;
|
|
69
|
+
readonly sshWorkspaceDir: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* One SSH-bound workspace: a local anchor directory (the host-visible
|
|
73
|
+
* workspace path, which sessions use as their cwd) bound to a directory on
|
|
74
|
+
* an SSH host. The fs/subprocess seams route by the anchor path: a session
|
|
75
|
+
* whose cwd is this anchor operates on the REMOTE directory; everything else
|
|
76
|
+
* stays local.
|
|
77
|
+
*/
|
|
78
|
+
export interface SshWorkspaceRecord {
|
|
79
|
+
/** Stable id (uuid). */
|
|
80
|
+
id: string;
|
|
81
|
+
/** Display title (sidebar). */
|
|
82
|
+
title: string;
|
|
83
|
+
/** SSH host alias (dsh-ssh host store). */
|
|
84
|
+
alias: string;
|
|
85
|
+
/** Resolved absolute remote root (the remote directory to operate in). */
|
|
86
|
+
remoteRoot: string;
|
|
87
|
+
/** Local anchor directory (host workspace path / session cwd). */
|
|
88
|
+
anchorPath: string;
|
|
89
|
+
/** When the record was created. */
|
|
90
|
+
createdAt: string;
|
|
91
|
+
}
|
|
92
|
+
/** The ledger of SSH-bound workspaces (persisted by the host). */
|
|
93
|
+
export type SshWorkspaceLedger = SshWorkspaceRecord[];
|
|
94
|
+
/** One remote directory entry for the picker tree. */
|
|
95
|
+
export interface RemoteDirEntry {
|
|
96
|
+
name: string;
|
|
97
|
+
type: 'dir' | 'file' | 'other';
|
|
98
|
+
size: number;
|
|
99
|
+
mtimeMs: number;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry of every built-in provider. The DSH runtime (and any consumer)
|
|
3
|
+
* uses this to mount local + ssh providers; third-party providers register
|
|
4
|
+
* the same way through the base plugin API.
|
|
5
|
+
*
|
|
6
|
+
* @module @tiphareth/dsh-hardssh/providers
|
|
7
|
+
*/
|
|
8
|
+
import type { WorkspaceProviderRegistry } from '../base/registry.ts';
|
|
9
|
+
import type { SshEngine } from '../ssh/engine.ts';
|
|
10
|
+
import type { HostStoreView } from '../core.ts';
|
|
11
|
+
/** Register both built-in providers. Returns per-provider disposers. */
|
|
12
|
+
export declare function registerBuiltinProviders(registry: WorkspaceProviderRegistry, deps?: {
|
|
13
|
+
engine?: SshEngine;
|
|
14
|
+
hosts?: HostStoreView;
|
|
15
|
+
}): Array<() => void>;
|
|
16
|
+
/** The canonical provider ids. */
|
|
17
|
+
export declare const BUILTIN_PROVIDER_IDS: readonly ["local", "ssh"];
|
|
18
|
+
export type BuiltinProviderId = (typeof BUILTIN_PROVIDER_IDS)[number];
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local provider — the workspace provider for local-disk workspaces. Direct
|
|
3
|
+
* Node fs implementation of `WorkspaceFileSystem`, so the local provider is
|
|
4
|
+
* usable OUTSIDE the dsh harness too (a consumer only needs `base`).
|
|
5
|
+
*
|
|
6
|
+
* The DSH runtime later re-wraps this over `dsh-fs-sandbox` / `dsh-fs-local`
|
|
7
|
+
* for sandbox semantics when running inside the harness; the base contract
|
|
8
|
+
* stays identical.
|
|
9
|
+
*
|
|
10
|
+
* @module @tiphareth/dsh-hardssh/providers/local
|
|
11
|
+
*/
|
|
12
|
+
import type { WorkspaceCapabilityMap, WorkspaceConnection, WorkspaceProvider, WorkspaceProviderManifest } from '../../base/model.ts';
|
|
13
|
+
import type { WorkspaceDirEntry, WorkspaceFileSystem, WorkspaceStat } from '../../base/capability.ts';
|
|
14
|
+
/** The local provider manifest. */
|
|
15
|
+
export declare const localProviderManifest: WorkspaceProviderManifest;
|
|
16
|
+
/** One open local workspace connection. */
|
|
17
|
+
export declare class LocalWorkspaceConnection implements WorkspaceConnection {
|
|
18
|
+
readonly workspaceId: string;
|
|
19
|
+
private readonly root;
|
|
20
|
+
readonly providerId = "local";
|
|
21
|
+
constructor(workspaceId: string, root: string);
|
|
22
|
+
get<K extends keyof WorkspaceCapabilityMap>(capability: K): WorkspaceCapabilityMap[K] | undefined;
|
|
23
|
+
status(): 'connecting' | 'ready' | 'degraded' | 'closed';
|
|
24
|
+
close(): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Node-fs implementation of `WorkspaceFileSystem` confined to a root.
|
|
28
|
+
* Workspace-relative paths (`/src/index.ts`, `src/index.ts`) are resolved
|
|
29
|
+
* against the root; `..` escapes are rejected; symlinks are not followed
|
|
30
|
+
* out of the root by the stat path (defense in depth — the contract says
|
|
31
|
+
* the provider enforces confinement).
|
|
32
|
+
*/
|
|
33
|
+
export declare class LocalWorkspaceFileSystem implements WorkspaceFileSystem {
|
|
34
|
+
private readonly root;
|
|
35
|
+
constructor(root: string);
|
|
36
|
+
/** Resolve a workspace-relative path into an absolute path inside root. */
|
|
37
|
+
private abs;
|
|
38
|
+
stat(path: string, signal?: AbortSignal): Promise<WorkspaceStat | undefined>;
|
|
39
|
+
list(path: string, signal?: AbortSignal): Promise<WorkspaceDirEntry[]>;
|
|
40
|
+
readFile(path: string, signal?: AbortSignal): Promise<Uint8Array>;
|
|
41
|
+
writeFile(path: string, data: Uint8Array, signal?: AbortSignal): Promise<void>;
|
|
42
|
+
mkdir(path: string, options?: {
|
|
43
|
+
recursive?: boolean;
|
|
44
|
+
signal?: AbortSignal;
|
|
45
|
+
}): Promise<void>;
|
|
46
|
+
rm(path: string, options?: {
|
|
47
|
+
recursive?: boolean;
|
|
48
|
+
signal?: AbortSignal;
|
|
49
|
+
}): Promise<void>;
|
|
50
|
+
rename(from: string, to: string, signal?: AbortSignal): Promise<void>;
|
|
51
|
+
/** Convenience: check the root exists and is readable (for open()). */
|
|
52
|
+
accessible(): Promise<boolean>;
|
|
53
|
+
}
|
|
54
|
+
/** The local provider factory. */
|
|
55
|
+
export declare function createLocalWorkspaceProvider(): WorkspaceProvider;
|
|
56
|
+
/** Helper: title mostly used by record factories. */
|
|
57
|
+
export declare function localDefaultTitle(root: string): string;
|
|
58
|
+
//# sourceMappingURL=provider.d.ts.map
|