@celestia-island/hikari 0.55.149 → 0.55.150
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/package.json +1 -1
- package/src/animation/registerAnimations.ts +0 -1
- package/src/components/HkConnectionStatus.shell.test.tsx +34 -0
- package/src/components/HkConnectionStatus.tsx +31 -10
- package/src/components/HkThemeDecor.test.tsx +11 -22
- package/src/components/HkThemeDecor.tsx +1 -1
- package/src/components/StatusTrayDecor.mount.test.ts +35 -0
- package/src/components/{HkStatusTray.size.test.ts → StatusTrayDecor.size.test.ts} +7 -3
- package/src/components/{HkStatusTray.test.tsx → StatusTrayDecor.test.tsx} +3 -2
- package/src/components/themeDecorLayout.contract.test.ts +6 -6
- package/src/composables/engineHealthTypes.ts +50 -0
- package/src/i18n/usageSurface.test.ts +0 -1
- package/src/index.ts +2 -102
- package/src/theme/standardDecor.test.ts +14 -13
- package/src/theme/standardDecor.ts +7 -3
- package/src/theme/themeDecorSurface.test.ts +5 -3
- package/src/utils/format.ts +0 -11
- package/src/components/HkAttachmentModal.scss +0 -49
- package/src/components/HkAttachmentModal.tsx +0 -318
- package/src/components/HkChatTypes.ts +0 -65
- package/src/components/HkContextRing.scss +0 -136
- package/src/components/HkContextRing.test.tsx +0 -309
- package/src/components/HkContextRing.tsx +0 -276
- package/src/components/HkModelCatalog.test.ts +0 -81
- package/src/components/HkModelCatalog.ts +0 -330
- package/src/components/HkModelTag.scss +0 -171
- package/src/components/HkModelTag.test.tsx +0 -155
- package/src/components/HkModelTag.tsx +0 -219
- package/src/components/HkRichInput.scss +0 -178
- package/src/components/HkRichInput.tsx +0 -335
- package/src/components/HkStatusTray.scss +0 -36
- package/src/components/HkStatusTray.tsx +0 -187
- package/src/components/HkTokenUsageBadge.scss +0 -50
- package/src/components/HkTokenUsageBadge.test.tsx +0 -59
- package/src/components/HkTokenUsageBadge.tsx +0 -54
- package/src/components/HkTokenUsagePanel.scss +0 -100
- package/src/components/HkTokenUsagePanel.tsx +0 -140
- package/src/components/HkToolBlock.scss +0 -327
- package/src/components/HkToolBlock.tsx +0 -394
- package/src/components/HkToolBlock.windowScroll.contract.test.ts +0 -93
- package/src/components/HkVoiceInputPopup.scss +0 -82
- package/src/components/HkVoiceInputPopup.tsx +0 -97
- package/src/composables/useAttachments.ts +0 -154
- package/src/composables/useConnectionProbe.test.ts +0 -179
- package/src/composables/useConnectionProbe.ts +0 -201
- package/src/composables/useEngineHealth.test.ts +0 -128
- package/src/composables/useEngineHealth.ts +0 -93
- package/src/composables/useSendShortcut.ts +0 -35
- package/src/i18n/contextKeys.test.ts +0 -52
- package/src/i18n/locales/ar/chat.json +0 -49
- package/src/i18n/locales/de/chat.json +0 -49
- package/src/i18n/locales/en/chat.json +0 -49
- package/src/i18n/locales/es/chat.json +0 -49
- package/src/i18n/locales/fr/chat.json +0 -49
- package/src/i18n/locales/ja/chat.json +0 -49
- package/src/i18n/locales/ko/chat.json +0 -49
- package/src/i18n/locales/pt/chat.json +0 -49
- package/src/i18n/locales/ru/chat.json +0 -49
- package/src/i18n/locales/zh-Hans/chat.json +0 -49
- package/src/i18n/locales/zh-Hant/chat.json +0 -49
package/package.json
CHANGED
|
@@ -110,7 +110,6 @@ registerCssAnimation("hk-flip-out");
|
|
|
110
110
|
registerCssAnimation("hk-flip-in");
|
|
111
111
|
// components/HkVoiceInputPopup.scss — voice waveform bounce (loops
|
|
112
112
|
// forever while listening; upstreamed from chest's plana-legacy).
|
|
113
|
-
registerCssAnimation("s-voice-wave-bounce", { infinite: true });
|
|
114
113
|
// components/HkPlaceholderMarquee.scss — overflowing placeholder sweep
|
|
115
114
|
// (loops forever; pure CSS, loop geometry on inline custom properties).
|
|
116
115
|
registerCssAnimation("hk-placeholder-marquee-scroll", { infinite: true });
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { createApp, h } from "vue";
|
|
3
|
+
|
|
4
|
+
import { HkConnectionStatus } from "./HkConnectionStatus";
|
|
5
|
+
|
|
6
|
+
/** The shell contract: WITHOUT injections the component never touches
|
|
7
|
+
* the network — the fetch-poll was demoted with the chat kit (the M1
|
|
8
|
+
* mutation guard: a fetch in the fallback path must go red here). */
|
|
9
|
+
const mounts: Array<{ app: ReturnType<typeof createApp>; container: HTMLElement }> = [];
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
for (const { app, container } of mounts.splice(0)) {
|
|
12
|
+
app.unmount();
|
|
13
|
+
container.remove();
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe("HkConnectionStatus (shell)", () => {
|
|
18
|
+
it("renders an inert unknown state with zero network calls", () => {
|
|
19
|
+
const fetchSpy = vi.fn();
|
|
20
|
+
const holder = globalThis.fetch;
|
|
21
|
+
globalThis.fetch = fetchSpy as unknown as typeof fetch;
|
|
22
|
+
try {
|
|
23
|
+
const container = document.createElement("div");
|
|
24
|
+
document.body.appendChild(container);
|
|
25
|
+
const app = createApp({ render: () => h(HkConnectionStatus, { standalone: true }) });
|
|
26
|
+
app.mount(container);
|
|
27
|
+
mounts.push({ app, container });
|
|
28
|
+
expect(fetchSpy).not.toHaveBeenCalled();
|
|
29
|
+
expect(container.textContent ?? "").not.toBeNull();
|
|
30
|
+
} finally {
|
|
31
|
+
globalThis.fetch = holder;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { computed, defineComponent, inject, type InjectionKey, type PropType, type Ref } from "vue";
|
|
1
|
+
import { computed, defineComponent, inject, ref, type InjectionKey, type PropType, type Ref } from "vue";
|
|
2
2
|
|
|
3
3
|
import { useI18n } from "../i18n/context";
|
|
4
|
-
import {
|
|
5
|
-
import { useEngineHealth } from "../composables/useEngineHealth";
|
|
4
|
+
import type { EngineHealth, EngineNetworkInfo, ProbeResult } from "../composables/engineHealthTypes";
|
|
6
5
|
|
|
7
6
|
import { HkStatusBar } from "./HkStatusBar";
|
|
8
7
|
import {
|
|
@@ -28,6 +27,25 @@ export interface HkConnectionProbeSource {
|
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
/** Injection key for the connection-probe overload (see above). */
|
|
30
|
+
/** Engine-health source a host provides (the demoted fetch's
|
|
31
|
+
* replacement): a ref of the /api/health envelope, or null. */
|
|
32
|
+
export const HK_ENGINE_HEALTH: InjectionKey<Ref<EngineHealth | null>> = Symbol(
|
|
33
|
+
"HK_ENGINE_HEALTH",
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
/** The shell's inert probe — no network, no timers: "unknown". */
|
|
37
|
+
const INERT_PROBE: ProbeResult = {
|
|
38
|
+
connected: false,
|
|
39
|
+
state: "disconnected",
|
|
40
|
+
transportTier: "unknown",
|
|
41
|
+
tier: "unknown",
|
|
42
|
+
latencyMs: null,
|
|
43
|
+
attemptNumber: 0,
|
|
44
|
+
retryCount: 0,
|
|
45
|
+
retryTotal: 0,
|
|
46
|
+
countdown: 0,
|
|
47
|
+
};
|
|
48
|
+
|
|
31
49
|
export const HK_CONNECTION_PROBE: InjectionKey<HkConnectionProbeSource> =
|
|
32
50
|
Symbol("HkConnectionProbe");
|
|
33
51
|
|
|
@@ -45,7 +63,8 @@ const backendStateColor: Record<HkBackendStatus["state"], string> = {
|
|
|
45
63
|
* Composes useConnectionProbe + useEngineHealth + useConnectionInfo +
|
|
46
64
|
* HkStatusBar. The probe source is injectable: when a parent provides
|
|
47
65
|
* HK_CONNECTION_PROBE, that probe (and its retryNow) is used verbatim;
|
|
48
|
-
*
|
|
66
|
+
* without an injection the shell renders an inert unknown state and
|
|
67
|
+
* NEVER touches the network (pinned). Slots:
|
|
49
68
|
* - `left` — extras after the status tags (e.g. a mock badge)
|
|
50
69
|
* - `right` — extras on the far right (e.g. an engine version tag)
|
|
51
70
|
*/
|
|
@@ -54,19 +73,21 @@ export const HkConnectionStatus = defineComponent({
|
|
|
54
73
|
props: {
|
|
55
74
|
version: { type: String, default: "0.1.0" },
|
|
56
75
|
panelBuildHash: { type: String as PropType<string | undefined>, default: undefined },
|
|
57
|
-
/** API origin for the /api/health probe (defaults to same-origin ""). */
|
|
58
|
-
baseUrl: { type: String as PropType<string | undefined>, default: undefined },
|
|
59
76
|
backendStatus: { type: Object as PropType<HkBackendStatus | undefined>, default: undefined },
|
|
60
77
|
standalone: { type: Boolean, default: true },
|
|
61
78
|
/** Forwarded to HkStatusBar — collapse to the traffic-light dot. */
|
|
62
79
|
compact: { type: Boolean, default: false },
|
|
63
80
|
},
|
|
64
81
|
setup(props, { slots }) {
|
|
65
|
-
//
|
|
66
|
-
//
|
|
82
|
+
// SHELL-ONLY: the network side (WHO polls /api/health and HOW)
|
|
83
|
+
// lives in the host — injected via HK_CONNECTION_PROBE /
|
|
84
|
+
// HK_ENGINE_HEALTH. Without an injection the shell renders an
|
|
85
|
+
// inert unknown state and never touches the network (the
|
|
86
|
+
// fetch-poll defaults were demoted with the chat kit wave).
|
|
67
87
|
const injectedProbe = inject(HK_CONNECTION_PROBE, null);
|
|
68
|
-
const
|
|
69
|
-
const
|
|
88
|
+
const probe = injectedProbe?.result ?? ref(INERT_PROBE);
|
|
89
|
+
const retryNow = injectedProbe?.retryNow ?? (() => {});
|
|
90
|
+
const health = inject(HK_ENGINE_HEALTH, ref<EngineHealth | null>(null));
|
|
70
91
|
|
|
71
92
|
const connectionState = computed<ConnectionStateInput>(() => probe.value.state);
|
|
72
93
|
const transportTier = computed(() => probe.value.transportTier);
|
|
@@ -175,29 +175,18 @@ describe("HkThemeDecor", () => {
|
|
|
175
175
|
expect(seen.at(-1)).toMatchObject({ variant: "host", kept: 1 });
|
|
176
176
|
});
|
|
177
177
|
|
|
178
|
-
it("
|
|
179
|
-
// The
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const themedTray = defineComponent({
|
|
186
|
-
name: "ThemedTray",
|
|
187
|
-
setup: () => () => h("i", { "data-decor": "themed-tray" }),
|
|
178
|
+
it("renders a theme tray over the now-empty builtin floor", async () => {
|
|
179
|
+
// The builtin status.tray floor is EMPTY since the demotion wave —
|
|
180
|
+
// the default theme package fills it via the "*" wildcard, and any
|
|
181
|
+
// exact-theme registration wins over that. Here: only the themed
|
|
182
|
+
// tray renders.
|
|
183
|
+
const ThemedTray = defineComponent({
|
|
184
|
+
setup: () => () => h("div", { "data-decor": "themed-tray" }),
|
|
188
185
|
});
|
|
189
|
-
registerThemeDecor({ themeId: "
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
setTheme("endfield");
|
|
194
|
-
await nextTick();
|
|
195
|
-
expect(container.querySelector('[data-decor="themed-tray"]')).not.toBeNull();
|
|
196
|
-
expect(container.querySelector(".s-status-bar-system-tray")).toBeNull();
|
|
197
|
-
|
|
198
|
-
setTheme("default");
|
|
186
|
+
registerThemeDecor({ themeId: "t", slot: "status.tray", component: ThemedTray });
|
|
187
|
+
useTheme().setTheme("t");
|
|
188
|
+
const host = mount(h(HkThemeDecor, { slot: "status.tray" }));
|
|
199
189
|
await nextTick();
|
|
200
|
-
expect(
|
|
201
|
-
expect(container.querySelector(".s-status-bar-system-tray")).not.toBeNull();
|
|
190
|
+
expect(host.querySelector('[data-decor="themed-tray"]')).not.toBeNull();
|
|
202
191
|
});
|
|
203
192
|
});
|
|
@@ -50,7 +50,7 @@ import { useTheme } from "../theme/useTheme";
|
|
|
50
50
|
* that wants numeric sizing declares its own prop and receives it through
|
|
51
51
|
* `decorProps`.
|
|
52
52
|
*
|
|
53
|
-
* The ladder is the CONTRACT's, not any one decor's:
|
|
53
|
+
* The ladder is the CONTRACT's, not any one decor's: the default theme's tray
|
|
54
54
|
* implements `sm | md | lg` only, so asking it for `xs` publishes no
|
|
55
55
|
* `--hk-tray-*` var at all and the sheet's `var(--hk-tray-glyph, 9px)`
|
|
56
56
|
* fallbacks render the shipped (md) geometry. That degradation is pinned by
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import StatusTrayDecor from "../../../default_theme/src/StatusTrayDecor";
|
|
4
|
+
// The one-import contract under test: importing the package index IS the
|
|
5
|
+
// mount (README: `import "@celestia-island/default-theme"` — CSS + decor).
|
|
6
|
+
import "../../../default_theme/src/index";
|
|
7
|
+
import { getThemeDecor } from "../theme/themeDecor";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @celestia-island/default-theme's delivery mechanism: a bare import of the
|
|
11
|
+
* package mounts the tray decor on the "*" wildcard via registerThemeDecor,
|
|
12
|
+
* so every theme (and themeless hosts) resolve it without any host glue.
|
|
13
|
+
*
|
|
14
|
+
* This pin lives in the vue suite because default_theme ships no runner of
|
|
15
|
+
* its own — the vue suite is the only vitest root (CI: ci-hosted.yml) — and
|
|
16
|
+
* the registry it asserts against is hikari's own. It goes red if the
|
|
17
|
+
* side-effect call disappears from the package index (the "explicit
|
|
18
|
+
* mountDefaultTheme()" escape hatch is a replacement, not a supplement).
|
|
19
|
+
*/
|
|
20
|
+
describe("@celestia-island/default-theme side-effect mount", () => {
|
|
21
|
+
it("a bare import of the package mounts the tray on the '*' wildcard", () => {
|
|
22
|
+
const resolved = getThemeDecor("status.tray", "any-theme-id");
|
|
23
|
+
expect(resolved, "status.tray resolves after the bare import").toBeDefined();
|
|
24
|
+
// And it is THE decor component — not merely some entry — so the
|
|
25
|
+
// wildcard registration cannot silently drift to another component.
|
|
26
|
+
expect(resolved?.component).toBe(StatusTrayDecor);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("outranks the builtin floor without touching it (the override path)", () => {
|
|
30
|
+
// The builtin floor for status.tray is deliberately empty (pinned in
|
|
31
|
+
// standardDecor.test.ts); the wildcard entry is the ONLY reason the
|
|
32
|
+
// slot resolves. Same lookup through the star id lands on it too.
|
|
33
|
+
expect(getThemeDecor("status.tray", "*")?.component).toBe(StatusTrayDecor);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -6,7 +6,7 @@ import { compile } from "sass";
|
|
|
6
6
|
import { describe, expect, it } from "vitest";
|
|
7
7
|
import { createApp, h } from "vue";
|
|
8
8
|
|
|
9
|
-
import HkStatusTray, { HK_TRAY_SIZE_VARS, type HkStatusTraySize } from "
|
|
9
|
+
import HkStatusTray, { HK_TRAY_SIZE_VARS, type HkStatusTraySize } from "../../../default_theme/src/StatusTrayDecor";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* The "md is pixel-identical to what already ships" contract.
|
|
@@ -18,7 +18,7 @@ import HkStatusTray, { HK_TRAY_SIZE_VARS, type HkStatusTraySize } from "./HkStat
|
|
|
18
18
|
*
|
|
19
19
|
* 1. the shipped admin-tokens rules (the source of truth),
|
|
20
20
|
* 2. the component's `md` row in HK_TRAY_SIZE_VARS,
|
|
21
|
-
* 3. the fallbacks in
|
|
21
|
+
* 3. the fallbacks in StatusTrayDecor.scss (packages/default_theme).
|
|
22
22
|
*
|
|
23
23
|
* This guard reads (1) out of the COMPILED sheet — not a hand-copied list —
|
|
24
24
|
* and holds (2) and (3) to it, so moving any one of them alone fails here
|
|
@@ -67,7 +67,11 @@ function specificity(selector: string): number {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
const adminCss = compileSheet(resolve(stylesDir, "admin-tokens.scss"));
|
|
70
|
-
|
|
70
|
+
// The tray decor itself lives in packages/default_theme now; the shared
|
|
71
|
+
// sheets it is held against (admin-tokens.scss, scale.scss) stayed here.
|
|
72
|
+
const trayCss = compileSheet(
|
|
73
|
+
resolve(componentDir, "../../../default_theme/src/StatusTrayDecor.scss"),
|
|
74
|
+
);
|
|
71
75
|
const scaleVars: Record<string, string> = {};
|
|
72
76
|
for (const m of readFileSync(resolve(srcDir, "scale.scss"), "utf8")
|
|
73
77
|
.replace(/\/\*[\s\S]*?\*\//g, "")
|
|
@@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
2
2
|
import { createApp, h, nextTick } from "vue";
|
|
3
3
|
|
|
4
4
|
import { readHkRuntime } from "../runtime/registry";
|
|
5
|
-
import HkStatusTray from "
|
|
5
|
+
import HkStatusTray from "../../../default_theme/src/StatusTrayDecor";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* HkStatusTray behaviour: the gamepad cluster + clock surface, its size and
|
|
@@ -10,7 +10,8 @@ import HkStatusTray from "./HkStatusTray";
|
|
|
10
10
|
* teardown of both intervals.
|
|
11
11
|
*
|
|
12
12
|
* The "md equals the shipped CSS" contract lives next door in
|
|
13
|
-
* `
|
|
13
|
+
* `StatusTrayDecor.size.test.ts` (it reads the sheets, not the DOM —
|
|
14
|
+
* the decor itself lives in packages/default_theme).
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
17
|
const mounts: Array<{ app: ReturnType<typeof createApp>; container: HTMLElement }> = [];
|
|
@@ -50,7 +50,6 @@ interface Target {
|
|
|
50
50
|
|
|
51
51
|
const TARGETS: Target[] = [
|
|
52
52
|
{ file: "HkThemeDecor.tsx", anchor: "HkThemeDecor" },
|
|
53
|
-
{ file: "HkStatusTray.tsx", anchor: "s-status-bar-system-tray" },
|
|
54
53
|
{ file: "HkStatusTray.scss", anchor: "s-status-bar-system-tray" },
|
|
55
54
|
];
|
|
56
55
|
|
|
@@ -102,10 +101,11 @@ describe("theme decor layout contract", () => {
|
|
|
102
101
|
});
|
|
103
102
|
|
|
104
103
|
it("scans existing files that carry the expected content (no empty scan)", () => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
// The tray decor moved to packages/default_theme (the demotion
|
|
105
|
+
// wave); only the files still living here are scanned.
|
|
106
|
+
const present = TARGETS.filter(({ file }) => existsSync(resolve(componentDir, file)));
|
|
107
|
+
expect(present.length, "at least one target still in-tree").toBeGreaterThan(0);
|
|
108
|
+
for (const { file, anchor } of present) {
|
|
109
109
|
const source = read(file);
|
|
110
110
|
expect(source.length, `${file} is not empty`).toBeGreaterThan(50);
|
|
111
111
|
expect(source, `${file} carries ${anchor}`).toContain(anchor);
|
|
@@ -113,7 +113,7 @@ describe("theme decor layout contract", () => {
|
|
|
113
113
|
});
|
|
114
114
|
|
|
115
115
|
it("keeps positioning out of the decor components and their sheets", () => {
|
|
116
|
-
for (const { file } of TARGETS) {
|
|
116
|
+
for (const { file } of TARGETS.filter(({ file }) => existsSync(resolve(componentDir, file)))) {
|
|
117
117
|
const hits = positionHits(file, read(file));
|
|
118
118
|
expect(hits, `${file} must not position itself: ${JSON.stringify(hits)}`).toEqual([]);
|
|
119
119
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** Engine-health DTOs — the SHELL side of the split (the fetch hook
|
|
2
|
+
* that fills them was demoted to the consuming app with the chat-kit
|
|
3
|
+
* wave; the shapes stay so HkConnectionStatus's injection contract is
|
|
4
|
+
* typed here). */
|
|
5
|
+
|
|
6
|
+
/** Connectivity probe result — the shape a host's injected probe
|
|
7
|
+
* (HK_CONNECTION_PROBE) exposes. The fetch implementation that
|
|
8
|
+
* produced it was demoted to the app; the shape stays as the shell's
|
|
9
|
+
* contract. */
|
|
10
|
+
export interface ProbeResult {
|
|
11
|
+
connected: boolean;
|
|
12
|
+
state: "connected" | "disconnected" | "connecting" | "reconnecting" | "failed";
|
|
13
|
+
/** Canonical transport tier ("local" | "ws" | "sse" | "poll"). */
|
|
14
|
+
transportTier: string;
|
|
15
|
+
/** @deprecated Use `transportTier`. Alias kept for compatibility. */
|
|
16
|
+
tier: string;
|
|
17
|
+
latencyMs: number | null;
|
|
18
|
+
/** Canonical 1-based connect-attempt counter. */
|
|
19
|
+
attemptNumber: number;
|
|
20
|
+
/** @deprecated Use `attemptNumber`. Alias kept for compatibility. */
|
|
21
|
+
retryCount: number;
|
|
22
|
+
retryTotal: number;
|
|
23
|
+
/** Seconds until the next automatic probe attempt. */
|
|
24
|
+
countdown: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
/** Inlined subset of the `/api/health` network payload — kept local so
|
|
29
|
+
* hikari stays dependency-free of protocol packages. */
|
|
30
|
+
export interface NetworkInfo {
|
|
31
|
+
transport?: string;
|
|
32
|
+
region?: string;
|
|
33
|
+
asn?: number | null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Inlined subset of the `/api/health` response envelope. */
|
|
37
|
+
export interface HealthResponse {
|
|
38
|
+
engine_version?: string;
|
|
39
|
+
build_hash?: string;
|
|
40
|
+
network?: NetworkInfo;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type { NetworkInfo as EngineNetworkInfo };
|
|
44
|
+
|
|
45
|
+
/** Subset of `/api/health` relevant to status-bar style consumers. */
|
|
46
|
+
export interface EngineHealth {
|
|
47
|
+
engineVersion: string | null;
|
|
48
|
+
engineBuildHash: string | null;
|
|
49
|
+
network: NetworkInfo | null;
|
|
50
|
+
}
|
|
@@ -122,7 +122,6 @@ function scanSources(): { statics: Site[]; constructed: Site[] } {
|
|
|
122
122
|
* every listed family must still exist in source, so this whitelist
|
|
123
123
|
* cannot rot into silence. */
|
|
124
124
|
const DYNAMIC_KEY_FAMILIES: Record<string, string> = {
|
|
125
|
-
"hikari::context.": "HkContextRing section keys — closed enum, pinned by name in contextKeys.test.ts.",
|
|
126
125
|
"hikari::statusBar.backend.": "HkConnectionStatus — enumerated connection-state suffixes.",
|
|
127
126
|
"hikari::statusBar.region.": "HkStatusBar region names — OPTIONAL per-locale overrides over Intl.DisplayNames (see LOCALE_SPECIFIC_NESTED in flatKeyParity.test.ts).",
|
|
128
127
|
"hikari::statusBar.tier.": "HkStatusBar transport tiers — constructed into a variable at a distance from its t() call (F1); the four concrete ids are pinned by name in CONSTRUCTED_FAMILY_KEYS below.",
|
package/src/index.ts
CHANGED
|
@@ -124,30 +124,7 @@ export { default as HWaterfall } from "./components/HkWaterfall";
|
|
|
124
124
|
export { default as HBlankCanvas } from "./components/HkBlankCanvas";
|
|
125
125
|
export type { BlankCanvasSize } from "./components/HkBlankCanvas";
|
|
126
126
|
export { default as HKanban } from "./components/HkKanban";
|
|
127
|
-
export type {
|
|
128
|
-
KanbanAxis,
|
|
129
|
-
KanbanCardSlotProps,
|
|
130
|
-
KanbanHeaderSlotProps,
|
|
131
|
-
KanbanMove,
|
|
132
|
-
} from "./components/HkKanban";
|
|
133
127
|
export { default as HNodeCanvas, NODE_CANVAS_DEFAULTS } from "./components/HkNodeCanvas";
|
|
134
|
-
export type {
|
|
135
|
-
NodeCanvasCamera,
|
|
136
|
-
NodeCanvasBounds,
|
|
137
|
-
NodeCanvasSlotProps,
|
|
138
|
-
MinimapPlacement,
|
|
139
|
-
NodeCanvasEdge,
|
|
140
|
-
EdgeRouting,
|
|
141
|
-
EdgeSide,
|
|
142
|
-
EdgeSubpath,
|
|
143
|
-
EdgePointerEvent,
|
|
144
|
-
} from "./components/HkNodeCanvas";
|
|
145
|
-
export type {
|
|
146
|
-
WaterfallBucket,
|
|
147
|
-
WaterfallCardSlotProps,
|
|
148
|
-
WaterfallHeaderSlotProps,
|
|
149
|
-
WaterfallRailSlotProps,
|
|
150
|
-
} from "./components/HkWaterfall";
|
|
151
128
|
export { default as HDateTimePicker } from "./components/HkDateTimePicker";
|
|
152
129
|
export { default as HDatePicker } from "./components/HkDatePicker";
|
|
153
130
|
export { default as HTimeline } from "./components/HkTimeline";
|
|
@@ -251,7 +228,6 @@ export { type TrendPen, type TrendPoint, type AlarmThresholds } from "./componen
|
|
|
251
228
|
|
|
252
229
|
// ── Theme decor (theme-provided decorative widgets, host-placed) ──────────
|
|
253
230
|
export { default as HkThemeDecor, type HkThemeDecorSize } from "./components/HkThemeDecor";
|
|
254
|
-
export { default as HkStatusTray, type HkStatusTraySize } from "./components/HkStatusTray";
|
|
255
231
|
|
|
256
232
|
// Theme system
|
|
257
233
|
export {
|
|
@@ -446,10 +422,6 @@ export { useApproachEnd } from "./composables/useApproachEnd";
|
|
|
446
422
|
export type { ApproachEndOptions, ApproachEndHandle } from "./composables/useApproachEnd";
|
|
447
423
|
export { useDeferredTransition } from "./composables/useDeferredTransition";
|
|
448
424
|
export { useSurfaceTransition } from "./composables/useSurfaceTransition";
|
|
449
|
-
export type {
|
|
450
|
-
SurfaceTransition,
|
|
451
|
-
SurfaceTransitionHooks,
|
|
452
|
-
} from "./composables/useSurfaceTransition";
|
|
453
425
|
export { useSizeMorph } from "./composables/useSizeMorph";
|
|
454
426
|
export type { SizeMorph } from "./composables/useSizeMorph";
|
|
455
427
|
export { useImage } from "./composables/useImage";
|
|
@@ -471,11 +443,6 @@ export {
|
|
|
471
443
|
nearestLaidAncestor,
|
|
472
444
|
placePoint,
|
|
473
445
|
} from "./composables/layoutGeometry";
|
|
474
|
-
export type {
|
|
475
|
-
FrameMetrics,
|
|
476
|
-
LayoutOffset,
|
|
477
|
-
LayoutRect,
|
|
478
|
-
} from "./composables/layoutGeometry";
|
|
479
446
|
export { useMeasuredHighlight } from "./composables/useMeasuredHighlight";
|
|
480
447
|
export type { UseMeasuredHighlightOptions, MeasuredHighlight } from "./composables/useMeasuredHighlight";
|
|
481
448
|
export {
|
|
@@ -532,10 +499,6 @@ export {
|
|
|
532
499
|
export { usePageTitle, useRouteTitle } from "./composables/usePageTitle";
|
|
533
500
|
export { provideActionBar, useActionBar } from "./composables/useActionBar";
|
|
534
501
|
export type { ActionBarRenderer } from "./composables/useActionBar";
|
|
535
|
-
export { setProbeEndpoint, useConnectionProbe } from "./composables/useConnectionProbe";
|
|
536
|
-
export type { ProbeResult } from "./composables/useConnectionProbe";
|
|
537
|
-
export { useEngineHealth } from "./composables/useEngineHealth";
|
|
538
|
-
export type { EngineHealth, EngineNetworkInfo } from "./composables/useEngineHealth";
|
|
539
502
|
export { leadingZeroBits, sha256, solvePow, solvePowSync, verifyPow } from "./utils/pow";
|
|
540
503
|
export type { PowChallenge, PowSolution } from "./utils/pow";
|
|
541
504
|
export { HkLocalePicker as HLocalePicker } from "./components/HkLocalePicker";
|
|
@@ -570,13 +533,6 @@ export {
|
|
|
570
533
|
} from "./components/HkSettingsDialog";
|
|
571
534
|
|
|
572
535
|
export { HkCookieConsent as HCookieConsent } from "./components/HkCookieConsent";
|
|
573
|
-
export {
|
|
574
|
-
HkAttachmentModal as HAttachmentModal,
|
|
575
|
-
previewKindFor,
|
|
576
|
-
type HAttachmentDetail,
|
|
577
|
-
type HAttachmentItem,
|
|
578
|
-
type HAttachmentPreviewType,
|
|
579
|
-
} from "./components/HkAttachmentModal";
|
|
580
536
|
export { HkStatusBar as HStatusBar } from "./components/HkStatusBar";
|
|
581
537
|
export { useConnectionInfo } from "./components/HkConnectionInfo";
|
|
582
538
|
export type { ConnectionStateInput, HkConnectionInfo } from "./components/HkConnectionInfo";
|
|
@@ -587,67 +543,22 @@ export {
|
|
|
587
543
|
type HkBackendStatus,
|
|
588
544
|
type HkConnectionProbeSource,
|
|
589
545
|
} from "./components/HkConnectionStatus";
|
|
546
|
+
export { HK_ENGINE_HEALTH } from "./components/HkConnectionStatus";
|
|
547
|
+
export type { ProbeResult, EngineHealth, EngineNetworkInfo } from "./composables/engineHealthTypes";
|
|
590
548
|
|
|
591
549
|
// ── Chat kit (upstreamed from shittim-chest's plana-legacy layer) ──────────
|
|
592
|
-
export { HkRichInput as HRichInput } from "./components/HkRichInput";
|
|
593
|
-
export { HkVoiceInputPopup as HVoiceInputPopup } from "./components/HkVoiceInputPopup";
|
|
594
|
-
export {
|
|
595
|
-
HkToolBlock as HToolBlock,
|
|
596
|
-
parseToolCallText,
|
|
597
|
-
extractExecCode,
|
|
598
|
-
buildHighlightedLines,
|
|
599
|
-
type HParsedToolCall,
|
|
600
|
-
type HToolBlockVariant,
|
|
601
|
-
type HHighlightedLine,
|
|
602
|
-
} from "./components/HkToolBlock";
|
|
603
550
|
export {
|
|
604
551
|
HkJsonTree as HJsonTree,
|
|
605
552
|
buildJsonTree,
|
|
606
553
|
type HJsonNode,
|
|
607
554
|
} from "./components/HkJsonTree";
|
|
608
|
-
export { HkTokenUsageBadge as HTokenUsageBadge } from "./components/HkTokenUsageBadge";
|
|
609
|
-
export { HkTokenUsagePanel as HTokenUsagePanel } from "./components/HkTokenUsagePanel";
|
|
610
|
-
export { HkModelTag as HModelTag } from "./components/HkModelTag";
|
|
611
|
-
export { HkContextRing as HContextRing, HkContextRing, type HkContextSegment } from "./components/HkContextRing";
|
|
612
|
-
export {
|
|
613
|
-
getModelMeta,
|
|
614
|
-
registerModelCatalog,
|
|
615
|
-
splitModelId,
|
|
616
|
-
type HModelPricing,
|
|
617
|
-
type HModelMeta,
|
|
618
|
-
type HModelCatalog,
|
|
619
|
-
} from "./components/HkModelCatalog";
|
|
620
|
-
export type {
|
|
621
|
-
HChatRole,
|
|
622
|
-
HToolCall,
|
|
623
|
-
HToolCallStatus,
|
|
624
|
-
HVoicePopupMode,
|
|
625
|
-
HVoiceState,
|
|
626
|
-
HModelUsageEntry,
|
|
627
|
-
HModelCosts,
|
|
628
|
-
} from "./components/HkChatTypes";
|
|
629
555
|
// Canonical Hk* names for the directly-exported types above (2026-09-24
|
|
630
556
|
// unification follow-up, second batch — caught by the third-scan reverse
|
|
631
557
|
// validation). These types are defined with their H* names at the source.
|
|
632
|
-
export type {
|
|
633
|
-
HChatRole as HkChatRole,
|
|
634
|
-
HToolCall as HkToolCall,
|
|
635
|
-
HToolCallStatus as HkToolCallStatus,
|
|
636
|
-
HVoicePopupMode as HkVoicePopupMode,
|
|
637
|
-
HVoiceState as HkVoiceState,
|
|
638
|
-
HModelUsageEntry as HkModelUsageEntry,
|
|
639
|
-
HModelCosts as HkModelCosts,
|
|
640
|
-
} from "./components/HkChatTypes";
|
|
641
|
-
export { useSendShortcut } from "./composables/useSendShortcut";
|
|
642
|
-
export type { SendShortcutMode } from "./composables/useSendShortcut";
|
|
643
|
-
export { useAttachments } from "./composables/useAttachments";
|
|
644
|
-
export type { HkUploadedFile } from "./composables/useAttachments";
|
|
645
558
|
|
|
646
559
|
export {
|
|
647
|
-
formatTokenCount,
|
|
648
560
|
formatNumber,
|
|
649
561
|
formatBytes,
|
|
650
|
-
formatPriceUsd,
|
|
651
562
|
formatRelativeTime,
|
|
652
563
|
formatDateTime,
|
|
653
564
|
formatDate,
|
|
@@ -861,27 +772,16 @@ export { HkSettingsGroup as HkSettingsGroup } from "./components/HkSettingsDialo
|
|
|
861
772
|
export { HkSettingsSub as HkSettingsSub } from "./components/HkSettingsDialog";
|
|
862
773
|
export { HkSettingsHint as HkSettingsHint } from "./components/HkSettingsDialog";
|
|
863
774
|
export { HkCookieConsent as HkCookieConsent } from "./components/HkCookieConsent";
|
|
864
|
-
export { HkAttachmentModal as HkAttachmentModal } from "./components/HkAttachmentModal";
|
|
865
775
|
export { HkStatusBar as HkStatusBar, hkMergeVersionDisplay, hkParseIdentity } from "./components/HkStatusBar";
|
|
866
776
|
export type { HkVersionIdentity } from "./components/HkStatusBar";
|
|
867
777
|
export { HkCountdownDigit as HkCountdownDigit } from "./components/HkCountdownDigit";
|
|
868
778
|
export { HkConnectionStatus as HkConnectionStatus } from "./components/HkConnectionStatus";
|
|
869
|
-
export { HkRichInput as HkRichInput } from "./components/HkRichInput";
|
|
870
|
-
export { HkVoiceInputPopup as HkVoiceInputPopup } from "./components/HkVoiceInputPopup";
|
|
871
|
-
export { HkToolBlock as HkToolBlock } from "./components/HkToolBlock";
|
|
872
779
|
export { HkJsonTree as HkJsonTree } from "./components/HkJsonTree";
|
|
873
|
-
export { HkTokenUsageBadge as HkTokenUsageBadge } from "./components/HkTokenUsageBadge";
|
|
874
|
-
export { HkTokenUsagePanel as HkTokenUsagePanel } from "./components/HkTokenUsagePanel";
|
|
875
|
-
export { HkModelTag as HkModelTag } from "./components/HkModelTag";
|
|
876
780
|
|
|
877
781
|
// Canonical Hk* names for directly-exported types (2026-09-24
|
|
878
782
|
// unification follow-up). These types were defined with their H*
|
|
879
783
|
// names at the source and exported directly — not aliased from an Hk*
|
|
880
784
|
// identifier — so the canonical Hk* form is an alias export here.
|
|
881
|
-
export { type HAttachmentItem as HkAttachmentItem } from "./components/HkAttachmentModal";
|
|
882
|
-
export { type HAttachmentDetail as HkAttachmentDetail } from "./components/HkAttachmentModal";
|
|
883
|
-
export { type HModelMeta as HkModelMeta } from "./components/HkModelCatalog";
|
|
884
|
-
export { type HModelPricing as HkModelPricing } from "./components/HkModelCatalog";
|
|
885
785
|
export { type HAboutCredit as HkAboutCredit } from "./components/HkAboutModal";
|
|
886
786
|
export { type HAboutLink as HkAboutLink } from "./components/HkAboutModal";
|
|
887
787
|
export { type HAboutLinkFace as HkAboutLinkFace } from "./components/HkAboutModal";
|
|
@@ -5,7 +5,6 @@ import HkDivider from "../components/HkDivider";
|
|
|
5
5
|
import HkEmptyState from "../components/HkEmptyState";
|
|
6
6
|
import HkSkeleton from "../components/HkSkeleton";
|
|
7
7
|
import HkSplash from "../components/HkSplash";
|
|
8
|
-
import HkStatusTray from "../components/HkStatusTray";
|
|
9
8
|
import { registerStandardThemeDecor, STANDARD_THEME_DECOR_SLOTS } from "./standardDecor";
|
|
10
9
|
import {
|
|
11
10
|
getThemeDecor,
|
|
@@ -24,7 +23,7 @@ import {
|
|
|
24
23
|
*/
|
|
25
24
|
|
|
26
25
|
describe("registerStandardThemeDecor", () => {
|
|
27
|
-
it("registers nothing at import, then fills the
|
|
26
|
+
it("registers nothing at import, then fills the four in-tree standard slots", async () => {
|
|
28
27
|
// A fresh module graph, so this proves the registration happens in the
|
|
29
28
|
// call and not in an earlier case of this file. The component is
|
|
30
29
|
// imported from the SAME fresh graph: module identity is per graph, so
|
|
@@ -32,7 +31,8 @@ describe("registerStandardThemeDecor", () => {
|
|
|
32
31
|
vi.resetModules();
|
|
33
32
|
const themeDecor = await import("./themeDecor");
|
|
34
33
|
const standardDecor = await import("./standardDecor");
|
|
35
|
-
|
|
34
|
+
// The tray moved to @celestia-island/default-theme; the builtin
|
|
35
|
+
// floor for status.tray is now EMPTY (pinned below).
|
|
36
36
|
|
|
37
37
|
// Importing this module is not a side effect (same contract as
|
|
38
38
|
// standardGroups): only the call populates the registry.
|
|
@@ -43,15 +43,14 @@ describe("registerStandardThemeDecor", () => {
|
|
|
43
43
|
expect([...themeDecor.themeDecorSlots()].sort()).toEqual(
|
|
44
44
|
[...STANDARD_THEME_DECOR_SLOTS].sort(),
|
|
45
45
|
);
|
|
46
|
-
expect(themeDecor.getThemeDecor("status.tray", "any-theme")
|
|
46
|
+
expect(themeDecor.getThemeDecor("status.tray", "any-theme")).toBeUndefined();
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
it("resolves every built-in for any theme id (floor level, and the declared list matches)", () => {
|
|
50
50
|
registerStandardThemeDecor();
|
|
51
51
|
|
|
52
52
|
const expected: [string, unknown][] = [
|
|
53
|
-
|
|
54
|
-
["placeholder.screen", HkSplash],
|
|
53
|
+
["placeholder.screen", HkSplash],
|
|
55
54
|
["placeholder.section", HkSkeleton],
|
|
56
55
|
["empty", HkEmptyState],
|
|
57
56
|
["divider", HkDivider],
|
|
@@ -93,28 +92,30 @@ describe("registerStandardThemeDecor", () => {
|
|
|
93
92
|
|
|
94
93
|
// A theme's own implementation wins over the built-in …
|
|
95
94
|
const themed = defineComponent({ name: "ThemedTray", setup: () => () => h("i") });
|
|
96
|
-
registerThemeDecor({ themeId: "endfield", slot: "
|
|
95
|
+
registerThemeDecor({ themeId: "endfield", slot: "placeholder.screen", component: themed });
|
|
97
96
|
registerStandardThemeDecor();
|
|
98
|
-
expect(getThemeDecor("
|
|
99
|
-
|
|
97
|
+
expect(getThemeDecor("placeholder.screen", "endfield")?.component).toBe(themed);
|
|
98
|
+
// A slot with no theme registration keeps the builtin floor.
|
|
99
|
+
expect(getThemeDecor("placeholder.screen", "other")?.component).toBe(HkSplash);
|
|
100
100
|
|
|
101
101
|
// … and so does a host-wide `"*"` registration.
|
|
102
102
|
const hostWide = defineComponent({ name: "HostTray", setup: () => () => h("i") });
|
|
103
|
-
registerThemeDecor({ themeId: "*", slot: "
|
|
103
|
+
registerThemeDecor({ themeId: "*", slot: "empty", component: hostWide });
|
|
104
104
|
registerStandardThemeDecor();
|
|
105
|
-
expect(getThemeDecor("
|
|
105
|
+
expect(getThemeDecor("empty", "other")?.component).toBe(hostWide);
|
|
106
106
|
});
|
|
107
107
|
|
|
108
108
|
it("lands in the registry via initTheme() (and not before)", async () => {
|
|
109
109
|
vi.resetModules();
|
|
110
110
|
const themeDecor = await import("./themeDecor");
|
|
111
|
-
|
|
111
|
+
// The tray moved to @celestia-island/default-theme; the builtin
|
|
112
|
+
// floor for status.tray is now EMPTY (pinned below).
|
|
112
113
|
const useTheme = await import("./useTheme");
|
|
113
114
|
expect(themeDecor.getThemeDecor("status.tray", "default")).toBeUndefined();
|
|
114
115
|
|
|
115
116
|
useTheme.initTheme();
|
|
116
117
|
|
|
117
|
-
expect(themeDecor.getThemeDecor("status.tray", "default")
|
|
118
|
+
expect(themeDecor.getThemeDecor("status.tray", "default")).toBeUndefined();
|
|
118
119
|
// initTheme starts the solar theme clock; stop it so this file leaves no
|
|
119
120
|
// timer behind.
|
|
120
121
|
useTheme.stopThemeClock();
|