khala-cli 0.4.11 → 0.4.13
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/dist/{chunk-HZH74L5T.mjs → chunk-2AIADANH.mjs} +6 -6
- package/dist/chunk-2BNIPJVW.mjs +27 -0
- package/dist/{chunk-YIKJI26V.mjs → chunk-32SGUUP5.mjs} +2 -2
- package/dist/{chunk-7FFHZ7EI.mjs → chunk-3GUVMXTM.mjs} +9 -9
- package/dist/{chunk-LDW4HOQW.mjs → chunk-3JA3Q5MK.mjs} +1 -1
- package/dist/{chunk-NN5RHU6C.mjs → chunk-6DE4V756.mjs} +10 -10
- package/dist/{chunk-FGHPOKXG.mjs → chunk-6P4PKPJW.mjs} +5 -5
- package/dist/{chunk-N6UYX3SY.mjs → chunk-72W7IC2O.mjs} +3 -3
- package/dist/{chunk-BVG7PJNZ.mjs → chunk-BJVJ5WJS.mjs} +16 -16
- package/dist/{chunk-NJ5ICCVZ.mjs → chunk-BWVC3EKG.mjs} +12 -12
- package/dist/{chunk-CXVANPY5.mjs → chunk-I4POSYHZ.mjs} +2 -2
- package/dist/{chunk-MAIMFERG.mjs → chunk-ICTAFDO6.mjs} +3 -3
- package/dist/{chunk-YFX5NDSL.mjs → chunk-JLENHMKE.mjs} +295 -78
- package/dist/{chunk-X3BAMHAR.mjs → chunk-JZZNVQKH.mjs} +2 -2
- package/dist/{chunk-NE4S7N3R.mjs → chunk-KMDLTHDW.mjs} +2 -2
- package/dist/{chunk-LNKI3CZO.mjs → chunk-MRSZOWFU.mjs} +1 -1
- package/dist/{chunk-JNSB3E6C.mjs → chunk-NHW62KEB.mjs} +1 -1
- package/dist/{chunk-4CENUF7M.mjs → chunk-O4QJ3ZT6.mjs} +3 -3
- package/dist/{chunk-3KHLSF4A.mjs → chunk-OIYAR2ND.mjs} +7 -7
- package/dist/{chunk-GVZD4TLW.mjs → chunk-ONAZVGVO.mjs} +45 -10
- package/dist/{chunk-R5NDTJRA.mjs → chunk-P3XZEYZF.mjs} +1 -1
- package/dist/{chunk-YNUCRFM2.mjs → chunk-QPYXV4BQ.mjs} +8 -8
- package/dist/{chunk-E5QRD6W3.mjs → chunk-QZUBLJW7.mjs} +2 -2
- package/dist/{chunk-NUQSDSVT.mjs → chunk-RUQDE5DI.mjs} +1 -1
- package/dist/{chunk-OSVXLZKJ.mjs → chunk-SDBMJPIA.mjs} +6 -6
- package/dist/{chunk-H2L5GQ5W.mjs → chunk-SKJ6YV3G.mjs} +12 -12
- package/dist/{chunk-WA5LB5GN.mjs → chunk-SUT7AKNZ.mjs} +6 -6
- package/dist/{chunk-TVQ4MSEI.mjs → chunk-SUUEWCY5.mjs} +1 -1
- package/dist/chunk-TVQ5NHFX.mjs +20 -0
- package/dist/chunk-WZD4JAG6.mjs +19 -0
- package/dist/{chunk-VWWI4S5A.mjs → chunk-XI5FPUNN.mjs} +2 -2
- package/dist/{chunk-NOKTVPSY.mjs → chunk-XR3JSUPF.mjs} +101 -73
- package/dist/{chunk-YDEZFVF7.mjs → chunk-XRV5GUSI.mjs} +3 -3
- package/dist/{chunk-4PUNVPC3.mjs → chunk-ZWWTVM6R.mjs} +2 -2
- package/dist/khala.mjs +11 -11
- package/dist/web/assets/local-DLmpMMaF.css +1 -0
- package/dist/web/assets/local-mElTRGcH.js +11 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/chunk-AQX2OYEF.mjs +0 -19
- package/dist/chunk-CYINL2V3.mjs +0 -20
- package/dist/chunk-MYIZQCRW.mjs +0 -27
- package/dist/web/assets/local-DPcMk9Xz.css +0 -1
- package/dist/web/assets/local-SDOFp8OA.js +0 -9
|
@@ -2,7 +2,7 @@ import { createRequire as __khalaCreateRequire } from 'node:module'; const requi
|
|
|
2
2
|
import {
|
|
3
3
|
DEFAULT_LISTENING_MODE,
|
|
4
4
|
decodeListeningMode
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-I4POSYHZ.mjs";
|
|
6
6
|
import {
|
|
7
7
|
advanceCursor,
|
|
8
8
|
isWakeEntry,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
readEntries,
|
|
14
14
|
unread,
|
|
15
15
|
wakesAgent
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-72W7IC2O.mjs";
|
|
17
17
|
import {
|
|
18
18
|
SESSION_ID_PATTERN,
|
|
19
19
|
StateError,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
sessionFiles,
|
|
24
24
|
stateRoot,
|
|
25
25
|
writeJsonAtomic
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-NHW62KEB.mjs";
|
|
27
27
|
import {
|
|
28
28
|
cancelAttempt,
|
|
29
29
|
confirmWakeText,
|
|
@@ -32,16 +32,16 @@ import {
|
|
|
32
32
|
settleAttempts,
|
|
33
33
|
wakeLine,
|
|
34
34
|
withWakeLock
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-SUUEWCY5.mjs";
|
|
36
36
|
import {
|
|
37
37
|
init_define_KHALA_BUNDLE
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-3JA3Q5MK.mjs";
|
|
39
39
|
|
|
40
40
|
// src/watch.ts
|
|
41
41
|
init_define_KHALA_BUNDLE();
|
|
42
42
|
import * as fs7 from "node:fs/promises";
|
|
43
43
|
import { watch as watchDirectory } from "node:fs";
|
|
44
|
-
import
|
|
44
|
+
import path7 from "node:path";
|
|
45
45
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
46
46
|
|
|
47
47
|
// src/monitor-storage.ts
|
|
@@ -76,21 +76,44 @@ async function monitorStorage(files) {
|
|
|
76
76
|
|
|
77
77
|
// src/mode.ts
|
|
78
78
|
init_define_KHALA_BUNDLE();
|
|
79
|
+
import path2 from "node:path";
|
|
80
|
+
async function readModeState(files) {
|
|
81
|
+
const content = await readJson(files.mode);
|
|
82
|
+
const record = typeof content === "object" && content !== null ? content : {};
|
|
83
|
+
const decoded = decodeListeningMode(record.mode);
|
|
84
|
+
return { mode: decoded.ok ? decoded.value : DEFAULT_LISTENING_MODE, archived: record.archived === true };
|
|
85
|
+
}
|
|
86
|
+
var delegateFile = (files) => path2.join(files.dir, "delegate.json");
|
|
87
|
+
async function delegateChannel(files, ms) {
|
|
88
|
+
await writeJsonAtomic(delegateFile(files), { until: Date.now() + ms });
|
|
89
|
+
}
|
|
90
|
+
async function isDelegated(files) {
|
|
91
|
+
const lease = await readJson(delegateFile(files)).catch(() => null);
|
|
92
|
+
return typeof lease?.until === "number" && lease.until > Date.now();
|
|
93
|
+
}
|
|
79
94
|
async function readListeningMode(files) {
|
|
95
|
+
const state = await readModeState(files);
|
|
96
|
+
return state.archived || await isDelegated(files) ? "async" : state.mode;
|
|
97
|
+
}
|
|
98
|
+
async function applyArchived(files, archived) {
|
|
80
99
|
const content = await readJson(files.mode);
|
|
81
|
-
|
|
82
|
-
|
|
100
|
+
if (content?.archived === true === archived) return;
|
|
101
|
+
if (!archived && (await readModeState(files)).mode !== "async") await skipBacklog(files);
|
|
102
|
+
await writeJsonAtomic(files.mode, { ...content ?? {}, archived });
|
|
83
103
|
}
|
|
84
|
-
async function
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const { cursor, entries } = await unread(files);
|
|
89
|
-
if (await advanceCursor(files, cursor, entries) !== "conflict") break;
|
|
90
|
-
if (attempt === 1) throw new StateError("storage_failed");
|
|
91
|
-
}
|
|
104
|
+
async function skipBacklog(files) {
|
|
105
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
106
|
+
const { cursor, entries } = await unread(files);
|
|
107
|
+
if (await advanceCursor(files, cursor, entries) !== "conflict") return;
|
|
92
108
|
}
|
|
93
|
-
|
|
109
|
+
throw new StateError("storage_failed");
|
|
110
|
+
}
|
|
111
|
+
var ATTENTION = { async: 0, sync: 1, steer: 2 };
|
|
112
|
+
async function applyListeningMode(files, next, meta, now = () => /* @__PURE__ */ new Date()) {
|
|
113
|
+
const { keepBacklog, ...record } = meta;
|
|
114
|
+
const { mode: previous, archived } = await readModeState(files);
|
|
115
|
+
if (previous === "async" && next !== "async" && !keepBacklog) await skipBacklog(files);
|
|
116
|
+
await writeJsonAtomic(files.mode, { mode: next, ...archived ? { archived } : {}, ...record, updatedAt: now().toISOString() });
|
|
94
117
|
return { previous, next };
|
|
95
118
|
}
|
|
96
119
|
|
|
@@ -100,11 +123,11 @@ init_define_KHALA_BUNDLE();
|
|
|
100
123
|
// src/wake/shared/settings.ts
|
|
101
124
|
init_define_KHALA_BUNDLE();
|
|
102
125
|
import * as fs2 from "node:fs/promises";
|
|
103
|
-
import
|
|
126
|
+
import path3 from "node:path";
|
|
104
127
|
import { randomBytes } from "node:crypto";
|
|
105
128
|
async function readWakeSettings(root) {
|
|
106
129
|
try {
|
|
107
|
-
const value = JSON.parse(await fs2.readFile(
|
|
130
|
+
const value = JSON.parse(await fs2.readFile(path3.join(root, "wake-settings.json"), "utf8"));
|
|
108
131
|
const entries = (input) => {
|
|
109
132
|
if (!input || typeof input !== "object" || Array.isArray(input)) return {};
|
|
110
133
|
return Object.fromEntries(Object.entries(input).filter(([, entry]) => entry && typeof entry === "object" && typeof entry.at === "string"));
|
|
@@ -117,7 +140,7 @@ async function readWakeSettings(root) {
|
|
|
117
140
|
}
|
|
118
141
|
async function writeWakeSettings(root, settings) {
|
|
119
142
|
await fs2.mkdir(root, { recursive: true, mode: 448 });
|
|
120
|
-
const target2 =
|
|
143
|
+
const target2 = path3.join(root, "wake-settings.json");
|
|
121
144
|
const temp = `${target2}.${randomBytes(8).toString("hex")}.tmp`;
|
|
122
145
|
try {
|
|
123
146
|
await fs2.writeFile(temp, JSON.stringify(settings), { mode: 384 });
|
|
@@ -144,7 +167,7 @@ init_define_KHALA_BUNDLE();
|
|
|
144
167
|
import { createInterface } from "node:readline";
|
|
145
168
|
import * as fs4 from "node:fs/promises";
|
|
146
169
|
import os2 from "node:os";
|
|
147
|
-
import
|
|
170
|
+
import path5 from "node:path";
|
|
148
171
|
|
|
149
172
|
// src/install/cursor.ts
|
|
150
173
|
init_define_KHALA_BUNDLE();
|
|
@@ -187,12 +210,12 @@ function nodeScriptCommand(platform, node, script) {
|
|
|
187
210
|
|
|
188
211
|
// src/install/launcher.ts
|
|
189
212
|
init_define_KHALA_BUNDLE();
|
|
190
|
-
function installedLauncher(platform,
|
|
213
|
+
function installedLauncher(platform, path8, home, env) {
|
|
191
214
|
const windows = platform === "win32";
|
|
192
215
|
const candidate = windows ? env.LOCALAPPDATA : env.XDG_DATA_HOME;
|
|
193
|
-
const dataHome = candidate &&
|
|
194
|
-
const prefix =
|
|
195
|
-
return { prefix, bin: windows ?
|
|
216
|
+
const dataHome = candidate && path8.isAbsolute(candidate) ? candidate : windows ? path8.join(home, "AppData", "Local") : path8.join(home, ".local", "share");
|
|
217
|
+
const prefix = path8.join(dataHome, "khala", "npm");
|
|
218
|
+
return { prefix, bin: windows ? path8.join(prefix, "khala.cmd") : path8.join(prefix, "bin", "khala") };
|
|
196
219
|
}
|
|
197
220
|
function launcherShellQuote(platform, bin) {
|
|
198
221
|
return platform === "win32" ? `"${bin}"` : `'${bin.replaceAll("'", `'\\''`)}'`;
|
|
@@ -201,7 +224,7 @@ function launcherShellQuote(platform, bin) {
|
|
|
201
224
|
// src/install/managed-file.ts
|
|
202
225
|
init_define_KHALA_BUNDLE();
|
|
203
226
|
import * as fs3 from "node:fs/promises";
|
|
204
|
-
import
|
|
227
|
+
import path4 from "node:path";
|
|
205
228
|
import { isDeepStrictEqual } from "node:util";
|
|
206
229
|
var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
207
230
|
var BOM = "\uFEFF";
|
|
@@ -250,7 +273,7 @@ var LEGACY_BACKUP = ".khala-bak";
|
|
|
250
273
|
var ManagedFiles = class {
|
|
251
274
|
store;
|
|
252
275
|
constructor(stateDir) {
|
|
253
|
-
this.store =
|
|
276
|
+
this.store = path4.join(stateDir, "install-originals.json");
|
|
254
277
|
}
|
|
255
278
|
async load() {
|
|
256
279
|
try {
|
|
@@ -266,14 +289,14 @@ var ManagedFiles = class {
|
|
|
266
289
|
await fs3.rm(this.store, { force: true });
|
|
267
290
|
return;
|
|
268
291
|
}
|
|
269
|
-
await fs3.mkdir(
|
|
292
|
+
await fs3.mkdir(path4.dirname(this.store), { recursive: true, mode: 448 });
|
|
270
293
|
const temp = `${this.store}.${process.pid}.tmp`;
|
|
271
294
|
await fs3.writeFile(temp, JSON.stringify(recordings, null, 2) + "\n", { mode: 384 });
|
|
272
295
|
await fs3.rename(temp, this.store);
|
|
273
296
|
}
|
|
274
297
|
/** The recorded original: `undefined` when nothing is recorded, `null` when the file did not exist. */
|
|
275
298
|
async original(file) {
|
|
276
|
-
const recording = (await this.load())[
|
|
299
|
+
const recording = (await this.load())[path4.resolve(file)];
|
|
277
300
|
if (recording) return recording.existed ? Buffer.from(recording.bytes ?? "", "base64") : null;
|
|
278
301
|
const legacy = await readBytes(file + LEGACY_BACKUP);
|
|
279
302
|
return legacy ?? void 0;
|
|
@@ -285,12 +308,12 @@ var ManagedFiles = class {
|
|
|
285
308
|
* the override still never replaces a previously saved recording.
|
|
286
309
|
*/
|
|
287
310
|
async record(file, options) {
|
|
288
|
-
const key =
|
|
311
|
+
const key = path4.resolve(file);
|
|
289
312
|
const recordings = await this.load();
|
|
290
313
|
if (recordings[key]) return;
|
|
291
314
|
const legacy = await readBytes(file + LEGACY_BACKUP);
|
|
292
315
|
const current = options ? options.original : legacy ?? await readBytes(file);
|
|
293
|
-
recordings[key] = current === null ? { existed: false, createdDirs: await missingDirs(
|
|
316
|
+
recordings[key] = current === null ? { existed: false, createdDirs: await missingDirs(path4.dirname(key)) } : { existed: true, bytes: current.toString("base64"), createdDirs: [] };
|
|
294
317
|
await this.save(recordings);
|
|
295
318
|
if (legacy) await fs3.rm(file + LEGACY_BACKUP, { force: true });
|
|
296
319
|
}
|
|
@@ -302,7 +325,7 @@ var ManagedFiles = class {
|
|
|
302
325
|
for (const { current } of entries) await this.record(current.file);
|
|
303
326
|
for (const { current, text, mode } of entries) {
|
|
304
327
|
if (text === current.text) continue;
|
|
305
|
-
await fs3.mkdir(
|
|
328
|
+
await fs3.mkdir(path4.dirname(current.file), { recursive: true });
|
|
306
329
|
await fs3.writeFile(current.file, text, mode === void 0 ? void 0 : { mode });
|
|
307
330
|
}
|
|
308
331
|
}
|
|
@@ -314,7 +337,7 @@ var ManagedFiles = class {
|
|
|
314
337
|
* stripped content. The recording is then dropped.
|
|
315
338
|
*/
|
|
316
339
|
async restore(current, format, strip) {
|
|
317
|
-
const key =
|
|
340
|
+
const key = path4.resolve(current.file);
|
|
318
341
|
const recordings = await this.load();
|
|
319
342
|
const recording = recordings[key];
|
|
320
343
|
const original = await this.original(current.file);
|
|
@@ -357,7 +380,7 @@ async function readBytes(file) {
|
|
|
357
380
|
}
|
|
358
381
|
async function missingDirs(dir) {
|
|
359
382
|
const missing = [];
|
|
360
|
-
for (let at = dir; ; at =
|
|
383
|
+
for (let at = dir; ; at = path4.dirname(at)) {
|
|
361
384
|
try {
|
|
362
385
|
await fs3.stat(at);
|
|
363
386
|
return missing;
|
|
@@ -365,24 +388,24 @@ async function missingDirs(dir) {
|
|
|
365
388
|
if (error.code !== "ENOENT") throw error;
|
|
366
389
|
}
|
|
367
390
|
missing.push(at);
|
|
368
|
-
if (
|
|
391
|
+
if (path4.dirname(at) === at) return missing;
|
|
369
392
|
}
|
|
370
393
|
}
|
|
371
394
|
|
|
372
395
|
// src/install/cursor.ts
|
|
373
396
|
var CURSOR_HOOK_EVENTS = ["beforeSubmitPrompt", "postToolUse", "stop"];
|
|
374
397
|
var HOOK_SUFFIX = " hook deliver --harness cursor";
|
|
375
|
-
function cursorPaths({ platform, path:
|
|
376
|
-
const cursorDir =
|
|
398
|
+
function cursorPaths({ platform, path: path8, home, env }, packageName = "khala-cli") {
|
|
399
|
+
const cursorDir = path8.join(home, ".cursor");
|
|
377
400
|
const windows = platform === "win32";
|
|
378
|
-
const { prefix } = installedLauncher(platform,
|
|
379
|
-
const modules = windows ?
|
|
401
|
+
const { prefix } = installedLauncher(platform, path8, home, env);
|
|
402
|
+
const modules = windows ? path8.join(prefix, "node_modules") : path8.join(prefix, "lib", "node_modules");
|
|
380
403
|
return {
|
|
381
404
|
cursorDir,
|
|
382
405
|
prefix,
|
|
383
|
-
mcpFile:
|
|
384
|
-
hooksFile:
|
|
385
|
-
script:
|
|
406
|
+
mcpFile: path8.join(cursorDir, "mcp.json"),
|
|
407
|
+
hooksFile: path8.join(cursorDir, "hooks.json"),
|
|
408
|
+
script: path8.join(modules, ...packageName.split("/"), "dist", "khala.mjs")
|
|
386
409
|
};
|
|
387
410
|
}
|
|
388
411
|
function cursorHookCommand(platform, node, script) {
|
|
@@ -481,8 +504,8 @@ var MUSE_WAKE_REQUEST = "muse-monitor-wake.json";
|
|
|
481
504
|
var shellQuote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
|
|
482
505
|
function museCliPath(env = process.env) {
|
|
483
506
|
const home = env.HOME || env.USERPROFILE || os2.homedir();
|
|
484
|
-
const { prefix } = cursorPaths({ platform: process.platform, path:
|
|
485
|
-
return process.platform === "win32" ?
|
|
507
|
+
const { prefix } = cursorPaths({ platform: process.platform, path: path5, home, env });
|
|
508
|
+
return process.platform === "win32" ? path5.join(prefix, "khala.cmd") : path5.join(prefix, "bin", "khala");
|
|
486
509
|
}
|
|
487
510
|
function museWatchCommand(sessionId, bin = museCliPath(), platform = process.platform) {
|
|
488
511
|
const quote = platform === "win32" ? (value) => `'${value.replaceAll("'", "''")}'` : shellQuote;
|
|
@@ -517,7 +540,7 @@ function createMuseMonitorDriver() {
|
|
|
517
540
|
if (ctx.signal.aborted || (await readActivity(ctx.files)).state !== "idle" || !await monitorArmed(ctx.files)) return "skipped";
|
|
518
541
|
const epoch = (await readActivity(ctx.files)).updatedAt;
|
|
519
542
|
for (const dir of monitorStorageCandidates(ctx.files)) {
|
|
520
|
-
if ((await readJson(
|
|
543
|
+
if ((await readJson(path5.join(dir, "monitor-wake-observed.json")))?.epoch === epoch) return "skipped";
|
|
521
544
|
}
|
|
522
545
|
const owner = await monitorOwner(ctx.files);
|
|
523
546
|
if (!owner) return "skipped";
|
|
@@ -530,7 +553,7 @@ function createMuseMonitorDriver() {
|
|
|
530
553
|
if (error.code !== "ENOENT") throw error;
|
|
531
554
|
}
|
|
532
555
|
}
|
|
533
|
-
await writeJsonAtomic(
|
|
556
|
+
await writeJsonAtomic(path5.join(ctx.files.dir, MUSE_WAKE_REQUEST), {
|
|
534
557
|
owner: owner.nonce,
|
|
535
558
|
line,
|
|
536
559
|
at: ctx.now,
|
|
@@ -545,8 +568,8 @@ function museJournalPath(sessionId, env) {
|
|
|
545
568
|
const created = new Date(Number.parseInt(sessionId.replaceAll("-", "").slice(0, 12), 16));
|
|
546
569
|
const date = [String(created.getFullYear()), String(created.getMonth() + 1).padStart(2, "0"), String(created.getDate()).padStart(2, "0")];
|
|
547
570
|
const home = env.HOME || env.USERPROFILE || os2.homedir();
|
|
548
|
-
const data = env.XDG_DATA_HOME &&
|
|
549
|
-
return
|
|
571
|
+
const data = env.XDG_DATA_HOME && path5.isAbsolute(env.XDG_DATA_HOME) ? env.XDG_DATA_HOME : path5.join(home, ".local", "share");
|
|
572
|
+
return path5.join(data, "muse", "sessions", ...date, sessionId, "session.jsonl");
|
|
550
573
|
}
|
|
551
574
|
async function museStopWakeText(stdin, files, env) {
|
|
552
575
|
const input = JSON.parse(stdin);
|
|
@@ -554,7 +577,7 @@ async function museStopWakeText(stdin, files, env) {
|
|
|
554
577
|
return museWakeProof(files, input.session_id, env, input.turn_id);
|
|
555
578
|
}
|
|
556
579
|
async function museWakeProof(files, sessionId, env, turnId) {
|
|
557
|
-
const request = await readJson(
|
|
580
|
+
const request = await readJson(path5.join(files.dir, MUSE_WAKE_REQUEST));
|
|
558
581
|
if (!request) return void 0;
|
|
559
582
|
const journal = museJournalPath(sessionId, env);
|
|
560
583
|
if (!journal) return void 0;
|
|
@@ -594,7 +617,7 @@ init_define_KHALA_BUNDLE();
|
|
|
594
617
|
import * as fs6 from "node:fs/promises";
|
|
595
618
|
import net from "node:net";
|
|
596
619
|
import os3 from "node:os";
|
|
597
|
-
import
|
|
620
|
+
import path6 from "node:path";
|
|
598
621
|
import { randomBytes as randomBytes2, randomUUID as randomUUID2 } from "node:crypto";
|
|
599
622
|
|
|
600
623
|
// src/wake/qwen-transcript.ts
|
|
@@ -633,23 +656,23 @@ async function verifyQwenTranscript(dir, filePath, now) {
|
|
|
633
656
|
}
|
|
634
657
|
|
|
635
658
|
// src/wake/qwen-socket.ts
|
|
636
|
-
var qwenHome = (env) => env.QWEN_HOME ?
|
|
659
|
+
var qwenHome = (env) => env.QWEN_HOME ? path6.resolve(env.QWEN_HOME) : path6.join(env.HOME ?? os3.homedir(), ".qwen");
|
|
637
660
|
async function qwenInboundAllowed(env, workspace = env.PWD ?? process.cwd()) {
|
|
638
|
-
for (const file of [
|
|
661
|
+
for (const file of [path6.join(qwenHome(env), "settings.json"), path6.join(workspace, ".qwen", "settings.json")]) {
|
|
639
662
|
const config = await readJson(file);
|
|
640
663
|
if (["hold", "refuse"].includes(config?.agents?.crossSessionInbound ?? "") || config?.agents?.crossSessionMessaging === false) return false;
|
|
641
664
|
}
|
|
642
665
|
return true;
|
|
643
666
|
}
|
|
644
|
-
var qwenControllerFile = (env) =>
|
|
667
|
+
var qwenControllerFile = (env) => path6.join(stateRoot(env), "qwen", "controller.json");
|
|
645
668
|
async function qwenSession(env) {
|
|
646
669
|
const socket = env.QWEN_CODE_MESSAGING_SOCKET;
|
|
647
670
|
if (!socket) return void 0;
|
|
648
671
|
try {
|
|
649
|
-
const dir =
|
|
672
|
+
const dir = path6.join(qwenHome(env), "sessions");
|
|
650
673
|
for (const file of await fs6.readdir(dir)) {
|
|
651
674
|
if (!/^\d+\.json$/u.test(file)) continue;
|
|
652
|
-
const record = await readJson(
|
|
675
|
+
const record = await readJson(path6.join(dir, file));
|
|
653
676
|
if (record?.ipcPath === socket && typeof record.sessionId === "string" && SESSION_ID_PATTERN.test(record.sessionId)) return record.sessionId;
|
|
654
677
|
}
|
|
655
678
|
} catch {
|
|
@@ -686,8 +709,8 @@ function qwenFrames(target2, line, from, replyToken, msgId) {
|
|
|
686
709
|
}
|
|
687
710
|
async function sendQwenWake(target2, line, signal, options = {}) {
|
|
688
711
|
if (signal.aborted) return "failed";
|
|
689
|
-
const dir = await fs6.mkdtemp(
|
|
690
|
-
const from =
|
|
712
|
+
const dir = await fs6.mkdtemp(path6.join(options.runtimeDir ?? os3.tmpdir(), "khala-qw-"));
|
|
713
|
+
const from = path6.join(dir, "r.sock");
|
|
691
714
|
if (Buffer.byteLength(from) > 103) {
|
|
692
715
|
await fs6.rm(dir, { recursive: true, force: true });
|
|
693
716
|
return "failed";
|
|
@@ -767,14 +790,14 @@ async function sendQwenWake(target2, line, signal, options = {}) {
|
|
|
767
790
|
function createQwenSocketDriver(deps = {}) {
|
|
768
791
|
const resolve = deps.resolve ?? target;
|
|
769
792
|
const policy = async (env) => {
|
|
770
|
-
const config = await readJson(
|
|
793
|
+
const config = await readJson(path6.join(qwenHome(env), "settings.json"));
|
|
771
794
|
return config?.agents;
|
|
772
795
|
};
|
|
773
796
|
const reason = async (ctx) => {
|
|
774
797
|
const config = await policy(ctx.env);
|
|
775
798
|
if (config?.crossSessionInbound === "hold") return "qwen_held";
|
|
776
799
|
if ((deps.platform ?? process.platform) === "win32") return "windows";
|
|
777
|
-
const receipt = await readJson(
|
|
800
|
+
const receipt = await readJson(path6.join(ctx.files.dir, "qwen-receipt.json"));
|
|
778
801
|
if (receipt?.status === "held" && config?.crossSessionInbound !== "accept") return "qwen_held";
|
|
779
802
|
if (config?.crossSessionMessaging === false || config?.crossSessionInbound === "refuse") return "qwen_refused";
|
|
780
803
|
if (!deps.resolve && !ctx.env.QWEN_CODE_MESSAGING_SOCKET) return "qwen_session_missing";
|
|
@@ -788,15 +811,15 @@ function createQwenSocketDriver(deps = {}) {
|
|
|
788
811
|
deadlineMs: 3e4,
|
|
789
812
|
verification: "transcript",
|
|
790
813
|
async verify(ctx) {
|
|
791
|
-
const journal = await readJson(
|
|
792
|
-
const receipt = await readJson(
|
|
814
|
+
const journal = await readJson(path6.join(ctx.files.dir, "wake-journal.json"));
|
|
815
|
+
const receipt = await readJson(path6.join(ctx.files.dir, "qwen-receipt.json"));
|
|
793
816
|
if (!journal?.attempts?.some((attempt) => attempt.driver === "socket") && receipt?.status !== "held") return;
|
|
794
|
-
const transcript = await readJson(
|
|
817
|
+
const transcript = await readJson(path6.join(ctx.files.dir, "qwen-transcript.json"));
|
|
795
818
|
if (!transcript?.path) return;
|
|
796
819
|
try {
|
|
797
820
|
const text = await verifyQwenTranscript(ctx.files.dir, transcript.path, ctx.now);
|
|
798
821
|
if (receipt?.status === "held" && receipt.nonce && text?.includes(`(k-${receipt.nonce})`)) {
|
|
799
|
-
await writeJsonAtomic(
|
|
822
|
+
await writeJsonAtomic(path6.join(ctx.files.dir, "qwen-receipt.json"), { status: "delivered" });
|
|
800
823
|
}
|
|
801
824
|
} catch {
|
|
802
825
|
}
|
|
@@ -810,7 +833,7 @@ function createQwenSocketDriver(deps = {}) {
|
|
|
810
833
|
const status = await (deps.send ?? sendQwenWake)(destination, line, ctx.signal);
|
|
811
834
|
await ensureStateDir(ctx.files.dir);
|
|
812
835
|
const nonce = line.match(/\(k-([0-9a-f]{8})\)$/u)?.[1];
|
|
813
|
-
await writeJsonAtomic(
|
|
836
|
+
await writeJsonAtomic(path6.join(ctx.files.dir, "qwen-receipt.json"), { status, nonce });
|
|
814
837
|
if (nonce && status === "held") await cancelAttempt(ctx.files.dir, nonce);
|
|
815
838
|
else if (nonce && status !== "delivered") await failAttempt(ctx.files.dir, nonce, ctx.now);
|
|
816
839
|
}
|
|
@@ -821,11 +844,11 @@ function createQwenSocketDriver(deps = {}) {
|
|
|
821
844
|
var MARKER = "monitor.json";
|
|
822
845
|
var OBSERVATION = "monitor-cursor.json";
|
|
823
846
|
var NONCE_PATTERN = /^[a-f0-9-]{36}$/;
|
|
824
|
-
var leaseFile = (dir, nonce) =>
|
|
847
|
+
var leaseFile = (dir, nonce) => path7.join(dir, `monitor-${nonce}.json`);
|
|
825
848
|
async function monitorOwner(files) {
|
|
826
849
|
const owners = [];
|
|
827
850
|
for (const dir of monitorStorageCandidates(files)) {
|
|
828
|
-
const owner = await readJson(
|
|
851
|
+
const owner = await readJson(path7.join(dir, MARKER));
|
|
829
852
|
if (!owner || !Number.isSafeInteger(owner.pid) || owner.pid <= 0 || typeof owner.nonce !== "string" || !NONCE_PATTERN.test(owner.nonce)) continue;
|
|
830
853
|
const lease = await readJson(leaseFile(dir, owner.nonce));
|
|
831
854
|
if (lease?.nonce !== owner.nonce) continue;
|
|
@@ -944,7 +967,7 @@ async function watchSession(files, io) {
|
|
|
944
967
|
}
|
|
945
968
|
const mode = await readListeningMode(target2);
|
|
946
969
|
const entries = await readEntries(target2);
|
|
947
|
-
const observed = await readJson(
|
|
970
|
+
const observed = await readJson(path7.join(await observationDir(target2), OBSERVATION));
|
|
948
971
|
const position = observed?.userId === session.userId && observed?.roomId === session.roomId && Number.isSafeInteger(observed.count) && observed.count >= 0 && observed.count <= entries.length && (observed.count === 0 || entries[observed.count - 1]?.eventId === observed.lastEventId) ? observed.count : 0;
|
|
949
972
|
const baseline = initialDelivered.get(target2.dir).cursor;
|
|
950
973
|
const initialCount = baseline.deliveredCount === 0 || entries[baseline.deliveredCount - 1]?.eventId === baseline.lastDeliveredEventId ? baseline.deliveredCount : 0;
|
|
@@ -970,7 +993,7 @@ async function watchSession(files, io) {
|
|
|
970
993
|
}
|
|
971
994
|
if (position !== entries.length && !done && await ownsSession() && JSON.stringify(await readJson(target2.session)) === JSON.stringify(latestSession)) {
|
|
972
995
|
try {
|
|
973
|
-
await writeJsonAtomic(
|
|
996
|
+
await writeJsonAtomic(path7.join(await observationDir(target2), OBSERVATION), {
|
|
974
997
|
userId: session.userId,
|
|
975
998
|
roomId: session.roomId,
|
|
976
999
|
count: entries.length,
|
|
@@ -982,7 +1005,7 @@ async function watchSession(files, io) {
|
|
|
982
1005
|
}
|
|
983
1006
|
}
|
|
984
1007
|
if (io.harness === "muse" && !done && await ownsSession()) {
|
|
985
|
-
const request = await readJson(
|
|
1008
|
+
const request = await readJson(path7.join(files.dir, MUSE_WAKE_REQUEST));
|
|
986
1009
|
const now = (io.now ?? Date.now)();
|
|
987
1010
|
const wakeNonce = typeof request?.line === "string" ? /\(k-([a-f0-9]{8})\)$/.exec(request.line)?.[1] : void 0;
|
|
988
1011
|
if (request?.owner === nonce && wakeNonce && wakeLine(wakeNonce) === request.line && request.line !== emittedRequest && now >= request.at && now < request.deadline && await driverAllowed(stateRoot(io.env ?? process.env), "muse", "monitor", false) && !(await readWakeState(files.dir)).monitor?.disabled && (await readActivity(files)).state === "idle") {
|
|
@@ -1000,7 +1023,7 @@ async function watchSession(files, io) {
|
|
|
1000
1023
|
const activity = await readActivity(files);
|
|
1001
1024
|
if (eligible && await ownsSession() && activity.state === "idle") {
|
|
1002
1025
|
const epoch = activity.updatedAt;
|
|
1003
|
-
const dedupFile =
|
|
1026
|
+
const dedupFile = path7.join(storage, "monitor-wake-observed.json");
|
|
1004
1027
|
const observed = await readJson(dedupFile);
|
|
1005
1028
|
if (observed?.epoch === epoch) return;
|
|
1006
1029
|
await writeJsonAtomic(dedupFile, { epoch, line: request.line });
|
|
@@ -1031,7 +1054,7 @@ async function watchSession(files, io) {
|
|
|
1031
1054
|
watcher.on("error", (error) => stop(3, errorReason(error)));
|
|
1032
1055
|
lastHeartbeat = Date.now();
|
|
1033
1056
|
await writeJsonAtomic(leaseFile(storage, nonce), { nonce, pid: process.pid, heartbeatAt: new Date(lastHeartbeat).toISOString() });
|
|
1034
|
-
await writeJsonAtomic(
|
|
1057
|
+
await writeJsonAtomic(path7.join(storage, MARKER), { nonce, pid: process.pid, startedAt: Date.now() });
|
|
1035
1058
|
published = true;
|
|
1036
1059
|
timer = setInterval(notify, 100);
|
|
1037
1060
|
io.signal.addEventListener("abort", abort, { once: true });
|
|
@@ -1064,8 +1087,8 @@ ${WATCH_USAGE}`);
|
|
|
1064
1087
|
return 1;
|
|
1065
1088
|
};
|
|
1066
1089
|
if (argv.length !== 0 && !(argv.length === 2 && ["--session", "--harness"].includes(argv[0])) && !(argv.length === 4 && argv[0] === "--harness" && argv[2] === "--session")) return invalid("invalid_arguments");
|
|
1067
|
-
const { resolveHarness, resolveSessionId } = await import("./chunk-
|
|
1068
|
-
const { adapterFor } = await import("./chunk-
|
|
1090
|
+
const { resolveHarness, resolveSessionId } = await import("./chunk-TVQ5NHFX.mjs");
|
|
1091
|
+
const { adapterFor } = await import("./chunk-WZD4JAG6.mjs");
|
|
1069
1092
|
const harness = resolveHarness(argv, process.env);
|
|
1070
1093
|
if (harness === "invalid" || !adapterFor(harness)?.codec) return invalid("invalid_harness");
|
|
1071
1094
|
const index = argv.indexOf("--session");
|
|
@@ -1093,7 +1116,12 @@ export {
|
|
|
1093
1116
|
readWakeSettings,
|
|
1094
1117
|
updateWakeSettings,
|
|
1095
1118
|
driverAllowed,
|
|
1119
|
+
readModeState,
|
|
1120
|
+
delegateChannel,
|
|
1121
|
+
isDelegated,
|
|
1096
1122
|
readListeningMode,
|
|
1123
|
+
applyArchived,
|
|
1124
|
+
ATTENTION,
|
|
1097
1125
|
applyListeningMode,
|
|
1098
1126
|
CURSOR_WORKSPACE_ENV,
|
|
1099
1127
|
CURSOR_DEFAULT_SESSION,
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
retryUnexpired
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-MRSZOWFU.mjs";
|
|
5
5
|
import {
|
|
6
6
|
StateError,
|
|
7
7
|
ensureStateDir,
|
|
8
8
|
writeJsonAtomic
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-NHW62KEB.mjs";
|
|
10
10
|
import {
|
|
11
11
|
__commonJS,
|
|
12
12
|
__export,
|
|
13
13
|
__toESM,
|
|
14
14
|
init_define_KHALA_BUNDLE
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-3JA3Q5MK.mjs";
|
|
16
16
|
|
|
17
17
|
// ../../node_modules/.pnpm/immediate@3.3.0/node_modules/immediate/lib/nextTick.js
|
|
18
18
|
var require_nextTick = __commonJS({
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
readJson,
|
|
5
5
|
readProcess,
|
|
6
6
|
writeJsonAtomic
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NHW62KEB.mjs";
|
|
8
8
|
import {
|
|
9
9
|
init_define_KHALA_BUNDLE
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-3JA3Q5MK.mjs";
|
|
11
11
|
|
|
12
12
|
// src/wake/terminal/capture.ts
|
|
13
13
|
init_define_KHALA_BUNDLE();
|
package/dist/khala.mjs
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
KHALA_AGENT_VERSION
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-32SGUUP5.mjs";
|
|
6
|
+
import "./chunk-RUQDE5DI.mjs";
|
|
7
7
|
import {
|
|
8
8
|
init_define_KHALA_BUNDLE
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-3JA3Q5MK.mjs";
|
|
10
10
|
|
|
11
11
|
// src/cli-bundle.ts
|
|
12
12
|
init_define_KHALA_BUNDLE();
|
|
@@ -84,15 +84,15 @@ async function runCli(argv, modules) {
|
|
|
84
84
|
|
|
85
85
|
// src/cli-bundle.ts
|
|
86
86
|
var hooks = {
|
|
87
|
-
"session-start": () => import("./chunk-
|
|
88
|
-
deliver: () => import("./chunk-
|
|
89
|
-
"claude-wake": () => import("./chunk-
|
|
87
|
+
"session-start": () => import("./chunk-SUT7AKNZ.mjs"),
|
|
88
|
+
deliver: () => import("./chunk-6DE4V756.mjs"),
|
|
89
|
+
"claude-wake": () => import("./chunk-SKJ6YV3G.mjs")
|
|
90
90
|
};
|
|
91
91
|
process.exitCode = await runCli(process.argv.slice(2), {
|
|
92
|
-
mcp: () => () => import("./chunk-
|
|
93
|
-
watch: () => () => import("./chunk-
|
|
94
|
-
local: () => () => import("./chunk-
|
|
95
|
-
install: () => () => import("./chunk-
|
|
96
|
-
wake: () => () => import("./chunk-
|
|
92
|
+
mcp: () => () => import("./chunk-JLENHMKE.mjs"),
|
|
93
|
+
watch: () => () => import("./chunk-OIYAR2ND.mjs"),
|
|
94
|
+
local: () => () => import("./chunk-3GUVMXTM.mjs"),
|
|
95
|
+
install: () => () => import("./chunk-BWVC3EKG.mjs"),
|
|
96
|
+
wake: () => () => import("./chunk-2BNIPJVW.mjs"),
|
|
97
97
|
hook: (name) => Object.hasOwn(hooks, name) ? hooks[name] : void 0
|
|
98
98
|
});
|