@agentvault/grok-bridge 0.2.1 → 0.3.1

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/dist/index.js CHANGED
@@ -9,9 +9,54 @@ var __export = (target, all) => {
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
11
 
12
+ // src/pending-invite.ts
13
+ import { existsSync, mkdirSync, chmodSync, readFileSync as readFileSync2, writeFileSync, rmSync } from "node:fs";
14
+ import { join as join5 } from "node:path";
15
+ function pendingInvitePath(dataDir) {
16
+ return join5(dataDir, PENDING_INVITE_FILE);
17
+ }
18
+ function writePendingInvite(dataDir, token) {
19
+ mkdirSync(dataDir, { recursive: true, mode: DIR_MODE2 });
20
+ chmodSync(dataDir, DIR_MODE2);
21
+ const p2 = pendingInvitePath(dataDir);
22
+ writeFileSync(p2, token, { mode: FILE_MODE2 });
23
+ chmodSync(p2, FILE_MODE2);
24
+ }
25
+ function readPendingInvite(dataDir) {
26
+ const p2 = pendingInvitePath(dataDir);
27
+ if (!existsSync(p2)) return void 0;
28
+ try {
29
+ const raw = readFileSync2(p2, "utf-8").trim();
30
+ return raw.length > 0 ? raw : void 0;
31
+ } catch {
32
+ return void 0;
33
+ }
34
+ }
35
+ function clearPendingInvite(dataDir) {
36
+ try {
37
+ rmSync(pendingInvitePath(dataDir), { force: true });
38
+ } catch {
39
+ }
40
+ }
41
+ function clearPendingInviteIfConsumed(dataDir, credsExist) {
42
+ if (!existsSync(pendingInvitePath(dataDir))) return false;
43
+ if (!credsExist(dataDir)) return false;
44
+ clearPendingInvite(dataDir);
45
+ return true;
46
+ }
47
+ var DIR_MODE2, FILE_MODE2, PENDING_INVITE_FILE;
48
+ var init_pending_invite = __esm({
49
+ "src/pending-invite.ts"() {
50
+ "use strict";
51
+ DIR_MODE2 = 448;
52
+ FILE_MODE2 = 384;
53
+ PENDING_INVITE_FILE = "pending-invite";
54
+ }
55
+ });
56
+
12
57
  // src/config.ts
13
- import { existsSync, readFileSync as readFileSync2, mkdirSync, chmodSync } from "node:fs";
14
- import { join as join5, resolve as resolve2, sep, dirname } from "node:path";
58
+ import { existsSync as existsSync2, readFileSync as readFileSync3, mkdirSync as mkdirSync2, chmodSync as chmodSync2 } from "node:fs";
59
+ import { join as join6, resolve as resolve2, sep, dirname } from "node:path";
15
60
  import { tmpdir } from "node:os";
16
61
  function parseInfoFlags(argv) {
17
62
  return {
@@ -32,14 +77,14 @@ function assertInstallableEntrypoint(entrypoint) {
32
77
  }
33
78
  function hasRecoverableBackup(dataDir) {
34
79
  try {
35
- const parsed = JSON.parse(readFileSync2(join5(dataDir, BACKUP_FILE), "utf-8"));
80
+ const parsed = JSON.parse(readFileSync3(join6(dataDir, BACKUP_FILE), "utf-8"));
36
81
  return !!(parsed && parsed.deviceId && parsed.deviceJwt && parsed.sessions && Object.keys(parsed.sessions).length > 0);
37
82
  } catch {
38
83
  return false;
39
84
  }
40
85
  }
41
86
  function hasPersistedCreds(dataDir) {
42
- if (CRED_FILES.some((f2) => existsSync(join5(dataDir, f2)))) return true;
87
+ if (CRED_FILES.some((f2) => existsSync2(join6(dataDir, f2)))) return true;
43
88
  return hasRecoverableBackup(dataDir);
44
89
  }
45
90
  function slugify2(name) {
@@ -47,19 +92,19 @@ function slugify2(name) {
47
92
  }
48
93
  function resolveDataDir(env) {
49
94
  if (env.AV_DATA_DIR) return { dataDir: env.AV_DATA_DIR, source: "explicit" };
50
- const base = join5(env.HOME ?? "", ".agentvault", "grok-room-bridge");
51
- return { dataDir: join5(base, slugify2(env.AV_AGENT_NAME ?? "grok")), source: "per-agent" };
95
+ const base = join6(env.HOME ?? "", ".agentvault", "grok-room-bridge");
96
+ return { dataDir: join6(base, slugify2(env.AV_AGENT_NAME ?? "grok")), source: "per-agent" };
52
97
  }
53
98
  function loadConfig(env, argv = []) {
54
99
  const { dataDir, source: dataDirSource } = resolveDataDir(env);
55
- const inviteToken = (argv[0] && !argv[0].startsWith("-") ? argv[0] : "") || env.AV_INVITE_TOKEN || "";
100
+ const inviteToken = (argv[0] && !argv[0].startsWith("-") ? argv[0] : "") || env.AV_INVITE_TOKEN || readPendingInvite(dataDir) || "";
56
101
  const unknownFlags = argv.filter((a2) => a2.startsWith("-") && !KNOWN_FLAGS.has(a2));
57
102
  if (unknownFlags.length) {
58
103
  throw new Error(
59
104
  `unknown option(s): ${unknownFlags.join(", ")} \u2014 supported flags are ${[...KNOWN_FLAGS].join(", ")}`
60
105
  );
61
106
  }
62
- const workspaceDir = env.AV_WORKSPACE_DIR || join5(dirname(dataDir), "workspaces", slugify2(env.AV_AGENT_NAME ?? "grok"));
107
+ const workspaceDir = env.AV_WORKSPACE_DIR || join6(dirname(dataDir), "workspaces", slugify2(env.AV_AGENT_NAME ?? "grok"));
63
108
  const wsReal = resolve2(workspaceDir);
64
109
  const ddReal = resolve2(dataDir);
65
110
  if (wsReal === ddReal || wsReal.startsWith(ddReal + sep) || ddReal.startsWith(wsReal + sep)) {
@@ -68,8 +113,8 @@ function loadConfig(env, argv = []) {
68
113
  );
69
114
  }
70
115
  try {
71
- mkdirSync(workspaceDir, { recursive: true, mode: 448 });
72
- chmodSync(workspaceDir, 448);
116
+ mkdirSync2(workspaceDir, { recursive: true, mode: 448 });
117
+ chmodSync2(workspaceDir, 448);
73
118
  } catch (e) {
74
119
  throw new Error(
75
120
  `Failed to create/secure the agent workspace at ${workspaceDir} (override with AV_WORKSPACE_DIR): ${e.message}`
@@ -99,7 +144,7 @@ function loadConfig(env, argv = []) {
99
144
  workspaceDir,
100
145
  grokPath: env.AV_GROK_PATH || void 0,
101
146
  sandboxProfile: env.GROK_SANDBOX ?? "workspace",
102
- fenceHome: env.AV_FENCE_HOME || join5(dataDir, "fence"),
147
+ fenceHome: env.AV_FENCE_HOME || join6(dataDir, "fence"),
103
148
  apiKey: env.XAI_API_KEY || void 0,
104
149
  systemPrompt: env.AV_SYSTEM_PROMPT || void 0
105
150
  };
@@ -108,6 +153,7 @@ var INSTALL_FLAG, VERSION_FLAGS, HELP_FLAGS, KNOWN_FLAGS, CRED_FILES, BACKUP_FIL
108
153
  var init_config = __esm({
109
154
  "src/config.ts"() {
110
155
  "use strict";
156
+ init_pending_invite();
111
157
  INSTALL_FLAG = "--install";
112
158
  VERSION_FLAGS = ["--version", "-v"];
113
159
  HELP_FLAGS = ["--help", "-h"];
@@ -197,7 +243,7 @@ var init_launcher = __esm({
197
243
  });
198
244
 
199
245
  // src/service/spec.ts
200
- import { join as join9 } from "node:path";
246
+ import { join as join10 } from "node:path";
201
247
  function buildServiceSpec(cfg, opts) {
202
248
  const env = {
203
249
  AV_AGENT_NAME: cfg.agentName,
@@ -209,7 +255,7 @@ function buildServiceSpec(cfg, opts) {
209
255
  if (cfg.workspaceDir) env.AV_WORKSPACE_DIR = cfg.workspaceDir;
210
256
  if (cfg.roomFilter) env.AV_ROOM_ID = cfg.roomFilter;
211
257
  if (cfg.grokPath) env.AV_GROK_PATH = cfg.grokPath;
212
- const launcherPath = join9(cfg.dataDir, "launch-grok-bridge.sh");
258
+ const launcherPath = join10(cfg.dataDir, "launch-grok-bridge.sh");
213
259
  return {
214
260
  label: `dev.agentvault.grok-${slugify2(cfg.agentName)}`,
215
261
  programArgs: [launcherPath],
@@ -217,8 +263,8 @@ function buildServiceSpec(cfg, opts) {
217
263
  launcherScript: renderLauncher({ installPath: opts.path, entrypoint: opts.entrypoint }),
218
264
  env,
219
265
  workingDir: cfg.workspaceDir ? cfg.workspaceDir : opts.home,
220
- logOut: join9(cfg.dataDir, "logs", "grok-bridge.log"),
221
- logErr: join9(cfg.dataDir, "logs", "grok-bridge.error.log"),
266
+ logOut: join10(cfg.dataDir, "logs", "grok-bridge.log"),
267
+ logErr: join10(cfg.dataDir, "logs", "grok-bridge.error.log"),
222
268
  keepAliveUnlessCleanExit: true,
223
269
  runAtLoad: true
224
270
  };
@@ -232,7 +278,7 @@ var init_spec = __esm({
232
278
  });
233
279
 
234
280
  // src/service/launchd.ts
235
- import { dirname as dirname3, join as join10 } from "node:path";
281
+ import { dirname as dirname3, join as join11 } from "node:path";
236
282
  function esc2(s2) {
237
283
  return s2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
238
284
  }
@@ -279,7 +325,7 @@ var init_launchd = __esm({
279
325
  }
280
326
  deps;
281
327
  plistPath(label) {
282
- return join10(this.deps.home, "Library", "LaunchAgents", `${label}.plist`);
328
+ return join11(this.deps.home, "Library", "LaunchAgents", `${label}.plist`);
283
329
  }
284
330
  domain() {
285
331
  return `gui/${this.deps.uid}`;
@@ -327,7 +373,7 @@ var init_launchd = __esm({
327
373
  });
328
374
 
329
375
  // src/service/systemd.ts
330
- import { dirname as dirname4, join as join11 } from "node:path";
376
+ import { dirname as dirname4, join as join12 } from "node:path";
331
377
  function q2(s2) {
332
378
  const esc3 = s2.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t").replace(/%/g, "%%");
333
379
  return `"${esc3}"`;
@@ -364,7 +410,7 @@ var init_systemd = __esm({
364
410
  }
365
411
  deps;
366
412
  unitPath(label) {
367
- return join11(this.deps.home, ".config", "systemd", "user", `${label}.service`);
413
+ return join12(this.deps.home, ".config", "systemd", "user", `${label}.service`);
368
414
  }
369
415
  install(spec) {
370
416
  const path2 = this.unitPath(spec.label);
@@ -404,7 +450,7 @@ __export(backend_exports, {
404
450
  selectBackend: () => selectBackend
405
451
  });
406
452
  import { spawnSync } from "node:child_process";
407
- import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync2, rmSync, existsSync as existsSync3, chmodSync as chmodSync4 } from "node:fs";
453
+ import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync3, rmSync as rmSync2, existsSync as existsSync4, chmodSync as chmodSync5 } from "node:fs";
408
454
  import { userInfo } from "node:os";
409
455
  function defaultDeps() {
410
456
  return {
@@ -415,11 +461,11 @@ function defaultDeps() {
415
461
  const r2 = spawnSync(cmd, args, { encoding: "utf8" });
416
462
  return { code: r2.status ?? 1, stdout: r2.stdout ?? "" };
417
463
  },
418
- writeFile: (p2, d2) => writeFileSync2(p2, d2),
419
- mkdir: (p2) => mkdirSync4(p2, { recursive: true }),
420
- chmod: (p2, m2) => chmodSync4(p2, m2),
421
- rm: (p2) => rmSync(p2, { force: true }),
422
- exists: (p2) => existsSync3(p2)
464
+ writeFile: (p2, d2) => writeFileSync3(p2, d2),
465
+ mkdir: (p2) => mkdirSync5(p2, { recursive: true }),
466
+ chmod: (p2, m2) => chmodSync5(p2, m2),
467
+ rm: (p2) => rmSync2(p2, { force: true }),
468
+ exists: (p2) => existsSync4(p2)
423
469
  };
424
470
  }
425
471
  function selectBackend(platform, deps) {
@@ -445,7 +491,13 @@ __export(subcommand_exports, {
445
491
  maybeRunServiceSubcommand: () => maybeRunServiceSubcommand
446
492
  });
447
493
  function labelFor(env) {
448
- return `dev.agentvault.grok-${slugify2(env.AV_AGENT_NAME ?? "grok")}`;
494
+ const name = env.AV_AGENT_NAME?.trim();
495
+ if (!name) {
496
+ throw new Error(
497
+ "AV_AGENT_NAME is required \u2014 it names WHICH agent's service to act on. Re-run as: AV_AGENT_NAME=<agent-name> agentvault-grok-bridge <subcommand>"
498
+ );
499
+ }
500
+ return `dev.agentvault.grok-${slugify2(name)}`;
449
501
  }
450
502
  function maybeRunServiceSubcommand(argv, env, deps) {
451
503
  const cmd = argv[2];
@@ -466,10 +518,9 @@ function maybeRunServiceSubcommand(argv, env, deps) {
466
518
  try {
467
519
  if (cmd === "install") {
468
520
  const cfg = loadConfig(env, []);
469
- if (!hasPersistedCreds(cfg.dataDir)) {
470
- throw new Error(
471
- "no credentials found \u2014 enroll first by running the bridge once (AV_INVITE_TOKEN=\u2026 npx @agentvault/grok-bridge), then re-run install"
472
- );
521
+ const firstBoot = !hasPersistedCreds(cfg.dataDir) && !!cfg.inviteToken;
522
+ if (firstBoot) {
523
+ writePendingInvite(cfg.dataDir, cfg.inviteToken);
473
524
  }
474
525
  const spec = buildServiceSpec(cfg, {
475
526
  entrypoint,
@@ -481,7 +532,13 @@ function maybeRunServiceSubcommand(argv, env, deps) {
481
532
  });
482
533
  backend.install(spec);
483
534
  log(`installed service ${spec.label} \u2014 logs: ${spec.logErr}`);
484
- log(`check it with: agentvault-grok-bridge status`);
535
+ if (firstBoot) {
536
+ log("now APPROVE the device in AgentVault \u2014 the service is waiting to enrol");
537
+ log("if it does not connect within a minute, the log above says why");
538
+ }
539
+ log(
540
+ `check it with: AV_AGENT_NAME=${cfg.agentName} agentvault-grok-bridge status`
541
+ );
485
542
  } else if (cmd === "uninstall") {
486
543
  const label = labelFor(env);
487
544
  backend.uninstall(label);
@@ -509,6 +566,7 @@ var init_subcommand = __esm({
509
566
  "src/service/subcommand.ts"() {
510
567
  "use strict";
511
568
  init_config();
569
+ init_pending_invite();
512
570
  init_log();
513
571
  init_spec();
514
572
  init_backend();
@@ -521,12 +579,12 @@ var install_on_ready_exports = {};
521
579
  __export(install_on_ready_exports, {
522
580
  installOnReady: () => installOnReady
523
581
  });
524
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
525
- import { join as join12 } from "node:path";
582
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
583
+ import { join as join13 } from "node:path";
526
584
  function installOnReady(channel, cfg, deps) {
527
585
  const hasCreds = deps.hasCreds ?? hasPersistedCreds;
528
- const readLauncher = deps.readLauncher ?? ((p2) => existsSync4(p2) ? readFileSync3(p2, "utf8") : void 0);
529
- const fenceAuthExists = deps.fenceAuthExists ?? ((home) => existsSync4(join12(home, ".grok", "auth.json")));
586
+ const readLauncher = deps.readLauncher ?? ((p2) => existsSync5(p2) ? readFileSync4(p2, "utf8") : void 0);
587
+ const fenceAuthExists = deps.fenceAuthExists ?? ((home) => existsSync5(join13(home, ".grok", "auth.json")));
530
588
  let fired = false;
531
589
  channel.on("ready", () => {
532
590
  if (fired) return;
@@ -611,8 +669,8 @@ var init_install_on_ready = __esm({
611
669
 
612
670
  // src/index.ts
613
671
  import { spawn } from "node:child_process";
614
- import { mkdirSync as mkdirSync5 } from "node:fs";
615
- import { join as join13 } from "node:path";
672
+ import { mkdirSync as mkdirSync6 } from "node:fs";
673
+ import { join as join14 } from "node:path";
616
674
 
617
675
  // ../plugin/dist/index.js
618
676
  import * as nc from "node:crypto";
@@ -98229,28 +98287,29 @@ await init_index();
98229
98287
 
98230
98288
  // src/index.ts
98231
98289
  init_config();
98290
+ init_pending_invite();
98232
98291
  init_log();
98233
98292
 
98234
98293
  // src/fence-auth.ts
98235
- import { copyFileSync, chmodSync as chmodSync2, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "node:fs";
98236
- import { join as join6 } from "node:path";
98294
+ import { copyFileSync, chmodSync as chmodSync3, existsSync as existsSync3, mkdirSync as mkdirSync3 } from "node:fs";
98295
+ import { join as join7 } from "node:path";
98237
98296
  function seedFenceCredential(opts) {
98238
98297
  const log = opts.log ?? (() => {
98239
98298
  });
98240
- const fenceGrok = join6(opts.fenceHome, ".grok");
98241
- const fenceAuth = join6(fenceGrok, "auth.json");
98242
- if (existsSync2(fenceAuth)) {
98299
+ const fenceGrok = join7(opts.fenceHome, ".grok");
98300
+ const fenceAuth = join7(fenceGrok, "auth.json");
98301
+ if (existsSync3(fenceAuth)) {
98243
98302
  log("[grok-bridge] fence credential already present; leaving it untouched");
98244
98303
  return "already-present";
98245
98304
  }
98246
- const hostAuth = join6(opts.hostHome, ".grok", "auth.json");
98247
- if (!existsSync2(hostAuth)) {
98305
+ const hostAuth = join7(opts.hostHome, ".grok", "auth.json");
98306
+ if (!existsSync3(hostAuth)) {
98248
98307
  log("[grok-bridge] no host credential to seed (run `grok login`, or set XAI_API_KEY)");
98249
98308
  return "no-host-credential";
98250
98309
  }
98251
- mkdirSync2(fenceGrok, { recursive: true });
98310
+ mkdirSync3(fenceGrok, { recursive: true });
98252
98311
  copyFileSync(hostAuth, fenceAuth);
98253
- chmodSync2(fenceAuth, 384);
98312
+ chmodSync3(fenceAuth, 384);
98254
98313
  log("[grok-bridge] seeded fence credential from the host grok login");
98255
98314
  return "seeded";
98256
98315
  }
@@ -98551,14 +98610,14 @@ var AcpConnection = class {
98551
98610
  };
98552
98611
 
98553
98612
  // src/grok-room-plugin.ts
98554
- import { mkdirSync as mkdirSync3, writeFileSync, chmodSync as chmodSync3 } from "node:fs";
98555
- import { join as join7 } from "node:path";
98613
+ import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync2, chmodSync as chmodSync4 } from "node:fs";
98614
+ import { join as join8 } from "node:path";
98556
98615
  var SERVER_KEY = "room";
98557
98616
  var GROK_ROOM_SAY_TOOL_NAME = `${SERVER_KEY}__say`;
98558
98617
  function writeRoomPluginHttp(dir, url3) {
98559
- mkdirSync3(join7(dir, ".claude-plugin"), { recursive: true });
98560
- writeFileSync(
98561
- join7(dir, ".claude-plugin", "plugin.json"),
98618
+ mkdirSync4(join8(dir, ".claude-plugin"), { recursive: true });
98619
+ writeFileSync2(
98620
+ join8(dir, ".claude-plugin", "plugin.json"),
98562
98621
  JSON.stringify(
98563
98622
  {
98564
98623
  name: "avroom",
@@ -98570,12 +98629,12 @@ function writeRoomPluginHttp(dir, url3) {
98570
98629
  2
98571
98630
  ) + "\n"
98572
98631
  );
98573
- writeFileSync(
98574
- join7(dir, ".mcp.json"),
98632
+ writeFileSync2(
98633
+ join8(dir, ".mcp.json"),
98575
98634
  JSON.stringify({ mcpServers: { [SERVER_KEY]: { type: "http", url: url3 } } }, null, 2) + "\n",
98576
98635
  { mode: 384 }
98577
98636
  );
98578
- chmodSync3(join7(dir, ".mcp.json"), 384);
98637
+ chmodSync4(join8(dir, ".mcp.json"), 384);
98579
98638
  }
98580
98639
 
98581
98640
  // src/grok-driver.ts
@@ -98710,7 +98769,7 @@ var GrokDriver = class {
98710
98769
  };
98711
98770
 
98712
98771
  // src/grok-spawn.ts
98713
- import { join as join8 } from "node:path";
98772
+ import { join as join9 } from "node:path";
98714
98773
  function grokSpawnArgs(opts) {
98715
98774
  const args = ["agent", "--no-leader"];
98716
98775
  if (opts.model) args.push("--model", opts.model);
@@ -98719,7 +98778,7 @@ function grokSpawnArgs(opts) {
98719
98778
  const env = {
98720
98779
  PATH: process.env.PATH,
98721
98780
  HOME: opts.fenceHome,
98722
- GROK_HOME: join8(opts.fenceHome, ".grok")
98781
+ GROK_HOME: join9(opts.fenceHome, ".grok")
98723
98782
  };
98724
98783
  if (opts.apiKey) env.XAI_API_KEY = opts.apiKey;
98725
98784
  return { command: opts.grokPath ?? "grok", args, env, cwd: opts.workspaceDir };
@@ -99084,7 +99143,7 @@ async function main() {
99084
99143
  const info = parseInfoFlags(process.argv.slice(2));
99085
99144
  if (info.showVersion || info.showHelp) {
99086
99145
  const version2 = buildClientVersion2(
99087
- true ? "0.2.1" : void 0
99146
+ true ? "0.3.1" : void 0
99088
99147
  );
99089
99148
  if (info.showVersion) printLine(version2);
99090
99149
  if (info.showHelp) {
@@ -99128,8 +99187,8 @@ async function main() {
99128
99187
  const { selectBackend: selectBackend2 } = await Promise.resolve().then(() => (init_backend(), backend_exports));
99129
99188
  selectBackend2(process.platform);
99130
99189
  }
99131
- mkdirSync5(cfg.workspaceDir, { recursive: true });
99132
- mkdirSync5(cfg.fenceHome, { recursive: true });
99190
+ mkdirSync6(cfg.workspaceDir, { recursive: true });
99191
+ mkdirSync6(cfg.fenceHome, { recursive: true });
99133
99192
  seedFenceCredential({
99134
99193
  fenceHome: cfg.fenceHome,
99135
99194
  hostHome: process.env.HOME ?? "",
@@ -99142,7 +99201,7 @@ async function main() {
99142
99201
  agentName: cfg.agentName,
99143
99202
  platform: "node",
99144
99203
  clientVersion: buildClientVersion2(
99145
- true ? "0.2.1" : void 0
99204
+ true ? "0.3.1" : void 0
99146
99205
  )
99147
99206
  });
99148
99207
  channelRef = channel;
@@ -99163,7 +99222,7 @@ async function main() {
99163
99222
  },
99164
99223
  log: (m2) => logLine(m2)
99165
99224
  });
99166
- const pluginDir = join13(cfg.fenceHome, "av-room-plugin");
99225
+ const pluginDir = join14(cfg.fenceHome, "av-room-plugin");
99167
99226
  writeRoomPluginHttp(pluginDir, mcp.url);
99168
99227
  const spawnSpec = grokSpawnArgs({
99169
99228
  grokPath: cfg.grokPath,
@@ -99228,6 +99287,11 @@ async function main() {
99228
99287
  log: (m2) => logLine("[grok-bridge] " + m2),
99229
99288
  onTerminal: (_reason, o2) => void shutdown(o2.restart ? 1 : 0)
99230
99289
  });
99290
+ channel.on("ready", () => {
99291
+ if (clearPendingInviteIfConsumed(cfg.dataDir, hasPersistedCreds)) {
99292
+ logLine("[grok-bridge] enrolled \u2014 pending invite consumed and removed");
99293
+ }
99294
+ });
99231
99295
  if (cfg.installAfterEnroll) {
99232
99296
  const { installOnReady: installOnReady2 } = await Promise.resolve().then(() => (init_install_on_ready(), install_on_ready_exports));
99233
99297
  installOnReady2(channel, cfg, {
@@ -0,0 +1,24 @@
1
+ export declare function pendingInvitePath(dataDir: string): string;
2
+ /** Persist the token for the service's first boot. Owner-only, unconditionally. */
3
+ export declare function writePendingInvite(dataDir: string, token: string): void;
4
+ /** The pending token, or undefined when there is none to consume. */
5
+ export declare function readPendingInvite(dataDir: string): string | undefined;
6
+ /** Remove it. Idempotent: nothing to remove is a success, not an error. */
7
+ export declare function clearPendingInvite(dataDir: string): void;
8
+ /**
9
+ * Delete the pending invite once there is EVIDENCE it was consumed — i.e.
10
+ * credentials have actually persisted to the data dir.
11
+ *
12
+ * Timing is the whole design here. Deleting on READ (inside loadConfig) would
13
+ * throw the token away before enrolment finished, so a process that died in
14
+ * between would leave a service that can never enrol and a customer whose
15
+ * single-use invite is gone. Never deleting leaves a credential on disk long
16
+ * after it is useless.
17
+ *
18
+ * `credsExist` is injected so the caller supplies `hasPersistedCreds` and this
19
+ * module stays free of a config import cycle.
20
+ *
21
+ * @returns true when a file was actually removed.
22
+ */
23
+ export declare function clearPendingInviteIfConsumed(dataDir: string, credsExist: (dataDir: string) => boolean): boolean;
24
+ //# sourceMappingURL=pending-invite.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"subcommand.d.ts","sourceRoot":"","sources":["../../src/service/subcommand.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAQD;;uFAEuF;AACvF,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAoFT"}
1
+ {"version":3,"file":"subcommand.d.ts","sourceRoot":"","sources":["../../src/service/subcommand.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAkCD;;uFAEuF;AACvF,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAkHT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentvault/grok-bridge",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "description": "AgentVault Grok Bridge — daemon bridging a Grok agent into E2E-encrypted AgentVault direct messages and rooms.",
6
6
  "main": "dist/index.js",