@jabberwocky238/dsh-ssh 0.0.0-stage → 0.2.4
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 +112 -2
- package/README.zh.md +113 -0
- package/lib/index.js +572 -0
- package/lib/protocol-CDhW_IHU.js +276 -0
- package/lib/protocol.js +2 -0
- package/lib/schemas-BD3YbDxe.js +189 -0
- package/lib/schemas.js +2 -0
- package/lib/stream-security-DJlQsPG-.js +75 -0
- package/lib/types/index.d.ts +121 -0
- package/lib/types/protocol.d.ts +50 -0
- package/lib/types/schemas.d.ts +217 -0
- package/lib/types/stream-security.d.ts +19 -0
- package/package.json +41 -3
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** Bounded, versioned requests between an SSH client and its private remote helper. */
|
|
2
|
+
import { EventEmitter } from 'node:events';
|
|
3
|
+
import type { Readable, Writable } from 'node:stream';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
/** Wire version shared by the installed helper and client package. */
|
|
6
|
+
export declare const SSH_PROTOCOL_VERSION = 2;
|
|
7
|
+
/** Maximum prepared or running process handles owned by one helper. */
|
|
8
|
+
export declare const SSH_MAX_PROCESS_HANDLES = 128;
|
|
9
|
+
/** Maximum open text iterators owned by one helper. */
|
|
10
|
+
export declare const SSH_MAX_TEXT_STREAMS = 128;
|
|
11
|
+
type RequestHandler = (method: string, params: unknown, signal: AbortSignal) => Promise<unknown>;
|
|
12
|
+
/** A remote error retains its typed filesystem or sandbox code. */
|
|
13
|
+
export declare class RemoteOperationError extends Error {
|
|
14
|
+
readonly code?: string | undefined;
|
|
15
|
+
constructor(message: string, code?: string | undefined);
|
|
16
|
+
}
|
|
17
|
+
/** The peer owns pending calls and rejects ambiguous operations on connection loss; it never replays requests. */
|
|
18
|
+
export declare class SshRpcPeer extends EventEmitter {
|
|
19
|
+
private readonly input;
|
|
20
|
+
private readonly output;
|
|
21
|
+
private readonly maxFrameBytes;
|
|
22
|
+
private readonly maxPending;
|
|
23
|
+
private readonly handler?;
|
|
24
|
+
private readonly pending;
|
|
25
|
+
private readonly active;
|
|
26
|
+
private writeTail;
|
|
27
|
+
private queuedBytes;
|
|
28
|
+
private failure;
|
|
29
|
+
constructor(input: Readable, output: Writable, maxFrameBytes: number, maxPending: number, handler?: RequestHandler | undefined);
|
|
30
|
+
/**
|
|
31
|
+
* Send one request and validate its response before exposing it to the caller.
|
|
32
|
+
* @param method - the private helper operation.
|
|
33
|
+
* @param params - JSON request fields.
|
|
34
|
+
* @param schema - validation for the remote response.
|
|
35
|
+
* @param signal - cancellation without rollback of remote effects.
|
|
36
|
+
* @returns the validated response or a transport/remote-operation rejection.
|
|
37
|
+
*/
|
|
38
|
+
request<T>(method: string, params: unknown, schema: z.ZodType<T>, signal?: AbortSignal): Promise<T>;
|
|
39
|
+
/**
|
|
40
|
+
* Fail pending operations and abort remote handlers without claiming rollback.
|
|
41
|
+
* @param error - the transport failure reported to all pending operations.
|
|
42
|
+
*/
|
|
43
|
+
close(error?: Error): void;
|
|
44
|
+
private send;
|
|
45
|
+
private readFrames;
|
|
46
|
+
private receive;
|
|
47
|
+
private atCapacity;
|
|
48
|
+
}
|
|
49
|
+
export {};
|
|
50
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/** Strict JSON validation for SSH helper requests and remote observations. */
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import type { Branded } from '@deepseek-ai/dsh-brand';
|
|
4
|
+
/** Identity of one prepared or running process in its owning SSH helper. */
|
|
5
|
+
export type SshProcessId = Branded<'SshProcessId'>;
|
|
6
|
+
/** Identity of one open text iterator in its owning SSH helper. */
|
|
7
|
+
export type SshTextStreamId = Branded<'SshTextStreamId'>;
|
|
8
|
+
/** Admit a process identity from the private helper protocol. */
|
|
9
|
+
export declare const processIdSchema: z.ZodPipe<z.ZodUUID, z.ZodTransform<SshProcessId, string>>;
|
|
10
|
+
/** Admit a text iterator identity from the private helper protocol. */
|
|
11
|
+
export declare const textStreamIdSchema: z.ZodPipe<z.ZodUUID, z.ZodTransform<SshTextStreamId, string>>;
|
|
12
|
+
/** A remote POSIX absolute path; spelling is preserved until remote canonicalization. */
|
|
13
|
+
export declare const remotePath: z.ZodString;
|
|
14
|
+
/** Filesystem identity returned by the remote filesystem provider. */
|
|
15
|
+
export declare const targetSchema: z.ZodObject<{
|
|
16
|
+
targetKey: z.ZodString;
|
|
17
|
+
displayPath: z.ZodString;
|
|
18
|
+
}, z.core.$strict>;
|
|
19
|
+
/** Remote metadata observation. */
|
|
20
|
+
export declare const infoSchema: z.ZodObject<{
|
|
21
|
+
version: z.ZodString;
|
|
22
|
+
type: z.ZodEnum<{
|
|
23
|
+
file: "file";
|
|
24
|
+
directory: "directory";
|
|
25
|
+
other: "other";
|
|
26
|
+
}>;
|
|
27
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
28
|
+
}, z.core.$strict>;
|
|
29
|
+
/** Metadata that preserves a final symlink. */
|
|
30
|
+
export declare const pathInfoSchema: z.ZodObject<{
|
|
31
|
+
version: z.ZodString;
|
|
32
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
33
|
+
type: z.ZodEnum<{
|
|
34
|
+
file: "file";
|
|
35
|
+
directory: "directory";
|
|
36
|
+
other: "other";
|
|
37
|
+
symlink: "symlink";
|
|
38
|
+
}>;
|
|
39
|
+
}, z.core.$strict>;
|
|
40
|
+
/** A resolved file-effect policy; the remote helper owns path canonicalization. */
|
|
41
|
+
export declare const policySchema: z.ZodObject<{
|
|
42
|
+
mode: z.ZodEnum<{
|
|
43
|
+
"read-only": "read-only";
|
|
44
|
+
"workspace-write": "workspace-write";
|
|
45
|
+
"danger-full-access": "danger-full-access";
|
|
46
|
+
}>;
|
|
47
|
+
workspaceRoot: z.ZodString;
|
|
48
|
+
sessionId: z.ZodOptional<z.ZodString>;
|
|
49
|
+
}, z.core.$strict>;
|
|
50
|
+
/** Complete directory entries. */
|
|
51
|
+
export declare const entriesSchema: z.ZodArray<z.ZodObject<{
|
|
52
|
+
name: z.ZodString;
|
|
53
|
+
type: z.ZodEnum<{
|
|
54
|
+
file: "file";
|
|
55
|
+
directory: "directory";
|
|
56
|
+
other: "other";
|
|
57
|
+
}>;
|
|
58
|
+
target: z.ZodObject<{
|
|
59
|
+
targetKey: z.ZodString;
|
|
60
|
+
displayPath: z.ZodString;
|
|
61
|
+
}, z.core.$strict>;
|
|
62
|
+
version: z.ZodOptional<z.ZodString>;
|
|
63
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
64
|
+
}, z.core.$strict>>;
|
|
65
|
+
/** Guarded write intent. */
|
|
66
|
+
export declare const intentSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
67
|
+
kind: z.ZodLiteral<"createIfAbsent">;
|
|
68
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
69
|
+
kind: z.ZodLiteral<"replaceIfVersion">;
|
|
70
|
+
version: z.ZodString;
|
|
71
|
+
}, z.core.$strict>], "kind">;
|
|
72
|
+
/** Literal text edit. */
|
|
73
|
+
export declare const editSchema: z.ZodObject<{
|
|
74
|
+
oldString: z.ZodString;
|
|
75
|
+
newString: z.ZodString;
|
|
76
|
+
replaceAll: z.ZodBoolean;
|
|
77
|
+
}, z.core.$strict>;
|
|
78
|
+
/** Atomic write observation. */
|
|
79
|
+
export declare const writeResultSchema: z.ZodObject<{
|
|
80
|
+
operation: z.ZodEnum<{
|
|
81
|
+
create: "create";
|
|
82
|
+
update: "update";
|
|
83
|
+
}>;
|
|
84
|
+
version: z.ZodString;
|
|
85
|
+
before: z.ZodNullable<z.ZodString>;
|
|
86
|
+
after: z.ZodString;
|
|
87
|
+
}, z.core.$strict>;
|
|
88
|
+
/** Atomic edit observation. */
|
|
89
|
+
export declare const editResultSchema: z.ZodObject<{
|
|
90
|
+
version: z.ZodString;
|
|
91
|
+
before: z.ZodString;
|
|
92
|
+
after: z.ZodString;
|
|
93
|
+
}, z.core.$strict>;
|
|
94
|
+
/** Explicit child environment; null encodes an environment tombstone. */
|
|
95
|
+
export declare const environmentSchema: z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>;
|
|
96
|
+
/** Ordinary or terminal process requested by a trusted SSH client. */
|
|
97
|
+
export declare const spawnSchema: z.ZodObject<{
|
|
98
|
+
argv: z.ZodArray<z.ZodString>;
|
|
99
|
+
cwd: z.ZodString;
|
|
100
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
|
|
101
|
+
graceMs: z.ZodNumber;
|
|
102
|
+
stdio: z.ZodOptional<z.ZodObject<{
|
|
103
|
+
stdin: z.ZodUnion<readonly [z.ZodLiteral<"ignore">, z.ZodLiteral<"pipe">, z.ZodObject<{
|
|
104
|
+
data: z.ZodString;
|
|
105
|
+
}, z.core.$strict>]>;
|
|
106
|
+
stdout: z.ZodUnion<readonly [z.ZodLiteral<"pipe">, z.ZodLiteral<"inherit">, z.ZodObject<{
|
|
107
|
+
maxBytes: z.ZodNumber;
|
|
108
|
+
spill: z.ZodOptional<z.ZodObject<{
|
|
109
|
+
maxBytes: z.ZodNumber;
|
|
110
|
+
}, z.core.$strict>>;
|
|
111
|
+
}, z.core.$strict>]>;
|
|
112
|
+
stderr: z.ZodUnion<readonly [z.ZodLiteral<"pipe">, z.ZodLiteral<"inherit">, z.ZodObject<{
|
|
113
|
+
maxBytes: z.ZodNumber;
|
|
114
|
+
spill: z.ZodOptional<z.ZodObject<{
|
|
115
|
+
maxBytes: z.ZodNumber;
|
|
116
|
+
}, z.core.$strict>>;
|
|
117
|
+
}, z.core.$strict>]>;
|
|
118
|
+
control: z.ZodOptional<z.ZodLiteral<"pipe">>;
|
|
119
|
+
}, z.core.$strict>>;
|
|
120
|
+
terminal: z.ZodOptional<z.ZodObject<{
|
|
121
|
+
terminalType: z.ZodString;
|
|
122
|
+
rows: z.ZodNumber;
|
|
123
|
+
cols: z.ZodNumber;
|
|
124
|
+
shellActivity: z.ZodOptional<z.ZodBoolean>;
|
|
125
|
+
}, z.core.$strict>>;
|
|
126
|
+
}, z.core.$strict>;
|
|
127
|
+
/** Connection handshake binds sockets and workspace to one helper process. */
|
|
128
|
+
export declare const helloSchema: z.ZodObject<{
|
|
129
|
+
protocol: z.ZodLiteral<2>;
|
|
130
|
+
hash: z.ZodString;
|
|
131
|
+
kind: z.ZodEnum<{
|
|
132
|
+
executable: "executable";
|
|
133
|
+
"node-script": "node-script";
|
|
134
|
+
}>;
|
|
135
|
+
platform: z.ZodEnum<{
|
|
136
|
+
linux: "linux";
|
|
137
|
+
darwin: "darwin";
|
|
138
|
+
}>;
|
|
139
|
+
nodeVersion: z.ZodString;
|
|
140
|
+
executable: z.ZodString;
|
|
141
|
+
root: z.ZodString;
|
|
142
|
+
workspace: z.ZodString;
|
|
143
|
+
bootstrapHash: z.ZodOptional<z.ZodString>;
|
|
144
|
+
}, z.core.$strict>;
|
|
145
|
+
/** A prepared process publishes its sockets before target code may execute. */
|
|
146
|
+
export declare const streamEndpointSchema: z.ZodObject<{
|
|
147
|
+
path: z.ZodString;
|
|
148
|
+
capability: z.ZodString;
|
|
149
|
+
}, z.core.$strict>;
|
|
150
|
+
/** A stream capability reaches only the authenticated SSH client and its helper. */
|
|
151
|
+
export type SshStreamEndpoint = z.infer<typeof streamEndpointSchema>;
|
|
152
|
+
/** Prepared process and its independently authenticated stream endpoints. */
|
|
153
|
+
export declare const preparedSchema: z.ZodObject<{
|
|
154
|
+
id: z.ZodPipe<z.ZodUUID, z.ZodTransform<SshProcessId, string>>;
|
|
155
|
+
streams: z.ZodRecord<z.ZodEnum<{
|
|
156
|
+
stdin: "stdin";
|
|
157
|
+
stdout: "stdout";
|
|
158
|
+
stderr: "stderr";
|
|
159
|
+
control: "control";
|
|
160
|
+
terminal: "terminal";
|
|
161
|
+
}> & z.core.$partial, z.ZodObject<{
|
|
162
|
+
path: z.ZodString;
|
|
163
|
+
capability: z.ZodString;
|
|
164
|
+
}, z.core.$strict>>;
|
|
165
|
+
}, z.core.$strict>;
|
|
166
|
+
/** Direct process exit facts. */
|
|
167
|
+
export declare const outcomeSchema: z.ZodObject<{
|
|
168
|
+
exitCode: z.ZodNullable<z.ZodNumber>;
|
|
169
|
+
signal: z.ZodNullable<z.ZodString>;
|
|
170
|
+
}, z.core.$strict>;
|
|
171
|
+
/** A bounded raw tail positioned in whole-stream byte coordinates. */
|
|
172
|
+
export declare const outputSnapshotSchema: z.ZodObject<{
|
|
173
|
+
tail: z.ZodBase64;
|
|
174
|
+
totalBytes: z.ZodNumber;
|
|
175
|
+
}, z.core.$strict>;
|
|
176
|
+
/**
|
|
177
|
+
* Bound one encoded tail and its RPC envelope by the declared collection budget.
|
|
178
|
+
* @param maxBytes - the collector's retained raw-byte limit.
|
|
179
|
+
* @returns the private snapshot frame limit, capped by the helper protocol ceiling.
|
|
180
|
+
*/
|
|
181
|
+
export declare function outputSnapshotFrameLimit(maxBytes: number): number;
|
|
182
|
+
/** Direct exit, retained output snapshots, and optional complete spill locations. */
|
|
183
|
+
export declare const doneSchema: z.ZodObject<{
|
|
184
|
+
outcome: z.ZodObject<{
|
|
185
|
+
exitCode: z.ZodNullable<z.ZodNumber>;
|
|
186
|
+
signal: z.ZodNullable<z.ZodString>;
|
|
187
|
+
}, z.core.$strict>;
|
|
188
|
+
spills: z.ZodObject<{
|
|
189
|
+
stdout: z.ZodOptional<z.ZodString>;
|
|
190
|
+
stderr: z.ZodOptional<z.ZodString>;
|
|
191
|
+
}, z.core.$strict>;
|
|
192
|
+
collected: z.ZodObject<{
|
|
193
|
+
stdout: z.ZodOptional<z.ZodObject<{
|
|
194
|
+
tail: z.ZodBase64;
|
|
195
|
+
totalBytes: z.ZodNumber;
|
|
196
|
+
}, z.core.$strict>>;
|
|
197
|
+
stderr: z.ZodOptional<z.ZodObject<{
|
|
198
|
+
tail: z.ZodBase64;
|
|
199
|
+
totalBytes: z.ZodNumber;
|
|
200
|
+
}, z.core.$strict>>;
|
|
201
|
+
}, z.core.$strict>;
|
|
202
|
+
}, z.core.$strict>;
|
|
203
|
+
/** Remote terminal foreground observation. */
|
|
204
|
+
export declare const foregroundSchema: z.ZodNullable<z.ZodObject<{
|
|
205
|
+
processGroupId: z.ZodNumber;
|
|
206
|
+
inputWaiting: z.ZodBoolean;
|
|
207
|
+
}, z.core.$strict>>;
|
|
208
|
+
/** Conservative shell lifecycle and process observation returned by the execution provider. */
|
|
209
|
+
export declare const terminalActivitySchema: z.ZodObject<{
|
|
210
|
+
state: z.ZodEnum<{
|
|
211
|
+
unknown: "unknown";
|
|
212
|
+
idle: "idle";
|
|
213
|
+
busy: "busy";
|
|
214
|
+
}>;
|
|
215
|
+
revision: z.ZodNumber;
|
|
216
|
+
}, z.core.$strict>;
|
|
217
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** TLS-PSK authenticates forwarded streams even when a remote pathname is replaced. */
|
|
2
|
+
import { type TLSSocket } from 'node:tls';
|
|
3
|
+
import type { Socket } from 'node:net';
|
|
4
|
+
/** Certificate-free PSK authentication and AEAD records; no unauthenticated cipher fallback. */
|
|
5
|
+
export declare const SSH_STREAM_TLS_OPTIONS: {
|
|
6
|
+
readonly ciphers: "PSK-AES256-GCM-SHA384";
|
|
7
|
+
readonly minVersion: "TLSv1.2";
|
|
8
|
+
readonly maxVersion: "TLSv1.2";
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Authenticate a forwarded socket with its private administrative-channel key.
|
|
12
|
+
* @param socket - the connected OpenSSH forwarding socket.
|
|
13
|
+
* @param capability - the per-stream 256-bit key encoded as hexadecimal.
|
|
14
|
+
* @param timeoutMs - deadline for completing TLS authentication.
|
|
15
|
+
* @param signal - cancellation of authentication and the resulting TLS stream.
|
|
16
|
+
* @returns an authenticated paused stream; the key is never transmitted as data.
|
|
17
|
+
*/
|
|
18
|
+
export declare function authenticateStream(socket: Socket, capability: string, timeoutMs: number, signal?: AbortSignal): Promise<TLSSocket>;
|
|
19
|
+
//# sourceMappingURL=stream-security.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jabberwocky238/dsh-ssh",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.2.4",
|
|
4
|
+
"description": "Shared OpenSSH connection to a versioned POSIX helper, with per-Agent login binding",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./lib/types/index.d.ts",
|
|
10
|
+
"default": "./lib/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./protocol": {
|
|
13
|
+
"types": "./lib/types/protocol.d.ts",
|
|
14
|
+
"default": "./lib/protocol.js"
|
|
15
|
+
},
|
|
16
|
+
"./schemas": {
|
|
17
|
+
"types": "./lib/types/schemas.d.ts",
|
|
18
|
+
"default": "./lib/schemas.js"
|
|
19
|
+
},
|
|
20
|
+
"./package.json": "./package.json"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"lib/*.js",
|
|
24
|
+
"lib/types/**/*.d.ts"
|
|
25
|
+
],
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/Jabberwocky238/deepseek-harness.git",
|
|
30
|
+
"directory": "packages/ssh/ssh"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@deepseek-ai/schemastery": "~3.18.5-alpha.1",
|
|
37
|
+
"zod": "^4.4.3"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1",
|
|
41
|
+
"@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
|
|
42
|
+
"@deepseek-ai/dsh-util-values": "0.2.1-alpha.2"
|
|
43
|
+
}
|
|
6
44
|
}
|