dsh-web-icon-indicator 0.4.2 → 0.5.0
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/CHANGELOG.md +19 -0
- package/README.md +88 -14
- package/README.zh.md +67 -13
- package/lib/client.js +715 -98
- package/lib/index.js +399 -48
- package/lib/types/index.d.ts +73 -4
- package/package.json +3 -3
- package/test/loader-hooks.mjs +21 -0
- package/test/stubs/dsh-settings.mjs +15 -0
- package/test/stubs/schemastery.mjs +12 -0
- package/test/verify.js +2026 -0
- package/docs/safari-favicon-research.md +0 -114
package/lib/types/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* config:
|
|
11
11
|
* askingHoldMs: 3500
|
|
12
12
|
* doneHoldMs: 5000
|
|
13
|
+
* defaultColor: '#5B8DEF' # per-instance default icon color
|
|
13
14
|
* states:
|
|
14
15
|
* idle: { effect: static, colors: ['#1a1a1a'] }
|
|
15
16
|
* running: { effect: static, colors: ['#FACC15'] }
|
|
@@ -60,15 +61,50 @@ export interface DshWebIconIndicatorConfig {
|
|
|
60
61
|
* Defaults to `<package>/icons/`.
|
|
61
62
|
*/
|
|
62
63
|
iconsDir?: string;
|
|
63
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Status JSON endpoint the browser polls. Default `/dsh-web-icon-status.json`.
|
|
66
|
+
*
|
|
67
|
+
* **Registration-time:** set it in the composition entry only. The route
|
|
68
|
+
* table and the injected script are built when the plugin mounts, so this key
|
|
69
|
+
* is intentionally absent from the settings schema (`settings.yaml`) — a
|
|
70
|
+
* settings-document change could never be honored and would point the browser
|
|
71
|
+
* at a path the server does not serve.
|
|
72
|
+
*/
|
|
64
73
|
statusPath?: string;
|
|
65
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* URL prefix where `base.svg` is served. Default `/dsh-web-icon-indicator`.
|
|
76
|
+
*
|
|
77
|
+
* **Registration-time:** set it in the composition entry only — see
|
|
78
|
+
* {@link statusPath}.
|
|
79
|
+
*/
|
|
66
80
|
iconPathPrefix?: string;
|
|
67
81
|
/** Minimum visibility of the asking state in milliseconds. Default 3500. */
|
|
68
82
|
askingHoldMs?: number;
|
|
69
83
|
/** Time the done state stays before falling back to idle, in milliseconds. Default 5000. */
|
|
70
84
|
doneHoldMs?: number;
|
|
71
|
-
/**
|
|
85
|
+
/**
|
|
86
|
+
* Default icon color — the idle whale's primary color, as `#rgb` / `#rrggbb`.
|
|
87
|
+
* Absent keeps the idle state's own `colors[0]` (the behavior before this key
|
|
88
|
+
* existed). Give each DSH instance a different value to tell their browser
|
|
89
|
+
* tabs apart: it is per instance (profile / `settings.yaml`), not per tab.
|
|
90
|
+
*
|
|
91
|
+
* Folded into `states.idle.colors[0]` at resolve time, so an idle entry that
|
|
92
|
+
* only needs its default is untouched. This is the **only** idle knob the
|
|
93
|
+
* settings card offers: idle paints one color and takes no animation, so it
|
|
94
|
+
* gets no per-state row (no effect / colors / cycle). A value perceptually too
|
|
95
|
+
* close to another state's color raises an advisory warning (settings card,
|
|
96
|
+
* host log, and {@link DshWebIconIndicatorAggregate.warnings}) but is still
|
|
97
|
+
* applied; a malformed value is ignored and reported.
|
|
98
|
+
*/
|
|
99
|
+
defaultColor?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Per-state visual config. Each entry is shallow-merged over its default.
|
|
102
|
+
*
|
|
103
|
+
* `idle` is not editable from the settings card (its color is
|
|
104
|
+
* {@link defaultColor}); a `states.idle` entry arriving from the composition
|
|
105
|
+
* entry or a hand-written `settings.yaml` is still honored for backward
|
|
106
|
+
* compatibility — including an idle `effect` and a second color.
|
|
107
|
+
*/
|
|
72
108
|
states?: Partial<Record<DshWebIconStateName, DshWebIconStateConfig>>;
|
|
73
109
|
}
|
|
74
110
|
|
|
@@ -91,6 +127,39 @@ export interface DshWebIconIndicatorAggregate {
|
|
|
91
127
|
* reload). Added in 0.2.x; older browser bundles ignore it.
|
|
92
128
|
*/
|
|
93
129
|
states: Partial<Record<DshWebIconStateName, DshWebIconStateConfig>>;
|
|
130
|
+
/**
|
|
131
|
+
* Effective default icon color (normalized to lowercase 6-digit hex), or
|
|
132
|
+
* `null` when none is configured — the status payload always carries the key.
|
|
133
|
+
* Added with the `defaultColor` key; older browser bundles ignore the extra
|
|
134
|
+
* field.
|
|
135
|
+
*/
|
|
136
|
+
defaultColor: string | null;
|
|
137
|
+
/**
|
|
138
|
+
* Advisory default-color warnings, echoed so any surface can show them.
|
|
139
|
+
* Added with the `defaultColor` key; older browser bundles ignore the key.
|
|
140
|
+
*/
|
|
141
|
+
warnings: DshWebIconColorWarning[];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* A perceptual-distance warning about the effective default icon color.
|
|
146
|
+
* Advisory only — the configured value is still applied.
|
|
147
|
+
*/
|
|
148
|
+
export interface DshWebIconColorWarning {
|
|
149
|
+
/** `color-too-close` | `rainbow-overlap` | `invalid-color`. */
|
|
150
|
+
code: "color-too-close" | "rainbow-overlap" | "invalid-color";
|
|
151
|
+
/** The other state involved (absent for `invalid-color`). */
|
|
152
|
+
state?: DshWebIconStateName;
|
|
153
|
+
/** The effective default color the warning is about. */
|
|
154
|
+
base?: string;
|
|
155
|
+
/** The colliding state color (absent for `rainbow-overlap` / `invalid-color`). */
|
|
156
|
+
color?: string;
|
|
157
|
+
/** CIE76 ΔE between `base` and `color`. */
|
|
158
|
+
deltaE?: number;
|
|
159
|
+
/** `strong` below ΔE 12; `warn` below ΔE 25. */
|
|
160
|
+
level?: "strong" | "warn";
|
|
161
|
+
/** The rejected raw value (only for `invalid-color`). */
|
|
162
|
+
value?: string;
|
|
94
163
|
}
|
|
95
164
|
|
|
96
165
|
/**
|
|
@@ -100,7 +169,7 @@ export interface DshWebIconIndicatorAggregate {
|
|
|
100
169
|
*/
|
|
101
170
|
declare const plugin: {
|
|
102
171
|
name: "dsh-web-icon-indicator";
|
|
103
|
-
inject: readonly ["webServer", "timer", "agents", "fs"
|
|
172
|
+
inject: readonly ["webServer", "timer", "agents", "fs"];
|
|
104
173
|
config: DshWebIconIndicatorConfig;
|
|
105
174
|
apply(ctx: unknown, config?: unknown): void;
|
|
106
175
|
/** Settings namespace carrying the config (`web-icon-indicator`). */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-web-icon-indicator",
|
|
3
3
|
"description": "Browser tab favicon reflects the DSH session state: idle / running / asking / done, recolored and animated from one base SVG in the browser (fully configurable colors + effects). · 浏览器标签页 favicon 实时反映 DSH 会话状态:待机 / 运行中 / 提问 / 完成,由单个 base.svg 在浏览器中动态上色与动画(颜色与特效完全可配置)。",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"dsh": ">=0.1.2-rc.1"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"type": "git",
|
|
14
14
|
"url": "git+https://github.com/waknow/dsh-web-icon-indicator.git"
|
|
15
15
|
},
|
|
16
|
-
"homepage": "https://github.
|
|
16
|
+
"homepage": "https://waknow.github.io/dsh-web-icon-indicator/",
|
|
17
17
|
"bugs": {
|
|
18
18
|
"url": "https://github.com/waknow/dsh-web-icon-indicator/issues"
|
|
19
19
|
},
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"lib",
|
|
52
52
|
"icons",
|
|
53
53
|
"assets",
|
|
54
|
-
"
|
|
54
|
+
"test",
|
|
55
55
|
"cordis.patch.yml",
|
|
56
56
|
"screenshots.json",
|
|
57
57
|
"CHANGELOG.md",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Loader hooks that redirect the two @deepseek-ai peer imports of
|
|
2
|
+
// lib/index.js to local zero-dependency stubs (test/stubs), so test/verify.js
|
|
3
|
+
// can import and drive the REAL host plugin without a node_modules.
|
|
4
|
+
// Registered from test/verify.js via module.register before importing
|
|
5
|
+
// ../lib/index.js.
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
|
+
import { dirname, join } from "node:path";
|
|
8
|
+
|
|
9
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
|
|
11
|
+
const STUBS = {
|
|
12
|
+
"@deepseek-ai/schemastery": join(here, "stubs", "schemastery.mjs"),
|
|
13
|
+
"@deepseek-ai/dsh-settings": join(here, "stubs", "dsh-settings.mjs"),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export async function resolve(specifier, context, nextResolve) {
|
|
17
|
+
if (specifier in STUBS) {
|
|
18
|
+
return { url: pathToFileURL(STUBS[specifier]).href, shortCircuit: true };
|
|
19
|
+
}
|
|
20
|
+
return nextResolve(specifier, context);
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Zero-dependency stub for `@deepseek-ai/dsh-settings`, used only by
|
|
2
|
+
// test/loader-hooks.mjs. Captures the installSettingsSection args into
|
|
3
|
+
// globalThis so test/verify.js can assert the settings wiring and drive the
|
|
4
|
+
// captured setSource/onChange hooks.
|
|
5
|
+
export function settingsNamespace(name) {
|
|
6
|
+
return name;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function installSettingsSection(ctx, ns, schema, entry, opts) {
|
|
10
|
+
const slot = (globalThis.__DSH_ICON_TEST__ ||= {});
|
|
11
|
+
slot.ns = ns;
|
|
12
|
+
slot.schema = schema;
|
|
13
|
+
slot.entry = entry;
|
|
14
|
+
slot.settingsOpts = opts;
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Zero-dependency stub for `@deepseek-ai/schemastery`, used only by
|
|
2
|
+
// test/loader-hooks.mjs so test/verify.js can import the REAL lib/index.js
|
|
3
|
+
// without resolving the actual peer dependency. Only the surface used at
|
|
4
|
+
// module top level (chainable z.object / z.array / z.string / z.number /
|
|
5
|
+
// z.union / z.dict with .default()) needs to not throw; CONFIG_SCHEMA is
|
|
6
|
+
// passed to the stubbed installSettingsSection and never validated.
|
|
7
|
+
const z = new Proxy(function schemasteryStub() {}, {
|
|
8
|
+
get: () => z,
|
|
9
|
+
apply: () => z,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export default z;
|