@duckmind/dm-darwin-arm64 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,67 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { Key, matchesKey } from "@mariozechner/pi-tui";
|
|
3
|
-
import { renderNeonBox } from "./chrome.ts";
|
|
4
|
-
import type { ThemeLike } from "./styles.ts";
|
|
5
|
-
|
|
6
|
-
export class AlpsDmPreviewComponent {
|
|
7
|
-
private readonly theme: ThemeLike;
|
|
8
|
-
private readonly done?: () => void;
|
|
9
|
-
private closed = false;
|
|
10
|
-
|
|
11
|
-
constructor(theme: ThemeLike, done?: () => void) {
|
|
12
|
-
this.theme = theme;
|
|
13
|
-
this.done = done;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
render(width: number): string[] {
|
|
17
|
-
const samples: Array<{ kind: any; lines: string[]; options?: Record<string, unknown> }> = [
|
|
18
|
-
{ kind: "custom", lines: ["Alps DM preview — press Esc, q, Enter, or Ctrl+C to close."] },
|
|
19
|
-
{ kind: "user", lines: ["Test panel / user message"] },
|
|
20
|
-
{ kind: "assistant", lines: ["Assistant reply content with **markdown** and a long wrapping example."] },
|
|
21
|
-
{ kind: "custom", lines: ["Extended custom message"] },
|
|
22
|
-
{ kind: "skill", lines: ["skill invocation block"] },
|
|
23
|
-
{ kind: "compaction", lines: ["Compacted summary preview"] },
|
|
24
|
-
{ kind: "branch", lines: ["Branch summary preview"] },
|
|
25
|
-
{ kind: "tool", lines: ["● pending"], options: { toolName: "read", status: "pending" } },
|
|
26
|
-
{ kind: "tool", lines: ["● completed"], options: { toolName: "todo", status: "success" } },
|
|
27
|
-
{ kind: "tool", lines: ["● failed"], options: { toolName: "bash", status: "error" } },
|
|
28
|
-
{ kind: "bash", lines: ["$ npm test", "running..."], options: { status: "pending" } },
|
|
29
|
-
{ kind: "bash", lines: ["$ npm test", "all tests passed"], options: { status: "success" } },
|
|
30
|
-
{ kind: "bash", lines: ["$ npm test", "exit 1"], options: { status: "error" } },
|
|
31
|
-
{ kind: "working", lines: ["⠋ Working..."] },
|
|
32
|
-
{ kind: "assistant", lines: ["\x1b[32mANSI green text\x1b[39m and normal text"] },
|
|
33
|
-
{ kind: "assistant", lines: ["```ts", "const ok = true;", "```"] },
|
|
34
|
-
{ kind: "tool", lines: ["very long line ".repeat(20)], options: { toolName: "grep", status: "success" } },
|
|
35
|
-
];
|
|
36
|
-
const rendered: string[] = [];
|
|
37
|
-
for (const sample of samples) {
|
|
38
|
-
rendered.push(...renderNeonBox(sample.kind, sample.lines, Math.max(1, width), this.theme, sample.options as any));
|
|
39
|
-
rendered.push("");
|
|
40
|
-
}
|
|
41
|
-
return rendered.slice(0, -1);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
invalidate(): void {}
|
|
45
|
-
|
|
46
|
-
handleInput(data: string): void {
|
|
47
|
-
if (
|
|
48
|
-
matchesKey(data, Key.escape) ||
|
|
49
|
-
matchesKey(data, Key.enter) ||
|
|
50
|
-
matchesKey(data, Key.ctrl("c")) ||
|
|
51
|
-
data === "q" ||
|
|
52
|
-
data === "Q"
|
|
53
|
-
) {
|
|
54
|
-
this.close();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
private close(): void {
|
|
59
|
-
if (this.closed) return;
|
|
60
|
-
this.closed = true;
|
|
61
|
-
this.done?.();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function createPreviewComponent(theme: ThemeLike, done?: () => void): AlpsDmPreviewComponent {
|
|
66
|
-
return new AlpsDmPreviewComponent(theme, done);
|
|
67
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { DEFAULT_SETTINGS, type AlpsDmSettings } from "../../settings.ts";
|
|
3
|
-
|
|
4
|
-
export type ThemeLike = {
|
|
5
|
-
fg(token: string, text: string): string;
|
|
6
|
-
bg(token: string, text: string): string;
|
|
7
|
-
bold?(text: string): string;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export type ChromeKind =
|
|
11
|
-
| "user"
|
|
12
|
-
| "assistant"
|
|
13
|
-
| "thinking"
|
|
14
|
-
| "custom"
|
|
15
|
-
| "skill"
|
|
16
|
-
| "compaction"
|
|
17
|
-
| "branch"
|
|
18
|
-
| "tool"
|
|
19
|
-
| "toolPending"
|
|
20
|
-
| "toolSuccess"
|
|
21
|
-
| "toolError"
|
|
22
|
-
| "bash"
|
|
23
|
-
| "working";
|
|
24
|
-
|
|
25
|
-
export type ChromeStatus = "pending" | "success" | "error";
|
|
26
|
-
|
|
27
|
-
export type ChromeStyle = {
|
|
28
|
-
bg: string;
|
|
29
|
-
border: string;
|
|
30
|
-
label: string;
|
|
31
|
-
text: string;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export type LabelOptions = {
|
|
35
|
-
toolName?: string;
|
|
36
|
-
status?: ChromeStatus;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export type ChromeConfig = {
|
|
40
|
-
styles: Record<string, ChromeStyle>;
|
|
41
|
-
settings: AlpsDmSettings;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export const DEFAULT_CONFIG: ChromeConfig = {
|
|
45
|
-
settings: DEFAULT_SETTINGS,
|
|
46
|
-
styles: {
|
|
47
|
-
user: { bg: "userMessageBg", border: "borderAccent", label: "accent", text: "userMessageText" },
|
|
48
|
-
assistant: { bg: "customMessageBg", border: "borderMuted", label: "accent", text: "text" },
|
|
49
|
-
thinking: { bg: "customMessageBg", border: "borderMuted", label: "accent", text: "text" },
|
|
50
|
-
custom: { bg: "customMessageBg", border: "borderAccent", label: "customMessageLabel", text: "customMessageText" },
|
|
51
|
-
skill: { bg: "customMessageBg", border: "borderAccent", label: "customMessageLabel", text: "customMessageText" },
|
|
52
|
-
compaction: { bg: "selectedBg", border: "borderMuted", label: "muted", text: "text" },
|
|
53
|
-
branch: { bg: "selectedBg", border: "borderMuted", label: "muted", text: "text" },
|
|
54
|
-
toolPending: { bg: "toolPendingBg", border: "borderAccent", label: "toolTitle", text: "toolOutput" },
|
|
55
|
-
toolSuccess: { bg: "toolSuccessBg", border: "success", label: "toolTitle", text: "toolOutput" },
|
|
56
|
-
toolError: { bg: "toolErrorBg", border: "error", label: "toolTitle", text: "toolOutput" },
|
|
57
|
-
bash: { bg: "toolPendingBg", border: "borderAccent", label: "toolTitle", text: "toolOutput" },
|
|
58
|
-
working: { bg: "selectedBg", border: "borderAccent", label: "accent", text: "muted" },
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export function normalizeKind(kind: ChromeKind, options: LabelOptions = {}): keyof typeof DEFAULT_CONFIG.styles {
|
|
63
|
-
if (kind === "tool" || kind === "bash") {
|
|
64
|
-
if (options.status === "error") return "toolError";
|
|
65
|
-
if (options.status === "success") return "toolSuccess";
|
|
66
|
-
if (options.status === "pending") return "toolPending";
|
|
67
|
-
}
|
|
68
|
-
return kind;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function getChromeStyle(kind: ChromeKind, options: LabelOptions = {}, config: ChromeConfig = DEFAULT_CONFIG): ChromeStyle {
|
|
72
|
-
return config.styles[normalizeKind(kind, options)] ?? config.styles.assistant;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function getChromeLabel(kind: ChromeKind, options: LabelOptions = {}): string {
|
|
76
|
-
switch (kind) {
|
|
77
|
-
case "user":
|
|
78
|
-
return "USER";
|
|
79
|
-
case "assistant":
|
|
80
|
-
return "ASSISTANT";
|
|
81
|
-
case "thinking":
|
|
82
|
-
return "THINK";
|
|
83
|
-
case "custom":
|
|
84
|
-
return "CUSTOM";
|
|
85
|
-
case "skill":
|
|
86
|
-
return "SKILL";
|
|
87
|
-
case "compaction":
|
|
88
|
-
return "COMPACT";
|
|
89
|
-
case "branch":
|
|
90
|
-
return "BRANCH";
|
|
91
|
-
case "bash":
|
|
92
|
-
return "BASH";
|
|
93
|
-
case "working":
|
|
94
|
-
return "WORKING";
|
|
95
|
-
case "tool":
|
|
96
|
-
case "toolPending":
|
|
97
|
-
case "toolSuccess":
|
|
98
|
-
case "toolError": {
|
|
99
|
-
const name = options.toolName ? ` ${options.toolName}` : "";
|
|
100
|
-
const status = kind === "toolSuccess" || options.status === "success" ? " ✓" : kind === "toolError" || options.status === "error" ? " ✗" : "";
|
|
101
|
-
return `TOOL${name}${status}`;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { CURSOR_MARKER, truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
|
|
3
|
-
import { sanitizeTerminalText } from "../../terminal-sanitizer.ts";
|
|
4
|
-
|
|
5
|
-
export const FIXED_EDITOR_CURSOR_MARKER = CURSOR_MARKER;
|
|
6
|
-
|
|
7
|
-
export type FixedEditorClusterInput = {
|
|
8
|
-
statusLines?: readonly string[];
|
|
9
|
-
topLines?: readonly string[];
|
|
10
|
-
editorLines?: readonly string[];
|
|
11
|
-
secondaryLines?: readonly string[];
|
|
12
|
-
lastPromptLines?: readonly string[];
|
|
13
|
-
width: number;
|
|
14
|
-
maxHeight: number;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type FixedEditorCursor = {
|
|
18
|
-
row: number;
|
|
19
|
-
col: number;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export type FixedEditorCluster = {
|
|
23
|
-
lines: string[];
|
|
24
|
-
cursor?: FixedEditorCursor;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
type ClusterLine = {
|
|
28
|
-
line: string;
|
|
29
|
-
cursorCol?: number;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
type ClusterSections = {
|
|
33
|
-
status: ClusterLine[];
|
|
34
|
-
top: ClusterLine[];
|
|
35
|
-
editor: ClusterLine[];
|
|
36
|
-
secondary: ClusterLine[];
|
|
37
|
-
lastPrompt: ClusterLine[];
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export function renderFixedEditorCluster(input: FixedEditorClusterInput): FixedEditorCluster {
|
|
41
|
-
const width = coerceDimension(input.width);
|
|
42
|
-
const maxHeight = coerceDimension(input.maxHeight);
|
|
43
|
-
if (width <= 0 || maxHeight <= 0) {
|
|
44
|
-
return { lines: [] };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const sections = collectClusterSections(input, width);
|
|
48
|
-
if (Object.values(sections).every((lines) => lines.length === 0)) {
|
|
49
|
-
return { lines: [] };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const visibleLines = limitClusterHeight(sections, maxHeight);
|
|
53
|
-
const lines = visibleLines.map((line) => line.line);
|
|
54
|
-
const cursorRow = findCursorLineIndex(visibleLines);
|
|
55
|
-
if (cursorRow === -1) {
|
|
56
|
-
return { lines };
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return {
|
|
60
|
-
lines,
|
|
61
|
-
cursor: {
|
|
62
|
-
row: cursorRow,
|
|
63
|
-
col: visibleLines[cursorRow]!.cursorCol!,
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function coerceDimension(value: number): number {
|
|
69
|
-
return Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function collectClusterSections(input: FixedEditorClusterInput, width: number): ClusterSections {
|
|
73
|
-
return {
|
|
74
|
-
status: normalizeLines(input.statusLines, width),
|
|
75
|
-
top: normalizeLines(input.topLines, width),
|
|
76
|
-
editor: normalizeLines(input.editorLines, width),
|
|
77
|
-
secondary: normalizeLines(input.secondaryLines, width),
|
|
78
|
-
lastPrompt: normalizeLines(input.lastPromptLines, width),
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function normalizeLines(lines: readonly string[] | undefined, width: number): ClusterLine[] {
|
|
83
|
-
return lines
|
|
84
|
-
? [...lines].map((line) => extractCursorMarker(truncateVisibleLine(sanitizeClusterLine(line), width)))
|
|
85
|
-
: [];
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function sanitizeClusterLine(line: string): string {
|
|
89
|
-
const placeholder = "\uE000ALPS_CURSOR\uE000";
|
|
90
|
-
const withPlaceholder = String(line).split(FIXED_EDITOR_CURSOR_MARKER).join(placeholder);
|
|
91
|
-
return sanitizeTerminalText(withPlaceholder, { allowNewline: false, allowTab: true, preserveSgr: true }).split(placeholder).join(FIXED_EDITOR_CURSOR_MARKER);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function extractCursorMarker(line: string): ClusterLine {
|
|
95
|
-
let cleanedLine = line;
|
|
96
|
-
let cursorCol: number | undefined;
|
|
97
|
-
let markerIndex = cleanedLine.indexOf(FIXED_EDITOR_CURSOR_MARKER);
|
|
98
|
-
while (markerIndex !== -1) {
|
|
99
|
-
if (cursorCol === undefined) {
|
|
100
|
-
cursorCol = visibleWidth(cleanedLine.slice(0, markerIndex));
|
|
101
|
-
}
|
|
102
|
-
cleanedLine = cleanedLine.slice(0, markerIndex) + cleanedLine.slice(markerIndex + FIXED_EDITOR_CURSOR_MARKER.length);
|
|
103
|
-
markerIndex = cleanedLine.indexOf(FIXED_EDITOR_CURSOR_MARKER, markerIndex);
|
|
104
|
-
}
|
|
105
|
-
return cursorCol === undefined ? { line: cleanedLine } : { line: cleanedLine, cursorCol };
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function truncateVisibleLine(line: string, width: number): string {
|
|
109
|
-
return visibleWidth(line) <= width ? line : truncateToWidth(line, width, "", false);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function limitClusterHeight(sections: ClusterSections, maxHeight: number): ClusterLine[] {
|
|
113
|
-
const editor = capEditorLines(sections.editor, maxHeight);
|
|
114
|
-
let remaining = maxHeight - editor.length;
|
|
115
|
-
|
|
116
|
-
const top = takeTail(sections.top, remaining);
|
|
117
|
-
remaining -= top.length;
|
|
118
|
-
|
|
119
|
-
const secondary = takeTail(sections.secondary, remaining);
|
|
120
|
-
remaining -= secondary.length;
|
|
121
|
-
|
|
122
|
-
const lastPrompt = takeTail(sections.lastPrompt, remaining);
|
|
123
|
-
remaining -= lastPrompt.length;
|
|
124
|
-
|
|
125
|
-
const status = takeTail(sections.status, remaining);
|
|
126
|
-
|
|
127
|
-
return [
|
|
128
|
-
...status,
|
|
129
|
-
...top,
|
|
130
|
-
...editor,
|
|
131
|
-
...secondary,
|
|
132
|
-
...lastPrompt,
|
|
133
|
-
];
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function capEditorLines(lines: ClusterLine[], count: number): ClusterLine[] {
|
|
137
|
-
if (count <= 0) return [];
|
|
138
|
-
if (lines.length <= count) return lines;
|
|
139
|
-
|
|
140
|
-
const cursorIndex = findCursorLineIndex(lines);
|
|
141
|
-
if (cursorIndex !== -1) {
|
|
142
|
-
const start = Math.max(0, Math.min(cursorIndex - count + 1, lines.length - count));
|
|
143
|
-
return lines.slice(start, start + count);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return lines.slice(0, count);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function takeTail(lines: ClusterLine[], count: number): ClusterLine[] {
|
|
150
|
-
if (count <= 0) return [];
|
|
151
|
-
return lines.length <= count ? lines : lines.slice(lines.length - count);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function findCursorLineIndex(lines: readonly ClusterLine[]): number {
|
|
155
|
-
for (let index = lines.length - 1; index >= 0; index--) {
|
|
156
|
-
if (lines[index]!.cursorCol !== undefined) {
|
|
157
|
-
return index;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return -1;
|
|
161
|
-
}
|