@hehanlin/open-agent-bridge 0.6.3

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 (65) hide show
  1. package/README.md +36 -0
  2. package/dist/adapters/acpAdapter.d.ts +45 -0
  3. package/dist/adapters/acpAdapter.js +171 -0
  4. package/dist/adapters/acpAdapter.js.map +1 -0
  5. package/dist/adapters/adapter.d.ts +50 -0
  6. package/dist/adapters/adapter.js +2 -0
  7. package/dist/adapters/adapter.js.map +1 -0
  8. package/dist/adapters/registry.d.ts +7 -0
  9. package/dist/adapters/registry.js +34 -0
  10. package/dist/adapters/registry.js.map +1 -0
  11. package/dist/agent/agentManager.d.ts +45 -0
  12. package/dist/agent/agentManager.js +110 -0
  13. package/dist/agent/agentManager.js.map +1 -0
  14. package/dist/cli.d.ts +13 -0
  15. package/dist/cli.js +178 -0
  16. package/dist/cli.js.map +1 -0
  17. package/dist/config.d.ts +15 -0
  18. package/dist/config.js +39 -0
  19. package/dist/config.js.map +1 -0
  20. package/dist/detect/acpProbe.d.ts +5 -0
  21. package/dist/detect/acpProbe.js +61 -0
  22. package/dist/detect/acpProbe.js.map +1 -0
  23. package/dist/detect/frameworkDetector.d.ts +30 -0
  24. package/dist/detect/frameworkDetector.js +88 -0
  25. package/dist/detect/frameworkDetector.js.map +1 -0
  26. package/dist/frontier/frontierClient.d.ts +37 -0
  27. package/dist/frontier/frontierClient.js +103 -0
  28. package/dist/frontier/frontierClient.js.map +1 -0
  29. package/dist/frontier/frontierKey.d.ts +19 -0
  30. package/dist/frontier/frontierKey.js +45 -0
  31. package/dist/frontier/frontierKey.js.map +1 -0
  32. package/dist/frontier/health.d.ts +18 -0
  33. package/dist/frontier/health.js +29 -0
  34. package/dist/frontier/health.js.map +1 -0
  35. package/dist/frontier/watchdog.d.ts +23 -0
  36. package/dist/frontier/watchdog.js +47 -0
  37. package/dist/frontier/watchdog.js.map +1 -0
  38. package/dist/fsx/localFs.d.ts +15 -0
  39. package/dist/fsx/localFs.js +29 -0
  40. package/dist/fsx/localFs.js.map +1 -0
  41. package/dist/fsx/safePath.d.ts +1 -0
  42. package/dist/fsx/safePath.js +44 -0
  43. package/dist/fsx/safePath.js.map +1 -0
  44. package/dist/hub/asyncQueue.d.ts +6 -0
  45. package/dist/hub/asyncQueue.js +30 -0
  46. package/dist/hub/asyncQueue.js.map +1 -0
  47. package/dist/hub/hub.d.ts +55 -0
  48. package/dist/hub/hub.js +328 -0
  49. package/dist/hub/hub.js.map +1 -0
  50. package/dist/install/autostart.d.ts +20 -0
  51. package/dist/install/autostart.js +76 -0
  52. package/dist/install/autostart.js.map +1 -0
  53. package/dist/mock/mockRun.d.ts +9 -0
  54. package/dist/mock/mockRun.js +94 -0
  55. package/dist/mock/mockRun.js.map +1 -0
  56. package/dist/store/seq.d.ts +12 -0
  57. package/dist/store/seq.js +55 -0
  58. package/dist/store/seq.js.map +1 -0
  59. package/dist/store/store.d.ts +26 -0
  60. package/dist/store/store.js +88 -0
  61. package/dist/store/store.js.map +1 -0
  62. package/dist/types.d.ts +36 -0
  63. package/dist/types.js +9 -0
  64. package/dist/types.js.map +1 -0
  65. package/package.json +32 -0
package/dist/cli.js ADDED
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env node
2
+ import { execFile } from 'node:child_process';
3
+ import { realpathSync } from 'node:fs';
4
+ import { appendFile, mkdir, writeFile } from 'node:fs/promises';
5
+ import { createRequire } from 'node:module';
6
+ import { hostname, homedir } from 'node:os';
7
+ import { join } from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+ import { FWS } from '@byted/frontier-web-sdk';
10
+ import WebSocket from 'ws';
11
+ import { AgentManager } from './agent/agentManager.js';
12
+ import { AcpAdapter } from './adapters/acpAdapter.js';
13
+ import { recipeFor } from './adapters/registry.js';
14
+ import { loadConfig } from './config.js';
15
+ import { FrameworkDetector } from './detect/frameworkDetector.js';
16
+ import { LocalFs } from './fsx/localFs.js';
17
+ import { exchangeFrontierKey } from './frontier/frontierKey.js';
18
+ import { FrontierClient } from './frontier/frontierClient.js';
19
+ import { HealthReporter } from './frontier/health.js';
20
+ import { Watchdog } from './frontier/watchdog.js';
21
+ import { Hub } from './hub/hub.js';
22
+ import { installAutostart } from './install/autostart.js';
23
+ import { runMock } from './mock/mockRun.js';
24
+ import { SeqAllocator } from './store/seq.js';
25
+ import { Store } from './store/store.js';
26
+ export function parseCliArgs(argv) {
27
+ const args = { detect: false, installAutostart: false, mockRun: false, dryRun: false, help: false, version: false };
28
+ for (let i = 0; i < argv.length; i += 1) {
29
+ const arg = argv[i];
30
+ if (arg === '--token') {
31
+ args.token = argv[++i];
32
+ }
33
+ else if (arg.startsWith('--token=')) {
34
+ args.token = arg.slice('--token='.length);
35
+ }
36
+ else if (arg === '--server') {
37
+ args.server = argv[++i];
38
+ }
39
+ else if (arg.startsWith('--server=')) {
40
+ args.server = arg.slice('--server='.length);
41
+ }
42
+ else if (arg === '--detect') {
43
+ args.detect = true;
44
+ }
45
+ else if (arg === '--install-autostart') {
46
+ args.installAutostart = true;
47
+ }
48
+ else if (arg === '--mock-run') {
49
+ args.mockRun = true;
50
+ }
51
+ else if (arg === '--dry-run') {
52
+ args.dryRun = true;
53
+ }
54
+ else if (arg === '--help' || arg === '-h') {
55
+ args.help = true;
56
+ }
57
+ else if (arg === '--version' || arg === '-v') {
58
+ args.version = true;
59
+ }
60
+ }
61
+ return args;
62
+ }
63
+ export async function main(argv = process.argv.slice(2)) {
64
+ const cli = parseCliArgs(argv);
65
+ if (cli.help) {
66
+ console.log(helpText());
67
+ return;
68
+ }
69
+ if (cli.version) {
70
+ console.log(packageVersion());
71
+ return;
72
+ }
73
+ const configArgv = cli.server ? ['--server', cli.server] : [];
74
+ const config = loadConfig(process.env, configArgv);
75
+ const store = new Store(config.oaHome);
76
+ const detector = new FrameworkDetector({ exec: execCommand });
77
+ if (cli.mockRun) {
78
+ await runMock();
79
+ return;
80
+ }
81
+ if (cli.installAutostart) {
82
+ const result = await installAutostart({ platform: process.platform, homedir: homedir(), writeFile }, { dryRun: cli.dryRun });
83
+ console.log(cli.dryRun ? result.content : result.hint);
84
+ return;
85
+ }
86
+ const frameworks = await detector.detect();
87
+ if (cli.detect) {
88
+ console.log(JSON.stringify({ frameworks }, null, 2));
89
+ return;
90
+ }
91
+ if (cli.token) {
92
+ await store.saveDeviceToken(cli.token);
93
+ }
94
+ const deviceToken = cli.token ?? (await store.loadDeviceToken());
95
+ if (!deviceToken) {
96
+ throw new Error('missing device token; create one from the cloud device/create flow, then run: npx @hehanlin/open-agent-bridge --token=<device_token>');
97
+ }
98
+ await mkdir(join(config.oaHome, 'logs'), { recursive: true });
99
+ const creds = await exchangeFrontierKey({ fetchImpl: fetch }, { serverBase: config.serverBase, deviceToken, hostname: hostname(), platform: process.platform, frameworks });
100
+ const client = new FrontierClient({ FwsCtor: FWS, wsImpl: WebSocket, now: Date.now }, creds, {
101
+ platform: process.platform,
102
+ rpcMethod: config.rpcMethod
103
+ });
104
+ const agents = new AgentManager({ store, detector });
105
+ const seq = new SeqAllocator(join(config.oaHome, 'seq'), config.seqBlockSize);
106
+ const hub = new Hub({
107
+ client,
108
+ agents,
109
+ store,
110
+ seq,
111
+ adapterFactory: (framework, ctx) => new AcpAdapter({
112
+ recipe: recipeFor(framework, ctx),
113
+ localFs: new LocalFs(ctx.workspace),
114
+ logSink: (line) => void appendFile(join(config.oaHome, 'logs', 'daemon.log'), `${line}\n`)
115
+ }),
116
+ fetchImpl: fetch,
117
+ config
118
+ });
119
+ const health = new HealthReporter({ send: (msg) => client.send(msg), agentsProvider: () => hub.agentStatuses() }, { intervalMs: config.healthIntervalMs });
120
+ const watchdog = new Watchdog({ now: Date.now, exit: (code) => process.exit(code), env: process.env }, {
121
+ softMs: config.watchdogSoftMs,
122
+ hardMs: config.watchdogHardMs,
123
+ tickMs: 10_000
124
+ }, client);
125
+ await agents.reviveAll();
126
+ hub.start();
127
+ client.connect();
128
+ health.start();
129
+ watchdog.start();
130
+ const shutdown = async () => {
131
+ health.stop();
132
+ watchdog.stop();
133
+ await hub.stopAll();
134
+ client.close();
135
+ };
136
+ process.once('SIGINT', () => void shutdown().finally(() => process.exit(0)));
137
+ process.once('SIGTERM', () => void shutdown().finally(() => process.exit(0)));
138
+ }
139
+ function helpText() {
140
+ return `Usage: open-agent-bridge [--token=<device_token>] [--server=<base>] [--detect] [--mock-run] [--install-autostart] [--dry-run]
141
+
142
+ Options:
143
+ --token Device token from the cloud device/create flow
144
+ --server Override openAgent server base URL
145
+ --detect Print locally detected frameworks and exit
146
+ --mock-run Run one mocked daemon turn without Frontier or token
147
+ --install-autostart Render/install launchd or systemd user autostart
148
+ --dry-run Print autostart file without writing
149
+ --help Show this help
150
+ --version Print package version`;
151
+ }
152
+ function packageVersion() {
153
+ const require = createRequire(import.meta.url);
154
+ return require('../package.json').version;
155
+ }
156
+ const execCommand = (cmd, args, opts) => new Promise((resolve) => {
157
+ execFile(cmd, args, { timeout: opts?.timeoutMs ?? 5_000 }, (error, stdout, stderr) => {
158
+ resolve({ code: error ? (typeof error.code === 'number' ? error.code : 1) : 0, stdout, stderr });
159
+ });
160
+ });
161
+ if (isEntrypoint()) {
162
+ main().catch((error) => {
163
+ console.error(error instanceof Error ? error.message : error);
164
+ process.exit(1);
165
+ });
166
+ }
167
+ function isEntrypoint() {
168
+ if (!process.argv[1]) {
169
+ return false;
170
+ }
171
+ try {
172
+ return realpathSync(process.argv[1]) === fileURLToPath(import.meta.url);
173
+ }
174
+ catch {
175
+ return false;
176
+ }
177
+ }
178
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface Config {
2
+ serverBase: string;
3
+ oaHome: string;
4
+ maxTurnMs: number;
5
+ firstUpdateMs: number;
6
+ approvalMaxMs: number;
7
+ healthIntervalMs: number;
8
+ watchdogSoftMs: number;
9
+ watchdogHardMs: number;
10
+ seqBlockSize: number;
11
+ idleExitMs: number;
12
+ rpcMethod: number;
13
+ }
14
+ export declare const DEFAULT_SERVER_BASE = "https://open-agent.bytedance.net";
15
+ export declare function loadConfig(env?: NodeJS.ProcessEnv, argv?: string[]): Config;
package/dist/config.js ADDED
@@ -0,0 +1,39 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ export const DEFAULT_SERVER_BASE = 'https://open-agent.bytedance.net';
4
+ function numberFromEnv(env, key, fallback) {
5
+ const value = env[key];
6
+ if (value === undefined || value === '') {
7
+ return fallback;
8
+ }
9
+ const parsed = Number(value);
10
+ return Number.isFinite(parsed) ? parsed : fallback;
11
+ }
12
+ function parseServerArg(argv) {
13
+ for (let i = 0; i < argv.length; i += 1) {
14
+ const arg = argv[i];
15
+ if (arg === '--server') {
16
+ return argv[i + 1];
17
+ }
18
+ if (arg.startsWith('--server=')) {
19
+ return arg.slice('--server='.length);
20
+ }
21
+ }
22
+ return undefined;
23
+ }
24
+ export function loadConfig(env = process.env, argv = process.argv.slice(2)) {
25
+ return {
26
+ serverBase: parseServerArg(argv) ?? env.OA_SERVER_BASE ?? DEFAULT_SERVER_BASE,
27
+ oaHome: env.OA_HOME ?? join(homedir(), '.open-agent-bridge'),
28
+ maxTurnMs: numberFromEnv(env, 'OA_MAX_MS', 3_600_000),
29
+ firstUpdateMs: numberFromEnv(env, 'OA_FIRST_UPDATE_MS', 600_000),
30
+ approvalMaxMs: numberFromEnv(env, 'OA_APPROVAL_MAX_MS', 86_400_000),
31
+ healthIntervalMs: numberFromEnv(env, 'OA_HEALTH_INTERVAL_MS', 10_000),
32
+ watchdogSoftMs: numberFromEnv(env, 'OA_WATCHDOG_SOFT_MS', 120_000),
33
+ watchdogHardMs: numberFromEnv(env, 'OA_WATCHDOG_HARD_MS', 900_000),
34
+ seqBlockSize: numberFromEnv(env, 'OA_SEQ_BLOCK_SIZE', 200),
35
+ idleExitMs: numberFromEnv(env, 'OA_IDLE_MS', 300_000),
36
+ rpcMethod: numberFromEnv(env, 'OA_RPC_METHOD', 1)
37
+ };
38
+ }
39
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAgBjC,MAAM,CAAC,MAAM,mBAAmB,GAAG,kCAAkC,CAAC;AAEtE,SAAS,aAAa,CAAC,GAAsB,EAAE,GAAW,EAAE,QAAgB;IAC1E,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACxC,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACrD,CAAC;AAED,SAAS,cAAc,CAAC,IAAc;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACrB,CAAC;QACD,IAAI,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,OAAO,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG,EAAE,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACrG,OAAO;QACL,UAAU,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,cAAc,IAAI,mBAAmB;QAC7E,MAAM,EAAE,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,oBAAoB,CAAC;QAC5D,SAAS,EAAE,aAAa,CAAC,GAAG,EAAE,WAAW,EAAE,SAAS,CAAC;QACrD,aAAa,EAAE,aAAa,CAAC,GAAG,EAAE,oBAAoB,EAAE,OAAO,CAAC;QAChE,aAAa,EAAE,aAAa,CAAC,GAAG,EAAE,oBAAoB,EAAE,UAAU,CAAC;QACnE,gBAAgB,EAAE,aAAa,CAAC,GAAG,EAAE,uBAAuB,EAAE,MAAM,CAAC;QACrE,cAAc,EAAE,aAAa,CAAC,GAAG,EAAE,qBAAqB,EAAE,OAAO,CAAC;QAClE,cAAc,EAAE,aAAa,CAAC,GAAG,EAAE,qBAAqB,EAAE,OAAO,CAAC;QAClE,YAAY,EAAE,aAAa,CAAC,GAAG,EAAE,mBAAmB,EAAE,GAAG,CAAC;QAC1D,UAAU,EAAE,aAAa,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,CAAC;QACrD,SAAS,EAAE,aAAa,CAAC,GAAG,EAAE,eAAe,EAAE,CAAC,CAAC;KAClD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { spawn } from 'node:child_process';
2
+ export declare function probeAcpHandshake(cmd: string, args: string[], opts?: {
3
+ timeoutMs?: number;
4
+ spawnImpl?: typeof spawn;
5
+ }): Promise<boolean>;
@@ -0,0 +1,61 @@
1
+ import { spawn } from 'node:child_process';
2
+ export function probeAcpHandshake(cmd, args, opts) {
3
+ const timeoutMs = opts?.timeoutMs ?? 5_000;
4
+ const spawnImpl = opts?.spawnImpl ?? spawn;
5
+ return new Promise((resolveProbe) => {
6
+ let settled = false;
7
+ let timer;
8
+ let child;
9
+ const finish = (ok) => {
10
+ if (settled) {
11
+ return;
12
+ }
13
+ settled = true;
14
+ if (timer) {
15
+ clearTimeout(timer);
16
+ }
17
+ try {
18
+ child.kill();
19
+ }
20
+ catch {
21
+ // Best-effort probe cleanup.
22
+ }
23
+ resolveProbe(ok);
24
+ };
25
+ try {
26
+ child = spawnImpl(cmd, args, { stdio: 'pipe' });
27
+ }
28
+ catch {
29
+ resolveProbe(false);
30
+ return;
31
+ }
32
+ let buffer = '';
33
+ child.stdout.on('data', (chunk) => {
34
+ buffer += String(chunk);
35
+ let newline = buffer.indexOf('\n');
36
+ while (newline >= 0) {
37
+ const line = buffer.slice(0, newline).trim();
38
+ buffer = buffer.slice(newline + 1);
39
+ if (line.length > 0) {
40
+ finish(isInitializeResult(line));
41
+ return;
42
+ }
43
+ newline = buffer.indexOf('\n');
44
+ }
45
+ });
46
+ child.on('error', () => finish(false));
47
+ child.on('exit', () => finish(false));
48
+ timer = setTimeout(() => finish(false), timeoutMs);
49
+ child.stdin.write(`${JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'initialize', params: {} })}\n`);
50
+ });
51
+ }
52
+ function isInitializeResult(line) {
53
+ try {
54
+ const msg = JSON.parse(line);
55
+ return Object.hasOwn(msg, 'result');
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
61
+ //# sourceMappingURL=acpProbe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acpProbe.js","sourceRoot":"","sources":["../../src/detect/acpProbe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { Framework } from '../types.js';
2
+ export interface ExecFn {
3
+ (cmd: string, args: string[], opts?: {
4
+ timeoutMs?: number;
5
+ }): Promise<{
6
+ code: number;
7
+ stdout: string;
8
+ stderr: string;
9
+ }>;
10
+ }
11
+ export interface DetectedFramework {
12
+ name: Framework;
13
+ version: string;
14
+ meta?: {
15
+ defaultAgentId?: string;
16
+ defaultWorkspace?: string;
17
+ };
18
+ }
19
+ export declare class FrameworkDetector {
20
+ private readonly deps;
21
+ private frameworksCache?;
22
+ constructor(deps: {
23
+ exec: ExecFn;
24
+ probeHermes?: () => Promise<boolean>;
25
+ });
26
+ detect(): Promise<DetectedFramework[]>;
27
+ private detectOne;
28
+ private probeHermes;
29
+ private detectOpenclawDefaultAgent;
30
+ }
@@ -0,0 +1,88 @@
1
+ import { probeAcpHandshake } from './acpProbe.js';
2
+ const SPECS = [
3
+ { name: 'claude-code', bin: 'claude' },
4
+ { name: 'codex', bin: 'codex' },
5
+ { name: 'openclaw', bin: 'openclaw' },
6
+ { name: 'hermes', bin: 'hermes' }
7
+ ];
8
+ export class FrameworkDetector {
9
+ deps;
10
+ frameworksCache;
11
+ constructor(deps) {
12
+ this.deps = deps;
13
+ }
14
+ async detect() {
15
+ if (this.frameworksCache) {
16
+ return this.frameworksCache;
17
+ }
18
+ const frameworks = [];
19
+ for (const spec of SPECS) {
20
+ const detected = await this.detectOne(spec);
21
+ if (detected) {
22
+ frameworks.push(detected);
23
+ }
24
+ }
25
+ this.frameworksCache = frameworks;
26
+ return frameworks;
27
+ }
28
+ async detectOne(spec) {
29
+ const found = await this.deps.exec('which', [spec.bin], { timeoutMs: 3_000 });
30
+ if (found.code !== 0) {
31
+ return null;
32
+ }
33
+ const versionResult = await this.deps.exec(spec.bin, ['--version'], { timeoutMs: 3_000 });
34
+ if (versionResult.code !== 0) {
35
+ return null;
36
+ }
37
+ if (spec.name === 'hermes') {
38
+ const ok = await this.probeHermes();
39
+ if (!ok) {
40
+ return null;
41
+ }
42
+ }
43
+ const detected = {
44
+ name: spec.name,
45
+ version: parseVersion(versionResult.stdout || versionResult.stderr)
46
+ };
47
+ if (spec.name === 'openclaw') {
48
+ const meta = await this.detectOpenclawDefaultAgent();
49
+ if (meta) {
50
+ detected.meta = meta;
51
+ }
52
+ }
53
+ return detected;
54
+ }
55
+ async probeHermes() {
56
+ try {
57
+ return await (this.deps.probeHermes?.() ?? probeAcpHandshake('hermes', ['acp']));
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
63
+ async detectOpenclawDefaultAgent() {
64
+ const result = await this.deps.exec('openclaw', ['--log-level', 'silent', 'agents', 'list', '--json'], { timeoutMs: 5_000 });
65
+ if (result.code !== 0) {
66
+ return undefined;
67
+ }
68
+ try {
69
+ const agents = JSON.parse(result.stdout);
70
+ const defaultAgent = agents.find((agent) => agent.isDefault === true);
71
+ if (!defaultAgent) {
72
+ return undefined;
73
+ }
74
+ return {
75
+ defaultAgentId: typeof defaultAgent.id === 'string' ? defaultAgent.id : undefined,
76
+ defaultWorkspace: typeof defaultAgent.workspace === 'string' ? defaultAgent.workspace : undefined
77
+ };
78
+ }
79
+ catch {
80
+ return undefined;
81
+ }
82
+ }
83
+ }
84
+ function parseVersion(output) {
85
+ const match = output.match(/\d+\.\d+\.\d+(?:[-+.\w]*)?/);
86
+ return match?.[0] ?? output.trim();
87
+ }
88
+ //# sourceMappingURL=frameworkDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frameworkDetector.js","sourceRoot":"","sources":["../../src/detect/frameworkDetector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { JsonRpcRequest, JsonRpcResponse } from '../types.js';
2
+ import type { FrontierCredentials } from './frontierKey.js';
3
+ export declare const RPC_METHOD = 1;
4
+ export declare const MAX_FRAME_BYTES = 6144;
5
+ export interface FwsLike {
6
+ send(payload: string, opts: {
7
+ method: number;
8
+ service: number;
9
+ }): void;
10
+ connect?: () => void;
11
+ reconnect?: () => void;
12
+ close?: () => void;
13
+ on?: (event: string, cb: (payload: unknown) => void) => void;
14
+ }
15
+ export declare class FrontierClient {
16
+ private readonly creds;
17
+ private readonly fws;
18
+ private readonly callbacks;
19
+ private readonly now;
20
+ private lastActivity;
21
+ private readonly rpcMethod;
22
+ constructor(deps: {
23
+ FwsCtor: new (o: Record<string, unknown>) => FwsLike;
24
+ wsImpl: unknown;
25
+ now?: () => number;
26
+ }, creds: FrontierCredentials, opts: {
27
+ platform: string;
28
+ rpcMethod?: number;
29
+ });
30
+ connect(): void;
31
+ send(msg: JsonRpcRequest | JsonRpcResponse): void;
32
+ onFrame(cb: (msg: JsonRpcRequest | JsonRpcResponse) => void): void;
33
+ forceReconnect(): void;
34
+ lastActivityAt(): number;
35
+ close(): void;
36
+ private handleInbound;
37
+ }
@@ -0,0 +1,103 @@
1
+ import { OaError } from '../types.js';
2
+ import { wsOrigin } from './frontierKey.js';
3
+ export const RPC_METHOD = 1;
4
+ export const MAX_FRAME_BYTES = 6144;
5
+ export class FrontierClient {
6
+ creds;
7
+ fws;
8
+ callbacks = [];
9
+ now;
10
+ lastActivity;
11
+ rpcMethod;
12
+ constructor(deps, creds, opts) {
13
+ this.creds = creds;
14
+ this.now = deps.now ?? Date.now;
15
+ this.lastActivity = this.now();
16
+ this.rpcMethod = opts.rpcMethod ?? RPC_METHOD;
17
+ const onmessage = (payload) => this.handleInbound(payload);
18
+ this.fws = new deps.FwsCtor({
19
+ fpID: creds.fpid,
20
+ aID: creds.aid,
21
+ accessKey: creds.accessKey,
22
+ deviceID: creds.deviceId,
23
+ url: wsOrigin(creds.wsUrl),
24
+ service: creds.serviceId,
25
+ ws: deps.wsImpl,
26
+ customParams: { platform: opts.platform },
27
+ enableTransformTextPayload: true,
28
+ payloadType: 'application/json',
29
+ onmessage,
30
+ onMessage: onmessage
31
+ });
32
+ this.fws.on?.('message', onmessage);
33
+ }
34
+ connect() {
35
+ this.fws.connect?.();
36
+ }
37
+ send(msg) {
38
+ const payload = JSON.stringify(msg);
39
+ if (Buffer.byteLength(payload, 'utf8') > MAX_FRAME_BYTES) {
40
+ throw new OaError('E_FRAME_TOO_LARGE');
41
+ }
42
+ this.fws.send(payload, { method: this.rpcMethod, service: this.creds.serviceId });
43
+ this.lastActivity = this.now();
44
+ }
45
+ onFrame(cb) {
46
+ this.callbacks.push(cb);
47
+ }
48
+ forceReconnect() {
49
+ this.fws.reconnect?.();
50
+ }
51
+ lastActivityAt() {
52
+ return this.lastActivity;
53
+ }
54
+ close() {
55
+ this.fws.close?.();
56
+ }
57
+ handleInbound(payload) {
58
+ this.lastActivity = this.now();
59
+ const textPayload = extractTextPayload(payload);
60
+ if (textPayload === undefined) {
61
+ return;
62
+ }
63
+ try {
64
+ const parsed = JSON.parse(textPayload);
65
+ if (isJsonRpc(parsed)) {
66
+ for (const cb of this.callbacks) {
67
+ cb(parsed);
68
+ }
69
+ }
70
+ }
71
+ catch {
72
+ // Invalid frames are ignored; Frontier callback reliability is handled above us.
73
+ }
74
+ }
75
+ }
76
+ function extractTextPayload(payload) {
77
+ if (typeof payload === 'string') {
78
+ return payload;
79
+ }
80
+ if (Buffer.isBuffer(payload)) {
81
+ return payload.toString('utf8');
82
+ }
83
+ if (typeof payload === 'object' && payload !== null) {
84
+ const maybe = payload;
85
+ for (const value of [maybe.textPayload, maybe.payload, maybe.data]) {
86
+ if (typeof value === 'string') {
87
+ return value;
88
+ }
89
+ }
90
+ }
91
+ return undefined;
92
+ }
93
+ function isJsonRpc(value) {
94
+ if (typeof value !== 'object' || value === null) {
95
+ return false;
96
+ }
97
+ const msg = value;
98
+ if (msg.jsonrpc !== '2.0') {
99
+ return false;
100
+ }
101
+ return typeof msg.method === 'string' || (msg.id !== undefined && (Object.hasOwn(msg, 'result') || Object.hasOwn(msg, 'error')));
102
+ }
103
+ //# sourceMappingURL=frontierClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontierClient.js","sourceRoot":"","sources":["../../src/frontier/frontierClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { DetectedFramework } from '../detect/frameworkDetector.js';
2
+ export interface FrontierCredentials {
3
+ deviceId: string;
4
+ accessKey: string;
5
+ wsUrl: string;
6
+ aid: string;
7
+ fpid: string;
8
+ serviceId: number;
9
+ }
10
+ export declare function exchangeFrontierKey(deps: {
11
+ fetchImpl: typeof fetch;
12
+ }, opts: {
13
+ serverBase: string;
14
+ deviceToken: string;
15
+ hostname: string;
16
+ platform: string;
17
+ frameworks: DetectedFramework[];
18
+ }): Promise<FrontierCredentials>;
19
+ export declare function wsOrigin(wsUrl: string): string;