@phnx-labs/agents-cli 1.20.71 → 1.20.73
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 +325 -1
- package/README.md +40 -4
- package/dist/bin/agents +0 -0
- package/dist/commands/activity.d.ts +12 -0
- package/dist/commands/activity.js +68 -0
- package/dist/commands/apply.d.ts +13 -0
- package/dist/commands/apply.js +28 -3
- package/dist/commands/browser.js +1 -1
- package/dist/commands/cloud.js +21 -11
- package/dist/commands/commands.js +2 -0
- package/dist/commands/doctor.js +8 -4
- package/dist/commands/events.d.ts +11 -10
- package/dist/commands/events.js +30 -21
- package/dist/commands/exec.d.ts +34 -0
- package/dist/commands/exec.js +337 -39
- package/dist/commands/feed.d.ts +13 -0
- package/dist/commands/feed.js +130 -29
- package/dist/commands/hq.d.ts +2 -0
- package/dist/commands/hq.js +58 -0
- package/dist/commands/lease.d.ts +19 -0
- package/dist/commands/lease.js +138 -11
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +123 -0
- package/dist/commands/logs.js +39 -10
- package/dist/commands/mcp.js +2 -0
- package/dist/commands/mine.d.ts +27 -0
- package/dist/commands/mine.js +207 -0
- package/dist/commands/monitors.js +79 -49
- package/dist/commands/plugins.js +1 -0
- package/dist/commands/profiles.js +158 -0
- package/dist/commands/repo.js +2 -60
- package/dist/commands/resource-view.d.ts +2 -0
- package/dist/commands/resource-view.js +8 -0
- package/dist/commands/resources.d.ts +5 -0
- package/dist/commands/resources.js +95 -0
- package/dist/commands/routines.d.ts +2 -0
- package/dist/commands/routines.js +139 -37
- package/dist/commands/secrets.js +234 -47
- package/dist/commands/send.d.ts +15 -0
- package/dist/commands/send.js +62 -0
- package/dist/commands/sessions-tail.d.ts +1 -0
- package/dist/commands/sessions-tail.js +20 -9
- package/dist/commands/sessions.d.ts +6 -0
- package/dist/commands/sessions.js +26 -3
- package/dist/commands/setup-mine.d.ts +18 -0
- package/dist/commands/setup-mine.js +106 -0
- package/dist/commands/setup-share.js +2 -2
- package/dist/commands/setup.js +3 -1
- package/dist/commands/share.d.ts +8 -1
- package/dist/commands/share.js +122 -37
- package/dist/commands/skills.js +2 -0
- package/dist/commands/ssh.d.ts +9 -0
- package/dist/commands/ssh.js +196 -26
- package/dist/commands/status.js +8 -2
- package/dist/commands/subagents.js +3 -1
- package/dist/commands/sync.js +1 -1
- package/dist/commands/teams.js +11 -2
- package/dist/commands/uninstall.d.ts +11 -0
- package/dist/commands/uninstall.js +158 -0
- package/dist/commands/utils.d.ts +29 -0
- package/dist/commands/utils.js +24 -0
- package/dist/commands/versions.js +120 -11
- package/dist/index.js +83 -12
- package/dist/lib/activity.d.ts +124 -0
- package/dist/lib/activity.js +542 -0
- package/dist/lib/agents.js +16 -5
- package/dist/lib/artifact-actions.d.ts +1 -1
- package/dist/lib/artifact-actions.js +1 -1
- package/dist/lib/ask-classifier.d.ts +2 -1
- package/dist/lib/ask-classifier.js +3 -3
- package/dist/lib/auth-health.d.ts +32 -4
- package/dist/lib/auth-health.js +40 -1
- package/dist/lib/auto-pull.js +8 -1
- package/dist/lib/brand.d.ts +40 -0
- package/dist/lib/brand.js +122 -0
- package/dist/lib/browser/drivers/ssh.js +4 -7
- package/dist/lib/browser/service.js +6 -8
- package/dist/lib/channels/providers/index.d.ts +2 -0
- package/dist/lib/channels/providers/index.js +20 -0
- package/dist/lib/channels/providers/mailbox.d.ts +2 -0
- package/dist/lib/channels/providers/mailbox.js +26 -0
- package/dist/lib/channels/providers/openclaw-telegram.d.ts +2 -0
- package/dist/lib/channels/providers/openclaw-telegram.js +34 -0
- package/dist/lib/channels/providers/rush.d.ts +6 -0
- package/dist/lib/channels/providers/rush.js +55 -0
- package/dist/lib/channels/registry.d.ts +42 -0
- package/dist/lib/channels/registry.js +20 -0
- package/dist/lib/channels/resolve.d.ts +11 -0
- package/dist/lib/channels/resolve.js +12 -0
- package/dist/lib/cli-resources.d.ts +18 -0
- package/dist/lib/cli-resources.js +53 -4
- package/dist/lib/cloud/codex.js +6 -3
- package/dist/lib/cloud/factory.d.ts +1 -0
- package/dist/lib/cloud/factory.js +10 -4
- package/dist/lib/cloud/rush.d.ts +3 -1
- package/dist/lib/cloud/rush.js +6 -1
- package/dist/lib/cloud/types.d.ts +2 -0
- package/dist/lib/codex-home.d.ts +35 -0
- package/dist/lib/codex-home.js +136 -0
- package/dist/lib/crabbox/cli.d.ts +44 -0
- package/dist/lib/crabbox/cli.js +120 -20
- package/dist/lib/crabbox/lease.d.ts +52 -1
- package/dist/lib/crabbox/lease.js +117 -16
- package/dist/lib/crabbox/progress.d.ts +31 -0
- package/dist/lib/crabbox/progress.js +76 -0
- package/dist/lib/crabbox/runtimes.d.ts +4 -0
- package/dist/lib/crabbox/runtimes.js +33 -8
- package/dist/lib/crabbox/setup-copy.d.ts +87 -0
- package/dist/lib/crabbox/setup-copy.js +127 -0
- package/dist/lib/daemon.d.ts +14 -5
- package/dist/lib/daemon.js +52 -9
- package/dist/lib/drive-sync.js +6 -3
- package/dist/lib/event-stream.d.ts +36 -0
- package/dist/lib/event-stream.js +68 -0
- package/dist/lib/events.d.ts +1 -1
- package/dist/lib/exec.d.ts +11 -0
- package/dist/lib/exec.js +23 -2
- package/dist/lib/feed-policy.d.ts +1 -1
- package/dist/lib/feed-policy.js +14 -9
- package/dist/lib/feed-ranking.d.ts +32 -0
- package/dist/lib/feed-ranking.js +224 -0
- package/dist/lib/feed.d.ts +35 -2
- package/dist/lib/feed.js +66 -3
- package/dist/lib/fleet/auth-sync.d.ts +53 -0
- package/dist/lib/fleet/auth-sync.js +92 -0
- package/dist/lib/fleet/remote-login.d.ts +187 -0
- package/dist/lib/fleet/remote-login.js +556 -0
- package/dist/lib/format.d.ts +30 -3
- package/dist/lib/format.js +34 -5
- package/dist/lib/fs-atomic.d.ts +7 -2
- package/dist/lib/fs-atomic.js +8 -12
- package/dist/lib/git.d.ts +16 -0
- package/dist/lib/git.js +79 -2
- package/dist/lib/heal.js +11 -3
- package/dist/lib/hosts/logs.d.ts +12 -0
- package/dist/lib/hosts/logs.js +18 -0
- package/dist/lib/hosts/progress.d.ts +28 -10
- package/dist/lib/hosts/progress.js +79 -22
- package/dist/lib/hosts/remote-cmd.js +4 -0
- package/dist/lib/hq/floor.d.ts +87 -0
- package/dist/lib/hq/floor.js +226 -0
- package/dist/lib/menubar/install-menubar.js +14 -20
- package/dist/lib/notify.d.ts +1 -0
- package/dist/lib/notify.js +3 -3
- package/dist/lib/open-url.d.ts +2 -0
- package/dist/lib/open-url.js +19 -0
- package/dist/lib/openclaw-keychain.d.ts +56 -0
- package/dist/lib/openclaw-keychain.js +236 -0
- package/dist/lib/overdue.js +10 -0
- package/dist/lib/permissions.d.ts +44 -1
- package/dist/lib/permissions.js +284 -7
- package/dist/lib/project-launch.d.ts +6 -12
- package/dist/lib/project-launch.js +13 -228
- package/dist/lib/project-resources.d.ts +7 -0
- package/dist/lib/project-resources.js +291 -0
- package/dist/lib/pty-client.d.ts +27 -0
- package/dist/lib/pty-client.js +136 -10
- package/dist/lib/refresh.js +14 -10
- package/dist/lib/resource-profiles.d.ts +26 -0
- package/dist/lib/resource-profiles.js +157 -0
- package/dist/lib/resources/permissions.js +7 -1
- package/dist/lib/resources/types.d.ts +1 -1
- package/dist/lib/resources.d.ts +1 -1
- package/dist/lib/resources.js +32 -3
- package/dist/lib/routines.d.ts +11 -0
- package/dist/lib/routines.js +56 -15
- package/dist/lib/runner.d.ts +1 -0
- package/dist/lib/runner.js +66 -5
- package/dist/lib/secrets/bundles.d.ts +16 -3
- package/dist/lib/secrets/bundles.js +206 -37
- package/dist/lib/secrets/icloud-import.d.ts +2 -2
- package/dist/lib/secrets/icloud-import.js +9 -6
- package/dist/lib/secrets/mcp.js +1 -1
- package/dist/lib/secrets/vault-age-helper.d.ts +1 -0
- package/dist/lib/secrets/vault-age-helper.js +34 -0
- package/dist/lib/secrets/vault.d.ts +49 -0
- package/dist/lib/secrets/vault.js +397 -0
- package/dist/lib/self-heal/checks/path.js +3 -1
- package/dist/lib/self-heal/checks/shadowing.js +10 -2
- package/dist/lib/self-heal/checks/shims.js +19 -11
- package/dist/lib/session/cloud.d.ts +2 -2
- package/dist/lib/session/cloud.js +2 -2
- package/dist/lib/session/db.d.ts +4 -0
- package/dist/lib/session/db.js +44 -7
- package/dist/lib/session/discover.d.ts +2 -0
- package/dist/lib/session/discover.js +114 -3
- package/dist/lib/session/stream-render.d.ts +3 -0
- package/dist/lib/session/stream-render.js +130 -0
- package/dist/lib/session/types.d.ts +6 -0
- package/dist/lib/share/analytics.d.ts +13 -0
- package/dist/lib/share/analytics.js +45 -0
- package/dist/lib/share/config.d.ts +19 -5
- package/dist/lib/share/config.js +44 -8
- package/dist/lib/share/provision.d.ts +58 -6
- package/dist/lib/share/provision.js +97 -22
- package/dist/lib/share/publish.d.ts +36 -13
- package/dist/lib/share/publish.js +55 -8
- package/dist/lib/share/worker-template.js +83 -17
- package/dist/lib/shims.d.ts +36 -0
- package/dist/lib/shims.js +120 -16
- package/dist/lib/ssh-exec.d.ts +14 -0
- package/dist/lib/ssh-exec.js +57 -0
- package/dist/lib/staleness/detectors/hooks.js +25 -1
- package/dist/lib/staleness/detectors/permissions.js +66 -0
- package/dist/lib/staleness/detectors/workflows.js +20 -0
- package/dist/lib/staleness/writers/hooks.js +58 -4
- package/dist/lib/staleness/writers/permissions.js +2 -2
- package/dist/lib/staleness/writers/skills.js +1 -1
- package/dist/lib/staleness/writers/sources.d.ts +10 -1
- package/dist/lib/staleness/writers/sources.js +68 -1
- package/dist/lib/star-nudge.d.ts +45 -0
- package/dist/lib/star-nudge.js +91 -0
- package/dist/lib/startup/command-registry.d.ts +7 -1
- package/dist/lib/startup/command-registry.js +19 -3
- package/dist/lib/state.d.ts +2 -0
- package/dist/lib/state.js +3 -0
- package/dist/lib/subagents-registry.d.ts +2 -0
- package/dist/lib/subagents-registry.js +3 -0
- package/dist/lib/teams/parsers.js +214 -6
- package/dist/lib/teams/supervisor.d.ts +7 -0
- package/dist/lib/teams/supervisor.js +2 -1
- package/dist/lib/template.d.ts +1 -1
- package/dist/lib/template.js +1 -1
- package/dist/lib/triggers/webhook.js +36 -3
- package/dist/lib/types.d.ts +73 -0
- package/dist/lib/uninstall.d.ts +84 -0
- package/dist/lib/uninstall.js +347 -0
- package/dist/lib/usage.d.ts +13 -1
- package/dist/lib/usage.js +32 -14
- package/dist/lib/version.d.ts +40 -0
- package/dist/lib/version.js +94 -16
- package/dist/lib/versions.d.ts +27 -0
- package/dist/lib/versions.js +248 -79
- package/dist/lib/workflows.d.ts +2 -0
- package/dist/lib/workflows.js +88 -0
- package/package.json +2 -1
- package/dist/commands/daemon.d.ts +0 -10
- package/dist/commands/daemon.js +0 -121
package/dist/lib/routines.js
CHANGED
|
@@ -107,11 +107,29 @@ const JOB_DEFAULTS = {
|
|
|
107
107
|
timeout: '10m',
|
|
108
108
|
enabled: true,
|
|
109
109
|
};
|
|
110
|
+
function overlayUserRoutineDevices(job, userJob) {
|
|
111
|
+
if (job.devices !== undefined)
|
|
112
|
+
return job;
|
|
113
|
+
if (!userJob)
|
|
114
|
+
return job;
|
|
115
|
+
const merged = { ...job };
|
|
116
|
+
if (userJob.devices && userJob.devices.length > 0) {
|
|
117
|
+
merged.devices = userJob.devices;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
delete merged.devices;
|
|
121
|
+
}
|
|
122
|
+
return merged;
|
|
123
|
+
}
|
|
110
124
|
/**
|
|
111
125
|
* List all job configs, scanning project > user > system routine dirs.
|
|
112
126
|
* Higher layers shadow lower ones of the same name (first-seen wins): a project
|
|
113
127
|
* routine shadows a user routine, and a user routine shadows a built-in system
|
|
114
128
|
* routine (`~/.agents/.system/routines/`, shipped via gh:phnx-labs/.agents-system).
|
|
129
|
+
* When a same-name project routine wins for inspection, the user-layer
|
|
130
|
+
* `devices` allowlist is overlaid only if the project routine does not declare
|
|
131
|
+
* its own allowlist, so CWD project discovery cannot hide an operational fleet
|
|
132
|
+
* pin or erase a project-authored one.
|
|
115
133
|
* Project discovery is opt-in via `cwd`; the daemon (which calls `listJobs()`
|
|
116
134
|
* with no argument) sees user + system routines, so a built-in routine fires for
|
|
117
135
|
* every install unless the user overrides or disables it by name.
|
|
@@ -120,22 +138,26 @@ export function listJobs(cwd) {
|
|
|
120
138
|
ensureAgentsDir();
|
|
121
139
|
const seen = new Set();
|
|
122
140
|
const jobs = [];
|
|
141
|
+
const userDir = getRoutinesDir();
|
|
123
142
|
const dirs = [];
|
|
124
143
|
if (cwd) {
|
|
125
144
|
const projectDir = getProjectRoutinesDir(cwd);
|
|
126
145
|
if (projectDir)
|
|
127
|
-
dirs.push(projectDir);
|
|
146
|
+
dirs.push({ scope: 'project', path: projectDir });
|
|
128
147
|
}
|
|
129
|
-
dirs.push(
|
|
130
|
-
dirs.push(getSystemRoutinesDir());
|
|
131
|
-
for (const dir of dirs) {
|
|
148
|
+
dirs.push({ scope: 'user', path: userDir });
|
|
149
|
+
dirs.push({ scope: 'system', path: getSystemRoutinesDir() });
|
|
150
|
+
for (const { scope, path: dir } of dirs) {
|
|
132
151
|
if (!fs.existsSync(dir))
|
|
133
152
|
continue;
|
|
134
153
|
const files = fs.readdirSync(dir).filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'));
|
|
135
154
|
for (const file of files) {
|
|
136
|
-
|
|
155
|
+
let job = readJobFile(path.join(dir, file));
|
|
137
156
|
if (!job)
|
|
138
157
|
continue;
|
|
158
|
+
if (scope === 'project') {
|
|
159
|
+
job = overlayUserRoutineDevices(job, readJobFromDir(userDir, job.name));
|
|
160
|
+
}
|
|
139
161
|
if (seen.has(job.name))
|
|
140
162
|
continue;
|
|
141
163
|
seen.add(job.name);
|
|
@@ -146,26 +168,39 @@ export function listJobs(cwd) {
|
|
|
146
168
|
}
|
|
147
169
|
/**
|
|
148
170
|
* Read a single job config by name, checking project > user > system.
|
|
171
|
+
* Same-name project routines keep the user-layer `devices` allowlist only when
|
|
172
|
+
* the project routine does not declare its own allowlist, for the same reason
|
|
173
|
+
* as listJobs().
|
|
149
174
|
* Project discovery is opt-in via `cwd`; daemon callers pass no argument and
|
|
150
175
|
* resolve user + system routines (a user routine of the same name shadows a
|
|
151
176
|
* built-in system routine).
|
|
152
177
|
*/
|
|
153
178
|
export function readJob(name, cwd) {
|
|
154
179
|
ensureAgentsDir();
|
|
180
|
+
const userDir = getRoutinesDir();
|
|
155
181
|
const dirs = [];
|
|
156
182
|
if (cwd) {
|
|
157
183
|
const projectDir = getProjectRoutinesDir(cwd);
|
|
158
184
|
if (projectDir)
|
|
159
|
-
dirs.push(projectDir);
|
|
160
|
-
}
|
|
161
|
-
dirs.push(
|
|
162
|
-
dirs.push(getSystemRoutinesDir());
|
|
163
|
-
for (const dir of dirs) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (
|
|
167
|
-
return
|
|
168
|
-
|
|
185
|
+
dirs.push({ scope: 'project', path: projectDir });
|
|
186
|
+
}
|
|
187
|
+
dirs.push({ scope: 'user', path: userDir });
|
|
188
|
+
dirs.push({ scope: 'system', path: getSystemRoutinesDir() });
|
|
189
|
+
for (const { scope, path: dir } of dirs) {
|
|
190
|
+
const job = readJobFromDir(dir, name);
|
|
191
|
+
if (job) {
|
|
192
|
+
if (scope === 'project')
|
|
193
|
+
return overlayUserRoutineDevices(job, readJobFromDir(userDir, name));
|
|
194
|
+
return job;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
function readJobFromDir(dir, name) {
|
|
200
|
+
for (const ext of ['.yml', '.yaml']) {
|
|
201
|
+
const filePath = safeJoin(dir, name + ext);
|
|
202
|
+
if (fs.existsSync(filePath)) {
|
|
203
|
+
return readJobFile(filePath);
|
|
169
204
|
}
|
|
170
205
|
}
|
|
171
206
|
return null;
|
|
@@ -440,6 +475,12 @@ export function validateTrigger(trigger) {
|
|
|
440
475
|
if (github.branch !== undefined && typeof github.branch !== 'string') {
|
|
441
476
|
errors.push('trigger.branch must be a string');
|
|
442
477
|
}
|
|
478
|
+
if (github.action !== undefined && typeof github.action !== 'string') {
|
|
479
|
+
errors.push('trigger.action must be a string');
|
|
480
|
+
}
|
|
481
|
+
if (github.label !== undefined && typeof github.label !== 'string') {
|
|
482
|
+
errors.push('trigger.label must be a string');
|
|
483
|
+
}
|
|
443
484
|
return errors;
|
|
444
485
|
}
|
|
445
486
|
const linear = t;
|
package/dist/lib/runner.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export interface RunResult {
|
|
|
25
25
|
}
|
|
26
26
|
/** Build the full CLI argv for executing a job, applying mode, model, and permission flags. */
|
|
27
27
|
export declare function buildJobCommand(config: JobConfig, resolvedPrompt: string): string[];
|
|
28
|
+
export declare function archiveRoutineTranscripts(meta: Pick<RunMeta, 'jobName' | 'runId' | 'agent'>, runDir: string, overlayHome?: string): void;
|
|
28
29
|
/** Pre-flight version/account selection for a routine job. */
|
|
29
30
|
export interface RoutineLaunchPlan {
|
|
30
31
|
/** Ordered attempts: primary first, then same-agent failover accounts. */
|
package/dist/lib/runner.js
CHANGED
|
@@ -19,13 +19,14 @@ import * as path from 'path';
|
|
|
19
19
|
import * as os from 'os';
|
|
20
20
|
import { resolveJobPrompt, parseTimeout, writeRunMeta, getRunDir, checkJobDeviceEligibility, finalizeRunMeta, } from './routines.js';
|
|
21
21
|
import { getRunsDir } from './state.js';
|
|
22
|
-
import { prepareJobHome, buildSpawnEnv } from './sandbox.js';
|
|
22
|
+
import { prepareJobHome, buildSpawnEnv, getJobHomePath } from './sandbox.js';
|
|
23
23
|
import { resolveModel, buildReasoningFlags } from './models.js';
|
|
24
24
|
import { createTimer, maybeRotate, redactPrompt } from './events.js';
|
|
25
25
|
import { normalizeMode, resolveHeadlessMode, buildExecEnv, detectRateLimit, } from './exec.js';
|
|
26
26
|
import { loadTask as loadHostTask } from './hosts/tasks.js';
|
|
27
27
|
import { reconcileTask as reconcileHostTask } from './hosts/reconcile.js';
|
|
28
28
|
import { backgroundSpawnOptions } from './platform/process.js';
|
|
29
|
+
import { walkForFiles } from './fs-walk.js';
|
|
29
30
|
import { getBinaryPath, isVersionInstalled, resolveVersion } from './versions.js';
|
|
30
31
|
import { getConfiguredRunStrategy, resolveRunVersion, rotationFailoverChain, readinessFromCandidate, } from './rotate.js';
|
|
31
32
|
/** CLI command templates per agent, with {prompt} as a placeholder. */
|
|
@@ -36,6 +37,10 @@ const AGENT_COMMANDS = {
|
|
|
36
37
|
kimi: ['kimi', '--prompt', '{prompt}', '--output-format', 'stream-json'],
|
|
37
38
|
droid: ['droid', 'exec', '{prompt}', '-o', 'stream-json'],
|
|
38
39
|
};
|
|
40
|
+
const ROUTINE_TRANSCRIPT_SPECS = {
|
|
41
|
+
claude: [{ root: ['.claude', 'projects'], ext: '.jsonl' }],
|
|
42
|
+
codex: [{ root: ['.codex', 'sessions'], ext: '.jsonl' }],
|
|
43
|
+
};
|
|
39
44
|
/** Build the full CLI argv for executing a job, applying mode, model, and permission flags. */
|
|
40
45
|
export function buildJobCommand(config, resolvedPrompt) {
|
|
41
46
|
// Workflow branch: delegate to `agents run <workflow>` which handles subagent
|
|
@@ -184,6 +189,35 @@ function appendModelAndReasoning(cmd, config) {
|
|
|
184
189
|
function generateRunId() {
|
|
185
190
|
return new Date().toISOString().replace(/[:.]/g, '-');
|
|
186
191
|
}
|
|
192
|
+
export function archiveRoutineTranscripts(meta, runDir, overlayHome) {
|
|
193
|
+
if (!meta.agent)
|
|
194
|
+
return;
|
|
195
|
+
const specs = ROUTINE_TRANSCRIPT_SPECS[meta.agent];
|
|
196
|
+
if (!specs)
|
|
197
|
+
return;
|
|
198
|
+
const home = overlayHome ?? getJobHomePath(meta.jobName);
|
|
199
|
+
for (const spec of specs) {
|
|
200
|
+
const sourceRoot = path.join(home, ...spec.root);
|
|
201
|
+
if (!fs.existsSync(sourceRoot))
|
|
202
|
+
continue;
|
|
203
|
+
const destRoot = path.join(runDir, 'sessions', meta.agent, spec.root[spec.root.length - 1]);
|
|
204
|
+
for (const sourcePath of walkForFiles(sourceRoot, spec.ext, 100_000)) {
|
|
205
|
+
const rel = path.relative(sourceRoot, sourcePath);
|
|
206
|
+
if (rel.startsWith('..') || path.isAbsolute(rel))
|
|
207
|
+
continue;
|
|
208
|
+
const destPath = path.join(destRoot, rel);
|
|
209
|
+
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
210
|
+
try {
|
|
211
|
+
fs.copyFileSync(sourcePath, destPath);
|
|
212
|
+
fs.chmodSync(destPath, 0o600);
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
// The process already reached a terminal state; a concurrently removed
|
|
216
|
+
// transcript should not rewrite that outcome.
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
187
221
|
/**
|
|
188
222
|
* Build the argv for a command-mode routine: run the shell string directly
|
|
189
223
|
* through the platform shell. No agent binary, no rotation, no sandbox.
|
|
@@ -533,6 +567,7 @@ export async function executeJob(config, deps) {
|
|
|
533
567
|
finalizeRunMeta(meta, loopFailed ? 'failed' : 'completed', loopFailed ? 1 : 0, loopFailed ? { errorMessage: `loop stopped: ${loopResult.stoppedBy}` } : undefined);
|
|
534
568
|
writeRunMeta(meta);
|
|
535
569
|
timer.end({ status: meta.status, exitCode: meta.exitCode ?? undefined, runId });
|
|
570
|
+
archiveRoutineTranscripts(meta, runDir, overlayHome);
|
|
536
571
|
return { meta, reportPath: null };
|
|
537
572
|
}
|
|
538
573
|
// Single-shot path: build the command once, then walk the launch chain on
|
|
@@ -577,6 +612,7 @@ export async function executeJob(config, deps) {
|
|
|
577
612
|
writeRunMeta(meta);
|
|
578
613
|
timer.end({ status: 'timeout', runId });
|
|
579
614
|
const reportPath = extractAndSaveReport(stdoutPath, effectiveAgent, runDir);
|
|
615
|
+
archiveRoutineTranscripts(meta, runDir, overlayHome);
|
|
580
616
|
return { meta, reportPath };
|
|
581
617
|
}
|
|
582
618
|
if (attempt.status === 'completed') {
|
|
@@ -584,6 +620,7 @@ export async function executeJob(config, deps) {
|
|
|
584
620
|
writeRunMeta(meta);
|
|
585
621
|
timer.end({ status: 'completed', exitCode: 0, runId });
|
|
586
622
|
const reportPath = extractAndSaveReport(stdoutPath, effectiveAgent, runDir);
|
|
623
|
+
archiveRoutineTranscripts(meta, runDir, overlayHome);
|
|
587
624
|
return { meta, reportPath };
|
|
588
625
|
}
|
|
589
626
|
// Failed — cascade only on rate/usage limit when more chain entries remain.
|
|
@@ -608,6 +645,7 @@ export async function executeJob(config, deps) {
|
|
|
608
645
|
...(attempt.error ? { error: attempt.error } : {}),
|
|
609
646
|
});
|
|
610
647
|
const reportPath = extractAndSaveReport(stdoutPath, effectiveAgent, runDir);
|
|
648
|
+
archiveRoutineTranscripts(meta, runDir, overlayHome);
|
|
611
649
|
return { meta, reportPath };
|
|
612
650
|
}
|
|
613
651
|
// Unreachable: chain is always non-empty, but keep a safe fallback.
|
|
@@ -830,13 +868,32 @@ export async function executeJobDetached(config) {
|
|
|
830
868
|
...backgroundSpawnOptions({ fdStdio: true }),
|
|
831
869
|
env: spawnEnv,
|
|
832
870
|
});
|
|
871
|
+
let settled = false;
|
|
872
|
+
const settle = (status, exitCode, errorMessage) => {
|
|
873
|
+
if (settled)
|
|
874
|
+
return;
|
|
875
|
+
settled = true;
|
|
876
|
+
finalizeRunMeta(meta, status, exitCode, errorMessage ? { errorMessage } : undefined);
|
|
877
|
+
writeRunMeta(meta);
|
|
878
|
+
archiveRoutineTranscripts(meta, runDir, overlayHome);
|
|
879
|
+
if (status !== 'timeout')
|
|
880
|
+
extractAndSaveReport(stdoutPath, effectiveAgent, runDir);
|
|
881
|
+
};
|
|
882
|
+
child.on('exit', (code) => {
|
|
883
|
+
const inferred = inferFinalStatusFromLog(stdoutPath, effectiveAgent);
|
|
884
|
+
if (inferred) {
|
|
885
|
+
settle(inferred.status, inferred.exitCode);
|
|
886
|
+
}
|
|
887
|
+
else {
|
|
888
|
+
settle(code === 0 ? 'completed' : 'failed', code ?? 1);
|
|
889
|
+
}
|
|
890
|
+
});
|
|
833
891
|
child.on('error', (err) => {
|
|
834
892
|
try {
|
|
835
893
|
fs.closeSync(stdoutFd);
|
|
836
894
|
}
|
|
837
895
|
catch { /* fd already closed */ }
|
|
838
|
-
|
|
839
|
-
writeRunMeta(meta);
|
|
896
|
+
settle('failed', 1, err.message);
|
|
840
897
|
process.stderr.write(`[agents] daemon: spawn failed for job "${config.name}": ${err.message}\n`);
|
|
841
898
|
});
|
|
842
899
|
child.unref();
|
|
@@ -1098,8 +1155,10 @@ export function monitorRunningJobs() {
|
|
|
1098
1155
|
if (Number.isFinite(wallClockMs) && wallClockMs > MAX_WALL_CLOCK_MS) {
|
|
1099
1156
|
finalizeRunMeta(meta, 'timeout', null, { errorMessage: 'exceeded max wall clock' });
|
|
1100
1157
|
writeRunMeta(meta);
|
|
1101
|
-
if (!isCommandRun)
|
|
1158
|
+
if (!isCommandRun) {
|
|
1102
1159
|
extractAndSaveReport(stdoutPath, meta.agent, runDirPath);
|
|
1160
|
+
archiveRoutineTranscripts(meta, runDirPath);
|
|
1161
|
+
}
|
|
1103
1162
|
continue;
|
|
1104
1163
|
}
|
|
1105
1164
|
if (!isPidOurs(meta.pid, meta.spawnedAt)) {
|
|
@@ -1122,8 +1181,10 @@ export function monitorRunningJobs() {
|
|
|
1122
1181
|
}
|
|
1123
1182
|
}
|
|
1124
1183
|
writeRunMeta(meta);
|
|
1125
|
-
if (!isCommandRun)
|
|
1184
|
+
if (!isCommandRun) {
|
|
1126
1185
|
extractAndSaveReport(stdoutPath, meta.agent, runDirPath);
|
|
1186
|
+
archiveRoutineTranscripts(meta, runDirPath);
|
|
1187
|
+
}
|
|
1127
1188
|
}
|
|
1128
1189
|
}
|
|
1129
1190
|
catch { /* corrupt or unreadable meta.json */ }
|
|
@@ -13,13 +13,16 @@
|
|
|
13
13
|
* SSH). The item-name scheme is identical, so the only difference is where
|
|
14
14
|
* bytes land. A file-backed bundle is discovered by the presence of its
|
|
15
15
|
* metadata item in the file store.
|
|
16
|
+
* - `vault`: a single age-encrypted ~/.agents/vault.age file unlocked by
|
|
17
|
+
* `agents login`; intended for user-managed cross-machine file sync.
|
|
16
18
|
*
|
|
17
|
-
*
|
|
18
|
-
* encrypted export/import flow; the bundle layer
|
|
19
|
+
* Server-backed cross-machine sync is handled by src/lib/secrets/sync.ts via
|
|
20
|
+
* an explicit encrypted export/import flow; the bundle layer also supports the
|
|
21
|
+
* local vault backend for user-managed file sync.
|
|
19
22
|
*/
|
|
20
23
|
import { type BundleValue, type SecretRef } from './index.js';
|
|
21
24
|
/** Which store carries a bundle's items. */
|
|
22
|
-
export type SecretsBackend = 'keychain' | 'file';
|
|
25
|
+
export type SecretsBackend = 'keychain' | 'file' | 'vault';
|
|
23
26
|
/**
|
|
24
27
|
* Discover a bundle's backend by location: a file-backed bundle's metadata
|
|
25
28
|
* item exists in the encrypted-file store. This is a plain file-existence
|
|
@@ -91,10 +94,12 @@ export interface LegacyBundleCandidate {
|
|
|
91
94
|
}
|
|
92
95
|
export declare const BUNDLE_NAME_PATTERN: RegExp;
|
|
93
96
|
export declare const ENV_KEY_PATTERN: RegExp;
|
|
97
|
+
export declare const BUNDLE_KEY_PATTERN: RegExp;
|
|
94
98
|
export declare const BUNDLE_META_PREFIX = "agents-cli.bundles.";
|
|
95
99
|
export declare const RESERVED_ENV_NAMES: Set<string>;
|
|
96
100
|
export declare function bundleToEnvPrefix(name: string): string;
|
|
97
101
|
export declare function isReservedEnvName(key: string): boolean;
|
|
102
|
+
export declare function bundleKeyToEnvKey(key: string): string;
|
|
98
103
|
export declare function isLoaderOrInterpreterEnv(name: string): boolean;
|
|
99
104
|
export declare function sanitizeProcessEnv(env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
100
105
|
/** Validate a bundle name against the allowed pattern. Throws on invalid input. */
|
|
@@ -140,6 +145,7 @@ export interface WriteBundleOptions {
|
|
|
140
145
|
*/
|
|
141
146
|
export declare function shouldEvictAfterBundleWrite(skipRequested: boolean, noAgentEnv: string | undefined, backendOverridden: boolean): boolean;
|
|
142
147
|
export declare function writeBundle(bundle: SecretsBundle, opts?: WriteBundleOptions): void;
|
|
148
|
+
export declare function writeBundleWithItems(bundle: SecretsBundle, items: Map<string, string>, opts?: WriteBundleOptions): void;
|
|
143
149
|
export declare function deleteBundle(name: string): boolean;
|
|
144
150
|
export declare function listBundles(): SecretsBundle[];
|
|
145
151
|
export interface BundleEntryInfo {
|
|
@@ -185,7 +191,14 @@ export interface ResolveBundleOptions {
|
|
|
185
191
|
* bundle-level expiry has passed) aborts the run before Touch ID is popped.
|
|
186
192
|
*/
|
|
187
193
|
allowExpired?: boolean;
|
|
194
|
+
/**
|
|
195
|
+
* `process` projects dotted account keys like `GITHUB_USERNAME.personal` to
|
|
196
|
+
* the shell-safe base env name (`GITHUB_USERNAME`). Direct value lookups and
|
|
197
|
+
* backup/export flows use `storage` to preserve the exact bundle key names.
|
|
198
|
+
*/
|
|
199
|
+
keyMode?: 'process' | 'storage';
|
|
188
200
|
}
|
|
201
|
+
export declare function canCacheResolvedEnv(bundle: SecretsBundle, selectedKeys: Set<string>, keyMode: ResolveBundleOptions['keyMode']): boolean;
|
|
189
202
|
/**
|
|
190
203
|
* Apply the --keys subset + expiry gate to an already-resolved snapshot from
|
|
191
204
|
* the secrets-agent fast-path. The agent stores the FULL bundle env, so a
|