@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
package/dm
CHANGED
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"status": "ok",
|
|
3
|
-
"prepared_at": "2026-06-
|
|
3
|
+
"prepared_at": "2026-06-06T15:41:00.991184+00:00",
|
|
4
4
|
"managed_entries": [
|
|
5
5
|
{
|
|
6
6
|
"id": "dm-context",
|
|
@@ -183,23 +183,6 @@
|
|
|
183
183
|
"src/"
|
|
184
184
|
],
|
|
185
185
|
"pinned_ref": "e5c82d549ad7665aae566cda0e9f9cda3daec998"
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
"id": "dm-alps",
|
|
189
|
-
"upstream_name": "alps-pi",
|
|
190
|
-
"source_url": "https://github.com/MrCKR/alps-pi.git",
|
|
191
|
-
"upstream_revision": "5bbb6ed6b5304ae0d2779c1667cbc6cd3a7c1359",
|
|
192
|
-
"target_dir": "extensions/dm-alps",
|
|
193
|
-
"bundle_mode": "source-package-with-runtime-deps",
|
|
194
|
-
"copied_paths": [
|
|
195
|
-
"README.md",
|
|
196
|
-
"LICENSE",
|
|
197
|
-
"package.json",
|
|
198
|
-
"index.ts",
|
|
199
|
-
"src/",
|
|
200
|
-
"themes/"
|
|
201
|
-
],
|
|
202
|
-
"pinned_ref": "5bbb6ed6b5304ae0d2779c1667cbc6cd3a7c1359"
|
|
203
186
|
}
|
|
204
187
|
],
|
|
205
188
|
"local_entries": [
|
|
@@ -345,15 +328,6 @@
|
|
|
345
328
|
"install_mode": "none",
|
|
346
329
|
"dependency_patches": []
|
|
347
330
|
},
|
|
348
|
-
{
|
|
349
|
-
"id": "dm-alps",
|
|
350
|
-
"source_dir": "extensions/dm-alps",
|
|
351
|
-
"staged_dir": "dist/extensions/dm-alps",
|
|
352
|
-
"bundle_mode": "source-package-with-runtime-deps",
|
|
353
|
-
"dependencies_installed": false,
|
|
354
|
-
"install_mode": "none",
|
|
355
|
-
"dependency_patches": []
|
|
356
|
-
},
|
|
357
331
|
{
|
|
358
332
|
"id": "dm-cua",
|
|
359
333
|
"source_dir": "extensions/dm-cua",
|
package/package.json
CHANGED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 MrCKR
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# dm-alps
|
|
2
|
-
|
|
3
|
-
`dm-alps` is the DM-bundled build of the Alps TUI extension from
|
|
4
|
-
`https://github.com/MrCKR/alps-pi.git`.
|
|
5
|
-
|
|
6
|
-
## What it adds
|
|
7
|
-
|
|
8
|
-
- `/theme` opens the DM appearance settings panel.
|
|
9
|
-
- `/theme preview` shows a compact preview of the framed message layout.
|
|
10
|
-
- The extension can frame chat/tool output, keep a fixed bottom input, beautify
|
|
11
|
-
the input border, and replace working/thinking/tool animations.
|
|
12
|
-
- The bundled `alps` theme is installed with DM and can be selected from
|
|
13
|
-
`/settings`.
|
|
14
|
-
|
|
15
|
-
## Notes for maintainers
|
|
16
|
-
|
|
17
|
-
- The source is refreshed by `scripts/sync_extensions.py` from the pinned
|
|
18
|
-
upstream commit and rebranded by `scripts/rebrand.py`.
|
|
19
|
-
- The package keeps the upstream-compatible `pi.extensions` and `pi.themes`
|
|
20
|
-
manifest keys because the runtime extension loader still reads those keys.
|
|
21
|
-
- User-facing package names, commands, settings namespace, README text, and
|
|
22
|
-
debug labels use DM naming.
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
3
|
-
import { registerAlpsDmCommand } from "./src/commands.ts";
|
|
4
|
-
import { disablePatch, enablePatch, getGlobalPatchState } from "./src/features/chrome-frame/index.ts";
|
|
5
|
-
import { cloneSettings, readPersistedSettings, writePersistedSettings } from "./src/settings-store.ts";
|
|
6
|
-
import { createBottomInputRuntime, registerBottomInputShortcuts, type BottomInputRuntime } from "./src/features/bottom-input/index.ts";
|
|
7
|
-
import { bindAnimationsSession, configureAnimations, disposeAnimations, handleAnimationsAgentEnd, handleAnimationsAgentStart, handleAnimationsMessageEnd, handleAnimationsMessageUpdate, handleAnimationsToolExecutionEnd, handleAnimationsToolExecutionStart, recordAnimationsLifecycleEvent } from "./src/features/animations/index.ts";
|
|
8
|
-
|
|
9
|
-
export type AlpsDmRuntimeDeps = {
|
|
10
|
-
bottomInputRuntime?: BottomInputRuntime;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const defaultBottomInputRuntime = createBottomInputRuntime();
|
|
14
|
-
|
|
15
|
-
export function registerAlpsDmExtension(pi: ExtensionAPI, deps: AlpsDmRuntimeDeps = {}) {
|
|
16
|
-
const bottomInputRuntime = deps.bottomInputRuntime ?? defaultBottomInputRuntime;
|
|
17
|
-
|
|
18
|
-
const state = getGlobalPatchState();
|
|
19
|
-
const persistedSettings = readPersistedSettings();
|
|
20
|
-
state.config.settings.chromeFrame.enabled = persistedSettings.chromeFrame.enabled;
|
|
21
|
-
state.config.settings.chromeFrame.assistantFrame = persistedSettings.chromeFrame.assistantFrame;
|
|
22
|
-
state.config.settings.chromeFrame.toolCompactMode = persistedSettings.chromeFrame.toolCompactMode;
|
|
23
|
-
state.config.settings.chromeFrame.compactEditTool = persistedSettings.chromeFrame.compactEditTool;
|
|
24
|
-
state.config.settings.fixedBottomEditor.enabled = persistedSettings.fixedBottomEditor.enabled;
|
|
25
|
-
state.config.settings.beautifiedInput.enabled = persistedSettings.beautifiedInput.enabled;
|
|
26
|
-
state.config.settings.animations = { ...persistedSettings.animations };
|
|
27
|
-
state.config.settings.shortcuts = { ...persistedSettings.shortcuts };
|
|
28
|
-
configureAnimations(state.config.settings.animations);
|
|
29
|
-
bottomInputRuntime.setShortcuts?.(state.config.settings.shortcuts);
|
|
30
|
-
bottomInputRuntime.setBeautifiedInputEnabled?.(state.config.settings.beautifiedInput.enabled);
|
|
31
|
-
|
|
32
|
-
if (state.config.settings.chromeFrame.enabled) {
|
|
33
|
-
enablePatch();
|
|
34
|
-
} else {
|
|
35
|
-
disablePatch();
|
|
36
|
-
}
|
|
37
|
-
registerAlpsDmCommand(pi, {
|
|
38
|
-
setFixedBottomEditorEnabled: (enabled, ctx) => {
|
|
39
|
-
const state = getGlobalPatchState();
|
|
40
|
-
state.config.settings.fixedBottomEditor.enabled = enabled;
|
|
41
|
-
bottomInputRuntime.bindSession(ctx);
|
|
42
|
-
const status = bottomInputRuntime.configure
|
|
43
|
-
? bottomInputRuntime.configure({
|
|
44
|
-
fixedEnabled: enabled,
|
|
45
|
-
beautifiedInputEnabled: state.config.settings.beautifiedInput.enabled,
|
|
46
|
-
})
|
|
47
|
-
: bottomInputRuntime.setEnabled(enabled);
|
|
48
|
-
if (!bottomInputRuntime.configure) bottomInputRuntime.setBeautifiedInputEnabled?.(state.config.settings.beautifiedInput.enabled);
|
|
49
|
-
writePersistedSettings(state.config.settings);
|
|
50
|
-
return status;
|
|
51
|
-
},
|
|
52
|
-
setBeautifiedInputEnabled: (enabled, ctx) => {
|
|
53
|
-
const state = getGlobalPatchState();
|
|
54
|
-
state.config.settings.beautifiedInput.enabled = enabled;
|
|
55
|
-
bottomInputRuntime.bindSession(ctx);
|
|
56
|
-
const status = bottomInputRuntime.configure?.({
|
|
57
|
-
fixedEnabled: state.config.settings.fixedBottomEditor.enabled,
|
|
58
|
-
beautifiedInputEnabled: enabled,
|
|
59
|
-
});
|
|
60
|
-
if (!bottomInputRuntime.configure) bottomInputRuntime.setBeautifiedInputEnabled?.(enabled);
|
|
61
|
-
writePersistedSettings(state.config.settings);
|
|
62
|
-
return status;
|
|
63
|
-
},
|
|
64
|
-
onSettingsChanged: (settings) => {
|
|
65
|
-
bottomInputRuntime.setShortcuts?.(settings.shortcuts);
|
|
66
|
-
configureAnimations(settings.animations);
|
|
67
|
-
writePersistedSettings(settings);
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
|
-
registerBottomInputShortcuts(pi, bottomInputRuntime);
|
|
71
|
-
|
|
72
|
-
pi.on("session_start", (_event: any, ctx: any) => {
|
|
73
|
-
bindAnimationsSession(ctx);
|
|
74
|
-
configureAnimations(getGlobalPatchState().config.settings.animations);
|
|
75
|
-
bottomInputRuntime.bindSession(ctx);
|
|
76
|
-
bottomInputRuntime.resetSessionStartTime();
|
|
77
|
-
bottomInputRuntime.setLastPrompt("");
|
|
78
|
-
bottomInputRuntime.setShortcuts?.(getGlobalPatchState().config.settings.shortcuts);
|
|
79
|
-
const state = getGlobalPatchState();
|
|
80
|
-
const status = bottomInputRuntime.configure
|
|
81
|
-
? bottomInputRuntime.configure({
|
|
82
|
-
fixedEnabled: state.config.settings.fixedBottomEditor.enabled,
|
|
83
|
-
beautifiedInputEnabled: state.config.settings.beautifiedInput.enabled,
|
|
84
|
-
})
|
|
85
|
-
: bottomInputRuntime.setEnabled(state.config.settings.fixedBottomEditor.enabled);
|
|
86
|
-
if (!bottomInputRuntime.configure) bottomInputRuntime.setBeautifiedInputEnabled?.(state.config.settings.beautifiedInput.enabled);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
pi.on("model_select", (_event: any, ctx: any) => {
|
|
90
|
-
bottomInputRuntime.bindSession(ctx);
|
|
91
|
-
bottomInputRuntime.requestRender();
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
pi.on("thinking_level_select", (event: any, ctx: any) => {
|
|
95
|
-
bottomInputRuntime.bindSession(ctx);
|
|
96
|
-
bottomInputRuntime.setThinkingLevel(event?.level);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
pi.on("before_agent_start", (event: any, ctx: any) => {
|
|
100
|
-
bottomInputRuntime.bindSession(ctx);
|
|
101
|
-
bottomInputRuntime.setLastPrompt(event?.prompt);
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
pi.on("agent_start", (event: any, ctx: any) => {
|
|
105
|
-
recordAnimationsLifecycleEvent("agent_start", ctx, event);
|
|
106
|
-
handleAnimationsAgentStart(event, ctx);
|
|
107
|
-
bottomInputRuntime.bindSession(ctx);
|
|
108
|
-
bottomInputRuntime.setStreaming?.(true);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
pi.on("message_update", (event: any, ctx: any) => {
|
|
112
|
-
recordAnimationsLifecycleEvent("message_update", ctx, event);
|
|
113
|
-
handleAnimationsMessageUpdate(event, ctx);
|
|
114
|
-
bottomInputRuntime.bindSession(ctx);
|
|
115
|
-
bottomInputRuntime.setLiveUsage(event?.message?.usage);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
pi.on("message_end", (event: any, ctx: any) => {
|
|
119
|
-
recordAnimationsLifecycleEvent("message_end", ctx, event);
|
|
120
|
-
handleAnimationsMessageEnd(ctx);
|
|
121
|
-
bottomInputRuntime.bindSession(ctx);
|
|
122
|
-
bottomInputRuntime.clearLiveUsage();
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
pi.on("tool_execution_start", (event: any, ctx: any) => {
|
|
126
|
-
recordAnimationsLifecycleEvent("tool_execution_start", ctx, event);
|
|
127
|
-
handleAnimationsToolExecutionStart(event, ctx);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
pi.on("tool_execution_update", (event: any, ctx: any) => {
|
|
131
|
-
recordAnimationsLifecycleEvent("tool_execution_update", ctx, event);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
pi.on("tool_execution_end", (event: any, ctx: any) => {
|
|
135
|
-
recordAnimationsLifecycleEvent("tool_execution_end", ctx, event);
|
|
136
|
-
handleAnimationsToolExecutionEnd(event, ctx);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
pi.on("agent_end", (event: any, ctx: any) => {
|
|
140
|
-
recordAnimationsLifecycleEvent("agent_end", ctx, event);
|
|
141
|
-
handleAnimationsAgentEnd(event, ctx);
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
pi.on("turn_end", (event: any, ctx: any) => {
|
|
145
|
-
recordAnimationsLifecycleEvent("turn_end", ctx, event);
|
|
146
|
-
bottomInputRuntime.bindSession(ctx);
|
|
147
|
-
bottomInputRuntime.clearLiveUsage();
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
pi.on("session_shutdown", (event: any, ctx: any) => {
|
|
151
|
-
recordAnimationsLifecycleEvent("session_shutdown", ctx, event);
|
|
152
|
-
const persisted = cloneSettings(getGlobalPatchState().config.settings);
|
|
153
|
-
try {
|
|
154
|
-
bottomInputRuntime.dispose();
|
|
155
|
-
} finally {
|
|
156
|
-
const state = getGlobalPatchState();
|
|
157
|
-
state.config.settings.chromeFrame.toolCompactMode = persisted.chromeFrame.toolCompactMode;
|
|
158
|
-
state.config.settings.chromeFrame.compactEditTool = persisted.chromeFrame.compactEditTool;
|
|
159
|
-
state.config.settings.fixedBottomEditor.enabled = persisted.fixedBottomEditor.enabled;
|
|
160
|
-
state.config.settings.beautifiedInput.enabled = persisted.beautifiedInput.enabled;
|
|
161
|
-
state.config.settings.animations = { ...persisted.animations };
|
|
162
|
-
state.config.settings.shortcuts = { ...persisted.shortcuts };
|
|
163
|
-
writePersistedSettings(state.config.settings);
|
|
164
|
-
disposeAnimations();
|
|
165
|
-
disablePatch();
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export default function alpsDm(pi: ExtensionAPI) {
|
|
171
|
-
registerAlpsDmExtension(pi);
|
|
172
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dm-alps",
|
|
3
|
-
"version": "0.1.1",
|
|
4
|
-
"description": "DM extension for Alps TUI frames, fixed input, animations, and the alps theme",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"author": null,
|
|
8
|
-
"keywords": [
|
|
9
|
-
"duckmind",
|
|
10
|
-
"dm",
|
|
11
|
-
"alps",
|
|
12
|
-
"tui",
|
|
13
|
-
"theme",
|
|
14
|
-
"animations"
|
|
15
|
-
],
|
|
16
|
-
"repository": {
|
|
17
|
-
"directory": "extensions/dm-alps",
|
|
18
|
-
"type": "git",
|
|
19
|
-
"url": "git+https://github.com/que-nguyen/dm.git"
|
|
20
|
-
},
|
|
21
|
-
"bugs": {
|
|
22
|
-
"url": "https://github.com/que-nguyen/dm/issues"
|
|
23
|
-
},
|
|
24
|
-
"homepage": "https://github.com/que-nguyen/dm/tree/main/extensions/dm-alps#readme",
|
|
25
|
-
"files": [
|
|
26
|
-
"index.ts",
|
|
27
|
-
"src",
|
|
28
|
-
"themes",
|
|
29
|
-
"README.md",
|
|
30
|
-
"LICENSE",
|
|
31
|
-
"package.json"
|
|
32
|
-
],
|
|
33
|
-
"pi": {
|
|
34
|
-
"extensions": [
|
|
35
|
-
"./index.ts"
|
|
36
|
-
],
|
|
37
|
-
"themes": [
|
|
38
|
-
"./themes"
|
|
39
|
-
]
|
|
40
|
-
},
|
|
41
|
-
"peerDependencies": {
|
|
42
|
-
"@mariozechner/pi-coding-agent": ">=0.75.5 <0.76.0",
|
|
43
|
-
"@mariozechner/pi-tui": ">=0.75.5 <0.76.0"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@mariozechner/pi-coding-agent": "^0.75.5",
|
|
47
|
-
"@mariozechner/pi-tui": "^0.75.5"
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
3
|
-
import { createPreviewComponent, disablePatch, enablePatch, getGlobalPatchState, getRuntimeTheme, type PatchState } from "./features/chrome-frame/index.ts";
|
|
4
|
-
import { createSettingsComponent } from "./settings-ui.ts";
|
|
5
|
-
import type { AlpsDmSettings, FixedBottomEditorStatus } from "./settings.ts";
|
|
6
|
-
|
|
7
|
-
export type CommandOps = {
|
|
8
|
-
enable?: () => PatchState;
|
|
9
|
-
disable?: () => PatchState;
|
|
10
|
-
setFixedBottomEditorEnabled?: (enabled: boolean, ctx: any) => FixedBottomEditorStatus | void;
|
|
11
|
-
setBeautifiedInputEnabled?: (enabled: boolean, ctx: any) => FixedBottomEditorStatus | void;
|
|
12
|
-
onSettingsChanged?: (settings: AlpsDmSettings, ctx: any) => void;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const HELP = "Usage: /theme opens the DM appearance settings panel; optional argument: preview.";
|
|
16
|
-
|
|
17
|
-
function notify(ctx: any, message: string, level: "info" | "warning" | "error" = "info") {
|
|
18
|
-
try {
|
|
19
|
-
if (ctx?.ui?.notify) {
|
|
20
|
-
ctx.ui.notify(message, level);
|
|
21
|
-
}
|
|
22
|
-
} catch {
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function readCommandUI(ctx: any): any | undefined {
|
|
27
|
-
try {
|
|
28
|
-
return ctx?.ui;
|
|
29
|
-
} catch {
|
|
30
|
-
return undefined;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function isStaleCtxError(error: unknown): boolean {
|
|
35
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
36
|
-
return message.includes("extension ctx is stale") || message.includes("stale ctx");
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function isEditorLike(component: any): boolean {
|
|
40
|
-
return Boolean(component)
|
|
41
|
-
&& typeof component.handleInput === "function"
|
|
42
|
-
&& typeof component.getText === "function"
|
|
43
|
-
&& typeof component.setText === "function";
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function findCurrentEditorInTree(root: any, seen = new Set<any>()): any | undefined {
|
|
47
|
-
if (!root || typeof root !== "object" || seen.has(root)) return undefined;
|
|
48
|
-
seen.add(root);
|
|
49
|
-
if (isEditorLike(root)) return root;
|
|
50
|
-
const children = Array.isArray(root.children) ? root.children : [];
|
|
51
|
-
for (const child of children) {
|
|
52
|
-
const editor = findCurrentEditorInTree(child, seen);
|
|
53
|
-
if (editor) return editor;
|
|
54
|
-
}
|
|
55
|
-
return undefined;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function hasVisibleOverlay(tui: any): boolean {
|
|
59
|
-
try {
|
|
60
|
-
if (typeof tui?.hasOverlay === "function") return Boolean(tui.hasOverlay());
|
|
61
|
-
const stack = Array.isArray(tui?.overlayStack) ? tui.overlayStack : [];
|
|
62
|
-
return stack.some((entry: any) => entry?.hidden !== true && entry?.visible !== false);
|
|
63
|
-
} catch {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function restoreEditorFocusAfterSettings(tui: any): void {
|
|
69
|
-
try {
|
|
70
|
-
if (!tui || hasVisibleOverlay(tui)) return;
|
|
71
|
-
const editor = findCurrentEditorInTree(tui.editorContainer) ?? findCurrentEditorInTree({ children: tui.children });
|
|
72
|
-
if (!editor || typeof tui.setFocus !== "function") return;
|
|
73
|
-
tui.setFocus(editor);
|
|
74
|
-
if (typeof tui.requestRender === "function") tui.requestRender(true);
|
|
75
|
-
} catch {
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function registerAlpsDmCommand(pi: ExtensionAPI, ops: CommandOps = {}): void {
|
|
80
|
-
pi.registerCommand("theme", {
|
|
81
|
-
description: "Open DM appearance settings",
|
|
82
|
-
handler: async (args: string, ctx: any) => {
|
|
83
|
-
const trimmedArgs = (args ?? "").trim();
|
|
84
|
-
const action = trimmedArgs === "" ? "" : trimmedArgs.split(/\s+/)[0]!;
|
|
85
|
-
const enableFn = ops.enable ?? (() => enablePatch());
|
|
86
|
-
const disableFn = ops.disable ?? (() => disablePatch());
|
|
87
|
-
const setBeautifiedInputEnabled = ops.setBeautifiedInputEnabled ?? ((enabled: boolean) => {
|
|
88
|
-
getGlobalPatchState().config.settings.beautifiedInput.enabled = enabled;
|
|
89
|
-
return undefined;
|
|
90
|
-
});
|
|
91
|
-
const onSettingsChanged = ops.onSettingsChanged ?? ((settings: AlpsDmSettings) => {
|
|
92
|
-
getGlobalPatchState().config.settings.shortcuts = { ...settings.shortcuts };
|
|
93
|
-
});
|
|
94
|
-
const setFixedEnabled = ops.setFixedBottomEditorEnabled ?? ((enabled: boolean) => {
|
|
95
|
-
const state = getGlobalPatchState();
|
|
96
|
-
state.config.settings.fixedBottomEditor.enabled = enabled;
|
|
97
|
-
const status: FixedBottomEditorStatus = { enabled: false, installed: false };
|
|
98
|
-
if (enabled) {
|
|
99
|
-
status.failure = "fixed bottom editor runtime ops not registered";
|
|
100
|
-
}
|
|
101
|
-
return status;
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
switch (action) {
|
|
105
|
-
case "": {
|
|
106
|
-
const ui = readCommandUI(ctx);
|
|
107
|
-
if (!ui?.custom) {
|
|
108
|
-
notify(ctx, "Settings require interactive UI.", "warning");
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
let active = true;
|
|
112
|
-
const runIfActive = <T>(operation: () => T): T | undefined => {
|
|
113
|
-
if (!active || readCommandUI(ctx) !== ui) return undefined;
|
|
114
|
-
try {
|
|
115
|
-
return operation();
|
|
116
|
-
} catch (error) {
|
|
117
|
-
if (!isStaleCtxError(error)) throw error;
|
|
118
|
-
active = false;
|
|
119
|
-
return undefined;
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
try {
|
|
123
|
-
const fallbackTheme = ui.theme ?? getRuntimeTheme();
|
|
124
|
-
let settingsTui: any;
|
|
125
|
-
let overlayHandle: { focus?: () => void } | undefined;
|
|
126
|
-
const refocusSettingsOverlay = () => {
|
|
127
|
-
if (!overlayHandle) return;
|
|
128
|
-
queueMicrotask(() => {
|
|
129
|
-
try {
|
|
130
|
-
overlayHandle?.focus?.();
|
|
131
|
-
} catch {
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
};
|
|
135
|
-
await ui.custom((tui: any, theme: any, _keybindings: any, done: () => void) => {
|
|
136
|
-
settingsTui = tui;
|
|
137
|
-
return createSettingsComponent(theme ?? fallbackTheme, done, {
|
|
138
|
-
getState: getGlobalPatchState,
|
|
139
|
-
disableChromeFrame: () => runIfActive(() => {
|
|
140
|
-
const result = disableFn();
|
|
141
|
-
onSettingsChanged(result.config.settings, ctx);
|
|
142
|
-
return result;
|
|
143
|
-
}) ?? getGlobalPatchState(),
|
|
144
|
-
enableChromeFrame: () => runIfActive(() => {
|
|
145
|
-
const result = enableFn();
|
|
146
|
-
onSettingsChanged(result.config.settings, ctx);
|
|
147
|
-
return result;
|
|
148
|
-
}) ?? getGlobalPatchState(),
|
|
149
|
-
setFixedBottomEditorEnabled: (enabled) => {
|
|
150
|
-
const result = runIfActive(() => setFixedEnabled(enabled, ctx));
|
|
151
|
-
refocusSettingsOverlay();
|
|
152
|
-
return result;
|
|
153
|
-
},
|
|
154
|
-
setBeautifiedInputEnabled: (enabled) => {
|
|
155
|
-
const result = runIfActive(() => setBeautifiedInputEnabled(enabled, ctx));
|
|
156
|
-
refocusSettingsOverlay();
|
|
157
|
-
return result;
|
|
158
|
-
},
|
|
159
|
-
onSettingsChanged: (settings) => {
|
|
160
|
-
runIfActive(() => onSettingsChanged(settings, ctx));
|
|
161
|
-
refocusSettingsOverlay();
|
|
162
|
-
},
|
|
163
|
-
requestRender: () => runIfActive(() => settingsTui?.requestRender?.()),
|
|
164
|
-
});
|
|
165
|
-
}, {
|
|
166
|
-
overlay: true,
|
|
167
|
-
overlayOptions: { anchor: "center", width: "90%", minWidth: 56, maxHeight: "80%", margin: 1 },
|
|
168
|
-
onHandle: (handle: { focus?: () => void }) => {
|
|
169
|
-
overlayHandle = handle;
|
|
170
|
-
},
|
|
171
|
-
});
|
|
172
|
-
restoreEditorFocusAfterSettings(settingsTui);
|
|
173
|
-
} catch (error) {
|
|
174
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
175
|
-
notify(ctx, `Settings failed: ${message}`, "error");
|
|
176
|
-
} finally {
|
|
177
|
-
active = false;
|
|
178
|
-
}
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
case "preview": {
|
|
182
|
-
const ui = readCommandUI(ctx);
|
|
183
|
-
if (!ui?.custom) {
|
|
184
|
-
notify(ctx, "Preview requires interactive UI.", "warning");
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
try {
|
|
188
|
-
const fallbackTheme = ui.theme ?? getRuntimeTheme();
|
|
189
|
-
await ui.custom(
|
|
190
|
-
(_tui: any, theme: any, _keybindings: any, done: () => void) => createPreviewComponent(theme ?? fallbackTheme, done),
|
|
191
|
-
{
|
|
192
|
-
overlay: true,
|
|
193
|
-
overlayOptions: { anchor: "center", width: "90%", maxHeight: "80%", margin: 1 },
|
|
194
|
-
},
|
|
195
|
-
);
|
|
196
|
-
} catch (error) {
|
|
197
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
198
|
-
notify(ctx, `Preview failed: ${message}`, "error");
|
|
199
|
-
}
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
default:
|
|
203
|
-
notify(ctx, HELP, "warning");
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
},
|
|
207
|
-
});
|
|
208
|
-
}
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { appendFileSync, mkdirSync } from "node:fs";
|
|
3
|
-
import { dirname, isAbsolute } from "node:path";
|
|
4
|
-
import { visibleWidth } from "@mariozechner/pi-tui";
|
|
5
|
-
import type { AnimationRuntimeState } from "./runtime.ts";
|
|
6
|
-
|
|
7
|
-
export type AnimationDebugEvent =
|
|
8
|
-
| "agent_start"
|
|
9
|
-
| "message_update"
|
|
10
|
-
| "message_end"
|
|
11
|
-
| "tool_execution_start"
|
|
12
|
-
| "tool_execution_update"
|
|
13
|
-
| "tool_execution_end"
|
|
14
|
-
| "turn_end"
|
|
15
|
-
| "agent_end"
|
|
16
|
-
| "session_shutdown"
|
|
17
|
-
| "configure"
|
|
18
|
-
| "bind_session"
|
|
19
|
-
| "pause"
|
|
20
|
-
| "resume"
|
|
21
|
-
| "timer_tick"
|
|
22
|
-
| "render_fail"
|
|
23
|
-
| "working_render"
|
|
24
|
-
| "working_render_skipped";
|
|
25
|
-
|
|
26
|
-
type AnimationDebugOptions = {
|
|
27
|
-
event: AnimationDebugEvent;
|
|
28
|
-
state: AnimationRuntimeState;
|
|
29
|
-
ctx?: any;
|
|
30
|
-
payload?: any;
|
|
31
|
-
error?: unknown;
|
|
32
|
-
note?: string;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const HASH_LIMIT = 8;
|
|
36
|
-
let sequence = 0;
|
|
37
|
-
|
|
38
|
-
export function isAnimationDebugEnabled(): boolean {
|
|
39
|
-
const logPath = process.env.ALPS_DM_ANIM_DEBUG_LOG?.trim();
|
|
40
|
-
return Boolean(logPath && isAbsolute(logPath));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function writeAnimationDebugLog(options: AnimationDebugOptions): void {
|
|
44
|
-
const logPath = process.env.ALPS_DM_ANIM_DEBUG_LOG?.trim();
|
|
45
|
-
if (!logPath || !isAbsolute(logPath)) return;
|
|
46
|
-
try {
|
|
47
|
-
mkdirSync(dirname(logPath), { recursive: true });
|
|
48
|
-
appendFileSync(logPath, `${JSON.stringify(buildEntry(options))}\n`, "utf8");
|
|
49
|
-
} catch {
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function buildEntry(options: AnimationDebugOptions) {
|
|
54
|
-
const ctx = options.ctx ?? options.state.currentEventCtx ?? options.state.currentCtx;
|
|
55
|
-
return {
|
|
56
|
-
event: options.event,
|
|
57
|
-
seq: ++sequence,
|
|
58
|
-
timestamp: new Date().toISOString(),
|
|
59
|
-
note: options.note,
|
|
60
|
-
animating: Boolean(options.state.animating),
|
|
61
|
-
timerActive: Boolean(options.state.timer),
|
|
62
|
-
toolCallIds: summarizeToolCallIds(options.state.toolCallIds),
|
|
63
|
-
thinkingActive: Boolean(options.state.thinkingActive),
|
|
64
|
-
workingMessageApplied: Boolean(options.state.workingMessageApplied),
|
|
65
|
-
workingIndicatorHidden: Boolean(options.state.workingIndicatorHidden),
|
|
66
|
-
lastWorkingLines: {
|
|
67
|
-
count: Math.max(0, options.state.lastWorkingLines || 0),
|
|
68
|
-
widths: Array.isArray(options.state.lastWorkingLineWidths) ? options.state.lastWorkingLineWidths.slice(0, 8) : [],
|
|
69
|
-
},
|
|
70
|
-
ctx: summarizeCtx(ctx, options.state.currentUiCtx ?? options.state.currentCtx),
|
|
71
|
-
eventCtx: summarizeCtx(ctx, options.state.currentEventCtx),
|
|
72
|
-
uiApi: summarizeUiApi((options.state.currentUiCtx ?? options.state.currentCtx)?.ui),
|
|
73
|
-
payload: summarizePayload(options.payload),
|
|
74
|
-
error: summarizeError(options.error),
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function summarizeToolCallIds(ids: Set<string> | undefined) {
|
|
79
|
-
const values = [...(ids ?? new Set<string>())].map((value) => stableHash(value)).sort();
|
|
80
|
-
return {
|
|
81
|
-
count: values.length,
|
|
82
|
-
hashes: values.slice(0, HASH_LIMIT),
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function summarizeCtx(ctx: any, currentCtx: any) {
|
|
87
|
-
if (!ctx) {
|
|
88
|
-
return {
|
|
89
|
-
present: false,
|
|
90
|
-
hash: null,
|
|
91
|
-
isCurrent: false,
|
|
92
|
-
hasUI: false,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
const idSource = typeof ctx?.id === "string" || typeof ctx?.id === "number" ? String(ctx.id) : objectTag(ctx);
|
|
96
|
-
return {
|
|
97
|
-
present: true,
|
|
98
|
-
hash: stableHash(idSource),
|
|
99
|
-
isCurrent: ctx === currentCtx,
|
|
100
|
-
hasUI: ctx?.hasUI !== false && Boolean(ctx?.ui),
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function summarizeUiApi(ui: any) {
|
|
105
|
-
return {
|
|
106
|
-
setWorkingMessage: typeof ui?.setWorkingMessage === "function",
|
|
107
|
-
setWorkingIndicator: typeof ui?.setWorkingIndicator === "function",
|
|
108
|
-
requestRender: typeof ui?.requestRender === "function",
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function summarizePayload(payload: any) {
|
|
113
|
-
const type = payload?.assistantMessageEvent?.type;
|
|
114
|
-
const toolCallId = payload?.toolCallId;
|
|
115
|
-
return {
|
|
116
|
-
assistantMessageEventType: typeof type === "string" ? type : null,
|
|
117
|
-
hasMessage: Boolean(payload?.message),
|
|
118
|
-
hasUsage: Boolean(payload?.message?.usage),
|
|
119
|
-
toolCallIdHash: toolCallId === undefined ? null : stableHash(String(toolCallId)),
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function summarizeError(error: unknown) {
|
|
124
|
-
if (!error) return null;
|
|
125
|
-
const anyError = error as any;
|
|
126
|
-
const name = error instanceof Error ? error.name : typeof error;
|
|
127
|
-
const code = typeof anyError?.code === "string" || typeof anyError?.code === "number" ? String(anyError.code) : null;
|
|
128
|
-
return { name, code, stale: isStaleCtxError(error) };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export function summarizeWorkingLineWidths(lines: readonly string[]): number[] {
|
|
132
|
-
return lines.slice(0, 8).map((line) => safeVisibleWidth(line));
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function safeVisibleWidth(line: string): number {
|
|
136
|
-
try {
|
|
137
|
-
return visibleWidth(String(line));
|
|
138
|
-
} catch {
|
|
139
|
-
return 0;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function objectTag(value: object): string {
|
|
144
|
-
const tag = Object.prototype.toString.call(value);
|
|
145
|
-
return `${tag}:${Object.keys(value as Record<string, unknown>).sort().join(",")}`;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function stableHash(value: string): string {
|
|
149
|
-
let hash = 2166136261;
|
|
150
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
151
|
-
hash ^= value.charCodeAt(index);
|
|
152
|
-
hash = Math.imul(hash, 16777619);
|
|
153
|
-
}
|
|
154
|
-
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function isStaleCtxError(error: unknown): boolean {
|
|
158
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
159
|
-
return message.includes("extension ctx is stale") || message.includes("stale ctx");
|
|
160
|
-
}
|