khala-cli 0.4.4 → 0.4.6
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-OS2JLDL7.mjs → chunk-2U4E7AM7.mjs} +22 -5
- package/dist/{chunk-GE3RXO2X.mjs → chunk-2XTYRBYX.mjs} +10 -4
- package/dist/{chunk-6OADQWV7.mjs → chunk-4X35OUAN.mjs} +100 -39
- package/dist/{chunk-ZKDDKUUA.mjs → chunk-55KBLEX5.mjs} +1 -1
- package/dist/{chunk-AK74S7EN.mjs → chunk-6E3UCO22.mjs} +32 -11
- package/dist/chunk-AWBKVTLV.mjs +238 -0
- package/dist/{chunk-FA6Z65DW.mjs → chunk-B2MOLCJM.mjs} +9 -5
- package/dist/{chunk-DC3OX6F4.mjs → chunk-CWHGNVZV.mjs} +0 -18
- package/dist/chunk-DPW43YNC.mjs +36 -0
- package/dist/{chunk-PJ3E3IVH.mjs → chunk-FH2CZX5T.mjs} +14 -12
- package/dist/{chunk-LHAMBQK7.mjs → chunk-IULQYQJZ.mjs} +3 -3
- package/dist/{chunk-FUU775QM.mjs → chunk-JG5J3SHW.mjs} +14 -1
- package/dist/{chunk-MZS7XFMC.mjs → chunk-OECJ45NM.mjs} +2 -2
- package/dist/{chunk-XEYKJMZL.mjs → chunk-OW3DSTEZ.mjs} +57 -4
- package/dist/{chunk-ZRFXZK72.mjs → chunk-PFDUXY3N.mjs} +1 -1
- package/dist/{chunk-MU4FUENP.mjs → chunk-PY2ZNVNY.mjs} +20 -5
- package/dist/{chunk-7CVU5OZ7.mjs → chunk-RRBIVI77.mjs} +1 -1
- package/dist/{chunk-LN3G2LJV.mjs → chunk-SZIEG3RS.mjs} +6 -5
- package/dist/chunk-WHONG7UF.mjs +267 -0
- package/dist/chunk-XUJIJ4KB.mjs +216 -0
- package/dist/{chunk-LQ6KNUNN.mjs → chunk-Z4EDYB6Y.mjs} +465 -349
- package/dist/chunk-ZHMGB3PP.mjs +82 -0
- package/dist/khala.mjs +10 -10
- package/dist/web/assets/local-K8EcTVxW.js +9 -0
- package/dist/web/assets/local-R2y0Gl4T.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/chunk-ENPBK5W2.mjs +0 -187
- package/dist/chunk-N5VYKQMR.mjs +0 -108
- package/dist/chunk-VUE2DDYY.mjs +0 -34
- package/dist/web/assets/local-Bk8hMIT-.js +0 -9
- package/dist/web/assets/local-vdvavyq0.css +0 -1
|
@@ -3,22 +3,6 @@ import {
|
|
|
3
3
|
decodeChannelEvent,
|
|
4
4
|
formatChannelEventLine
|
|
5
5
|
} from "./chunk-P5CP32X2.mjs";
|
|
6
|
-
import {
|
|
7
|
-
readJson,
|
|
8
|
-
writeJsonAtomic
|
|
9
|
-
} from "./chunk-XEYKJMZL.mjs";
|
|
10
|
-
|
|
11
|
-
// src/activity.ts
|
|
12
|
-
import path from "node:path";
|
|
13
|
-
async function readActivity(files) {
|
|
14
|
-
const activity = await readJson(path.join(files.dir, "activity.json"));
|
|
15
|
-
return activity && ["idle", "busy"].includes(activity.state) && typeof activity.updatedAt === "string" && Number.isFinite(Date.parse(activity.updatedAt)) ? activity : { state: "busy", updatedAt: (/* @__PURE__ */ new Date(0)).toISOString() };
|
|
16
|
-
}
|
|
17
|
-
async function writeActivity(files, state, now = () => /* @__PURE__ */ new Date()) {
|
|
18
|
-
const activity = { state, updatedAt: now().toISOString() };
|
|
19
|
-
await writeJsonAtomic(path.join(files.dir, "activity.json"), activity);
|
|
20
|
-
return activity;
|
|
21
|
-
}
|
|
22
6
|
|
|
23
7
|
// src/events/receive.ts
|
|
24
8
|
function toEventInboxEntry(base, rawContent) {
|
|
@@ -44,8 +28,6 @@ function isWakeEntry(entry) {
|
|
|
44
28
|
}
|
|
45
29
|
|
|
46
30
|
export {
|
|
47
|
-
readActivity,
|
|
48
|
-
writeActivity,
|
|
49
31
|
toEventInboxEntry,
|
|
50
32
|
createEventKeyFilter,
|
|
51
33
|
isWakeEntry
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
+
|
|
3
|
+
// ../contracts/src/m1/harness.ts
|
|
4
|
+
var LEGACY_HARNESSES = ["claude", "codex", "cursor"];
|
|
5
|
+
var HARNESS_REGISTRY = [
|
|
6
|
+
{ id: "claude", displayName: "Claude Code", modelName: "Claude", logoKey: "claude", steer: true, sync: true, idleWake: "default", registered: true },
|
|
7
|
+
{ id: "codex", displayName: "Codex", modelName: "Codex", logoKey: "codex", steer: true, sync: true, idleWake: "default", registered: true },
|
|
8
|
+
{ id: "cursor", displayName: "Cursor", modelName: "Cursor", logoKey: "cursor", steer: true, sync: true, idleWake: "none", registered: true },
|
|
9
|
+
{ id: "opencode", displayName: "OpenCode", modelName: "OpenCode", logoKey: "opencode", steer: true, sync: true, idleWake: "default", registered: true },
|
|
10
|
+
{ id: "copilot", displayName: "Copilot CLI", modelName: "Copilot", logoKey: "copilot", steer: true, sync: true, idleWake: "opt-in", registered: true },
|
|
11
|
+
{ id: "vscode", displayName: "Copilot (VS Code)", modelName: "VSCode", logoKey: "vscode", steer: true, sync: true, idleWake: "opt-in", registered: true },
|
|
12
|
+
{ id: "gemini", displayName: "Gemini CLI", modelName: "Gemini", logoKey: "gemini", steer: true, sync: true, idleWake: "opt-in", registered: true },
|
|
13
|
+
// U29 and U33 establish these capabilities after their spikes.
|
|
14
|
+
{ id: "antigravity", displayName: "Antigravity CLI", modelName: "Antigravity", logoKey: "antigravity", steer: false, sync: false, idleWake: "none", registered: true },
|
|
15
|
+
{ id: "qwen", displayName: "Qwen Code", modelName: "Qwen", logoKey: "qwen", steer: true, sync: true, idleWake: "default", registered: true },
|
|
16
|
+
{ id: "muse", displayName: "Muse Code", modelName: "Muse", logoKey: "muse", steer: false, sync: false, idleWake: "none", registered: true },
|
|
17
|
+
{ id: "generic", displayName: "MCP agent", modelName: "Agent", logoKey: null, steer: false, sync: false, idleWake: "none", registered: true }
|
|
18
|
+
];
|
|
19
|
+
function harnessInfo(id) {
|
|
20
|
+
return HARNESS_REGISTRY.find((row) => row.id === id) ?? {
|
|
21
|
+
id,
|
|
22
|
+
displayName: id.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" "),
|
|
23
|
+
modelName: "Agent",
|
|
24
|
+
logoKey: null,
|
|
25
|
+
steer: false,
|
|
26
|
+
sync: false,
|
|
27
|
+
idleWake: "none",
|
|
28
|
+
registered: false
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
LEGACY_HARNESSES,
|
|
34
|
+
HARNESS_REGISTRY,
|
|
35
|
+
harnessInfo
|
|
36
|
+
};
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
ensureHelper,
|
|
4
|
-
helperPaths,
|
|
5
|
-
readHelperFile
|
|
6
|
-
} from "./chunk-LHAMBQK7.mjs";
|
|
7
2
|
import {
|
|
8
3
|
parseChannelLink,
|
|
9
4
|
resolveLocalOwnerName
|
|
10
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-OECJ45NM.mjs";
|
|
11
6
|
import {
|
|
12
7
|
KHALA_AGENT_VERSION
|
|
13
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-RRBIVI77.mjs";
|
|
9
|
+
import {
|
|
10
|
+
ensureHelper,
|
|
11
|
+
helperPaths,
|
|
12
|
+
readHelperFile
|
|
13
|
+
} from "./chunk-IULQYQJZ.mjs";
|
|
14
14
|
import {
|
|
15
15
|
LOCAL_AGENT_DEVICE_PREFIX,
|
|
16
16
|
LOCAL_IDLE_EXIT_MS,
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
LOCAL_TOKEN_BYTES,
|
|
23
23
|
base64url,
|
|
24
24
|
checkName,
|
|
25
|
+
checkNewUsername,
|
|
25
26
|
decodeChannelSecrets,
|
|
26
27
|
decodeLocalEvent,
|
|
27
28
|
decodeOwnerProfile,
|
|
@@ -35,10 +36,10 @@ import {
|
|
|
35
36
|
newLocalEventId,
|
|
36
37
|
newLocalRoomId,
|
|
37
38
|
normalizeInitials
|
|
38
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-2U4E7AM7.mjs";
|
|
39
40
|
import {
|
|
40
41
|
bundle
|
|
41
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-PFDUXY3N.mjs";
|
|
42
43
|
import "./chunk-5GLTKWJ5.mjs";
|
|
43
44
|
import {
|
|
44
45
|
CHANNEL_EVENT_TYPE,
|
|
@@ -46,12 +47,13 @@ import {
|
|
|
46
47
|
encodeChannelEvent,
|
|
47
48
|
memberRenameContent
|
|
48
49
|
} from "./chunk-P5CP32X2.mjs";
|
|
50
|
+
import "./chunk-DPW43YNC.mjs";
|
|
49
51
|
import {
|
|
50
52
|
StateError,
|
|
51
53
|
ensureStateDir,
|
|
52
54
|
readJson,
|
|
53
55
|
writeJsonAtomic
|
|
54
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-OW3DSTEZ.mjs";
|
|
55
57
|
import {
|
|
56
58
|
DEFAULT_LISTENING_MODE,
|
|
57
59
|
LISTENING_MODE_COMMAND_TYPE,
|
|
@@ -69,7 +71,7 @@ import {
|
|
|
69
71
|
validAgentRejoinSecret,
|
|
70
72
|
validAgentSessionId
|
|
71
73
|
} from "./chunk-SN3STAO2.mjs";
|
|
72
|
-
import "./chunk-
|
|
74
|
+
import "./chunk-55KBLEX5.mjs";
|
|
73
75
|
|
|
74
76
|
// src/local/cli.ts
|
|
75
77
|
import { setTimeout as sleepDefault } from "node:timers/promises";
|
|
@@ -1427,7 +1429,7 @@ function profileRoutes(options = {}) {
|
|
|
1427
1429
|
route("POST", /^\/api\/local\/profile\/username$/u, async (req, ctx) => {
|
|
1428
1430
|
const parsed = field(req.body, "username");
|
|
1429
1431
|
if (!parsed.ok) return fail5(400, "invalid_request");
|
|
1430
|
-
const checked =
|
|
1432
|
+
const checked = checkNewUsername(parsed.value);
|
|
1431
1433
|
if (!checked.ok) return { status: 400, json: { error: "invalid_username", reason: checked.error } };
|
|
1432
1434
|
const username = checked.name;
|
|
1433
1435
|
const p = ctx.store.owner();
|
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
KhalaClientError,
|
|
4
4
|
LOCAL_DEFAULT_PORT,
|
|
5
5
|
decodeHelperFile
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2U4E7AM7.mjs";
|
|
7
7
|
import {
|
|
8
8
|
bundle
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-PFDUXY3N.mjs";
|
|
10
10
|
import {
|
|
11
11
|
StateError,
|
|
12
12
|
ensureStateDir,
|
|
13
13
|
readJson,
|
|
14
14
|
stateRoot
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-OW3DSTEZ.mjs";
|
|
16
16
|
|
|
17
17
|
// src/local/lifecycle.ts
|
|
18
18
|
import * as fs from "node:fs/promises";
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
memberListeningMode
|
|
12
12
|
} from "./chunk-AUJEUKVM.mjs";
|
|
13
13
|
import "./chunk-SN3STAO2.mjs";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-55KBLEX5.mjs";
|
|
15
15
|
|
|
16
16
|
// src/matrix/session.ts
|
|
17
17
|
import { createClient, ClientEvent, RoomEvent, MatrixEventEvent, SyncState, Direction, Method, EventType } from "matrix-js-sdk";
|
|
@@ -308,6 +308,19 @@ async function createAgentMatrixSession(creds, opts) {
|
|
|
308
308
|
}
|
|
309
309
|
if (event.getType() === "m.room.encrypted" || event.isDecryptionFailure()) {
|
|
310
310
|
undecryptable++;
|
|
311
|
+
const eventId = event.getId(), sender = event.getSender();
|
|
312
|
+
if (eventId && sender && eventId !== before) {
|
|
313
|
+
const body = "[Encrypted message unavailable: this device does not have its key. Messages from before joining may not have been shared.]";
|
|
314
|
+
messages.push({
|
|
315
|
+
eventId,
|
|
316
|
+
roomId,
|
|
317
|
+
sender,
|
|
318
|
+
ts: event.getTs(),
|
|
319
|
+
type: "m.room.message",
|
|
320
|
+
body,
|
|
321
|
+
content: { msgtype: "m.notice", body, "com.khala.unavailable": true }
|
|
322
|
+
});
|
|
323
|
+
}
|
|
311
324
|
continue;
|
|
312
325
|
}
|
|
313
326
|
const m = message(event);
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
MODEL_NAMES,
|
|
5
5
|
checkName,
|
|
6
6
|
isDefaultAgentName
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2U4E7AM7.mjs";
|
|
8
8
|
import {
|
|
9
9
|
StateError,
|
|
10
10
|
readJson,
|
|
11
11
|
stateRoot,
|
|
12
12
|
writeJsonAtomic
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-OW3DSTEZ.mjs";
|
|
14
14
|
import {
|
|
15
15
|
HARNESSES,
|
|
16
16
|
validateAgentName
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
// src/state.ts
|
|
7
7
|
import { constants } from "node:fs";
|
|
8
8
|
import * as fs from "node:fs/promises";
|
|
9
|
-
import { randomUUID } from "node:crypto";
|
|
9
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
10
10
|
import os from "node:os";
|
|
11
11
|
import path from "node:path";
|
|
12
12
|
var SESSION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
@@ -38,6 +38,38 @@ function stateRoot(env = process.env) {
|
|
|
38
38
|
function filesForDir(dir) {
|
|
39
39
|
return { dir, mode: path.join(dir, "mode.json"), join: path.join(dir, "join.json"), session: path.join(dir, "session.json"), inbox: path.join(dir, "inbox.jsonl"), cursor: path.join(dir, "cursor.json"), status: path.join(dir, "status.json") };
|
|
40
40
|
}
|
|
41
|
+
function stateKey(value) {
|
|
42
|
+
return createHash("sha256").update(value).digest("hex").slice(0, 24);
|
|
43
|
+
}
|
|
44
|
+
function channelsDir(files) {
|
|
45
|
+
return path.join(files.dir, "channels");
|
|
46
|
+
}
|
|
47
|
+
function channelFiles(files, roomId) {
|
|
48
|
+
return filesForDir(path.join(channelsDir(files), stateKey(roomId)));
|
|
49
|
+
}
|
|
50
|
+
function joinFilePath(files, key) {
|
|
51
|
+
if (!/^[a-f0-9]{24}$/.test(key)) throw new StateError("storage_failed");
|
|
52
|
+
return path.join(files.dir, "joins", `${key}.json`);
|
|
53
|
+
}
|
|
54
|
+
async function writeJoinFile(files, link, join) {
|
|
55
|
+
const file = joinFilePath(files, stateKey(link));
|
|
56
|
+
await ensureStateDir(path.dirname(file));
|
|
57
|
+
await writeJsonAtomic(file, join);
|
|
58
|
+
}
|
|
59
|
+
async function readJoinFile(files, link) {
|
|
60
|
+
const file = joinFilePath(files, stateKey(link));
|
|
61
|
+
await ensureStateDir(path.dirname(file));
|
|
62
|
+
return readJson(file);
|
|
63
|
+
}
|
|
64
|
+
async function removeJoinFile(files, link) {
|
|
65
|
+
const file = joinFilePath(files, stateKey(link));
|
|
66
|
+
await ensureStateDir(path.dirname(file));
|
|
67
|
+
try {
|
|
68
|
+
await fs.unlink(file);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (error.code !== "ENOENT") throw new StateError("storage_failed");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
41
73
|
function sessionFiles(harness, sessionId, env) {
|
|
42
74
|
if (!HARNESSES.includes(harness) || !SESSION_ID_PATTERN.test(sessionId)) throw new StateError("invalid_session_id");
|
|
43
75
|
return filesForDir(path.join(stateRoot(env), harness, sessionId));
|
|
@@ -47,7 +79,20 @@ function resolveStateDir(harness, sessionId, env) {
|
|
|
47
79
|
}
|
|
48
80
|
async function ensureStateDir(dir) {
|
|
49
81
|
try {
|
|
50
|
-
|
|
82
|
+
let sessionDir = dir;
|
|
83
|
+
if (path.basename(path.dirname(dir)) === "channels" && /^[a-f0-9]{24}$/.test(path.basename(dir)) && HARNESSES.includes(path.basename(path.dirname(path.dirname(path.dirname(dir)))))) {
|
|
84
|
+
sessionDir = path.dirname(path.dirname(dir));
|
|
85
|
+
} else if (["channels", "joins"].includes(path.basename(dir)) && HARNESSES.includes(path.basename(path.dirname(path.dirname(dir))))) {
|
|
86
|
+
sessionDir = path.dirname(dir);
|
|
87
|
+
}
|
|
88
|
+
const directories = [path.dirname(path.dirname(sessionDir)), path.dirname(sessionDir), sessionDir];
|
|
89
|
+
const relative = path.relative(sessionDir, dir);
|
|
90
|
+
let parent = sessionDir;
|
|
91
|
+
for (const component of relative ? relative.split(path.sep) : []) {
|
|
92
|
+
parent = path.join(parent, component);
|
|
93
|
+
directories.push(parent);
|
|
94
|
+
}
|
|
95
|
+
for (const directory of directories) {
|
|
51
96
|
try {
|
|
52
97
|
await fs.mkdir(directory, { recursive: true, mode: 448 });
|
|
53
98
|
} catch (error) {
|
|
@@ -105,7 +150,7 @@ function readStatus(files) {
|
|
|
105
150
|
return readJson(files.status);
|
|
106
151
|
}
|
|
107
152
|
async function writeStateFile(dir, name, value) {
|
|
108
|
-
if (!["join.json", "session.json", "cursor.json", "status.json", "mode.json", "rejoin.json"].includes(name)) throw new StateError("storage_failed");
|
|
153
|
+
if (!["join.json", "session.json", "cursor.json", "status.json", "mode.json", "rejoin.json", "channel.json", "resume.json"].includes(name)) throw new StateError("storage_failed");
|
|
109
154
|
await writeJsonAtomic(path.join(dir, name), value);
|
|
110
155
|
}
|
|
111
156
|
function readStateFile(dir, name) {
|
|
@@ -120,12 +165,19 @@ async function removeStateFile(dir, name) {
|
|
|
120
165
|
if (error.code !== "ENOENT") throw new StateError("storage_failed");
|
|
121
166
|
}
|
|
122
167
|
}
|
|
168
|
+
var TERMINAL_SESSION_DETAILS = ["left", "removed", "revoked", "unauthorized", "channel_deleted"];
|
|
123
169
|
|
|
124
170
|
export {
|
|
125
171
|
SESSION_ID_PATTERN,
|
|
126
172
|
StateError,
|
|
127
173
|
stateRoot,
|
|
128
174
|
filesForDir,
|
|
175
|
+
stateKey,
|
|
176
|
+
channelsDir,
|
|
177
|
+
channelFiles,
|
|
178
|
+
writeJoinFile,
|
|
179
|
+
readJoinFile,
|
|
180
|
+
removeJoinFile,
|
|
129
181
|
sessionFiles,
|
|
130
182
|
resolveStateDir,
|
|
131
183
|
ensureStateDir,
|
|
@@ -134,5 +186,6 @@ export {
|
|
|
134
186
|
readStatus,
|
|
135
187
|
writeStateFile,
|
|
136
188
|
readStateFile,
|
|
137
|
-
removeStateFile
|
|
189
|
+
removeStateFile,
|
|
190
|
+
TERMINAL_SESSION_DETAILS
|
|
138
191
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
define_KHALA_BUNDLE_default
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-55KBLEX5.mjs";
|
|
5
5
|
|
|
6
6
|
// src/bundle.ts
|
|
7
7
|
var bundle = typeof define_KHALA_BUNDLE_default === "undefined" ? void 0 : define_KHALA_BUNDLE_default;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
-
import "./chunk-
|
|
2
|
+
import "./chunk-55KBLEX5.mjs";
|
|
3
3
|
|
|
4
4
|
// hooks/claude-wake.ts
|
|
5
5
|
import fs from "node:fs/promises";
|
|
@@ -18,7 +18,7 @@ async function readJson(file) {
|
|
|
18
18
|
throw error;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
async function
|
|
21
|
+
async function unreadChannelMessages(dir) {
|
|
22
22
|
const cursor = await readJson(path.join(dir, "cursor.json"));
|
|
23
23
|
const delivered = cursor && (cursor.lastDeliveredEventId === null || typeof cursor.lastDeliveredEventId === "string") && Number.isSafeInteger(cursor.deliveredCount) && typeof cursor.deliveredCount === "number" && cursor.deliveredCount >= 0 ? cursor.deliveredCount : 0;
|
|
24
24
|
let content;
|
|
@@ -41,6 +41,22 @@ async function unreadMessages(dir) {
|
|
|
41
41
|
}
|
|
42
42
|
return messages;
|
|
43
43
|
}
|
|
44
|
+
async function unreadMessages(dir) {
|
|
45
|
+
const directories = [dir];
|
|
46
|
+
try {
|
|
47
|
+
for (const entry of await fs.readdir(path.join(dir, "channels"), { withFileTypes: true })) {
|
|
48
|
+
if (entry.isDirectory() && !entry.isSymbolicLink()) directories.push(path.join(dir, "channels", entry.name));
|
|
49
|
+
}
|
|
50
|
+
} catch (error) {
|
|
51
|
+
if (error.code !== "ENOENT") throw error;
|
|
52
|
+
}
|
|
53
|
+
let messages = 0;
|
|
54
|
+
for (const directory of directories) {
|
|
55
|
+
if ((await readJson(path.join(directory, "mode.json")))?.mode === "async") continue;
|
|
56
|
+
messages += await unreadChannelMessages(directory);
|
|
57
|
+
}
|
|
58
|
+
return messages;
|
|
59
|
+
}
|
|
44
60
|
function testDuration(value, fallback) {
|
|
45
61
|
const number = Number(value);
|
|
46
62
|
return Number.isSafeInteger(number) && number > 0 ? number : fallback;
|
|
@@ -78,11 +94,10 @@ async function watch(stdin, _argv, io = { stderr: process.stderr, env: process.e
|
|
|
78
94
|
const activity = await readJson(path.join(dir, "activity.json"));
|
|
79
95
|
return activity?.state === "idle" && typeof activity.updatedAt === "string" && Number.isFinite(Date.parse(activity.updatedAt));
|
|
80
96
|
};
|
|
81
|
-
const listening = async () => (await readJson(path.join(dir, "mode.json")))?.mode !== "async";
|
|
82
97
|
while (io.now().getTime() < deadline) {
|
|
83
98
|
if (!await owns() || !parentAlive(parent)) return 0;
|
|
84
|
-
if (await
|
|
85
|
-
if (await unreadMessages(dir) > 0 && await
|
|
99
|
+
if (await idle() && await unreadMessages(dir) > 0) {
|
|
100
|
+
if (await unreadMessages(dir) > 0 && await idle() && await owns() && parentAlive(parent) && io.now().getTime() < deadline) {
|
|
86
101
|
io.stderr.write(NOTICE);
|
|
87
102
|
return 2;
|
|
88
103
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
bundle
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PFDUXY3N.mjs";
|
|
5
5
|
|
|
6
6
|
// src/version.ts
|
|
7
7
|
var KHALA_AGENT_VERSION = bundle?.version ?? "0.0.0";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
ensureHelper
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-IULQYQJZ.mjs";
|
|
5
5
|
import {
|
|
6
6
|
KhalaClientError,
|
|
7
7
|
LOCAL_LONG_POLL_MAX_S,
|
|
@@ -16,19 +16,20 @@ import {
|
|
|
16
16
|
decodeLocalNameContent,
|
|
17
17
|
decodeLocalSendResult,
|
|
18
18
|
localRoomPath
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-2U4E7AM7.mjs";
|
|
20
|
+
import "./chunk-PFDUXY3N.mjs";
|
|
21
21
|
import "./chunk-5GLTKWJ5.mjs";
|
|
22
22
|
import {
|
|
23
23
|
CHANNEL_EVENT_TYPE,
|
|
24
24
|
memberRenameContent
|
|
25
25
|
} from "./chunk-P5CP32X2.mjs";
|
|
26
|
-
import "./chunk-
|
|
26
|
+
import "./chunk-DPW43YNC.mjs";
|
|
27
|
+
import "./chunk-OW3DSTEZ.mjs";
|
|
27
28
|
import {
|
|
28
29
|
LISTENING_MODE_COMMAND_TYPE
|
|
29
30
|
} from "./chunk-AUJEUKVM.mjs";
|
|
30
31
|
import "./chunk-SN3STAO2.mjs";
|
|
31
|
-
import "./chunk-
|
|
32
|
+
import "./chunk-55KBLEX5.mjs";
|
|
32
33
|
|
|
33
34
|
// src/local/session.ts
|
|
34
35
|
import { randomUUID } from "node:crypto";
|