khala-cli 0.4.9 → 0.4.11
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/THIRD_PARTY_NOTICES.txt +28 -0
- package/dist/{chunk-DJM23SIU.mjs → chunk-3KHLSF4A.mjs} +7 -8
- package/dist/{chunk-PDZ5Z5ZE.mjs → chunk-4CENUF7M.mjs} +24 -9
- package/dist/{chunk-QKWEZXR3.mjs → chunk-4PUNVPC3.mjs} +12 -4
- package/dist/{chunk-WDOHRV3D.mjs → chunk-7FFHZ7EI.mjs} +14 -14
- package/dist/chunk-AQX2OYEF.mjs +19 -0
- package/dist/{chunk-ITFD3JZS.mjs → chunk-BVG7PJNZ.mjs} +424 -78
- package/dist/{chunk-NGSYOVQ4.mjs → chunk-CXVANPY5.mjs} +2 -2
- package/dist/chunk-CYINL2V3.mjs +20 -0
- package/dist/{chunk-KMLXOPBQ.mjs → chunk-E5QRD6W3.mjs} +4 -2
- package/dist/{chunk-FO5GXCST.mjs → chunk-FGHPOKXG.mjs} +5 -5
- package/dist/{chunk-FZEH2IXZ.mjs → chunk-GVZD4TLW.mjs} +180 -26
- package/dist/{chunk-V4F3SYKW.mjs → chunk-H2L5GQ5W.mjs} +25 -17
- package/dist/chunk-HZH74L5T.mjs +901 -0
- package/dist/{chunk-NPSQNCOY.mjs → chunk-JNSB3E6C.mjs} +13 -4
- package/dist/{chunk-7R3EIDGR.mjs → chunk-LDW4HOQW.mjs} +1 -1
- package/dist/chunk-LNKI3CZO.mjs +15 -0
- package/dist/{chunk-TEFOQXBK.mjs → chunk-MAIMFERG.mjs} +3 -3
- package/dist/chunk-MYIZQCRW.mjs +27 -0
- package/dist/{chunk-TANCKTDK.mjs → chunk-N6UYX3SY.mjs} +72 -5
- package/dist/{chunk-6BO3JSUP.mjs → chunk-NE4S7N3R.mjs} +2 -2
- package/dist/{chunk-BLCRVRIK.mjs → chunk-NJ5ICCVZ.mjs} +456 -87
- package/dist/{chunk-3R6HFSLL.mjs → chunk-NN5RHU6C.mjs} +92 -38
- package/dist/{chunk-NIX5F4LT.mjs → chunk-NOKTVPSY.mjs} +330 -66
- package/dist/{chunk-3KDOTR54.mjs → chunk-NUQSDSVT.mjs} +1 -1
- package/dist/{chunk-BEO7WIIM.mjs → chunk-OSVXLZKJ.mjs} +28 -8
- package/dist/{chunk-SSO5RFOX.mjs → chunk-R5NDTJRA.mjs} +1 -1
- package/dist/{chunk-K7V7X6WU.mjs → chunk-TVQ4MSEI.mjs} +21 -4
- package/dist/{chunk-BV45NK7K.mjs → chunk-VWWI4S5A.mjs} +100 -6
- package/dist/{chunk-UK5GJO4Y.mjs → chunk-WA5LB5GN.mjs} +6 -5
- package/dist/chunk-X3BAMHAR.mjs +14 -0
- package/dist/{chunk-PAJ4JJPV.mjs → chunk-YDEZFVF7.mjs} +43 -6
- package/dist/{chunk-GSZADJMW.mjs → chunk-YFX5NDSL.mjs} +338 -81
- package/dist/{chunk-ANSR4IAW.mjs → chunk-YIKJI26V.mjs} +2 -2
- package/dist/{chunk-T7IL7V7Q.mjs → chunk-YNUCRFM2.mjs} +13 -10
- package/dist/iterm2_send.py +56 -0
- package/dist/khala.mjs +11 -11
- package/dist/web/assets/local-DPcMk9Xz.css +1 -0
- package/dist/web/assets/local-SDOFp8OA.js +9 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/chunk-47XNLAJG.mjs +0 -38
- package/dist/chunk-LBT47HLZ.mjs +0 -19
- package/dist/chunk-P3YIN7G7.mjs +0 -26
- package/dist/chunk-XBQDIKB5.mjs +0 -18
- package/dist/chunk-XUCWSYVS.mjs +0 -148
- package/dist/web/assets/local-CFzRHZpB.js +0 -9
- package/dist/web/assets/local-ciypUFoK.css +0 -1
|
@@ -3,32 +3,33 @@ import {
|
|
|
3
3
|
WAKE_HARNESSES,
|
|
4
4
|
wakeDrivers,
|
|
5
5
|
wakeStatus
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-HZH74L5T.mjs";
|
|
7
7
|
import {
|
|
8
8
|
adapterFor,
|
|
9
|
+
registerAntigravityWake,
|
|
9
10
|
resolveSources
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-BVG7PJNZ.mjs";
|
|
11
12
|
import {
|
|
12
13
|
CURSOR_DEFAULT_SESSION,
|
|
13
14
|
updateWakeSettings
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-NOKTVPSY.mjs";
|
|
15
16
|
import {
|
|
16
17
|
SESSION_ID_PATTERN,
|
|
17
18
|
filesForDir,
|
|
18
19
|
stateRoot
|
|
19
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-JNSB3E6C.mjs";
|
|
20
21
|
import {
|
|
21
22
|
resetWakeDriver
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-TVQ4MSEI.mjs";
|
|
23
24
|
import {
|
|
24
25
|
init_define_KHALA_BUNDLE
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-LDW4HOQW.mjs";
|
|
26
27
|
|
|
27
28
|
// src/wake/cli.ts
|
|
28
29
|
init_define_KHALA_BUNDLE();
|
|
29
30
|
import * as fs from "node:fs/promises";
|
|
30
31
|
import path from "node:path";
|
|
31
|
-
var WAKE_USAGE = "usage: khala wake on|off|status [--driver <d>] [--harness <id>] [--json]";
|
|
32
|
+
var WAKE_USAGE = "usage: khala wake on|off|status|register [--driver <d>] [--harness <id>] [--json]";
|
|
32
33
|
async function sessionIds(harness, env) {
|
|
33
34
|
try {
|
|
34
35
|
return (await fs.readdir(path.join(stateRoot(env), harness), { withFileTypes: true })).filter((entry) => entry.isDirectory() && SESSION_ID_PATTERN.test(entry.name)).map((entry) => entry.name);
|
|
@@ -53,10 +54,15 @@ async function setWake(harness, drivers, on, env) {
|
|
|
53
54
|
}
|
|
54
55
|
});
|
|
55
56
|
if (on) for (const id of await sessionIds(harness, env)) {
|
|
56
|
-
for (const driver of drivers)
|
|
57
|
+
for (const driver of drivers) {
|
|
58
|
+
const dir = filesForDir(path.join(root, harness, id)).dir;
|
|
59
|
+
await resetWakeDriver(dir, driver);
|
|
60
|
+
if (harness === "qwen" && driver === "socket") await fs.rm(path.join(dir, "qwen-receipt.json"), { force: true });
|
|
61
|
+
}
|
|
57
62
|
}
|
|
58
63
|
}
|
|
59
64
|
function consentLine(harness, drivers, on) {
|
|
65
|
+
if (harness === "antigravity" && on) return `Idle wake is on (${drivers.join(", ")}): native wake preserves drafts; terminal fallback requires an empty prompt. Wake and Sync continuation use billed model turns. Run \`khala wake off --harness antigravity\` to turn it off.`;
|
|
60
66
|
return on ? `Idle wake is on (${drivers.join(", ")}): Khala may send a fixed wake line into this agent's existing session when messages wait and ${harness === "muse" ? "the session is idle (through Muse\u2019s native monitor)" : "the prompt is empty"}. Run \`khala wake off --harness ${harness}\` to turn it off.` : `Idle wake is off for ${drivers.join(", ")}. Run \`khala wake on --harness ${harness}\` to turn it on.`;
|
|
61
67
|
}
|
|
62
68
|
async function currentSessionId(harness, env) {
|
|
@@ -85,6 +91,20 @@ async function runWake(argv, deps = {}) {
|
|
|
85
91
|
return 2;
|
|
86
92
|
}
|
|
87
93
|
}
|
|
94
|
+
if (command === "register") {
|
|
95
|
+
if (harness !== "antigravity" || driver || json) {
|
|
96
|
+
err(WAKE_USAGE);
|
|
97
|
+
return 2;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
await registerAntigravityWake(env);
|
|
101
|
+
out("Registered Antigravity native wake for this session.");
|
|
102
|
+
return 0;
|
|
103
|
+
} catch {
|
|
104
|
+
err("khala: Antigravity wake registration unavailable; run this command through the agent shell.");
|
|
105
|
+
return 1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
88
108
|
if (!["on", "off", "status"].includes(command ?? "")) {
|
|
89
109
|
err(WAKE_USAGE);
|
|
90
110
|
return 2;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
init_define_KHALA_BUNDLE
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LDW4HOQW.mjs";
|
|
5
5
|
|
|
6
6
|
// src/events/member-rename.ts
|
|
7
7
|
init_define_KHALA_BUNDLE();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
init_define_KHALA_BUNDLE
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LDW4HOQW.mjs";
|
|
5
5
|
|
|
6
6
|
// src/wake/shared/nonce.ts
|
|
7
7
|
init_define_KHALA_BUNDLE();
|
|
@@ -138,8 +138,14 @@ async function settleAttempts(dir, input) {
|
|
|
138
138
|
const baselineAt = typeof attempt.activityUpdatedAt === "number" ? attempt.activityUpdatedAt : attempt.activityUpdatedAt === void 0 ? attempt.at : Date.parse(attempt.activityUpdatedAt);
|
|
139
139
|
const verified = input.promptText?.includes(`(k-${attempt.nonce})`);
|
|
140
140
|
const activityChanged = input.activity && (input.activity.state !== "idle" || activityAt > baselineAt);
|
|
141
|
-
if (
|
|
142
|
-
|
|
141
|
+
if (input.deferVerification && !activityChanged) attempt.verificationDeferred = true;
|
|
142
|
+
if (attempt.verification === "transcript") {
|
|
143
|
+
if (input.now >= attempt.deadline && input.activity?.state === "idle") status = "failure";
|
|
144
|
+
} else if (verified && input.verifiedAt !== void 0 && input.verifiedAt >= attempt.at && input.verifiedAt <= attempt.deadline) status = "success";
|
|
145
|
+
else if (attempt.verificationDeferred) {
|
|
146
|
+
if (verified && input.now <= attempt.deadline) status = "success";
|
|
147
|
+
else if (input.now >= attempt.deadline) status = activityChanged ? "void" : "failure";
|
|
148
|
+
} else if (activityChanged && !(attempt.startsActivity && input.activity?.state === "busy" && input.promptText === void 0)) status = "void";
|
|
143
149
|
else if (verified && input.verifiedAt === void 0 && input.now <= attempt.deadline) status = "success";
|
|
144
150
|
else if (input.now >= attempt.deadline && input.activity?.state === "idle") status = "failure";
|
|
145
151
|
else if (input.promptText !== void 0) status = "void";
|
|
@@ -192,8 +198,18 @@ async function takeWakeDisableNotices(dir) {
|
|
|
192
198
|
return drivers;
|
|
193
199
|
});
|
|
194
200
|
}
|
|
201
|
+
async function confirmWakeText(dir, driver, text, now) {
|
|
202
|
+
await locked(dir, (data) => {
|
|
203
|
+
data.attempts = data.attempts.filter((attempt) => {
|
|
204
|
+
if (attempt.driver !== driver || now > attempt.deadline || !text.includes(`(k-${attempt.nonce})`)) return true;
|
|
205
|
+
data.state[driver] = { failures: 0 };
|
|
206
|
+
return false;
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
}
|
|
195
210
|
|
|
196
211
|
export {
|
|
212
|
+
CODEX_IDLE_WAKE_NOTICE,
|
|
197
213
|
newNonce,
|
|
198
214
|
wakeLine,
|
|
199
215
|
withWakeLock,
|
|
@@ -203,5 +219,6 @@ export {
|
|
|
203
219
|
cancelAttempt,
|
|
204
220
|
failAttempt,
|
|
205
221
|
resetWakeDriver,
|
|
206
|
-
takeWakeDisableNotices
|
|
222
|
+
takeWakeDisableNotices,
|
|
223
|
+
confirmWakeText
|
|
207
224
|
};
|
|
@@ -5,20 +5,22 @@ import {
|
|
|
5
5
|
fail,
|
|
6
6
|
label,
|
|
7
7
|
literal,
|
|
8
|
+
object,
|
|
8
9
|
safeInteger,
|
|
9
10
|
utcTimestamp,
|
|
10
11
|
utf8Length,
|
|
11
12
|
version
|
|
12
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-JNSB3E6C.mjs";
|
|
13
14
|
import {
|
|
14
15
|
init_define_KHALA_BUNDLE
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-LDW4HOQW.mjs";
|
|
16
17
|
|
|
17
18
|
// ../contracts/src/m1/channel-event.ts
|
|
18
19
|
init_define_KHALA_BUNDLE();
|
|
19
20
|
var CHANNEL_EVENT_TYPE = "com.khala.event.v1";
|
|
20
21
|
var CHANNEL_EVENT_STATUSES = ["info", "pending", "success", "failure", "attention"];
|
|
21
22
|
var MAX_CHANNEL_EVENT_BYTES = 4096;
|
|
23
|
+
var COORDINATION_KINDS = ["handoff", "handoff_ack", "verdict", "claim", "release", "note"];
|
|
22
24
|
function record(input, path) {
|
|
23
25
|
if (typeof input !== "object" || input === null || Array.isArray(input)) fail(path, "not_object");
|
|
24
26
|
const prototype = Object.getPrototypeOf(input);
|
|
@@ -76,10 +78,66 @@ function decodeChannelEvent(raw) {
|
|
|
76
78
|
...r.has("url") ? { url: readUrl(r.field("url")) } : {},
|
|
77
79
|
...r.has("occurred_at") ? { occurred_at: utcTimestamp(r.field("occurred_at"), "occurred_at") } : {},
|
|
78
80
|
...r.has("source") ? { source: readSource(r.field("source")) } : {},
|
|
79
|
-
...r.has("key") ? { key: nonempty(label(r.field("key"), "key", 200), "key") } : {}
|
|
81
|
+
...r.has("key") ? { key: nonempty(label(r.field("key"), "key", 200), "key") } : {},
|
|
82
|
+
// Older senders may use these kind names without data: such events stay plain events.
|
|
83
|
+
...r.has("data") && isCoordinationKind(kind) ? { data: readData(kind, r.field("data")) } : {}
|
|
80
84
|
};
|
|
81
85
|
}));
|
|
82
86
|
}
|
|
87
|
+
function isCoordinationKind(kind) {
|
|
88
|
+
return COORDINATION_KINDS.includes(kind);
|
|
89
|
+
}
|
|
90
|
+
var short = (input, path) => display(input, path, 256, 64);
|
|
91
|
+
var reason = (input, path) => display(input, path, 800, 200);
|
|
92
|
+
function readData(kind, input) {
|
|
93
|
+
const fields = {
|
|
94
|
+
handoff: ["ticket", "from", "to", "reason", "state"],
|
|
95
|
+
handoff_ack: ["ticket"],
|
|
96
|
+
verdict: ["pr", "verdict", "reason"],
|
|
97
|
+
claim: ["key"],
|
|
98
|
+
release: ["key"],
|
|
99
|
+
note: ["key", "value"]
|
|
100
|
+
}[kind];
|
|
101
|
+
const r = object(input, "data", fields);
|
|
102
|
+
const read = (key) => {
|
|
103
|
+
const value = r.field(key);
|
|
104
|
+
switch (key) {
|
|
105
|
+
case "pr": {
|
|
106
|
+
const pr = safeInteger(value, r.at(key));
|
|
107
|
+
if (pr === 0) fail(r.at(key), "invalid_value");
|
|
108
|
+
return pr;
|
|
109
|
+
}
|
|
110
|
+
case "verdict":
|
|
111
|
+
return literal(value, r.at(key), ["approved", "changes_requested"]);
|
|
112
|
+
case "reason":
|
|
113
|
+
return reason(value, r.at(key));
|
|
114
|
+
case "key":
|
|
115
|
+
return nonempty(label(value, r.at(key), 128), r.at(key));
|
|
116
|
+
// An empty value clears the note.
|
|
117
|
+
case "value":
|
|
118
|
+
return typeof value === "string" && value === "" ? "" : reason(value, r.at(key));
|
|
119
|
+
default:
|
|
120
|
+
return short(value, r.at(key));
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
return Object.fromEntries(fields.map((key) => [key, read(key)]));
|
|
124
|
+
}
|
|
125
|
+
function coordinationSummary(kind, d) {
|
|
126
|
+
switch (kind) {
|
|
127
|
+
case "handoff":
|
|
128
|
+
return `handoff ${d.ticket} ${d.from} \u2192 ${d.to} (${d.state}): ${d.reason}`;
|
|
129
|
+
case "handoff_ack":
|
|
130
|
+
return `handoff ${d.ticket} acknowledged`;
|
|
131
|
+
case "verdict":
|
|
132
|
+
return `PR #${d.pr} ${d.verdict === "approved" ? "approved" : "changes requested"}: ${d.reason}`;
|
|
133
|
+
case "claim":
|
|
134
|
+
return `claimed ${d.key}`;
|
|
135
|
+
case "release":
|
|
136
|
+
return `released ${d.key}`;
|
|
137
|
+
case "note":
|
|
138
|
+
return d.value === "" ? `note ${d.key} cleared` : `note ${d.key} = ${d.value}`;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
83
141
|
function readSubject(input) {
|
|
84
142
|
const r = record(input, "subject");
|
|
85
143
|
let pr;
|
|
@@ -127,8 +185,23 @@ function formatChannelEventLine(content) {
|
|
|
127
185
|
function encodeChannelEvent(input) {
|
|
128
186
|
return safely(() => {
|
|
129
187
|
const checked = decodeWith(() => {
|
|
130
|
-
record(input, "");
|
|
131
|
-
|
|
188
|
+
const r = record(input, "");
|
|
189
|
+
const raw = input;
|
|
190
|
+
const kind = raw.kind;
|
|
191
|
+
if (typeof kind !== "string" || !isCoordinationKind(kind)) {
|
|
192
|
+
if (r.has("data")) fail("data", "invalid_value");
|
|
193
|
+
return { ...raw, v: 1, body: "" };
|
|
194
|
+
}
|
|
195
|
+
const data = readData(kind, r.field("data"));
|
|
196
|
+
const derived = coordinationSummary(kind, data);
|
|
197
|
+
return {
|
|
198
|
+
...raw,
|
|
199
|
+
v: 1,
|
|
200
|
+
body: "",
|
|
201
|
+
data,
|
|
202
|
+
...r.has("summary") ? {} : { summary: [...derived].length > 200 ? [...derived].slice(0, 199).join("") + "\u2026" : derived },
|
|
203
|
+
...r.has("status") || kind !== "verdict" ? {} : { status: data.verdict === "approved" ? "success" : "attention" }
|
|
204
|
+
};
|
|
132
205
|
});
|
|
133
206
|
if (!checked.ok) return checked;
|
|
134
207
|
const decoded = decodeChannelEvent(checked.value);
|
|
@@ -163,6 +236,26 @@ function statusFor(content) {
|
|
|
163
236
|
return content.kind.startsWith("agent.attention.") && !content.kind.endsWith(".resolved") ? "attention" : "info";
|
|
164
237
|
}
|
|
165
238
|
}
|
|
239
|
+
function foldCoordination(events) {
|
|
240
|
+
const handoffs = /* @__PURE__ */ new Map();
|
|
241
|
+
const claims = /* @__PURE__ */ new Map();
|
|
242
|
+
const notes = /* @__PURE__ */ new Map();
|
|
243
|
+
for (const { sender, by, at, content: { kind, data } } of events) {
|
|
244
|
+
if (!data) continue;
|
|
245
|
+
const s = (key) => String(data[key]);
|
|
246
|
+
if (kind === "handoff") {
|
|
247
|
+
handoffs.delete(s("ticket"));
|
|
248
|
+
handoffs.set(s("ticket"), { ticket: s("ticket"), from: s("from"), to: s("to"), reason: s("reason"), state: s("state"), by, at });
|
|
249
|
+
} else if (kind === "handoff_ack") handoffs.delete(s("ticket"));
|
|
250
|
+
else if (kind === "claim" && !claims.has(s("key"))) claims.set(s("key"), { key: s("key"), by, sender, at });
|
|
251
|
+
else if (kind === "release" && claims.get(s("key"))?.sender === sender) claims.delete(s("key"));
|
|
252
|
+
else if (kind === "note") {
|
|
253
|
+
notes.delete(s("key"));
|
|
254
|
+
if (s("value") !== "") notes.set(s("key"), s("value"));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return { openHandoffs: [...handoffs.values()], activeClaims: [...claims.values()], notes: Object.fromEntries(notes) };
|
|
258
|
+
}
|
|
166
259
|
|
|
167
260
|
export {
|
|
168
261
|
CHANNEL_EVENT_TYPE,
|
|
@@ -170,5 +263,6 @@ export {
|
|
|
170
263
|
formatChannelEventLine,
|
|
171
264
|
encodeChannelEvent,
|
|
172
265
|
memberRenameContent,
|
|
173
|
-
statusFor
|
|
266
|
+
statusFor,
|
|
267
|
+
foldCoordination
|
|
174
268
|
};
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
sessionStartWakeChannels
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-MAIMFERG.mjs";
|
|
5
5
|
import {
|
|
6
6
|
capturePane
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4PUNVPC3.mjs";
|
|
8
8
|
import {
|
|
9
9
|
listChannels,
|
|
10
10
|
writeActivity
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-N6UYX3SY.mjs";
|
|
12
|
+
import "./chunk-VWWI4S5A.mjs";
|
|
12
13
|
import {
|
|
13
14
|
TERMINAL_SESSION_DETAILS,
|
|
14
15
|
openSessionDir,
|
|
15
16
|
readJson
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-JNSB3E6C.mjs";
|
|
17
18
|
import {
|
|
18
19
|
init_define_KHALA_BUNDLE
|
|
19
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-LDW4HOQW.mjs";
|
|
20
21
|
|
|
21
22
|
// hooks/session-start.ts
|
|
22
23
|
init_define_KHALA_BUNDLE();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
init_define_KHALA_BUNDLE
|
|
4
|
+
} from "./chunk-LDW4HOQW.mjs";
|
|
5
|
+
|
|
6
|
+
// src/transport.ts
|
|
7
|
+
init_define_KHALA_BUNDLE();
|
|
8
|
+
var RESTORE_HISTORY_MAX_PAGES = 20;
|
|
9
|
+
var startChannelSession = async (creds, options) => creds.transport === "local" ? (await import("./chunk-YNUCRFM2.mjs")).createLocalSession(creds) : (await import("./chunk-GVZD4TLW.mjs")).createAgentMatrixSession(creds, options);
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
RESTORE_HISTORY_MAX_PAGES,
|
|
13
|
+
startChannelSession
|
|
14
|
+
};
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
retryUnexpired
|
|
4
|
+
} from "./chunk-LNKI3CZO.mjs";
|
|
2
5
|
import {
|
|
3
6
|
StateError,
|
|
4
7
|
ensureStateDir,
|
|
5
8
|
writeJsonAtomic
|
|
6
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-JNSB3E6C.mjs";
|
|
7
10
|
import {
|
|
8
11
|
__commonJS,
|
|
9
12
|
__export,
|
|
10
13
|
__toESM,
|
|
11
14
|
init_define_KHALA_BUNDLE
|
|
12
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-LDW4HOQW.mjs";
|
|
13
16
|
|
|
14
17
|
// ../../node_modules/.pnpm/immediate@3.3.0/node_modules/immediate/lib/nextTick.js
|
|
15
18
|
var require_nextTick = __commonJS({
|
|
@@ -9623,7 +9626,8 @@ async function readIdentity(file) {
|
|
|
9623
9626
|
const stat = await handle.stat();
|
|
9624
9627
|
if (!stat.isFile() || process.platform !== "win32" && (stat.mode & 63) !== 0 || typeof process.getuid === "function" && stat.uid !== process.getuid()) throw new StateError("unsafe_state_dir");
|
|
9625
9628
|
const value = JSON.parse(await handle.readFile("utf8"));
|
|
9626
|
-
if (!value || typeof value.homeserver !== "string" || typeof value.userId !== "string" || typeof value.deviceId !== "string" || value.accessToken !== void 0 && typeof value.accessToken !== "string" || value.joinedAt !== void 0 && !Number.isFinite(value.joinedAt)) throw new CryptoStoreCorruptError();
|
|
9629
|
+
if (!value || typeof value.homeserver !== "string" || typeof value.userId !== "string" || typeof value.deviceId !== "string" || value.accessToken !== void 0 && typeof value.accessToken !== "string" || value.joinedAt !== void 0 && !Number.isFinite(value.joinedAt) || value.undecryptableEventIds !== void 0 && (!Array.isArray(value.undecryptableEventIds) || value.undecryptableEventIds.length > 100 || value.undecryptableEventIds.some((entry) => typeof entry !== "string" && (!entry || typeof entry !== "object" || typeof entry.id !== "string" || typeof entry.firstSeen !== "number" || !Number.isFinite(entry.firstSeen) || entry.firstSeen < 0 || entry.firstSeen > Number.MAX_SAFE_INTEGER)))) throw new CryptoStoreCorruptError();
|
|
9630
|
+
if (value.undecryptableEventIds) value.undecryptableEventIds = value.undecryptableEventIds.filter((entry) => typeof entry !== "string" && retryUnexpired(entry));
|
|
9627
9631
|
return value;
|
|
9628
9632
|
} catch (error) {
|
|
9629
9633
|
if (error instanceof StateError) throw error;
|
|
@@ -9735,18 +9739,32 @@ async function openCryptoStore(dir, root, creds) {
|
|
|
9735
9739
|
if (!restored) {
|
|
9736
9740
|
await deleteStores(prefix, dir);
|
|
9737
9741
|
}
|
|
9738
|
-
|
|
9742
|
+
const saved = { ...identity, ...restored && previous?.joinedAt !== void 0 ? { joinedAt: previous.joinedAt } : {}, ...restored && previous?.undecryptableEventIds ? { undecryptableEventIds: previous.undecryptableEventIds } : {} };
|
|
9743
|
+
await writeJsonAtomic(identityFile, saved);
|
|
9739
9744
|
const sync = new DurableSyncStore({ indexedDB: globalThis.indexedDB, dbName: prefix });
|
|
9740
9745
|
let closed;
|
|
9746
|
+
let identitySave = Promise.resolve();
|
|
9747
|
+
const saveIdentity = () => {
|
|
9748
|
+
const saving = identitySave.then(() => writeJsonAtomic(identityFile, saved));
|
|
9749
|
+
identitySave = saving.catch(() => {
|
|
9750
|
+
});
|
|
9751
|
+
return saving;
|
|
9752
|
+
};
|
|
9741
9753
|
return {
|
|
9742
9754
|
prefix,
|
|
9743
9755
|
sync,
|
|
9744
9756
|
restored,
|
|
9745
9757
|
...recovered ? { recovered } : {},
|
|
9746
9758
|
...restored && previous?.joinedAt !== void 0 ? { joinedAt: previous?.joinedAt } : {},
|
|
9759
|
+
undecryptableEventIds: saved.undecryptableEventIds ?? [],
|
|
9760
|
+
async rememberUndecryptable(ids) {
|
|
9761
|
+
saved.undecryptableEventIds = ids.filter((entry) => retryUnexpired(entry)).slice(-100);
|
|
9762
|
+
await saveIdentity();
|
|
9763
|
+
},
|
|
9747
9764
|
async rememberJoin(ts) {
|
|
9748
9765
|
if (this.joinedAt === void 0) {
|
|
9749
|
-
|
|
9766
|
+
saved.joinedAt = ts;
|
|
9767
|
+
await saveIdentity();
|
|
9750
9768
|
this.joinedAt = ts;
|
|
9751
9769
|
}
|
|
9752
9770
|
},
|
|
@@ -9767,7 +9785,7 @@ async function openCryptoStore(dir, root, creds) {
|
|
|
9767
9785
|
throw error;
|
|
9768
9786
|
}
|
|
9769
9787
|
}
|
|
9770
|
-
async function wipeCryptoStore(dir, root) {
|
|
9788
|
+
async function wipeCryptoStore(dir, root, fetcher = fetch) {
|
|
9771
9789
|
try {
|
|
9772
9790
|
const names = await fs3.readdir(dir);
|
|
9773
9791
|
if (!["crypto.json", "crypto.sqlite", "sync.sqlite"].some((name) => names.includes(name))) return;
|
|
@@ -9784,6 +9802,25 @@ async function wipeCryptoStore(dir, root) {
|
|
|
9784
9802
|
retries: { retries: 12, minTimeout: 1e3, maxTimeout: 1e3 }
|
|
9785
9803
|
});
|
|
9786
9804
|
try {
|
|
9805
|
+
let identity;
|
|
9806
|
+
try {
|
|
9807
|
+
identity = await readIdentity(path.join(dir, "crypto.json"));
|
|
9808
|
+
} catch {
|
|
9809
|
+
identity = null;
|
|
9810
|
+
}
|
|
9811
|
+
if (identity?.accessToken) {
|
|
9812
|
+
try {
|
|
9813
|
+
const response = await fetcher(`${identity.homeserver}/_matrix/client/v3/logout`, {
|
|
9814
|
+
method: "POST",
|
|
9815
|
+
headers: { authorization: `Bearer ${identity.accessToken}`, "content-type": "application/json" },
|
|
9816
|
+
body: "{}",
|
|
9817
|
+
signal: AbortSignal.timeout(5e3)
|
|
9818
|
+
});
|
|
9819
|
+
if (!response.ok && response.status !== 401) console.error("khala: discarded_device_logout_failed");
|
|
9820
|
+
} catch {
|
|
9821
|
+
console.error("khala: discarded_device_logout_failed");
|
|
9822
|
+
}
|
|
9823
|
+
}
|
|
9787
9824
|
await unlink2(path.join(dir, "crypto.json"));
|
|
9788
9825
|
await deleteStores(prefix, dir);
|
|
9789
9826
|
} finally {
|