@songsid/agend 2.2.0-alpha.1 → 2.2.0-alpha.3
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 +6 -4
- package/README.zh-TW.md +6 -4
- package/dist/agent-cli.js +6 -1
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +4 -1
- package/dist/agent-endpoint.js +82 -14
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-token-header.d.ts +13 -0
- package/dist/agent-token-header.js +16 -0
- package/dist/agent-token-header.js.map +1 -0
- package/dist/atomic-write.d.ts +21 -0
- package/dist/atomic-write.js +65 -0
- package/dist/atomic-write.js.map +1 -0
- package/dist/auth-api.js +2 -0
- package/dist/auth-api.js.map +1 -1
- package/dist/backend/antigravity.js +4 -3
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/codex.d.ts +7 -0
- package/dist/backend/codex.js +7 -0
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/grok.js +1 -1
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro.d.ts +7 -0
- package/dist/backend/kiro.js +82 -33
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/muse.d.ts +7 -0
- package/dist/backend/muse.js +8 -1
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/types.d.ts +12 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/binary-probe.d.ts +80 -0
- package/dist/binary-probe.js +182 -0
- package/dist/binary-probe.js.map +1 -0
- package/dist/cache-analysis.d.ts +92 -0
- package/dist/cache-analysis.js +147 -0
- package/dist/cache-analysis.js.map +1 -0
- package/dist/cache-ledger.d.ts +108 -0
- package/dist/cache-ledger.js +230 -0
- package/dist/cache-ledger.js.map +1 -0
- package/dist/cache-prices.d.ts +32 -0
- package/dist/cache-prices.js +73 -0
- package/dist/cache-prices.js.map +1 -0
- package/dist/cache-scan.d.ts +39 -0
- package/dist/cache-scan.js +115 -0
- package/dist/cache-scan.js.map +1 -0
- package/dist/cache-service.d.ts +131 -0
- package/dist/cache-service.js +452 -0
- package/dist/cache-service.js.map +1 -0
- package/dist/channel/adapters/discord.d.ts +5 -1
- package/dist/channel/adapters/discord.js +56 -11
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +38 -1
- package/dist/channel/adapters/telegram.js +82 -0
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-tools.js +1 -1
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/tool-router.d.ts +8 -1
- package/dist/channel/tool-router.js +4 -2
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/channel/types.d.ts +21 -0
- package/dist/cli-entry.d.ts +19 -0
- package/dist/cli-entry.js +36 -0
- package/dist/cli-entry.js.map +1 -0
- package/dist/cli.js +376 -54
- package/dist/cli.js.map +1 -1
- package/dist/connection-secrets.d.ts +5 -0
- package/dist/connection-secrets.js.map +1 -1
- package/dist/cpu-profile.js +50 -0
- package/dist/cpu-profile.js.map +1 -1
- package/dist/daemon.d.ts +18 -0
- package/dist/daemon.js +256 -63
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-outbox.d.ts +1 -0
- package/dist/delivery-outbox.js +12 -0
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/discord-permissions.d.ts +33 -0
- package/dist/discord-permissions.js +42 -0
- package/dist/discord-permissions.js.map +1 -0
- package/dist/env-file.d.ts +11 -0
- package/dist/env-file.js +27 -0
- package/dist/env-file.js.map +1 -0
- package/dist/event-log.d.ts +4 -1
- package/dist/event-log.js +6 -3
- package/dist/event-log.js.map +1 -1
- package/dist/fleet-context.d.ts +5 -0
- package/dist/fleet-context.js.map +1 -1
- package/dist/fleet-control-audit.d.ts +5 -0
- package/dist/fleet-control-audit.js +7 -0
- package/dist/fleet-control-audit.js.map +1 -1
- package/dist/fleet-level-config.d.ts +8 -1
- package/dist/fleet-level-config.js +53 -0
- package/dist/fleet-level-config.js.map +1 -1
- package/dist/fleet-manager.d.ts +122 -7
- package/dist/fleet-manager.js +871 -152
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-stop-budget.d.ts +22 -0
- package/dist/fleet-stop-budget.js +95 -0
- package/dist/fleet-stop-budget.js.map +1 -0
- package/dist/full-restart.js +2 -3
- package/dist/full-restart.js.map +1 -1
- package/dist/general-knowledge/skills/persona-emoji/SKILL.md +3 -1
- package/dist/install-lock.d.ts +49 -0
- package/dist/install-lock.js +200 -0
- package/dist/install-lock.js.map +1 -0
- package/dist/instance-config-impact.js +3 -2
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/kiro-transcript-lane.d.ts +8 -4
- package/dist/kiro-transcript-lane.js +66 -44
- package/dist/kiro-transcript-lane.js.map +1 -1
- package/dist/locale.js +96 -0
- package/dist/locale.js.map +1 -1
- package/dist/next-steps.d.ts +5 -0
- package/dist/next-steps.js +26 -0
- package/dist/next-steps.js.map +1 -0
- package/dist/outbound-handlers.js +8 -0
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +4 -0
- package/dist/outbound-schemas.js +7 -2
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/outbox-open-error.d.ts +7 -0
- package/dist/outbox-open-error.js +15 -0
- package/dist/outbox-open-error.js.map +1 -0
- package/dist/package-preimage.d.ts +26 -0
- package/dist/package-preimage.js +96 -0
- package/dist/package-preimage.js.map +1 -0
- package/dist/pane-context-cache.d.ts +25 -0
- package/dist/pane-context-cache.js +73 -0
- package/dist/pane-context-cache.js.map +1 -0
- package/dist/paths.d.ts +0 -7
- package/dist/paths.js +8 -2
- package/dist/paths.js.map +1 -1
- package/dist/provider-probe.d.ts +15 -0
- package/dist/provider-probe.js +20 -0
- package/dist/provider-probe.js.map +1 -1
- package/dist/public-link-progress.d.ts +73 -0
- package/dist/public-link-progress.js +190 -0
- package/dist/public-link-progress.js.map +1 -0
- package/dist/public-web-gateway.js +2 -2
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +6 -1
- package/dist/public-web-link.js +87 -15
- package/dist/public-web-link.js.map +1 -1
- package/dist/quickstart-api.d.ts +93 -20
- package/dist/quickstart-api.js +194 -62
- package/dist/quickstart-api.js.map +1 -1
- package/dist/quickstart.d.ts +15 -0
- package/dist/quickstart.js +110 -33
- package/dist/quickstart.js.map +1 -1
- package/dist/reply-buttons-controller.d.ts +98 -0
- package/dist/reply-buttons-controller.js +174 -0
- package/dist/reply-buttons-controller.js.map +1 -0
- package/dist/reply-buttons.d.ts +113 -0
- package/dist/reply-buttons.js +208 -0
- package/dist/reply-buttons.js.map +1 -0
- package/dist/reply-dedup.js +3 -1
- package/dist/reply-dedup.js.map +1 -1
- package/dist/restart-guard.d.ts +53 -0
- package/dist/restart-guard.js +114 -0
- package/dist/restart-guard.js.map +1 -0
- package/dist/scheduler/db.js +6 -2
- package/dist/scheduler/db.js.map +1 -1
- package/dist/service-activation.d.ts +62 -7
- package/dist/service-activation.js +237 -55
- package/dist/service-activation.js.map +1 -1
- package/dist/service-installer.d.ts +56 -1
- package/dist/service-installer.js +152 -12
- package/dist/service-installer.js.map +1 -1
- package/dist/service-plan.d.ts +65 -0
- package/dist/service-plan.js +108 -0
- package/dist/service-plan.js.map +1 -0
- package/dist/settings-api.js +92 -10
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-authority.d.ts +11 -0
- package/dist/settings-authority.js +128 -0
- package/dist/settings-authority.js.map +1 -0
- package/dist/settings-change.d.ts +5 -0
- package/dist/settings-change.js +37 -8
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-confirmation.d.ts +3 -0
- package/dist/settings-confirmation.js +7 -1
- package/dist/settings-confirmation.js.map +1 -1
- package/dist/settings-effect.js +19 -7
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.js +1 -1
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/settings-redaction.d.ts +18 -0
- package/dist/settings-redaction.js +58 -0
- package/dist/settings-redaction.js.map +1 -0
- package/dist/setup-form.d.ts +9 -1
- package/dist/setup-form.js +25 -1
- package/dist/setup-form.js.map +1 -1
- package/dist/setup-host.js +15 -6
- package/dist/setup-host.js.map +1 -1
- package/dist/setup-wizard.js +27 -19
- package/dist/setup-wizard.js.map +1 -1
- package/dist/sqlite-open-errors.d.ts +12 -0
- package/dist/sqlite-open-errors.js +13 -0
- package/dist/sqlite-open-errors.js.map +1 -0
- package/dist/systemd-runtime.d.ts +15 -0
- package/dist/systemd-runtime.js +41 -0
- package/dist/systemd-runtime.js.map +1 -0
- package/dist/tmux-control.d.ts +44 -0
- package/dist/tmux-control.js +170 -21
- package/dist/tmux-control.js.map +1 -1
- package/dist/token-env-name.d.ts +37 -0
- package/dist/token-env-name.js +93 -0
- package/dist/token-env-name.js.map +1 -0
- package/dist/tool-permissions.js +5 -3
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.d.ts +7 -16
- package/dist/topic-commands.js +56 -85
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-monitor.js +3 -0
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-sources.d.ts +68 -0
- package/dist/transcript-sources.js +336 -29
- package/dist/transcript-sources.js.map +1 -1
- package/dist/transcript-turns.d.ts +39 -0
- package/dist/transcript-turns.js +58 -0
- package/dist/transcript-turns.js.map +1 -0
- package/dist/tunnel/cloudflared-install.d.ts +18 -0
- package/dist/tunnel/cloudflared-install.js +15 -1
- package/dist/tunnel/cloudflared-install.js.map +1 -1
- package/dist/turn-reply-guard.d.ts +3 -0
- package/dist/turn-reply-guard.js.map +1 -1
- package/dist/ui/chat-commands.js +43 -0
- package/dist/ui/chat-render.js +34 -8
- package/dist/ui/chat-store.js +51 -2
- package/dist/ui/chat-strings.js +30 -2
- package/dist/ui/chat-thread.js +141 -47
- package/dist/ui/first-run.js +64 -0
- package/dist/ui/fleet-cache.js +168 -0
- package/dist/ui/html-attachment.js +26 -0
- package/dist/ui/panel-chat.js +117 -23
- package/dist/ui/panel-fleet.js +31 -17
- package/dist/ui/panel-settings.js +29 -15
- package/dist/ui/preview-panel.js +237 -0
- package/dist/ui/preview.js +7 -3
- package/dist/ui/settings-apply.js +3 -1
- package/dist/ui/settings-dialogs.js +95 -25
- package/dist/ui/settings-discord.js +130 -0
- package/dist/ui/settings-model.js +21 -0
- package/dist/ui/settings-strings.js +50 -8
- package/dist/ui/settings-token.js +54 -0
- package/dist/ui/settings-wizard.js +63 -29
- package/dist/ui/shared/app-route.js +1 -1
- package/dist/ui/shared/app-shell.js +25 -37
- package/dist/ui/shared/app-store.js +5 -3
- package/dist/ui/shared/app-stream.js +2 -1
- package/dist/ui/shared/app.css +181 -5
- package/dist/ui/shared/app.js +2 -1
- package/dist/ui/shared/instance-nav.js +310 -0
- package/dist/ui/shared/panel-view.js +12 -190
- package/dist/ui/shared/signin.js +13 -1
- package/dist/ui/shared/ui-icons.js +2 -0
- package/dist/ui/shared/view-roster-store.js +5 -0
- package/dist/ui/shared/view-strings.js +12 -0
- package/dist/ui/signin.html +2 -1
- package/dist/update-dispatch.d.ts +28 -0
- package/dist/update-dispatch.js +73 -0
- package/dist/update-dispatch.js.map +1 -0
- package/dist/update-install.d.ts +78 -8
- package/dist/update-install.js +158 -30
- package/dist/update-install.js.map +1 -1
- package/dist/update-launch.d.ts +22 -0
- package/dist/update-launch.js +106 -0
- package/dist/update-launch.js.map +1 -0
- package/dist/update-marker.js +3 -8
- package/dist/update-marker.js.map +1 -1
- package/dist/usage/format-rich.js +7 -1
- package/dist/usage/format-rich.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 +4 -0
- package/dist/usage/providers.js +2 -1
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/usage-api.js +48 -2
- package/dist/usage/usage-api.js.map +1 -1
- package/dist/view-api.d.ts +40 -0
- package/dist/view-api.js +28 -10
- package/dist/view-api.js.map +1 -1
- package/dist/web-api.d.ts +22 -0
- package/dist/web-api.js +115 -16
- package/dist/web-api.js.map +1 -1
- package/dist/web-auth.d.ts +8 -0
- package/dist/web-auth.js +34 -8
- package/dist/web-auth.js.map +1 -1
- package/dist/web-chat-history.d.ts +21 -0
- package/dist/web-chat-history.js +44 -0
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +77 -0
- package/dist/web-commands.js +81 -0
- package/dist/web-commands.js.map +1 -0
- package/dist/web-host-guard.d.ts +18 -2
- package/dist/web-host-guard.js +30 -5
- package/dist/web-host-guard.js.map +1 -1
- package/dist/web-session.d.ts +7 -1
- package/dist/web-session.js +23 -2
- package/dist/web-session.js.map +1 -1
- package/dist/web-shell-routes.d.ts +1 -1
- package/dist/web-shell-routes.js +1 -1
- package/dist/web-shell-routes.js.map +1 -1
- package/launcher/agend +110 -0
- package/launcher/agend-agent +110 -0
- package/launcher/agend-agent.cjs +4 -0
- package/launcher/agend.cjs +4 -0
- package/launcher/install-admission.cjs +105 -0
- package/launcher/launch.cjs +64 -0
- package/launcher/postinstall.cjs +118 -0
- package/launcher/run-in-process.cjs +13 -0
- package/launcher/runtime-platform.cjs +86 -0
- package/launcher/runtime-select.cjs +217 -0
- package/package.json +12 -4
- package/scripts/preinstall-guard.cjs +40 -21
- package/templates/launchd.plist.ejs +2 -2
- package/templates/systemd.service.ejs +4 -4
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #1519 P1 (docs/design/ux-onboarding-walkthrough.md §5.2): the env var that holds a connection's bot token is
|
|
3
|
+
* generated, never asked for — `AGEND_<PLATFORM>_<ID>_TOKEN`, upper-cased, the id reduced to [A-Z0-9_], a numeric
|
|
4
|
+
* suffix on collision. A name is never one another connection holds, a provider key, a reserved shell name, or a key
|
|
5
|
+
* already in the data dir's .env or this process's environment: a generated name only ever names a new value.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { isReservedProviderEnvKey, providerRegistryEnvKeys } from "./provider-secret-registry.js";
|
|
10
|
+
import { parseEnvText } from "./env-file.js";
|
|
11
|
+
/** What a token env name must look like (fleet.yaml and the wizard). */
|
|
12
|
+
export const TOKEN_ENV_PATTERN = /^[A-Z][A-Z0-9_]{2,63}$/;
|
|
13
|
+
const sanitize = (s) => s.toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
14
|
+
/** `AGEND_<PLATFORM>_TOKEN` for the platform's own id, else `AGEND_<PLATFORM>_<ID>_TOKEN` (a leading "<platform>-" dropped). */
|
|
15
|
+
export function tokenEnvBase(platform, channelId) {
|
|
16
|
+
const p = sanitize(platform) || "BOT";
|
|
17
|
+
const lowerId = channelId.toLowerCase(), lowerP = platform.toLowerCase();
|
|
18
|
+
const rest = lowerId === lowerP ? "" : sanitize(lowerId.startsWith(`${lowerP}-`) ? channelId.slice(platform.length + 1) : channelId);
|
|
19
|
+
const middle = rest ? `_${rest}` : "";
|
|
20
|
+
// AGEND_ + P + middle + _TOKEN must fit 64 characters (with room for a "_99" suffix).
|
|
21
|
+
const room = 64 - "AGEND_".length - p.length - "_TOKEN".length - 4;
|
|
22
|
+
return `AGEND_${p}${middle.slice(0, Math.max(0, room)).replace(/_+$/, "")}_TOKEN`;
|
|
23
|
+
}
|
|
24
|
+
/** The base name, or with `_2`, `_3`… before `_TOKEN` until it is free. */
|
|
25
|
+
export function generateTokenEnvName(platform, channelId, taken) {
|
|
26
|
+
const base = tokenEnvBase(platform, channelId);
|
|
27
|
+
const free = (name) => !taken.has(name) && !isReservedProviderEnvKey(name);
|
|
28
|
+
if (free(base))
|
|
29
|
+
return base;
|
|
30
|
+
const stem = base.slice(0, -"_TOKEN".length);
|
|
31
|
+
for (let n = 2; n < 10_000; n++) {
|
|
32
|
+
const candidate = `${stem}_${n}_TOKEN`;
|
|
33
|
+
if (free(candidate))
|
|
34
|
+
return candidate;
|
|
35
|
+
}
|
|
36
|
+
throw new Error("no free token env name");
|
|
37
|
+
}
|
|
38
|
+
/** The .env could not be read, so which names it holds is unknown — never taken as "none" (#1529 review). */
|
|
39
|
+
export class EnvFileUnreadableError extends Error {
|
|
40
|
+
constructor(cause) { super(`the data dir's .env cannot be read: ${cause?.message ?? String(cause)}`); }
|
|
41
|
+
}
|
|
42
|
+
/** The names already in the data dir's .env (names only). No file: none. A file that cannot be read throws. */
|
|
43
|
+
export function envFileKeys(dataDir) {
|
|
44
|
+
let text;
|
|
45
|
+
try {
|
|
46
|
+
text = readFileSync(join(dataDir, ".env"), "utf-8");
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
if (err?.code === "ENOENT")
|
|
50
|
+
return new Set();
|
|
51
|
+
throw new EnvFileUnreadableError(err);
|
|
52
|
+
}
|
|
53
|
+
return new Set(parseEnvText(text).keys()); // the same reading as the fleet's (env-file.ts)
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Why a GENERATED name (#1519 P1) can no longer be written, or null. A generated name only ever names a new value, so
|
|
57
|
+
* at the write it must still be free of everything the plan avoided — another connection, a provider or reserved name,
|
|
58
|
+
* a key in .env (read under the caller's lease), one in this process's environment. Throws when .env is unreadable.
|
|
59
|
+
*/
|
|
60
|
+
export function generatedTokenEnvStale(name, opts) {
|
|
61
|
+
const taken = takenTokenEnvNames({ channelEnvs: opts.channelEnvs, envFile: envFileKeys(opts.dataDir), processEnv: opts.processEnv ?? Object.keys(process.env) });
|
|
62
|
+
if (taken.has(name) || isReservedProviderEnvKey(name))
|
|
63
|
+
return `${name} is no longer free (it was taken after this setup was planned) — plan it again`;
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
/** Every name a new connection's token must not take. */
|
|
67
|
+
export function takenTokenEnvNames(opts) {
|
|
68
|
+
const taken = new Set(providerRegistryEnvKeys());
|
|
69
|
+
for (const name of opts.channelEnvs)
|
|
70
|
+
if (name)
|
|
71
|
+
taken.add(name);
|
|
72
|
+
for (const name of opts.envFile ?? [])
|
|
73
|
+
taken.add(name);
|
|
74
|
+
for (const name of opts.processEnv ?? [])
|
|
75
|
+
taken.add(name);
|
|
76
|
+
return taken;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Why `name` cannot be the token env of a NEW connection, or null. Only the names that would make it another holder's
|
|
80
|
+
* value: another connection's, a provider key, a reserved shell name (a key merely present in .env is allowed when a
|
|
81
|
+
* caller names it explicitly — the pre-fleet setup form and the CLI do).
|
|
82
|
+
*/
|
|
83
|
+
export function newTokenEnvConflict(name, channels) {
|
|
84
|
+
if (!TOKEN_ENV_PATTERN.test(name))
|
|
85
|
+
return "token_env must be an UPPER_SNAKE env var name";
|
|
86
|
+
if (isReservedProviderEnvKey(name) || providerRegistryEnvKeys().has(name))
|
|
87
|
+
return `${name} is reserved`;
|
|
88
|
+
const owner = channels.find(channel => channel.token_env === name);
|
|
89
|
+
if (owner)
|
|
90
|
+
return `${name} already holds the token of the "${owner.id}" connection — a new connection never replaces one; use Replace token on that connection`;
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=token-env-name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-env-name.js","sourceRoot":"","sources":["../src/token-env-name.ts"],"names":[],"mappings":"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"}
|
package/dist/tool-permissions.js
CHANGED
|
@@ -15,13 +15,15 @@
|
|
|
15
15
|
* — not only the ones in cli mode.
|
|
16
16
|
*
|
|
17
17
|
* Which is why keeping a tool out of the schema is a way to spend fewer tokens
|
|
18
|
-
* and get a clearer error, and is not
|
|
18
|
+
* and get a clearer error, and is not an authorization check. The policy check is this module,
|
|
19
19
|
* called at the points where those four paths converge: the fleet's IPC
|
|
20
20
|
* dispatch and the agent endpoint. See
|
|
21
21
|
* `docs/design/coordinator-tool-perms.zh-TW.md`.
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
23
|
+
* This policy is enforced for the identity resolved by the IPC socket or token.
|
|
24
|
+
* Same-uid agents with a shell can read a sibling's agent.token or connect to
|
|
25
|
+
* its channel.sock and assume that identity. A tool profile is policy protection,
|
|
26
|
+
* not an isolation boundary against those agents; that requires OS isolation.
|
|
25
27
|
*/
|
|
26
28
|
import { TOOLS } from "./channel/mcp-tools.js";
|
|
27
29
|
/** Everything an agent that is doing the work needs, and nothing that runs the fleet. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-permissions.js","sourceRoot":"","sources":["../src/tool-permissions.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tool-permissions.js","sourceRoot":"","sources":["../src/tool-permissions.ts"],"names":[],"mappings":"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"}
|
package/dist/topic-commands.d.ts
CHANGED
|
@@ -147,27 +147,18 @@ export declare function scrapePaneContext(instanceName: string, backend: string)
|
|
|
147
147
|
context: number | null;
|
|
148
148
|
tokenRatio: TokenContextRatio | null;
|
|
149
149
|
};
|
|
150
|
-
/** Forget a deleted instance
|
|
150
|
+
/** Forget a deleted instance and revoke any outstanding refresh for its old pane. */
|
|
151
151
|
export declare function forgetInstanceContext(instanceName: string): void;
|
|
152
152
|
/**
|
|
153
|
-
*
|
|
154
|
-
* Claude
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
* returned as-is; a stale or missing one is returned immediately anyway while a
|
|
159
|
-
* background refresh runs. This used to scrape synchronously with `execFileSync`
|
|
160
|
-
* (2s timeout) on a cache miss, and the 12s TTL is LONGER than the dashboard's
|
|
161
|
-
* 10s poll — so roughly every other tick did N blocking captures. With ten
|
|
162
|
-
* non-claude-code instances and a slow tmux that froze the entire fleet event
|
|
163
|
-
* loop for up to 20s per tick: no IPC, no message delivery, no watchdog ping.
|
|
164
|
-
* Three open browser tabs ran three independent polls.
|
|
165
|
-
*
|
|
166
|
-
* Pass `bypassCache` for a synchronous, authoritative read — used by `/ctx`,
|
|
167
|
-
* where a user is asking right now and 2s of blocking is the correct trade.
|
|
153
|
+
* Shared context percentage for /ctx, /status and View, using the same pane parsers.
|
|
154
|
+
* Claude Code prefers its authoritative statusline.json.
|
|
155
|
+
* Polled reads return cached values immediately and refresh through the captured
|
|
156
|
+
* owner after the monotonic 8s interval. A missing pane owner returns unknown.
|
|
157
|
+
* Explicit /ctx retains its synchronous authoritative read via bypassCache.
|
|
168
158
|
*/
|
|
169
159
|
export declare function resolveInstanceContext(dataDir: string, instanceName: string, backend: string, opts?: {
|
|
170
160
|
bypassCache?: boolean;
|
|
161
|
+
source?: import("./pane-context-cache.js").PaneContextSource | null;
|
|
171
162
|
}): {
|
|
172
163
|
context: number | null;
|
|
173
164
|
tokenRatio: TokenContextRatio | null;
|
package/dist/topic-commands.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PaneContextCache } from "./pane-context-cache.js";
|
|
1
2
|
import { measureSyncWork } from "./sync-work-attribution.js";
|
|
2
3
|
import { LOOPBACK_HOST_NAMES } from "./web-host-guard.js";
|
|
3
4
|
import { WEB_REMOTE_DOCS_URL } from "./upgrade-notices.js";
|
|
@@ -20,7 +21,9 @@ import { isGeneralInstance } from "./general-instance.js";
|
|
|
20
21
|
import { instanceSupportsSteer } from "./steer-capability.js";
|
|
21
22
|
import { SYSINFO_BACKEND_IDS } from "./backend/types.js";
|
|
22
23
|
import { recordInternalRequest, withOrigin } from "./fleet-control-audit.js";
|
|
23
|
-
import {
|
|
24
|
+
import { resolveInstalledAgend } from "./update-dispatch.js";
|
|
25
|
+
import { resolveUpdateLaunch, watchUpdateLaunch } from "./update-launch.js";
|
|
26
|
+
import { selfCommand } from "./cli-entry.js";
|
|
24
27
|
export { parseContextPercent, parseTokenContextRatio } from "./context-percent.js";
|
|
25
28
|
/** Longest one setMyCommands call may take. */
|
|
26
29
|
const TELEGRAM_COMMANDS_TIMEOUT_MS = 10_000;
|
|
@@ -382,60 +385,17 @@ export function scrapePaneContext(instanceName, backend) {
|
|
|
382
385
|
return { context: null, tokenRatio: null };
|
|
383
386
|
}
|
|
384
387
|
}
|
|
385
|
-
const paneContextCache = new
|
|
386
|
-
|
|
387
|
-
// guaranteed to be stale on roughly every other tick, which is what made the
|
|
388
|
-
// blocking scrape fire so often. Now a tick either hits the cache or triggers a
|
|
389
|
-
// background refresh, never a synchronous capture.
|
|
390
|
-
const PANE_CONTEXT_CACHE_MS = 8_000;
|
|
391
|
-
/** Instances with a background scrape in flight, so polls don't pile up captures. */
|
|
392
|
-
const paneScrapeInFlight = new Set();
|
|
393
|
-
/** Async twin of scrapePaneContext — same parsers, no blocking. */
|
|
394
|
-
async function scrapePaneContextAsync(instanceName, backend) {
|
|
395
|
-
try {
|
|
396
|
-
const socketName = getTmuxSocketName();
|
|
397
|
-
const baseArgs = ["capture-pane", "-t", `${getTmuxSessionName()}:${instanceName}`, "-p", "-S", "-60"];
|
|
398
|
-
const tmuxArgs = socketName ? ["-L", socketName, ...baseArgs] : baseArgs;
|
|
399
|
-
const { promisify } = await import("node:util");
|
|
400
|
-
const { execFile } = await import("node:child_process");
|
|
401
|
-
const { stdout } = await promisify(execFile)("tmux", tmuxArgs, { encoding: "utf-8", timeout: 2000 });
|
|
402
|
-
const pane = stdout.toString();
|
|
403
|
-
const tokenRatio = backend === "grok" ? parseTokenContextRatio(pane) : null;
|
|
404
|
-
return { context: tokenRatio?.percentage ?? parseContextPercent(pane), tokenRatio };
|
|
405
|
-
}
|
|
406
|
-
catch {
|
|
407
|
-
return { context: null, tokenRatio: null };
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
/** Refresh one instance's cached context in the background (deduped per instance). */
|
|
411
|
-
function refreshPaneContext(instanceName, backend) {
|
|
412
|
-
if (paneScrapeInFlight.has(instanceName))
|
|
413
|
-
return;
|
|
414
|
-
paneScrapeInFlight.add(instanceName);
|
|
415
|
-
void scrapePaneContextAsync(instanceName, backend)
|
|
416
|
-
.then(scraped => { paneContextCache.set(instanceName, { at: Date.now(), ...scraped }); })
|
|
417
|
-
.finally(() => { paneScrapeInFlight.delete(instanceName); });
|
|
418
|
-
}
|
|
419
|
-
/** Forget a deleted instance's cached context so the map can't grow forever. */
|
|
388
|
+
const paneContextCache = new PaneContextCache();
|
|
389
|
+
/** Forget a deleted instance and revoke any outstanding refresh for its old pane. */
|
|
420
390
|
export function forgetInstanceContext(instanceName) {
|
|
421
|
-
paneContextCache.
|
|
391
|
+
paneContextCache.forget(instanceName);
|
|
422
392
|
}
|
|
423
393
|
/**
|
|
424
|
-
*
|
|
425
|
-
* Claude
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
* returned as-is; a stale or missing one is returned immediately anyway while a
|
|
430
|
-
* background refresh runs. This used to scrape synchronously with `execFileSync`
|
|
431
|
-
* (2s timeout) on a cache miss, and the 12s TTL is LONGER than the dashboard's
|
|
432
|
-
* 10s poll — so roughly every other tick did N blocking captures. With ten
|
|
433
|
-
* non-claude-code instances and a slow tmux that froze the entire fleet event
|
|
434
|
-
* loop for up to 20s per tick: no IPC, no message delivery, no watchdog ping.
|
|
435
|
-
* Three open browser tabs ran three independent polls.
|
|
436
|
-
*
|
|
437
|
-
* Pass `bypassCache` for a synchronous, authoritative read — used by `/ctx`,
|
|
438
|
-
* where a user is asking right now and 2s of blocking is the correct trade.
|
|
394
|
+
* Shared context percentage for /ctx, /status and View, using the same pane parsers.
|
|
395
|
+
* Claude Code prefers its authoritative statusline.json.
|
|
396
|
+
* Polled reads return cached values immediately and refresh through the captured
|
|
397
|
+
* owner after the monotonic 8s interval. A missing pane owner returns unknown.
|
|
398
|
+
* Explicit /ctx retains its synchronous authoritative read via bypassCache.
|
|
439
399
|
*/
|
|
440
400
|
export function resolveInstanceContext(dataDir, instanceName, backend, opts) {
|
|
441
401
|
if (backend === "claude-code") {
|
|
@@ -445,17 +405,10 @@ export function resolveInstanceContext(dataDir, instanceName, backend, opts) {
|
|
|
445
405
|
}
|
|
446
406
|
if (opts?.bypassCache) {
|
|
447
407
|
const scraped = scrapePaneContext(instanceName, backend);
|
|
448
|
-
paneContextCache.
|
|
408
|
+
paneContextCache.record(dataDir, instanceName, backend, scraped, opts.source);
|
|
449
409
|
return scraped;
|
|
450
410
|
}
|
|
451
|
-
|
|
452
|
-
if (hit && Date.now() - hit.at < PANE_CONTEXT_CACHE_MS) {
|
|
453
|
-
return { context: hit.context, tokenRatio: hit.tokenRatio };
|
|
454
|
-
}
|
|
455
|
-
// Stale or absent: kick off the refresh and answer with what we have. A brand-new
|
|
456
|
-
// instance reads as "no data" for one tick rather than blocking the fleet.
|
|
457
|
-
refreshPaneContext(instanceName, backend);
|
|
458
|
-
return hit ? { context: hit.context, tokenRatio: hit.tokenRatio } : { context: null, tokenRatio: null };
|
|
411
|
+
return paneContextCache.resolve(dataDir, instanceName, backend, opts?.source);
|
|
459
412
|
}
|
|
460
413
|
const PROFILE_RE = /^\/profile(?:@\w+)?(?:\s+([\s\S]*))?$/;
|
|
461
414
|
const RESTART_RE = /^\/restart(?:@[A-Za-z0-9_]*)?(?:\s+(.*))?$/i;
|
|
@@ -956,7 +909,7 @@ export class TopicCommands {
|
|
|
956
909
|
// classic channel manager for those so we don't mis-report defaults.backend.
|
|
957
910
|
const backend = this.effectiveBackend(instanceName);
|
|
958
911
|
// Fresh scrape for /ctx (user is asking right now) — bypass short cache.
|
|
959
|
-
const { context, tokenRatio } = resolveInstanceContext(this.ctx.dataDir, instanceName, backend, { bypassCache: true });
|
|
912
|
+
const { context, tokenRatio } = resolveInstanceContext(this.ctx.dataDir, instanceName, backend, { bypassCache: true, source: this.ctx.getPaneContextSource?.(instanceName) });
|
|
960
913
|
const contextLine = context == null ? null : formatContextUsageLine(context, tokenRatio);
|
|
961
914
|
// Effective model (resolves per-instance → fleet default → classic channel →
|
|
962
915
|
// the CLI's own default) via the shared resolver, so /ctx and /model agree.
|
|
@@ -1368,7 +1321,7 @@ export class TopicCommands {
|
|
|
1368
1321
|
// Without this, kiro/grok/codex always showed "-" in the Ctx column.
|
|
1369
1322
|
const { context } = backend === "-"
|
|
1370
1323
|
? { context: null }
|
|
1371
|
-
: resolveInstanceContext(this.ctx.dataDir, name, backend);
|
|
1324
|
+
: resolveInstanceContext(this.ctx.dataDir, name, backend, { source: this.ctx.getPaneContextSource?.(name) });
|
|
1372
1325
|
const contextStr = context == null ? "-" : `${Math.round(context)}%`;
|
|
1373
1326
|
const costCents = this.ctx.costGuard?.getDailyCostCents(name) ?? 0;
|
|
1374
1327
|
// Merged State (#1052): lifecycle + execution state in one column. The
|
|
@@ -1535,15 +1488,29 @@ export class TopicCommands {
|
|
|
1535
1488
|
}
|
|
1536
1489
|
const sent = await adapter.sendText(chatId, t("update.progress.preparing", 0), { threadId });
|
|
1537
1490
|
this.ctx.beginUpdateProgress?.(adapter, chatId, threadId, sent.messageId);
|
|
1538
|
-
// The CLI picks the channel from the installed version it replaces; see UPDATE_COMMAND.
|
|
1539
|
-
|
|
1491
|
+
// The CLI picks the channel from the installed version it replaces; see UPDATE_COMMAND. #1450 C5: the INSTALLED
|
|
1492
|
+
// agend, verified by identity, by absolute path — or a refusal, never whatever `agend` is first on PATH.
|
|
1493
|
+
const installed = await resolveInstalledAgend();
|
|
1494
|
+
if (!installed.ok) {
|
|
1495
|
+
this.ctx.failUpdateProgress?.(`/update cannot verify the installed AgEnD (${installed.reason}). Run \`agend update\` from a shell.`);
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1540
1498
|
const { spawn } = await import("node:child_process");
|
|
1541
1499
|
const origin = `command /update by ${msg.adapterId}:${msg.userId}`;
|
|
1542
1500
|
recordInternalRequest(this.ctx.dataDir, "update", origin);
|
|
1543
|
-
const
|
|
1501
|
+
const launch = await resolveUpdateLaunch(installed.agend);
|
|
1502
|
+
if (!launch.ok) {
|
|
1503
|
+
this.ctx.failUpdateProgress?.(`/update cannot prepare an independent updater (${launch.reason}). Run ` + "`agend update` from a host shell.");
|
|
1504
|
+
return;
|
|
1505
|
+
}
|
|
1506
|
+
if (!this.ctx.hasFleetAdmins(msg.adapterId) || !this.ctx.isFleetAdmin(msg.userId, msg.adapterId) || this.ctx.isFleetStopping()) {
|
|
1507
|
+
this.ctx.failUpdateProgress?.(t("not_authorized"));
|
|
1508
|
+
return;
|
|
1509
|
+
}
|
|
1510
|
+
const child = spawn(launch.command, launch.args, {
|
|
1544
1511
|
detached: true, stdio: "ignore", env: withOrigin(origin),
|
|
1545
1512
|
});
|
|
1546
|
-
child
|
|
1513
|
+
watchUpdateLaunch(child, message => this.ctx.failUpdateProgress?.(message));
|
|
1547
1514
|
child.unref();
|
|
1548
1515
|
}
|
|
1549
1516
|
/** #1302: `/visibility [full|summary|hidden]` in the General topic. */
|
|
@@ -1580,7 +1547,9 @@ export class TopicCommands {
|
|
|
1580
1547
|
try {
|
|
1581
1548
|
const { execFile } = await import("node:child_process");
|
|
1582
1549
|
const { promisify } = await import("node:util");
|
|
1583
|
-
|
|
1550
|
+
// This CLI on this Node, not whichever `agend` is first on PATH (#1450 C5).
|
|
1551
|
+
const doctor = selfCommand(["backend", "doctor", backend]);
|
|
1552
|
+
const { stdout } = await promisify(execFile)(doctor.command, doctor.args, {
|
|
1584
1553
|
timeout: 30_000,
|
|
1585
1554
|
encoding: "utf-8",
|
|
1586
1555
|
});
|
|
@@ -1651,26 +1620,22 @@ export class TopicCommands {
|
|
|
1651
1620
|
if (!botToken)
|
|
1652
1621
|
return;
|
|
1653
1622
|
let configChanged = false;
|
|
1623
|
+
const channels = this.ctx.fleetConfig?.channels ?? (this.ctx.fleetConfig?.channel ? [this.ctx.fleetConfig.channel] : []);
|
|
1654
1624
|
for (const [name, config] of Object.entries(this.ctx.fleetConfig.instances)) {
|
|
1655
1625
|
if (config.topic_id != null)
|
|
1656
1626
|
continue;
|
|
1657
|
-
//
|
|
1627
|
+
// #1549 review: the agent's own connection decides — its channel_id, else the first. A topic is made, or a
|
|
1628
|
+
// General bound, only in that connection's chat: an owner that is not configured is left unbound, and nothing
|
|
1629
|
+
// is borrowed from another connection (a topic in the old group, the old bot's General).
|
|
1630
|
+
const ownerId = config.channel_id;
|
|
1631
|
+
const owner = ownerId != null ? channels.find(c => (c.id ?? c.type) === ownerId) : channels[0];
|
|
1632
|
+
if (!owner) {
|
|
1633
|
+
this.ctx.logger.warn({ name, channelId: ownerId }, "Agent's connection is not configured — leaving its topic unbound");
|
|
1634
|
+
continue;
|
|
1635
|
+
}
|
|
1658
1636
|
if (config.general_topic) {
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
if (config.channel_id) {
|
|
1662
|
-
const matched = channels.find(c => (c.id ?? c.type) === config.channel_id);
|
|
1663
|
-
platformType = matched?.type;
|
|
1664
|
-
}
|
|
1665
|
-
if (!platformType) {
|
|
1666
|
-
if (name.includes("telegram"))
|
|
1667
|
-
platformType = "telegram";
|
|
1668
|
-
else if (name.includes("discord"))
|
|
1669
|
-
platformType = "discord";
|
|
1670
|
-
}
|
|
1671
|
-
if (platformType === "discord") {
|
|
1672
|
-
const ch = channels.find(c => c.type === "discord");
|
|
1673
|
-
const gcid = ch?.options?.general_channel_id;
|
|
1637
|
+
if (owner.type === "discord") {
|
|
1638
|
+
const gcid = owner.options?.general_channel_id;
|
|
1674
1639
|
// A Discord general needs a real channel id — NOT the TG-convention
|
|
1675
1640
|
// "1", which makes the DC adapter throw fetching channel "1". Skip
|
|
1676
1641
|
// (leave unbound) if there's no valid channel to bind to.
|
|
@@ -1684,7 +1649,13 @@ export class TopicCommands {
|
|
|
1684
1649
|
config.topic_id = 1;
|
|
1685
1650
|
}
|
|
1686
1651
|
configChanged = true;
|
|
1687
|
-
this.ctx.logger.info({ name, topicId: config.topic_id, platformType }, "Bound to General topic");
|
|
1652
|
+
this.ctx.logger.info({ name, topicId: config.topic_id, platformType: owner.type }, "Bound to General topic");
|
|
1653
|
+
continue;
|
|
1654
|
+
}
|
|
1655
|
+
// A new topic is made through the primary connection only (createForumTopic's adapter): an agent of another
|
|
1656
|
+
// connection is not given a topic in the primary's group.
|
|
1657
|
+
if (owner !== channels[0]) {
|
|
1658
|
+
this.ctx.logger.info({ name, channelId: ownerId }, "Agent belongs to another connection — not auto-creating a topic in the primary group");
|
|
1688
1659
|
continue;
|
|
1689
1660
|
}
|
|
1690
1661
|
try {
|