ssh-mcp-pro 1.0.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.
- package/AGENTS.md +127 -0
- package/ARCHITECTURE.md +145 -0
- package/LICENSE +21 -0
- package/LICENSES/MIT.txt +21 -0
- package/MIGRATION.md +14 -0
- package/README.md +175 -0
- package/REGISTRY_SUBMISSION.md +38 -0
- package/SECURITY.md +40 -0
- package/SECURITY_DECISIONS.md +59 -0
- package/dist/agent-bin.d.ts +3 -0
- package/dist/agent-bin.d.ts.map +1 -0
- package/dist/agent-bin.js +8 -0
- package/dist/agent-bin.js.map +1 -0
- package/dist/audit.d.ts +25 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +50 -0
- package/dist/audit.js.map +1 -0
- package/dist/auth.d.ts +4 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +33 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +99 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +103 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +490 -0
- package/dist/config.js.map +1 -0
- package/dist/connector-credentials.d.ts +8 -0
- package/dist/connector-credentials.d.ts.map +1 -0
- package/dist/connector-credentials.js +132 -0
- package/dist/connector-credentials.js.map +1 -0
- package/dist/connector-profile.d.ts +17 -0
- package/dist/connector-profile.d.ts.map +1 -0
- package/dist/connector-profile.js +81 -0
- package/dist/connector-profile.js.map +1 -0
- package/dist/container.d.ts +18 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/container.js +52 -0
- package/dist/container.js.map +1 -0
- package/dist/detect.d.ts +7 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +271 -0
- package/dist/detect.js.map +1 -0
- package/dist/ensure.d.ts +17 -0
- package/dist/ensure.d.ts.map +1 -0
- package/dist/ensure.js +531 -0
- package/dist/ensure.js.map +1 -0
- package/dist/errors.d.ts +54 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +84 -0
- package/dist/errors.js.map +1 -0
- package/dist/fs-tools.d.ts +26 -0
- package/dist/fs-tools.d.ts.map +1 -0
- package/dist/fs-tools.js +599 -0
- package/dist/fs-tools.js.map +1 -0
- package/dist/http-rate-limit.d.ts +9 -0
- package/dist/http-rate-limit.d.ts.map +1 -0
- package/dist/http-rate-limit.js +41 -0
- package/dist/http-rate-limit.js.map +1 -0
- package/dist/http-security.d.ts +22 -0
- package/dist/http-security.d.ts.map +1 -0
- package/dist/http-security.js +88 -0
- package/dist/http-security.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +201 -0
- package/dist/index.js.map +1 -0
- package/dist/logging.d.ts +52 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +180 -0
- package/dist/logging.js.map +1 -0
- package/dist/mcp.d.ts +16 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +159 -0
- package/dist/mcp.js.map +1 -0
- package/dist/metrics.d.ts +95 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +204 -0
- package/dist/metrics.js.map +1 -0
- package/dist/oauth.d.ts +14 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +105 -0
- package/dist/oauth.js.map +1 -0
- package/dist/policy.d.ts +64 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +368 -0
- package/dist/policy.js.map +1 -0
- package/dist/process.d.ts +24 -0
- package/dist/process.d.ts.map +1 -0
- package/dist/process.js +212 -0
- package/dist/process.js.map +1 -0
- package/dist/prompts.d.ts +49 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +191 -0
- package/dist/prompts.js.map +1 -0
- package/dist/rate-limiter.d.ts +57 -0
- package/dist/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter.js +141 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/remote/agent-cli.d.ts +2 -0
- package/dist/remote/agent-cli.d.ts.map +1 -0
- package/dist/remote/agent-cli.js +270 -0
- package/dist/remote/agent-cli.js.map +1 -0
- package/dist/remote/agent-executor.d.ts +26 -0
- package/dist/remote/agent-executor.d.ts.map +1 -0
- package/dist/remote/agent-executor.js +400 -0
- package/dist/remote/agent-executor.js.map +1 -0
- package/dist/remote/config.d.ts +3 -0
- package/dist/remote/config.d.ts.map +1 -0
- package/dist/remote/config.js +52 -0
- package/dist/remote/config.js.map +1 -0
- package/dist/remote/control-plane.d.ts +57 -0
- package/dist/remote/control-plane.d.ts.map +1 -0
- package/dist/remote/control-plane.js +1248 -0
- package/dist/remote/control-plane.js.map +1 -0
- package/dist/remote/crypto.d.ts +38 -0
- package/dist/remote/crypto.d.ts.map +1 -0
- package/dist/remote/crypto.js +143 -0
- package/dist/remote/crypto.js.map +1 -0
- package/dist/remote/mcp-tools.d.ts +10 -0
- package/dist/remote/mcp-tools.d.ts.map +1 -0
- package/dist/remote/mcp-tools.js +201 -0
- package/dist/remote/mcp-tools.js.map +1 -0
- package/dist/remote/policy.d.ts +11 -0
- package/dist/remote/policy.d.ts.map +1 -0
- package/dist/remote/policy.js +94 -0
- package/dist/remote/policy.js.map +1 -0
- package/dist/remote/schemas.d.ts +298 -0
- package/dist/remote/schemas.d.ts.map +1 -0
- package/dist/remote/schemas.js +111 -0
- package/dist/remote/schemas.js.map +1 -0
- package/dist/remote/scopes.d.ts +6 -0
- package/dist/remote/scopes.d.ts.map +1 -0
- package/dist/remote/scopes.js +24 -0
- package/dist/remote/scopes.js.map +1 -0
- package/dist/remote/store.d.ts +45 -0
- package/dist/remote/store.d.ts.map +1 -0
- package/dist/remote/store.js +355 -0
- package/dist/remote/store.js.map +1 -0
- package/dist/remote/types.d.ts +183 -0
- package/dist/remote/types.d.ts.map +1 -0
- package/dist/remote/types.js +103 -0
- package/dist/remote/types.js.map +1 -0
- package/dist/remote/util.d.ts +6 -0
- package/dist/remote/util.d.ts.map +1 -0
- package/dist/remote/util.js +45 -0
- package/dist/remote/util.js.map +1 -0
- package/dist/remote/websocket.d.ts +26 -0
- package/dist/remote/websocket.d.ts.map +1 -0
- package/dist/remote/websocket.js +167 -0
- package/dist/remote/websocket.js.map +1 -0
- package/dist/render-http.d.ts +2 -0
- package/dist/render-http.d.ts.map +1 -0
- package/dist/render-http.js +14 -0
- package/dist/render-http.js.map +1 -0
- package/dist/resources.d.ts +19 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +96 -0
- package/dist/resources.js.map +1 -0
- package/dist/retry.d.ts +45 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +120 -0
- package/dist/retry.js.map +1 -0
- package/dist/safety.d.ts +31 -0
- package/dist/safety.d.ts.map +1 -0
- package/dist/safety.js +174 -0
- package/dist/safety.js.map +1 -0
- package/dist/server-http.d.ts +2 -0
- package/dist/server-http.d.ts.map +1 -0
- package/dist/server-http.js +432 -0
- package/dist/server-http.js.map +1 -0
- package/dist/session.d.ts +116 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +666 -0
- package/dist/session.js.map +1 -0
- package/dist/shell.d.ts +10 -0
- package/dist/shell.d.ts.map +1 -0
- package/dist/shell.js +83 -0
- package/dist/shell.js.map +1 -0
- package/dist/ssh-config.d.ts +94 -0
- package/dist/ssh-config.d.ts.map +1 -0
- package/dist/ssh-config.js +234 -0
- package/dist/ssh-config.js.map +1 -0
- package/dist/streaming.d.ts +36 -0
- package/dist/streaming.d.ts.map +1 -0
- package/dist/streaming.js +140 -0
- package/dist/streaming.js.map +1 -0
- package/dist/telemetry.d.ts +17 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +101 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/tools/connector.provider.d.ts +28 -0
- package/dist/tools/connector.provider.d.ts.map +1 -0
- package/dist/tools/connector.provider.js +360 -0
- package/dist/tools/connector.provider.js.map +1 -0
- package/dist/tools/ensure.provider.d.ts +18 -0
- package/dist/tools/ensure.provider.d.ts.map +1 -0
- package/dist/tools/ensure.provider.js +173 -0
- package/dist/tools/ensure.provider.js.map +1 -0
- package/dist/tools/fs.provider.d.ts +21 -0
- package/dist/tools/fs.provider.d.ts.map +1 -0
- package/dist/tools/fs.provider.js +259 -0
- package/dist/tools/fs.provider.js.map +1 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +68 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/metadata.d.ts +11 -0
- package/dist/tools/metadata.d.ts.map +1 -0
- package/dist/tools/metadata.js +10 -0
- package/dist/tools/metadata.js.map +1 -0
- package/dist/tools/output-schemas.d.ts +217 -0
- package/dist/tools/output-schemas.d.ts.map +1 -0
- package/dist/tools/output-schemas.js +300 -0
- package/dist/tools/output-schemas.js.map +1 -0
- package/dist/tools/process.provider.d.ts +22 -0
- package/dist/tools/process.provider.d.ts.map +1 -0
- package/dist/tools/process.provider.js +146 -0
- package/dist/tools/process.provider.js.map +1 -0
- package/dist/tools/registry.d.ts +12 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +163 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/results.d.ts +4 -0
- package/dist/tools/results.d.ts.map +1 -0
- package/dist/tools/results.js +5 -0
- package/dist/tools/results.js.map +1 -0
- package/dist/tools/session.provider.d.ts +23 -0
- package/dist/tools/session.provider.d.ts.map +1 -0
- package/dist/tools/session.provider.js +299 -0
- package/dist/tools/session.provider.js.map +1 -0
- package/dist/tools/system.provider.d.ts +18 -0
- package/dist/tools/system.provider.d.ts.map +1 -0
- package/dist/tools/system.provider.js +81 -0
- package/dist/tools/system.provider.js.map +1 -0
- package/dist/tools/transfer.provider.d.ts +16 -0
- package/dist/tools/transfer.provider.d.ts.map +1 -0
- package/dist/tools/transfer.provider.js +85 -0
- package/dist/tools/transfer.provider.js.map +1 -0
- package/dist/tools/tunnel.provider.d.ts +18 -0
- package/dist/tools/tunnel.provider.d.ts.map +1 -0
- package/dist/tools/tunnel.provider.js +142 -0
- package/dist/tools/tunnel.provider.js.map +1 -0
- package/dist/tools/types.d.ts +16 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/transfer.d.ts +40 -0
- package/dist/transfer.d.ts.map +1 -0
- package/dist/transfer.js +363 -0
- package/dist/transfer.js.map +1 -0
- package/dist/tunnel.d.ts +37 -0
- package/dist/tunnel.d.ts.map +1 -0
- package/dist/tunnel.js +234 -0
- package/dist/tunnel.js.map +1 -0
- package/dist/types.d.ts +341 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +184 -0
- package/dist/types.js.map +1 -0
- package/docs/docker.md +22 -0
- package/examples/README.md +77 -0
- package/mcp.json +21 -0
- package/package.json +147 -0
- package/registry/ssh-mcp-pro/mcp.json +21 -0
- package/server.json +76 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ServerResponse } from "node:http";
|
|
2
|
+
export declare function parseList(value: string | undefined): string[];
|
|
3
|
+
export declare function jsonResponse(res: ServerResponse, status: number, body: unknown, headers?: Record<string, string>): void;
|
|
4
|
+
export declare function formDecode(body: string): Record<string, string>;
|
|
5
|
+
export declare function userSafeError(error: unknown): string;
|
|
6
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/remote/util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAQ7D;AAED,wBAAgB,YAAY,CAC1B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACnC,IAAI,CAMN;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAU/D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAgBpD"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export function parseList(value) {
|
|
2
|
+
if (!value) {
|
|
3
|
+
return [];
|
|
4
|
+
}
|
|
5
|
+
return value
|
|
6
|
+
.split(/[\n,]/u)
|
|
7
|
+
.map((item) => item.trim())
|
|
8
|
+
.filter(Boolean);
|
|
9
|
+
}
|
|
10
|
+
export function jsonResponse(res, status, body, headers = {}) {
|
|
11
|
+
res.writeHead(status, {
|
|
12
|
+
"Content-Type": "application/json",
|
|
13
|
+
...headers,
|
|
14
|
+
});
|
|
15
|
+
res.end(JSON.stringify(body, null, 2));
|
|
16
|
+
}
|
|
17
|
+
export function formDecode(body) {
|
|
18
|
+
const params = new URLSearchParams(body);
|
|
19
|
+
const decoded = {};
|
|
20
|
+
for (const [key, value] of params.entries()) {
|
|
21
|
+
if (key in decoded) {
|
|
22
|
+
throw new Error(`Duplicate form parameter: ${key}`);
|
|
23
|
+
}
|
|
24
|
+
decoded[key] = value;
|
|
25
|
+
}
|
|
26
|
+
return decoded;
|
|
27
|
+
}
|
|
28
|
+
export function userSafeError(error) {
|
|
29
|
+
if (error instanceof Error) {
|
|
30
|
+
return error.message;
|
|
31
|
+
}
|
|
32
|
+
if (error && typeof error === "object") {
|
|
33
|
+
const record = error;
|
|
34
|
+
const message = typeof record.message === "string" ? record.message : undefined;
|
|
35
|
+
const code = typeof record.code === "string" ? record.code : undefined;
|
|
36
|
+
if (message && code) {
|
|
37
|
+
return `${code}: ${message}`;
|
|
38
|
+
}
|
|
39
|
+
if (message) {
|
|
40
|
+
return message;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return String(error);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/remote/util.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,SAAS,CAAC,KAAyB;IACjD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK;SACT,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,GAAmB,EACnB,MAAc,EACd,IAAa,EACb,UAAkC,EAAE;IAEpC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE;QACpB,cAAc,EAAE,kBAAkB;QAClC,GAAG,OAAO;KACX,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,IAAI,GAAG,IAAI,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,6BAA6B,GAAG,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACvB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IACD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,KAAgC,CAAC;QAChD,MAAM,OAAO,GAAG,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QAChF,MAAM,IAAI,GAAG,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QACvE,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACpB,OAAO,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC;QAC/B,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { IncomingMessage } from "node:http";
|
|
2
|
+
import type { Duplex } from "node:stream";
|
|
3
|
+
export type WebSocketTextHandler = (message: string) => void;
|
|
4
|
+
export type WebSocketCloseHandler = () => void;
|
|
5
|
+
export declare class MinimalWebSocketConnection {
|
|
6
|
+
private readonly socket;
|
|
7
|
+
private static readonly MAX_FRAME_BYTES;
|
|
8
|
+
private buffer;
|
|
9
|
+
private closed;
|
|
10
|
+
private closeNotified;
|
|
11
|
+
private readonly textHandlers;
|
|
12
|
+
private readonly closeHandlers;
|
|
13
|
+
constructor(socket: Duplex, initialBuffer?: Buffer<ArrayBufferLike>);
|
|
14
|
+
onText(handler: WebSocketTextHandler): void;
|
|
15
|
+
onClose(handler: WebSocketCloseHandler): void;
|
|
16
|
+
sendJson(value: unknown): void;
|
|
17
|
+
sendText(value: string): void;
|
|
18
|
+
close(): void;
|
|
19
|
+
private handleData;
|
|
20
|
+
private drainFrames;
|
|
21
|
+
private createFrameHeader;
|
|
22
|
+
private handleClose;
|
|
23
|
+
private notifyClose;
|
|
24
|
+
}
|
|
25
|
+
export declare function acceptWebSocketUpgrade(req: IncomingMessage, socket: Duplex, head?: Buffer<ArrayBufferLike>): MinimalWebSocketConnection;
|
|
26
|
+
//# sourceMappingURL=websocket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/remote/websocket.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAC7D,MAAM,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC;AAE/C,qBAAa,0BAA0B;IASnC,OAAO,CAAC,QAAQ,CAAC,MAAM;IARzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAa;IACpD,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAmC;IAChE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoC;gBAG/C,MAAM,EAAE,MAAM,EAC/B,aAAa,GAAE,MAAM,CAAC,eAAe,CAAmB;IAa1D,MAAM,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAK3C,OAAO,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAI7C,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAI9B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAS7B,KAAK,IAAI,IAAI;IASb,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,WAAW;IA+DnB,OAAO,CAAC,iBAAiB;IAkBzB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,WAAW;CASpB;AAED,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,MAAM,CAAC,eAAe,CAAmB,GAC9C,0BAA0B,CAoB5B"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
export class MinimalWebSocketConnection {
|
|
3
|
+
socket;
|
|
4
|
+
static MAX_FRAME_BYTES = 1_048_576;
|
|
5
|
+
buffer = Buffer.alloc(0);
|
|
6
|
+
closed = false;
|
|
7
|
+
closeNotified = false;
|
|
8
|
+
textHandlers = new Set();
|
|
9
|
+
closeHandlers = new Set();
|
|
10
|
+
constructor(socket, initialBuffer = Buffer.alloc(0)) {
|
|
11
|
+
this.socket = socket;
|
|
12
|
+
if (initialBuffer.length > MinimalWebSocketConnection.MAX_FRAME_BYTES) {
|
|
13
|
+
socket.destroy();
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
this.buffer = initialBuffer;
|
|
17
|
+
}
|
|
18
|
+
socket.on("data", (chunk) => this.handleData(chunk));
|
|
19
|
+
socket.on("close", () => this.handleClose());
|
|
20
|
+
socket.on("end", () => this.handleClose());
|
|
21
|
+
socket.on("error", () => this.handleClose());
|
|
22
|
+
}
|
|
23
|
+
onText(handler) {
|
|
24
|
+
this.textHandlers.add(handler);
|
|
25
|
+
this.drainFrames();
|
|
26
|
+
}
|
|
27
|
+
onClose(handler) {
|
|
28
|
+
this.closeHandlers.add(handler);
|
|
29
|
+
}
|
|
30
|
+
sendJson(value) {
|
|
31
|
+
this.sendText(JSON.stringify(value));
|
|
32
|
+
}
|
|
33
|
+
sendText(value) {
|
|
34
|
+
if (this.closed) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const payload = Buffer.from(value, "utf8");
|
|
38
|
+
const header = this.createFrameHeader(payload.length, 0x1);
|
|
39
|
+
this.socket.write(Buffer.concat([header, payload]));
|
|
40
|
+
}
|
|
41
|
+
close() {
|
|
42
|
+
if (this.closed) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
this.closed = true;
|
|
46
|
+
this.socket.end(Buffer.from([0x88, 0x00]));
|
|
47
|
+
this.notifyClose();
|
|
48
|
+
}
|
|
49
|
+
handleData(chunk) {
|
|
50
|
+
if (this.buffer.length + chunk.length > MinimalWebSocketConnection.MAX_FRAME_BYTES) {
|
|
51
|
+
this.close();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
55
|
+
this.drainFrames();
|
|
56
|
+
}
|
|
57
|
+
drainFrames() {
|
|
58
|
+
while (this.buffer.length >= 2) {
|
|
59
|
+
const first = this.buffer[0] ?? 0;
|
|
60
|
+
const second = this.buffer[1] ?? 0;
|
|
61
|
+
const opcode = first & 0x0f;
|
|
62
|
+
const masked = (second & 0x80) !== 0;
|
|
63
|
+
let length = second & 0x7f;
|
|
64
|
+
let offset = 2;
|
|
65
|
+
if (length === 126) {
|
|
66
|
+
if (this.buffer.length < 4) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
length = this.buffer.readUInt16BE(2);
|
|
70
|
+
offset = 4;
|
|
71
|
+
}
|
|
72
|
+
else if (length === 127) {
|
|
73
|
+
if (this.buffer.length < 10) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const longLength = this.buffer.readBigUInt64BE(2);
|
|
77
|
+
if (longLength > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
78
|
+
this.close();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
length = Number(longLength);
|
|
82
|
+
offset = 10;
|
|
83
|
+
}
|
|
84
|
+
if (length > MinimalWebSocketConnection.MAX_FRAME_BYTES) {
|
|
85
|
+
this.close();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const maskLength = masked ? 4 : 0;
|
|
89
|
+
if (this.buffer.length < offset + maskLength + length) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const mask = masked ? this.buffer.subarray(offset, offset + 4) : undefined;
|
|
93
|
+
offset += maskLength;
|
|
94
|
+
const payload = Buffer.from(this.buffer.subarray(offset, offset + length));
|
|
95
|
+
this.buffer = this.buffer.subarray(offset + length);
|
|
96
|
+
if (mask) {
|
|
97
|
+
for (let index = 0; index < payload.length; index++) {
|
|
98
|
+
payload[index] = (payload[index] ?? 0) ^ (mask[index % 4] ?? 0);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (opcode === 0x8) {
|
|
102
|
+
this.close();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (opcode === 0x9) {
|
|
106
|
+
this.socket.write(Buffer.concat([this.createFrameHeader(payload.length, 0x0a), payload]));
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (opcode === 0x1) {
|
|
110
|
+
const message = payload.toString("utf8");
|
|
111
|
+
for (const handler of this.textHandlers) {
|
|
112
|
+
handler(message);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
createFrameHeader(length, opcode) {
|
|
118
|
+
if (length < 126) {
|
|
119
|
+
return Buffer.from([0x80 | opcode, length]);
|
|
120
|
+
}
|
|
121
|
+
if (length <= 0xffff) {
|
|
122
|
+
const header = Buffer.alloc(4);
|
|
123
|
+
header[0] = 0x80 | opcode;
|
|
124
|
+
header[1] = 126;
|
|
125
|
+
header.writeUInt16BE(length, 2);
|
|
126
|
+
return header;
|
|
127
|
+
}
|
|
128
|
+
const header = Buffer.alloc(10);
|
|
129
|
+
header[0] = 0x80 | opcode;
|
|
130
|
+
header[1] = 127;
|
|
131
|
+
header.writeBigUInt64BE(BigInt(length), 2);
|
|
132
|
+
return header;
|
|
133
|
+
}
|
|
134
|
+
handleClose() {
|
|
135
|
+
this.closed = true;
|
|
136
|
+
this.notifyClose();
|
|
137
|
+
}
|
|
138
|
+
notifyClose() {
|
|
139
|
+
if (this.closeNotified) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
this.closeNotified = true;
|
|
143
|
+
for (const handler of this.closeHandlers) {
|
|
144
|
+
handler();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
export function acceptWebSocketUpgrade(req, socket, head = Buffer.alloc(0)) {
|
|
149
|
+
const key = req.headers["sec-websocket-key"];
|
|
150
|
+
if (typeof key !== "string") {
|
|
151
|
+
socket.destroy();
|
|
152
|
+
throw new Error("Missing Sec-WebSocket-Key");
|
|
153
|
+
}
|
|
154
|
+
const accept = createHash("sha1")
|
|
155
|
+
.update(`${key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`)
|
|
156
|
+
.digest("base64");
|
|
157
|
+
socket.write([
|
|
158
|
+
"HTTP/1.1 101 Switching Protocols",
|
|
159
|
+
"Upgrade: websocket",
|
|
160
|
+
"Connection: Upgrade",
|
|
161
|
+
`Sec-WebSocket-Accept: ${accept}`,
|
|
162
|
+
"",
|
|
163
|
+
"",
|
|
164
|
+
].join("\r\n"));
|
|
165
|
+
return new MinimalWebSocketConnection(socket, head);
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=websocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../src/remote/websocket.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-http.d.ts","sourceRoot":"","sources":["../src/render-http.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { chmodSync, mkdtempSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
const bearerToken = process.env.SSH_MCP_HTTP_BEARER_TOKEN?.trim();
|
|
5
|
+
if (bearerToken && !process.env.SSH_MCP_HTTP_BEARER_TOKEN_FILE) {
|
|
6
|
+
const tokenDir = mkdtempSync(join(tmpdir(), "ssh-mcp-pro-"));
|
|
7
|
+
chmodSync(tokenDir, 0o700);
|
|
8
|
+
const tokenPath = join(tokenDir, "bearer-token");
|
|
9
|
+
writeFileSync(tokenPath, bearerToken, { encoding: "utf8", mode: 0o600 });
|
|
10
|
+
chmodSync(tokenPath, 0o600);
|
|
11
|
+
process.env.SSH_MCP_HTTP_BEARER_TOKEN_FILE = tokenPath;
|
|
12
|
+
}
|
|
13
|
+
await import("./server-http.js");
|
|
14
|
+
//# sourceMappingURL=render-http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-http.js","sourceRoot":"","sources":["../src/render-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,IAAI,EAAE,CAAC;AAElE,IAAI,WAAW,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,CAAC;IAC/D,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;IAC7D,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IACjD,aAAa,CAAC,SAAS,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACzE,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,8BAA8B,GAAG,SAAS,CAAC;AACzD,CAAC;AAED,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AppContainer } from "./container.js";
|
|
2
|
+
import { type ToolProfile } from "./connector-profile.js";
|
|
3
|
+
export interface MCPResource {
|
|
4
|
+
uri: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
mimeType: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function listResources(profile?: ToolProfile): {
|
|
10
|
+
resources: MCPResource[];
|
|
11
|
+
};
|
|
12
|
+
export declare function readResource(uri: string, container: AppContainer, profile?: ToolProfile): Promise<{
|
|
13
|
+
contents: Array<{
|
|
14
|
+
uri: string;
|
|
15
|
+
mimeType: string;
|
|
16
|
+
text: string;
|
|
17
|
+
}>;
|
|
18
|
+
}>;
|
|
19
|
+
//# sourceMappingURL=resources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA+CD,wBAAgB,aAAa,CAAC,OAAO,GAAE,WAAoB,GAAG;IAAE,SAAS,EAAE,WAAW,EAAE,CAAA;CAAE,CAOzF;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,YAAY,EACvB,OAAO,GAAE,WAAoB,GAC5B,OAAO,CAAC;IACT,QAAQ,EAAE,KAAK,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;CACJ,CAAC,CA+BD"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { getConfiguredHosts } from "./ssh-config.js";
|
|
2
|
+
import { filterResourcesForProfile, isResourceAllowedForProfile, } from "./connector-profile.js";
|
|
3
|
+
const RESOURCE_DEFINITIONS = [
|
|
4
|
+
{
|
|
5
|
+
uri: "ssh-mcp-pro://sessions/active",
|
|
6
|
+
name: "Active SSH sessions",
|
|
7
|
+
description: "Current in-memory SSH sessions tracked by the session manager",
|
|
8
|
+
mimeType: "application/json",
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
uri: "ssh-mcp-pro://metrics/json",
|
|
12
|
+
name: "Metrics snapshot",
|
|
13
|
+
description: "Current runtime metrics in JSON format",
|
|
14
|
+
mimeType: "application/json",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
uri: "ssh-mcp-pro://metrics/prometheus",
|
|
18
|
+
name: "Prometheus metrics",
|
|
19
|
+
description: "Prometheus-formatted metrics export",
|
|
20
|
+
mimeType: "text/plain",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
uri: "ssh-mcp-pro://ssh-config/hosts",
|
|
24
|
+
name: "Configured SSH hosts",
|
|
25
|
+
description: "Parsed host aliases from the local ~/.ssh/config cache",
|
|
26
|
+
mimeType: "application/json",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
uri: "ssh-mcp-pro://policy/effective",
|
|
30
|
+
name: "Effective safety policy",
|
|
31
|
+
description: "Current command, path, host, and privilege policy after env/file overrides",
|
|
32
|
+
mimeType: "application/json",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
uri: "ssh-mcp-pro://audit/recent",
|
|
36
|
+
name: "Recent audit events",
|
|
37
|
+
description: "Recent policy and high-risk operation audit events",
|
|
38
|
+
mimeType: "application/json",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
uri: "ssh-mcp-pro://capabilities/support-matrix",
|
|
42
|
+
name: "Support matrix",
|
|
43
|
+
description: "Supported and experimental host capabilities for this server",
|
|
44
|
+
mimeType: "application/json",
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
export function listResources(profile = "full") {
|
|
48
|
+
return {
|
|
49
|
+
resources: filterResourcesForProfile(RESOURCE_DEFINITIONS.map((resource) => ({ ...resource })), profile),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export async function readResource(uri, container, profile = "full") {
|
|
53
|
+
if (!isResourceAllowedForProfile(uri, profile)) {
|
|
54
|
+
throw new Error(`Resource ${uri} is not exposed by the ${profile} connector profile`);
|
|
55
|
+
}
|
|
56
|
+
switch (uri) {
|
|
57
|
+
case "ssh-mcp-pro://sessions/active":
|
|
58
|
+
return jsonResource(uri, "application/json", container.sessionManager.getActiveSessions());
|
|
59
|
+
case "ssh-mcp-pro://metrics/json":
|
|
60
|
+
return jsonResource(uri, "application/json", container.metrics.getMetrics());
|
|
61
|
+
case "ssh-mcp-pro://metrics/prometheus":
|
|
62
|
+
return textResource(uri, "text/plain", container.metrics.exportPrometheus());
|
|
63
|
+
case "ssh-mcp-pro://ssh-config/hosts":
|
|
64
|
+
return jsonResource(uri, "application/json", {
|
|
65
|
+
hosts: await getConfiguredHosts(),
|
|
66
|
+
});
|
|
67
|
+
case "ssh-mcp-pro://policy/effective":
|
|
68
|
+
return jsonResource(uri, "application/json", container.policy.getEffectivePolicy());
|
|
69
|
+
case "ssh-mcp-pro://audit/recent":
|
|
70
|
+
return jsonResource(uri, "application/json", { events: container.auditLog.list(100) });
|
|
71
|
+
case "ssh-mcp-pro://capabilities/support-matrix":
|
|
72
|
+
return jsonResource(uri, "application/json", {
|
|
73
|
+
linux: "full",
|
|
74
|
+
macos: "session/process/fs/transfer; package/service helpers limited to tested managers",
|
|
75
|
+
"BusyBox/dropbear": "experimental: session/process/basic fs without SFTP",
|
|
76
|
+
windows: "experimental: session/process/fs/transfer; ensure_package supports winget/choco; sudo/service helpers unsupported",
|
|
77
|
+
});
|
|
78
|
+
default:
|
|
79
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function jsonResource(uri, mimeType, value) {
|
|
83
|
+
return textResource(uri, mimeType, JSON.stringify(value, null, 2));
|
|
84
|
+
}
|
|
85
|
+
function textResource(uri, mimeType, text) {
|
|
86
|
+
return {
|
|
87
|
+
contents: [
|
|
88
|
+
{
|
|
89
|
+
uri,
|
|
90
|
+
mimeType,
|
|
91
|
+
text,
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
|
package/dist/retry.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry configuration options
|
|
3
|
+
*/
|
|
4
|
+
export interface RetryOptions {
|
|
5
|
+
/** Maximum number of retry attempts */
|
|
6
|
+
maxAttempts: number;
|
|
7
|
+
/** Initial delay between retries in milliseconds */
|
|
8
|
+
initialDelayMs: number;
|
|
9
|
+
/** Maximum delay between retries in milliseconds */
|
|
10
|
+
maxDelayMs: number;
|
|
11
|
+
/** Multiplier for exponential backoff */
|
|
12
|
+
backoffMultiplier: number;
|
|
13
|
+
/** Whether to add jitter to delays */
|
|
14
|
+
jitter: boolean;
|
|
15
|
+
/** Function to determine if error is retryable */
|
|
16
|
+
isRetryable?: (error: unknown) => boolean;
|
|
17
|
+
/** Callback on each retry attempt */
|
|
18
|
+
onRetry?: (attempt: number, error: unknown, delayMs: number) => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Result of a retry operation
|
|
22
|
+
*/
|
|
23
|
+
export interface RetryResult<T> {
|
|
24
|
+
success: boolean;
|
|
25
|
+
result?: T;
|
|
26
|
+
error?: unknown;
|
|
27
|
+
attempts: number;
|
|
28
|
+
totalTimeMs: number;
|
|
29
|
+
}
|
|
30
|
+
type DecoratedAsyncMethod = (...args: unknown[]) => Promise<unknown>;
|
|
31
|
+
/**
|
|
32
|
+
* Execute a function with retry logic
|
|
33
|
+
* Uses exponential backoff with optional jitter
|
|
34
|
+
*/
|
|
35
|
+
export declare function withRetry<T>(fn: () => Promise<T>, options?: Partial<RetryOptions>): Promise<RetryResult<T>>;
|
|
36
|
+
/**
|
|
37
|
+
* Decorator-style retry wrapper for class methods
|
|
38
|
+
*/
|
|
39
|
+
export declare function retryable(options?: Partial<RetryOptions>): (_target: object, _propertyKey: string, descriptor: TypedPropertyDescriptor<DecoratedAsyncMethod>) => TypedPropertyDescriptor<DecoratedAsyncMethod>;
|
|
40
|
+
/**
|
|
41
|
+
* Simple retry wrapper that throws on failure
|
|
42
|
+
*/
|
|
43
|
+
export declare function retry<T>(fn: () => Promise<T>, options?: Partial<RetryOptions>): Promise<T>;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,cAAc,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sCAAsC;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,kDAAkD;IAClD,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IAC1C,qCAAqC;IACrC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACtE;AAED;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,CAAC;IACX,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,KAAK,oBAAoB,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAuDrE;;;GAGG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE,OAAO,CAAC,YAAY,CAAM,GAClC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CA+CzB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,OAAO,CAAC,YAAY,CAAM,IAEzD,SAAS,MAAM,EACf,cAAc,MAAM,EACpB,YAAY,uBAAuB,CAAC,oBAAoB,CAAC,mDAmB5D;AAED;;GAEG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAC3B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE,OAAO,CAAC,YAAY,CAAM,GAClC,OAAO,CAAC,CAAC,CAAC,CAQZ"}
|
package/dist/retry.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { logger } from "./logging.js";
|
|
2
|
+
const DEFAULT_OPTIONS = {
|
|
3
|
+
maxAttempts: 3,
|
|
4
|
+
initialDelayMs: 1000,
|
|
5
|
+
maxDelayMs: 30000,
|
|
6
|
+
backoffMultiplier: 2,
|
|
7
|
+
jitter: true,
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Default retry predicate - retries on network and timeout errors
|
|
11
|
+
*/
|
|
12
|
+
function defaultIsRetryable(error) {
|
|
13
|
+
if (error instanceof Error) {
|
|
14
|
+
const message = error.message.toLowerCase();
|
|
15
|
+
// Retry on transient errors
|
|
16
|
+
return (message.includes("timeout") ||
|
|
17
|
+
message.includes("etimedout") ||
|
|
18
|
+
message.includes("econnreset") ||
|
|
19
|
+
message.includes("econnrefused") ||
|
|
20
|
+
message.includes("epipe") ||
|
|
21
|
+
message.includes("network") ||
|
|
22
|
+
message.includes("socket hang up"));
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Calculate delay with optional jitter
|
|
28
|
+
*/
|
|
29
|
+
function calculateDelay(attempt, options) {
|
|
30
|
+
const exponentialDelay = options.initialDelayMs * Math.pow(options.backoffMultiplier, attempt - 1);
|
|
31
|
+
const cappedDelay = Math.min(exponentialDelay, options.maxDelayMs);
|
|
32
|
+
if (options.jitter) {
|
|
33
|
+
// Add random jitter: ±25% of the delay
|
|
34
|
+
const jitterRange = cappedDelay * 0.25;
|
|
35
|
+
const jitter = (Math.random() * 2 - 1) * jitterRange;
|
|
36
|
+
return Math.max(0, cappedDelay + jitter);
|
|
37
|
+
}
|
|
38
|
+
return cappedDelay;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Sleep for a given duration
|
|
42
|
+
*/
|
|
43
|
+
function sleep(ms) {
|
|
44
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Execute a function with retry logic
|
|
48
|
+
* Uses exponential backoff with optional jitter
|
|
49
|
+
*/
|
|
50
|
+
export async function withRetry(fn, options = {}) {
|
|
51
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
52
|
+
const isRetryable = opts.isRetryable ?? defaultIsRetryable;
|
|
53
|
+
const startTime = Date.now();
|
|
54
|
+
let lastError;
|
|
55
|
+
for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {
|
|
56
|
+
try {
|
|
57
|
+
const result = await fn();
|
|
58
|
+
return {
|
|
59
|
+
success: true,
|
|
60
|
+
result,
|
|
61
|
+
attempts: attempt,
|
|
62
|
+
totalTimeMs: Date.now() - startTime,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
lastError = error;
|
|
67
|
+
// Check if we should retry
|
|
68
|
+
if (attempt >= opts.maxAttempts || !isRetryable(error)) {
|
|
69
|
+
logger.debug("Retry: giving up", {
|
|
70
|
+
attempt,
|
|
71
|
+
maxAttempts: opts.maxAttempts,
|
|
72
|
+
retryable: isRetryable(error),
|
|
73
|
+
});
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
const delayMs = calculateDelay(attempt, opts);
|
|
77
|
+
logger.debug("Retry: scheduling retry", { attempt, delayMs });
|
|
78
|
+
if (opts.onRetry) {
|
|
79
|
+
opts.onRetry(attempt, error, delayMs);
|
|
80
|
+
}
|
|
81
|
+
await sleep(delayMs);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
success: false,
|
|
86
|
+
error: lastError,
|
|
87
|
+
attempts: opts.maxAttempts,
|
|
88
|
+
totalTimeMs: Date.now() - startTime,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Decorator-style retry wrapper for class methods
|
|
93
|
+
*/
|
|
94
|
+
export function retryable(options = {}) {
|
|
95
|
+
return function (_target, _propertyKey, descriptor) {
|
|
96
|
+
const originalMethod = descriptor.value;
|
|
97
|
+
if (!originalMethod) {
|
|
98
|
+
return descriptor;
|
|
99
|
+
}
|
|
100
|
+
descriptor.value = async function (...args) {
|
|
101
|
+
const result = await withRetry(() => originalMethod.apply(this, args), options);
|
|
102
|
+
if (!result.success) {
|
|
103
|
+
throw result.error;
|
|
104
|
+
}
|
|
105
|
+
return result.result;
|
|
106
|
+
};
|
|
107
|
+
return descriptor;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Simple retry wrapper that throws on failure
|
|
112
|
+
*/
|
|
113
|
+
export async function retry(fn, options = {}) {
|
|
114
|
+
const result = await withRetry(fn, options);
|
|
115
|
+
if (!result.success) {
|
|
116
|
+
throw result.error;
|
|
117
|
+
}
|
|
118
|
+
return result.result;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"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"}
|
package/dist/safety.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safety utilities for SSH command execution
|
|
3
|
+
*
|
|
4
|
+
* Provides warnings for potentially dangerous commands without blocking them.
|
|
5
|
+
* Users are free to execute any command - this is just informational.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Command safety check result
|
|
9
|
+
*/
|
|
10
|
+
export interface SafetyCheckResult {
|
|
11
|
+
safe: boolean;
|
|
12
|
+
warning?: string;
|
|
13
|
+
riskLevel?: "low" | "medium" | "high" | "critical";
|
|
14
|
+
suggestion?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Checks if a command is potentially dangerous
|
|
18
|
+
* This NEVER blocks commands - only provides warnings
|
|
19
|
+
*/
|
|
20
|
+
export declare function checkCommandSafety(command: string): SafetyCheckResult;
|
|
21
|
+
/**
|
|
22
|
+
* Formats a safety warning for inclusion in command output
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatSafetyWarning(result: SafetyCheckResult): string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Enhances command result with safety warning if applicable
|
|
27
|
+
*/
|
|
28
|
+
export declare function addSafetyWarningToResult<T extends object>(command: string, result: T): T & {
|
|
29
|
+
safetyWarning?: string;
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=safety.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../src/safety.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA+HD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAwBrE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAmBjF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,MAAM,EACvD,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,CAAC,GACR,CAAC,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,CAShC"}
|