@songsid/agend 2.3.2-beta.1 → 2.3.2-beta.11
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/THIRD_PARTY_NOTICES.md +40 -0
- package/dist/agent-cli.js +69 -2
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.js +11 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-whats-new.js +3 -0
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/antigravity-usage-scan.d.ts +58 -0
- package/dist/antigravity-usage-scan.js +257 -0
- package/dist/antigravity-usage-scan.js.map +1 -0
- package/dist/antigravity-usage-worker.d.ts +1 -0
- package/dist/antigravity-usage-worker.js +10 -0
- package/dist/antigravity-usage-worker.js.map +1 -0
- package/dist/auth-api.js +4 -0
- package/dist/auth-api.js.map +1 -1
- package/dist/backend/kiro-classic-archive.d.ts +52 -0
- package/dist/backend/kiro-classic-archive.js +444 -0
- package/dist/backend/kiro-classic-archive.js.map +1 -0
- package/dist/backend/kiro-identity.d.ts +83 -0
- package/dist/backend/kiro-identity.js +144 -0
- package/dist/backend/kiro-identity.js.map +1 -1
- package/dist/backend/kiro-migration-verify.d.ts +10 -0
- package/dist/backend/kiro-migration-verify.js +52 -0
- package/dist/backend/kiro-migration-verify.js.map +1 -0
- package/dist/backend/kiro-retired-model.d.ts +62 -0
- package/dist/backend/kiro-retired-model.js +160 -0
- package/dist/backend/kiro-retired-model.js.map +1 -0
- package/dist/backend/kiro-v2-store-worker.js +21 -1
- package/dist/backend/kiro-v2-store-worker.js.map +1 -1
- package/dist/backend/kiro-v2-store.d.ts +8 -0
- package/dist/backend/kiro-v2-store.js.map +1 -1
- package/dist/backend/kiro.d.ts +169 -2
- package/dist/backend/kiro.js +703 -28
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/types.d.ts +108 -0
- package/dist/backend/types.js +9 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-signin-guide.d.ts +1 -0
- package/dist/backend-signin-guide.js +9 -0
- package/dist/backend-signin-guide.js.map +1 -0
- package/dist/backend-signin-pending.d.ts +10 -0
- package/dist/backend-signin-pending.js +44 -0
- package/dist/backend-signin-pending.js.map +1 -0
- package/dist/browser-backend-signins.d.ts +56 -0
- package/dist/browser-backend-signins.js +189 -0
- package/dist/browser-backend-signins.js.map +1 -0
- package/dist/cache-ledger.d.ts +38 -2
- package/dist/cache-ledger.js +133 -8
- package/dist/cache-ledger.js.map +1 -1
- package/dist/cache-prices.d.ts +2 -1
- package/dist/cache-prices.js +5 -2
- package/dist/cache-prices.js.map +1 -1
- package/dist/cache-service.d.ts +68 -0
- package/dist/cache-service.js +355 -13
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +11 -0
- package/dist/channel/adapters/discord.js +71 -14
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/ipc-timeouts.js +3 -0
- package/dist/channel/ipc-timeouts.js.map +1 -1
- package/dist/channel/mcp-tools.js +41 -2
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/tool-router.js +2 -1
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/classic-channel-manager.d.ts +11 -0
- package/dist/classic-channel-manager.js +39 -1
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +54 -2
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.d.ts +7 -1
- package/dist/config-validator.js +55 -10
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +19 -0
- package/dist/config.js +33 -1
- package/dist/config.js.map +1 -1
- package/dist/cpu-quota.d.ts +23 -0
- package/dist/cpu-quota.js +86 -0
- package/dist/cpu-quota.js.map +1 -0
- package/dist/daemon.d.ts +68 -0
- package/dist/daemon.js +448 -26
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard-permissions.d.ts +31 -6
- package/dist/dashboard-permissions.js +84 -9
- package/dist/dashboard-permissions.js.map +1 -1
- package/dist/doctor.js +2 -1
- package/dist/doctor.js.map +1 -1
- package/dist/fleet-control-audit.d.ts +1 -1
- package/dist/fleet-control-audit.js +3 -0
- package/dist/fleet-control-audit.js.map +1 -1
- package/dist/fleet-manager.d.ts +133 -2
- package/dist/fleet-manager.js +905 -94
- package/dist/fleet-manager.js.map +1 -1
- package/dist/forged-envelope-scan.d.ts +9 -0
- package/dist/forged-envelope-scan.js +30 -5
- package/dist/forged-envelope-scan.js.map +1 -1
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +5 -2
- package/dist/general-knowledge/skills/kiro-engine-migration/SKILL.md +24 -1
- package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +49 -1
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +49 -1
- package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +47 -9
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +54 -11
- package/dist/instance-config-impact.js +10 -5
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +23 -0
- package/dist/instance-lifecycle.js +62 -12
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/kiro-db-reader.d.ts +5 -0
- package/dist/kiro-db-reader.js +18 -0
- package/dist/kiro-db-reader.js.map +1 -1
- package/dist/kiro-engine-status.d.ts +2 -0
- package/dist/kiro-engine-status.js +9 -0
- package/dist/kiro-engine-status.js.map +1 -1
- package/dist/kiro-migrate.d.ts +60 -0
- package/dist/kiro-migrate.js +160 -0
- package/dist/kiro-migrate.js.map +1 -0
- package/dist/kiro-session-proof.d.ts +41 -0
- package/dist/kiro-session-proof.js +89 -0
- package/dist/kiro-session-proof.js.map +1 -0
- package/dist/kiro-transcript-lane.d.ts +2 -0
- package/dist/kiro-transcript-lane.js.map +1 -1
- package/dist/kiro-transcript-worker.js +1 -0
- package/dist/kiro-transcript-worker.js.map +1 -1
- package/dist/kiro-tui-forensic.d.ts +12 -0
- package/dist/kiro-tui-forensic.js +110 -0
- package/dist/kiro-tui-forensic.js.map +1 -0
- package/dist/kiro-usage-run.d.ts +7 -0
- package/dist/kiro-usage-run.js +39 -0
- package/dist/kiro-usage-run.js.map +1 -0
- package/dist/kiro-usage-scan.d.ts +49 -0
- package/dist/kiro-usage-scan.js +223 -0
- package/dist/kiro-usage-scan.js.map +1 -0
- package/dist/kiro-usage-worker.d.ts +1 -0
- package/dist/kiro-usage-worker.js +10 -0
- package/dist/kiro-usage-worker.js.map +1 -0
- package/dist/kiro-usage.d.ts +58 -0
- package/dist/kiro-usage.js +310 -0
- package/dist/kiro-usage.js.map +1 -0
- package/dist/locale.js +230 -8
- package/dist/locale.js.map +1 -1
- package/dist/log-service.js +1 -1
- package/dist/log-service.js.map +1 -1
- package/dist/login-url.d.ts +4 -0
- package/dist/login-url.js +22 -0
- package/dist/login-url.js.map +1 -0
- package/dist/needs-you-hub.d.ts +2 -1
- package/dist/needs-you-hub.js +1 -1
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you.d.ts +10 -2
- package/dist/needs-you.js +10 -2
- package/dist/needs-you.js.map +1 -1
- package/dist/notice-delivery.d.ts +16 -0
- package/dist/notice-delivery.js +35 -0
- package/dist/notice-delivery.js.map +1 -0
- package/dist/office-share-page.d.ts +16 -0
- package/dist/office-share-page.js +85 -0
- package/dist/office-share-page.js.map +1 -0
- package/dist/office-share-service.d.ts +91 -0
- package/dist/office-share-service.js +176 -0
- package/dist/office-share-service.js.map +1 -0
- package/dist/office-share.d.ts +268 -0
- package/dist/office-share.js +574 -0
- package/dist/office-share.js.map +1 -0
- package/dist/opencode-usage-scan.d.ts +28 -0
- package/dist/opencode-usage-scan.js +92 -0
- package/dist/opencode-usage-scan.js.map +1 -0
- package/dist/opencode-usage-worker.d.ts +1 -0
- package/dist/opencode-usage-worker.js +10 -0
- package/dist/opencode-usage-worker.js.map +1 -0
- package/dist/outbound-handlers.js +22 -2
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +65 -2
- package/dist/outbound-schemas.js +56 -2
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-web-gateway.js +7 -1
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/quickstart-api.js +13 -2
- package/dist/quickstart-api.js.map +1 -1
- package/dist/quickstart.js +2 -1
- package/dist/quickstart.js.map +1 -1
- package/dist/remote-card-answer.d.ts +83 -0
- package/dist/remote-card-answer.js +208 -0
- package/dist/remote-card-answer.js.map +1 -0
- package/dist/remote-card-prompt.d.ts +38 -0
- package/dist/remote-card-prompt.js +86 -0
- package/dist/remote-card-prompt.js.map +1 -0
- package/dist/reply-triggers.d.ts +2 -0
- package/dist/reply-triggers.js +3 -0
- package/dist/reply-triggers.js.map +1 -0
- package/dist/settings-api.d.ts +2 -0
- package/dist/settings-api.js +41 -16
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +20 -14
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-effect.js +7 -1
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-instance-patch.js +4 -1
- package/dist/settings-instance-patch.js.map +1 -1
- package/dist/setup-form.d.ts +1 -1
- package/dist/setup-form.js +55 -6
- package/dist/setup-form.js.map +1 -1
- package/dist/setup-host.d.ts +9 -0
- package/dist/setup-host.js +127 -6
- package/dist/setup-host.js.map +1 -1
- package/dist/setup-signin-assets.d.ts +2 -0
- package/dist/setup-signin-assets.js +6 -0
- package/dist/setup-signin-assets.js.map +1 -0
- package/dist/setup-wizard.js +2 -0
- package/dist/setup-wizard.js.map +1 -1
- package/dist/structured-signin-transport.d.ts +8 -0
- package/dist/structured-signin-transport.js +79 -0
- package/dist/structured-signin-transport.js.map +1 -0
- package/dist/structured-signin.d.ts +131 -0
- package/dist/structured-signin.js +388 -0
- package/dist/structured-signin.js.map +1 -0
- package/dist/tool-permissions.js +29 -0
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.js +6 -2
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-sources.d.ts +27 -2
- package/dist/transcript-sources.js +104 -40
- package/dist/transcript-sources.js.map +1 -1
- package/dist/turn-reply-guard.d.ts +1 -1
- package/dist/turn-reply-guard.js +1 -1
- package/dist/turn-reply-guard.js.map +1 -1
- package/dist/types.d.ts +33 -8
- package/dist/ui/backend-signin.js +63 -10
- package/dist/ui/chat-store.js +3 -2
- package/dist/ui/chat-strings.js +4 -4
- package/dist/ui/fleet-office-editor.js +68 -11
- package/dist/ui/fleet-office-layout.js +110 -35
- package/dist/ui/fleet-office-model.js +6 -3
- package/dist/ui/fleet-office-overview.js +167 -0
- package/dist/ui/fleet-office-pack.d.ts +13 -3
- package/dist/ui/fleet-office-pack.js +214 -24
- package/dist/ui/fleet-office-skin.js +98 -23
- package/dist/ui/fleet-office-store.js +82 -5
- package/dist/ui/fleet-office-view.js +5 -4
- package/dist/ui/fleet-office-zones.js +232 -21
- package/dist/ui/fleet-office.js +549 -186
- package/dist/ui/fleet-usage.js +19 -15
- package/dist/ui/office-share-dialog.js +145 -0
- package/dist/ui/office-share-page.js +164 -0
- package/dist/ui/panel-chat.js +22 -3
- package/dist/ui/panel-log.js +4 -4
- package/dist/ui/panel-needs.js +5 -5
- package/dist/ui/panel-settings.js +38 -12
- package/dist/ui/settings-dialogs.js +8 -1
- package/dist/ui/settings-guests.js +17 -7
- package/dist/ui/settings-model.js +22 -6
- package/dist/ui/settings-registry.js +4 -0
- package/dist/ui/settings-strings.js +18 -2
- package/dist/ui/shared/app-i18n.js +4 -2
- package/dist/ui/shared/app-shell.js +14 -6
- package/dist/ui/shared/app-stream.js +2 -1
- package/dist/ui/shared/app.css +85 -4
- package/dist/ui/shared/office/cozy.png +0 -0
- package/dist/ui/shared/side-panel.js +95 -0
- package/dist/ui/structured-signin.js +115 -0
- package/dist/usage-report.d.ts +20 -0
- package/dist/usage-report.js +54 -17
- package/dist/usage-report.js.map +1 -1
- package/dist/usage-rollup.d.ts +9 -1
- package/dist/usage-rollup.js +20 -4
- package/dist/usage-rollup.js.map +1 -1
- package/dist/web-api.d.ts +23 -1
- package/dist/web-api.js +292 -3
- package/dist/web-api.js.map +1 -1
- package/dist/web-auth.js +1 -1
- package/dist/web-auth.js.map +1 -1
- package/dist/web-backend-login.d.ts +1 -7
- package/dist/web-backend-login.js +2 -24
- package/dist/web-backend-login.js.map +1 -1
- package/dist/web-office-acts.d.ts +173 -0
- package/dist/web-office-acts.js +285 -0
- package/dist/web-office-acts.js.map +1 -0
- package/dist/web-office-pack-read.d.ts +35 -0
- package/dist/web-office-pack-read.js +252 -0
- package/dist/web-office-pack-read.js.map +1 -0
- package/dist/web-office-pack-tools.d.ts +232 -0
- package/dist/web-office-pack-tools.js +754 -0
- package/dist/web-office-pack-tools.js.map +1 -0
- package/dist/web-office-skins.d.ts +71 -6
- package/dist/web-office-skins.js +321 -35
- package/dist/web-office-skins.js.map +1 -1
- package/dist/web-office-store.d.ts +5 -2
- package/dist/web-office-store.js +69 -10
- package/dist/web-office-store.js.map +1 -1
- package/dist/web-settings-patch.d.ts +2 -1
- package/dist/web-settings-patch.js +4 -1
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/working-recovery.d.ts +2 -2
- package/dist/working-recovery.js +43 -8
- package/dist/working-recovery.js.map +1 -1
- package/dist/working-state-journal.d.ts +2 -0
- package/dist/working-state-journal.js +16 -1
- package/dist/working-state-journal.js.map +1 -1
- package/package.json +3 -2
- package/templates/windows-shortcuts.ps1 +155 -140
|
@@ -27,7 +27,7 @@ import "./settings-strings.js";
|
|
|
27
27
|
import { api, attach, confirmedWrite, newKey } from "./settings-confirm.js";
|
|
28
28
|
import { dismissOperation, operationActive, restartFleet, startOperation, takeLeftover } from "./settings-apply.js";
|
|
29
29
|
import {
|
|
30
|
-
ACCESS_MODES, AGENT_MODES, DASHBOARD_FEATURES, DEFAULT_SCHEMA, ownChoiceImpact, HANG_TIMEOUT_DEFAULT_MINUTES, LOG_LEVELS, TOOL_PROGRESS, TOOL_SETS, VISIBILITY_MODES, batchImpact,
|
|
30
|
+
ACCESS_MODES, AGENT_MODES, DASHBOARD_FEATURES, SEPARATE_FEATURE_KEYS, DEFAULT_SCHEMA, ownChoiceImpact, HANG_TIMEOUT_DEFAULT_MINUTES, LOG_LEVELS, TOOL_PROGRESS, TOOL_SETS, VISIBILITY_MODES, batchImpact,
|
|
31
31
|
changedFields, channelId, channelsOf, chLabel, connectionState, dashboardDefault, effectiveSummary, fleetModel, fromYaml, fullModelRequests, groupAgents,
|
|
32
32
|
hasOwn, impactOf, localeOptions, defaultsImpact, requestImpact, nonNegative, positive, replyGuardSupported, sameValue, shortName, STATUS_ORDER, toYaml,
|
|
33
33
|
toolSetDefault, visibilityDefault, worstImpact,
|
|
@@ -46,6 +46,7 @@ import { startTour } from "./chat-tour.js";
|
|
|
46
46
|
import "./chat-strings.js";
|
|
47
47
|
import { AppearanceSection } from "./settings-appearance.js";
|
|
48
48
|
import { GuestsCard } from "./settings-guests.js";
|
|
49
|
+
import { OfficeSharesCard } from "./office-share-dialog.js";
|
|
49
50
|
import { syncStage, useDraft } from "./settings-draft.js";
|
|
50
51
|
import { WebAuthorityCard } from "./settings-web-authority.js";
|
|
51
52
|
import { SignInList } from "./backend-signin.js";
|
|
@@ -952,8 +953,14 @@ function Classic({ ctx, search, openDialog }) {
|
|
|
952
953
|
})}</div>`;
|
|
953
954
|
}
|
|
954
955
|
|
|
956
|
+
// Sign-in notices and daily tips post in the topic or not at all: the DM choice was withdrawn (hmsg-d1809f2a,
|
|
957
|
+
// hmsg-3b8ac2af), and an old "dm" reads as on.
|
|
958
|
+
const noticeMode = (v) => v !== "false" && v !== false;
|
|
959
|
+
const noticeChoices = () => [{ value: "true", label: tn("noticeTopic") }, { value: "false", label: tn("noticeOff") }];
|
|
960
|
+
const noticeLabel = (v) => tn(v ? "noticeTopic" : "noticeOff");
|
|
961
|
+
|
|
955
962
|
/** General's form, from the saved defaults (`d`) and ClassicBot's (`c`). */
|
|
956
|
-
function generalForm(d, c, fleet = {}) {
|
|
963
|
+
function generalForm(d, c, fleet = {}, schema = {}) {
|
|
957
964
|
const hang = d.hang_detector || {}, startup = d.startup || {};
|
|
958
965
|
return {
|
|
959
966
|
backend: d.backend || "claude-code", model: d.model || "", locale: d.locale || "", auto: String(d.auto_pause_after ?? 0),
|
|
@@ -966,6 +973,9 @@ function generalForm(d, c, fleet = {}) {
|
|
|
966
973
|
// #2347 §10 review: unset startup concurrency is automatic (deriveSpawnConcurrency: 2–10 by free memory and cores),
|
|
967
974
|
// not 10 — an empty field, and a save that leaves it unset (the defaults merge replaces `startup` whole).
|
|
968
975
|
concurrency: startup.concurrency == null ? "" : String(startup.concurrency), stagger: String(startup.stagger_delay_ms ?? 500),
|
|
976
|
+
tips: String(noticeMode(d.tips)),
|
|
977
|
+
replyTriggers: Boolean(d.reply_triggers ?? schema.reply_triggers_default),
|
|
978
|
+
classicReplyTriggers: Boolean(c.reply_triggers ?? d.reply_triggers ?? schema.reply_triggers_default), classicReplyTriggersInherit: !hasOwn(c, "reply_triggers"),
|
|
969
979
|
classicBackend: c.backend || d.backend || "claude-code",
|
|
970
980
|
classicToolProgress: c.tool_progress ?? d.tool_progress ?? "off", classicToolProgressInherit: !hasOwn(c, "tool_progress"),
|
|
971
981
|
classicReply: c.reply_completion_guard ?? d.reply_completion_guard ?? true, classicReplyInherit: !hasOwn(c, "reply_completion_guard"),
|
|
@@ -985,7 +995,7 @@ function General({ ctx, part = "all" }) {
|
|
|
985
995
|
const hang = d.hang_detector || {}, startup = d.startup || {};
|
|
986
996
|
const primary = channelsOf(ctx.fleet)[0];
|
|
987
997
|
const original = useMemo(() => ({ c: structuredClone(c) }), []);
|
|
988
|
-
const base = useMemo(() => generalForm(d, c, ctx.fleet), []);
|
|
998
|
+
const base = useMemo(() => generalForm(d, c, ctx.fleet, schema), []);
|
|
989
999
|
const [f, setF] = useDraft(ctx, "general", () => base);
|
|
990
1000
|
const set = (k) => (v) => setF((x) => ({ ...x, [k]: v }));
|
|
991
1001
|
/** The class of a field's row: `field`, and `s-dirty` while one of its keys differs from what is saved. */
|
|
@@ -1011,27 +1021,31 @@ function General({ ctx, part = "all" }) {
|
|
|
1011
1021
|
const defaultsPatch = changedFields({
|
|
1012
1022
|
backend: f.backend, model: f.model || undefined, locale: f.locale || null, auto_pause_after: num(f.auto),
|
|
1013
1023
|
agent_mode: f.agent_mode, tool_set: f.tool_set || null, tool_progress: f.tool_progress, cross_instance_visibility: f.visibility,
|
|
1014
|
-
reply_completion_guard: f.reply, log_level: f.log_level,
|
|
1015
|
-
// The dashboard features every agent may use unless its own setting says otherwise. All
|
|
1024
|
+
tips: noticeMode(f.tips), reply_triggers: f.replyTriggers, reply_completion_guard: f.reply, log_level: f.log_level,
|
|
1025
|
+
// The dashboard features every agent may use unless its own setting says otherwise. All of them go, because the write
|
|
1016
1026
|
// to the fleet's defaults merges top-level keys only (`dashboard` is replaced whole): the untouched ones as saved.
|
|
1017
|
-
dashboard: Object.fromEntries(DASHBOARD_FEATURES.map((k) => [k, f[`dash_${k}`]])),
|
|
1027
|
+
dashboard: Object.fromEntries(DASHBOARD_FEATURES.filter((k) => !Object.hasOwn(SEPARATE_FEATURE_KEYS, k)).map((k) => [k, f[`dash_${k}`]])),
|
|
1028
|
+
...Object.fromEntries(Object.entries(SEPARATE_FEATURE_KEYS).map(([k, key]) => [key, f[`dash_${k}`]])),
|
|
1018
1029
|
hang_detector: { enabled: f.hangOn, timeout_minutes: num(f.hang) },
|
|
1019
1030
|
startup: { ...(f.concurrency.trim() === "" ? {} : { concurrency: num(f.concurrency) }), stagger_delay_ms: num(f.stagger) },
|
|
1020
1031
|
}, {
|
|
1021
1032
|
backend: d.backend || "claude-code", model: d.model || undefined, locale: d.locale || null, auto_pause_after: d.auto_pause_after ?? 0,
|
|
1022
1033
|
agent_mode: d.agent_mode || "mcp", tool_set: TOOL_SETS.includes(d.tool_set) ? d.tool_set : null, tool_progress: d.tool_progress ?? "off",
|
|
1023
|
-
cross_instance_visibility: visibilityDefault(d), reply_completion_guard: d.reply_completion_guard ?? true, log_level: d.log_level || "info",
|
|
1024
|
-
dashboard: Object.fromEntries(DASHBOARD_FEATURES.map((k) => [k, dashboardDefault(d, k)])),
|
|
1034
|
+
tips: d.tips ?? true, cross_instance_visibility: visibilityDefault(d), reply_triggers: Boolean(d.reply_triggers ?? schema.reply_triggers_default), reply_completion_guard: d.reply_completion_guard ?? true, log_level: d.log_level || "info",
|
|
1035
|
+
dashboard: Object.fromEntries(DASHBOARD_FEATURES.filter((k) => !Object.hasOwn(SEPARATE_FEATURE_KEYS, k)).map((k) => [k, dashboardDefault(d, k)])),
|
|
1036
|
+
...Object.fromEntries(Object.entries(SEPARATE_FEATURE_KEYS).map(([k, key]) => [key, dashboardDefault(d, k)])),
|
|
1025
1037
|
hang_detector: { enabled: hang.enabled !== false, timeout_minutes: hang.timeout_minutes ?? HANG_TIMEOUT_DEFAULT_MINUTES },
|
|
1026
1038
|
startup: { ...(startup.concurrency == null ? {} : { concurrency: startup.concurrency }), stagger_delay_ms: startup.stagger_delay_ms ?? 500 },
|
|
1027
1039
|
});
|
|
1028
1040
|
const oc = original.c;
|
|
1029
1041
|
const classicPatch = changedFields({
|
|
1042
|
+
reply_triggers: f.classicReplyTriggersInherit ? null : f.classicReplyTriggers,
|
|
1030
1043
|
backend: f.classicBackend,
|
|
1031
1044
|
tool_progress: f.classicToolProgressInherit ? null : f.classicToolProgress,
|
|
1032
1045
|
reply_completion_guard: f.classicReplyInherit ? null : f.classicReply,
|
|
1033
1046
|
admin_users: f.admins, allowed_guilds: f.guilds,
|
|
1034
1047
|
}, {
|
|
1048
|
+
reply_triggers: hasOwn(oc, "reply_triggers") ? oc.reply_triggers : null,
|
|
1035
1049
|
backend: oc.backend || d.backend || "claude-code",
|
|
1036
1050
|
tool_progress: hasOwn(oc, "tool_progress") ? oc.tool_progress : null,
|
|
1037
1051
|
reply_completion_guard: hasOwn(oc, "reply_completion_guard") ? oc.reply_completion_guard : null,
|
|
@@ -1054,7 +1068,7 @@ function General({ ctx, part = "all" }) {
|
|
|
1054
1068
|
// ClassicBot's inherited ones say what they inherit from Agent defaults.
|
|
1055
1069
|
const unset = {
|
|
1056
1070
|
locale: !d.locale, backend: !d.backend, model: !d.model, auto: !hasOwn(d, "auto_pause_after"), tool_progress: !hasOwn(d, "tool_progress"),
|
|
1057
|
-
visibility: !VISIBILITY_MODES.includes(d.cross_instance_visibility), reply: !hasOwn(d, "reply_completion_guard"), tool_set: !d.tool_set,
|
|
1071
|
+
tips: !hasOwn(d, "tips"), replyTriggers: !hasOwn(d, "reply_triggers"), visibility: !VISIBILITY_MODES.includes(d.cross_instance_visibility), reply: !hasOwn(d, "reply_completion_guard"), tool_set: !d.tool_set,
|
|
1058
1072
|
log_level: !d.log_level, agent_mode: !d.agent_mode, hangOn: !hasOwn(hang, "enabled"), hang: !hasOwn(hang, "timeout_minutes"),
|
|
1059
1073
|
concurrency: !hasOwn(startup, "concurrency"), stagger: !hasOwn(startup, "stagger_delay_ms"),
|
|
1060
1074
|
};
|
|
@@ -1077,6 +1091,8 @@ function General({ ctx, part = "all" }) {
|
|
|
1077
1091
|
<div class=${fc("field", "tool_progress")}>${L(tn("toolProgress"), "defaults.tool_progress", "g-tp", "tool_progress")}<${Select} id="g-tp" value=${f.tool_progress} onChange=${set("tool_progress")} options=${TOOL_PROGRESS} /></div>
|
|
1078
1092
|
<div class=${fc("field", "visibility")}>${L(tn("crossInstanceVisibility"), "defaults.cross_instance_visibility", "g-vis", "visibility")}<${Select} id="g-vis" value=${f.visibility} onChange=${set("visibility")} options=${VISIBILITY_MODES} />
|
|
1079
1093
|
<p class="note">${tn("crossInstanceVisibilityHint")}</p></div>
|
|
1094
|
+
<div class=${fc("field", "tips")}>${L(tn("dailyTips"), "defaults.tips", "g-tips", "tips")}<${Select} id="g-tips" value=${f.tips} onChange=${set("tips")} options=${noticeChoices()} /><${InEffect} text=${noticeLabel(noticeMode(f.tips))} /><p class="note">${tn("dailyTipsHint")}</p></div>
|
|
1095
|
+
<div class=${fc("field", "replyTriggers")}><label class="check"><input id="g-reply-triggers" type="checkbox" checked=${f.replyTriggers} onChange=${(e) => set("replyTriggers")(e.target.checked)} /><span>${tn("replyTriggers")}</span>${dm("replyTriggers")}<${Impact} schema=${schema} field="defaults.reply_triggers" /></label><p class="note">${tn("replyTriggersHint")}</p></div>
|
|
1080
1096
|
<div class=${fc("field", "reply")}><label class="check"><input id="g-reply" type="checkbox" checked=${f.reply} onChange=${(e) => set("reply")(e.target.checked)} /><span>${tn("replyCompletionGuard")}</span>${dm("reply")}<${Impact} schema=${schema} field="defaults.reply_completion_guard" /></label>
|
|
1081
1097
|
<p class="note">${fleetReply}</p></div>
|
|
1082
1098
|
</div>
|
|
@@ -1093,6 +1109,9 @@ function General({ ctx, part = "all" }) {
|
|
|
1093
1109
|
<div class=${fc("field", "classicToolProgress", "classicToolProgressInherit")}>${L(tn("toolProgress"), "classic_defaults.tool_progress", "g-ctp")}
|
|
1094
1110
|
<${Override} inherit=${f.classicToolProgressInherit} onInherit=${set("classicToolProgressInherit")} inherited=${fromDefaults("tool_progress", d.tool_progress ?? "off", "#g-tp")}>
|
|
1095
1111
|
<${Select} id="g-ctp" disabled=${f.classicToolProgressInherit} value=${f.classicToolProgressInherit ? (d.tool_progress ?? "off") : f.classicToolProgress} onChange=${set("classicToolProgress")} options=${TOOL_PROGRESS} /></${Override}></div>
|
|
1112
|
+
<div class=${fc("field", "classicReplyTriggers", "classicReplyTriggersInherit")}>${L(tn("replyTriggers"), "classic_defaults.reply_triggers")}
|
|
1113
|
+
<${Override} inherit=${f.classicReplyTriggersInherit} onInherit=${set("classicReplyTriggersInherit")} inherited=${fromDefaults("reply_triggers", Boolean(d.reply_triggers ?? schema.reply_triggers_default), "#g-reply-triggers")}>
|
|
1114
|
+
<label class="check"><input id="g-creply-triggers" type="checkbox" disabled=${f.classicReplyTriggersInherit} checked=${f.classicReplyTriggersInherit ? Boolean(d.reply_triggers ?? schema.reply_triggers_default) : f.classicReplyTriggers} onChange=${(e) => set("classicReplyTriggers")(e.target.checked)} /><span>${tn("replyTriggers")}</span></label></${Override}><p class="note">${tn("replyTriggersHint")}</p></div>
|
|
1096
1115
|
<div class=${fc("field", "classicReply", "classicReplyInherit")}>${L(tn("replyCompletionGuard"), "classic_defaults.reply_completion_guard")}
|
|
1097
1116
|
<${Override} inherit=${f.classicReplyInherit} onInherit=${set("classicReplyInherit")} inherited=${fromDefaults("reply_completion_guard", d.reply_completion_guard ?? true, "#g-reply")}>
|
|
1098
1117
|
<label class="check"><input id="g-creply" type="checkbox" disabled=${f.classicReplyInherit} checked=${f.classicReplyInherit ? (d.reply_completion_guard ?? true) : f.classicReply} onChange=${(e) => set("classicReply")(e.target.checked)} /><span>${tn("replyCompletionGuard")}</span></label></${Override}>
|
|
@@ -1140,7 +1159,7 @@ function General({ ctx, part = "all" }) {
|
|
|
1140
1159
|
* the temporary public link none of it can be changed — the form says so and stays disabled (the server refuses too).
|
|
1141
1160
|
*/
|
|
1142
1161
|
export const WEB_READ_ONLY = [
|
|
1143
|
-
"web.allowed_hosts", "web.view_access", "web.
|
|
1162
|
+
"web.allowed_hosts", "web.view_access", "web.preview", "web.preview_port", "web.preview_origin", "web.preview_on_public_link",
|
|
1144
1163
|
"web.usage_panel", "web.search", "web.provider_secrets", "web.upload_max_file_mb", "web.upload_max_total_mb", "web_terminal.bind", "web_terminal.tunnel",
|
|
1145
1164
|
];
|
|
1146
1165
|
/**
|
|
@@ -1173,6 +1192,7 @@ function WebSection({ ctx, staged, part = "all" }) {
|
|
|
1173
1192
|
// serves their reads there).
|
|
1174
1193
|
const overPublicLink = globalThis.document?.body?.dataset?.publicLink === "1";
|
|
1175
1194
|
const original = useMemo(() => ({
|
|
1195
|
+
notify: noticeMode(web.notify_login),
|
|
1176
1196
|
echo: web.echo_to_channel ?? true,
|
|
1177
1197
|
log: web.log_tab === true, // #1218: off by default
|
|
1178
1198
|
usagePub: web.usage_report_on_public_link === true, // #2122: off by default
|
|
@@ -1182,7 +1202,7 @@ function WebSection({ ctx, staged, part = "all" }) {
|
|
|
1182
1202
|
}), []);
|
|
1183
1203
|
const text = (v) => (v === null || v === undefined ? "" : String(v));
|
|
1184
1204
|
/** #2347: a field's row class: `s-dirty` while it differs from what is saved (the draft may come from before). */
|
|
1185
|
-
const savedForm = useMemo(() => ({ echo: original.echo, log: original.log, usagePub: original.usagePub, pub: original.pub.allow_public,
|
|
1205
|
+
const savedForm = useMemo(() => ({ notify: String(original.notify), echo: original.echo, log: original.log, usagePub: original.usagePub, pub: original.pub.allow_public,
|
|
1186
1206
|
ttl: String(original.pub.ttl_minutes), protocol: original.pub.protocol, hostname: original.pub.hostname, originPort: String(original.pub.origin_port),
|
|
1187
1207
|
abs: text(original.session.absolute_hours), idle: text(original.session.idle_hours), termOn: original.terminal.enabled !== false,
|
|
1188
1208
|
termTtl: text(original.terminal.ttl_minutes), autoOpen: original.pub.auto_open }), []);
|
|
@@ -1194,6 +1214,7 @@ function WebSection({ ctx, staged, part = "all" }) {
|
|
|
1194
1214
|
const pub = pending.public_link || {}, session = pending.session?.local || {}, terminal = pending.web_terminal || {};
|
|
1195
1215
|
const pick = (obj, key, fallback) => Object.prototype.hasOwnProperty.call(obj, key) ? obj[key] : fallback;
|
|
1196
1216
|
return {
|
|
1217
|
+
notify: String(pick(pending, "notify_login", original.notify)),
|
|
1197
1218
|
echo: pick(pending, "echo_to_channel", original.echo), log: pick(pending, "log_tab", original.log), usagePub: pick(pending, "usage_report_on_public_link", original.usagePub),
|
|
1198
1219
|
pub: pick(pub, "allow_public", original.pub.allow_public), ttl: String(pick(pub, "ttl_minutes", original.pub.ttl_minutes)), protocol: pick(pub, "protocol", original.pub.protocol),
|
|
1199
1220
|
hostname: pick(pub, "hostname", original.pub.hostname), originPort: String(pick(pub, "origin_port", original.pub.origin_port)), autoOpen: pick(pub, "auto_open", original.pub.auto_open),
|
|
@@ -1242,6 +1263,7 @@ function WebSection({ ctx, staged, part = "all" }) {
|
|
|
1242
1263
|
const terminalPatch = changedFields({ enabled: f.termOn === (original.terminal.enabled !== false) ? original.terminal.enabled : f.termOn ? null : false,
|
|
1243
1264
|
ttl_minutes: value(f.termTtl) }, original.terminal);
|
|
1244
1265
|
const body = {
|
|
1266
|
+
...(noticeMode(f.notify) !== original.notify ? { notify_login: noticeMode(f.notify) } : {}),
|
|
1245
1267
|
...(f.echo !== original.echo ? { echo_to_channel: f.echo } : {}),
|
|
1246
1268
|
...(f.log !== original.log ? { log_tab: f.log } : {}),
|
|
1247
1269
|
...(f.usagePub !== original.usagePub ? { usage_report_on_public_link: f.usagePub } : {}),
|
|
@@ -1250,6 +1272,7 @@ function WebSection({ ctx, staged, part = "all" }) {
|
|
|
1250
1272
|
...(Object.keys(terminalPatch).length ? { web_terminal: terminalPatch } : {}),
|
|
1251
1273
|
};
|
|
1252
1274
|
const fields = [
|
|
1275
|
+
...(body.notify_login !== undefined ? ["web.notify_login"] : []),
|
|
1253
1276
|
...(body.echo_to_channel !== undefined ? ["web.echo_to_channel"] : []),
|
|
1254
1277
|
...(body.log_tab !== undefined ? ["web.log_tab"] : []),
|
|
1255
1278
|
...(body.usage_report_on_public_link !== undefined ? ["web.usage_report_on_public_link"] : []),
|
|
@@ -1297,6 +1320,7 @@ function WebSection({ ctx, staged, part = "all" }) {
|
|
|
1297
1320
|
${overPublicLink && part !== "readonly" ? html`<p class="note" role="status" id="webPublicRefused">${tn("webPublicRefused")}</p>` : null}
|
|
1298
1321
|
${has("access") ? lock(html`<section class="card"><h3>${tn("webSessionTitle")}</h3>
|
|
1299
1322
|
<p class="note">${tn("webSessionHint")}</p>
|
|
1323
|
+
<div class=${fc("field", "notify")}><label for="webNotifyLogin">${tn("webNotifyLogin")}<${Impact} schema=${schema} field="web.notify_login" /></label><${Select} id="webNotifyLogin" value=${f.notify} onChange=${set("notify")} options=${noticeChoices()} /><${InEffect} text=${noticeLabel(noticeMode(f.notify))} />${web.notify_login === undefined ? html`<${DefaultMark} />` : null}<p class="note">${tn("webNotifyLoginHint")}</p></div>
|
|
1300
1324
|
<div class="grid2">
|
|
1301
1325
|
<div class=${fc("field", "abs")}><label for="webSessionAbsolute">${tn("sessionAbsolute")}</label><input id="webSessionAbsolute" type="number" min="1" max="720" step="any"
|
|
1302
1326
|
class=${errors.abs ? "invalid" : ""} value=${f.abs} onInput=${(e) => set("abs")(e.target.value)} /><${Feedback} error=${errors.abs} />
|
|
@@ -1331,7 +1355,9 @@ function WebSection({ ctx, staged, part = "all" }) {
|
|
|
1331
1355
|
${named || f.autoOpen ? html`<label class=${fc("check", "autoOpen")}><input id="publicAutoOpen" type="checkbox" checked=${f.autoOpen} onChange=${(e) => set("autoOpen")(e.target.checked)} /><span>${tn("publicAutoOpen")}</span><${Impact} schema=${schema} field="web.public_link.auto_open" /></label>
|
|
1332
1356
|
<p class="note">${tn("publicAutoOpenHint")}</p><${Feedback} error=${errors.autoOpen} />` : null}
|
|
1333
1357
|
</section>`) : null}
|
|
1334
|
-
${has("access") && !overPublicLink ? html`<${PublicTunnelToken}
|
|
1358
|
+
${has("access") && !overPublicLink ? html`<${PublicTunnelToken} />` : null}
|
|
1359
|
+
${has("access") ? html`<${OfficeSharesCard} />` : null}
|
|
1360
|
+
${has("access") && !overPublicLink ? html`<${GuestsCard} ctx=${ctx} staged=${staged} /><${WebAuthorityCard} ctx=${ctx} staged=${staged} />` : null}
|
|
1335
1361
|
${has("chat") ? lock(html`<section class="card"><h3>${tn("webChat")}</h3>
|
|
1336
1362
|
<label class=${fc("check", "echo")}><input id="webEchoToChannel" type="checkbox" checked=${f.echo} onChange=${(e) => set("echo")(e.target.checked)} /><span>${tn("webEcho")}</span><${Impact} schema=${schema} field="web.echo_to_channel" /></label>
|
|
1337
1363
|
<p class="note">${tn("webEchoHint")}</p>
|
|
@@ -642,6 +642,7 @@ export function ClassicDialog({ room, ctx, onClose }) {
|
|
|
642
642
|
const inherited = {
|
|
643
643
|
backend: cd.backend || fd.backend || "claude-code", model: cd.model || fd.model || "",
|
|
644
644
|
auto_pause_after: cd.auto_pause_after ?? fd.auto_pause_after ?? 0, tool_progress: cd.tool_progress ?? fd.tool_progress ?? "off",
|
|
645
|
+
reply_triggers: Boolean(cd.reply_triggers ?? fd.reply_triggers ?? schema.reply_triggers_default),
|
|
645
646
|
reply_completion_guard: cd.reply_completion_guard ?? fd.reply_completion_guard ?? true,
|
|
646
647
|
};
|
|
647
648
|
const c = room;
|
|
@@ -649,8 +650,9 @@ export function ClassicDialog({ room, ctx, onClose }) {
|
|
|
649
650
|
backend: c.backend || inherited.backend, model: c.model || "",
|
|
650
651
|
auto_pause_after: String(c.auto_pause_after ?? inherited.auto_pause_after), tool_progress: c.tool_progress ?? inherited.tool_progress,
|
|
651
652
|
reply_completion_guard: c.reply_completion_guard ?? inherited.reply_completion_guard,
|
|
653
|
+
reply_triggers: c.reply_triggers ?? inherited.reply_triggers,
|
|
652
654
|
collab: !!c.collab, web_echo: classicWebEchoEffective(c, fleet), context_lines: String(c.context_lines ?? cd.context_lines ?? 5),
|
|
653
|
-
inherit: { auto_pause_after: !hasOwn(c, "auto_pause_after"), tool_progress: !hasOwn(c, "tool_progress"), reply_completion_guard: !hasOwn(c, "reply_completion_guard") },
|
|
655
|
+
inherit: { reply_triggers: !hasOwn(c, "reply_triggers"), auto_pause_after: !hasOwn(c, "auto_pause_after"), tool_progress: !hasOwn(c, "tool_progress"), reply_completion_guard: !hasOwn(c, "reply_completion_guard") },
|
|
654
656
|
}));
|
|
655
657
|
const set = (k) => (v) => setF((x) => ({ ...x, [k]: v }));
|
|
656
658
|
const setInherit = (k) => (on) => setF((x) => ({ ...x, inherit: { ...x.inherit, [k]: on } }));
|
|
@@ -664,12 +666,14 @@ export function ClassicDialog({ room, ctx, onClose }) {
|
|
|
664
666
|
auto_pause_after: f.inherit.auto_pause_after ? null : Number(f.auto_pause_after),
|
|
665
667
|
tool_progress: f.inherit.tool_progress ? null : f.tool_progress,
|
|
666
668
|
reply_completion_guard: f.inherit.reply_completion_guard ? null : f.reply_completion_guard,
|
|
669
|
+
reply_triggers: f.inherit.reply_triggers ? null : f.reply_triggers,
|
|
667
670
|
collab: f.collab, context_lines: Number(f.context_lines), web_echo: f.web_echo,
|
|
668
671
|
}, {
|
|
669
672
|
backend: c.backend || inherited.backend, model: (c.model && c.model.trim()) || null,
|
|
670
673
|
auto_pause_after: hasOwn(c, "auto_pause_after") ? c.auto_pause_after : null,
|
|
671
674
|
tool_progress: hasOwn(c, "tool_progress") ? c.tool_progress : null,
|
|
672
675
|
reply_completion_guard: hasOwn(c, "reply_completion_guard") ? c.reply_completion_guard : null,
|
|
676
|
+
reply_triggers: hasOwn(c, "reply_triggers") ? c.reply_triggers : null,
|
|
673
677
|
collab: !!c.collab, context_lines: c.context_lines ?? cd.context_lines ?? 5, web_echo: classicWebEchoEffective(c, fleet),
|
|
674
678
|
});
|
|
675
679
|
const stage = async () => {
|
|
@@ -707,6 +711,9 @@ export function ClassicDialog({ room, ctx, onClose }) {
|
|
|
707
711
|
<label class="check"><input type="checkbox" disabled=${f.inherit.reply_completion_guard} checked=${f.inherit.reply_completion_guard ? inherited.reply_completion_guard : f.reply_completion_guard}
|
|
708
712
|
onChange=${(e) => set("reply_completion_guard")(e.target.checked)} /><span>${tn("replyCompletionGuard")}</span></label></${Override}>
|
|
709
713
|
<p class="note">${replyHint(f.backend, classicMode, fd.kiro_ui)}</p></div>
|
|
714
|
+
<div class="field">${L(tn("replyTriggers"), "classic.reply_triggers")}
|
|
715
|
+
<${Override} inherit=${f.inherit.reply_triggers} onInherit=${setInherit("reply_triggers")} inherited=${roomInh("reply_triggers", "", "#g-creply-triggers", "#g-reply-triggers")}>
|
|
716
|
+
<label class="check"><input type="checkbox" disabled=${f.inherit.reply_triggers} checked=${f.inherit.reply_triggers ? inherited.reply_triggers : f.reply_triggers} onChange=${(e) => set("reply_triggers")(e.target.checked)} /><span>${tn("replyTriggers")}</span></label></${Override}><p class="note">${tn("replyTriggersHint")}</p></div>
|
|
710
717
|
<label class="check"><input type="checkbox" checked=${f.collab} onChange=${(e) => set("collab")(e.target.checked)} /><span>${tn("collabMode")}</span><${Impact} schema=${schema} field="classic.collab" /></label>
|
|
711
718
|
<label class="check"><input type="checkbox" checked=${f.web_echo} onChange=${(e) => set("web_echo")(e.target.checked)} /><span>${tn("webEcho")}</span><${Impact} schema=${schema} field="classic.web_echo" /></label>
|
|
712
719
|
</div>
|
|
@@ -60,11 +60,19 @@ function wroteTo(names) {
|
|
|
60
60
|
return html`${before}${names.map((n, i) => html`${i ? ", " : ""}<span key=${n} class="g-wrote">${n}</span>`)}${after}`;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
/** #2667: a granted name as a person reads it — a ClassicBot room by its display name, when it has one. */
|
|
64
|
+
const shownName = (rooms, n) => { const r = (rooms || []).find((x) => x.name === n); return (r && r.display_name) || n; };
|
|
65
|
+
|
|
66
|
+
/** The agents to choose from: fleet.yaml's instances, then (#2667) the ClassicBot rooms, under their own heading. */
|
|
67
|
+
function Names({ id, all, rooms = [], value, wrote = [], onChange }) {
|
|
64
68
|
const chosen = new Set(value || []);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
<
|
|
69
|
+
const order = [...all, ...rooms.map((r) => r.name)];
|
|
70
|
+
const box = (n, label, note) => html`<label key=${n} class="check guest-name" title=${note ? n : undefined}>
|
|
71
|
+
<input type="checkbox" checked=${chosen.has(n)} onChange=${(e) => { const s = new Set(chosen); if (e.target.checked) s.add(n); else s.delete(n); onChange(order.filter((x) => s.has(x))); }} />
|
|
72
|
+
<span>${label}${note ? html` <span class="note">${n}</span>` : null}${wrote.includes(n) ? html` <span class="note">${tn("grantsWroteHere")}</span>` : null}</span></label>`;
|
|
73
|
+
return html`<div class="guest-names" id=${id} role="group">${all.map((n) => box(n, n, false))}
|
|
74
|
+
${rooms.length ? html`<span class="guest-names-group note" key="--rooms">${tn("grantsClassicRooms")}</span>` : null}
|
|
75
|
+
${rooms.map((r) => box(r.name, r.display_name || r.name, !!r.display_name))}</div>`;
|
|
68
76
|
}
|
|
69
77
|
|
|
70
78
|
const clock = (ms) => new Date(ms).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
@@ -147,6 +155,8 @@ export function GuestsSection({ ctx, staged }) {
|
|
|
147
155
|
const setGrant = (k, grant) => { setStatus(null); setF((x) => { const g = { ...(x.grants || {}) }; if (grant) g[k] = grant; else delete g[k]; return { ...x, grants: g }; }); };
|
|
148
156
|
const guests = (overview && overview.guests) || [];
|
|
149
157
|
const instances = (overview && overview.instances) || [];
|
|
158
|
+
const rooms = (overview && Array.isArray(overview.rooms) && overview.rooms) || [];
|
|
159
|
+
const choosable = [...instances, ...rooms.map((r) => r.name)];
|
|
150
160
|
const who = (k) => {
|
|
151
161
|
const g = guests.find((x) => accountKey(x) === k), p = (people || []).find((x) => accountKey(x) === k);
|
|
152
162
|
const grant = (f.grants && f.grants[k]) || (original.grants && original.grants[k]);
|
|
@@ -223,10 +233,10 @@ export function GuestsSection({ ctx, staged }) {
|
|
|
223
233
|
<div class="g-head"><span class="g-av" aria-hidden="true">${(person.name || "?").slice(0, 1).toUpperCase()}</span>
|
|
224
234
|
<div class="g-id"><strong>${person.name}</strong> <span class="note">${PLATFORMS[person.platform] || person.platform}${person.username ? ` · @${person.username}` : ""}</span></div>
|
|
225
235
|
${removed ? html`<span class="g-state">${tn("grantsWillBeRemoved")}</span>` : added ? html`<span class="g-state">${tn("grantsNew")}</span>` : pill(person)}</div>
|
|
226
|
-
<div class="g-chips">${((draft || saved).instances || []).map((n) => html`<span key=${n} class="g-chip">${n}</span>`)}</div>
|
|
236
|
+
<div class="g-chips">${((draft || saved).instances || []).map((n) => html`<span key=${n} class="g-chip" title=${shownName(rooms, n) !== n ? n : undefined}>${shownName(rooms, n)}</span>`)}</div>
|
|
227
237
|
${draft && !draft.instances.length ? html`<p class="note g-error" role="alert">${tn("grantsNoAgents")}</p>` : null}
|
|
228
238
|
${editing === k && draft ? html`<div class="g-edit"><p class="note">${tn("grantsMaySee", person.name)}</p>
|
|
229
|
-
<${Names} id=${`grant-${k}`} all=${instances} value=${draft.instances} wrote=${person.wrote} onChange=${(list) => setGrant(k, { ...draft, instances: list })} /></div>` : null}
|
|
239
|
+
<${Names} id=${`grant-${k}`} all=${instances} rooms=${rooms} value=${draft.instances} wrote=${person.wrote} onChange=${(list) => setGrant(k, { ...draft, instances: list })} /></div>` : null}
|
|
230
240
|
${readOnly ? null : html`<div class="guest-actions">
|
|
231
241
|
${draft ? html`<button type="button" class="btn btn-sm" aria-expanded=${editing === k ? "true" : "false"} onClick=${() => setEditing(editing === k ? null : k)}>${tn("grantsEditAgents")}</button>` : null}
|
|
232
242
|
${draft ? html`<button type="button" class="btn btn-sm g-send" disabled=${!applied || ss.sending || cooling || !f.enabled || !original.enabled}
|
|
@@ -245,7 +255,7 @@ export function GuestsSection({ ctx, staged }) {
|
|
|
245
255
|
<span class="g-av" aria-hidden="true">${(p.name || "?").slice(0, 1).toUpperCase()}</span>
|
|
246
256
|
<div class="g-id"><strong>${p.name}</strong> <span class="note">${PLATFORMS[p.platform] || p.platform}${p.username ? ` · @${p.username}` : ""} · <span class="g-when">${tn("grantsLastSeen", new Date(p.lastSeen).toLocaleString())}</span></span>
|
|
247
257
|
${p.instances && p.instances.length ? html`<div class="note">${wroteTo(p.instances)}</div>` : null}</div>
|
|
248
|
-
<button type="button" class="btn btn-sm" onClick=${() => { const k = accountKey(p); setGrant(k, { ...(p.name ? { name: p.name } : {}), instances:
|
|
258
|
+
<button type="button" class="btn btn-sm" onClick=${() => { const k = accountKey(p); setGrant(k, { ...(p.name ? { name: p.name } : {}), instances: choosable.filter((n) => (p.instances || []).includes(n)) }); setEditing(k); }}>${tn("grantsChoose")}</button></li>`)}</ul>`}`}
|
|
249
259
|
</fieldset>
|
|
250
260
|
${overview && overview.audit ? html`<h4>${tn("grantsRecent")}</h4>${!overview.audit.length ? html`<p class="note" id="grantsRecentNone">${tn("grantsRecentNone")}</p>`
|
|
251
261
|
: html`<ul class="g-audit" id="grantsRecentList">${overview.audit.map((e, i) => html`<li key=${`${e.at}-${i}`} class="g-audit-row" data-kind=${e.kind}>
|
|
@@ -40,20 +40,32 @@ export function changedFields(next, baseline) {
|
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* The dashboard features an agent may use (dashboard-permissions.ts): each "inherit" (the fleet default: `defaults.dashboard`,
|
|
43
|
-
* else allowed), "on" or "off". The patch names only the features that changed: null
|
|
43
|
+
* else allowed — off for OFF_UNLESS_ON, `office` and `office_packs`), "on" or "off". The patch names only the features that changed: null
|
|
44
|
+
* follows the default again.
|
|
44
45
|
*/
|
|
45
|
-
export const DASHBOARD_FEATURES = ["appearance", "task_board", "web_settings"];
|
|
46
|
+
export const DASHBOARD_FEATURES = ["appearance", "task_board", "web_settings", "office", "office_packs"];
|
|
47
|
+
/** #2578, #2692: the features a person switches on — unset is off (dashboard-permissions.ts OFF_UNLESS_ON). */
|
|
48
|
+
export const OFF_UNLESS_ON = ["office", "office_packs"];
|
|
49
|
+
/** #2601, #2692: the features kept beside `dashboard` under their own key (dashboard-permissions.ts SEPARATE_FEATURE_KEYS). */
|
|
50
|
+
export const SEPARATE_FEATURE_KEYS = { office: "office_access", office_packs: "office_pack_access" };
|
|
46
51
|
export const DASHBOARD_CHOICES = ["inherit", "on", "off"];
|
|
47
52
|
const dashboardOf = (v) => (v && typeof v === "object" && !Array.isArray(v) ? v : {});
|
|
48
|
-
/** What a feature is for an agent with no setting of its own: the default's, else allowed. */
|
|
49
|
-
export const dashboardDefault = (defaults, feature) =>
|
|
53
|
+
/** What a feature is for an agent with no setting of its own: the default's, else allowed (off for OFF_UNLESS_ON). */
|
|
54
|
+
export const dashboardDefault = (defaults, feature) => {
|
|
55
|
+
const key = Object.hasOwn(SEPARATE_FEATURE_KEYS, feature) ? SEPARATE_FEATURE_KEYS[feature] : null;
|
|
56
|
+
const v = key && defaults && Object.hasOwn(defaults, key) ? defaults[key] : dashboardOf(defaults && defaults.dashboard)[feature];
|
|
57
|
+
return OFF_UNLESS_ON.includes(feature) ? v === true : v !== false;
|
|
58
|
+
};
|
|
50
59
|
export function dashboardForm(inst) {
|
|
51
|
-
const own = dashboardOf(inst.dashboard);
|
|
60
|
+
const own = { ...dashboardOf(inst.dashboard) };
|
|
61
|
+
for (const [feature, key] of Object.entries(SEPARATE_FEATURE_KEYS)) if (Object.hasOwn(inst, key)) own[feature] = inst[key];
|
|
52
62
|
return Object.fromEntries(DASHBOARD_FEATURES.map((f) => [f, own[f] === true ? "on" : own[f] === false ? "off" : "inherit"]));
|
|
53
63
|
}
|
|
54
64
|
export function dashboardPatchValue(choices) {
|
|
55
|
-
return Object.fromEntries(DASHBOARD_FEATURES.map((f) => [f, choices[f] === "on" ? true : choices[f] === "off" ? false : null]));
|
|
65
|
+
return Object.fromEntries(DASHBOARD_FEATURES.filter((f) => !Object.hasOwn(SEPARATE_FEATURE_KEYS, f)).map((f) => [f, choices[f] === "on" ? true : choices[f] === "off" ? false : null]));
|
|
56
66
|
}
|
|
67
|
+
/** A separately kept feature's own key in a patch (office_access, office_pack_access): true, false or null (inherit). */
|
|
68
|
+
export const separateChoice = (choice) => (choice === "on" ? true : choice === "off" ? false : null);
|
|
57
69
|
|
|
58
70
|
/** #1302: cross-instance notices. Unset, or a value the fleet does not know, means full. */
|
|
59
71
|
export const visibilityDefault = (defaults) => (VISIBILITY_MODES.includes(defaults && defaults.cross_instance_visibility) ? defaults.cross_instance_visibility : "full");
|
|
@@ -175,6 +187,8 @@ export function agentPatch(form, inst, defaults, visibilityBaseline, statusEmoji
|
|
|
175
187
|
display_name: form.inherit.display_name ? null : form.display_name.trim(),
|
|
176
188
|
status_emojis: form.status_emojis,
|
|
177
189
|
dashboard: dashboardPatchValue(form.dashboard),
|
|
190
|
+
office_access: separateChoice(form.dashboard.office),
|
|
191
|
+
office_pack_access: separateChoice(form.dashboard.office_packs),
|
|
178
192
|
};
|
|
179
193
|
return changedFields(next, {
|
|
180
194
|
backend: inst.backend || defaults.backend || "claude-code",
|
|
@@ -198,6 +212,8 @@ export function agentPatch(form, inst, defaults, visibilityBaseline, statusEmoji
|
|
|
198
212
|
display_name: hasOwn(inst, "display_name") ? inst.display_name : null,
|
|
199
213
|
status_emojis: statusEmojisBaseline,
|
|
200
214
|
dashboard: dashboardPatchValue(dashboardForm(inst)),
|
|
215
|
+
office_access: separateChoice(dashboardForm(inst).office),
|
|
216
|
+
office_pack_access: separateChoice(dashboardForm(inst).office_packs),
|
|
201
217
|
});
|
|
202
218
|
}
|
|
203
219
|
|
|
@@ -33,6 +33,8 @@ const ROWS = [
|
|
|
33
33
|
// Fleet · Agents
|
|
34
34
|
["agents.new", "agents", "#newAgentBtn", "settings.newAgent", null, ["new agent", "create", "add agent", "instance"], ["新增 agent", "建立", "新 agent"]],
|
|
35
35
|
["agents.provider-keys", "agents", ".s-provider-keys", "settings.providerKeys", "web.provider_secrets", ["api key", "provider", "openai", "anthropic", "token", "secret"], ["API 金鑰", "金鑰", "供應商", "token"]],
|
|
36
|
+
["defaults.tips", "agent-defaults", "#g-tips", "settings.dailyTips", "defaults.tips", ["daily tips", "notices"], ["每日提示"]],
|
|
37
|
+
["web.notify-login", "access", "#webNotifyLogin", "settings.webNotifyLogin", "web.notify_login", ["sign in", "login", "notices"], ["登入通知"]],
|
|
36
38
|
// Fleet · Agent defaults
|
|
37
39
|
["defaults.locale", "agent-defaults", "#g-locale", "settings.language", "defaults.locale", ["language", "bot language", "reply language", "locale"], ["語言", "回覆語言", "bot 語言"]],
|
|
38
40
|
["defaults.backend", "agent-defaults", "#g-be", "settings.defaultBackend", "defaults.backend", ["backend", "cli", "claude", "codex", "kiro"], ["後端", "CLI"]],
|
|
@@ -40,6 +42,8 @@ const ROWS = [
|
|
|
40
42
|
["defaults.auto-pause", "agent-defaults", "#g-auto", "settings.autoPause", "defaults.auto_pause_after", ["auto pause", "idle", "sleep", "minutes"], ["自動暫停", "閒置", "休眠"]],
|
|
41
43
|
["defaults.tool-progress", "agent-defaults", "#g-tp", "settings.toolProgress", "defaults.tool_progress", ["tool progress", "verbose", "steps"], ["工具進度", "詳細"]],
|
|
42
44
|
["defaults.visibility", "agent-defaults", "#g-vis", "settings.crossInstanceVisibility", "defaults.cross_instance_visibility", ["visibility", "bot to bot", "cross instance", "messages"], ["可見性", "bot 之間", "跨 instance"]],
|
|
45
|
+
["defaults.reply-triggers", "agent-defaults", "#g-reply-triggers", "settings.replyTriggers", "defaults.reply_triggers", ["classic native reply", "reply trigger"], ["原生回覆觸發"]],
|
|
46
|
+
["chat.classic-reply-triggers", "chat", "#g-creply-triggers", "settings.replyTriggers", "classic_defaults.reply_triggers", ["classic native reply"], ["ClassicBot 原生回覆觸發"]],
|
|
43
47
|
["defaults.reply-guard", "agent-defaults", "#g-reply", "settings.replyCompletionGuard", "defaults.reply_completion_guard", ["delivered reply", "reply guard", "require reply"], ["送達回覆", "回覆保護"]],
|
|
44
48
|
["defaults.tool-set", "agent-defaults", "#g-ts", "settings.toolSet", "defaults.tool_set", ["tool set", "tools", "mcp"], ["工具組", "工具"]],
|
|
45
49
|
["defaults.dashboard", "agent-defaults", "#g-dash", "settings.dashboardAccess", "defaults.dashboard", ["dashboard access", "dashboard features", "permissions", "appearance tools", "task board", "web settings"], ["Dashboard 權限", "權限", "外觀", "任務看板", "網頁設定"]],
|
|
@@ -4,6 +4,10 @@ import { register } from "/assets/app-i18n.js";
|
|
|
4
4
|
|
|
5
5
|
register("settings", {
|
|
6
6
|
en: {
|
|
7
|
+
noticeTopic: "Topic", noticeOff: "Off",
|
|
8
|
+
webNotifyLogin: "Web sign-in notices", dailyTips: "Daily tips",
|
|
9
|
+
webNotifyLoginHint: "Posted in the topic. Off suppresses operator notices only; guest and public-link security notices still post. Default: Topic.",
|
|
10
|
+
dailyTipsHint: "Posted in the General topic. Default: Topic. /tips still posts where invoked.",
|
|
7
11
|
title: "Settings",
|
|
8
12
|
myAgents: "My Agents",
|
|
9
13
|
bots: "Bots",
|
|
@@ -108,6 +112,8 @@ register("settings", {
|
|
|
108
112
|
dashboard_appearance: "Its look (theme, pictures, widgets, effects, mod proposals)",
|
|
109
113
|
dashboard_task_board: "The task board",
|
|
110
114
|
dashboard_web_settings: "Your web appearance settings",
|
|
115
|
+
dashboard_office: "Office: walk, speak and act in the Office view",
|
|
116
|
+
dashboard_office_packs: "Office skin packs: check, upload, replace and restore them (everyone sees them)",
|
|
111
117
|
dashboardInherit: "Fleet default ({0})",
|
|
112
118
|
dashboardOn: "allowed",
|
|
113
119
|
dashboardOff: "off",
|
|
@@ -527,7 +533,7 @@ register("settings", {
|
|
|
527
533
|
grantsLegacy: "Guests now reach what their chat access gives them. Saving grants switches to explicit access: only the people below, only their ticked agents.",
|
|
528
534
|
grantsConvert: "Start from today's guests", grantsWithAccess: "People with access", grantsNoneYet: "No one has guest access yet.",
|
|
529
535
|
grantsAdd: "Add a person", grantsSearch: "Search people who have written to your agents", grantsNoPeople: "No one matches. A person must have written to an agent first.",
|
|
530
|
-
grantsChoose: "Choose", grantsChosen: "Chosen", grantsMaySee: "{0} may see:", grantsWroteHere: "wrote here", grantsWroteTo: "Wrote to: {0}",
|
|
536
|
+
grantsChoose: "Choose", grantsChosen: "Chosen", grantsMaySee: "{0} may see:", grantsClassicRooms: "ClassicBot rooms", grantsWroteHere: "wrote here", grantsWroteTo: "Wrote to: {0}",
|
|
531
537
|
grantsLastSeen: "last seen {0}", grantsRecent: "Recent changes", grantsRecentNone: "No change to anyone's access yet.", grantsAuditDirect: "applied at once", grantsAuditConfirmed: "confirmed in General", grantsAuditEnded: "{0} session(s) ended", grantsAuditCodeSent: "sign-in code sent", grantsAuditCodeNot: "sign-in code not sent ({0})", grantsAuditDmFailed: "the DM did not go through", grantsAuditWait: "asked again within a minute", grantsAuditAdminLimit: "the admin's limit of codes was reached",
|
|
532
538
|
grantsEditAgents: "Edit agents", grantsRemove: "Remove access", grantsUndoRemove: "Keep access",
|
|
533
539
|
grantsWillBeRemoved: "Access ends when you save.", grantsNew: "New — granted when you save", grantsNoAgents: "Tick at least one agent, or remove this person.",
|
|
@@ -570,6 +576,8 @@ register("settings", {
|
|
|
570
576
|
removeItem: "Remove {0}",
|
|
571
577
|
zeroDisabled: "0 = off",
|
|
572
578
|
optional: "optional",
|
|
579
|
+
replyTriggers: "Native replies trigger ClassicBot",
|
|
580
|
+
replyTriggersHint: "Off by default: only an exact @bot mention triggers a collab room. On also accepts one-hop replies to that bot. Forwarded content never counts; fleet-topic traffic is unchanged.",
|
|
573
581
|
collabMode: "Collaboration mode",
|
|
574
582
|
contextLines: "Context lines",
|
|
575
583
|
refresh: "Refresh",
|
|
@@ -672,6 +680,10 @@ register("settings", {
|
|
|
672
680
|
se_externalEmojiHint: "使用其他伺服器的 emoji,bot 在要加反應的頻道需有「使用外部表情符號」權限。",
|
|
673
681
|
se_unavailable: "無法使用",
|
|
674
682
|
se_hint: "留空即使用預設值。預覽由 AgEnD 依 bot 實際 react 的方式解析。進度前綴不是反應,而是進度訊息開頭的 emoji。",
|
|
683
|
+
noticeTopic: "頻道", noticeOff: "關閉",
|
|
684
|
+
webNotifyLogin: "網頁登入通知", dailyTips: "每日提示",
|
|
685
|
+
webNotifyLoginHint: "發在頻道。關閉只停用管理者登入通知;訪客與公開連結安全通知仍會發出。預設:頻道。",
|
|
686
|
+
dailyTipsHint: "發在 General 頻道。預設:頻道。/tips 仍送至呼叫的聊天室。",
|
|
675
687
|
title: "設定",
|
|
676
688
|
myAgents: "我的 Agent",
|
|
677
689
|
bots: "機器人",
|
|
@@ -750,6 +762,8 @@ register("settings", {
|
|
|
750
762
|
dashboard_appearance: "它的外觀(主題、圖片、小工具、特效、mod 提案)",
|
|
751
763
|
dashboard_task_board: "任務看板",
|
|
752
764
|
dashboard_web_settings: "你的網頁外觀設定",
|
|
765
|
+
dashboard_office: "辦公室:在辦公室畫面走動、說話、做動作",
|
|
766
|
+
dashboard_office_packs: "辦公室外觀包:檢查、上傳、取代與還原(全 fleet 都看得到)",
|
|
753
767
|
dashboardInherit: "跟 fleet 預設({0})",
|
|
754
768
|
dashboardOn: "允許",
|
|
755
769
|
dashboardOff: "關閉",
|
|
@@ -1167,7 +1181,7 @@ register("settings", {
|
|
|
1167
1181
|
grantsLegacy: "目前訪客能看到的,取決於他們在聊天中的權限。儲存授權後改為明確授權:只有下列的人,只看得到勾選的 agent。",
|
|
1168
1182
|
grantsConvert: "以目前的訪客為起點", grantsWithAccess: "有存取權的人", grantsNoneYet: "還沒有人有訪客存取權。",
|
|
1169
1183
|
grantsAdd: "新增人員", grantsSearch: "搜尋曾傳訊息給你的 agent 的人", grantsNoPeople: "沒有符合的人。對方必須先傳過訊息給某個 agent。",
|
|
1170
|
-
grantsChoose: "選擇", grantsChosen: "已選擇", grantsMaySee: "{0} 可以看到:", grantsWroteHere: "傳過訊息", grantsWroteTo: "傳過訊息給:{0}",
|
|
1184
|
+
grantsChoose: "選擇", grantsChosen: "已選擇", grantsMaySee: "{0} 可以看到:", grantsClassicRooms: "ClassicBot 聊天室", grantsWroteHere: "傳過訊息", grantsWroteTo: "傳過訊息給:{0}",
|
|
1171
1185
|
grantsLastSeen: "最後出現 {0}", grantsRecent: "最近的變更", grantsRecentNone: "還沒有人的存取權變更過。", grantsAuditDirect: "立即生效", grantsAuditConfirmed: "在 General 確認後生效", grantsAuditEnded: "結束了 {0} 個登入", grantsAuditCodeSent: "已寄出登入碼", grantsAuditCodeNot: "登入碼未寄出({0})", grantsAuditDmFailed: "私訊沒有送達", grantsAuditWait: "一分鐘內重複要求", grantsAuditAdminLimit: "已達管理員的登入碼上限",
|
|
1172
1186
|
grantsEditAgents: "編輯 agent", grantsRemove: "移除存取權", grantsUndoRemove: "保留存取權",
|
|
1173
1187
|
grantsWillBeRemoved: "儲存後存取權就會結束。", grantsNew: "新增 —— 儲存後授權", grantsNoAgents: "至少勾選一個 agent,或移除這個人。",
|
|
@@ -1210,6 +1224,8 @@ register("settings", {
|
|
|
1210
1224
|
removeItem: "移除 {0}",
|
|
1211
1225
|
zeroDisabled: "0 = 關閉",
|
|
1212
1226
|
optional: "選填",
|
|
1227
|
+
replyTriggers: "原生回覆觸發 ClassicBot",
|
|
1228
|
+
replyTriggersHint: "預設關閉:協作房間只有精確 @bot 提及才觸發。開啟後也接受對該機器人的單層原生回覆;轉發內容不算。Fleet 話題的訊息接收方式不變。",
|
|
1213
1229
|
collabMode: "協作模式",
|
|
1214
1230
|
contextLines: "上下文行數",
|
|
1215
1231
|
refresh: "重新整理",
|
|
@@ -103,8 +103,9 @@ register("app", {
|
|
|
103
103
|
// #2293: global search — chats, cross-instance messages and tasks (not the sidebar's filter of agents).
|
|
104
104
|
search: "Search", searchTitle: "Search chats, messages between agents and tasks ({0})",
|
|
105
105
|
confirmTitle: "Please confirm", confirmOk: "Continue", cancel: "Cancel",
|
|
106
|
+
sidePanelLeave: "Leave {0} without saving? Your changes there will be lost.", sidePanelDiscard: "Discard changes",
|
|
106
107
|
// The server's own wording (src/locale.ts needs.reason.*), so the web says what Discord says.
|
|
107
|
-
needs_reason_hang: "Not responding", needs_reason_exited: "Exited", needs_reason_assist: "Waiting at its terminal", needs_reason_permission: "Permission needed", needs_reason_dangerous_command: "Dangerous command waiting", needs_reason_login: "Sign-in needed", needs_reason_dialog: "Waiting at a dialog", needs_reason_terminal_input: "May be waiting for input", needs_reason_auth_paused: "Paused: sign-in needed", needs_reason_crashed: "Crashed", needs_reason_delivery_uncertain: "Could not confirm delivery", needs_reason_delivery_failed: "Delivery failed", needs_reason_task_review: "Waiting for your confirmation", needs_reason_task_blocked: "Blocked: asks you",
|
|
108
|
+
needs_reason_hang: "Not responding", needs_reason_exited: "Exited", needs_reason_assist: "Waiting at its terminal", needs_reason_question: "Asking you a question", needs_reason_permission: "Permission needed", needs_reason_dangerous_command: "Dangerous command waiting", needs_reason_login: "Sign-in needed", needs_reason_dialog: "Waiting at a dialog", needs_reason_terminal_input: "May be waiting for input", needs_reason_auth_paused: "Paused: sign-in needed", needs_reason_backend_signin: "Backend sign-in needed", needs_reason_crashed: "Crashed", needs_reason_delivery_uncertain: "Could not confirm delivery", needs_reason_delivery_failed: "Delivery failed", needs_reason_task_review: "Waiting for your confirmation", needs_reason_task_blocked: "Blocked: asks you",
|
|
108
109
|
},
|
|
109
110
|
"zh-TW": {
|
|
110
111
|
brand: "AgEnD", fleet: "Fleet", fleetOverview: "Fleet 概覽", view: "檢視", settings: "設定", instances: "Instances", newInstance: "新增 instance", newAgent: "新增 Agent",
|
|
@@ -143,6 +144,7 @@ register("app", {
|
|
|
143
144
|
needsNav: "等你處理", needsTab: "待處理", needsCount: "{0} 件待處理",
|
|
144
145
|
search: "搜尋", searchTitle: "搜尋聊天、agent 之間的訊息與任務({0})",
|
|
145
146
|
confirmTitle: "請確認", confirmOk: "繼續", cancel: "取消",
|
|
146
|
-
|
|
147
|
+
sidePanelLeave: "不儲存就離開「{0}」?你在那裡的修改會遺失。", sidePanelDiscard: "捨棄修改",
|
|
148
|
+
needs_reason_hang: "沒有回應", needs_reason_exited: "已結束", needs_reason_assist: "在終端機上等待", needs_reason_question: "正在問你問題", needs_reason_permission: "需要權限", needs_reason_dangerous_command: "危險指令待確認", needs_reason_login: "需要登入", needs_reason_dialog: "停在對話框", needs_reason_terminal_input: "可能在等輸入", needs_reason_auth_paused: "已暫停:需要登入", needs_reason_backend_signin: "後端需要登入", needs_reason_crashed: "已崩潰", needs_reason_delivery_uncertain: "無法確認是否送達", needs_reason_delivery_failed: "傳送失敗", needs_reason_task_review: "等你確認", needs_reason_task_blocked: "卡住,在問你",
|
|
147
149
|
},
|
|
148
150
|
});
|
|
@@ -16,7 +16,8 @@ import { onPrefsChanged, savePref } from "./app-prefs.js";
|
|
|
16
16
|
import { applyPageTheme, pageNow, resolvedMode, themesStore } from "./app-themes.js";
|
|
17
17
|
import { ErrorState, Skeleton } from "./ui-states.js";
|
|
18
18
|
import { InstanceNav, RosterNav, namesStore, setNamesPrimary } from "./instance-nav.js";
|
|
19
|
-
import {
|
|
19
|
+
import { usageRailStore } from "./header-tools.js";
|
|
20
|
+
import { RightRail, sidePanelStore } from "./side-panel.js";
|
|
20
21
|
import { OwnerCssKeepBar } from "./owner-css.js";
|
|
21
22
|
import { AgentWidget, fleetBinds, sidebarWidget, sidebarWidgetStore } from "./agent-widget.js";
|
|
22
23
|
|
|
@@ -89,14 +90,17 @@ export function openSearch(preset = {}) {
|
|
|
89
90
|
}
|
|
90
91
|
/**
|
|
91
92
|
* Ctrl+K (⌘K) anywhere opens search; Ctrl+F (⌘F) in an agent's chat opens it narrowed to that agent — elsewhere the
|
|
92
|
-
* browser's own find stays. Not while another dialog is open (search, open already, has its input focused)
|
|
93
|
+
* browser's own find stays. Not while another dialog is open (search, open already, has its input focused); a docked
|
|
94
|
+
* side panel (#2585) is not one.
|
|
93
95
|
*/
|
|
94
96
|
export function handleSearchKey(e) {
|
|
95
97
|
if (!searchOffered(true)) return;
|
|
96
98
|
if (e.isComposing || e.altKey || e.shiftKey || !(isMacLike() ? e.metaKey : e.ctrlKey)) return;
|
|
97
99
|
const key = (e.key || "").toLowerCase();
|
|
98
100
|
if (key !== "k" && key !== "f") return;
|
|
99
|
-
|
|
101
|
+
// #2585: a docked side panel is not modal — the page beside it is in use, so search is too (a result that leaves
|
|
102
|
+
// the page asks first when the panel holds changes: side-panel.js).
|
|
103
|
+
if (typeof document !== "undefined" && document.querySelector("dialog[open]:not(.side-panel)")) return;
|
|
100
104
|
const route = navStore.get().route;
|
|
101
105
|
if (key === "f" && !(route && route.panel === "chat" && route.instance)) return;
|
|
102
106
|
e.preventDefault();
|
|
@@ -127,7 +131,7 @@ export const sidebarWidthStore = createStore({ width: null });
|
|
|
127
131
|
function mainBudget() {
|
|
128
132
|
const vw = viewportWidth();
|
|
129
133
|
if (vw < 1200 || typeof document === "undefined") return vw;
|
|
130
|
-
const rail = document.querySelector(".u-rail");
|
|
134
|
+
const rail = document.querySelector(".shell > .u-rail, .shell > .side-panel"); // #2585: a docked panel in its place
|
|
131
135
|
if (!rail) return vw;
|
|
132
136
|
const w = Math.round(rail.getBoundingClientRect ? rail.getBoundingClientRect().width : 0) || RAIL_W;
|
|
133
137
|
return vw - w;
|
|
@@ -181,11 +185,15 @@ function SidebarResize() {
|
|
|
181
185
|
// once the page has drawn its change.
|
|
182
186
|
const again = () => afterPaint(applyKeptSidebarWidth);
|
|
183
187
|
const offRail = usageRailStore.subscribe(again);
|
|
188
|
+
// #2585: a docked panel in the rail's place (it is published on every render of its editor: only its coming and
|
|
189
|
+
// going changes the room).
|
|
190
|
+
let docked = !!sidePanelStore.get().panel;
|
|
191
|
+
const offPanel = sidePanelStore.subscribe(() => { const now = !!sidePanelStore.get().panel; if (now !== docked) { docked = now; again(); } });
|
|
184
192
|
const offNav = navStore.subscribe(again);
|
|
185
193
|
const w = win();
|
|
186
194
|
if (w && typeof w.addEventListener === "function") w.addEventListener("resize", applyKeptSidebarWidth);
|
|
187
195
|
return () => {
|
|
188
|
-
offRail(); offNav();
|
|
196
|
+
offRail(); offPanel(); offNav();
|
|
189
197
|
if (w && typeof w.removeEventListener === "function") w.removeEventListener("resize", applyKeptSidebarWidth);
|
|
190
198
|
if (activeDrag) activeDrag.end(false); // unmounted mid-drag: nothing kept, nothing left behind
|
|
191
199
|
};
|
|
@@ -787,7 +795,7 @@ export function Shell({ panels, onNewInstance, viewOnly = false }) {
|
|
|
787
795
|
${viewOnly || guest || !shell.banner ? null : html`<${shell.banner} />`}
|
|
788
796
|
<${Outlet} route=${nav.route} seq=${nav.seq} panels=${panels} />
|
|
789
797
|
</main>
|
|
790
|
-
${guest ? null : html`<${
|
|
798
|
+
${guest ? null : html`<${RightRail} route=${nav.route} />`}
|
|
791
799
|
<${BottomTabs} route=${nav.route} viewOnly=${viewOnly} />
|
|
792
800
|
${shell.dialog ? html`<${shell.dialog.Component} ...${shell.dialog.props} onClose=${closeDialog} />` : null}
|
|
793
801
|
${viewOnly || guest || (nav.route && nav.route.panel === "settings") ? null : html`<${PendingChanges} />`}
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
// tasks — the task board changed: the card numbers a write touched (SSE only: the board reads again when it is shown).
|
|
37
37
|
// offices — the stored offices changed ({ rev }; SSE only: the Office view reads /ui/offices again).
|
|
38
38
|
// office_skins — a skin pack was uploaded or deleted ({ rev }; SSE only: the Office view reads /ui/office-skins again).
|
|
39
|
-
|
|
39
|
+
// office_acts — the agents' live acts in the Office view changed ({ acts }, #2578; a poll page reads /ui/office-acts).
|
|
40
|
+
const EVENTS = ["status", "message", "agent_reply_live", "delivery", "deliveries", "prompt", "prompts", "prompt_resolved", "activity", "needs", "reply_buttons", "reactions", "steps_tick", "clock", "traffic", "delegation", "backend_login", "tasks", "offices", "office_skins", "office_acts", "office_pack_changes"];
|
|
40
41
|
const MAX_HELD = 1000; // live events held during one catch-up read; more → read again afterwards
|
|
41
42
|
const RETRY_DELAYS = [1000, 2000, 4000]; // after the first failed catch-up read; then it waits for Retry
|
|
42
43
|
const POLL_LIMIT_MS = 10000; // a poll that has not answered by then counts as failed
|