dsh-winrm 0.1.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 (64) hide show
  1. package/LICENSE +73 -0
  2. package/README.md +112 -0
  3. package/README.zh.md +119 -0
  4. package/RELEASING.md +75 -0
  5. package/cordis.patch.yml +8 -0
  6. package/lib/client.js +2076 -0
  7. package/lib/index.js +2458 -0
  8. package/lib/invariant.js +6 -0
  9. package/lib/types/client/api.d.ts +59 -0
  10. package/lib/types/client/index.d.ts +38 -0
  11. package/lib/types/client/locales.d.ts +231 -0
  12. package/lib/types/client/panel/ConsoleTab.d.ts +11 -0
  13. package/lib/types/client/panel/HostFormDialog.d.ts +12 -0
  14. package/lib/types/client/panel/HostsTab.d.ts +9 -0
  15. package/lib/types/client/panel/ProcessesTab.d.ts +7 -0
  16. package/lib/types/client/panel/ServicesTab.d.ts +7 -0
  17. package/lib/types/client/panel/TransferTab.d.ts +7 -0
  18. package/lib/types/client/panel/WinrmPanel.d.ts +12 -0
  19. package/lib/types/client/panel/WinrmPanelIcon.d.ts +8 -0
  20. package/lib/types/client/panel/helpers.d.ts +16 -0
  21. package/lib/types/engine/client.d.ts +49 -0
  22. package/lib/types/engine/console.d.ts +23 -0
  23. package/lib/types/engine.d.ts +58 -0
  24. package/lib/types/index.d.ts +44 -0
  25. package/lib/types/invariant.d.ts +3 -0
  26. package/lib/types/loopback.d.ts +24 -0
  27. package/lib/types/mount-once.d.ts +24 -0
  28. package/lib/types/powershell.d.ts +73 -0
  29. package/lib/types/protocol.d.ts +176 -0
  30. package/lib/types/routes.d.ts +26 -0
  31. package/lib/types/smb.d.ts +31 -0
  32. package/lib/types/store.d.ts +44 -0
  33. package/lib/types/tools.d.ts +20 -0
  34. package/package.json +111 -0
  35. package/scripts/enable-winrm.ps1 +0 -0
  36. package/scripts/postbuild.mjs +40 -0
  37. package/scripts/validate-manifest.mjs +18 -0
  38. package/src/client/api.ts +345 -0
  39. package/src/client/css-modules.d.ts +5 -0
  40. package/src/client/index.ts +82 -0
  41. package/src/client/locales.ts +243 -0
  42. package/src/client/panel/ConsoleTab.tsx +142 -0
  43. package/src/client/panel/HostFormDialog.tsx +142 -0
  44. package/src/client/panel/HostsTab.tsx +153 -0
  45. package/src/client/panel/ProcessesTab.tsx +119 -0
  46. package/src/client/panel/ServicesTab.tsx +123 -0
  47. package/src/client/panel/TransferTab.tsx +161 -0
  48. package/src/client/panel/WinrmPanel.tsx +85 -0
  49. package/src/client/panel/WinrmPanelIcon.tsx +27 -0
  50. package/src/client/panel/helpers.ts +33 -0
  51. package/src/client/panel/panel.module.css +1000 -0
  52. package/src/engine/client.ts +291 -0
  53. package/src/engine/console.ts +62 -0
  54. package/src/engine.ts +331 -0
  55. package/src/index.ts +142 -0
  56. package/src/invariant.ts +4 -0
  57. package/src/loopback.ts +63 -0
  58. package/src/mount-once.ts +48 -0
  59. package/src/powershell.ts +208 -0
  60. package/src/protocol.ts +178 -0
  61. package/src/routes.ts +490 -0
  62. package/src/smb.ts +129 -0
  63. package/src/store.ts +232 -0
  64. package/src/tools.ts +387 -0
@@ -0,0 +1,6 @@
1
+ //#region src/invariant.ts
2
+ /** Invariant companion plugin (no assertions — nothing to check at runtime). */
3
+ /** Provides no assertions: the winrm plugin owns no cross-package runtime invariants. */
4
+ function apply() {}
5
+ //#endregion
6
+ export { apply };
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Browser-side API client for the /api/dsh-winrm route family. The only data
3
+ * access path the panel components use — plain fetch/WebSocket, same origin.
4
+ */
5
+ import { type ClusterResult, type ExecResult, type ProcessInfo, type RemoteDirEntry, type ServiceInfo, type TestResult, type TransferProgress, type WinHostPayload, type WinHostSummary } from '../protocol.ts';
6
+ /** Error carrying the route's JSON error message. */
7
+ export declare class WinrmApiError extends Error {
8
+ constructor(message: string);
9
+ }
10
+ /** One open console connection (WebSocket JSON frames). */
11
+ export interface ConsoleConnection {
12
+ onReady: (() => void) | undefined;
13
+ onOutput: ((data: string) => void) | undefined;
14
+ onExit: ((code: number | null, error?: string) => void) | undefined;
15
+ send(data: string): void;
16
+ close(): void;
17
+ }
18
+ /** The browser half's only data entry point. */
19
+ export declare class WinrmApi {
20
+ listHosts(queryText?: string): Promise<WinHostSummary[]>;
21
+ createHost(payload: WinHostPayload): Promise<WinHostSummary>;
22
+ updateHost(alias: string, patch: WinHostPayload): Promise<WinHostSummary>;
23
+ deleteHost(alias: string): Promise<void>;
24
+ testHost(alias: string): Promise<TestResult>;
25
+ exec(alias: string, command: string, timeoutMs?: number): Promise<ExecResult>;
26
+ cluster(options: {
27
+ command: string;
28
+ aliases?: string[];
29
+ environment?: string;
30
+ tags?: string[];
31
+ timeoutMs?: number;
32
+ maxWorkers?: number;
33
+ }): Promise<ClusterResult[]>;
34
+ listServices(alias: string): Promise<ServiceInfo[]>;
35
+ serviceAction(alias: string, name: string, action: string): Promise<ServiceInfo>;
36
+ listProcesses(alias: string): Promise<ProcessInfo[]>;
37
+ killProcess(alias: string, id: number): Promise<void>;
38
+ ls(alias: string, dir: string): Promise<RemoteDirEntry[]>;
39
+ /**
40
+ * Upload one file (raw bytes) to a remote path. Progress arrives through
41
+ * the NDJSON response stream; resolves when the result frame lands.
42
+ */
43
+ uploadFile(file: File, alias: string, remotePath: string, onProgress?: (progress: TransferProgress) => void): Promise<{
44
+ transferredBytes: number;
45
+ }>;
46
+ /**
47
+ * Download a remote file with client-side progress. Streams straight to
48
+ * disk when the File System Access API is available; otherwise falls back
49
+ * to an in-memory Blob.
50
+ */
51
+ downloadFile(alias: string, remotePath: string, onProgress?: (progress: TransferProgress) => void): Promise<{
52
+ blob?: Blob;
53
+ filename: string;
54
+ streamed: boolean;
55
+ bytes: number;
56
+ }>;
57
+ /** Open a WebSocket PowerShell console session. */
58
+ openConsole(alias: string): ConsoleConnection;
59
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Browser-half entry for the dsh-winrm plugin — runs inside the dsh web GUI.
3
+ * Registers locale dictionaries and contributes the "Windows" sidebar entry
4
+ * plus the central operations panel through the shell's slot system: a
5
+ * `sidebar.panellist` list row (icon + label) that selects the keyed `main`
6
+ * panel, and the `main` occupant that renders the tabbed WinRM panel in the
7
+ * center column. This replaces the earlier DOM-injection approach with the
8
+ * first-class extension points the shell now provides. DOM/slot mounting
9
+ * problems are logged, never thrown — an external plugin must not take the
10
+ * GUI down.
11
+ *
12
+ * Export discipline (packages/client rule): the /client surface carries what
13
+ * cordis loading needs plus types only — all value exports stay internal.
14
+ */
15
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
16
+ import { type WinKey } from './locales.ts';
17
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
18
+ interface LocaleNamespaceMap {
19
+ /** dsh-winrm surface copy. */
20
+ 'dsh-winrm': WinKey;
21
+ }
22
+ }
23
+ /** Required services (fiber inject waiting — slots, locale, and layout must be up first). */
24
+ export declare const inject: string[];
25
+ /** Type-only surface (export discipline: no value exports beyond the plugin contract). */
26
+ export type { WinrmPanelProps } from './panel/WinrmPanel.tsx';
27
+ export type { HostsTabProps } from './panel/HostsTab.tsx';
28
+ export type { HostFormDialogProps } from './panel/HostFormDialog.tsx';
29
+ export type { ConsoleTabProps } from './panel/ConsoleTab.tsx';
30
+ export type { ServicesTabProps } from './panel/ServicesTab.tsx';
31
+ export type { ProcessesTabProps } from './panel/ProcessesTab.tsx';
32
+ export type { TransferTabProps } from './panel/TransferTab.tsx';
33
+ export type { WinKey } from './locales.ts';
34
+ /**
35
+ * Contribute the Windows sidebar entry and the tabbed WinRM panel it opens.
36
+ * @param ctx - client root context (locale, slots, layout services).
37
+ */
38
+ export declare function apply(ctx: ClientContext): void;
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Locale dictionaries for the WinRM panel (zh / en), bound to the shared
3
+ * interpolator in panel/helpers.ts.
4
+ */
5
+ export declare const zh: {
6
+ readonly 'entry.label': "Windows";
7
+ readonly 'entry.tooltip': "Windows 远程管理(WinRM)";
8
+ readonly 'panel.title': "Windows 远程管理";
9
+ readonly 'panel.backToConversation': "返回对话";
10
+ readonly 'tab.hosts': "主机";
11
+ readonly 'tab.console': "控制台";
12
+ readonly 'tab.services': "服务";
13
+ readonly 'tab.processes': "进程";
14
+ readonly 'tab.transfer': "传输";
15
+ readonly 'common.loading': "加载中…";
16
+ readonly 'common.error': "错误:{error}";
17
+ readonly 'common.refresh': "刷新";
18
+ readonly 'hosts.search': "搜索主机…";
19
+ readonly 'hosts.add': "添加主机";
20
+ readonly 'hosts.test': "测试";
21
+ readonly 'hosts.testing': "测试中…";
22
+ readonly 'hosts.edit': "编辑";
23
+ readonly 'hosts.delete': "删除";
24
+ readonly 'hosts.deleteConfirm': "确认删除主机 {alias}?";
25
+ readonly 'hosts.connect': "连接控制台";
26
+ readonly 'hosts.testOk': "连接成功({latency} ms)";
27
+ readonly 'hosts.testFail': "连接失败:{error}";
28
+ readonly 'hosts.empty': "尚未配置 Windows 主机,点「添加主机」开始。";
29
+ readonly 'hosts.col.alias': "别名";
30
+ readonly 'hosts.col.host': "主机";
31
+ readonly 'hosts.col.user': "用户";
32
+ readonly 'hosts.col.auth': "认证";
33
+ readonly 'hosts.col.transport': "传输";
34
+ readonly 'hosts.col.environment': "环境";
35
+ readonly 'hosts.col.tags': "标签";
36
+ readonly 'hosts.col.description': "备注";
37
+ readonly 'hosts.col.actions': "操作";
38
+ readonly 'form.title.create': "添加 Windows 主机";
39
+ readonly 'form.title.edit': "编辑主机 {alias}";
40
+ readonly 'form.alias': "别名";
41
+ readonly 'form.aliasHint': "英文字母/数字/点/连字符/下划线";
42
+ readonly 'form.host': "主机名或 IP";
43
+ readonly 'form.port': "WinRM 端口";
44
+ readonly 'form.user': "用户名";
45
+ readonly 'form.userHint': "由原生 Node WinRM 客户端自动选择 NTLM/Negotiate 或 Basic;支持本地账户、DOMAIN\\user 或 user@domain";
46
+ readonly 'form.password': "密码";
47
+ readonly 'form.passwordHint': "仅保存在本机 ~/.dsh/dsh-winrm.json(0600),不显示在页面上";
48
+ readonly 'form.transport': "传输";
49
+ readonly 'form.transport.http': "HTTP (5985)";
50
+ readonly 'form.transport.https': "HTTPS (5986)";
51
+ readonly 'form.rejectUnauthorized': "接受自签名证书(HTTPS)";
52
+ readonly 'form.environment': "环境(development / production…)";
53
+ readonly 'form.tags': "标签(逗号分隔)";
54
+ readonly 'form.description': "备注";
55
+ readonly 'form.save': "保存";
56
+ readonly 'form.cancel': "取消";
57
+ readonly 'form.error': "错误:{error}";
58
+ readonly 'form.passwordPlaceholder': "(保持不变)";
59
+ readonly 'console.select': "选择主机开始控制台";
60
+ readonly 'console.connecting': "正在连接 {alias}…";
61
+ readonly 'console.connected': "已连接 {alias} — 输入 PowerShell 命令,回车执行;输入 exit 退出";
62
+ readonly 'console.disconnected': "连接已关闭";
63
+ readonly 'console.disconnect': "断开";
64
+ readonly 'console.inputPlaceholder': "PowerShell 命令…";
65
+ readonly 'console.send': "发送";
66
+ readonly 'console.utf8Note': "注意:控制台经 WinRM 传输,中文输出可能乱码;需要精确中文输出请用「exec」或文件传输";
67
+ readonly 'services.select': "选择主机查看服务";
68
+ readonly 'services.list': "服务列表";
69
+ readonly 'services.name': "服务名";
70
+ readonly 'services.displayName': "显示名";
71
+ readonly 'services.status': "状态";
72
+ readonly 'services.startMode': "启动类型";
73
+ readonly 'services.startName': "运行账户";
74
+ readonly 'services.start': "启动";
75
+ readonly 'services.stop': "停止";
76
+ readonly 'services.restart': "重启";
77
+ readonly 'services.auto': "自动";
78
+ readonly 'services.manual': "手动";
79
+ readonly 'services.disabled': "禁用";
80
+ readonly 'services.actionOk': "操作成功:{name} → {status}";
81
+ readonly 'services.actionFail': "操作失败:{error}";
82
+ readonly 'services.filter': "筛选…";
83
+ readonly 'processes.select': "选择主机查看进程";
84
+ readonly 'processes.id': "PID";
85
+ readonly 'processes.name': "名称";
86
+ readonly 'processes.cpu': "CPU";
87
+ readonly 'processes.memMB': "内存(MB)";
88
+ readonly 'processes.startTime': "启动时间";
89
+ readonly 'processes.path': "路径";
90
+ readonly 'processes.kill': "结束";
91
+ readonly 'processes.killConfirm': "确认结束进程 {name} (PID {id})?";
92
+ readonly 'processes.killed': "已结束进程 PID {id}";
93
+ readonly 'processes.killFail': "结束失败:{error}";
94
+ readonly 'processes.filter': "筛选…";
95
+ readonly 'transfer.select': "选择主机浏览文件";
96
+ readonly 'transfer.path': "路径";
97
+ readonly 'transfer.go': "打开";
98
+ readonly 'transfer.up': "上级";
99
+ readonly 'transfer.root': "根目录";
100
+ readonly 'transfer.name': "名称";
101
+ readonly 'transfer.type': "类型";
102
+ readonly 'transfer.size': "大小";
103
+ readonly 'transfer.modified': "修改时间";
104
+ readonly 'transfer.download': "下载";
105
+ readonly 'transfer.upload': "上传文件";
106
+ readonly 'transfer.uploading': "上传中…";
107
+ readonly 'transfer.downloading': "下载中…";
108
+ readonly 'transfer.uploaded': "已上传 {bytes} 字节";
109
+ readonly 'transfer.downloaded': "已下载 {bytes} 字节";
110
+ readonly 'transfer.fail': "传输失败:{error}";
111
+ readonly 'transfer.bytes': "B";
112
+ readonly 'transfer.kib': "KB";
113
+ readonly 'transfer.mib': "MB";
114
+ readonly 'transfer.dir': "目录";
115
+ readonly 'transfer.file': "文件";
116
+ };
117
+ export declare const en: {
118
+ readonly 'entry.label': "Windows";
119
+ readonly 'entry.tooltip': "Windows remote administration (WinRM)";
120
+ readonly 'panel.title': "Windows Remote";
121
+ readonly 'panel.backToConversation': "Back to chat";
122
+ readonly 'tab.hosts': "Hosts";
123
+ readonly 'tab.console': "Console";
124
+ readonly 'tab.services': "Services";
125
+ readonly 'tab.processes': "Processes";
126
+ readonly 'tab.transfer': "Transfer";
127
+ readonly 'common.loading': "Loading…";
128
+ readonly 'common.error': "Error: {error}";
129
+ readonly 'common.refresh': "Refresh";
130
+ readonly 'hosts.search': "Search hosts…";
131
+ readonly 'hosts.add': "Add host";
132
+ readonly 'hosts.test': "Test";
133
+ readonly 'hosts.testing': "Testing…";
134
+ readonly 'hosts.edit': "Edit";
135
+ readonly 'hosts.delete': "Delete";
136
+ readonly 'hosts.deleteConfirm': "Delete host {alias}?";
137
+ readonly 'hosts.connect': "Console";
138
+ readonly 'hosts.testOk': "connected ({latency} ms)";
139
+ readonly 'hosts.testFail': "failed: {error}";
140
+ readonly 'hosts.empty': "No Windows hosts configured yet — click \"Add host\" to start.";
141
+ readonly 'hosts.col.alias': "Alias";
142
+ readonly 'hosts.col.host': "Host";
143
+ readonly 'hosts.col.user': "User";
144
+ readonly 'hosts.col.auth': "Auth";
145
+ readonly 'hosts.col.transport': "Transport";
146
+ readonly 'hosts.col.environment': "Environment";
147
+ readonly 'hosts.col.tags': "Tags";
148
+ readonly 'hosts.col.description': "Description";
149
+ readonly 'hosts.col.actions': "Actions";
150
+ readonly 'form.title.create': "Add Windows host";
151
+ readonly 'form.title.edit': "Edit host {alias}";
152
+ readonly 'form.alias': "Alias";
153
+ readonly 'form.aliasHint': "letters, digits, dots, hyphens or underscores";
154
+ readonly 'form.host': "Hostname or IP";
155
+ readonly 'form.port': "WinRM port";
156
+ readonly 'form.user': "Username";
157
+ readonly 'form.userHint': "Native Node WinRM client auto-selects NTLM/Negotiate or Basic; supports local, DOMAIN\\user, or user@domain accounts";
158
+ readonly 'form.password': "Password";
159
+ readonly 'form.passwordHint': "Stored locally only in ~/.dsh/dsh-winrm.json (0600), never shown here";
160
+ readonly 'form.transport': "Transport";
161
+ readonly 'form.transport.http': "HTTP (5985)";
162
+ readonly 'form.transport.https': "HTTPS (5986)";
163
+ readonly 'form.rejectUnauthorized': "Accept self-signed certificates (HTTPS)";
164
+ readonly 'form.environment': "Environment (development / production…)";
165
+ readonly 'form.tags': "Tags (comma separated)";
166
+ readonly 'form.description': "Description";
167
+ readonly 'form.save': "Save";
168
+ readonly 'form.cancel': "Cancel";
169
+ readonly 'form.error': "Error: {error}";
170
+ readonly 'form.passwordPlaceholder': "(unchanged)";
171
+ readonly 'console.select': "Pick a host to open the console";
172
+ readonly 'console.connecting': "Connecting to {alias}…";
173
+ readonly 'console.connected': "Connected to {alias} — type a PowerShell command and press Enter; type exit to quit";
174
+ readonly 'console.disconnected': "Connection closed";
175
+ readonly 'console.disconnect': "Disconnect";
176
+ readonly 'console.inputPlaceholder': "PowerShell command…";
177
+ readonly 'console.send': "Send";
178
+ readonly 'console.utf8Note': "Note: the console travels over WinRM and non-ASCII output may garble; use exec or file transfer for exact UTF-8 content";
179
+ readonly 'services.select': "Pick a host to view services";
180
+ readonly 'services.list': "Services";
181
+ readonly 'services.name': "Name";
182
+ readonly 'services.displayName': "Display name";
183
+ readonly 'services.status': "Status";
184
+ readonly 'services.startMode': "Start mode";
185
+ readonly 'services.startName': "Run as";
186
+ readonly 'services.start': "Start";
187
+ readonly 'services.stop': "Stop";
188
+ readonly 'services.restart': "Restart";
189
+ readonly 'services.auto': "Auto";
190
+ readonly 'services.manual': "Manual";
191
+ readonly 'services.disabled': "Disabled";
192
+ readonly 'services.actionOk': "OK: {name} → {status}";
193
+ readonly 'services.actionFail': "Failed: {error}";
194
+ readonly 'services.filter': "Filter…";
195
+ readonly 'processes.select': "Pick a host to view processes";
196
+ readonly 'processes.id': "PID";
197
+ readonly 'processes.name': "Name";
198
+ readonly 'processes.cpu': "CPU";
199
+ readonly 'processes.memMB': "Mem(MB)";
200
+ readonly 'processes.startTime': "Started";
201
+ readonly 'processes.path': "Path";
202
+ readonly 'processes.kill': "Kill";
203
+ readonly 'processes.killConfirm': "Kill process {name} (PID {id})?";
204
+ readonly 'processes.killed': "Killed PID {id}";
205
+ readonly 'processes.killFail': "Failed: {error}";
206
+ readonly 'processes.filter': "Filter…";
207
+ readonly 'transfer.select': "Pick a host to browse files";
208
+ readonly 'transfer.path': "Path";
209
+ readonly 'transfer.go': "Open";
210
+ readonly 'transfer.up': "Up";
211
+ readonly 'transfer.root': "Root";
212
+ readonly 'transfer.name': "Name";
213
+ readonly 'transfer.type': "Type";
214
+ readonly 'transfer.size': "Size";
215
+ readonly 'transfer.modified': "Modified";
216
+ readonly 'transfer.download': "Download";
217
+ readonly 'transfer.upload': "Upload file";
218
+ readonly 'transfer.uploading': "Uploading…";
219
+ readonly 'transfer.downloading': "Downloading…";
220
+ readonly 'transfer.uploaded': "Uploaded {bytes} bytes";
221
+ readonly 'transfer.downloaded': "Downloaded {bytes} bytes";
222
+ readonly 'transfer.fail': "Transfer failed: {error}";
223
+ readonly 'transfer.bytes': "B";
224
+ readonly 'transfer.kib': "KB";
225
+ readonly 'transfer.mib': "MB";
226
+ readonly 'transfer.dir': "dir";
227
+ readonly 'transfer.file': "file";
228
+ };
229
+ export type WinKey = keyof typeof zh;
230
+ /** Translate a key in one dictionary with optional {name} params. */
231
+ export declare function t(dict: Record<string, string>, key: WinKey, values?: Record<string, string | number>): string;
@@ -0,0 +1,11 @@
1
+ import type { WinrmApi } from '../api.ts';
2
+ /** Console tab props. */
3
+ export interface ConsoleTabProps {
4
+ api: WinrmApi;
5
+ /** Alias to auto-connect (from the hosts tab). */
6
+ presetAlias?: string;
7
+ /** Increments when a new connect request arrives. */
8
+ requestId?: number;
9
+ }
10
+ /** The streaming PowerShell console. */
11
+ export declare function ConsoleTab({ api, presetAlias, requestId }: ConsoleTabProps): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import type { WinrmApi } from '../api.ts';
2
+ import type { WinHostSummary } from '../../protocol.ts';
3
+ /** Host form dialog props. */
4
+ export interface HostFormDialogProps {
5
+ api: WinrmApi;
6
+ /** The host being edited, or null for create. */
7
+ editing: WinHostSummary | null;
8
+ onClose: () => void;
9
+ onSaved: () => void;
10
+ }
11
+ /** The create/edit host dialog. */
12
+ export declare function HostFormDialog({ api, editing, onClose, onSaved }: HostFormDialogProps): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import type { WinrmApi } from '../api.ts';
2
+ /** Hosts tab props. */
3
+ export interface HostsTabProps {
4
+ api: WinrmApi;
5
+ /** Connect the given alias in the console tab. */
6
+ onConnect: (alias: string) => void;
7
+ }
8
+ /** The hosts table plus its toolbar and dialogs. */
9
+ export declare function HostsTab({ api, onConnect }: HostsTabProps): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import type { WinrmApi } from '../api.ts';
2
+ /** Processes tab props. */
3
+ export interface ProcessesTabProps {
4
+ api: WinrmApi;
5
+ }
6
+ /** The processes table with host picker and kill actions. */
7
+ export declare function ProcessesTab({ api }: ProcessesTabProps): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import type { WinrmApi } from '../api.ts';
2
+ /** Services tab props. */
3
+ export interface ServicesTabProps {
4
+ api: WinrmApi;
5
+ }
6
+ /** The services table with host picker and actions. */
7
+ export declare function ServicesTab({ api }: ServicesTabProps): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import type { WinrmApi } from '../api.ts';
2
+ /** Transfer tab props. */
3
+ export interface TransferTabProps {
4
+ api: WinrmApi;
5
+ }
6
+ /** The file browser with upload/download. */
7
+ export declare function TransferTab({ api }: TransferTabProps): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import type { WinrmApi } from '../api.ts';
2
+ /** The panel's tab identifiers. */
3
+ export type WinrmTab = 'hosts' | 'console' | 'services' | 'processes' | 'transfer';
4
+ /** Panel shell props (the inject face supplied by the main-slot registration). */
5
+ export interface WinrmPanelProps {
6
+ /** The WinRM API client every tab operates through. */
7
+ api: WinrmApi;
8
+ /** Return to the Conversation (wired to ctx.layout.selectPanel(null)). */
9
+ onBack: () => void;
10
+ }
11
+ /** The tabbed WinRM panel. */
12
+ export declare function WinrmPanel({ api, onBack }: WinrmPanelProps): import("react").JSX.Element;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Sidebar `panellist` icon for the WinRM panel. The shell owns the row
3
+ * button and its label; this component only renders the glyph at the size
4
+ * and active state the row requests.
5
+ */
6
+ import type { SidebarPanelIconOwnerProps } from '@deepseek-ai/dsh-client-ui-sidebar/client';
7
+ /** One glyph contribution for the `sidebar.panellist` list slot. */
8
+ export declare function WinrmPanelIcon({ size }: SidebarPanelIconOwnerProps): import("react").JSX.Element;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Shared panel helpers: the active-dictionary pick (document-language based)
3
+ * bound to the dsh-winrm interpolator in locales.ts, plus a small
4
+ * error-message extractor.
5
+ */
6
+ import { type WinKey } from '../locales.ts';
7
+ /** Template values accepted by the interpolator. */
8
+ export type TranslateValues = Record<string, string | number>;
9
+ /** Active dictionary, picked by the document language at call time. */
10
+ export declare function dictionary(): Record<string, string>;
11
+ /** Translate a key with optional {name} template params (current language). */
12
+ export declare function tt(key: WinKey, values?: TranslateValues): string;
13
+ /** Human-readable error text from an unknown thrown value. */
14
+ export declare function errorMessage(error: unknown): string;
15
+ /** Format a byte count into B/KB/MB. */
16
+ export declare function formatBytes(bytes: number): string;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * WinRM transport bridge.
3
+ *
4
+ * Runs each PowerShell payload over a native Node.js WinRM client
5
+ * (winrm-client) — no Python/pywinrm subprocess. The script rides the
6
+ * UTF-8 base64 envelope (marker + base64 of UTF-8 output) so Chinese and
7
+ * any codepage output survives the WinRM transport losslessly; the envelope
8
+ * is base64-encoded with `-EncodedCommand`, keeping the command line a
9
+ * single ASCII-safe line that WinRS/cmd.exe cannot mangle.
10
+ *
11
+ * Auth is chosen per attempt (HTTPS: Basic first, then NTLM; HTTP: NTLM
12
+ * first, then Basic) with fallback, so a host that only enables one scheme
13
+ * still connects. Credentials are passed to the library in-process — they
14
+ * never appear in a child-process argument list.
15
+ */
16
+ import type { WinHostEntry } from '../protocol.ts';
17
+ /** Connection parameters for one target (transport-agnostic projection of a host entry). */
18
+ export interface WinRMParams {
19
+ host: string;
20
+ port: number;
21
+ path: string;
22
+ username: string;
23
+ password: string;
24
+ useHttps?: boolean;
25
+ rejectUnauthorized?: boolean;
26
+ }
27
+ export declare function runScript(conn: WinRMParams, script: string, options?: {
28
+ timeoutMs?: number;
29
+ onChunk?: (chunk: {
30
+ output: string;
31
+ stderr: string;
32
+ }) => void;
33
+ }): Promise<{
34
+ stdout: string;
35
+ stderr: string;
36
+ exitCode: number | null;
37
+ timedOut: boolean;
38
+ durationMs: number;
39
+ }>;
40
+ export declare function connOf(entry: WinHostEntry): WinRMParams;
41
+ export declare function testConnection(conn: WinRMParams): Promise<{
42
+ ok: boolean;
43
+ latencyMs: number;
44
+ error?: string;
45
+ }>;
46
+ export declare const TRANSFER_CHUNK: number;
47
+ export declare function remoteFileSize(conn: WinRMParams, remotePath: string, timeoutMs?: number): Promise<number>;
48
+ export declare function downloadChunks(conn: WinRMParams, remotePath: string, onChunk: (b64: string, bytes: number) => void, onProgress?: (transferred: number, total: number) => void, timeoutMs?: number): Promise<number>;
49
+ export declare function uploadBuffer(conn: WinRMParams, remotePath: string, data: Buffer, onProgress?: (transferred: number, total: number) => void, timeoutMs?: number): Promise<number>;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * WebSocket PowerShell console backed by winrm-client one-shot commands.
3
+ *
4
+ * The native Node WinRM client executes each submitted command through the
5
+ * same UTF-8 envelope as winrm_exec; the WebSocket remains open while
6
+ * commands are serialized. This is intentionally a command console rather
7
+ * than a persistent remote process, so every line is authenticated and
8
+ * isolated.
9
+ */
10
+ import type { WinRMParams } from './client.ts';
11
+ export declare class ConsoleSession {
12
+ private conn;
13
+ private running;
14
+ private exited;
15
+ private queue;
16
+ onData: ((data: string) => void) | undefined;
17
+ onExit: ((code: number | null, error?: string) => void) | undefined;
18
+ constructor(conn: WinRMParams);
19
+ start(): Promise<void>;
20
+ send(data: string): void;
21
+ close(): void;
22
+ private finish;
23
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The WinRM engine facade: host lookup, PowerShell exec (UTF-8 envelope),
3
+ * service & process management, directory listing, base64-chunked file
4
+ * transfer, cluster execution and the streaming console. The heavy lifting
5
+ * lives in engine/ (client, console); this class composes them behind one
6
+ * WinRmEngine instance per plugin apply.
7
+ */
8
+ import type { ClusterResult, ExecResult, ProcessInfo, RemoteDirEntry, ServiceInfo, TestResult, TransferProgress, WinHostSummary } from './protocol.ts';
9
+ import type { HostStore } from './store.ts';
10
+ import { type TransferChannel } from './smb.ts';
11
+ import { ConsoleSession } from './engine/console.ts';
12
+ /** The engine. One instance per plugin apply; dispose() clears nothing pooled (WinRM is per-call HTTP). */
13
+ export declare class WinRmEngine {
14
+ readonly store: HostStore;
15
+ private gate;
16
+ constructor(store: HostStore);
17
+ /** Secret-free host list (filtered by the optional query). */
18
+ list(query?: string): WinHostSummary[];
19
+ /** One host summary by alias. */
20
+ find(alias: string): WinHostSummary | undefined;
21
+ /** Run one PowerShell command on `alias`. */
22
+ exec(alias: string, command: string, timeoutMs?: number): Promise<ExecResult>;
23
+ /** Run one command against many hosts concurrently. */
24
+ cluster(options: {
25
+ command: string;
26
+ aliases?: string[];
27
+ environment?: string;
28
+ tags?: string[];
29
+ timeoutMs?: number;
30
+ maxWorkers?: number;
31
+ }): Promise<ClusterResult[]>;
32
+ /** Full service table. */
33
+ listServices(alias: string): Promise<ServiceInfo[]>;
34
+ /** One service action, returning the refreshed service row. */
35
+ serviceAction(alias: string, name: string, action: 'start' | 'stop' | 'restart' | 'set-auto' | 'set-manual' | 'set-disabled'): Promise<ServiceInfo>;
36
+ /** Full process table. */
37
+ listProcesses(alias: string): Promise<ProcessInfo[]>;
38
+ /** Kill one process by id. */
39
+ killProcess(alias: string, id: number): Promise<void>;
40
+ /** List a remote directory. */
41
+ ls(alias: string, dir: string): Promise<RemoteDirEntry[]>;
42
+ /** Upload one local file to a remote path. Defaults to SMB with WinRM fallback. */
43
+ upload(alias: string, localPath: string, remotePath: string, onProgress?: (progress: TransferProgress) => void, channel?: TransferChannel): Promise<{
44
+ bytes: number;
45
+ channel?: TransferChannel;
46
+ }>;
47
+ /** Download one remote file to a local path. Defaults to SMB with WinRM fallback. */
48
+ download(alias: string, remotePath: string, localPath: string, onProgress?: (progress: TransferProgress) => void, channel?: TransferChannel): Promise<{
49
+ bytes: number;
50
+ channel?: TransferChannel;
51
+ }>;
52
+ /** Open a streaming PowerShell console session (standalone connection). */
53
+ openConsole(alias: string): Promise<ConsoleSession>;
54
+ /** Probe connectivity. */
55
+ test(alias: string): Promise<TestResult>;
56
+ /** No pooled resources to close (WinRM is per-call HTTP). */
57
+ dispose(): void;
58
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * dsh-winrm — host half. Mounts the WinRM engine (per-call PowerShell
3
+ * execution with a UTF-8 envelope, streaming console, service/process
4
+ * management, base64-chunked file transfer, cluster), the /api/dsh-winrm
5
+ * route family plus the console WebSocket upgrade, the agent tools
6
+ * (winrm_list, winrm_exec, winrm_service, winrm_process, winrm_upload,
7
+ * winrm_download, winrm_cluster), and a system-prompt announcement. The
8
+ * browser half (./client) renders the host manager and operations panel.
9
+ * Everything rides official NPM SDK packages — no dsh source changes.
10
+ *
11
+ * Config is read live through `Volatile` references (`.get()`), so the
12
+ * Settings page can flip `enabled` / `announceToAgent` without remounting;
13
+ * `loader/volatile-update` re-runs the registration sync when they change.
14
+ */
15
+ import type { Context, Volatile } from '@deepseek-ai/cordis';
16
+ import z from '@deepseek-ai/schemastery';
17
+ /** Stable cordis plugin name. */
18
+ export declare const name = "winrm";
19
+ /** Services required before the WinRM surfaces can mount. */
20
+ export declare const inject: string[];
21
+ /** Plugin config, validated by the same-named schemastery schema. Live fields are `Volatile`. */
22
+ export interface Config {
23
+ /** When true (default), a system-prompt section announces the plugin to every agent. */
24
+ announceToAgent?: Volatile<boolean>;
25
+ /** Master switch for the plugin (routes, tools, prompt section). */
26
+ enabled?: Volatile<boolean>;
27
+ }
28
+ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
29
+ announceToAgent: z<boolean, boolean, "volatile-defined">;
30
+ enabled: z<boolean, boolean, "volatile-defined">;
31
+ }>>, Schemastery.ObjectT<NoInfer<{
32
+ announceToAgent: z<boolean, boolean, "volatile-defined">;
33
+ enabled: z<boolean, boolean, "volatile-defined">;
34
+ }>>, "plain">;
35
+ /** Model-facing announcement: plugin presence, capabilities, and limits. */
36
+ export declare const WINRM_GUIDANCE = "\u672C\u673A\u5DF2\u5B89\u88C5 dsh-winrm \u63D2\u4EF6\uFF08DSH \u8FDC\u7A0B Windows \u8FD0\u7EF4\uFF0CWinRM/PowerShell Remoting\uFF09\uFF1A\u4FA7\u8FB9\u680F\u300CWindows\u300D\u5165\u53E3\uFF1B\u4EFF\u7167 dsh-ssh \u63D2\u4EF6\u5F00\u53D1\u3002\u80FD\u529B\uFF1A\u4E3B\u673A\u914D\u7F6E\u5B58 ~/.dsh/dsh-winrm.json\uFF08GUI \u914D\u7F6E\u540E agent \u65B9\u53EF\u4F7F\u7528\uFF09\uFF1Bwinrm_list \u5217\u51FA\u4E3B\u673A\u3001winrm_exec \u6267\u884C PowerShell \u547D\u4EE4\uFF08UTF-8 \u4FE1\u5C01\uFF0C\u4E2D\u6587\u4E0D\u4E71\u7801\uFF09\u3001winrm_service \u670D\u52A1\u7BA1\u7406\uFF08start/stop/restart/\u542F\u52A8\u7C7B\u578B\uFF09\u3001winrm_process \u8FDB\u7A0B\u7BA1\u7406\uFF08list/kill\uFF09\u3001winrm_upload/winrm_download \u6587\u4EF6\u4F20\u8F93\uFF08base64 \u5206\u5757\uFF0C\u65E0 SMB \u4F9D\u8D56\uFF09\u3001winrm_cluster \u96C6\u7FA4\u5E76\u53D1\u6267\u884C\uFF1BWeb \u63A7\u5236\u53F0\u8D70 WebSocket\u3002\u8BA4\u8BC1\uFF1A\u901A\u8FC7\u539F\u751F Node.js WinRM \u5BA2\u6237\u7AEF\uFF08winrm-client\uFF09\u7684 NTLM/Negotiate \u4E0E Basic \u5B9E\u73B0\uFF0C\u517C\u5BB9\u672C\u5730\u8D26\u6237\u4E0E\u57DF\u8D26\u6237\uFF1B\u4F20\u8F93\u652F\u6301 http(5985)/https(5986)\u3002\u524D\u63D0\uFF1A\u76EE\u6807\u673A\u9700\u542F\u7528 WinRM\uFF08scripts/enable-winrm.ps1\uFF09\uFF0C\u672C\u673A\u65E0\u9700 Python \u2014\u2014 WinRM \u8D70\u7EAF Node \u4F9D\u8D56\u3002HTTP \u4EC5\u5EFA\u8BAE\u53D7\u4FE1\u5185\u7F51\u4F7F\u7528\uFF1B\u5BC6\u7801\u4EE5\u660E\u6587\u5B58\u5728\u7528\u6237\u4E3B\u76EE\u5F55\u79C1\u6709\u6587\u4EF6\uFF08\u6743\u9650 0600\uFF09\uFF1B\u547D\u4EE4\u8F93\u51FA\u53EF\u80FD\u542B\u654F\u611F\u4FE1\u606F\uFF1B\u4F20\u8F93/\u6267\u884C\u6D88\u8017\u771F\u5B9E\u8FDC\u7A0B\u8D44\u6E90\uFF0C\u5148\u786E\u8BA4\u518D\u64CD\u4F5C\u3002\u7528\u6237\u63D0\u5230\u300CWindows \u670D\u52A1\u5668 / WinRM / PowerShell \u8FDC\u7A0B / \u670D\u52A1\u7BA1\u7406 / \u8FDB\u7A0B\u7BA1\u7406\u300D\u65F6\u5373\u6307\u672C\u63D2\u4EF6\uFF0C\u8BF7\u636E\u6B64\u534F\u4F5C\u3002";
37
+ /**
38
+ * Mount the WinRM engine, routes, tools, and announcement.
39
+ * @param ctx - host plugin context carrying webServer/tools/systemPrompt.
40
+ * @param config - resolved plugin config (volatile fields read via `.get()`).
41
+ */
42
+ export declare const apply: typeof applyImpl;
43
+ declare function applyImpl(ctx: Context, config?: Config): void;
44
+ export {};
@@ -0,0 +1,3 @@
1
+ /** Invariant companion plugin (no assertions — nothing to check at runtime). */
2
+ /** Provides no assertions: the winrm plugin owns no cross-package runtime invariants. */
3
+ export declare function apply(): void;