@duckmind/dm-darwin-x64 0.13.6 → 0.13.8
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 +26 -2
- package/extensions/dm-phone/README.md +23 -0
- package/extensions/dm-phone/index.ts +12 -0
- package/extensions/dm-phone/node_modules/.package-lock.json +29 -0
- package/extensions/dm-phone/node_modules/ws/LICENSE +20 -0
- package/extensions/dm-phone/node_modules/ws/README.md +548 -0
- package/extensions/dm-phone/node_modules/ws/browser.js +8 -0
- package/extensions/dm-phone/node_modules/ws/index.js +22 -0
- package/extensions/dm-phone/node_modules/ws/lib/buffer-util.js +131 -0
- package/extensions/dm-phone/node_modules/ws/lib/constants.js +19 -0
- package/extensions/dm-phone/node_modules/ws/lib/event-target.js +292 -0
- package/extensions/dm-phone/node_modules/ws/lib/extension.js +203 -0
- package/extensions/dm-phone/node_modules/ws/lib/limiter.js +55 -0
- package/extensions/dm-phone/node_modules/ws/lib/permessage-deflate.js +528 -0
- package/extensions/dm-phone/node_modules/ws/lib/receiver.js +706 -0
- package/extensions/dm-phone/node_modules/ws/lib/sender.js +602 -0
- package/extensions/dm-phone/node_modules/ws/lib/stream.js +161 -0
- package/extensions/dm-phone/node_modules/ws/lib/subprotocol.js +62 -0
- package/extensions/dm-phone/node_modules/ws/lib/validation.js +152 -0
- package/extensions/dm-phone/node_modules/ws/lib/websocket-server.js +554 -0
- package/extensions/dm-phone/node_modules/ws/lib/websocket.js +1393 -0
- package/extensions/dm-phone/node_modules/ws/package.json +70 -0
- package/extensions/dm-phone/node_modules/ws/wrapper.mjs +21 -0
- package/extensions/dm-phone/package-lock.json +66 -0
- package/extensions/dm-phone/package.json +35 -0
- package/extensions/dm-phone/phone-session-pool.ts +8 -0
- package/extensions/dm-phone/public/app/attachments.js +233 -0
- package/extensions/dm-phone/public/app/autocomplete-controller.js +81 -0
- package/extensions/dm-phone/public/app/autocomplete.js +135 -0
- package/extensions/dm-phone/public/app/bindings.js +178 -0
- package/extensions/dm-phone/public/app/command-catalog.js +76 -0
- package/extensions/dm-phone/public/app/commands.js +370 -0
- package/extensions/dm-phone/public/app/constants.js +60 -0
- package/extensions/dm-phone/public/app/formatters.js +131 -0
- package/extensions/dm-phone/public/app/handlers.js +442 -0
- package/extensions/dm-phone/public/app/main.js +6 -0
- package/extensions/dm-phone/public/app/markdown.js +105 -0
- package/extensions/dm-phone/public/app/messages.js +418 -0
- package/extensions/dm-phone/public/app/sheet-actions.js +113 -0
- package/extensions/dm-phone/public/app/sheet-navigation.js +19 -0
- package/extensions/dm-phone/public/app/sheets-view.js +272 -0
- package/extensions/dm-phone/public/app/state.js +95 -0
- package/extensions/dm-phone/public/app/tool-rendering.js +562 -0
- package/extensions/dm-phone/public/app/transport.js +176 -0
- package/extensions/dm-phone/public/app/ui.js +409 -0
- package/extensions/dm-phone/public/app.js +1 -0
- package/extensions/dm-phone/public/icon.svg +15 -0
- package/extensions/dm-phone/public/index.html +147 -0
- package/extensions/dm-phone/public/manifest.webmanifest +17 -0
- package/extensions/dm-phone/public/styles.css +1139 -0
- package/extensions/dm-phone/public/sw.js +78 -0
- package/extensions/dm-phone/src/extension/phone-args.ts +121 -0
- package/extensions/dm-phone/src/extension/phone-paths.ts +250 -0
- package/extensions/dm-phone/src/extension/phone-quota.ts +188 -0
- package/extensions/dm-phone/src/extension/phone-runtime.ts +154 -0
- package/extensions/dm-phone/src/extension/phone-server-runtime.ts +1217 -0
- package/extensions/dm-phone/src/extension/phone-sessions.ts +139 -0
- package/extensions/dm-phone/src/extension/phone-static.ts +30 -0
- package/extensions/dm-phone/src/extension/phone-tailscale.ts +148 -0
- package/extensions/dm-phone/src/extension/phone-theme.ts +85 -0
- package/extensions/dm-phone/src/extension/register-phone-child-extension.ts +112 -0
- package/extensions/dm-phone/src/extension/register-phone-extension.ts +106 -0
- package/extensions/dm-phone/src/extension/types.ts +73 -0
- package/extensions/dm-phone/src/session-pool/parent-session-worker.ts +881 -0
- package/extensions/dm-phone/src/session-pool/session-pool.ts +470 -0
- package/extensions/dm-phone/src/session-pool/session-worker.ts +734 -0
- package/extensions/dm-phone/src/session-pool/types.ts +105 -0
- package/extensions/dm-phone/src/session-pool/utils.ts +23 -0
- package/extensions/dm-subagents/agent-management.ts +15 -6
- package/extensions/dm-subagents/agent-manager-detail.ts +12 -2
- package/extensions/dm-subagents/agent-manager-edit.ts +75 -23
- package/extensions/dm-subagents/agent-manager-list.ts +9 -2
- package/extensions/dm-subagents/agent-manager.ts +199 -11
- package/extensions/dm-subagents/agents.ts +315 -20
- package/extensions/dm-ultrathink/README.md +5 -0
- package/extensions/dm-ultrathink/src/naming.ts +75 -3
- package/package.json +1 -1
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import type { PersistedPhoneRuntime } from "./types";
|
|
5
|
+
|
|
6
|
+
const runtimeStateDir = join(tmpdir(), "dm-phone-extension");
|
|
7
|
+
export const phoneControlStopPath = "/__dm_phone__/control/stop";
|
|
8
|
+
|
|
9
|
+
function normalizeControlHost(host: string) {
|
|
10
|
+
if (!host || host === "0.0.0.0") return "127.0.0.1";
|
|
11
|
+
if (host === "::" || host === "[::]") return "[::1]";
|
|
12
|
+
if (host.includes(":") && !host.startsWith("[")) return `[${host}]`;
|
|
13
|
+
return host;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function isLoopbackAddress(address: string | undefined | null) {
|
|
17
|
+
if (!address) return false;
|
|
18
|
+
return address === "127.0.0.1" || address === "::1" || address === "::ffff:127.0.0.1";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function buildControlUrl(host: string, port: number, controlToken: string, pathname = phoneControlStopPath) {
|
|
22
|
+
const url = new URL(`http://${normalizeControlHost(host)}:${port}`);
|
|
23
|
+
url.pathname = pathname;
|
|
24
|
+
url.searchParams.set("token", controlToken);
|
|
25
|
+
return url;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getPersistedRuntimeStatePath(host: string, port: number) {
|
|
29
|
+
const hostKey = ["127.0.0.1", "localhost", "::1", "[::1]", "0.0.0.0", "::", "[::]"].includes(host)
|
|
30
|
+
? "local"
|
|
31
|
+
: encodeURIComponent(host);
|
|
32
|
+
return join(runtimeStateDir, `${hostKey}-${port}.json`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function readPersistedRuntimeState(host: string, port: number): Promise<PersistedPhoneRuntime | null> {
|
|
36
|
+
try {
|
|
37
|
+
const payload = await readFile(getPersistedRuntimeStatePath(host, port), "utf8");
|
|
38
|
+
const parsed = JSON.parse(payload);
|
|
39
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
40
|
+
if (typeof parsed.host !== "string" || typeof parsed.port !== "number" || typeof parsed.controlToken !== "string") {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
pid: typeof parsed.pid === "number" ? parsed.pid : 0,
|
|
46
|
+
host: parsed.host,
|
|
47
|
+
port: parsed.port,
|
|
48
|
+
controlToken: parsed.controlToken,
|
|
49
|
+
startedAt: typeof parsed.startedAt === "string" ? parsed.startedAt : "",
|
|
50
|
+
};
|
|
51
|
+
} catch (error: any) {
|
|
52
|
+
if (error?.code === "ENOENT") return null;
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function writePersistedRuntimeState(host: string, port: number, controlToken: string) {
|
|
58
|
+
const nextPath = getPersistedRuntimeStatePath(host, port);
|
|
59
|
+
await mkdir(runtimeStateDir, { recursive: true });
|
|
60
|
+
await writeFile(nextPath, JSON.stringify({
|
|
61
|
+
pid: process.pid,
|
|
62
|
+
host,
|
|
63
|
+
port,
|
|
64
|
+
controlToken,
|
|
65
|
+
startedAt: new Date().toISOString(),
|
|
66
|
+
} satisfies PersistedPhoneRuntime, null, 2), "utf8");
|
|
67
|
+
return nextPath;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function removePersistedRuntimeState(pathToRemove: string | null) {
|
|
71
|
+
if (!pathToRemove) return;
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
await unlink(pathToRemove);
|
|
75
|
+
} catch (error: any) {
|
|
76
|
+
if (error?.code !== "ENOENT") {
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function isProcessRunning(pid: number) {
|
|
83
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
84
|
+
try {
|
|
85
|
+
process.kill(pid, 0);
|
|
86
|
+
return true;
|
|
87
|
+
} catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function waitForPersistedRuntimeShutdown(runtime: PersistedPhoneRuntime, timeoutMs = 2000) {
|
|
93
|
+
const deadline = Date.now() + timeoutMs;
|
|
94
|
+
while (Date.now() < deadline) {
|
|
95
|
+
await new Promise((resolvePromise) => setTimeout(resolvePromise, 100));
|
|
96
|
+
try {
|
|
97
|
+
const healthUrl = buildControlUrl(runtime.host, runtime.port, runtime.controlToken, "/api/health");
|
|
98
|
+
healthUrl.searchParams.delete("token");
|
|
99
|
+
await fetch(healthUrl, { method: "GET" });
|
|
100
|
+
} catch {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export async function stopPersistedRuntime(host: string, port: number) {
|
|
108
|
+
const runtimeStatePath = getPersistedRuntimeStatePath(host, port);
|
|
109
|
+
const runtime = await readPersistedRuntimeState(host, port);
|
|
110
|
+
if (!runtime) {
|
|
111
|
+
return { stopped: false, found: false, message: "No running DM Phone instance was found for this port." };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const response = await fetch(buildControlUrl(runtime.host, runtime.port, runtime.controlToken), {
|
|
116
|
+
method: "POST",
|
|
117
|
+
});
|
|
118
|
+
const payload = await response.json().catch(() => null);
|
|
119
|
+
if (!response.ok || !payload || payload.ok !== true) {
|
|
120
|
+
return {
|
|
121
|
+
stopped: false,
|
|
122
|
+
found: true,
|
|
123
|
+
message: `DM Phone stop request failed with HTTP ${response.status}.`,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const stopped = await waitForPersistedRuntimeShutdown(runtime);
|
|
128
|
+
if (!stopped) {
|
|
129
|
+
return {
|
|
130
|
+
stopped: false,
|
|
131
|
+
found: true,
|
|
132
|
+
message: "DM Phone received the stop request but is still shutting down. Try /phone-start again in a moment.",
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
await removePersistedRuntimeState(runtimeStatePath);
|
|
137
|
+
return { stopped: true, found: true, message: "Stopped the other DM Phone instance." };
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (!isProcessRunning(runtime.pid)) {
|
|
140
|
+
await removePersistedRuntimeState(runtimeStatePath);
|
|
141
|
+
return {
|
|
142
|
+
stopped: false,
|
|
143
|
+
found: true,
|
|
144
|
+
message: "Removed stale DM Phone runtime state. Nothing was listening anymore.",
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
stopped: false,
|
|
150
|
+
found: true,
|
|
151
|
+
message: error instanceof Error ? error.message : String(error),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|