@phnx-labs/agents-cli 1.22.46 → 1.22.49
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 +663 -0
- package/LICENSE +102 -182
- package/README.md +96 -49
- package/dist/bootstrap.js +4 -2
- package/dist/cli/command-registry.d.ts +2 -1
- package/dist/cli/command-registry.js +6 -2
- package/dist/commands/accounts.d.ts +58 -0
- package/dist/commands/accounts.js +243 -25
- package/dist/commands/artifacts.js +7 -6
- package/dist/commands/attach.js +1 -1
- package/dist/commands/auth.js +7 -5
- package/dist/commands/browser-sessions-picker.js +9 -7
- package/dist/commands/browser.js +711 -62
- package/dist/commands/config.d.ts +0 -1
- package/dist/commands/config.js +26 -24
- package/dist/commands/cost.d.ts +1 -1
- package/dist/commands/daemon.d.ts +21 -0
- package/dist/commands/daemon.js +147 -12
- package/dist/commands/detach.d.ts +13 -0
- package/dist/commands/detach.js +11 -8
- package/dist/commands/exec.js +107 -53
- package/dist/commands/feed-watch.d.ts +2 -0
- package/dist/commands/feed-watch.js +28 -0
- package/dist/commands/feed.js +27 -0
- package/dist/commands/feedback.js +3 -19
- package/dist/commands/focus.d.ts +14 -0
- package/dist/commands/focus.js +48 -5
- package/dist/commands/go.d.ts +3 -0
- package/dist/commands/go.js +16 -3
- package/dist/commands/insights.d.ts +1 -1
- package/dist/commands/insights.js +2 -2
- package/dist/commands/inspect.js +2 -2
- package/dist/commands/lease.d.ts +1 -1
- package/dist/commands/lease.js +7 -6
- package/dist/commands/mailboxes.js +4 -3
- package/dist/commands/menubar.js +11 -4
- package/dist/commands/projects.d.ts +16 -1
- package/dist/commands/projects.js +58 -64
- package/dist/commands/resume.js +1 -1
- package/dist/commands/route.js +4 -4
- package/dist/commands/routines.js +4 -3
- package/dist/commands/run-broadcast.d.ts +1 -1
- package/dist/commands/run-broadcast.js +1 -1
- package/dist/commands/sessions-picker-factory.d.ts +2 -1
- package/dist/commands/sessions-picker-factory.js +1 -1
- package/dist/commands/sessions-picker.d.ts +22 -0
- package/dist/commands/sessions-picker.js +48 -9
- package/dist/commands/sessions-stop.d.ts +24 -0
- package/dist/commands/sessions-stop.js +66 -0
- package/dist/commands/sessions-trace.d.ts +82 -0
- package/dist/commands/sessions-trace.js +387 -0
- package/dist/commands/sessions.js +5 -0
- package/dist/commands/setup-secrets.js +23 -0
- package/dist/commands/share.d.ts +20 -5
- package/dist/commands/share.js +152 -52
- package/dist/commands/ssh.d.ts +15 -0
- package/dist/commands/ssh.js +243 -18
- package/dist/commands/teams.js +34 -2
- package/dist/commands/traces.d.ts +2 -0
- package/dist/commands/traces.js +184 -0
- package/dist/commands/view.d.ts +2 -0
- package/dist/commands/view.js +32 -62
- package/dist/commands/watchdog.js +9 -14
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/dist/lib/account-capabilities.d.ts +4 -0
- package/dist/lib/account-capabilities.js +13 -9
- package/dist/lib/account-registry.d.ts +2 -0
- package/dist/lib/account-registry.js +30 -2
- package/dist/lib/accounting/rotate.d.ts +9 -0
- package/dist/lib/accounting/rotate.js +12 -2
- package/dist/lib/accounting/usage.d.ts +84 -6
- package/dist/lib/accounting/usage.js +293 -75
- package/dist/lib/agent-modes.js +29 -1
- package/dist/lib/agent-spec/agents.d.ts +4 -3
- package/dist/lib/agent-spec/agents.js +25 -15
- package/dist/lib/analytics/mix-commands.d.ts +1 -1
- package/dist/lib/analytics/mix-commands.js +2 -2
- package/dist/lib/auth-health.d.ts +13 -3
- package/dist/lib/auth-health.js +50 -8
- package/dist/lib/browser/devices.d.ts +19 -0
- package/dist/lib/browser/devices.js +23 -0
- package/dist/lib/browser/drivers/ssh.d.ts +16 -2
- package/dist/lib/browser/drivers/ssh.js +36 -9
- package/dist/lib/browser/ipc.d.ts +1 -1
- package/dist/lib/browser/ipc.js +40 -9
- package/dist/lib/browser/profiles.d.ts +104 -65
- package/dist/lib/browser/profiles.js +277 -165
- package/dist/lib/browser/registry.d.ts +39 -0
- package/dist/lib/browser/registry.js +149 -0
- package/dist/lib/browser/remote-control.d.ts +28 -2
- package/dist/lib/browser/remote-control.js +35 -3
- package/dist/lib/browser/resolve-target.d.ts +68 -0
- package/dist/lib/browser/resolve-target.js +250 -0
- package/dist/lib/browser/runtime-state.d.ts +44 -11
- package/dist/lib/browser/runtime-state.js +98 -15
- package/dist/lib/browser/service.d.ts +65 -9
- package/dist/lib/browser/service.js +196 -61
- package/dist/lib/browser/sessions-list.d.ts +1 -3
- package/dist/lib/browser/sessions-list.js +3 -16
- package/dist/lib/browser/task-index.d.ts +70 -0
- package/dist/lib/browser/task-index.js +180 -0
- package/dist/lib/browser/types.d.ts +12 -1
- package/dist/lib/byok-usage.js +2 -2
- package/dist/lib/claude-statusline.d.ts +29 -0
- package/dist/lib/claude-statusline.js +139 -0
- package/dist/lib/cloud/host.d.ts +1 -1
- package/dist/lib/cloud/host.js +1 -1
- package/dist/lib/cloud/rush.js +1 -1
- package/dist/lib/codex-policy.d.ts +11 -1
- package/dist/lib/codex-policy.js +20 -5
- package/dist/lib/computer/computer-rpc.js +2 -2
- package/dist/lib/computer/download.d.ts +15 -15
- package/dist/lib/computer/download.js +35 -98
- package/dist/lib/computer/ssh-tunnel.d.ts +0 -3
- package/dist/lib/computer/ssh-tunnel.js +12 -22
- package/dist/lib/config-keys.d.ts +6 -11
- package/dist/lib/config-keys.js +18 -19
- package/dist/lib/crabbox/cli.d.ts +1 -1
- package/dist/lib/crabbox/cli.js +2 -2
- package/dist/lib/crabbox/lease.d.ts +9 -0
- package/dist/lib/crabbox/lease.js +70 -15
- package/dist/lib/crabbox/runtimes.js +1 -1
- package/dist/lib/daemon/account-state-daemon-service.d.ts +16 -0
- package/dist/lib/daemon/account-state-daemon-service.js +26 -0
- package/dist/lib/daemon/browser-ipc-service.d.ts +20 -0
- package/dist/lib/daemon/browser-ipc-service.js +46 -0
- package/dist/lib/daemon/daemon.d.ts +3 -0
- package/dist/lib/daemon/daemon.js +212 -444
- package/dist/lib/daemon/device-probe-service.d.ts +26 -0
- package/dist/lib/daemon/device-probe-service.js +47 -0
- package/dist/lib/daemon/keychain-reap-service.d.ts +17 -0
- package/dist/lib/daemon/keychain-reap-service.js +32 -0
- package/dist/lib/daemon/monitor-engine-service.d.ts +22 -0
- package/dist/lib/daemon/monitor-engine-service.js +29 -0
- package/dist/lib/daemon/runner.js +15 -2
- package/dist/lib/daemon/secrets-broker-service.d.ts +20 -0
- package/dist/lib/daemon/secrets-broker-service.js +66 -0
- package/dist/lib/daemon/self-heal-service.d.ts +27 -0
- package/dist/lib/daemon/self-heal-service.js +48 -0
- package/dist/lib/daemon/service.d.ts +102 -0
- package/dist/lib/daemon/service.js +98 -0
- package/dist/lib/daemon/session-index-service.d.ts +22 -0
- package/dist/lib/daemon/session-index-service.js +40 -0
- package/dist/lib/daemon/state-dir-check-service.d.ts +43 -0
- package/dist/lib/daemon/state-dir-check-service.js +63 -0
- package/dist/lib/daemon/supervisor.d.ts +87 -0
- package/dist/lib/daemon/supervisor.js +298 -0
- package/dist/lib/daemon/watchdog-service.d.ts +19 -0
- package/dist/lib/daemon/watchdog-service.js +40 -0
- package/dist/lib/daemon-health.d.ts +15 -0
- package/dist/lib/daemon-health.js +29 -5
- package/dist/lib/daemon-services.d.ts +8 -1
- package/dist/lib/daemon-services.js +55 -0
- package/dist/lib/daemon-ticks.d.ts +13 -2
- package/dist/lib/daemon-ticks.js +22 -20
- package/dist/lib/device-config.d.ts +25 -10
- package/dist/lib/device-config.js +90 -39
- package/dist/lib/devices/config-migration.d.ts +7 -0
- package/dist/lib/devices/config-migration.js +67 -3
- package/dist/lib/devices/health.d.ts +27 -2
- package/dist/lib/devices/health.js +39 -9
- package/dist/lib/devices/interactive-host.d.ts +15 -0
- package/dist/lib/devices/interactive-host.js +53 -0
- package/dist/lib/devices/registry.d.ts +61 -4
- package/dist/lib/devices/registry.js +94 -38
- package/dist/lib/devices/stats-cache.d.ts +26 -0
- package/dist/lib/devices/stats-cache.js +59 -7
- package/dist/lib/devices/worker-pick.d.ts +48 -0
- package/dist/lib/devices/worker-pick.js +113 -0
- package/dist/lib/exec.d.ts +70 -14
- package/dist/lib/exec.js +110 -38
- package/dist/lib/feed/answer.d.ts +29 -0
- package/dist/lib/feed/answer.js +145 -0
- package/dist/lib/feed/attention.d.ts +83 -0
- package/dist/lib/feed/attention.js +0 -0
- package/dist/lib/feed/feed.d.ts +109 -0
- package/dist/lib/feed/feed.js +154 -3
- package/dist/lib/feed/pr-status.d.ts +14 -0
- package/dist/lib/feed/pr-status.js +47 -0
- package/dist/lib/feed/watch.d.ts +59 -0
- package/dist/lib/feed/watch.js +180 -0
- package/dist/lib/fleet/capture.js +6 -0
- package/dist/lib/fleet/remote-login.js +8 -3
- package/dist/lib/fleet/types.d.ts +17 -0
- package/dist/lib/harness/adapter.d.ts +11 -0
- package/dist/lib/harness/adapters/claude.js +38 -24
- package/dist/lib/harness/adapters/codex.js +2 -4
- package/dist/lib/harness/adapters/cursor.js +8 -11
- package/dist/lib/helper-download.d.ts +108 -0
- package/dist/lib/helper-download.js +194 -0
- package/dist/lib/helper-versions.d.ts +52 -0
- package/dist/lib/helper-versions.js +58 -0
- package/dist/lib/hooks/cache.js +19 -0
- package/dist/lib/hooks/install.js +2 -2
- package/dist/lib/hooks/match.d.ts +3 -0
- package/dist/lib/hooks/match.js +25 -0
- package/dist/lib/hosts/credentials.d.ts +1 -1
- package/dist/lib/hosts/credentials.js +1 -1
- package/dist/lib/hosts/dispatch.d.ts +7 -1
- package/dist/lib/hosts/dispatch.js +24 -5
- package/dist/lib/hosts/passthrough.d.ts +8 -15
- package/dist/lib/hosts/passthrough.js +35 -16
- package/dist/lib/hosts/providers/devices.d.ts +1 -1
- package/dist/lib/hosts/providers/devices.js +1 -1
- package/dist/lib/hosts/reconnect.d.ts +179 -21
- package/dist/lib/hosts/reconnect.js +266 -45
- package/dist/lib/hosts/registry.js +7 -0
- package/dist/lib/installations/migrate.d.ts +4 -5
- package/dist/lib/installations/migrate.js +6 -7
- package/dist/lib/installations/shims.d.ts +1 -1
- package/dist/lib/installations/shims.js +23 -13
- package/dist/lib/installations/versions.js +25 -2
- package/dist/lib/linear-autoclose.d.ts +1 -1
- package/dist/lib/linear-autoclose.js +1 -1
- package/dist/lib/loop.d.ts +2 -2
- package/dist/lib/loop.js +1 -1
- package/dist/lib/menubar/download-menubar.d.ts +47 -0
- package/dist/lib/menubar/download-menubar.js +60 -0
- package/dist/lib/menubar/install-menubar.d.ts +44 -7
- package/dist/lib/menubar/install-menubar.js +105 -23
- package/dist/lib/menubar/notify-desktop.d.ts +3 -3
- package/dist/lib/menubar/notify-desktop.js +6 -6
- package/dist/lib/model-tiers.d.ts +1 -1
- package/dist/lib/open-url.d.ts +60 -2
- package/dist/lib/open-url.js +167 -12
- package/dist/lib/project-probe.d.ts +1 -1
- package/dist/lib/project-probe.js +1 -1
- package/dist/lib/project-pull.d.ts +1 -1
- package/dist/lib/project-pull.js +2 -2
- package/dist/lib/projects.d.ts +1 -1
- package/dist/lib/projects.js +1 -1
- package/dist/lib/refresh-coordinator.d.ts +1 -1
- package/dist/lib/refresh-coordinator.js +1 -1
- package/dist/lib/sandbox.js +6 -7
- package/dist/lib/secrets/download-keychain.d.ts +47 -0
- package/dist/lib/secrets/download-keychain.js +70 -0
- package/dist/lib/secrets/install-helper.d.ts +20 -1
- package/dist/lib/secrets/install-helper.js +44 -3
- package/dist/lib/session/active.d.ts +67 -0
- package/dist/lib/session/active.js +86 -2
- package/dist/lib/session/db.d.ts +11 -1
- package/dist/lib/session/db.js +142 -8
- package/dist/lib/session/discover.d.ts +23 -1
- package/dist/lib/session/discover.js +44 -10
- package/dist/lib/session/highlights.d.ts +49 -1
- package/dist/lib/session/highlights.js +95 -0
- package/dist/lib/session/host-link.d.ts +16 -2
- package/dist/lib/session/host-link.js +7 -1
- package/dist/lib/session/parse.js +33 -1
- package/dist/lib/session/prompt.d.ts +35 -0
- package/dist/lib/session/prompt.js +56 -0
- package/dist/lib/session/remote/remote-list.d.ts +9 -0
- package/dist/lib/session/remote/remote-list.js +19 -2
- package/dist/lib/session/remote/watch.d.ts +1 -1
- package/dist/lib/session/remote/watch.js +17 -3
- package/dist/lib/session/render.js +7 -3
- package/dist/lib/session/session-cache.d.ts +53 -0
- package/dist/lib/session/session-cache.js +93 -1
- package/dist/lib/session/state.js +1 -1
- package/dist/lib/session/tool-calls.d.ts +2 -0
- package/dist/lib/session/tool-calls.js +1 -1
- package/dist/lib/session/trajectory-compare.d.ts +47 -0
- package/dist/lib/session/trajectory-compare.js +116 -0
- package/dist/lib/session/trajectory-html.d.ts +19 -0
- package/dist/lib/session/trajectory-html.js +770 -0
- package/dist/lib/session/trajectory-lineage.d.ts +92 -0
- package/dist/lib/session/trajectory-lineage.js +195 -0
- package/dist/lib/session/trajectory-text.d.ts +37 -0
- package/dist/lib/session/trajectory-text.js +284 -0
- package/dist/lib/session/trajectory.d.ts +102 -0
- package/dist/lib/session/trajectory.js +384 -0
- package/dist/lib/session/types.d.ts +15 -0
- package/dist/lib/sha256-asset.d.ts +26 -0
- package/dist/lib/sha256-asset.js +41 -0
- package/dist/lib/share/backend.d.ts +95 -0
- package/dist/lib/share/backend.js +139 -0
- package/dist/lib/share/delete.d.ts +6 -2
- package/dist/lib/share/delete.js +8 -9
- package/dist/lib/share/html.d.ts +22 -0
- package/dist/lib/share/html.js +88 -0
- package/dist/lib/share/provision.d.ts +18 -4
- package/dist/lib/share/provision.js +38 -4
- package/dist/lib/share/publish.d.ts +39 -15
- package/dist/lib/share/publish.js +55 -26
- package/dist/lib/share/worker-template.js +171 -11
- package/dist/lib/sqlite.js +16 -3
- package/dist/lib/ssh-exec.d.ts +65 -0
- package/dist/lib/ssh-exec.js +120 -4
- package/dist/lib/startup/command-registry.d.ts +3 -1
- package/dist/lib/startup/command-registry.js +6 -3
- package/dist/lib/startup/dev-build.js +3 -3
- package/dist/lib/state.d.ts +2 -2
- package/dist/lib/state.js +11 -5
- package/dist/lib/subagents-registry.js +1 -1
- package/dist/lib/teams/agents.js +9 -0
- package/dist/lib/terminal/index.d.ts +1 -1
- package/dist/lib/terminal/inject.d.ts +19 -0
- package/dist/lib/terminal/inject.js +19 -9
- package/dist/lib/terminal/types.d.ts +1 -1
- package/dist/lib/terminal/types.js +1 -1
- package/dist/lib/tmux/orphan-reap.js +1 -1
- package/dist/lib/tmux/session.d.ts +46 -13
- package/dist/lib/tmux/session.js +204 -27
- package/dist/lib/traces/backend.d.ts +29 -0
- package/dist/lib/traces/backend.js +46 -0
- package/dist/lib/traces/classify.d.ts +52 -0
- package/dist/lib/traces/classify.js +72 -0
- package/dist/lib/traces/config.d.ts +10 -0
- package/dist/lib/traces/config.js +2 -0
- package/dist/lib/traces/provision.d.ts +19 -0
- package/dist/lib/traces/provision.js +30 -0
- package/dist/lib/traces/sync.d.ts +150 -0
- package/dist/lib/traces/sync.js +447 -0
- package/dist/lib/traces/worker-template.d.ts +4 -0
- package/dist/lib/traces/worker-template.js +159 -0
- package/dist/lib/types.d.ts +34 -19
- package/dist/lib/types.js +14 -0
- package/dist/lib/usage-backoff.d.ts +2 -1
- package/dist/lib/usage-backoff.js +60 -19
- package/dist/lib/usage-refresh.d.ts +18 -4
- package/dist/lib/usage-refresh.js +68 -19
- package/dist/lib/watchdog/log.d.ts +1 -1
- package/dist/lib/watchdog/log.js +1 -1
- package/dist/lib/watchdog/runner.d.ts +36 -45
- package/dist/lib/watchdog/runner.js +150 -119
- package/dist/lib/watchdog/service.d.ts +0 -1
- package/dist/lib/watchdog/service.js +0 -1
- package/dist/lib/watchdog/watchdog-agent.d.ts +38 -0
- package/dist/lib/watchdog/watchdog-agent.js +59 -0
- package/dist/lib/watchdog/watchdog.d.ts +11 -2
- package/dist/lib/watchdog/watchdog.js +37 -104
- package/dist/lib/workflows.d.ts +1 -1
- package/package.json +5 -7
- package/dist/commands/usage.d.ts +0 -27
- package/dist/commands/usage.js +0 -96
- package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/Info.plist +0 -24
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/Resources/AppIcon.icns +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/_CodeSignature/CodeResources +0 -128
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/Info.plist +0 -24
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +0 -123
- package/dist/lib/secrets/Agents CLI.app/Contents/embedded.provisionprofile +0 -0
- package/dist/lib/usage-fleet.d.ts +0 -32
- package/dist/lib/usage-fleet.js +0 -125
|
@@ -52,6 +52,7 @@ import { getWriter, getDetector } from '../staleness/registry.js';
|
|
|
52
52
|
import { syncMemoryToVersionHome } from '../memory.js';
|
|
53
53
|
import { listPluginSkillNames, resolveCommandSource, resolveSkillSource } from '../staleness/writers/sources.js';
|
|
54
54
|
import { syncProjectResourcesToAgent } from '../project-resources.js';
|
|
55
|
+
import { installClaudeStatusLine } from '../claude-statusline.js';
|
|
55
56
|
/** Promisified exec for running shell commands. */
|
|
56
57
|
const execAsync = promisify(exec);
|
|
57
58
|
const execFileAsync = promisify(execFile);
|
|
@@ -120,6 +121,17 @@ function sourceMapFromWorkflows(cwd) {
|
|
|
120
121
|
.filter(d => d.isDirectory() && fs.existsSync(path.join(dir, d.name, 'WORKFLOW.md')))
|
|
121
122
|
.map(d => d.name));
|
|
122
123
|
}
|
|
124
|
+
// A plugin is a directory whose marker is `.claude-plugin/plugin.json`. Attribute
|
|
125
|
+
// each to the layer it actually resolves from (system / user / project / extra) —
|
|
126
|
+
// the same first-wins resolution the plugins staleness checker uses. Hardcoding
|
|
127
|
+
// 'user' here made a `system:*` selection expand to zero plugins, so
|
|
128
|
+
// `agents sync <agent> system` silently skipped system-layer plugins like `swarm`
|
|
129
|
+
// (RUSH-3207).
|
|
130
|
+
function sourceMapFromPlugins(cwd) {
|
|
131
|
+
return sourceMapFromLayeredDirectory(cwd, ['plugins'], (dir) => fs.readdirSync(dir, { withFileTypes: true })
|
|
132
|
+
.filter(d => d.isDirectory() && fs.existsSync(path.join(dir, d.name, '.claude-plugin', 'plugin.json')))
|
|
133
|
+
.map(d => d.name));
|
|
134
|
+
}
|
|
123
135
|
function sourceMapFromPluginSkills(plugins, activePluginNames, cwd) {
|
|
124
136
|
const sourceRank = new Map([
|
|
125
137
|
['user', 0],
|
|
@@ -2185,8 +2197,13 @@ function resourceSourceMap(kind, cwd, available) {
|
|
|
2185
2197
|
}
|
|
2186
2198
|
case 'mcp':
|
|
2187
2199
|
return new Map(getScopedMcpResources(cwd).map(r => [r.name, r.scope]));
|
|
2188
|
-
case 'plugins':
|
|
2189
|
-
|
|
2200
|
+
case 'plugins': {
|
|
2201
|
+
const sources = sourceMapFromPlugins(cwd);
|
|
2202
|
+
return new Map(available.plugins.flatMap((n) => {
|
|
2203
|
+
const source = sources.get(n);
|
|
2204
|
+
return source ? [[n, source]] : [];
|
|
2205
|
+
}));
|
|
2206
|
+
}
|
|
2190
2207
|
case 'workflows': {
|
|
2191
2208
|
const sources = sourceMapFromWorkflows(cwd);
|
|
2192
2209
|
return new Map(available.workflows.flatMap((n) => {
|
|
@@ -2359,6 +2376,12 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2359
2376
|
console.warn(`agents: SessionStart hook not installed for ${agent}@${version}: ${trackerResult.error}`);
|
|
2360
2377
|
}
|
|
2361
2378
|
}
|
|
2379
|
+
if (agent === 'claude') {
|
|
2380
|
+
const statusLine = installClaudeStatusLine(versionHome);
|
|
2381
|
+
if (statusLine.error) {
|
|
2382
|
+
console.warn(`agents: Claude status line not installed for ${agent}@${version}: ${statusLine.error}`);
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2362
2385
|
// Fast guard BEFORE getAvailableResources / pattern expansion /
|
|
2363
2386
|
// ensureVersionResourcePatterns. Guard needs only loadManifest + isStale
|
|
2364
2387
|
// (~6 ms); the work that used to sit ahead of it was ~12.5 ms of the 21.5 ms
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* routine YAML's `command:` shell script so the routine stays self-contained
|
|
8
8
|
* and independent of the CLI build.
|
|
9
9
|
*
|
|
10
|
-
* @see
|
|
10
|
+
* @see cli/routines/linear-autoclose.yml
|
|
11
11
|
*/
|
|
12
12
|
/**
|
|
13
13
|
* Subset of `gh pr view --json state,mergedAt` output that drives the
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* routine YAML's `command:` shell script so the routine stays self-contained
|
|
8
8
|
* and independent of the CLI build.
|
|
9
9
|
*
|
|
10
|
-
* @see
|
|
10
|
+
* @see cli/routines/linear-autoclose.yml
|
|
11
11
|
*/
|
|
12
12
|
/**
|
|
13
13
|
* Pure decision: returns true when the PR has been merged and its linked
|
package/dist/lib/loop.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* can spawn subagents freely). Every guard — `max_iterations`, `budget`, the
|
|
7
7
|
* `until: signal` condition, SIGINT/SIGTERM — lives OUTSIDE the agent, so the
|
|
8
8
|
* agent cannot vote past a kill-switch (the standard answer to runaway-loop and
|
|
9
|
-
* runaway-cost failure modes; see docs/
|
|
9
|
+
* runaway-cost failure modes; see docs/execution.md).
|
|
10
10
|
*
|
|
11
11
|
* Structure mirrors the teams supervisor (`runSupervisor` in teams/supervisor.ts):
|
|
12
12
|
* a bounded for-loop with a hard cap, a SIGINT/SIGTERM trap that flips a stop
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
import type { AgentId } from './types.js';
|
|
22
22
|
import type { ExecOptions } from './exec.js';
|
|
23
23
|
import { type Checkpoint } from './checkpoint.js';
|
|
24
|
-
/** Loop block config
|
|
24
|
+
/** Loop block config; see docs/execution.md. */
|
|
25
25
|
export interface LoopConfig {
|
|
26
26
|
/** Stop condition. `signal` reads loop-signal.json; absence is fail-closed. */
|
|
27
27
|
until?: 'signal';
|
package/dist/lib/loop.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* can spawn subagents freely). Every guard — `max_iterations`, `budget`, the
|
|
7
7
|
* `until: signal` condition, SIGINT/SIGTERM — lives OUTSIDE the agent, so the
|
|
8
8
|
* agent cannot vote past a kill-switch (the standard answer to runaway-loop and
|
|
9
|
-
* runaway-cost failure modes; see docs/
|
|
9
|
+
* runaway-cost failure modes; see docs/execution.md).
|
|
10
10
|
*
|
|
11
11
|
* Structure mirrors the teams supervisor (`runSupervisor` in teams/supervisor.ts):
|
|
12
12
|
* a bounded for-loop with a hard cap, a SIGINT/SIGTERM trap that flips a stop
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* On-demand download + verification of the macOS menu-bar helper
|
|
3
|
+
* ("MenubarHelper.app").
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the ComputerHelper download model (`../computer/download.ts`): the
|
|
6
|
+
* helper ships as a signed + notarized `.app` zipped as a GitHub release asset
|
|
7
|
+
* on the helper's own `menubar/v<x.y.z>` tag, NOT the CLI's tag (see
|
|
8
|
+
* `helper-versions.ts`). A fresh `npm i -g` machine whose tarball lacks a
|
|
9
|
+
* bundled copy fetches the asset for the pinned helper version, verifies its
|
|
10
|
+
* sha256 + code signature before install.
|
|
11
|
+
*
|
|
12
|
+
* The one difference — and the reason this is not the ComputerHelper spec — is
|
|
13
|
+
* the DESIGNATED-REQUIREMENT pin. macOS keys the menu bar's Accessibility (TCC)
|
|
14
|
+
* grant to the bundle's designated requirement (bundle id
|
|
15
|
+
* `com.phnx-labs.agents-menubar` + Developer ID Team `2HTP252L87`), and
|
|
16
|
+
* re-validates each new version against it. A downloaded bundle whose DR drops
|
|
17
|
+
* either pin would silently revoke the user's grant, so `MENUBAR_HELPER_SPEC`
|
|
18
|
+
* sets `expectedBundleId` and the shared `verifyHelperApp` enforces the DR
|
|
19
|
+
* before the bundle is ever installed. This matches the release-time gate in
|
|
20
|
+
* `scripts/verify-menubar-helper.sh`.
|
|
21
|
+
*/
|
|
22
|
+
import { type HelperSpec } from '../helper-download.js';
|
|
23
|
+
/** The zipped `.app` release asset name. */
|
|
24
|
+
export declare const MENUBAR_HELPER_ASSET = "MenubarHelper.app.zip";
|
|
25
|
+
/** The bundle directory name once extracted. */
|
|
26
|
+
export declare const MENUBAR_HELPER_APP_NAME = "MenubarHelper.app";
|
|
27
|
+
/** The bundle id the Accessibility grant (and thus the designated requirement)
|
|
28
|
+
* is keyed to — the same value `install-menubar.ts`'s `SERVICE_LABEL_BASE` and
|
|
29
|
+
* `scripts/verify-menubar-helper.sh` pin. */
|
|
30
|
+
export declare const MENUBAR_HELPER_BUNDLE_ID = "com.phnx-labs.agents-menubar";
|
|
31
|
+
/** MenubarHelper identity + verification policy — DR-pinned (see docblock). */
|
|
32
|
+
export declare const MENUBAR_HELPER_SPEC: HelperSpec;
|
|
33
|
+
/** Release-asset URLs for the menu-bar helper zip + its checksum at `v<version>`. */
|
|
34
|
+
export declare function menubarHelperAssetUrls(version: string): {
|
|
35
|
+
zip: string;
|
|
36
|
+
sha256: string;
|
|
37
|
+
};
|
|
38
|
+
/** Cache dir for the downloaded menu-bar helper, one subdir per release tag. */
|
|
39
|
+
export declare function menubarHelperCacheDir(version: string): string;
|
|
40
|
+
/** Verify a menu-bar helper `.app`: codesign + Team + DR pin + notarization. */
|
|
41
|
+
export declare function verifyMenubarHelper(appPath: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Download the menu-bar helper release asset for `version`, verify sha256 +
|
|
44
|
+
* signature + DR pin, and return the path to the extracted `MenubarHelper.app`
|
|
45
|
+
* in the cache. A missing asset is a hard error naming the exact tag.
|
|
46
|
+
*/
|
|
47
|
+
export declare function downloadMenubarHelperApp(version: string): Promise<string>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* On-demand download + verification of the macOS menu-bar helper
|
|
3
|
+
* ("MenubarHelper.app").
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the ComputerHelper download model (`../computer/download.ts`): the
|
|
6
|
+
* helper ships as a signed + notarized `.app` zipped as a GitHub release asset
|
|
7
|
+
* on the helper's own `menubar/v<x.y.z>` tag, NOT the CLI's tag (see
|
|
8
|
+
* `helper-versions.ts`). A fresh `npm i -g` machine whose tarball lacks a
|
|
9
|
+
* bundled copy fetches the asset for the pinned helper version, verifies its
|
|
10
|
+
* sha256 + code signature before install.
|
|
11
|
+
*
|
|
12
|
+
* The one difference — and the reason this is not the ComputerHelper spec — is
|
|
13
|
+
* the DESIGNATED-REQUIREMENT pin. macOS keys the menu bar's Accessibility (TCC)
|
|
14
|
+
* grant to the bundle's designated requirement (bundle id
|
|
15
|
+
* `com.phnx-labs.agents-menubar` + Developer ID Team `2HTP252L87`), and
|
|
16
|
+
* re-validates each new version against it. A downloaded bundle whose DR drops
|
|
17
|
+
* either pin would silently revoke the user's grant, so `MENUBAR_HELPER_SPEC`
|
|
18
|
+
* sets `expectedBundleId` and the shared `verifyHelperApp` enforces the DR
|
|
19
|
+
* before the bundle is ever installed. This matches the release-time gate in
|
|
20
|
+
* `scripts/verify-menubar-helper.sh`.
|
|
21
|
+
*/
|
|
22
|
+
import { EXPECTED_TEAM_ID, downloadHelperApp, helperAssetUrls, helperCacheDir, verifyHelperApp, } from '../helper-download.js';
|
|
23
|
+
/** The zipped `.app` release asset name. */
|
|
24
|
+
export const MENUBAR_HELPER_ASSET = 'MenubarHelper.app.zip';
|
|
25
|
+
/** The bundle directory name once extracted. */
|
|
26
|
+
export const MENUBAR_HELPER_APP_NAME = 'MenubarHelper.app';
|
|
27
|
+
/** The bundle id the Accessibility grant (and thus the designated requirement)
|
|
28
|
+
* is keyed to — the same value `install-menubar.ts`'s `SERVICE_LABEL_BASE` and
|
|
29
|
+
* `scripts/verify-menubar-helper.sh` pin. */
|
|
30
|
+
export const MENUBAR_HELPER_BUNDLE_ID = 'com.phnx-labs.agents-menubar';
|
|
31
|
+
/** MenubarHelper identity + verification policy — DR-pinned (see docblock). */
|
|
32
|
+
export const MENUBAR_HELPER_SPEC = {
|
|
33
|
+
helper: 'menubar',
|
|
34
|
+
assetName: MENUBAR_HELPER_ASSET,
|
|
35
|
+
appName: MENUBAR_HELPER_APP_NAME,
|
|
36
|
+
cacheSubdir: ['menubar', 'mac-helper'],
|
|
37
|
+
expectedTeamId: EXPECTED_TEAM_ID,
|
|
38
|
+
expectedBundleId: MENUBAR_HELPER_BUNDLE_ID,
|
|
39
|
+
localBuildHint: 'menubar/scripts/build.sh release, then cp -R menubar/dist/MenubarHelper.app bin/MenubarHelper.app',
|
|
40
|
+
};
|
|
41
|
+
/** Release-asset URLs for the menu-bar helper zip + its checksum at `v<version>`. */
|
|
42
|
+
export function menubarHelperAssetUrls(version) {
|
|
43
|
+
return helperAssetUrls(MENUBAR_HELPER_SPEC, version);
|
|
44
|
+
}
|
|
45
|
+
/** Cache dir for the downloaded menu-bar helper, one subdir per release tag. */
|
|
46
|
+
export function menubarHelperCacheDir(version) {
|
|
47
|
+
return helperCacheDir(MENUBAR_HELPER_SPEC, version);
|
|
48
|
+
}
|
|
49
|
+
/** Verify a menu-bar helper `.app`: codesign + Team + DR pin + notarization. */
|
|
50
|
+
export function verifyMenubarHelper(appPath) {
|
|
51
|
+
verifyHelperApp(appPath, MENUBAR_HELPER_SPEC);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Download the menu-bar helper release asset for `version`, verify sha256 +
|
|
55
|
+
* signature + DR pin, and return the path to the extracted `MenubarHelper.app`
|
|
56
|
+
* in the cache. A missing asset is a hard error naming the exact tag.
|
|
57
|
+
*/
|
|
58
|
+
export function downloadMenubarHelperApp(version) {
|
|
59
|
+
return downloadHelperApp(MENUBAR_HELPER_SPEC, version);
|
|
60
|
+
}
|
|
@@ -14,6 +14,20 @@
|
|
|
14
14
|
* migration (`installMenubarLaunchAgent` in migrate.ts) honors, so a disabled
|
|
15
15
|
* menu bar never silently comes back on the next release.
|
|
16
16
|
*/
|
|
17
|
+
/**
|
|
18
|
+
* The bundled executable's basename (RUSH-3101) — what launchd execs directly
|
|
19
|
+
* inside `Contents/MacOS/`, bypassing LaunchServices name resolution. Before
|
|
20
|
+
* this it was `MenubarHelper`, so that raw Mach-O basename is exactly what
|
|
21
|
+
* macOS showed in System Settings > Privacy & Security > Accessibility and in
|
|
22
|
+
* the "would like to control this computer" prompt. Renaming this constant
|
|
23
|
+
* alone does NOT touch the bundle id, Team ID, or designated requirement
|
|
24
|
+
* (`SERVICE_LABEL_BASE`, `MENUBAR_HELPER_BUNDLE_ID` in download-menubar.ts) —
|
|
25
|
+
* those are what keep the existing Accessibility grant alive across upgrades.
|
|
26
|
+
* Every basename-matching check reads this constant rather than re-deriving
|
|
27
|
+
* the string; the Swift side has its own equal in
|
|
28
|
+
* `menubar/Sources/MenubarHelper/HelperIdentity.swift`.
|
|
29
|
+
*/
|
|
30
|
+
export declare const MENUBAR_HELPER_EXECUTABLE_NAME = "AGI Menu";
|
|
17
31
|
/**
|
|
18
32
|
* launchd Label for this process's helper — the production identifier for a
|
|
19
33
|
* real invocation, namespaced under a redirected HOME (RUSH-2639). launchd
|
|
@@ -22,9 +36,9 @@
|
|
|
22
36
|
*/
|
|
23
37
|
export declare function serviceLabel(): string;
|
|
24
38
|
/**
|
|
25
|
-
* Absolute path to the installed
|
|
26
|
-
* else null. The desktop notifier (notify-desktop.ts) routes daemon
|
|
27
|
-
* notifications through this one-shot (`
|
|
39
|
+
* Absolute path to the installed menu-bar helper executable if it exists on
|
|
40
|
+
* disk, else null. The desktop notifier (notify-desktop.ts) routes daemon
|
|
41
|
+
* notifications through this one-shot (`"AGI Menu" --notify ...`) so they
|
|
28
42
|
* carry the agents-cli mark rather than the generic osascript icon. Null on
|
|
29
43
|
* non-darwin or when the helper is not installed (menu bar disabled, a Linux
|
|
30
44
|
* package, or a dev checkout without a built bundle).
|
|
@@ -61,6 +75,7 @@ export declare function hasDeveloperIdSignature(appPath: string): boolean;
|
|
|
61
75
|
*/
|
|
62
76
|
export declare function ensureMenubarAppInstalled(opts?: {
|
|
63
77
|
forceReinstall?: boolean;
|
|
78
|
+
sourceAppPath?: string;
|
|
64
79
|
}): string | null;
|
|
65
80
|
export declare function generateServicePlist(execPath: string): string;
|
|
66
81
|
/**
|
|
@@ -106,11 +121,20 @@ export declare function restartMenubarHelperAfterSwap(uid: number, ownProcesses:
|
|
|
106
121
|
* Install + start the menu-bar helper as a launchd user service (idempotent).
|
|
107
122
|
* Clears the sticky opt-out, installs the .app, writes the plist, and
|
|
108
123
|
* bootstraps it into the GUI domain. Returns false on non-darwin or when no
|
|
109
|
-
* helper bundle
|
|
124
|
+
* helper bundle can be resolved for this install.
|
|
125
|
+
*
|
|
126
|
+
* ASYNC and download-capable: this is the EXPLICIT user-initiated path
|
|
127
|
+
* (`agents menubar enable`). When no bundled/local `.app` ships (a fresh
|
|
128
|
+
* `npm i -g` machine whose tarball lacks the bundle), it fetches the signed +
|
|
129
|
+
* notarized release asset for the running CLI version — verified (sha256 +
|
|
130
|
+
* codesign + Team + designated-requirement pin + notarization) before install
|
|
131
|
+
* — and starts the service from that cached copy. The startup self-heal never
|
|
132
|
+
* routes here: it calls `startMenubarServiceFromSource` and stays sync +
|
|
133
|
+
* network-free, no-opping when no local source exists.
|
|
110
134
|
*/
|
|
111
135
|
export declare function enableMenubarService(opts?: {
|
|
112
136
|
clearOptOut?: boolean;
|
|
113
|
-
}): boolean
|
|
137
|
+
}): Promise<boolean>;
|
|
114
138
|
/**
|
|
115
139
|
* Pure staleness decision (no I/O) so the truth table is unit-testable. The
|
|
116
140
|
* installed service is stale when the helper binary is gone, or when it was
|
|
@@ -296,7 +320,7 @@ export declare function processesToEnd(status: Pick<MenubarStatus, 'instances' |
|
|
|
296
320
|
* 4. login item — write the plist (RunAtLoad + KeepAlive) and bootstrap it
|
|
297
321
|
* 5. single — verify exactly one helper came back up
|
|
298
322
|
*/
|
|
299
|
-
export declare function runMenubarSetup(): SetupResult
|
|
323
|
+
export declare function runMenubarSetup(): Promise<SetupResult>;
|
|
300
324
|
/** A live MenubarHelper process: its pid and the executable it is running. */
|
|
301
325
|
export interface MenubarProcess {
|
|
302
326
|
pid: number;
|
|
@@ -320,7 +344,7 @@ export interface MenubarProcess {
|
|
|
320
344
|
*
|
|
321
345
|
* Identity comes from `comm` (the resolved executable), never from a substring
|
|
322
346
|
* of the command line: matching the latter flags any shell that merely mentions
|
|
323
|
-
*
|
|
347
|
+
* the helper's name. `command` is consulted only to drop `--notify` one-shots.
|
|
324
348
|
*/
|
|
325
349
|
export declare function classifyMenubarProcesses(commOutput: string, commandOutput: string, installedExec: string): {
|
|
326
350
|
own: MenubarProcess[];
|
|
@@ -370,6 +394,19 @@ export interface PidStaleness {
|
|
|
370
394
|
* PREVIOUS binary — the exact condition `restartMenubarHelperAfterSwap` exists
|
|
371
395
|
* to fix. Millisecond epoch timestamps in, so the truth table is unit-testable
|
|
372
396
|
* without a live process or filesystem.
|
|
397
|
+
*
|
|
398
|
+
* The two timestamps do not have the same resolution. `pidStartTimeMs` parses
|
|
399
|
+
* `ps -o lstart`, which prints whole SECONDS, while the bundle mtime carries
|
|
400
|
+
* sub-second precision — and the restart this check exists to detect happens
|
|
401
|
+
* within a second of the swap that triggered it. A raw `<` therefore called a
|
|
402
|
+
* healthy just-restarted helper stale on essentially every upgrade: measured on
|
|
403
|
+
* zion at 1.22.46, pid start 1787441353000 vs bundle mtime 1787441353700, 700ms
|
|
404
|
+
* apart inside one second, reported as "running the OLD binary" and surfaced as
|
|
405
|
+
* `accessibilityHintNeeded` — telling the user to re-grant Accessibility after
|
|
406
|
+
* an upgrade that had already restarted the helper correctly. So the bundle
|
|
407
|
+
* mtime is truncated to the same whole second `ps` reports before comparing: a
|
|
408
|
+
* pid that started in the swap's own second is fresh, and a genuinely stale pid
|
|
409
|
+
* (a full second or more older) is still caught.
|
|
373
410
|
*/
|
|
374
411
|
export declare function isMenubarProcessStaleAgainstBundle(pidStartedAtMs: number, bundleMtimeMs: number): boolean;
|
|
375
412
|
/**
|
|
@@ -25,9 +25,25 @@ import { getCliVersion, resolveAgentsBin, resolveInstalledLayout } from '../vers
|
|
|
25
25
|
import { copyAppBundle, withInstallLock } from '../app-bundle-install.js';
|
|
26
26
|
import { compareVersions } from '../agent-spec/primitives.js';
|
|
27
27
|
import { namespacedServiceLabel, serviceManifestHomeEnv, serviceManagerRegistrationAllowed } from '../service-manifest.js';
|
|
28
|
+
import { downloadMenubarHelperApp } from './download-menubar.js';
|
|
29
|
+
import { helperFloor } from '../helper-versions.js';
|
|
28
30
|
const APP_BUNDLE_NAME = 'MenubarHelper.app';
|
|
29
31
|
const INSTALL_DIR_NAME = 'agents-cli';
|
|
30
32
|
const SERVICE_LABEL_BASE = 'com.phnx-labs.agents-menubar';
|
|
33
|
+
/**
|
|
34
|
+
* The bundled executable's basename (RUSH-3101) — what launchd execs directly
|
|
35
|
+
* inside `Contents/MacOS/`, bypassing LaunchServices name resolution. Before
|
|
36
|
+
* this it was `MenubarHelper`, so that raw Mach-O basename is exactly what
|
|
37
|
+
* macOS showed in System Settings > Privacy & Security > Accessibility and in
|
|
38
|
+
* the "would like to control this computer" prompt. Renaming this constant
|
|
39
|
+
* alone does NOT touch the bundle id, Team ID, or designated requirement
|
|
40
|
+
* (`SERVICE_LABEL_BASE`, `MENUBAR_HELPER_BUNDLE_ID` in download-menubar.ts) —
|
|
41
|
+
* those are what keep the existing Accessibility grant alive across upgrades.
|
|
42
|
+
* Every basename-matching check reads this constant rather than re-deriving
|
|
43
|
+
* the string; the Swift side has its own equal in
|
|
44
|
+
* `menubar/Sources/MenubarHelper/HelperIdentity.swift`.
|
|
45
|
+
*/
|
|
46
|
+
export const MENUBAR_HELPER_EXECUTABLE_NAME = 'AGI Menu';
|
|
31
47
|
/**
|
|
32
48
|
* launchd Label for this process's helper — the production identifier for a
|
|
33
49
|
* real invocation, namespaced under a redirected HOME (RUSH-2639). launchd
|
|
@@ -83,12 +99,12 @@ function readInstalledMenubarVersion() {
|
|
|
83
99
|
}
|
|
84
100
|
/** Executable inside the installed bundle. */
|
|
85
101
|
function installedExecutablePath() {
|
|
86
|
-
return path.join(installedAppPath(), 'Contents', 'MacOS',
|
|
102
|
+
return path.join(installedAppPath(), 'Contents', 'MacOS', MENUBAR_HELPER_EXECUTABLE_NAME);
|
|
87
103
|
}
|
|
88
104
|
/**
|
|
89
|
-
* Absolute path to the installed
|
|
90
|
-
* else null. The desktop notifier (notify-desktop.ts) routes daemon
|
|
91
|
-
* notifications through this one-shot (`
|
|
105
|
+
* Absolute path to the installed menu-bar helper executable if it exists on
|
|
106
|
+
* disk, else null. The desktop notifier (notify-desktop.ts) routes daemon
|
|
107
|
+
* notifications through this one-shot (`"AGI Menu" --notify ...`) so they
|
|
92
108
|
* carry the agents-cli mark rather than the generic osascript icon. Null on
|
|
93
109
|
* non-darwin or when the helper is not installed (menu bar disabled, a Linux
|
|
94
110
|
* package, or a dev checkout without a built bundle).
|
|
@@ -119,7 +135,7 @@ export function menubarServiceInstalled() {
|
|
|
119
135
|
* Locate the source `.app` shipped alongside the compiled JS.
|
|
120
136
|
* 1. dist/lib/menubar/MenubarHelper.app — npm install layout (sibling of this file)
|
|
121
137
|
* 2. <repo>/bin/MenubarHelper.app — raw working tree (tsx/dev)
|
|
122
|
-
* 3.
|
|
138
|
+
* 3. cli/menubar/dist/MenubarHelper.app — fresh local build
|
|
123
139
|
* 4. <on-disk install>/dist/lib/menubar/MenubarHelper.app — Bun single-file
|
|
124
140
|
* binary: `import.meta.url` is a virtual `/$bunfs/` path, so the sibling
|
|
125
141
|
* candidates above can't see the on-disk bundle; recover it via the
|
|
@@ -229,7 +245,12 @@ export function hasDeveloperIdSignature(appPath) {
|
|
|
229
245
|
export function ensureMenubarAppInstalled(opts = {}) {
|
|
230
246
|
if (!onDarwin())
|
|
231
247
|
return null;
|
|
232
|
-
|
|
248
|
+
// An explicit `sourceAppPath` (a pre-downloaded cache path from the explicit
|
|
249
|
+
// enable/setup path) overrides local discovery. This function itself does NO
|
|
250
|
+
// network — the download happens in the async callers before they hand a path
|
|
251
|
+
// here, so the sync startup self-heal that calls it with no override stays
|
|
252
|
+
// network-free and simply no-ops when `sourceAppPath()` finds nothing.
|
|
253
|
+
const src = opts.sourceAppPath ?? sourceAppPath();
|
|
233
254
|
if (!src)
|
|
234
255
|
return null;
|
|
235
256
|
const dest = installedAppPath();
|
|
@@ -393,15 +414,18 @@ export function restartMenubarHelperAfterSwap(uid, ownProcesses, exec = execFile
|
|
|
393
414
|
}
|
|
394
415
|
}
|
|
395
416
|
/**
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
417
|
+
* Sync install + start core: install the given (already-on-disk) source `.app`
|
|
418
|
+
* and start the launchd service. NO network — the source `.app` must already be
|
|
419
|
+
* local (a bundled/local copy for the sync startup self-heal, or a pre-downloaded
|
|
420
|
+
* cache path for the explicit async enable/setup path). Returns false on
|
|
421
|
+
* non-darwin, when no source resolves, or when the bundle fails the Gatekeeper
|
|
422
|
+
* check. Shared by the sync self-heal (`installMenubarLaunchAgentOnUpgrade`) and
|
|
423
|
+
* the async `enableMenubarService`.
|
|
400
424
|
*/
|
|
401
|
-
|
|
425
|
+
function startMenubarServiceFromSource(opts = {}) {
|
|
402
426
|
if (!onDarwin())
|
|
403
427
|
return false;
|
|
404
|
-
const exec = ensureMenubarAppInstalled({ forceReinstall: true });
|
|
428
|
+
const exec = ensureMenubarAppInstalled({ forceReinstall: true, sourceAppPath: opts.sourceAppPath });
|
|
405
429
|
if (!exec)
|
|
406
430
|
return false;
|
|
407
431
|
// Never bootstrap a helper macOS will reject at launch: an invalid signature
|
|
@@ -420,6 +444,29 @@ export function enableMenubarService(opts = { clearOptOut: true }) {
|
|
|
420
444
|
installAndStartService(exec);
|
|
421
445
|
return true;
|
|
422
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* Install + start the menu-bar helper as a launchd user service (idempotent).
|
|
449
|
+
* Clears the sticky opt-out, installs the .app, writes the plist, and
|
|
450
|
+
* bootstraps it into the GUI domain. Returns false on non-darwin or when no
|
|
451
|
+
* helper bundle can be resolved for this install.
|
|
452
|
+
*
|
|
453
|
+
* ASYNC and download-capable: this is the EXPLICIT user-initiated path
|
|
454
|
+
* (`agents menubar enable`). When no bundled/local `.app` ships (a fresh
|
|
455
|
+
* `npm i -g` machine whose tarball lacks the bundle), it fetches the signed +
|
|
456
|
+
* notarized release asset for the running CLI version — verified (sha256 +
|
|
457
|
+
* codesign + Team + designated-requirement pin + notarization) before install
|
|
458
|
+
* — and starts the service from that cached copy. The startup self-heal never
|
|
459
|
+
* routes here: it calls `startMenubarServiceFromSource` and stays sync +
|
|
460
|
+
* network-free, no-opping when no local source exists.
|
|
461
|
+
*/
|
|
462
|
+
export async function enableMenubarService(opts = { clearOptOut: true }) {
|
|
463
|
+
if (!onDarwin())
|
|
464
|
+
return false;
|
|
465
|
+
let src = sourceAppPath();
|
|
466
|
+
if (!src)
|
|
467
|
+
src = await downloadMenubarHelperApp(helperFloor('menubar'));
|
|
468
|
+
return startMenubarServiceFromSource({ ...opts, sourceAppPath: src });
|
|
469
|
+
}
|
|
423
470
|
/** Drop the sticky `agents menubar disable` sentinel. */
|
|
424
471
|
function clearMenubarOptOut() {
|
|
425
472
|
try {
|
|
@@ -602,8 +649,19 @@ export function mayInstallMenubarHelper(opts) {
|
|
|
602
649
|
// No owner recorded yet (fresh or pre-`AGENTS_ENTRY` plist) — adopt it.
|
|
603
650
|
if (!opts.plistEntry)
|
|
604
651
|
return true;
|
|
652
|
+
// The recorded owner's entry path is gone from disk, so this install may adopt
|
|
653
|
+
// the helper — but a non-Developer-ID (ad-hoc/dev) source may NOT seize a
|
|
654
|
+
// healthy install this way. Recopying an ad-hoc bundle over the Developer-ID
|
|
655
|
+
// one poisons the shared Accessibility grant (an ad-hoc signature fails the
|
|
656
|
+
// grant's stored code requirement, so macOS revokes it and re-prompts on the
|
|
657
|
+
// next paste) and Gatekeeper then rejects the result as "damaged" (RUSH-2134).
|
|
658
|
+
// This does not strand a genuinely broken helper: escape (1) above
|
|
659
|
+
// (helperExecMissing / needsDevIdHeal) already lets ANY source repair a
|
|
660
|
+
// missing-or-ad-hoc install, so refusing here only declines to re-point the
|
|
661
|
+
// plist of a helper that is already present and working — the menu bar keeps
|
|
662
|
+
// running, nothing deadlocks.
|
|
605
663
|
if (!opts.ownerEntryExists)
|
|
606
|
-
return
|
|
664
|
+
return opts.sourceIsDeveloperId;
|
|
607
665
|
if (opts.installedVersion && opts.currentVersion) {
|
|
608
666
|
const versionOrder = compareVersions(opts.currentVersion, opts.installedVersion);
|
|
609
667
|
if (versionOrder > 0)
|
|
@@ -703,7 +761,7 @@ export function installMenubarLaunchAgentOnUpgrade() {
|
|
|
703
761
|
if (!sourceAppPath())
|
|
704
762
|
return;
|
|
705
763
|
if (!menubarServiceInstalled()) {
|
|
706
|
-
|
|
764
|
+
startMenubarServiceFromSource({ clearOptOut: false });
|
|
707
765
|
return;
|
|
708
766
|
}
|
|
709
767
|
// Re-enable (recopy helper + rewrite plist) when the version drifted OR the
|
|
@@ -724,7 +782,7 @@ export function installMenubarLaunchAgentOnUpgrade() {
|
|
|
724
782
|
// false without installing when the bundle fails the Gatekeeper check, and
|
|
725
783
|
// stamping first would spend the shared cooldown on a no-op — locking every
|
|
726
784
|
// non-owner out for another hour while nothing had been fixed.
|
|
727
|
-
if (
|
|
785
|
+
if (startMenubarServiceFromSource({ clearOptOut: false })) {
|
|
728
786
|
stampMenubarHeal();
|
|
729
787
|
// One-time: the ad-hoc -> Developer ID transition leaves a dead TCC row
|
|
730
788
|
// under the old identity (tccutil on zion reset it 11 times across
|
|
@@ -828,7 +886,7 @@ function endProcess(pid) {
|
|
|
828
886
|
* 4. login item — write the plist (RunAtLoad + KeepAlive) and bootstrap it
|
|
829
887
|
* 5. single — verify exactly one helper came back up
|
|
830
888
|
*/
|
|
831
|
-
export function runMenubarSetup() {
|
|
889
|
+
export async function runMenubarSetup() {
|
|
832
890
|
const steps = [];
|
|
833
891
|
const step = (name, outcome, detail) => {
|
|
834
892
|
steps.push({ name, outcome, detail });
|
|
@@ -838,9 +896,20 @@ export function runMenubarSetup() {
|
|
|
838
896
|
return { steps, configured: false, status: getMenubarStatus() };
|
|
839
897
|
}
|
|
840
898
|
const before = getMenubarStatus();
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
899
|
+
// Explicit user-initiated path: when no bundled/local `.app` ships (a fresh
|
|
900
|
+
// `npm i -g` machine whose tarball lacks the bundle), fetch the signed +
|
|
901
|
+
// notarized release asset for this CLI version. Verified (sha256 + codesign +
|
|
902
|
+
// Team + designated-requirement pin + notarization) before install; the
|
|
903
|
+
// cached copy is the source for `ensureMenubarAppInstalled` below.
|
|
904
|
+
let src = sourceAppPath();
|
|
905
|
+
if (!src) {
|
|
906
|
+
try {
|
|
907
|
+
src = await downloadMenubarHelperApp(helperFloor('menubar'));
|
|
908
|
+
}
|
|
909
|
+
catch (e) {
|
|
910
|
+
step('bundle', 'failed', `no AGI Menu bundle ships with this install, and the release-asset download failed: ${e.message}`);
|
|
911
|
+
return { steps, configured: false, status: before };
|
|
912
|
+
}
|
|
844
913
|
}
|
|
845
914
|
// 3 before 1: end the running copies BEFORE swapping the bundle underneath
|
|
846
915
|
// them, so no helper keeps a status item alive on a binary that no longer
|
|
@@ -857,7 +926,7 @@ export function runMenubarSetup() {
|
|
|
857
926
|
else {
|
|
858
927
|
step('duplicates', 'ok', 'no helper was running');
|
|
859
928
|
}
|
|
860
|
-
const exec = ensureMenubarAppInstalled({ forceReinstall: true });
|
|
929
|
+
const exec = ensureMenubarAppInstalled({ forceReinstall: true, sourceAppPath: src });
|
|
861
930
|
if (!exec) {
|
|
862
931
|
step('bundle', 'failed', 'could not install the helper bundle');
|
|
863
932
|
return { steps, configured: false, status: getMenubarStatus() };
|
|
@@ -935,14 +1004,14 @@ function parsePsLines(psOutput) {
|
|
|
935
1004
|
*
|
|
936
1005
|
* Identity comes from `comm` (the resolved executable), never from a substring
|
|
937
1006
|
* of the command line: matching the latter flags any shell that merely mentions
|
|
938
|
-
*
|
|
1007
|
+
* the helper's name. `command` is consulted only to drop `--notify` one-shots.
|
|
939
1008
|
*/
|
|
940
1009
|
export function classifyMenubarProcesses(commOutput, commandOutput, installedExec) {
|
|
941
1010
|
const commands = parsePsLines(commandOutput);
|
|
942
1011
|
const own = [];
|
|
943
1012
|
const foreign = [];
|
|
944
1013
|
for (const [pid, executable] of parsePsLines(commOutput)) {
|
|
945
|
-
if (path.basename(executable) !==
|
|
1014
|
+
if (path.basename(executable) !== MENUBAR_HELPER_EXECUTABLE_NAME)
|
|
946
1015
|
continue;
|
|
947
1016
|
// `--notify` is a one-shot that posts a notification and exits; it runs the
|
|
948
1017
|
// installed binary but never claims the status item or the chords.
|
|
@@ -990,9 +1059,22 @@ export function getMenubarStatus() {
|
|
|
990
1059
|
* PREVIOUS binary — the exact condition `restartMenubarHelperAfterSwap` exists
|
|
991
1060
|
* to fix. Millisecond epoch timestamps in, so the truth table is unit-testable
|
|
992
1061
|
* without a live process or filesystem.
|
|
1062
|
+
*
|
|
1063
|
+
* The two timestamps do not have the same resolution. `pidStartTimeMs` parses
|
|
1064
|
+
* `ps -o lstart`, which prints whole SECONDS, while the bundle mtime carries
|
|
1065
|
+
* sub-second precision — and the restart this check exists to detect happens
|
|
1066
|
+
* within a second of the swap that triggered it. A raw `<` therefore called a
|
|
1067
|
+
* healthy just-restarted helper stale on essentially every upgrade: measured on
|
|
1068
|
+
* zion at 1.22.46, pid start 1787441353000 vs bundle mtime 1787441353700, 700ms
|
|
1069
|
+
* apart inside one second, reported as "running the OLD binary" and surfaced as
|
|
1070
|
+
* `accessibilityHintNeeded` — telling the user to re-grant Accessibility after
|
|
1071
|
+
* an upgrade that had already restarted the helper correctly. So the bundle
|
|
1072
|
+
* mtime is truncated to the same whole second `ps` reports before comparing: a
|
|
1073
|
+
* pid that started in the swap's own second is fresh, and a genuinely stale pid
|
|
1074
|
+
* (a full second or more older) is still caught.
|
|
993
1075
|
*/
|
|
994
1076
|
export function isMenubarProcessStaleAgainstBundle(pidStartedAtMs, bundleMtimeMs) {
|
|
995
|
-
return pidStartedAtMs < bundleMtimeMs;
|
|
1077
|
+
return pidStartedAtMs < Math.floor(bundleMtimeMs / 1000) * 1000;
|
|
996
1078
|
}
|
|
997
1079
|
/** Wall-clock start time of a live pid via `ps`, or null if it can't be read. */
|
|
998
1080
|
function pidStartTimeMs(pid) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The one place the daemon (overdue routines, heal, routine start/finish/output)
|
|
5
5
|
* emits a native desktop notification. On macOS it routes through the installed
|
|
6
|
-
* `MenubarHelper.app` companion — a one-shot `
|
|
6
|
+
* `MenubarHelper.app` companion — a one-shot `"AGI Menu" --notify` invocation —
|
|
7
7
|
* so the notification is attributed to that bundle and carries the agents-cli
|
|
8
8
|
* mark instead of the generic AppleScript icon. A banner carries two images: the
|
|
9
9
|
* agents-cli app icon on the LEFT (the sender) and, when the event belongs to one
|
|
@@ -48,7 +48,7 @@ export interface DesktopNotification {
|
|
|
48
48
|
*/
|
|
49
49
|
agent?: string;
|
|
50
50
|
}
|
|
51
|
-
/** Argv for the
|
|
51
|
+
/** Argv for the "AGI Menu" one-shot notify mode. Exported for tests. */
|
|
52
52
|
export declare function buildMenubarNotifyArgs(n: DesktopNotification): string[];
|
|
53
53
|
/** AppleScript for the osascript degradation path. Exported for tests. */
|
|
54
54
|
export declare function buildOsascriptNotifyArgs(n: DesktopNotification): string[];
|
|
@@ -67,7 +67,7 @@ export declare function buildOsascriptNotifyArgs(n: DesktopNotification): string
|
|
|
67
67
|
*/
|
|
68
68
|
export declare function spawnDetachedQuiet(command: string, args: string[], timeoutMs?: number): ChildProcess;
|
|
69
69
|
/**
|
|
70
|
-
* Fire a native desktop notification, branded via the
|
|
70
|
+
* Fire a native desktop notification, branded via the "AGI Menu" companion on
|
|
71
71
|
* macOS. Best-effort — any failure is swallowed so a notification hiccup never
|
|
72
72
|
* blocks or crashes the daemon.
|
|
73
73
|
*/
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The one place the daemon (overdue routines, heal, routine start/finish/output)
|
|
5
5
|
* emits a native desktop notification. On macOS it routes through the installed
|
|
6
|
-
* `MenubarHelper.app` companion — a one-shot `
|
|
6
|
+
* `MenubarHelper.app` companion — a one-shot `"AGI Menu" --notify` invocation —
|
|
7
7
|
* so the notification is attributed to that bundle and carries the agents-cli
|
|
8
8
|
* mark instead of the generic AppleScript icon. A banner carries two images: the
|
|
9
9
|
* agents-cli app icon on the LEFT (the sender) and, when the event belongs to one
|
|
@@ -32,7 +32,7 @@ import { resolveInstalledMenubarExecutable } from './install-menubar.js';
|
|
|
32
32
|
* only if the child never self-exits.
|
|
33
33
|
*/
|
|
34
34
|
const NOTIFY_TIMEOUT_MS = 4000;
|
|
35
|
-
/** Argv for the
|
|
35
|
+
/** Argv for the "AGI Menu" one-shot notify mode. Exported for tests. */
|
|
36
36
|
export function buildMenubarNotifyArgs(n) {
|
|
37
37
|
const args = ['--notify', '--title', n.title, '--body', n.body];
|
|
38
38
|
if (n.subtitle)
|
|
@@ -88,7 +88,7 @@ export function spawnDetachedQuiet(command, args, timeoutMs = NOTIFY_TIMEOUT_MS)
|
|
|
88
88
|
return child;
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
91
|
-
* Fire a native desktop notification, branded via the
|
|
91
|
+
* Fire a native desktop notification, branded via the "AGI Menu" companion on
|
|
92
92
|
* macOS. Best-effort — any failure is swallowed so a notification hiccup never
|
|
93
93
|
* blocks or crashes the daemon.
|
|
94
94
|
*/
|
|
@@ -98,9 +98,9 @@ export function notifyDesktop(n) {
|
|
|
98
98
|
if (platform === 'darwin') {
|
|
99
99
|
const exec = resolveInstalledMenubarExecutable();
|
|
100
100
|
if (exec) {
|
|
101
|
-
// Branded path: the notification is attributed to MenubarHelper.app
|
|
102
|
-
// shows the agents-cli mark and its click
|
|
103
|
-
// helper's UNUserNotificationCenter delegate.
|
|
101
|
+
// Branded path: the notification is attributed to MenubarHelper.app
|
|
102
|
+
// ("AGI Menu" on disk), so it shows the agents-cli mark and its click
|
|
103
|
+
// action is handled by the running helper's UNUserNotificationCenter delegate.
|
|
104
104
|
spawnDetachedQuiet(exec, buildMenubarNotifyArgs(n));
|
|
105
105
|
return;
|
|
106
106
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* actually ships — so `--model cheap|default|best|ultra` works on `agents run`
|
|
8
8
|
* and `agents teams add` alike, funnelling through `resolveModel()`.
|
|
9
9
|
*
|
|
10
|
-
* Ranking signal, in priority (see
|
|
10
|
+
* Ranking signal, in priority (see cli/docs — model ranking mechanisms):
|
|
11
11
|
* 1. Provider-declared lineup — the catalog's own family names / descriptions
|
|
12
12
|
* (opus/sonnet/haiku/fable; Codex "frontier / balanced / fast"). Most
|
|
13
13
|
* drift-proof: the provider tells us its own ranking.
|