@borgee/agents-host 0.2.1 → 0.2.26

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 (78) hide show
  1. package/README.md +184 -21
  2. package/dist/agents-host-supervisor.d.ts +7 -5
  3. package/dist/agents-host-supervisor.js +24 -4
  4. package/dist/agents-host.d.ts +89 -15
  5. package/dist/agents-host.js +2099 -142
  6. package/dist/chat/chat-control-plane.d.ts +14 -3
  7. package/dist/chat/sdk-chat-control-plane.d.ts +16 -4
  8. package/dist/chat/sdk-chat-control-plane.js +69 -9
  9. package/dist/cli-args.d.ts +46 -5
  10. package/dist/cli-args.js +313 -32
  11. package/dist/cli.d.ts +9 -0
  12. package/dist/cli.js +112 -5
  13. package/dist/compatibility-gates.d.ts +35 -0
  14. package/dist/compatibility-gates.js +127 -0
  15. package/dist/config.d.ts +1 -0
  16. package/dist/config.js +23 -5
  17. package/dist/connections-state-store.d.ts +81 -0
  18. package/dist/connections-state-store.js +228 -0
  19. package/dist/context/injection.d.ts +109 -0
  20. package/dist/context/injection.js +350 -0
  21. package/dist/context/prompt.d.ts +4 -1
  22. package/dist/context/prompt.js +170 -1
  23. package/dist/context/turn-preparation.d.ts +9 -0
  24. package/dist/context/turn-preparation.js +106 -0
  25. package/dist/debug.d.ts +44 -0
  26. package/dist/debug.js +135 -0
  27. package/dist/gateway/localhost-gateway.d.ts +52 -0
  28. package/dist/gateway/localhost-gateway.js +857 -0
  29. package/dist/index.js +7 -5
  30. package/dist/local-config.d.ts +4 -1
  31. package/dist/local-config.js +24 -7
  32. package/dist/managed-daemon-log.d.ts +34 -0
  33. package/dist/managed-daemon-log.js +261 -0
  34. package/dist/managed-daemon.d.ts +220 -0
  35. package/dist/managed-daemon.js +1601 -0
  36. package/dist/policy/authorization-audit.d.ts +63 -0
  37. package/dist/policy/authorization-audit.js +94 -0
  38. package/dist/policy/copilot-permission.d.ts +15 -0
  39. package/dist/policy/copilot-permission.js +193 -0
  40. package/dist/policy/gateway-authorization.d.ts +42 -0
  41. package/dist/policy/gateway-authorization.js +162 -0
  42. package/dist/providers/awaiting-user.d.ts +12 -0
  43. package/dist/providers/awaiting-user.js +151 -0
  44. package/dist/providers/claude/adapter.d.ts +3 -1
  45. package/dist/providers/claude/adapter.js +8 -12
  46. package/dist/providers/claude/cli-client.d.ts +12 -5
  47. package/dist/providers/claude/cli-client.js +184 -37
  48. package/dist/providers/claude/session-store.d.ts +24 -0
  49. package/dist/providers/claude/session-store.js +65 -12
  50. package/dist/providers/codex/adapter.d.ts +11 -0
  51. package/dist/providers/codex/adapter.js +19 -0
  52. package/dist/providers/codex/cli-client.d.ts +103 -0
  53. package/dist/providers/codex/cli-client.js +1133 -0
  54. package/dist/providers/codex/project-doc.d.ts +3 -0
  55. package/dist/providers/codex/project-doc.js +66 -0
  56. package/dist/providers/codex/session-store.d.ts +38 -0
  57. package/dist/providers/codex/session-store.js +150 -0
  58. package/dist/providers/copilot/adapter.d.ts +3 -1
  59. package/dist/providers/copilot/adapter.js +8 -12
  60. package/dist/providers/copilot/cli-client.d.ts +20 -2
  61. package/dist/providers/copilot/cli-client.js +251 -71
  62. package/dist/providers/copilot/session-store.d.ts +24 -0
  63. package/dist/providers/copilot/session-store.js +65 -12
  64. package/dist/providers/create-provider.d.ts +11 -2
  65. package/dist/providers/create-provider.js +131 -12
  66. package/dist/run.d.ts +1 -0
  67. package/dist/run.js +5 -2
  68. package/dist/state-paths.d.ts +13 -1
  69. package/dist/state-paths.js +84 -3
  70. package/dist/task-thread-resolution.d.ts +10 -0
  71. package/dist/task-thread-resolution.js +48 -0
  72. package/dist/types.d.ts +174 -1
  73. package/dist/visible-mentions.d.ts +3 -0
  74. package/dist/visible-mentions.js +15 -0
  75. package/package.json +19 -17
  76. package/skills/borgee-agent/SKILL.md +33 -0
  77. package/skills/borgee-agent/borgee-agent.mjs +473 -0
  78. package/skills/borgee-agent/borgee-agent.py +409 -0
package/dist/cli-args.js CHANGED
@@ -1,26 +1,72 @@
1
1
  /**
2
- * Maps single-agent `agents-host start` CLI flags to the env vars `config.ts`
3
- * reads. Keeping this as a plain lookup table (rather than duplicating
4
- * `loadConfigFromEnv`'s parsing logic) means the CLI and the env-var entry
5
- * point (`index.ts`) always agree on defaults/validation.
2
+ * Maps `agents-host start` / `agents-host start-managed` agent flags to the env
3
+ * vars `config.ts` reads. Keeping this as a plain lookup table (rather than
4
+ * duplicating `loadConfigFromEnv`'s parsing logic) means the CLI and the
5
+ * standalone env-var entry point (`index.ts`) always agree on
6
+ * defaults/validation.
6
7
  */
7
8
  export const CLI_FLAG_TO_ENV = {
8
9
  name: 'BORGEE_AGENT_NAME',
9
10
  provider: 'RUNTIME_PROVIDER',
10
11
  'claude-command': 'CLAUDE_COMMAND',
11
12
  'claude-args': 'CLAUDE_ARGS',
13
+ 'codex-command': 'CODEX_COMMAND',
14
+ 'codex-args': 'CODEX_ARGS',
12
15
  'copilot-command': 'COPILOT_COMMAND',
13
16
  'copilot-args': 'COPILOT_ARGS',
14
17
  'copilot-session-ttl-minutes': 'COPILOT_SESSION_TTL_MINUTES',
15
18
  };
16
19
  const SINGLE_AGENT_FLAG_NAMES = new Set(Object.keys(CLI_FLAG_TO_ENV));
20
+ const FLAGS_ALLOWING_DASH_PREFIX_VALUE = new Set(['claude-args', 'codex-args', 'copilot-args']);
17
21
  export class CliUsageError extends Error {
18
22
  }
23
+ function parseSingleAgentPositionals(positionals) {
24
+ const [serverUrl, apiKey, ...extra] = positionals;
25
+ if (!serverUrl) {
26
+ throw new CliUsageError('Missing <serverUrl>');
27
+ }
28
+ if (!apiKey) {
29
+ throw new CliUsageError('Missing <apiKey>');
30
+ }
31
+ if (extra.length > 0) {
32
+ throw new CliUsageError(`Unexpected argument: ${extra[0]}`);
33
+ }
34
+ return { serverUrl, apiKey };
35
+ }
36
+ function readSingleAgentFlagValue(argv, index, flag) {
37
+ const value = argv[index + 1];
38
+ if (value === undefined ||
39
+ (value.startsWith('--') && !FLAGS_ALLOWING_DASH_PREFIX_VALUE.has(flag))) {
40
+ throw new CliUsageError(`Missing value for --${flag}`);
41
+ }
42
+ return value;
43
+ }
44
+ function applySingleAgentFlag(argv, index, env, seenSingleAgentFlags) {
45
+ const flag = argv[index]?.slice(2) ?? '';
46
+ const envKey = CLI_FLAG_TO_ENV[flag];
47
+ if (!envKey) {
48
+ throw new CliUsageError(`Unknown option: --${flag}`);
49
+ }
50
+ env[envKey] = readSingleAgentFlagValue(argv, index, flag);
51
+ seenSingleAgentFlags.add(flag);
52
+ return index + 1;
53
+ }
54
+ function parseNonNegativeInteger(value, flag) {
55
+ if (!/^\d+$/u.test(value)) {
56
+ throw new CliUsageError(`--${flag} must be a non-negative integer`);
57
+ }
58
+ const parsed = Number.parseInt(value, 10);
59
+ if (!Number.isSafeInteger(parsed)) {
60
+ throw new CliUsageError(`--${flag} must be a non-negative integer`);
61
+ }
62
+ return parsed;
63
+ }
19
64
  export function parseStartArgs(argv) {
20
65
  const positionals = [];
21
66
  const env = {};
22
67
  const seenSingleAgentFlags = new Set();
23
68
  let configPath;
69
+ let debug = false;
24
70
  for (let i = 0; i < argv.length; i++) {
25
71
  const arg = argv[i];
26
72
  if (!arg.startsWith('--')) {
@@ -28,25 +74,22 @@ export function parseStartArgs(argv) {
28
74
  continue;
29
75
  }
30
76
  const flag = arg.slice(2);
31
- const value = argv[i + 1];
32
- if (value === undefined || value.startsWith('--')) {
33
- throw new CliUsageError(`Missing value for --${flag}`);
77
+ if (flag === 'debug') {
78
+ if (debug) {
79
+ throw new CliUsageError('--debug may only be specified once');
80
+ }
81
+ debug = true;
82
+ continue;
34
83
  }
35
84
  if (flag === 'config') {
36
85
  if (configPath !== undefined) {
37
86
  throw new CliUsageError('--config may only be specified once');
38
87
  }
39
- configPath = value;
88
+ configPath = readSingleAgentFlagValue(argv, i, flag);
40
89
  i++;
41
90
  continue;
42
91
  }
43
- const envKey = CLI_FLAG_TO_ENV[flag];
44
- if (!envKey) {
45
- throw new CliUsageError(`Unknown option: --${flag}`);
46
- }
47
- env[envKey] = value;
48
- seenSingleAgentFlags.add(flag);
49
- i++;
92
+ i = applySingleAgentFlag(argv, i, env, seenSingleAgentFlags);
50
93
  }
51
94
  if (configPath !== undefined) {
52
95
  if (positionals.length > 0) {
@@ -58,25 +101,49 @@ export function parseStartArgs(argv) {
58
101
  return {
59
102
  mode: 'local-config',
60
103
  configPath,
104
+ debug,
61
105
  };
62
106
  }
63
- const [serverUrl, apiKey, ...extra] = positionals;
64
- if (!serverUrl) {
65
- throw new CliUsageError('Missing <serverUrl>');
66
- }
67
- if (!apiKey) {
68
- throw new CliUsageError('Missing <apiKey>');
69
- }
70
- if (extra.length > 0) {
71
- throw new CliUsageError(`Unexpected argument: ${extra[0]}`);
72
- }
107
+ const { serverUrl, apiKey } = parseSingleAgentPositionals(positionals);
73
108
  return {
74
109
  mode: 'single-agent',
75
110
  serverUrl,
76
111
  apiKey,
112
+ debug,
77
113
  env,
78
114
  };
79
115
  }
116
+ export function parseManagedStartArgs(argv) {
117
+ const positionals = [];
118
+ const env = {};
119
+ const seenSingleAgentFlags = new Set();
120
+ for (let i = 0; i < argv.length; i++) {
121
+ const arg = argv[i];
122
+ if (!arg.startsWith('--')) {
123
+ positionals.push(arg);
124
+ continue;
125
+ }
126
+ const flag = arg.slice(2);
127
+ if (flag === 'debug') {
128
+ throw new CliUsageError('start-managed does not support --debug; use foreground start for debug logging');
129
+ }
130
+ if (flag === 'config') {
131
+ throw new CliUsageError('start-managed does not support --config');
132
+ }
133
+ i = applySingleAgentFlag(argv, i, env, seenSingleAgentFlags);
134
+ }
135
+ if (positionals.length === 1) {
136
+ if (seenSingleAgentFlags.size > 0) {
137
+ throw new CliUsageError(`Cannot combine bare start-managed <serverUrl> resume with agent option --${[...seenSingleAgentFlags][0]}; provide <apiKey> to bootstrap or update an agent`);
138
+ }
139
+ return {
140
+ serverUrl: positionals[0],
141
+ env,
142
+ };
143
+ }
144
+ const { serverUrl, apiKey } = parseSingleAgentPositionals(positionals);
145
+ return { serverUrl, apiKey, env };
146
+ }
80
147
  export function parseValidateArgs(argv) {
81
148
  const positionals = [];
82
149
  let configPath;
@@ -218,27 +285,234 @@ export function parseGenerateConfigArgs(argv) {
218
285
  }
219
286
  return { rootPath, input: 'argv', specJson };
220
287
  }
288
+ export function parseDaemonArgs(argv) {
289
+ const positionals = [];
290
+ let rootPath;
291
+ let debug = false;
292
+ for (let i = 0; i < argv.length; i++) {
293
+ const arg = argv[i];
294
+ if (!arg.startsWith('--')) {
295
+ positionals.push(arg);
296
+ continue;
297
+ }
298
+ const flag = arg.slice(2);
299
+ if (flag === 'debug') {
300
+ if (debug) {
301
+ throw new CliUsageError('--debug may only be specified once');
302
+ }
303
+ debug = true;
304
+ continue;
305
+ }
306
+ if (flag === 'root') {
307
+ const value = argv[i + 1];
308
+ if (value === undefined || value.startsWith('--')) {
309
+ throw new CliUsageError('Missing value for --root');
310
+ }
311
+ if (rootPath !== undefined) {
312
+ throw new CliUsageError('--root may only be specified once');
313
+ }
314
+ rootPath = value;
315
+ i++;
316
+ continue;
317
+ }
318
+ throw new CliUsageError(`Unknown option: --${flag}`);
319
+ }
320
+ if (positionals.length > 0) {
321
+ throw new CliUsageError(`Unexpected argument: ${positionals[0]}`);
322
+ }
323
+ if (!rootPath) {
324
+ throw new CliUsageError('Missing required --root <dir>');
325
+ }
326
+ return { rootPath, debug };
327
+ }
328
+ export function parseLogArgs(argv) {
329
+ const positionals = [];
330
+ let lines = 100;
331
+ let follow = false;
332
+ let pathOnly = false;
333
+ let linesSpecified = false;
334
+ for (let i = 0; i < argv.length; i++) {
335
+ const arg = argv[i];
336
+ if (!arg.startsWith('--')) {
337
+ positionals.push(arg);
338
+ continue;
339
+ }
340
+ const flag = arg.slice(2);
341
+ if (flag === 'follow') {
342
+ if (follow) {
343
+ throw new CliUsageError('--follow may only be specified once');
344
+ }
345
+ follow = true;
346
+ continue;
347
+ }
348
+ if (flag === 'path') {
349
+ if (pathOnly) {
350
+ throw new CliUsageError('--path may only be specified once');
351
+ }
352
+ pathOnly = true;
353
+ continue;
354
+ }
355
+ if (flag === 'lines') {
356
+ if (linesSpecified) {
357
+ throw new CliUsageError('--lines may only be specified once');
358
+ }
359
+ const value = argv[i + 1];
360
+ if (value === undefined || value.startsWith('--')) {
361
+ throw new CliUsageError('Missing value for --lines');
362
+ }
363
+ lines = parseNonNegativeInteger(value, 'lines');
364
+ linesSpecified = true;
365
+ i++;
366
+ continue;
367
+ }
368
+ throw new CliUsageError(`Unknown option: --${flag}`);
369
+ }
370
+ const [serverUrl, ...extra] = positionals;
371
+ if (!serverUrl) {
372
+ throw new CliUsageError('Missing <serverUrl>');
373
+ }
374
+ if (extra.length > 0) {
375
+ throw new CliUsageError(`Unexpected argument: ${extra[0]}`);
376
+ }
377
+ if (pathOnly && (follow || linesSpecified)) {
378
+ throw new CliUsageError('--path cannot be combined with --follow or --lines');
379
+ }
380
+ return { serverUrl, lines, follow, pathOnly };
381
+ }
382
+ export function parseDescribeManagedArgs(argv) {
383
+ const [serverUrl, ...extra] = argv;
384
+ if (!serverUrl) {
385
+ throw new CliUsageError('Missing <serverUrl>');
386
+ }
387
+ if (serverUrl.startsWith('--')) {
388
+ throw new CliUsageError(`Unknown option: ${serverUrl}`);
389
+ }
390
+ if (extra.length > 0) {
391
+ throw new CliUsageError(`Unexpected argument: ${extra[0]}`);
392
+ }
393
+ return { serverUrl };
394
+ }
395
+ export function parseCleanupManagedArgs(argv) {
396
+ const positionals = [];
397
+ let purge = false;
398
+ for (let i = 0; i < argv.length; i++) {
399
+ const arg = argv[i];
400
+ if (!arg.startsWith('--')) {
401
+ positionals.push(arg);
402
+ continue;
403
+ }
404
+ const flag = arg.slice(2);
405
+ if (flag === 'purge') {
406
+ if (purge) {
407
+ throw new CliUsageError('--purge may only be specified once');
408
+ }
409
+ purge = true;
410
+ continue;
411
+ }
412
+ throw new CliUsageError(`Unknown option: --${flag}`);
413
+ }
414
+ const [serverUrl, ...extra] = positionals;
415
+ if (!serverUrl) {
416
+ throw new CliUsageError('Missing <serverUrl>');
417
+ }
418
+ if (extra.length > 0) {
419
+ throw new CliUsageError(`Unexpected argument: ${extra[0]}`);
420
+ }
421
+ return { serverUrl, purge };
422
+ }
423
+ export function parseApplyManagedArgs(argv) {
424
+ const positionals = [];
425
+ let specJson;
426
+ let stdin = false;
427
+ for (let i = 0; i < argv.length; i++) {
428
+ const arg = argv[i];
429
+ if (!arg.startsWith('--')) {
430
+ positionals.push(arg);
431
+ continue;
432
+ }
433
+ const flag = arg.slice(2);
434
+ if (flag === 'stdin') {
435
+ if (stdin) {
436
+ throw new CliUsageError('--stdin may only be specified once');
437
+ }
438
+ stdin = true;
439
+ continue;
440
+ }
441
+ if (flag === 'spec-json') {
442
+ const value = argv[i + 1];
443
+ if (value === undefined || value.startsWith('--')) {
444
+ throw new CliUsageError('Missing value for --spec-json');
445
+ }
446
+ if (specJson !== undefined) {
447
+ throw new CliUsageError('--spec-json may only be specified once');
448
+ }
449
+ specJson = value;
450
+ i++;
451
+ continue;
452
+ }
453
+ throw new CliUsageError(`Unknown option: --${flag}`);
454
+ }
455
+ const [serverUrl, ...extra] = positionals;
456
+ if (!serverUrl) {
457
+ throw new CliUsageError('Missing <serverUrl>');
458
+ }
459
+ if (extra.length > 0) {
460
+ throw new CliUsageError(`Unexpected argument: ${extra[0]}`);
461
+ }
462
+ if (stdin && specJson !== undefined) {
463
+ throw new CliUsageError('apply-managed accepts exactly one input source: --stdin or --spec-json');
464
+ }
465
+ if (stdin) {
466
+ return { serverUrl, input: 'stdin' };
467
+ }
468
+ if (!specJson) {
469
+ throw new CliUsageError('Missing required input: use --stdin or --spec-json <json>');
470
+ }
471
+ return { serverUrl, input: 'argv', specJson };
472
+ }
221
473
  export const USAGE = `Usage:
222
474
  agents-host start <serverUrl> <apiKey> [options]
223
- agents-host start --config <path-to-host-config>
475
+ agents-host start-managed <serverUrl>
476
+ agents-host start-managed <serverUrl> <apiKey> [agent-options]
477
+ agents-host describe-managed <serverUrl>
478
+ agents-host cleanup-managed <serverUrl> [--purge]
479
+ agents-host apply-managed <serverUrl> --stdin
480
+ agents-host apply-managed <serverUrl> --spec-json <json>
481
+ agents-host log <serverUrl> [--lines <n>] [--follow]
482
+ agents-host log <serverUrl> --path
483
+ agents-host start --config <path-to-host-config> [--debug]
224
484
  agents-host validate --config <path-to-host-config>
225
485
  agents-host describe --config <path-to-host-config>
226
486
  agents-host print-layout --root <dir>
227
487
  agents-host generate-config --root <dir> --stdin
228
488
  agents-host generate-config --root <dir> --spec-json <json>
229
489
 
230
- Single-agent options:
490
+ Foreground start options:
491
+ --debug Enable host/provider debug logs (or set AGENTS_HOST_DEBUG=1)
492
+
493
+ Single-agent agent options:
231
494
  --name <name> Display name (default: Assistant)
232
- --provider <claude|copilot> Runtime provider (default: claude)
495
+ --provider <claude|codex|copilot>
496
+ Runtime provider (default: claude)
233
497
  --claude-command <cmd> Local Claude CLI command (default: claude)
234
- --claude-args <args> Local Claude CLI args (default: --print)
498
+ --claude-args <args> Local Claude CLI args (default: --print --permission-mode bypassPermissions)
499
+ --codex-command <cmd> Local Codex ACP adapter command (default: codex-acp)
500
+ --codex-args <args> Local Codex ACP adapter args
235
501
  --copilot-command <cmd> Local Copilot CLI command (default: copilot)
236
502
  --copilot-args <args> Ignored by the Copilot ACP prototype
237
503
  --copilot-session-ttl-minutes <minutes>
238
504
  Idle session TTL for Copilot ACP sessions (default: 2880)
239
505
 
240
- Local-config mode:
506
+ Command summary:
507
+ start <serverUrl> <apiKey> Start one foreground hosted agent (legacy-compatible behavior)
241
508
  start --config <path> Start agents + supervisor + watchers from a host config file
509
+ start-managed <serverUrl> Restart or resume an existing per-serverUrl managed daemon
510
+ start-managed <serverUrl> <apiKey>
511
+ Upsert one agent into the per-serverUrl local daemon and exit after reconcile
512
+ describe-managed <serverUrl> Print managed-runtime spec JSON for machine callers
513
+ cleanup-managed <serverUrl> Stop one managed-runtime daemon locally; --purge also removes its runtime root
514
+ apply-managed <serverUrl> Apply one managed-runtime full-set spec for machine callers
515
+ log <serverUrl> Print the managed daemon log tail for one server runtime
242
516
  validate --config <path> Validate local-config files without starting agents or watchers
243
517
  describe --config <path> Print the current managed full-set spec as JSON
244
518
  print-layout --root <dir> Print the canonical default local-config layout as JSON
@@ -247,8 +521,15 @@ Local-config mode:
247
521
  Compatibility input; JSON is exposed in process arguments
248
522
 
249
523
  Examples:
250
- agents-host start https://borgee.example.com bgr_xxxxxxxx --provider copilot
251
- agents-host start --config ./agents-host.yaml
524
+ agents-host start https://borgee.example.com bgr_xxxxxxxx --provider copilot --debug
525
+ agents-host start-managed https://borgee.example.com
526
+ agents-host start-managed https://borgee.example.com bgr_xxxxxxxx --provider copilot
527
+ agents-host describe-managed https://borgee.example.com
528
+ agents-host cleanup-managed https://borgee.example.com --purge
529
+ printf '%s' '{"host":{"borgeeBaseUrl":"https://borgee.example.com"},"agents":[{"key":"cp1","name":"Copilot","apiKey":"bgr_xxx","provider":"copilot"}]}' | agents-host apply-managed https://borgee.example.com --stdin
530
+ agents-host log https://borgee.example.com --lines 200 --follow
531
+ agents-host log https://borgee.example.com --path
532
+ agents-host start --config ./agents-host.yaml --debug
252
533
  agents-host validate --config ./agents-host.yaml
253
534
  agents-host describe --config ./agents-host.yaml
254
535
  agents-host print-layout --root ./runtime-root
package/dist/cli.d.ts CHANGED
@@ -1,14 +1,23 @@
1
1
  #!/usr/bin/env node
2
+ import { applyManagedSpec, bootstrapManagedDaemonStart, cleanupManagedRuntime, describeManagedSpec } from './managed-daemon.js';
3
+ import { runManagedDaemonLogCommand } from './managed-daemon-log.js';
2
4
  import { describeLocalConfig, generateLocalConfig, printLocalConfigLayout, runMain, validateLocalConfig } from './run.js';
3
5
  export interface CliDeps {
4
6
  env?: NodeJS.ProcessEnv;
5
7
  logger?: Pick<Console, 'error'>;
6
8
  runMain?: typeof runMain;
9
+ bootstrapManagedDaemonStart?: typeof bootstrapManagedDaemonStart;
10
+ startManagedDaemon?: (rootPath: string, debug: boolean) => Promise<void>;
7
11
  validateLocalConfig?: typeof validateLocalConfig;
8
12
  describeLocalConfig?: typeof describeLocalConfig;
9
13
  printLocalConfigLayout?: typeof printLocalConfigLayout;
10
14
  generateLocalConfig?: typeof generateLocalConfig;
11
15
  readStdin?: () => Promise<string>;
16
+ runManagedDaemonLogCommand?: typeof runManagedDaemonLogCommand;
17
+ describeManagedSpec?: typeof describeManagedSpec;
18
+ cleanupManagedRuntime?: typeof cleanupManagedRuntime;
19
+ applyManagedSpec?: typeof applyManagedSpec;
20
+ stdout?: Pick<Console, 'log'>;
12
21
  }
13
22
  interface CliEntrypointDeps {
14
23
  realpath?: (path: string) => string;
package/dist/cli.js CHANGED
@@ -1,36 +1,85 @@
1
1
  #!/usr/bin/env node
2
2
  import { realpathSync } from 'node:fs';
3
- import { resolve } from 'node:path';
3
+ import { dirname, resolve } from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
- import { CliUsageError, parseDescribeArgs, parseGenerateConfigArgs, parsePrintLayoutArgs, parseStartArgs, parseValidateArgs, USAGE, } from './cli-args.js';
6
- import { describeLocalConfig, generateLocalConfig, printLocalConfigLayout, runMain, validateLocalConfig } from './run.js';
5
+ import { CliUsageError, parseApplyManagedArgs, parseDaemonArgs, parseDescribeArgs, parseDescribeManagedArgs, parseCleanupManagedArgs, parseGenerateConfigArgs, parseLogArgs, parseManagedStartArgs, parsePrintLayoutArgs, parseStartArgs, parseValidateArgs, USAGE, } from './cli-args.js';
6
+ import { resolveAgentsHostDebugMode } from './debug.js';
7
+ import { applyManagedSpec, bootstrapManagedDaemonStart, cleanupManagedRuntime, describeManagedSpec, ManagedAgentsHostDaemon, } from './managed-daemon.js';
8
+ import { runManagedDaemonLogCommand } from './managed-daemon-log.js';
9
+ import { describeLocalConfig, generateLocalConfig, printLocalConfigLayout, runMain, validateLocalConfig, } from './run.js';
7
10
  function formatErrorMessage(error) {
8
11
  if (error instanceof Error) {
9
12
  return error.message;
10
13
  }
11
14
  return String(error);
12
15
  }
16
+ const TASK_WORKSPACE_ROOT_DIR_ENV = 'AGENTS_HOST_INTERNAL_TASK_WORKSPACE_ROOT_DIR';
13
17
  export async function dispatchCli(argv, deps = {}) {
14
18
  const [command, ...rest] = argv;
15
19
  const env = deps.env ?? process.env;
16
20
  const runMainImpl = deps.runMain ?? runMain;
21
+ const bootstrapManagedDaemonStartImpl = deps.bootstrapManagedDaemonStart ?? bootstrapManagedDaemonStart;
17
22
  const validateLocalConfigImpl = deps.validateLocalConfig ?? validateLocalConfig;
18
23
  const describeLocalConfigImpl = deps.describeLocalConfig ?? describeLocalConfig;
19
24
  const printLocalConfigLayoutImpl = deps.printLocalConfigLayout ?? printLocalConfigLayout;
20
25
  const generateLocalConfigImpl = deps.generateLocalConfig ?? generateLocalConfig;
26
+ const runManagedDaemonLogCommandImpl = deps.runManagedDaemonLogCommand ?? runManagedDaemonLogCommand;
27
+ const describeManagedSpecImpl = deps.describeManagedSpec ?? describeManagedSpec;
28
+ const cleanupManagedRuntimeImpl = deps.cleanupManagedRuntime ?? cleanupManagedRuntime;
29
+ const applyManagedSpecImpl = deps.applyManagedSpec ?? applyManagedSpec;
30
+ const startManagedDaemonImpl = deps.startManagedDaemon ??
31
+ (async (rootPath, debug) => {
32
+ env[TASK_WORKSPACE_ROOT_DIR_ENV] = rootPath;
33
+ const daemon = new ManagedAgentsHostDaemon(rootPath, debug, {
34
+ logPath: env.AGENTS_HOST_MANAGED_DAEMON_LOG_PATH,
35
+ });
36
+ const shutdown = async (signal) => {
37
+ console.log(`[agents-host] managed daemon received ${signal}, shutting down`);
38
+ await daemon.stop().catch((error) => {
39
+ console.error('[agents-host] managed daemon shutdown failed', error);
40
+ });
41
+ process.exit(0);
42
+ };
43
+ process.on('SIGINT', () => void shutdown('SIGINT'));
44
+ process.on('SIGTERM', () => void shutdown('SIGTERM'));
45
+ await daemon.start();
46
+ });
21
47
  const readStdin = deps.readStdin ?? readAllStdin;
48
+ const stdout = deps.stdout ?? console;
22
49
  if (command === 'start') {
23
50
  const parsed = parseStartArgs(rest);
51
+ const debug = resolveAgentsHostDebugMode(parsed.debug, env);
24
52
  if (parsed.mode === 'single-agent') {
25
53
  env.BORGEE_BASE_URL = parsed.serverUrl;
26
54
  env.BORGEE_AGENT_API_KEY = parsed.apiKey;
27
55
  for (const [key, value] of Object.entries(parsed.env)) {
28
56
  env[key] = value;
29
57
  }
30
- await runMainImpl();
58
+ await runMainImpl({ debug });
31
59
  return;
32
60
  }
33
- await runMainImpl({ configPath: parsed.configPath });
61
+ env[TASK_WORKSPACE_ROOT_DIR_ENV] = dirname(resolve(parsed.configPath));
62
+ await runMainImpl({ configPath: parsed.configPath, debug });
63
+ return;
64
+ }
65
+ if (command === 'start-managed') {
66
+ const parsed = parseManagedStartArgs(rest);
67
+ if (resolveAgentsHostDebugMode(false, env)) {
68
+ throw new CliUsageError('start-managed does not support debug mode; use foreground start or start --config --debug instead');
69
+ }
70
+ if (parsed.apiKey === undefined) {
71
+ await bootstrapManagedDaemonStartImpl({
72
+ serverUrl: parsed.serverUrl,
73
+ processEnv: env,
74
+ });
75
+ return;
76
+ }
77
+ await bootstrapManagedDaemonStartImpl({
78
+ serverUrl: parsed.serverUrl,
79
+ apiKey: parsed.apiKey,
80
+ env: parsed.env,
81
+ processEnv: env,
82
+ });
34
83
  return;
35
84
  }
36
85
  if (command === 'validate') {
@@ -58,6 +107,64 @@ export async function dispatchCli(argv, deps = {}) {
58
107
  }
59
108
  return;
60
109
  }
110
+ if (command === 'describe-managed') {
111
+ const parsed = parseDescribeManagedArgs(rest);
112
+ stdout.log(JSON.stringify(await describeManagedSpecImpl({
113
+ serverUrl: parsed.serverUrl,
114
+ processEnv: env,
115
+ })));
116
+ return;
117
+ }
118
+ if (command === 'cleanup-managed') {
119
+ const parsed = parseCleanupManagedArgs(rest);
120
+ await cleanupManagedRuntimeImpl({
121
+ serverUrl: parsed.serverUrl,
122
+ purge: parsed.purge,
123
+ processEnv: env,
124
+ });
125
+ return;
126
+ }
127
+ if (command === 'apply-managed') {
128
+ const parsed = parseApplyManagedArgs(rest);
129
+ const specJson = parsed.input === 'stdin' ? await readStdin() : parsed.specJson;
130
+ let parsedSpec;
131
+ try {
132
+ parsedSpec = JSON.parse(specJson);
133
+ }
134
+ catch (error) {
135
+ stdout.log(JSON.stringify({
136
+ ok: false,
137
+ error: {
138
+ code: 'MANAGED_SPEC_INVALID',
139
+ message: `Invalid managed spec JSON: ${formatErrorMessage(error)}`,
140
+ },
141
+ }));
142
+ return;
143
+ }
144
+ stdout.log(JSON.stringify(await applyManagedSpecImpl({
145
+ serverUrl: parsed.serverUrl,
146
+ spec: parsedSpec,
147
+ processEnv: env,
148
+ })));
149
+ return;
150
+ }
151
+ if (command === 'log') {
152
+ const parsed = parseLogArgs(rest);
153
+ await runManagedDaemonLogCommandImpl({
154
+ serverUrl: parsed.serverUrl,
155
+ lines: parsed.lines,
156
+ follow: parsed.follow,
157
+ pathOnly: parsed.pathOnly,
158
+ env,
159
+ });
160
+ return;
161
+ }
162
+ if (command === 'daemon') {
163
+ const parsed = parseDaemonArgs(rest);
164
+ env[TASK_WORKSPACE_ROOT_DIR_ENV] = parsed.rootPath;
165
+ await startManagedDaemonImpl(parsed.rootPath, parsed.debug);
166
+ return;
167
+ }
61
168
  throw new CliUsageError(`Unknown command: ${command}`);
62
169
  }
63
170
  async function readAllStdin() {
@@ -0,0 +1,35 @@
1
+ export declare const CLAUDE_PROVIDER_V2_COMPATIBILITY_GATE = "claude-provider-v2";
2
+ export declare const COPILOT_PROVIDER_V2_COMPATIBILITY_GATE = "copilot-provider-v2";
3
+ export declare const CODEX_PROVIDER_COMPATIBILITY_GATE = "codex-provider";
4
+ export declare const CONNECTIONS_STATE_LAYER_COMPATIBILITY_GATE = "connections-state-layer";
5
+ export declare const CONTEXT_INJECTION_COMPATIBILITY_GATE = "context-injection";
6
+ export declare const SKILL_RUNTIME_COMPATIBILITY_GATE = "skill-runtime";
7
+ export declare const LOCALHOST_GATEWAY_COMPATIBILITY_GATE = "localhost-gateway";
8
+ export declare const COLLABORATION_SKILL_FIRST_COMPATIBILITY_GATE = "collaboration-skill-first";
9
+ export declare const TOKEN_BINDING_COMPATIBILITY_GATE = "token-binding";
10
+ export declare const POLICY_AUDIT_ENFORCEMENT_COMPATIBILITY_GATE = "policy-audit-enforcement";
11
+ export declare const MANAGED_RUNTIME_CONVERGENCE_COMPATIBILITY_GATE = "managed-runtime-convergence";
12
+ export declare const COMPATIBILITY_GATES_ENV = "AGENTS_HOST_INTERNAL_COMPATIBILITY_GATES";
13
+ export declare const INTERNAL_POLICY_MODE_ENV = "AGENTS_HOST_INTERNAL_POLICY_MODE";
14
+ export declare const INTERNAL_PROVIDER_IMPLEMENTATIONS_ENV = "AGENTS_HOST_INTERNAL_PROVIDER_IMPLEMENTATIONS";
15
+ export declare const MANAGED_RUNTIME_SETTINGS_SCHEMA_VERSION = 1;
16
+ export type InternalPolicyMode = 'audit-only' | 'enforce';
17
+ export type InternalProviderImplementationPath = 'v1' | 'v2';
18
+ export type InternalProviderImplementationKey = 'claude' | 'copilot';
19
+ export type InternalProviderImplementationOverrides = Partial<Record<InternalProviderImplementationKey, InternalProviderImplementationPath>>;
20
+ export interface ManagedRuntimeSettingsSnapshot {
21
+ schemaVersion: number;
22
+ compatibilityGates: string[];
23
+ providerImplementationOverrides: string[];
24
+ internalPolicyMode: InternalPolicyMode;
25
+ }
26
+ export declare function parseCompatibilityGates(rawValue: string | undefined): ReadonlySet<string>;
27
+ export declare function resolveInternalCompatibilityGates(): ReadonlySet<string>;
28
+ export declare function normalizeInternalProviderImplementationOverrides(rawValue: string | undefined): string[];
29
+ export declare function parseInternalProviderImplementationOverrides(rawValue: string | undefined): InternalProviderImplementationOverrides;
30
+ export declare function resolveManagedRuntimeProviderImplementationOverrides(env?: NodeJS.ProcessEnv, compatibilityGates?: string[]): string[];
31
+ export declare function resolveManagedRuntimeCompatibilityGates(env?: NodeJS.ProcessEnv): string[];
32
+ export declare function resolveInternalPolicyMode(gateEnabled: boolean, env?: NodeJS.ProcessEnv): InternalPolicyMode;
33
+ export declare function resolveManagedRuntimeSettingsSnapshot(env?: NodeJS.ProcessEnv): ManagedRuntimeSettingsSnapshot;
34
+ export declare function serializeManagedRuntimeSettingsSnapshot(snapshot: ManagedRuntimeSettingsSnapshot): string;
35
+ export declare function createManagedRuntimeSettingsFingerprint(snapshot: ManagedRuntimeSettingsSnapshot): string;