@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.
- package/dist/{autostart-77BPPTEG.js → autostart-ASW5MDQS.js} +46 -14
- package/dist/autostart-ASW5MDQS.js.map +1 -0
- package/dist/{chunk-GBLMB3XB.js → chunk-6LRDE2ZS.js} +9 -3
- package/dist/chunk-6LRDE2ZS.js.map +1 -0
- package/dist/cli.js +1293 -187
- package/dist/cli.js.map +1 -1
- package/package.json +7 -2
- package/dist/autostart-77BPPTEG.js.map +0 -1
- package/dist/chunk-GBLMB3XB.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strideops/bridge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Stride Bridge daemon — runs local Claude Code agents for StrideOps Build",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,10 +21,15 @@
|
|
|
21
21
|
"test:watch": "vitest"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"commander": "^12.1.0"
|
|
24
|
+
"commander": "^12.1.0",
|
|
25
|
+
"ws": "^8.21.0"
|
|
26
|
+
},
|
|
27
|
+
"optionalDependencies": {
|
|
28
|
+
"node-pty": "^1.1.0"
|
|
25
29
|
},
|
|
26
30
|
"devDependencies": {
|
|
27
31
|
"@types/node": "^20.17.0",
|
|
32
|
+
"@types/ws": "^8.5.12",
|
|
28
33
|
"tsup": "^8.3.0",
|
|
29
34
|
"typescript": "^5.6.0",
|
|
30
35
|
"vitest": "^2.1.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/autostart.ts"],"names":[],"mappings":"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","file":"autostart-77BPPTEG.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 { join } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { BRIDGE_DIR } from \"./config.js\"\nimport { log, logError } from \"./log.js\"\n\nconst TASK_NAME = \"StrideBridge\"\n\nfunction cliEntryPath(): string {\n // dist/cli.js — this module is bundled into it, so resolve self.\n return fileURLToPath(import.meta.url)\n}\n\nfunction runSchtasks(args: string[]): string {\n return execFileSync(\"schtasks\", args, { encoding: \"utf-8\" })\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 // cmd wrapper so stdout/stderr land in a log file the user can read.\n const command = `cmd /c \"\"${process.execPath}\" \"${cliEntryPath()}\" start >> \"${logFile}\" 2>&1\"`\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 (err) {\n logError(\"Failed to create scheduled task (try an elevated terminal)\", err)\n process.exitCode = 1\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 try {\n runSchtasks([\"/Delete\", \"/F\", \"/TN\", TASK_NAME])\n log(`Task Scheduler task \"${TASK_NAME}\" removed.`)\n } catch (err) {\n logError(`Failed to remove task \"${TASK_NAME}\" (was it installed?)`, err)\n process.exitCode = 1\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:`)\n process.stdout.write(out)\n } catch {\n log(`Task \"${TASK_NAME}\" 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"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/state.ts","../src/config.ts","../src/log.ts"],"names":["join","existsSync"],"mappings":"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","file":"chunk-GBLMB3XB.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"]}
|