@duckmind/dm-darwin-x64 0.32.9 → 0.33.1
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 +14 -65
- package/extensions/dm-9router-ext/README.md +142 -0
- package/extensions/dm-9router-ext/package.json +45 -0
- package/extensions/dm-9router-ext/src/index.ts +541 -0
- package/extensions/dm-9router-ext/tsconfig.json +17 -0
- package/extensions/dm-subagents/package-lock.json +3 -3
- package/extensions/dm-tasks/node_modules/.package-lock.json +3 -3
- package/extensions/dm-tasks/node_modules/typebox/build/type/script/mapping.d.mts +2 -2
- package/extensions/dm-tasks/node_modules/typebox/build/type/script/parser.d.mts +2 -2
- package/extensions/dm-tasks/node_modules/typebox/build/type/script/parser.mjs +2 -2
- package/extensions/dm-tasks/node_modules/typebox/build/type/types/number.d.mts +1 -1
- package/extensions/dm-tasks/node_modules/typebox/build/type/types/number.mjs +1 -1
- package/extensions/dm-tasks/node_modules/typebox/build/type/types/record.d.mts +1 -1
- package/extensions/dm-tasks/node_modules/typebox/package.json +1 -1
- package/extensions/dm-tasks/package-lock.json +3 -3
- package/package.json +1 -1
- package/theme/theme-alps.json +93 -0
- package/extensions/dm-chime/README.md +0 -11
- package/extensions/dm-chime/docs/protocols.md +0 -107
- package/extensions/dm-chime/index.ts +0 -205
- package/extensions/dm-chime/package.json +0 -33
- package/extensions/dm-phone/README.md +0 -24
- package/extensions/dm-phone/index.ts +0 -12
- package/extensions/dm-phone/node_modules/.package-lock.json +0 -29
- package/extensions/dm-phone/node_modules/ws/LICENSE +0 -20
- package/extensions/dm-phone/node_modules/ws/README.md +0 -548
- package/extensions/dm-phone/node_modules/ws/browser.js +0 -8
- package/extensions/dm-phone/node_modules/ws/index.js +0 -22
- package/extensions/dm-phone/node_modules/ws/lib/buffer-util.js +0 -131
- package/extensions/dm-phone/node_modules/ws/lib/constants.js +0 -19
- package/extensions/dm-phone/node_modules/ws/lib/event-target.js +0 -292
- package/extensions/dm-phone/node_modules/ws/lib/extension.js +0 -203
- package/extensions/dm-phone/node_modules/ws/lib/limiter.js +0 -55
- package/extensions/dm-phone/node_modules/ws/lib/permessage-deflate.js +0 -528
- package/extensions/dm-phone/node_modules/ws/lib/receiver.js +0 -760
- package/extensions/dm-phone/node_modules/ws/lib/sender.js +0 -607
- package/extensions/dm-phone/node_modules/ws/lib/stream.js +0 -161
- package/extensions/dm-phone/node_modules/ws/lib/subprotocol.js +0 -62
- package/extensions/dm-phone/node_modules/ws/lib/validation.js +0 -152
- package/extensions/dm-phone/node_modules/ws/lib/websocket-server.js +0 -562
- package/extensions/dm-phone/node_modules/ws/lib/websocket.js +0 -1407
- package/extensions/dm-phone/node_modules/ws/package.json +0 -70
- package/extensions/dm-phone/node_modules/ws/wrapper.mjs +0 -21
- package/extensions/dm-phone/package-lock.json +0 -66
- package/extensions/dm-phone/package.json +0 -35
- package/extensions/dm-phone/phone-session-pool.ts +0 -8
- package/extensions/dm-phone/public/app/attachments.js +0 -233
- package/extensions/dm-phone/public/app/autocomplete-controller.js +0 -81
- package/extensions/dm-phone/public/app/autocomplete.js +0 -135
- package/extensions/dm-phone/public/app/bindings.js +0 -178
- package/extensions/dm-phone/public/app/command-catalog.js +0 -76
- package/extensions/dm-phone/public/app/commands.js +0 -376
- package/extensions/dm-phone/public/app/constants.js +0 -60
- package/extensions/dm-phone/public/app/formatters.js +0 -131
- package/extensions/dm-phone/public/app/handlers.js +0 -442
- package/extensions/dm-phone/public/app/main.js +0 -6
- package/extensions/dm-phone/public/app/markdown.js +0 -105
- package/extensions/dm-phone/public/app/messages.js +0 -418
- package/extensions/dm-phone/public/app/sheet-actions.js +0 -113
- package/extensions/dm-phone/public/app/sheet-navigation.js +0 -19
- package/extensions/dm-phone/public/app/sheets-view.js +0 -287
- package/extensions/dm-phone/public/app/state.js +0 -95
- package/extensions/dm-phone/public/app/tool-rendering.js +0 -562
- package/extensions/dm-phone/public/app/transport.js +0 -176
- package/extensions/dm-phone/public/app/ui.js +0 -417
- package/extensions/dm-phone/public/app.js +0 -1
- package/extensions/dm-phone/public/icon.svg +0 -15
- package/extensions/dm-phone/public/index.html +0 -146
- package/extensions/dm-phone/public/manifest.webmanifest +0 -17
- package/extensions/dm-phone/public/styles.css +0 -1139
- package/extensions/dm-phone/public/sw.js +0 -78
- package/extensions/dm-phone/src/extension/duckmind-models.js +0 -264
- package/extensions/dm-phone/src/extension/phone-args.ts +0 -121
- package/extensions/dm-phone/src/extension/phone-paths.ts +0 -250
- package/extensions/dm-phone/src/extension/phone-quota.ts +0 -188
- package/extensions/dm-phone/src/extension/phone-runtime.ts +0 -154
- package/extensions/dm-phone/src/extension/phone-server-runtime.ts +0 -1217
- package/extensions/dm-phone/src/extension/phone-sessions.ts +0 -139
- package/extensions/dm-phone/src/extension/phone-static.ts +0 -30
- package/extensions/dm-phone/src/extension/phone-tailscale.ts +0 -148
- package/extensions/dm-phone/src/extension/phone-theme.ts +0 -85
- package/extensions/dm-phone/src/extension/register-phone-child-extension.ts +0 -112
- package/extensions/dm-phone/src/extension/register-phone-extension.ts +0 -106
- package/extensions/dm-phone/src/extension/types.ts +0 -73
- package/extensions/dm-phone/src/session-pool/parent-session-worker.ts +0 -882
- package/extensions/dm-phone/src/session-pool/session-pool.ts +0 -470
- package/extensions/dm-phone/src/session-pool/session-worker.ts +0 -739
- package/extensions/dm-phone/src/session-pool/types.ts +0 -111
- package/extensions/dm-phone/src/session-pool/utils.ts +0 -23
- package/extensions/dm-phone/test/duckmind-models.test.js +0 -147
- package/extensions/dm-thinking-timer/LICENSE +0 -21
- package/extensions/dm-thinking-timer/README.md +0 -7
- package/extensions/dm-thinking-timer/package.json +0 -20
- package/extensions/dm-thinking-timer/thinking-timer.ts +0 -250
|
@@ -1256,9 +1256,9 @@
|
|
|
1256
1256
|
"optional": true
|
|
1257
1257
|
},
|
|
1258
1258
|
"node_modules/typebox": {
|
|
1259
|
-
"version": "1.2.
|
|
1260
|
-
"resolved": "https://registry.npmjs.org/typebox/-/typebox-1.2.
|
|
1261
|
-
"integrity": "sha512-
|
|
1259
|
+
"version": "1.2.1",
|
|
1260
|
+
"resolved": "https://registry.npmjs.org/typebox/-/typebox-1.2.1.tgz",
|
|
1261
|
+
"integrity": "sha512-0upGv6+mxJR7/Wc7yoxjc/U6SjOk2aNDNzbihYacSHh+JfOsf28IJ8ggW4/3tRlDKfbInvEDPVneEywjOWYCzw==",
|
|
1262
1262
|
"license": "MIT"
|
|
1263
1263
|
},
|
|
1264
1264
|
"node_modules/typescript": {
|
package/package.json
CHANGED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://duckmind.ai/theme-schema.json",
|
|
3
|
+
"name": "theme-alps",
|
|
4
|
+
"vars": {
|
|
5
|
+
"bg": "#000000",
|
|
6
|
+
"bgAlt": "#241b2f",
|
|
7
|
+
"fg": "#ffffff",
|
|
8
|
+
"comment": "#848bbd",
|
|
9
|
+
"string": "#ff8b39",
|
|
10
|
+
"variable": "#ff7edb",
|
|
11
|
+
"type": "#fe4450",
|
|
12
|
+
"constant": "#f97e72",
|
|
13
|
+
"keyword": "#fede5d",
|
|
14
|
+
"func": "#36f9f6",
|
|
15
|
+
"tag": "#72f1b8",
|
|
16
|
+
"tagBrkt": "#36f9f6",
|
|
17
|
+
"inherit": "#DD5500",
|
|
18
|
+
"quote": "#b6b1b1",
|
|
19
|
+
"mdLink": "#72f1b8",
|
|
20
|
+
"mdLinkUrl": "#DD5500",
|
|
21
|
+
"mdBold": "#2EE2FA",
|
|
22
|
+
"mdList": "#ff7edb",
|
|
23
|
+
"mdHeading": "#ff7edb",
|
|
24
|
+
"bgDark": "#1a1628",
|
|
25
|
+
"bgMid": "#1e1a2e",
|
|
26
|
+
"bgLight": "#2e2840",
|
|
27
|
+
"surface": "#34294f",
|
|
28
|
+
"selection": "#322d44",
|
|
29
|
+
"dimmed": "#6a6f96",
|
|
30
|
+
"warmGray": "#8a8570",
|
|
31
|
+
"gitMod": "#b893ce",
|
|
32
|
+
"gitAdd": "#09f7a0",
|
|
33
|
+
"gitDel": "#fe4450"
|
|
34
|
+
},
|
|
35
|
+
"colors": {
|
|
36
|
+
"accent": "variable",
|
|
37
|
+
"border": "surface",
|
|
38
|
+
"borderAccent": "func",
|
|
39
|
+
"borderMuted": "keyword",
|
|
40
|
+
"success": "tag",
|
|
41
|
+
"error": "type",
|
|
42
|
+
"warning": "warmGray",
|
|
43
|
+
"muted": "comment",
|
|
44
|
+
"dim": "dimmed",
|
|
45
|
+
"text": "",
|
|
46
|
+
"thinkingText": "comment",
|
|
47
|
+
"selectedBg": "selection",
|
|
48
|
+
"userMessageBg": "bgAlt",
|
|
49
|
+
"userMessageText": "",
|
|
50
|
+
"customMessageBg": "#1f1a30",
|
|
51
|
+
"customMessageText": "",
|
|
52
|
+
"customMessageLabel": "tag",
|
|
53
|
+
"toolPendingBg": "bgMid",
|
|
54
|
+
"toolSuccessBg": "#1a2e26",
|
|
55
|
+
"toolErrorBg": "#2e1a1e",
|
|
56
|
+
"toolTitle": "func",
|
|
57
|
+
"toolOutput": "comment",
|
|
58
|
+
"mdHeading": "mdHeading",
|
|
59
|
+
"mdLink": "mdLink",
|
|
60
|
+
"mdLinkUrl": "mdLinkUrl",
|
|
61
|
+
"mdCode": "string",
|
|
62
|
+
"mdCodeBlock": "fg",
|
|
63
|
+
"mdCodeBlockBorder": "surface",
|
|
64
|
+
"mdQuote": "quote",
|
|
65
|
+
"mdQuoteBorder": "comment",
|
|
66
|
+
"mdHr": "surface",
|
|
67
|
+
"mdListBullet": "mdList",
|
|
68
|
+
"toolDiffAdded": "gitAdd",
|
|
69
|
+
"toolDiffRemoved": "gitDel",
|
|
70
|
+
"toolDiffContext": "comment",
|
|
71
|
+
"syntaxComment": "comment",
|
|
72
|
+
"syntaxKeyword": "keyword",
|
|
73
|
+
"syntaxFunction": "func",
|
|
74
|
+
"syntaxVariable": "variable",
|
|
75
|
+
"syntaxString": "string",
|
|
76
|
+
"syntaxNumber": "constant",
|
|
77
|
+
"syntaxType": "type",
|
|
78
|
+
"syntaxOperator": "keyword",
|
|
79
|
+
"syntaxPunctuation": "comment",
|
|
80
|
+
"thinkingOff": "#444251",
|
|
81
|
+
"thinkingMinimal": "dimmed",
|
|
82
|
+
"thinkingLow": "#6796e6",
|
|
83
|
+
"thinkingMedium": "variable",
|
|
84
|
+
"thinkingHigh": "type",
|
|
85
|
+
"thinkingXhigh": "type",
|
|
86
|
+
"bashMode": "keyword"
|
|
87
|
+
},
|
|
88
|
+
"export": {
|
|
89
|
+
"pageBg": "#1a1628",
|
|
90
|
+
"cardBg": "#000000",
|
|
91
|
+
"infoBg": "#2e2840"
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# dm-chime
|
|
2
|
-
|
|
3
|
-
Bundled DM extension that plays terminal chimes for agent events.
|
|
4
|
-
|
|
5
|
-
## Bundled with dm
|
|
6
|
-
|
|
7
|
-
No separate install step is required. Install `dm`, then enable the bundled extension from the normal DM extension flow.
|
|
8
|
-
|
|
9
|
-
## Source
|
|
10
|
-
|
|
11
|
-
This managed bundled copy is generated by the DM rebrand pipeline from the pinned upstream source recorded in `extensions/.dm-extensions.json`.
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# Terminal Notification Protocols
|
|
2
|
-
|
|
3
|
-
A quick reference on the escape sequences and mechanisms dm-chime uses under the hood.
|
|
4
|
-
|
|
5
|
-
## BEL — The Universal Bell
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
\x07 (0x07, also \a)
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
The oldest terminal notification mechanism. Every terminal emulator supports it. Depending on configuration, it either produces an audible beep, a visual flash, or bounces the dock icon (macOS). It carries no message text — just an attention signal. dm-chime always sends BEL last regardless of which richer protocol ran before it.
|
|
12
|
-
|
|
13
|
-
## OSC 9 — iTerm2 / Ghostty / WezTerm Notification
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
\x1b]9;<message>\x07
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Originated by iTerm2. A single-field notification with both title and body combined. Now also supported natively by **Ghostty** and **WezTerm**. On supported terminals, this produces a native OS-level notification banner.
|
|
20
|
-
|
|
21
|
-
**Format breakdown:**
|
|
22
|
-
|
|
23
|
-
- `\x1b]9` — OSC command identifier 9
|
|
24
|
-
- `;<message>` — the notification text (title + body combined)
|
|
25
|
-
- `\x07` — BEL character terminates the sequence
|
|
26
|
-
|
|
27
|
-
## OSC 777 — rxvt-unicode Notify
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
\x1b]777;notify;<title>;<body>\x07
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Originated by rxvt-unicode. Structured with separate title and body fields. Supported by Warp, Kitty, and many VTE-based terminals. On terminals that support it, this produces a native OS-level notification banner with both a title and body.
|
|
34
|
-
|
|
35
|
-
**Format breakdown:**
|
|
36
|
-
|
|
37
|
-
- `\x1b]777` — OSC command identifier 777
|
|
38
|
-
- `;notify;` — the notify subtype
|
|
39
|
-
- `<title>` — notification title
|
|
40
|
-
- `<body>` — notification body text
|
|
41
|
-
- `\x07` — BEL character terminates the sequence (can also use `\x1b\\` as ST)
|
|
42
|
-
|
|
43
|
-
## OSC 99 — Kitty Notification Protocol
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
\x1b]99;i=1:d=0;<title>\x1b\\
|
|
47
|
-
\x1b]99;i=1:p=body;<body>\x1b\\
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Kitty's native notification protocol. Richer than OSC 777 — supports notification IDs (for updating/closing), key-value metadata, urgency levels, and chunked payloads for long text.
|
|
51
|
-
|
|
52
|
-
**Format breakdown:**
|
|
53
|
-
|
|
54
|
-
- `\x1b]99` — OSC command identifier 99
|
|
55
|
-
- `i=1` — notification ID (used to update or close later)
|
|
56
|
-
- `d=0` — done flag (0 = more data coming, 1 = complete)
|
|
57
|
-
- `p=body` — payload type key
|
|
58
|
-
- `\x1b\\` — ST (String Terminator) ends the sequence
|
|
59
|
-
|
|
60
|
-
The ID allows sending the title first (`d=0`) and body second, letting Kitty group them into a single notification. dm-chime sends both in quick succession.
|
|
61
|
-
|
|
62
|
-
## macOS osascript — Notification Center Banner
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
osascript -e 'display notification "body" with title "Title"'
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Not an escape sequence — a macOS command-line tool that triggers a native Notification Center banner. dm-chime **always** sends this on macOS, regardless of terminal type, to ensure a visible push-style notification. Silently fails if the calling terminal app hasn't been granted notification permissions in System Settings.
|
|
69
|
-
|
|
70
|
-
**Note:** The `osascript` notification inherits the sandbox of the parent terminal process. If the terminal app lacks notification permissions, macOS silently drops the banner with no error.
|
|
71
|
-
|
|
72
|
-
## Terminal Detection
|
|
73
|
-
|
|
74
|
-
dm-chime detects the terminal using environment variables set by each emulator. It checks unique env vars first, then falls back to `TERM_PROGRAM` (which survives through `sudo`, `tmux`, and `ssh` in many cases):
|
|
75
|
-
|
|
76
|
-
| Priority | Env Variable | Terminal |
|
|
77
|
-
| -------- | ----------------------------------------------- | ------------------ |
|
|
78
|
-
| 1 | `KITTY_WINDOW_ID` | Kitty |
|
|
79
|
-
| 1 | `WEZTERM_PANE` | WezTerm |
|
|
80
|
-
| 1 | `GHOSTTY_RESOURCES_DIR` | Ghostty |
|
|
81
|
-
| 1 | `ITERM_SESSION_ID` | iTerm2 |
|
|
82
|
-
| 2 | `TERM_PROGRAM=WarpTerminal` or `WARP_HONOR_PS1` | Warp |
|
|
83
|
-
| 2 | `TERM_PROGRAM=Apple_Terminal` | macOS Terminal.app |
|
|
84
|
-
| 2 | `TERM_PROGRAM=WezTerm` | WezTerm |
|
|
85
|
-
| 2 | `TERM_PROGRAM=ghostty` | Ghostty |
|
|
86
|
-
| 2 | `TERM_PROGRAM=iTerm.app` | iTerm2 |
|
|
87
|
-
|
|
88
|
-
When none match, it falls back to OSC 777 (widest support among modern terminals) + BEL.
|
|
89
|
-
|
|
90
|
-
## macOS Notification Troubleshooting
|
|
91
|
-
|
|
92
|
-
If you aren't seeing Notification Center banners:
|
|
93
|
-
|
|
94
|
-
1. **Check terminal permissions:** System Settings → Notifications → [Your Terminal] → Allow Notifications
|
|
95
|
-
2. **Try `/chime`:** Run the `/chime` command in DM. It reports the detected terminal.
|
|
96
|
-
3. **Test manually:** Run `osascript -e 'display notification "test" with title "test"'` in your terminal. If nothing appears, the terminal app lacks notification permission.
|
|
97
|
-
|
|
98
|
-
## Why BEL Always Fires Last
|
|
99
|
-
|
|
100
|
-
Regardless of which protocol is used, BEL is sent as the final character. This ensures that even if a terminal ignores or doesn't surface the OSC notification, the user still gets an attention signal. It's the one thing every terminal understands.
|
|
101
|
-
|
|
102
|
-
## Further Reading
|
|
103
|
-
|
|
104
|
-
- [Kitty notification protocol](https://sw.kovidgoyal.net/kitty/protocol-extensions.html#id3)
|
|
105
|
-
- [WezTerm notification handling](https://wezfurlong.org/wezterm/config/notification-handling.html)
|
|
106
|
-
- [Ghostty OSC support](https://ghostty.org/docs/support/osc)
|
|
107
|
-
- [iTerm2 proprietary escape codes](https://iterm2.com/documentation-escape codes.html)
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
2
|
-
import { execFile } from "node:child_process";
|
|
3
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { homedir } from "node:os";
|
|
5
|
-
import { join } from "node:path";
|
|
6
|
-
|
|
7
|
-
type TerminalType =
|
|
8
|
-
| "kitty"
|
|
9
|
-
| "wezterm"
|
|
10
|
-
| "ghostty"
|
|
11
|
-
| "iterm2"
|
|
12
|
-
| "macos-terminal"
|
|
13
|
-
| "warp"
|
|
14
|
-
| "unknown";
|
|
15
|
-
|
|
16
|
-
interface ChimeConfig {
|
|
17
|
-
sound?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// ── Config storage ──────────────────────────────────────────────────────────
|
|
21
|
-
|
|
22
|
-
const CONFIG_DIR = join(homedir(), ".config", "dm-chime");
|
|
23
|
-
const CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
24
|
-
|
|
25
|
-
const DEFAULT_SOUND = "Purr";
|
|
26
|
-
|
|
27
|
-
const AVAILABLE_SOUNDS = [
|
|
28
|
-
{ name: "Purr", description: "Soft and pleasant" },
|
|
29
|
-
{ name: "Glass", description: "Clear timer-like" },
|
|
30
|
-
{ name: "Hero", description: "Triumphant" },
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
const loadConfig = (): ChimeConfig => {
|
|
34
|
-
try {
|
|
35
|
-
if (existsSync(CONFIG_PATH)) {
|
|
36
|
-
const raw = readFileSync(CONFIG_PATH, "utf-8");
|
|
37
|
-
return JSON.parse(raw) as ChimeConfig;
|
|
38
|
-
}
|
|
39
|
-
} catch {
|
|
40
|
-
// ignore read/parse errors
|
|
41
|
-
}
|
|
42
|
-
return {};
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const saveConfig = (config: ChimeConfig): void => {
|
|
46
|
-
try {
|
|
47
|
-
if (!existsSync(CONFIG_DIR)) {
|
|
48
|
-
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
49
|
-
}
|
|
50
|
-
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
|
|
51
|
-
} catch {
|
|
52
|
-
// ignore write errors
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const getSound = (): string => loadConfig().sound ?? DEFAULT_SOUND;
|
|
57
|
-
|
|
58
|
-
// ── Terminal detection ──────────────────────────────────────────────────────
|
|
59
|
-
|
|
60
|
-
const normalizeTerm = (s?: string): string => (s ?? "").toLowerCase().trim();
|
|
61
|
-
|
|
62
|
-
const detectTerminal = (): TerminalType => {
|
|
63
|
-
const tp = normalizeTerm(process.env.TERM_PROGRAM);
|
|
64
|
-
|
|
65
|
-
// Primary: unique env vars set by each terminal (most reliable)
|
|
66
|
-
if (process.env.KITTY_WINDOW_ID) return "kitty";
|
|
67
|
-
if (process.env.WEZTERM_PANE) return "wezterm";
|
|
68
|
-
if (process.env.GHOSTTY_RESOURCES_DIR) return "ghostty";
|
|
69
|
-
if (process.env.ITERM_SESSION_ID) return "iterm2";
|
|
70
|
-
|
|
71
|
-
// Secondary: TERM_PROGRAM (handles sudo, ssh, tmux passthrough)
|
|
72
|
-
if (tp === "warpterminal" || process.env.WARP_HONOR_PS1) return "warp";
|
|
73
|
-
if (tp === "apple_terminal") return "macos-terminal";
|
|
74
|
-
if (tp === "wezterm") return "wezterm";
|
|
75
|
-
if (tp === "ghostty") return "ghostty";
|
|
76
|
-
if (tp === "iterm.app") return "iterm2";
|
|
77
|
-
|
|
78
|
-
return "unknown";
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// ── Terminal-native protocols ───────────────────────────────────────────────
|
|
82
|
-
|
|
83
|
-
const notifyOSC99 = (title: string, body: string): void => {
|
|
84
|
-
// Kitty native: multi-part with ID so title + body group into one notification
|
|
85
|
-
process.stdout.write(`\x1b]99;i=1:d=0;${title}\x1b\\`);
|
|
86
|
-
process.stdout.write(`\x1b]99;i=1:p=body;${body}\x1b\\`);
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const notifyOSC777 = (title: string, body: string): void => {
|
|
90
|
-
// rxvt-unicode originated; supported by Warp and many VTE terminals
|
|
91
|
-
process.stdout.write(`\x1b]777;notify;${title};${body}\x07`);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const notifyOSC9 = (message: string): void => {
|
|
95
|
-
// iTerm2 native; adopted by Ghostty and WezTerm
|
|
96
|
-
process.stdout.write(`\x1b]9;${message}\x07`);
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const notifyBEL = (): void => {
|
|
100
|
-
process.stdout.write("\x07");
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
// ── macOS desktop notification ──────────────────────────────────────────────
|
|
104
|
-
|
|
105
|
-
const isDarwin = process.platform === "darwin";
|
|
106
|
-
|
|
107
|
-
const escapeAppleScript = (s: string): string => s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
108
|
-
|
|
109
|
-
const notifyMacOS = (title: string, body: string, sound?: string): void => {
|
|
110
|
-
const soundArg = sound ? ` sound name "${escapeAppleScript(sound)}"` : "";
|
|
111
|
-
const script = `display notification "${escapeAppleScript(body)}" with title "${escapeAppleScript(title)}"${soundArg}`;
|
|
112
|
-
execFile("osascript", ["-e", script], (err) => {
|
|
113
|
-
if (err) return;
|
|
114
|
-
});
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
// ── Main chime routine ──────────────────────────────────────────────────────
|
|
118
|
-
|
|
119
|
-
const chime = (title: string, body: string): void => {
|
|
120
|
-
const sound = getSound();
|
|
121
|
-
|
|
122
|
-
// On macOS, use the host notification system so the configured system sound
|
|
123
|
-
// is actually requested. Terminal-native OSC notifications do not carry the
|
|
124
|
-
// macOS `sound name` option and can silently prevent the chime from playing.
|
|
125
|
-
if (isDarwin) {
|
|
126
|
-
notifyMacOS(title, body, sound);
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const terminal = detectTerminal();
|
|
131
|
-
|
|
132
|
-
// Prefer terminal-native notifications when supported on non-macOS hosts.
|
|
133
|
-
switch (terminal) {
|
|
134
|
-
case "kitty":
|
|
135
|
-
notifyOSC99(title, body);
|
|
136
|
-
return;
|
|
137
|
-
case "ghostty":
|
|
138
|
-
case "wezterm":
|
|
139
|
-
case "iterm2":
|
|
140
|
-
// Ghostty, WezTerm, and iTerm2 all support OSC 9 natively
|
|
141
|
-
notifyOSC9(`${title}: ${body}`);
|
|
142
|
-
return;
|
|
143
|
-
case "warp":
|
|
144
|
-
case "unknown":
|
|
145
|
-
// OSC 777 has broad support among terminals that implement notifications
|
|
146
|
-
notifyOSC777(title, body);
|
|
147
|
-
return;
|
|
148
|
-
case "macos-terminal":
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Universal fallback for non-macOS environments.
|
|
153
|
-
notifyBEL();
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
// ── Settings menu ───────────────────────────────────────────────────────────
|
|
157
|
-
|
|
158
|
-
const showSettingsMenu = async (ctx: {
|
|
159
|
-
ui: {
|
|
160
|
-
select: (title: string, options: string[]) => Promise<string | undefined>;
|
|
161
|
-
notify: (message: string, type?: "info" | "warning" | "error") => void;
|
|
162
|
-
};
|
|
163
|
-
}): Promise<void> => {
|
|
164
|
-
const currentSound = getSound();
|
|
165
|
-
|
|
166
|
-
const choice = await ctx.ui.select("Chime Settings", [
|
|
167
|
-
"Test notification",
|
|
168
|
-
`Change sound (current: ${currentSound})`,
|
|
169
|
-
"Exit",
|
|
170
|
-
]);
|
|
171
|
-
|
|
172
|
-
if (choice === "Test notification") {
|
|
173
|
-
chime("DM Chime", "Test notification");
|
|
174
|
-
ctx.ui.notify(`Chime sent with sound: ${getSound()}`, "info");
|
|
175
|
-
} else if (choice?.startsWith("Change sound")) {
|
|
176
|
-
const soundOptions = AVAILABLE_SOUNDS.map((s) => `${s.name} — ${s.description}`);
|
|
177
|
-
const selected = await ctx.ui.select("Select notification sound", soundOptions);
|
|
178
|
-
|
|
179
|
-
if (selected) {
|
|
180
|
-
const soundName = selected.split(" — ")[0];
|
|
181
|
-
if (soundName) {
|
|
182
|
-
saveConfig({ sound: soundName });
|
|
183
|
-
ctx.ui.notify(`Notification sound set to: ${soundName}`, "info");
|
|
184
|
-
// Preview the selected sound immediately
|
|
185
|
-
notifyMacOS("DM Chime", "Sound preview", soundName);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
// Exit: do nothing
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
// ── Extension entrypoint ────────────────────────────────────────────────────
|
|
193
|
-
|
|
194
|
-
export default (pi: ExtensionAPI): void => {
|
|
195
|
-
pi.on("agent_end", () => {
|
|
196
|
-
chime("DM", "Ready for input");
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
pi.registerCommand("chime", {
|
|
200
|
-
description: "Chime settings — test notification or change sound",
|
|
201
|
-
handler: async (_args, ctx) => {
|
|
202
|
-
await showSettingsMenu(ctx);
|
|
203
|
-
},
|
|
204
|
-
});
|
|
205
|
-
};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dm-chime",
|
|
3
|
-
"version": "0.0.1",
|
|
4
|
-
"description": "DM extension that plays terminal chimes for agent events",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./index.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"index.ts",
|
|
9
|
-
"README.md",
|
|
10
|
-
"docs"
|
|
11
|
-
],
|
|
12
|
-
"pi": {
|
|
13
|
-
"extensions": [
|
|
14
|
-
"./index.ts"
|
|
15
|
-
]
|
|
16
|
-
},
|
|
17
|
-
"keywords": [
|
|
18
|
-
"duckmind",
|
|
19
|
-
"dm",
|
|
20
|
-
"chime",
|
|
21
|
-
"notifications",
|
|
22
|
-
"terminal"
|
|
23
|
-
],
|
|
24
|
-
"scripts": {
|
|
25
|
-
"prepublishOnly": "tsdown --no-config --format esm --format cjs --dts --exports --clean --sourcemap --shims index.ts"
|
|
26
|
-
},
|
|
27
|
-
"peerDependencies": {
|
|
28
|
-
"@mariozechner/pi-coding-agent": "*"
|
|
29
|
-
},
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"typescript": "5.8.3"
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# dm-phone
|
|
2
|
-
|
|
3
|
-
Bundled DM extension that mirrors a live DM session to a phone-friendly web UI and can spawn parallel `dm --mode rpc` sessions on demand.
|
|
4
|
-
|
|
5
|
-
## Included commands
|
|
6
|
-
|
|
7
|
-
- `/phone-start`
|
|
8
|
-
- `/phone-stop`
|
|
9
|
-
- `/phone-status`
|
|
10
|
-
- `/phone-token`
|
|
11
|
-
|
|
12
|
-
## Runtime notes
|
|
13
|
-
|
|
14
|
-
- Default bind: `127.0.0.1:8787`
|
|
15
|
-
- Optional Tailscale Serve integration for phone access
|
|
16
|
-
- Parallel child sessions run through `dm --mode rpc`
|
|
17
|
-
- Phone model picker keeps `Free`, `Auto`, `Lite`, `Smart`, `Deep`, plus `Ultra` when Ultradex accounts are available, and also shows connected provider models
|
|
18
|
-
- Default agent paths resolve through `~/.dm/agent`
|
|
19
|
-
- Optional DM env override: `DM_CODING_AGENT_DIR`
|
|
20
|
-
- Compatibility fallbacks still accepted: `PI_CODING_AGENT_DIR`, `PI_PHONE_*`
|
|
21
|
-
|
|
22
|
-
## Bundled with dm
|
|
23
|
-
|
|
24
|
-
No separate install step is required. Install `dm`, run `/phone-start`, and open the reported URL from your phone.
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
2
|
-
import registerPhoneChildExtension from "./src/extension/register-phone-child-extension";
|
|
3
|
-
import registerPhoneExtension from "./src/extension/register-phone-extension";
|
|
4
|
-
|
|
5
|
-
export default function registerDmPhone(pi: ExtensionAPI) {
|
|
6
|
-
if (process.env.DM_PHONE_CHILD === "1" || process.env.PI_PHONE_CHILD === "1") {
|
|
7
|
-
registerPhoneChildExtension(pi);
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
registerPhoneExtension(pi);
|
|
12
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dm-phone",
|
|
3
|
-
"version": "0.0.13",
|
|
4
|
-
"lockfileVersion": 3,
|
|
5
|
-
"requires": true,
|
|
6
|
-
"packages": {
|
|
7
|
-
"node_modules/ws": {
|
|
8
|
-
"version": "8.21.0",
|
|
9
|
-
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
|
|
10
|
-
"integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
|
|
11
|
-
"license": "MIT",
|
|
12
|
-
"engines": {
|
|
13
|
-
"node": ">=10.0.0"
|
|
14
|
-
},
|
|
15
|
-
"peerDependencies": {
|
|
16
|
-
"bufferutil": "^4.0.1",
|
|
17
|
-
"utf-8-validate": ">=5.0.2"
|
|
18
|
-
},
|
|
19
|
-
"peerDependenciesMeta": {
|
|
20
|
-
"bufferutil": {
|
|
21
|
-
"optional": true
|
|
22
|
-
},
|
|
23
|
-
"utf-8-validate": {
|
|
24
|
-
"optional": true
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
|
|
2
|
-
Copyright (c) 2013 Arnout Kazemier and contributors
|
|
3
|
-
Copyright (c) 2016 Luigi Pinca and contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
-
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
-
the Software without restriction, including without limitation the rights to
|
|
8
|
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
-
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
-
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, FITNESS
|
|
17
|
-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|