@aarmos/bridge 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 (43) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +280 -0
  3. package/dist/bridge.js +129 -0
  4. package/dist/bridge.js.map +1 -0
  5. package/dist/commands/attest.js +62 -0
  6. package/dist/commands/attest.js.map +1 -0
  7. package/dist/commands/demo.js +169 -0
  8. package/dist/commands/demo.js.map +1 -0
  9. package/dist/commands/dev.js +56 -0
  10. package/dist/commands/dev.js.map +1 -0
  11. package/dist/commands/pack.js +94 -0
  12. package/dist/commands/pack.js.map +1 -0
  13. package/dist/commands/playbook.js +55 -0
  14. package/dist/commands/playbook.js.map +1 -0
  15. package/dist/commands/run.js +279 -0
  16. package/dist/commands/run.js.map +1 -0
  17. package/dist/commands/simulate.js +181 -0
  18. package/dist/commands/simulate.js.map +1 -0
  19. package/dist/commands/verify.js +81 -0
  20. package/dist/commands/verify.js.map +1 -0
  21. package/dist/index.js +231 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/lib/attest.js +160 -0
  24. package/dist/lib/attest.js.map +1 -0
  25. package/dist/lib/http-broker.js +82 -0
  26. package/dist/lib/http-broker.js.map +1 -0
  27. package/dist/lib/mcp-broker.js +80 -0
  28. package/dist/lib/mcp-broker.js.map +1 -0
  29. package/dist/lib/pack.js +80 -0
  30. package/dist/lib/pack.js.map +1 -0
  31. package/dist/lib/playbook.js +199 -0
  32. package/dist/lib/playbook.js.map +1 -0
  33. package/dist/lib/scope-templates.js +129 -0
  34. package/dist/lib/scope-templates.js.map +1 -0
  35. package/dist/rpc/router.js +321 -0
  36. package/dist/rpc/router.js.map +1 -0
  37. package/dist/session.js +100 -0
  38. package/dist/session.js.map +1 -0
  39. package/dist/watchers/files.js +31 -0
  40. package/dist/watchers/files.js.map +1 -0
  41. package/dist/watchers/git.js +39 -0
  42. package/dist/watchers/git.js.map +1 -0
  43. package/package.json +67 -0
@@ -0,0 +1,321 @@
1
+ import { z } from "zod";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { spawn } from "node:child_process";
5
+ import { simpleGit } from "simple-git";
6
+ import pg from "pg";
7
+ import { HttpCallParams, previewHttpCall, executeHttpCall } from "../lib/http-broker.js";
8
+ import { McpToolParams, previewMcpTool, executeMcpTool } from "../lib/mcp-broker.js";
9
+ const RpcRequest = z.object({
10
+ id: z.union([z.string(), z.number()]),
11
+ type: z.literal("rpc"),
12
+ method: z.string(),
13
+ params: z.unknown().optional(),
14
+ });
15
+ const BatchAction = z.object({
16
+ kind: z.enum(["fs.write", "shell.exec", "http.call", "mcp.tool"]),
17
+ params: z.unknown(),
18
+ });
19
+ export async function handleRpc(session, msg) {
20
+ const parsed = RpcRequest.safeParse(msg);
21
+ if (!parsed.success)
22
+ return { type: "error", error: "invalid rpc envelope" };
23
+ const { id, method, params } = parsed.data;
24
+ try {
25
+ const result = await dispatch(session, method, params);
26
+ return { id, type: "result", result };
27
+ }
28
+ catch (err) {
29
+ return { id, type: "error", error: err instanceof Error ? err.message : String(err) };
30
+ }
31
+ }
32
+ async function dispatch(session, method, params) {
33
+ switch (method) {
34
+ // ---- reads (always live, never previewed) ------------------------------
35
+ case "fs.read": {
36
+ const { path: rel, encoding } = z
37
+ .object({ path: z.string(), encoding: z.enum(["utf8", "base64"]).default("utf8") })
38
+ .parse(params);
39
+ const abs = session.resolveInJail(rel);
40
+ const buf = await fs.readFile(abs);
41
+ return { path: rel, encoding, data: encoding === "utf8" ? buf.toString("utf8") : buf.toString("base64") };
42
+ }
43
+ case "fs.list": {
44
+ const { path: rel } = z.object({ path: z.string().default(".") }).parse(params);
45
+ const abs = session.resolveInJail(rel);
46
+ const entries = await fs.readdir(abs, { withFileTypes: true });
47
+ return entries.map((e) => ({ name: e.name, dir: e.isDirectory(), file: e.isFile() }));
48
+ }
49
+ case "git.status": {
50
+ return await simpleGit(session.workspace).status();
51
+ }
52
+ case "git.branch": {
53
+ return await simpleGit(session.workspace).branch();
54
+ }
55
+ // ---- mutations (previewed under dry-run) -------------------------------
56
+ case "fs.write": {
57
+ const preview = await previewFsWrite(session, params);
58
+ if (session.dryRun)
59
+ return { preview: true, action: preview };
60
+ return await executeFsWrite(session, params);
61
+ }
62
+ case "shell.exec": {
63
+ const preview = previewShellExec(session, params);
64
+ if (session.dryRun)
65
+ return { preview: true, action: preview };
66
+ return await executeShellExec(session, params);
67
+ }
68
+ case "http.call": {
69
+ const p = HttpCallParams.parse(params);
70
+ const preview = { kind: "http.call", params: p, preview: previewHttpCall(p, session.httpAllow) };
71
+ if (session.dryRun)
72
+ return { preview: true, action: preview };
73
+ return await executeHttpCall(p, session.httpAllow);
74
+ }
75
+ case "mcp.tool": {
76
+ const p = McpToolParams.parse(params);
77
+ const preview = { kind: "mcp.tool", params: p, preview: previewMcpTool(p, session.mcpAllow) };
78
+ if (session.dryRun)
79
+ return { preview: true, action: preview };
80
+ return await executeMcpTool(p, session.mcpAllow);
81
+ }
82
+ // ---- session controls --------------------------------------------------
83
+ case "session.setDryRun": {
84
+ const { on } = z.object({ on: z.boolean() }).parse(params);
85
+ session.dryRun = on;
86
+ return { dryRun: session.dryRun };
87
+ }
88
+ case "session.state": {
89
+ return { dryRun: session.dryRun, workspace: session.workspace };
90
+ }
91
+ // ---- read-only Postgres (only if operator passed --allow-sql) ----------
92
+ case "db.list": {
93
+ return {
94
+ databases: [...session.sqlAllow.values()].map((s) => ({ alias: s.alias })),
95
+ };
96
+ }
97
+ case "db.query": {
98
+ return await executeDbQuery(session, params);
99
+ }
100
+ // ---- scoped filesystem read (only if operator passed --allow-read) ------
101
+ case "fs.scopedRoots": {
102
+ return { roots: [...session.readAllow] };
103
+ }
104
+ case "fs.scopedRead": {
105
+ const { path: abs, encoding } = z
106
+ .object({
107
+ path: z.string(),
108
+ encoding: z.enum(["utf8", "base64"]).default("utf8"),
109
+ })
110
+ .parse(params);
111
+ const real = session.assertReadable(abs);
112
+ const buf = await fs.readFile(real);
113
+ // Soft cap: refuse to shovel enormous files through the WS in one shot.
114
+ if (buf.byteLength > 2 * 1024 * 1024) {
115
+ throw new Error(`file too large for scopedRead (${buf.byteLength} bytes; cap 2 MiB)`);
116
+ }
117
+ return {
118
+ path: real,
119
+ encoding,
120
+ bytes: buf.byteLength,
121
+ data: encoding === "utf8" ? buf.toString("utf8") : buf.toString("base64"),
122
+ };
123
+ }
124
+ case "fs.scopedList": {
125
+ const { path: abs } = z.object({ path: z.string() }).parse(params);
126
+ const real = session.assertReadable(abs);
127
+ const entries = await fs.readdir(real, { withFileTypes: true });
128
+ return {
129
+ path: real,
130
+ entries: entries.map((e) => ({
131
+ name: e.name,
132
+ absPath: path.join(real, e.name),
133
+ dir: e.isDirectory(),
134
+ file: e.isFile(),
135
+ })),
136
+ };
137
+ }
138
+ // ---- batch apply (commits an approved plan, ignoring dryRun) -----------
139
+ case "apply.batch": {
140
+ const { actions } = z.object({ actions: z.array(BatchAction) }).parse(params);
141
+ const results = [];
142
+ for (const a of actions) {
143
+ try {
144
+ let res;
145
+ if (a.kind === "fs.write")
146
+ res = await executeFsWrite(session, a.params);
147
+ else if (a.kind === "shell.exec")
148
+ res = await executeShellExec(session, a.params);
149
+ else if (a.kind === "http.call")
150
+ res = await executeHttpCall(HttpCallParams.parse(a.params), session.httpAllow);
151
+ else
152
+ res = await executeMcpTool(McpToolParams.parse(a.params), session.mcpAllow);
153
+ results.push({ ok: true, kind: a.kind, result: res });
154
+ }
155
+ catch (err) {
156
+ results.push({
157
+ ok: false,
158
+ kind: a.kind,
159
+ error: err instanceof Error ? err.message : String(err),
160
+ });
161
+ // Stop-on-first-error keeps partial-commit surprises out of the workspace.
162
+ break;
163
+ }
164
+ }
165
+ return { applied: results.length, results };
166
+ }
167
+ default:
168
+ throw new Error(`unknown method: ${method}`);
169
+ }
170
+ }
171
+ // -------- execution + preview helpers ----------------------------------------
172
+ const FsWriteParams = z.object({
173
+ path: z.string(),
174
+ data: z.string(),
175
+ encoding: z.enum(["utf8", "base64"]).default("utf8"),
176
+ });
177
+ async function previewFsWrite(session, params) {
178
+ const p = FsWriteParams.parse(params);
179
+ const abs = session.resolveInJail(p.path);
180
+ let before = null;
181
+ let existed = false;
182
+ try {
183
+ const buf = await fs.readFile(abs);
184
+ existed = true;
185
+ before = p.encoding === "utf8" ? buf.toString("utf8") : buf.toString("base64");
186
+ }
187
+ catch {
188
+ // new file
189
+ }
190
+ const after = p.data;
191
+ return {
192
+ kind: "fs.write",
193
+ params: p,
194
+ preview: {
195
+ path: p.path,
196
+ encoding: p.encoding,
197
+ existed,
198
+ bytesBefore: before?.length ?? 0,
199
+ bytesAfter: after.length,
200
+ before,
201
+ after,
202
+ },
203
+ };
204
+ }
205
+ async function executeFsWrite(session, params) {
206
+ const p = FsWriteParams.parse(params);
207
+ const abs = session.resolveInJail(p.path);
208
+ await fs.mkdir(pathDirname(abs), { recursive: true });
209
+ await fs.writeFile(abs, p.encoding === "utf8" ? p.data : Buffer.from(p.data, "base64"));
210
+ return { path: p.path, bytes: p.data.length };
211
+ }
212
+ const ShellExecParams = z.object({
213
+ bin: z.string(),
214
+ args: z.array(z.string()).default([]),
215
+ cwd: z.string().default("."),
216
+ });
217
+ function previewShellExec(session, params) {
218
+ const p = ShellExecParams.parse(params);
219
+ if (!session.shellAllow.has(p.bin))
220
+ throw new Error(`shell binary not allowed: ${p.bin}`);
221
+ const absCwd = session.resolveInJail(p.cwd);
222
+ return {
223
+ kind: "shell.exec",
224
+ params: p,
225
+ preview: {
226
+ commandLine: [p.bin, ...p.args].join(" "),
227
+ cwd: absCwd,
228
+ binary: p.bin,
229
+ args: p.args,
230
+ },
231
+ };
232
+ }
233
+ async function executeShellExec(session, params) {
234
+ const p = ShellExecParams.parse(params);
235
+ if (!session.shellAllow.has(p.bin))
236
+ throw new Error(`shell binary not allowed: ${p.bin}`);
237
+ const absCwd = session.resolveInJail(p.cwd);
238
+ return await execAllowed(p.bin, p.args, absCwd);
239
+ }
240
+ function pathDirname(p) {
241
+ const i = p.lastIndexOf("/");
242
+ return i >= 0 ? p.slice(0, i) : ".";
243
+ }
244
+ function execAllowed(bin, args, cwd) {
245
+ return new Promise((resolve) => {
246
+ const child = spawn(bin, args, { cwd, shell: false });
247
+ let stdout = "";
248
+ let stderr = "";
249
+ child.stdout.on("data", (b) => (stdout += b.toString()));
250
+ child.stderr.on("data", (b) => (stderr += b.toString()));
251
+ child.on("close", (code) => resolve({ code: code ?? 0, stdout, stderr }));
252
+ });
253
+ }
254
+ // -------- read-only Postgres --------------------------------------------------
255
+ //
256
+ // Guarantees enforced here, not by convention:
257
+ // 1. The operator must have opted in via `--allow-sql <alias>=<dsn>`.
258
+ // Without a matching alias, we throw before opening a connection.
259
+ // 2. The query runs inside `BEGIN READ ONLY` with a bounded
260
+ // `statement_timeout`. Any write (INSERT/UPDATE/DELETE/DDL) is
261
+ // rejected by Postgres itself with `read_only_sql_transaction`.
262
+ // 3. Rows are hard-capped; if the query returns more than `rowLimit`,
263
+ // we truncate and mark `truncated: true`. Model can page by `LIMIT`.
264
+ // 4. Parameters go through the extended query protocol (`$1`, `$2`, …)
265
+ // so a single call cannot smuggle in a second statement via `;`.
266
+ // 5. The DSN is never returned to the caller — only the alias, and
267
+ // row / column data.
268
+ const DbQueryParams = z.object({
269
+ alias: z.string().optional(),
270
+ sql: z.string().min(1),
271
+ params: z.array(z.unknown()).default([]),
272
+ rowLimit: z.number().int().min(1).max(10_000).default(500),
273
+ statementTimeoutMs: z.number().int().min(100).max(30_000).default(5_000),
274
+ });
275
+ async function executeDbQuery(session, params) {
276
+ const p = DbQueryParams.parse(params);
277
+ if (session.sqlAllow.size === 0) {
278
+ throw new Error("db.query is not permitted — start the CLI with --allow-sql <alias>=<dsn> to opt in.");
279
+ }
280
+ let entry;
281
+ if (p.alias) {
282
+ entry = session.sqlAllow.get(p.alias);
283
+ if (!entry)
284
+ throw new Error(`unknown --allow-sql alias: ${p.alias}`);
285
+ }
286
+ else if (session.sqlAllow.size === 1) {
287
+ entry = session.sqlAllow.values().next().value;
288
+ }
289
+ else {
290
+ throw new Error(`alias required (registered: ${[...session.sqlAllow.keys()].join(", ")})`);
291
+ }
292
+ const client = new pg.Client({ connectionString: entry.dsn });
293
+ const started = Date.now();
294
+ try {
295
+ await client.connect();
296
+ await client.query("BEGIN READ ONLY");
297
+ await client.query(`SET LOCAL statement_timeout = ${p.statementTimeoutMs}`);
298
+ const res = await client.query({ text: p.sql, values: p.params });
299
+ await client.query("ROLLBACK");
300
+ const truncated = res.rows.length > p.rowLimit;
301
+ return {
302
+ alias: entry.alias,
303
+ command: res.command,
304
+ rowCount: res.rowCount,
305
+ returnedRows: Math.min(res.rows.length, p.rowLimit),
306
+ truncated,
307
+ fields: res.fields?.map((f) => ({ name: f.name, dataTypeID: f.dataTypeID })),
308
+ rows: truncated ? res.rows.slice(0, p.rowLimit) : res.rows,
309
+ elapsedMs: Date.now() - started,
310
+ };
311
+ }
312
+ finally {
313
+ try {
314
+ await client.end();
315
+ }
316
+ catch {
317
+ /* ignore */
318
+ }
319
+ }
320
+ }
321
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/rpc/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ import path from "node:path";
2
+ import fs from "node:fs";
3
+ export const DEFAULT_SHELL_ALLOW = [
4
+ "git",
5
+ "npm",
6
+ "pnpm",
7
+ "bun",
8
+ "node",
9
+ "ls",
10
+ "cat",
11
+ "rg",
12
+ "grep",
13
+ ];
14
+ export function createSession(opts) {
15
+ const workspace = path.resolve(opts.workspace);
16
+ const shellAllow = new Set([...DEFAULT_SHELL_ALLOW, ...opts.extraShellAllow]);
17
+ const sqlAllow = new Map();
18
+ for (const entry of opts.sqlAllow ?? []) {
19
+ if (sqlAllow.has(entry.alias)) {
20
+ throw new Error(`duplicate --allow-sql alias: ${entry.alias}`);
21
+ }
22
+ sqlAllow.set(entry.alias, entry);
23
+ }
24
+ // Resolve each opted-in read root once, via realpath, so symlink games
25
+ // at request time can't sneak in an unlisted path.
26
+ const readAllow = [];
27
+ for (const raw of opts.readAllow ?? []) {
28
+ const abs = path.resolve(raw);
29
+ let real;
30
+ try {
31
+ real = fs.realpathSync(abs);
32
+ }
33
+ catch {
34
+ throw new Error(`--allow-read path does not exist: ${raw}`);
35
+ }
36
+ readAllow.push(real);
37
+ }
38
+ const httpAllow = new Set(opts.httpAllow ?? []);
39
+ const mcpAllow = new Set(opts.mcpAllow ?? []);
40
+ const capabilities = [
41
+ "fs.read",
42
+ "fs.write",
43
+ "fs.list",
44
+ "shell.exec",
45
+ "git.status",
46
+ "git.branch",
47
+ "events.fs",
48
+ "events.git",
49
+ "session.setDryRun",
50
+ "apply.batch",
51
+ ];
52
+ if (sqlAllow.size > 0) {
53
+ capabilities.push("db.list", "db.query");
54
+ }
55
+ if (readAllow.length > 0) {
56
+ capabilities.push("fs.scopedRoots", "fs.scopedRead", "fs.scopedList");
57
+ }
58
+ if (httpAllow.size > 0)
59
+ capabilities.push("http.call");
60
+ if (mcpAllow.size > 0)
61
+ capabilities.push("mcp.tool");
62
+ return {
63
+ workspace,
64
+ shellAllow,
65
+ sqlAllow,
66
+ readAllow,
67
+ httpAllow,
68
+ mcpAllow,
69
+ dryRun: true,
70
+ capabilities,
71
+ resolveInJail(rel) {
72
+ const abs = path.resolve(workspace, rel);
73
+ const rrel = path.relative(workspace, abs);
74
+ if (rrel.startsWith("..") || path.isAbsolute(rrel)) {
75
+ throw new Error(`path escapes workspace: ${rel}`);
76
+ }
77
+ return abs;
78
+ },
79
+ assertReadable(abs) {
80
+ if (!path.isAbsolute(abs)) {
81
+ throw new Error(`fs.scoped* requires an absolute path: ${abs}`);
82
+ }
83
+ let real;
84
+ try {
85
+ real = fs.realpathSync(abs);
86
+ }
87
+ catch {
88
+ throw new Error(`path not found: ${abs}`);
89
+ }
90
+ for (const root of readAllow) {
91
+ const rel = path.relative(root, real);
92
+ if (rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel))) {
93
+ return real;
94
+ }
95
+ }
96
+ throw new Error(`path is not inside any --allow-read root: ${abs}`);
97
+ },
98
+ };
99
+ }
100
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,MAAM;CACE,CAAC;AA8BX,MAAM,UAAU,aAAa,CAAC,IAO7B;IACC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAS,CAAC,GAAG,mBAAmB,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;IACtF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC7C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACxC,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,gCAAgC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;IACD,uEAAuE;IACvE,mDAAmD;IACnD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAS,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAS,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAEtD,MAAM,YAAY,GAAG;QACnB,SAAS;QACT,UAAU;QACV,SAAS;QACT,YAAY;QACZ,YAAY;QACZ,YAAY;QACZ,WAAW;QACX,YAAY;QACZ,mBAAmB;QACnB,aAAa;KACd,CAAC;IACF,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACtB,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,YAAY,CAAC,IAAI,CAAC,gBAAgB,EAAE,eAAe,EAAE,eAAe,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,GAAG,CAAC;QAAE,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACvD,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC;QAAE,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAErD,OAAO;QACL,SAAS;QACT,UAAU;QACV,QAAQ;QACR,SAAS;QACT,SAAS;QACT,QAAQ;QACR,MAAM,EAAE,IAAI;QACZ,YAAY;QACZ,aAAa,CAAC,GAAW;YACvB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YACzC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC3C,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;QACD,cAAc,CAAC,GAAW;YACxB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,yCAAyC,GAAG,EAAE,CAAC,CAAC;YAClE,CAAC;YACD,IAAI,IAAY,CAAC;YACjB,IAAI,CAAC;gBACH,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;YAC9B,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC;YAC5C,CAAC;YACD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACtC,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;oBACnE,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YACD,MAAM,IAAI,KAAK,CACb,6CAA6C,GAAG,EAAE,CACnD,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,31 @@
1
+ import chokidar from "chokidar";
2
+ import path from "node:path";
3
+ /**
4
+ * Watches the workspace and streams debounced file-change events to the PWA.
5
+ * This is the fix for the "developer edits in VS Code, PWA drifts out of sync"
6
+ * problem: any external write invalidates PWA-side state within ~150ms.
7
+ */
8
+ export function startFileWatcher(session, emit) {
9
+ const watcher = chokidar.watch(session.workspace, {
10
+ ignored: [
11
+ /(^|[/\\])\../, // dotfiles
12
+ /node_modules/,
13
+ /dist|build|\.next|\.turbo|\.cache/,
14
+ ],
15
+ ignoreInitial: true,
16
+ awaitWriteFinish: { stabilityThreshold: 120, pollInterval: 40 },
17
+ persistent: true,
18
+ });
19
+ const send = (kind) => (p) => {
20
+ const rel = path.relative(session.workspace, p) || ".";
21
+ emit({ kind, path: rel, at: Date.now() });
22
+ };
23
+ watcher
24
+ .on("add", send("add"))
25
+ .on("change", send("change"))
26
+ .on("unlink", send("unlink"))
27
+ .on("addDir", send("addDir"))
28
+ .on("unlinkDir", send("unlinkDir"));
29
+ return () => void watcher.close();
30
+ }
31
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/watchers/files.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,IAAI,MAAM,WAAW,CAAC;AAS7B;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB,EAAE,IAA4B;IAC7E,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE;QAChD,OAAO,EAAE;YACP,cAAc,EAAE,WAAW;YAC3B,cAAc;YACd,mCAAmC;SACpC;QACD,aAAa,EAAE,IAAI;QACnB,gBAAgB,EAAE,EAAE,kBAAkB,EAAE,GAAG,EAAE,YAAY,EAAE,EAAE,EAAE;QAC/D,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,CAAC,IAAqB,EAAE,EAAE,CAAC,CAAC,CAAS,EAAE,EAAE;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC;QACvD,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC;IAEF,OAAO;SACJ,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;SACtB,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;SAC5B,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;SAC5B,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;SAC5B,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IAEtC,OAAO,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { simpleGit } from "simple-git";
2
+ /**
3
+ * Polls git HEAD + current branch every 1.5s. Fires only on change.
4
+ * This catches `git checkout`, `git switch`, and `git commit` performed inside
5
+ * VS Code, keeping the PWA agent's view of the repo consistent.
6
+ */
7
+ export function startGitWatcher(session, emit) {
8
+ const git = simpleGit(session.workspace);
9
+ let lastBranch = null;
10
+ let lastHead = null;
11
+ let stopped = false;
12
+ const tick = async () => {
13
+ if (stopped)
14
+ return;
15
+ try {
16
+ const status = await git.status();
17
+ const head = (await git.revparse(["HEAD"])).trim();
18
+ const branch = status.current ?? null;
19
+ if (branch !== lastBranch || head !== lastHead) {
20
+ const kind = branch !== lastBranch ? "branch" : "head";
21
+ lastBranch = branch;
22
+ lastHead = head;
23
+ emit({ kind, branch, head, at: Date.now() });
24
+ }
25
+ }
26
+ catch {
27
+ // not a git repo — quietly stop polling
28
+ stopped = true;
29
+ return;
30
+ }
31
+ if (!stopped)
32
+ setTimeout(tick, 1500);
33
+ };
34
+ void tick();
35
+ return () => {
36
+ stopped = true;
37
+ };
38
+ }
39
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/watchers/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAUvC;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgB,EAAE,IAA6B;IAC7E,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACzC,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;QACtB,IAAI,OAAO;YAAE,OAAO;QACpB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;YAClC,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACnD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC;YACtC,IAAI,MAAM,KAAK,UAAU,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC/C,MAAM,IAAI,GAAqB,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;gBACzE,UAAU,GAAG,MAAM,CAAC;gBACpB,QAAQ,GAAG,IAAI,CAAC;gBAChB,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,wCAAwC;YACxC,OAAO,GAAG,IAAI,CAAC;YACf,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO;YAAE,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC,CAAC;IAEF,KAAK,IAAI,EAAE,CAAC;IACZ,OAAO,GAAG,EAAE;QACV,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@aarmos/bridge",
3
+ "version": "0.1.0",
4
+ "description": "Aarmos CLI bridge — local WebSocket host that gives the Aarmos PWA scoped, deny-by-default access to files, shell, git, and read-only Postgres on the developer's machine. The PWA stays the brain; this is the arms.",
5
+ "keywords": [
6
+ "aarmos",
7
+ "agent",
8
+ "agent-runtime",
9
+ "mcp",
10
+ "local-first",
11
+ "bridge",
12
+ "pwa",
13
+ "developer-tools"
14
+ ],
15
+ "bin": {
16
+ "aarmos-bridge": "./dist/index.js"
17
+ },
18
+ "type": "module",
19
+ "scripts": {
20
+ "build": "tsc -p tsconfig.json",
21
+ "dev": "tsx src/index.ts dev",
22
+ "start": "node dist/index.js",
23
+ "test": "tsx test/e2e.ts && tsx test/sample-smoke.ts && tsx test/daemon-e2e.ts && node test/crash-handling.mjs",
24
+ "prepublishOnly": "npm run build && npm test"
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "README.md",
29
+ "LICENSE"
30
+ ],
31
+ "publishConfig": {
32
+ "access": "public",
33
+ "tag": "next"
34
+ },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/aarmatix/aarmos.git",
38
+ "directory": "packages/cli"
39
+ },
40
+ "homepage": "https://www.aarmos.io",
41
+ "bugs": {
42
+ "url": "https://github.com/aarmatix/aarmos/issues"
43
+ },
44
+ "author": "Aarmatix LLC",
45
+ "license": "Apache-2.0",
46
+ "dependencies": {
47
+ "@aarmos/avar-core": "1.0.0-rc.1",
48
+ "@types/pg": "^8.20.0",
49
+ "chokidar": "^3.6.0",
50
+ "commander": "^12.1.0",
51
+ "fflate": "^0.8.3",
52
+ "open": "^10.1.0",
53
+ "pg": "^8.22.0",
54
+ "simple-git": "^3.25.0",
55
+ "ws": "^8.18.0",
56
+ "zod": "^3.23.8"
57
+ },
58
+ "devDependencies": {
59
+ "@types/node": "^22.5.0",
60
+ "@types/ws": "^8.5.12",
61
+ "tsx": "^4.19.0",
62
+ "typescript": "^5.6.2"
63
+ },
64
+ "engines": {
65
+ "node": ">=18.17"
66
+ }
67
+ }