ai-remote 0.5.0 → 0.6.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/README.md +40 -0
- package/SKILL.md +123 -13
- package/dist/{cli-chunk-Q33YGIDO.mjs → cli-chunk-L6E2YYPQ.mjs} +19 -5
- package/dist/{cli-chunk-F2TSY3YW.mjs → cli-chunk-P4645KKB.mjs} +3 -3
- package/dist/{cli-chunk-OZG2CODR.mjs → cli-chunk-TKKENOSJ.mjs} +1 -1
- package/dist/{cli-chunk-S2TWL5LF.mjs → cli-chunk-UD2YES3P.mjs} +107 -39
- package/dist/cli-chunk-WWORJ2NE.mjs +72 -0
- package/dist/{cli-copy-BOF44DWQ.mjs → cli-copy-2HQU2E7D.mjs} +18 -5
- package/dist/{cli-daemon-3BBFQCML.mjs → cli-daemon-3L36TBIB.mjs} +852 -274
- package/dist/{cli-identities-ZILT4XCR.mjs → cli-identities-GBQWYF2O.mjs} +4 -4
- package/dist/cli-known-hosts-UU427T4N.mjs +12 -0
- package/dist/{cli-secrets-26D3F6EN.mjs → cli-secrets-BMYFPDB2.mjs} +1 -1
- package/dist/cli-shell-JEC6BEME.mjs +11 -0
- package/dist/{cli-window-ZKAXEHQV.mjs → cli-window-AWXZ5NJX.mjs} +2 -2
- package/dist/cli.mjs +219 -109
- package/dist/computer.d.ts +77 -0
- package/dist/computer.js +3 -0
- package/dist/index.d.ts +80 -1
- package/dist/index.js +1 -1
- package/dist/protocols.d.ts +247 -17
- package/dist/protocols.js +16 -16
- package/package.json +6 -1
- package/dist/cli-shell-45XRTE7O.mjs +0 -10
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// src/cli/known-hosts.ts
|
|
2
|
+
import { chmodSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
function configDir() {
|
|
6
|
+
const base = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
7
|
+
return join(base, "ai-remote");
|
|
8
|
+
}
|
|
9
|
+
var storePath = () => join(configDir(), "known_hosts.json");
|
|
10
|
+
function read() {
|
|
11
|
+
try {
|
|
12
|
+
const parsed = JSON.parse(readFileSync(storePath(), "utf8"));
|
|
13
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
14
|
+
} catch {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function write(store) {
|
|
19
|
+
mkdirSync(configDir(), { recursive: true, mode: 448 });
|
|
20
|
+
writeFileSync(storePath(), `${JSON.stringify(store, null, 2)}
|
|
21
|
+
`, { mode: 384 });
|
|
22
|
+
chmodSync(storePath(), 384);
|
|
23
|
+
}
|
|
24
|
+
var hostAddress = (host, port) => `${host}:${port}`;
|
|
25
|
+
function checkHostKey(address, info, { insecure = false } = {}) {
|
|
26
|
+
const store = read();
|
|
27
|
+
const known = store[address];
|
|
28
|
+
if (known && known.fingerprint === info.fingerprint) {
|
|
29
|
+
return { accepted: true, status: "known", message: "" };
|
|
30
|
+
}
|
|
31
|
+
if (known && !insecure) {
|
|
32
|
+
return {
|
|
33
|
+
accepted: false,
|
|
34
|
+
status: "changed",
|
|
35
|
+
message: [
|
|
36
|
+
`The host key for ${address} has changed.`,
|
|
37
|
+
` expected: ${known.fingerprint}`,
|
|
38
|
+
` received: ${info.fingerprint} (${info.keyType})`,
|
|
39
|
+
"Someone may be intercepting this connection. If the machine was genuinely",
|
|
40
|
+
`rebuilt, run \`ai-remote forget-host ${address}\` and connect again.`
|
|
41
|
+
].join("\n")
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
store[address] = {
|
|
45
|
+
fingerprint: info.fingerprint,
|
|
46
|
+
keyType: info.keyType,
|
|
47
|
+
firstSeen: (/* @__PURE__ */ new Date()).toISOString()
|
|
48
|
+
};
|
|
49
|
+
write(store);
|
|
50
|
+
return {
|
|
51
|
+
accepted: true,
|
|
52
|
+
status: known ? "known" : "new",
|
|
53
|
+
message: known ? `Host key for ${address} replaced at your request: ${info.fingerprint}` : `Recorded host key for ${address}: ${info.fingerprint} (${info.keyType})`
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function forgetHostKey(address) {
|
|
57
|
+
const store = read();
|
|
58
|
+
if (!(address in store)) return false;
|
|
59
|
+
delete store[address];
|
|
60
|
+
write(store);
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
function knownHosts() {
|
|
64
|
+
return Object.entries(read()).map(([address, entry]) => ({ address, ...entry })).toSorted((a, b) => a.address < b.address ? -1 : a.address > b.address ? 1 : 0);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export {
|
|
68
|
+
hostAddress,
|
|
69
|
+
checkHostKey,
|
|
70
|
+
forgetHostKey,
|
|
71
|
+
knownHosts
|
|
72
|
+
};
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SshSession,
|
|
3
3
|
TcpTransport
|
|
4
|
-
} from "./cli-chunk-
|
|
4
|
+
} from "./cli-chunk-UD2YES3P.mjs";
|
|
5
5
|
import {
|
|
6
6
|
SshReader,
|
|
7
7
|
SshWriter
|
|
8
8
|
} from "./cli-chunk-XT2FISR5.mjs";
|
|
9
|
+
import {
|
|
10
|
+
checkHostKey,
|
|
11
|
+
hostAddress
|
|
12
|
+
} from "./cli-chunk-WWORJ2NE.mjs";
|
|
9
13
|
|
|
10
14
|
// src/cli/copy.ts
|
|
11
15
|
import { open as openFile, mkdir, readdir, stat as statFile } from "node:fs/promises";
|
|
@@ -438,10 +442,19 @@ var SftpConnection = class {
|
|
|
438
442
|
// and still redirectable on its own.
|
|
439
443
|
log: (step, detail) => process.stderr.write(`[SSH] ${step} ${JSON.stringify(detail)}
|
|
440
444
|
`),
|
|
441
|
-
// The same
|
|
442
|
-
//
|
|
443
|
-
|
|
444
|
-
|
|
445
|
+
// The same known_hosts file the terminal uses, on the same accept-new
|
|
446
|
+
// terms: a key that changed stops the copy rather than completing it.
|
|
447
|
+
verifyHost: (info) => {
|
|
448
|
+
const verdict = checkHostKey(
|
|
449
|
+
hostAddress(options.host, options.port),
|
|
450
|
+
info,
|
|
451
|
+
{ insecure: options.insecureHostKey }
|
|
452
|
+
);
|
|
453
|
+
if (verdict.message) process.stderr.write(`${verdict.message}
|
|
454
|
+
`);
|
|
455
|
+
if (!verdict.accepted) this.#error = verdict.message;
|
|
456
|
+
return verdict.accepted;
|
|
457
|
+
},
|
|
445
458
|
openTransport: () => new TcpTransport(options.host, options.port)
|
|
446
459
|
});
|
|
447
460
|
this.sftp = new Sftp({ write: (bytes) => this.#session.write(bytes) });
|