@songsid/agend 2.3.3-beta.1 → 2.3.3-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-cli.js +13 -112
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +0 -1
- package/dist/agent-endpoint.js +1 -9
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-whats-new.d.ts +3 -6
- package/dist/agent-whats-new.js +7 -18
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/auth-api.d.ts +0 -7
- package/dist/auth-api.js +1 -15
- package/dist/auth-api.js.map +1 -1
- package/dist/authority/authority-state.js +1 -1
- package/dist/authority/authority-state.js.map +1 -1
- package/dist/authority/web-authority.d.ts +9 -4
- package/dist/authority/web-authority.js +10 -5
- package/dist/authority/web-authority.js.map +1 -1
- package/dist/backend/antigravity.js +6 -1
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.d.ts +7 -0
- package/dist/backend/claude-code.js +34 -28
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/claude-transcript-errors.d.ts +18 -0
- package/dist/backend/claude-transcript-errors.js +19 -0
- package/dist/backend/claude-transcript-errors.js.map +1 -0
- package/dist/backend/codex-session-lookup.d.ts +16 -3
- package/dist/backend/codex-session-lookup.js +45 -11
- package/dist/backend/codex-session-lookup.js.map +1 -1
- package/dist/backend/codex.d.ts +16 -0
- package/dist/backend/codex.js +184 -35
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/grok.js +58 -12
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro.js +2 -0
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/muse.js +2 -1
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/types.d.ts +46 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/bundled-skills.d.ts +4 -6
- package/dist/bundled-skills.js +10 -14
- package/dist/bundled-skills.js.map +1 -1
- package/dist/channel/adapters/discord.js +60 -17
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/mcp-server.js +5 -5
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.d.ts +1 -3
- package/dist/channel/mcp-tools.js +4 -58
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/classic-channel-manager.d.ts +4 -1
- package/dist/classic-channel-manager.js +21 -7
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +21 -4
- package/dist/cli.js.map +1 -1
- package/dist/config-history.d.ts +50 -0
- package/dist/config-history.js +263 -0
- package/dist/config-history.js.map +1 -0
- package/dist/config-validator.js +7 -7
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.js +11 -4
- package/dist/config.js.map +1 -1
- package/dist/daemon.d.ts +73 -3
- package/dist/daemon.js +334 -121
- package/dist/daemon.js.map +1 -1
- package/dist/daily-summary.d.ts +8 -1
- package/dist/daily-summary.js +8 -5
- package/dist/daily-summary.js.map +1 -1
- package/dist/dashboard-live.d.ts +1 -1
- package/dist/dashboard-live.js +3 -3
- package/dist/dashboard-live.js.map +1 -1
- package/dist/dashboard-permissions.d.ts +1 -1
- package/dist/dashboard-permissions.js +1 -3
- package/dist/dashboard-permissions.js.map +1 -1
- package/dist/delivery-outbox.d.ts +4 -0
- package/dist/delivery-outbox.js +12 -2
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/doctor.d.ts +4 -0
- package/dist/doctor.js +16 -1
- package/dist/doctor.js.map +1 -1
- package/dist/fleet-level-config.js +1 -1
- package/dist/fleet-level-config.js.map +1 -1
- package/dist/fleet-manager.d.ts +70 -54
- package/dist/fleet-manager.js +257 -322
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-process-handlers.d.ts +5 -0
- package/dist/fleet-process-handlers.js +21 -0
- package/dist/fleet-process-handlers.js.map +1 -1
- package/dist/fleet-service-owner.d.ts +11 -0
- package/dist/fleet-service-owner.js +3 -0
- package/dist/fleet-service-owner.js.map +1 -0
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +11 -1
- package/dist/general-knowledge/skills/session-management/SKILL.md +6 -0
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +13 -204
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +29 -67
- package/dist/instance-lifecycle.d.ts +19 -0
- package/dist/instance-lifecycle.js +52 -10
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/locale.js +92 -42
- package/dist/locale.js.map +1 -1
- package/dist/needs-you-hub.d.ts +1 -0
- package/dist/needs-you-hub.js +6 -3
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you-live.d.ts +3 -1
- package/dist/needs-you-live.js +24 -2
- package/dist/needs-you-live.js.map +1 -1
- package/dist/needs-you.d.ts +13 -2
- package/dist/needs-you.js +11 -1
- package/dist/needs-you.js.map +1 -1
- package/dist/notify-socket.d.ts +10 -0
- package/dist/notify-socket.js +45 -0
- package/dist/notify-socket.js.map +1 -0
- package/dist/outbound-handlers.js +19 -7
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +0 -62
- package/dist/outbound-schemas.js +3 -42
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/parked-notices.d.ts +87 -0
- package/dist/parked-notices.js +194 -0
- package/dist/parked-notices.js.map +1 -0
- package/dist/public-link-progress.d.ts +5 -2
- package/dist/public-link-progress.js +4 -3
- package/dist/public-link-progress.js.map +1 -1
- package/dist/public-web-gateway.js +0 -9
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +12 -0
- package/dist/public-web-link.js +29 -5
- package/dist/public-web-link.js.map +1 -1
- package/dist/quota-notice.d.ts +23 -0
- package/dist/quota-notice.js +22 -0
- package/dist/quota-notice.js.map +1 -0
- package/dist/scheduler/task-board.d.ts +0 -13
- package/dist/scheduler/task-board.js +0 -14
- package/dist/scheduler/task-board.js.map +1 -1
- package/dist/sd-notify.d.ts +10 -1
- package/dist/sd-notify.js +27 -2
- package/dist/sd-notify.js.map +1 -1
- package/dist/search/search-docs.d.ts +1 -1
- package/dist/search/search-docs.js +2 -2
- package/dist/search/search-docs.js.map +1 -1
- package/dist/settings-api.d.ts +16 -0
- package/dist/settings-api.js +55 -2
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +3 -1
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-confirmation.d.ts +17 -3
- package/dist/settings-confirmation.js +8 -5
- package/dist/settings-confirmation.js.map +1 -1
- package/dist/settings-http-confirmation.js +31 -1
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/setup-wizard.d.ts +3 -0
- package/dist/setup-wizard.js +4 -2
- package/dist/setup-wizard.js.map +1 -1
- package/dist/task-board-waker.d.ts +4 -1
- package/dist/task-board-waker.js +13 -2
- package/dist/task-board-waker.js.map +1 -1
- package/dist/tool-permissions.js +3 -10
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.d.ts +27 -7
- package/dist/topic-commands.js +95 -36
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-monitor.d.ts +7 -0
- package/dist/transcript-monitor.js +48 -3
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/tunnel/cloudflared.d.ts +5 -0
- package/dist/tunnel/cloudflared.js +32 -1
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/named-diagnostics.d.ts +2 -1
- package/dist/tunnel/named-diagnostics.js +4 -1
- package/dist/tunnel/named-diagnostics.js.map +1 -1
- package/dist/tunnel/named-link-test.d.ts +90 -0
- package/dist/tunnel/named-link-test.js +270 -0
- package/dist/tunnel/named-link-test.js.map +1 -0
- package/dist/tunnel/purpose-lane.d.ts +3 -1
- package/dist/tunnel/purpose-lane.js +2 -0
- package/dist/tunnel/purpose-lane.js.map +1 -1
- package/dist/types.d.ts +8 -6
- package/dist/ui/chat-ambient.js +4 -4
- package/dist/ui/chat-commands.js +3 -2
- package/dist/ui/chat-store.js +4 -1
- package/dist/ui/chat-strings.js +12 -46
- package/dist/ui/chat-thread.js +51 -59
- package/dist/ui/fleet-office-skin.js +37 -14
- package/dist/ui/fleet-office.js +31 -7
- package/dist/ui/html-attachment.js +22 -8
- package/dist/ui/panel-chat.js +21 -50
- package/dist/ui/panel-needs.js +11 -9
- package/dist/ui/panel-settings.js +5 -3
- package/dist/ui/preview-panel.js +12 -21
- package/dist/ui/preview.js +10 -3
- package/dist/ui/search-dialog.js +30 -14
- package/dist/ui/settings-appearance.js +1 -3
- package/dist/ui/settings-confirm.js +18 -0
- package/dist/ui/settings-guests.js +13 -4
- package/dist/ui/settings-learn.js +1 -1
- package/dist/ui/settings-mods.js +5 -12
- package/dist/ui/settings-named-test.js +144 -0
- package/dist/ui/settings-registry.js +0 -1
- package/dist/ui/settings-strings.js +14 -14
- package/dist/ui/settings-web-authority.js +4 -3
- package/dist/ui/shared/app-i18n.js +15 -4
- package/dist/ui/shared/app-needs.js +5 -1
- package/dist/ui/shared/app-prefs.js +17 -17
- package/dist/ui/shared/app-shell.js +47 -9
- package/dist/ui/shared/app-store.js +6 -2
- package/dist/ui/shared/app.css +33 -39
- package/dist/ui/shared/app.js +5 -4
- package/dist/ui/shared/instance-nav.js +9 -9
- package/dist/ui/shared/instance-switch.js +8 -2
- package/dist/ui/shared/panel-view.js +22 -8
- package/dist/ui/shared/view-strings.js +6 -0
- package/dist/ui/shared/web-authorize.js +35 -13
- package/dist/usage/usage-api.d.ts +3 -0
- package/dist/usage/usage-api.js +5 -1
- package/dist/usage/usage-api.js.map +1 -1
- package/dist/view-api.d.ts +2 -0
- package/dist/view-api.js +64 -0
- package/dist/view-api.js.map +1 -1
- package/dist/web-api.d.ts +9 -17
- package/dist/web-api.js +257 -371
- package/dist/web-api.js.map +1 -1
- package/dist/web-appearance-tools.d.ts +0 -2
- package/dist/web-appearance-tools.js +2 -5
- package/dist/web-appearance-tools.js.map +1 -1
- package/dist/web-appearance-view.d.ts +0 -6
- package/dist/web-appearance-view.js +0 -1
- package/dist/web-appearance-view.js.map +1 -1
- package/dist/web-appearance.d.ts +14 -7
- package/dist/web-appearance.js +5 -6
- package/dist/web-appearance.js.map +1 -1
- package/dist/web-asset-parts.d.ts +1 -17
- package/dist/web-asset-parts.js +1 -15
- package/dist/web-asset-parts.js.map +1 -1
- package/dist/web-auth.js +1 -7
- package/dist/web-auth.js.map +1 -1
- package/dist/web-chat-history.d.ts +3 -7
- package/dist/web-chat-history.js +10 -17
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +9 -1
- package/dist/web-commands.js +13 -0
- package/dist/web-commands.js.map +1 -1
- package/dist/web-experimental.d.ts +2 -11
- package/dist/web-experimental.js +8 -36
- package/dist/web-experimental.js.map +1 -1
- package/dist/web-guest-access.d.ts +40 -2
- package/dist/web-guest-access.js +50 -14
- package/dist/web-guest-access.js.map +1 -1
- package/dist/web-mod-bundle.d.ts +2 -45
- package/dist/web-mod-bundle.js +15 -63
- package/dist/web-mod-bundle.js.map +1 -1
- package/dist/web-mod-store.d.ts +3 -48
- package/dist/web-mod-store.js +30 -97
- package/dist/web-mod-store.js.map +1 -1
- package/dist/web-prefs.d.ts +13 -0
- package/dist/web-prefs.js +38 -0
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-preview.d.ts +6 -13
- package/dist/web-preview.js +12 -23
- package/dist/web-preview.js.map +1 -1
- package/dist/web-session.d.ts +11 -3
- package/dist/web-session.js +22 -11
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +1 -0
- package/dist/web-settings-patch.js +6 -3
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-settings-tools.d.ts +0 -13
- package/dist/web-settings-tools.js +12 -84
- package/dist/web-settings-tools.js.map +1 -1
- package/launcher/agend-install.cjs +7 -1
- package/launcher/fleet-service-owner.cjs +150 -0
- package/package.json +1 -1
- package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +0 -376
- package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +0 -673
- package/dist/task-board-summary.d.ts +0 -101
- package/dist/task-board-summary.js +0 -177
- package/dist/task-board-summary.js.map +0 -1
- package/dist/ui/app-effects.js +0 -251
- package/dist/ui/chat-effect-posters.js +0 -42
- package/dist/ui/chat-effects.js +0 -167
- package/dist/ui/effect-trial-controller.js +0 -124
- package/dist/ui/effect-trial-offer.js +0 -2
- package/dist/ui/effect-trial-panel.js +0 -40
- package/dist/ui/effects-waker.js +0 -2
- package/dist/ui/settings-effects.js +0 -202
- package/dist/ui/settings-owner-effects.js +0 -82
- package/dist/ui/shared/effect-app-runtime.js +0 -299
- package/dist/ui/shared/effect-baseline.js +0 -64
- package/dist/ui/shared/effect-chat-runtime.js +0 -162
- package/dist/ui/shared/effect-cursor.js +0 -126
- package/dist/ui/shared/effect-display-metadata.js +0 -39
- package/dist/ui/shared/effect-frame.js +0 -146
- package/dist/ui/shared/effect-geometry.js +0 -137
- package/dist/ui/shared/effect-host-style.js +0 -10
- package/dist/ui/shared/effect-owner-regions.js +0 -74
- package/dist/ui/shared/effect-owner-source.js +0 -122
- package/dist/ui/shared/effect-policy.js +0 -151
- package/dist/ui/shared/effect-poster-reader.js +0 -98
- package/dist/ui/shared/effect-posters.js +0 -117
- package/dist/ui/shared/effect-profiler.js +0 -184
- package/dist/ui/shared/effect-profiles.js +0 -65
- package/dist/ui/shared/effect-registry.js +0 -545
- package/dist/ui/shared/effect-runtime-loader.js +0 -236
- package/dist/ui/shared/effect-safety.js +0 -153
- package/dist/ui/shared/effect-stock-snapshot.js +0 -43
- package/dist/ui/shared/effect-stock-trust.js +0 -217
- package/dist/ui/shared/effect-trial-shadow.js +0 -62
- package/dist/ui/shared/effect-trial-source.js +0 -103
- package/dist/ui/shared/effect-trial-stage.js +0 -170
- package/dist/ui/shared/effect-trial.css +0 -40
- package/dist/ui/shared/feature-flags.js +0 -127
- package/dist/ui/shared/owner-effect-prefs.js +0 -117
- package/dist/web-effect-bootstrap.d.ts +0 -12
- package/dist/web-effect-bootstrap.js +0 -49
- package/dist/web-effect-bootstrap.js.map +0 -1
- package/dist/web-effect-bundle.d.ts +0 -28
- package/dist/web-effect-bundle.js +0 -171
- package/dist/web-effect-bundle.js.map +0 -1
- package/dist/web-effect-canonical.d.ts +0 -8
- package/dist/web-effect-canonical.js +0 -27
- package/dist/web-effect-canonical.js.map +0 -1
- package/dist/web-effect-library.d.ts +0 -114
- package/dist/web-effect-library.js +0 -530
- package/dist/web-effect-library.js.map +0 -1
- package/dist/web-effect-playback.d.ts +0 -30
- package/dist/web-effect-playback.js +0 -71
- package/dist/web-effect-playback.js.map +0 -1
- package/dist/web-effect-poster.d.ts +0 -8
- package/dist/web-effect-poster.js +0 -52
- package/dist/web-effect-poster.js.map +0 -1
- package/dist/web-effect-profiles.d.ts +0 -118
- package/dist/web-effect-profiles.js +0 -181
- package/dist/web-effect-profiles.js.map +0 -1
- package/dist/web-effect-service.d.ts +0 -93
- package/dist/web-effect-service.js +0 -335
- package/dist/web-effect-service.js.map +0 -1
- package/dist/web-effect-tools.d.ts +0 -48
- package/dist/web-effect-tools.js +0 -129
- package/dist/web-effect-tools.js.map +0 -1
- package/dist/web-effect-trials.d.ts +0 -86
- package/dist/web-effect-trials.js +0 -204
- package/dist/web-effect-trials.js.map +0 -1
- package/dist/web-effect-upload.d.ts +0 -27
- package/dist/web-effect-upload.js +0 -185
- package/dist/web-effect-upload.js.map +0 -1
- package/dist/web-effect-worker.d.ts +0 -8
- package/dist/web-effect-worker.js +0 -170
- package/dist/web-effect-worker.js.map +0 -1
- package/dist/web-effect.d.ts +0 -103
- package/dist/web-effect.js +0 -153
- package/dist/web-effect.js.map +0 -1
- package/dist/web-experimental-http.d.ts +0 -2
- package/dist/web-experimental-http.js +0 -12
- package/dist/web-experimental-http.js.map +0 -1
- package/dist/web-mod-agent.d.ts +0 -50
- package/dist/web-mod-agent.js +0 -207
- package/dist/web-mod-agent.js.map +0 -1
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import type { Card, Project, ProjectStats } from "./scheduler/task-board.js";
|
|
2
|
-
/** Cards listed per section; the rest are counted. */
|
|
3
|
-
export declare const SUMMARY_LISTED = 10;
|
|
4
|
-
/**
|
|
5
|
-
* `defaults.task_board.summary_at`: `"HH:MM"` (24 h) → itself, `"off"` (any case) or not set → null (off); anything
|
|
6
|
-
* else → undefined (the validator refuses it; the clock then sends nothing). Off unless set (2.3.0-beta.25, the
|
|
7
|
-
* user's call after beta.24's task-board flood, #2425): a fleet that wants the summary names its time.
|
|
8
|
-
*/
|
|
9
|
-
export declare function summaryTime(value: unknown): string | null | undefined;
|
|
10
|
-
/** The wall clock at `now` in `zone` ("YYYY-MM-DD", "HH:MM"); a zone the runtime does not know reads as UTC. */
|
|
11
|
-
export declare function wallClock(now: Date, zone: string): {
|
|
12
|
-
date: string;
|
|
13
|
-
time: string;
|
|
14
|
-
};
|
|
15
|
-
/** When the last summary went out: its local date and the end of the time it covered. */
|
|
16
|
-
export interface SummaryMark {
|
|
17
|
-
date: string;
|
|
18
|
-
until: string;
|
|
19
|
-
}
|
|
20
|
-
/** The mark on disk (`<dataDir>/task-board-summary.json`); a missing or unreadable file is no mark. */
|
|
21
|
-
export declare function summaryMarkFile(path: string): {
|
|
22
|
-
read(): SummaryMark | null;
|
|
23
|
-
write(mark: SummaryMark): void;
|
|
24
|
-
};
|
|
25
|
-
export interface SummaryClockDeps {
|
|
26
|
-
/** `defaults.task_board.summary_at` as it is now ("HH:MM"), or null when off. Read at every look. */
|
|
27
|
-
at(): string | null;
|
|
28
|
-
zone(): string;
|
|
29
|
-
now(): Date;
|
|
30
|
-
mark: {
|
|
31
|
-
read(): SummaryMark | null;
|
|
32
|
-
write(mark: SummaryMark): void;
|
|
33
|
-
};
|
|
34
|
-
/** Gather and post the summary of [since, until). */
|
|
35
|
-
send(since: Date, until: Date): void;
|
|
36
|
-
/** A look that threw (the data directory gone, a board that cannot be read): logged, and the next look tries again. */
|
|
37
|
-
failed?(err: unknown): void;
|
|
38
|
-
setInterval?(fn: () => void, ms: number): unknown;
|
|
39
|
-
clearInterval?(handle: unknown): void;
|
|
40
|
-
}
|
|
41
|
-
export declare class TaskBoardSummaryClock {
|
|
42
|
-
private readonly deps;
|
|
43
|
-
private timer;
|
|
44
|
-
private first;
|
|
45
|
-
constructor(deps: SummaryClockDeps);
|
|
46
|
-
/** A look 5 s after start (a summary missed while the fleet was down), then every minute. */
|
|
47
|
-
start(): void;
|
|
48
|
-
stop(): void;
|
|
49
|
-
/** One look: true when a summary was due today and is now handled (sent, or quiet). */
|
|
50
|
-
tick(): boolean;
|
|
51
|
-
}
|
|
52
|
-
export interface ProjectLine {
|
|
53
|
-
name: string;
|
|
54
|
-
percent: number;
|
|
55
|
-
done: number;
|
|
56
|
-
total: number;
|
|
57
|
-
waiting: number;
|
|
58
|
-
blocked: number;
|
|
59
|
-
}
|
|
60
|
-
export interface BoardSummary {
|
|
61
|
-
since: Date;
|
|
62
|
-
until: Date;
|
|
63
|
-
review: Card[];
|
|
64
|
-
blocked: Card[];
|
|
65
|
-
done: Card[];
|
|
66
|
-
created: Card[];
|
|
67
|
-
projects: ProjectLine[];
|
|
68
|
-
}
|
|
69
|
-
export interface SummaryRead {
|
|
70
|
-
/** What waits for the person now (TaskBoard.waitingForPerson): review cards that need them, blocked cards they handed out. */
|
|
71
|
-
waiting: Card[];
|
|
72
|
-
done: Card[];
|
|
73
|
-
created: Card[];
|
|
74
|
-
/** Every live main task's project and assignee: a project's line goes to the chats whose instances hold one. */
|
|
75
|
-
mains: Array<{
|
|
76
|
-
projectId: number | null;
|
|
77
|
-
assignee: string | null;
|
|
78
|
-
}>;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* One chat's summary: the cards `inChat` keeps (by assignee), and the active projects one of its cards' main tasks is
|
|
82
|
-
* in, with the project's numbers over all its cards (projectStats).
|
|
83
|
-
*/
|
|
84
|
-
export declare function buildSummary(read: SummaryRead, since: Date, until: Date, opts: {
|
|
85
|
-
inChat(assignee: string | null): boolean;
|
|
86
|
-
projects: Project[];
|
|
87
|
-
stats: Record<string, ProjectStats>;
|
|
88
|
-
}): BoardSummary;
|
|
89
|
-
/** Nothing waits and nothing moved: no summary that day. */
|
|
90
|
-
export declare function isQuiet(s: BoardSummary): boolean;
|
|
91
|
-
type T = (key: string, ...args: (string | number)[]) => string;
|
|
92
|
-
/**
|
|
93
|
-
* The summary as plain text in the fleet's language (no markup: Telegram, Discord and the web chat read it the same).
|
|
94
|
-
* `projectOf`: a main task's project name.
|
|
95
|
-
*/
|
|
96
|
-
export declare function renderSummary(s: BoardSummary, opts: {
|
|
97
|
-
zone: string;
|
|
98
|
-
t: T;
|
|
99
|
-
projectOf(card: Card): string | null;
|
|
100
|
-
}): string;
|
|
101
|
-
export {};
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* #2246 step 3: the task board's daily summary for the person, as taskhall sends it. Once a day at
|
|
3
|
-
* `defaults.task_board.summary_at` (the fleet's zone): what waits for their confirmation and what is blocked now, what
|
|
4
|
-
* got done and what was opened since the last summary, and each project's progress. Each chat world's General gets the
|
|
5
|
-
* cards of its own instances (a card nobody in a world holds goes to the primary one); the web chat's Generals too.
|
|
6
|
-
*
|
|
7
|
-
* The clock is taskhall's: it looks every minute, sends at most once a calendar day, and a summary missed while the
|
|
8
|
-
* fleet was down goes out when it is back that day, covering the time since the last one (at most a week). A quiet day
|
|
9
|
-
* (nothing waits, nothing moved) sends nothing. The first summary after this ships waits for the next morning.
|
|
10
|
-
*/
|
|
11
|
-
import { atomicWriteFileSync } from "./atomic-write.js";
|
|
12
|
-
import { readFileSync } from "node:fs";
|
|
13
|
-
/** Cards listed per section; the rest are counted. */
|
|
14
|
-
export const SUMMARY_LISTED = 10;
|
|
15
|
-
const WEEK_MS = 7 * 86_400_000;
|
|
16
|
-
/**
|
|
17
|
-
* `defaults.task_board.summary_at`: `"HH:MM"` (24 h) → itself, `"off"` (any case) or not set → null (off); anything
|
|
18
|
-
* else → undefined (the validator refuses it; the clock then sends nothing). Off unless set (2.3.0-beta.25, the
|
|
19
|
-
* user's call after beta.24's task-board flood, #2425): a fleet that wants the summary names its time.
|
|
20
|
-
*/
|
|
21
|
-
export function summaryTime(value) {
|
|
22
|
-
if (value === undefined || value === null)
|
|
23
|
-
return null;
|
|
24
|
-
if (typeof value !== "string")
|
|
25
|
-
return undefined;
|
|
26
|
-
const v = value.trim().toLowerCase();
|
|
27
|
-
if (v === "off")
|
|
28
|
-
return null;
|
|
29
|
-
return /^([01]\d|2[0-3]):[0-5]\d$/.test(v) ? v : undefined;
|
|
30
|
-
}
|
|
31
|
-
/** The wall clock at `now` in `zone` ("YYYY-MM-DD", "HH:MM"); a zone the runtime does not know reads as UTC. */
|
|
32
|
-
export function wallClock(now, zone) {
|
|
33
|
-
let wall;
|
|
34
|
-
try {
|
|
35
|
-
wall = now.toLocaleString("sv-SE", { timeZone: zone, hour12: false });
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
wall = now.toLocaleString("sv-SE", { timeZone: "UTC", hour12: false });
|
|
39
|
-
}
|
|
40
|
-
return { date: wall.slice(0, 10), time: wall.slice(11, 16) };
|
|
41
|
-
}
|
|
42
|
-
/** The mark on disk (`<dataDir>/task-board-summary.json`); a missing or unreadable file is no mark. */
|
|
43
|
-
export function summaryMarkFile(path) {
|
|
44
|
-
return {
|
|
45
|
-
read() {
|
|
46
|
-
try {
|
|
47
|
-
const m = JSON.parse(readFileSync(path, "utf8"));
|
|
48
|
-
return typeof m.date === "string" && typeof m.until === "string" ? { date: m.date, until: m.until } : null;
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
write(mark) { atomicWriteFileSync(path, JSON.stringify(mark) + "\n"); },
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
export class TaskBoardSummaryClock {
|
|
58
|
-
deps;
|
|
59
|
-
timer = null;
|
|
60
|
-
first = null;
|
|
61
|
-
constructor(deps) {
|
|
62
|
-
this.deps = deps;
|
|
63
|
-
}
|
|
64
|
-
/** A look 5 s after start (a summary missed while the fleet was down), then every minute. */
|
|
65
|
-
start() {
|
|
66
|
-
if (this.timer)
|
|
67
|
-
return;
|
|
68
|
-
const every = this.deps.setInterval ?? ((fn, ms) => { const h = setInterval(fn, ms); h.unref?.(); return h; });
|
|
69
|
-
const look = () => { try {
|
|
70
|
-
this.tick();
|
|
71
|
-
}
|
|
72
|
-
catch (err) {
|
|
73
|
-
this.deps.failed?.(err);
|
|
74
|
-
} };
|
|
75
|
-
this.timer = every(look, 60_000);
|
|
76
|
-
this.first = setTimeout(look, 5_000);
|
|
77
|
-
this.first.unref?.();
|
|
78
|
-
}
|
|
79
|
-
stop() {
|
|
80
|
-
if (this.timer)
|
|
81
|
-
(this.deps.clearInterval ?? ((h) => clearInterval(h)))(this.timer);
|
|
82
|
-
if (this.first)
|
|
83
|
-
clearTimeout(this.first);
|
|
84
|
-
this.timer = null;
|
|
85
|
-
this.first = null;
|
|
86
|
-
}
|
|
87
|
-
/** One look: true when a summary was due today and is now handled (sent, or quiet). */
|
|
88
|
-
tick() {
|
|
89
|
-
const at = this.deps.at();
|
|
90
|
-
if (!at)
|
|
91
|
-
return false;
|
|
92
|
-
const now = this.deps.now();
|
|
93
|
-
const wall = wallClock(now, this.deps.zone());
|
|
94
|
-
if (wall.time < at)
|
|
95
|
-
return false;
|
|
96
|
-
const last = this.deps.mark.read();
|
|
97
|
-
if (last?.date === wall.date)
|
|
98
|
-
return false;
|
|
99
|
-
// Marked before it is sent: a send that throws does not repeat every minute.
|
|
100
|
-
this.deps.mark.write({ date: wall.date, until: now.toISOString() });
|
|
101
|
-
if (!last)
|
|
102
|
-
return false; // the first day: nothing to look back on yet; the next one covers from now
|
|
103
|
-
const since = Math.min(Math.max(Date.parse(last.until) || 0, now.getTime() - WEEK_MS), now.getTime());
|
|
104
|
-
this.deps.send(new Date(since), now);
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
/** Main tasks first, then by number. */
|
|
109
|
-
const byNumber = (a, b) => (a.kind === b.kind ? 0 : a.kind === "main" ? -1 : 1) || Number(a.code.slice(2)) - Number(b.code.slice(2));
|
|
110
|
-
/**
|
|
111
|
-
* One chat's summary: the cards `inChat` keeps (by assignee), and the active projects one of its cards' main tasks is
|
|
112
|
-
* in, with the project's numbers over all its cards (projectStats).
|
|
113
|
-
*/
|
|
114
|
-
export function buildSummary(read, since, until, opts) {
|
|
115
|
-
const mine = (cards) => cards.filter((c) => opts.inChat(c.assignee)).sort(byNumber);
|
|
116
|
-
const here = new Set(read.mains.filter((m) => m.projectId !== null && opts.inChat(m.assignee)).map((m) => m.projectId));
|
|
117
|
-
return {
|
|
118
|
-
since, until,
|
|
119
|
-
review: mine(read.waiting.filter((c) => c.status === "review")),
|
|
120
|
-
blocked: mine(read.waiting.filter((c) => c.status === "blocked")),
|
|
121
|
-
done: mine(read.done),
|
|
122
|
-
created: mine(read.created),
|
|
123
|
-
projects: opts.projects.filter((p) => !p.archived && here.has(p.id)).flatMap((p) => {
|
|
124
|
-
const st = opts.stats[String(p.id)];
|
|
125
|
-
return st && st.mains ? [{ name: p.name, percent: st.percent, done: st.units.done, total: st.units.total, waiting: st.waiting, blocked: st.blocked }] : [];
|
|
126
|
-
}),
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
/** Nothing waits and nothing moved: no summary that day. */
|
|
130
|
-
export function isQuiet(s) {
|
|
131
|
-
return !s.review.length && !s.blocked.length && !s.done.length && !s.created.length;
|
|
132
|
-
}
|
|
133
|
-
const short = (s, n) => (Array.from(s).length > n ? Array.from(s).slice(0, n - 1).join("") + "…" : s);
|
|
134
|
-
/** `M/D HH:MM` in the fleet's zone. */
|
|
135
|
-
function shortTime(d, zone) {
|
|
136
|
-
const { date, time } = wallClock(d, zone);
|
|
137
|
-
return `${Number(date.slice(5, 7))}/${Number(date.slice(8, 10))} ${time}`;
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* The summary as plain text in the fleet's language (no markup: Telegram, Discord and the web chat read it the same).
|
|
141
|
-
* `projectOf`: a main task's project name.
|
|
142
|
-
*/
|
|
143
|
-
export function renderSummary(s, opts) {
|
|
144
|
-
const { t } = opts;
|
|
145
|
-
const ref = (c) => t("board_summary.card", c.code, short(c.title, 30))
|
|
146
|
-
+ (c.kind === "main" ? (opts.projectOf(c) ? ` · ${opts.projectOf(c)}` : "") : c.assignee ? ` @${c.assignee}` : "");
|
|
147
|
-
const list = (cards, line) => {
|
|
148
|
-
const out = cards.slice(0, SUMMARY_LISTED).map((c) => `• ${line(c)}`);
|
|
149
|
-
if (cards.length > SUMMARY_LISTED)
|
|
150
|
-
out.push(`• ${t("board_summary.more", cards.length - SUMMARY_LISTED)}`);
|
|
151
|
-
return out;
|
|
152
|
-
};
|
|
153
|
-
// Finished and new: a main task a line each, sub tasks folded into one line of numbers.
|
|
154
|
-
const folded = (cards) => {
|
|
155
|
-
const mains = cards.filter((c) => c.kind === "main"), subs = cards.filter((c) => c.kind === "sub");
|
|
156
|
-
const out = list(mains, ref);
|
|
157
|
-
if (subs.length) {
|
|
158
|
-
const codes = subs.slice(0, SUMMARY_LISTED).map((c) => c.code).join(t("board_summary.join"));
|
|
159
|
-
out.push(`• ${t(subs.length > SUMMARY_LISTED ? "board_summary.subs_more" : "board_summary.subs", subs.length, codes)}`);
|
|
160
|
-
}
|
|
161
|
-
return out;
|
|
162
|
-
};
|
|
163
|
-
const blocks = [t("board_summary.title", shortTime(s.since, opts.zone), shortTime(s.until, opts.zone))];
|
|
164
|
-
const section = (title, lines) => { if (lines.length)
|
|
165
|
-
blocks.push([title, ...lines].join("\n")); };
|
|
166
|
-
section(t("board_summary.review", s.review.length), list(s.review, ref));
|
|
167
|
-
section(t("board_summary.blocked", s.blocked.length), list(s.blocked, (c) => ref(c) + (c.kind === "main" && c.assignee ? ` @${c.assignee}` : "") + (c.blockedReason ? t("board_summary.reason", short(c.blockedReason, 60)) : "")));
|
|
168
|
-
section(t("board_summary.done", s.done.length), folded(s.done));
|
|
169
|
-
section(t("board_summary.created", s.created.length), folded(s.created));
|
|
170
|
-
section(t("board_summary.projects"), s.projects.map((p) => {
|
|
171
|
-
const extra = [p.waiting ? t("board_summary.project_waiting", p.waiting) : "", p.blocked ? t("board_summary.project_blocked", p.blocked) : ""].filter(Boolean);
|
|
172
|
-
return `• ${t("board_summary.project", p.name, p.percent, p.done, p.total)}${extra.length ? t("board_summary.project_extra", extra.join(t("board_summary.join"))) : ""}`;
|
|
173
|
-
}));
|
|
174
|
-
blocks.push(t("board_summary.footer"));
|
|
175
|
-
return blocks.join("\n\n");
|
|
176
|
-
}
|
|
177
|
-
//# sourceMappingURL=task-board-summary.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"task-board-summary.js","sourceRoot":"","sources":["../src/task-board-summary.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/app-effects.js
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
/** #1629: one session-only app effect owner. Importing this module starts nothing. */
|
|
2
|
-
import { appStore } from "/assets/app-store.js";
|
|
3
|
-
import { motionBlocked, onMotionChange } from "/assets/fx-motion.js";
|
|
4
|
-
import { navStore } from "/assets/app-nav.js";
|
|
5
|
-
import { onPrefsChanged } from "/assets/app-prefs.js";
|
|
6
|
-
import { resolvedMode, themesStore, themesShown } from "/assets/app-themes.js";
|
|
7
|
-
import { ownerCssLifecycle, safeMode } from "/assets/owner-css.js";
|
|
8
|
-
import { canvasWorkerEnabled } from "/assets/feature-flags.js";
|
|
9
|
-
import { constrainedDevice } from "/assets/effect-policy.js";
|
|
10
|
-
import { createAppEffectRuntime } from "/assets/effect-app-runtime.js";
|
|
11
|
-
import { effectBootstrapReady } from "/assets/effect-frame.js";
|
|
12
|
-
import { createEffectCursor } from "/assets/effect-cursor.js";
|
|
13
|
-
import { createOwnerEffectRegions } from "/assets/effect-owner-regions.js";
|
|
14
|
-
import { chatEffectIdentity, effectPlaybackIdentity } from "/assets/effect-chat-runtime.js";
|
|
15
|
-
import { createEffectTrialController } from "./effect-trial-controller.js";
|
|
16
|
-
import { effectTrialMessage } from "./effect-trial-offer.js";
|
|
17
|
-
import { claimPanel, panelVersion, panelStore, openTrialPanel, closePanel } from "./preview-panel.js";
|
|
18
|
-
const owners = new WeakMap();
|
|
19
|
-
export function getAppEffects(host = window) { const value = owners.get(host); return value && !value.dead && value.api?.ok ? value : null; }
|
|
20
|
-
|
|
21
|
-
/** Boot once with the page's Chat store, including when the first visible panel is Fleet. */
|
|
22
|
-
export function startAppEffects({ store, window: host = window, factories = {} } = {}) {
|
|
23
|
-
if (!canvasWorkerEnabled()) return null;
|
|
24
|
-
const existing = owners.get(host);
|
|
25
|
-
if (existing) { if (!existing.dead) existing.bindStore(store); return getAppEffects(host); }
|
|
26
|
-
const playbackIdentity = effectPlaybackIdentity(host), ownerIdentity = chatEffectIdentity(host);
|
|
27
|
-
if (!playbackIdentity || typeof host.AgendAuth?.onSessionEnd !== "function" || typeof host.AgendAuth?.sessionEnded !== "function") return null;
|
|
28
|
-
const doc = host.document, releases = [], ended = new Set(), updates = new Set(), trialUpdates = new Set(); let replyOff = null, replyStore = null, regions = null, cursor = null, cursorStamp = null, trialControl = null, trialIntent = null, trialHint = ownerIdentity ? null : false, trialSerial = 0, trialStamp = null, chatBinding = null;
|
|
29
|
-
const safe = fn => { try { return fn(); } catch { return null; } };
|
|
30
|
-
const hold = off => { if (entry.dead) safe(() => off?.()); else releases.push(off); };
|
|
31
|
-
const entry = { dead: false, api: null, disposed: null,
|
|
32
|
-
cursorSnapshot: () => cursor?.snapshot() ?? { status: "unavailable", id: null },
|
|
33
|
-
gates: () => context(),
|
|
34
|
-
subscribe(fn) { if (typeof fn !== "function" || entry.dead) return () => {}; updates.add(fn); return () => updates.delete(fn); },
|
|
35
|
-
subscribeTrial(fn) { if (typeof fn !== "function" || entry.dead) return () => {}; trialUpdates.add(fn); return () => trialUpdates.delete(fn); },
|
|
36
|
-
onEnd(fn) { if (typeof fn !== "function") return () => {}; if (entry.dead) { safe(fn); return () => {}; } ended.add(fn); return () => ended.delete(fn); },
|
|
37
|
-
bindStore(value) {
|
|
38
|
-
if (entry.dead || value === replyStore) return;
|
|
39
|
-
safe(() => replyOff?.()); replyOff = null; replyStore = value;
|
|
40
|
-
trialControl?.stop(); chatBinding = null; entry.api?.detachChat();
|
|
41
|
-
if (typeof value?.onAgentReply === "function") {
|
|
42
|
-
const off = value.onAgentReply(event => { if (!entry.dead && replyStore === value) entry.api?.reply(event); });
|
|
43
|
-
if (entry.dead || replyStore !== value) safe(() => off?.()); else replyOff = off;
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
trialStatus(message) {
|
|
47
|
-
const offer = safe(() => effectTrialMessage(message)), nav = navStore.get();
|
|
48
|
-
const now = safe(() => host.Date.now());
|
|
49
|
-
if (!offer || !Number.isFinite(now) || now >= offer.expiresAt) return "expired";
|
|
50
|
-
if (trialHint === null && !entry.dead) return "checking";
|
|
51
|
-
if (entry.dead || !trialHint || trialControl?.ok !== true) return "localAdmin";
|
|
52
|
-
if (!chatBinding || safe(() => chatBinding.current()) !== true || message.instance !== nav.route?.instance || nav.route?.panel !== "chat") return "chatChanged";
|
|
53
|
-
const state = trialControl.snapshot();
|
|
54
|
-
if (state.phase !== "idle" || state.busy) return "busy";
|
|
55
|
-
return trialPlaybackStatus();
|
|
56
|
-
},
|
|
57
|
-
trialFailure(message) {
|
|
58
|
-
const offer = safe(() => effectTrialMessage(message)), state = trialControl?.snapshot();
|
|
59
|
-
return offer && state?.phase === "idle" && state.offer === offer.offer && !["stopped", "replaced"].includes(state.reason) ? state.reason : null;
|
|
60
|
-
},
|
|
61
|
-
canTry(message) { return entry.trialStatus(message) === "ready"; },
|
|
62
|
-
stopTrial() { trialControl?.stop(); },
|
|
63
|
-
startTrial(message) {
|
|
64
|
-
if (!entry.canTry(message)) return Promise.resolve(false);
|
|
65
|
-
const nav = navStore.get(); trialIntent = { name: message.instance, seq: nav.seq, claim: claimPanel(), handle: null, chat: chatBinding };
|
|
66
|
-
return trialControl.start(message);
|
|
67
|
-
},
|
|
68
|
-
attachChat(options) {
|
|
69
|
-
const nav = navStore.get(), name = options?.name;
|
|
70
|
-
if (entry.dead || !entry.api?.ok || nav.route?.panel !== "chat" || nav.route.instance !== name || typeof options.current !== "function") return null;
|
|
71
|
-
const binding = { current: () => !entry.dead && host.document === doc && navStore.get().seq === nav.seq && navStore.get().route?.panel === "chat" && navStore.get().route?.instance === name && options.current() === true };
|
|
72
|
-
chatBinding = binding; trialControl?.stop();
|
|
73
|
-
if (entry.dead || chatBinding !== binding) return null;
|
|
74
|
-
const handle = entry.api.attachChat({ ...options, current: () => chatBinding === binding && binding.current() });
|
|
75
|
-
if (entry.dead || chatBinding !== binding) { safe(() => handle?.dispose()); return null; }
|
|
76
|
-
if (!handle) chatBinding = null;
|
|
77
|
-
return handle;
|
|
78
|
-
},
|
|
79
|
-
dispose(restartable = false) {
|
|
80
|
-
if (entry.dead) return entry.disposed; entry.dead = true;
|
|
81
|
-
if (restartable && owners.get(host) === entry) owners.delete(host);
|
|
82
|
-
safe(() => trialControl?.dispose()); const coreDisposed = safe(() => entry.api?.dispose(restartable === true)); safe(() => replyOff?.()); replyOff = null; replyStore = null;
|
|
83
|
-
for (const off of releases.splice(0)) safe(off);
|
|
84
|
-
updates.clear(); trialUpdates.clear(); const listeners = [...ended]; ended.clear(); for (const fn of listeners) safe(fn);
|
|
85
|
-
entry.disposed = Promise.all([coreDisposed, safe(() => cursor?.whenDisposed?.())]);
|
|
86
|
-
return entry.disposed;
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
owners.set(host, entry); // Reentrant setup never constructs another owner.
|
|
90
|
-
let media, coarse;
|
|
91
|
-
function ownerCssForPlayback() {
|
|
92
|
-
if (doc.body.dataset.tier !== "guest") return ownerCssLifecycle.get().state;
|
|
93
|
-
// Guests never install owner CSS. Prove its absence rather than borrowing the uninstalled
|
|
94
|
-
// lifecycle's initial unknown, and refuse unexpected styles instead of trusting a missing id.
|
|
95
|
-
try {
|
|
96
|
-
if (doc.body.dataset.ownerCss || doc.querySelectorAll("#owner-css").length) return "unknown";
|
|
97
|
-
// A CSP-refused or disabled STYLE has no paint. Recheck on every proof so enabling
|
|
98
|
-
// it never borrows an earlier absence verdict (WebKit capture inserts a refused no-op).
|
|
99
|
-
for (const style of doc.querySelectorAll("style")) if (style.sheet && style.sheet.disabled !== true) return "unknown";
|
|
100
|
-
const allowed = new Set(["/assets/tokens.css", "/assets/app.css"]);
|
|
101
|
-
for (const link of doc.querySelectorAll('link[rel~="stylesheet"]')) {
|
|
102
|
-
const url = new URL(link.getAttribute("href"), host.location.origin);
|
|
103
|
-
if (url.origin !== host.location.origin || !allowed.has(url.pathname) || url.search || url.hash) return "unknown";
|
|
104
|
-
}
|
|
105
|
-
return "off";
|
|
106
|
-
} catch { return "unknown"; }
|
|
107
|
-
}
|
|
108
|
-
function guestChatVersion(value) {
|
|
109
|
-
if (doc.body.dataset.tier !== "guest") return null;
|
|
110
|
-
const name = navStore.get().route?.instance, v = value.instances?.find(i => i.name === name)?.effect_chat_v;
|
|
111
|
-
return typeof v === "string" && /^[a-f0-9]{32}$/.test(v) ? v : null;
|
|
112
|
-
}
|
|
113
|
-
// #2188: whether a dialog, menu or popover is open — a whole-document query when none is (the usual case), asked
|
|
114
|
-
// several times per sync. Read once per task: the cached value is dropped at the next microtask, and whenever the
|
|
115
|
-
// document changes (the MutationObserver below drops it before it reads).
|
|
116
|
-
let modalCache = null;
|
|
117
|
-
function modalOpen() {
|
|
118
|
-
if (modalCache === null) {
|
|
119
|
-
modalCache = !!doc.querySelector("dialog[open],.menu-list,.pop,[role=alertdialog],.oc-keep,.shell.sb-open");
|
|
120
|
-
Promise.resolve().then(() => { modalCache = null; });
|
|
121
|
-
}
|
|
122
|
-
return modalCache;
|
|
123
|
-
}
|
|
124
|
-
function context() {
|
|
125
|
-
return { safe: safeMode(), publicLink: doc.body.dataset.publicLink === "1", reducedMotion: motionBlocked(host), saveData: host.navigator?.connection?.saveData === true,
|
|
126
|
-
hidden: doc.visibilityState !== "visible", enabled: entry.api?.playbackAvailable !== false && typeof host.OffscreenCanvas === "function" && typeof host.Worker === "function" && typeof host.MutationObserver === "function" && typeof host.ResizeObserver === "function",
|
|
127
|
-
show: themesShown(), transportReady: effectBootstrapReady(host, host.location?.origin, doc.body.dataset.effectBoot),
|
|
128
|
-
constrained: constrainedDevice({ memory: host.navigator?.deviceMemory, cores: host.navigator?.hardwareConcurrency, coarse: coarse?.matches === true, width: host.innerWidth }),
|
|
129
|
-
modal: modalOpen(), openInstance: null };
|
|
130
|
-
}
|
|
131
|
-
function trialCurrent(name) {
|
|
132
|
-
const intent = trialIntent, nav = navStore.get();
|
|
133
|
-
return !entry.dead && host.document === doc && !!intent && !!intent.chat && chatBinding === intent.chat && intent.chat.current() === true && intent.name === name && nav.seq === intent.seq && nav.route?.panel === "chat" && nav.route.instance === name
|
|
134
|
-
&& (panelVersion() === intent.claim || intent.handle !== null && panelStore.get().open?.handle === intent.handle);
|
|
135
|
-
}
|
|
136
|
-
// One priority order feeds both presentation and redraw identity: false→different-false must redraw.
|
|
137
|
-
function trialPlaybackStatus() {
|
|
138
|
-
const c = context();
|
|
139
|
-
if (c.safe) return "safe";
|
|
140
|
-
if (!c.show) return "effectsOff";
|
|
141
|
-
if (c.reducedMotion) return "reducedMotion";
|
|
142
|
-
if (!c.enabled) return "unsupported";
|
|
143
|
-
if (!c.transportReady) return "transport";
|
|
144
|
-
if (c.publicLink) return "localAdmin";
|
|
145
|
-
if (c.hidden || doc.hasFocus?.() !== true) return "inactive";
|
|
146
|
-
if (c.modal) return "dialog";
|
|
147
|
-
return "ready";
|
|
148
|
-
}
|
|
149
|
-
function trialAllowed() {
|
|
150
|
-
const c = context();
|
|
151
|
-
return !entry.dead && doc.visibilityState === "visible" && doc.hasFocus?.() === true
|
|
152
|
-
&& c.enabled && c.show && c.transportReady && !c.safe && !c.publicLink && !c.reducedMotion && !c.hidden && !c.modal;
|
|
153
|
-
}
|
|
154
|
-
function mountTrial(handle) {
|
|
155
|
-
const intent = trialIntent; if (!intent || !trialCurrent(handle.instance) || !handle.current() || !Number.isSafeInteger(++trialSerial)) throw Error("trial_unavailable");
|
|
156
|
-
intent.handle = handle;
|
|
157
|
-
const binding = Object.freeze({ key: `trial:${trialSerial}:${handle.reply.trial}`, id: handle.reply.offer.id, run: handle.reply.trial, instance: handle.instance, generation: trialSerial });
|
|
158
|
-
let stage = null, source = null;
|
|
159
|
-
const cleanup = () => {
|
|
160
|
-
safe(() => source?.stop()); safe(() => stage?.dispose());
|
|
161
|
-
if (panelStore.get().open?.handle === handle) closePanel();
|
|
162
|
-
};
|
|
163
|
-
try {
|
|
164
|
-
openTrialPanel({ key: binding.key, instance: handle.instance, binding, handle,
|
|
165
|
-
onStage(value) {
|
|
166
|
-
stage = value;
|
|
167
|
-
if (!handle.current()) { cleanup(); handle.stop(); return; }
|
|
168
|
-
source = entry.api.attachTrial({ reply: handle.reply, offer: handle.reply.offer.offer, startedAt: handle.startedAt, stage,
|
|
169
|
-
current: handle.current, onStop: handle.stop });
|
|
170
|
-
if (!source) { cleanup(); handle.stop(); }
|
|
171
|
-
},
|
|
172
|
-
});
|
|
173
|
-
} catch (error) { cleanup(); throw error; }
|
|
174
|
-
return cleanup;
|
|
175
|
-
}
|
|
176
|
-
function notifyTrial() {
|
|
177
|
-
if (entry.dead) return;
|
|
178
|
-
const nav = navStore.get(), next = JSON.stringify([trialHint, safe(() => chatBinding?.current()) === true, trialPlaybackStatus(), nav.route?.panel, nav.route?.instance, trialControl?.snapshot()]);
|
|
179
|
-
if (next === trialStamp) return; trialStamp = next;
|
|
180
|
-
for (const fn of [...trialUpdates]) safe(fn);
|
|
181
|
-
}
|
|
182
|
-
const notify = () => { if (!entry.dead) { trialControl?.sync(); notifyTrial(); for (const fn of [...updates]) safe(fn); } };
|
|
183
|
-
const cursorDragging = () => doc.body.classList?.contains("side-resizing") === true || !!doc.querySelector(".chat-split.resizing");
|
|
184
|
-
function syncCursor() {
|
|
185
|
-
if (entry.dead || !cursor) return;
|
|
186
|
-
const c = context();
|
|
187
|
-
cursor.update(entry.api?.cursorSelection?.() ?? null, c.enabled && c.show && c.transportReady && !c.safe && !c.publicLink && !c.reducedMotion && !c.hidden && !c.modal && !cursorDragging());
|
|
188
|
-
}
|
|
189
|
-
try {
|
|
190
|
-
if (appStore.get().connection === "ended") { entry.dispose(); return null; }
|
|
191
|
-
media = host.matchMedia?.("(prefers-reduced-motion: reduce)") ?? { matches: true };
|
|
192
|
-
coarse = host.matchMedia?.("(pointer: coarse)") ?? { matches: false };
|
|
193
|
-
entry.api = (factories.runtime ?? createAppEffectRuntime)({ window: host, current: () => !entry.dead && host.document === doc,
|
|
194
|
-
observe: () => ({ context: context(), ownerCss: ownerCssForPlayback(), mode: resolvedMode() }), onDispose: () => entry.dispose(),
|
|
195
|
-
resolveOwnerTarget: (slot, manifest, proof) => !entry.dead ? regions?.resolve?.(slot, manifest.box, proof) ?? null : null,
|
|
196
|
-
onChange: () => { syncCursor(); notify(); } });
|
|
197
|
-
if (entry.dead || !entry.api.ok) { entry.dispose(); return null; }
|
|
198
|
-
if (ownerIdentity) trialControl = (factories.trialController ?? createEffectTrialController)({ window: host, current: trialCurrent, allowed: trialAllowed, onStart: mountTrial, onChange: notify });
|
|
199
|
-
hold(() => trialControl?.dispose());
|
|
200
|
-
if (ownerIdentity && typeof host.AgendAuth.trialSession === "function") Promise.resolve().then(() => host.AgendAuth.trialSession()).then(value => {
|
|
201
|
-
if (entry.dead) return; trialHint = value?.localAdmin === true && value.epoch === chatEffectIdentity(host)?.epoch; notify();
|
|
202
|
-
}).catch(() => { if (!entry.dead) { trialHint = false; notify(); } });
|
|
203
|
-
hold(panelStore.subscribe(() => { trialControl?.sync(); notifyTrial(); }));
|
|
204
|
-
const ownRegions = ownerIdentity && (factories.regions ?? createOwnerEffectRegions)({ window: host, current: () => !entry.dead && host.document === doc });
|
|
205
|
-
regions = ownRegions?.ok ? ownRegions : null; hold(() => ownRegions?.dispose?.());
|
|
206
|
-
if (entry.dead) return null;
|
|
207
|
-
const ownCursor = ownerIdentity && safe(() => (factories.cursor ?? createEffectCursor)({ window: host, current: () => !entry.dead && host.document === doc,
|
|
208
|
-
readImage: (selection, signal) => entry.api?.cursorImageSettled?.(selection, signal) ?? Promise.resolve(null),
|
|
209
|
-
onChange(value) { const next = JSON.stringify(value); if (next !== cursorStamp) { cursorStamp = next; notify(); } },
|
|
210
|
-
}));
|
|
211
|
-
cursor = ownCursor?.ok ? ownCursor : null; hold(() => ownCursor?.dispose?.());
|
|
212
|
-
if (entry.dead) return null;
|
|
213
|
-
const sync = () => { if (!entry.dead) { trialControl?.sync(); entry.api.sync(); syncCursor(); notifyTrial(); } };
|
|
214
|
-
let revision = appStore.get().themesRev, prefsRevision = appStore.get().prefsRev, guestRevision = guestChatVersion(appStore.get()), navSeq = navStore.get().seq;
|
|
215
|
-
hold(navStore.subscribe(value => { if (entry.dead || value.seq === navSeq) return; navSeq = value.seq; trialControl?.stop(); chatBinding = null; entry.api.detachChat(); syncCursor(); }));
|
|
216
|
-
hold(appStore.subscribe(value => {
|
|
217
|
-
if (entry.dead) return;
|
|
218
|
-
if (!canvasWorkerEnabled()) { entry.dispose(true); return; }
|
|
219
|
-
if (value.connection === "ended") { entry.dispose(); return; }
|
|
220
|
-
const guestNext = guestChatVersion(value), chatChanged = value.themesRev !== revision || guestNext !== guestRevision, ownerChanged = value.prefsRev !== prefsRevision;
|
|
221
|
-
revision = value.themesRev; prefsRevision = value.prefsRev; guestRevision = guestNext;
|
|
222
|
-
if (chatChanged) entry.api.changedChat();
|
|
223
|
-
if (ownerChanged) entry.api.changedOwner();
|
|
224
|
-
if (!chatChanged && !ownerChanged) sync();
|
|
225
|
-
}));
|
|
226
|
-
hold(ownerCssLifecycle.subscribe(sync)); hold(themesStore.subscribe(sync)); hold(onPrefsChanged(sync)); hold(onMotionChange(sync));
|
|
227
|
-
if (typeof host.AgendTheme?.onChange === "function") hold(host.AgendTheme.onChange(sync));
|
|
228
|
-
for (const [target, type] of [[media, "change"], [coarse, "change"], [doc, "visibilitychange"], [host, "resize"], [host.navigator?.connection, "change"]]) {
|
|
229
|
-
if (target?.addEventListener) { target.addEventListener(type, sync); hold(() => target.removeEventListener(type, sync)); }
|
|
230
|
-
}
|
|
231
|
-
if (entry.dead) return null;
|
|
232
|
-
let modal = context().modal, dragging = cursorDragging(), queuedSurface = false;
|
|
233
|
-
// Panel commits can happen after navigation and contain no Chat lease. Reproject fixed owner targets
|
|
234
|
-
// once after stock DOM changes. Body-level effect roots/frames/rules do not schedule themselves.
|
|
235
|
-
const surfaceChanged = () => {
|
|
236
|
-
if (entry.dead || queuedSurface) return; queuedSurface = true;
|
|
237
|
-
Promise.resolve().then(() => { queuedSurface = false; sync(); });
|
|
238
|
-
};
|
|
239
|
-
const barriers = typeof host.MutationObserver === "function" ? new host.MutationObserver(records => {
|
|
240
|
-
if (entry.dead) return;
|
|
241
|
-
modalCache = null; // the document changed: a dialog may have opened or closed (read it again)
|
|
242
|
-
const value = context().modal, drag = cursorDragging(); if (value !== modal || drag !== dragging) { modal = value; dragging = drag; sync(); }
|
|
243
|
-
if (Array.isArray(records) && records.some(r => r.target?.closest?.("#app") || r.target === doc.getElementById?.("app"))) surfaceChanged();
|
|
244
|
-
}) : null;
|
|
245
|
-
hold(() => barriers?.disconnect());
|
|
246
|
-
if (entry.dead) return null;
|
|
247
|
-
barriers?.observe(doc.documentElement, { subtree: true, childList: true, attributes: true, attributeFilter: ["class", "open", "hidden", "role"] });
|
|
248
|
-
entry.bindStore(store); sync();
|
|
249
|
-
return getAppEffects(host);
|
|
250
|
-
} catch { entry.dispose(); return null; }
|
|
251
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/** #1629: static Chat fallback. It requires no preview origin, device consent, Worker or personal identity. */
|
|
2
|
-
import { useLayoutEffect } from "/assets/app-html.js";
|
|
3
|
-
import { appStore } from "/assets/app-store.js";
|
|
4
|
-
import { onPrefsChanged } from "/assets/app-prefs.js";
|
|
5
|
-
import { themesShown, themesStore } from "/assets/app-themes.js";
|
|
6
|
-
import { ownerCssLifecycle } from "/assets/owner-css.js";
|
|
7
|
-
import { effectPlaybackIdentity } from "/assets/effect-chat-runtime.js";
|
|
8
|
-
import { effectBootstrapReady } from "/assets/effect-frame.js";
|
|
9
|
-
import { motionBlocked, onMotionChange } from "/assets/fx-motion.js";
|
|
10
|
-
import { createChatPosters } from "/assets/effect-posters.js";
|
|
11
|
-
|
|
12
|
-
export function ChatEffectPosters({ name, lease, element }) {
|
|
13
|
-
useLayoutEffect(() => {
|
|
14
|
-
let live = true, api = null;
|
|
15
|
-
const releases = [], host = window;
|
|
16
|
-
const current = () => live && lease.current();
|
|
17
|
-
const cleanup = () => { if (!live) return; live = false; try { api?.dispose?.(); } catch { /* optional */ } for (const off of releases) { try { off?.(); } catch { /* release all */ } } };
|
|
18
|
-
lease.hold(cleanup);
|
|
19
|
-
try {
|
|
20
|
-
const motion = host.matchMedia?.("(prefers-reduced-motion: reduce)") ?? { matches: true };
|
|
21
|
-
const observe = () => {
|
|
22
|
-
// This is a surface fallback, not a replacement for an explicit Pause, queued effect or failed live read.
|
|
23
|
-
const playback = effectPlaybackIdentity(host) && typeof host.Worker === "function" && typeof host.OffscreenCanvas === "function" &&
|
|
24
|
-
effectBootstrapReady(host, host.location?.origin, host.document.body.dataset.effectBoot) && !motionBlocked(host);
|
|
25
|
-
return { shown: themesShown(), fallback: !playback, ownerCss: ownerCssLifecycle.get().state };
|
|
26
|
-
};
|
|
27
|
-
api = createChatPosters({ window: host, name, element: element.current, current, observe });
|
|
28
|
-
if (!api.ok) return cleanup;
|
|
29
|
-
const sync = () => { if (current()) api.sync(); };
|
|
30
|
-
let revision = appStore.get().themesRev;
|
|
31
|
-
releases.push(appStore.subscribe(s => {
|
|
32
|
-
if (!current()) return;
|
|
33
|
-
if (s.connection === "ended") { api.dispose(); return; }
|
|
34
|
-
if (s.themesRev !== revision) { revision = s.themesRev; api.changed(); } else sync();
|
|
35
|
-
}));
|
|
36
|
-
releases.push(ownerCssLifecycle.subscribe(sync)); releases.push(themesStore.subscribe(sync)); releases.push(onPrefsChanged(sync)); releases.push(onMotionChange(sync));
|
|
37
|
-
for (const target of [motion, host.navigator?.connection]) if (target?.addEventListener) { target.addEventListener("change", sync); releases.push(() => target.removeEventListener("change", sync)); }
|
|
38
|
-
sync(); return cleanup;
|
|
39
|
-
} catch { cleanup(); return cleanup; }
|
|
40
|
-
}, [name, lease]);
|
|
41
|
-
return null;
|
|
42
|
-
}
|