@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.
Files changed (105) hide show
  1. package/PURPOSE.md +73 -0
  2. package/README.md +33 -0
  3. package/dist/automations-host.d.ts +19 -0
  4. package/dist/automations-host.js +41 -0
  5. package/dist/automations-host.js.map +1 -0
  6. package/dist/boot.d.ts +53 -0
  7. package/dist/boot.js +249 -0
  8. package/dist/boot.js.map +1 -0
  9. package/dist/bundle-apps.d.ts +12 -0
  10. package/dist/bundle-apps.js +71 -0
  11. package/dist/bundle-apps.js.map +1 -0
  12. package/dist/bundle-automations.d.ts +8 -0
  13. package/dist/bundle-automations.js +106 -0
  14. package/dist/bundle-automations.js.map +1 -0
  15. package/dist/bundle-bindings.d.ts +8 -0
  16. package/dist/bundle-bindings.js +101 -0
  17. package/dist/bundle-bindings.js.map +1 -0
  18. package/dist/bundle-port.d.ts +14 -0
  19. package/dist/bundle-port.js +166 -0
  20. package/dist/bundle-port.js.map +1 -0
  21. package/dist/chat-host.d.ts +32 -0
  22. package/dist/chat-host.js +167 -0
  23. package/dist/chat-host.js.map +1 -0
  24. package/dist/chat-payloads-host.d.ts +8 -0
  25. package/dist/chat-payloads-host.js +76 -0
  26. package/dist/chat-payloads-host.js.map +1 -0
  27. package/dist/chat-relay-host.d.ts +24 -0
  28. package/dist/chat-relay-host.js +90 -0
  29. package/dist/chat-relay-host.js.map +1 -0
  30. package/dist/cli.d.ts +1 -0
  31. package/dist/cli.js +157 -0
  32. package/dist/cli.js.map +1 -0
  33. package/dist/compose.d.ts +32 -0
  34. package/dist/compose.js +35 -0
  35. package/dist/compose.js.map +1 -0
  36. package/dist/credentials-host.d.ts +7 -0
  37. package/dist/credentials-host.js +143 -0
  38. package/dist/credentials-host.js.map +1 -0
  39. package/dist/diagnostics-host.d.ts +3 -0
  40. package/dist/diagnostics-host.js +92 -0
  41. package/dist/diagnostics-host.js.map +1 -0
  42. package/dist/drivers/claude-code.d.ts +27 -0
  43. package/dist/drivers/claude-code.js +72 -0
  44. package/dist/drivers/claude-code.js.map +1 -0
  45. package/dist/event-triggers-host.d.ts +4 -0
  46. package/dist/event-triggers-host.js +48 -0
  47. package/dist/event-triggers-host.js.map +1 -0
  48. package/dist/events-host.d.ts +9 -0
  49. package/dist/events-host.js +34 -0
  50. package/dist/events-host.js.map +1 -0
  51. package/dist/external-proxy-host.d.ts +15 -0
  52. package/dist/external-proxy-host.js +166 -0
  53. package/dist/external-proxy-host.js.map +1 -0
  54. package/dist/filesystem.d.ts +7 -0
  55. package/dist/filesystem.js +71 -0
  56. package/dist/filesystem.js.map +1 -0
  57. package/dist/forward.d.ts +11 -0
  58. package/dist/forward.js +36 -0
  59. package/dist/forward.js.map +1 -0
  60. package/dist/gateway.d.ts +33 -0
  61. package/dist/gateway.js +85 -0
  62. package/dist/gateway.js.map +1 -0
  63. package/dist/index.d.ts +23 -0
  64. package/dist/index.js +14 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/local-host.d.ts +8 -0
  67. package/dist/local-host.js +101 -0
  68. package/dist/local-host.js.map +1 -0
  69. package/dist/machine-host.d.ts +56 -0
  70. package/dist/machine-host.js +340 -0
  71. package/dist/machine-host.js.map +1 -0
  72. package/dist/main.d.ts +2 -0
  73. package/dist/main.js +4 -0
  74. package/dist/main.js.map +1 -0
  75. package/dist/parity.d.ts +40 -0
  76. package/dist/parity.js +108 -0
  77. package/dist/parity.js.map +1 -0
  78. package/dist/ports-host.d.ts +8 -0
  79. package/dist/ports-host.js +26 -0
  80. package/dist/ports-host.js.map +1 -0
  81. package/dist/pty-host.d.ts +14 -0
  82. package/dist/pty-host.js +141 -0
  83. package/dist/pty-host.js.map +1 -0
  84. package/dist/release-catalog.d.ts +5 -0
  85. package/dist/release-catalog.js +23 -0
  86. package/dist/release-catalog.js.map +1 -0
  87. package/dist/state-host.d.ts +4 -0
  88. package/dist/state-host.js +67 -0
  89. package/dist/state-host.js.map +1 -0
  90. package/dist/state-store.d.ts +15 -0
  91. package/dist/state-store.js +63 -0
  92. package/dist/state-store.js.map +1 -0
  93. package/dist/user-ground-host.d.ts +58 -0
  94. package/dist/user-ground-host.js +809 -0
  95. package/dist/user-ground-host.js.map +1 -0
  96. package/dist/wire-client.d.ts +44 -0
  97. package/dist/wire-client.js +235 -0
  98. package/dist/wire-client.js.map +1 -0
  99. package/dist/workspace-host.d.ts +5 -0
  100. package/dist/workspace-host.js +73 -0
  101. package/dist/workspace-host.js.map +1 -0
  102. package/dist/workspace-store.d.ts +10 -0
  103. package/dist/workspace-store.js +47 -0
  104. package/dist/workspace-store.js.map +1 -0
  105. package/package.json +55 -0
@@ -0,0 +1,92 @@
1
+ import { open, stat } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { createDiagnosticsApi } from "@amalgm/core/diagnostics";
4
+ /** Filesystem effects for Core's bounded diagnostics law. */
5
+ export function diagnosticsMount(logDir) {
6
+ const api = createDiagnosticsApi(diagnosticLogHost(logDir));
7
+ return {
8
+ prefix: "/diagnostics",
9
+ stream: async (req, res, pathname) => {
10
+ try {
11
+ const response = await api(await fetchRequest(req, pathname));
12
+ res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
13
+ res.end(Buffer.from(await response.arrayBuffer()));
14
+ }
15
+ catch (error) {
16
+ res.writeHead(500, { "content-type": "application/json" });
17
+ res.end(JSON.stringify({ error: error instanceof Error ? error.message : "internal error" }));
18
+ }
19
+ },
20
+ };
21
+ }
22
+ function diagnosticLogHost(logDir) {
23
+ return {
24
+ async readTail(filename, maxBytes) {
25
+ const path = join(logDir, filename);
26
+ try {
27
+ const stats = await stat(path);
28
+ if (!stats.isFile())
29
+ return { kind: "not_file", path };
30
+ const bytes = Math.min(stats.size, maxBytes);
31
+ if (bytes === 0) {
32
+ return {
33
+ kind: "found",
34
+ tail: {
35
+ path,
36
+ size: stats.size,
37
+ mtime: stats.mtime.toISOString(),
38
+ bytes: 0,
39
+ content: "",
40
+ byteTruncated: false,
41
+ },
42
+ };
43
+ }
44
+ const file = await open(path, "r");
45
+ try {
46
+ const buffer = Buffer.alloc(bytes);
47
+ await file.read(buffer, 0, bytes, stats.size - bytes);
48
+ return {
49
+ kind: "found",
50
+ tail: {
51
+ path,
52
+ size: stats.size,
53
+ mtime: stats.mtime.toISOString(),
54
+ bytes,
55
+ content: buffer.toString("utf8"),
56
+ byteTruncated: stats.size > bytes,
57
+ },
58
+ };
59
+ }
60
+ finally {
61
+ await file.close();
62
+ }
63
+ }
64
+ catch (error) {
65
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
66
+ return { kind: "not_found", path };
67
+ }
68
+ return {
69
+ kind: "error",
70
+ path,
71
+ message: error instanceof Error ? error.message : "Failed to read diagnostic log",
72
+ };
73
+ }
74
+ },
75
+ };
76
+ }
77
+ async function fetchRequest(req, pathname) {
78
+ const url = new URL(req.url ?? pathname, "http://diagnostics.local");
79
+ const headers = new Headers();
80
+ for (const [name, value] of Object.entries(req.headers)) {
81
+ if (Array.isArray(value))
82
+ for (const item of value)
83
+ headers.append(name, item);
84
+ else if (value !== undefined)
85
+ headers.set(name, value);
86
+ }
87
+ return new Request(`http://diagnostics.local${pathname}${url.search}`, {
88
+ method: req.method ?? "GET",
89
+ headers,
90
+ });
91
+ }
92
+ //# sourceMappingURL=diagnostics-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics-host.js","sourceRoot":"","sources":["../src/diagnostics-host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { ChatDriver } from "../chat-host.js";
2
+ /** The SDK surface the driver consumes: a prompt in, a message stream out. */
3
+ export type ClaudeQuery = (input: {
4
+ prompt: string;
5
+ options?: Record<string, unknown>;
6
+ }) => AsyncIterable<Record<string, unknown>>;
7
+ export interface ClaudeCodeDriverOptions {
8
+ /**
9
+ * The turn-running query function. Defaults to the real
10
+ * @anthropic-ai/claude-agent-sdk `query` — the same SDK the engine's
11
+ * claude adapter calls. Inject a fake to test the wiring without a model.
12
+ */
13
+ query?: ClaudeQuery;
14
+ /** Extra SDK options merged over the defaults (model, cwd, mcpServers…). */
15
+ queryOptions?: Record<string, unknown>;
16
+ cwd?: string;
17
+ clockMs?: () => number;
18
+ }
19
+ /**
20
+ * The real chat driver: the engine's claude adapter loop
21
+ * (chat-core/adapters/claude.js:99-161) composed from brick law. Every SDK
22
+ * message goes through the chat brick's Claude normalizer; the result
23
+ * message becomes usageFinal records, an error event when the turn failed,
24
+ * and done — the same order the engine yields them. Provider sessions are
25
+ * remembered per amalgm session so follow-up turns resume.
26
+ */
27
+ export declare function createClaudeCodeDriver(options?: ClaudeCodeDriverOptions): ChatDriver;
@@ -0,0 +1,72 @@
1
+ import { createEventConstructors } from "@amalgm/chat/events";
2
+ import { createClaudeNormalizer } from "@amalgm/chat/normalizers";
3
+ /**
4
+ * The real chat driver: the engine's claude adapter loop
5
+ * (chat-core/adapters/claude.js:99-161) composed from brick law. Every SDK
6
+ * message goes through the chat brick's Claude normalizer; the result
7
+ * message becomes usageFinal records, an error event when the turn failed,
8
+ * and done — the same order the engine yields them. Provider sessions are
9
+ * remembered per amalgm session so follow-up turns resume.
10
+ */
11
+ export function createClaudeCodeDriver(options = {}) {
12
+ const events = createEventConstructors({ clockMs: options.clockMs ?? (() => Date.now()) });
13
+ const normalizer = createClaudeNormalizer(events);
14
+ const providerSessions = new Map();
15
+ return {
16
+ async run(input, emit) {
17
+ const query = options.query ??
18
+ (await import("@anthropic-ai/claude-agent-sdk")).query;
19
+ const resume = providerSessions.get(input.sessionId);
20
+ const state = { providerSessionId: resume ?? null };
21
+ emit(events.reasoningStarted({ providerSessionId: state.providerSessionId }));
22
+ const stream = query({
23
+ prompt: input.prompt,
24
+ options: {
25
+ cwd: options.cwd ?? process.cwd(),
26
+ permissionMode: "bypassPermissions",
27
+ includePartialMessages: true,
28
+ ...(resume ? { resume } : {}),
29
+ ...options.queryOptions,
30
+ },
31
+ });
32
+ for await (const message of stream) {
33
+ if (typeof message.session_id === "string" && message.session_id) {
34
+ providerSessions.set(input.sessionId, message.session_id);
35
+ state.providerSessionId = message.session_id;
36
+ }
37
+ const normalized = normalizer.normalizeClaudeMessage(message, state);
38
+ if (normalized.length > 0) {
39
+ for (const event of normalized)
40
+ emit(event);
41
+ continue;
42
+ }
43
+ if (message.type === "result") {
44
+ const raw = { source: "claude.sdk.message", method: "claude/result", payload: message };
45
+ const usageRecords = normalizer.usageRecordsFromClaudeResult(message, undefined);
46
+ if (usageRecords.length === 0) {
47
+ usageRecords.push(normalizer.usageFromClaude(message.usage, undefined));
48
+ }
49
+ for (const usageRecord of usageRecords) {
50
+ emit(events.usageFinal({
51
+ ...usageRecord,
52
+ costUsd: usageRecords.length === 1 ? (message.total_cost_usd ?? null) : null,
53
+ }, { providerSessionId: state.providerSessionId, raw }));
54
+ }
55
+ if (message.is_error) {
56
+ const errors = Array.isArray(message.errors) ? message.errors.join("\n") : null;
57
+ emit(events.errorEvent(errors || message.stop_reason || "Claude turn failed", {
58
+ providerSessionId: state.providerSessionId,
59
+ raw,
60
+ }));
61
+ }
62
+ emit(events.done({
63
+ providerSessionId: state.providerSessionId,
64
+ stopReason: message.stop_reason || "end_turn",
65
+ raw,
66
+ }));
67
+ }
68
+ }
69
+ },
70
+ };
71
+ }
72
+ //# sourceMappingURL=claude-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/drivers/claude-code.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { AutomationsHostConfig } from "./automations-host.js";
2
+ import type { BrickMount } from "./gateway.js";
3
+ /** Legacy root projection over the Automations brick's canonical trigger CRUD. */
4
+ export declare function eventTriggersMount(config: AutomationsHostConfig): BrickMount;
@@ -0,0 +1,48 @@
1
+ import { automationPrincipal } from "./automations-host.js";
2
+ async function listAutomations(config, request) {
3
+ const principal = await automationPrincipal(config, request);
4
+ const crud = config.service.for(principal);
5
+ const automations = [];
6
+ for (let offset = 0;; offset += 100) {
7
+ const page = await crud.automations.list({ limit: 100, offset });
8
+ automations.push(...page.items);
9
+ if (!page.hasMore)
10
+ break;
11
+ }
12
+ const triggerGroups = await Promise.all(automations.map(async (automation) => ((await crud.triggers.list(automation.id)).map((trigger) => ({
13
+ ...trigger,
14
+ automationName: automation.name || "",
15
+ automationDescription: automation.description || "",
16
+ targetId: automation.targetId,
17
+ })))));
18
+ return { automations, triggers: triggerGroups.flat() };
19
+ }
20
+ /** Legacy root projection over the Automations brick's canonical trigger CRUD. */
21
+ export function eventTriggersMount(config) {
22
+ return {
23
+ prefix: "/event-triggers",
24
+ stream: async (req, res, pathname) => {
25
+ if (pathname !== "/event-triggers" || req.method !== "GET") {
26
+ res.writeHead(req.method === "GET" ? 404 : 405, { "content-type": "application/json" });
27
+ res.end(JSON.stringify({ error: req.method === "GET" ? "not found" : "method not allowed" }));
28
+ return;
29
+ }
30
+ const headers = {};
31
+ for (const [name, value] of Object.entries(req.headers)) {
32
+ if (typeof value === "string")
33
+ headers[name] = value;
34
+ }
35
+ try {
36
+ const request = new Request("http://automations.local/event-triggers", { headers });
37
+ const result = await listAutomations(config, request);
38
+ res.writeHead(200, { "content-type": "application/json", "cache-control": "no-store" });
39
+ res.end(JSON.stringify(result));
40
+ }
41
+ catch {
42
+ res.writeHead(500, { "content-type": "application/json", "cache-control": "no-store" });
43
+ res.end(JSON.stringify({ error: "Automations service failed" }));
44
+ }
45
+ },
46
+ };
47
+ }
48
+ //# sourceMappingURL=event-triggers-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-triggers-host.js","sourceRoot":"","sources":["../src/event-triggers-host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { type AutomationEventsApiConfig } from "@amalgm/automations";
2
+ import type { BrickMount } from "./gateway.js";
3
+ export type AutomationEventsHostConfig = AutomationEventsApiConfig;
4
+ /**
5
+ * Node HTTP transport for the Automations brick's /events Fetch API. Target
6
+ * identity and delivery capabilities are injected; all ingress decisions stay
7
+ * in @amalgm/automations.
8
+ */
9
+ export declare function automationEventsMount(config: AutomationEventsHostConfig): BrickMount;
@@ -0,0 +1,34 @@
1
+ import { Readable } from "node:stream";
2
+ import { createAutomationEventsApi, } from "@amalgm/automations";
3
+ /**
4
+ * Node HTTP transport for the Automations brick's /events Fetch API. Target
5
+ * identity and delivery capabilities are injected; all ingress decisions stay
6
+ * in @amalgm/automations.
7
+ */
8
+ export function automationEventsMount(config) {
9
+ const api = createAutomationEventsApi(config);
10
+ return {
11
+ prefix: "/events",
12
+ stream: async (req, res, pathname) => {
13
+ const source = new URL(req.url ?? pathname, "http://localhost");
14
+ const headers = new Headers();
15
+ for (const [name, value] of Object.entries(req.headers)) {
16
+ if (Array.isArray(value))
17
+ headers.set(name, value.join(", "));
18
+ else if (value !== undefined)
19
+ headers.set(name, value);
20
+ }
21
+ const method = req.method ?? "GET";
22
+ const init = { method, headers };
23
+ if (method !== "GET" && method !== "HEAD") {
24
+ init.body = Readable.toWeb(req);
25
+ init.duplex = "half";
26
+ }
27
+ const request = new Request(`http://automations.local${pathname}${source.search}`, init);
28
+ const response = await api(request);
29
+ res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
30
+ res.end(Buffer.from(await response.arrayBuffer()));
31
+ },
32
+ };
33
+ }
34
+ //# sourceMappingURL=events-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events-host.js","sourceRoot":"","sources":["../src/events-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EACL,yBAAyB,GAE1B,MAAM,qBAAqB,CAAC;AAM7B;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAkC;IACtE,MAAM,GAAG,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAC9C,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE;YACnC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,QAAQ,EAAE,kBAAkB,CAAC,CAAC;YAChE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;YAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;oBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;qBACzD,IAAI,KAAK,KAAK,SAAS;oBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACzD,CAAC;YACD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC;YACnC,MAAM,IAAI,GAAsC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;YACpE,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC1C,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAA+B,CAAC;gBAC9D,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;YACvB,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,OAAO,CACzB,2BAA2B,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,EACrD,IAAI,CACL,CAAC;YACF,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC;YACpC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC/E,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QACrD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { Apps } from "@amalgm/apps";
2
+ import type { BrickMount, BrickUpgradeMount } from "./gateway.js";
3
+ export interface ExternalProxyHostConfig {
4
+ readonly apps: Apps;
5
+ readonly gatewayPort: () => number | null;
6
+ readonly localAgentAppPort: number | null;
7
+ readonly monitoredPreviewPorts?: () => ReadonlySet<number>;
8
+ }
9
+ export interface ExternalProxyHost {
10
+ readonly mount: BrickMount;
11
+ readonly upgrade: BrickUpgradeMount;
12
+ close(): void;
13
+ }
14
+ /** Engine reference: amalgm-engine/runtime/scripts/local-gateway.js:180-250,656-769,924-1000. */
15
+ export declare function createExternalProxyHost(config: ExternalProxyHostConfig): ExternalProxyHost;
@@ -0,0 +1,166 @@
1
+ import { request as httpRequest } from "node:http";
2
+ import { externalProxyTargetForPath, HOP_BY_HOP_HEADERS, isAllowedPreviewPort, isAppRoutable, normalizeAppRef, RUNTIME_TOKEN_HEADER, stripHeaders, WS_CLOSE_POLICY_VIOLATION, WS_CLOSE_UNAUTHORIZED, WS_CLOSE_UPSTREAM_FAILURE, WS_HANDSHAKE_HEADERS, } from "@amalgm/core/transport";
3
+ import { WebSocket, WebSocketServer } from "ws";
4
+ /** Engine reference: amalgm-engine/runtime/scripts/local-gateway.js:180-250,656-769,924-1000. */
5
+ export function createExternalProxyHost(config) {
6
+ const wss = new WebSocketServer({ noServer: true });
7
+ const sockets = new Set();
8
+ const resolve = (pathname) => resolveTarget(pathname, config);
9
+ return {
10
+ mount: {
11
+ prefix: "/__amalgm",
12
+ stream(req, res, pathname) {
13
+ if (req.method === "GET" && pathname === "/__amalgm") {
14
+ const apps = routableApps(config.apps);
15
+ res.writeHead(200, { "content-type": "application/json", "cache-control": "no-store" });
16
+ res.end(JSON.stringify({
17
+ service: "external-proxy",
18
+ apps: apps.map((app) => ({ appRef: normalizeAppRef(app), port: Number(app.port), name: app.name })),
19
+ previewPorts: [...new Set(apps.map((app) => Number(app.port)))],
20
+ }));
21
+ return;
22
+ }
23
+ const target = resolve(pathname);
24
+ if (!target) {
25
+ jsonError(res, 404, "Unknown local gateway route");
26
+ return;
27
+ }
28
+ if ("error" in target) {
29
+ jsonError(res, target.error.status, target.error.message);
30
+ return;
31
+ }
32
+ proxyHttp(req, res, target);
33
+ },
34
+ },
35
+ upgrade: {
36
+ prefix: "/__amalgm",
37
+ handle(req, socket, head, authorized) {
38
+ wss.handleUpgrade(req, socket, head, (client) => {
39
+ sockets.add(client);
40
+ client.on("close", () => sockets.delete(client));
41
+ if (!authorized) {
42
+ client.close(WS_CLOSE_UNAUTHORIZED.code, WS_CLOSE_UNAUTHORIZED.reason);
43
+ return;
44
+ }
45
+ const pathname = new URL(req.url ?? "/", "http://proxy.local").pathname;
46
+ const target = resolve(pathname);
47
+ if (!target) {
48
+ client.close(WS_CLOSE_POLICY_VIOLATION, "Unknown local gateway route");
49
+ return;
50
+ }
51
+ if ("error" in target) {
52
+ client.close(target.error.status === 403 ? WS_CLOSE_POLICY_VIOLATION : WS_CLOSE_UPSTREAM_FAILURE, target.error.message);
53
+ return;
54
+ }
55
+ proxyWebSocket(req, client, target, sockets);
56
+ });
57
+ },
58
+ },
59
+ close() {
60
+ for (const socket of sockets)
61
+ socket.terminate();
62
+ sockets.clear();
63
+ },
64
+ };
65
+ }
66
+ function resolveTarget(pathname, config) {
67
+ const apps = routableApps(config.apps);
68
+ const activeAppPorts = new Set(apps.map((app) => Number(app.port)));
69
+ return externalProxyTargetForPath(pathname, {
70
+ appPortForRef(appRef) {
71
+ const app = apps.find((candidate) => normalizeAppRef(candidate) === appRef);
72
+ return app ? Number(app.port) : null;
73
+ },
74
+ isAllowedPreviewPort(port) {
75
+ const gatewayPort = config.gatewayPort();
76
+ return isAllowedPreviewPort(port, {
77
+ internal: {
78
+ localAgentAppPort: config.localAgentAppPort,
79
+ servicePorts: gatewayPort === null ? [] : [gatewayPort],
80
+ },
81
+ activeAppPorts,
82
+ monitoredPreviewPorts: config.monitoredPreviewPorts?.() ?? new Set(),
83
+ });
84
+ },
85
+ });
86
+ }
87
+ function routableApps(apps) {
88
+ return apps.list().filter(isAppRoutable);
89
+ }
90
+ function proxyHttp(req, res, target) {
91
+ const url = new URL(req.url ?? "/", "http://proxy.local");
92
+ const headers = externalHeaders(req.headers, HOP_BY_HOP_HEADERS);
93
+ const forwardedHost = firstHeader(req.headers["x-forwarded-host"]);
94
+ const upstream = httpRequest({
95
+ host: "127.0.0.1",
96
+ port: target.port,
97
+ method: req.method,
98
+ path: forwardPath(url, target.prefix),
99
+ headers: { ...headers, host: forwardedHost || `127.0.0.1:${target.port}` },
100
+ timeout: 60_000,
101
+ }, (response) => {
102
+ res.writeHead(response.statusCode ?? 502, stripHeaders(response.headers, HOP_BY_HOP_HEADERS));
103
+ response.pipe(res);
104
+ });
105
+ upstream.on("timeout", () => upstream.destroy(new Error("Upstream request timed out")));
106
+ upstream.on("error", (error) => {
107
+ if (!res.headersSent) {
108
+ res.writeHead(502, { "content-type": "application/json" });
109
+ res.end(JSON.stringify({ error: "External preview request failed", detail: error.message }));
110
+ return;
111
+ }
112
+ res.destroy(error);
113
+ });
114
+ res.on("close", () => {
115
+ if (!res.writableFinished)
116
+ upstream.destroy();
117
+ });
118
+ req.pipe(upstream);
119
+ }
120
+ function proxyWebSocket(req, client, target, sockets) {
121
+ const url = new URL(req.url ?? "/", "http://proxy.local");
122
+ const protocols = firstHeader(req.headers["sec-websocket-protocol"])
123
+ .split(",").map((value) => value.trim()).filter(Boolean);
124
+ const headers = externalHeaders(req.headers, new Set([...HOP_BY_HOP_HEADERS, ...WS_HANDSHAKE_HEADERS]));
125
+ const address = `ws://127.0.0.1:${target.port}${forwardPath(url, target.prefix)}`;
126
+ const upstream = protocols.length > 0
127
+ ? new WebSocket(address, protocols, { headers })
128
+ : new WebSocket(address, { headers });
129
+ sockets.add(upstream);
130
+ client.on("message", (data, isBinary) => {
131
+ if (upstream.readyState === WebSocket.OPEN)
132
+ upstream.send(data, { binary: isBinary });
133
+ });
134
+ upstream.on("message", (data, isBinary) => {
135
+ if (client.readyState === WebSocket.OPEN)
136
+ client.send(data, { binary: isBinary });
137
+ });
138
+ client.on("close", (code, reason) => upstream.close(code, reason.toString("utf8")));
139
+ upstream.on("close", (code, reason) => {
140
+ sockets.delete(upstream);
141
+ client.close(code, reason.toString("utf8"));
142
+ });
143
+ upstream.on("error", (error) => client.close(WS_CLOSE_UPSTREAM_FAILURE, error.message));
144
+ }
145
+ function externalHeaders(headers, drop) {
146
+ const out = stripHeaders(headers, drop);
147
+ for (const name of Object.keys(out)) {
148
+ if (name.toLowerCase() === RUNTIME_TOKEN_HEADER)
149
+ delete out[name];
150
+ }
151
+ return out;
152
+ }
153
+ function forwardPath(url, prefix) {
154
+ const pathname = url.pathname.slice(prefix.length) || "/";
155
+ return `${pathname.startsWith("/") ? pathname : `/${pathname}`}${url.search}`;
156
+ }
157
+ function firstHeader(value) {
158
+ if (typeof value === "string")
159
+ return value;
160
+ return value?.[0] ?? "";
161
+ }
162
+ function jsonError(res, status, error) {
163
+ res.writeHead(status, { "content-type": "application/json", "cache-control": "no-store" });
164
+ res.end(JSON.stringify({ error }));
165
+ }
166
+ //# sourceMappingURL=external-proxy-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-proxy-host.js","sourceRoot":"","sources":["../src/external-proxy-host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare function ensurePrivateDir(directory: string): void;
2
+ export declare function atomicWrite(file: string, bytes: string | Uint8Array, mode?: number): void;
3
+ export declare function readJson<T>(file: string): T | null;
4
+ export declare function atomicJson(file: string, value: unknown): void;
5
+ /** Commit related JSON documents without ever leaving a split public/secret
6
+ * pair. Existing files are restored if any rename fails. */
7
+ export declare function atomicJsonSet(documents: readonly (readonly [string, unknown])[]): void;
@@ -0,0 +1,71 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ export function ensurePrivateDir(directory) {
5
+ mkdirSync(directory, { recursive: true, mode: 0o700 });
6
+ chmodSync(directory, 0o700);
7
+ }
8
+ export function atomicWrite(file, bytes, mode = 0o600) {
9
+ ensurePrivateDir(dirname(file));
10
+ const temporary = `${file}.${randomUUID()}.tmp`;
11
+ try {
12
+ writeFileSync(temporary, bytes, { mode, flag: "wx" });
13
+ renameSync(temporary, file);
14
+ chmodSync(file, mode);
15
+ }
16
+ finally {
17
+ rmSync(temporary, { force: true });
18
+ }
19
+ }
20
+ export function readJson(file) {
21
+ try {
22
+ return JSON.parse(readFileSync(file, "utf8"));
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ export function atomicJson(file, value) {
29
+ atomicWrite(file, `${JSON.stringify(value, null, 2)}\n`);
30
+ }
31
+ /** Commit related JSON documents without ever leaving a split public/secret
32
+ * pair. Existing files are restored if any rename fails. */
33
+ export function atomicJsonSet(documents) {
34
+ const transaction = randomUUID();
35
+ const temporary = [];
36
+ const backups = [];
37
+ const written = [];
38
+ try {
39
+ for (const [file, value] of documents) {
40
+ const temp = `${file}.${transaction}.tmp`;
41
+ ensurePrivateDir(dirname(file));
42
+ writeFileSync(temp, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600, flag: "wx" });
43
+ temporary.push(temp);
44
+ }
45
+ for (let index = 0; index < documents.length; index += 1) {
46
+ const [file] = documents[index];
47
+ const backup = `${file}.${transaction}.bak`;
48
+ if (existsSync(file)) {
49
+ renameSync(file, backup);
50
+ backups.push([file, backup]);
51
+ }
52
+ renameSync(temporary[index], file);
53
+ chmodSync(file, 0o600);
54
+ written.push(file);
55
+ }
56
+ for (const [, backup] of backups)
57
+ rmSync(backup, { force: true });
58
+ }
59
+ catch (error) {
60
+ for (const file of written)
61
+ rmSync(file, { force: true });
62
+ for (const [file, backup] of [...backups].reverse()) {
63
+ if (existsSync(backup))
64
+ renameSync(backup, file);
65
+ }
66
+ for (const temp of temporary)
67
+ rmSync(temp, { force: true });
68
+ throw error;
69
+ }
70
+ }
71
+ //# sourceMappingURL=filesystem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../src/filesystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,MAAM,EACN,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,KAA0B,EAAE,IAAI,GAAG,KAAK;IAChF,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAChC,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,UAAU,EAAE,MAAM,CAAC;IAChD,IAAI,CAAC;QACH,aAAa,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC5B,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACxB,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAI,IAAY;IACtC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAM,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,KAAc;IACrD,WAAW,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED;4DAC4D;AAC5D,MAAM,UAAU,aAAa,CAAC,SAAkD;IAC9E,MAAM,WAAW,GAAG,UAAU,EAAE,CAAC;IACjC,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAqC,EAAE,CAAC;IACrD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,GAAG,IAAI,IAAI,WAAW,MAAM,CAAC;YAC1C,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YAChC,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACxF,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;QACD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YACzD,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,CAA+B,CAAC;YAC9D,MAAM,MAAM,GAAG,GAAG,IAAI,IAAI,WAAW,MAAM,CAAC;YAC5C,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrB,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACzB,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;YAC/B,CAAC;YACD,UAAU,CAAC,SAAS,CAAC,KAAK,CAAW,EAAE,IAAI,CAAC,CAAC;YAC7C,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;QACD,KAAK,MAAM,CAAC,EAAE,MAAM,CAAC,IAAI,OAAO;YAAE,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,KAAK,MAAM,IAAI,IAAI,OAAO;YAAE,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;YACpD,IAAI,UAAU,CAAC,MAAM,CAAC;gBAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACnD,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,SAAS;YAAE,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { BrickMount } from "./gateway.js";
2
+ /**
3
+ * Forward a gateway prefix to a brick's own HTTP server on loopback —
4
+ * the engine's gateway architecture (prefixes route to per-service ports)
5
+ * applied inside the shell. The prefix is re-rooted onto the brick
6
+ * server's own root (both agents and browser root their APIs at /v1):
7
+ * /agents/sessions reaches the agents server as /v1/sessions.
8
+ */
9
+ export declare function forwardMount(prefix: string, port: () => number, options?: {
10
+ root?: string;
11
+ }): BrickMount;