@phnx-labs/agents-cli 1.20.78 → 1.20.82
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 +487 -0
- package/README.md +25 -25
- package/dist/bin/agents +0 -0
- package/dist/commands/activity.d.ts +9 -0
- package/dist/commands/activity.js +153 -24
- package/dist/commands/apply.js +11 -4
- package/dist/commands/cli.js +1 -1
- package/dist/commands/commands.d.ts +1 -1
- package/dist/commands/commands.js +7 -6
- package/dist/commands/defaults.js +3 -11
- package/dist/commands/doctor.d.ts +65 -0
- package/dist/commands/doctor.js +575 -31
- package/dist/commands/events.js +1 -1
- package/dist/commands/exec.js +24 -5
- package/dist/commands/feed.d.ts +4 -0
- package/dist/commands/feed.js +87 -11
- package/dist/commands/harness.js +2 -2
- package/dist/commands/hooks.js +1 -1
- package/dist/commands/import.js +8 -4
- package/dist/commands/logs.js +6 -0
- package/dist/commands/models.js +1 -1
- package/dist/commands/packages.js +6 -6
- package/dist/commands/permissions.js +1 -1
- package/dist/commands/profiles.js +1 -1
- package/dist/commands/pull.d.ts +1 -1
- package/dist/commands/pull.js +4 -4
- package/dist/commands/repo.d.ts +78 -0
- package/dist/commands/repo.js +187 -11
- package/dist/commands/routines.js +12 -2
- package/dist/commands/rules.js +13 -12
- package/dist/commands/secrets.d.ts +3 -1
- package/dist/commands/secrets.js +100 -32
- package/dist/commands/sessions-inject.d.ts +7 -4
- package/dist/commands/sessions-inject.js +18 -18
- package/dist/commands/sessions-picker.js +32 -3
- package/dist/commands/sessions-resume.d.ts +16 -0
- package/dist/commands/sessions-resume.js +14 -13
- package/dist/commands/sessions.d.ts +31 -0
- package/dist/commands/sessions.js +141 -16
- package/dist/commands/set.d.ts +15 -0
- package/dist/commands/set.js +79 -0
- package/dist/commands/setup-fleet.d.ts +21 -0
- package/dist/commands/setup-fleet.js +201 -0
- package/dist/commands/setup-secrets.d.ts +20 -0
- package/dist/commands/setup-secrets.js +223 -0
- package/dist/commands/setup.js +17 -3
- package/dist/commands/skills.js +1 -1
- package/dist/commands/sync.js +7 -2
- package/dist/commands/teams-picker.js +0 -1
- package/dist/commands/teams.d.ts +33 -1
- package/dist/commands/teams.js +208 -44
- package/dist/commands/versions.js +10 -5
- package/dist/commands/view.d.ts +1 -0
- package/dist/commands/view.js +11 -0
- package/dist/index.js +5 -8
- package/dist/lib/acp/harnesses.js +0 -7
- package/dist/lib/activity.d.ts +156 -0
- package/dist/lib/activity.js +282 -0
- package/dist/lib/agents.d.ts +9 -2
- package/dist/lib/agents.js +72 -63
- package/dist/lib/browser/service.js +3 -0
- package/dist/lib/browser/types.d.ts +7 -0
- package/dist/lib/capabilities.js +6 -2
- package/dist/lib/crabbox/lease.js +2 -2
- package/dist/lib/crabbox/setup-copy.d.ts +4 -4
- package/dist/lib/crabbox/setup-copy.js +4 -4
- package/dist/lib/daemon.d.ts +18 -0
- package/dist/lib/daemon.js +47 -6
- package/dist/lib/devices/fleet.d.ts +1 -1
- package/dist/lib/devices/fleet.js +1 -1
- package/dist/lib/doctor-diff.d.ts +20 -0
- package/dist/lib/doctor-diff.js +6 -1
- package/dist/lib/drift.d.ts +31 -11
- package/dist/lib/drift.js +58 -7
- package/dist/lib/events.d.ts +8 -1
- package/dist/lib/events.js +10 -1
- package/dist/lib/exec.js +35 -8
- package/dist/lib/feed-post.d.ts +28 -1
- package/dist/lib/feed-post.js +110 -2
- package/dist/lib/fleet/apply.js +8 -1
- package/dist/lib/fleet/auth-sync.d.ts +18 -1
- package/dist/lib/fleet/auth-sync.js +25 -11
- package/dist/lib/fleet/remote-login.js +5 -0
- package/dist/lib/git.d.ts +14 -14
- package/dist/lib/git.js +41 -44
- package/dist/lib/hooks.d.ts +42 -0
- package/dist/lib/hooks.js +137 -93
- package/dist/lib/hosts/dispatch.d.ts +28 -1
- package/dist/lib/hosts/dispatch.js +33 -5
- package/dist/lib/hosts/option.js +2 -2
- package/dist/lib/hosts/passthrough.d.ts +22 -1
- package/dist/lib/hosts/passthrough.js +238 -13
- package/dist/lib/hosts/run-target.d.ts +2 -0
- package/dist/lib/hosts/run-target.js +1 -0
- package/dist/lib/hq/floor.d.ts +1 -1
- package/dist/lib/hq/floor.js +6 -1
- package/dist/lib/mcp.js +3 -71
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/notify-desktop.d.ts +15 -0
- package/dist/lib/menubar/notify-desktop.js +41 -5
- package/dist/lib/merged-resources.d.ts +11 -0
- package/dist/{commands/resources.js → lib/merged-resources.js} +11 -19
- package/dist/lib/permissions.d.ts +0 -32
- package/dist/lib/permissions.js +4 -157
- package/dist/lib/picker.js +1 -1
- package/dist/lib/platform/process.d.ts +16 -5
- package/dist/lib/platform/process.js +54 -0
- package/dist/lib/plugins.d.ts +0 -8
- package/dist/lib/plugins.js +4 -110
- package/dist/lib/project-resources.js +4 -1
- package/dist/lib/refresh.d.ts +5 -3
- package/dist/lib/refresh.js +7 -5
- package/dist/lib/resources/commands.js +4 -1
- package/dist/lib/resources/mcp.js +0 -4
- package/dist/lib/resources/permissions.d.ts +1 -1
- package/dist/lib/resources/permissions.js +1 -5
- package/dist/lib/resources/rules.js +4 -1
- package/dist/lib/resources/skills.js +4 -1
- package/dist/lib/resources/subagents.js +4 -0
- package/dist/lib/resources/types.d.ts +1 -1
- package/dist/lib/routines.d.ts +20 -0
- package/dist/lib/routines.js +6 -0
- package/dist/lib/run-defaults.d.ts +1 -0
- package/dist/lib/run-defaults.js +9 -0
- package/dist/lib/runner.d.ts +0 -12
- package/dist/lib/runner.js +49 -10
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/agent.d.ts +16 -0
- package/dist/lib/secrets/agent.js +105 -3
- package/dist/lib/secrets/audit.d.ts +46 -0
- package/dist/lib/secrets/audit.js +56 -0
- package/dist/lib/secrets/bundles.d.ts +11 -8
- package/dist/lib/secrets/bundles.js +31 -23
- package/dist/lib/secrets/index.d.ts +2 -1
- package/dist/lib/secrets/index.js +8 -2
- package/dist/lib/secrets/remote.d.ts +75 -2
- package/dist/lib/secrets/remote.js +139 -5
- package/dist/lib/secrets/sync.js +3 -3
- package/dist/lib/session/active.d.ts +110 -26
- package/dist/lib/session/active.js +161 -50
- package/dist/lib/session/actor-sidecar.d.ts +23 -0
- package/dist/lib/session/actor-sidecar.js +101 -0
- package/dist/lib/session/db.d.ts +4 -1
- package/dist/lib/session/db.js +65 -8
- package/dist/lib/session/discover.d.ts +4 -0
- package/dist/lib/session/discover.js +13 -0
- package/dist/lib/session/hook-sessions.d.ts +9 -0
- package/dist/lib/session/hook-sessions.js +57 -8
- package/dist/lib/session/pid-registry.d.ts +13 -0
- package/dist/lib/session/render.d.ts +2 -0
- package/dist/lib/session/render.js +1 -1
- package/dist/lib/session/types.d.ts +16 -0
- package/dist/lib/staleness/detectors/commands.js +2 -2
- package/dist/lib/staleness/detectors/permissions.js +1 -45
- package/dist/lib/staleness/writers/commands.js +4 -5
- package/dist/lib/staleness/writers/hooks.js +1 -1
- package/dist/lib/startup/command-registry.d.ts +1 -2
- package/dist/lib/startup/command-registry.js +2 -4
- package/dist/lib/subagents-registry.js +5 -12
- package/dist/lib/subagents.d.ts +0 -10
- package/dist/lib/subagents.js +0 -12
- package/dist/lib/teams/agents.d.ts +0 -2
- package/dist/lib/teams/agents.js +10 -27
- package/dist/lib/teams/index.d.ts +1 -1
- package/dist/lib/teams/index.js +1 -1
- package/dist/lib/types.d.ts +17 -9
- package/dist/lib/usage.d.ts +28 -5
- package/dist/lib/usage.js +271 -8
- package/dist/lib/versions.js +7 -1
- package/dist/lib/watchdog/watchdog.d.ts +1 -1
- package/dist/lib/watchdog/watchdog.js +25 -13
- package/package.json +1 -2
- package/dist/commands/check.d.ts +0 -15
- package/dist/commands/check.js +0 -180
- package/dist/commands/resources.d.ts +0 -5
package/dist/lib/plugins.js
CHANGED
|
@@ -22,7 +22,6 @@ import { shouldInstallCommandAsSkill, installCommandSkillToVersion } from './com
|
|
|
22
22
|
import { copyPluginToMarketplace, syncMarketplaceManifest, registerMarketplace, unregisterMarketplace, addPluginToSettings, removePluginFromSettings, removePluginFromMarketplace, registerDroidInstalledPlugin, unregisterDroidInstalledPlugin, isDroidPluginInstalled, registerCopilotInstalledPlugin, unregisterCopilotInstalledPlugin, marketplaceIsEmpty, removeEmptyMarketplaceDir, isInstalledInMarketplace, marketplaceRoot, discoverMarketplaces, marketplaceNameFor, MARKETPLACE_NAME, PROJECT_MARKETPLACE_NAME, SYSTEM_MARKETPLACE_NAME, } from './plugin-marketplace.js';
|
|
23
23
|
const PLUGIN_MANIFEST_DIR = '.claude-plugin';
|
|
24
24
|
const PLUGIN_MANIFEST_FILE = 'plugin.json';
|
|
25
|
-
const GEMINI_EXTENSION_MANIFEST_FILE = 'gemini-extension.json';
|
|
26
25
|
const HERMES_PLUGIN_MANIFEST_FILE = 'plugin.yaml';
|
|
27
26
|
const USER_CONFIG_FILE = '.user-config.json';
|
|
28
27
|
const SOURCE_FILE = '.source';
|
|
@@ -518,13 +517,16 @@ export function syncPluginToVersion(plugin, agent, versionHome, options = {}) {
|
|
|
518
517
|
if (!pluginSupportsAgent(plugin, agent)) {
|
|
519
518
|
return result;
|
|
520
519
|
}
|
|
520
|
+
if (!isCapable(agent, 'plugins')) {
|
|
521
|
+
return result;
|
|
522
|
+
}
|
|
521
523
|
// OpenCode uses TS/JS modules under ~/.config/opencode/plugins/, not the
|
|
522
524
|
// Claude marketplace layout. Install those modules and return early.
|
|
523
525
|
if (agent === 'opencode') {
|
|
524
526
|
// Trust gate (RUSH-1756): OpenCode plugins are raw executable TS/JS modules,
|
|
525
527
|
// so they must clear the same consent check as every other exec surface
|
|
526
528
|
// before install — this branch used to return early, bypassing the gate the
|
|
527
|
-
//
|
|
529
|
+
// Hermes/marketplace branches all apply.
|
|
528
530
|
const enablePlugin = options.allowExecSurfaces === true || !hasPluginExecSurfaces(inspectPluginCapabilities(plugin.root));
|
|
529
531
|
if (!enablePlugin) {
|
|
530
532
|
return result;
|
|
@@ -535,27 +537,6 @@ export function syncPluginToVersion(plugin, agent, versionHome, options = {}) {
|
|
|
535
537
|
result.skills.push(plugin.name);
|
|
536
538
|
return result;
|
|
537
539
|
}
|
|
538
|
-
// Gemini CLI loads extensions from $HOME/.gemini/extensions/<name>/.
|
|
539
|
-
// Copy the plugin bundle as an extension and synthesize gemini-extension.json.
|
|
540
|
-
if (agent === 'gemini') {
|
|
541
|
-
const enablePlugin = options.allowExecSurfaces === true || !hasPluginExecSurfaces(inspectPluginCapabilities(plugin.root));
|
|
542
|
-
if (!enablePlugin) {
|
|
543
|
-
return result;
|
|
544
|
-
}
|
|
545
|
-
const ok = installGeminiPlugin(plugin, versionHome);
|
|
546
|
-
result.success = ok;
|
|
547
|
-
if (ok) {
|
|
548
|
-
result.skills = plugin.skills.map(s => `${plugin.name}:${s}`);
|
|
549
|
-
result.commands = plugin.commands.map(c => `${plugin.name}:${c}`);
|
|
550
|
-
result.agentDefs = plugin.agentDefs.map(a => `${plugin.name}:${a}`);
|
|
551
|
-
result.bin = plugin.bin;
|
|
552
|
-
result.hooks = plugin.hooks;
|
|
553
|
-
result.mcp = plugin.hasMcp;
|
|
554
|
-
result.settings = plugin.hasSettings;
|
|
555
|
-
result.permissions = pluginHasPermissions(plugin);
|
|
556
|
-
}
|
|
557
|
-
return result;
|
|
558
|
-
}
|
|
559
540
|
// Goose loads Open Plugins from $HOME/.agents/plugins/<name>/ (same layout as
|
|
560
541
|
// agents-cli's source tree). Under the shim HOME is the version home.
|
|
561
542
|
if (agent === 'goose') {
|
|
@@ -965,53 +946,6 @@ export function removeOpenCodePlugin(pluginName, versionHome) {
|
|
|
965
946
|
}
|
|
966
947
|
return removed;
|
|
967
948
|
}
|
|
968
|
-
// ─── Gemini extensions ───────────────────────────────────────────────────────
|
|
969
|
-
/**
|
|
970
|
-
* Gemini CLI extensions live under `$HOME/.gemini/extensions/<name>/` and
|
|
971
|
-
* require a `gemini-extension.json` manifest at the extension root.
|
|
972
|
-
*/
|
|
973
|
-
export function geminiExtensionsDir(versionHome) {
|
|
974
|
-
return path.join(versionHome, '.gemini', 'extensions');
|
|
975
|
-
}
|
|
976
|
-
function readPluginMcpConfigForGemini(pluginRoot) {
|
|
977
|
-
const mcpPath = path.join(pluginRoot, '.mcp.json');
|
|
978
|
-
if (!fs.existsSync(mcpPath))
|
|
979
|
-
return undefined;
|
|
980
|
-
try {
|
|
981
|
-
const parsed = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));
|
|
982
|
-
if (!parsed.mcpServers || typeof parsed.mcpServers !== 'object')
|
|
983
|
-
return undefined;
|
|
984
|
-
return rewriteGeminiExtensionVars(parsed.mcpServers);
|
|
985
|
-
}
|
|
986
|
-
catch {
|
|
987
|
-
return undefined;
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
function rewriteGeminiExtensionVars(value) {
|
|
991
|
-
if (typeof value === 'string') {
|
|
992
|
-
return value
|
|
993
|
-
.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, '${extensionPath}')
|
|
994
|
-
.replace(/\$\{CLAUDE_PLUGIN_DATA\}/g, '${extensionPath}/.data');
|
|
995
|
-
}
|
|
996
|
-
if (Array.isArray(value))
|
|
997
|
-
return value.map(rewriteGeminiExtensionVars);
|
|
998
|
-
if (value && typeof value === 'object') {
|
|
999
|
-
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, rewriteGeminiExtensionVars(item)]));
|
|
1000
|
-
}
|
|
1001
|
-
return value;
|
|
1002
|
-
}
|
|
1003
|
-
function writeGeminiExtensionManifest(plugin, destRoot) {
|
|
1004
|
-
const manifest = {
|
|
1005
|
-
name: plugin.manifest.name,
|
|
1006
|
-
version: plugin.manifest.version,
|
|
1007
|
-
description: plugin.manifest.description,
|
|
1008
|
-
};
|
|
1009
|
-
const mcpServers = readPluginMcpConfigForGemini(destRoot);
|
|
1010
|
-
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
1011
|
-
manifest.mcpServers = mcpServers;
|
|
1012
|
-
}
|
|
1013
|
-
fs.writeFileSync(path.join(destRoot, GEMINI_EXTENSION_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\n`, 'utf-8');
|
|
1014
|
-
}
|
|
1015
949
|
/**
|
|
1016
950
|
* Security (RUSH-1755): `fs.cpSync(..., { recursive: true })` copies symlinks
|
|
1017
951
|
* verbatim (dereference defaults to false), so a malicious plugin can ship a
|
|
@@ -1078,36 +1012,6 @@ function stripEscapingSymlinks(destRoot, sourceRoot) {
|
|
|
1078
1012
|
walk(destRoot);
|
|
1079
1013
|
return removed;
|
|
1080
1014
|
}
|
|
1081
|
-
export function installGeminiPlugin(plugin, versionHome) {
|
|
1082
|
-
const destRoot = path.join(geminiExtensionsDir(versionHome), plugin.name);
|
|
1083
|
-
try {
|
|
1084
|
-
if (fs.existsSync(destRoot)) {
|
|
1085
|
-
fs.rmSync(destRoot, { recursive: true, force: true });
|
|
1086
|
-
}
|
|
1087
|
-
fs.cpSync(plugin.root, destRoot, { recursive: true });
|
|
1088
|
-
stripEscapingSymlinks(destRoot, plugin.root);
|
|
1089
|
-
const userConfig = loadUserConfig(plugin.name);
|
|
1090
|
-
if (Object.keys(userConfig).length > 0) {
|
|
1091
|
-
expandUserConfigInDir(destRoot, userConfig);
|
|
1092
|
-
}
|
|
1093
|
-
writeGeminiExtensionManifest(plugin, destRoot);
|
|
1094
|
-
fs.writeFileSync(path.join(destRoot, '.agents-cli-managed'), `plugin=${plugin.name}\n`, 'utf-8');
|
|
1095
|
-
return true;
|
|
1096
|
-
}
|
|
1097
|
-
catch {
|
|
1098
|
-
return false;
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
export function isGeminiPluginInstalled(pluginName, versionHome) {
|
|
1102
|
-
return fs.existsSync(path.join(geminiExtensionsDir(versionHome), pluginName, GEMINI_EXTENSION_MANIFEST_FILE));
|
|
1103
|
-
}
|
|
1104
|
-
export function removeGeminiPlugin(pluginName, versionHome) {
|
|
1105
|
-
const destRoot = path.join(geminiExtensionsDir(versionHome), pluginName);
|
|
1106
|
-
if (!fs.existsSync(destRoot))
|
|
1107
|
-
return false;
|
|
1108
|
-
fs.rmSync(destRoot, { recursive: true, force: true });
|
|
1109
|
-
return true;
|
|
1110
|
-
}
|
|
1111
1015
|
// ─── Goose plugins (Open Plugins under .agents/plugins/) ─────────────────────
|
|
1112
1016
|
/**
|
|
1113
1017
|
* Goose auto-discovers Open Plugins at `$HOME/.agents/plugins/<name>/`.
|
|
@@ -1254,9 +1158,6 @@ export function isPluginSynced(plugin, agent, versionHome) {
|
|
|
1254
1158
|
if (agent === 'opencode') {
|
|
1255
1159
|
return isOpenCodePluginInstalled(plugin.name, versionHome);
|
|
1256
1160
|
}
|
|
1257
|
-
if (agent === 'gemini') {
|
|
1258
|
-
return isGeminiPluginInstalled(plugin.name, versionHome);
|
|
1259
|
-
}
|
|
1260
1161
|
if (agent === 'goose') {
|
|
1261
1162
|
return isGoosePluginInstalled(plugin.name, versionHome);
|
|
1262
1163
|
}
|
|
@@ -1297,13 +1198,6 @@ export function removePluginFromVersion(pluginName, pluginRoot, agent, versionHo
|
|
|
1297
1198
|
}
|
|
1298
1199
|
return result;
|
|
1299
1200
|
}
|
|
1300
|
-
// Gemini: remove extension directory from ~/.gemini/extensions/.
|
|
1301
|
-
if (agent === 'gemini') {
|
|
1302
|
-
if (removeGeminiPlugin(pluginName, versionHome)) {
|
|
1303
|
-
result.skills.push(pluginName);
|
|
1304
|
-
}
|
|
1305
|
-
return result;
|
|
1306
|
-
}
|
|
1307
1201
|
// Goose: remove Open Plugin directory from versionHome/.agents/plugins/.
|
|
1308
1202
|
if (agent === 'goose') {
|
|
1309
1203
|
if (removeGoosePlugin(pluginName, versionHome)) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
|
-
import { AGENTS, agentConfigDirName } from './agents.js';
|
|
3
|
+
import { AGENTS, agentConfigDirName, isAgentHardDeprecated } from './agents.js';
|
|
4
4
|
import { supports } from './capabilities.js';
|
|
5
5
|
import { buildCommandSkillContent, commandSkillName, readSkillSourceCommandMarker, shouldInstallCommandAsSkill } from './command-skills.js';
|
|
6
6
|
import { commandAppliesTo, parseCommandMetadata } from './commands.js';
|
|
@@ -16,6 +16,9 @@ export function projectAgentRoot(projectRoot, agent) {
|
|
|
16
16
|
return path.join(projectRoot, agentConfigDirName(agent));
|
|
17
17
|
}
|
|
18
18
|
export function syncProjectResourcesToAgent(agent, version, projectAgentsDir) {
|
|
19
|
+
if (isAgentHardDeprecated(agent)) {
|
|
20
|
+
return { synced: [], skipped: [] };
|
|
21
|
+
}
|
|
19
22
|
const projectRoot = path.dirname(projectAgentsDir);
|
|
20
23
|
const agentRoot = projectAgentRoot(projectRoot, agent);
|
|
21
24
|
const manifest = loadProjectManifest(agentRoot);
|
package/dist/lib/refresh.d.ts
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
* sync resources into installed version homes, register hooks, add shims to
|
|
4
4
|
* PATH, prompt for missing default versions, install declared host-CLIs.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* operations — that lives
|
|
6
|
+
* The reconcile stage behind `agents sync` (the umbrella `--local` path calls
|
|
7
|
+
* this; see sync-umbrella.ts) and any other caller that needs to re-derive local
|
|
8
|
+
* state from declared configuration. Does NOT do any git operations — that lives
|
|
9
|
+
* in `agents repo pull`. (Also still reachable via the deprecated, hidden
|
|
10
|
+
* `agents repo refresh` alias.)
|
|
9
11
|
*/
|
|
10
12
|
import type { AgentId } from './types.js';
|
|
11
13
|
export interface RefreshOptions {
|
package/dist/lib/refresh.js
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
* sync resources into installed version homes, register hooks, add shims to
|
|
4
4
|
* PATH, prompt for missing default versions, install declared host-CLIs.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* operations — that lives
|
|
6
|
+
* The reconcile stage behind `agents sync` (the umbrella `--local` path calls
|
|
7
|
+
* this; see sync-umbrella.ts) and any other caller that needs to re-derive local
|
|
8
|
+
* state from declared configuration. Does NOT do any git operations — that lives
|
|
9
|
+
* in `agents repo pull`. (Also still reachable via the deprecated, hidden
|
|
10
|
+
* `agents repo refresh` alias.)
|
|
9
11
|
*/
|
|
10
12
|
import * as fs from 'fs';
|
|
11
13
|
import * as path from 'path';
|
|
@@ -13,7 +15,7 @@ import chalk from 'chalk';
|
|
|
13
15
|
import ora from 'ora';
|
|
14
16
|
import { select, confirm } from '@inquirer/prompts';
|
|
15
17
|
import { capableAgents } from './capabilities.js';
|
|
16
|
-
import { AGENTS,
|
|
18
|
+
import { AGENTS, MANAGED_AGENT_IDS, getAllCliStates, registerMcpToTargets, agentLabel, } from './agents.js';
|
|
17
19
|
import { readManifest, MANIFEST_FILENAME } from './manifest.js';
|
|
18
20
|
import { getUserAgentsDir } from './state.js';
|
|
19
21
|
import { installVersion, listInstalledVersions, isVersionIsolated, getGlobalDefault, setGlobalDefault, getVersionHomePath, syncResourcesToVersion, getAvailableResources, getActuallySyncedResources, getNewResources, getProjectOnlyResources, hasNewResources, promptNewResourceSelection, promptResourceSelection, resolveConfiguredAgentTargets, } from './versions.js';
|
|
@@ -114,7 +116,7 @@ export async function refresh(options = {}) {
|
|
|
114
116
|
}
|
|
115
117
|
// 3. Sync resources to default version homes
|
|
116
118
|
const cliStates = await getAllCliStates();
|
|
117
|
-
const agentsToSync = agentFilter ? [agentFilter] :
|
|
119
|
+
const agentsToSync = agentFilter ? [agentFilter] : MANAGED_AGENT_IDS;
|
|
118
120
|
const available = getAvailableResources();
|
|
119
121
|
for (const agentId of agentsToSync) {
|
|
120
122
|
if (!cliStates[agentId]?.installed && listInstalledVersions(agentId).length === 0)
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import * as fs from 'fs';
|
|
9
9
|
import * as path from 'path';
|
|
10
10
|
import { getProjectAgentsDir, getUserAgentsDir, getSystemAgentsDir, getEnabledExtraRepos, } from '../state.js';
|
|
11
|
-
import { AGENTS, agentConfigDirName } from '../agents.js';
|
|
11
|
+
import { AGENTS, agentConfigDirName, isAgentHardDeprecated } from '../agents.js';
|
|
12
12
|
import { markdownToToml } from '../convert.js';
|
|
13
13
|
/**
|
|
14
14
|
* Get the commands directory for a given layer root.
|
|
@@ -162,6 +162,9 @@ export class CommandsHandler {
|
|
|
162
162
|
* Copies/transforms commands as needed for the agent's expected format.
|
|
163
163
|
*/
|
|
164
164
|
sync(agent, versionHome, cwd) {
|
|
165
|
+
if (isAgentHardDeprecated(agent)) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
165
168
|
const agentConfig = AGENTS[agent];
|
|
166
169
|
const targetFormat = this.format(agent);
|
|
167
170
|
const targetDir = path.join(versionHome, agentConfigDirName(agent), this.targetDir(agent));
|
|
@@ -115,8 +115,6 @@ export function getMcpConfigPath(agent, versionHome) {
|
|
|
115
115
|
return path.join(versionHome, '.config', 'opencode', 'opencode.jsonc');
|
|
116
116
|
case 'cursor':
|
|
117
117
|
return path.join(versionHome, '.cursor', 'mcp.json');
|
|
118
|
-
case 'gemini':
|
|
119
|
-
return path.join(versionHome, '.gemini', 'settings.json');
|
|
120
118
|
case 'openclaw':
|
|
121
119
|
return path.join(versionHome, '.openclaw', 'openclaw.json');
|
|
122
120
|
case 'antigravity':
|
|
@@ -126,8 +124,6 @@ export function getMcpConfigPath(agent, versionHome) {
|
|
|
126
124
|
return path.join(versionHome, '.grok', 'mcp.json');
|
|
127
125
|
case 'hermes':
|
|
128
126
|
return path.join(versionHome, '.hermes', 'config.yaml');
|
|
129
|
-
case 'forge':
|
|
130
|
-
return path.join(versionHome, '.forge', '.mcp.json');
|
|
131
127
|
default:
|
|
132
128
|
return null;
|
|
133
129
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Permissions are stored as YAML files in permissions/ directories at each layer.
|
|
5
5
|
* Resolution: project > user > system (higher layer wins on name conflict).
|
|
6
6
|
* Unlike other resources, permissions merge into agent-specific config files
|
|
7
|
-
* (Claude
|
|
7
|
+
* (Claude: settings.json, Codex: config.toml, OpenCode: opencode.jsonc).
|
|
8
8
|
*/
|
|
9
9
|
import type { ResourceHandler } from './types.js';
|
|
10
10
|
import type { PermissionSet } from '../types.js';
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Permissions are stored as YAML files in permissions/ directories at each layer.
|
|
5
5
|
* Resolution: project > user > system (higher layer wins on name conflict).
|
|
6
6
|
* Unlike other resources, permissions merge into agent-specific config files
|
|
7
|
-
* (Claude
|
|
7
|
+
* (Claude: settings.json, Codex: config.toml, OpenCode: opencode.jsonc).
|
|
8
8
|
*/
|
|
9
9
|
import * as fs from 'fs';
|
|
10
10
|
import * as path from 'path';
|
|
@@ -65,8 +65,6 @@ function getAgentConfigPath(agent, versionHome) {
|
|
|
65
65
|
return path.join(versionHome, '.claude', 'settings.json');
|
|
66
66
|
case 'codex':
|
|
67
67
|
return path.join(versionHome, '.codex', 'config.toml');
|
|
68
|
-
case 'gemini':
|
|
69
|
-
return path.join(versionHome, '.gemini', 'settings.json');
|
|
70
68
|
case 'opencode':
|
|
71
69
|
return path.join(versionHome, '.config', 'opencode', 'opencode.jsonc');
|
|
72
70
|
case 'kimi':
|
|
@@ -79,8 +77,6 @@ function getAgentConfigPath(agent, versionHome) {
|
|
|
79
77
|
return path.join(versionHome, '.openclaw', 'openclaw.json');
|
|
80
78
|
case 'copilot':
|
|
81
79
|
return path.join(versionHome, '.copilot', 'permissions-config.json');
|
|
82
|
-
case 'forge':
|
|
83
|
-
return path.join(versionHome, '.forge', 'permissions.yaml');
|
|
84
80
|
case 'hermes':
|
|
85
81
|
return path.join(versionHome, '.hermes', 'config.yaml');
|
|
86
82
|
case 'goose':
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - All unique subrules across layers are unioned
|
|
10
10
|
*/
|
|
11
11
|
import * as fs from 'fs';
|
|
12
|
-
import { agentConfigDirName } from '../agents.js';
|
|
12
|
+
import { agentConfigDirName, isAgentHardDeprecated } from '../agents.js';
|
|
13
13
|
import * as path from 'path';
|
|
14
14
|
import { getSystemRulesDir, getUserRulesDir, getProjectAgentsDir, getEnabledExtraRepos, } from '../state.js';
|
|
15
15
|
const SUBRULES_DIR = 'subrules';
|
|
@@ -158,6 +158,9 @@ export const RulesHandler = {
|
|
|
158
158
|
return resolveRule(name, getLayerDirs(cwd));
|
|
159
159
|
},
|
|
160
160
|
sync(agent, versionHome, _cwd) {
|
|
161
|
+
if (isAgentHardDeprecated(agent)) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
161
164
|
// Rules sync is handled by the compose module and syncResourcesToVersion.
|
|
162
165
|
// This method ensures the agent config directory exists.
|
|
163
166
|
// The actual composition and write happens in versions.ts via composeRulesFromState().
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Format is the same for all agents. Resolution order: project > user > system.
|
|
6
6
|
*/
|
|
7
7
|
import * as fs from 'fs';
|
|
8
|
-
import { AGENTS, agentConfigDirName } from '../agents.js';
|
|
8
|
+
import { AGENTS, agentConfigDirName, isAgentHardDeprecated } from '../agents.js';
|
|
9
9
|
import * as path from 'path';
|
|
10
10
|
import * as yaml from 'yaml';
|
|
11
11
|
import { getSystemSkillsDir, getUserSkillsDir, getProjectAgentsDir, getEnabledExtraRepos, } from '../state.js';
|
|
@@ -201,6 +201,9 @@ export function createSkillsHandler(provider = defaultProvider) {
|
|
|
201
201
|
return null;
|
|
202
202
|
},
|
|
203
203
|
sync(agent, versionHome, cwd) {
|
|
204
|
+
if (isAgentHardDeprecated(agent)) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
204
207
|
// Agents that read directly from central ~/.agents/skills/ (e.g. Gemini,
|
|
205
208
|
// Goose via the Summon extension) should not get a per-version copy.
|
|
206
209
|
if (AGENTS[agent]?.nativeAgentsSkillsDir) {
|
|
@@ -8,6 +8,7 @@ import * as fs from 'fs';
|
|
|
8
8
|
import * as path from 'path';
|
|
9
9
|
import * as yaml from 'yaml';
|
|
10
10
|
import { getProjectAgentsDir, getUserSubagentsDir, getSystemSubagentsDir, getEnabledExtraRepos, } from '../state.js';
|
|
11
|
+
import { isAgentHardDeprecated } from '../agents.js';
|
|
11
12
|
/** Get layer directories for subagent resolution. */
|
|
12
13
|
function getLayerDirs(cwd) {
|
|
13
14
|
const projectDir = getProjectAgentsDir(cwd);
|
|
@@ -155,6 +156,9 @@ export class SubagentsHandler {
|
|
|
155
156
|
* Copies YAML files to the target directory.
|
|
156
157
|
*/
|
|
157
158
|
sync(agent, versionHome, cwd) {
|
|
159
|
+
if (isAgentHardDeprecated(agent)) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
158
162
|
const targetDir = path.join(versionHome, this.targetDir(agent));
|
|
159
163
|
// Ensure target directory exists
|
|
160
164
|
if (!fs.existsSync(targetDir)) {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* - Union: All resources from all layers are combined
|
|
6
6
|
* - Override on name conflict: Higher layer wins (project > user > system)
|
|
7
7
|
*/
|
|
8
|
-
export type AgentId = 'claude' | 'codex' | 'gemini' | 'cursor' | 'opencode' | 'openclaw' | 'copilot' | 'kiro' | 'goose' | 'antigravity' | 'grok' | 'kimi' | 'droid' | 'hermes'
|
|
8
|
+
export type AgentId = 'claude' | 'codex' | 'gemini' | 'cursor' | 'opencode' | 'openclaw' | 'copilot' | 'kiro' | 'goose' | 'antigravity' | 'grok' | 'kimi' | 'droid' | 'hermes';
|
|
9
9
|
export type Layer = 'system' | 'user' | 'project';
|
|
10
10
|
export type ResourceKind = 'command' | 'hook' | 'skill' | 'rule' | 'mcp' | 'permission' | 'subagent' | 'workflow' | 'memory';
|
|
11
11
|
/** A resolved resource with its origin layer. */
|
package/dist/lib/routines.d.ts
CHANGED
|
@@ -187,6 +187,14 @@ export interface JobConfig {
|
|
|
187
187
|
resume?: string;
|
|
188
188
|
/** When set, executeJob runs this job through the loop driver instead of once. */
|
|
189
189
|
loop?: LoopConfig;
|
|
190
|
+
/**
|
|
191
|
+
* Actor id of whoever CREATED this routine (`resolveActor().id`, stamped by
|
|
192
|
+
* `writeJob` at creation and preserved across edits). Propagated into each
|
|
193
|
+
* fired run's env and RunMeta so an unattended cron traces back to the person
|
|
194
|
+
* who scheduled it, not the `UNRESOLVED@<host>` a live resolve would give.
|
|
195
|
+
* RUSH-2020.
|
|
196
|
+
*/
|
|
197
|
+
actor?: string;
|
|
190
198
|
}
|
|
191
199
|
/** Metadata for a single job execution, persisted as JSON in the run directory. */
|
|
192
200
|
export interface RunMeta {
|
|
@@ -216,6 +224,18 @@ export interface RunMeta {
|
|
|
216
224
|
cloudTaskId?: string;
|
|
217
225
|
/** Cloud provider id when the run was cloud-dispatched. */
|
|
218
226
|
cloudProvider?: string;
|
|
227
|
+
/**
|
|
228
|
+
* Actor id of the routine's CREATOR (stamped at creation, carried from the job
|
|
229
|
+
* config). Answers "whose scheduled run is this" for an unattended cron fire,
|
|
230
|
+
* where resolving the actor live would only yield `UNRESOLVED@<host>`. RUSH-2020.
|
|
231
|
+
*/
|
|
232
|
+
actor?: string;
|
|
233
|
+
/**
|
|
234
|
+
* Actor id that TRIGGERED this particular run (`resolveActor().id` at fire
|
|
235
|
+
* time): a person for a manual `agents routines run`, `UNRESOLVED@<host>` for
|
|
236
|
+
* an unattended scheduled fire. Distinct from {@link actor} (the creator).
|
|
237
|
+
*/
|
|
238
|
+
triggeredBy?: string;
|
|
219
239
|
}
|
|
220
240
|
/**
|
|
221
241
|
* Finalize a run record with a terminal status, computing `duration` from
|
package/dist/lib/routines.js
CHANGED
|
@@ -15,6 +15,7 @@ import { safeJoin, isSafeSegmentName } from './paths.js';
|
|
|
15
15
|
import { atomicWriteFileSync } from './fs-atomic.js';
|
|
16
16
|
import { ALL_AGENT_IDS } from './agents.js';
|
|
17
17
|
import { machineId, normalizeHost } from './machine-id.js';
|
|
18
|
+
import { resolveActor } from './actor.js';
|
|
18
19
|
export const HOST_STRATEGIES = ['local', 'host', 'fleet', 'cloud'];
|
|
19
20
|
/** Canonical set of accepted GitHub trigger events — single source for validation. */
|
|
20
21
|
export const GITHUB_TRIGGER_EVENTS = [
|
|
@@ -268,6 +269,11 @@ function readJobFile(filePath) {
|
|
|
268
269
|
*/
|
|
269
270
|
export function writeJob(config) {
|
|
270
271
|
ensureAgentsDir();
|
|
272
|
+
// Stamp the creator once (RUSH-2020). An edit re-writes a config loaded from
|
|
273
|
+
// disk, which already carries `actor`, so this preserves the original creator;
|
|
274
|
+
// only a brand-new routine (no actor yet) gets the current resolver.
|
|
275
|
+
if (!config.actor)
|
|
276
|
+
config.actor = resolveActor().id;
|
|
271
277
|
const jobsDir = getRoutinesDir();
|
|
272
278
|
const ymlPath = safeJoin(jobsDir, config.name + '.yml');
|
|
273
279
|
const yamlPath = safeJoin(jobsDir, config.name + '.yaml');
|
|
@@ -36,6 +36,7 @@ export declare function parseRunDefaultSelector(input: string): ParsedRunDefault
|
|
|
36
36
|
export declare function resolveRunDefaultsFromConfig(runConfig: RunConfig | undefined, agent: AgentId, version?: string | null): ResolvedRunDefaults;
|
|
37
37
|
export declare function resolveRunDefaultsFromConfigs(runConfigs: Array<RunConfig | undefined>, agent: AgentId, version?: string | null): ResolvedRunDefaults;
|
|
38
38
|
export declare function resolveRunDefaults(agent: AgentId, version?: string | null, startPath?: string): ResolvedRunDefaults;
|
|
39
|
+
export declare function formatRunDefaultEntry(entry: RunDefaultEntry): string;
|
|
39
40
|
export declare function listRunDefaults(): RunDefaultEntry[];
|
|
40
41
|
export declare function setRunDefault(selectorInput: string, defaultsInput: RunDefaultsInput): RunDefaultEntry;
|
|
41
42
|
export declare function unsetRunDefault(selectorInput: string): boolean;
|
package/dist/lib/run-defaults.js
CHANGED
|
@@ -15,6 +15,7 @@ import { ALL_MODES } from './types.js';
|
|
|
15
15
|
import { AGENTS } from './agents.js';
|
|
16
16
|
import { readMeta, updateMeta } from './state.js';
|
|
17
17
|
import { getProjectRunConfigs } from './run-config.js';
|
|
18
|
+
import chalk from 'chalk';
|
|
18
19
|
const VERSION_RE = /^(?:\*|latest|(?!.*\.\.)[A-Za-z0-9._+-]{1,64})$/;
|
|
19
20
|
function isAgentId(value) {
|
|
20
21
|
return value in AGENTS;
|
|
@@ -128,6 +129,14 @@ export function resolveRunDefaults(agent, version, startPath = process.cwd()) {
|
|
|
128
129
|
const projectRunConfigs = getProjectRunConfigs(startPath).reverse();
|
|
129
130
|
return resolveRunDefaultsFromConfigs([readMeta().run, ...projectRunConfigs], agent, version);
|
|
130
131
|
}
|
|
132
|
+
export function formatRunDefaultEntry(entry) {
|
|
133
|
+
const parts = [];
|
|
134
|
+
if (entry.defaults.mode)
|
|
135
|
+
parts.push(`mode ${chalk.white(entry.defaults.mode)}`);
|
|
136
|
+
if (entry.defaults.model)
|
|
137
|
+
parts.push(`model ${chalk.white(entry.defaults.model)}`);
|
|
138
|
+
return `${chalk.cyan(entry.selector.padEnd(22))} ${parts.join(' ')}`;
|
|
139
|
+
}
|
|
131
140
|
export function listRunDefaults() {
|
|
132
141
|
const defaults = readMeta().run?.defaults ?? {};
|
|
133
142
|
return Object.entries(defaults)
|
package/dist/lib/runner.d.ts
CHANGED
|
@@ -64,18 +64,6 @@ export declare function dispatchesViaAgentsRun(config: Pick<JobConfig, 'workflow
|
|
|
64
64
|
* with `agents run`.
|
|
65
65
|
*/
|
|
66
66
|
export declare function buildRoutineSpawnEnv(baseEnv: Record<string, string>, agent: AgentId, version: string | undefined, timezone?: string): Record<string, string>;
|
|
67
|
-
/**
|
|
68
|
-
* Execute a job synchronously (waits for completion or timeout before resolving).
|
|
69
|
-
*
|
|
70
|
-
* When `config.loop` is set the job is routed through the loop driver (`runLoop`
|
|
71
|
-
* from loop.ts) instead of a single spawn — same driver as `agents run --loop` and
|
|
72
|
-
* workflow `loop:` blocks (issue #400). The optional `deps` parameter provides
|
|
73
|
-
* injectable seams (runIteration, sleep, writeCheckpoint) used by tests; production
|
|
74
|
-
* callers omit it and get the defaults.
|
|
75
|
-
*
|
|
76
|
-
* Single-shot path: pre-flight version/account selection + mid-run rate-limit
|
|
77
|
-
* failover across healthy same-agent accounts (RUSH-1016).
|
|
78
|
-
*/
|
|
79
67
|
export declare function executeJob(config: JobConfig, deps?: LoopDeps): Promise<RunResult>;
|
|
80
68
|
/**
|
|
81
69
|
* Optional lifecycle callbacks for a detached routine run. The daemon passes an
|
package/dist/lib/runner.js
CHANGED
|
@@ -23,6 +23,7 @@ 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, detectAuthFailure, isAuthFailureFromLog, authFailureReason, } from './exec.js';
|
|
26
|
+
import { resolveActor } from './actor.js';
|
|
26
27
|
import { loadTask as loadHostTask } from './hosts/tasks.js';
|
|
27
28
|
import { reconcileTask as reconcileHostTask } from './hosts/reconcile.js';
|
|
28
29
|
import { backgroundSpawnOptions } from './platform/process.js';
|
|
@@ -398,12 +399,22 @@ export function buildRoutineSpawnEnv(baseEnv, agent, version, timezone) {
|
|
|
398
399
|
if (v !== undefined)
|
|
399
400
|
out[k] = v;
|
|
400
401
|
}
|
|
401
|
-
//
|
|
402
|
-
//
|
|
403
|
-
//
|
|
404
|
-
//
|
|
405
|
-
//
|
|
406
|
-
//
|
|
402
|
+
// A routine authenticates through the pinned account's own CLAUDE_CONFIG_DIR
|
|
403
|
+
// login on THIS box (buildExecEnv points it at the per-account version home).
|
|
404
|
+
// Claude Code's interactive session refreshes itself per-device; keeping the
|
|
405
|
+
// daemon out of the credential entirely is what avoids the fleet-wide rotation
|
|
406
|
+
// logout — a shared/rotating token was the cause, not the fix.
|
|
407
|
+
//
|
|
408
|
+
// Injecting a token was already ruled out, but INHERITING one was not:
|
|
409
|
+
// buildExecEnv spreads the ambient process.env (exec.ts) and sanitizeProcessEnv
|
|
410
|
+
// only strips loader/interpreter vars, never credentials. So on any box whose
|
|
411
|
+
// daemon environment happens to carry CLAUDE_CODE_OAUTH_TOKEN, every routine
|
|
412
|
+
// spawn silently ran on that one shared rotating token instead of the host's
|
|
413
|
+
// own login — the exact fleet-wide-logout path, arriving by inheritance rather
|
|
414
|
+
// than injection. CI never caught it because CI has no token to inherit; a
|
|
415
|
+
// provisioned box does. Drop it here so a routine always uses the login of the
|
|
416
|
+
// machine it runs on.
|
|
417
|
+
delete out.CLAUDE_CODE_OAUTH_TOKEN;
|
|
407
418
|
if (timezone)
|
|
408
419
|
out.TZ = timezone;
|
|
409
420
|
return out;
|
|
@@ -499,6 +510,28 @@ function spawnJobAttempt(cmd, env, attemptLogPath, timeoutMs, combinedLogPath) {
|
|
|
499
510
|
* Single-shot path: pre-flight version/account selection + mid-run rate-limit
|
|
500
511
|
* failover across healthy same-agent accounts (RUSH-1016).
|
|
501
512
|
*/
|
|
513
|
+
/**
|
|
514
|
+
* Actor provenance for a routine run (RUSH-2020): `actor` is the routine's
|
|
515
|
+
* CREATOR (carried from the job config), `triggeredBy` is whoever kicked off THIS
|
|
516
|
+
* run (`resolveActor().id` — a person for a manual run, `UNRESOLVED@<host>` for an
|
|
517
|
+
* unattended scheduled fire). Spread into every RunMeta so a fired cron traces
|
|
518
|
+
* back to the person who scheduled it.
|
|
519
|
+
*/
|
|
520
|
+
function runProvenance(config) {
|
|
521
|
+
return { ...(config.actor ? { actor: config.actor } : {}), triggeredBy: resolveActor().id };
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Inject the routine creator's actor into a run's base env so the fired agent
|
|
525
|
+
* INHERITS it (the `AGENTS_ACTOR` path in actor.ts) instead of re-resolving to
|
|
526
|
+
* `UNRESOLVED@<host>` on an unattended fire — so its session, events, and commits
|
|
527
|
+
* all attribute to the person who scheduled the routine (RUSH-2020). Mutates and
|
|
528
|
+
* returns the same env object for call-site brevity.
|
|
529
|
+
*/
|
|
530
|
+
function injectRoutineActor(env, config) {
|
|
531
|
+
if (config.actor && !env.AGENTS_ACTOR)
|
|
532
|
+
env.AGENTS_ACTOR = config.actor;
|
|
533
|
+
return env;
|
|
534
|
+
}
|
|
502
535
|
export async function executeJob(config, deps) {
|
|
503
536
|
const eligibility = checkJobDeviceEligibility(config);
|
|
504
537
|
if (eligibility) {
|
|
@@ -545,9 +578,9 @@ export async function executeJob(config, deps) {
|
|
|
545
578
|
const runId = generateRunId();
|
|
546
579
|
const runDir = getRunDir(config.name, runId);
|
|
547
580
|
fs.mkdirSync(runDir, { recursive: true });
|
|
548
|
-
const baseEnv = useSandbox
|
|
581
|
+
const baseEnv = injectRoutineActor(useSandbox
|
|
549
582
|
? buildSpawnEnv(overlayHome)
|
|
550
|
-
: { ...process.env };
|
|
583
|
+
: { ...process.env }, config);
|
|
551
584
|
// Workflows run via `agents run <workflow>` which delegates to claude under the hood.
|
|
552
585
|
// Use 'claude' as the effective agent for report extraction and metadata when workflow is set.
|
|
553
586
|
// (command jobs branched out earlier, so config.agent is set on the non-workflow path.)
|
|
@@ -555,6 +588,7 @@ export async function executeJob(config, deps) {
|
|
|
555
588
|
const meta = {
|
|
556
589
|
jobName: config.name,
|
|
557
590
|
runId,
|
|
591
|
+
...runProvenance(config),
|
|
558
592
|
agent: effectiveAgent,
|
|
559
593
|
...(config.workflow ? { workflow: config.workflow } : {}),
|
|
560
594
|
pid: null,
|
|
@@ -770,6 +804,7 @@ async function executeJobOnCloud(config, opts) {
|
|
|
770
804
|
const meta = {
|
|
771
805
|
jobName: config.name,
|
|
772
806
|
runId,
|
|
807
|
+
...runProvenance(config),
|
|
773
808
|
agent: config.agent,
|
|
774
809
|
pid: null,
|
|
775
810
|
spawnedAt: Date.now(),
|
|
@@ -841,6 +876,7 @@ async function executeJobOnHost(config, opts) {
|
|
|
841
876
|
const meta = {
|
|
842
877
|
jobName: config.name,
|
|
843
878
|
runId,
|
|
879
|
+
...runProvenance(config),
|
|
844
880
|
agent: config.agent,
|
|
845
881
|
pid: null, // no local process — the run lives on the host
|
|
846
882
|
spawnedAt: Date.now(),
|
|
@@ -888,6 +924,7 @@ async function executeCommandJobForeground(config) {
|
|
|
888
924
|
const meta = {
|
|
889
925
|
jobName: config.name,
|
|
890
926
|
runId,
|
|
927
|
+
...runProvenance(config),
|
|
891
928
|
command: config.command,
|
|
892
929
|
pid: null,
|
|
893
930
|
spawnedAt: Date.now(),
|
|
@@ -1019,9 +1056,9 @@ export async function executeJobDetached(config, hooks) {
|
|
|
1019
1056
|
fs.mkdirSync(runDir, { recursive: true });
|
|
1020
1057
|
const stdoutPath = path.join(runDir, 'stdout.log');
|
|
1021
1058
|
const stdoutFd = fs.openSync(stdoutPath, 'w', 0o600);
|
|
1022
|
-
const baseEnv = useSandbox
|
|
1059
|
+
const baseEnv = injectRoutineActor(useSandbox
|
|
1023
1060
|
? buildSpawnEnv(overlayHome)
|
|
1024
|
-
: { ...process.env };
|
|
1061
|
+
: { ...process.env }, config);
|
|
1025
1062
|
const spawnEnv = dispatchesViaAgentsRun(config)
|
|
1026
1063
|
? (() => {
|
|
1027
1064
|
const e = { ...baseEnv };
|
|
@@ -1035,6 +1072,7 @@ export async function executeJobDetached(config, hooks) {
|
|
|
1035
1072
|
const meta = {
|
|
1036
1073
|
jobName: config.name,
|
|
1037
1074
|
runId,
|
|
1075
|
+
...runProvenance(config),
|
|
1038
1076
|
agent: effectiveAgent,
|
|
1039
1077
|
...(config.workflow ? { workflow: config.workflow } : {}),
|
|
1040
1078
|
pid: null,
|
|
@@ -1155,6 +1193,7 @@ function executeCommandJobDetached(config, hooks) {
|
|
|
1155
1193
|
const meta = {
|
|
1156
1194
|
jobName: config.name,
|
|
1157
1195
|
runId,
|
|
1196
|
+
...runProvenance(config),
|
|
1158
1197
|
command: config.command,
|
|
1159
1198
|
pid: null,
|
|
1160
1199
|
spawnedAt: Date.now(),
|
|
Binary file
|
|
Binary file
|