@songsid/agend 2.2.1 → 2.2.5
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/dist/agent-cli-instructions.md +5 -2
- package/dist/agent-cli.js +284 -2
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +2 -0
- package/dist/agent-endpoint.js +29 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-file-read.d.ts +38 -0
- package/dist/agent-file-read.js +317 -0
- package/dist/agent-file-read.js.map +1 -0
- package/dist/agent-whats-new.d.ts +11 -0
- package/dist/agent-whats-new.js +34 -2
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/atomic-write.js +9 -1
- package/dist/atomic-write.js.map +1 -1
- package/dist/auth-api.d.ts +30 -1
- package/dist/auth-api.js +61 -12
- package/dist/auth-api.js.map +1 -1
- package/dist/authority/authority-state.d.ts +38 -0
- package/dist/authority/authority-state.js +114 -0
- package/dist/authority/authority-state.js.map +1 -0
- package/dist/authority/session-authorizations.d.ts +43 -0
- package/dist/authority/session-authorizations.js +102 -0
- package/dist/authority/session-authorizations.js.map +1 -0
- package/dist/authority/web-authority.d.ts +120 -0
- package/dist/authority/web-authority.js +157 -0
- package/dist/authority/web-authority.js.map +1 -0
- package/dist/backend/antigravity.js +3 -3
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.d.ts +2 -2
- package/dist/backend/claude-code.js +10 -5
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/launch-effort.js +1 -1
- package/dist/backend/launch-effort.js.map +1 -1
- package/dist/backend/muse.js +10 -2
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/types.d.ts +14 -0
- package/dist/backend/types.js +25 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-availability.d.ts +120 -0
- package/dist/backend-availability.js +396 -0
- package/dist/backend-availability.js.map +1 -0
- package/dist/backend-command.d.ts +21 -3
- package/dist/backend-command.js +23 -4
- package/dist/backend-command.js.map +1 -1
- package/dist/bundled-skills.d.ts +14 -0
- package/dist/bundled-skills.js +29 -0
- package/dist/bundled-skills.js.map +1 -0
- package/dist/cache-analysis.d.ts +47 -1
- package/dist/cache-analysis.js +68 -8
- package/dist/cache-analysis.js.map +1 -1
- package/dist/cache-ledger.d.ts +16 -3
- package/dist/cache-ledger.js +33 -13
- package/dist/cache-ledger.js.map +1 -1
- package/dist/cache-report-tool.d.ts +17 -0
- package/dist/cache-report-tool.js +40 -0
- package/dist/cache-report-tool.js.map +1 -0
- package/dist/cache-service.d.ts +70 -3
- package/dist/cache-service.js +178 -17
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord-client-retirement.d.ts +5 -0
- package/dist/channel/adapters/discord-client-retirement.js +57 -0
- package/dist/channel/adapters/discord-client-retirement.js.map +1 -0
- package/dist/channel/adapters/discord.d.ts +11 -0
- package/dist/channel/adapters/discord.js +66 -6
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +8 -1
- package/dist/channel/adapters/telegram.js +74 -4
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-tools.js +48 -2
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/types.d.ts +21 -0
- package/dist/classic-channel-manager.d.ts +10 -5
- package/dist/classic-channel-manager.js +12 -9
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +142 -110
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.js +119 -4
- package/dist/config-validator.js.map +1 -1
- package/dist/daemon.d.ts +8 -0
- package/dist/daemon.js +298 -22
- package/dist/daemon.js.map +1 -1
- package/dist/decision-list.d.ts +25 -0
- package/dist/decision-list.js +30 -0
- package/dist/decision-list.js.map +1 -0
- package/dist/delivery-outbox.d.ts +10 -0
- package/dist/delivery-outbox.js +12 -1
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/fleet-context.d.ts +15 -0
- package/dist/fleet-manager.d.ts +514 -12
- package/dist/fleet-manager.js +1885 -163
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-process-handlers.d.ts +18 -0
- package/dist/fleet-process-handlers.js +69 -0
- package/dist/fleet-process-handlers.js.map +1 -0
- package/dist/fleet-traffic.d.ts +74 -0
- package/dist/fleet-traffic.js +196 -0
- package/dist/fleet-traffic.js.map +1 -0
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +20 -5
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +6 -1
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +3 -2
- package/dist/general-knowledge/skills/persona-emoji/SKILL.md +1 -1
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +492 -0
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +482 -0
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
- package/dist/human-delivery-receipts.d.ts +24 -1
- package/dist/human-delivery-receipts.js +64 -11
- package/dist/human-delivery-receipts.js.map +1 -1
- package/dist/instance-avatar.js +3 -0
- package/dist/instance-avatar.js.map +1 -1
- package/dist/instance-config-impact.js +6 -1
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +2 -0
- package/dist/instance-lifecycle.js +20 -10
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instance-names.d.ts +4 -0
- package/dist/instance-names.js +12 -0
- package/dist/instance-names.js.map +1 -0
- package/dist/instructions.d.ts +12 -1
- package/dist/instructions.js +13 -2
- package/dist/instructions.js.map +1 -1
- package/dist/locale.js +100 -8
- package/dist/locale.js.map +1 -1
- package/dist/ls-attach-resolve.d.ts +95 -0
- package/dist/ls-attach-resolve.js +174 -0
- package/dist/ls-attach-resolve.js.map +1 -0
- package/dist/memory-hogs.d.ts +27 -0
- package/dist/memory-hogs.js +124 -0
- package/dist/memory-hogs.js.map +1 -0
- package/dist/needs-you-hub.d.ts +4 -0
- package/dist/needs-you-hub.js +31 -6
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you.d.ts +1 -13
- package/dist/needs-you.js +3 -37
- package/dist/needs-you.js.map +1 -1
- package/dist/outbound-handlers.d.ts +15 -0
- package/dist/outbound-handlers.js +152 -11
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +228 -4
- package/dist/outbound-schemas.js +147 -1
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-web-gateway.js +21 -1
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +9 -0
- package/dist/public-web-link.js +8 -0
- package/dist/public-web-link.js.map +1 -1
- package/dist/quickstart-api.d.ts +10 -1
- package/dist/quickstart-api.js +12 -4
- package/dist/quickstart-api.js.map +1 -1
- package/dist/reply-buttons-controller.d.ts +4 -0
- package/dist/reply-buttons-controller.js +2 -2
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/repo-worktree-guard.d.ts +36 -0
- package/dist/repo-worktree-guard.js +143 -0
- package/dist/repo-worktree-guard.js.map +1 -0
- package/dist/restart-progress.d.ts +65 -1
- package/dist/restart-progress.js +236 -10
- package/dist/restart-progress.js.map +1 -1
- package/dist/rollout-index.d.ts +5 -0
- package/dist/rollout-index.js +26 -5
- package/dist/rollout-index.js.map +1 -1
- package/dist/scheduler/scheduler.d.ts +70 -1
- package/dist/scheduler/scheduler.js +256 -17
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/service-installer.d.ts +2 -1
- package/dist/service-installer.js +18 -3
- package/dist/service-installer.js.map +1 -1
- package/dist/settings-api.d.ts +23 -0
- package/dist/settings-api.js +233 -2
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +112 -0
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-effect.js +32 -2
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.js +5 -0
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/tmux-manager.d.ts +5 -0
- package/dist/tmux-manager.js +16 -0
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tool-permissions.d.ts +4 -6
- package/dist/tool-permissions.js +100 -2
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.d.ts +17 -7
- package/dist/topic-commands.js +39 -21
- package/dist/topic-commands.js.map +1 -1
- package/dist/topic-link.d.ts +128 -0
- package/dist/topic-link.js +269 -0
- package/dist/topic-link.js.map +1 -0
- package/dist/types.d.ts +61 -1
- package/dist/ui/app-effects.js +245 -0
- package/dist/ui/chat-ambient.js +307 -0
- package/dist/ui/chat-effect-posters.js +42 -0
- package/dist/ui/chat-effects.js +160 -0
- package/dist/ui/chat-live-replies.js +58 -0
- package/dist/ui/chat-render.js +25 -7
- package/dist/ui/chat-store.js +41 -13
- package/dist/ui/chat-strings.js +86 -2
- package/dist/ui/chat-thread.js +204 -37
- package/dist/ui/chat-tour.js +1 -1
- package/dist/ui/effect-trial-controller.js +124 -0
- package/dist/ui/effect-trial-offer.js +31 -0
- package/dist/ui/effect-trial-panel.js +40 -0
- package/dist/ui/fleet-cache.js +23 -1
- package/dist/ui/fleet-canvas-layout.js +111 -0
- package/dist/ui/fleet-canvas.js +525 -0
- package/dist/ui/fleet-org.js +27 -12
- package/dist/ui/fleet-traffic.js +343 -0
- package/dist/ui/fleet-usage.js +401 -0
- package/dist/ui/image-lightbox.js +1 -1
- package/dist/ui/panel-chat.js +252 -58
- package/dist/ui/panel-details.js +20 -6
- package/dist/ui/panel-fleet.js +45 -19
- package/dist/ui/panel-log.js +6 -6
- package/dist/ui/panel-needs.js +3 -3
- package/dist/ui/panel-settings.js +58 -13
- package/dist/ui/preview-panel.js +25 -9
- package/dist/ui/preview.js +3 -2
- package/dist/ui/settings-appearance.js +349 -0
- package/dist/ui/settings-catalog.js +92 -0
- package/dist/ui/settings-dialogs.js +40 -12
- package/dist/ui/settings-effects.js +202 -0
- package/dist/ui/settings-guests.js +117 -0
- package/dist/ui/settings-learn.js +25 -0
- package/dist/ui/settings-model.js +15 -6
- package/dist/ui/settings-mods.js +271 -0
- package/dist/ui/settings-owner-effects.js +80 -0
- package/dist/ui/settings-strings.js +335 -10
- package/dist/ui/settings-web-authority.js +91 -0
- package/dist/ui/shared/agend-auth.js +28 -4
- package/dist/ui/shared/agent-widget.js +248 -0
- package/dist/ui/shared/app-i18n.js +6 -2
- package/dist/ui/shared/app-prefs.js +34 -13
- package/dist/ui/shared/app-route.js +42 -2
- package/dist/ui/shared/app-session.js +3 -1
- package/dist/ui/shared/app-shell.js +119 -41
- package/dist/ui/shared/app-store.js +28 -1
- package/dist/ui/shared/app-stream.js +14 -7
- package/dist/ui/shared/app-themes.js +206 -0
- package/dist/ui/shared/app.css +566 -5
- package/dist/ui/shared/app.js +23 -10
- package/dist/ui/shared/card-strings.js +32 -0
- package/dist/ui/shared/effect-app-runtime.js +297 -0
- package/dist/ui/shared/effect-baseline.js +64 -0
- package/dist/ui/shared/effect-chat-runtime.js +167 -0
- package/dist/ui/shared/effect-cursor.js +125 -0
- package/dist/ui/shared/effect-frame.js +146 -0
- package/dist/ui/shared/effect-geometry.js +137 -0
- package/dist/ui/shared/effect-host-style.js +10 -0
- package/dist/ui/shared/effect-owner-regions.js +74 -0
- package/dist/ui/shared/effect-owner-source.js +122 -0
- package/dist/ui/shared/effect-policy.js +151 -0
- package/dist/ui/shared/effect-poster-reader.js +98 -0
- package/dist/ui/shared/effect-posters.js +117 -0
- package/dist/ui/shared/effect-profiler.js +184 -0
- package/dist/ui/shared/effect-profiles.js +65 -0
- package/dist/ui/shared/effect-registry.js +543 -0
- package/dist/ui/shared/effect-runtime-loader.js +234 -0
- package/dist/ui/shared/effect-safety.js +153 -0
- package/dist/ui/shared/effect-stock-snapshot.js +43 -0
- package/dist/ui/shared/effect-stock-trust.js +217 -0
- package/dist/ui/shared/effect-trial-shadow.js +62 -0
- package/dist/ui/shared/effect-trial-source.js +103 -0
- package/dist/ui/shared/effect-trial-stage.js +170 -0
- package/dist/ui/shared/effect-trial.css +40 -0
- package/dist/ui/shared/fx-motion.js +67 -0
- package/dist/ui/shared/header-tools.js +1 -1
- package/dist/ui/shared/identity-card.js +273 -0
- package/dist/ui/shared/identity-color.js +261 -0
- package/dist/ui/shared/instance-nav.js +215 -41
- package/dist/ui/shared/owner-css.js +250 -0
- package/dist/ui/shared/owner-effect-prefs.js +117 -0
- package/dist/ui/shared/panel-view.js +103 -10
- package/dist/ui/shared/signin.js +2 -0
- package/dist/ui/shared/tokens.css +9 -3
- package/dist/ui/shared/ui-dialog.js +1 -1
- package/dist/ui/shared/ui-icons.js +3 -0
- package/dist/ui/shared/ui-menu.js +1 -1
- package/dist/ui/shared/ui-toast.js +1 -1
- package/dist/ui/shared/usage-dialog.js +22 -2
- package/dist/ui/shared/view-strings.js +98 -2
- package/dist/ui/shared/web-authorize.js +151 -0
- package/dist/ui/signin.html +1 -0
- package/dist/ui/web-terminal/terminal.css +4 -4
- package/dist/usage/providers.d.ts +28 -0
- package/dist/usage/providers.js +126 -36
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage-report.d.ts +158 -0
- package/dist/usage-report.js +226 -0
- package/dist/usage-report.js.map +1 -0
- package/dist/usage-rollup.d.ts +51 -0
- package/dist/usage-rollup.js +168 -0
- package/dist/usage-rollup.js.map +1 -0
- package/dist/view-api.d.ts +68 -0
- package/dist/view-api.js +249 -8
- package/dist/view-api.js.map +1 -1
- package/dist/web-ambient.d.ts +72 -0
- package/dist/web-ambient.js +161 -0
- package/dist/web-ambient.js.map +1 -0
- package/dist/web-api.d.ts +117 -7
- package/dist/web-api.js +1283 -70
- package/dist/web-api.js.map +1 -1
- package/dist/web-appearance-limits.d.ts +82 -0
- package/dist/web-appearance-limits.js +83 -0
- package/dist/web-appearance-limits.js.map +1 -0
- package/dist/web-appearance-policy.d.ts +64 -0
- package/dist/web-appearance-policy.js +87 -0
- package/dist/web-appearance-policy.js.map +1 -0
- package/dist/web-appearance-tools.d.ts +53 -0
- package/dist/web-appearance-tools.js +124 -0
- package/dist/web-appearance-tools.js.map +1 -0
- package/dist/web-appearance-view.d.ts +124 -0
- package/dist/web-appearance-view.js +278 -0
- package/dist/web-appearance-view.js.map +1 -0
- package/dist/web-appearance.d.ts +93 -0
- package/dist/web-appearance.js +373 -0
- package/dist/web-appearance.js.map +1 -0
- package/dist/web-asset-parts.d.ts +93 -0
- package/dist/web-asset-parts.js +133 -0
- package/dist/web-asset-parts.js.map +1 -0
- package/dist/web-auth.js +20 -2
- package/dist/web-auth.js.map +1 -1
- package/dist/web-card.d.ts +110 -0
- package/dist/web-card.js +266 -0
- package/dist/web-card.js.map +1 -0
- package/dist/web-channel-echo.d.ts +7 -1
- package/dist/web-channel-echo.js +6 -2
- package/dist/web-channel-echo.js.map +1 -1
- package/dist/web-chat-history.d.ts +63 -0
- package/dist/web-chat-history.js +109 -6
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +1 -0
- package/dist/web-effect-bootstrap.d.ts +12 -0
- package/dist/web-effect-bootstrap.js +49 -0
- package/dist/web-effect-bootstrap.js.map +1 -0
- package/dist/web-effect-bundle.d.ts +28 -0
- package/dist/web-effect-bundle.js +171 -0
- package/dist/web-effect-bundle.js.map +1 -0
- package/dist/web-effect-canonical.d.ts +8 -0
- package/dist/web-effect-canonical.js +27 -0
- package/dist/web-effect-canonical.js.map +1 -0
- package/dist/web-effect-library.d.ts +114 -0
- package/dist/web-effect-library.js +530 -0
- package/dist/web-effect-library.js.map +1 -0
- package/dist/web-effect-playback.d.ts +30 -0
- package/dist/web-effect-playback.js +71 -0
- package/dist/web-effect-playback.js.map +1 -0
- package/dist/web-effect-poster.d.ts +8 -0
- package/dist/web-effect-poster.js +52 -0
- package/dist/web-effect-poster.js.map +1 -0
- package/dist/web-effect-profiles.d.ts +118 -0
- package/dist/web-effect-profiles.js +180 -0
- package/dist/web-effect-profiles.js.map +1 -0
- package/dist/web-effect-service.d.ts +93 -0
- package/dist/web-effect-service.js +335 -0
- package/dist/web-effect-service.js.map +1 -0
- package/dist/web-effect-tools.d.ts +48 -0
- package/dist/web-effect-tools.js +129 -0
- package/dist/web-effect-tools.js.map +1 -0
- package/dist/web-effect-trials.d.ts +86 -0
- package/dist/web-effect-trials.js +204 -0
- package/dist/web-effect-trials.js.map +1 -0
- package/dist/web-effect-upload.d.ts +27 -0
- package/dist/web-effect-upload.js +185 -0
- package/dist/web-effect-upload.js.map +1 -0
- package/dist/web-effect-worker.d.ts +8 -0
- package/dist/web-effect-worker.js +170 -0
- package/dist/web-effect-worker.js.map +1 -0
- package/dist/web-effect.d.ts +103 -0
- package/dist/web-effect.js +153 -0
- package/dist/web-effect.js.map +1 -0
- package/dist/web-guest-access.d.ts +125 -0
- package/dist/web-guest-access.js +234 -0
- package/dist/web-guest-access.js.map +1 -0
- package/dist/web-guest-rooms.d.ts +82 -0
- package/dist/web-guest-rooms.js +135 -0
- package/dist/web-guest-rooms.js.map +1 -0
- package/dist/web-identity-color.d.ts +87 -0
- package/dist/web-identity-color.js +209 -0
- package/dist/web-identity-color.js.map +1 -0
- package/dist/web-identity-palette.d.ts +113 -0
- package/dist/web-identity-palette.js +84 -0
- package/dist/web-identity-palette.js.map +1 -0
- package/dist/web-image-meta.d.ts +38 -0
- package/dist/web-image-meta.js +262 -0
- package/dist/web-image-meta.js.map +1 -0
- package/dist/web-login.d.ts +47 -0
- package/dist/web-login.js +115 -0
- package/dist/web-login.js.map +1 -1
- package/dist/web-mod-agent.d.ts +50 -0
- package/dist/web-mod-agent.js +207 -0
- package/dist/web-mod-agent.js.map +1 -0
- package/dist/web-mod-bundle.d.ts +157 -0
- package/dist/web-mod-bundle.js +529 -0
- package/dist/web-mod-bundle.js.map +1 -0
- package/dist/web-mod-export.d.ts +68 -0
- package/dist/web-mod-export.js +100 -0
- package/dist/web-mod-export.js.map +1 -0
- package/dist/web-mod-store.d.ts +289 -0
- package/dist/web-mod-store.js +638 -0
- package/dist/web-mod-store.js.map +1 -0
- package/dist/web-org.d.ts +3 -3
- package/dist/web-org.js +11 -17
- package/dist/web-org.js.map +1 -1
- package/dist/web-owner-css-store.d.ts +222 -0
- package/dist/web-owner-css-store.js +440 -0
- package/dist/web-owner-css-store.js.map +1 -0
- package/dist/web-owner-css.d.ts +58 -0
- package/dist/web-owner-css.js +552 -0
- package/dist/web-owner-css.js.map +1 -0
- package/dist/web-prefs.d.ts +62 -0
- package/dist/web-prefs.js +232 -36
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-preview.d.ts +15 -3
- package/dist/web-preview.js +28 -9
- package/dist/web-preview.js.map +1 -1
- package/dist/web-returning-device.d.ts +41 -0
- package/dist/web-returning-device.js +57 -5
- package/dist/web-returning-device.js.map +1 -1
- package/dist/web-session-authorization.d.ts +132 -0
- package/dist/web-session-authorization.js +193 -0
- package/dist/web-session-authorization.js.map +1 -0
- package/dist/web-session.d.ts +70 -10
- package/dist/web-session.js +137 -22
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +67 -2
- package/dist/web-settings-patch.js +196 -1
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-settings-tools.d.ts +89 -0
- package/dist/web-settings-tools.js +273 -0
- package/dist/web-settings-tools.js.map +1 -0
- package/dist/web-shell-routes.d.ts +2 -2
- package/dist/web-shell-routes.js +2 -2
- package/dist/web-shell-routes.js.map +1 -1
- package/dist/web-theme-store.d.ts +257 -0
- package/dist/web-theme-store.js +627 -0
- package/dist/web-theme-store.js.map +1 -0
- package/dist/web-theme.d.ts +123 -0
- package/dist/web-theme.js +416 -0
- package/dist/web-theme.js.map +1 -0
- package/dist/web-upload.d.ts +13 -0
- package/dist/web-upload.js +39 -3
- package/dist/web-upload.js.map +1 -1
- package/dist/web-widget.d.ts +72 -0
- package/dist/web-widget.js +245 -0
- package/dist/web-widget.js.map +1 -0
- package/dist/workflow-templates/default.md +1 -1
- package/package.json +1 -1
- package/templates/systemd.service.ejs +8 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
export type AvailabilityState = "usable" | "not_installed" | "not_signed_in" | "too_old" | "unknown";
|
|
2
|
+
/** A login's state: `not_required` — the CLI talks to a provider of its own (codex's custom provider), no login of ours. */
|
|
3
|
+
export type AuthState = "valid" | "invalid" | "unknown" | "not_required";
|
|
4
|
+
export interface BackendAvailability {
|
|
5
|
+
backend: string;
|
|
6
|
+
state: AvailabilityState;
|
|
7
|
+
/** The executable the launch would run (null: not found or not probed). */
|
|
8
|
+
path: string | null;
|
|
9
|
+
version: string | null;
|
|
10
|
+
auth: AuthState;
|
|
11
|
+
/** The oldest version AgEnD supports, when the state is too_old. */
|
|
12
|
+
minVersion: string | null;
|
|
13
|
+
/** When it was last probed (monotonic ms), or null: never. */
|
|
14
|
+
checkedAt: number | null;
|
|
15
|
+
}
|
|
16
|
+
/** The oldest CLI version each backend supports. Only gates there is evidence for; others have none. */
|
|
17
|
+
export declare const MIN_SUPPORTED_VERSION: Readonly<Record<string, string>>;
|
|
18
|
+
/** How old a snapshot may be before a read asks for a refresh (it is still served). */
|
|
19
|
+
export declare const AVAILABILITY_STALE_MS: number;
|
|
20
|
+
/** "2.30.1" from "kiro-cli 2.30.1 (abc)"; null when there is no version in it. */
|
|
21
|
+
export declare function parseVersion(text: string | null | undefined): string | null;
|
|
22
|
+
/** a < b, for dotted numeric versions. */
|
|
23
|
+
export declare function versionBelow(a: string, b: string): boolean;
|
|
24
|
+
/** The state for what the probes answered. Pure. */
|
|
25
|
+
export declare function availabilityState(a: {
|
|
26
|
+
installed: boolean | null;
|
|
27
|
+
version: string | null;
|
|
28
|
+
auth: AuthState;
|
|
29
|
+
minVersion: string | null;
|
|
30
|
+
}): AvailabilityState;
|
|
31
|
+
/** What the store needs from the host; tests pass fakes (no CLI, no account, no network). */
|
|
32
|
+
export interface AvailabilityProbes {
|
|
33
|
+
/** The executable's path, null when it is not installed, undefined when there was no answer in time. */
|
|
34
|
+
resolve(backend: string): Promise<string | null | undefined>;
|
|
35
|
+
/** `<path> --version`, parsed; null when there is no answer. */
|
|
36
|
+
version(backend: string, path: string): Promise<string | null>;
|
|
37
|
+
/** The backend's default login, read offline (credential files, API-key variables). */
|
|
38
|
+
auth(backend: string): Promise<AuthState>;
|
|
39
|
+
/** What changes when the binary or its login changes (mtimes and sizes); null when it cannot be read. */
|
|
40
|
+
signature(backend: string, path: string): Promise<string | null>;
|
|
41
|
+
}
|
|
42
|
+
export declare class BackendAvailabilityStore {
|
|
43
|
+
private readonly backends;
|
|
44
|
+
private readonly probes;
|
|
45
|
+
private rows;
|
|
46
|
+
private queue;
|
|
47
|
+
private pending;
|
|
48
|
+
private readonly now;
|
|
49
|
+
private readonly onChange;
|
|
50
|
+
constructor(backends: readonly string[], probes: AvailabilityProbes, opts?: {
|
|
51
|
+
now?: () => number;
|
|
52
|
+
onChange?: () => void;
|
|
53
|
+
});
|
|
54
|
+
/**
|
|
55
|
+
* The published rows, in the catalog's order. Never probes, not even in the background (a handler must not fork):
|
|
56
|
+
* the owner refreshes at launch, on its timer and after an install or sign-in.
|
|
57
|
+
*/
|
|
58
|
+
snapshot(): BackendAvailability[];
|
|
59
|
+
get(backend: string): BackendAvailability | null;
|
|
60
|
+
/** Whether any row is older than AVAILABILITY_STALE_MS (or never probed). */
|
|
61
|
+
stale(): boolean;
|
|
62
|
+
private view;
|
|
63
|
+
private isStale;
|
|
64
|
+
/**
|
|
65
|
+
* Probe these backends (all by default), ONE AT A TIME across every caller; resolves when they are published.
|
|
66
|
+
* `force`: probe even when nothing changed (Refresh, a /login install or sign-in).
|
|
67
|
+
*/
|
|
68
|
+
refresh(backends?: readonly string[], opts?: {
|
|
69
|
+
force?: boolean;
|
|
70
|
+
}): Promise<void>;
|
|
71
|
+
private probeOne;
|
|
72
|
+
}
|
|
73
|
+
/** Found the way the launch finds it (resolveBinary): on PATH, else in a known install directory. */
|
|
74
|
+
export declare function resolveBackendBinary(backend: string): Promise<string | null | undefined>;
|
|
75
|
+
/** The cap a `--version` run gets: no CLI started for a probe can take the fleet's memory (one OOM took a fleet down). */
|
|
76
|
+
export declare const VERSION_PROBE_MEMORY = "512M";
|
|
77
|
+
/** Each CLI's own "do not update" switches, set for a `--version` run (belt and braces: there is no network anyway). */
|
|
78
|
+
export declare const NO_UPDATE_ENV: Readonly<Record<string, string>>;
|
|
79
|
+
/** A backend whose version is read from a file next to its launcher: starting it at all can update it (#2078 review). */
|
|
80
|
+
export declare const STATIC_VERSION_FILES: Readonly<Record<string, (path: string) => string>>;
|
|
81
|
+
/**
|
|
82
|
+
* The version from what is on disk, starting nothing: a launcher's own version file (muse), else a version segment
|
|
83
|
+
* the package.json of the npm package that owns the binary (under node_modules), else a version segment of the real
|
|
84
|
+
* path in a layout we know (claude's `…/versions/2.1.302`, codex's `…/releases/0.162.1-<target>/`). Null when none says.
|
|
85
|
+
*/
|
|
86
|
+
export declare function staticBackendVersion(backend: string, path: string): Promise<string | null>;
|
|
87
|
+
/**
|
|
88
|
+
* The version, without letting any CLI change anything or reach the network (the leader's rule, #2078):
|
|
89
|
+
* 1. what is on disk (staticBackendVersion) — every OS, every backend;
|
|
90
|
+
* 2. else, on Linux where an unprivileged network namespace can be made, `<path> --version` inside it (no network),
|
|
91
|
+
* with the CLIs' no-update switches, a deadline and (where systemd can) a memory cap; muse never (STATIC_VERSION_FILES);
|
|
92
|
+
* 3. else unknown — never a networked `--version`. No version is no "too old" claim: the backend stays selectable.
|
|
93
|
+
*/
|
|
94
|
+
export declare function probeBackendVersion(backend: string, path: string): Promise<string | null>;
|
|
95
|
+
/**
|
|
96
|
+
* Whether codex's own config runs it on a provider other than OpenAI (no login of ours): "yes", "no", or "unknown".
|
|
97
|
+
* Its default is the top level's `model_provider`, or the provider of the profile the top level selects
|
|
98
|
+
* (`profile = "x"` → `[profiles.x]`). A selected profile that cannot be read is unknown, never "no" (#2078 review).
|
|
99
|
+
*/
|
|
100
|
+
export declare function codexUsesOwnProvider(env?: NodeJS.ProcessEnv): Promise<"yes" | "no" | "unknown">;
|
|
101
|
+
interface OfflineLogin {
|
|
102
|
+
/** Any of these files present (non-empty) means a login is stored. */
|
|
103
|
+
files: (env: NodeJS.ProcessEnv, home: string) => string[];
|
|
104
|
+
/** Any of these variables set means the CLI authenticates without a stored login. */
|
|
105
|
+
keys?: string[];
|
|
106
|
+
/** No file and no key: "invalid" when that is proof, "unknown" when the CLI has other ways we cannot see offline. */
|
|
107
|
+
absent: (platform: NodeJS.Platform) => "invalid" | "unknown";
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Where each CLI keeps its login (the same paths usage/providers.ts reads). Presence is all that is checked offline:
|
|
111
|
+
* a stored login that has since expired still reads as signed in until the CLI says otherwise.
|
|
112
|
+
*/
|
|
113
|
+
export declare const OFFLINE_LOGINS: Readonly<Record<string, OfflineLogin>>;
|
|
114
|
+
/** The default login's state, from files and variables only. */
|
|
115
|
+
export declare function probeOfflineAuth(backend: string, env?: NodeJS.ProcessEnv, home?: string): Promise<AuthState>;
|
|
116
|
+
/** mtime and size of the binary and the login files: the probe runs a CLI again only when this changes. */
|
|
117
|
+
export declare function availabilitySignature(backend: string, path: string, env?: NodeJS.ProcessEnv, home?: string): Promise<string | null>;
|
|
118
|
+
/** The host's probes. */
|
|
119
|
+
export declare const hostAvailabilityProbes: AvailabilityProbes;
|
|
120
|
+
export {};
|
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #2072: which backends actually work on this host — installed, signed in, new enough — as one published snapshot.
|
|
3
|
+
*
|
|
4
|
+
* Pickers (`/backend` on the web, Discord and Telegram; `/ui/backends`; ClassicBot's `/start`; the setup wizard) used to
|
|
5
|
+
* ask "is it installed?" each in their own way, three of them with a synchronous `which` on the fleet's event loop, and
|
|
6
|
+
* none of them asked whether the CLI was signed in or new enough. Here the questions are answered by bounded
|
|
7
|
+
* asynchronous probes (child processes with deadlines, never an fs walk on the loop) and published; a handler only
|
|
8
|
+
* reads the snapshot (#tool-handlers-never-fork) and never asks for a probe — the fleet refreshes it at launch, every
|
|
9
|
+
* AVAILABILITY_STALE_MS, and after a /login install or sign-in.
|
|
10
|
+
*
|
|
11
|
+
* Unknown is never "unusable": a backend not probed yet, or whose probe gave no answer, stays selectable and is checked
|
|
12
|
+
* again when it is applied. Only a definite answer disables it: not installed, not signed in (for a login that needs
|
|
13
|
+
* one), or older than the minimum AgEnD supports. A probe that fails keeps the last definite answer (fail open).
|
|
14
|
+
*
|
|
15
|
+
* Cost and safety (the leader's rules, #2072):
|
|
16
|
+
* - Sign-in is read OFFLINE from credential files and API-key variables — never a model or API request, never the
|
|
17
|
+
* CLI's own status command (`grok models` and `agy models` call the vendor; grok's also always exits 0, #1792).
|
|
18
|
+
* Where a login cannot be judged offline the answer is unknown, not "signed in".
|
|
19
|
+
* - Probes run one backend at a time. The only CLI ever started is `<binary> --version`, and only when the binary or
|
|
20
|
+
* its credential files changed since the last probe: inside a memory-capped scope where systemd can make one, and in
|
|
21
|
+
* a network namespace with no network (`unshare -rn`) so no CLI can update itself or reach a vendor (#2078 review:
|
|
22
|
+
* `muse --version` updated its own launcher). Before that, the version is read from disk wherever it is written there
|
|
23
|
+
* (a version file, a versioned install path, an npm package.json), which starts nothing; muse is never started at
|
|
24
|
+
* all. Without a network namespace (macOS, or a host that forbids one) no `--version` runs: unknown.
|
|
25
|
+
* - Each pass still asks whether each binary is there (`which`, and one `sh` test of the install directories, both
|
|
26
|
+
* bounded children) — never a CLI.
|
|
27
|
+
*/
|
|
28
|
+
import { homedir } from "node:os";
|
|
29
|
+
import { dirname, join } from "node:path";
|
|
30
|
+
import { readFile, readdir, realpath, stat } from "node:fs/promises";
|
|
31
|
+
import { binaryProbe, spawnProbeCommand, PROBE_DEADLINE_MS } from "./binary-probe.js";
|
|
32
|
+
import { BACKEND_INSTALLATION_INFO } from "./instance-lifecycle.js";
|
|
33
|
+
import { KIRO_SUPPORTED_MIN } from "./backend/kiro.js";
|
|
34
|
+
/** The oldest CLI version each backend supports. Only gates there is evidence for; others have none. */
|
|
35
|
+
export const MIN_SUPPORTED_VERSION = { "kiro-cli": KIRO_SUPPORTED_MIN };
|
|
36
|
+
/** How old a snapshot may be before a read asks for a refresh (it is still served). */
|
|
37
|
+
export const AVAILABILITY_STALE_MS = 10 * 60_000;
|
|
38
|
+
/** "2.30.1" from "kiro-cli 2.30.1 (abc)"; null when there is no version in it. */
|
|
39
|
+
export function parseVersion(text) {
|
|
40
|
+
const m = /(\d+)\.(\d+)(?:\.(\d+))?/.exec(text ?? "");
|
|
41
|
+
return m ? `${m[1]}.${m[2]}.${m[3] ?? "0"}` : null;
|
|
42
|
+
}
|
|
43
|
+
/** a < b, for dotted numeric versions. */
|
|
44
|
+
export function versionBelow(a, b) {
|
|
45
|
+
const pa = a.split(".").map(Number), pb = b.split(".").map(Number);
|
|
46
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
47
|
+
const x = pa[i] ?? 0, y = pb[i] ?? 0;
|
|
48
|
+
if (x !== y)
|
|
49
|
+
return x < y;
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
/** The state for what the probes answered. Pure. */
|
|
54
|
+
export function availabilityState(a) {
|
|
55
|
+
if (a.installed === false)
|
|
56
|
+
return "not_installed";
|
|
57
|
+
if (a.installed === null)
|
|
58
|
+
return "unknown";
|
|
59
|
+
if (a.minVersion && a.version && versionBelow(a.version, a.minVersion))
|
|
60
|
+
return "too_old";
|
|
61
|
+
if (a.auth === "invalid")
|
|
62
|
+
return "not_signed_in";
|
|
63
|
+
return a.version === null && a.auth === "unknown" ? "unknown" : "usable";
|
|
64
|
+
}
|
|
65
|
+
export class BackendAvailabilityStore {
|
|
66
|
+
backends;
|
|
67
|
+
probes;
|
|
68
|
+
rows = new Map();
|
|
69
|
+
queue = Promise.resolve();
|
|
70
|
+
pending = new Set();
|
|
71
|
+
now;
|
|
72
|
+
onChange;
|
|
73
|
+
constructor(backends, probes, opts = {}) {
|
|
74
|
+
this.backends = backends;
|
|
75
|
+
this.probes = probes;
|
|
76
|
+
this.now = opts.now ?? (() => performance.now());
|
|
77
|
+
this.onChange = opts.onChange ?? (() => { });
|
|
78
|
+
for (const backend of backends)
|
|
79
|
+
this.rows.set(backend, { backend, state: "unknown", path: null, version: null, auth: "unknown", minVersion: null, checkedAt: null, signature: null });
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The published rows, in the catalog's order. Never probes, not even in the background (a handler must not fork):
|
|
83
|
+
* the owner refreshes at launch, on its timer and after an install or sign-in.
|
|
84
|
+
*/
|
|
85
|
+
snapshot() {
|
|
86
|
+
return this.backends.map(b => this.view(b));
|
|
87
|
+
}
|
|
88
|
+
get(backend) {
|
|
89
|
+
return this.rows.has(backend) ? this.view(backend) : null;
|
|
90
|
+
}
|
|
91
|
+
/** Whether any row is older than AVAILABILITY_STALE_MS (or never probed). */
|
|
92
|
+
stale() { return this.backends.some(b => this.isStale(b)); }
|
|
93
|
+
view(backend) {
|
|
94
|
+
const row = this.rows.get(backend);
|
|
95
|
+
if (!row)
|
|
96
|
+
return null;
|
|
97
|
+
const { signature: _s, ...shown } = row;
|
|
98
|
+
return shown;
|
|
99
|
+
}
|
|
100
|
+
isStale(backend) {
|
|
101
|
+
const at = this.rows.get(backend)?.checkedAt;
|
|
102
|
+
return at === null || at === undefined || this.now() - at > AVAILABILITY_STALE_MS;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Probe these backends (all by default), ONE AT A TIME across every caller; resolves when they are published.
|
|
106
|
+
* `force`: probe even when nothing changed (Refresh, a /login install or sign-in).
|
|
107
|
+
*/
|
|
108
|
+
refresh(backends = this.backends, opts = {}) {
|
|
109
|
+
const wanted = backends.filter(b => this.rows.has(b) && (opts.force || !this.pending.has(b)));
|
|
110
|
+
for (const b of wanted)
|
|
111
|
+
this.pending.add(b);
|
|
112
|
+
const run = this.queue.then(async () => {
|
|
113
|
+
for (const b of wanted) {
|
|
114
|
+
try {
|
|
115
|
+
await this.probeOne(b, !!opts.force);
|
|
116
|
+
}
|
|
117
|
+
catch { /* a failed probe keeps the last answer */ }
|
|
118
|
+
this.pending.delete(b);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
this.queue = run.catch(() => { });
|
|
122
|
+
return run;
|
|
123
|
+
}
|
|
124
|
+
async probeOne(backend, force) {
|
|
125
|
+
const previous = this.rows.get(backend);
|
|
126
|
+
let path;
|
|
127
|
+
try {
|
|
128
|
+
path = await this.probes.resolve(backend);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
path = undefined;
|
|
132
|
+
}
|
|
133
|
+
// No answer: keep what was known (fail open — never turn a usable backend into "unknown" or worse on a timeout).
|
|
134
|
+
if (path === undefined) {
|
|
135
|
+
this.rows.set(backend, { ...previous, checkedAt: previous.checkedAt === null ? null : this.now() });
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const signature = path ? await this.probes.signature(backend, path).catch(() => null) : "absent";
|
|
139
|
+
// Nothing changed since the last full probe: no CLI is started (the leader's cost rule).
|
|
140
|
+
if (!force && signature !== null && signature === previous.signature && previous.checkedAt !== null) {
|
|
141
|
+
this.rows.set(backend, { ...previous, checkedAt: this.now() });
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
let version = null, auth = "unknown";
|
|
145
|
+
if (path) {
|
|
146
|
+
version = await this.probes.version(backend, path).catch(() => null);
|
|
147
|
+
auth = await this.probes.auth(backend).catch(() => "unknown");
|
|
148
|
+
}
|
|
149
|
+
// A version probe that failed keeps the version we knew for the same binary.
|
|
150
|
+
if (path && version === null && previous.path === path)
|
|
151
|
+
version = previous.version;
|
|
152
|
+
const minVersion = MIN_SUPPORTED_VERSION[backend] ?? null;
|
|
153
|
+
const state = availabilityState({ installed: path !== null, version, auth, minVersion });
|
|
154
|
+
const row = { backend, state, path, version, auth, minVersion: state === "too_old" ? minVersion : null, checkedAt: this.now(), signature };
|
|
155
|
+
this.rows.set(backend, row);
|
|
156
|
+
if (previous.state !== row.state || previous.path !== row.path || previous.version !== row.version || previous.auth !== row.auth)
|
|
157
|
+
this.onChange();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// ── The host's probes: child processes with deadlines (binary-probe.ts's rules), never a synchronous spawn ──
|
|
161
|
+
/** Run one probe child and read its first output line within the deadline; undefined when there is no answer. */
|
|
162
|
+
async function answer(child, deadlineMs = PROBE_DEADLINE_MS) {
|
|
163
|
+
let timer;
|
|
164
|
+
try {
|
|
165
|
+
return await Promise.race([child.answer, new Promise(r => { timer = setTimeout(() => { child.kill(); r(undefined); }, deadlineMs); })]);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
if (timer)
|
|
172
|
+
clearTimeout(timer);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/** `npm prefix -g`, asked once per process (an answer only; no answer is asked again next time). */
|
|
176
|
+
let npmPrefixAnswer;
|
|
177
|
+
async function npmPrefix() {
|
|
178
|
+
if (npmPrefixAnswer !== undefined)
|
|
179
|
+
return npmPrefixAnswer;
|
|
180
|
+
const got = await answer(spawnProbeCommand("npm", ["prefix", "-g"]), 3000);
|
|
181
|
+
if (got !== undefined)
|
|
182
|
+
npmPrefixAnswer = got;
|
|
183
|
+
return got ?? null;
|
|
184
|
+
}
|
|
185
|
+
/** The directories resolveBinary searches after PATH, without its synchronous `npm prefix -g` and readdir. */
|
|
186
|
+
async function fallbackDirs(backend) {
|
|
187
|
+
const home = homedir();
|
|
188
|
+
const dirs = [...(BACKEND_INSTALLATION_INFO[backend]?.binDirs?.(process.env, home) ?? []), dirname(process.execPath),
|
|
189
|
+
join(home, ".local", "bin"), join(home, ".npm-global", "bin"), "/usr/local/bin", "/usr/bin", "/bin"];
|
|
190
|
+
try {
|
|
191
|
+
for (const v of (await readdir(join(home, ".nvm", "versions", "node"))).sort().reverse())
|
|
192
|
+
dirs.push(join(home, ".nvm", "versions", "node", v, "bin"));
|
|
193
|
+
}
|
|
194
|
+
catch { /* optional */ }
|
|
195
|
+
const prefix = await npmPrefix();
|
|
196
|
+
if (prefix)
|
|
197
|
+
dirs.push(join(prefix, "bin"));
|
|
198
|
+
return [...new Set(dirs)];
|
|
199
|
+
}
|
|
200
|
+
/** Found the way the launch finds it (resolveBinary): on PATH, else in a known install directory. */
|
|
201
|
+
export async function resolveBackendBinary(backend) {
|
|
202
|
+
const binary = BACKEND_INSTALLATION_INFO[backend]?.binary;
|
|
203
|
+
if (!binary)
|
|
204
|
+
return null;
|
|
205
|
+
const onPath = await binaryProbe.probe(binary);
|
|
206
|
+
if (onPath.known && onPath.path)
|
|
207
|
+
return onPath.path;
|
|
208
|
+
const dirs = await fallbackDirs(backend);
|
|
209
|
+
// One child tests every candidate (an fs check on a dead mount could hang a pool thread forever; a child can be killed).
|
|
210
|
+
const found = await answer(spawnProbeCommand("sh", ["-c", 'for p; do [ -f "$p" ] && [ -x "$p" ] && { echo "$p"; exit 0; }; done; exit 1', "sh",
|
|
211
|
+
...dirs.map(d => join(d, binary))]));
|
|
212
|
+
if (found)
|
|
213
|
+
return found;
|
|
214
|
+
// Not on PATH (a definite answer) and in no install directory: not installed. No answer from either: unknown.
|
|
215
|
+
return onPath.known && found === null ? null : undefined;
|
|
216
|
+
}
|
|
217
|
+
/** Whether `systemd-run --user --scope` works here (Linux with a user manager); learned once. */
|
|
218
|
+
let scopeWorks = null;
|
|
219
|
+
function canScope() {
|
|
220
|
+
if (process.platform !== "linux")
|
|
221
|
+
return Promise.resolve(false);
|
|
222
|
+
return scopeWorks ??= answer(spawnProbeCommand("systemd-run", ["--user", "--scope", "-q", "-p", "MemoryMax=64M", "--", "echo", "ok"]), 5000).then(a => a === "ok");
|
|
223
|
+
}
|
|
224
|
+
/** The cap a `--version` run gets: no CLI started for a probe can take the fleet's memory (one OOM took a fleet down). */
|
|
225
|
+
export const VERSION_PROBE_MEMORY = "512M";
|
|
226
|
+
/** Whether `unshare -rn` works here (a user and a network namespace, so a CLI runs with no network); learned once. */
|
|
227
|
+
let netlessWorks = null;
|
|
228
|
+
function canRunNetless() {
|
|
229
|
+
if (process.platform !== "linux")
|
|
230
|
+
return Promise.resolve(false);
|
|
231
|
+
return netlessWorks ??= answer(spawnProbeCommand("unshare", ["-rn", "--", "echo", "ok"]), 3000).then(a => a === "ok");
|
|
232
|
+
}
|
|
233
|
+
/** Each CLI's own "do not update" switches, set for a `--version` run (belt and braces: there is no network anyway). */
|
|
234
|
+
export const NO_UPDATE_ENV = {
|
|
235
|
+
DISABLE_AUTOUPDATER: "1", OPENCODE_DISABLE_AUTOUPDATE: "1", NO_UPDATE_NOTIFIER: "1", CI: "1",
|
|
236
|
+
};
|
|
237
|
+
/** A backend whose version is read from a file next to its launcher: starting it at all can update it (#2078 review). */
|
|
238
|
+
export const STATIC_VERSION_FILES = {
|
|
239
|
+
muse: (path) => join(dirname(path), ".muse-version"),
|
|
240
|
+
};
|
|
241
|
+
/**
|
|
242
|
+
* The version from what is on disk, starting nothing: a launcher's own version file (muse), else a version segment
|
|
243
|
+
* the package.json of the npm package that owns the binary (under node_modules), else a version segment of the real
|
|
244
|
+
* path in a layout we know (claude's `…/versions/2.1.302`, codex's `…/releases/0.162.1-<target>/`). Null when none says.
|
|
245
|
+
*/
|
|
246
|
+
export async function staticBackendVersion(backend, path) {
|
|
247
|
+
const file = STATIC_VERSION_FILES[backend];
|
|
248
|
+
if (file) {
|
|
249
|
+
try {
|
|
250
|
+
return parseVersion(await readFile(file(path), "utf8"));
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
let real;
|
|
257
|
+
try {
|
|
258
|
+
real = await realpath(path);
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
const parts = real.split("/");
|
|
264
|
+
// An npm-installed CLI: the package that owns the binary (…/node_modules/<pkg> or …/node_modules/@scope/<pkg>). Read
|
|
265
|
+
// first: an nvm prefix puts Node's own version in the path (…/nvm/versions/node/v22.22.2/…, #2078 review).
|
|
266
|
+
const nm = parts.lastIndexOf("node_modules");
|
|
267
|
+
if (nm >= 0 && parts[nm + 1]) {
|
|
268
|
+
const pkgDir = parts.slice(0, nm + (parts[nm + 1].startsWith("@") ? 3 : 2)).join("/");
|
|
269
|
+
try {
|
|
270
|
+
const pkg = JSON.parse(await readFile(join(pkgDir, "package.json"), "utf8"));
|
|
271
|
+
if (typeof pkg.version === "string")
|
|
272
|
+
return parseVersion(pkg.version);
|
|
273
|
+
}
|
|
274
|
+
catch { /* no package.json there */ }
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
// The versioned layouts we know: claude's …/versions/<v>, codex's …/releases/<v>-<target>/…. Only a segment whose
|
|
278
|
+
// parent is one of those names — never any version-looking directory on the way.
|
|
279
|
+
for (let i = parts.length - 1; i > 0; i--) {
|
|
280
|
+
if ((parts[i - 1] === "versions" || parts[i - 1] === "releases") && /^v?\d+\.\d+\.\d+(?:[-+.][\w.-]*)?$/.test(parts[i]))
|
|
281
|
+
return parseVersion(parts[i]);
|
|
282
|
+
}
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* The version, without letting any CLI change anything or reach the network (the leader's rule, #2078):
|
|
287
|
+
* 1. what is on disk (staticBackendVersion) — every OS, every backend;
|
|
288
|
+
* 2. else, on Linux where an unprivileged network namespace can be made, `<path> --version` inside it (no network),
|
|
289
|
+
* with the CLIs' no-update switches, a deadline and (where systemd can) a memory cap; muse never (STATIC_VERSION_FILES);
|
|
290
|
+
* 3. else unknown — never a networked `--version`. No version is no "too old" claim: the backend stays selectable.
|
|
291
|
+
*/
|
|
292
|
+
export async function probeBackendVersion(backend, path) {
|
|
293
|
+
const known = await staticBackendVersion(backend, path);
|
|
294
|
+
if (known || STATIC_VERSION_FILES[backend])
|
|
295
|
+
return known;
|
|
296
|
+
if (!(await canRunNetless()))
|
|
297
|
+
return null;
|
|
298
|
+
const argv = ["unshare", "-rn", "--", "env", ...Object.entries(NO_UPDATE_ENV).map(([k, v]) => `${k}=${v}`), path, "--version"];
|
|
299
|
+
const child = (await canScope())
|
|
300
|
+
? spawnProbeCommand("systemd-run", ["--user", "--scope", "-q", "-p", `MemoryMax=${VERSION_PROBE_MEMORY}`, "--", ...argv])
|
|
301
|
+
: spawnProbeCommand(argv[0], argv.slice(1));
|
|
302
|
+
return parseVersion(await answer(child, 5000));
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Whether codex's own config runs it on a provider other than OpenAI (no login of ours): "yes", "no", or "unknown".
|
|
306
|
+
* Its default is the top level's `model_provider`, or the provider of the profile the top level selects
|
|
307
|
+
* (`profile = "x"` → `[profiles.x]`). A selected profile that cannot be read is unknown, never "no" (#2078 review).
|
|
308
|
+
*/
|
|
309
|
+
export async function codexUsesOwnProvider(env = process.env) {
|
|
310
|
+
let text;
|
|
311
|
+
try {
|
|
312
|
+
text = await readFile(join(env.CODEX_HOME || join(homedir(), ".codex"), "config.toml"), "utf8");
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
return "no";
|
|
316
|
+
}
|
|
317
|
+
const top = text.split(/^\s*\[/m)[0] ?? "";
|
|
318
|
+
const provider = (body) => /^\s*model_provider\s*=\s*"([^"]+)"/m.exec(body)?.[1] ?? null;
|
|
319
|
+
const own = (p) => (p ? (p !== "openai" ? "yes" : "no") : null);
|
|
320
|
+
const selected = /^\s*profile\s*=\s*"([^"]+)"/m.exec(top)?.[1];
|
|
321
|
+
if (selected) {
|
|
322
|
+
const name = selected.replace(/[.*+?^$()|[\]\\{}]/g, "\\$&");
|
|
323
|
+
const at = text.search(new RegExp(`^\\s*\\[profiles\\.(?:"${name}"|${name})\\]\\s*$`, "m"));
|
|
324
|
+
if (at < 0)
|
|
325
|
+
return "unknown";
|
|
326
|
+
const body = text.slice(at).split(/^\s*\[/m)[1] ?? "";
|
|
327
|
+
return own(provider(body)) ?? own(provider(top)) ?? "no";
|
|
328
|
+
}
|
|
329
|
+
return own(provider(top)) ?? "no";
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Where each CLI keeps its login (the same paths usage/providers.ts reads). Presence is all that is checked offline:
|
|
333
|
+
* a stored login that has since expired still reads as signed in until the CLI says otherwise.
|
|
334
|
+
*/
|
|
335
|
+
export const OFFLINE_LOGINS = {
|
|
336
|
+
// macOS keeps Claude's login in the Keychain, which we do not open: there, no file is not proof.
|
|
337
|
+
// The config dir claude itself reads (claudeConfigDirFor): CLAUDE_CONFIG_DIR, else ~/.claude (#2078 review).
|
|
338
|
+
"claude-code": { files: (env, home) => [join(env.CLAUDE_CONFIG_DIR?.trim() || join(home, ".claude"), ".credentials.json")], keys: ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN"],
|
|
339
|
+
absent: (platform) => platform === "darwin" ? "unknown" : "invalid" },
|
|
340
|
+
codex: { files: (env, home) => [join(env.CODEX_HOME || join(home, ".codex"), "auth.json")], keys: ["OPENAI_API_KEY"], absent: () => "invalid" },
|
|
341
|
+
// #1792: `grok models` exits 0 signed out, and calls xAI — the file is the only offline truth.
|
|
342
|
+
grok: { files: (env, home) => [join(env.GROK_HOME || join(home, ".grok"), "auth.json")], keys: ["XAI_API_KEY", "GROK_API_KEY"], absent: () => "invalid" },
|
|
343
|
+
antigravity: { files: (env, home) => [join(env.GEMINI_HOME || join(home, ".gemini"), "antigravity-cli", "antigravity-oauth-token")], absent: () => "invalid" },
|
|
344
|
+
// kiro keeps data.sqlite3 after a sign-out, so its presence proves only that kiro was used here, not a live login:
|
|
345
|
+
// it can read "signed in" for a signed-out kiro (fail open — never the other way).
|
|
346
|
+
"kiro-cli": { files: (env, home) => [join(env.KIRO_CLI_HOME || join(home, ".local", "share", "kiro-cli"), "data.sqlite3")], absent: () => "invalid" },
|
|
347
|
+
// OpenCode reads many providers' keys from the environment: no file is not proof.
|
|
348
|
+
opencode: { files: (env, home) => [join(env.XDG_DATA_HOME || join(home, ".local", "share"), "opencode", "auth.json")], absent: () => "unknown" },
|
|
349
|
+
};
|
|
350
|
+
/** The default login's state, from files and variables only. */
|
|
351
|
+
export async function probeOfflineAuth(backend, env = process.env, home = homedir()) {
|
|
352
|
+
if (backend === "codex") {
|
|
353
|
+
const own = await codexUsesOwnProvider(env);
|
|
354
|
+
if (own === "yes")
|
|
355
|
+
return "not_required";
|
|
356
|
+
if (own === "unknown")
|
|
357
|
+
return "unknown";
|
|
358
|
+
}
|
|
359
|
+
const login = OFFLINE_LOGINS[backend];
|
|
360
|
+
if (!login)
|
|
361
|
+
return "unknown";
|
|
362
|
+
if (login.keys?.some(k => (env[k] ?? "").trim()))
|
|
363
|
+
return "valid";
|
|
364
|
+
for (const file of login.files(env, home)) {
|
|
365
|
+
try {
|
|
366
|
+
if ((await stat(file)).size > 0)
|
|
367
|
+
return "valid";
|
|
368
|
+
}
|
|
369
|
+
catch { /* next */ }
|
|
370
|
+
}
|
|
371
|
+
return login.absent(process.platform);
|
|
372
|
+
}
|
|
373
|
+
/** mtime and size of the binary and the login files: the probe runs a CLI again only when this changes. */
|
|
374
|
+
export async function availabilitySignature(backend, path, env = process.env, home = homedir()) {
|
|
375
|
+
const parts = [];
|
|
376
|
+
for (const file of [path, ...(OFFLINE_LOGINS[backend]?.files(env, home) ?? [])]) {
|
|
377
|
+
try {
|
|
378
|
+
const st = await stat(file);
|
|
379
|
+
parts.push(`${file}:${st.mtimeMs}:${st.size}`);
|
|
380
|
+
}
|
|
381
|
+
catch {
|
|
382
|
+
parts.push(`${file}:-`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
for (const k of OFFLINE_LOGINS[backend]?.keys ?? [])
|
|
386
|
+
parts.push(`${k}:${env[k] ? 1 : 0}`);
|
|
387
|
+
return parts.join("|");
|
|
388
|
+
}
|
|
389
|
+
/** The host's probes. */
|
|
390
|
+
export const hostAvailabilityProbes = {
|
|
391
|
+
resolve: resolveBackendBinary,
|
|
392
|
+
version: probeBackendVersion,
|
|
393
|
+
auth: (backend) => probeOfflineAuth(backend),
|
|
394
|
+
signature: (backend, path) => availabilitySignature(backend, path),
|
|
395
|
+
};
|
|
396
|
+
//# sourceMappingURL=backend-availability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-availability.js","sourceRoot":"","sources":["../src/backend-availability.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* the web chat only present it (fleet-manager.ts, web-commands.ts).
|
|
13
13
|
*/
|
|
14
14
|
import type { ModelOption } from "./backend/types.js";
|
|
15
|
+
import type { AvailabilityState } from "./backend-availability.js";
|
|
15
16
|
/** The word that picks the inherited value of a model or an effort, in the typed form and in the menus. */
|
|
16
17
|
export declare const BACKEND_DEFAULT = "default";
|
|
17
18
|
export interface BackendCommandDeps {
|
|
@@ -19,8 +20,15 @@ export interface BackendCommandDeps {
|
|
|
19
20
|
currentBackend(instance: string): string;
|
|
20
21
|
/** What the instance runs on now, as a reply shows it: "claude-code · opus". */
|
|
21
22
|
currentDisplay(instance: string): string;
|
|
22
|
-
/**
|
|
23
|
-
|
|
23
|
+
/**
|
|
24
|
+
* #2072: every backend of the catalog (never removed or test-only ones) with what this host's published snapshot says
|
|
25
|
+
* about it — installed, signed in, new enough. Read only; never probes.
|
|
26
|
+
*/
|
|
27
|
+
availability(): Array<{
|
|
28
|
+
backend: string;
|
|
29
|
+
state: AvailabilityState;
|
|
30
|
+
minVersion?: string | null;
|
|
31
|
+
}>;
|
|
24
32
|
/** The models `/model` would offer on that backend; empty when none are known. */
|
|
25
33
|
models(backend: string): Promise<ModelOption[]>;
|
|
26
34
|
/** A name the backend accepts beyond its list (claude-code's aliases and account catalog). */
|
|
@@ -45,11 +53,21 @@ export interface BackendPlan {
|
|
|
45
53
|
model: string | null;
|
|
46
54
|
effort: string | null;
|
|
47
55
|
}
|
|
48
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* One choice of a step. `token` is the argument it adds; `label` what the button says. `disabled`: why it cannot be
|
|
58
|
+
* chosen here (shown, not hidden — a surface that cannot disable an option shows the reason and the step refuses it).
|
|
59
|
+
*/
|
|
49
60
|
export interface BackendChoice {
|
|
50
61
|
token: string;
|
|
51
62
|
label: string;
|
|
63
|
+
disabled?: string;
|
|
52
64
|
}
|
|
65
|
+
/** Why a backend cannot be chosen, or null when it can (usable, or unknown: checked again when applied). */
|
|
66
|
+
export declare function backendUnusable(t: BackendCommandDeps["t"], row: {
|
|
67
|
+
backend: string;
|
|
68
|
+
state: AvailabilityState;
|
|
69
|
+
minVersion?: string | null;
|
|
70
|
+
}): string | null;
|
|
53
71
|
export type BackendStep = {
|
|
54
72
|
kind: "choose";
|
|
55
73
|
step: "backend" | "model" | "effort";
|
package/dist/backend-command.js
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
export const BACKEND_DEFAULT = "default";
|
|
3
3
|
/** The most choices one step offers: a Discord select menu's 25, less "default". */
|
|
4
4
|
const MAX_MODEL_CHOICES = 24;
|
|
5
|
+
/** Why a backend cannot be chosen, or null when it can (usable, or unknown: checked again when applied). */
|
|
6
|
+
export function backendUnusable(t, row) {
|
|
7
|
+
switch (row.state) {
|
|
8
|
+
case "not_installed": return t("backend.reason_not_installed");
|
|
9
|
+
case "not_signed_in": return t("backend.reason_not_signed_in");
|
|
10
|
+
case "too_old": return t("backend.reason_too_old", row.minVersion ?? "?");
|
|
11
|
+
default: return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
5
14
|
/** A chosen model or effort as a reply says it; `null` is the inherited one, named. */
|
|
6
15
|
function shown(deps, key, value) {
|
|
7
16
|
if (value !== null)
|
|
@@ -40,18 +49,28 @@ export async function backendStep(deps, instance, args) {
|
|
|
40
49
|
if (args.length > 3)
|
|
41
50
|
return { kind: "refuse", text: t("backend.usage") };
|
|
42
51
|
const from = deps.currentBackend(instance);
|
|
43
|
-
const
|
|
52
|
+
const rows = deps.availability();
|
|
53
|
+
// The instance's own backend is never shown as unusable: a failed or stale probe must not disable it (fail open).
|
|
54
|
+
const why = (row) => (row.backend === from ? null : backendUnusable(t, row));
|
|
44
55
|
if (args.length === 0) {
|
|
45
56
|
return {
|
|
46
57
|
kind: "choose", step: "backend", args: [], current: from,
|
|
47
58
|
text: t("backend.menu", deps.currentDisplay(instance)),
|
|
48
|
-
choices:
|
|
59
|
+
choices: rows.map(row => {
|
|
60
|
+
const reason = why(row);
|
|
61
|
+
const label = row.backend === from ? `✓ ${row.backend}` : row.state === "unknown" ? `${row.backend} — ${t("backend.reason_unchecked")}` : row.backend;
|
|
62
|
+
return reason ? { token: row.backend, label: `${row.backend} — ${reason}`, disabled: reason } : { token: row.backend, label };
|
|
63
|
+
}),
|
|
49
64
|
};
|
|
50
65
|
}
|
|
51
66
|
const backend = args[0].toLowerCase();
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
const row = rows.find(r => r.backend === backend);
|
|
68
|
+
if (!row) {
|
|
69
|
+
return { kind: "refuse", text: t("backend.unknown_backend", args[0], rows.map(r => r.backend).join(", ") || "—") };
|
|
54
70
|
}
|
|
71
|
+
const reason = why(row);
|
|
72
|
+
if (reason)
|
|
73
|
+
return { kind: "refuse", text: t("backend.unusable", backend, reason) };
|
|
55
74
|
// The same backend is not a switch: nothing to restart for. A model or effort on it is /model's and /effort's job.
|
|
56
75
|
if (backend === from)
|
|
57
76
|
return { kind: "refuse", text: t("backend.same", instance, backend), noop: true };
|