@songsid/agend 2.2.0-beta.1 → 2.2.0-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/README.md +1 -1
- package/README.zh-TW.md +1 -1
- package/dist/agent-cli-instructions.md +16 -9
- package/dist/agent-cli.js +15 -7
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.js +24 -9
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-whats-new.d.ts +47 -0
- package/dist/agent-whats-new.js +147 -0
- package/dist/agent-whats-new.js.map +1 -0
- package/dist/auth-api.d.ts +5 -3
- package/dist/auth-api.js +19 -3
- package/dist/auth-api.js.map +1 -1
- package/dist/backend/antigravity.d.ts +8 -0
- package/dist/backend/antigravity.js +32 -9
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-carry.d.ts +22 -0
- package/dist/backend/claude-carry.js +170 -0
- package/dist/backend/claude-carry.js.map +1 -0
- package/dist/backend/claude-code.d.ts +65 -2
- package/dist/backend/claude-code.js +226 -33
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex-metadata.d.ts +33 -0
- package/dist/backend/codex-metadata.js +122 -18
- package/dist/backend/codex-metadata.js.map +1 -1
- package/dist/backend/codex.d.ts +3 -0
- package/dist/backend/codex.js +17 -1
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/credential-profile.d.ts +40 -3
- package/dist/backend/credential-profile.js +113 -5
- package/dist/backend/credential-profile.js.map +1 -1
- package/dist/backend/effort-metadata.d.ts +37 -1
- package/dist/backend/effort-metadata.js +86 -15
- package/dist/backend/effort-metadata.js.map +1 -1
- package/dist/backend/grok.d.ts +4 -0
- package/dist/backend/grok.js +14 -0
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro-engine-ledger.d.ts +5 -0
- package/dist/backend/kiro-engine-ledger.js +20 -0
- package/dist/backend/kiro-engine-ledger.js.map +1 -1
- package/dist/backend/kiro-identity.d.ts +6 -0
- package/dist/backend/kiro-identity.js +19 -5
- package/dist/backend/kiro-identity.js.map +1 -1
- package/dist/backend/kiro.d.ts +39 -3
- package/dist/backend/kiro.js +143 -19
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/launch-effort.d.ts +61 -0
- package/dist/backend/launch-effort.js +170 -0
- package/dist/backend/launch-effort.js.map +1 -0
- package/dist/backend/muse.d.ts +84 -0
- package/dist/backend/muse.js +449 -53
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/types.d.ts +47 -4
- package/dist/backend/types.js +12 -1
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-command.d.ts +91 -0
- package/dist/backend-command.js +122 -0
- package/dist/backend-command.js.map +1 -0
- package/dist/background-work-ended.d.ts +18 -0
- package/dist/background-work-ended.js +30 -0
- package/dist/background-work-ended.js.map +1 -0
- package/dist/cache-service.d.ts +2 -0
- package/dist/cache-service.js +2 -1
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +36 -1
- package/dist/channel/adapters/discord.js +126 -4
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +42 -2
- package/dist/channel/adapters/telegram.js +142 -23
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-server.js +9 -1
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.d.ts +11 -0
- package/dist/channel/mcp-tools.js +26 -13
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/message-edit-errors.d.ts +5 -0
- package/dist/channel/message-edit-errors.js +24 -0
- package/dist/channel/message-edit-errors.js.map +1 -0
- package/dist/channel/telegram-markdown.d.ts +6 -0
- package/dist/channel/telegram-markdown.js +104 -0
- package/dist/channel/telegram-markdown.js.map +1 -0
- package/dist/channel/tool-router.d.ts +2 -0
- package/dist/channel/tool-router.js +10 -4
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/channel/types.d.ts +55 -3
- package/dist/cli.js +167 -39
- package/dist/cli.js.map +1 -1
- package/dist/command-table.d.ts +2 -2
- package/dist/command-table.js +6 -3
- package/dist/command-table.js.map +1 -1
- package/dist/config-validator.js +59 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/cross-instance-envelope.d.ts +15 -2
- package/dist/cross-instance-envelope.js +29 -5
- package/dist/cross-instance-envelope.js.map +1 -1
- package/dist/daemon.d.ts +156 -1
- package/dist/daemon.js +773 -89
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-outbox.d.ts +70 -8
- package/dist/delivery-outbox.js +315 -24
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/delivery-reconciliation.d.ts +18 -1
- package/dist/delivery-reconciliation.js +67 -2
- package/dist/delivery-reconciliation.js.map +1 -1
- package/dist/fleet-context.d.ts +10 -1
- package/dist/fleet-manager.d.ts +404 -13
- package/dist/fleet-manager.js +2039 -210
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/backend-providers/SKILL.md +1 -1
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +92 -21
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +27 -3
- package/dist/general-knowledge/skills/delegation-playbook/SKILL.md +8 -8
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +5 -5
- package/dist/general-knowledge/skills/fleet-health/SKILL.md +4 -4
- package/dist/general-knowledge/skills/fleet-restart/SKILL.md +13 -13
- package/dist/general-knowledge/skills/instance-lifecycle/SKILL.md +3 -2
- package/dist/general-knowledge/skills/kiro-engine-migration/SKILL.md +6 -0
- package/dist/general-knowledge/skills/model-discovery/SKILL.md +12 -9
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +8 -2
- package/dist/general-knowledge/skills/scheduling/SKILL.md +5 -3
- package/dist/general-knowledge/skills/session-management/SKILL.md +6 -5
- package/dist/general-knowledge/skills/tui-effort/SKILL.md +2 -2
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +8 -3
- package/dist/general-knowledge/steering/core-rules.md +8 -7
- package/dist/host-memory.d.ts +10 -0
- package/dist/host-memory.js +33 -1
- package/dist/host-memory.js.map +1 -1
- package/dist/human-delivery-receipts.d.ts +83 -0
- package/dist/human-delivery-receipts.js +194 -0
- package/dist/human-delivery-receipts.js.map +1 -0
- package/dist/instance-avatar.d.ts +36 -0
- package/dist/instance-avatar.js +57 -0
- package/dist/instance-avatar.js.map +1 -0
- package/dist/instance-config-impact.js +6 -0
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +29 -6
- package/dist/instance-lifecycle.js +79 -28
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +3 -1
- package/dist/instructions.js +11 -8
- package/dist/instructions.js.map +1 -1
- package/dist/kiro-log-gate.d.ts +42 -0
- package/dist/kiro-log-gate.js +39 -0
- package/dist/kiro-log-gate.js.map +1 -0
- package/dist/locale.js +226 -44
- package/dist/locale.js.map +1 -1
- package/dist/log-service.d.ts +99 -0
- package/dist/log-service.js +243 -0
- package/dist/log-service.js.map +1 -0
- package/dist/log-steps.d.ts +169 -0
- package/dist/log-steps.js +858 -0
- package/dist/log-steps.js.map +1 -0
- package/dist/login-controller.d.ts +20 -3
- package/dist/login-controller.js +71 -19
- package/dist/login-controller.js.map +1 -1
- package/dist/login-flows.d.ts +5 -2
- package/dist/login-flows.js +5 -4
- package/dist/login-flows.js.map +1 -1
- package/dist/memory-pressure.d.ts +13 -1
- package/dist/memory-pressure.js +50 -10
- package/dist/memory-pressure.js.map +1 -1
- package/dist/needs-you-hub.js +2 -0
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you-live.d.ts +6 -0
- package/dist/needs-you-live.js +23 -3
- package/dist/needs-you-live.js.map +1 -1
- package/dist/next-steps.js +1 -1
- package/dist/next-steps.js.map +1 -1
- package/dist/outbound-handlers.d.ts +100 -0
- package/dist/outbound-handlers.js +284 -97
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +38 -15
- package/dist/outbound-schemas.js +36 -8
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-link-progress.d.ts +1 -1
- package/dist/public-link-progress.js +8 -2
- package/dist/public-link-progress.js.map +1 -1
- package/dist/public-preview.d.ts +101 -0
- package/dist/public-preview.js +236 -0
- package/dist/public-preview.js.map +1 -0
- package/dist/public-web-gateway.js +14 -4
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +24 -1
- package/dist/public-web-link.js +63 -9
- package/dist/public-web-link.js.map +1 -1
- package/dist/reply-buttons-controller.d.ts +89 -5
- package/dist/reply-buttons-controller.js +273 -8
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/reply-buttons.d.ts +48 -3
- package/dist/reply-buttons.js +105 -10
- package/dist/reply-buttons.js.map +1 -1
- package/dist/reply-polls.d.ts +85 -0
- package/dist/reply-polls.js +154 -0
- package/dist/reply-polls.js.map +1 -0
- package/dist/restart-guard.d.ts +6 -3
- package/dist/restart-guard.js +6 -3
- package/dist/restart-guard.js.map +1 -1
- package/dist/restart-progress.d.ts +33 -0
- package/dist/restart-progress.js +30 -0
- package/dist/restart-progress.js.map +1 -1
- package/dist/service-activation.d.ts +15 -7
- package/dist/service-activation.js +46 -29
- package/dist/service-activation.js.map +1 -1
- package/dist/service-installer.d.ts +31 -0
- package/dist/service-installer.js +41 -2
- package/dist/service-installer.js.map +1 -1
- package/dist/settings-api.js +85 -25
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +72 -1
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-effect.js +28 -4
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.js +7 -0
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/setup-form.d.ts +1 -1
- package/dist/setup-form.js +1 -1
- package/dist/spawn-gate.js +5 -1
- package/dist/spawn-gate.js.map +1 -1
- package/dist/spawn-hold-reply.d.ts +12 -0
- package/dist/spawn-hold-reply.js +39 -0
- package/dist/spawn-hold-reply.js.map +1 -0
- package/dist/status-emojis.d.ts +10 -3
- package/dist/status-emojis.js +11 -2
- package/dist/status-emojis.js.map +1 -1
- package/dist/systemd-peer-bus.d.ts +95 -0
- package/dist/systemd-peer-bus.js +430 -0
- package/dist/systemd-peer-bus.js.map +1 -0
- package/dist/systemd-runtime.d.ts +27 -1
- package/dist/systemd-runtime.js +69 -7
- package/dist/systemd-runtime.js.map +1 -1
- package/dist/tips.js +4 -4
- package/dist/tips.js.map +1 -1
- package/dist/tool-permissions.js +3 -3
- package/dist/tool-permissions.js.map +1 -1
- package/dist/tool-progress.js +3 -2
- package/dist/tool-progress.js.map +1 -1
- package/dist/topic-commands.d.ts +42 -2
- package/dist/topic-commands.js +101 -11
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-delta-reader.d.ts +3 -3
- package/dist/transcript-delta-reader.js +8 -8
- package/dist/transcript-delta-reader.js.map +1 -1
- package/dist/transcript-jsonl.d.ts +80 -3
- package/dist/transcript-jsonl.js +147 -10
- package/dist/transcript-jsonl.js.map +1 -1
- package/dist/transcript-monitor.d.ts +19 -0
- package/dist/transcript-monitor.js +87 -15
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-sources.d.ts +78 -0
- package/dist/transcript-sources.js +375 -64
- package/dist/transcript-sources.js.map +1 -1
- package/dist/transcript-turns.d.ts +15 -2
- package/dist/transcript-turns.js +15 -2
- package/dist/transcript-turns.js.map +1 -1
- package/dist/tunnel/cloudflared.d.ts +7 -15
- package/dist/tunnel/cloudflared.js +36 -1
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/purpose-lane.d.ts +5 -1
- package/dist/tunnel/purpose-lane.js +14 -7
- package/dist/tunnel/purpose-lane.js.map +1 -1
- package/dist/tunnel/types.d.ts +5 -1
- package/dist/tunnel/types.js.map +1 -1
- package/dist/turn-resume.d.ts +2 -0
- package/dist/turn-resume.js +1 -1
- package/dist/turn-resume.js.map +1 -1
- package/dist/types.d.ts +25 -0
- package/dist/ui/chat-commands.js +1 -0
- package/dist/ui/chat-emojis.js +33 -0
- package/dist/ui/chat-mentions.js +63 -0
- package/dist/ui/chat-render.js +61 -4
- package/dist/ui/chat-store.js +37 -3
- package/dist/ui/chat-strings.js +40 -20
- package/dist/ui/chat-thread.js +111 -12
- package/dist/ui/chat-time.js +80 -0
- package/dist/ui/panel-chat.js +41 -10
- package/dist/ui/panel-details.js +2 -0
- package/dist/ui/panel-fleet.js +199 -57
- package/dist/ui/panel-log.js +428 -0
- package/dist/ui/panel-needs.js +6 -2
- package/dist/ui/panel-settings.js +184 -32
- package/dist/ui/preview-panel.js +55 -15
- package/dist/ui/preview-status.js +28 -0
- package/dist/ui/preview.js +44 -3
- package/dist/ui/settings-dialogs.js +7 -2
- package/dist/ui/settings-model.js +2 -1
- package/dist/ui/settings-strings.js +56 -4
- package/dist/ui/settings-token.js +1 -1
- package/dist/ui/shared/app-i18n.js +43 -17
- package/dist/ui/shared/app-prefs.js +250 -0
- package/dist/ui/shared/app-route.js +7 -2
- package/dist/ui/shared/app-shell.js +165 -8
- package/dist/ui/shared/app-store.js +5 -1
- package/dist/ui/shared/app-stream.js +26 -5
- package/dist/ui/shared/app.css +163 -22
- package/dist/ui/shared/app.js +11 -1
- package/dist/ui/shared/fonts/README.md +1 -1
- package/dist/ui/shared/header-tools.js +55 -5
- package/dist/ui/shared/instance-nav.js +241 -45
- package/dist/ui/shared/instance-switch.js +4 -4
- package/dist/ui/shared/panel-view.js +6 -0
- package/dist/ui/shared/signin.js +7 -7
- package/dist/ui/shared/theme.js +39 -7
- package/dist/ui/shared/tokens.css +1 -1
- package/dist/ui/shared/ui-icons.js +1 -0
- package/dist/ui/shared/usage-dialog.js +23 -5
- package/dist/ui/shared/view-strings.js +32 -4
- package/dist/ui/signin.html +1 -1
- package/dist/unrecognised-prompt.d.ts +23 -0
- package/dist/unrecognised-prompt.js +74 -0
- package/dist/unrecognised-prompt.js.map +1 -0
- package/dist/update-check.d.ts +31 -0
- package/dist/update-check.js +47 -0
- package/dist/update-check.js.map +1 -1
- package/dist/update-install.d.ts +28 -2
- package/dist/update-install.js +22 -4
- package/dist/update-install.js.map +1 -1
- package/dist/update-launch.d.ts +46 -1
- package/dist/update-launch.js +146 -3
- package/dist/update-launch.js.map +1 -1
- package/dist/update-marker.d.ts +51 -0
- package/dist/update-marker.js +61 -0
- package/dist/update-marker.js.map +1 -1
- package/dist/update-preflight.d.ts +100 -0
- package/dist/update-preflight.js +264 -0
- package/dist/update-preflight.js.map +1 -0
- package/dist/updater-caller.d.ts +31 -0
- package/dist/updater-caller.js +109 -0
- package/dist/updater-caller.js.map +1 -0
- 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 +34 -5
- package/dist/usage/providers.js +160 -27
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/statusline-usage.d.ts +6 -2
- package/dist/usage/statusline-usage.js +10 -4
- package/dist/usage/statusline-usage.js.map +1 -1
- package/dist/view-api.d.ts +1 -1
- package/dist/view-api.js +38 -8
- package/dist/view-api.js.map +1 -1
- package/dist/wake-coordinator.d.ts +11 -0
- package/dist/wake-coordinator.js +38 -4
- package/dist/wake-coordinator.js.map +1 -1
- package/dist/web-api.d.ts +89 -4
- package/dist/web-api.js +551 -45
- package/dist/web-api.js.map +1 -1
- package/dist/web-auth.d.ts +2 -2
- package/dist/web-auth.js +9 -4
- package/dist/web-auth.js.map +1 -1
- package/dist/web-chat-history.d.ts +12 -1
- package/dist/web-chat-history.js +29 -7
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +27 -4
- package/dist/web-commands.js +19 -4
- package/dist/web-commands.js.map +1 -1
- package/dist/web-host-guard.d.ts +3 -11
- package/dist/web-host-guard.js +3 -12
- package/dist/web-host-guard.js.map +1 -1
- package/dist/web-images.d.ts +47 -0
- package/dist/web-images.js +169 -0
- package/dist/web-images.js.map +1 -0
- package/dist/web-login.d.ts +14 -0
- package/dist/web-login.js +4 -2
- package/dist/web-login.js.map +1 -1
- package/dist/web-mentions.d.ts +44 -0
- package/dist/web-mentions.js +75 -0
- package/dist/web-mentions.js.map +1 -0
- package/dist/web-prefs.d.ts +81 -0
- package/dist/web-prefs.js +297 -0
- package/dist/web-prefs.js.map +1 -0
- package/dist/web-preview.d.ts +14 -1
- package/dist/web-preview.js +35 -13
- package/dist/web-preview.js.map +1 -1
- package/dist/web-profile.d.ts +32 -0
- package/dist/web-profile.js +132 -0
- package/dist/web-profile.js.map +1 -0
- package/dist/web-reply-files.d.ts +45 -0
- package/dist/web-reply-files.js +223 -0
- package/dist/web-reply-files.js.map +1 -0
- package/dist/web-schedules.d.ts +12 -0
- package/dist/web-schedules.js +34 -0
- package/dist/web-schedules.js.map +1 -0
- package/dist/web-server-drain.d.ts +10 -0
- package/dist/web-server-drain.js +50 -0
- package/dist/web-server-drain.js.map +1 -0
- package/dist/web-session.d.ts +50 -1
- package/dist/web-session.js +63 -6
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +23 -0
- package/dist/web-settings-patch.js +77 -0
- package/dist/web-settings-patch.js.map +1 -0
- package/dist/web-shell-routes.d.ts +5 -1
- package/dist/web-shell-routes.js +10 -1
- package/dist/web-shell-routes.js.map +1 -1
- package/dist/web-upload.d.ts +17 -4
- package/dist/web-upload.js +64 -13
- package/dist/web-upload.js.map +1 -1
- package/dist/workflow-templates/default.md +1 -1
- package/package.json +1 -1
- package/templates/launchd.plist.ejs +3 -1
- package/templates/systemd.service.ejs +2 -1
package/dist/web-preview.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-preview.js","sourceRoot":"","sources":["../src/web-preview.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"web-preview.js","sourceRoot":"","sources":["../src/web-preview.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare const WEB_NAME_FALLBACK = "web-user";
|
|
2
|
+
export declare const WEB_NAME_MAX_GRAPHEMES = 32;
|
|
3
|
+
/** The bound account a session was signed in as (its sign-in code's owner); none is the host operator. */
|
|
4
|
+
export interface WebAccount {
|
|
5
|
+
readonly adapterId: string;
|
|
6
|
+
readonly userId: string;
|
|
7
|
+
}
|
|
8
|
+
/** A web person's key in the web preferences: their account (connection and user id), or the operator. */
|
|
9
|
+
export declare function webPersonKey(owner: WebAccount | undefined): string;
|
|
10
|
+
export declare function hasStrayInvisible(s: string): boolean;
|
|
11
|
+
/** A name's UTF-16 length: well under what web-prefs.json keeps (256), so every accepted name loads back. */
|
|
12
|
+
export declare const WEB_NAME_MAX_UNITS = 128;
|
|
13
|
+
export declare function graphemeCount(s: string): number;
|
|
14
|
+
/**
|
|
15
|
+
* A name as a person typed it: NFC, trimmed, inner whitespace one space; then checked. `reserved` says whether a name
|
|
16
|
+
* (compared case-insensitively) belongs to something else here — an instance, its display name, a bot.
|
|
17
|
+
*/
|
|
18
|
+
export declare function validateWebName(raw: unknown, reserved?: (lowered: string) => boolean): {
|
|
19
|
+
ok: true;
|
|
20
|
+
name: string;
|
|
21
|
+
} | {
|
|
22
|
+
ok: false;
|
|
23
|
+
error: string;
|
|
24
|
+
};
|
|
25
|
+
/** The name to show for a stored one: itself if it still passes, else the fallback. */
|
|
26
|
+
export declare function webNameInUse(stored: unknown, reserved?: (lowered: string) => boolean): string;
|
|
27
|
+
/**
|
|
28
|
+
* An account's display name as a web name: what the rules refuse is dropped (a grapheme at a time), whitespace is
|
|
29
|
+
* collapsed, and it is cut to the maximum. What is left must then pass in full (no "via", nothing reserved); if it does
|
|
30
|
+
* not, or nothing is left, it is the fallback.
|
|
31
|
+
*/
|
|
32
|
+
export declare function safeWebName(raw: unknown, reserved?: (lowered: string) => boolean): string;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #1827: the name a web person shows agents and chats, instead of "web-user". Design: #1827 issuecomment-6169960931.
|
|
3
|
+
*
|
|
4
|
+
* - A web person is whoever a session was signed in for: the chat user a `/dashboard` code was sent to privately
|
|
5
|
+
* (`<connection>:<user id>`, recorded on the session), or — a code from `agend web`, a session from before — the host
|
|
6
|
+
* operator. They keep one name and one id on every device; the id is random (web-prefs.ts), never the name.
|
|
7
|
+
* - The name is self-asserted display text. It grants nothing: web messages stay `via web` with no verified actor
|
|
8
|
+
* (#1756). What it must not do is pose as something else — a platform header, a mention, an instance, AgEnD itself —
|
|
9
|
+
* so it is refused (never silently rewritten) unless it is plain: letters, marks, digits, spaces, emoji, `. - _ ' ·`.
|
|
10
|
+
* - A stored name is checked again where it is used (the file can be edited, an instance can be named after it later):
|
|
11
|
+
* one that no longer passes reads as "web-user".
|
|
12
|
+
*/
|
|
13
|
+
import { OPERATOR } from "./web-prefs.js";
|
|
14
|
+
export const WEB_NAME_FALLBACK = "web-user";
|
|
15
|
+
export const WEB_NAME_MAX_GRAPHEMES = 32;
|
|
16
|
+
/** A web person's key in the web preferences: their account (connection and user id), or the operator. */
|
|
17
|
+
export function webPersonKey(owner) {
|
|
18
|
+
return owner ? `person:${owner.adapterId}:${owner.userId}` : OPERATOR;
|
|
19
|
+
}
|
|
20
|
+
// Bidi controls (ALM, LRM/RLM, embeddings and overrides, isolates) and zero-width / invisible formatting characters.
|
|
21
|
+
// eslint-disable-next-line no-misleading-character-class
|
|
22
|
+
const INVISIBLE = /[\u061c\u200b-\u200f\u202a-\u202e\u2060-\u2064\u2066-\u2069\ufeff\u00ad]/u;
|
|
23
|
+
// eslint-disable-next-line no-control-regex
|
|
24
|
+
const CONTROL = /[\u0000-\u001f\u007f-\u009f\u2028\u2029]/u;
|
|
25
|
+
/**
|
|
26
|
+
* What a name may contain. Letters, combining marks, digits, spaces; emoji (pictographs with variation selectors, skin
|
|
27
|
+
* tones and keycaps — not joined sequences: a zero-width joiner is invisible, refused above); and `. - _ ' ·`. Everything else — `[ ] < > @ : , # / \` among it — is refused:
|
|
28
|
+
* those are what a `[user:… via …, id:…]` header, a `<@id>` mention or a path would be forged with.
|
|
29
|
+
*/
|
|
30
|
+
const ALLOWED = /^(?:[\p{L}\p{M}\p{N} ._'\u00b7-]|\p{Extended_Pictographic}|[\ufe0e\ufe0f]|[\u{1f3fb}-\u{1f3ff}]|\u20e3)+$/u;
|
|
31
|
+
/**
|
|
32
|
+
* Default-ignorable characters render as nothing (or leave what they follow unchanged): a name spelled with one looks
|
|
33
|
+
* like a name it is not ("Pri"+CGJ+"sm" is not "prism" to a comparison, and reads as it). They are refused everywhere —
|
|
34
|
+
* bidi and zero-width ones included — except an emoji's own presentation selector: VS15/VS16 on a pictograph, or in a
|
|
35
|
+
* keycap (digit, # or * + VS16 + U+20E3). (#1833 review.)
|
|
36
|
+
*/
|
|
37
|
+
const DEFAULT_IGNORABLE = /\p{Default_Ignorable_Code_Point}/u;
|
|
38
|
+
const PICTOGRAPH = /\p{Extended_Pictographic}/u;
|
|
39
|
+
const VS15 = String.fromCharCode(0xfe0e), VS16 = String.fromCharCode(0xfe0f), KEYCAP = String.fromCharCode(0x20e3);
|
|
40
|
+
export function hasStrayInvisible(s) {
|
|
41
|
+
const cps = Array.from(s);
|
|
42
|
+
for (let i = 0; i < cps.length; i++) {
|
|
43
|
+
const c = cps[i];
|
|
44
|
+
if (!DEFAULT_IGNORABLE.test(c))
|
|
45
|
+
continue;
|
|
46
|
+
const prev = cps[i - 1] ?? "";
|
|
47
|
+
if ((c === VS15 || c === VS16) && (PICTOGRAPH.test(prev) || (/^[0-9#*]$/.test(prev) && cps[i + 1] === KEYCAP)))
|
|
48
|
+
continue;
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
/** A name's UTF-16 length: well under what web-prefs.json keeps (256), so every accepted name loads back. */
|
|
54
|
+
export const WEB_NAME_MAX_UNITS = 128;
|
|
55
|
+
const segmenter = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter(undefined, { granularity: "grapheme" }) : null;
|
|
56
|
+
export function graphemeCount(s) {
|
|
57
|
+
if (segmenter) {
|
|
58
|
+
let n = 0;
|
|
59
|
+
for (const _ of segmenter.segment(s))
|
|
60
|
+
n++;
|
|
61
|
+
return n;
|
|
62
|
+
}
|
|
63
|
+
return Array.from(s).length;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* A name as a person typed it: NFC, trimmed, inner whitespace one space; then checked. `reserved` says whether a name
|
|
67
|
+
* (compared case-insensitively) belongs to something else here — an instance, its display name, a bot.
|
|
68
|
+
*/
|
|
69
|
+
export function validateWebName(raw, reserved = () => false) {
|
|
70
|
+
if (typeof raw !== "string")
|
|
71
|
+
return { ok: false, error: "name: text" };
|
|
72
|
+
if (CONTROL.test(raw))
|
|
73
|
+
return { ok: false, error: "name: one line, without control characters" };
|
|
74
|
+
if (INVISIBLE.test(raw) || hasStrayInvisible(raw))
|
|
75
|
+
return { ok: false, error: "name: no invisible or text-direction characters" };
|
|
76
|
+
const name = raw.normalize("NFC").trim().replace(/\s+/gu, " ");
|
|
77
|
+
const n = graphemeCount(name);
|
|
78
|
+
if (n < 1)
|
|
79
|
+
return { ok: false, error: "name: at least one character" };
|
|
80
|
+
if (n > WEB_NAME_MAX_GRAPHEMES)
|
|
81
|
+
return { ok: false, error: `name: at most ${WEB_NAME_MAX_GRAPHEMES} characters (${n} given)` };
|
|
82
|
+
if (name.length > WEB_NAME_MAX_UNITS)
|
|
83
|
+
return { ok: false, error: "name: too long (too many accents or joined marks)" };
|
|
84
|
+
if (!ALLOWED.test(name))
|
|
85
|
+
return { ok: false, error: "name: letters, digits, spaces, emoji and . - _ ' · only" };
|
|
86
|
+
const lowered = name.toLocaleLowerCase("en-US");
|
|
87
|
+
if (/(^|[\s._'\u00b7-])via($|[\s._'\u00b7-])/u.test(lowered))
|
|
88
|
+
return { ok: false, error: "name: the word \"via\" is reserved (it would read as a platform)" };
|
|
89
|
+
if (lowered === WEB_NAME_FALLBACK || lowered === "general" || lowered.startsWith("agend")) {
|
|
90
|
+
return { ok: false, error: "name: reserved by AgEnD" };
|
|
91
|
+
}
|
|
92
|
+
if (reserved(lowered))
|
|
93
|
+
return { ok: false, error: "name: already the name of an agent or bot here" };
|
|
94
|
+
return { ok: true, name };
|
|
95
|
+
}
|
|
96
|
+
/** The name to show for a stored one: itself if it still passes, else the fallback. */
|
|
97
|
+
export function webNameInUse(stored, reserved = () => false) {
|
|
98
|
+
if (typeof stored !== "string")
|
|
99
|
+
return WEB_NAME_FALLBACK;
|
|
100
|
+
const v = validateWebName(stored, reserved);
|
|
101
|
+
return v.ok && v.name === stored ? v.name : WEB_NAME_FALLBACK;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* An account's display name as a web name: what the rules refuse is dropped (a grapheme at a time), whitespace is
|
|
105
|
+
* collapsed, and it is cut to the maximum. What is left must then pass in full (no "via", nothing reserved); if it does
|
|
106
|
+
* not, or nothing is left, it is the fallback.
|
|
107
|
+
*/
|
|
108
|
+
export function safeWebName(raw, reserved = () => false) {
|
|
109
|
+
if (typeof raw !== "string")
|
|
110
|
+
return WEB_NAME_FALLBACK;
|
|
111
|
+
let kept = "";
|
|
112
|
+
const pieces = segmenter ? Array.from(segmenter.segment(raw.normalize("NFC")), (p) => p.segment) : Array.from(raw.normalize("NFC"));
|
|
113
|
+
let n = 0;
|
|
114
|
+
for (const g of pieces) {
|
|
115
|
+
if (n >= WEB_NAME_MAX_GRAPHEMES)
|
|
116
|
+
break;
|
|
117
|
+
if (/\s/u.test(g)) {
|
|
118
|
+
if (kept && !kept.endsWith(" ")) {
|
|
119
|
+
kept += " ";
|
|
120
|
+
n++;
|
|
121
|
+
}
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (CONTROL.test(g) || INVISIBLE.test(g) || hasStrayInvisible(g) || !ALLOWED.test(g))
|
|
125
|
+
continue;
|
|
126
|
+
kept += g;
|
|
127
|
+
n++;
|
|
128
|
+
}
|
|
129
|
+
const v = validateWebName(kept, reserved);
|
|
130
|
+
return v.ok ? v.name : WEB_NAME_FALLBACK;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=web-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-profile.js","sourceRoot":"","sources":["../src/web-profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare const WEB_FILES_DIR = "web-files";
|
|
2
|
+
/** Per instance. One reply can carry 20 files of 50 MB: the newest reply always fits whole. */
|
|
3
|
+
export declare const REPLY_FILES_MAX_BYTES: number;
|
|
4
|
+
/** An instance's snapshot directory; null for a name that is not a safe directory name. */
|
|
5
|
+
export declare function webFilesDir(home: string, instance: string): string | null;
|
|
6
|
+
/** The extension a snapshot keeps (lower-cased, so the served type is the one the source's name gives); "" when not plain. */
|
|
7
|
+
export declare function snapshotExt(path: string): string;
|
|
8
|
+
export type SnapshotResult =
|
|
9
|
+
/** Copied: serve `path`. `evicted`: ids whose snapshots were removed to make room (their messages show them as gone). */
|
|
10
|
+
{
|
|
11
|
+
ok: true;
|
|
12
|
+
path: string;
|
|
13
|
+
size: number;
|
|
14
|
+
evicted: string[];
|
|
15
|
+
}
|
|
16
|
+
/** Not a file the web chat shows (a symlink, not a regular file, over the limit, a state file, missing). */
|
|
17
|
+
| {
|
|
18
|
+
ok: false;
|
|
19
|
+
refused: true;
|
|
20
|
+
reason: string;
|
|
21
|
+
}
|
|
22
|
+
/** Could not be copied (I/O): the caller may serve the agent's own path, as before #1770 — until a restart. */
|
|
23
|
+
| {
|
|
24
|
+
ok: false;
|
|
25
|
+
refused: false;
|
|
26
|
+
reason: string;
|
|
27
|
+
evicted: string[];
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Copy the agent's file `src` into `dir` as `<id><ext>`. The path itself must not be a symlink; it is opened without
|
|
31
|
+
* following one, and what is copied is that open file — a regular file within maxFileBytes, the same file (device +
|
|
32
|
+
* inode) its real path names, and not a state file. Written to a temp name and renamed, so a snapshot is never partial.
|
|
33
|
+
*/
|
|
34
|
+
export declare function snapshotReplyFile(src: string, dir: string, id: string, opts: {
|
|
35
|
+
stateDir: string;
|
|
36
|
+
maxFileBytes?: number;
|
|
37
|
+
maxDirBytes?: number;
|
|
38
|
+
}): Promise<SnapshotResult>;
|
|
39
|
+
/** Remove the oldest snapshots until `incoming` more bytes fit under `maxBytes`; the ids removed. */
|
|
40
|
+
export declare function makeRoom(dir: string, incoming: number, maxBytes: number): string[];
|
|
41
|
+
/**
|
|
42
|
+
* At fleet start, after the web chat history is restored: remove every snapshot of `dir` whose id no restored message
|
|
43
|
+
* holds (`held`), and every temp file a stopped copy left. Nothing but our own names is touched. How many were removed.
|
|
44
|
+
*/
|
|
45
|
+
export declare function sweepReplySnapshots(dir: string, held: ReadonlySet<string>): number;
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #1770: the files an agent attaches to a reply, as the web chat shows them. When the reply is routed, each file is
|
|
3
|
+
* copied (a snapshot) into the instance's own `workspaces/<instance>/web-files/`, named by the id it is served under,
|
|
4
|
+
* and that copy is what the chat serves and what its history keeps. The agent's file may then be rewritten, moved or
|
|
5
|
+
* cleaned out of /tmp, and the fleet may restart: the message still shows what was sent. Telegram and Discord send
|
|
6
|
+
* the agent's own path, as before; nothing here touches that.
|
|
7
|
+
*
|
|
8
|
+
* Bounded: a snapshot leaves with its message (WebFileLedger.dropServed unlinks it), an instance's directory is held
|
|
9
|
+
* to REPLY_FILES_MAX_BYTES (the oldest go first), and a fleet start removes what no restored message holds.
|
|
10
|
+
*/
|
|
11
|
+
import { constants as fsConstants, closeSync, existsSync, fstatSync, lstatSync, openSync, readdirSync, realpathSync, unlinkSync } from "node:fs";
|
|
12
|
+
import { lstat, mkdir, open, realpath, rename, stat, unlink } from "node:fs/promises";
|
|
13
|
+
import { basename, dirname, extname, join, resolve, sep } from "node:path";
|
|
14
|
+
import { isSafeInstanceDirName } from "./web-chat-store.js";
|
|
15
|
+
import { MAX_SERVED_BYTES } from "./web-upload.js";
|
|
16
|
+
export const WEB_FILES_DIR = "web-files";
|
|
17
|
+
/** Per instance. One reply can carry 20 files of 50 MB: the newest reply always fits whole. */
|
|
18
|
+
export const REPLY_FILES_MAX_BYTES = 1024 ** 3;
|
|
19
|
+
/** A snapshot's name: its served id and the source's plain extension. Nothing else in the directory is ours. */
|
|
20
|
+
const SNAPSHOT_NAME = /^([0-9a-f]{32})(\.[a-z0-9]{1,10})?$/;
|
|
21
|
+
const TMP_NAME = /^\.tmp-[0-9a-f]{32}$/;
|
|
22
|
+
const CHUNK = 1 << 20;
|
|
23
|
+
const PROC_FD = process.platform === "linux" ? "/proc/self/fd" : null;
|
|
24
|
+
/** An instance's snapshot directory; null for a name that is not a safe directory name. */
|
|
25
|
+
export function webFilesDir(home, instance) {
|
|
26
|
+
return isSafeInstanceDirName(instance) ? join(home, "workspaces", instance, WEB_FILES_DIR) : null;
|
|
27
|
+
}
|
|
28
|
+
/** The extension a snapshot keeps (lower-cased, so the served type is the one the source's name gives); "" when not plain. */
|
|
29
|
+
export function snapshotExt(path) {
|
|
30
|
+
const ext = extname(path).toLowerCase();
|
|
31
|
+
return /^\.[a-z0-9]{1,10}$/.test(ext) ? ext : "";
|
|
32
|
+
}
|
|
33
|
+
/** The reply tool's own rule (tool-router assertSendable), applied again when copying: nothing under the state dir but inbox/. */
|
|
34
|
+
function isStateFile(real, stateDir) {
|
|
35
|
+
const roots = new Set([resolve(stateDir)]);
|
|
36
|
+
try {
|
|
37
|
+
roots.add(realpathSync(stateDir));
|
|
38
|
+
}
|
|
39
|
+
catch { /* not there: the resolved path is the rule */ }
|
|
40
|
+
return [...roots].some((root) => real.startsWith(root + sep) && !real.includes(sep + "inbox" + sep));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Copy the agent's file `src` into `dir` as `<id><ext>`. The path itself must not be a symlink; it is opened without
|
|
44
|
+
* following one, and what is copied is that open file — a regular file within maxFileBytes, the same file (device +
|
|
45
|
+
* inode) its real path names, and not a state file. Written to a temp name and renamed, so a snapshot is never partial.
|
|
46
|
+
*/
|
|
47
|
+
export async function snapshotReplyFile(src, dir, id, opts) {
|
|
48
|
+
const maxFile = opts.maxFileBytes ?? MAX_SERVED_BYTES;
|
|
49
|
+
const refused = (reason) => ({ ok: false, refused: true, reason });
|
|
50
|
+
let fh = null;
|
|
51
|
+
let tmp = null;
|
|
52
|
+
let evicted = [];
|
|
53
|
+
try {
|
|
54
|
+
let size, mtimeMs;
|
|
55
|
+
try {
|
|
56
|
+
const own = await lstat(src);
|
|
57
|
+
if (own.isSymbolicLink())
|
|
58
|
+
return refused("a symlink");
|
|
59
|
+
if (!own.isFile())
|
|
60
|
+
return refused("not a regular file");
|
|
61
|
+
fh = await open(src, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
|
|
62
|
+
const st = await fh.stat();
|
|
63
|
+
if (!st.isFile())
|
|
64
|
+
return refused("not a regular file");
|
|
65
|
+
if (st.size > maxFile)
|
|
66
|
+
return refused("over the size limit");
|
|
67
|
+
const real = await realpath(src);
|
|
68
|
+
const named = await stat(real);
|
|
69
|
+
if (named.dev !== st.dev || named.ino !== st.ino)
|
|
70
|
+
return refused("replaced while it was opened");
|
|
71
|
+
if (isStateFile(real, opts.stateDir))
|
|
72
|
+
return refused("inside the AgEnD state directory");
|
|
73
|
+
({ size, mtimeMs } = st);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return refused("cannot be read");
|
|
77
|
+
}
|
|
78
|
+
await mkdir(dir, { recursive: true, mode: 0o700 });
|
|
79
|
+
if (!inTree(dir))
|
|
80
|
+
return { ok: false, refused: false, reason: "the snapshot directory is not the instance's own", evicted };
|
|
81
|
+
evicted = makeRoom(dir, size, opts.maxDirBytes ?? REPLY_FILES_MAX_BYTES);
|
|
82
|
+
tmp = join(dir, `.tmp-${id}`);
|
|
83
|
+
const out = await open(tmp, "wx", 0o600);
|
|
84
|
+
let off = 0;
|
|
85
|
+
try {
|
|
86
|
+
const buf = Buffer.alloc(Math.min(CHUNK, Math.max(1, size)));
|
|
87
|
+
while (off < size) {
|
|
88
|
+
const { bytesRead } = await fh.read(buf, 0, Math.min(buf.length, size - off), off);
|
|
89
|
+
if (bytesRead <= 0)
|
|
90
|
+
break;
|
|
91
|
+
await out.write(buf, 0, bytesRead);
|
|
92
|
+
off += bytesRead;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
await out.close();
|
|
97
|
+
}
|
|
98
|
+
const after = await fh.stat();
|
|
99
|
+
// Rewritten while it was copied: the copy may be torn — not kept.
|
|
100
|
+
if (off !== size || after.size !== size || after.mtimeMs !== mtimeMs)
|
|
101
|
+
return { ok: false, refused: false, reason: "changed while it was copied", evicted };
|
|
102
|
+
const path = join(dir, id + snapshotExt(src));
|
|
103
|
+
await rename(tmp, path);
|
|
104
|
+
tmp = null;
|
|
105
|
+
return { ok: true, path, size, evicted };
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
return { ok: false, refused: false, reason: err.code ?? "copy failed", evicted };
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
if (fh)
|
|
112
|
+
await fh.close().catch(() => { });
|
|
113
|
+
if (tmp)
|
|
114
|
+
await unlink(tmp).catch(() => { });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** `dir` is a real directory at its own path (not a link elsewhere, nor under one). */
|
|
118
|
+
function inTree(dir) {
|
|
119
|
+
try {
|
|
120
|
+
return lstatSync(dir).isDirectory() && realpathSync(dir) === join(realpathSync(dirname(dir)), basename(dir));
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Run `fn` on `dir` opened as a directory and checked to be the in-tree one: removals go through the open directory
|
|
128
|
+
* where the platform allows it, so a parent swapped for a link afterwards cannot redirect them (as sweepOrphanedUploads).
|
|
129
|
+
*/
|
|
130
|
+
function withPinnedDir(dir, fallback, fn) {
|
|
131
|
+
let fd = null;
|
|
132
|
+
try {
|
|
133
|
+
if (!inTree(dir))
|
|
134
|
+
return fallback;
|
|
135
|
+
fd = openSync(dir, fsConstants.O_RDONLY | fsConstants.O_DIRECTORY | fsConstants.O_NOFOLLOW);
|
|
136
|
+
const pinned = fstatSync(fd);
|
|
137
|
+
const here = lstatSync(dir);
|
|
138
|
+
if (pinned.dev !== here.dev || pinned.ino !== here.ino)
|
|
139
|
+
return fallback;
|
|
140
|
+
const anchor = PROC_FD && existsSync(`${PROC_FD}/${fd}`) ? `${PROC_FD}/${fd}` : dir;
|
|
141
|
+
const stillPinned = () => {
|
|
142
|
+
if (anchor !== dir)
|
|
143
|
+
return true;
|
|
144
|
+
const now = lstatSync(dir);
|
|
145
|
+
return now.isDirectory() && now.dev === pinned.dev && now.ino === pinned.ino && inTree(dir);
|
|
146
|
+
};
|
|
147
|
+
return fn(anchor, stillPinned);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return fallback;
|
|
151
|
+
}
|
|
152
|
+
finally {
|
|
153
|
+
if (fd !== null)
|
|
154
|
+
try {
|
|
155
|
+
closeSync(fd);
|
|
156
|
+
}
|
|
157
|
+
catch { /* closed */ }
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/** The snapshots in `dir` (regular files named as ours), oldest first. */
|
|
161
|
+
function snapshotsIn(anchor) {
|
|
162
|
+
const out = [];
|
|
163
|
+
for (const name of readdirSync(anchor)) {
|
|
164
|
+
const m = SNAPSHOT_NAME.exec(name);
|
|
165
|
+
if (!m)
|
|
166
|
+
continue;
|
|
167
|
+
try {
|
|
168
|
+
const st = lstatSync(join(anchor, name));
|
|
169
|
+
if (st.isFile())
|
|
170
|
+
out.push({ id: m[1], name, size: st.size, mtimeMs: st.mtimeMs });
|
|
171
|
+
}
|
|
172
|
+
catch { /* vanished */ }
|
|
173
|
+
}
|
|
174
|
+
return out.sort((a, b) => a.mtimeMs - b.mtimeMs || (a.name < b.name ? -1 : 1));
|
|
175
|
+
}
|
|
176
|
+
/** Remove the oldest snapshots until `incoming` more bytes fit under `maxBytes`; the ids removed. */
|
|
177
|
+
export function makeRoom(dir, incoming, maxBytes) {
|
|
178
|
+
return withPinnedDir(dir, [], (anchor, stillPinned) => {
|
|
179
|
+
const all = snapshotsIn(anchor);
|
|
180
|
+
let total = all.reduce((n, s) => n + s.size, 0);
|
|
181
|
+
const evicted = [];
|
|
182
|
+
for (const s of all) {
|
|
183
|
+
if (total + incoming <= maxBytes)
|
|
184
|
+
break;
|
|
185
|
+
if (!stillPinned())
|
|
186
|
+
break;
|
|
187
|
+
try {
|
|
188
|
+
unlinkSync(join(anchor, s.name));
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
total -= s.size;
|
|
194
|
+
evicted.push(s.id);
|
|
195
|
+
}
|
|
196
|
+
return evicted;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* At fleet start, after the web chat history is restored: remove every snapshot of `dir` whose id no restored message
|
|
201
|
+
* holds (`held`), and every temp file a stopped copy left. Nothing but our own names is touched. How many were removed.
|
|
202
|
+
*/
|
|
203
|
+
export function sweepReplySnapshots(dir, held) {
|
|
204
|
+
return withPinnedDir(dir, 0, (anchor, stillPinned) => {
|
|
205
|
+
let removed = 0;
|
|
206
|
+
for (const name of readdirSync(anchor)) {
|
|
207
|
+
const m = SNAPSHOT_NAME.exec(name);
|
|
208
|
+
if (!(m && !held.has(m[1])) && !TMP_NAME.test(name))
|
|
209
|
+
continue;
|
|
210
|
+
try {
|
|
211
|
+
if (!lstatSync(join(anchor, name)).isFile())
|
|
212
|
+
continue; // a link or a directory is not one of ours
|
|
213
|
+
if (!stillPinned())
|
|
214
|
+
break;
|
|
215
|
+
unlinkSync(join(anchor, name));
|
|
216
|
+
removed++;
|
|
217
|
+
}
|
|
218
|
+
catch { /* vanished */ }
|
|
219
|
+
}
|
|
220
|
+
return removed;
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=web-reply-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-reply-files.js","sourceRoot":"","sources":["../src/web-reply-files.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Schedule, ScheduleRetry } from "./scheduler/types.js";
|
|
2
|
+
export interface ScheduleView extends Schedule {
|
|
3
|
+
/** The next run (epoch ms), or null: disabled, a cron with no further occurrence, or a one-shot already past. */
|
|
4
|
+
next_run_ms: number | null;
|
|
5
|
+
/** next_run_ms in the fleet's zone, e.g. "2026-10-13 14:00 (UTC+8)"; null when there is none. */
|
|
6
|
+
next_run_text: string | null;
|
|
7
|
+
/** A one-shot's time in the fleet's zone; null for a cron. */
|
|
8
|
+
at_text: string | null;
|
|
9
|
+
/** A one-shot past its time with a retry pending (#1426): it has not run yet, it will retry. */
|
|
10
|
+
retrying: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function scheduleView(s: Schedule, retry: ScheduleRetry | null, nowMs?: number, tz?: string): ScheduleView;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #1724: a schedule as the web lists it — the row's own fields, plus what a person reads that the page should not work
|
|
3
|
+
* out itself: the next run (a cron's next occurrence in its own timezone, or a one-shot's time) and the one-shot's time,
|
|
4
|
+
* each in the fleet's zone (formatFleetTime, #1586); whether a one-shot past its time is waiting on a retry (#1426).
|
|
5
|
+
* A disabled schedule has no next run. Nothing here parses cron on the page.
|
|
6
|
+
*/
|
|
7
|
+
import { Cron } from "croner";
|
|
8
|
+
import { formatFleetTime } from "./tz-utils.js";
|
|
9
|
+
export function scheduleView(s, retry, nowMs = Date.now(), tz) {
|
|
10
|
+
const atMs = s.at ? Date.parse(s.at) : NaN;
|
|
11
|
+
const retrying = !!s.at && Number.isFinite(atMs) && atMs < nowMs && !!retry;
|
|
12
|
+
let next = null;
|
|
13
|
+
if (s.enabled) {
|
|
14
|
+
if (s.cron) {
|
|
15
|
+
try {
|
|
16
|
+
next = new Cron(s.cron, { timezone: s.timezone }).nextRun(new Date(nowMs))?.getTime() ?? null;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
next = null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
else if (Number.isFinite(atMs)) {
|
|
23
|
+
next = atMs >= nowMs ? atMs : retrying ? retry.due_at_ms : null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
...s,
|
|
28
|
+
next_run_ms: next,
|
|
29
|
+
next_run_text: next !== null ? formatFleetTime(next, tz) : null,
|
|
30
|
+
at_text: Number.isFinite(atMs) ? formatFleetTime(atMs, tz) : null,
|
|
31
|
+
retrying,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=web-schedules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-schedules.js","sourceRoot":"","sources":["../src/web-schedules.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAahD,MAAM,UAAU,YAAY,CAAC,CAAW,EAAE,KAA2B,EAAE,QAAgB,IAAI,CAAC,GAAG,EAAE,EAAE,EAAW;IAC5G,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3C,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC;IAC5E,IAAI,IAAI,GAAkB,IAAI,CAAC;IAC/B,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;QACd,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YACX,IAAI,CAAC;gBAAC,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,IAAI,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC;gBAAC,IAAI,GAAG,IAAI,CAAC;YAAC,CAAC;QAC/H,CAAC;aAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,IAAI,GAAG,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;QACnE,CAAC;IACH,CAAC;IACD,OAAO;QACL,GAAG,CAAC;QACJ,WAAW,EAAE,IAAI;QACjB,aAAa,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI;QAC/D,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI;QACjE,QAAQ;KACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Server, ServerResponse } from "node:http";
|
|
2
|
+
export declare const WEB_DRAIN_MS = 1000;
|
|
3
|
+
export declare const WEB_SHUTDOWN_RETRY_MS = 10000;
|
|
4
|
+
/** One listener owns its connections, including HTTP upgrades. Install before listen(). */
|
|
5
|
+
export declare function trackWebServer(server: Server): {
|
|
6
|
+
readonly closing: boolean;
|
|
7
|
+
/** Stop accepts first; finish SSE and ordinary responses before the bounded forceful tail. */
|
|
8
|
+
close(clients: Set<ServerResponse>): Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
export type WebServerDrain = ReturnType<typeof trackWebServer>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const WEB_DRAIN_MS = 1_000;
|
|
2
|
+
export const WEB_SHUTDOWN_RETRY_MS = 10_000;
|
|
3
|
+
const SHUTDOWN_FRAME = `event: shutdown\ndata: ${JSON.stringify({ retry_ms: WEB_SHUTDOWN_RETRY_MS })}\n\n`;
|
|
4
|
+
/** One listener owns its connections, including HTTP upgrades. Install before listen(). */
|
|
5
|
+
export function trackWebServer(server) {
|
|
6
|
+
const sockets = new Set();
|
|
7
|
+
const connected = (socket) => {
|
|
8
|
+
sockets.add(socket);
|
|
9
|
+
socket.once("close", () => sockets.delete(socket));
|
|
10
|
+
};
|
|
11
|
+
server.on("connection", connected);
|
|
12
|
+
let closing = false;
|
|
13
|
+
let inFlight = null;
|
|
14
|
+
return {
|
|
15
|
+
get closing() { return closing; },
|
|
16
|
+
/** Stop accepts first; finish SSE and ordinary responses before the bounded forceful tail. */
|
|
17
|
+
close(clients) {
|
|
18
|
+
if (inFlight)
|
|
19
|
+
return inFlight;
|
|
20
|
+
closing = true;
|
|
21
|
+
inFlight = new Promise(resolve => {
|
|
22
|
+
const timer = setTimeout(() => {
|
|
23
|
+
server.closeAllConnections();
|
|
24
|
+
// closeAllConnections excludes upgraded protocols and incomplete HTTP connections.
|
|
25
|
+
for (const socket of sockets)
|
|
26
|
+
socket.destroy();
|
|
27
|
+
}, WEB_DRAIN_MS);
|
|
28
|
+
server.close(() => {
|
|
29
|
+
clearTimeout(timer);
|
|
30
|
+
server.off("connection", connected);
|
|
31
|
+
resolve();
|
|
32
|
+
});
|
|
33
|
+
for (const response of [...clients]) {
|
|
34
|
+
const socket = response.socket;
|
|
35
|
+
clients.delete(response);
|
|
36
|
+
if (response.destroyed || response.writableEnded)
|
|
37
|
+
continue;
|
|
38
|
+
try {
|
|
39
|
+
response.end(SHUTDOWN_FRAME, () => socket?.end());
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
socket?.destroy();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return inFlight;
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=web-server-drain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-server-drain.js","sourceRoot":"","sources":["../src/web-server-drain.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC;AAClC,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAC5C,MAAM,cAAc,GAAG,0BAA0B,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,qBAAqB,EAAE,CAAC,MAAM,CAAC;AAE3G,2FAA2F;AAC3F,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,SAAS,GAAG,CAAC,MAAc,EAAQ,EAAE;QACzC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC;IACF,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACnC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,QAAQ,GAAyB,IAAI,CAAC;IAC1C,OAAO;QACL,IAAI,OAAO,KAAc,OAAO,OAAO,CAAC,CAAC,CAAC;QAC1C,8FAA8F;QAC9F,KAAK,CAAC,OAA4B;YAChC,IAAI,QAAQ;gBAAE,OAAO,QAAQ,CAAC;YAC9B,OAAO,GAAG,IAAI,CAAC;YACf,QAAQ,GAAG,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;gBACrC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;oBAC5B,MAAM,CAAC,mBAAmB,EAAE,CAAC;oBAC7B,mFAAmF;oBACnF,KAAK,MAAM,MAAM,IAAI,OAAO;wBAAE,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjD,CAAC,EAAE,YAAY,CAAC,CAAC;gBACjB,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;oBAChB,YAAY,CAAC,KAAK,CAAC,CAAC;oBACpB,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;oBACpC,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;gBACH,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC;oBACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;oBAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;oBACzB,IAAI,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,aAAa;wBAAE,SAAS;oBAC3D,IAAI,CAAC;wBACH,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;oBACpD,CAAC;oBAAC,MAAM,CAAC;wBACP,MAAM,EAAE,OAAO,EAAE,CAAC;oBACpB,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC"}
|