@songsid/agend 2.2.0 → 2.3.0-beta.2
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 +248 -2
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +2 -0
- package/dist/agent-endpoint.js +25 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-file-read.d.ts +35 -0
- package/dist/agent-file-read.js +144 -0
- package/dist/agent-file-read.js.map +1 -0
- package/dist/agent-whats-new.js +8 -0
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/atomic-write.js +9 -1
- package/dist/atomic-write.js.map +1 -1
- package/dist/auth-api.js +17 -0
- package/dist/auth-api.js.map +1 -1
- package/dist/backend/antigravity.js +3 -3
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.js +5 -1
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/launch-effort.js +1 -1
- package/dist/backend/launch-effort.js.map +1 -1
- package/dist/backend/muse.js +10 -2
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/types.d.ts +8 -0
- package/dist/backend/types.js +10 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/cache-analysis.d.ts +47 -1
- package/dist/cache-analysis.js +68 -8
- package/dist/cache-analysis.js.map +1 -1
- package/dist/cache-report-tool.d.ts +17 -0
- package/dist/cache-report-tool.js +40 -0
- package/dist/cache-report-tool.js.map +1 -0
- package/dist/cache-service.d.ts +15 -0
- package/dist/cache-service.js +26 -1
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +2 -0
- package/dist/channel/adapters/discord.js +17 -2
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +8 -1
- package/dist/channel/adapters/telegram.js +74 -4
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-tools.js +36 -0
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/types.d.ts +15 -0
- package/dist/cli.js +7 -3
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.js +22 -2
- package/dist/config-validator.js.map +1 -1
- package/dist/daemon.js +244 -20
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-context.d.ts +5 -0
- package/dist/fleet-manager.d.ts +92 -0
- package/dist/fleet-manager.js +410 -29
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +7 -0
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +367 -0
- package/dist/instance-avatar.js +3 -0
- package/dist/instance-avatar.js.map +1 -1
- package/dist/instance-config-impact.js +3 -0
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.js +9 -4
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/needs-you-hub.d.ts +4 -0
- package/dist/needs-you-hub.js +31 -6
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you.d.ts +1 -13
- package/dist/needs-you.js +3 -37
- package/dist/needs-you.js.map +1 -1
- package/dist/outbound-handlers.d.ts +7 -0
- package/dist/outbound-handlers.js +65 -10
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +74 -0
- package/dist/outbound-schemas.js +56 -0
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-web-gateway.js +14 -0
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/repo-worktree-guard.d.ts +36 -0
- package/dist/repo-worktree-guard.js +143 -0
- package/dist/repo-worktree-guard.js.map +1 -0
- package/dist/scheduler/scheduler.d.ts +70 -1
- package/dist/scheduler/scheduler.js +256 -17
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/service-installer.d.ts +2 -1
- package/dist/service-installer.js +18 -3
- package/dist/service-installer.js.map +1 -1
- package/dist/settings-api.js +74 -1
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +8 -0
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-effect.js +16 -2
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.js +5 -0
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/tool-permissions.d.ts +5 -0
- package/dist/tool-permissions.js +61 -2
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.d.ts +10 -6
- package/dist/topic-commands.js +21 -17
- package/dist/topic-commands.js.map +1 -1
- package/dist/topic-link.d.ts +128 -0
- package/dist/topic-link.js +269 -0
- package/dist/topic-link.js.map +1 -0
- package/dist/types.d.ts +13 -0
- package/dist/ui/app-effects.js +187 -0
- package/dist/ui/chat-effect-posters.js +42 -0
- package/dist/ui/chat-effects.js +72 -0
- package/dist/ui/chat-live-replies.js +58 -0
- package/dist/ui/chat-render.js +4 -4
- package/dist/ui/chat-store.js +9 -3
- package/dist/ui/chat-strings.js +15 -0
- package/dist/ui/chat-thread.js +47 -21
- package/dist/ui/chat-tour.js +1 -1
- package/dist/ui/effect-trial-controller.js +119 -0
- package/dist/ui/effect-trial-offer.js +31 -0
- package/dist/ui/effect-trial-panel.js +37 -0
- package/dist/ui/fleet-cache.js +23 -1
- package/dist/ui/image-lightbox.js +1 -1
- package/dist/ui/panel-chat.js +85 -17
- package/dist/ui/panel-details.js +18 -5
- package/dist/ui/panel-fleet.js +3 -3
- package/dist/ui/panel-log.js +6 -6
- package/dist/ui/panel-needs.js +3 -3
- package/dist/ui/panel-settings.js +8 -5
- package/dist/ui/preview-panel.js +25 -9
- package/dist/ui/settings-appearance.js +325 -0
- package/dist/ui/settings-effects.js +201 -0
- package/dist/ui/settings-mods.js +257 -0
- package/dist/ui/settings-owner-effects.js +80 -0
- package/dist/ui/settings-strings.js +245 -0
- package/dist/ui/shared/agend-auth.js +27 -3
- package/dist/ui/shared/agent-widget.js +248 -0
- package/dist/ui/shared/app-i18n.js +2 -0
- package/dist/ui/shared/app-prefs.js +30 -10
- package/dist/ui/shared/app-route.js +23 -1
- package/dist/ui/shared/app-session.js +1 -1
- package/dist/ui/shared/app-shell.js +29 -16
- package/dist/ui/shared/app-store.js +2 -0
- package/dist/ui/shared/app-stream.js +12 -7
- package/dist/ui/shared/app-themes.js +188 -0
- package/dist/ui/shared/app.css +225 -3
- package/dist/ui/shared/app.js +6 -0
- package/dist/ui/shared/card-strings.js +28 -0
- package/dist/ui/shared/effect-app-runtime.js +248 -0
- package/dist/ui/shared/effect-baseline.js +64 -0
- package/dist/ui/shared/effect-chat-runtime.js +154 -0
- package/dist/ui/shared/effect-cursor.js +125 -0
- package/dist/ui/shared/effect-frame.js +127 -0
- package/dist/ui/shared/effect-geometry.js +122 -0
- package/dist/ui/shared/effect-host-style.js +10 -0
- package/dist/ui/shared/effect-owner-regions.js +74 -0
- package/dist/ui/shared/effect-owner-source.js +115 -0
- package/dist/ui/shared/effect-policy.js +137 -0
- package/dist/ui/shared/effect-poster-reader.js +98 -0
- package/dist/ui/shared/effect-posters.js +117 -0
- package/dist/ui/shared/effect-profiler.js +162 -0
- package/dist/ui/shared/effect-profiles.js +65 -0
- package/dist/ui/shared/effect-registry.js +496 -0
- package/dist/ui/shared/effect-runtime-loader.js +234 -0
- package/dist/ui/shared/effect-safety.js +153 -0
- package/dist/ui/shared/effect-stock-snapshot.js +34 -0
- package/dist/ui/shared/effect-stock-trust.js +165 -0
- package/dist/ui/shared/effect-trial-source.js +103 -0
- package/dist/ui/shared/effect-trial-stage.js +147 -0
- package/dist/ui/shared/header-tools.js +1 -1
- package/dist/ui/shared/identity-card.js +202 -0
- package/dist/ui/shared/identity-color.js +261 -0
- package/dist/ui/shared/instance-nav.js +37 -19
- package/dist/ui/shared/owner-css.js +221 -0
- package/dist/ui/shared/owner-effect-prefs.js +117 -0
- package/dist/ui/shared/panel-view.js +81 -8
- package/dist/ui/shared/signin.js +2 -0
- package/dist/ui/shared/ui-dialog.js +1 -1
- package/dist/ui/shared/ui-icons.js +2 -0
- package/dist/ui/shared/ui-menu.js +1 -1
- package/dist/ui/shared/ui-toast.js +1 -1
- package/dist/ui/shared/usage-dialog.js +14 -2
- package/dist/ui/shared/view-strings.js +36 -2
- package/dist/ui/signin.html +1 -0
- package/dist/usage/providers.d.ts +3 -0
- package/dist/usage/providers.js +4 -3
- package/dist/usage/providers.js.map +1 -1
- package/dist/view-api.d.ts +29 -0
- package/dist/view-api.js +188 -8
- package/dist/view-api.js.map +1 -1
- package/dist/web-api.d.ts +42 -0
- package/dist/web-api.js +898 -36
- package/dist/web-api.js.map +1 -1
- package/dist/web-appearance-limits.d.ts +82 -0
- package/dist/web-appearance-limits.js +83 -0
- package/dist/web-appearance-limits.js.map +1 -0
- package/dist/web-appearance-policy.d.ts +66 -0
- package/dist/web-appearance-policy.js +94 -0
- package/dist/web-appearance-policy.js.map +1 -0
- package/dist/web-appearance-tools.d.ts +50 -0
- package/dist/web-appearance-tools.js +105 -0
- package/dist/web-appearance-tools.js.map +1 -0
- package/dist/web-appearance-view.d.ts +99 -0
- package/dist/web-appearance-view.js +163 -0
- package/dist/web-appearance-view.js.map +1 -0
- package/dist/web-appearance.d.ts +79 -0
- package/dist/web-appearance.js +298 -0
- package/dist/web-appearance.js.map +1 -0
- package/dist/web-asset-parts.d.ts +93 -0
- package/dist/web-asset-parts.js +133 -0
- package/dist/web-asset-parts.js.map +1 -0
- package/dist/web-auth.js +17 -1
- package/dist/web-auth.js.map +1 -1
- package/dist/web-card.d.ts +96 -0
- package/dist/web-card.js +232 -0
- package/dist/web-card.js.map +1 -0
- package/dist/web-chat-history.d.ts +13 -0
- package/dist/web-chat-history.js +23 -2
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-effect-bundle.d.ts +28 -0
- package/dist/web-effect-bundle.js +126 -0
- package/dist/web-effect-bundle.js.map +1 -0
- package/dist/web-effect-canonical.d.ts +8 -0
- package/dist/web-effect-canonical.js +27 -0
- package/dist/web-effect-canonical.js.map +1 -0
- package/dist/web-effect-library.d.ts +114 -0
- package/dist/web-effect-library.js +530 -0
- package/dist/web-effect-library.js.map +1 -0
- package/dist/web-effect-poster.d.ts +8 -0
- package/dist/web-effect-poster.js +52 -0
- package/dist/web-effect-poster.js.map +1 -0
- package/dist/web-effect-profiles.d.ts +118 -0
- package/dist/web-effect-profiles.js +180 -0
- package/dist/web-effect-profiles.js.map +1 -0
- package/dist/web-effect-service.d.ts +86 -0
- package/dist/web-effect-service.js +314 -0
- package/dist/web-effect-service.js.map +1 -0
- package/dist/web-effect-tools.d.ts +47 -0
- package/dist/web-effect-tools.js +129 -0
- package/dist/web-effect-tools.js.map +1 -0
- package/dist/web-effect-trials.d.ts +86 -0
- package/dist/web-effect-trials.js +204 -0
- package/dist/web-effect-trials.js.map +1 -0
- package/dist/web-effect-upload.d.ts +27 -0
- package/dist/web-effect-upload.js +185 -0
- package/dist/web-effect-upload.js.map +1 -0
- package/dist/web-effect-worker.d.ts +8 -0
- package/dist/web-effect-worker.js +170 -0
- package/dist/web-effect-worker.js.map +1 -0
- package/dist/web-effect.d.ts +103 -0
- package/dist/web-effect.js +153 -0
- package/dist/web-effect.js.map +1 -0
- package/dist/web-identity-color.d.ts +87 -0
- package/dist/web-identity-color.js +209 -0
- package/dist/web-identity-color.js.map +1 -0
- package/dist/web-identity-palette.d.ts +113 -0
- package/dist/web-identity-palette.js +84 -0
- package/dist/web-identity-palette.js.map +1 -0
- package/dist/web-image-meta.d.ts +25 -0
- package/dist/web-image-meta.js +200 -0
- package/dist/web-image-meta.js.map +1 -0
- package/dist/web-mod-agent.d.ts +50 -0
- package/dist/web-mod-agent.js +205 -0
- package/dist/web-mod-agent.js.map +1 -0
- package/dist/web-mod-bundle.d.ts +149 -0
- package/dist/web-mod-bundle.js +470 -0
- package/dist/web-mod-bundle.js.map +1 -0
- package/dist/web-mod-export.d.ts +59 -0
- package/dist/web-mod-export.js +79 -0
- package/dist/web-mod-export.js.map +1 -0
- package/dist/web-mod-store.d.ts +283 -0
- package/dist/web-mod-store.js +625 -0
- package/dist/web-mod-store.js.map +1 -0
- package/dist/web-org.d.ts +3 -3
- package/dist/web-org.js +11 -17
- package/dist/web-org.js.map +1 -1
- package/dist/web-owner-css-store.d.ts +180 -0
- package/dist/web-owner-css-store.js +384 -0
- package/dist/web-owner-css-store.js.map +1 -0
- package/dist/web-owner-css.d.ts +58 -0
- package/dist/web-owner-css.js +552 -0
- package/dist/web-owner-css.js.map +1 -0
- package/dist/web-prefs.d.ts +48 -0
- package/dist/web-prefs.js +209 -33
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-preview.d.ts +9 -1
- package/dist/web-preview.js +24 -7
- package/dist/web-preview.js.map +1 -1
- package/dist/web-settings-patch.d.ts +18 -0
- package/dist/web-settings-patch.js +51 -0
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-shell-routes.d.ts +1 -1
- package/dist/web-shell-routes.js +1 -1
- package/dist/web-shell-routes.js.map +1 -1
- package/dist/web-theme-store.d.ts +218 -0
- package/dist/web-theme-store.js +516 -0
- package/dist/web-theme-store.js.map +1 -0
- package/dist/web-theme.d.ts +121 -0
- package/dist/web-theme.js +407 -0
- package/dist/web-theme.js.map +1 -0
- package/dist/web-widget.d.ts +72 -0
- package/dist/web-widget.js +245 -0
- package/dist/web-widget.js.map +1 -0
- package/package.json +1 -1
- package/templates/systemd.service.ejs +8 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-effect-worker.js","sourceRoot":"","sources":["../src/web-effect-worker.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAAC;AAC5C,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAEjD,sGAAsG;AACtG,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;CAwB5C,CAAC;AAEF,2GAA2G;AAC3G,MAAM,UAAU,kBAAkB;IAChC,OAAO;;IAEL,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAgDjB,CAAC;AACP,CAAC;AAED,SAAS,OAAO,CAAC,KAAc;IAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACpH,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,qBAAqB,CAAC,MAAc,EAAE,OAA0B;IAC9E,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAA;;IAEvB,mBAAmB;aACV,OAAO,CAAC,MAAM,CAAC,aAAa,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,SAAS,gBAAgB,YAAY,iBAAiB;eACrG,OAAO,CAAC,kBAAkB,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA0EtC,CAAC;IACL,OAAO,oOAAoO,MAAM,yBAAyB,CAAC;AAC7Q,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/** CW1 effect manifests are metadata, never placement authority. Widgets are host-rendered elsewhere. */
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export declare const WEB_EFFECT_ID: RegExp;
|
|
4
|
+
export declare const WEB_EFFECT_REGIONS: readonly ["chat", "sidebar", "header", "page", "box"];
|
|
5
|
+
export declare const WEB_EFFECT_WANTS: readonly ["pointer", "state", "reply", "mention", "theme"];
|
|
6
|
+
declare const manifest: z.ZodObject<{
|
|
7
|
+
v: z.ZodLiteral<1>;
|
|
8
|
+
kind: z.ZodDefault<z.ZodLiteral<"effect">>;
|
|
9
|
+
runtime: z.ZodLiteral<"canvas-worker-v1">;
|
|
10
|
+
worker: z.ZodLiteral<"worker.js">;
|
|
11
|
+
name: z.ZodString;
|
|
12
|
+
title: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
13
|
+
description: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
14
|
+
poster: z.ZodOptional<z.ZodLiteral<"poster.png">>;
|
|
15
|
+
regions: z.ZodArray<z.ZodEnum<{
|
|
16
|
+
chat: "chat";
|
|
17
|
+
sidebar: "sidebar";
|
|
18
|
+
header: "header";
|
|
19
|
+
page: "page";
|
|
20
|
+
box: "box";
|
|
21
|
+
}>>;
|
|
22
|
+
layer: z.ZodEnum<{
|
|
23
|
+
behind: "behind";
|
|
24
|
+
front: "front";
|
|
25
|
+
}>;
|
|
26
|
+
box: z.ZodOptional<z.ZodObject<{
|
|
27
|
+
anchor: z.ZodEnum<{
|
|
28
|
+
"top-left": "top-left";
|
|
29
|
+
"top-right": "top-right";
|
|
30
|
+
"bottom-left": "bottom-left";
|
|
31
|
+
"bottom-right": "bottom-right";
|
|
32
|
+
center: "center";
|
|
33
|
+
}>;
|
|
34
|
+
width: z.ZodNumber;
|
|
35
|
+
height: z.ZodNumber;
|
|
36
|
+
offset: z.ZodNumber;
|
|
37
|
+
}, z.core.$strict>>;
|
|
38
|
+
cursor: z.ZodOptional<z.ZodObject<{
|
|
39
|
+
hotspot: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
40
|
+
}, z.core.$strict>>;
|
|
41
|
+
wants: z.ZodArray<z.ZodEnum<{
|
|
42
|
+
mention: "mention";
|
|
43
|
+
state: "state";
|
|
44
|
+
theme: "theme";
|
|
45
|
+
pointer: "pointer";
|
|
46
|
+
reply: "reply";
|
|
47
|
+
}>>;
|
|
48
|
+
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
49
|
+
type: z.ZodLiteral<"number">;
|
|
50
|
+
min: z.ZodNumber;
|
|
51
|
+
max: z.ZodNumber;
|
|
52
|
+
step: z.ZodOptional<z.ZodNumber>;
|
|
53
|
+
default: z.ZodNumber;
|
|
54
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
55
|
+
type: z.ZodLiteral<"int">;
|
|
56
|
+
min: z.ZodNumber;
|
|
57
|
+
max: z.ZodNumber;
|
|
58
|
+
default: z.ZodNumber;
|
|
59
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
60
|
+
type: z.ZodLiteral<"bool">;
|
|
61
|
+
default: z.ZodBoolean;
|
|
62
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
63
|
+
type: z.ZodLiteral<"enum">;
|
|
64
|
+
values: z.ZodArray<z.ZodString>;
|
|
65
|
+
default: z.ZodString;
|
|
66
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
67
|
+
type: z.ZodLiteral<"color">;
|
|
68
|
+
default: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
69
|
+
}, z.core.$strict>], "type">>>;
|
|
70
|
+
}, z.core.$strict>;
|
|
71
|
+
export type WebEffectManifest = z.infer<typeof manifest>;
|
|
72
|
+
export type EffectParamValue = string | number | boolean;
|
|
73
|
+
export declare function parseWebEffectManifest(value: unknown): {
|
|
74
|
+
ok: true;
|
|
75
|
+
manifest: WebEffectManifest;
|
|
76
|
+
} | {
|
|
77
|
+
ok: false;
|
|
78
|
+
error: "invalid_manifest";
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* #2017: whether an effect can be placed in a chat — its manifest's regions include `chat` (else it is saved but never
|
|
82
|
+
* plays there). Only a NEW chat placement is checked (agent tool, person's route, a mod's theme.effects); an older one
|
|
83
|
+
* stays as it is (filtered at run time) and can be removed. A non-chat effect stays a valid upload and personal choice.
|
|
84
|
+
*/
|
|
85
|
+
export declare function chatCompatible(manifest: {
|
|
86
|
+
regions?: readonly string[];
|
|
87
|
+
}): boolean;
|
|
88
|
+
/** #2017: the same test on an effect's files (its effect.json), for a mod export: an unreadable manifest is not chat. */
|
|
89
|
+
export declare function filesPlayInChat(files: ReadonlyMap<string, Uint8Array>): boolean;
|
|
90
|
+
export declare const EFFECT_REGION: Readonly<{
|
|
91
|
+
error: "effect_region";
|
|
92
|
+
message: string;
|
|
93
|
+
}>;
|
|
94
|
+
/** Defaults and overrides are resolved together before a placement or mod commit can write. */
|
|
95
|
+
export declare function resolveEffectParams(input: WebEffectManifest, overrides?: unknown): {
|
|
96
|
+
ok: true;
|
|
97
|
+
values: Record<string, EffectParamValue>;
|
|
98
|
+
overrides: Record<string, EffectParamValue>;
|
|
99
|
+
} | {
|
|
100
|
+
ok: false;
|
|
101
|
+
error: "invalid_params";
|
|
102
|
+
};
|
|
103
|
+
export {};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/** CW1 effect manifests are metadata, never placement authority. Widgets are host-rendered elsewhere. */
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { canonicalText } from "./web-theme.js";
|
|
4
|
+
export const WEB_EFFECT_ID = /^[0-9a-f]{32}$/;
|
|
5
|
+
export const WEB_EFFECT_REGIONS = ["chat", "sidebar", "header", "page", "box"];
|
|
6
|
+
export const WEB_EFFECT_WANTS = ["pointer", "state", "reply", "mention", "theme"];
|
|
7
|
+
const slug = z.string().regex(/^[a-z0-9][a-z0-9-]{0,31}$/);
|
|
8
|
+
function text(max, min) {
|
|
9
|
+
return z.string().max(max * 10).transform((value, ctx) => {
|
|
10
|
+
const result = min === 0 && value === "" ? "" : canonicalText(value, Math.max(1, min), max);
|
|
11
|
+
if (result === null) {
|
|
12
|
+
ctx.addIssue({ code: "custom", message: "Invalid display text" });
|
|
13
|
+
return z.NEVER;
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
const finite = z.number().finite().min(-1e9).max(1e9);
|
|
19
|
+
const numeric = z.strictObject({ type: z.literal("number"), min: finite, max: finite, step: z.number().finite().positive().max(2e9).optional(), default: finite });
|
|
20
|
+
const integer = z.strictObject({ type: z.literal("int"), min: finite.int(), max: finite.int(), default: finite.int() });
|
|
21
|
+
const param = z.discriminatedUnion("type", [
|
|
22
|
+
numeric, integer, z.strictObject({ type: z.literal("bool"), default: z.boolean() }),
|
|
23
|
+
z.strictObject({ type: z.literal("enum"), values: z.array(slug).min(1).max(16), default: slug }),
|
|
24
|
+
z.strictObject({ type: z.literal("color"), default: z.string().regex(/^#[0-9a-fA-F]{6}$/).transform(value => value.toLowerCase()) }),
|
|
25
|
+
]).refine(d => {
|
|
26
|
+
if (d.type === "enum")
|
|
27
|
+
return new Set(d.values).size === d.values.length && d.values.includes(d.default);
|
|
28
|
+
if (d.type === "number" || d.type === "int")
|
|
29
|
+
return d.min <= d.max && d.default >= d.min && d.default <= d.max && (d.type !== "number" || d.step === undefined || aligned(d.default, d.min, d.step));
|
|
30
|
+
return true;
|
|
31
|
+
});
|
|
32
|
+
function aligned(value, min, step) {
|
|
33
|
+
const distance = (value - min) / step;
|
|
34
|
+
return Number.isFinite(distance) && Math.abs(distance - Math.round(distance)) <= 1e-8;
|
|
35
|
+
}
|
|
36
|
+
const manifest = z.strictObject({
|
|
37
|
+
v: z.literal(1), kind: z.literal("effect").default("effect"), runtime: z.literal("canvas-worker-v1"), worker: z.literal("worker.js"),
|
|
38
|
+
name: slug, title: text(40, 1), description: text(200, 0).optional(), poster: z.literal("poster.png").optional(),
|
|
39
|
+
regions: z.array(z.enum(WEB_EFFECT_REGIONS)).min(1).max(5).refine(v => new Set(v).size === v.length),
|
|
40
|
+
layer: z.enum(["behind", "front"]),
|
|
41
|
+
box: z.strictObject({ anchor: z.enum(["top-left", "top-right", "bottom-left", "bottom-right", "center"]), width: z.number().int().min(32).max(480), height: z.number().int().min(32).max(480), offset: z.number().int().min(0).max(64) }).optional(),
|
|
42
|
+
cursor: z.strictObject({ hotspot: z.tuple([z.number().int().min(0).max(63), z.number().int().min(0).max(63)]) }).optional(),
|
|
43
|
+
wants: z.array(z.enum(WEB_EFFECT_WANTS)).max(5).refine(v => new Set(v).size === v.length),
|
|
44
|
+
params: z.record(z.string().regex(/^[a-z][a-z0-9_]{0,31}$/), param).refine(v => Object.keys(v).length <= 16).optional(),
|
|
45
|
+
});
|
|
46
|
+
/** Bounded data only. Do not invoke getters or interpret unreadable values as an absent field. */
|
|
47
|
+
function plainData(value) {
|
|
48
|
+
const pending = [{ value, depth: 0 }];
|
|
49
|
+
let nodes = 0;
|
|
50
|
+
while (pending.length) {
|
|
51
|
+
const { value, depth } = pending.pop();
|
|
52
|
+
if (++nodes > 1024 || depth > 8)
|
|
53
|
+
return false;
|
|
54
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
55
|
+
continue;
|
|
56
|
+
if (typeof value === "number") {
|
|
57
|
+
if (!Number.isFinite(value))
|
|
58
|
+
return false;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (typeof value !== "object")
|
|
62
|
+
return false;
|
|
63
|
+
const array = Array.isArray(value), proto = Object.getPrototypeOf(value);
|
|
64
|
+
if (array ? proto !== Array.prototype : proto !== Object.prototype && proto !== null)
|
|
65
|
+
return false;
|
|
66
|
+
const keys = Reflect.ownKeys(value);
|
|
67
|
+
if (keys.length > 33 || array && value.length > 32)
|
|
68
|
+
return false;
|
|
69
|
+
for (const key of keys) {
|
|
70
|
+
if (typeof key !== "string")
|
|
71
|
+
return false;
|
|
72
|
+
if (array && key === "length")
|
|
73
|
+
continue;
|
|
74
|
+
const field = Object.getOwnPropertyDescriptor(value, key);
|
|
75
|
+
if (!("value" in field))
|
|
76
|
+
return false;
|
|
77
|
+
pending.push({ value: field.value, depth: depth + 1 });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
export function parseWebEffectManifest(value) {
|
|
83
|
+
try {
|
|
84
|
+
if (!plainData(value))
|
|
85
|
+
return { ok: false, error: "invalid_manifest" };
|
|
86
|
+
const result = manifest.safeParse(value);
|
|
87
|
+
return result.success ? { ok: true, manifest: result.data } : { ok: false, error: "invalid_manifest" };
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return { ok: false, error: "invalid_manifest" };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* #2017: whether an effect can be placed in a chat — its manifest's regions include `chat` (else it is saved but never
|
|
95
|
+
* plays there). Only a NEW chat placement is checked (agent tool, person's route, a mod's theme.effects); an older one
|
|
96
|
+
* stays as it is (filtered at run time) and can be removed. A non-chat effect stays a valid upload and personal choice.
|
|
97
|
+
*/
|
|
98
|
+
export function chatCompatible(manifest) {
|
|
99
|
+
return Array.isArray(manifest.regions) && manifest.regions.includes("chat");
|
|
100
|
+
}
|
|
101
|
+
/** #2017: the same test on an effect's files (its effect.json), for a mod export: an unreadable manifest is not chat. */
|
|
102
|
+
export function filesPlayInChat(files) {
|
|
103
|
+
const raw = files.get("effect.json");
|
|
104
|
+
if (!raw)
|
|
105
|
+
return false;
|
|
106
|
+
try {
|
|
107
|
+
return chatCompatible(JSON.parse(Buffer.from(raw).toString("utf8")));
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
export const EFFECT_REGION = Object.freeze({ error: "effect_region", message: "This effect's regions do not include chat." });
|
|
114
|
+
/** Defaults and overrides are resolved together before a placement or mod commit can write. */
|
|
115
|
+
export function resolveEffectParams(input, overrides = {}) {
|
|
116
|
+
try {
|
|
117
|
+
if (!plainData(overrides) || !overrides || Array.isArray(overrides) || typeof overrides !== "object")
|
|
118
|
+
return { ok: false, error: "invalid_params" };
|
|
119
|
+
const schema = input.params ?? {};
|
|
120
|
+
for (const key of Object.keys(overrides))
|
|
121
|
+
if (!Object.hasOwn(schema, key))
|
|
122
|
+
return { ok: false, error: "invalid_params" };
|
|
123
|
+
const values = Object.create(null), changed = Object.create(null);
|
|
124
|
+
for (const [name, d] of Object.entries(schema)) {
|
|
125
|
+
let value = Object.hasOwn(overrides, name) ? overrides[name] : d.default;
|
|
126
|
+
if (d.type === "number" || d.type === "int") {
|
|
127
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < d.min || value > d.max || d.type === "int" && !Number.isSafeInteger(value) || d.type === "number" && d.step !== undefined && !aligned(value, d.min, d.step))
|
|
128
|
+
return { ok: false, error: "invalid_params" };
|
|
129
|
+
}
|
|
130
|
+
else if (d.type === "bool") {
|
|
131
|
+
if (typeof value !== "boolean")
|
|
132
|
+
return { ok: false, error: "invalid_params" };
|
|
133
|
+
}
|
|
134
|
+
else if (d.type === "enum") {
|
|
135
|
+
if (typeof value !== "string" || !d.values.includes(value))
|
|
136
|
+
return { ok: false, error: "invalid_params" };
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
if (typeof value !== "string" || !/^#[0-9a-fA-F]{6}$/.test(value))
|
|
140
|
+
return { ok: false, error: "invalid_params" };
|
|
141
|
+
value = value.toLowerCase();
|
|
142
|
+
}
|
|
143
|
+
values[name] = value;
|
|
144
|
+
if (value !== d.default)
|
|
145
|
+
changed[name] = value;
|
|
146
|
+
}
|
|
147
|
+
return { ok: true, values, overrides: changed };
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return { ok: false, error: "invalid_params" };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=web-effect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-effect.js","sourceRoot":"","sources":["../src/web-effect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
import { type ThemeMode } from "./web-theme.js";
|
|
3
|
+
import { type IdentityColor, type Placement } from "./web-identity-palette.js";
|
|
4
|
+
export { AUTO_PALETTE, autoIdentityColor, canonicalIdentityColor, canonicalPlacements, DEFAULT_PLACEMENTS, IDENTITY_PALETTE, identityColorValue, PLACEMENTS, type AutoId, type IdentityColor, type Placement, type PresetId } from "./web-identity-palette.js";
|
|
5
|
+
/** The sidebar's own background (src/ui/shared/tokens.css --bg-sidebar), where names are drawn as well as the page's. */
|
|
6
|
+
export declare const SIDEBAR_BG: Record<ThemeMode, string>;
|
|
7
|
+
export type IdentityColorSource = "person" | "agent" | "role" | "auto";
|
|
8
|
+
export type PlacementSource = "person" | "agent" | "host";
|
|
9
|
+
/**
|
|
10
|
+
* The shade of `hex` that name text uses on a page in `mode`: the colour itself if it reads at 4.5:1 against the
|
|
11
|
+
* page's and the sidebar's backgrounds, else the nearest step toward black (light page) or white (dark page) that does.
|
|
12
|
+
*/
|
|
13
|
+
export declare function readableShade(hex: string, mode: ThemeMode): string;
|
|
14
|
+
/** The tiers one instance has, as the status frame carries them (`auto` always). */
|
|
15
|
+
export interface IdentityColorTiers {
|
|
16
|
+
person?: IdentityColor;
|
|
17
|
+
agent?: string;
|
|
18
|
+
role?: string;
|
|
19
|
+
auto: IdentityColor;
|
|
20
|
+
}
|
|
21
|
+
/** The placement tiers one instance has (the host's default is the viewer's prefs, not the instance's). */
|
|
22
|
+
export interface PlacementTiers {
|
|
23
|
+
person?: Placement[];
|
|
24
|
+
agent?: Placement[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The colour in force and where it comes from. `showThemes`: whether the viewer shows agents' themes (fx.show, not
|
|
28
|
+
* safe mode) — when not, the agent's tier is skipped, as the rest of the agent's theme is.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveIdentityColor(t: IdentityColorTiers, opts: {
|
|
31
|
+
showThemes: boolean;
|
|
32
|
+
}): {
|
|
33
|
+
color: IdentityColor;
|
|
34
|
+
source: IdentityColorSource;
|
|
35
|
+
};
|
|
36
|
+
/** Where the colour shows: a person's choice, else the agent's (themes shown), else the host's default, else ring + bar. */
|
|
37
|
+
export declare function resolvePlacements(t: PlacementTiers, opts: {
|
|
38
|
+
showThemes: boolean;
|
|
39
|
+
hostDefault?: unknown;
|
|
40
|
+
}): {
|
|
41
|
+
show: Placement[];
|
|
42
|
+
source: PlacementSource;
|
|
43
|
+
};
|
|
44
|
+
/** A person's choice for one instance: a colour, the places it shows, or both (null: not chosen — the next tier). */
|
|
45
|
+
export interface PersonIdentity {
|
|
46
|
+
color: IdentityColor | null;
|
|
47
|
+
show: Placement[] | null;
|
|
48
|
+
}
|
|
49
|
+
export type ColorWrite = {
|
|
50
|
+
ok: true;
|
|
51
|
+
} | {
|
|
52
|
+
ok: false;
|
|
53
|
+
status: 400 | 503;
|
|
54
|
+
error: string;
|
|
55
|
+
detail?: string;
|
|
56
|
+
};
|
|
57
|
+
/** The people's choices, one row per instance. */
|
|
58
|
+
export declare class IdentityColorStore {
|
|
59
|
+
private readonly openDb;
|
|
60
|
+
private readonly now;
|
|
61
|
+
constructor(openDb: () => Database.Database, now?: () => number);
|
|
62
|
+
get(name: string): PersonIdentity;
|
|
63
|
+
/** Every choice, for a status read: only when profiles.db exists and has the table — a read creates nothing. */
|
|
64
|
+
static all(dataDir: string, openDb: () => Database.Database): Map<string, PersonIdentity>;
|
|
65
|
+
/**
|
|
66
|
+
* A person's choice, field by field: only the fields given change; `null` (or "" for the colour) clears one — the next
|
|
67
|
+
* tier shows again. Both checked before anything is written. A row with nothing left is removed.
|
|
68
|
+
*/
|
|
69
|
+
set(name: string, patch: {
|
|
70
|
+
color?: unknown;
|
|
71
|
+
show?: unknown;
|
|
72
|
+
}): ColorWrite;
|
|
73
|
+
/** The patch, checked: `undefined` for a field not given, `null` to clear it. Writes nothing. */
|
|
74
|
+
check(patch: {
|
|
75
|
+
color?: unknown;
|
|
76
|
+
show?: unknown;
|
|
77
|
+
}): {
|
|
78
|
+
ok: true;
|
|
79
|
+
color?: IdentityColor | null;
|
|
80
|
+
show?: Placement[] | null;
|
|
81
|
+
} | {
|
|
82
|
+
ok: false;
|
|
83
|
+
status: 400;
|
|
84
|
+
error: string;
|
|
85
|
+
detail: string;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #1958: an instance's identity colour — the cue people scan the sidebar by — and where it shows (its placements: the
|
|
3
|
+
* name, a bar at the row's left edge, the avatar's ring). docs/design/1958-identity-color.md has the decisions.
|
|
4
|
+
*
|
|
5
|
+
* The colour, in a fixed order:
|
|
6
|
+
* 1. person — a person's pick from the web dashboard (this module's store), shared host-wide like the profile and
|
|
7
|
+
* the identity card;
|
|
8
|
+
* 2. agent — the agent's own (#1629 theme.identity.color, else its theme accent), only where the viewer shows
|
|
9
|
+
* agents' themes;
|
|
10
|
+
* 3. role — the own bot's colour from its highest coloured Discord role (never a shared bot's);
|
|
11
|
+
* 4. auto — one of a few soft colours, chosen by a stable hash of the name (two instances may share one).
|
|
12
|
+
* The placements, likewise: a person's choice for this instance > the agent's (theme.identity.show, while themes are
|
|
13
|
+
* shown) > the host's default (web prefs `color.show`, else ring + bar). The host may turn colours off altogether
|
|
14
|
+
* (`color.off`): nothing is drawn, and every pick is kept for when they come back.
|
|
15
|
+
*
|
|
16
|
+
* A colour is kept and sent as `preset:<id>`, `auto:<id>` (both drawn with their light or dark value, readable on the
|
|
17
|
+
* page's background) or `#rrggbb` (a custom colour, drawn as it is; name text uses a readable shade of it).
|
|
18
|
+
* Its own table (instance_identity), never new columns on instance_profile or instance_card: "Clear card" leaves the
|
|
19
|
+
* colour alone, and an older AgEnD reading profiles.db sees what it knew.
|
|
20
|
+
*/
|
|
21
|
+
import { existsSync } from "node:fs";
|
|
22
|
+
import { join } from "node:path";
|
|
23
|
+
import { canonicalColor, contrastRatio, THEME_DEFAULTS } from "./web-theme.js";
|
|
24
|
+
import { canonicalIdentityColor, canonicalPlacements, DEFAULT_PLACEMENTS } from "./web-identity-palette.js";
|
|
25
|
+
export { AUTO_PALETTE, autoIdentityColor, canonicalIdentityColor, canonicalPlacements, DEFAULT_PLACEMENTS, IDENTITY_PALETTE, identityColorValue, PLACEMENTS } from "./web-identity-palette.js";
|
|
26
|
+
/** The sidebar's own background (src/ui/shared/tokens.css --bg-sidebar), where names are drawn as well as the page's. */
|
|
27
|
+
export const SIDEBAR_BG = { light: "#f9f9f9", dark: "#171717" };
|
|
28
|
+
/**
|
|
29
|
+
* The shade of `hex` that name text uses on a page in `mode`: the colour itself if it reads at 4.5:1 against the
|
|
30
|
+
* page's and the sidebar's backgrounds, else the nearest step toward black (light page) or white (dark page) that does.
|
|
31
|
+
*/
|
|
32
|
+
export function readableShade(hex, mode) {
|
|
33
|
+
const backgrounds = [THEME_DEFAULTS[mode].bg, SIDEBAR_BG[mode]];
|
|
34
|
+
const base = canonicalColor(hex);
|
|
35
|
+
if (!base)
|
|
36
|
+
return THEME_DEFAULTS[mode].text;
|
|
37
|
+
const toward = mode === "light" ? 0 : 255;
|
|
38
|
+
const channels = [1, 3, 5].map(i => parseInt(base.slice(i, i + 2), 16));
|
|
39
|
+
for (let step = 0; step <= 20; step++) {
|
|
40
|
+
const mix = channels.map(c => Math.round(c + (toward - c) * (step / 20)));
|
|
41
|
+
const shade = `#${mix.map(c => c.toString(16).padStart(2, "0")).join("")}`;
|
|
42
|
+
if (backgrounds.every(bg => contrastRatio(shade, bg) >= 4.5))
|
|
43
|
+
return shade;
|
|
44
|
+
}
|
|
45
|
+
return THEME_DEFAULTS[mode].text;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The colour in force and where it comes from. `showThemes`: whether the viewer shows agents' themes (fx.show, not
|
|
49
|
+
* safe mode) — when not, the agent's tier is skipped, as the rest of the agent's theme is.
|
|
50
|
+
*/
|
|
51
|
+
export function resolveIdentityColor(t, opts) {
|
|
52
|
+
if (t.person)
|
|
53
|
+
return { color: t.person, source: "person" };
|
|
54
|
+
const agent = opts.showThemes ? canonicalIdentityColor(t.agent) : null;
|
|
55
|
+
if (agent)
|
|
56
|
+
return { color: agent, source: "agent" };
|
|
57
|
+
const role = canonicalColor(t.role);
|
|
58
|
+
if (role)
|
|
59
|
+
return { color: role, source: "role" };
|
|
60
|
+
return { color: t.auto, source: "auto" };
|
|
61
|
+
}
|
|
62
|
+
/** Where the colour shows: a person's choice, else the agent's (themes shown), else the host's default, else ring + bar. */
|
|
63
|
+
export function resolvePlacements(t, opts) {
|
|
64
|
+
const person = canonicalPlacements(t.person);
|
|
65
|
+
if (person)
|
|
66
|
+
return { show: person, source: "person" };
|
|
67
|
+
const agent = opts.showThemes ? canonicalPlacements(t.agent) : null;
|
|
68
|
+
if (agent)
|
|
69
|
+
return { show: agent, source: "agent" };
|
|
70
|
+
return { show: canonicalPlacements(opts.hostDefault) ?? [...DEFAULT_PLACEMENTS], source: "host" };
|
|
71
|
+
}
|
|
72
|
+
/** The first cut's table (instance_color, colour only, on feat/2.3-web-mod before 2.3 ships). */
|
|
73
|
+
const LEGACY = "instance_color";
|
|
74
|
+
/** Done once per database, recorded in it: the first cut's picks were carried over (Prism #2003 P2-1). */
|
|
75
|
+
const MIGRATED = "instance_color_carried";
|
|
76
|
+
const hasTable = (db, name) => !!db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(name);
|
|
77
|
+
const migrated = (db) => hasTable(db, "instance_identity_meta") && !!db.prepare("SELECT 1 FROM instance_identity_meta WHERE key = ?").get(MIGRATED);
|
|
78
|
+
const ready = new WeakSet();
|
|
79
|
+
/**
|
|
80
|
+
* The table, made once per connection. The first cut's picks carry over once per database — recorded in
|
|
81
|
+
* instance_identity_meta, so a pick reset since never comes back on a later connection — and never over a newer choice;
|
|
82
|
+
* the old table is left as it is. Prism #2003 P2-2: a connection counts as ready only when this ran outside a
|
|
83
|
+
* transaction (a rollback would take the tables away, never the mark), and the route sets it up before its transaction.
|
|
84
|
+
*/
|
|
85
|
+
function table(db) {
|
|
86
|
+
if (!ready.has(db)) {
|
|
87
|
+
db.transaction(() => {
|
|
88
|
+
db.exec(`CREATE TABLE IF NOT EXISTS instance_identity (
|
|
89
|
+
instance_name TEXT PRIMARY KEY,
|
|
90
|
+
color TEXT,
|
|
91
|
+
show TEXT,
|
|
92
|
+
updated_at INTEGER
|
|
93
|
+
);
|
|
94
|
+
CREATE TABLE IF NOT EXISTS instance_identity_meta (key TEXT PRIMARY KEY, value TEXT);`);
|
|
95
|
+
if (!migrated(db)) {
|
|
96
|
+
if (hasTable(db, LEGACY))
|
|
97
|
+
db.exec(`INSERT OR IGNORE INTO instance_identity (instance_name, color, show, updated_at) SELECT instance_name, color, NULL, updated_at FROM ${LEGACY}`);
|
|
98
|
+
db.prepare("INSERT OR IGNORE INTO instance_identity_meta (key, value) VALUES (?, '1')").run(MIGRATED);
|
|
99
|
+
}
|
|
100
|
+
})();
|
|
101
|
+
if (!db.inTransaction)
|
|
102
|
+
ready.add(db);
|
|
103
|
+
}
|
|
104
|
+
return db;
|
|
105
|
+
}
|
|
106
|
+
const parseShow = (raw) => {
|
|
107
|
+
if (raw === null)
|
|
108
|
+
return null;
|
|
109
|
+
try {
|
|
110
|
+
return canonicalPlacements(JSON.parse(raw));
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
/** The people's choices, one row per instance. */
|
|
117
|
+
export class IdentityColorStore {
|
|
118
|
+
openDb;
|
|
119
|
+
now;
|
|
120
|
+
constructor(openDb, now = () => Date.now()) {
|
|
121
|
+
this.openDb = openDb;
|
|
122
|
+
this.now = now;
|
|
123
|
+
}
|
|
124
|
+
get(name) {
|
|
125
|
+
const row = table(this.openDb()).prepare("SELECT color, show FROM instance_identity WHERE instance_name = ?").get(name);
|
|
126
|
+
return { color: row?.color ? canonicalIdentityColor(row.color) : null, show: parseShow(row?.show ?? null) };
|
|
127
|
+
}
|
|
128
|
+
/** Every choice, for a status read: only when profiles.db exists and has the table — a read creates nothing. */
|
|
129
|
+
static all(dataDir, openDb) {
|
|
130
|
+
if (!existsSync(join(dataDir, "profiles.db")))
|
|
131
|
+
return new Map();
|
|
132
|
+
try {
|
|
133
|
+
const db = openDb();
|
|
134
|
+
const out = new Map();
|
|
135
|
+
if (hasTable(db, "instance_identity")) {
|
|
136
|
+
for (const r of db.prepare("SELECT instance_name, color, show FROM instance_identity").all()) {
|
|
137
|
+
// A value this version cannot read is no choice, not an error.
|
|
138
|
+
const p = { color: r.color ? canonicalIdentityColor(r.color) : null, show: parseShow(r.show) };
|
|
139
|
+
if (p.color || p.show)
|
|
140
|
+
out.set(r.instance_name, p);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (!migrated(db) && hasTable(db, LEGACY)) {
|
|
144
|
+
// Not carried over yet (nothing has written since): the first cut's picks read as they are, under a newer one.
|
|
145
|
+
for (const r of db.prepare(`SELECT instance_name, color FROM ${LEGACY}`).all()) {
|
|
146
|
+
const c = canonicalIdentityColor(r.color);
|
|
147
|
+
if (c && !out.has(r.instance_name))
|
|
148
|
+
out.set(r.instance_name, { color: c, show: null });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return new Map();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* A person's choice, field by field: only the fields given change; `null` (or "" for the colour) clears one — the next
|
|
159
|
+
* tier shows again. Both checked before anything is written. A row with nothing left is removed.
|
|
160
|
+
*/
|
|
161
|
+
set(name, patch) {
|
|
162
|
+
const next = this.check(patch);
|
|
163
|
+
if (!next.ok)
|
|
164
|
+
return next;
|
|
165
|
+
try {
|
|
166
|
+
const db = table(this.openDb());
|
|
167
|
+
const prev = this.get(name);
|
|
168
|
+
const color = next.color === undefined ? prev.color : next.color;
|
|
169
|
+
const show = next.show === undefined ? prev.show : next.show;
|
|
170
|
+
if (color === null && show === null)
|
|
171
|
+
db.prepare("DELETE FROM instance_identity WHERE instance_name = ?").run(name);
|
|
172
|
+
else
|
|
173
|
+
db.prepare(`INSERT INTO instance_identity (instance_name, color, show, updated_at) VALUES (@n, @c, @s, @t)
|
|
174
|
+
ON CONFLICT(instance_name) DO UPDATE SET color = excluded.color, show = excluded.show, updated_at = excluded.updated_at`)
|
|
175
|
+
.run({ n: name, c: color, s: show === null ? null : JSON.stringify(show), t: this.now() });
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
return { ok: false, status: 503, error: "color_write_failed", detail: err.message };
|
|
179
|
+
}
|
|
180
|
+
return { ok: true };
|
|
181
|
+
}
|
|
182
|
+
/** The patch, checked: `undefined` for a field not given, `null` to clear it. Writes nothing. */
|
|
183
|
+
check(patch) {
|
|
184
|
+
const out = { ok: true };
|
|
185
|
+
if (patch.color !== undefined) {
|
|
186
|
+
const v = patch.color;
|
|
187
|
+
if (v === null || (typeof v === "string" && !v.trim()))
|
|
188
|
+
out.color = null;
|
|
189
|
+
else {
|
|
190
|
+
const c = canonicalIdentityColor(v);
|
|
191
|
+
if (!c)
|
|
192
|
+
return { ok: false, status: 400, error: "color", detail: "a preset id or a hex colour #rrggbb" };
|
|
193
|
+
out.color = c;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (patch.show !== undefined) {
|
|
197
|
+
if (patch.show === null)
|
|
198
|
+
out.show = null;
|
|
199
|
+
else {
|
|
200
|
+
const s = canonicalPlacements(patch.show);
|
|
201
|
+
if (!s)
|
|
202
|
+
return { ok: false, status: 400, error: "color_show", detail: "a list of where the colour shows: name, bar, ring (each once; [] for nowhere)" };
|
|
203
|
+
out.show = s;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return out;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=web-identity-color.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-identity-color.js","sourceRoot":"","sources":["../src/web-identity-color.ts"],"names":[],"mappings":"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"}
|