@duckmind/dm-darwin-x64 0.35.3 → 0.35.5
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/dm +0 -0
- package/extensions/.dm-extensions.json +1 -27
- package/package.json +1 -1
- package/extensions/dm-alps/LICENSE +0 -21
- package/extensions/dm-alps/README.md +0 -22
- package/extensions/dm-alps/index.ts +0 -172
- package/extensions/dm-alps/package.json +0 -49
- package/extensions/dm-alps/src/commands.ts +0 -208
- package/extensions/dm-alps/src/features/animations/debug.ts +0 -160
- package/extensions/dm-alps/src/features/animations/index.ts +0 -33
- package/extensions/dm-alps/src/features/animations/patch.ts +0 -112
- package/extensions/dm-alps/src/features/animations/preview.ts +0 -117
- package/extensions/dm-alps/src/features/animations/registry.ts +0 -593
- package/extensions/dm-alps/src/features/animations/runtime.ts +0 -563
- package/extensions/dm-alps/src/features/animations/settings.ts +0 -69
- package/extensions/dm-alps/src/features/bottom-input/cluster.ts +0 -2
- package/extensions/dm-alps/src/features/bottom-input/compositor.ts +0 -2
- package/extensions/dm-alps/src/features/bottom-input/editor.ts +0 -148
- package/extensions/dm-alps/src/features/bottom-input/frame.ts +0 -224
- package/extensions/dm-alps/src/features/bottom-input/icons.ts +0 -36
- package/extensions/dm-alps/src/features/bottom-input/index.ts +0 -8
- package/extensions/dm-alps/src/features/bottom-input/runtime.ts +0 -1197
- package/extensions/dm-alps/src/features/bottom-input/shortcuts.ts +0 -286
- package/extensions/dm-alps/src/features/bottom-input/status.ts +0 -663
- package/extensions/dm-alps/src/features/bottom-status/index.ts +0 -2
- package/extensions/dm-alps/src/features/chrome-frame/chrome.ts +0 -222
- package/extensions/dm-alps/src/features/chrome-frame/debug.ts +0 -212
- package/extensions/dm-alps/src/features/chrome-frame/image.ts +0 -11
- package/extensions/dm-alps/src/features/chrome-frame/index.ts +0 -4
- package/extensions/dm-alps/src/features/chrome-frame/osc.ts +0 -111
- package/extensions/dm-alps/src/features/chrome-frame/patch.ts +0 -769
- package/extensions/dm-alps/src/features/chrome-frame/preview.ts +0 -67
- package/extensions/dm-alps/src/features/chrome-frame/styles.ts +0 -105
- package/extensions/dm-alps/src/features/fixed-bottom-editor/cluster.ts +0 -161
- package/extensions/dm-alps/src/features/fixed-bottom-editor/compositor.ts +0 -1149
- package/extensions/dm-alps/src/features/fixed-bottom-editor/index.ts +0 -3
- package/extensions/dm-alps/src/features/fixed-bottom-editor/runtime.ts +0 -3
- package/extensions/dm-alps/src/settings-store.ts +0 -194
- package/extensions/dm-alps/src/settings-ui.ts +0 -653
- package/extensions/dm-alps/src/settings.ts +0 -102
- package/extensions/dm-alps/src/terminal-sanitizer.ts +0 -91
- package/extensions/dm-alps/themes/LICENSE.synthwave-84 +0 -21
- package/extensions/dm-alps/themes/alps.json +0 -93
|
@@ -1,769 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
AssistantMessageComponent,
|
|
4
|
-
BashExecutionComponent,
|
|
5
|
-
BranchSummaryMessageComponent,
|
|
6
|
-
CompactionSummaryMessageComponent,
|
|
7
|
-
CustomMessageComponent,
|
|
8
|
-
SkillInvocationMessageComponent,
|
|
9
|
-
ToolExecutionComponent,
|
|
10
|
-
UserMessageComponent,
|
|
11
|
-
} from "@mariozechner/pi-coding-agent";
|
|
12
|
-
import { truncateToWidth } from "@mariozechner/pi-tui";
|
|
13
|
-
import { isEmptyMessageChrome, renderCompactThinkingBox, renderNeonBox } from "./chrome.ts";
|
|
14
|
-
import { isChromeFrameDebugEnabled, summarizeChromeFrameCacheKey, writeChromeFrameDebugLog, type ChromeFrameDebugBranch } from "./debug.ts";
|
|
15
|
-
import { containsImageLine, isImageEscapeLine } from "./image.ts";
|
|
16
|
-
import { cloneDefaultSettings, type AlpsDmSettings } from "../../settings.ts";
|
|
17
|
-
import { sanitizeTerminalText } from "../../terminal-sanitizer.ts";
|
|
18
|
-
import { DEFAULT_CONFIG, getChromeStyle, type ChromeConfig, type ChromeKind, type ChromeStatus, type ThemeLike } from "./styles.ts";
|
|
19
|
-
|
|
20
|
-
export const PATCH_KEY = Symbol.for("alps.dm.patch.v1");
|
|
21
|
-
|
|
22
|
-
export type PatchState = {
|
|
23
|
-
enabled: boolean;
|
|
24
|
-
originals: Map<string, Function>;
|
|
25
|
-
patched: Set<string>;
|
|
26
|
-
failures: Map<string, string>;
|
|
27
|
-
conflicts: Set<string>;
|
|
28
|
-
config: ChromeConfig;
|
|
29
|
-
configVersion: number;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export type ComponentTarget = {
|
|
33
|
-
id: string;
|
|
34
|
-
kind: ChromeKind;
|
|
35
|
-
ctor: any;
|
|
36
|
-
core?: boolean;
|
|
37
|
-
getTheme: (instance?: any) => ThemeLike;
|
|
38
|
-
forceImageFallback?: boolean;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export type SafeBoxRenderOptions = {
|
|
42
|
-
getTheme: () => ThemeLike;
|
|
43
|
-
getFallback: () => string[];
|
|
44
|
-
forceImageFallback?: boolean;
|
|
45
|
-
toolName?: string;
|
|
46
|
-
status?: ChromeStatus;
|
|
47
|
-
config?: ChromeConfig;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
type RenderCacheEntry = {
|
|
51
|
-
width: number;
|
|
52
|
-
innerKey: string;
|
|
53
|
-
styleKey: string;
|
|
54
|
-
elapsedText?: string;
|
|
55
|
-
lines: string[];
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const RENDER_CACHE_KEY = Symbol.for("alps.dm.renderCache.v4");
|
|
59
|
-
const TIMING_STATE_KEY = Symbol.for("alps.dm.timingState.v1");
|
|
60
|
-
const TRACKED_SETTINGS_KEY = Symbol.for("alps.dm.trackedSettings.v1");
|
|
61
|
-
const WRAPPED_RENDER_KEY = Symbol.for("alps.dm.wrappedRender.v2");
|
|
62
|
-
const WRAPPED_RENDER_VERSION = 5;
|
|
63
|
-
const CACHE_KEY_SEPARATOR = "\x1f";
|
|
64
|
-
|
|
65
|
-
type WrappedRenderMetadata = {
|
|
66
|
-
id: string;
|
|
67
|
-
version: number;
|
|
68
|
-
originalRender: Function;
|
|
69
|
-
owner: symbol;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
type TimingState = {
|
|
73
|
-
sequence: number;
|
|
74
|
-
generation: number;
|
|
75
|
-
lastSignature: string;
|
|
76
|
-
lastUpdatedAt: number;
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
const CHROME_PATCH_OWNER = Symbol.for("alps.dm.chromeFrame.patchOwner.v1");
|
|
80
|
-
const timingRegistry = new Map<number, TimingState>();
|
|
81
|
-
let nextTimingSequence = 1;
|
|
82
|
-
let timingGeneration = 1;
|
|
83
|
-
|
|
84
|
-
function getWrappedRenderMetadata(render: unknown): WrappedRenderMetadata | undefined {
|
|
85
|
-
return typeof render === "function" ? (render as any)[WRAPPED_RENDER_KEY] as WrappedRenderMetadata | undefined : undefined;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function markWrappedRender(render: Function, metadata: WrappedRenderMetadata): void {
|
|
89
|
-
Object.defineProperty(render, WRAPPED_RENDER_KEY, {
|
|
90
|
-
value: metadata,
|
|
91
|
-
configurable: false,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function isCurrentWrappedRender(id: string, render: unknown): boolean {
|
|
96
|
-
const metadata = getWrappedRenderMetadata(render);
|
|
97
|
-
return metadata?.id === id && metadata.version === WRAPPED_RENDER_VERSION && metadata.owner === CHROME_PATCH_OWNER;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function resetTimingRegistry(): void {
|
|
101
|
-
timingRegistry.clear();
|
|
102
|
-
nextTimingSequence = 1;
|
|
103
|
-
timingGeneration += 1;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function initializeTimingState(timing?: TimingState): TimingState {
|
|
107
|
-
const next = timing ?? {
|
|
108
|
-
sequence: 0,
|
|
109
|
-
generation: timingGeneration,
|
|
110
|
-
lastSignature: "",
|
|
111
|
-
lastUpdatedAt: 0,
|
|
112
|
-
};
|
|
113
|
-
next.sequence = nextTimingSequence++;
|
|
114
|
-
next.generation = timingGeneration;
|
|
115
|
-
next.lastSignature = "";
|
|
116
|
-
next.lastUpdatedAt = 0;
|
|
117
|
-
timingRegistry.set(next.sequence, next);
|
|
118
|
-
return next;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function getTimingState(instance: any): TimingState {
|
|
122
|
-
let timing = instance?.[TIMING_STATE_KEY] as TimingState | undefined;
|
|
123
|
-
if (timing?.generation === timingGeneration) return timing;
|
|
124
|
-
if (timing) return initializeTimingState(timing);
|
|
125
|
-
timing = initializeTimingState();
|
|
126
|
-
Object.defineProperty(instance, TIMING_STATE_KEY, {
|
|
127
|
-
value: timing,
|
|
128
|
-
configurable: false,
|
|
129
|
-
});
|
|
130
|
-
return timing;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function updateTimingState(instance: any, signature: string): TimingState {
|
|
134
|
-
const timing = getTimingState(instance);
|
|
135
|
-
if (timing.lastSignature !== signature) {
|
|
136
|
-
timing.lastSignature = signature;
|
|
137
|
-
timing.lastUpdatedAt = Date.now();
|
|
138
|
-
}
|
|
139
|
-
return timing;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function formatElapsedSincePrevious(timing: TimingState): string | undefined {
|
|
143
|
-
const previous = timingRegistry.get(timing.sequence - 1);
|
|
144
|
-
if (!previous) return undefined;
|
|
145
|
-
return formatElapsedDuration(timing.lastUpdatedAt - previous.lastUpdatedAt);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export function formatElapsedDuration(ms: number): string {
|
|
149
|
-
const totalSeconds = Math.max(1, Math.ceil(Math.max(0, ms) / 1000));
|
|
150
|
-
const hours = Math.floor(totalSeconds / 3600);
|
|
151
|
-
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
152
|
-
const seconds = totalSeconds % 60;
|
|
153
|
-
if (hours > 0) return `${hours}h${String(minutes).padStart(2, "0")}m`;
|
|
154
|
-
if (minutes > 0) return `${minutes}m${String(seconds).padStart(2, "0")}s`;
|
|
155
|
-
return `${seconds}s`;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function createTrackedObject<T extends object>(value: T, onChange: () => void): T {
|
|
159
|
-
const existing = value as T & { [TRACKED_SETTINGS_KEY]?: true };
|
|
160
|
-
if (existing[TRACKED_SETTINGS_KEY]) return value;
|
|
161
|
-
return new Proxy(value, {
|
|
162
|
-
set(target, property, nextValue) {
|
|
163
|
-
if ((target as any)[property] === nextValue) return true;
|
|
164
|
-
(target as any)[property] = nextValue;
|
|
165
|
-
onChange();
|
|
166
|
-
return true;
|
|
167
|
-
},
|
|
168
|
-
get(target, property, receiver) {
|
|
169
|
-
if (property === TRACKED_SETTINGS_KEY) return true;
|
|
170
|
-
return Reflect.get(target, property, receiver);
|
|
171
|
-
},
|
|
172
|
-
}) as T;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
function normalizeSettings(settings: AlpsDmSettings | any, enabled?: boolean): AlpsDmSettings {
|
|
176
|
-
if (settings?.chromeFrame) {
|
|
177
|
-
return {
|
|
178
|
-
chromeFrame: {
|
|
179
|
-
...DEFAULT_CONFIG.settings.chromeFrame,
|
|
180
|
-
...settings.chromeFrame,
|
|
181
|
-
enabled: typeof enabled === "boolean" ? enabled : Boolean(settings.chromeFrame.enabled ?? DEFAULT_CONFIG.settings.chromeFrame.enabled),
|
|
182
|
-
},
|
|
183
|
-
fixedBottomEditor: {
|
|
184
|
-
...DEFAULT_CONFIG.settings.fixedBottomEditor,
|
|
185
|
-
...(settings.fixedBottomEditor ?? {}),
|
|
186
|
-
},
|
|
187
|
-
beautifiedInput: {
|
|
188
|
-
...DEFAULT_CONFIG.settings.beautifiedInput,
|
|
189
|
-
...(settings.beautifiedInput ?? {}),
|
|
190
|
-
},
|
|
191
|
-
animations: {
|
|
192
|
-
...DEFAULT_CONFIG.settings.animations,
|
|
193
|
-
...(settings.animations ?? {}),
|
|
194
|
-
},
|
|
195
|
-
shortcuts: {
|
|
196
|
-
...DEFAULT_CONFIG.settings.shortcuts,
|
|
197
|
-
...(settings.shortcuts ?? {}),
|
|
198
|
-
},
|
|
199
|
-
} as AlpsDmSettings;
|
|
200
|
-
}
|
|
201
|
-
return {
|
|
202
|
-
chromeFrame: {
|
|
203
|
-
enabled: typeof enabled === "boolean" ? enabled : Boolean(settings?.enabled ?? DEFAULT_CONFIG.settings.chromeFrame.enabled),
|
|
204
|
-
assistantFrame: Boolean(settings?.assistantFrame ?? DEFAULT_CONFIG.settings.chromeFrame.assistantFrame),
|
|
205
|
-
toolCompactMode: Boolean(settings?.toolCompactMode ?? DEFAULT_CONFIG.settings.chromeFrame.toolCompactMode),
|
|
206
|
-
compactEditTool: Boolean(settings?.compactEditTool ?? DEFAULT_CONFIG.settings.chromeFrame.compactEditTool),
|
|
207
|
-
},
|
|
208
|
-
fixedBottomEditor: {
|
|
209
|
-
enabled: Boolean(settings?.fixedBottomEditor?.enabled ?? DEFAULT_CONFIG.settings.fixedBottomEditor.enabled),
|
|
210
|
-
},
|
|
211
|
-
beautifiedInput: {
|
|
212
|
-
enabled: Boolean(settings?.beautifiedInput?.enabled ?? DEFAULT_CONFIG.settings.beautifiedInput.enabled),
|
|
213
|
-
},
|
|
214
|
-
animations: {
|
|
215
|
-
...DEFAULT_CONFIG.settings.animations,
|
|
216
|
-
...(settings?.animations ?? {}),
|
|
217
|
-
},
|
|
218
|
-
shortcuts: {
|
|
219
|
-
...DEFAULT_CONFIG.settings.shortcuts,
|
|
220
|
-
...(settings?.shortcuts ?? {}),
|
|
221
|
-
},
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function syncChromeFrameEnabled(state: PatchState): void {
|
|
226
|
-
state.config.settings.chromeFrame.enabled = state.enabled;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function createTrackedSettings(settings: AlpsDmSettings, onChange: () => void, enabled?: boolean): AlpsDmSettings {
|
|
230
|
-
const normalized = normalizeSettings(settings, enabled);
|
|
231
|
-
normalized.chromeFrame = createTrackedObject(normalized.chromeFrame, onChange);
|
|
232
|
-
normalized.fixedBottomEditor = createTrackedObject(normalized.fixedBottomEditor, onChange);
|
|
233
|
-
normalized.beautifiedInput = createTrackedObject(normalized.beautifiedInput, onChange);
|
|
234
|
-
normalized.animations = createTrackedObject(normalized.animations, onChange);
|
|
235
|
-
normalized.shortcuts = createTrackedObject(normalized.shortcuts, onChange);
|
|
236
|
-
return createTrackedObject(normalized, onChange);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function ensurePatchStateConfigTracking(state: PatchState): PatchState {
|
|
240
|
-
if (typeof state.configVersion !== "number") state.configVersion = 0;
|
|
241
|
-
if (!(state as any).conflicts) state.conflicts = new Set();
|
|
242
|
-
state.config.settings = createTrackedSettings(state.config.settings, () => {
|
|
243
|
-
state.configVersion += 1;
|
|
244
|
-
});
|
|
245
|
-
return state;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
function createPatchConfig(state: Pick<PatchState, "configVersion" | "enabled">): ChromeConfig {
|
|
249
|
-
return {
|
|
250
|
-
...DEFAULT_CONFIG,
|
|
251
|
-
settings: createTrackedSettings(cloneDefaultSettings(), () => {
|
|
252
|
-
state.configVersion += 1;
|
|
253
|
-
}),
|
|
254
|
-
styles: DEFAULT_CONFIG.styles,
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
export function createInitialPatchState(): PatchState {
|
|
259
|
-
resetTimingRegistry();
|
|
260
|
-
const state: PatchState = {
|
|
261
|
-
enabled: false,
|
|
262
|
-
originals: new Map(),
|
|
263
|
-
patched: new Set(),
|
|
264
|
-
failures: new Map(),
|
|
265
|
-
conflicts: new Set(),
|
|
266
|
-
config: undefined as unknown as ChromeConfig,
|
|
267
|
-
configVersion: 0,
|
|
268
|
-
};
|
|
269
|
-
state.config = createPatchConfig(state);
|
|
270
|
-
return state;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
export function getGlobalPatchState(): PatchState {
|
|
274
|
-
const existing = (globalThis as any)[PATCH_KEY] as PatchState | undefined;
|
|
275
|
-
if (existing) return ensurePatchStateConfigTracking(existing);
|
|
276
|
-
const state = createInitialPatchState();
|
|
277
|
-
(globalThis as any)[PATCH_KEY] = state;
|
|
278
|
-
return state;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
function asLines(value: unknown): string[] {
|
|
282
|
-
if (Array.isArray(value)) return value.map(String);
|
|
283
|
-
if (value === undefined || value === null) return [];
|
|
284
|
-
return [String(value)];
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
function sanitizeNarrowFallbackLines(lines: readonly string[], width: number): string[] {
|
|
288
|
-
const maxWidth = Number.isFinite(width) ? Math.max(0, Math.floor(width)) : 0;
|
|
289
|
-
if (maxWidth <= 0) return [];
|
|
290
|
-
return lines
|
|
291
|
-
.flatMap((line) => sanitizeTerminalText(line, { preserveSgr: true }).split("\n"))
|
|
292
|
-
.map((line) => truncateToWidth(line, maxWidth, "", false));
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
function getToolStatus(instance: any): ChromeStatus {
|
|
296
|
-
if (instance?.isPartial !== false) return "pending";
|
|
297
|
-
if (instance?.result?.isError) return "error";
|
|
298
|
-
return "success";
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
function getBashStatus(instance: any): ChromeStatus {
|
|
302
|
-
if (instance?.status === "error") return "error";
|
|
303
|
-
if (instance?.status === "cancelled") return "error";
|
|
304
|
-
if (instance?.status === "complete") return "success";
|
|
305
|
-
if (typeof instance?.exitCode === "number") return instance.exitCode === 0 ? "success" : "error";
|
|
306
|
-
return "pending";
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
function deriveStatus(kind: ChromeKind, instance: any): ChromeStatus | undefined {
|
|
310
|
-
if (kind === "tool") return getToolStatus(instance);
|
|
311
|
-
if (kind === "toolPending") return "pending";
|
|
312
|
-
if (kind === "toolSuccess") return "success";
|
|
313
|
-
if (kind === "toolError") return "error";
|
|
314
|
-
if (kind === "bash") return getBashStatus(instance);
|
|
315
|
-
return undefined;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
function isNonEmptyText(value: unknown): boolean {
|
|
319
|
-
return typeof value === "string" && value.trim().length > 0;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
function isThinkingOnlyAssistant(instance: any): boolean {
|
|
323
|
-
const content = instance?.lastMessage?.content;
|
|
324
|
-
if (!Array.isArray(content)) return false;
|
|
325
|
-
let hasThinking = false;
|
|
326
|
-
for (const block of content) {
|
|
327
|
-
if (block?.type === "thinking" && isNonEmptyText(block.thinking)) {
|
|
328
|
-
hasThinking = true;
|
|
329
|
-
continue;
|
|
330
|
-
}
|
|
331
|
-
if (block?.type === "text" && isNonEmptyText(block.text)) return false;
|
|
332
|
-
}
|
|
333
|
-
return hasThinking;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
function resolveRenderKind(kind: ChromeKind, instance: any): ChromeKind {
|
|
337
|
-
if (kind === "assistant" && isThinkingOnlyAssistant(instance)) return "thinking";
|
|
338
|
-
return kind;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
function deriveToolName(kind: ChromeKind, instance: any, fallback?: string): string | undefined {
|
|
342
|
-
if (kind === "tool" || kind === "toolPending" || kind === "toolSuccess" || kind === "toolError") {
|
|
343
|
-
return String(instance?.toolName ?? fallback ?? "tool");
|
|
344
|
-
}
|
|
345
|
-
return fallback;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
function stripControlMarkers(line: string): string {
|
|
349
|
-
if (!line.includes("\x1b")) return line;
|
|
350
|
-
return line.replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "").replace(/\x1b\][\s\S]*?(?:\x07|\x1b\\)/g, "");
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
function isVisibleTextLine(line: string): boolean {
|
|
354
|
-
if (isImageEscapeLine(line)) return false;
|
|
355
|
-
return stripControlMarkers(line).trim().length > 0;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
function firstVisibleTextLine(lines: readonly string[]): string | undefined {
|
|
359
|
-
for (const raw of lines) {
|
|
360
|
-
for (const line of String(raw).split("\n")) {
|
|
361
|
-
if (isVisibleTextLine(line)) return line;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
return undefined;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
function getToolResultContentLines(instance: any): string[] | undefined {
|
|
368
|
-
const content = instance?.result?.content;
|
|
369
|
-
if (!Array.isArray(content)) return undefined;
|
|
370
|
-
return content.filter((block: any) => block?.type === "text").map((block: any) => String(block.text ?? ""));
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
function normalizeToolLine(line: string): string {
|
|
374
|
-
return stripControlMarkers(line).trim();
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
const LOW_VALUE_TOOL_REST_PATTERN = /^[=::≡☰-]+$/;
|
|
378
|
-
const STATUS_ONLY_TOOL_LINE_PATTERN = /^[✓✔✗✘×✕-]+$/;
|
|
379
|
-
const STRUCTURAL_ONLY_TOOL_TEXT_PATTERN = /^[{}\[\],]+$/;
|
|
380
|
-
const FRONTMATTER_BOUNDARY_PATTERN = /^-{3,}$/;
|
|
381
|
-
const MARKDOWN_FENCE_PATTERN = /^`{3,}/;
|
|
382
|
-
const ARG_SUMMARY_VALUE_LIMIT = 48;
|
|
383
|
-
const ARG_SUMMARY_PART_LIMIT = 4;
|
|
384
|
-
|
|
385
|
-
type ToolLineMatcher = {
|
|
386
|
-
lowerToolName?: string;
|
|
387
|
-
toolNameLength: number;
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
function createToolLineMatcher(toolName?: string): ToolLineMatcher {
|
|
391
|
-
const normalized = toolName?.trim();
|
|
392
|
-
return normalized ? { lowerToolName: normalized.toLowerCase(), toolNameLength: normalized.length } : { toolNameLength: 0 };
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
function isAsciiWordChar(char: string): boolean {
|
|
396
|
-
const code = char.charCodeAt(0);
|
|
397
|
-
return code === 95 || (code >= 48 && code <= 57) || (code >= 65 && code <= 90) || (code >= 97 && code <= 122);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
function getToolLineRest(text: string, matcher: ToolLineMatcher): string | undefined {
|
|
401
|
-
if (!matcher.lowerToolName) return undefined;
|
|
402
|
-
if (text.length < matcher.toolNameLength) return undefined;
|
|
403
|
-
if (text.slice(0, matcher.toolNameLength).toLowerCase() !== matcher.lowerToolName) return undefined;
|
|
404
|
-
const rest = text.slice(matcher.toolNameLength);
|
|
405
|
-
if (!rest) return "";
|
|
406
|
-
if (isAsciiWordChar(rest[0]!)) return undefined;
|
|
407
|
-
return rest.trim();
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
function isLowValueToolRest(rest: string): boolean {
|
|
411
|
-
return rest.length === 0 || LOW_VALUE_TOOL_REST_PATTERN.test(rest);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
function isStatusOnlyToolText(text: string): boolean {
|
|
415
|
-
return STATUS_ONLY_TOOL_LINE_PATTERN.test(text);
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
function isStructuralOnlyToolText(text: string): boolean {
|
|
419
|
-
return STRUCTURAL_ONLY_TOOL_TEXT_PATTERN.test(text) || FRONTMATTER_BOUNDARY_PATTERN.test(text) || MARKDOWN_FENCE_PATTERN.test(text);
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
function isLowValueToolText(text: string, matcher?: ToolLineMatcher): boolean {
|
|
423
|
-
if (isStatusOnlyToolText(text) || isStructuralOnlyToolText(text)) return true;
|
|
424
|
-
const rest = matcher ? getToolLineRest(text, matcher) : undefined;
|
|
425
|
-
return rest !== undefined && isLowValueToolRest(rest);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
function isRenderedResourceSummaryLine(text: string): boolean {
|
|
429
|
-
return /^\[(?:skill|resource|docs)\]\s+\S/i.test(text);
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
function firstInvocationSummaryLine(lines: readonly string[], matcher: ToolLineMatcher): string | undefined {
|
|
433
|
-
for (const raw of lines) {
|
|
434
|
-
for (const line of String(raw).split("\n")) {
|
|
435
|
-
if (!isVisibleTextLine(line)) continue;
|
|
436
|
-
const text = normalizeToolLine(line);
|
|
437
|
-
if (text.startsWith("$ ") && text.slice(2).trim().length > 0) return line;
|
|
438
|
-
if (isRenderedResourceSummaryLine(text)) return line;
|
|
439
|
-
const rest = getToolLineRest(text, matcher);
|
|
440
|
-
if (rest !== undefined && !isLowValueToolRest(rest)) return line;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
return undefined;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
function firstMeaningfulToolLine(lines: readonly string[], matcher?: ToolLineMatcher): string | undefined {
|
|
447
|
-
for (const raw of lines) {
|
|
448
|
-
for (const line of String(raw).split("\n")) {
|
|
449
|
-
if (!isVisibleTextLine(line)) continue;
|
|
450
|
-
const text = normalizeToolLine(line);
|
|
451
|
-
if (isLowValueToolText(text, matcher)) continue;
|
|
452
|
-
return line;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
return undefined;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
function firstNonBoilerplateToolLine(lines: readonly string[], matcher: ToolLineMatcher): string | undefined {
|
|
459
|
-
return firstMeaningfulToolLine(lines, matcher);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
function compactArgValue(value: unknown): string | undefined {
|
|
463
|
-
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") return undefined;
|
|
464
|
-
const normalized = String(value).replace(/\s+/g, " ").trim();
|
|
465
|
-
if (!normalized) return undefined;
|
|
466
|
-
return normalized.length > ARG_SUMMARY_VALUE_LIMIT ? `${normalized.slice(0, ARG_SUMMARY_VALUE_LIMIT - 1)}…` : normalized;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
function createToolArgsSummary(toolName: string | undefined, instance: any): string | undefined {
|
|
470
|
-
if (!toolName) return undefined;
|
|
471
|
-
const args = instance?.args;
|
|
472
|
-
if (!args || typeof args !== "object" || Array.isArray(args)) return undefined;
|
|
473
|
-
const parts: string[] = [];
|
|
474
|
-
for (const [key, value] of Object.entries(args)) {
|
|
475
|
-
const compactValue = compactArgValue(value);
|
|
476
|
-
if (compactValue === undefined) continue;
|
|
477
|
-
parts.push(`${key}=${compactValue}`);
|
|
478
|
-
if (parts.length >= ARG_SUMMARY_PART_LIMIT) break;
|
|
479
|
-
}
|
|
480
|
-
return parts.length > 0 ? `${toolName} ${parts.join(" ")}` : undefined;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
export function compactToolLines(lines: readonly string[], instance?: any): string[] {
|
|
484
|
-
const toolName = instance?.toolName === undefined ? undefined : String(instance.toolName);
|
|
485
|
-
const matcher = createToolLineMatcher(toolName);
|
|
486
|
-
const invocationLine = firstInvocationSummaryLine(lines, matcher);
|
|
487
|
-
const argsSummaryLine = createToolArgsSummary(toolName, instance);
|
|
488
|
-
const resultLines = instance ? getToolResultContentLines(instance) : undefined;
|
|
489
|
-
const resultLine = resultLines ? firstMeaningfulToolLine(resultLines) : undefined;
|
|
490
|
-
const line = invocationLine ?? argsSummaryLine ?? resultLine ?? firstNonBoilerplateToolLine(lines, matcher);
|
|
491
|
-
return line ? [line] : [];
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
function shouldCompactTool(kind: ChromeKind, toolName: string | undefined, instance: any, config: ChromeConfig): boolean {
|
|
495
|
-
if (kind !== "tool") return false;
|
|
496
|
-
if (!config.settings.chromeFrame.toolCompactMode) return false;
|
|
497
|
-
if (Boolean(instance?.expanded)) return false;
|
|
498
|
-
if (toolName === "edit" && !config.settings.chromeFrame.compactEditTool) return false;
|
|
499
|
-
return true;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
function createStyleSignature(id: string, kind: ChromeKind, status: ChromeStatus | undefined, toolName: string | undefined, config: ChromeConfig, configVersion: number, expanded: boolean): string {
|
|
503
|
-
const style = getChromeStyle(kind, { toolName, status }, config);
|
|
504
|
-
return [id, kind, status ?? "", toolName ?? "", configVersion, expanded ? "expanded" : "collapsed", style.bg, style.border, style.label, style.text].join(CACHE_KEY_SEPARATOR);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
function createTimingContentKey(kind: ChromeKind, instance: any, innerLines: readonly string[]): string {
|
|
508
|
-
if (kind === "tool" && instance?.toolCallId) return `tool:${String(instance.toolCallId)}`;
|
|
509
|
-
return innerLines.join("\n");
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
function shouldUseCompactThinkingBox(kind: ChromeKind, instance: any): boolean {
|
|
513
|
-
return kind === "thinking" && instance?.hideThinkingBlock === true;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
export function createSafeBoxRender(kind: ChromeKind, inner: (innerWidth: number) => string[], options: SafeBoxRenderOptions): (width: number) => string[] {
|
|
517
|
-
return (width: number) => {
|
|
518
|
-
const innerWidth = Math.max(1, Math.floor(width) - 4);
|
|
519
|
-
const innerLines = asLines(inner(innerWidth));
|
|
520
|
-
if (isEmptyMessageChrome(kind, innerLines)) return [];
|
|
521
|
-
if (options.forceImageFallback && containsImageLine(innerLines)) {
|
|
522
|
-
return options.getFallback();
|
|
523
|
-
}
|
|
524
|
-
return renderNeonBox(kind, innerLines, width, options.getTheme(), {
|
|
525
|
-
toolName: options.toolName,
|
|
526
|
-
status: options.status,
|
|
527
|
-
config: options.config,
|
|
528
|
-
});
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
export function createWrappedRender(
|
|
533
|
-
id: string,
|
|
534
|
-
kind: ChromeKind,
|
|
535
|
-
originalRender: Function,
|
|
536
|
-
getTheme: (instance?: any) => ThemeLike,
|
|
537
|
-
extra: Record<string, unknown> = {},
|
|
538
|
-
): (this: any, width: number) => string[] {
|
|
539
|
-
const debugEnabled = isChromeFrameDebugEnabled();
|
|
540
|
-
const wrapped = function alpsChromeWrappedRender(this: any, width: number): string[] {
|
|
541
|
-
const instance = this;
|
|
542
|
-
const renderKind = resolveRenderKind(kind, instance);
|
|
543
|
-
const status = deriveStatus(renderKind, instance);
|
|
544
|
-
const toolName = deriveToolName(renderKind, instance, extra.toolName as string | undefined);
|
|
545
|
-
const numericWidth = Number.isFinite(width) ? Math.floor(width) : 0;
|
|
546
|
-
let innerWidth: number | null = null;
|
|
547
|
-
let innerLines: string[] | undefined;
|
|
548
|
-
let displayedLines: string[] | undefined;
|
|
549
|
-
let branch: ChromeFrameDebugBranch = "normal";
|
|
550
|
-
let cacheKeySummary: string | null = null;
|
|
551
|
-
const debugReturn = debugEnabled
|
|
552
|
-
? (lines: string[], nextBranch: ChromeFrameDebugBranch, error?: unknown): string[] => {
|
|
553
|
-
writeChromeFrameDebugLog({
|
|
554
|
-
targetId: id,
|
|
555
|
-
targetKind: renderKind,
|
|
556
|
-
inputWidth: numericWidth,
|
|
557
|
-
resolvedFrameWidth: numericWidth,
|
|
558
|
-
innerWidth,
|
|
559
|
-
originalLineCount: innerLines?.length ?? null,
|
|
560
|
-
displayedLineCount: displayedLines?.length ?? null,
|
|
561
|
-
boxedLineCount: lines.length,
|
|
562
|
-
branch: nextBranch,
|
|
563
|
-
cacheKeySummary,
|
|
564
|
-
hasImageLine: displayedLines ? containsImageLine(displayedLines) : false,
|
|
565
|
-
usesCompactThinking: shouldUseCompactThinkingBox(renderKind, instance),
|
|
566
|
-
error: error instanceof Error ? error.name : error ? typeof error : undefined,
|
|
567
|
-
lines,
|
|
568
|
-
});
|
|
569
|
-
return lines;
|
|
570
|
-
}
|
|
571
|
-
: undefined;
|
|
572
|
-
const fallback = () => asLines(originalRender.call(instance, width));
|
|
573
|
-
try {
|
|
574
|
-
if (numericWidth < 8) {
|
|
575
|
-
branch = "narrowFallback";
|
|
576
|
-
const rawFallback = fallback();
|
|
577
|
-
innerLines = rawFallback;
|
|
578
|
-
displayedLines = rawFallback;
|
|
579
|
-
const lines = sanitizeNarrowFallbackLines(rawFallback, numericWidth);
|
|
580
|
-
return debugReturn ? debugReturn(lines, branch) : lines;
|
|
581
|
-
}
|
|
582
|
-
innerWidth = Math.max(1, numericWidth - 4);
|
|
583
|
-
innerLines = asLines(originalRender.call(instance, innerWidth));
|
|
584
|
-
const state = getGlobalPatchState();
|
|
585
|
-
const config = state.config;
|
|
586
|
-
if (kind === "assistant" && !config.settings.chromeFrame.assistantFrame) {
|
|
587
|
-
branch = "fallback";
|
|
588
|
-
const rawFallback = fallback();
|
|
589
|
-
displayedLines = rawFallback;
|
|
590
|
-
return debugReturn ? debugReturn(rawFallback, branch) : rawFallback;
|
|
591
|
-
}
|
|
592
|
-
displayedLines = shouldCompactTool(renderKind, toolName, instance, config) ? compactToolLines(innerLines, instance) : innerLines;
|
|
593
|
-
if (isEmptyMessageChrome(renderKind, displayedLines)) {
|
|
594
|
-
branch = "empty";
|
|
595
|
-
return debugReturn ? debugReturn([], branch) : [];
|
|
596
|
-
}
|
|
597
|
-
if (Boolean(extra.forceImageFallback) && containsImageLine(displayedLines)) {
|
|
598
|
-
branch = "imageFallback";
|
|
599
|
-
const rawFallback = fallback();
|
|
600
|
-
return debugReturn ? debugReturn(rawFallback, branch) : rawFallback;
|
|
601
|
-
}
|
|
602
|
-
const innerKey = displayedLines.join("\n");
|
|
603
|
-
const styleKey = createStyleSignature(id, renderKind, status, toolName, config, state.configVersion, Boolean(instance?.expanded));
|
|
604
|
-
cacheKeySummary = debugReturn ? summarizeChromeFrameCacheKey(innerKey) : null;
|
|
605
|
-
const timingContentKey = createTimingContentKey(renderKind, instance, innerLines);
|
|
606
|
-
const timingKey = [timingContentKey, renderKind, toolName ?? "", status ?? ""].join(CACHE_KEY_SEPARATOR);
|
|
607
|
-
const timing = updateTimingState(instance, timingKey);
|
|
608
|
-
const elapsedText = formatElapsedSincePrevious(timing);
|
|
609
|
-
const cache = (instance as any)[RENDER_CACHE_KEY] as RenderCacheEntry | undefined;
|
|
610
|
-
if (cache && cache.width === numericWidth && cache.innerKey === innerKey && cache.styleKey === styleKey && cache.elapsedText === elapsedText) {
|
|
611
|
-
branch = "cacheHit";
|
|
612
|
-
return debugReturn ? debugReturn(cache.lines, branch) : cache.lines;
|
|
613
|
-
}
|
|
614
|
-
const usesCompactThinking = shouldUseCompactThinkingBox(renderKind, instance);
|
|
615
|
-
branch = usesCompactThinking ? "compactThinking" : "normal";
|
|
616
|
-
const lines = usesCompactThinking
|
|
617
|
-
? renderCompactThinkingBox(displayedLines, numericWidth, getTheme(instance), config)
|
|
618
|
-
: renderNeonBox(renderKind, displayedLines, numericWidth, getTheme(instance), {
|
|
619
|
-
toolName,
|
|
620
|
-
status,
|
|
621
|
-
config,
|
|
622
|
-
elapsedText,
|
|
623
|
-
});
|
|
624
|
-
(instance as any)[RENDER_CACHE_KEY] = { width: numericWidth, innerKey, styleKey, elapsedText, lines } satisfies RenderCacheEntry;
|
|
625
|
-
return debugReturn ? debugReturn(lines, branch) : lines;
|
|
626
|
-
} catch (error) {
|
|
627
|
-
try {
|
|
628
|
-
branch = "errorFallback";
|
|
629
|
-
const rawFallback = fallback();
|
|
630
|
-
innerLines = innerLines ?? rawFallback;
|
|
631
|
-
displayedLines = displayedLines ?? rawFallback;
|
|
632
|
-
return debugReturn ? debugReturn(rawFallback, branch, error) : rawFallback;
|
|
633
|
-
} catch (fallbackError) {
|
|
634
|
-
return debugReturn ? debugReturn([], "errorFallback", fallbackError) : [];
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
};
|
|
638
|
-
markWrappedRender(wrapped, { id, version: WRAPPED_RENDER_VERSION, originalRender, owner: CHROME_PATCH_OWNER });
|
|
639
|
-
return wrapped;
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
function validateTarget(target: ComponentTarget): string | undefined {
|
|
643
|
-
if (!target.ctor) return "component constructor missing";
|
|
644
|
-
if (!target.ctor.prototype) return "component prototype missing";
|
|
645
|
-
if (typeof target.ctor.prototype.render !== "function") return "prototype.render missing";
|
|
646
|
-
return undefined;
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
export function enablePatch(targets: readonly ComponentTarget[] = createRuntimeTargets()): PatchState {
|
|
650
|
-
const state = getGlobalPatchState();
|
|
651
|
-
state.failures.clear();
|
|
652
|
-
|
|
653
|
-
for (const target of targets) {
|
|
654
|
-
try {
|
|
655
|
-
const validation = validateTarget(target);
|
|
656
|
-
if (validation) {
|
|
657
|
-
state.failures.set(target.id, validation);
|
|
658
|
-
if (target.core) {
|
|
659
|
-
disablePatch(targets);
|
|
660
|
-
state.enabled = false;
|
|
661
|
-
syncChromeFrameEnabled(state);
|
|
662
|
-
return state;
|
|
663
|
-
}
|
|
664
|
-
continue;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
const current = target.ctor.prototype.render;
|
|
668
|
-
if (state.conflicts.has(target.id) && !isCurrentWrappedRender(target.id, current)) {
|
|
669
|
-
state.failures.set(target.id, "skip enable: prototype.render conflict from previous disable is still active");
|
|
670
|
-
if (target.core) {
|
|
671
|
-
disablePatch(targets);
|
|
672
|
-
state.enabled = false;
|
|
673
|
-
syncChromeFrameEnabled(state);
|
|
674
|
-
return state;
|
|
675
|
-
}
|
|
676
|
-
continue;
|
|
677
|
-
}
|
|
678
|
-
state.conflicts.delete(target.id);
|
|
679
|
-
const currentMetadata = getWrappedRenderMetadata(current);
|
|
680
|
-
const original = state.originals.get(target.id) ?? currentMetadata?.originalRender ?? current;
|
|
681
|
-
if (!state.originals.has(target.id)) {
|
|
682
|
-
state.originals.set(target.id, original);
|
|
683
|
-
}
|
|
684
|
-
if (state.patched.has(target.id) && isCurrentWrappedRender(target.id, current)) {
|
|
685
|
-
continue;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
target.ctor.prototype.render = createWrappedRender(
|
|
689
|
-
target.id,
|
|
690
|
-
target.kind,
|
|
691
|
-
original,
|
|
692
|
-
target.getTheme,
|
|
693
|
-
{ forceImageFallback: target.forceImageFallback },
|
|
694
|
-
);
|
|
695
|
-
state.patched.add(target.id);
|
|
696
|
-
} catch (error) {
|
|
697
|
-
state.failures.set(target.id, error instanceof Error ? error.message : String(error));
|
|
698
|
-
if (target.core) {
|
|
699
|
-
disablePatch(targets);
|
|
700
|
-
state.enabled = false;
|
|
701
|
-
syncChromeFrameEnabled(state);
|
|
702
|
-
return state;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
state.enabled = state.patched.size > 0;
|
|
708
|
-
syncChromeFrameEnabled(state);
|
|
709
|
-
return state;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
export function disablePatch(targets: readonly ComponentTarget[] = createRuntimeTargets()): PatchState {
|
|
713
|
-
resetTimingRegistry();
|
|
714
|
-
const state = getGlobalPatchState();
|
|
715
|
-
for (const target of targets) {
|
|
716
|
-
const original = state.originals.get(target.id);
|
|
717
|
-
if (original && target.ctor?.prototype) {
|
|
718
|
-
try {
|
|
719
|
-
const current = target.ctor.prototype.render;
|
|
720
|
-
if (isCurrentWrappedRender(target.id, current)) {
|
|
721
|
-
target.ctor.prototype.render = original;
|
|
722
|
-
state.originals.delete(target.id);
|
|
723
|
-
state.patched.delete(target.id);
|
|
724
|
-
state.conflicts.delete(target.id);
|
|
725
|
-
} else {
|
|
726
|
-
state.failures.set(target.id, "skip restore: prototype.render is no longer owned by dm-alps chrome-frame");
|
|
727
|
-
state.conflicts.add(target.id);
|
|
728
|
-
state.originals.delete(target.id);
|
|
729
|
-
state.patched.delete(target.id);
|
|
730
|
-
}
|
|
731
|
-
} catch (error) {
|
|
732
|
-
state.failures.set(target.id, error instanceof Error ? error.message : String(error));
|
|
733
|
-
}
|
|
734
|
-
} else {
|
|
735
|
-
state.originals.delete(target.id);
|
|
736
|
-
state.patched.delete(target.id);
|
|
737
|
-
if (!target.ctor?.prototype) state.conflicts.delete(target.id);
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
state.enabled = state.patched.size > 0;
|
|
741
|
-
syncChromeFrameEnabled(state);
|
|
742
|
-
return state;
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
export function createRuntimeTargets(themeOverride?: ThemeLike): ComponentTarget[] {
|
|
746
|
-
const getTheme = () => themeOverride ?? getRuntimeTheme();
|
|
747
|
-
return [
|
|
748
|
-
{ id: "UserMessageComponent", kind: "user", ctor: UserMessageComponent, core: true, getTheme },
|
|
749
|
-
{ id: "AssistantMessageComponent", kind: "assistant", ctor: AssistantMessageComponent, core: true, getTheme },
|
|
750
|
-
{ id: "CustomMessageComponent", kind: "custom", ctor: CustomMessageComponent, getTheme },
|
|
751
|
-
{ id: "SkillInvocationMessageComponent", kind: "skill", ctor: SkillInvocationMessageComponent, getTheme },
|
|
752
|
-
{ id: "CompactionSummaryMessageComponent", kind: "compaction", ctor: CompactionSummaryMessageComponent, getTheme },
|
|
753
|
-
{ id: "BranchSummaryMessageComponent", kind: "branch", ctor: BranchSummaryMessageComponent, getTheme },
|
|
754
|
-
{ id: "ToolExecutionComponent", kind: "tool", ctor: ToolExecutionComponent, getTheme, forceImageFallback: true },
|
|
755
|
-
{ id: "BashExecutionComponent", kind: "bash", ctor: BashExecutionComponent, getTheme },
|
|
756
|
-
];
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
export function getRuntimeTheme(): ThemeLike {
|
|
760
|
-
const key = Symbol.for("@mariozechner/pi-coding-agent:theme");
|
|
761
|
-
const fallbackKey = Symbol.for("@mariozechner/pi-coding-agent:theme");
|
|
762
|
-
const candidate = (globalThis as any)[key] ?? (globalThis as any)[fallbackKey];
|
|
763
|
-
if (candidate?.fg && candidate?.bg) return candidate as ThemeLike;
|
|
764
|
-
return {
|
|
765
|
-
fg: (_token: string, text: string) => text,
|
|
766
|
-
bg: (_token: string, text: string) => text,
|
|
767
|
-
bold: (text: string) => text,
|
|
768
|
-
};
|
|
769
|
-
}
|