@phnx-labs/agents-cli 1.20.63 → 1.20.65
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/CHANGELOG.md +56 -3
- package/README.md +46 -2
- package/dist/bin/agents +0 -0
- package/dist/commands/apply.d.ts +12 -0
- package/dist/commands/apply.js +274 -0
- package/dist/commands/browser.js +2 -2
- package/dist/commands/cloud.js +32 -2
- package/dist/commands/doctor.js +4 -1
- package/dist/commands/exec.js +149 -77
- package/dist/commands/feed.d.ts +4 -0
- package/dist/commands/feed.js +52 -19
- package/dist/commands/hosts.js +44 -6
- package/dist/commands/lease.d.ts +23 -0
- package/dist/commands/lease.js +201 -0
- package/dist/commands/mailboxes.d.ts +20 -0
- package/dist/commands/mailboxes.js +390 -0
- package/dist/commands/mcp.js +55 -5
- package/dist/commands/monitors.d.ts +12 -0
- package/dist/commands/monitors.js +740 -0
- package/dist/commands/output.js +2 -2
- package/dist/commands/routines.js +43 -16
- package/dist/commands/secrets.d.ts +16 -0
- package/dist/commands/secrets.js +215 -64
- package/dist/commands/serve.js +31 -0
- package/dist/commands/sessions-export.d.ts +2 -0
- package/dist/commands/sessions-export.js +284 -0
- package/dist/commands/sessions-import.d.ts +2 -0
- package/dist/commands/sessions-import.js +230 -0
- package/dist/commands/sessions.d.ts +16 -0
- package/dist/commands/sessions.js +40 -6
- package/dist/commands/ssh.js +143 -5
- package/dist/commands/usage.d.ts +2 -0
- package/dist/commands/usage.js +7 -2
- package/dist/commands/versions.js +7 -3
- package/dist/commands/view.d.ts +27 -1
- package/dist/commands/view.js +32 -9
- package/dist/commands/webhook.js +10 -2
- package/dist/index.js +35 -14
- package/dist/lib/agents.d.ts +36 -0
- package/dist/lib/agents.js +80 -20
- package/dist/lib/auto-dispatch-provider.js +7 -2
- package/dist/lib/auto-dispatch.d.ts +3 -0
- package/dist/lib/auto-dispatch.js +3 -0
- package/dist/lib/browser/chrome.js +2 -2
- package/dist/lib/browser/drivers/ssh.js +19 -2
- package/dist/lib/cloud/antigravity.js +2 -2
- package/dist/lib/cloud/host.d.ts +59 -0
- package/dist/lib/cloud/host.js +224 -0
- package/dist/lib/cloud/registry.js +4 -0
- package/dist/lib/cloud/types.d.ts +6 -4
- package/dist/lib/comms-render.d.ts +37 -0
- package/dist/lib/comms-render.js +89 -0
- package/dist/lib/computer-rpc.js +3 -1
- package/dist/lib/crabbox/cli.d.ts +72 -0
- package/dist/lib/crabbox/cli.js +162 -9
- package/dist/lib/crabbox/runtimes.d.ts +13 -0
- package/dist/lib/crabbox/runtimes.js +35 -2
- package/dist/lib/daemon.d.ts +20 -4
- package/dist/lib/daemon.js +68 -20
- package/dist/lib/devices/fleet.d.ts +3 -2
- package/dist/lib/devices/fleet.js +9 -0
- package/dist/lib/devices/health.d.ts +77 -0
- package/dist/lib/devices/health.js +186 -0
- package/dist/lib/devices/registry.d.ts +15 -0
- package/dist/lib/devices/registry.js +9 -0
- package/dist/lib/exec.d.ts +19 -2
- package/dist/lib/exec.js +41 -13
- package/dist/lib/fleet/apply.d.ts +63 -0
- package/dist/lib/fleet/apply.js +214 -0
- package/dist/lib/fleet/auth-sync.d.ts +67 -0
- package/dist/lib/fleet/auth-sync.js +142 -0
- package/dist/lib/fleet/manifest.d.ts +29 -0
- package/dist/lib/fleet/manifest.js +127 -0
- package/dist/lib/fleet/types.d.ts +129 -0
- package/dist/lib/fleet/types.js +13 -0
- package/dist/lib/git.d.ts +27 -0
- package/dist/lib/git.js +34 -2
- package/dist/lib/hosts/dispatch.d.ts +29 -8
- package/dist/lib/hosts/dispatch.js +46 -18
- package/dist/lib/hosts/passthrough.js +2 -0
- package/dist/lib/hosts/providers/devices.d.ts +27 -0
- package/dist/lib/hosts/providers/devices.js +98 -0
- package/dist/lib/hosts/registry.d.ts +10 -16
- package/dist/lib/hosts/registry.js +17 -50
- package/dist/lib/hosts/remote-cmd.d.ts +23 -0
- package/dist/lib/hosts/remote-cmd.js +71 -0
- package/dist/lib/hosts/run-target.d.ts +84 -0
- package/dist/lib/hosts/run-target.js +99 -0
- package/dist/lib/hosts/types.d.ts +23 -5
- package/dist/lib/hosts/types.js +22 -4
- package/dist/lib/linear-autoclose.d.ts +30 -0
- package/dist/lib/linear-autoclose.js +22 -0
- package/dist/lib/mailbox.d.ts +39 -0
- package/dist/lib/mailbox.js +112 -0
- package/dist/lib/mcp.d.ts +27 -1
- package/dist/lib/mcp.js +126 -12
- package/dist/lib/monitors/config.d.ts +161 -0
- package/dist/lib/monitors/config.js +372 -0
- package/dist/lib/monitors/dispatch.d.ts +28 -0
- package/dist/lib/monitors/dispatch.js +91 -0
- package/dist/lib/monitors/engine.d.ts +61 -0
- package/dist/lib/monitors/engine.js +201 -0
- package/dist/lib/monitors/sources/command.d.ts +11 -0
- package/dist/lib/monitors/sources/command.js +31 -0
- package/dist/lib/monitors/sources/device.d.ts +13 -0
- package/dist/lib/monitors/sources/device.js +35 -0
- package/dist/lib/monitors/sources/file.d.ts +14 -0
- package/dist/lib/monitors/sources/file.js +57 -0
- package/dist/lib/monitors/sources/http.d.ts +10 -0
- package/dist/lib/monitors/sources/http.js +34 -0
- package/dist/lib/monitors/sources/index.d.ts +14 -0
- package/dist/lib/monitors/sources/index.js +31 -0
- package/dist/lib/monitors/sources/poll.d.ts +9 -0
- package/dist/lib/monitors/sources/poll.js +9 -0
- package/dist/lib/monitors/sources/types.d.ts +18 -0
- package/dist/lib/monitors/sources/types.js +9 -0
- package/dist/lib/monitors/sources/webhook.d.ts +23 -0
- package/dist/lib/monitors/sources/webhook.js +47 -0
- package/dist/lib/monitors/sources/ws.d.ts +14 -0
- package/dist/lib/monitors/sources/ws.js +45 -0
- package/dist/lib/monitors/state.d.ts +69 -0
- package/dist/lib/monitors/state.js +144 -0
- package/dist/lib/paths.d.ts +13 -0
- package/dist/lib/paths.js +26 -4
- package/dist/lib/platform/exec.d.ts +16 -0
- package/dist/lib/platform/exec.js +17 -0
- package/dist/lib/plugins.js +101 -2
- package/dist/lib/redact.d.ts +14 -1
- package/dist/lib/redact.js +47 -1
- package/dist/lib/remote-agents-json.js +7 -1
- package/dist/lib/rotate.d.ts +6 -3
- package/dist/lib/rotate.js +0 -1
- package/dist/lib/routines.d.ts +37 -2
- package/dist/lib/routines.js +54 -12
- package/dist/lib/runner.d.ts +1 -0
- package/dist/lib/runner.js +348 -13
- package/dist/lib/sandbox.d.ts +9 -1
- package/dist/lib/sandbox.js +11 -2
- package/dist/lib/secrets/agent.d.ts +48 -10
- package/dist/lib/secrets/agent.js +123 -15
- package/dist/lib/secrets/bundles.d.ts +26 -0
- package/dist/lib/secrets/bundles.js +59 -8
- package/dist/lib/secrets/mcp.js +4 -2
- package/dist/lib/secrets/remote.d.ts +17 -0
- package/dist/lib/secrets/remote.js +40 -0
- package/dist/lib/self-update.d.ts +20 -0
- package/dist/lib/self-update.js +54 -1
- package/dist/lib/serve/control.d.ts +95 -0
- package/dist/lib/serve/control.js +260 -0
- package/dist/lib/serve/server.d.ts +35 -1
- package/dist/lib/serve/server.js +106 -76
- package/dist/lib/serve/stream.d.ts +43 -0
- package/dist/lib/serve/stream.js +116 -0
- package/dist/lib/serve/token.d.ts +35 -0
- package/dist/lib/serve/token.js +85 -0
- package/dist/lib/session/bundle.d.ts +164 -0
- package/dist/lib/session/bundle.js +200 -0
- package/dist/lib/session/remote-bundle.d.ts +12 -0
- package/dist/lib/session/remote-bundle.js +61 -0
- package/dist/lib/session/remote-list.js +5 -1
- package/dist/lib/session/state.d.ts +7 -25
- package/dist/lib/session/state.js +16 -6
- package/dist/lib/session/sync/agents.d.ts +54 -6
- package/dist/lib/session/sync/agents.js +0 -0
- package/dist/lib/session/sync/config.js +8 -2
- package/dist/lib/session/sync/manifest.d.ts +14 -3
- package/dist/lib/session/sync/manifest.js +4 -0
- package/dist/lib/session/sync/sync.d.ts +23 -2
- package/dist/lib/session/sync/sync.js +177 -74
- package/dist/lib/session/types.d.ts +30 -0
- package/dist/lib/ssh-tunnel.d.ts +19 -1
- package/dist/lib/ssh-tunnel.js +99 -8
- package/dist/lib/staleness/detectors/subagents.d.ts +5 -0
- package/dist/lib/staleness/detectors/subagents.js +5 -192
- package/dist/lib/staleness/writers/subagents.d.ts +10 -0
- package/dist/lib/staleness/writers/subagents.js +11 -102
- package/dist/lib/startup/command-registry.d.ts +4 -0
- package/dist/lib/startup/command-registry.js +9 -0
- package/dist/lib/state.d.ts +5 -0
- package/dist/lib/state.js +12 -0
- package/dist/lib/subagents-registry.d.ts +85 -0
- package/dist/lib/subagents-registry.js +393 -0
- package/dist/lib/subagents.d.ts +8 -8
- package/dist/lib/subagents.js +32 -663
- package/dist/lib/sync-umbrella.d.ts +1 -0
- package/dist/lib/sync-umbrella.js +14 -3
- package/dist/lib/tmux/session.d.ts +7 -0
- package/dist/lib/tmux/session.js +3 -1
- package/dist/lib/triggers/webhook.d.ts +18 -0
- package/dist/lib/triggers/webhook.js +105 -0
- package/dist/lib/types.d.ts +35 -1
- package/dist/lib/usage.d.ts +42 -3
- package/dist/lib/usage.js +163 -21
- package/dist/lib/versions.js +14 -11
- package/dist/lib/workflows.d.ts +20 -0
- package/dist/lib/workflows.js +24 -0
- package/package.json +2 -1
package/dist/lib/ssh-tunnel.js
CHANGED
|
@@ -24,7 +24,7 @@ import { fileURLToPath } from 'url';
|
|
|
24
24
|
import { randomBytes, createHash } from 'crypto';
|
|
25
25
|
import { Readable } from 'stream';
|
|
26
26
|
import { pipeline } from 'stream/promises';
|
|
27
|
-
import { sshExec, SSH_OPTS } from './ssh-exec.js';
|
|
27
|
+
import { sshExec, SSH_OPTS, assertValidSshTarget } from './ssh-exec.js';
|
|
28
28
|
import { backgroundSpawnOptions } from './platform/process.js';
|
|
29
29
|
import { encodePowerShell } from './browser/drivers/ssh.js';
|
|
30
30
|
import { getDevice } from './devices/registry.js';
|
|
@@ -57,6 +57,18 @@ export function buildTunnelArgs(user, host, localPort, remotePort) {
|
|
|
57
57
|
*/
|
|
58
58
|
export function startSSHTunnel(user, host, localPort, remotePort, opts = {}) {
|
|
59
59
|
return new Promise((resolve, reject) => {
|
|
60
|
+
// `user`/`host` can originate from a browser ssh:// profile or a device
|
|
61
|
+
// record. buildTunnelArgs places `${user}@${host}` before `-N`/SSH_OPTS, so
|
|
62
|
+
// a `-`-leading user would be parsed as an ssh option flag (option
|
|
63
|
+
// injection). Validate at the spawn sink so every caller is covered; reject
|
|
64
|
+
// (rather than throw synchronously) to keep the Promise contract.
|
|
65
|
+
try {
|
|
66
|
+
assertValidSshTarget(`${user}@${host}`);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
reject(err);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
60
72
|
const args = buildTunnelArgs(user, host, localPort, remotePort);
|
|
61
73
|
const tunnel = spawn('ssh', args, {
|
|
62
74
|
stdio: opts.detached ? 'ignore' : ['ignore', 'ignore', 'pipe'],
|
|
@@ -91,6 +103,8 @@ export const REMOTE_HELPER_PORT = 8765;
|
|
|
91
103
|
export const REMOTE_TASK_NAME = 'AgentsComputerHelper';
|
|
92
104
|
/** Basename of the cross-published exe under native/computer-win/dist. */
|
|
93
105
|
export const WIN_HELPER_EXE = 'computer-helper-win.exe';
|
|
106
|
+
/** Basename of the daemon's shared-secret token file under %LOCALAPPDATA%\agents. */
|
|
107
|
+
export const WIN_HELPER_TOKEN_FILE = 'helper-token';
|
|
94
108
|
/**
|
|
95
109
|
* Locate a locally built Windows daemon exe — a repo-checkout build output from
|
|
96
110
|
* `scripts/build-win.sh`, or one bundled next to the package. Local paths are
|
|
@@ -222,6 +236,37 @@ export function clearRemoteState(device) {
|
|
|
222
236
|
/* already gone */
|
|
223
237
|
}
|
|
224
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Local file holding the shared-secret token for a device's helper daemon.
|
|
241
|
+
* Written at `setup --host` (0600), read at `start --host` so the RPC client
|
|
242
|
+
* authenticates. The remote daemon reads the same value from its own
|
|
243
|
+
* `--token-file`; the CLI is the source of truth and never round-trips it back.
|
|
244
|
+
*/
|
|
245
|
+
export function helperTokenPath(device) {
|
|
246
|
+
return path.join(remoteStateDir(), `${device}.token`);
|
|
247
|
+
}
|
|
248
|
+
export function readHelperToken(device) {
|
|
249
|
+
try {
|
|
250
|
+
const t = fs.readFileSync(helperTokenPath(device), 'utf-8').trim();
|
|
251
|
+
return t.length > 0 ? t : null;
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
export function writeHelperToken(device, token) {
|
|
258
|
+
const dir = remoteStateDir();
|
|
259
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
260
|
+
fs.writeFileSync(helperTokenPath(device), token, { mode: 0o600 });
|
|
261
|
+
}
|
|
262
|
+
export function clearHelperToken(device) {
|
|
263
|
+
try {
|
|
264
|
+
fs.unlinkSync(helperTokenPath(device));
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
/* already gone */
|
|
268
|
+
}
|
|
269
|
+
}
|
|
225
270
|
/** Resolve a registered device to its ssh pieces, or throw a clear error. */
|
|
226
271
|
export async function resolveRemoteDevice(name) {
|
|
227
272
|
const device = await getDevice(name);
|
|
@@ -272,10 +317,26 @@ export function buildVerifyPushScript(remotePath, expectedBytes) {
|
|
|
272
317
|
* survives ssh disconnect — the same rationale as the browser WMI launch. The
|
|
273
318
|
* task is started immediately so the caller need not log out/in.
|
|
274
319
|
*/
|
|
275
|
-
|
|
320
|
+
/**
|
|
321
|
+
* PowerShell that writes the shared-secret token under %LOCALAPPDATA%\agents
|
|
322
|
+
* with an owner-only ACL (inheritance removed, read granted only to the current
|
|
323
|
+
* user) and echoes the resolved path so the caller can pass it to `--token-file`.
|
|
324
|
+
*/
|
|
325
|
+
export function buildWriteTokenScript(token) {
|
|
326
|
+
return [
|
|
327
|
+
`$dir = Join-Path $env:LOCALAPPDATA 'agents'`,
|
|
328
|
+
`New-Item -ItemType Directory -Force -Path $dir | Out-Null`,
|
|
329
|
+
`$tok = Join-Path $dir '${WIN_HELPER_TOKEN_FILE}'`,
|
|
330
|
+
`Set-Content -LiteralPath $tok -Value ${psSingleQuote(token)} -NoNewline -Encoding ascii`,
|
|
331
|
+
`icacls $tok /inheritance:r /grant:r ("$($env:USERNAME):(R)") | Out-Null`,
|
|
332
|
+
`Write-Output $tok`,
|
|
333
|
+
].join('; ');
|
|
334
|
+
}
|
|
335
|
+
export function buildRegisterTaskScript(port, taskName, tokenPath) {
|
|
336
|
+
const argument = `--port ${port} --token-file "${tokenPath}"`;
|
|
276
337
|
return [
|
|
277
338
|
`$exe = Join-Path (Join-Path $env:LOCALAPPDATA 'agents') '${WIN_HELPER_EXE}'`,
|
|
278
|
-
`$action = New-ScheduledTaskAction -Execute $exe -Argument
|
|
339
|
+
`$action = New-ScheduledTaskAction -Execute $exe -Argument ${psSingleQuote(argument)}`,
|
|
279
340
|
`$trigger = New-ScheduledTaskTrigger -AtLogOn`,
|
|
280
341
|
`$principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType Interactive -RunLevel Highest`,
|
|
281
342
|
`$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit ([TimeSpan]::Zero)`,
|
|
@@ -357,13 +418,28 @@ export async function setupRemoteHelper(name) {
|
|
|
357
418
|
if (verify.code !== 0) {
|
|
358
419
|
throw new Error(`verifying helper exe on '${name}' failed (exit ${verify.code ?? 'null'}): ${verify.stderr.trim() || verify.stdout.trim()}`);
|
|
359
420
|
}
|
|
360
|
-
//
|
|
361
|
-
|
|
421
|
+
// Provision the auth token: generate it locally, write it on the remote with
|
|
422
|
+
// an owner-only ACL, and register the task with --token-file. The daemon now
|
|
423
|
+
// refuses to start without a token, so a token-less (open-to-any-local-process)
|
|
424
|
+
// daemon can no longer be stood up through the CLI.
|
|
425
|
+
const token = generateToken();
|
|
426
|
+
const tokWrite = sshExec(target, encodePowerShell(buildWriteTokenScript(token)), { timeoutMs: 60_000 });
|
|
427
|
+
if (tokWrite.code !== 0) {
|
|
428
|
+
throw new Error(`writing helper token on '${name}' failed (exit ${tokWrite.code ?? 'null'}): ${tokWrite.stderr.trim() || tokWrite.stdout.trim()}`);
|
|
429
|
+
}
|
|
430
|
+
const remoteTokenPath = tokWrite.stdout.trim().split(/\r?\n/).filter(Boolean).at(-1);
|
|
431
|
+
if (!remoteTokenPath) {
|
|
432
|
+
throw new Error(`writing helper token on '${name}' did not return a destination path`);
|
|
433
|
+
}
|
|
434
|
+
// Register + start the LOGON task, pointing it at the token file.
|
|
435
|
+
const reg = sshExec(target, encodePowerShell(buildRegisterTaskScript(REMOTE_HELPER_PORT, REMOTE_TASK_NAME, remoteTokenPath)), {
|
|
362
436
|
timeoutMs: 60_000,
|
|
363
437
|
});
|
|
364
438
|
if (reg.code !== 0) {
|
|
365
439
|
throw new Error(`registering scheduled task on '${name}' failed (exit ${reg.code ?? 'null'}): ${reg.stderr.trim() || reg.stdout.trim()}`);
|
|
366
440
|
}
|
|
441
|
+
// Persist the token locally so `start --host` authenticates to the daemon.
|
|
442
|
+
writeHelperToken(name, token);
|
|
367
443
|
return { target, taskName: REMOTE_TASK_NAME };
|
|
368
444
|
}
|
|
369
445
|
/** Reserve a free local TCP port by binding :0 and reading the assigned port. */
|
|
@@ -391,9 +467,17 @@ export async function startRemoteTunnel(name) {
|
|
|
391
467
|
const tunnelPid = tunnel.pid ?? 0;
|
|
392
468
|
// Verify the daemon answers through the tunnel before we record it. This is
|
|
393
469
|
// the real end-to-end check: tunnel up + daemon listening + RPC round-trips.
|
|
394
|
-
|
|
470
|
+
// The daemon now requires a token, so the probe must authenticate with the one
|
|
471
|
+
// provisioned at `setup`. A missing token means setup predates auth — guide
|
|
472
|
+
// the user to re-run it rather than silently failing the RPC.
|
|
473
|
+
const token = readHelperToken(name);
|
|
395
474
|
const prevTcp = process.env.COMPUTER_HELPER_TCP;
|
|
475
|
+
const prevTok = process.env.COMPUTER_HELPER_TOKEN;
|
|
396
476
|
process.env.COMPUTER_HELPER_TCP = `127.0.0.1:${localPort}`;
|
|
477
|
+
if (token)
|
|
478
|
+
process.env.COMPUTER_HELPER_TOKEN = token;
|
|
479
|
+
else
|
|
480
|
+
delete process.env.COMPUTER_HELPER_TOKEN;
|
|
397
481
|
const client = openComputerClient();
|
|
398
482
|
let ok = false;
|
|
399
483
|
let probeErr = '';
|
|
@@ -412,6 +496,10 @@ export async function startRemoteTunnel(name) {
|
|
|
412
496
|
delete process.env.COMPUTER_HELPER_TCP;
|
|
413
497
|
else
|
|
414
498
|
process.env.COMPUTER_HELPER_TCP = prevTcp;
|
|
499
|
+
if (prevTok === undefined)
|
|
500
|
+
delete process.env.COMPUTER_HELPER_TOKEN;
|
|
501
|
+
else
|
|
502
|
+
process.env.COMPUTER_HELPER_TOKEN = prevTok;
|
|
415
503
|
}
|
|
416
504
|
if (!ok) {
|
|
417
505
|
try {
|
|
@@ -419,8 +507,10 @@ export async function startRemoteTunnel(name) {
|
|
|
419
507
|
process.kill(tunnelPid);
|
|
420
508
|
}
|
|
421
509
|
catch { /* gone */ }
|
|
422
|
-
|
|
423
|
-
`Is it installed? Run: agents computer setup --host ${name}`
|
|
510
|
+
const hint = token
|
|
511
|
+
? `Is it installed? Run: agents computer setup --host ${name}`
|
|
512
|
+
: `No auth token on record for '${name}' — re-run: agents computer setup --host ${name}`;
|
|
513
|
+
throw new Error(`tunnel to '${name}' opened but the daemon did not answer (${probeErr}). ${hint}`);
|
|
424
514
|
}
|
|
425
515
|
const state = {
|
|
426
516
|
device: name,
|
|
@@ -461,6 +551,7 @@ export async function stopRemoteHelper(name) {
|
|
|
461
551
|
/* device gone / offline — local teardown still succeeds */
|
|
462
552
|
}
|
|
463
553
|
clearRemoteState(name);
|
|
554
|
+
clearHelperToken(name);
|
|
464
555
|
return { tunnelKilled, taskRemoved };
|
|
465
556
|
}
|
|
466
557
|
/**
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subagents detector. The installed-name enumeration for every agent's on-disk
|
|
3
|
+
* layout is declared once in the subagent registry; this detector is generic
|
|
4
|
+
* and delegates to `listInstalledSubagentNames` instead of a per-agent builder.
|
|
5
|
+
*/
|
|
1
6
|
import type { AgentId } from '../../types.js';
|
|
2
7
|
import type { ResourceDetector } from './types.js';
|
|
3
8
|
export declare const subagentsDetectors: Partial<Record<AgentId, ResourceDetector>>;
|
|
@@ -1,205 +1,18 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subagents detector. Claude/Gemini/Grok: flat .md files under `<agentDir>/agents/`.
|
|
3
|
-
* Codex: flat .toml files under `<versionHome>/.codex/agents/`.
|
|
4
|
-
* Droid: flat .md files under `<versionHome>/.factory/droids/`.
|
|
5
|
-
* Cursor: flat .md files under `<versionHome>/.cursor/agents/`.
|
|
6
|
-
* ForgeCode: flat .md files under `<versionHome>/.forge/agents/`.
|
|
7
|
-
* OpenClaw: subdirectories containing AGENTS.md under `<versionHome>/.openclaw/`.
|
|
8
|
-
* Mirrors versions.ts:521-539.
|
|
9
|
-
*/
|
|
10
|
-
import * as fs from 'fs';
|
|
11
|
-
import * as path from 'path';
|
|
12
1
|
import { capableAgents } from '../../capabilities.js';
|
|
2
|
+
import { listInstalledSubagentNames } from '../../subagents-registry.js';
|
|
13
3
|
import { lazyAgentMap } from '../writers/lazy-map.js';
|
|
14
|
-
function
|
|
4
|
+
function buildSubagentsDetector(agent) {
|
|
15
5
|
return {
|
|
16
6
|
kind: 'subagents',
|
|
17
7
|
agent,
|
|
18
8
|
list({ versionHome }) {
|
|
19
|
-
|
|
20
|
-
if (!fs.existsSync(agentsDir))
|
|
21
|
-
return [];
|
|
22
|
-
return fs.readdirSync(agentsDir)
|
|
23
|
-
.filter(f => f.endsWith('.md'))
|
|
24
|
-
.map(f => f.replace('.md', ''));
|
|
9
|
+
return listInstalledSubagentNames(agent, versionHome);
|
|
25
10
|
},
|
|
26
11
|
};
|
|
27
12
|
}
|
|
28
|
-
function buildClaudeDetector() {
|
|
29
|
-
return buildFlatMdAgentsDetector('claude', '.claude');
|
|
30
|
-
}
|
|
31
|
-
function buildGrokDetector() {
|
|
32
|
-
return buildFlatMdAgentsDetector('grok', '.grok');
|
|
33
|
-
}
|
|
34
|
-
function buildGeminiDetector() {
|
|
35
|
-
return buildFlatMdAgentsDetector('gemini', '.gemini');
|
|
36
|
-
}
|
|
37
|
-
function buildCodexDetector() {
|
|
38
|
-
return {
|
|
39
|
-
kind: 'subagents',
|
|
40
|
-
agent: 'codex',
|
|
41
|
-
list({ versionHome }) {
|
|
42
|
-
const agentsDir = path.join(versionHome, '.codex', 'agents');
|
|
43
|
-
if (!fs.existsSync(agentsDir))
|
|
44
|
-
return [];
|
|
45
|
-
return fs.readdirSync(agentsDir)
|
|
46
|
-
.filter(f => f.endsWith('.toml'))
|
|
47
|
-
.map(f => f.replace(/\.toml$/, ''));
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
function buildDroidDetector() {
|
|
52
|
-
return {
|
|
53
|
-
kind: 'subagents',
|
|
54
|
-
agent: 'droid',
|
|
55
|
-
list({ versionHome }) {
|
|
56
|
-
const droidsDir = path.join(versionHome, '.factory', 'droids');
|
|
57
|
-
if (!fs.existsSync(droidsDir))
|
|
58
|
-
return [];
|
|
59
|
-
return fs.readdirSync(droidsDir)
|
|
60
|
-
.filter(f => f.endsWith('.md'))
|
|
61
|
-
.map(f => f.replace('.md', ''));
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
function buildCopilotDetector() {
|
|
66
|
-
return {
|
|
67
|
-
kind: 'subagents',
|
|
68
|
-
agent: 'copilot',
|
|
69
|
-
list({ versionHome }) {
|
|
70
|
-
const agentsDir = path.join(versionHome, '.copilot', 'agents');
|
|
71
|
-
if (!fs.existsSync(agentsDir))
|
|
72
|
-
return [];
|
|
73
|
-
return fs.readdirSync(agentsDir)
|
|
74
|
-
.filter(f => f.endsWith('.agent.md'))
|
|
75
|
-
.map(f => f.replace('.agent.md', ''));
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
function buildCursorDetector() {
|
|
80
|
-
return {
|
|
81
|
-
kind: 'subagents',
|
|
82
|
-
agent: 'cursor',
|
|
83
|
-
list({ versionHome }) {
|
|
84
|
-
const agentsDir = path.join(versionHome, '.cursor', 'agents');
|
|
85
|
-
if (!fs.existsSync(agentsDir))
|
|
86
|
-
return [];
|
|
87
|
-
return fs.readdirSync(agentsDir)
|
|
88
|
-
.filter(f => f.endsWith('.md'))
|
|
89
|
-
.map(f => f.replace(/\.md$/, ''));
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
function buildOpenclawDetector() {
|
|
94
|
-
return {
|
|
95
|
-
kind: 'subagents',
|
|
96
|
-
agent: 'openclaw',
|
|
97
|
-
list({ versionHome }) {
|
|
98
|
-
const openclawDir = path.join(versionHome, '.openclaw');
|
|
99
|
-
if (!fs.existsSync(openclawDir))
|
|
100
|
-
return [];
|
|
101
|
-
return fs.readdirSync(openclawDir, { withFileTypes: true })
|
|
102
|
-
.filter(d => d.isDirectory() && fs.existsSync(path.join(openclawDir, d.name, 'AGENTS.md')))
|
|
103
|
-
.map(d => d.name);
|
|
104
|
-
},
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
function buildKimiDetector() {
|
|
108
|
-
return {
|
|
109
|
-
kind: 'subagents',
|
|
110
|
-
agent: 'kimi',
|
|
111
|
-
list({ versionHome }) {
|
|
112
|
-
const agentsDir = path.join(versionHome, '.kimi-code', 'agents');
|
|
113
|
-
if (!fs.existsSync(agentsDir))
|
|
114
|
-
return [];
|
|
115
|
-
// Parent is `_agents-cli.yaml` (underscore-prefixed reserved name).
|
|
116
|
-
return fs.readdirSync(agentsDir)
|
|
117
|
-
.filter(f => f.endsWith('.yaml') && !f.startsWith('_'))
|
|
118
|
-
.map(f => f.replace(/\.yaml$/, ''));
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
function buildKiroDetector() {
|
|
123
|
-
return {
|
|
124
|
-
kind: 'subagents',
|
|
125
|
-
agent: 'kiro',
|
|
126
|
-
list({ versionHome }) {
|
|
127
|
-
const agentsDir = path.join(versionHome, '.kiro', 'agents');
|
|
128
|
-
if (!fs.existsSync(agentsDir))
|
|
129
|
-
return [];
|
|
130
|
-
return fs.readdirSync(agentsDir)
|
|
131
|
-
.filter(f => f.endsWith('.json'))
|
|
132
|
-
.map(f => f.replace(/\.json$/, ''));
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
function buildForgeDetector() {
|
|
137
|
-
return buildFlatMdAgentsDetector('forge', '.forge');
|
|
138
|
-
}
|
|
139
|
-
function buildGooseDetector() {
|
|
140
|
-
return {
|
|
141
|
-
kind: 'subagents',
|
|
142
|
-
agent: 'goose',
|
|
143
|
-
list({ versionHome }) {
|
|
144
|
-
const agentsDir = path.join(versionHome, '.config', 'goose', 'agents');
|
|
145
|
-
if (!fs.existsSync(agentsDir))
|
|
146
|
-
return [];
|
|
147
|
-
return fs.readdirSync(agentsDir)
|
|
148
|
-
.filter(f => f.endsWith('.yaml'))
|
|
149
|
-
.map(f => f.replace(/\.yaml$/, ''));
|
|
150
|
-
},
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
function buildOpenCodeDetector() {
|
|
154
|
-
return {
|
|
155
|
-
kind: 'subagents',
|
|
156
|
-
agent: 'opencode',
|
|
157
|
-
list({ versionHome }) {
|
|
158
|
-
const agentsDir = path.join(versionHome, '.config', 'opencode', 'agents');
|
|
159
|
-
if (!fs.existsSync(agentsDir))
|
|
160
|
-
return [];
|
|
161
|
-
return fs.readdirSync(agentsDir)
|
|
162
|
-
.filter(f => f.endsWith('.md'))
|
|
163
|
-
.map(f => f.replace(/\.md$/, ''));
|
|
164
|
-
},
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
function buildAntigravityDetector() {
|
|
168
|
-
return {
|
|
169
|
-
kind: 'subagents',
|
|
170
|
-
agent: 'antigravity',
|
|
171
|
-
list({ versionHome }) {
|
|
172
|
-
const agentsDir = path.join(versionHome, '.gemini', 'config', 'agents');
|
|
173
|
-
if (!fs.existsSync(agentsDir))
|
|
174
|
-
return [];
|
|
175
|
-
return fs.readdirSync(agentsDir, { withFileTypes: true })
|
|
176
|
-
.filter(d => d.isDirectory() && fs.existsSync(path.join(agentsDir, d.name, 'agent.md')))
|
|
177
|
-
.map(d => d.name);
|
|
178
|
-
},
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
const handlers = {
|
|
182
|
-
claude: buildClaudeDetector,
|
|
183
|
-
copilot: buildCopilotDetector,
|
|
184
|
-
gemini: buildGeminiDetector,
|
|
185
|
-
grok: buildGrokDetector,
|
|
186
|
-
codex: buildCodexDetector,
|
|
187
|
-
kimi: buildKimiDetector,
|
|
188
|
-
opencode: buildOpenCodeDetector,
|
|
189
|
-
antigravity: buildAntigravityDetector,
|
|
190
|
-
droid: buildDroidDetector,
|
|
191
|
-
openclaw: buildOpenclawDetector,
|
|
192
|
-
kiro: buildKiroDetector,
|
|
193
|
-
cursor: buildCursorDetector,
|
|
194
|
-
forge: buildForgeDetector,
|
|
195
|
-
goose: buildGooseDetector,
|
|
196
|
-
};
|
|
197
13
|
export const subagentsDetectors = lazyAgentMap(() => {
|
|
198
14
|
const m = {};
|
|
199
|
-
for (const agent of capableAgents('subagents'))
|
|
200
|
-
|
|
201
|
-
if (f)
|
|
202
|
-
m[agent] = f();
|
|
203
|
-
}
|
|
15
|
+
for (const agent of capableAgents('subagents'))
|
|
16
|
+
m[agent] = buildSubagentsDetector(agent);
|
|
204
17
|
return m;
|
|
205
18
|
});
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subagents writer. Every agent's on-disk layout (target dir, file/dir shape,
|
|
3
|
+
* transform, and any post-sync finalize such as Kimi's parent index) is
|
|
4
|
+
* declared once in the subagent registry; this writer is generic and iterates
|
|
5
|
+
* the registry instead of a per-agent `else if` chain.
|
|
6
|
+
*
|
|
7
|
+
* Source-side discovery is `listInstalledSubagents` from lib/subagents.ts —
|
|
8
|
+
* it reads user + system layers only (project layer excluded for the same
|
|
9
|
+
* defense as commands/skills/hooks).
|
|
10
|
+
*/
|
|
1
11
|
import type { AgentId } from '../../types.js';
|
|
2
12
|
import type { ResourceWriter } from './types.js';
|
|
3
13
|
export declare const subagentsWriters: Partial<Record<AgentId, ResourceWriter<string[]>>>;
|
|
@@ -1,123 +1,32 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subagents writer. Claude/Gemini/Grok flatten each subagent into a single
|
|
3
|
-
* .md file under their native agents directory. Codex writes TOML under
|
|
4
|
-
* `.codex/agents/`.
|
|
5
|
-
* Droid (Factory AI) flattens each into a custom droid .md under
|
|
6
|
-
* `<versionHome>/.factory/droids/`. Cursor flattens each into a custom
|
|
7
|
-
* subagent .md under `<versionHome>/.cursor/agents/`. OpenClaw copies the
|
|
8
|
-
* full subagent directory (with AGENT.md renamed to AGENTS.md) into
|
|
9
|
-
* `<versionHome>/.openclaw/<name>/`.
|
|
10
|
-
*
|
|
11
|
-
* Source-side discovery is `listInstalledSubagents` from lib/subagents.ts —
|
|
12
|
-
* it reads user + system layers only (project layer excluded for the same
|
|
13
|
-
* defense as commands/skills/hooks).
|
|
14
|
-
*/
|
|
15
|
-
import * as fs from 'fs';
|
|
16
|
-
import * as path from 'path';
|
|
17
1
|
import { capableAgents } from '../../capabilities.js';
|
|
18
|
-
import { listInstalledSubagents
|
|
19
|
-
import {
|
|
2
|
+
import { listInstalledSubagents } from '../../subagents.js';
|
|
3
|
+
import { subagentTarget } from '../../subagents-registry.js';
|
|
20
4
|
import { lazyAgentMap } from './lazy-map.js';
|
|
21
5
|
function buildSubagentsWriter(agent) {
|
|
22
6
|
return {
|
|
23
7
|
kind: 'subagents',
|
|
24
8
|
agent,
|
|
25
9
|
write({ versionHome, selection }) {
|
|
10
|
+
const target = subagentTarget(agent);
|
|
11
|
+
if (!target)
|
|
12
|
+
return { synced: [] };
|
|
26
13
|
const all = listInstalledSubagents();
|
|
27
14
|
const map = new Map(all.map(s => [s.name, s]));
|
|
15
|
+
const dir = target.dir(versionHome);
|
|
28
16
|
const synced = [];
|
|
29
17
|
for (const name of selection) {
|
|
30
18
|
const sub = map.get(name);
|
|
31
19
|
if (!sub)
|
|
32
20
|
continue;
|
|
33
21
|
try {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const agentsDir = path.join(versionHome, agentsRoot, 'agents');
|
|
37
|
-
fs.mkdirSync(agentsDir, { recursive: true });
|
|
38
|
-
fs.writeFileSync(safeJoin(agentsDir, `${sub.name}.md`), transformSubagentForClaude(sub.path));
|
|
39
|
-
synced.push(sub.name);
|
|
40
|
-
}
|
|
41
|
-
else if (agent === 'codex') {
|
|
42
|
-
const agentsDir = path.join(versionHome, '.codex', 'agents');
|
|
43
|
-
fs.mkdirSync(agentsDir, { recursive: true });
|
|
44
|
-
fs.writeFileSync(safeJoin(agentsDir, `${sub.name}.toml`), transformSubagentForCodex(sub.path));
|
|
45
|
-
synced.push(sub.name);
|
|
46
|
-
}
|
|
47
|
-
else if (agent === 'kimi') {
|
|
48
|
-
writeKimiSubagentFiles(path.join(versionHome, '.kimi-code', 'agents'), sub.path, sub.name);
|
|
49
|
-
synced.push(sub.name);
|
|
50
|
-
}
|
|
51
|
-
else if (agent === 'opencode') {
|
|
52
|
-
const agentsDir = path.join(versionHome, '.config', 'opencode', 'agents');
|
|
53
|
-
fs.mkdirSync(agentsDir, { recursive: true });
|
|
54
|
-
fs.writeFileSync(safeJoin(agentsDir, `${sub.name}.md`), transformSubagentForOpenCode(sub.path));
|
|
55
|
-
synced.push(sub.name);
|
|
56
|
-
}
|
|
57
|
-
else if (agent === 'antigravity') {
|
|
58
|
-
const agentDir = safeJoin(path.join(versionHome, '.gemini', 'config', 'agents'), sub.name);
|
|
59
|
-
fs.mkdirSync(agentDir, { recursive: true });
|
|
60
|
-
fs.writeFileSync(safeJoin(agentDir, 'agent.md'), transformSubagentForAntigravity(sub.path));
|
|
61
|
-
synced.push(sub.name);
|
|
62
|
-
}
|
|
63
|
-
else if (agent === 'droid') {
|
|
64
|
-
const droidsDir = path.join(versionHome, '.factory', 'droids');
|
|
65
|
-
fs.mkdirSync(droidsDir, { recursive: true });
|
|
66
|
-
fs.writeFileSync(safeJoin(droidsDir, `${sub.name}.md`), transformSubagentForDroid(sub.path));
|
|
67
|
-
synced.push(sub.name);
|
|
68
|
-
}
|
|
69
|
-
else if (agent === 'copilot') {
|
|
70
|
-
const agentsDir = path.join(versionHome, '.copilot', 'agents');
|
|
71
|
-
fs.mkdirSync(agentsDir, { recursive: true });
|
|
72
|
-
fs.writeFileSync(safeJoin(agentsDir, `${sub.name}.agent.md`), transformSubagentForCopilot(sub.path));
|
|
73
|
-
synced.push(sub.name);
|
|
74
|
-
}
|
|
75
|
-
else if (agent === 'openclaw') {
|
|
76
|
-
const target = safeJoin(path.join(versionHome, '.openclaw'), sub.name);
|
|
77
|
-
const r = syncSubagentToOpenclaw(sub.path, target);
|
|
78
|
-
if (r.success)
|
|
79
|
-
synced.push(sub.name);
|
|
80
|
-
}
|
|
81
|
-
else if (agent === 'kiro') {
|
|
82
|
-
const agentsDir = path.join(versionHome, '.kiro', 'agents');
|
|
83
|
-
fs.mkdirSync(agentsDir, { recursive: true });
|
|
84
|
-
fs.writeFileSync(safeJoin(agentsDir, `${sub.name}.json`), transformSubagentForKiro(sub.path));
|
|
85
|
-
synced.push(sub.name);
|
|
86
|
-
}
|
|
87
|
-
else if (agent === 'cursor') {
|
|
88
|
-
const agentsDir = path.join(versionHome, '.cursor', 'agents');
|
|
89
|
-
fs.mkdirSync(agentsDir, { recursive: true });
|
|
90
|
-
fs.writeFileSync(safeJoin(agentsDir, `${sub.name}.md`), transformSubagentForCursor(sub.path));
|
|
91
|
-
synced.push(sub.name);
|
|
92
|
-
}
|
|
93
|
-
else if (agent === 'forge') {
|
|
94
|
-
const agentsDir = path.join(versionHome, '.forge', 'agents');
|
|
95
|
-
fs.mkdirSync(agentsDir, { recursive: true });
|
|
96
|
-
fs.writeFileSync(safeJoin(agentsDir, `${sub.name}.md`), transformSubagentForForge(sub.path));
|
|
97
|
-
synced.push(sub.name);
|
|
98
|
-
}
|
|
99
|
-
else if (agent === 'goose') {
|
|
100
|
-
const agentsDir = path.join(versionHome, '.config', 'goose', 'agents');
|
|
101
|
-
fs.mkdirSync(agentsDir, { recursive: true });
|
|
102
|
-
fs.writeFileSync(safeJoin(agentsDir, `${sub.name}.yaml`), transformSubagentForGoose(sub.path));
|
|
103
|
-
synced.push(sub.name);
|
|
104
|
-
}
|
|
22
|
+
target.write(dir, sub);
|
|
23
|
+
synced.push(sub.name);
|
|
105
24
|
}
|
|
106
25
|
catch { /* per-item sync failure: skip */ }
|
|
107
26
|
}
|
|
108
|
-
//
|
|
109
|
-
if (
|
|
110
|
-
|
|
111
|
-
const entries = synced.map((name) => {
|
|
112
|
-
const sub = map.get(name);
|
|
113
|
-
const fm = parseSubagentFrontmatter(path.join(sub.path, 'AGENT.md'));
|
|
114
|
-
return {
|
|
115
|
-
name,
|
|
116
|
-
description: fm?.description ?? name,
|
|
117
|
-
relativePath: `./${name}.yaml`,
|
|
118
|
-
};
|
|
119
|
-
});
|
|
120
|
-
fs.writeFileSync(safeJoin(agentsDir, KIMI_SUBAGENTS_PARENT_FILE), buildKimiSubagentsParentYaml(entries));
|
|
27
|
+
// Optional cross-item pass (e.g. Kimi's `_agents-cli.yaml` parent index).
|
|
28
|
+
if (target.finalize && synced.length > 0) {
|
|
29
|
+
target.finalize(dir, synced.map((name) => map.get(name)));
|
|
121
30
|
}
|
|
122
31
|
return { synced };
|
|
123
32
|
},
|
|
@@ -43,6 +43,7 @@ export declare const loadImport: ModuleLoader;
|
|
|
43
43
|
export declare const loadPackages: ModuleLoader;
|
|
44
44
|
export declare const loadDaemon: ModuleLoader;
|
|
45
45
|
export declare const loadRoutines: ModuleLoader;
|
|
46
|
+
export declare const loadMonitors: ModuleLoader;
|
|
46
47
|
export declare const loadRun: ModuleLoader;
|
|
47
48
|
export declare const loadDefaults: ModuleLoader;
|
|
48
49
|
export declare const loadModels: ModuleLoader;
|
|
@@ -50,6 +51,7 @@ export declare const loadPrune: ModuleLoader;
|
|
|
50
51
|
export declare const loadTrash: ModuleLoader;
|
|
51
52
|
export declare const loadRestore: ModuleLoader;
|
|
52
53
|
export declare const loadDoctor: ModuleLoader;
|
|
54
|
+
export declare const loadApply: ModuleLoader;
|
|
53
55
|
export declare const loadCheck: ModuleLoader;
|
|
54
56
|
export declare const loadStatus: ModuleLoader;
|
|
55
57
|
export declare const loadProfiles: ModuleLoader;
|
|
@@ -74,6 +76,7 @@ export declare const loadWatchdog: ModuleLoader;
|
|
|
74
76
|
export declare const loadBrowser: ModuleLoader;
|
|
75
77
|
export declare const loadComputer: ModuleLoader;
|
|
76
78
|
export declare const loadHosts: ModuleLoader;
|
|
79
|
+
export declare const loadLease: ModuleLoader;
|
|
77
80
|
export declare const loadLogs: ModuleLoader;
|
|
78
81
|
export declare const loadEvents: ModuleLoader;
|
|
79
82
|
export declare const loadSsh: ModuleLoader;
|
|
@@ -86,6 +89,7 @@ export declare const loadTeams: ModuleLoader;
|
|
|
86
89
|
export declare const loadCloud: ModuleLoader;
|
|
87
90
|
export declare const loadMessage: ModuleLoader;
|
|
88
91
|
export declare const loadFeed: ModuleLoader;
|
|
92
|
+
export declare const loadMailboxes: ModuleLoader;
|
|
89
93
|
export declare const loadServe: ModuleLoader;
|
|
90
94
|
export declare const loadAudit: ModuleLoader;
|
|
91
95
|
export declare const loadWebhook: ModuleLoader;
|
|
@@ -21,6 +21,7 @@ export const loadImport = async () => (await import('../../commands/import.js'))
|
|
|
21
21
|
export const loadPackages = async () => (await import('../../commands/packages.js')).registerPackagesCommands;
|
|
22
22
|
export const loadDaemon = async () => (await import('../../commands/daemon.js')).registerDaemonCommands;
|
|
23
23
|
export const loadRoutines = async () => (await import('../../commands/routines.js')).registerRoutinesCommands;
|
|
24
|
+
export const loadMonitors = async () => (await import('../../commands/monitors.js')).registerMonitorsCommands;
|
|
24
25
|
export const loadRun = async () => (await import('../../commands/exec.js')).registerRunCommand;
|
|
25
26
|
export const loadDefaults = async () => (await import('../../commands/defaults.js')).registerDefaultsCommands;
|
|
26
27
|
export const loadModels = async () => (await import('../../commands/models.js')).registerModelsCommand;
|
|
@@ -28,6 +29,7 @@ export const loadPrune = async () => (await import('../../commands/prune.js')).r
|
|
|
28
29
|
export const loadTrash = async () => (await import('../../commands/trash.js')).registerTrashCommands;
|
|
29
30
|
export const loadRestore = async () => (await import('../../commands/trash.js')).registerRestoreCommand;
|
|
30
31
|
export const loadDoctor = async () => (await import('../../commands/doctor.js')).registerDoctorCommand;
|
|
32
|
+
export const loadApply = async () => (await import('../../commands/apply.js')).registerApplyCommand;
|
|
31
33
|
export const loadCheck = async () => (await import('../../commands/check.js')).registerCheckCommand;
|
|
32
34
|
export const loadStatus = async () => (await import('../../commands/status.js')).registerStatusCommand;
|
|
33
35
|
export const loadProfiles = async () => (await import('../../commands/profiles.js')).registerProfilesCommands;
|
|
@@ -52,6 +54,7 @@ export const loadWatchdog = async () => (await import('../../commands/watchdog.j
|
|
|
52
54
|
export const loadBrowser = async () => (await import('../../commands/browser.js')).registerBrowserCommand;
|
|
53
55
|
export const loadComputer = async () => (await import('../../commands/computer.js')).registerComputerCommand;
|
|
54
56
|
export const loadHosts = async () => (await import('../../commands/hosts.js')).registerHostsCommand;
|
|
57
|
+
export const loadLease = async () => (await import('../../commands/lease.js')).registerLeaseCommand;
|
|
55
58
|
export const loadLogs = async () => (await import('../../commands/logs.js')).registerLogsCommand;
|
|
56
59
|
export const loadEvents = async () => (await import('../../commands/events.js')).registerEventsCommand;
|
|
57
60
|
export const loadSsh = async () => (await import('../../commands/ssh.js')).registerSshCommands;
|
|
@@ -64,6 +67,7 @@ export const loadTeams = async () => (await import('../../commands/teams.js')).r
|
|
|
64
67
|
export const loadCloud = async () => (await import('../../commands/cloud.js')).registerCloudCommands;
|
|
65
68
|
export const loadMessage = async () => (await import('../../commands/message.js')).registerMessageCommand;
|
|
66
69
|
export const loadFeed = async () => (await import('../../commands/feed.js')).registerFeedCommand;
|
|
70
|
+
export const loadMailboxes = async () => (await import('../../commands/mailboxes.js')).registerMailboxesCommand;
|
|
67
71
|
export const loadServe = async () => (await import('../../commands/serve.js')).registerServeCommand;
|
|
68
72
|
export const loadAudit = async () => (await import('../../commands/audit.js')).registerAuditCommands;
|
|
69
73
|
export const loadWebhook = async () => (await import('../../commands/webhook.js')).registerWebhookCommand;
|
|
@@ -119,12 +123,14 @@ export const COMMAND_LOADERS = {
|
|
|
119
123
|
install: [loadPackages],
|
|
120
124
|
daemon: [loadDaemon],
|
|
121
125
|
routines: [loadRoutines],
|
|
126
|
+
monitors: [loadMonitors],
|
|
122
127
|
run: [loadRun],
|
|
123
128
|
defaults: [loadDefaults],
|
|
124
129
|
models: [loadModels],
|
|
125
130
|
trash: [loadTrash],
|
|
126
131
|
restore: [loadRestore],
|
|
127
132
|
doctor: [loadDoctor],
|
|
133
|
+
apply: [loadApply],
|
|
128
134
|
check: [loadCheck],
|
|
129
135
|
status: [loadStatus],
|
|
130
136
|
profiles: [loadProfiles],
|
|
@@ -149,6 +155,7 @@ export const COMMAND_LOADERS = {
|
|
|
149
155
|
browser: [loadBrowser],
|
|
150
156
|
computer: [loadComputer],
|
|
151
157
|
hosts: [loadHosts],
|
|
158
|
+
lease: [loadLease],
|
|
152
159
|
logs: [loadLogs],
|
|
153
160
|
events: [loadEvents],
|
|
154
161
|
ssh: [loadSsh],
|
|
@@ -169,6 +176,8 @@ export const COMMAND_LOADERS = {
|
|
|
169
176
|
cloud: [loadCloud],
|
|
170
177
|
message: [loadMessage],
|
|
171
178
|
feed: [loadFeed],
|
|
179
|
+
mailboxes: [loadMailboxes],
|
|
180
|
+
mailbox: [loadMailboxes],
|
|
172
181
|
serve: [loadServe],
|
|
173
182
|
audit: [loadAudit],
|
|
174
183
|
webhook: [loadWebhook],
|
package/dist/lib/state.d.ts
CHANGED
|
@@ -128,6 +128,11 @@ export declare function getSystemRoutinesDir(): string;
|
|
|
128
128
|
export declare function getProjectRoutinesDir(cwd?: string): string | null;
|
|
129
129
|
/** Path to routine execution logs (~/.agents/.history/runs/). */
|
|
130
130
|
export declare function getRunsDir(): string;
|
|
131
|
+
/** Path to monitor YAML definitions (~/.agents/monitors/). */
|
|
132
|
+
export declare function getMonitorsDir(): string;
|
|
133
|
+
/** Path to the durable per-monitor state-diff store + fire history
|
|
134
|
+
* (~/.agents/.history/monitors/). */
|
|
135
|
+
export declare function getMonitorsHistoryDir(): string;
|
|
131
136
|
/** Root for per-agent mailboxes (~/.agents/.history/mailbox/). */
|
|
132
137
|
export declare function getMailboxRootDir(): string;
|
|
133
138
|
/** Root for open-block feed records (~/.agents/.history/feed/). */
|