@groeponline/pi-wishcraft 1.1.0 → 1.2.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 +13 -0
- package/README.md +16 -7
- package/ROADMAP.md +41 -260
- package/docs/commands.md +6 -2
- package/docs/configuration.md +21 -0
- package/docs/design/accessibility.md +71 -0
- package/docs/design/deck-layout.md +69 -0
- package/docs/design/motion-gallery.md +80 -0
- package/docs/design/motion-system.md +119 -0
- package/docs/design/presets.md +196 -0
- package/docs/design/regression-testing.md +54 -0
- package/docs/design/responsive.md +53 -0
- package/docs/design/signal.md +68 -0
- package/docs/design/theme-contract.md +132 -0
- package/docs/design/vnext-overview.md +55 -0
- package/docs/design/vnext-release-plan.md +212 -0
- package/docs/index.md +19 -1
- package/docs/segments.md +1 -1
- package/package.json +2 -1
- package/src/config/appearance.ts +230 -0
- package/src/config/parse.ts +41 -0
- package/src/config/presets.ts +184 -0
- package/src/config/structural-presets.ts +555 -0
- package/src/config/tokens.ts +154 -0
- package/src/config/types.ts +210 -2
- package/src/extension/commands/commands.ts +36 -12
- package/src/extension/commands/powerline-completions.ts +4 -0
- package/src/extension/commands/queue-commands.ts +6 -0
- package/src/extension/core/segment-context.ts +7 -1
- package/src/extension/core/state.ts +14 -0
- package/src/extension/core/types.ts +7 -0
- package/src/extension/session/session-lifecycle.ts +20 -0
- package/src/extension/settings/appearance-write.ts +135 -0
- package/src/extension/settings/wishcraft-config-items.ts +119 -0
- package/src/extension/settings/wishcraft-config.ts +28 -114
- package/src/extension/skills/skill-manager.ts +5 -0
- package/src/extension/ui/deck/component.ts +358 -0
- package/src/extension/ui/deck/index.ts +34 -0
- package/src/extension/ui/deck/render.ts +260 -0
- package/src/extension/ui/deck/route-bodies.ts +209 -0
- package/src/extension/ui/deck/routes.ts +37 -0
- package/src/extension/ui/deck/session-snapshot.ts +104 -0
- package/src/extension/ui/deck/types.ts +92 -0
- package/src/extension/ui/powerline-menu-view.ts +19 -15
- package/src/extension/ui/signal-layout.ts +77 -0
- package/src/extension/ui/status-line-renderers.ts +20 -2
- package/src/motion/accessibility.ts +59 -0
- package/src/motion/catalog-extra.ts +429 -0
- package/src/motion/catalog.ts +336 -0
- package/src/motion/composer.ts +147 -0
- package/src/motion/frames.ts +84 -0
- package/src/motion/gallery.ts +77 -0
- package/src/motion/index.ts +78 -0
- package/src/motion/policy.ts +128 -0
- package/src/motion/scheduler.ts +159 -0
- package/src/motion/types.ts +132 -0
- package/src/render/timer.ts +1 -0
- package/src/signal/controller.ts +123 -0
- package/src/signal/integration.ts +42 -0
- package/src/signal/render.ts +178 -0
- package/src/theme/detect.ts +48 -0
- package/src/theme/tokens/index.ts +9 -0
- package/src/theme/tokens/mapping.ts +62 -0
- package/src/theme/tokens/types.ts +39 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* appearance.ts
|
|
3
|
+
* ---------------------------------------------------------------------------
|
|
4
|
+
* Mixable appearance resolution for Wishcraft vNext. Users can pair any
|
|
5
|
+
* structural preset base with independent palette, signal layout, chrome,
|
|
6
|
+
* glyph, deck, welcome, and motion layers.
|
|
7
|
+
* ---------------------------------------------------------------------------
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
AppearanceMixConfig,
|
|
12
|
+
ChromeSpec,
|
|
13
|
+
ColorScheme,
|
|
14
|
+
DeckSpec,
|
|
15
|
+
GlyphSet,
|
|
16
|
+
MotionRef,
|
|
17
|
+
PresetDef,
|
|
18
|
+
ResolvedAppearance,
|
|
19
|
+
SignalSpec,
|
|
20
|
+
StructuralPresetName,
|
|
21
|
+
WelcomeSpec,
|
|
22
|
+
WishcraftTokens,
|
|
23
|
+
} from "./types.ts";
|
|
24
|
+
import type { MotionEvent } from "../motion/types.ts";
|
|
25
|
+
import { getMotion } from "../motion/catalog.ts";
|
|
26
|
+
import { colorSchemeFromTokens, presetColorScheme, resolveTokens } from "./tokens.ts";
|
|
27
|
+
import {
|
|
28
|
+
STRUCTURAL_PRESETS,
|
|
29
|
+
getStructuralPreset,
|
|
30
|
+
isStructuralPresetName,
|
|
31
|
+
} from "./structural-presets.ts";
|
|
32
|
+
|
|
33
|
+
function layerPreset(
|
|
34
|
+
config: AppearanceMixConfig,
|
|
35
|
+
key: keyof Pick<
|
|
36
|
+
AppearanceMixConfig,
|
|
37
|
+
"palette" | "signalLayout" | "chrome" | "glyphs" | "deck" | "welcome"
|
|
38
|
+
>,
|
|
39
|
+
base: StructuralPresetName,
|
|
40
|
+
): StructuralPresetName {
|
|
41
|
+
return config[key] ?? base;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function resolveMotionLayer(
|
|
45
|
+
config: AppearanceMixConfig,
|
|
46
|
+
base: StructuralPresetName,
|
|
47
|
+
): Partial<Record<MotionEvent, MotionRef>> {
|
|
48
|
+
if (!config.motion) {
|
|
49
|
+
return { ...STRUCTURAL_PRESETS[base].motion };
|
|
50
|
+
}
|
|
51
|
+
if (typeof config.motion === "string") {
|
|
52
|
+
return { ...STRUCTURAL_PRESETS[config.motion].motion };
|
|
53
|
+
}
|
|
54
|
+
return { ...STRUCTURAL_PRESETS[base].motion, ...config.motion };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Resolve a decoupled appearance mix into concrete tokens, chrome, signal,
|
|
59
|
+
* motion, deck, welcome, and glyph layers.
|
|
60
|
+
*/
|
|
61
|
+
export function resolveAppearanceMix(
|
|
62
|
+
config: AppearanceMixConfig = {},
|
|
63
|
+
): ResolvedAppearance {
|
|
64
|
+
const baseName = config.base ?? "lanternwake";
|
|
65
|
+
const base = getStructuralPreset(baseName);
|
|
66
|
+
|
|
67
|
+
const paletteName = layerPreset(config, "palette", baseName);
|
|
68
|
+
const signalName = layerPreset(config, "signalLayout", baseName);
|
|
69
|
+
const chromeName = layerPreset(config, "chrome", baseName);
|
|
70
|
+
const glyphName = layerPreset(config, "glyphs", baseName);
|
|
71
|
+
const deckName = layerPreset(config, "deck", baseName);
|
|
72
|
+
const welcomeName = layerPreset(config, "welcome", baseName);
|
|
73
|
+
|
|
74
|
+
const palette = getStructuralPreset(paletteName);
|
|
75
|
+
const signalPreset = getStructuralPreset(signalName);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
base: baseName,
|
|
79
|
+
tokens: resolveTokens(palette.tokens),
|
|
80
|
+
chrome: cloneChrome(getStructuralPreset(chromeName).chrome),
|
|
81
|
+
signal: cloneSignal(signalPreset.signal),
|
|
82
|
+
motion: resolveMotionLayer(config, baseName),
|
|
83
|
+
deck: cloneDeck(getStructuralPreset(deckName).deck),
|
|
84
|
+
welcome: cloneWelcome(getStructuralPreset(welcomeName).welcome),
|
|
85
|
+
glyphs: cloneGlyphs(getStructuralPreset(glyphName).glyphs),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** True when the user (or a structural layout name) has set any appearance layer. */
|
|
90
|
+
export function appearanceHasExplicitLayers(mix: AppearanceMixConfig): boolean {
|
|
91
|
+
return Boolean(
|
|
92
|
+
mix.base ||
|
|
93
|
+
mix.palette ||
|
|
94
|
+
mix.signalLayout ||
|
|
95
|
+
mix.chrome ||
|
|
96
|
+
mix.glyphs ||
|
|
97
|
+
mix.deck ||
|
|
98
|
+
mix.welcome ||
|
|
99
|
+
mix.motion,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Layout colors stay until appearance is in effect. If `powerline.preset` is a
|
|
105
|
+
* structural name and appearance is empty, treat that name as `base`.
|
|
106
|
+
*/
|
|
107
|
+
export function effectiveAppearanceMix(
|
|
108
|
+
appearance: AppearanceMixConfig = {},
|
|
109
|
+
layoutPreset?: string,
|
|
110
|
+
): AppearanceMixConfig {
|
|
111
|
+
if (appearanceHasExplicitLayers(appearance)) return appearance;
|
|
112
|
+
if (layoutPreset && isStructuralPresetName(layoutPreset)) {
|
|
113
|
+
return { base: layoutPreset };
|
|
114
|
+
}
|
|
115
|
+
return appearance;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Colors the live Signal should paint with. Layout preset colors win until an
|
|
120
|
+
* appearance mix is in effect; then structural tokens override segment colors.
|
|
121
|
+
*/
|
|
122
|
+
export function liveColorScheme(
|
|
123
|
+
layoutPreset: Pick<PresetDef, "colors" | "tokens">,
|
|
124
|
+
appearance: AppearanceMixConfig,
|
|
125
|
+
layoutPresetName: string | undefined,
|
|
126
|
+
defaults: () => Required<ColorScheme>,
|
|
127
|
+
): ColorScheme {
|
|
128
|
+
const mix = effectiveAppearanceMix(appearance, layoutPresetName);
|
|
129
|
+
const layoutColors = presetColorScheme(layoutPreset, defaults);
|
|
130
|
+
if (!appearanceHasExplicitLayers(mix)) return layoutColors;
|
|
131
|
+
return {
|
|
132
|
+
...layoutColors,
|
|
133
|
+
...colorSchemeFromTokens(resolveAppearanceMix(mix).tokens),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Pick the model ornament for the active glyph mode. */
|
|
138
|
+
export function resolveGlyphOrnament(
|
|
139
|
+
glyphs: GlyphSet,
|
|
140
|
+
useNerd: boolean,
|
|
141
|
+
role: "model" | "segment" = "model",
|
|
142
|
+
): string {
|
|
143
|
+
if (role === "model") {
|
|
144
|
+
if (useNerd) return glyphs.model ?? "";
|
|
145
|
+
return glyphs.modelAscii ?? glyphs.model ?? "";
|
|
146
|
+
}
|
|
147
|
+
if (useNerd) return glyphs.segment ?? "";
|
|
148
|
+
return glyphs.segmentAscii ?? glyphs.segment ?? "";
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Whether glyphs should use Nerd ornaments for this set. */
|
|
152
|
+
export function glyphsPreferNerd(glyphs: GlyphSet, nerdAvailable: boolean): boolean {
|
|
153
|
+
switch (glyphs.mode) {
|
|
154
|
+
case "nerd":
|
|
155
|
+
return true;
|
|
156
|
+
case "ascii":
|
|
157
|
+
return false;
|
|
158
|
+
case "auto":
|
|
159
|
+
return nerdAvailable;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Validate that every motion ref in a resolved appearance exists in the catalog. */
|
|
164
|
+
export function validateAppearanceMotions(
|
|
165
|
+
appearance: ResolvedAppearance,
|
|
166
|
+
): { ok: true } | { ok: false; missing: string[] } {
|
|
167
|
+
const missing: string[] = [];
|
|
168
|
+
for (const [event, ref] of Object.entries(appearance.motion) as Array<
|
|
169
|
+
[MotionEvent, MotionRef | undefined]
|
|
170
|
+
>) {
|
|
171
|
+
if (ref && !getMotion(ref)) {
|
|
172
|
+
missing.push(`${event}:${ref}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (appearance.welcome.motionId && !getMotion(appearance.welcome.motionId)) {
|
|
176
|
+
missing.push(`welcome:${appearance.welcome.motionId}`);
|
|
177
|
+
}
|
|
178
|
+
if (!getMotion(appearance.signal.animation)) {
|
|
179
|
+
missing.push(`signal:${appearance.signal.animation}`);
|
|
180
|
+
}
|
|
181
|
+
return missing.length === 0 ? { ok: true } : { ok: false, missing };
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function cloneChrome(chrome: ChromeSpec): ChromeSpec {
|
|
185
|
+
return {
|
|
186
|
+
...chrome,
|
|
187
|
+
corners: { ...chrome.corners },
|
|
188
|
+
dividers: { ...chrome.dividers },
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function cloneSignal(signal: SignalSpec): SignalSpec {
|
|
193
|
+
return {
|
|
194
|
+
...signal,
|
|
195
|
+
separators: { ...signal.separators },
|
|
196
|
+
caps: { ...signal.caps },
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function cloneDeck(deck: DeckSpec): DeckSpec {
|
|
201
|
+
return { ...deck };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function cloneWelcome(welcome: WelcomeSpec): WelcomeSpec {
|
|
205
|
+
return { ...welcome };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function cloneGlyphs(glyphs: GlyphSet): GlyphSet {
|
|
209
|
+
return { ...glyphs };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** Merge structural personality fields onto a layout preset without mutating it. */
|
|
213
|
+
export function withStructuralPersonality(
|
|
214
|
+
preset: import("./types.ts").PresetDef,
|
|
215
|
+
structural: StructuralPresetName,
|
|
216
|
+
): import("./types.ts").PresetDef {
|
|
217
|
+
const personality = getStructuralPreset(structural);
|
|
218
|
+
return {
|
|
219
|
+
...preset,
|
|
220
|
+
tokens: personality.tokens,
|
|
221
|
+
chrome: personality.chrome,
|
|
222
|
+
signal: personality.signal,
|
|
223
|
+
motion: personality.motion,
|
|
224
|
+
deck: personality.deck,
|
|
225
|
+
welcome: personality.welcome,
|
|
226
|
+
glyphs: personality.glyphs,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export type { WishcraftTokens };
|
package/src/config/parse.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
import { normalizeDisabledSegments, normalizeLayout } from "./segment-ids.ts";
|
|
18
18
|
import { normalizeSegmentOptions } from "./segment-options.ts";
|
|
19
19
|
import type {
|
|
20
|
+
AppearanceMixConfig,
|
|
20
21
|
CustomSegmentConfig,
|
|
21
22
|
CustomStatusItem,
|
|
22
23
|
PowerlinePlacement,
|
|
@@ -26,6 +27,8 @@ import type {
|
|
|
26
27
|
StatusLineSegmentOptions,
|
|
27
28
|
StatusLineSeparatorStyle,
|
|
28
29
|
} from "./types.ts";
|
|
30
|
+
import { isStructuralPresetName } from "./structural-presets.ts";
|
|
31
|
+
import { isMotionLevel, type MotionLevel } from "../motion/accessibility.ts";
|
|
29
32
|
|
|
30
33
|
export interface PowerlineConfig {
|
|
31
34
|
preset: StatusLinePreset;
|
|
@@ -51,6 +54,10 @@ export interface PowerlineConfig {
|
|
|
51
54
|
presets: Record<string, import("./types.ts").CustomPresetConfig>;
|
|
52
55
|
/** Per-segment custom text label shown before the value (e.g. tps -> "speed"). */
|
|
53
56
|
segmentLabels: Record<string, string>;
|
|
57
|
+
/** Independently mixable vNext structural appearance layers. */
|
|
58
|
+
appearance: AppearanceMixConfig;
|
|
59
|
+
/** Persisted motion sensitivity. Environment can still force off. */
|
|
60
|
+
motionLevel: MotionLevel;
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
export function parsePowerlineConfig(
|
|
@@ -76,6 +83,8 @@ export function parsePowerlineConfig(
|
|
|
76
83
|
segments: {},
|
|
77
84
|
presets: {},
|
|
78
85
|
segmentLabels: {},
|
|
86
|
+
appearance: {},
|
|
87
|
+
motionLevel: "full",
|
|
79
88
|
};
|
|
80
89
|
|
|
81
90
|
const directPreset = normalizePreset(value, presets);
|
|
@@ -139,5 +148,37 @@ export function parsePowerlineConfig(
|
|
|
139
148
|
segments: customSegments,
|
|
140
149
|
presets: customPresetDefs,
|
|
141
150
|
segmentLabels: normalizeSegmentLabels(value.segmentLabels),
|
|
151
|
+
appearance: normalizeAppearance(value.appearance),
|
|
152
|
+
motionLevel: isMotionLevel(value.motionLevel) ? value.motionLevel : "full",
|
|
142
153
|
};
|
|
143
154
|
}
|
|
155
|
+
|
|
156
|
+
function normalizeAppearance(value: unknown): AppearanceMixConfig {
|
|
157
|
+
if (!isRecord(value)) return {};
|
|
158
|
+
const result: AppearanceMixConfig = {};
|
|
159
|
+
const presetKeys = [
|
|
160
|
+
"base",
|
|
161
|
+
"palette",
|
|
162
|
+
"signalLayout",
|
|
163
|
+
"chrome",
|
|
164
|
+
"glyphs",
|
|
165
|
+
"deck",
|
|
166
|
+
"welcome",
|
|
167
|
+
] as const;
|
|
168
|
+
for (const key of presetKeys) {
|
|
169
|
+
const candidate = value[key];
|
|
170
|
+
if (typeof candidate === "string" && isStructuralPresetName(candidate)) {
|
|
171
|
+
result[key] = candidate;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (typeof value.motion === "string" && isStructuralPresetName(value.motion)) {
|
|
175
|
+
result.motion = value.motion;
|
|
176
|
+
} else if (isRecord(value.motion)) {
|
|
177
|
+
const refs: Record<string, string> = {};
|
|
178
|
+
for (const [event, ref] of Object.entries(value.motion)) {
|
|
179
|
+
if (typeof ref === "string" && ref.trim()) refs[event] = ref.trim();
|
|
180
|
+
}
|
|
181
|
+
result.motion = refs as AppearanceMixConfig["motion"];
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
}
|
package/src/config/presets.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ColorScheme, PresetDef, StatusLinePreset } from "./types.ts";
|
|
2
2
|
import { getDefaultColors } from "../theme/theme.ts";
|
|
3
3
|
import type { CustomPresetConfig } from "./types.ts";
|
|
4
|
+
import { createTokens, deriveColorSchemeFromTokens } from "../theme/tokens/mapping.ts";
|
|
4
5
|
|
|
5
6
|
// Get base colors from theme.ts (single source of truth)
|
|
6
7
|
const DEFAULT_COLORS: ColorScheme = getDefaultColors();
|
|
@@ -30,6 +31,100 @@ const CHEF_COLORS: ColorScheme = {
|
|
|
30
31
|
queue: "dim",
|
|
31
32
|
};
|
|
32
33
|
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// 10 vNext Structural Signature Presets
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
const LANTERNWAKE_TOKENS = createTokens({
|
|
39
|
+
primary: "#f59e0b",
|
|
40
|
+
accent: "#ea580c",
|
|
41
|
+
surface: "#0f172a",
|
|
42
|
+
surfaceRaised: "#1e293b",
|
|
43
|
+
motionHot: "#fbbf24",
|
|
44
|
+
motionTrail: "#78350f",
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const THREADBOUND_TOKENS = createTokens({
|
|
48
|
+
primary: "#6366f1",
|
|
49
|
+
secondary: "#818cf8",
|
|
50
|
+
accent: "#ec4899",
|
|
51
|
+
surface: "#18181b",
|
|
52
|
+
surfaceRaised: "#27272a",
|
|
53
|
+
motionHot: "#a855f7",
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const SCRYGLASS_TOKENS = createTokens({
|
|
57
|
+
primary: "#06b6d4",
|
|
58
|
+
secondary: "#38bdf8",
|
|
59
|
+
accent: "#8b5cf6",
|
|
60
|
+
surface: "#090d16",
|
|
61
|
+
surfaceRaised: "#161e2e",
|
|
62
|
+
motionHot: "#22d3ee",
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const RUNEBLOOM_TOKENS = createTokens({
|
|
66
|
+
primary: "#10b981",
|
|
67
|
+
secondary: "#34d399",
|
|
68
|
+
accent: "#eab308",
|
|
69
|
+
surface: "#0c140f",
|
|
70
|
+
surfaceRaised: "#19261e",
|
|
71
|
+
motionHot: "#facc15",
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const MOONWELL_TOKENS = createTokens({
|
|
75
|
+
primary: "#94a3b8",
|
|
76
|
+
secondary: "#cbd5e1",
|
|
77
|
+
accent: "#38bdf8",
|
|
78
|
+
surface: "#020617",
|
|
79
|
+
surfaceRaised: "#0f172a",
|
|
80
|
+
motionHot: "#e2e8f0",
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const HEXFORGE_TOKENS = createTokens({
|
|
84
|
+
primary: "#f97316",
|
|
85
|
+
secondary: "#fb923c",
|
|
86
|
+
accent: "#ef4444",
|
|
87
|
+
surface: "#1c1917",
|
|
88
|
+
surfaceRaised: "#292524",
|
|
89
|
+
motionHot: "#ffedd5",
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const VELLUM_TOKENS = createTokens({
|
|
93
|
+
primary: "#d97706",
|
|
94
|
+
secondary: "#b45309",
|
|
95
|
+
accent: "#a16207",
|
|
96
|
+
surface: "#1a1815",
|
|
97
|
+
surfaceRaised: "#292520",
|
|
98
|
+
motionHot: "#f59e0b",
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const WISP_TOKENS = createTokens({
|
|
102
|
+
primary: "#cbd5e1",
|
|
103
|
+
secondary: "#94a3b8",
|
|
104
|
+
accent: "#38bdf8",
|
|
105
|
+
surface: "#0b0f19",
|
|
106
|
+
surfaceRaised: "#111827",
|
|
107
|
+
motionHot: "#67e8f9",
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const STARWEAVE_TOKENS = createTokens({
|
|
111
|
+
primary: "#a855f7",
|
|
112
|
+
secondary: "#c084fc",
|
|
113
|
+
accent: "#38bdf8",
|
|
114
|
+
surface: "#050515",
|
|
115
|
+
surfaceRaised: "#13112c",
|
|
116
|
+
motionHot: "#f472b6",
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const CRUCIBLE_TOKENS = createTokens({
|
|
120
|
+
primary: "#ec4899",
|
|
121
|
+
secondary: "#f43f5e",
|
|
122
|
+
accent: "#fb7185",
|
|
123
|
+
surface: "#110b11",
|
|
124
|
+
surfaceRaised: "#241424",
|
|
125
|
+
motionHot: "#fda4af",
|
|
126
|
+
});
|
|
127
|
+
|
|
33
128
|
export const PRESETS: Record<StatusLinePreset, PresetDef> = {
|
|
34
129
|
// v2 preset lineup — an explicit information ladder:
|
|
35
130
|
// minimal (branch only) → compact (+ short commit) → default (full git,
|
|
@@ -276,6 +371,94 @@ export const PRESETS: Record<StatusLinePreset, PresetDef> = {
|
|
|
276
371
|
openPorts: { includeUdp: false },
|
|
277
372
|
},
|
|
278
373
|
},
|
|
374
|
+
|
|
375
|
+
// 10 vNext Structural Presets
|
|
376
|
+
lanternwake: {
|
|
377
|
+
leftSegments: ["model", "thinking", "shell_mode", "path", "git", "session", "queue"],
|
|
378
|
+
rightSegments: ["token_in", "token_out", "cost", "context_pct", "time_spent"],
|
|
379
|
+
secondarySegments: ["extension_statuses"],
|
|
380
|
+
separator: "powerline",
|
|
381
|
+
colors: deriveColorSchemeFromTokens(LANTERNWAKE_TOKENS),
|
|
382
|
+
tokens: LANTERNWAKE_TOKENS,
|
|
383
|
+
motion: {
|
|
384
|
+
streaming: "ember-relay",
|
|
385
|
+
thinking: "ember-relay",
|
|
386
|
+
"tool.start": "hex-relay",
|
|
387
|
+
success: "rune-bloom",
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
|
|
391
|
+
threadbound: {
|
|
392
|
+
leftSegments: ["model", "path", "git", "queue"],
|
|
393
|
+
rightSegments: ["tps", "cost", "context_pct"],
|
|
394
|
+
separator: "powerline-thin",
|
|
395
|
+
colors: deriveColorSchemeFromTokens(THREADBOUND_TOKENS),
|
|
396
|
+
tokens: THREADBOUND_TOKENS,
|
|
397
|
+
},
|
|
398
|
+
|
|
399
|
+
scryglass: {
|
|
400
|
+
leftSegments: ["model", "path", "git"],
|
|
401
|
+
rightSegments: ["token_total", "cost", "context_pct"],
|
|
402
|
+
separator: "chevron",
|
|
403
|
+
colors: deriveColorSchemeFromTokens(SCRYGLASS_TOKENS),
|
|
404
|
+
tokens: SCRYGLASS_TOKENS,
|
|
405
|
+
},
|
|
406
|
+
|
|
407
|
+
runebloom: {
|
|
408
|
+
leftSegments: ["model", "git", "queue"],
|
|
409
|
+
rightSegments: ["context_pct", "time_spent"],
|
|
410
|
+
separator: "dot",
|
|
411
|
+
colors: deriveColorSchemeFromTokens(RUNEBLOOM_TOKENS),
|
|
412
|
+
tokens: RUNEBLOOM_TOKENS,
|
|
413
|
+
},
|
|
414
|
+
|
|
415
|
+
moonwell: {
|
|
416
|
+
leftSegments: ["model", "thinking", "git"],
|
|
417
|
+
rightSegments: ["context_pct", "time"],
|
|
418
|
+
separator: "slash",
|
|
419
|
+
colors: deriveColorSchemeFromTokens(MOONWELL_TOKENS),
|
|
420
|
+
tokens: MOONWELL_TOKENS,
|
|
421
|
+
},
|
|
422
|
+
|
|
423
|
+
hexforge: {
|
|
424
|
+
leftSegments: ["hostname", "model", "shell_mode", "git", "queue"],
|
|
425
|
+
rightSegments: ["tps", "open_ports", "cost", "context_pct"],
|
|
426
|
+
separator: "block",
|
|
427
|
+
colors: deriveColorSchemeFromTokens(HEXFORGE_TOKENS),
|
|
428
|
+
tokens: HEXFORGE_TOKENS,
|
|
429
|
+
},
|
|
430
|
+
|
|
431
|
+
vellum: {
|
|
432
|
+
leftSegments: ["model", "path", "git"],
|
|
433
|
+
rightSegments: ["cost", "context_pct"],
|
|
434
|
+
separator: "none",
|
|
435
|
+
colors: deriveColorSchemeFromTokens(VELLUM_TOKENS),
|
|
436
|
+
tokens: VELLUM_TOKENS,
|
|
437
|
+
},
|
|
438
|
+
|
|
439
|
+
wisp: {
|
|
440
|
+
leftSegments: ["model", "git"],
|
|
441
|
+
rightSegments: ["context_pct"],
|
|
442
|
+
separator: "none",
|
|
443
|
+
colors: deriveColorSchemeFromTokens(WISP_TOKENS),
|
|
444
|
+
tokens: WISP_TOKENS,
|
|
445
|
+
},
|
|
446
|
+
|
|
447
|
+
starweave: {
|
|
448
|
+
leftSegments: ["model", "path", "git", "subagents"],
|
|
449
|
+
rightSegments: ["token_in", "token_out", "context_pct"],
|
|
450
|
+
separator: "star",
|
|
451
|
+
colors: deriveColorSchemeFromTokens(STARWEAVE_TOKENS),
|
|
452
|
+
tokens: STARWEAVE_TOKENS,
|
|
453
|
+
},
|
|
454
|
+
|
|
455
|
+
crucible: {
|
|
456
|
+
leftSegments: ["model", "thinking", "shell_mode", "git"],
|
|
457
|
+
rightSegments: ["tps", "cost", "context_pct"],
|
|
458
|
+
separator: "block",
|
|
459
|
+
colors: deriveColorSchemeFromTokens(CRUCIBLE_TOKENS),
|
|
460
|
+
tokens: CRUCIBLE_TOKENS,
|
|
461
|
+
},
|
|
279
462
|
};
|
|
280
463
|
|
|
281
464
|
export function getPreset(name: string): PresetDef {
|
|
@@ -298,6 +481,7 @@ export function registerCustomPresets(
|
|
|
298
481
|
separator: def.separator ?? "slash",
|
|
299
482
|
segmentOptions: def.segmentOptions,
|
|
300
483
|
colors: def.colors,
|
|
484
|
+
tokens: def.tokens,
|
|
301
485
|
};
|
|
302
486
|
customPresets.set(name, presetDef);
|
|
303
487
|
}
|