aisnitch 0.2.20 → 0.2.22
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/README.md +6 -0
- package/dist/cli/index.cjs +1835 -119
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +1812 -91
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +7219 -6428
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +165 -4
- package/dist/index.d.ts +165 -4
- package/dist/index.js +7243 -6459
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/cli/index.js
CHANGED
|
@@ -1,4 +1,739 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js
|
|
13
|
+
import fs from "fs";
|
|
14
|
+
function hasDockerEnv() {
|
|
15
|
+
try {
|
|
16
|
+
fs.statSync("/.dockerenv");
|
|
17
|
+
return true;
|
|
18
|
+
} catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function hasDockerCGroup() {
|
|
23
|
+
try {
|
|
24
|
+
return fs.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function isDocker() {
|
|
30
|
+
if (isDockerCached === void 0) {
|
|
31
|
+
isDockerCached = hasDockerEnv() || hasDockerCGroup();
|
|
32
|
+
}
|
|
33
|
+
return isDockerCached;
|
|
34
|
+
}
|
|
35
|
+
var isDockerCached;
|
|
36
|
+
var init_is_docker = __esm({
|
|
37
|
+
"node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js"() {
|
|
38
|
+
"use strict";
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
|
|
43
|
+
import fs2 from "fs";
|
|
44
|
+
function isInsideContainer() {
|
|
45
|
+
if (cachedResult === void 0) {
|
|
46
|
+
cachedResult = hasContainerEnv() || isDocker();
|
|
47
|
+
}
|
|
48
|
+
return cachedResult;
|
|
49
|
+
}
|
|
50
|
+
var cachedResult, hasContainerEnv;
|
|
51
|
+
var init_is_inside_container = __esm({
|
|
52
|
+
"node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js"() {
|
|
53
|
+
"use strict";
|
|
54
|
+
init_is_docker();
|
|
55
|
+
hasContainerEnv = () => {
|
|
56
|
+
try {
|
|
57
|
+
fs2.statSync("/run/.containerenv");
|
|
58
|
+
return true;
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// node_modules/.pnpm/is-wsl@3.1.1/node_modules/is-wsl/index.js
|
|
67
|
+
import process2 from "process";
|
|
68
|
+
import os from "os";
|
|
69
|
+
import fs3 from "fs";
|
|
70
|
+
var isWsl, is_wsl_default;
|
|
71
|
+
var init_is_wsl = __esm({
|
|
72
|
+
"node_modules/.pnpm/is-wsl@3.1.1/node_modules/is-wsl/index.js"() {
|
|
73
|
+
"use strict";
|
|
74
|
+
init_is_inside_container();
|
|
75
|
+
isWsl = () => {
|
|
76
|
+
if (process2.platform !== "linux") {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
if (os.release().toLowerCase().includes("microsoft")) {
|
|
80
|
+
if (isInsideContainer()) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
if (fs3.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft")) {
|
|
87
|
+
return !isInsideContainer();
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
}
|
|
91
|
+
if (fs3.existsSync("/proc/sys/fs/binfmt_misc/WSLInterop") || fs3.existsSync("/run/WSL")) {
|
|
92
|
+
return !isInsideContainer();
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
};
|
|
96
|
+
is_wsl_default = process2.env.__IS_WSL_TEST__ ? isWsl : isWsl();
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// node_modules/.pnpm/powershell-utils@0.1.0/node_modules/powershell-utils/index.js
|
|
101
|
+
import process3 from "process";
|
|
102
|
+
import { Buffer as Buffer2 } from "buffer";
|
|
103
|
+
import { promisify as promisify15 } from "util";
|
|
104
|
+
import childProcess from "child_process";
|
|
105
|
+
import fs4, { constants as fsConstants } from "fs/promises";
|
|
106
|
+
var execFile15, powerShellPath, executePowerShell;
|
|
107
|
+
var init_powershell_utils = __esm({
|
|
108
|
+
"node_modules/.pnpm/powershell-utils@0.1.0/node_modules/powershell-utils/index.js"() {
|
|
109
|
+
"use strict";
|
|
110
|
+
execFile15 = promisify15(childProcess.execFile);
|
|
111
|
+
powerShellPath = () => `${process3.env.SYSTEMROOT || process3.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
|
|
112
|
+
executePowerShell = async (command, options = {}) => {
|
|
113
|
+
const {
|
|
114
|
+
powerShellPath: psPath,
|
|
115
|
+
...execFileOptions
|
|
116
|
+
} = options;
|
|
117
|
+
const encodedCommand = executePowerShell.encodeCommand(command);
|
|
118
|
+
return execFile15(
|
|
119
|
+
psPath ?? powerShellPath(),
|
|
120
|
+
[
|
|
121
|
+
...executePowerShell.argumentsPrefix,
|
|
122
|
+
encodedCommand
|
|
123
|
+
],
|
|
124
|
+
{
|
|
125
|
+
encoding: "utf8",
|
|
126
|
+
...execFileOptions
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
};
|
|
130
|
+
executePowerShell.argumentsPrefix = [
|
|
131
|
+
"-NoProfile",
|
|
132
|
+
"-NonInteractive",
|
|
133
|
+
"-ExecutionPolicy",
|
|
134
|
+
"Bypass",
|
|
135
|
+
"-EncodedCommand"
|
|
136
|
+
];
|
|
137
|
+
executePowerShell.encodeCommand = (command) => Buffer2.from(command, "utf16le").toString("base64");
|
|
138
|
+
executePowerShell.escapeArgument = (value) => `'${String(value).replaceAll("'", "''")}'`;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/utilities.js
|
|
143
|
+
function parseMountPointFromConfig(content) {
|
|
144
|
+
for (const line of content.split("\n")) {
|
|
145
|
+
if (/^\s*#/.test(line)) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const match = /^\s*root\s*=\s*(?<mountPoint>"[^"]*"|'[^']*'|[^#]*)/.exec(line);
|
|
149
|
+
if (!match) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
return match.groups.mountPoint.trim().replaceAll(/^["']|["']$/g, "");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
var init_utilities = __esm({
|
|
156
|
+
"node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/utilities.js"() {
|
|
157
|
+
"use strict";
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/index.js
|
|
162
|
+
import { promisify as promisify16 } from "util";
|
|
163
|
+
import childProcess2 from "child_process";
|
|
164
|
+
import fs5, { constants as fsConstants2 } from "fs/promises";
|
|
165
|
+
var execFile16, wslDrivesMountPoint, powerShellPathFromWsl, powerShellPath2, canAccessPowerShellPromise, canAccessPowerShell, wslDefaultBrowser, convertWslPathToWindows;
|
|
166
|
+
var init_wsl_utils = __esm({
|
|
167
|
+
"node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/index.js"() {
|
|
168
|
+
"use strict";
|
|
169
|
+
init_is_wsl();
|
|
170
|
+
init_powershell_utils();
|
|
171
|
+
init_utilities();
|
|
172
|
+
init_is_wsl();
|
|
173
|
+
execFile16 = promisify16(childProcess2.execFile);
|
|
174
|
+
wslDrivesMountPoint = /* @__PURE__ */ (() => {
|
|
175
|
+
const defaultMountPoint = "/mnt/";
|
|
176
|
+
let mountPoint;
|
|
177
|
+
return async function() {
|
|
178
|
+
if (mountPoint) {
|
|
179
|
+
return mountPoint;
|
|
180
|
+
}
|
|
181
|
+
const configFilePath = "/etc/wsl.conf";
|
|
182
|
+
let isConfigFileExists = false;
|
|
183
|
+
try {
|
|
184
|
+
await fs5.access(configFilePath, fsConstants2.F_OK);
|
|
185
|
+
isConfigFileExists = true;
|
|
186
|
+
} catch {
|
|
187
|
+
}
|
|
188
|
+
if (!isConfigFileExists) {
|
|
189
|
+
return defaultMountPoint;
|
|
190
|
+
}
|
|
191
|
+
const configContent = await fs5.readFile(configFilePath, { encoding: "utf8" });
|
|
192
|
+
const parsedMountPoint = parseMountPointFromConfig(configContent);
|
|
193
|
+
if (parsedMountPoint === void 0) {
|
|
194
|
+
return defaultMountPoint;
|
|
195
|
+
}
|
|
196
|
+
mountPoint = parsedMountPoint;
|
|
197
|
+
mountPoint = mountPoint.endsWith("/") ? mountPoint : `${mountPoint}/`;
|
|
198
|
+
return mountPoint;
|
|
199
|
+
};
|
|
200
|
+
})();
|
|
201
|
+
powerShellPathFromWsl = async () => {
|
|
202
|
+
const mountPoint = await wslDrivesMountPoint();
|
|
203
|
+
return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
|
|
204
|
+
};
|
|
205
|
+
powerShellPath2 = is_wsl_default ? powerShellPathFromWsl : powerShellPath;
|
|
206
|
+
canAccessPowerShell = async () => {
|
|
207
|
+
canAccessPowerShellPromise ??= (async () => {
|
|
208
|
+
try {
|
|
209
|
+
const psPath = await powerShellPath2();
|
|
210
|
+
await fs5.access(psPath, fsConstants2.X_OK);
|
|
211
|
+
return true;
|
|
212
|
+
} catch {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
})();
|
|
216
|
+
return canAccessPowerShellPromise;
|
|
217
|
+
};
|
|
218
|
+
wslDefaultBrowser = async () => {
|
|
219
|
+
const psPath = await powerShellPath2();
|
|
220
|
+
const command = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
|
|
221
|
+
const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
|
|
222
|
+
return stdout.trim();
|
|
223
|
+
};
|
|
224
|
+
convertWslPathToWindows = async (path2) => {
|
|
225
|
+
if (/^[a-z]+:\/\//i.test(path2)) {
|
|
226
|
+
return path2;
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
const { stdout } = await execFile16("wslpath", ["-aw", path2], { encoding: "utf8" });
|
|
230
|
+
return stdout.trim();
|
|
231
|
+
} catch {
|
|
232
|
+
return path2;
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// node_modules/.pnpm/define-lazy-prop@3.0.0/node_modules/define-lazy-prop/index.js
|
|
239
|
+
function defineLazyProperty(object, propertyName, valueGetter) {
|
|
240
|
+
const define = (value) => Object.defineProperty(object, propertyName, { value, enumerable: true, writable: true });
|
|
241
|
+
Object.defineProperty(object, propertyName, {
|
|
242
|
+
configurable: true,
|
|
243
|
+
enumerable: true,
|
|
244
|
+
get() {
|
|
245
|
+
const result = valueGetter();
|
|
246
|
+
define(result);
|
|
247
|
+
return result;
|
|
248
|
+
},
|
|
249
|
+
set(value) {
|
|
250
|
+
define(value);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
return object;
|
|
254
|
+
}
|
|
255
|
+
var init_define_lazy_prop = __esm({
|
|
256
|
+
"node_modules/.pnpm/define-lazy-prop@3.0.0/node_modules/define-lazy-prop/index.js"() {
|
|
257
|
+
"use strict";
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// node_modules/.pnpm/default-browser-id@5.0.1/node_modules/default-browser-id/index.js
|
|
262
|
+
import { promisify as promisify17 } from "util";
|
|
263
|
+
import process4 from "process";
|
|
264
|
+
import { execFile as execFile17 } from "child_process";
|
|
265
|
+
async function defaultBrowserId() {
|
|
266
|
+
if (process4.platform !== "darwin") {
|
|
267
|
+
throw new Error("macOS only");
|
|
268
|
+
}
|
|
269
|
+
const { stdout } = await execFileAsync2("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
|
|
270
|
+
const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
|
|
271
|
+
const browserId = match?.groups.id ?? "com.apple.Safari";
|
|
272
|
+
if (browserId === "com.apple.safari") {
|
|
273
|
+
return "com.apple.Safari";
|
|
274
|
+
}
|
|
275
|
+
return browserId;
|
|
276
|
+
}
|
|
277
|
+
var execFileAsync2;
|
|
278
|
+
var init_default_browser_id = __esm({
|
|
279
|
+
"node_modules/.pnpm/default-browser-id@5.0.1/node_modules/default-browser-id/index.js"() {
|
|
280
|
+
"use strict";
|
|
281
|
+
execFileAsync2 = promisify17(execFile17);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// node_modules/.pnpm/run-applescript@7.1.0/node_modules/run-applescript/index.js
|
|
286
|
+
import process5 from "process";
|
|
287
|
+
import { promisify as promisify18 } from "util";
|
|
288
|
+
import { execFile as execFile18, execFileSync } from "child_process";
|
|
289
|
+
async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
|
|
290
|
+
if (process5.platform !== "darwin") {
|
|
291
|
+
throw new Error("macOS only");
|
|
292
|
+
}
|
|
293
|
+
const outputArguments = humanReadableOutput ? [] : ["-ss"];
|
|
294
|
+
const execOptions = {};
|
|
295
|
+
if (signal) {
|
|
296
|
+
execOptions.signal = signal;
|
|
297
|
+
}
|
|
298
|
+
const { stdout } = await execFileAsync3("osascript", ["-e", script, outputArguments], execOptions);
|
|
299
|
+
return stdout.trim();
|
|
300
|
+
}
|
|
301
|
+
var execFileAsync3;
|
|
302
|
+
var init_run_applescript = __esm({
|
|
303
|
+
"node_modules/.pnpm/run-applescript@7.1.0/node_modules/run-applescript/index.js"() {
|
|
304
|
+
"use strict";
|
|
305
|
+
execFileAsync3 = promisify18(execFile18);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// node_modules/.pnpm/bundle-name@4.1.0/node_modules/bundle-name/index.js
|
|
310
|
+
async function bundleName(bundleId) {
|
|
311
|
+
return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string
|
|
312
|
+
tell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
|
|
313
|
+
}
|
|
314
|
+
var init_bundle_name = __esm({
|
|
315
|
+
"node_modules/.pnpm/bundle-name@4.1.0/node_modules/bundle-name/index.js"() {
|
|
316
|
+
"use strict";
|
|
317
|
+
init_run_applescript();
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// node_modules/.pnpm/default-browser@5.5.0/node_modules/default-browser/windows.js
|
|
322
|
+
import { promisify as promisify19 } from "util";
|
|
323
|
+
import { execFile as execFile19 } from "child_process";
|
|
324
|
+
async function defaultBrowser(_execFileAsync = execFileAsync4) {
|
|
325
|
+
const { stdout } = await _execFileAsync("reg", [
|
|
326
|
+
"QUERY",
|
|
327
|
+
" HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
|
|
328
|
+
"/v",
|
|
329
|
+
"ProgId"
|
|
330
|
+
]);
|
|
331
|
+
const match = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
|
|
332
|
+
if (!match) {
|
|
333
|
+
throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
|
|
334
|
+
}
|
|
335
|
+
const { id } = match.groups;
|
|
336
|
+
const dotIndex = id.lastIndexOf(".");
|
|
337
|
+
const hyphenIndex = id.lastIndexOf("-");
|
|
338
|
+
const baseIdByDot = dotIndex === -1 ? void 0 : id.slice(0, dotIndex);
|
|
339
|
+
const baseIdByHyphen = hyphenIndex === -1 ? void 0 : id.slice(0, hyphenIndex);
|
|
340
|
+
return windowsBrowserProgIds[id] ?? windowsBrowserProgIds[baseIdByDot] ?? windowsBrowserProgIds[baseIdByHyphen] ?? { name: id, id };
|
|
341
|
+
}
|
|
342
|
+
var execFileAsync4, windowsBrowserProgIds, _windowsBrowserProgIdMap, UnknownBrowserError;
|
|
343
|
+
var init_windows = __esm({
|
|
344
|
+
"node_modules/.pnpm/default-browser@5.5.0/node_modules/default-browser/windows.js"() {
|
|
345
|
+
"use strict";
|
|
346
|
+
execFileAsync4 = promisify19(execFile19);
|
|
347
|
+
windowsBrowserProgIds = {
|
|
348
|
+
MSEdgeHTM: { name: "Edge", id: "com.microsoft.edge" },
|
|
349
|
+
// The missing `L` is correct.
|
|
350
|
+
MSEdgeBHTML: { name: "Edge Beta", id: "com.microsoft.edge.beta" },
|
|
351
|
+
MSEdgeDHTML: { name: "Edge Dev", id: "com.microsoft.edge.dev" },
|
|
352
|
+
AppXq0fevzme2pys62n3e0fbqa7peapykr8v: { name: "Edge", id: "com.microsoft.edge.old" },
|
|
353
|
+
ChromeHTML: { name: "Chrome", id: "com.google.chrome" },
|
|
354
|
+
ChromeBHTML: { name: "Chrome Beta", id: "com.google.chrome.beta" },
|
|
355
|
+
ChromeDHTML: { name: "Chrome Dev", id: "com.google.chrome.dev" },
|
|
356
|
+
ChromiumHTM: { name: "Chromium", id: "org.chromium.Chromium" },
|
|
357
|
+
BraveHTML: { name: "Brave", id: "com.brave.Browser" },
|
|
358
|
+
BraveBHTML: { name: "Brave Beta", id: "com.brave.Browser.beta" },
|
|
359
|
+
BraveDHTML: { name: "Brave Dev", id: "com.brave.Browser.dev" },
|
|
360
|
+
BraveSSHTM: { name: "Brave Nightly", id: "com.brave.Browser.nightly" },
|
|
361
|
+
FirefoxURL: { name: "Firefox", id: "org.mozilla.firefox" },
|
|
362
|
+
OperaStable: { name: "Opera", id: "com.operasoftware.Opera" },
|
|
363
|
+
VivaldiHTM: { name: "Vivaldi", id: "com.vivaldi.Vivaldi" },
|
|
364
|
+
"IE.HTTP": { name: "Internet Explorer", id: "com.microsoft.ie" }
|
|
365
|
+
};
|
|
366
|
+
_windowsBrowserProgIdMap = new Map(Object.entries(windowsBrowserProgIds));
|
|
367
|
+
UnknownBrowserError = class extends Error {
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
// node_modules/.pnpm/default-browser@5.5.0/node_modules/default-browser/index.js
|
|
373
|
+
import { promisify as promisify20 } from "util";
|
|
374
|
+
import process6 from "process";
|
|
375
|
+
import { execFile as execFile20 } from "child_process";
|
|
376
|
+
async function defaultBrowser2() {
|
|
377
|
+
if (process6.platform === "darwin") {
|
|
378
|
+
const id = await defaultBrowserId();
|
|
379
|
+
const name = await bundleName(id);
|
|
380
|
+
return { name, id };
|
|
381
|
+
}
|
|
382
|
+
if (process6.platform === "linux") {
|
|
383
|
+
const { stdout } = await execFileAsync5("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
|
|
384
|
+
const id = stdout.trim();
|
|
385
|
+
const name = titleize(id.replace(/.desktop$/, "").replace("-", " "));
|
|
386
|
+
return { name, id };
|
|
387
|
+
}
|
|
388
|
+
if (process6.platform === "win32") {
|
|
389
|
+
return defaultBrowser();
|
|
390
|
+
}
|
|
391
|
+
throw new Error("Only macOS, Linux, and Windows are supported");
|
|
392
|
+
}
|
|
393
|
+
var execFileAsync5, titleize;
|
|
394
|
+
var init_default_browser = __esm({
|
|
395
|
+
"node_modules/.pnpm/default-browser@5.5.0/node_modules/default-browser/index.js"() {
|
|
396
|
+
"use strict";
|
|
397
|
+
init_default_browser_id();
|
|
398
|
+
init_bundle_name();
|
|
399
|
+
init_windows();
|
|
400
|
+
init_windows();
|
|
401
|
+
execFileAsync5 = promisify20(execFile20);
|
|
402
|
+
titleize = (string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
// node_modules/.pnpm/is-in-ssh@1.0.0/node_modules/is-in-ssh/index.js
|
|
407
|
+
import process7 from "process";
|
|
408
|
+
var isInSsh, is_in_ssh_default;
|
|
409
|
+
var init_is_in_ssh = __esm({
|
|
410
|
+
"node_modules/.pnpm/is-in-ssh@1.0.0/node_modules/is-in-ssh/index.js"() {
|
|
411
|
+
"use strict";
|
|
412
|
+
isInSsh = Boolean(process7.env.SSH_CONNECTION || process7.env.SSH_CLIENT || process7.env.SSH_TTY);
|
|
413
|
+
is_in_ssh_default = isInSsh;
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
// node_modules/.pnpm/open@11.0.0/node_modules/open/index.js
|
|
418
|
+
var open_exports = {};
|
|
419
|
+
__export(open_exports, {
|
|
420
|
+
apps: () => apps,
|
|
421
|
+
default: () => open_default,
|
|
422
|
+
openApp: () => openApp
|
|
423
|
+
});
|
|
424
|
+
import process8 from "process";
|
|
425
|
+
import path from "path";
|
|
426
|
+
import { fileURLToPath } from "url";
|
|
427
|
+
import childProcess3 from "child_process";
|
|
428
|
+
import fs6, { constants as fsConstants3 } from "fs/promises";
|
|
429
|
+
function detectArchBinary(binary) {
|
|
430
|
+
if (typeof binary === "string" || Array.isArray(binary)) {
|
|
431
|
+
return binary;
|
|
432
|
+
}
|
|
433
|
+
const { [arch]: archBinary } = binary;
|
|
434
|
+
if (!archBinary) {
|
|
435
|
+
throw new Error(`${arch} is not supported`);
|
|
436
|
+
}
|
|
437
|
+
return archBinary;
|
|
438
|
+
}
|
|
439
|
+
function detectPlatformBinary({ [platform]: platformBinary }, { wsl } = {}) {
|
|
440
|
+
if (wsl && is_wsl_default) {
|
|
441
|
+
return detectArchBinary(wsl);
|
|
442
|
+
}
|
|
443
|
+
if (!platformBinary) {
|
|
444
|
+
throw new Error(`${platform} is not supported`);
|
|
445
|
+
}
|
|
446
|
+
return detectArchBinary(platformBinary);
|
|
447
|
+
}
|
|
448
|
+
var fallbackAttemptSymbol, __dirname, localXdgOpenPath, platform, arch, tryEachApp, baseOpen, open, openApp, apps, open_default;
|
|
449
|
+
var init_open = __esm({
|
|
450
|
+
"node_modules/.pnpm/open@11.0.0/node_modules/open/index.js"() {
|
|
451
|
+
"use strict";
|
|
452
|
+
init_wsl_utils();
|
|
453
|
+
init_powershell_utils();
|
|
454
|
+
init_define_lazy_prop();
|
|
455
|
+
init_default_browser();
|
|
456
|
+
init_is_inside_container();
|
|
457
|
+
init_is_in_ssh();
|
|
458
|
+
fallbackAttemptSymbol = /* @__PURE__ */ Symbol("fallbackAttempt");
|
|
459
|
+
__dirname = import.meta.url ? path.dirname(fileURLToPath(import.meta.url)) : "";
|
|
460
|
+
localXdgOpenPath = path.join(__dirname, "xdg-open");
|
|
461
|
+
({ platform, arch } = process8);
|
|
462
|
+
tryEachApp = async (apps2, opener) => {
|
|
463
|
+
if (apps2.length === 0) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
const errors = [];
|
|
467
|
+
for (const app of apps2) {
|
|
468
|
+
try {
|
|
469
|
+
return await opener(app);
|
|
470
|
+
} catch (error) {
|
|
471
|
+
errors.push(error);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
throw new AggregateError(errors, "Failed to open in all supported apps");
|
|
475
|
+
};
|
|
476
|
+
baseOpen = async (options) => {
|
|
477
|
+
options = {
|
|
478
|
+
wait: false,
|
|
479
|
+
background: false,
|
|
480
|
+
newInstance: false,
|
|
481
|
+
allowNonzeroExitCode: false,
|
|
482
|
+
...options
|
|
483
|
+
};
|
|
484
|
+
const isFallbackAttempt = options[fallbackAttemptSymbol] === true;
|
|
485
|
+
delete options[fallbackAttemptSymbol];
|
|
486
|
+
if (Array.isArray(options.app)) {
|
|
487
|
+
return tryEachApp(options.app, (singleApp) => baseOpen({
|
|
488
|
+
...options,
|
|
489
|
+
app: singleApp,
|
|
490
|
+
[fallbackAttemptSymbol]: true
|
|
491
|
+
}));
|
|
492
|
+
}
|
|
493
|
+
let { name: app, arguments: appArguments = [] } = options.app ?? {};
|
|
494
|
+
appArguments = [...appArguments];
|
|
495
|
+
if (Array.isArray(app)) {
|
|
496
|
+
return tryEachApp(app, (appName) => baseOpen({
|
|
497
|
+
...options,
|
|
498
|
+
app: {
|
|
499
|
+
name: appName,
|
|
500
|
+
arguments: appArguments
|
|
501
|
+
},
|
|
502
|
+
[fallbackAttemptSymbol]: true
|
|
503
|
+
}));
|
|
504
|
+
}
|
|
505
|
+
if (app === "browser" || app === "browserPrivate") {
|
|
506
|
+
const ids = {
|
|
507
|
+
"com.google.chrome": "chrome",
|
|
508
|
+
"google-chrome.desktop": "chrome",
|
|
509
|
+
"com.brave.browser": "brave",
|
|
510
|
+
"org.mozilla.firefox": "firefox",
|
|
511
|
+
"firefox.desktop": "firefox",
|
|
512
|
+
"com.microsoft.msedge": "edge",
|
|
513
|
+
"com.microsoft.edge": "edge",
|
|
514
|
+
"com.microsoft.edgemac": "edge",
|
|
515
|
+
"microsoft-edge.desktop": "edge",
|
|
516
|
+
"com.apple.safari": "safari"
|
|
517
|
+
};
|
|
518
|
+
const flags = {
|
|
519
|
+
chrome: "--incognito",
|
|
520
|
+
brave: "--incognito",
|
|
521
|
+
firefox: "--private-window",
|
|
522
|
+
edge: "--inPrivate"
|
|
523
|
+
// Safari doesn't support private mode via command line
|
|
524
|
+
};
|
|
525
|
+
let browser;
|
|
526
|
+
if (is_wsl_default) {
|
|
527
|
+
const progId = await wslDefaultBrowser();
|
|
528
|
+
const browserInfo = _windowsBrowserProgIdMap.get(progId);
|
|
529
|
+
browser = browserInfo ?? {};
|
|
530
|
+
} else {
|
|
531
|
+
browser = await defaultBrowser2();
|
|
532
|
+
}
|
|
533
|
+
if (browser.id in ids) {
|
|
534
|
+
const browserName = ids[browser.id.toLowerCase()];
|
|
535
|
+
if (app === "browserPrivate") {
|
|
536
|
+
if (browserName === "safari") {
|
|
537
|
+
throw new Error("Safari doesn't support opening in private mode via command line");
|
|
538
|
+
}
|
|
539
|
+
appArguments.push(flags[browserName]);
|
|
540
|
+
}
|
|
541
|
+
return baseOpen({
|
|
542
|
+
...options,
|
|
543
|
+
app: {
|
|
544
|
+
name: apps[browserName],
|
|
545
|
+
arguments: appArguments
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
throw new Error(`${browser.name} is not supported as a default browser`);
|
|
550
|
+
}
|
|
551
|
+
let command;
|
|
552
|
+
const cliArguments = [];
|
|
553
|
+
const childProcessOptions = {};
|
|
554
|
+
let shouldUseWindowsInWsl = false;
|
|
555
|
+
if (is_wsl_default && !isInsideContainer() && !is_in_ssh_default && !app) {
|
|
556
|
+
shouldUseWindowsInWsl = await canAccessPowerShell();
|
|
557
|
+
}
|
|
558
|
+
if (platform === "darwin") {
|
|
559
|
+
command = "open";
|
|
560
|
+
if (options.wait) {
|
|
561
|
+
cliArguments.push("--wait-apps");
|
|
562
|
+
}
|
|
563
|
+
if (options.background) {
|
|
564
|
+
cliArguments.push("--background");
|
|
565
|
+
}
|
|
566
|
+
if (options.newInstance) {
|
|
567
|
+
cliArguments.push("--new");
|
|
568
|
+
}
|
|
569
|
+
if (app) {
|
|
570
|
+
cliArguments.push("-a", app);
|
|
571
|
+
}
|
|
572
|
+
} else if (platform === "win32" || shouldUseWindowsInWsl) {
|
|
573
|
+
command = await powerShellPath2();
|
|
574
|
+
cliArguments.push(...executePowerShell.argumentsPrefix);
|
|
575
|
+
if (!is_wsl_default) {
|
|
576
|
+
childProcessOptions.windowsVerbatimArguments = true;
|
|
577
|
+
}
|
|
578
|
+
if (is_wsl_default && options.target) {
|
|
579
|
+
options.target = await convertWslPathToWindows(options.target);
|
|
580
|
+
}
|
|
581
|
+
const encodedArguments = ["$ProgressPreference = 'SilentlyContinue';", "Start"];
|
|
582
|
+
if (options.wait) {
|
|
583
|
+
encodedArguments.push("-Wait");
|
|
584
|
+
}
|
|
585
|
+
if (app) {
|
|
586
|
+
encodedArguments.push(executePowerShell.escapeArgument(app));
|
|
587
|
+
if (options.target) {
|
|
588
|
+
appArguments.push(options.target);
|
|
589
|
+
}
|
|
590
|
+
} else if (options.target) {
|
|
591
|
+
encodedArguments.push(executePowerShell.escapeArgument(options.target));
|
|
592
|
+
}
|
|
593
|
+
if (appArguments.length > 0) {
|
|
594
|
+
appArguments = appArguments.map((argument) => executePowerShell.escapeArgument(argument));
|
|
595
|
+
encodedArguments.push("-ArgumentList", appArguments.join(","));
|
|
596
|
+
}
|
|
597
|
+
options.target = executePowerShell.encodeCommand(encodedArguments.join(" "));
|
|
598
|
+
if (!options.wait) {
|
|
599
|
+
childProcessOptions.stdio = "ignore";
|
|
600
|
+
}
|
|
601
|
+
} else {
|
|
602
|
+
if (app) {
|
|
603
|
+
command = app;
|
|
604
|
+
} else {
|
|
605
|
+
const isBundled = !__dirname || __dirname === "/";
|
|
606
|
+
let exeLocalXdgOpen = false;
|
|
607
|
+
try {
|
|
608
|
+
await fs6.access(localXdgOpenPath, fsConstants3.X_OK);
|
|
609
|
+
exeLocalXdgOpen = true;
|
|
610
|
+
} catch {
|
|
611
|
+
}
|
|
612
|
+
const useSystemXdgOpen = process8.versions.electron ?? (platform === "android" || isBundled || !exeLocalXdgOpen);
|
|
613
|
+
command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
|
|
614
|
+
}
|
|
615
|
+
if (appArguments.length > 0) {
|
|
616
|
+
cliArguments.push(...appArguments);
|
|
617
|
+
}
|
|
618
|
+
if (!options.wait) {
|
|
619
|
+
childProcessOptions.stdio = "ignore";
|
|
620
|
+
childProcessOptions.detached = true;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
if (platform === "darwin" && appArguments.length > 0) {
|
|
624
|
+
cliArguments.push("--args", ...appArguments);
|
|
625
|
+
}
|
|
626
|
+
if (options.target) {
|
|
627
|
+
cliArguments.push(options.target);
|
|
628
|
+
}
|
|
629
|
+
const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
|
|
630
|
+
if (options.wait) {
|
|
631
|
+
return new Promise((resolve2, reject) => {
|
|
632
|
+
subprocess.once("error", reject);
|
|
633
|
+
subprocess.once("close", (exitCode) => {
|
|
634
|
+
if (!options.allowNonzeroExitCode && exitCode !== 0) {
|
|
635
|
+
reject(new Error(`Exited with code ${exitCode}`));
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
resolve2(subprocess);
|
|
639
|
+
});
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
if (isFallbackAttempt) {
|
|
643
|
+
return new Promise((resolve2, reject) => {
|
|
644
|
+
subprocess.once("error", reject);
|
|
645
|
+
subprocess.once("spawn", () => {
|
|
646
|
+
subprocess.once("close", (exitCode) => {
|
|
647
|
+
subprocess.off("error", reject);
|
|
648
|
+
if (exitCode !== 0) {
|
|
649
|
+
reject(new Error(`Exited with code ${exitCode}`));
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
subprocess.unref();
|
|
653
|
+
resolve2(subprocess);
|
|
654
|
+
});
|
|
655
|
+
});
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
subprocess.unref();
|
|
659
|
+
return new Promise((resolve2, reject) => {
|
|
660
|
+
subprocess.once("error", reject);
|
|
661
|
+
subprocess.once("spawn", () => {
|
|
662
|
+
subprocess.off("error", reject);
|
|
663
|
+
resolve2(subprocess);
|
|
664
|
+
});
|
|
665
|
+
});
|
|
666
|
+
};
|
|
667
|
+
open = (target, options) => {
|
|
668
|
+
if (typeof target !== "string") {
|
|
669
|
+
throw new TypeError("Expected a `target`");
|
|
670
|
+
}
|
|
671
|
+
return baseOpen({
|
|
672
|
+
...options,
|
|
673
|
+
target
|
|
674
|
+
});
|
|
675
|
+
};
|
|
676
|
+
openApp = (name, options) => {
|
|
677
|
+
if (typeof name !== "string" && !Array.isArray(name)) {
|
|
678
|
+
throw new TypeError("Expected a valid `name`");
|
|
679
|
+
}
|
|
680
|
+
const { arguments: appArguments = [] } = options ?? {};
|
|
681
|
+
if (appArguments !== void 0 && appArguments !== null && !Array.isArray(appArguments)) {
|
|
682
|
+
throw new TypeError("Expected `appArguments` as Array type");
|
|
683
|
+
}
|
|
684
|
+
return baseOpen({
|
|
685
|
+
...options,
|
|
686
|
+
app: {
|
|
687
|
+
name,
|
|
688
|
+
arguments: appArguments
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
};
|
|
692
|
+
apps = {
|
|
693
|
+
browser: "browser",
|
|
694
|
+
browserPrivate: "browserPrivate"
|
|
695
|
+
};
|
|
696
|
+
defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
|
|
697
|
+
darwin: "google chrome",
|
|
698
|
+
win32: "chrome",
|
|
699
|
+
// `chromium-browser` is the older deb package name used by Ubuntu/Debian before snap.
|
|
700
|
+
linux: ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser"]
|
|
701
|
+
}, {
|
|
702
|
+
wsl: {
|
|
703
|
+
ia32: "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe",
|
|
704
|
+
x64: ["/mnt/c/Program Files/Google/Chrome/Application/chrome.exe", "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"]
|
|
705
|
+
}
|
|
706
|
+
}));
|
|
707
|
+
defineLazyProperty(apps, "brave", () => detectPlatformBinary({
|
|
708
|
+
darwin: "brave browser",
|
|
709
|
+
win32: "brave",
|
|
710
|
+
linux: ["brave-browser", "brave"]
|
|
711
|
+
}, {
|
|
712
|
+
wsl: {
|
|
713
|
+
ia32: "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe",
|
|
714
|
+
x64: ["/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe", "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe"]
|
|
715
|
+
}
|
|
716
|
+
}));
|
|
717
|
+
defineLazyProperty(apps, "firefox", () => detectPlatformBinary({
|
|
718
|
+
darwin: "firefox",
|
|
719
|
+
win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
|
|
720
|
+
linux: "firefox"
|
|
721
|
+
}, {
|
|
722
|
+
wsl: "/mnt/c/Program Files/Mozilla Firefox/firefox.exe"
|
|
723
|
+
}));
|
|
724
|
+
defineLazyProperty(apps, "edge", () => detectPlatformBinary({
|
|
725
|
+
darwin: "microsoft edge",
|
|
726
|
+
win32: "msedge",
|
|
727
|
+
linux: ["microsoft-edge", "microsoft-edge-dev"]
|
|
728
|
+
}, {
|
|
729
|
+
wsl: "/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
|
|
730
|
+
}));
|
|
731
|
+
defineLazyProperty(apps, "safari", () => detectPlatformBinary({
|
|
732
|
+
darwin: "Safari"
|
|
733
|
+
}));
|
|
734
|
+
open_default = open;
|
|
735
|
+
}
|
|
736
|
+
});
|
|
2
737
|
|
|
3
738
|
// src/cli/index.ts
|
|
4
739
|
import { CommanderError } from "commander";
|
|
@@ -8,7 +743,7 @@ import { Command, InvalidArgumentError } from "commander";
|
|
|
8
743
|
|
|
9
744
|
// src/package-info.ts
|
|
10
745
|
var AISNITCH_PACKAGE_NAME = "aisnitch";
|
|
11
|
-
var AISNITCH_VERSION = "0.2.
|
|
746
|
+
var AISNITCH_VERSION = "0.2.22";
|
|
12
747
|
var AISNITCH_DESCRIPTION = "Universal bridge for AI coding tool activity \u2014 capture, normalize, stream.";
|
|
13
748
|
|
|
14
749
|
// src/core/events/schema.ts
|
|
@@ -49,6 +784,8 @@ var TOOL_NAMES = [
|
|
|
49
784
|
"kiro",
|
|
50
785
|
"augment-code",
|
|
51
786
|
"mistral",
|
|
787
|
+
"zed",
|
|
788
|
+
"pi",
|
|
52
789
|
"unknown"
|
|
53
790
|
];
|
|
54
791
|
var ERROR_TYPES = [
|
|
@@ -96,6 +833,11 @@ var ToolInputSchema = z.strictObject({
|
|
|
96
833
|
(value) => value.filePath !== void 0 || value.command !== void 0,
|
|
97
834
|
"toolInput must include filePath or command"
|
|
98
835
|
);
|
|
836
|
+
var ThinkingContentSchema = z.string().max(1e5).describe("Raw thinking/reasoning content from the AI model");
|
|
837
|
+
var ToolCallNameSchema = z.string().min(1).max(100).describe("Name of the tool being invoked (e.g., Edit, Bash, Grep)");
|
|
838
|
+
var FinalMessageSchema = z.string().max(5e4).describe("End-of-run summary or completion message");
|
|
839
|
+
var ToolResultSchema = z.string().max(1e4).describe("Tool execution result or output");
|
|
840
|
+
var MessageContentSchema = z.string().max(1e5).describe("Raw text content from AI messages");
|
|
99
841
|
var ToolNameSchema = z.enum(TOOL_NAMES);
|
|
100
842
|
var AISnitchEventTypeSchema = z.enum(AISNITCH_EVENT_TYPES);
|
|
101
843
|
var ErrorTypeSchema = z.enum(ERROR_TYPES);
|
|
@@ -110,6 +852,9 @@ var EventDataSchema = z.strictObject({
|
|
|
110
852
|
activeFile: z.string().min(1).max(4096).optional(),
|
|
111
853
|
model: z.string().min(1).max(200).optional(),
|
|
112
854
|
tokensUsed: z.number().int().min(0).optional(),
|
|
855
|
+
inputTokens: z.number().int().min(0).optional(),
|
|
856
|
+
outputTokens: z.number().int().min(0).optional(),
|
|
857
|
+
cachedTokens: z.number().int().min(0).optional(),
|
|
113
858
|
errorMessage: z.string().min(1).max(1e4).optional(),
|
|
114
859
|
errorType: ErrorTypeSchema.optional(),
|
|
115
860
|
raw: z.record(z.string(), z.unknown()).optional(),
|
|
@@ -118,7 +863,13 @@ var EventDataSchema = z.strictObject({
|
|
|
118
863
|
pid: z.number().int().positive().optional(),
|
|
119
864
|
instanceId: z.string().min(1).max(255).optional(),
|
|
120
865
|
instanceIndex: z.number().int().min(1).optional(),
|
|
121
|
-
instanceTotal: z.number().int().min(1).optional()
|
|
866
|
+
instanceTotal: z.number().int().min(1).optional(),
|
|
867
|
+
// New fields for enhanced content capture
|
|
868
|
+
thinkingContent: ThinkingContentSchema.optional(),
|
|
869
|
+
toolCallName: ToolCallNameSchema.optional(),
|
|
870
|
+
finalMessage: FinalMessageSchema.optional(),
|
|
871
|
+
toolResult: ToolResultSchema.optional(),
|
|
872
|
+
messageContent: MessageContentSchema.optional()
|
|
122
873
|
});
|
|
123
874
|
var AISnitchEventSchema = z.strictObject({
|
|
124
875
|
specversion: z.literal("1.0"),
|
|
@@ -923,8 +1674,8 @@ var ClaudeCodeSetup = class extends FileToolSetupBase {
|
|
|
923
1674
|
return `${JSON.stringify(nextSettings, null, 2)}
|
|
924
1675
|
`;
|
|
925
1676
|
}
|
|
926
|
-
getFileBackupPath(
|
|
927
|
-
return `${
|
|
1677
|
+
getFileBackupPath(path2) {
|
|
1678
|
+
return `${path2}.bak`;
|
|
928
1679
|
}
|
|
929
1680
|
};
|
|
930
1681
|
var OpenCodeSetup = class extends FileToolSetupBase {
|
|
@@ -1164,8 +1915,8 @@ var CopilotCLISetup = class {
|
|
|
1164
1915
|
return `${JSON.stringify(nextConfig, null, 2)}
|
|
1165
1916
|
`;
|
|
1166
1917
|
}
|
|
1167
|
-
getBackupPath(
|
|
1168
|
-
return `${
|
|
1918
|
+
getBackupPath(path2) {
|
|
1919
|
+
return `${path2}.bak`;
|
|
1169
1920
|
}
|
|
1170
1921
|
};
|
|
1171
1922
|
var OpenClawSetup = class {
|
|
@@ -1290,8 +2041,8 @@ var OpenClawSetup = class {
|
|
|
1290
2041
|
return `${JSON.stringify(nextConfig, null, 2)}
|
|
1291
2042
|
`;
|
|
1292
2043
|
}
|
|
1293
|
-
getBackupPath(
|
|
1294
|
-
return `${
|
|
2044
|
+
getBackupPath(path2) {
|
|
2045
|
+
return `${path2}.bak`;
|
|
1295
2046
|
}
|
|
1296
2047
|
};
|
|
1297
2048
|
async function createToolSetup(toolName, options = {}, dependencies = {}) {
|
|
@@ -2334,17 +3085,17 @@ async function isBinaryAvailable(binaryName) {
|
|
|
2334
3085
|
return false;
|
|
2335
3086
|
}
|
|
2336
3087
|
}
|
|
2337
|
-
async function fileExists(
|
|
3088
|
+
async function fileExists(path2) {
|
|
2338
3089
|
try {
|
|
2339
|
-
await access(
|
|
3090
|
+
await access(path2, constants.F_OK);
|
|
2340
3091
|
return true;
|
|
2341
3092
|
} catch {
|
|
2342
3093
|
return false;
|
|
2343
3094
|
}
|
|
2344
3095
|
}
|
|
2345
|
-
async function readOptionalFile(
|
|
3096
|
+
async function readOptionalFile(path2) {
|
|
2346
3097
|
try {
|
|
2347
|
-
return await readFile2(
|
|
3098
|
+
return await readFile2(path2, "utf8");
|
|
2348
3099
|
} catch (error) {
|
|
2349
3100
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
2350
3101
|
return null;
|
|
@@ -2355,14 +3106,14 @@ async function readOptionalFile(path) {
|
|
|
2355
3106
|
function shellEscapeSingle(value) {
|
|
2356
3107
|
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
2357
3108
|
}
|
|
2358
|
-
async function restoreBackupOrRemove(
|
|
2359
|
-
const backupPath = `${
|
|
3109
|
+
async function restoreBackupOrRemove(path2) {
|
|
3110
|
+
const backupPath = `${path2}.bak`;
|
|
2360
3111
|
if (await fileExists(backupPath)) {
|
|
2361
|
-
await copyFile(backupPath,
|
|
3112
|
+
await copyFile(backupPath, path2);
|
|
2362
3113
|
await rm(backupPath, { force: true });
|
|
2363
3114
|
return;
|
|
2364
3115
|
}
|
|
2365
|
-
await rm(
|
|
3116
|
+
await rm(path2, { force: true });
|
|
2366
3117
|
}
|
|
2367
3118
|
function buildAiderNotificationCommand(options) {
|
|
2368
3119
|
const cliArgs = [process.execPath, resolveCurrentCliEntryPath(), "aider-notify"];
|
|
@@ -2432,11 +3183,11 @@ function toConfigPathOptions(options) {
|
|
|
2432
3183
|
// src/cli/runtime.ts
|
|
2433
3184
|
import { execFile as execFileCallback14, spawn as spawnChildProcess2 } from "child_process";
|
|
2434
3185
|
import { closeSync, openSync } from "fs";
|
|
2435
|
-
import { mkdtemp, readFile as
|
|
3186
|
+
import { mkdtemp, readFile as readFile15, rename, rm as rm4, writeFile as writeFile5 } from "fs/promises";
|
|
2436
3187
|
import { createConnection as createConnection3 } from "net";
|
|
2437
3188
|
import { tmpdir } from "os";
|
|
2438
|
-
import { basename as
|
|
2439
|
-
import { promisify as
|
|
3189
|
+
import { basename as basename12, join as join18 } from "path";
|
|
3190
|
+
import { promisify as promisify21 } from "util";
|
|
2440
3191
|
|
|
2441
3192
|
// src/adapters/generic-pty.ts
|
|
2442
3193
|
import { basename as basename3 } from "path";
|
|
@@ -2507,9 +3258,11 @@ var TOOL_BINARY_MAP = {
|
|
|
2507
3258
|
"openhands": "openhands",
|
|
2508
3259
|
"openclaw": "openclaw",
|
|
2509
3260
|
"opencode": "opencode",
|
|
3261
|
+
"pi": "pi",
|
|
2510
3262
|
"qwen-code": "qwen",
|
|
2511
3263
|
"unknown": "unknown",
|
|
2512
|
-
"windsurf": "windsurf"
|
|
3264
|
+
"windsurf": "windsurf",
|
|
3265
|
+
"zed": "zed"
|
|
2513
3266
|
};
|
|
2514
3267
|
var ContextDetector = class {
|
|
2515
3268
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -4370,7 +5123,7 @@ var UDSServer = class {
|
|
|
4370
5123
|
};
|
|
4371
5124
|
|
|
4372
5125
|
// src/core/engine/pipeline.ts
|
|
4373
|
-
import { join as
|
|
5126
|
+
import { join as join15 } from "path";
|
|
4374
5127
|
import { z as z4 } from "zod";
|
|
4375
5128
|
|
|
4376
5129
|
// src/adapters/aider.ts
|
|
@@ -4477,20 +5230,29 @@ var BaseAdapter = class {
|
|
|
4477
5230
|
});
|
|
4478
5231
|
let published;
|
|
4479
5232
|
try {
|
|
4480
|
-
published = await
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
5233
|
+
published = await SHARED_BREAKERS.adapterEmit.execute(async () => {
|
|
5234
|
+
return await this.publishEventImplementation(event, {
|
|
5235
|
+
cwd: context.cwd,
|
|
5236
|
+
env: context.env,
|
|
5237
|
+
hookPayload: context.hookPayload,
|
|
5238
|
+
pid: context.pid,
|
|
5239
|
+
sessionId,
|
|
5240
|
+
source: context.source,
|
|
5241
|
+
transcriptPath: context.transcriptPath
|
|
5242
|
+
});
|
|
4488
5243
|
});
|
|
4489
5244
|
} catch (error) {
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
5245
|
+
if (error instanceof Error && error.name === "CircuitOpenError") {
|
|
5246
|
+
logger.warn(
|
|
5247
|
+
{ error, eventType: type, adapter: this.name },
|
|
5248
|
+
"\u{1F4D6} Adapter emit blocked by open circuit \u2014 event dropped"
|
|
5249
|
+
);
|
|
5250
|
+
} else {
|
|
5251
|
+
logger.error(
|
|
5252
|
+
{ error, eventType: type, adapter: this.name, sessionId },
|
|
5253
|
+
"\u{1F4D6} Failed to publish event \u2014 swallowing to prevent daemon crash"
|
|
5254
|
+
);
|
|
5255
|
+
}
|
|
4494
5256
|
published = false;
|
|
4495
5257
|
}
|
|
4496
5258
|
if (published) {
|
|
@@ -5504,7 +6266,11 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
5504
6266
|
return;
|
|
5505
6267
|
}
|
|
5506
6268
|
case "SessionEnd": {
|
|
5507
|
-
|
|
6269
|
+
const finalMessage = extractFinalMessageFromPayload(payload);
|
|
6270
|
+
await this.emitStateChange("session.end", {
|
|
6271
|
+
...sharedData,
|
|
6272
|
+
finalMessage
|
|
6273
|
+
}, context);
|
|
5508
6274
|
return;
|
|
5509
6275
|
}
|
|
5510
6276
|
case "UserPromptSubmit":
|
|
@@ -5521,12 +6287,22 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
5521
6287
|
return;
|
|
5522
6288
|
}
|
|
5523
6289
|
case "PreToolUse": {
|
|
5524
|
-
|
|
6290
|
+
const toolCallName = extractToolNameFromPayload(payload);
|
|
6291
|
+
await this.emitStateChange("agent.tool_call", {
|
|
6292
|
+
...sharedData,
|
|
6293
|
+
toolCallName
|
|
6294
|
+
}, context);
|
|
5525
6295
|
return;
|
|
5526
6296
|
}
|
|
5527
6297
|
case "PostToolUse": {
|
|
6298
|
+
const toolCallName = extractToolNameFromPayload(payload);
|
|
6299
|
+
const toolResult = extractToolResultFromPayload(payload);
|
|
5528
6300
|
const emittedType = isClaudeCodingTool(sharedData.toolName) ? "agent.coding" : "agent.tool_call";
|
|
5529
|
-
await this.emitStateChange(emittedType,
|
|
6301
|
+
await this.emitStateChange(emittedType, {
|
|
6302
|
+
...sharedData,
|
|
6303
|
+
toolCallName,
|
|
6304
|
+
toolResult
|
|
6305
|
+
}, context);
|
|
5530
6306
|
return;
|
|
5531
6307
|
}
|
|
5532
6308
|
case "PostToolUseFailure":
|
|
@@ -5711,7 +6487,7 @@ function extractClaudeTranscriptObservations(payload, transcriptPath) {
|
|
|
5711
6487
|
});
|
|
5712
6488
|
const contentParts = extractClaudeContentParts(payload);
|
|
5713
6489
|
const model = getString(payload, "model") ?? getString(getRecord(payload.message), "model");
|
|
5714
|
-
const
|
|
6490
|
+
const tokens = extractTokenUsageDetailed(payload);
|
|
5715
6491
|
const rawPayload = payload;
|
|
5716
6492
|
const sharedContext = {
|
|
5717
6493
|
// 📖 Pass process.env so terminal detection works from transcript path too
|
|
@@ -5724,25 +6500,57 @@ function extractClaudeTranscriptObservations(payload, transcriptPath) {
|
|
|
5724
6500
|
const sharedData = {
|
|
5725
6501
|
model,
|
|
5726
6502
|
raw: rawPayload,
|
|
5727
|
-
tokensUsed
|
|
6503
|
+
tokensUsed: tokens.total,
|
|
6504
|
+
inputTokens: tokens.input,
|
|
6505
|
+
outputTokens: tokens.output,
|
|
6506
|
+
cachedTokens: tokens.cached
|
|
5728
6507
|
};
|
|
5729
6508
|
const observations = [];
|
|
5730
6509
|
if (contentParts.some((part) => part.type === "thinking")) {
|
|
6510
|
+
const thinkingParts = contentParts.filter((part) => part.type === "thinking");
|
|
6511
|
+
const thinkingText = thinkingParts.map((part) => {
|
|
6512
|
+
const text = part.text;
|
|
6513
|
+
return typeof text === "string" ? text : void 0;
|
|
6514
|
+
}).filter((text) => text !== void 0).join("\n");
|
|
5731
6515
|
observations.push({
|
|
5732
6516
|
context: sharedContext,
|
|
5733
|
-
data:
|
|
6517
|
+
data: {
|
|
6518
|
+
...sharedData,
|
|
6519
|
+
thinkingContent: thinkingText.length > 0 ? thinkingText : void 0
|
|
6520
|
+
},
|
|
5734
6521
|
type: "agent.thinking"
|
|
5735
6522
|
});
|
|
5736
6523
|
}
|
|
5737
6524
|
if (contentParts.some(
|
|
5738
6525
|
(part) => part.type === "text" && typeof part.text === "string" && part.text.trim().length > 0
|
|
5739
6526
|
)) {
|
|
6527
|
+
const messageTexts = contentParts.filter((part) => part.type === "text").map((part) => part.text).filter((text) => text.trim().length > 0);
|
|
6528
|
+
const messageContent = messageTexts.join("\n");
|
|
5740
6529
|
observations.push({
|
|
5741
6530
|
context: sharedContext,
|
|
5742
|
-
data:
|
|
6531
|
+
data: {
|
|
6532
|
+
...sharedData,
|
|
6533
|
+
messageContent: messageContent.length > 0 ? messageContent : void 0
|
|
6534
|
+
},
|
|
5743
6535
|
type: "agent.streaming"
|
|
5744
6536
|
});
|
|
5745
6537
|
}
|
|
6538
|
+
const toolUseParts = contentParts.filter(
|
|
6539
|
+
(part) => part.type === "tool_use" || part.type === "toolUse"
|
|
6540
|
+
);
|
|
6541
|
+
if (toolUseParts.length > 0) {
|
|
6542
|
+
const toolName = getString(toolUseParts[0], "name") ?? getString(toolUseParts[0], "tool");
|
|
6543
|
+
if (toolName) {
|
|
6544
|
+
observations.push({
|
|
6545
|
+
context: sharedContext,
|
|
6546
|
+
data: {
|
|
6547
|
+
...sharedData,
|
|
6548
|
+
toolCallName: toolName
|
|
6549
|
+
},
|
|
6550
|
+
type: "agent.tool_call"
|
|
6551
|
+
});
|
|
6552
|
+
}
|
|
6553
|
+
}
|
|
5746
6554
|
return observations;
|
|
5747
6555
|
}
|
|
5748
6556
|
function extractClaudeContentParts(payload) {
|
|
@@ -5753,23 +6561,28 @@ function extractClaudeContentParts(payload) {
|
|
|
5753
6561
|
}
|
|
5754
6562
|
return content.filter(isRecord2);
|
|
5755
6563
|
}
|
|
5756
|
-
function
|
|
6564
|
+
function extractTokenUsageDetailed(payload) {
|
|
5757
6565
|
const tokens = getNumber(payload, "tokens");
|
|
5758
6566
|
if (tokens !== void 0) {
|
|
5759
|
-
return tokens;
|
|
6567
|
+
return { total: tokens };
|
|
5760
6568
|
}
|
|
5761
6569
|
const usage = getRecord(payload.usage);
|
|
5762
6570
|
if (!usage) {
|
|
5763
|
-
return
|
|
6571
|
+
return {};
|
|
5764
6572
|
}
|
|
5765
6573
|
const totalTokens = getNumber(usage, "total_tokens");
|
|
5766
6574
|
if (totalTokens !== void 0) {
|
|
5767
|
-
return
|
|
6575
|
+
return {
|
|
6576
|
+
total: totalTokens,
|
|
6577
|
+
input: getNumber(usage, "input_tokens"),
|
|
6578
|
+
output: getNumber(usage, "output_tokens"),
|
|
6579
|
+
cached: getNumber(usage, "cached_tokens")
|
|
6580
|
+
};
|
|
5768
6581
|
}
|
|
5769
6582
|
const inputTokens = getNumber(usage, "input_tokens") ?? 0;
|
|
5770
6583
|
const outputTokens = getNumber(usage, "output_tokens") ?? 0;
|
|
5771
6584
|
const usageSum = inputTokens + outputTokens;
|
|
5772
|
-
return usageSum > 0 ? usageSum :
|
|
6585
|
+
return usageSum > 0 ? { total: usageSum, input: inputTokens, output: outputTokens } : {};
|
|
5773
6586
|
}
|
|
5774
6587
|
function extractClaudeToolInput(payload) {
|
|
5775
6588
|
const toolInput = getRecord(payload.tool_input) ?? getRecord(payload.toolInput);
|
|
@@ -5865,6 +6678,51 @@ function getString(payload, key) {
|
|
|
5865
6678
|
const value = payload[key];
|
|
5866
6679
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
5867
6680
|
}
|
|
6681
|
+
function extractToolNameFromPayload(payload) {
|
|
6682
|
+
const directToolName = getString(payload, "tool_name") ?? getString(payload, "toolName");
|
|
6683
|
+
if (directToolName) {
|
|
6684
|
+
return directToolName;
|
|
6685
|
+
}
|
|
6686
|
+
const toolUse = getRecord(payload.tool_use) ?? getRecord(payload.toolUse);
|
|
6687
|
+
if (toolUse) {
|
|
6688
|
+
return getString(toolUse, "name") ?? getString(toolUse, "tool");
|
|
6689
|
+
}
|
|
6690
|
+
const toolInput = getRecord(payload.tool_input) ?? getRecord(payload.toolInput);
|
|
6691
|
+
if (toolInput) {
|
|
6692
|
+
return getString(toolInput, "tool_name") ?? getString(toolInput, "type");
|
|
6693
|
+
}
|
|
6694
|
+
return void 0;
|
|
6695
|
+
}
|
|
6696
|
+
function extractToolResultFromPayload(payload) {
|
|
6697
|
+
const directResult = getString(payload, "result") ?? getString(payload, "output");
|
|
6698
|
+
if (directResult) {
|
|
6699
|
+
return directResult;
|
|
6700
|
+
}
|
|
6701
|
+
const toolResult = getRecord(payload.tool_result) ?? getRecord(payload.toolResult);
|
|
6702
|
+
if (toolResult) {
|
|
6703
|
+
return getString(toolResult, "content") ?? getString(toolResult, "output");
|
|
6704
|
+
}
|
|
6705
|
+
const errorField = getString(payload, "error") ?? getString(payload, "error_message");
|
|
6706
|
+
if (errorField) {
|
|
6707
|
+
return errorField;
|
|
6708
|
+
}
|
|
6709
|
+
return void 0;
|
|
6710
|
+
}
|
|
6711
|
+
function extractFinalMessageFromPayload(payload) {
|
|
6712
|
+
const directMessage = getString(payload, "final_message") ?? getString(payload, "finalMessage") ?? getString(payload, "summary") ?? getString(payload, "completion_message");
|
|
6713
|
+
if (directMessage) {
|
|
6714
|
+
return directMessage;
|
|
6715
|
+
}
|
|
6716
|
+
const result = getString(payload, "result") ?? getString(payload, "output") ?? getString(payload, "message");
|
|
6717
|
+
if (result) {
|
|
6718
|
+
return result;
|
|
6719
|
+
}
|
|
6720
|
+
const stats = getRecord(payload.stats);
|
|
6721
|
+
if (stats) {
|
|
6722
|
+
return getString(stats, "summary") ?? getString(stats, "completion_summary");
|
|
6723
|
+
}
|
|
6724
|
+
return void 0;
|
|
6725
|
+
}
|
|
5868
6726
|
|
|
5869
6727
|
// src/adapters/copilot-cli.ts
|
|
5870
6728
|
import { execFile as execFileCallback5 } from "child_process";
|
|
@@ -10828,7 +11686,17 @@ var OpenCodeAdapter = class extends BaseAdapter {
|
|
|
10828
11686
|
project: extractOpenCodeProject(payload),
|
|
10829
11687
|
raw: payload,
|
|
10830
11688
|
toolInput: extractOpenCodeToolInput(payload),
|
|
10831
|
-
toolName: extractOpenCodeToolName(payload)
|
|
11689
|
+
toolName: extractOpenCodeToolName(payload),
|
|
11690
|
+
// 📖 Extract token usage from payload (with input/output/cached breakdown)
|
|
11691
|
+
...(() => {
|
|
11692
|
+
const tokens = extractOpenCodeTokens(payload);
|
|
11693
|
+
return {
|
|
11694
|
+
tokensUsed: tokens.total,
|
|
11695
|
+
inputTokens: tokens.inputTokens,
|
|
11696
|
+
outputTokens: tokens.outputTokens,
|
|
11697
|
+
cachedTokens: tokens.cachedTokens
|
|
11698
|
+
};
|
|
11699
|
+
})()
|
|
10832
11700
|
};
|
|
10833
11701
|
switch (eventType) {
|
|
10834
11702
|
case "session.created": {
|
|
@@ -10838,7 +11706,11 @@ var OpenCodeAdapter = class extends BaseAdapter {
|
|
|
10838
11706
|
return;
|
|
10839
11707
|
}
|
|
10840
11708
|
case "session.deleted": {
|
|
10841
|
-
|
|
11709
|
+
const finalMessage = extractOpenCodeFinalMessage(payload);
|
|
11710
|
+
await this.emitStateChange("session.end", {
|
|
11711
|
+
...sharedData,
|
|
11712
|
+
finalMessage
|
|
11713
|
+
}, context);
|
|
10842
11714
|
return;
|
|
10843
11715
|
}
|
|
10844
11716
|
case "session.error": {
|
|
@@ -10853,9 +11725,21 @@ var OpenCodeAdapter = class extends BaseAdapter {
|
|
|
10853
11725
|
await this.emitStateChange("agent.compact", sharedData, context);
|
|
10854
11726
|
return;
|
|
10855
11727
|
}
|
|
11728
|
+
case "thinking": {
|
|
11729
|
+
const thinkingContent = extractOpenCodeThinkingContent(payload);
|
|
11730
|
+
await this.emitStateChange("agent.thinking", {
|
|
11731
|
+
...sharedData,
|
|
11732
|
+
thinkingContent
|
|
11733
|
+
}, context);
|
|
11734
|
+
return;
|
|
11735
|
+
}
|
|
10856
11736
|
case "message.updated":
|
|
10857
11737
|
case "message.part.updated": {
|
|
10858
|
-
|
|
11738
|
+
const messageContent = extractOpenCodeMessageContent(payload);
|
|
11739
|
+
await this.emitStateChange("agent.streaming", {
|
|
11740
|
+
...sharedData,
|
|
11741
|
+
messageContent
|
|
11742
|
+
}, context);
|
|
10859
11743
|
return;
|
|
10860
11744
|
}
|
|
10861
11745
|
case "permission.asked": {
|
|
@@ -10863,12 +11747,22 @@ var OpenCodeAdapter = class extends BaseAdapter {
|
|
|
10863
11747
|
return;
|
|
10864
11748
|
}
|
|
10865
11749
|
case "tool.execute.before": {
|
|
10866
|
-
|
|
11750
|
+
const toolCallName = extractOpenCodeToolName(payload);
|
|
11751
|
+
await this.emitStateChange("agent.tool_call", {
|
|
11752
|
+
...sharedData,
|
|
11753
|
+
toolCallName
|
|
11754
|
+
}, context);
|
|
10867
11755
|
return;
|
|
10868
11756
|
}
|
|
10869
11757
|
case "tool.execute.after": {
|
|
11758
|
+
const toolCallName = extractOpenCodeToolName(payload);
|
|
11759
|
+
const toolResult = extractOpenCodeToolResult(payload);
|
|
10870
11760
|
const emittedType = isOpenCodeCodingTool(sharedData.toolName) ? "agent.coding" : "agent.tool_call";
|
|
10871
|
-
await this.emitStateChange(emittedType,
|
|
11761
|
+
await this.emitStateChange(emittedType, {
|
|
11762
|
+
...sharedData,
|
|
11763
|
+
toolCallName,
|
|
11764
|
+
toolResult
|
|
11765
|
+
}, context);
|
|
10872
11766
|
return;
|
|
10873
11767
|
}
|
|
10874
11768
|
default: {
|
|
@@ -11035,9 +11929,599 @@ function getString10(payload, key) {
|
|
|
11035
11929
|
const value = payload[key];
|
|
11036
11930
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
11037
11931
|
}
|
|
11038
|
-
|
|
11039
|
-
|
|
11040
|
-
|
|
11932
|
+
function extractOpenCodeFinalMessage(payload) {
|
|
11933
|
+
const directMessage = getString10(payload, "final_message") ?? getString10(payload, "finalMessage") ?? getString10(payload, "summary") ?? getString10(payload, "completion_message");
|
|
11934
|
+
if (directMessage) {
|
|
11935
|
+
return directMessage;
|
|
11936
|
+
}
|
|
11937
|
+
const result = getString10(payload, "result") ?? getString10(payload, "output") ?? getString10(getRecord9(payload.properties), "result");
|
|
11938
|
+
if (result) {
|
|
11939
|
+
return result;
|
|
11940
|
+
}
|
|
11941
|
+
return void 0;
|
|
11942
|
+
}
|
|
11943
|
+
function extractOpenCodeToolResult(payload) {
|
|
11944
|
+
const directResult = getString10(payload, "result") ?? getString10(payload, "output") ?? getString10(payload, "toolResult");
|
|
11945
|
+
if (directResult) {
|
|
11946
|
+
return directResult;
|
|
11947
|
+
}
|
|
11948
|
+
const toolResult = getRecord9(payload.tool_result) ?? getRecord9(payload.toolResult);
|
|
11949
|
+
if (toolResult) {
|
|
11950
|
+
return getString10(toolResult, "content") ?? getString10(toolResult, "output");
|
|
11951
|
+
}
|
|
11952
|
+
const props = getRecord9(payload.properties);
|
|
11953
|
+
if (props) {
|
|
11954
|
+
const nestedResult = getRecord9(props.tool_result) ?? getRecord9(props.toolResult);
|
|
11955
|
+
if (nestedResult) {
|
|
11956
|
+
return getString10(nestedResult, "content") ?? getString10(nestedResult, "output");
|
|
11957
|
+
}
|
|
11958
|
+
}
|
|
11959
|
+
return void 0;
|
|
11960
|
+
}
|
|
11961
|
+
function extractOpenCodeMessageContent(payload) {
|
|
11962
|
+
const directMessage = getString10(payload, "text") ?? getString10(payload, "message") ?? getString10(payload, "content") ?? getString10(payload, "output");
|
|
11963
|
+
if (directMessage) {
|
|
11964
|
+
return directMessage;
|
|
11965
|
+
}
|
|
11966
|
+
const part = getRecord9(payload.part) ?? getRecord9(getRecord9(payload.properties)?.part);
|
|
11967
|
+
if (part) {
|
|
11968
|
+
return getString10(part, "text") ?? getString10(part, "content");
|
|
11969
|
+
}
|
|
11970
|
+
const props = getRecord9(payload.properties);
|
|
11971
|
+
if (props) {
|
|
11972
|
+
const message = getRecord9(props.message) ?? getRecord9(props.info);
|
|
11973
|
+
if (message) {
|
|
11974
|
+
return getString10(message, "text") ?? getString10(message, "content");
|
|
11975
|
+
}
|
|
11976
|
+
return getString10(props, "text") ?? getString10(props, "message");
|
|
11977
|
+
}
|
|
11978
|
+
return void 0;
|
|
11979
|
+
}
|
|
11980
|
+
function extractOpenCodeThinkingContent(payload) {
|
|
11981
|
+
const directThinking = getString10(payload, "thinking") ?? getString10(payload, "thinkingContent") ?? getString10(payload, "reasoning") ?? getString10(payload, "thought");
|
|
11982
|
+
if (directThinking) {
|
|
11983
|
+
return directThinking;
|
|
11984
|
+
}
|
|
11985
|
+
const props = getRecord9(payload.properties);
|
|
11986
|
+
if (props) {
|
|
11987
|
+
return getString10(props, "thinking") ?? getString10(props, "reasoning") ?? getString10(props, "thought");
|
|
11988
|
+
}
|
|
11989
|
+
return void 0;
|
|
11990
|
+
}
|
|
11991
|
+
function extractOpenCodeTokens(payload) {
|
|
11992
|
+
const directTokens = getNumber8(payload, "tokensUsed") ?? getNumber8(payload, "tokens");
|
|
11993
|
+
if (directTokens !== void 0) {
|
|
11994
|
+
return { total: directTokens };
|
|
11995
|
+
}
|
|
11996
|
+
const props = getRecord9(payload.properties);
|
|
11997
|
+
if (props) {
|
|
11998
|
+
const info = getRecord9(props.info);
|
|
11999
|
+
if (info) {
|
|
12000
|
+
const tokens = getRecord9(info.tokens);
|
|
12001
|
+
if (tokens) {
|
|
12002
|
+
const inputTokens = getNumber8(tokens, "input") ?? 0;
|
|
12003
|
+
const outputTokens = getNumber8(tokens, "output") ?? 0;
|
|
12004
|
+
const reasoningTokens = getNumber8(tokens, "reasoning") ?? 0;
|
|
12005
|
+
const total = inputTokens + outputTokens + reasoningTokens;
|
|
12006
|
+
return total > 0 ? {
|
|
12007
|
+
total,
|
|
12008
|
+
inputTokens,
|
|
12009
|
+
outputTokens,
|
|
12010
|
+
// reasoning tokens are often billed as cached on some providers
|
|
12011
|
+
cachedTokens: reasoningTokens
|
|
12012
|
+
} : {};
|
|
12013
|
+
}
|
|
12014
|
+
}
|
|
12015
|
+
const fallbackTokens = getNumber8(props, "tokensUsed") ?? getNumber8(props, "tokens");
|
|
12016
|
+
if (fallbackTokens !== void 0) {
|
|
12017
|
+
return { total: fallbackTokens };
|
|
12018
|
+
}
|
|
12019
|
+
}
|
|
12020
|
+
return {};
|
|
12021
|
+
}
|
|
12022
|
+
|
|
12023
|
+
// src/adapters/pi.ts
|
|
12024
|
+
import { execFile as execFile14 } from "child_process";
|
|
12025
|
+
import { join as join13 } from "path";
|
|
12026
|
+
import { promisify as promisify14 } from "util";
|
|
12027
|
+
var execFileAsync = promisify14(execFile14);
|
|
12028
|
+
var PiAdapter = class extends BaseAdapter {
|
|
12029
|
+
displayName = "Pi (MiniMax)";
|
|
12030
|
+
name = "pi";
|
|
12031
|
+
strategies = [
|
|
12032
|
+
"process-detect",
|
|
12033
|
+
"api-client",
|
|
12034
|
+
"log-watch"
|
|
12035
|
+
];
|
|
12036
|
+
apiPort = 7890;
|
|
12037
|
+
logPath;
|
|
12038
|
+
poller = null;
|
|
12039
|
+
activePiSessions = /* @__PURE__ */ new Map();
|
|
12040
|
+
lastCheckedTime = 0;
|
|
12041
|
+
constructor(options) {
|
|
12042
|
+
super(options);
|
|
12043
|
+
this.logPath = join13(
|
|
12044
|
+
options.homeDirectory ?? process.env.HOME ?? "",
|
|
12045
|
+
".pi",
|
|
12046
|
+
"agent.log"
|
|
12047
|
+
);
|
|
12048
|
+
}
|
|
12049
|
+
start() {
|
|
12050
|
+
if (this.getStatus().running) {
|
|
12051
|
+
return Promise.resolve();
|
|
12052
|
+
}
|
|
12053
|
+
this.setRunning(true);
|
|
12054
|
+
this.startPolling();
|
|
12055
|
+
logger.info({ adapter: this.name }, "Pi adapter started");
|
|
12056
|
+
return Promise.resolve();
|
|
12057
|
+
}
|
|
12058
|
+
stop() {
|
|
12059
|
+
if (this.poller !== null) {
|
|
12060
|
+
clearInterval(this.poller);
|
|
12061
|
+
this.poller = null;
|
|
12062
|
+
}
|
|
12063
|
+
this.setRunning(false);
|
|
12064
|
+
logger.info({ adapter: this.name }, "Pi adapter stopped");
|
|
12065
|
+
return Promise.resolve();
|
|
12066
|
+
}
|
|
12067
|
+
async handleHook(payload) {
|
|
12068
|
+
const normalized = this.parseNormalizedHookPayload(payload);
|
|
12069
|
+
if (normalized === null) {
|
|
12070
|
+
return;
|
|
12071
|
+
}
|
|
12072
|
+
const context = {
|
|
12073
|
+
cwd: normalized.cwd,
|
|
12074
|
+
pid: normalized.pid,
|
|
12075
|
+
sessionId: normalized.sessionId,
|
|
12076
|
+
source: "pi-hook"
|
|
12077
|
+
};
|
|
12078
|
+
const eventType = this.mapEventType(normalized.type ?? "");
|
|
12079
|
+
const eventData = this.buildEventData(eventType, normalized);
|
|
12080
|
+
await this.emit(eventType, eventData, context);
|
|
12081
|
+
}
|
|
12082
|
+
startPolling() {
|
|
12083
|
+
this.poller = setInterval(() => {
|
|
12084
|
+
void this.pollPiActivity();
|
|
12085
|
+
}, 2e3);
|
|
12086
|
+
}
|
|
12087
|
+
async pollPiActivity() {
|
|
12088
|
+
const running = await this.detectPiInstance();
|
|
12089
|
+
if (!running) {
|
|
12090
|
+
for (const [sessionId, activity] of this.activePiSessions) {
|
|
12091
|
+
if (activity.state !== "idle") {
|
|
12092
|
+
activity.state = "idle";
|
|
12093
|
+
await this.emitIdle(sessionId);
|
|
12094
|
+
}
|
|
12095
|
+
}
|
|
12096
|
+
return;
|
|
12097
|
+
}
|
|
12098
|
+
try {
|
|
12099
|
+
const response = await fetch(
|
|
12100
|
+
`http://127.0.0.1:${this.apiPort}/api/status`,
|
|
12101
|
+
{
|
|
12102
|
+
signal: AbortSignal.timeout(500)
|
|
12103
|
+
}
|
|
12104
|
+
);
|
|
12105
|
+
if (response.ok) {
|
|
12106
|
+
const data = await response.json();
|
|
12107
|
+
await this.processPiApiResponse(data);
|
|
12108
|
+
}
|
|
12109
|
+
} catch {
|
|
12110
|
+
await this.checkMiniMaxApi();
|
|
12111
|
+
}
|
|
12112
|
+
}
|
|
12113
|
+
async detectPiInstance() {
|
|
12114
|
+
try {
|
|
12115
|
+
const result = await execFileAsync("pgrep", ["-l", "pi|minimax"]);
|
|
12116
|
+
if (result.stdout.includes("pi") || result.stdout.includes("minimax")) {
|
|
12117
|
+
return true;
|
|
12118
|
+
}
|
|
12119
|
+
} catch {
|
|
12120
|
+
}
|
|
12121
|
+
try {
|
|
12122
|
+
const response = await fetch(
|
|
12123
|
+
`http://127.0.0.1:${this.apiPort}/health`,
|
|
12124
|
+
{
|
|
12125
|
+
signal: AbortSignal.timeout(200)
|
|
12126
|
+
}
|
|
12127
|
+
);
|
|
12128
|
+
if (response.ok) {
|
|
12129
|
+
return true;
|
|
12130
|
+
}
|
|
12131
|
+
} catch {
|
|
12132
|
+
}
|
|
12133
|
+
return false;
|
|
12134
|
+
}
|
|
12135
|
+
async checkMiniMaxApi() {
|
|
12136
|
+
try {
|
|
12137
|
+
const response = await fetch("http://127.0.0.1:3000/api/agent/status", {
|
|
12138
|
+
signal: AbortSignal.timeout(500)
|
|
12139
|
+
});
|
|
12140
|
+
if (response.ok) {
|
|
12141
|
+
const data = await response.json();
|
|
12142
|
+
await this.processPiApiResponse(data);
|
|
12143
|
+
}
|
|
12144
|
+
} catch {
|
|
12145
|
+
}
|
|
12146
|
+
}
|
|
12147
|
+
async processPiApiResponse(data) {
|
|
12148
|
+
const rawSession = data.sessionId ?? data.project ?? "default";
|
|
12149
|
+
const sessionId = `pi:${rawSession.replace(/[^a-zA-Z0-9-_]/g, "-")}`;
|
|
12150
|
+
let activity = this.activePiSessions.get(sessionId);
|
|
12151
|
+
if (!activity) {
|
|
12152
|
+
activity = { sessionId, state: "idle" };
|
|
12153
|
+
this.activePiSessions.set(sessionId, activity);
|
|
12154
|
+
await this.emitSessionStart(sessionId, data);
|
|
12155
|
+
}
|
|
12156
|
+
const rawState = data.state ?? "idle";
|
|
12157
|
+
const state = rawState;
|
|
12158
|
+
if (state !== activity.state) {
|
|
12159
|
+
switch (state) {
|
|
12160
|
+
case "thinking": {
|
|
12161
|
+
const rawThinking = data.thinking;
|
|
12162
|
+
if (rawThinking) {
|
|
12163
|
+
await this.emitThinking(sessionId, rawThinking);
|
|
12164
|
+
}
|
|
12165
|
+
break;
|
|
12166
|
+
}
|
|
12167
|
+
case "tool": {
|
|
12168
|
+
const rawFilePath = data.filePath;
|
|
12169
|
+
const rawCommand = data.command;
|
|
12170
|
+
const rawToolName = data.toolName ?? "unknown";
|
|
12171
|
+
await this.emitToolCall(
|
|
12172
|
+
sessionId,
|
|
12173
|
+
{
|
|
12174
|
+
filePath: rawFilePath ?? "",
|
|
12175
|
+
command: rawCommand ?? ""
|
|
12176
|
+
},
|
|
12177
|
+
rawToolName
|
|
12178
|
+
);
|
|
12179
|
+
break;
|
|
12180
|
+
}
|
|
12181
|
+
case "output": {
|
|
12182
|
+
const rawOutput = data.output;
|
|
12183
|
+
if (rawOutput) {
|
|
12184
|
+
await this.emitOutput(sessionId, rawOutput);
|
|
12185
|
+
}
|
|
12186
|
+
break;
|
|
12187
|
+
}
|
|
12188
|
+
case "error": {
|
|
12189
|
+
const rawError = data.error ?? "Unknown error";
|
|
12190
|
+
await this.emitError(sessionId, rawError);
|
|
12191
|
+
break;
|
|
12192
|
+
}
|
|
12193
|
+
case "idle":
|
|
12194
|
+
await this.emitIdle(sessionId);
|
|
12195
|
+
break;
|
|
12196
|
+
}
|
|
12197
|
+
activity.state = state;
|
|
12198
|
+
}
|
|
12199
|
+
}
|
|
12200
|
+
async emitSessionStart(sessionId, data) {
|
|
12201
|
+
const rawProject = data.project ?? "pi-project";
|
|
12202
|
+
const rawModel = data.model ?? "minimax/moonshot";
|
|
12203
|
+
const eventData = {
|
|
12204
|
+
state: "session.start",
|
|
12205
|
+
project: rawProject,
|
|
12206
|
+
model: rawModel,
|
|
12207
|
+
raw: data
|
|
12208
|
+
};
|
|
12209
|
+
await this.emit("session.start", eventData, { sessionId });
|
|
12210
|
+
}
|
|
12211
|
+
async emitThinking(sessionId, content) {
|
|
12212
|
+
if (!content) return;
|
|
12213
|
+
const eventData = {
|
|
12214
|
+
state: "agent.thinking",
|
|
12215
|
+
thinkingContent: content
|
|
12216
|
+
};
|
|
12217
|
+
await this.emit("agent.thinking", eventData, { sessionId });
|
|
12218
|
+
}
|
|
12219
|
+
async emitToolCall(sessionId, toolInput, toolName) {
|
|
12220
|
+
const eventData = {
|
|
12221
|
+
state: "agent.tool_call",
|
|
12222
|
+
toolCallName: toolName,
|
|
12223
|
+
toolInput,
|
|
12224
|
+
activeFile: toolInput.filePath
|
|
12225
|
+
};
|
|
12226
|
+
await this.emit("agent.tool_call", eventData, { sessionId });
|
|
12227
|
+
}
|
|
12228
|
+
async emitOutput(sessionId, content) {
|
|
12229
|
+
if (!content) return;
|
|
12230
|
+
const eventData = {
|
|
12231
|
+
state: "agent.streaming",
|
|
12232
|
+
messageContent: content
|
|
12233
|
+
};
|
|
12234
|
+
await this.emit("agent.streaming", eventData, { sessionId });
|
|
12235
|
+
}
|
|
12236
|
+
async emitError(sessionId, errorMessage) {
|
|
12237
|
+
const eventData = {
|
|
12238
|
+
state: "agent.error",
|
|
12239
|
+
errorMessage,
|
|
12240
|
+
errorType: "api_error"
|
|
12241
|
+
};
|
|
12242
|
+
await this.emit("agent.error", eventData, { sessionId });
|
|
12243
|
+
}
|
|
12244
|
+
async emitIdle(sessionId) {
|
|
12245
|
+
const eventData = {
|
|
12246
|
+
state: "agent.idle"
|
|
12247
|
+
};
|
|
12248
|
+
await this.emit("agent.idle", eventData, { sessionId });
|
|
12249
|
+
}
|
|
12250
|
+
mapEventType(type) {
|
|
12251
|
+
const mapping = {
|
|
12252
|
+
"session.start": "session.start",
|
|
12253
|
+
"session.end": "session.end",
|
|
12254
|
+
"task.start": "task.start",
|
|
12255
|
+
"task.complete": "task.complete",
|
|
12256
|
+
thinking: "agent.thinking",
|
|
12257
|
+
tool: "agent.tool_call",
|
|
12258
|
+
coding: "agent.coding",
|
|
12259
|
+
output: "agent.streaming",
|
|
12260
|
+
message: "agent.streaming",
|
|
12261
|
+
ask: "agent.asking_user",
|
|
12262
|
+
error: "agent.error",
|
|
12263
|
+
idle: "agent.idle",
|
|
12264
|
+
compact: "agent.compact"
|
|
12265
|
+
};
|
|
12266
|
+
return mapping[type] ?? "agent.streaming";
|
|
12267
|
+
}
|
|
12268
|
+
buildEventData(eventType, payload) {
|
|
12269
|
+
const data = payload.data ?? {};
|
|
12270
|
+
return {
|
|
12271
|
+
state: eventType,
|
|
12272
|
+
project: data.project,
|
|
12273
|
+
activeFile: data.activeFile,
|
|
12274
|
+
model: data.model,
|
|
12275
|
+
toolInput: data.toolInput,
|
|
12276
|
+
toolCallName: data.toolCallName,
|
|
12277
|
+
thinkingContent: data.thinkingContent,
|
|
12278
|
+
messageContent: data.messageContent,
|
|
12279
|
+
finalMessage: data.finalMessage,
|
|
12280
|
+
toolResult: data.toolResult,
|
|
12281
|
+
errorMessage: data.errorMessage,
|
|
12282
|
+
errorType: data.errorType,
|
|
12283
|
+
raw: data.raw
|
|
12284
|
+
};
|
|
12285
|
+
}
|
|
12286
|
+
};
|
|
12287
|
+
|
|
12288
|
+
// src/adapters/zed.ts
|
|
12289
|
+
import { readFile as readFile12 } from "fs/promises";
|
|
12290
|
+
import { basename as basename11, join as join14 } from "path";
|
|
12291
|
+
var ZedAdapter = class extends BaseAdapter {
|
|
12292
|
+
displayName = "Zed AI";
|
|
12293
|
+
name = "zed";
|
|
12294
|
+
strategies = [
|
|
12295
|
+
"process-detect",
|
|
12296
|
+
"api-client"
|
|
12297
|
+
];
|
|
12298
|
+
logPaths;
|
|
12299
|
+
apiPort = 9876;
|
|
12300
|
+
pollIntervalMs;
|
|
12301
|
+
poller = null;
|
|
12302
|
+
lastEventTime = 0;
|
|
12303
|
+
activeZedSessions = /* @__PURE__ */ new Map();
|
|
12304
|
+
constructor(options) {
|
|
12305
|
+
super(options);
|
|
12306
|
+
this.pollIntervalMs = 2e3;
|
|
12307
|
+
this.logPaths = [
|
|
12308
|
+
join14(options.homeDirectory ?? process.env.HOME ?? "", ".config", "zed", "logs", "agent.log"),
|
|
12309
|
+
"/tmp/zed-agent.log"
|
|
12310
|
+
];
|
|
12311
|
+
}
|
|
12312
|
+
start() {
|
|
12313
|
+
if (this.getStatus().running) {
|
|
12314
|
+
return Promise.resolve();
|
|
12315
|
+
}
|
|
12316
|
+
this.setRunning(true);
|
|
12317
|
+
this.startPolling();
|
|
12318
|
+
logger.info({ adapter: this.name }, "Zed adapter started");
|
|
12319
|
+
return Promise.resolve();
|
|
12320
|
+
}
|
|
12321
|
+
stop() {
|
|
12322
|
+
if (this.poller !== null) {
|
|
12323
|
+
clearInterval(this.poller);
|
|
12324
|
+
this.poller = null;
|
|
12325
|
+
}
|
|
12326
|
+
this.setRunning(false);
|
|
12327
|
+
logger.info({ adapter: this.name }, "Zed adapter stopped");
|
|
12328
|
+
return Promise.resolve();
|
|
12329
|
+
}
|
|
12330
|
+
async handleHook(payload) {
|
|
12331
|
+
const normalized = this.parseNormalizedHookPayload(payload);
|
|
12332
|
+
if (normalized === null) {
|
|
12333
|
+
return;
|
|
12334
|
+
}
|
|
12335
|
+
const context = {
|
|
12336
|
+
cwd: normalized.cwd,
|
|
12337
|
+
pid: normalized.pid,
|
|
12338
|
+
sessionId: normalized.sessionId,
|
|
12339
|
+
source: "zed-hook"
|
|
12340
|
+
};
|
|
12341
|
+
const eventType = this.mapEventType(normalized.type ?? "");
|
|
12342
|
+
const eventData = this.buildEventData(eventType, normalized);
|
|
12343
|
+
await this.emit(eventType, eventData, context);
|
|
12344
|
+
}
|
|
12345
|
+
startPolling() {
|
|
12346
|
+
this.poller = setInterval(() => {
|
|
12347
|
+
void this.pollZedStatus();
|
|
12348
|
+
}, this.pollIntervalMs);
|
|
12349
|
+
}
|
|
12350
|
+
async pollZedStatus() {
|
|
12351
|
+
try {
|
|
12352
|
+
const response = await fetch(`http://127.0.0.1:${this.apiPort}/api/agent/status`, {
|
|
12353
|
+
signal: AbortSignal.timeout(1e3)
|
|
12354
|
+
});
|
|
12355
|
+
if (response.ok) {
|
|
12356
|
+
const data = await response.json();
|
|
12357
|
+
if (data.sessionId && typeof data.sessionId === "string") {
|
|
12358
|
+
const sessionId = `zed:${data.sessionId}`;
|
|
12359
|
+
if (!this.activeZedSessions.has(sessionId)) {
|
|
12360
|
+
this.activeZedSessions.set(sessionId, sessionId);
|
|
12361
|
+
await this.emitSessionStart(sessionId, data);
|
|
12362
|
+
}
|
|
12363
|
+
if (data.state === "thinking" && this.lastEventTime < Date.now() - 5e3) {
|
|
12364
|
+
const rawThinking = data.thinking;
|
|
12365
|
+
if (rawThinking) {
|
|
12366
|
+
await this.emitThinking(sessionId, rawThinking);
|
|
12367
|
+
}
|
|
12368
|
+
} else if (data.state === "tool" && data.toolName) {
|
|
12369
|
+
const rawFilePath = data.filePath;
|
|
12370
|
+
const rawCommand = data.command;
|
|
12371
|
+
const rawToolName = data.toolName ?? "unknown";
|
|
12372
|
+
await this.emitToolCall(
|
|
12373
|
+
sessionId,
|
|
12374
|
+
{
|
|
12375
|
+
filePath: rawFilePath ?? "",
|
|
12376
|
+
command: rawCommand ?? ""
|
|
12377
|
+
},
|
|
12378
|
+
rawToolName
|
|
12379
|
+
);
|
|
12380
|
+
} else if (data.state === "idle") {
|
|
12381
|
+
await this.emitIdle(sessionId);
|
|
12382
|
+
}
|
|
12383
|
+
}
|
|
12384
|
+
}
|
|
12385
|
+
} catch {
|
|
12386
|
+
await this.checkLogFiles();
|
|
12387
|
+
}
|
|
12388
|
+
}
|
|
12389
|
+
async checkLogFiles() {
|
|
12390
|
+
for (const logPath of this.logPaths) {
|
|
12391
|
+
try {
|
|
12392
|
+
const content = await readFile12(logPath, "utf8");
|
|
12393
|
+
await this.parseLogContent(content);
|
|
12394
|
+
} catch {
|
|
12395
|
+
}
|
|
12396
|
+
}
|
|
12397
|
+
}
|
|
12398
|
+
async parseLogContent(content) {
|
|
12399
|
+
const lines = content.split("\n").filter((line) => line.trim());
|
|
12400
|
+
for (const line of lines) {
|
|
12401
|
+
if (this.lastEventTime > 0 && this.lastEventTime >= Date.now() - 2e3) {
|
|
12402
|
+
continue;
|
|
12403
|
+
}
|
|
12404
|
+
const event = this.extractZedEventFromLog(line);
|
|
12405
|
+
if (event) {
|
|
12406
|
+
await this.handleHook(event);
|
|
12407
|
+
this.lastEventTime = Date.now();
|
|
12408
|
+
}
|
|
12409
|
+
}
|
|
12410
|
+
}
|
|
12411
|
+
extractZedEventFromLog(line) {
|
|
12412
|
+
try {
|
|
12413
|
+
const parsed = JSON.parse(line);
|
|
12414
|
+
if (!parsed.type || typeof parsed.type !== "string") {
|
|
12415
|
+
return null;
|
|
12416
|
+
}
|
|
12417
|
+
const rawSessionId = parsed.sessionId;
|
|
12418
|
+
const rawWorkspace = parsed.workspace;
|
|
12419
|
+
const sessionId = rawSessionId ? rawSessionId : rawWorkspace ? `zed:${basename11(rawWorkspace)}` : `zed:${Date.now()}`;
|
|
12420
|
+
const rawCwd = parsed.cwd ?? rawWorkspace;
|
|
12421
|
+
return {
|
|
12422
|
+
type: parsed.type,
|
|
12423
|
+
sessionId,
|
|
12424
|
+
cwd: rawCwd,
|
|
12425
|
+
data: {
|
|
12426
|
+
project: parsed.project ?? rawWorkspace ? basename11(String(rawWorkspace)) : void 0,
|
|
12427
|
+
model: parsed.model,
|
|
12428
|
+
state: parsed.type,
|
|
12429
|
+
thinkingContent: parsed.thinking,
|
|
12430
|
+
toolCallName: parsed.toolName,
|
|
12431
|
+
toolInput: parsed.toolInput,
|
|
12432
|
+
messageContent: parsed.message ?? parsed.output,
|
|
12433
|
+
errorMessage: parsed.error,
|
|
12434
|
+
raw: parsed
|
|
12435
|
+
}
|
|
12436
|
+
};
|
|
12437
|
+
} catch {
|
|
12438
|
+
if (line.includes("[zed:agent]")) {
|
|
12439
|
+
const cleaned = line.replace(/^\[.*?\] \[.*?\] /, "");
|
|
12440
|
+
if (cleaned.includes("Thinking:")) {
|
|
12441
|
+
return { type: "thinking", thinkingContent: cleaned.replace("Thinking:", "").trim() };
|
|
12442
|
+
}
|
|
12443
|
+
if (cleaned.includes("Executing tool:")) {
|
|
12444
|
+
return { type: "tool", toolCallName: cleaned.replace("Executing tool:", "").trim() };
|
|
12445
|
+
}
|
|
12446
|
+
if (cleaned.includes("Error:")) {
|
|
12447
|
+
return { type: "error", errorMessage: cleaned.replace("Error:", "").trim() };
|
|
12448
|
+
}
|
|
12449
|
+
}
|
|
12450
|
+
return null;
|
|
12451
|
+
}
|
|
12452
|
+
}
|
|
12453
|
+
async emitSessionStart(sessionId, _data) {
|
|
12454
|
+
const eventData = {
|
|
12455
|
+
state: "session.start",
|
|
12456
|
+
project: sessionId.split(":")[1] ?? "unknown"
|
|
12457
|
+
};
|
|
12458
|
+
await this.emit("session.start", eventData, { sessionId });
|
|
12459
|
+
}
|
|
12460
|
+
async emitThinking(sessionId, content) {
|
|
12461
|
+
if (!content) return;
|
|
12462
|
+
const eventData = {
|
|
12463
|
+
state: "agent.thinking",
|
|
12464
|
+
thinkingContent: content
|
|
12465
|
+
};
|
|
12466
|
+
await this.emit("agent.thinking", eventData, { sessionId });
|
|
12467
|
+
this.lastEventTime = Date.now();
|
|
12468
|
+
}
|
|
12469
|
+
async emitToolCall(sessionId, toolInput, toolName) {
|
|
12470
|
+
const eventData = {
|
|
12471
|
+
state: "agent.tool_call",
|
|
12472
|
+
toolCallName: toolName,
|
|
12473
|
+
toolInput,
|
|
12474
|
+
activeFile: toolInput.filePath
|
|
12475
|
+
};
|
|
12476
|
+
await this.emit("agent.tool_call", eventData, { sessionId });
|
|
12477
|
+
this.lastEventTime = Date.now();
|
|
12478
|
+
}
|
|
12479
|
+
async emitIdle(sessionId) {
|
|
12480
|
+
const eventData = {
|
|
12481
|
+
state: "agent.idle"
|
|
12482
|
+
};
|
|
12483
|
+
await this.emit("agent.idle", eventData, { sessionId });
|
|
12484
|
+
}
|
|
12485
|
+
mapEventType(type) {
|
|
12486
|
+
const mapping = {
|
|
12487
|
+
"session.start": "session.start",
|
|
12488
|
+
"session.end": "session.end",
|
|
12489
|
+
"task.start": "task.start",
|
|
12490
|
+
"task.complete": "task.complete",
|
|
12491
|
+
thinking: "agent.thinking",
|
|
12492
|
+
tool: "agent.tool_call",
|
|
12493
|
+
coding: "agent.coding",
|
|
12494
|
+
output: "agent.streaming",
|
|
12495
|
+
message: "agent.streaming",
|
|
12496
|
+
ask: "agent.asking_user",
|
|
12497
|
+
error: "agent.error",
|
|
12498
|
+
idle: "agent.idle",
|
|
12499
|
+
compact: "agent.compact"
|
|
12500
|
+
};
|
|
12501
|
+
return mapping[type] ?? "agent.streaming";
|
|
12502
|
+
}
|
|
12503
|
+
buildEventData(eventType, payload) {
|
|
12504
|
+
const data = payload.data ?? {};
|
|
12505
|
+
return {
|
|
12506
|
+
state: eventType,
|
|
12507
|
+
project: data.project,
|
|
12508
|
+
activeFile: data.activeFile,
|
|
12509
|
+
model: data.model,
|
|
12510
|
+
toolInput: data.toolInput,
|
|
12511
|
+
toolCallName: data.toolCallName,
|
|
12512
|
+
thinkingContent: data.thinkingContent,
|
|
12513
|
+
messageContent: data.messageContent,
|
|
12514
|
+
finalMessage: data.finalMessage,
|
|
12515
|
+
toolResult: data.toolResult,
|
|
12516
|
+
errorMessage: data.errorMessage,
|
|
12517
|
+
errorType: data.errorType,
|
|
12518
|
+
raw: data.raw
|
|
12519
|
+
};
|
|
12520
|
+
}
|
|
12521
|
+
};
|
|
12522
|
+
|
|
12523
|
+
// src/adapters/registry.ts
|
|
12524
|
+
var AdapterRegistry = class {
|
|
11041
12525
|
adapters = /* @__PURE__ */ new Map();
|
|
11042
12526
|
/**
|
|
11043
12527
|
* Registers one built-in or community adapter instance.
|
|
@@ -11119,7 +12603,9 @@ function createDefaultAdapters(options) {
|
|
|
11119
12603
|
new KiloAdapter(options),
|
|
11120
12604
|
new CodexAdapter(options),
|
|
11121
12605
|
new OpenClawAdapter(options),
|
|
11122
|
-
new OpenCodeAdapter(options)
|
|
12606
|
+
new OpenCodeAdapter(options),
|
|
12607
|
+
new PiAdapter(options),
|
|
12608
|
+
new ZedAdapter(options)
|
|
11123
12609
|
];
|
|
11124
12610
|
}
|
|
11125
12611
|
|
|
@@ -11140,7 +12626,7 @@ function getSocketPath(aisnitchHomePath) {
|
|
|
11140
12626
|
if (process.platform === "win32") {
|
|
11141
12627
|
return "\\\\.\\pipe\\aisnitch.sock";
|
|
11142
12628
|
}
|
|
11143
|
-
return
|
|
12629
|
+
return join15(aisnitchHomePath, "aisnitch.sock");
|
|
11144
12630
|
}
|
|
11145
12631
|
var Pipeline = class {
|
|
11146
12632
|
eventBus = new EventBus();
|
|
@@ -11345,6 +12831,30 @@ var Pipeline = class {
|
|
|
11345
12831
|
getEventBus() {
|
|
11346
12832
|
return this.eventBus;
|
|
11347
12833
|
}
|
|
12834
|
+
/**
|
|
12835
|
+
* Returns the adapter registry for graceful shutdown coordination.
|
|
12836
|
+
*/
|
|
12837
|
+
getAdapterRegistry() {
|
|
12838
|
+
return this.adapterRegistry ?? void 0;
|
|
12839
|
+
}
|
|
12840
|
+
/**
|
|
12841
|
+
* Returns the HTTP receiver for graceful shutdown coordination.
|
|
12842
|
+
*/
|
|
12843
|
+
getHttpReceiver() {
|
|
12844
|
+
return this.httpReceiver;
|
|
12845
|
+
}
|
|
12846
|
+
/**
|
|
12847
|
+
* Returns the UDS server for graceful shutdown coordination.
|
|
12848
|
+
*/
|
|
12849
|
+
getUdsServer() {
|
|
12850
|
+
return this.udsServer;
|
|
12851
|
+
}
|
|
12852
|
+
/**
|
|
12853
|
+
* Returns the WebSocket server for graceful shutdown coordination.
|
|
12854
|
+
*/
|
|
12855
|
+
getWsServer() {
|
|
12856
|
+
return this.wsServer;
|
|
12857
|
+
}
|
|
11348
12858
|
getHealthSnapshot() {
|
|
11349
12859
|
const status = this.getStatus();
|
|
11350
12860
|
return {
|
|
@@ -11469,6 +12979,72 @@ var DEFAULT_TIMEOUTS = Object.freeze({
|
|
|
11469
12979
|
pipelineStartup: 15e3
|
|
11470
12980
|
});
|
|
11471
12981
|
|
|
12982
|
+
// src/core/graceful-shutdown.ts
|
|
12983
|
+
async function withShutdownTimeout(fn, timeoutMs, component) {
|
|
12984
|
+
if (timeoutMs <= 0) {
|
|
12985
|
+
await fn();
|
|
12986
|
+
return;
|
|
12987
|
+
}
|
|
12988
|
+
const timeoutPromise = new Promise((resolve2) => {
|
|
12989
|
+
setTimeout(() => {
|
|
12990
|
+
resolve2("timed_out");
|
|
12991
|
+
}, timeoutMs).unref();
|
|
12992
|
+
});
|
|
12993
|
+
const result = await Promise.race([
|
|
12994
|
+
fn().then(() => "completed"),
|
|
12995
|
+
timeoutPromise
|
|
12996
|
+
]);
|
|
12997
|
+
if (result === "timed_out") {
|
|
12998
|
+
logger.warn(
|
|
12999
|
+
{ component, timeoutMs },
|
|
13000
|
+
`Graceful shutdown exceeded ${timeoutMs}ms timeout \u2014 forcing through`
|
|
13001
|
+
);
|
|
13002
|
+
}
|
|
13003
|
+
}
|
|
13004
|
+
async function shutdownInOrder(components, timeouts, label) {
|
|
13005
|
+
const getTimeout = (key) => {
|
|
13006
|
+
return timeouts[key] ?? DEFAULT_TIMEOUTS.daemonShutdown;
|
|
13007
|
+
};
|
|
13008
|
+
const stopSafely = async (key, fn) => {
|
|
13009
|
+
const timeoutMs = getTimeout(key);
|
|
13010
|
+
try {
|
|
13011
|
+
await withShutdownTimeout(fn, timeoutMs, `${label}.${key}`);
|
|
13012
|
+
} catch (error) {
|
|
13013
|
+
logger.warn(
|
|
13014
|
+
{ error, key, label },
|
|
13015
|
+
`Error during shutdown of ${key} \u2014 continuing with remaining components`
|
|
13016
|
+
);
|
|
13017
|
+
}
|
|
13018
|
+
};
|
|
13019
|
+
if (components.cleanupFns) {
|
|
13020
|
+
for (const cleanupFn of components.cleanupFns) {
|
|
13021
|
+
try {
|
|
13022
|
+
await withShutdownTimeout(
|
|
13023
|
+
async () => {
|
|
13024
|
+
const result = cleanupFn();
|
|
13025
|
+
if (result instanceof Promise) {
|
|
13026
|
+
await result;
|
|
13027
|
+
}
|
|
13028
|
+
},
|
|
13029
|
+
1e3,
|
|
13030
|
+
`${label}.cleanup`
|
|
13031
|
+
);
|
|
13032
|
+
} catch (error) {
|
|
13033
|
+
logger.warn({ error, label }, "Cleanup function failed");
|
|
13034
|
+
}
|
|
13035
|
+
}
|
|
13036
|
+
}
|
|
13037
|
+
if (components.eventBus) {
|
|
13038
|
+
components.eventBus.unsubscribeAll();
|
|
13039
|
+
}
|
|
13040
|
+
await stopSafely("wsServer", () => components.wsServer.stop());
|
|
13041
|
+
await stopSafely("udsServer", () => components.udsServer.stop());
|
|
13042
|
+
await stopSafely("httpReceiver", () => components.httpReceiver.stop());
|
|
13043
|
+
if (components.adapterRegistry) {
|
|
13044
|
+
await stopSafely("adapterRegistry", () => components.adapterRegistry.stopAll());
|
|
13045
|
+
}
|
|
13046
|
+
}
|
|
13047
|
+
|
|
11472
13048
|
// src/tui/index.tsx
|
|
11473
13049
|
import { render } from "ink";
|
|
11474
13050
|
import { withFullScreen } from "fullscreen-ink";
|
|
@@ -11672,9 +13248,11 @@ var TOOL_COLORS = {
|
|
|
11672
13248
|
"openhands": "#facc15",
|
|
11673
13249
|
"openclaw": "#ef4444",
|
|
11674
13250
|
"opencode": "#10b981",
|
|
13251
|
+
"pi": "#1db954",
|
|
11675
13252
|
"qwen-code": "#22c55e",
|
|
11676
13253
|
"unknown": "#94a3b8",
|
|
11677
|
-
"windsurf": "#a855f7"
|
|
13254
|
+
"windsurf": "#a855f7",
|
|
13255
|
+
"zed": "#e85d04"
|
|
11678
13256
|
};
|
|
11679
13257
|
var EVENT_COLORS = {
|
|
11680
13258
|
"agent.asking_user": "#ef4444",
|
|
@@ -13428,10 +15006,10 @@ async function renderManagedTui(options) {
|
|
|
13428
15006
|
|
|
13429
15007
|
// src/cli/pid.ts
|
|
13430
15008
|
import { constants as constants3 } from "fs";
|
|
13431
|
-
import { mkdir as mkdir3, readFile as
|
|
15009
|
+
import { mkdir as mkdir3, readFile as readFile13, rm as rm3, stat as stat10, writeFile as writeFile3, access as access3 } from "fs/promises";
|
|
13432
15010
|
import { createConnection as createConnection2 } from "net";
|
|
13433
15011
|
import { homedir as homedir4 } from "os";
|
|
13434
|
-
import { dirname as dirname7, join as
|
|
15012
|
+
import { dirname as dirname7, join as join16 } from "path";
|
|
13435
15013
|
import { z as z5 } from "zod";
|
|
13436
15014
|
var DaemonStateSchema = z5.strictObject({
|
|
13437
15015
|
pid: z5.number().int().positive(),
|
|
@@ -13446,7 +15024,7 @@ function getDefaultSocketPath(options) {
|
|
|
13446
15024
|
if (process.platform === "win32") {
|
|
13447
15025
|
return "\\\\.\\pipe\\aisnitch.sock";
|
|
13448
15026
|
}
|
|
13449
|
-
return
|
|
15027
|
+
return join16(getAISnitchHomePath(options), "aisnitch.sock");
|
|
13450
15028
|
}
|
|
13451
15029
|
async function cleanupSocketPathIfStale(socketPath) {
|
|
13452
15030
|
if (process.platform === "win32") {
|
|
@@ -13481,16 +15059,16 @@ async function cleanupSocketPathIfStale(socketPath) {
|
|
|
13481
15059
|
return true;
|
|
13482
15060
|
}
|
|
13483
15061
|
function getPidFilePath(options = {}) {
|
|
13484
|
-
return
|
|
15062
|
+
return join16(getAISnitchHomePath(options), "aisnitch.pid");
|
|
13485
15063
|
}
|
|
13486
15064
|
function getDaemonStatePath(options = {}) {
|
|
13487
|
-
return
|
|
15065
|
+
return join16(getAISnitchHomePath(options), "daemon-state.json");
|
|
13488
15066
|
}
|
|
13489
15067
|
function getDaemonLogPath(options = {}) {
|
|
13490
|
-
return
|
|
15068
|
+
return join16(getAISnitchHomePath(options), "daemon.log");
|
|
13491
15069
|
}
|
|
13492
15070
|
function getLaunchAgentPath(options = {}) {
|
|
13493
|
-
return
|
|
15071
|
+
return join16(
|
|
13494
15072
|
options.launchAgentHomeDirectory ?? homedir4(),
|
|
13495
15073
|
"Library",
|
|
13496
15074
|
"LaunchAgents",
|
|
@@ -13506,7 +15084,7 @@ async function writePid(pid, options = {}) {
|
|
|
13506
15084
|
}
|
|
13507
15085
|
async function readPid(options = {}) {
|
|
13508
15086
|
try {
|
|
13509
|
-
const rawPid = await
|
|
15087
|
+
const rawPid = await readFile13(getPidFilePath(options), "utf8");
|
|
13510
15088
|
const parsedPid = Number.parseInt(rawPid.trim(), 10);
|
|
13511
15089
|
if (!Number.isInteger(parsedPid) || parsedPid <= 0) {
|
|
13512
15090
|
throw new Error("Invalid PID file contents.");
|
|
@@ -13536,7 +15114,7 @@ async function writeDaemonState(state, options = {}) {
|
|
|
13536
15114
|
}
|
|
13537
15115
|
async function readDaemonState(options = {}) {
|
|
13538
15116
|
try {
|
|
13539
|
-
const rawJson = await
|
|
15117
|
+
const rawJson = await readFile13(getDaemonStatePath(options), "utf8");
|
|
13540
15118
|
const parsedJson = JSON.parse(rawJson);
|
|
13541
15119
|
return DaemonStateSchema.parse(parsedJson);
|
|
13542
15120
|
} catch (error) {
|
|
@@ -13604,9 +15182,9 @@ function getEffectiveCliConfigPath(options = {}) {
|
|
|
13604
15182
|
|
|
13605
15183
|
// src/cli/auto-update.ts
|
|
13606
15184
|
import { spawn as spawnChildProcess } from "child_process";
|
|
13607
|
-
import { mkdir as mkdir4, readFile as
|
|
15185
|
+
import { mkdir as mkdir4, readFile as readFile14, writeFile as writeFile4 } from "fs/promises";
|
|
13608
15186
|
import { realpath } from "fs/promises";
|
|
13609
|
-
import { join as
|
|
15187
|
+
import { join as join17 } from "path";
|
|
13610
15188
|
var AUTO_UPDATE_STATE_FILE = "auto-update.json";
|
|
13611
15189
|
var AUTO_UPDATE_LOG_FILE = "auto-update.log";
|
|
13612
15190
|
function createAutoUpdateController(dependencies = {}) {
|
|
@@ -13621,7 +15199,7 @@ function createAutoUpdateController(dependencies = {}) {
|
|
|
13621
15199
|
const args = resolveUpdateArgs(options.manager);
|
|
13622
15200
|
const aisnitchHomePath = getAISnitchHomePath(pathOptions);
|
|
13623
15201
|
await mkdir4(aisnitchHomePath, { recursive: true });
|
|
13624
|
-
const logFilePath =
|
|
15202
|
+
const logFilePath = join17(aisnitchHomePath, AUTO_UPDATE_LOG_FILE);
|
|
13625
15203
|
const startedAt = now().toISOString();
|
|
13626
15204
|
await writeAutoUpdateState(
|
|
13627
15205
|
{
|
|
@@ -13809,7 +15387,7 @@ function resolveUpdateArgs(manager) {
|
|
|
13809
15387
|
async function readAutoUpdateState(options) {
|
|
13810
15388
|
const statePath = getAutoUpdateStatePath(options);
|
|
13811
15389
|
try {
|
|
13812
|
-
const rawJson = await
|
|
15390
|
+
const rawJson = await readFile14(statePath, "utf8");
|
|
13813
15391
|
return JSON.parse(rawJson);
|
|
13814
15392
|
} catch (error) {
|
|
13815
15393
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -13829,7 +15407,7 @@ async function writeAutoUpdateState(state, options) {
|
|
|
13829
15407
|
);
|
|
13830
15408
|
}
|
|
13831
15409
|
function getAutoUpdateStatePath(options) {
|
|
13832
|
-
return
|
|
15410
|
+
return join17(getAISnitchHomePath(options), AUTO_UPDATE_STATE_FILE);
|
|
13833
15411
|
}
|
|
13834
15412
|
function toPathOptions(options) {
|
|
13835
15413
|
return {
|
|
@@ -13943,9 +15521,9 @@ function flattenValue(lines, currentPath, value) {
|
|
|
13943
15521
|
}
|
|
13944
15522
|
lines.push(formatLoggerField(currentPath, value, inferValueKind(value)));
|
|
13945
15523
|
}
|
|
13946
|
-
function formatLoggerField(
|
|
15524
|
+
function formatLoggerField(path2, value, kind) {
|
|
13947
15525
|
const renderedValue = typeof value === "string" ? JSON.stringify(value) : value === null ? "null" : typeof value === "undefined" ? "undefined" : JSON.stringify(value);
|
|
13948
|
-
return `${colorize(
|
|
15526
|
+
return `${colorize(path2, TUI_THEME.warning)} ${colorize("=", TUI_THEME.muted)} ${colorize(
|
|
13949
15527
|
renderedValue,
|
|
13950
15528
|
getValueColor(kind)
|
|
13951
15529
|
)}`;
|
|
@@ -14020,7 +15598,8 @@ function isRecord13(value) {
|
|
|
14020
15598
|
}
|
|
14021
15599
|
|
|
14022
15600
|
// src/cli/runtime.ts
|
|
14023
|
-
var
|
|
15601
|
+
var openPromise = Promise.resolve().then(() => (init_open(), open_exports));
|
|
15602
|
+
var execFile21 = promisify21(execFileCallback14);
|
|
14024
15603
|
var DAEMON_READY_TIMEOUT_MS = 4e3;
|
|
14025
15604
|
var DAEMON_READY_POLL_INTERVAL_MS = 100;
|
|
14026
15605
|
var DAEMON_STOP_TIMEOUT_MS = 4e3;
|
|
@@ -14036,7 +15615,7 @@ function createCliRuntime(dependencies = {}) {
|
|
|
14036
15615
|
spawn: spawnImplementation
|
|
14037
15616
|
});
|
|
14038
15617
|
const execFileImplementation = dependencies.execFile ?? (async (file, args) => {
|
|
14039
|
-
return await
|
|
15618
|
+
return await execFile21(file, [...args], {
|
|
14040
15619
|
encoding: "utf8"
|
|
14041
15620
|
});
|
|
14042
15621
|
});
|
|
@@ -14211,7 +15790,7 @@ function createCliRuntime(dependencies = {}) {
|
|
|
14211
15790
|
}
|
|
14212
15791
|
async function readDaemonStartupFailure(pathOptions) {
|
|
14213
15792
|
try {
|
|
14214
|
-
const daemonLog = await
|
|
15793
|
+
const daemonLog = await readFile15(getDaemonLogPath(pathOptions), "utf8");
|
|
14215
15794
|
const logLines = daemonLog.split(/\r?\n/u).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
14216
15795
|
const lastLine = logLines.at(-1);
|
|
14217
15796
|
if (!lastLine) {
|
|
@@ -14309,22 +15888,35 @@ function createCliRuntime(dependencies = {}) {
|
|
|
14309
15888
|
return;
|
|
14310
15889
|
}
|
|
14311
15890
|
shuttingDown = true;
|
|
14312
|
-
|
|
14313
|
-
|
|
14314
|
-
|
|
14315
|
-
|
|
14316
|
-
|
|
15891
|
+
const shutdownTimeouts = {
|
|
15892
|
+
adapterRegistry: DEFAULT_TIMEOUTS.adapterShutdown,
|
|
15893
|
+
httpReceiver: DEFAULT_TIMEOUTS.httpRequest,
|
|
15894
|
+
udsServer: DEFAULT_TIMEOUTS.fileOperation,
|
|
15895
|
+
wsServer: DEFAULT_TIMEOUTS.wsConnection,
|
|
15896
|
+
cleanupFns: 1e3
|
|
15897
|
+
};
|
|
15898
|
+
const components = {
|
|
15899
|
+
adapterRegistry: pipeline.getAdapterRegistry(),
|
|
15900
|
+
httpReceiver: pipeline.getHttpReceiver(),
|
|
15901
|
+
udsServer: pipeline.getUdsServer(),
|
|
15902
|
+
wsServer: pipeline.getWsServer(),
|
|
15903
|
+
eventBus: pipeline.getEventBus(),
|
|
15904
|
+
cleanupFns: daemonMode ? [async () => {
|
|
14317
15905
|
await Promise.all([
|
|
14318
|
-
removePid(
|
|
14319
|
-
removeDaemonState(
|
|
15906
|
+
removePid(toPathOptions2(options)),
|
|
15907
|
+
removeDaemonState(toPathOptions2(options))
|
|
14320
15908
|
]);
|
|
14321
|
-
}
|
|
14322
|
-
}
|
|
14323
|
-
|
|
14324
|
-
|
|
15909
|
+
}] : []
|
|
15910
|
+
};
|
|
15911
|
+
try {
|
|
15912
|
+
await shutdownInOrder(components, shutdownTimeouts, "pipeline");
|
|
15913
|
+
} finally {
|
|
15914
|
+
if (!daemonMode) {
|
|
15915
|
+
output.stdout(`AISnitch stopped after ${signal}.
|
|
14325
15916
|
`);
|
|
15917
|
+
}
|
|
15918
|
+
process.exit(exitCode);
|
|
14326
15919
|
}
|
|
14327
|
-
process.exit(exitCode);
|
|
14328
15920
|
};
|
|
14329
15921
|
if (daemonMode) {
|
|
14330
15922
|
process.once("SIGTERM", () => {
|
|
@@ -14510,6 +16102,113 @@ function createCliRuntime(dependencies = {}) {
|
|
|
14510
16102
|
}
|
|
14511
16103
|
});
|
|
14512
16104
|
}
|
|
16105
|
+
async function fullscreen(options) {
|
|
16106
|
+
const snapshot = await getStatusSnapshot(options);
|
|
16107
|
+
if (!snapshot.running && options.daemonMode) {
|
|
16108
|
+
output.stdout("Starting daemon...\n");
|
|
16109
|
+
await startDetachedDaemon(options);
|
|
16110
|
+
}
|
|
16111
|
+
if (!snapshot.running && !options.daemonMode) {
|
|
16112
|
+
throw new Error(
|
|
16113
|
+
"AISnitch daemon is not running. Start one with `aisnitch start --daemon` or use `aisnitch fs --daemon` to start and open the dashboard."
|
|
16114
|
+
);
|
|
16115
|
+
}
|
|
16116
|
+
for (let i = 0; i < 20; i++) {
|
|
16117
|
+
const health = await fetchHealth(snapshot.httpPort);
|
|
16118
|
+
if (health) break;
|
|
16119
|
+
await new Promise((resolve2) => setTimeout(resolve2, 200).unref());
|
|
16120
|
+
}
|
|
16121
|
+
const dashboardPort = options.dashboardPort ?? 5174;
|
|
16122
|
+
const dashboardUrl = `http://127.0.0.1:${dashboardPort}`;
|
|
16123
|
+
const distPath = join18(process.cwd(), "examples", "fullscreen-dashboard", "dist");
|
|
16124
|
+
output.stdout(`Starting dashboard server on port ${dashboardPort}...
|
|
16125
|
+
`);
|
|
16126
|
+
const viteProcess = spawnImplementation(process.execPath, [
|
|
16127
|
+
"-e",
|
|
16128
|
+
`
|
|
16129
|
+
import { createServer } from 'vite';
|
|
16130
|
+
import path from 'path';
|
|
16131
|
+
|
|
16132
|
+
const distPath = '${distPath}';
|
|
16133
|
+
const port = ${dashboardPort};
|
|
16134
|
+
|
|
16135
|
+
const server = await createServer({
|
|
16136
|
+
root: distPath,
|
|
16137
|
+
server: {
|
|
16138
|
+
port,
|
|
16139
|
+
strictPort: true,
|
|
16140
|
+
allowedHosts: true,
|
|
16141
|
+
},
|
|
16142
|
+
preview: {
|
|
16143
|
+
port,
|
|
16144
|
+
strictPort: true,
|
|
16145
|
+
},
|
|
16146
|
+
});
|
|
16147
|
+
|
|
16148
|
+
await server.listen();
|
|
16149
|
+
console.log('READY');
|
|
16150
|
+
|
|
16151
|
+
process.stdin.resume();
|
|
16152
|
+
`
|
|
16153
|
+
], {
|
|
16154
|
+
cwd: distPath,
|
|
16155
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
16156
|
+
});
|
|
16157
|
+
let serverOutput = "";
|
|
16158
|
+
viteProcess.stdout?.on("data", (data) => {
|
|
16159
|
+
serverOutput += data.toString();
|
|
16160
|
+
});
|
|
16161
|
+
viteProcess.stderr?.on("data", (data) => {
|
|
16162
|
+
serverOutput += data.toString();
|
|
16163
|
+
});
|
|
16164
|
+
let serverReady = false;
|
|
16165
|
+
for (let i = 0; i < 100; i++) {
|
|
16166
|
+
await new Promise((resolve2) => setTimeout(resolve2, 100).unref());
|
|
16167
|
+
try {
|
|
16168
|
+
const response = await fetchImplementation(dashboardUrl);
|
|
16169
|
+
if (response.ok) {
|
|
16170
|
+
serverReady = true;
|
|
16171
|
+
break;
|
|
16172
|
+
}
|
|
16173
|
+
} catch {
|
|
16174
|
+
}
|
|
16175
|
+
if (!viteProcess.pid) break;
|
|
16176
|
+
}
|
|
16177
|
+
if (!serverReady) {
|
|
16178
|
+
output.stdout(`Server output: ${serverOutput}
|
|
16179
|
+
`);
|
|
16180
|
+
throw new Error("Failed to start dashboard server");
|
|
16181
|
+
}
|
|
16182
|
+
output.stdout(`Dashboard ready at ${dashboardUrl}
|
|
16183
|
+
`);
|
|
16184
|
+
if (!options.noBrowser) {
|
|
16185
|
+
output.stdout("Opening browser...\n");
|
|
16186
|
+
const openModule = await openPromise;
|
|
16187
|
+
await openModule.default(dashboardUrl);
|
|
16188
|
+
}
|
|
16189
|
+
output.stdout("Press Ctrl+C to stop\n");
|
|
16190
|
+
await new Promise((resolve2) => {
|
|
16191
|
+
const shutdown = () => {
|
|
16192
|
+
process.off("SIGINT", handleSigint);
|
|
16193
|
+
process.off("SIGTERM", handleSigterm);
|
|
16194
|
+
if (viteProcess.pid !== void 0) {
|
|
16195
|
+
try {
|
|
16196
|
+
process.kill(viteProcess.pid, "SIGTERM");
|
|
16197
|
+
} catch {
|
|
16198
|
+
}
|
|
16199
|
+
}
|
|
16200
|
+
resolve2();
|
|
16201
|
+
};
|
|
16202
|
+
const handleSigint = () => {
|
|
16203
|
+
shutdown();
|
|
16204
|
+
};
|
|
16205
|
+
const handleSigterm = () => {
|
|
16206
|
+
shutdown();
|
|
16207
|
+
};
|
|
16208
|
+
process.once("SIGINT", handleSigint);
|
|
16209
|
+
process.once("SIGTERM", handleSigterm);
|
|
16210
|
+
});
|
|
16211
|
+
}
|
|
14513
16212
|
async function logger2(options) {
|
|
14514
16213
|
const snapshot = await getStatusSnapshot(options);
|
|
14515
16214
|
if (!snapshot.running) {
|
|
@@ -14581,7 +16280,7 @@ function createCliRuntime(dependencies = {}) {
|
|
|
14581
16280
|
}
|
|
14582
16281
|
const { config } = await loadEffectiveConfig(options);
|
|
14583
16282
|
setLoggerLevel(getForegroundSafeLogLevel(config.logLevel, false));
|
|
14584
|
-
const ephemeralHomeDirectory = await mkdtemp(
|
|
16283
|
+
const ephemeralHomeDirectory = await mkdtemp(join18(tmpdir(), "aisnitch-mock-"));
|
|
14585
16284
|
const ephemeralPipeline = new Pipeline();
|
|
14586
16285
|
const status2 = await ephemeralPipeline.start({
|
|
14587
16286
|
config: {
|
|
@@ -14665,7 +16364,7 @@ function createCliRuntime(dependencies = {}) {
|
|
|
14665
16364
|
} else {
|
|
14666
16365
|
const { config } = await loadEffectiveConfig(options);
|
|
14667
16366
|
setLoggerLevel(getForegroundSafeLogLevel(config.logLevel, false));
|
|
14668
|
-
ephemeralHomeDirectory = await mkdtemp(
|
|
16367
|
+
ephemeralHomeDirectory = await mkdtemp(join18(tmpdir(), "aisnitch-wrap-"));
|
|
14669
16368
|
ephemeralPipeline = new Pipeline();
|
|
14670
16369
|
await ephemeralPipeline.start({
|
|
14671
16370
|
config: {
|
|
@@ -14740,7 +16439,7 @@ function createCliRuntime(dependencies = {}) {
|
|
|
14740
16439
|
},
|
|
14741
16440
|
pid: process.ppid > 1 ? process.ppid : void 0,
|
|
14742
16441
|
source: "aisnitch://adapters/aider/notifications-command",
|
|
14743
|
-
transcriptPath:
|
|
16442
|
+
transcriptPath: join18(process.cwd(), ".aider.chat.history.md"),
|
|
14744
16443
|
type: "agent.idle"
|
|
14745
16444
|
}),
|
|
14746
16445
|
headers: {
|
|
@@ -14801,6 +16500,7 @@ function createCliRuntime(dependencies = {}) {
|
|
|
14801
16500
|
adapters,
|
|
14802
16501
|
aiderNotify,
|
|
14803
16502
|
attach,
|
|
16503
|
+
fullscreen,
|
|
14804
16504
|
install,
|
|
14805
16505
|
logger: logger2,
|
|
14806
16506
|
mock,
|
|
@@ -14941,7 +16641,7 @@ function joinSocketPath(pathOptions) {
|
|
|
14941
16641
|
}
|
|
14942
16642
|
function resolveCliEntryPath() {
|
|
14943
16643
|
const cliEntryPath = process.argv[1];
|
|
14944
|
-
if (!cliEntryPath ||
|
|
16644
|
+
if (!cliEntryPath || basename12(cliEntryPath).length === 0) {
|
|
14945
16645
|
throw new Error("Unable to resolve the AISnitch CLI entry path.");
|
|
14946
16646
|
}
|
|
14947
16647
|
return cliEntryPath;
|
|
@@ -15012,6 +16712,9 @@ Examples:
|
|
|
15012
16712
|
aisnitch start --daemon
|
|
15013
16713
|
aisnitch start --view full-data
|
|
15014
16714
|
aisnitch start --mock
|
|
16715
|
+
aisnitch fs
|
|
16716
|
+
aisnitch fs --daemon
|
|
16717
|
+
aisnitch fs --dashboard-port 8080
|
|
15015
16718
|
aisnitch status
|
|
15016
16719
|
aisnitch attach
|
|
15017
16720
|
aisnitch attach --view full-data
|
|
@@ -15035,6 +16738,7 @@ Examples:
|
|
|
15035
16738
|
addAdaptersCommand(program, runtime);
|
|
15036
16739
|
addSetupCommand(program, runtime);
|
|
15037
16740
|
addAttachCommand(program, runtime);
|
|
16741
|
+
addFullscreenCommand(program, runtime);
|
|
15038
16742
|
addLoggerCommand(program, runtime);
|
|
15039
16743
|
addMockCommand(program, runtime);
|
|
15040
16744
|
addWrapCommand(program, runtime);
|
|
@@ -15167,6 +16871,23 @@ function addAttachCommand(program, runtime) {
|
|
|
15167
16871
|
await runtime.attach(options);
|
|
15168
16872
|
});
|
|
15169
16873
|
}
|
|
16874
|
+
function addFullscreenCommand(program, runtime) {
|
|
16875
|
+
addCommonOptions(
|
|
16876
|
+
program.command("fs").description("Open the fullscreen web dashboard in browser (starts daemon if needed with --daemon)").alias("fullscreen").option(
|
|
16877
|
+
"--daemon",
|
|
16878
|
+
"Start the daemon automatically if not running"
|
|
16879
|
+
).option(
|
|
16880
|
+
"--dashboard-port <port>",
|
|
16881
|
+
"Port for the dashboard server (default: 5174)",
|
|
16882
|
+
wrapOptionParser(parsePortOption)
|
|
16883
|
+
).option(
|
|
16884
|
+
"--no-browser",
|
|
16885
|
+
"Start server without opening browser"
|
|
16886
|
+
)
|
|
16887
|
+
).action(async (options) => {
|
|
16888
|
+
await runtime.fullscreen(options);
|
|
16889
|
+
});
|
|
16890
|
+
}
|
|
15170
16891
|
function addWrapCommand(program, runtime) {
|
|
15171
16892
|
addCommonOptions(
|
|
15172
16893
|
program.command("wrap").description("Run a command inside a PTY while AISnitch observes its terminal activity").allowUnknownOption(true).argument("<command>", "Command to wrap").argument("[args...]", "Arguments forwarded to the wrapped command").option("--cwd <path>", "Run the wrapped command from a specific working directory")
|