@strideops/bridge 0.1.3 → 0.1.5

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.
@@ -1,23 +1,31 @@
1
1
  #!/usr/bin/env node
2
- import { BRIDGE_DIR, log, logError } from './chunk-GBLMB3XB.js';
2
+ import { BRIDGE_DIR, log, logWarn, logError } from './chunk-6LRDE2ZS.js';
3
3
  import { execFileSync } from 'child_process';
4
- import { join } from 'path';
4
+ import { join, dirname } from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
 
7
7
  var TASK_NAME = "StrideBridge";
8
+ var RUN_KEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
8
9
  function cliEntryPath() {
9
- return fileURLToPath(import.meta.url);
10
+ return join(dirname(fileURLToPath(import.meta.url)), "cli.js");
10
11
  }
11
12
  function runSchtasks(args) {
12
13
  return execFileSync("schtasks", args, { encoding: "utf-8" });
13
14
  }
15
+ function runReg(args) {
16
+ return execFileSync("reg", args, { encoding: "utf-8" });
17
+ }
18
+ function startCommand() {
19
+ const logFile = join(BRIDGE_DIR, "daemon.log");
20
+ return `cmd /c ""${process.execPath}" "${cliEntryPath()}" start >> "${logFile}" 2>&1"`;
21
+ }
14
22
  function autostartInstall() {
15
23
  if (process.platform !== "win32") {
16
24
  printPosixInstructions();
17
25
  return;
18
26
  }
19
27
  const logFile = join(BRIDGE_DIR, "daemon.log");
20
- const command = `cmd /c ""${process.execPath}" "${cliEntryPath()}" start >> "${logFile}" 2>&1"`;
28
+ const command = startCommand();
21
29
  try {
22
30
  runSchtasks([
23
31
  "/Create",
@@ -35,9 +43,17 @@ function autostartInstall() {
35
43
  log(`Task Scheduler task "${TASK_NAME}" installed \u2014 the daemon starts at logon.`);
36
44
  log(`Logs: ${logFile}`);
37
45
  log(`Start it now without rebooting: schtasks /Run /TN ${TASK_NAME}`);
38
- } catch (err) {
39
- logError("Failed to create scheduled task (try an elevated terminal)", err);
40
- process.exitCode = 1;
46
+ } catch {
47
+ logWarn("Task Scheduler denied (non-elevated terminal) \u2014 using registry Run key instead.");
48
+ try {
49
+ runReg(["add", RUN_KEY, "/v", TASK_NAME, "/t", "REG_SZ", "/d", command, "/f"]);
50
+ log(`Registry autostart installed \u2014 the daemon starts at login.`);
51
+ log(`Logs: ${logFile}`);
52
+ log(`Start it now without rebooting: stride-bridge start (or log out and back in)`);
53
+ } catch (err) {
54
+ logError("Failed to install autostart (schtasks AND registry both denied)", err);
55
+ process.exitCode = 1;
56
+ }
41
57
  }
42
58
  }
43
59
  function autostartRemove() {
@@ -45,12 +61,21 @@ function autostartRemove() {
45
61
  log("Autostart install/remove is Windows-only; on macOS/Linux manage your launchd/systemd unit directly.");
46
62
  return;
47
63
  }
64
+ let removed = false;
48
65
  try {
49
66
  runSchtasks(["/Delete", "/F", "/TN", TASK_NAME]);
50
67
  log(`Task Scheduler task "${TASK_NAME}" removed.`);
51
- } catch (err) {
52
- logError(`Failed to remove task "${TASK_NAME}" (was it installed?)`, err);
53
- process.exitCode = 1;
68
+ removed = true;
69
+ } catch {
70
+ }
71
+ try {
72
+ runReg(["delete", RUN_KEY, "/v", TASK_NAME, "/f"]);
73
+ log(`Registry autostart entry removed.`);
74
+ removed = true;
75
+ } catch {
76
+ }
77
+ if (!removed) {
78
+ log(`No autostart found (neither scheduled task nor registry entry).`);
54
79
  }
55
80
  }
56
81
  function autostartStatus() {
@@ -60,10 +85,17 @@ function autostartStatus() {
60
85
  }
61
86
  try {
62
87
  const out = runSchtasks(["/Query", "/TN", TASK_NAME]);
63
- log(`Task "${TASK_NAME}" is installed:`);
88
+ log(`Task "${TASK_NAME}" is installed (Task Scheduler):`);
89
+ process.stdout.write(out);
90
+ return;
91
+ } catch {
92
+ }
93
+ try {
94
+ const out = runReg(["query", RUN_KEY, "/v", TASK_NAME]);
95
+ log(`Registry autostart is installed:`);
64
96
  process.stdout.write(out);
65
97
  } catch {
66
- log(`Task "${TASK_NAME}" is not installed. Run: stride-bridge autostart install`);
98
+ log(`Autostart is not installed. Run: stride-bridge autostart install`);
67
99
  }
68
100
  }
69
101
  function printPosixInstructions() {
@@ -74,5 +106,5 @@ function printPosixInstructions() {
74
106
  }
75
107
 
76
108
  export { autostartInstall, autostartRemove, autostartStatus };
77
- //# sourceMappingURL=autostart-77BPPTEG.js.map
78
- //# sourceMappingURL=autostart-77BPPTEG.js.map
109
+ //# sourceMappingURL=autostart-ASW5MDQS.js.map
110
+ //# sourceMappingURL=autostart-ASW5MDQS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/autostart.ts"],"names":[],"mappings":"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","file":"autostart-ASW5MDQS.js","sourcesContent":["/**\n * autostart.ts — Survive reboots (Phase 2).\n *\n * Windows: registers a Task Scheduler task that runs `stride-bridge start`\n * at user logon (the cortex-os Windows lesson: `pm2 startup` is broken on\n * Windows; a logon task in user context is the reliable path).\n * macOS/Linux: prints the launchd/systemd instructions instead — most\n * customers are Windows-first, and a wrong unit file is worse than a recipe.\n */\n\nimport { execFileSync } from \"node:child_process\"\nimport { dirname, join } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { BRIDGE_DIR } from \"./config.js\"\nimport { log, logError, logWarn } from \"./log.js\"\n\nconst TASK_NAME = \"StrideBridge\"\nconst RUN_KEY = \"HKCU\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\"\n\nfunction cliEntryPath(): string {\n // tsup code-splits the bundle, so import.meta.url may resolve to a CHUNK\n // (dist/autostart-XXXX.js) — point explicitly at cli.js in the same dir.\n return join(dirname(fileURLToPath(import.meta.url)), \"cli.js\")\n}\n\nfunction runSchtasks(args: string[]): string {\n return execFileSync(\"schtasks\", args, { encoding: \"utf-8\" })\n}\n\nfunction runReg(args: string[]): string {\n return execFileSync(\"reg\", args, { encoding: \"utf-8\" })\n}\n\nfunction startCommand(): string {\n const logFile = join(BRIDGE_DIR, \"daemon.log\")\n return `cmd /c \"\"${process.execPath}\" \"${cliEntryPath()}\" start >> \"${logFile}\" 2>&1\"`\n}\n\nexport function autostartInstall(): void {\n if (process.platform !== \"win32\") {\n printPosixInstructions()\n return\n }\n const logFile = join(BRIDGE_DIR, \"daemon.log\")\n const command = startCommand()\n try {\n runSchtasks([\n \"/Create\",\n \"/F\", // overwrite if exists\n \"/TN\", TASK_NAME,\n \"/TR\", command,\n \"/SC\", \"ONLOGON\",\n \"/RL\", \"LIMITED\",\n ])\n log(`Task Scheduler task \"${TASK_NAME}\" installed — the daemon starts at logon.`)\n log(`Logs: ${logFile}`)\n log(`Start it now without rebooting: schtasks /Run /TN ${TASK_NAME}`)\n } catch {\n // Non-elevated terminals are denied schtasks on some Windows editions —\n // fall back to the HKCU Run key (user-context, no elevation needed).\n logWarn(\"Task Scheduler denied (non-elevated terminal) — using registry Run key instead.\")\n try {\n runReg([\"add\", RUN_KEY, \"/v\", TASK_NAME, \"/t\", \"REG_SZ\", \"/d\", command, \"/f\"])\n log(`Registry autostart installed — the daemon starts at login.`)\n log(`Logs: ${logFile}`)\n log(`Start it now without rebooting: stride-bridge start (or log out and back in)`)\n } catch (err) {\n logError(\"Failed to install autostart (schtasks AND registry both denied)\", err)\n process.exitCode = 1\n }\n }\n}\n\nexport function autostartRemove(): void {\n if (process.platform !== \"win32\") {\n log(\"Autostart install/remove is Windows-only; on macOS/Linux manage your launchd/systemd unit directly.\")\n return\n }\n let removed = false\n try {\n runSchtasks([\"/Delete\", \"/F\", \"/TN\", TASK_NAME])\n log(`Task Scheduler task \"${TASK_NAME}\" removed.`)\n removed = true\n } catch {\n // not installed as a task — try the registry fallback below\n }\n try {\n runReg([\"delete\", RUN_KEY, \"/v\", TASK_NAME, \"/f\"])\n log(`Registry autostart entry removed.`)\n removed = true\n } catch {\n // not installed as a registry entry either\n }\n if (!removed) {\n log(`No autostart found (neither scheduled task nor registry entry).`)\n }\n}\n\nexport function autostartStatus(): void {\n if (process.platform !== \"win32\") {\n printPosixInstructions()\n return\n }\n try {\n const out = runSchtasks([\"/Query\", \"/TN\", TASK_NAME])\n log(`Task \"${TASK_NAME}\" is installed (Task Scheduler):`)\n process.stdout.write(out)\n return\n } catch {\n // fall through to registry check\n }\n try {\n const out = runReg([\"query\", RUN_KEY, \"/v\", TASK_NAME])\n log(`Registry autostart is installed:`)\n process.stdout.write(out)\n } catch {\n log(`Autostart is not installed. Run: stride-bridge autostart install`)\n }\n}\n\nfunction printPosixInstructions(): void {\n log(\"Autostart auto-install is currently Windows-only. On macOS/Linux:\")\n log(` macOS — create a LaunchAgent running: ${process.execPath} ${cliEntryPath()} start`)\n log(` Linux — create a systemd user unit: ExecStart=${process.execPath} ${cliEntryPath()} start`)\n log(\" then: systemctl --user enable --now stride-bridge\")\n}\n"]}
@@ -4,6 +4,12 @@ import { homedir } from 'os';
4
4
  import { existsSync, chmodSync, readFileSync, mkdirSync, copyFileSync, writeFileSync, renameSync, unlinkSync } from 'fs';
5
5
  import { randomBytes } from 'crypto';
6
6
 
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
7
13
  function stripBom(s) {
8
14
  return s.charCodeAt(0) === 65279 ? s.slice(1) : s;
9
15
  }
@@ -90,6 +96,6 @@ function logWarn(message) {
90
96
  console.warn(`[stride-bridge] ${ts} WARN ${message}`);
91
97
  }
92
98
 
93
- export { AGENTS_DIR, BRIDGE_DIR, CONFIG_PATH, PENDING_REPORTS_PATH, isConfigured, log, logError, logWarn, readConfig, readJsonSafe, requireConfig, writeConfig, writeJsonAtomic };
94
- //# sourceMappingURL=chunk-GBLMB3XB.js.map
95
- //# sourceMappingURL=chunk-GBLMB3XB.js.map
99
+ export { AGENTS_DIR, BRIDGE_DIR, CONFIG_PATH, PENDING_REPORTS_PATH, __require, isConfigured, log, logError, logWarn, readConfig, readJsonSafe, requireConfig, writeConfig, writeJsonAtomic };
100
+ //# sourceMappingURL=chunk-6LRDE2ZS.js.map
101
+ //# sourceMappingURL=chunk-6LRDE2ZS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/state.ts","../src/config.ts","../src/log.ts"],"names":["join","existsSync"],"mappings":"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","file":"chunk-6LRDE2ZS.js","sourcesContent":["/**\n * state.ts — BOM-safe file reading + atomic JSON write utilities.\n *\n * BOM stripping ported from cortex-os/src/utils/strip-bom.ts (MIT, Cortext LLC).\n * Atomic write ported from cortex-os/src/utils/atomic.ts (MIT, Cortext LLC).\n *\n * Windows PowerShell Out-File / Set-Content and many editors write UTF-8 BOM\n * (EF BB BF / U+FEFF). JSON.parse and ^ anchored regex silently fail on BOM\n * bytes. Always strip before parsing any user-editable file.\n */\n\nimport {\n readFileSync,\n writeFileSync,\n renameSync,\n mkdirSync,\n existsSync,\n copyFileSync,\n unlinkSync,\n} from \"node:fs\"\nimport { dirname, join } from \"node:path\"\nimport { randomBytes } from \"node:crypto\"\n\n// ---------------------------------------------------------------------------\n// BOM handling (ported from cortex-os strip-bom.ts)\n// ---------------------------------------------------------------------------\n\n/**\n * Strip a leading UTF-8 BOM (U+FEFF) if present.\n * Fast path: single charCodeAt(0) check; no allocation when no BOM.\n */\nexport function stripBom(s: string): string {\n return s.charCodeAt(0) === 0xfeff ? s.slice(1) : s\n}\n\n/**\n * Read a UTF-8 text file and strip any leading BOM.\n * Use this for all config / JSON files that may have been written by Windows tools.\n */\nexport function readFileTextStripped(path: string): string {\n return stripBom(readFileSync(path, \"utf-8\"))\n}\n\n// ---------------------------------------------------------------------------\n// Atomic write (ported from cortex-os atomic.ts)\n// ---------------------------------------------------------------------------\n\n/**\n * Atomically write data to filePath by writing to a temp file first, then\n * renaming. rename() is atomic on the same filesystem.\n *\n * When keepBak is true, the current file is copied to <filePath>.bak before\n * overwriting. Best-effort — backup failures never block the main write.\n */\nexport function atomicWriteSync(\n filePath: string,\n data: string,\n keepBak = false,\n): void {\n const dir = dirname(filePath)\n mkdirSync(dir, { recursive: true })\n\n if (keepBak && existsSync(filePath)) {\n try {\n copyFileSync(filePath, filePath + \".bak\")\n } catch {\n // Ignore backup errors — do not block the main write.\n }\n }\n\n const tmpPath = join(dir, `.tmp.${randomBytes(6).toString(\"hex\")}`)\n try {\n writeFileSync(tmpPath, data, { encoding: \"utf-8\", mode: 0o600 })\n renameSync(tmpPath, filePath)\n } catch (err) {\n try {\n unlinkSync(tmpPath)\n } catch {\n // Ignore cleanup errors.\n }\n throw err\n }\n}\n\n// ---------------------------------------------------------------------------\n// JSON helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Read and parse a JSON file, stripping BOM first.\n * Returns null if the file does not exist or cannot be parsed.\n */\nexport function readJsonSafe<T>(filePath: string): T | null {\n if (!existsSync(filePath)) return null\n try {\n const text = readFileTextStripped(filePath)\n return JSON.parse(text) as T\n } catch {\n return null\n }\n}\n\n/**\n * Atomically write a value as pretty-printed JSON.\n */\nexport function writeJsonAtomic(filePath: string, value: unknown): void {\n atomicWriteSync(filePath, JSON.stringify(value, null, 2))\n}\n","/**\n * config.ts — Bridge configuration: read/write ~/.stride-bridge/config.json.\n *\n * The config file is written atomically and chmod 600 on POSIX to prevent\n * other users from reading the bridge token.\n */\n\nimport { join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { chmodSync, existsSync } from \"node:fs\"\nimport { readJsonSafe, writeJsonAtomic } from \"./state.js\"\n\nexport const BRIDGE_DIR = join(homedir(), \".stride-bridge\")\nexport const CONFIG_PATH = join(BRIDGE_DIR, \"config.json\")\nexport const PENDING_REPORTS_PATH = join(BRIDGE_DIR, \"pending-reports.json\")\nexport const AGENTS_DIR = join(BRIDGE_DIR, \"agents\")\n\nexport interface BridgeConfig {\n apiBaseUrl: string\n /** Opaque bearer token issued by the server during pairing. Never log. */\n bridgeToken: string\n bridgeId: string\n orgId: string\n bridgeName: string\n /**\n * How the agent authenticates with Anthropic.\n * \"claude_login\" = uses the local Claude Code OAuth session (Phase 1).\n * \"org_api_key\" = org-provided key injected into env (TODO Phase 2).\n */\n authMode: \"claude_login\" | \"org_api_key\"\n}\n\n/**\n * Read the config from disk. Returns null if not yet configured.\n */\nexport function readConfig(): BridgeConfig | null {\n return readJsonSafe<BridgeConfig>(CONFIG_PATH)\n}\n\n/**\n * Persist config atomically. On POSIX, chmod 600 after write so only the\n * current user can read the bridge token.\n */\nexport function writeConfig(config: BridgeConfig): void {\n writeJsonAtomic(CONFIG_PATH, config)\n if (process.platform !== \"win32\") {\n try {\n chmodSync(CONFIG_PATH, 0o600)\n } catch {\n // Non-fatal — best effort.\n }\n }\n}\n\n/**\n * Require a valid config or exit with a clear error message.\n */\nexport function requireConfig(): BridgeConfig {\n const config = readConfig()\n if (!config) {\n console.error(\n \"[stride-bridge] Not connected. Run `stride-bridge connect <PAIRING_CODE>` first.\",\n )\n process.exit(1)\n }\n return config\n}\n\n/**\n * Check whether a config file exists (does not validate contents).\n */\nexport function isConfigured(): boolean {\n return existsSync(CONFIG_PATH)\n}\n","/**\n * log.ts — Minimal structured logging with timestamps.\n *\n * All log lines are prefixed with \"[stride-bridge] <ISO timestamp>\" so they\n * are easy to grep in process manager output. Secrets (bridgeToken,\n * hookSecret) must NEVER be passed to these functions.\n */\n\nexport function log(message: string): void {\n const ts = new Date().toISOString()\n console.log(`[stride-bridge] ${ts} ${message}`)\n}\n\nexport function logError(message: string, err?: unknown): void {\n const ts = new Date().toISOString()\n const detail =\n err instanceof Error ? err.message : err !== undefined ? String(err) : \"\"\n console.error(`[stride-bridge] ${ts} ERROR ${message}${detail ? \": \" + detail : \"\"}`)\n}\n\nexport function logWarn(message: string): void {\n const ts = new Date().toISOString()\n console.warn(`[stride-bridge] ${ts} WARN ${message}`)\n}\n"]}