@amalgm/shell 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.
- package/PURPOSE.md +73 -0
- package/README.md +33 -0
- package/dist/automations-host.d.ts +19 -0
- package/dist/automations-host.js +41 -0
- package/dist/automations-host.js.map +1 -0
- package/dist/boot.d.ts +53 -0
- package/dist/boot.js +249 -0
- package/dist/boot.js.map +1 -0
- package/dist/bundle-apps.d.ts +12 -0
- package/dist/bundle-apps.js +71 -0
- package/dist/bundle-apps.js.map +1 -0
- package/dist/bundle-automations.d.ts +8 -0
- package/dist/bundle-automations.js +106 -0
- package/dist/bundle-automations.js.map +1 -0
- package/dist/bundle-bindings.d.ts +8 -0
- package/dist/bundle-bindings.js +101 -0
- package/dist/bundle-bindings.js.map +1 -0
- package/dist/bundle-port.d.ts +14 -0
- package/dist/bundle-port.js +166 -0
- package/dist/bundle-port.js.map +1 -0
- package/dist/chat-host.d.ts +32 -0
- package/dist/chat-host.js +167 -0
- package/dist/chat-host.js.map +1 -0
- package/dist/chat-payloads-host.d.ts +8 -0
- package/dist/chat-payloads-host.js +76 -0
- package/dist/chat-payloads-host.js.map +1 -0
- package/dist/chat-relay-host.d.ts +24 -0
- package/dist/chat-relay-host.js +90 -0
- package/dist/chat-relay-host.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +157 -0
- package/dist/cli.js.map +1 -0
- package/dist/compose.d.ts +32 -0
- package/dist/compose.js +35 -0
- package/dist/compose.js.map +1 -0
- package/dist/credentials-host.d.ts +7 -0
- package/dist/credentials-host.js +143 -0
- package/dist/credentials-host.js.map +1 -0
- package/dist/diagnostics-host.d.ts +3 -0
- package/dist/diagnostics-host.js +92 -0
- package/dist/diagnostics-host.js.map +1 -0
- package/dist/drivers/claude-code.d.ts +27 -0
- package/dist/drivers/claude-code.js +72 -0
- package/dist/drivers/claude-code.js.map +1 -0
- package/dist/event-triggers-host.d.ts +4 -0
- package/dist/event-triggers-host.js +48 -0
- package/dist/event-triggers-host.js.map +1 -0
- package/dist/events-host.d.ts +9 -0
- package/dist/events-host.js +34 -0
- package/dist/events-host.js.map +1 -0
- package/dist/external-proxy-host.d.ts +15 -0
- package/dist/external-proxy-host.js +166 -0
- package/dist/external-proxy-host.js.map +1 -0
- package/dist/filesystem.d.ts +7 -0
- package/dist/filesystem.js +71 -0
- package/dist/filesystem.js.map +1 -0
- package/dist/forward.d.ts +11 -0
- package/dist/forward.js +36 -0
- package/dist/forward.js.map +1 -0
- package/dist/gateway.d.ts +33 -0
- package/dist/gateway.js +85 -0
- package/dist/gateway.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/local-host.d.ts +8 -0
- package/dist/local-host.js +101 -0
- package/dist/local-host.js.map +1 -0
- package/dist/machine-host.d.ts +56 -0
- package/dist/machine-host.js +340 -0
- package/dist/machine-host.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +4 -0
- package/dist/main.js.map +1 -0
- package/dist/parity.d.ts +40 -0
- package/dist/parity.js +108 -0
- package/dist/parity.js.map +1 -0
- package/dist/ports-host.d.ts +8 -0
- package/dist/ports-host.js +26 -0
- package/dist/ports-host.js.map +1 -0
- package/dist/pty-host.d.ts +14 -0
- package/dist/pty-host.js +141 -0
- package/dist/pty-host.js.map +1 -0
- package/dist/release-catalog.d.ts +5 -0
- package/dist/release-catalog.js +23 -0
- package/dist/release-catalog.js.map +1 -0
- package/dist/state-host.d.ts +4 -0
- package/dist/state-host.js +67 -0
- package/dist/state-host.js.map +1 -0
- package/dist/state-store.d.ts +15 -0
- package/dist/state-store.js +63 -0
- package/dist/state-store.js.map +1 -0
- package/dist/user-ground-host.d.ts +58 -0
- package/dist/user-ground-host.js +809 -0
- package/dist/user-ground-host.js.map +1 -0
- package/dist/wire-client.d.ts +44 -0
- package/dist/wire-client.js +235 -0
- package/dist/wire-client.js.map +1 -0
- package/dist/workspace-host.d.ts +5 -0
- package/dist/workspace-host.js +73 -0
- package/dist/workspace-host.js.map +1 -0
- package/dist/workspace-store.d.ts +10 -0
- package/dist/workspace-store.js +47 -0
- package/dist/workspace-store.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BrickMount } from "./gateway.js";
|
|
2
|
+
/**
|
|
3
|
+
* Host effects for the chat brick's machine-payload API. The engine stores
|
|
4
|
+
* this map in SQLite `local_meta`; the shell preserves the same durable map
|
|
5
|
+
* contract in its existing system state directory. Record, GC, and HTTP laws
|
|
6
|
+
* remain in @amalgm/chat.
|
|
7
|
+
*/
|
|
8
|
+
export declare function chatPayloadsMount(stateDir: string): BrickMount;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { createChatPayloadApi } from "@amalgm/chat/api";
|
|
4
|
+
import { ChatPayloadStore } from "@amalgm/chat/warm";
|
|
5
|
+
const FILE_NAME = "chat-payloads.json";
|
|
6
|
+
/**
|
|
7
|
+
* Host effects for the chat brick's machine-payload API. The engine stores
|
|
8
|
+
* this map in SQLite `local_meta`; the shell preserves the same durable map
|
|
9
|
+
* contract in its existing system state directory. Record, GC, and HTTP laws
|
|
10
|
+
* remain in @amalgm/chat.
|
|
11
|
+
*/
|
|
12
|
+
export function chatPayloadsMount(stateDir) {
|
|
13
|
+
const api = createChatPayloadApi(new ChatPayloadStore({
|
|
14
|
+
store: fileStore(stateDir),
|
|
15
|
+
clockIso: () => new Date().toISOString(),
|
|
16
|
+
clockMs: () => Date.now(),
|
|
17
|
+
}));
|
|
18
|
+
return {
|
|
19
|
+
prefix: "/chat-payloads",
|
|
20
|
+
stream: async (req, res, pathname) => {
|
|
21
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
22
|
+
const request = new Request(`http://chat.local${pathname}${url.search}`, {
|
|
23
|
+
method: req.method ?? "GET",
|
|
24
|
+
headers: requestHeaders(req),
|
|
25
|
+
body: await requestBody(req),
|
|
26
|
+
});
|
|
27
|
+
await writeResponse(res, await api(request));
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function fileStore(stateDir) {
|
|
32
|
+
const path = join(stateDir, FILE_NAME);
|
|
33
|
+
return {
|
|
34
|
+
read() {
|
|
35
|
+
try {
|
|
36
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
37
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
38
|
+
? parsed
|
|
39
|
+
: {};
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return {};
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
write(payloads) {
|
|
46
|
+
mkdirSync(stateDir, { recursive: true });
|
|
47
|
+
const temporary = `${path}.${process.pid}.tmp`;
|
|
48
|
+
writeFileSync(temporary, JSON.stringify(payloads), "utf8");
|
|
49
|
+
renameSync(temporary, path);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function requestHeaders(req) {
|
|
54
|
+
const headers = new Headers();
|
|
55
|
+
for (const [name, value] of Object.entries(req.headers)) {
|
|
56
|
+
if (typeof value === "string")
|
|
57
|
+
headers.set(name, value);
|
|
58
|
+
else if (value)
|
|
59
|
+
for (const item of value)
|
|
60
|
+
headers.append(name, item);
|
|
61
|
+
}
|
|
62
|
+
return headers;
|
|
63
|
+
}
|
|
64
|
+
async function requestBody(req) {
|
|
65
|
+
if (req.method === "GET" || req.method === "HEAD")
|
|
66
|
+
return undefined;
|
|
67
|
+
const chunks = [];
|
|
68
|
+
for await (const chunk of req)
|
|
69
|
+
chunks.push(chunk);
|
|
70
|
+
return chunks.length ? Buffer.concat(chunks).toString("utf8") : undefined;
|
|
71
|
+
}
|
|
72
|
+
async function writeResponse(res, response) {
|
|
73
|
+
res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
|
|
74
|
+
res.end(Buffer.from(await response.arrayBuffer()));
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=chat-payloads-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-payloads-host.js","sourceRoot":"","sources":["../src/chat-payloads-host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ChatRelayContract, ChatRelayTurn, RelayFetchPort } from "@amalgm/chat/relay";
|
|
2
|
+
import type { BrickMount } from "./gateway.js";
|
|
3
|
+
export interface ChatRelayHostConfig {
|
|
4
|
+
readonly proxyCredentials: () => Promise<{
|
|
5
|
+
readonly baseUrl: string;
|
|
6
|
+
readonly token: string;
|
|
7
|
+
}>;
|
|
8
|
+
readonly contractForInput?: (input: Record<string, unknown>) => ChatRelayContract | null;
|
|
9
|
+
readonly turnForSession: (sessionId: string) => ChatRelayTurn | null;
|
|
10
|
+
readonly defaultMcpServer?: (contract: ChatRelayContract) => unknown;
|
|
11
|
+
readonly fetch?: RelayFetchPort;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Node sockets and the frozen-contract registry for Chat's portable relay API.
|
|
15
|
+
* Destination, authentication, and header laws remain in @amalgm/chat.
|
|
16
|
+
*/
|
|
17
|
+
export declare class ChatRelayHost {
|
|
18
|
+
#private;
|
|
19
|
+
constructor(config: ChatRelayHostConfig);
|
|
20
|
+
/** First registration owns relay authority for the lifetime of a session. */
|
|
21
|
+
registerInput(input: Record<string, unknown>, sessionId: string): ChatRelayContract | null;
|
|
22
|
+
forget(sessionId: string): void;
|
|
23
|
+
mounts(): BrickMount[];
|
|
24
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { createChatRelayApi } from "@amalgm/chat/relay";
|
|
2
|
+
/**
|
|
3
|
+
* Node sockets and the frozen-contract registry for Chat's portable relay API.
|
|
4
|
+
* Destination, authentication, and header laws remain in @amalgm/chat.
|
|
5
|
+
*/
|
|
6
|
+
export class ChatRelayHost {
|
|
7
|
+
#contracts = new Map();
|
|
8
|
+
#contractForInput;
|
|
9
|
+
#api;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.#contractForInput = config.contractForInput;
|
|
12
|
+
this.#api = createChatRelayApi({
|
|
13
|
+
contractForSession: (sessionId) => this.#contracts.get(sessionId) ?? null,
|
|
14
|
+
turnForSession: config.turnForSession,
|
|
15
|
+
proxyCredentials: config.proxyCredentials,
|
|
16
|
+
defaultMcpServer: config.defaultMcpServer,
|
|
17
|
+
fetch: config.fetch ?? globalThis.fetch,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/** First registration owns relay authority for the lifetime of a session. */
|
|
21
|
+
registerInput(input, sessionId) {
|
|
22
|
+
const next = this.#contractForInput?.(input) ?? null;
|
|
23
|
+
if (!next?.sessionId)
|
|
24
|
+
return null;
|
|
25
|
+
if (next.sessionId !== sessionId)
|
|
26
|
+
return next;
|
|
27
|
+
const existing = this.#contracts.get(next.sessionId);
|
|
28
|
+
if (existing)
|
|
29
|
+
return existing;
|
|
30
|
+
this.#contracts.set(next.sessionId, next);
|
|
31
|
+
return next;
|
|
32
|
+
}
|
|
33
|
+
forget(sessionId) {
|
|
34
|
+
this.#contracts.delete(sessionId);
|
|
35
|
+
}
|
|
36
|
+
mounts() {
|
|
37
|
+
return ["/egress", "/mcp-relay"].map((prefix) => ({
|
|
38
|
+
prefix,
|
|
39
|
+
stream: async (req, res, pathname) => this.#serve(req, res, pathname),
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
async #serve(req, res, pathname) {
|
|
43
|
+
try {
|
|
44
|
+
const response = await this.#api(await fetchRequest(req, pathname));
|
|
45
|
+
res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
|
|
46
|
+
if (!response.body) {
|
|
47
|
+
res.end();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const reader = response.body.getReader();
|
|
51
|
+
while (!res.destroyed) {
|
|
52
|
+
const chunk = await reader.read();
|
|
53
|
+
if (chunk.done)
|
|
54
|
+
break;
|
|
55
|
+
res.write(Buffer.from(chunk.value));
|
|
56
|
+
}
|
|
57
|
+
if (!res.writableEnded)
|
|
58
|
+
res.end();
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (res.headersSent || res.destroyed)
|
|
62
|
+
return;
|
|
63
|
+
res.writeHead(500, { "content-type": "application/json" });
|
|
64
|
+
res.end(JSON.stringify({ error: error instanceof Error ? error.message : "internal error" }));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function fetchRequest(req, pathname) {
|
|
69
|
+
const url = new URL(req.url ?? pathname, "http://chat.local");
|
|
70
|
+
const headers = new Headers();
|
|
71
|
+
for (const [name, value] of Object.entries(req.headers)) {
|
|
72
|
+
if (Array.isArray(value))
|
|
73
|
+
for (const item of value)
|
|
74
|
+
headers.append(name, item);
|
|
75
|
+
else if (value !== undefined)
|
|
76
|
+
headers.set(name, value);
|
|
77
|
+
}
|
|
78
|
+
const method = req.method ?? "GET";
|
|
79
|
+
const chunks = [];
|
|
80
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
81
|
+
for await (const chunk of req)
|
|
82
|
+
chunks.push(chunk);
|
|
83
|
+
}
|
|
84
|
+
return new Request(`http://chat.local${pathname}${url.search}`, {
|
|
85
|
+
method,
|
|
86
|
+
headers,
|
|
87
|
+
body: chunks.length ? Buffer.concat(chunks) : undefined,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=chat-relay-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-relay-host.js","sourceRoot":"","sources":["../src/chat-relay-host.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runCli(argv?: string[]): Promise<number>;
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { MachineSetupError } from "@amalgm/core/identity";
|
|
3
|
+
import { MachineHost, defaultMachineName } from "./machine-host.js";
|
|
4
|
+
const VERSION = "0.1.0";
|
|
5
|
+
export async function runCli(argv = process.argv) {
|
|
6
|
+
const parsed = parseArguments(argv.slice(2));
|
|
7
|
+
if (parsed.command === "help" || parsed.options.help) {
|
|
8
|
+
process.stdout.write(helpText());
|
|
9
|
+
return 0;
|
|
10
|
+
}
|
|
11
|
+
if (parsed.command === "version" || parsed.options.version) {
|
|
12
|
+
process.stdout.write(`${VERSION}\n`);
|
|
13
|
+
return 0;
|
|
14
|
+
}
|
|
15
|
+
if (!["login", "run", "status"].includes(parsed.command)) {
|
|
16
|
+
process.stderr.write(`Unknown command: ${parsed.command}\n\n${helpText()}`);
|
|
17
|
+
return 2;
|
|
18
|
+
}
|
|
19
|
+
const appUrl = option(parsed, "app-url") || process.env.AMALGM_APP_URL || "https://amalgm.ai";
|
|
20
|
+
const userEmail = option(parsed, "user") || undefined;
|
|
21
|
+
const host = new MachineHost({
|
|
22
|
+
homedir: option(parsed, "home") || undefined,
|
|
23
|
+
amalgmRoot: option(parsed, "amalgm-root") || undefined,
|
|
24
|
+
userEmail,
|
|
25
|
+
appUrl,
|
|
26
|
+
runtimeVersion: VERSION,
|
|
27
|
+
runtimeLabel: option(parsed, "runtime-label") || "main",
|
|
28
|
+
branch: option(parsed, "branch") || "main",
|
|
29
|
+
proxyUrl: option(parsed, "proxy-url") || undefined,
|
|
30
|
+
runtimePort: numericOption(parsed, "port"),
|
|
31
|
+
showSetup: async ({ verificationUrl, setupCode }) => {
|
|
32
|
+
process.stdout.write([
|
|
33
|
+
"",
|
|
34
|
+
"Open this URL in a browser to finish login:",
|
|
35
|
+
verificationUrl,
|
|
36
|
+
"",
|
|
37
|
+
`Setup code: ${setupCode}`,
|
|
38
|
+
"",
|
|
39
|
+
].join("\n"));
|
|
40
|
+
if (!parsed.options["no-open"])
|
|
41
|
+
openBrowser(verificationUrl);
|
|
42
|
+
},
|
|
43
|
+
diagnostic: (event) => {
|
|
44
|
+
process.stdout.write(`AMALGM_SETUP ${JSON.stringify(event)}\n`);
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
try {
|
|
48
|
+
if (parsed.command === "status") {
|
|
49
|
+
const paths = host.selectedPaths();
|
|
50
|
+
process.stdout.write(`${JSON.stringify({
|
|
51
|
+
user: userEmail,
|
|
52
|
+
deviceFile: host.deviceFile,
|
|
53
|
+
userRoot: paths.userRoot,
|
|
54
|
+
machineDir: paths.machineDir,
|
|
55
|
+
database: `${paths.machineDir}/live/identity.db`,
|
|
56
|
+
}, null, 2)}\n`);
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
const ready = parsed.command === "login"
|
|
60
|
+
? await host.join({
|
|
61
|
+
name: option(parsed, "name") || defaultMachineName(),
|
|
62
|
+
...(option(parsed, "setup-code") ? { setupCode: option(parsed, "setup-code") } : {}),
|
|
63
|
+
})
|
|
64
|
+
: await host.resume();
|
|
65
|
+
process.stdout.write(`AMALGM_READY ${JSON.stringify({
|
|
66
|
+
userId: ready.userId,
|
|
67
|
+
computerId: ready.computerId,
|
|
68
|
+
deviceId: ready.deviceId,
|
|
69
|
+
userRoot: ready.userGround.localRoot,
|
|
70
|
+
cloudHead: ready.userGround.cloudHead,
|
|
71
|
+
cloudMode: ready.userGround.mode,
|
|
72
|
+
entities: ready.userGround.entityCount,
|
|
73
|
+
watchers: ready.userGround.watcherRoots,
|
|
74
|
+
services: ready.installation.services,
|
|
75
|
+
})}\n`);
|
|
76
|
+
if (parsed.options["exit-after-ready"]) {
|
|
77
|
+
await ready.runtime.stop();
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
await waitForShutdown();
|
|
81
|
+
return 0;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (error instanceof MachineSetupError) {
|
|
85
|
+
process.stderr.write(`Machine setup failed at ${error.stage}: ${error.code}\n`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
89
|
+
}
|
|
90
|
+
return 1;
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
await host.close();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function parseArguments(args) {
|
|
97
|
+
const remaining = [...args];
|
|
98
|
+
const command = remaining.shift() || "help";
|
|
99
|
+
const options = {};
|
|
100
|
+
const positionals = [];
|
|
101
|
+
for (let index = 0; index < remaining.length; index += 1) {
|
|
102
|
+
const argument = remaining[index];
|
|
103
|
+
if (!argument.startsWith("--")) {
|
|
104
|
+
positionals.push(argument);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const separator = argument.indexOf("=");
|
|
108
|
+
if (separator !== -1) {
|
|
109
|
+
options[argument.slice(2, separator)] = argument.slice(separator + 1);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const key = argument.slice(2);
|
|
113
|
+
const next = remaining[index + 1];
|
|
114
|
+
if (next && !next.startsWith("--")) {
|
|
115
|
+
options[key] = next;
|
|
116
|
+
index += 1;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
options[key] = true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return { command, options, positionals };
|
|
123
|
+
}
|
|
124
|
+
function option(parsed, key) {
|
|
125
|
+
const value = parsed.options[key];
|
|
126
|
+
return typeof value === "string" ? value : "";
|
|
127
|
+
}
|
|
128
|
+
function numericOption(parsed, key) {
|
|
129
|
+
const value = Number(option(parsed, key));
|
|
130
|
+
return Number.isInteger(value) && value > 0 && value <= 65_535 ? value : undefined;
|
|
131
|
+
}
|
|
132
|
+
function openBrowser(url) {
|
|
133
|
+
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
134
|
+
const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
135
|
+
try {
|
|
136
|
+
const child = spawn(command, args, { detached: true, stdio: "ignore", windowsHide: true });
|
|
137
|
+
child.unref();
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// The URL and setup code are always printed; browser launch is optional.
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function waitForShutdown() {
|
|
144
|
+
return new Promise((resolve) => {
|
|
145
|
+
const finish = () => {
|
|
146
|
+
process.off("SIGINT", finish);
|
|
147
|
+
process.off("SIGTERM", finish);
|
|
148
|
+
resolve();
|
|
149
|
+
};
|
|
150
|
+
process.once("SIGINT", finish);
|
|
151
|
+
process.once("SIGTERM", finish);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function helpText() {
|
|
155
|
+
return `amalgm-shell ${VERSION}\n\nUsage:\n amalgm-shell login [--setup-code CODE] [--no-open]\n amalgm-shell run --user EMAIL\n amalgm-shell status --user EMAIL\n\nOptions:\n --app-url URL Amalgm control plane (default: https://amalgm.ai)\n --amalgm-root PATH Visible installation root (default: ~/amalgm)\n --home PATH OS home override\n --user EMAIL Select one of multiple local users\n --name NAME Computer display name\n --exit-after-ready Examination-only: prove readiness, then stop\n`;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { guardBearerRequest } from "@amalgm/core/transport";
|
|
2
|
+
export interface ShellConfig {
|
|
3
|
+
/** Environment to resolve state dirs against. Defaults to process.env. */
|
|
4
|
+
env?: NodeJS.ProcessEnv;
|
|
5
|
+
/** Home directory override for tests. */
|
|
6
|
+
homedir?: string;
|
|
7
|
+
/** Visible Amalgm root override. Defaults to <homedir>/amalgm. */
|
|
8
|
+
amalgmRoot?: string;
|
|
9
|
+
/** Canonical user email; this is the presentation segment, not identity. */
|
|
10
|
+
userEmail?: string;
|
|
11
|
+
/** Compatibility spelling for tests and embedded callers. */
|
|
12
|
+
scope?: string;
|
|
13
|
+
/** Stable physical-device identity used only below the local control dir. */
|
|
14
|
+
deviceId?: string;
|
|
15
|
+
/** Runtime bearer token; when set, every guarded request must present it. */
|
|
16
|
+
runtimeToken?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ComposedShell {
|
|
19
|
+
/** Visible installation root and the selected portable user ground. */
|
|
20
|
+
amalgmRoot: string;
|
|
21
|
+
userDir: string;
|
|
22
|
+
deviceId: string;
|
|
23
|
+
/** Absolute state dir for every primitive the kernel knows about. */
|
|
24
|
+
stateDirs: Record<string, string>;
|
|
25
|
+
/** Fail-closed bearer guard bound to the shell's runtime token. */
|
|
26
|
+
guard: (headers: Record<string, string | string[] | undefined>) => ReturnType<typeof guardBearerRequest>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Assemble the shell: one identity resolution and one auth guard, both owned
|
|
30
|
+
* by kernel law. The shell contributes wiring only — no behavior of its own.
|
|
31
|
+
*/
|
|
32
|
+
export declare function composeShell(config?: ShellConfig): ComposedShell;
|
package/dist/compose.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { homedir as osHomedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { PRIMITIVE_DIRS, resolveProductStateDir, scopedAmalgmDir, } from "@amalgm/core/identity";
|
|
5
|
+
import { guardBearerRequest } from "@amalgm/core/transport";
|
|
6
|
+
/**
|
|
7
|
+
* Assemble the shell: one identity resolution and one auth guard, both owned
|
|
8
|
+
* by kernel law. The shell contributes wiring only — no behavior of its own.
|
|
9
|
+
*/
|
|
10
|
+
export function composeShell(config = {}) {
|
|
11
|
+
const env = config.env ?? process.env;
|
|
12
|
+
const home = config.homedir ?? osHomedir();
|
|
13
|
+
const amalgmRoot = config.amalgmRoot ?? env.AMALGM_ROOT ?? join(home, "amalgm");
|
|
14
|
+
const userScope = config.userEmail ?? config.scope ?? env.AMALGM_USER_EMAIL ?? "local";
|
|
15
|
+
const userDir = scopedAmalgmDir(amalgmRoot, userScope);
|
|
16
|
+
const deviceId = config.deviceId ?? env.AMALGM_DEVICE_ID ?? "local-device";
|
|
17
|
+
const stateDirs = {};
|
|
18
|
+
for (const primitive of PRIMITIVE_DIRS) {
|
|
19
|
+
stateDirs[primitive] = resolveProductStateDir({
|
|
20
|
+
product: primitive,
|
|
21
|
+
primitive,
|
|
22
|
+
env,
|
|
23
|
+
homedir: amalgmRoot,
|
|
24
|
+
scope: userScope,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const guard = (headers) => guardBearerRequest({
|
|
28
|
+
// Kernel law is fail-closed: an unconfigured token ("") matches nothing.
|
|
29
|
+
headers,
|
|
30
|
+
expectedToken: config.runtimeToken ?? "",
|
|
31
|
+
timingSafeEqual,
|
|
32
|
+
});
|
|
33
|
+
return { amalgmRoot, userDir, deviceId, stateDirs, guard };
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=compose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AA8B5D;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,SAAsB,EAAE;IACnD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACtC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,IAAI,SAAS,EAAE,CAAC;IAC3C,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAChF,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC;IACvF,MAAM,OAAO,GAAG,eAAe,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,GAAG,CAAC,gBAAgB,IAAI,cAAc,CAAC;IAE3E,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,KAAK,MAAM,SAAS,IAAI,cAAc,EAAE,CAAC;QACvC,SAAS,CAAC,SAAS,CAAC,GAAG,sBAAsB,CAAC;YAC5C,OAAO,EAAE,SAAS;YAClB,SAAS;YACT,GAAG;YACH,OAAO,EAAE,UAAU;YACnB,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,KAAK,GAA2B,CAAC,OAAO,EAAE,EAAE,CAChD,kBAAkB,CAAC;QACjB,yEAAyE;QACzE,OAAO;QACP,aAAa,EAAE,MAAM,CAAC,YAAY,IAAI,EAAE;QACxC,eAAe;KAChB,CAAC,CAAC;IAEL,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BrickMount } from "./gateway.js";
|
|
2
|
+
/**
|
|
3
|
+
* Host effects for Core's one local credential vault. The cipher and file
|
|
4
|
+
* bytes remain compatible with Engine's
|
|
5
|
+
* runtime/scripts/chat-core/credentials/store.js.
|
|
6
|
+
*/
|
|
7
|
+
export declare function credentialsMounts(file: string): readonly BrickMount[];
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { createCipheriv, createDecipheriv, createHash, randomBytes, randomUUID, scryptSync, } from "node:crypto";
|
|
2
|
+
import { chmodSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { homedir, hostname, userInfo } from "node:os";
|
|
4
|
+
import { dirname } from "node:path";
|
|
5
|
+
import { createCredentialsApi, CredentialVault } from "@amalgm/core/credentials";
|
|
6
|
+
const CIPHER = "aes-256-gcm";
|
|
7
|
+
/**
|
|
8
|
+
* Host effects for Core's one local credential vault. The cipher and file
|
|
9
|
+
* bytes remain compatible with Engine's
|
|
10
|
+
* runtime/scripts/chat-core/credentials/store.js.
|
|
11
|
+
*/
|
|
12
|
+
export function credentialsMounts(file) {
|
|
13
|
+
const vault = new CredentialVault({
|
|
14
|
+
store: fileStore(file),
|
|
15
|
+
cipher: machineCipher(),
|
|
16
|
+
now: () => new Date().toISOString(),
|
|
17
|
+
randomId: () => `cred_${randomUUID().replace(/-/g, "").slice(0, 18)}`,
|
|
18
|
+
});
|
|
19
|
+
const api = createCredentialsApi(vault);
|
|
20
|
+
const stream = async (req, res, pathname) => {
|
|
21
|
+
try {
|
|
22
|
+
const response = await api(await fetchRequest(req, pathname));
|
|
23
|
+
res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
|
|
24
|
+
res.end(Buffer.from(await response.arrayBuffer()));
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
res.writeHead(500, { "content-type": "application/json" });
|
|
28
|
+
res.end(JSON.stringify({ error: error instanceof Error ? error.message : "internal error" }));
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return [
|
|
32
|
+
{ prefix: "/credentials", stream },
|
|
33
|
+
{ prefix: "/user-api-keys", stream },
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
function fileStore(file) {
|
|
37
|
+
return {
|
|
38
|
+
read() {
|
|
39
|
+
try {
|
|
40
|
+
return JSON.parse(readFileSync(file, "utf8"));
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
write(document) {
|
|
47
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
48
|
+
const temporary = `${file}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
|
|
49
|
+
try {
|
|
50
|
+
writeFileSync(temporary, `${JSON.stringify(document, null, 2)}\n`, {
|
|
51
|
+
encoding: "utf8",
|
|
52
|
+
flag: "wx",
|
|
53
|
+
mode: 0o600,
|
|
54
|
+
});
|
|
55
|
+
chmodSync(temporary, 0o600);
|
|
56
|
+
renameSync(temporary, file);
|
|
57
|
+
chmodSync(file, 0o600);
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
rmSync(temporary, { force: true });
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function machineCipher() {
|
|
66
|
+
const deriveKey = (salt) => scryptSync(machineSecret(), salt, 32);
|
|
67
|
+
return {
|
|
68
|
+
encrypt(secret) {
|
|
69
|
+
const salt = randomBytes(16);
|
|
70
|
+
const iv = randomBytes(12);
|
|
71
|
+
const cipher = createCipheriv(CIPHER, deriveKey(salt), iv);
|
|
72
|
+
const data = Buffer.concat([cipher.update(secret, "utf8"), cipher.final()]);
|
|
73
|
+
return {
|
|
74
|
+
alg: CIPHER,
|
|
75
|
+
salt: salt.toString("base64url"),
|
|
76
|
+
iv: iv.toString("base64url"),
|
|
77
|
+
tag: cipher.getAuthTag().toString("base64url"),
|
|
78
|
+
data: data.toString("base64url"),
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
decrypt(value) {
|
|
82
|
+
const encrypted = credentialEnvelope(value);
|
|
83
|
+
const decipher = createDecipheriv(CIPHER, deriveKey(Buffer.from(encrypted.salt, "base64url")), Buffer.from(encrypted.iv, "base64url"));
|
|
84
|
+
decipher.setAuthTag(Buffer.from(encrypted.tag, "base64url"));
|
|
85
|
+
return Buffer.concat([
|
|
86
|
+
decipher.update(Buffer.from(encrypted.data, "base64url")),
|
|
87
|
+
decipher.final(),
|
|
88
|
+
]).toString("utf8");
|
|
89
|
+
},
|
|
90
|
+
fingerprint(secret) {
|
|
91
|
+
return createHash("sha256").update(secret).digest("hex").slice(0, 16);
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function machineSecret() {
|
|
96
|
+
return [hostname(), userInfo().username, homedir(), process.platform].filter(Boolean).join(":");
|
|
97
|
+
}
|
|
98
|
+
function credentialEnvelope(value) {
|
|
99
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
100
|
+
throw new Error("Unsupported credential encryption format");
|
|
101
|
+
}
|
|
102
|
+
const candidate = value;
|
|
103
|
+
if (candidate.alg !== CIPHER
|
|
104
|
+
|| typeof candidate.salt !== "string"
|
|
105
|
+
|| typeof candidate.iv !== "string"
|
|
106
|
+
|| typeof candidate.tag !== "string"
|
|
107
|
+
|| typeof candidate.data !== "string") {
|
|
108
|
+
throw new Error("Unsupported credential encryption format");
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
alg: CIPHER,
|
|
112
|
+
salt: candidate.salt,
|
|
113
|
+
iv: candidate.iv,
|
|
114
|
+
tag: candidate.tag,
|
|
115
|
+
data: candidate.data,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
async function fetchRequest(req, pathname) {
|
|
119
|
+
const source = new URL(req.url ?? pathname, "http://credentials.local");
|
|
120
|
+
const method = req.method ?? "GET";
|
|
121
|
+
const chunks = [];
|
|
122
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
123
|
+
for await (const chunk of req)
|
|
124
|
+
chunks.push(chunk);
|
|
125
|
+
}
|
|
126
|
+
return new Request(`http://credentials.local${pathname}${source.search}`, {
|
|
127
|
+
method,
|
|
128
|
+
headers: requestHeaders(req),
|
|
129
|
+
body: chunks.length ? Buffer.concat(chunks) : undefined,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
function requestHeaders(req) {
|
|
133
|
+
const headers = new Headers();
|
|
134
|
+
for (const [name, value] of Object.entries(req.headers)) {
|
|
135
|
+
if (typeof value === "string")
|
|
136
|
+
headers.set(name, value);
|
|
137
|
+
else if (value)
|
|
138
|
+
for (const item of value)
|
|
139
|
+
headers.append(name, item);
|
|
140
|
+
}
|
|
141
|
+
return headers;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=credentials-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials-host.js","sourceRoot":"","sources":["../src/credentials-host.ts"],"names":[],"mappings":"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"}
|