@phnx-labs/agents-cli 1.20.72 → 1.20.74
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 +395 -0
- 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/doctor.js +21 -5
- 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/export.d.ts +11 -0
- package/dist/commands/export.js +215 -0
- 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/import.js +51 -3
- 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 +1 -1
- 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/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.js +18 -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 +9 -2
- package/dist/commands/share.d.ts +8 -1
- package/dist/commands/share.js +122 -37
- package/dist/commands/ssh.d.ts +9 -0
- package/dist/commands/ssh.js +196 -26
- package/dist/commands/sync.js +1 -1
- package/dist/commands/teams.js +11 -2
- package/dist/commands/versions.js +36 -5
- package/dist/commands/view.js +75 -27
- package/dist/index.js +80 -10
- package/dist/lib/activity.d.ts +124 -0
- package/dist/lib/activity.js +542 -0
- package/dist/lib/agents.d.ts +35 -0
- package/dist/lib/agents.js +79 -6
- 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/config-transfer.d.ts +16 -0
- package/dist/lib/config-transfer.js +56 -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 +5 -5
- package/dist/lib/daemon.js +9 -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/export.d.ts +72 -0
- package/dist/lib/export.js +269 -0
- 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/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/import.d.ts +23 -0
- package/dist/lib/import.js +74 -2
- package/dist/lib/isolation-boundary-report.d.ts +10 -0
- package/dist/lib/isolation-boundary-report.js +35 -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 +306 -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 +35 -0
- package/dist/lib/shims.js +159 -13
- 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 +17 -4
- 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 +84 -0
- package/dist/lib/uninstall.js +1 -45
- package/dist/lib/version.d.ts +40 -0
- package/dist/lib/version.js +94 -16
- package/dist/lib/versions.d.ts +24 -0
- package/dist/lib/versions.js +269 -78
- 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
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { execFileSync, spawnSync } from 'child_process';
|
|
2
|
+
import { getCliLaunch } from './cli-entry.js';
|
|
3
|
+
import { buildAddGenericPasswordArgs, buildAddGenericPasswordSpawnOptions, } from './secrets/index.js';
|
|
4
|
+
export const OPENCLAW_KEYCHAIN_ACCOUNT = 'openclaw';
|
|
5
|
+
export const OPENCLAW_KEYCHAIN_PROVIDER = 'agents_keychain';
|
|
6
|
+
export const OPENCLAW_KEYCHAIN_ENV_SERVICES = {
|
|
7
|
+
OPENROUTER_API_KEY: 'openrouter-api-key',
|
|
8
|
+
LINEAR_API_KEY: 'linear-api-key',
|
|
9
|
+
GRAFANA_API_KEY: 'grafana-api-key',
|
|
10
|
+
POSTHOG_API_KEY: 'posthog-api-key',
|
|
11
|
+
};
|
|
12
|
+
function isRecord(value) {
|
|
13
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
14
|
+
}
|
|
15
|
+
function secretRef(provider, service) {
|
|
16
|
+
return { source: 'exec', provider, id: service };
|
|
17
|
+
}
|
|
18
|
+
function openClawPath(parts) {
|
|
19
|
+
return parts.join('.');
|
|
20
|
+
}
|
|
21
|
+
function collectOpenClawEnv(config) {
|
|
22
|
+
const env = isRecord(config.env) ? config.env : null;
|
|
23
|
+
const out = new Map();
|
|
24
|
+
if (!env)
|
|
25
|
+
return out;
|
|
26
|
+
for (const [key, service] of Object.entries(OPENCLAW_KEYCHAIN_ENV_SERVICES)) {
|
|
27
|
+
void service;
|
|
28
|
+
const top = env[key];
|
|
29
|
+
if (typeof top === 'string' && top.trim()) {
|
|
30
|
+
out.set(key, { path: ['env', key], value: top });
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const vars = isRecord(env.vars) ? env.vars : null;
|
|
34
|
+
const nested = vars?.[key];
|
|
35
|
+
if (typeof nested === 'string' && nested.trim()) {
|
|
36
|
+
out.set(key, { path: ['env', 'vars', key], value: nested });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
function deletePath(config, parts) {
|
|
42
|
+
let current = config;
|
|
43
|
+
for (const part of parts.slice(0, -1)) {
|
|
44
|
+
if (!isRecord(current))
|
|
45
|
+
return false;
|
|
46
|
+
current = current[part];
|
|
47
|
+
}
|
|
48
|
+
if (!isRecord(current))
|
|
49
|
+
return false;
|
|
50
|
+
const key = parts[parts.length - 1];
|
|
51
|
+
if (!(key in current))
|
|
52
|
+
return false;
|
|
53
|
+
delete current[key];
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
function normalizeObject(value) {
|
|
57
|
+
return isRecord(value) ? value : {};
|
|
58
|
+
}
|
|
59
|
+
function ensureOpenClawKeychainProvider(config, opts, agentsBin) {
|
|
60
|
+
const launch = getCliLaunch(['secrets', 'openclaw-keychain', 'resolve', '--account', opts.account], agentsBin);
|
|
61
|
+
const secrets = normalizeObject(config.secrets);
|
|
62
|
+
const providers = normalizeObject(secrets.providers);
|
|
63
|
+
providers[opts.provider] = {
|
|
64
|
+
source: 'exec',
|
|
65
|
+
command: launch.command,
|
|
66
|
+
args: launch.args,
|
|
67
|
+
jsonOnly: true,
|
|
68
|
+
};
|
|
69
|
+
secrets.providers = providers;
|
|
70
|
+
config.secrets = secrets;
|
|
71
|
+
}
|
|
72
|
+
function providerEnvKeyForPath(parts) {
|
|
73
|
+
if (parts.length === 8 &&
|
|
74
|
+
parts[0] === 'plugins' &&
|
|
75
|
+
parts[1] === 'entries' &&
|
|
76
|
+
parts[3] === 'config' &&
|
|
77
|
+
parts[4] === 'mcpServers' &&
|
|
78
|
+
parts[6] === 'env') {
|
|
79
|
+
return parts[7];
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
function serviceForSupportedPath(parts) {
|
|
84
|
+
const envKey = providerEnvKeyForPath(parts);
|
|
85
|
+
if (envKey)
|
|
86
|
+
return OPENCLAW_KEYCHAIN_ENV_SERVICES[envKey] ?? null;
|
|
87
|
+
if (parts.length === 4 && parts[0] === 'models' && parts[1] === 'providers' && parts[3] === 'apiKey') {
|
|
88
|
+
if (parts[2] === 'openrouter')
|
|
89
|
+
return OPENCLAW_KEYCHAIN_ENV_SERVICES.OPENROUTER_API_KEY;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
function envKeyForService(service) {
|
|
94
|
+
return Object.entries(OPENCLAW_KEYCHAIN_ENV_SERVICES).find(([, known]) => known === service)?.[0] ?? service;
|
|
95
|
+
}
|
|
96
|
+
function assertSameOpenClawSecretValue(envKey, service, existingPath, existingValue, nextPath, nextValue) {
|
|
97
|
+
if (existingValue === nextValue)
|
|
98
|
+
return;
|
|
99
|
+
throw new Error(`OpenClaw credential value mismatch for ${envKey} (${service}): ${existingPath} and ${nextPath} differ. ` +
|
|
100
|
+
`Resolve the plaintext values before migrating to Keychain.`);
|
|
101
|
+
}
|
|
102
|
+
function canReplaceByValue(parts) {
|
|
103
|
+
if (parts.length === 4 && parts[0] === 'models' && parts[1] === 'providers' && parts[3] === 'apiKey')
|
|
104
|
+
return true;
|
|
105
|
+
if (parts.length === 6 && parts[0] === 'plugins' && parts[1] === 'entries' && parts[3] === 'config' && parts[4] === 'webSearch' && parts[5] === 'apiKey')
|
|
106
|
+
return true;
|
|
107
|
+
if (parts.length === 5 && parts[0] === 'tools' && parts[1] === 'web' && parts[2] === 'search' && parts[4] === 'apiKey')
|
|
108
|
+
return true;
|
|
109
|
+
if (parts.length === 4 && parts[0] === 'tools' && parts[1] === 'web' && parts[2] === 'search' && parts[3] === 'apiKey')
|
|
110
|
+
return true;
|
|
111
|
+
return providerEnvKeyForPath(parts) !== null;
|
|
112
|
+
}
|
|
113
|
+
function replaceSupportedSecrets(current, parts, provider, envByValue, env, services, servicePaths, replacedPaths) {
|
|
114
|
+
if (!isRecord(current) && !Array.isArray(current))
|
|
115
|
+
return;
|
|
116
|
+
const entries = Array.isArray(current)
|
|
117
|
+
? current.map((value, index) => [String(index), value])
|
|
118
|
+
: Object.entries(current);
|
|
119
|
+
for (const [key, value] of entries) {
|
|
120
|
+
const childParts = [...parts, key];
|
|
121
|
+
if (typeof value === 'string' && value.trim() && canReplaceByValue(childParts)) {
|
|
122
|
+
const directService = serviceForSupportedPath(childParts);
|
|
123
|
+
const matchedService = directService ?? envByValue.get(value);
|
|
124
|
+
if (matchedService) {
|
|
125
|
+
const envKey = envKeyForService(matchedService);
|
|
126
|
+
const childPath = openClawPath(childParts);
|
|
127
|
+
const existingService = services.get(matchedService);
|
|
128
|
+
if (existingService) {
|
|
129
|
+
assertSameOpenClawSecretValue(envKey, matchedService, servicePaths.get(matchedService) ?? matchedService, existingService.value, childPath, value);
|
|
130
|
+
}
|
|
131
|
+
if (directService) {
|
|
132
|
+
const envEntry = env.get(envKey);
|
|
133
|
+
if (envEntry) {
|
|
134
|
+
assertSameOpenClawSecretValue(envKey, matchedService, openClawPath(envEntry.path), envEntry.value, childPath, value);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
services.set(matchedService, { envKey, service: matchedService, value });
|
|
138
|
+
servicePaths.set(matchedService, childPath);
|
|
139
|
+
current[key] = secretRef(provider, matchedService);
|
|
140
|
+
replacedPaths.push(childPath);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
replaceSupportedSecrets(value, childParts, provider, envByValue, env, services, servicePaths, replacedPaths);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
export function migrateOpenClawConfigToKeychainRefs(config, opts = {}) {
|
|
148
|
+
const account = opts.account ?? OPENCLAW_KEYCHAIN_ACCOUNT;
|
|
149
|
+
const provider = opts.provider ?? OPENCLAW_KEYCHAIN_PROVIDER;
|
|
150
|
+
const env = collectOpenClawEnv(config);
|
|
151
|
+
const envByValue = new Map();
|
|
152
|
+
for (const [envKey, entry] of env) {
|
|
153
|
+
envByValue.set(entry.value, OPENCLAW_KEYCHAIN_ENV_SERVICES[envKey]);
|
|
154
|
+
}
|
|
155
|
+
const services = new Map();
|
|
156
|
+
const servicePaths = new Map();
|
|
157
|
+
const replacedPaths = [];
|
|
158
|
+
replaceSupportedSecrets(config, [], provider, envByValue, env, services, servicePaths, replacedPaths);
|
|
159
|
+
const removedEnvPaths = [];
|
|
160
|
+
const unsupportedEnvKeys = [];
|
|
161
|
+
for (const [envKey, entry] of env) {
|
|
162
|
+
const service = OPENCLAW_KEYCHAIN_ENV_SERVICES[envKey];
|
|
163
|
+
const mappedService = services.get(service);
|
|
164
|
+
if (!mappedService) {
|
|
165
|
+
unsupportedEnvKeys.push(envKey);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
assertSameOpenClawSecretValue(envKey, service, servicePaths.get(service) ?? service, mappedService.value, openClawPath(entry.path), entry.value);
|
|
169
|
+
if (deletePath(config, entry.path))
|
|
170
|
+
removedEnvPaths.push(openClawPath(entry.path));
|
|
171
|
+
}
|
|
172
|
+
if (services.size > 0) {
|
|
173
|
+
ensureOpenClawKeychainProvider(config, { account, provider }, opts.agentsBin);
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
services: [...services.values()],
|
|
177
|
+
replacedPaths,
|
|
178
|
+
removedEnvPaths,
|
|
179
|
+
unsupportedEnvKeys,
|
|
180
|
+
changed: services.size > 0 || replacedPaths.length > 0 || removedEnvPaths.length > 0,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
export function buildOpenClawKeychainStoreInvocation(service, value, account = OPENCLAW_KEYCHAIN_ACCOUNT) {
|
|
184
|
+
return {
|
|
185
|
+
command: '/usr/bin/security',
|
|
186
|
+
args: buildAddGenericPasswordArgs(account, service),
|
|
187
|
+
options: buildAddGenericPasswordSpawnOptions(value),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
export function storeOpenClawKeychainServices(services, account = OPENCLAW_KEYCHAIN_ACCOUNT) {
|
|
191
|
+
if (process.platform !== 'darwin') {
|
|
192
|
+
throw new Error('OpenClaw Keychain migration must run on macOS.');
|
|
193
|
+
}
|
|
194
|
+
for (const { service, value } of services) {
|
|
195
|
+
const write = buildOpenClawKeychainStoreInvocation(service, value, account);
|
|
196
|
+
const result = spawnSync(write.command, write.args, write.options);
|
|
197
|
+
if (result.status !== 0) {
|
|
198
|
+
const msg = result.stderr?.toString().trim();
|
|
199
|
+
throw new Error(msg || `Failed to write OpenClaw Keychain service '${service}'.`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function stripSecurityTrailingNewline(value) {
|
|
204
|
+
return value.replace(/\r?\n$/, '');
|
|
205
|
+
}
|
|
206
|
+
export function readOpenClawKeychainService(service, account = OPENCLAW_KEYCHAIN_ACCOUNT) {
|
|
207
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._:/#-]{0,255}$/.test(service)) {
|
|
208
|
+
throw new Error(`Invalid OpenClaw Keychain service id '${service}'.`);
|
|
209
|
+
}
|
|
210
|
+
if (process.platform !== 'darwin') {
|
|
211
|
+
throw new Error('OpenClaw Keychain resolver must run on macOS.');
|
|
212
|
+
}
|
|
213
|
+
const value = execFileSync('/usr/bin/security', ['find-generic-password', '-s', service, '-a', account, '-w'], {
|
|
214
|
+
encoding: 'utf-8',
|
|
215
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
216
|
+
});
|
|
217
|
+
return stripSecurityTrailingNewline(value);
|
|
218
|
+
}
|
|
219
|
+
export function resolveOpenClawKeychainRequest(request, lookup) {
|
|
220
|
+
const ids = Array.isArray(request.ids) ? request.ids.filter((id) => typeof id === 'string') : [];
|
|
221
|
+
const values = {};
|
|
222
|
+
const errors = {};
|
|
223
|
+
for (const id of ids) {
|
|
224
|
+
try {
|
|
225
|
+
values[id] = lookup(id);
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
errors[id] = { code: 'NOT_FOUND' };
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
protocolVersion: 1,
|
|
233
|
+
values,
|
|
234
|
+
...(Object.keys(errors).length > 0 ? { errors } : {}),
|
|
235
|
+
};
|
|
236
|
+
}
|
package/dist/lib/overdue.js
CHANGED
|
@@ -93,6 +93,11 @@ export function notifyOverdue(jobs) {
|
|
|
93
93
|
const safeTitle = title.replace(/"/g, '\\"');
|
|
94
94
|
const safeBody = body.replace(/"/g, '\\"');
|
|
95
95
|
const child = spawn('osascript', ['-e', `display notification "${safeBody}" with title "${safeTitle}"`], { detached: true, stdio: 'ignore' });
|
|
96
|
+
// A missing binary surfaces as an async 'error' event, NOT a synchronous
|
|
97
|
+
// throw the try/catch would catch. Without a listener Node re-throws it as
|
|
98
|
+
// an uncaught exception and takes the whole daemon down. Swallow it — the
|
|
99
|
+
// notification is best-effort.
|
|
100
|
+
child.on('error', () => { });
|
|
96
101
|
child.unref();
|
|
97
102
|
}
|
|
98
103
|
else if (platform === 'linux') {
|
|
@@ -100,6 +105,11 @@ export function notifyOverdue(jobs) {
|
|
|
100
105
|
detached: true,
|
|
101
106
|
stdio: 'ignore',
|
|
102
107
|
});
|
|
108
|
+
// Headless Linux boxes have no `notify-send` (libnotify-bin); its ENOENT
|
|
109
|
+
// arrives as an async 'error' event, not a throw. Without this listener
|
|
110
|
+
// the daemon crashes on every overdue routine and systemd restart-loops it
|
|
111
|
+
// (which also tears down the browser IPC socket). Swallow — best-effort.
|
|
112
|
+
child.on('error', () => { });
|
|
103
113
|
child.unref();
|
|
104
114
|
}
|
|
105
115
|
}
|
|
@@ -104,6 +104,22 @@ export declare function convertToClaudeFormat(set: PermissionSet): ClaudePermiss
|
|
|
104
104
|
* (`~/.cursor/cli-config.json` permissions.allow/deny).
|
|
105
105
|
*/
|
|
106
106
|
export declare function convertToCursorFormat(set: PermissionSet): CursorPermissions;
|
|
107
|
+
type CopilotToolApproval = {
|
|
108
|
+
kind: 'commands';
|
|
109
|
+
commandIdentifiers: string[];
|
|
110
|
+
} | {
|
|
111
|
+
kind: 'read' | 'write';
|
|
112
|
+
} | {
|
|
113
|
+
kind: 'mcp';
|
|
114
|
+
serverName: string;
|
|
115
|
+
toolName: string | null;
|
|
116
|
+
};
|
|
117
|
+
export interface CopilotPermissionsConfig {
|
|
118
|
+
locations: Record<string, {
|
|
119
|
+
tool_approvals?: CopilotToolApproval[];
|
|
120
|
+
allowed_directories?: string[];
|
|
121
|
+
}>;
|
|
122
|
+
}
|
|
107
123
|
/**
|
|
108
124
|
* Convert canonical permission set to Gemini format.
|
|
109
125
|
* Gemini reads tool allow/deny lists from settings.json under
|
|
@@ -117,6 +133,7 @@ export declare function convertToGeminiFormat(set: PermissionSet): {
|
|
|
117
133
|
exclude?: string[];
|
|
118
134
|
};
|
|
119
135
|
};
|
|
136
|
+
export declare function convertToCopilotFormat(set: PermissionSet, location: string): CopilotPermissionsConfig;
|
|
120
137
|
/** Convert canonical Bash rules into Droid's command arrays. */
|
|
121
138
|
export declare function convertToDroidFormat(set: PermissionSet): {
|
|
122
139
|
commandAllowlist: string[];
|
|
@@ -137,6 +154,31 @@ export declare function convertToOpenClawFormat(set: PermissionSet): {
|
|
|
137
154
|
alsoAllow: string[];
|
|
138
155
|
deny: string[];
|
|
139
156
|
};
|
|
157
|
+
export type ForgePermission = 'allow' | 'deny' | 'confirm';
|
|
158
|
+
export type ForgeOperation = 'read' | 'write' | 'command' | 'url';
|
|
159
|
+
export type ForgePolicy = {
|
|
160
|
+
permission: ForgePermission;
|
|
161
|
+
rule: Partial<Record<ForgeOperation, string>>;
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Convert canonical permissions to ForgeCode's permissions.yaml policy list.
|
|
165
|
+
*
|
|
166
|
+
* ForgeCode gates built-in tools by operation family (`read`, `write`,
|
|
167
|
+
* `command`, `url`) plus glob patterns, optionally scoped by `dir`. The policy
|
|
168
|
+
* file is ignored unless `.forge.toml` has `restricted = true`, and MCP tools
|
|
169
|
+
* bypass permissions.yaml entirely; agents-cli therefore maps only canonical
|
|
170
|
+
* built-in allow/deny rules and does not try to express per-named-MCP-tool
|
|
171
|
+
* grants.
|
|
172
|
+
*/
|
|
173
|
+
export declare function convertToForgeFormat(set: PermissionSet): {
|
|
174
|
+
policies: ForgePolicy[];
|
|
175
|
+
};
|
|
176
|
+
export declare function convertToHermesFormat(set: PermissionSet): {
|
|
177
|
+
command_allowlist: string[];
|
|
178
|
+
approvals: {
|
|
179
|
+
deny: string[];
|
|
180
|
+
};
|
|
181
|
+
};
|
|
140
182
|
/**
|
|
141
183
|
* Convert canonical permission set to Antigravity format.
|
|
142
184
|
* Antigravity reads ~/.gemini/antigravity-cli/settings.json with
|
|
@@ -252,7 +294,7 @@ export declare function openCodeConfigPath(scope: 'user' | 'project', cwd?: stri
|
|
|
252
294
|
* Apply a permission set to a specific version's home directory.
|
|
253
295
|
* This writes to {versionHome}/.{agent}/settings.json (or equivalent).
|
|
254
296
|
*/
|
|
255
|
-
export declare function applyPermissionsToVersion(agentId: AgentId, set: PermissionSet, versionHome: string, merge?: boolean): {
|
|
297
|
+
export declare function applyPermissionsToVersion(agentId: AgentId, set: PermissionSet, versionHome: string, merge?: boolean, cwd?: string): {
|
|
256
298
|
success: boolean;
|
|
257
299
|
error?: string;
|
|
258
300
|
};
|
|
@@ -302,3 +344,4 @@ export declare function saveDefaultPermissionSet(set: PermissionSet): {
|
|
|
302
344
|
success: boolean;
|
|
303
345
|
error?: string;
|
|
304
346
|
};
|
|
347
|
+
export {};
|