@songsid/agend 2.2.0-beta.2 → 2.2.0-beta.20
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/README.md +40 -24
- package/README.zh-TW.md +40 -24
- package/dist/agent-cli-instructions.md +6 -2
- package/dist/agent-cli.js +15 -7
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.js +3 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-whats-new.js +16 -4
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/auth-api.d.ts +3 -1
- package/dist/auth-api.js +17 -1
- package/dist/auth-api.js.map +1 -1
- package/dist/backend/antigravity.d.ts +33 -0
- package/dist/backend/antigravity.js +126 -18
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-carry.d.ts +22 -0
- package/dist/backend/claude-carry.js +170 -0
- package/dist/backend/claude-carry.js.map +1 -0
- package/dist/backend/claude-code.d.ts +65 -2
- package/dist/backend/claude-code.js +226 -33
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex-metadata.d.ts +33 -0
- package/dist/backend/codex-metadata.js +122 -18
- package/dist/backend/codex-metadata.js.map +1 -1
- package/dist/backend/codex.d.ts +3 -0
- package/dist/backend/codex.js +17 -1
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/credential-profile.d.ts +40 -3
- package/dist/backend/credential-profile.js +113 -5
- package/dist/backend/credential-profile.js.map +1 -1
- package/dist/backend/effort-metadata.d.ts +37 -1
- package/dist/backend/effort-metadata.js +86 -15
- package/dist/backend/effort-metadata.js.map +1 -1
- package/dist/backend/grok.d.ts +4 -0
- package/dist/backend/grok.js +14 -0
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro.d.ts +27 -1
- package/dist/backend/kiro.js +63 -10
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/launch-effort.d.ts +61 -0
- package/dist/backend/launch-effort.js +170 -0
- package/dist/backend/launch-effort.js.map +1 -0
- package/dist/backend/muse.d.ts +84 -0
- package/dist/backend/muse.js +449 -53
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/types.d.ts +48 -2
- package/dist/backend/types.js +12 -1
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-command.d.ts +91 -0
- package/dist/backend-command.js +122 -0
- package/dist/backend-command.js.map +1 -0
- package/dist/background-work-ended.d.ts +18 -0
- package/dist/background-work-ended.js +30 -0
- package/dist/background-work-ended.js.map +1 -0
- package/dist/cache-service.d.ts +2 -0
- package/dist/cache-service.js +2 -1
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +26 -1
- package/dist/channel/adapters/discord.js +103 -3
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +35 -3
- package/dist/channel/adapters/telegram.js +122 -23
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-tools.js +5 -3
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/message-edit-errors.d.ts +5 -0
- package/dist/channel/message-edit-errors.js +24 -0
- package/dist/channel/message-edit-errors.js.map +1 -0
- package/dist/channel/telegram-markdown.d.ts +6 -0
- package/dist/channel/telegram-markdown.js +104 -0
- package/dist/channel/telegram-markdown.js.map +1 -0
- package/dist/channel/tool-router.d.ts +2 -0
- package/dist/channel/tool-router.js +6 -5
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/channel/types.d.ts +46 -4
- package/dist/cli.js +184 -34
- package/dist/cli.js.map +1 -1
- package/dist/command-table.d.ts +2 -2
- package/dist/command-table.js +5 -2
- package/dist/command-table.js.map +1 -1
- package/dist/compact-watch.d.ts +86 -0
- package/dist/compact-watch.js +288 -0
- package/dist/compact-watch.js.map +1 -0
- package/dist/config-validator.js +55 -5
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/cross-instance-envelope.js +2 -0
- package/dist/cross-instance-envelope.js.map +1 -1
- package/dist/daemon.d.ts +129 -1
- package/dist/daemon.js +754 -94
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-outbox.d.ts +64 -8
- package/dist/delivery-outbox.js +315 -24
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/delivery-reconciliation.d.ts +18 -1
- package/dist/delivery-reconciliation.js +67 -2
- package/dist/delivery-reconciliation.js.map +1 -1
- package/dist/doctor.js +7 -0
- package/dist/doctor.js.map +1 -1
- package/dist/fleet-context.d.ts +12 -1
- package/dist/fleet-manager.d.ts +392 -19
- package/dist/fleet-manager.js +2030 -275
- package/dist/fleet-manager.js.map +1 -1
- package/dist/forged-envelope-scan.d.ts +4 -3
- package/dist/forged-envelope-scan.js +4 -3
- package/dist/forged-envelope-scan.js.map +1 -1
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +84 -16
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +16 -1
- package/dist/general-knowledge/skills/model-discovery/SKILL.md +4 -1
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +4 -0
- package/dist/host-memory.d.ts +10 -0
- package/dist/host-memory.js +33 -1
- package/dist/host-memory.js.map +1 -1
- package/dist/human-delivery-receipts.d.ts +83 -0
- package/dist/human-delivery-receipts.js +194 -0
- package/dist/human-delivery-receipts.js.map +1 -0
- package/dist/install-lock.d.ts +18 -1
- package/dist/install-lock.js +30 -3
- package/dist/install-lock.js.map +1 -1
- package/dist/instance-avatar.d.ts +5 -4
- package/dist/instance-avatar.js +12 -8
- package/dist/instance-avatar.js.map +1 -1
- package/dist/instance-config-impact.js +1 -0
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +25 -6
- package/dist/instance-lifecycle.js +76 -27
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +1 -1
- package/dist/instructions.js +3 -3
- package/dist/instructions.js.map +1 -1
- package/dist/kiro-compact-pane.d.ts +38 -0
- package/dist/kiro-compact-pane.js +57 -0
- package/dist/kiro-compact-pane.js.map +1 -0
- package/dist/kiro-log-gate.d.ts +42 -0
- package/dist/kiro-log-gate.js +39 -0
- package/dist/kiro-log-gate.js.map +1 -0
- package/dist/launchd-handoff.d.ts +43 -0
- package/dist/launchd-handoff.js +56 -0
- package/dist/launchd-handoff.js.map +1 -0
- package/dist/locale.js +268 -42
- package/dist/locale.js.map +1 -1
- package/dist/log-service.d.ts +99 -0
- package/dist/log-service.js +243 -0
- package/dist/log-service.js.map +1 -0
- package/dist/log-steps.d.ts +169 -0
- package/dist/log-steps.js +858 -0
- package/dist/log-steps.js.map +1 -0
- package/dist/login-controller.d.ts +20 -3
- package/dist/login-controller.js +71 -19
- package/dist/login-controller.js.map +1 -1
- package/dist/login-flows.d.ts +5 -2
- package/dist/login-flows.js +5 -4
- package/dist/login-flows.js.map +1 -1
- package/dist/login-shell.d.ts +21 -0
- package/dist/login-shell.js +98 -0
- package/dist/login-shell.js.map +1 -0
- package/dist/memory-pressure.d.ts +13 -1
- package/dist/memory-pressure.js +50 -10
- package/dist/memory-pressure.js.map +1 -1
- package/dist/needs-you-hub.js +2 -0
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you-live.d.ts +6 -0
- package/dist/needs-you-live.js +23 -3
- package/dist/needs-you-live.js.map +1 -1
- package/dist/outbound-handlers.d.ts +100 -0
- package/dist/outbound-handlers.js +277 -93
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +30 -15
- package/dist/outbound-schemas.js +23 -5
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/provider-probe.d.ts +29 -0
- package/dist/provider-probe.js +198 -2
- package/dist/provider-probe.js.map +1 -1
- package/dist/public-link-progress.d.ts +1 -1
- package/dist/public-link-progress.js +8 -2
- package/dist/public-link-progress.js.map +1 -1
- package/dist/public-preview.d.ts +101 -0
- package/dist/public-preview.js +236 -0
- package/dist/public-preview.js.map +1 -0
- package/dist/public-web-gateway.d.ts +2 -0
- package/dist/public-web-gateway.js +20 -6
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +24 -1
- package/dist/public-web-link.js +63 -9
- package/dist/public-web-link.js.map +1 -1
- package/dist/quickstart-api.d.ts +1 -1
- package/dist/quickstart-api.js +8 -6
- package/dist/quickstart-api.js.map +1 -1
- package/dist/quickstart.d.ts +12 -0
- package/dist/quickstart.js +36 -6
- package/dist/quickstart.js.map +1 -1
- package/dist/reply-buttons-controller.d.ts +89 -5
- package/dist/reply-buttons-controller.js +273 -8
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/reply-buttons.d.ts +48 -3
- package/dist/reply-buttons.js +105 -10
- package/dist/reply-buttons.js.map +1 -1
- package/dist/reply-polls.d.ts +85 -0
- package/dist/reply-polls.js +154 -0
- package/dist/reply-polls.js.map +1 -0
- package/dist/restart-guard.d.ts +6 -3
- package/dist/restart-guard.js +6 -3
- package/dist/restart-guard.js.map +1 -1
- package/dist/restart-progress.d.ts +33 -2
- package/dist/restart-progress.js +30 -2
- package/dist/restart-progress.js.map +1 -1
- package/dist/sd-notify.d.ts +22 -1
- package/dist/sd-notify.js +63 -10
- package/dist/sd-notify.js.map +1 -1
- package/dist/service-activation.d.ts +15 -7
- package/dist/service-activation.js +42 -26
- package/dist/service-activation.js.map +1 -1
- package/dist/service-installer.d.ts +55 -0
- package/dist/service-installer.js +90 -3
- package/dist/service-installer.js.map +1 -1
- package/dist/service-plan.d.ts +11 -0
- package/dist/service-plan.js +23 -0
- package/dist/service-plan.js.map +1 -1
- package/dist/settings-api.js +14 -4
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +4 -2
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-effect.js +2 -0
- package/dist/settings-effect.js.map +1 -1
- package/dist/spawn-gate.js +5 -1
- package/dist/spawn-gate.js.map +1 -1
- package/dist/spawn-hold-reply.d.ts +12 -0
- package/dist/spawn-hold-reply.js +39 -0
- package/dist/spawn-hold-reply.js.map +1 -0
- package/dist/systemd-peer-bus.d.ts +95 -0
- package/dist/systemd-peer-bus.js +430 -0
- package/dist/systemd-peer-bus.js.map +1 -0
- package/dist/systemd-runtime.d.ts +27 -1
- package/dist/systemd-runtime.js +69 -7
- package/dist/systemd-runtime.js.map +1 -1
- package/dist/tips.js +1 -1
- package/dist/tips.js.map +1 -1
- package/dist/tool-permissions.js +3 -3
- package/dist/tool-permissions.js.map +1 -1
- package/dist/tool-progress.js +3 -2
- package/dist/tool-progress.js.map +1 -1
- package/dist/topic-commands.d.ts +71 -4
- package/dist/topic-commands.js +167 -34
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-delta-reader.d.ts +3 -3
- package/dist/transcript-delta-reader.js +8 -8
- package/dist/transcript-delta-reader.js.map +1 -1
- package/dist/transcript-jsonl.d.ts +85 -3
- package/dist/transcript-jsonl.js +156 -13
- package/dist/transcript-jsonl.js.map +1 -1
- package/dist/transcript-monitor.d.ts +11 -0
- package/dist/transcript-monitor.js +61 -13
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-sources.d.ts +24 -0
- package/dist/transcript-sources.js +211 -56
- package/dist/transcript-sources.js.map +1 -1
- package/dist/tunnel/cloudflared.d.ts +7 -15
- package/dist/tunnel/cloudflared.js +36 -1
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/purpose-lane.d.ts +5 -1
- package/dist/tunnel/purpose-lane.js +14 -7
- package/dist/tunnel/purpose-lane.js.map +1 -1
- package/dist/tunnel/types.d.ts +5 -1
- package/dist/tunnel/types.js.map +1 -1
- package/dist/turn-resume.d.ts +2 -0
- package/dist/turn-resume.js +1 -1
- package/dist/turn-resume.js.map +1 -1
- package/dist/types.d.ts +22 -0
- package/dist/ui/chat-commands.js +1 -0
- package/dist/ui/chat-mentions.js +63 -0
- package/dist/ui/chat-render.js +80 -10
- package/dist/ui/chat-store.js +70 -6
- package/dist/ui/chat-strings.js +62 -32
- package/dist/ui/chat-thread.js +199 -24
- package/dist/ui/chat-time.js +80 -0
- package/dist/ui/chat-tour.js +17 -14
- package/dist/ui/panel-chat.js +45 -21
- package/dist/ui/panel-details.js +2 -0
- package/dist/ui/panel-fleet.js +213 -58
- package/dist/ui/panel-log.js +428 -0
- package/dist/ui/panel-needs.js +14 -10
- package/dist/ui/panel-settings.js +82 -17
- package/dist/ui/preview-panel.js +55 -15
- package/dist/ui/preview-status.js +28 -0
- package/dist/ui/preview.js +44 -3
- package/dist/ui/settings-dialogs.js +11 -6
- package/dist/ui/settings-model.js +3 -1
- package/dist/ui/settings-strings.js +32 -12
- package/dist/ui/settings-token.js +8 -1
- package/dist/ui/settings-wizard.js +5 -3
- package/dist/ui/shared/app-i18n.js +41 -15
- package/dist/ui/shared/app-prefs.js +250 -0
- package/dist/ui/shared/app-route.js +6 -1
- package/dist/ui/shared/app-shell.js +165 -8
- package/dist/ui/shared/app-store.js +5 -1
- package/dist/ui/shared/app-stream.js +26 -5
- package/dist/ui/shared/app.css +170 -30
- package/dist/ui/shared/app.js +11 -1
- package/dist/ui/shared/fonts/README.md +1 -1
- package/dist/ui/shared/header-tools.js +83 -13
- package/dist/ui/shared/instance-nav.js +178 -51
- package/dist/ui/shared/instance-switch.js +8 -5
- package/dist/ui/shared/panel-view.js +21 -4
- package/dist/ui/shared/signin.js +15 -9
- package/dist/ui/shared/theme.js +39 -7
- package/dist/ui/shared/tokens.css +1 -1
- package/dist/ui/shared/ui-icons.js +2 -0
- package/dist/ui/shared/usage-dialog.js +23 -5
- package/dist/ui/shared/view-strings.js +40 -4
- package/dist/ui/signin.html +8 -3
- package/dist/unrecognised-prompt.d.ts +23 -0
- package/dist/unrecognised-prompt.js +74 -0
- package/dist/unrecognised-prompt.js.map +1 -0
- package/dist/update-check.d.ts +31 -0
- package/dist/update-check.js +47 -0
- package/dist/update-check.js.map +1 -1
- package/dist/update-install.d.ts +13 -1
- package/dist/update-install.js +16 -4
- package/dist/update-install.js.map +1 -1
- package/dist/update-launch.d.ts +48 -1
- package/dist/update-launch.js +159 -5
- package/dist/update-launch.js.map +1 -1
- package/dist/update-marker.d.ts +51 -0
- package/dist/update-marker.js +61 -0
- package/dist/update-marker.js.map +1 -1
- package/dist/usage/i18n-keys.d.ts +1 -1
- package/dist/usage/i18n-keys.js +1 -1
- package/dist/usage/i18n-keys.js.map +1 -1
- package/dist/usage/providers.d.ts +62 -13
- package/dist/usage/providers.js +256 -68
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/statusline-usage.d.ts +6 -2
- package/dist/usage/statusline-usage.js +10 -4
- package/dist/usage/statusline-usage.js.map +1 -1
- package/dist/view-api.js +31 -9
- package/dist/view-api.js.map +1 -1
- package/dist/web-api.d.ts +82 -4
- package/dist/web-api.js +632 -88
- package/dist/web-api.js.map +1 -1
- package/dist/web-auth.js +5 -2
- package/dist/web-auth.js.map +1 -1
- package/dist/web-chat-history.d.ts +26 -1
- package/dist/web-chat-history.js +47 -8
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +41 -5
- package/dist/web-commands.js +25 -7
- package/dist/web-commands.js.map +1 -1
- package/dist/web-login.d.ts +14 -0
- package/dist/web-login.js +4 -2
- package/dist/web-login.js.map +1 -1
- package/dist/web-mentions.d.ts +44 -0
- package/dist/web-mentions.js +75 -0
- package/dist/web-mentions.js.map +1 -0
- package/dist/web-prefs.d.ts +81 -0
- package/dist/web-prefs.js +297 -0
- package/dist/web-prefs.js.map +1 -0
- package/dist/web-preview.d.ts +14 -1
- package/dist/web-preview.js +35 -13
- package/dist/web-preview.js.map +1 -1
- package/dist/web-profile.d.ts +32 -0
- package/dist/web-profile.js +132 -0
- package/dist/web-profile.js.map +1 -0
- package/dist/web-reply-files.d.ts +45 -0
- package/dist/web-reply-files.js +223 -0
- package/dist/web-reply-files.js.map +1 -0
- package/dist/web-schedules.d.ts +12 -0
- package/dist/web-schedules.js +34 -0
- package/dist/web-schedules.js.map +1 -0
- package/dist/web-server-drain.d.ts +10 -0
- package/dist/web-server-drain.js +50 -0
- package/dist/web-server-drain.js.map +1 -0
- package/dist/web-session.d.ts +14 -0
- package/dist/web-session.js +11 -1
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +3 -1
- package/dist/web-settings-patch.js +4 -1
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-shell-routes.d.ts +4 -0
- package/dist/web-shell-routes.js +9 -0
- package/dist/web-shell-routes.js.map +1 -1
- package/dist/web-upload.d.ts +135 -7
- package/dist/web-upload.js +315 -51
- package/dist/web-upload.js.map +1 -1
- package/launcher/install-admission.cjs +61 -6
- package/package.json +3 -3
- package/templates/launchd.plist.ejs +3 -1
- package/templates/systemd.service.ejs +2 -1
package/dist/topic-commands.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { PaneContextCache } from "./pane-context-cache.js";
|
|
2
|
+
import { LOGIN_BACKEND_ALIASES } from "./login-flows.js";
|
|
2
3
|
import { measureSyncWork } from "./sync-work-attribution.js";
|
|
3
4
|
import { LOOPBACK_HOST_NAMES } from "./web-host-guard.js";
|
|
4
5
|
import { WEB_REMOTE_DOCS_URL } from "./upgrade-notices.js";
|
|
5
|
-
import { readFileSync, existsSync } from "node:fs";
|
|
6
|
+
import { closeSync, readFileSync, existsSync } from "node:fs";
|
|
6
7
|
import { exec, execFileSync } from "node:child_process";
|
|
7
8
|
import { promisify } from "node:util";
|
|
8
9
|
import { join, basename } from "node:path";
|
|
@@ -20,10 +21,11 @@ import { runVisibilityCommand } from "./cross-instance-notice.js";
|
|
|
20
21
|
import { clampContextPercent, parseContextPercent, parseTokenContextRatio, } from "./context-percent.js";
|
|
21
22
|
import { isGeneralInstance } from "./general-instance.js";
|
|
22
23
|
import { instanceSupportsSteer } from "./steer-capability.js";
|
|
24
|
+
import { compareSemver } from "./update-check.js";
|
|
23
25
|
import { SYSINFO_BACKEND_IDS } from "./backend/types.js";
|
|
24
26
|
import { recordInternalRequest, withOrigin } from "./fleet-control-audit.js";
|
|
25
27
|
import { resolveInstalledAgend } from "./update-dispatch.js";
|
|
26
|
-
import { resolveUpdateLaunch, watchUpdateLaunch } from "./update-launch.js";
|
|
28
|
+
import { resolveUpdateLaunch, openUpdateLog, updateLogPath, watchUpdateLaunch } from "./update-launch.js";
|
|
27
29
|
import { selfCommand } from "./cli-entry.js";
|
|
28
30
|
export { parseContextPercent, parseTokenContextRatio } from "./context-percent.js";
|
|
29
31
|
/** Longest one setMyCommands call may take. */
|
|
@@ -159,6 +161,54 @@ function disambiguateLabel(name, explicit, base, used) {
|
|
|
159
161
|
}
|
|
160
162
|
/** Allowed filename for /save and /load (no path separators, no shell/inject chars). */
|
|
161
163
|
export const SAVE_FILENAME_RE = /^[\w.-]+$/;
|
|
164
|
+
/**
|
|
165
|
+
* #1809: resolve a display label (as shown by `agend ls`) back to a real instance name.
|
|
166
|
+
* Returns the real name on a unique match, `null` when the query does not match any label,
|
|
167
|
+
* or `{ ambiguous: true, realNames }` when two labels are identical under case-folding
|
|
168
|
+
* (e.g. display_names "Prism" and "prism" both fold to "prism").
|
|
169
|
+
* Always case-insensitive. Real names are NOT resolved here — callers must try real names first.
|
|
170
|
+
*/
|
|
171
|
+
export function resolveByLabel(query, entries) {
|
|
172
|
+
const labelMap = assignDisplayLabels(entries);
|
|
173
|
+
const q = query.toLowerCase();
|
|
174
|
+
const matches = [];
|
|
175
|
+
for (const [realName, label] of labelMap) {
|
|
176
|
+
if (label.toLowerCase() === q)
|
|
177
|
+
matches.push(realName);
|
|
178
|
+
}
|
|
179
|
+
if (matches.length === 0)
|
|
180
|
+
return null;
|
|
181
|
+
if (matches.length === 1)
|
|
182
|
+
return matches[0];
|
|
183
|
+
return { ambiguous: true, realNames: matches };
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* #1809: full label/name resolution pipeline without process.exit or readline — suitable for
|
|
187
|
+
* unit testing and for callers that want to decide what to do on each outcome.
|
|
188
|
+
*
|
|
189
|
+
* Resolution order:
|
|
190
|
+
* 1. Exact match on real name (case-insensitive) — always wins.
|
|
191
|
+
* 2. Exact match on the display label `agend ls` shows (via `resolveByLabel`).
|
|
192
|
+
* 3. No match → `{ kind: "none" }`.
|
|
193
|
+
*
|
|
194
|
+
* Returns `{ kind: "name", realName }` on success,
|
|
195
|
+
* `{ kind: "ambiguous", realNames }` when two labels are case-identical,
|
|
196
|
+
* or `{ kind: "none" }` when nothing matched.
|
|
197
|
+
*/
|
|
198
|
+
export function resolveName(query, entries) {
|
|
199
|
+
// Step 1: exact real-name match wins.
|
|
200
|
+
const q = query.toLowerCase();
|
|
201
|
+
const exactReal = entries.find(e => e.name.toLowerCase() === q);
|
|
202
|
+
if (exactReal)
|
|
203
|
+
return { kind: "name", realName: exactReal.name };
|
|
204
|
+
// Step 2: label match.
|
|
205
|
+
const labelResult = resolveByLabel(query, entries);
|
|
206
|
+
if (labelResult === null)
|
|
207
|
+
return { kind: "none" };
|
|
208
|
+
if (typeof labelResult === "string")
|
|
209
|
+
return { kind: "name", realName: labelResult };
|
|
210
|
+
return { kind: "ambiguous", realNames: labelResult.realNames };
|
|
211
|
+
}
|
|
162
212
|
/** Backends with a native side-question command that does not steer the active turn. */
|
|
163
213
|
export const BTW_SUPPORTED_BACKENDS = new Set(["claude-code"]);
|
|
164
214
|
/**
|
|
@@ -240,10 +290,18 @@ function backendCliLines(versions) {
|
|
|
240
290
|
}),
|
|
241
291
|
];
|
|
242
292
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
293
|
+
/**
|
|
294
|
+
* Board 0340ec89: agy's own `/compact` summarizes the conversation (verified on 1.3.6: "Conversation compacted · 5 steps
|
|
295
|
+
* summarized", tests/fixtures/agy-1.3.6-compact.pane.txt). AgEnD used to send `/clear` for an agy compact, which wiped
|
|
296
|
+
* the conversation instead. An agy known to be older than the version `/compact` was verified on is refused (null),
|
|
297
|
+
* never cleared; an agy whose version is not known yet gets `/compact` (a version without it ignores the line).
|
|
298
|
+
*/
|
|
299
|
+
export const AGY_COMPACT_MIN_VERSION = "1.3.6";
|
|
300
|
+
export function compactCommandForBackend(backend, version) {
|
|
301
|
+
if (backend !== "antigravity")
|
|
302
|
+
return "/compact";
|
|
303
|
+
const v = typeof version === "string" ? version.match(/\d+\.\d+\.\d+/)?.[0] : undefined;
|
|
304
|
+
return v && (compareSemver(v, AGY_COMPACT_MIN_VERSION) ?? 0) < 0 ? null : "/compact";
|
|
247
305
|
}
|
|
248
306
|
/**
|
|
249
307
|
* Backends whose `/compact` verifiably takes custom summarization instructions
|
|
@@ -255,7 +313,7 @@ export function compactCommandForBackend(backend) {
|
|
|
255
313
|
* compact into a prompt, so it must never be appended.
|
|
256
314
|
* - grok 1.0.46: the binary answers "/compact takes no arguments."
|
|
257
315
|
* - opencode 1.18: `/compact` calls session.summarize with no text.
|
|
258
|
-
* - kiro-cli: takes none (audit); antigravity
|
|
316
|
+
* - kiro-cli: takes none (audit); antigravity's own /compact (1.3.6+, board 0340ec89) takes none either.
|
|
259
317
|
* - muse 1.4.2: accepts the line (empty session: "nothing to summarize") but
|
|
260
318
|
* no use of the text is verifiable — unsupported until shown otherwise.
|
|
261
319
|
*/
|
|
@@ -446,6 +504,7 @@ const INSTANCE_FORMS = [
|
|
|
446
504
|
["collab", bare("collab")],
|
|
447
505
|
["effort", withArgs("effort")],
|
|
448
506
|
["model", withArgs("model")],
|
|
507
|
+
["backend", withArgs("backend")],
|
|
449
508
|
["compact", text => parseCompactCommand(text) !== null],
|
|
450
509
|
["steer", withArgs("steer")],
|
|
451
510
|
["btw", withArgs("btw")],
|
|
@@ -488,8 +547,15 @@ export class TopicCommands {
|
|
|
488
547
|
}, "telegram");
|
|
489
548
|
if (decision.allow || "passthrough" in decision)
|
|
490
549
|
return null;
|
|
550
|
+
// A command off for want of fleet admins names where they go (`{0}` in its disabled reply).
|
|
551
|
+
if (decision.reply === spec.disabled)
|
|
552
|
+
return [...decision.reply, this.adminListKey(msg.adapterId)];
|
|
491
553
|
return decision.reply;
|
|
492
554
|
}
|
|
555
|
+
/** Where the adapter's fleet-admin list is in fleet.yaml (the fleet's answer; a bare key without it). */
|
|
556
|
+
adminListKey(adapterId) {
|
|
557
|
+
return this.ctx.adminListKey?.(adapterId) ?? "access.allowed_users";
|
|
558
|
+
}
|
|
493
559
|
async sendRefusal(msg, [key, ...args]) {
|
|
494
560
|
const adapter = this.getReplyAdapter(msg);
|
|
495
561
|
if (adapter)
|
|
@@ -595,6 +661,13 @@ export class TopicCommands {
|
|
|
595
661
|
}
|
|
596
662
|
return false;
|
|
597
663
|
}
|
|
664
|
+
/**
|
|
665
|
+
* General's action-first menu. The click owns private issuance; no URL or code exists in this copy.
|
|
666
|
+
*/
|
|
667
|
+
getDashboardMenuText() {
|
|
668
|
+
const access = this.ctx.getDashboardAccess?.();
|
|
669
|
+
return access?.ready && access.token ? t("dashboard.menu_instruction") : t("dashboard.starting");
|
|
670
|
+
}
|
|
598
671
|
/**
|
|
599
672
|
* Pure, secret-free dashboard/menu copy. Issuance belongs to the private
|
|
600
673
|
* delivery action; rendering or previewing this text cannot retire a code.
|
|
@@ -632,7 +705,7 @@ export class TopicCommands {
|
|
|
632
705
|
const threadId = msg.threadId;
|
|
633
706
|
// The caller's own adapter decides, and an empty list means the command is off for everyone.
|
|
634
707
|
if (!this.ctx.hasFleetAdmins(msg.adapterId)) {
|
|
635
|
-
await adapter.sendText(chatId, t("dashboard.disabled"), { threadId });
|
|
708
|
+
await adapter.sendText(chatId, t("dashboard.disabled", this.adminListKey(msg.adapterId)), { threadId });
|
|
636
709
|
return;
|
|
637
710
|
}
|
|
638
711
|
if (!this.ctx.isFleetAdmin(msg.userId, msg.adapterId)) {
|
|
@@ -769,6 +842,23 @@ export class TopicCommands {
|
|
|
769
842
|
}
|
|
770
843
|
return true;
|
|
771
844
|
}
|
|
845
|
+
if (command === "backend") {
|
|
846
|
+
const adapter = this.getReplyAdapter(msg);
|
|
847
|
+
if (!adapter)
|
|
848
|
+
return false;
|
|
849
|
+
// #1806: the same gate as /model.
|
|
850
|
+
if (!this.ctx.isFleetAdmin(msg.userId, msg.adapterId)) {
|
|
851
|
+
await adapter.sendText(msg.chatId, t("permission.denied"), { threadId: msg.threadId });
|
|
852
|
+
return true;
|
|
853
|
+
}
|
|
854
|
+
if (this.ctx.runBackendCommand) {
|
|
855
|
+
await this.ctx.runBackendCommand(instanceName, text, msg.userId, msg.threadId ?? msg.chatId, adapter, msg.chatId, msg.threadId, msg.adapterId);
|
|
856
|
+
}
|
|
857
|
+
else {
|
|
858
|
+
await adapter.sendText(msg.chatId, t("backend.usage"), { threadId: msg.threadId });
|
|
859
|
+
}
|
|
860
|
+
return true;
|
|
861
|
+
}
|
|
772
862
|
if (command === "compact") {
|
|
773
863
|
const compact = parseCompactCommand(text);
|
|
774
864
|
const adapter = this.getReplyAdapter(msg);
|
|
@@ -989,6 +1079,14 @@ export class TopicCommands {
|
|
|
989
1079
|
}
|
|
990
1080
|
/** Send the backend-appropriate compact command to an instance's tmux pane */
|
|
991
1081
|
async sendCompact(instanceName, instructions) {
|
|
1082
|
+
return this.compactInstance(instanceName, instructions).text;
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* sendCompact, saying whether the command was handed to the daemon (the web chat follows a sent one to its end,
|
|
1086
|
+
* board 003648ac). `notify` runs only when it is about to be handed over; its id rides along so the daemon says when
|
|
1087
|
+
* the command reached the pane (`raw_paste_written`). A write the IPC refuses is not sent.
|
|
1088
|
+
*/
|
|
1089
|
+
compactInstance(instanceName, instructions, notify) {
|
|
992
1090
|
const ipc = this.ctx.instanceIpcClients.get(instanceName);
|
|
993
1091
|
if (ipc?.connected) {
|
|
994
1092
|
const classicBackend = this.ctx.classicChannels?.getChannelIdByInstance(instanceName)
|
|
@@ -997,26 +1095,34 @@ export class TopicCommands {
|
|
|
997
1095
|
const backend = this.ctx.fleetConfig?.instances[instanceName]?.backend
|
|
998
1096
|
?? classicBackend
|
|
999
1097
|
?? this.ctx.fleetConfig?.defaults?.backend ?? "claude-code";
|
|
1000
|
-
const
|
|
1098
|
+
const agyVersion = backend === "antigravity" ? this.ctx.getBackendCliVersionSnapshot?.()?.antigravity?.version ?? null : null;
|
|
1099
|
+
const base = compactCommandForBackend(backend, agyVersion);
|
|
1100
|
+
if (base === null)
|
|
1101
|
+
return { sent: false, text: t("compact.unsupported_version", backend, agyVersion ?? "?", AGY_COMPACT_MIN_VERSION) };
|
|
1001
1102
|
const custom = normalizeCompactInstructions(instructions);
|
|
1002
1103
|
if (custom.length > COMPACT_INSTRUCTIONS_MAX) {
|
|
1003
1104
|
// Refuse rather than cut: a truncated instruction is a different instruction.
|
|
1004
|
-
return t("compact.instructions_too_long", String(COMPACT_INSTRUCTIONS_MAX));
|
|
1105
|
+
return { sent: false, text: t("compact.instructions_too_long", String(COMPACT_INSTRUCTIONS_MAX)) };
|
|
1005
1106
|
}
|
|
1107
|
+
const id = notify?.() ?? null;
|
|
1108
|
+
const paste = (content) => ipc.send({ type: "raw_paste", content, ...(id ? { notify_written: id } : {}) }) !== false;
|
|
1006
1109
|
if (!custom) {
|
|
1007
|
-
|
|
1008
|
-
|
|
1110
|
+
if (!paste(base))
|
|
1111
|
+
return { sent: false, text: t("compact.not_connected") };
|
|
1112
|
+
return { sent: true, text: t("compact.sent", base) };
|
|
1009
1113
|
}
|
|
1010
1114
|
if (backendSupportsCompactInstructions(backend)) {
|
|
1011
|
-
|
|
1012
|
-
|
|
1115
|
+
if (!paste(`${base} ${custom}`))
|
|
1116
|
+
return { sent: false, text: t("compact.not_connected") };
|
|
1117
|
+
return { sent: true, text: t("compact.sent_with_instructions", base) };
|
|
1013
1118
|
}
|
|
1014
1119
|
// Compact as asked, without the text, and say so — never send it (codex
|
|
1015
1120
|
// would take it for a chat message) and never drop it unannounced.
|
|
1016
|
-
|
|
1017
|
-
|
|
1121
|
+
if (!paste(base))
|
|
1122
|
+
return { sent: false, text: t("compact.not_connected") };
|
|
1123
|
+
return { sent: true, text: `${t("compact.sent", base)}\n${t("compact.instructions_ignored", backend)}` };
|
|
1018
1124
|
}
|
|
1019
|
-
return t("compact.not_connected");
|
|
1125
|
+
return { sent: false, text: t("compact.not_connected") };
|
|
1020
1126
|
}
|
|
1021
1127
|
/** Whether the instance backend exposes a verified full-reset command. */
|
|
1022
1128
|
supportsClear(instanceName) {
|
|
@@ -1046,7 +1152,7 @@ export class TopicCommands {
|
|
|
1046
1152
|
const ipc = this.ctx.instanceIpcClients.get(instanceName);
|
|
1047
1153
|
if (!ipc?.connected)
|
|
1048
1154
|
return t("steer.not_connected");
|
|
1049
|
-
|
|
1155
|
+
const payload = {
|
|
1050
1156
|
type: "steer",
|
|
1051
1157
|
content,
|
|
1052
1158
|
delivery_epoch: this.ctx.getDeliveryEpoch?.(instanceName) ?? undefined,
|
|
@@ -1059,7 +1165,12 @@ export class TopicCommands {
|
|
|
1059
1165
|
adapter_id: msg.adapterId ?? "",
|
|
1060
1166
|
source: msg.source,
|
|
1061
1167
|
},
|
|
1062
|
-
}
|
|
1168
|
+
};
|
|
1169
|
+
const sent = this.ctx.sendHumanControl
|
|
1170
|
+
? this.ctx.sendHumanControl(instanceName, payload, msg.humanOrigin, msg.humanOriginalBody ?? content)
|
|
1171
|
+
: ipc.send(payload) !== false;
|
|
1172
|
+
if (!sent)
|
|
1173
|
+
return t("steer.not_connected");
|
|
1063
1174
|
return t("steer.sent", instanceName);
|
|
1064
1175
|
}
|
|
1065
1176
|
/** Ask a Claude Code side question without folding it into the active turn. */
|
|
@@ -1070,7 +1181,7 @@ export class TopicCommands {
|
|
|
1070
1181
|
const ipc = this.ctx.instanceIpcClients.get(instanceName);
|
|
1071
1182
|
if (!ipc?.connected)
|
|
1072
1183
|
return t("btw.not_connected");
|
|
1073
|
-
|
|
1184
|
+
const payload = {
|
|
1074
1185
|
type: "btw",
|
|
1075
1186
|
content,
|
|
1076
1187
|
delivery_epoch: this.ctx.getDeliveryEpoch?.(instanceName) ?? undefined,
|
|
@@ -1083,25 +1194,34 @@ export class TopicCommands {
|
|
|
1083
1194
|
adapter_id: msg.adapterId ?? "",
|
|
1084
1195
|
source: msg.source,
|
|
1085
1196
|
},
|
|
1086
|
-
}
|
|
1197
|
+
};
|
|
1198
|
+
const sent = this.ctx.sendHumanControl
|
|
1199
|
+
? this.ctx.sendHumanControl(instanceName, payload, msg.humanOrigin, msg.humanOriginalBody ?? content)
|
|
1200
|
+
: ipc.send(payload) !== false;
|
|
1201
|
+
if (!sent)
|
|
1202
|
+
return t("btw.not_connected");
|
|
1087
1203
|
return t("btw.sent", instanceName);
|
|
1088
1204
|
}
|
|
1089
1205
|
/** Send the backend-appropriate full conversation reset through raw_paste. */
|
|
1090
1206
|
async sendClear(instanceName) {
|
|
1207
|
+
return this.clearInstance(instanceName).text;
|
|
1208
|
+
}
|
|
1209
|
+
/** sendClear, saying whether the command was handed to the daemon (board 003648ac: the web chat's card then leaves). */
|
|
1210
|
+
clearInstance(instanceName) {
|
|
1091
1211
|
const backend = this.effectiveBackend(instanceName);
|
|
1092
1212
|
const cmd = clearCommandForBackend(backend);
|
|
1093
1213
|
if (!cmd)
|
|
1094
|
-
return t("clear.unsupported");
|
|
1214
|
+
return { sent: false, text: t("clear.unsupported") };
|
|
1095
1215
|
const ipc = this.ctx.instanceIpcClients.get(instanceName);
|
|
1096
1216
|
if (ipc?.connected) {
|
|
1097
|
-
ipc.send({
|
|
1217
|
+
const sent = ipc.send({
|
|
1098
1218
|
type: "raw_paste",
|
|
1099
1219
|
content: cmd,
|
|
1100
1220
|
...(backend === "kiro-cli" ? { confirm_clear: true } : {}),
|
|
1101
|
-
});
|
|
1102
|
-
return t("clear.sent", cmd);
|
|
1221
|
+
}) !== false;
|
|
1222
|
+
return sent ? { sent: true, text: t("clear.sent", cmd) } : { sent: false, text: t("clear.not_connected") };
|
|
1103
1223
|
}
|
|
1104
|
-
return t("clear.not_connected");
|
|
1224
|
+
return { sent: false, text: t("clear.not_connected") };
|
|
1105
1225
|
}
|
|
1106
1226
|
/** Send a backend-appropriate session-save command to a fleet-topic instance. */
|
|
1107
1227
|
async sendSave(instanceName, filename) {
|
|
@@ -1212,11 +1332,17 @@ export class TopicCommands {
|
|
|
1212
1332
|
await adapter.sendText(msg.chatId, await this.ctx.cancelLoginSession(), { threadId: msg.threadId });
|
|
1213
1333
|
return;
|
|
1214
1334
|
}
|
|
1215
|
-
|
|
1335
|
+
// `<backend> [profile]` (#1699 part 2): a second word is the credential profile to sign in; nothing more.
|
|
1336
|
+
const words = arg.split(/\s+/);
|
|
1337
|
+
// A profile only after a backend this fleet can sign in: `/login reinstall codex` stays a usage error (#1137).
|
|
1338
|
+
if (words.length > 2 || (words.length === 2 && !Object.hasOwn(LOGIN_BACKEND_ALIASES, words[0].toLowerCase()))) {
|
|
1216
1339
|
await adapter.sendText(msg.chatId, t("login.usage"), { threadId: msg.threadId });
|
|
1217
1340
|
return;
|
|
1218
1341
|
}
|
|
1219
|
-
const
|
|
1342
|
+
const [backend, profile] = words;
|
|
1343
|
+
const started = profile !== undefined
|
|
1344
|
+
? await this.ctx.startLoginSession(backend, chat, { profile })
|
|
1345
|
+
: await this.ctx.startLoginSession(backend, chat);
|
|
1220
1346
|
// null → the still-valid-auth confirmation prompt was posted instead.
|
|
1221
1347
|
if (started)
|
|
1222
1348
|
await adapter.sendText(msg.chatId, started, { threadId: msg.threadId });
|
|
@@ -1481,7 +1607,7 @@ export class TopicCommands {
|
|
|
1481
1607
|
const threadId = msg.threadId;
|
|
1482
1608
|
// Access control — only fleet admins of THIS adapter can trigger an update; empty = disabled
|
|
1483
1609
|
if (!this.ctx.hasFleetAdmins(msg.adapterId)) {
|
|
1484
|
-
await adapter.sendText(chatId, t("update.disabled"), { threadId });
|
|
1610
|
+
await adapter.sendText(chatId, t("update.disabled", this.adminListKey(msg.adapterId)), { threadId });
|
|
1485
1611
|
return;
|
|
1486
1612
|
}
|
|
1487
1613
|
if (!this.ctx.isFleetAdmin(msg.userId, msg.adapterId)) {
|
|
@@ -1494,7 +1620,7 @@ export class TopicCommands {
|
|
|
1494
1620
|
// agend, verified by identity, by absolute path — or a refusal, never whatever `agend` is first on PATH.
|
|
1495
1621
|
const installed = await resolveInstalledAgend();
|
|
1496
1622
|
if (!installed.ok) {
|
|
1497
|
-
this.ctx.failUpdateProgress?.(
|
|
1623
|
+
this.ctx.failUpdateProgress?.(`${t("update.failure.shell")} ${t("update.failure.installed", installed.reason)}`);
|
|
1498
1624
|
return;
|
|
1499
1625
|
}
|
|
1500
1626
|
const { spawn } = await import("node:child_process");
|
|
@@ -1502,17 +1628,22 @@ export class TopicCommands {
|
|
|
1502
1628
|
recordInternalRequest(this.ctx.dataDir, "update", origin);
|
|
1503
1629
|
const launch = await resolveUpdateLaunch(installed.agend);
|
|
1504
1630
|
if (!launch.ok) {
|
|
1505
|
-
this.ctx.failUpdateProgress?.(
|
|
1631
|
+
this.ctx.failUpdateProgress?.(`${t("update.failure.shell")} ${t("update.failure.independent", launch.reason)}`);
|
|
1506
1632
|
return;
|
|
1507
1633
|
}
|
|
1508
1634
|
if (!this.ctx.hasFleetAdmins(msg.adapterId) || !this.ctx.isFleetAdmin(msg.userId, msg.adapterId) || this.ctx.isFleetStopping()) {
|
|
1509
1635
|
this.ctx.failUpdateProgress?.(t("not_authorized"));
|
|
1510
1636
|
return;
|
|
1511
1637
|
}
|
|
1638
|
+
const logPath = updateLogPath(this.ctx.dataDir);
|
|
1639
|
+
const ts = new Date().toISOString();
|
|
1640
|
+
const logFd = openUpdateLog(logPath, `--- /update ${ts} ---`);
|
|
1512
1641
|
const child = spawn(launch.command, launch.args, {
|
|
1513
|
-
detached: true, stdio: "ignore", env: withOrigin(origin),
|
|
1642
|
+
detached: true, stdio: ["ignore", logFd ? logFd.fd : "ignore", logFd ? logFd.fd : "ignore"], env: withOrigin(origin),
|
|
1514
1643
|
});
|
|
1515
|
-
|
|
1644
|
+
if (logFd)
|
|
1645
|
+
closeSync(logFd.fd);
|
|
1646
|
+
watchUpdateLaunch(child, message => this.ctx.failUpdateProgress?.(message), logFd ? logPath : undefined, logFd?.offset, installed.agend);
|
|
1516
1647
|
child.unref();
|
|
1517
1648
|
}
|
|
1518
1649
|
/** #1302: `/visibility [full|summary|hidden]` in the General topic. */
|
|
@@ -1704,6 +1835,8 @@ export class TopicCommands {
|
|
|
1704
1835
|
this.ctx.logger.warn({ adapterId }, "Skipping Telegram bot-command registration — the bot token is not set");
|
|
1705
1836
|
return;
|
|
1706
1837
|
}
|
|
1838
|
+
// #1736: honour telegram_api_root the same way the adapter does.
|
|
1839
|
+
const apiRoot = (ch.telegram_api_root ?? "https://api.telegram.org").replace(/\/+$/, "");
|
|
1707
1840
|
// Locks come from the command table's Telegram column (#1177), descriptions from the locale.
|
|
1708
1841
|
const menu = (which) => telegramMenu(which).map(({ name, lock, argHint }) => ({
|
|
1709
1842
|
command: name,
|
|
@@ -1712,7 +1845,7 @@ export class TopicCommands {
|
|
|
1712
1845
|
const fleetCommands = menu("fleet");
|
|
1713
1846
|
const classicCommands = menu("classic");
|
|
1714
1847
|
const setCommands = async (commands, scope) => {
|
|
1715
|
-
const response = await fetch(
|
|
1848
|
+
const response = await fetch(`${apiRoot}/bot${botToken}/setMyCommands`, {
|
|
1716
1849
|
method: "POST",
|
|
1717
1850
|
headers: { "Content-Type": "application/json" },
|
|
1718
1851
|
body: JSON.stringify({ commands, scope }),
|