khala-cli 0.4.9 → 0.4.10
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-NIX5F4LT.mjs → chunk-2AMWQ7RB.mjs} +330 -66
- package/dist/{chunk-PAJ4JJPV.mjs → chunk-3E5DH3Y6.mjs} +43 -6
- package/dist/{chunk-NGSYOVQ4.mjs → chunk-4BP7V3OP.mjs} +2 -2
- package/dist/{chunk-TEFOQXBK.mjs → chunk-4BZQ4GVW.mjs} +3 -3
- package/dist/{chunk-ITFD3JZS.mjs → chunk-5JSGA6OB.mjs} +424 -78
- package/dist/{chunk-QKWEZXR3.mjs → chunk-6AQVW5W7.mjs} +12 -4
- package/dist/{chunk-UK5GJO4Y.mjs → chunk-6J2PUM7L.mjs} +6 -5
- package/dist/{chunk-P3YIN7G7.mjs → chunk-6SUV3EW6.mjs} +11 -10
- package/dist/{chunk-GSZADJMW.mjs → chunk-ARIDZOTI.mjs} +309 -81
- package/dist/chunk-C2WEDMAF.mjs +15 -0
- package/dist/{chunk-DJM23SIU.mjs → chunk-CHC4VZF5.mjs} +7 -8
- package/dist/{chunk-BLCRVRIK.mjs → chunk-CKLCR5G4.mjs} +456 -87
- package/dist/{chunk-7R3EIDGR.mjs → chunk-EVT2DWNZ.mjs} +1 -1
- package/dist/{chunk-KMLXOPBQ.mjs → chunk-FJVVSKZ3.mjs} +4 -2
- package/dist/{chunk-3KDOTR54.mjs → chunk-G3NMB4PY.mjs} +1 -1
- package/dist/{chunk-SSO5RFOX.mjs → chunk-HHEZVPRR.mjs} +1 -1
- package/dist/{chunk-BV45NK7K.mjs → chunk-JKOJQTFT.mjs} +100 -6
- package/dist/{chunk-T7IL7V7Q.mjs → chunk-NDMFD5IM.mjs} +13 -10
- package/dist/{chunk-TANCKTDK.mjs → chunk-OEV5DFLW.mjs} +70 -5
- package/dist/{chunk-BEO7WIIM.mjs → chunk-OIZ4R5H7.mjs} +28 -8
- package/dist/{chunk-FZEH2IXZ.mjs → chunk-PJKI7SRI.mjs} +176 -26
- package/dist/{chunk-NPSQNCOY.mjs → chunk-PN25BUQ4.mjs} +13 -4
- package/dist/{chunk-3R6HFSLL.mjs → chunk-QDPJ4VT2.mjs} +92 -38
- package/dist/{chunk-FO5GXCST.mjs → chunk-SRZTHCXP.mjs} +5 -5
- package/dist/{chunk-LBT47HLZ.mjs → chunk-TSK3HJEG.mjs} +10 -9
- package/dist/{chunk-6BO3JSUP.mjs → chunk-UX34IVN5.mjs} +2 -2
- package/dist/{chunk-V4F3SYKW.mjs → chunk-VAC3JTAV.mjs} +25 -17
- package/dist/{chunk-PDZ5Z5ZE.mjs → chunk-VDZK4LW3.mjs} +24 -9
- package/dist/chunk-W6HM6F2U.mjs +901 -0
- package/dist/{chunk-WDOHRV3D.mjs → chunk-WPNMWNCL.mjs} +14 -14
- package/dist/chunk-WUDXHF2Q.mjs +14 -0
- package/dist/{chunk-XBQDIKB5.mjs → chunk-WZJ6DQJV.mjs} +9 -8
- package/dist/{chunk-ANSR4IAW.mjs → chunk-XR625T3I.mjs} +2 -2
- package/dist/{chunk-K7V7X6WU.mjs → chunk-ZSKLNZWZ.mjs} +21 -4
- package/dist/iterm2_send.py +56 -0
- package/dist/khala.mjs +11 -11
- package/dist/web/assets/local-CSPuGnH2.css +1 -0
- package/dist/web/assets/local-Dtyxaacx.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-XUCWSYVS.mjs +0 -148
- package/dist/web/assets/local-CFzRHZpB.js +0 -9
- package/dist/web/assets/local-ciypUFoK.css +0 -1
|
@@ -45,7 +45,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
45
45
|
var define_KHALA_BUNDLE_default;
|
|
46
46
|
var init_define_KHALA_BUNDLE = __esm({
|
|
47
47
|
"<define:__KHALA_BUNDLE__>"() {
|
|
48
|
-
define_KHALA_BUNDLE_default = { name: "khala-cli", version: "0.4.
|
|
48
|
+
define_KHALA_BUNDLE_default = { name: "khala-cli", version: "0.4.10" };
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
51
|
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
cancelAttempt,
|
|
4
|
+
confirmWakeText,
|
|
4
5
|
failAttempt,
|
|
5
6
|
readWakeState,
|
|
6
7
|
recordAttempt,
|
|
7
8
|
resetWakeDriver,
|
|
8
9
|
settleAttempts,
|
|
9
10
|
takeWakeDisableNotices
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-ZSKLNZWZ.mjs";
|
|
12
|
+
import "./chunk-EVT2DWNZ.mjs";
|
|
12
13
|
export {
|
|
13
14
|
cancelAttempt,
|
|
15
|
+
confirmWakeText,
|
|
14
16
|
failAttempt,
|
|
15
17
|
readWakeState,
|
|
16
18
|
recordAttempt,
|
|
@@ -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-EVT2DWNZ.mjs";
|
|
5
5
|
|
|
6
6
|
// src/events/member-rename.ts
|
|
7
7
|
init_define_KHALA_BUNDLE();
|
|
@@ -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-PN25BUQ4.mjs";
|
|
13
14
|
import {
|
|
14
15
|
init_define_KHALA_BUNDLE
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-EVT2DWNZ.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
|
};
|
|
@@ -14,21 +14,21 @@ import {
|
|
|
14
14
|
decodeLocalSendResult,
|
|
15
15
|
ensureHelper,
|
|
16
16
|
localRoomPath
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-SRZTHCXP.mjs";
|
|
18
|
+
import "./chunk-HHEZVPRR.mjs";
|
|
19
|
+
import "./chunk-XR625T3I.mjs";
|
|
20
|
+
import "./chunk-G3NMB4PY.mjs";
|
|
21
|
+
import {
|
|
22
|
+
LISTENING_MODE_COMMAND_TYPE
|
|
23
|
+
} from "./chunk-4BP7V3OP.mjs";
|
|
19
24
|
import {
|
|
20
25
|
CHANNEL_EVENT_TYPE,
|
|
21
26
|
memberRenameContent
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import "./chunk-
|
|
24
|
-
import "./chunk-3KDOTR54.mjs";
|
|
25
|
-
import {
|
|
26
|
-
LISTENING_MODE_COMMAND_TYPE
|
|
27
|
-
} from "./chunk-NGSYOVQ4.mjs";
|
|
28
|
-
import "./chunk-NPSQNCOY.mjs";
|
|
27
|
+
} from "./chunk-JKOJQTFT.mjs";
|
|
28
|
+
import "./chunk-PN25BUQ4.mjs";
|
|
29
29
|
import {
|
|
30
30
|
init_define_KHALA_BUNDLE
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-EVT2DWNZ.mjs";
|
|
32
32
|
|
|
33
33
|
// src/local/session.ts
|
|
34
34
|
init_define_KHALA_BUNDLE();
|
|
@@ -124,6 +124,7 @@ async function createLocalSession(creds, opts = {}) {
|
|
|
124
124
|
let name;
|
|
125
125
|
let invitedBy;
|
|
126
126
|
let after = 0;
|
|
127
|
+
let joinedAt;
|
|
127
128
|
function check(roomId) {
|
|
128
129
|
if (stopped) throw new Error("session_stopped");
|
|
129
130
|
if (roomId !== creds.roomId) throw new Error("unknown_room");
|
|
@@ -323,6 +324,7 @@ async function createLocalSession(creds, opts = {}) {
|
|
|
323
324
|
joining ??= (async () => {
|
|
324
325
|
const result = decoded(await withHelper(() => request("POST", "join", {})), decodeLocalJoined);
|
|
325
326
|
after = result.seq;
|
|
327
|
+
joinedAt = result.ts;
|
|
326
328
|
await me();
|
|
327
329
|
const members = decoded(await withHelper(() => request("GET", "members?wire=2")), decodeLocalMembersResponse);
|
|
328
330
|
check(roomId);
|
|
@@ -340,6 +342,7 @@ async function createLocalSession(creds, opts = {}) {
|
|
|
340
342
|
joining = void 0;
|
|
341
343
|
}
|
|
342
344
|
},
|
|
345
|
+
joinedAt: (roomId) => roomId === creds.roomId ? joinedAt : void 0,
|
|
343
346
|
async history(roomId, limit, before) {
|
|
344
347
|
check(roomId);
|
|
345
348
|
const page = decoded(await withHelper(() => request("GET", `messages?wire=2&limit=${limit}${before !== void 0 ? `&before=${encodeURIComponent(before)}` : ""}`)), decodeLocalHistoryPage);
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
decodeChannelEvent,
|
|
4
|
+
formatChannelEventLine
|
|
5
|
+
} from "./chunk-JKOJQTFT.mjs";
|
|
2
6
|
import {
|
|
3
7
|
StateError,
|
|
4
8
|
channelFiles,
|
|
@@ -10,10 +14,50 @@ import {
|
|
|
10
14
|
stateKey,
|
|
11
15
|
writeJsonAtomic,
|
|
12
16
|
writeStateFile
|
|
13
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-PN25BUQ4.mjs";
|
|
14
18
|
import {
|
|
15
19
|
init_define_KHALA_BUNDLE
|
|
16
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-EVT2DWNZ.mjs";
|
|
21
|
+
|
|
22
|
+
// src/events/receive.ts
|
|
23
|
+
init_define_KHALA_BUNDLE();
|
|
24
|
+
function toEventInboxEntry(base, rawContent, you) {
|
|
25
|
+
const decoded = decodeChannelEvent(rawContent);
|
|
26
|
+
if (!decoded.ok) return null;
|
|
27
|
+
const content = decoded.value;
|
|
28
|
+
const to = content.kind === "handoff" ? String(content.data?.to ?? "").replace(/^@/u, "").toLowerCase() : "";
|
|
29
|
+
return {
|
|
30
|
+
entry: {
|
|
31
|
+
...base,
|
|
32
|
+
kind: "event",
|
|
33
|
+
body: formatChannelEventLine(content) + (content.url ? " " + content.url : ""),
|
|
34
|
+
eventKind: content.kind,
|
|
35
|
+
...content.data ? { data: content.data } : {},
|
|
36
|
+
...to && to === you?.toLowerCase() ? { mention: true } : {}
|
|
37
|
+
},
|
|
38
|
+
...content.key !== void 0 ? { key: content.key } : {}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function createEventKeyFilter() {
|
|
42
|
+
const seen = /* @__PURE__ */ new Set();
|
|
43
|
+
return (key) => {
|
|
44
|
+
if (key === void 0) return true;
|
|
45
|
+
if (seen.has(key)) return false;
|
|
46
|
+
seen.add(key);
|
|
47
|
+
return true;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function isWakeEntry(entry) {
|
|
51
|
+
return entry.kind === "message" || entry.mention === true;
|
|
52
|
+
}
|
|
53
|
+
function mentions(entry, name) {
|
|
54
|
+
if (!name) return false;
|
|
55
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
56
|
+
return new RegExp(`(?<![\\p{L}\\p{N}_])@?${escaped}(?![\\p{L}\\p{N}_])`, "iu").test(entry.body);
|
|
57
|
+
}
|
|
58
|
+
function wakesAgent(entry, mode, you) {
|
|
59
|
+
return isWakeEntry(entry) && (mode !== "sync" || entry.senderKind !== "agent" || entry.mention === true || mentions(entry, you));
|
|
60
|
+
}
|
|
17
61
|
|
|
18
62
|
// src/inbox.ts
|
|
19
63
|
init_define_KHALA_BUNDLE();
|
|
@@ -63,16 +107,18 @@ async function unread(files) {
|
|
|
63
107
|
}
|
|
64
108
|
async function unreadCounts(files) {
|
|
65
109
|
const { entries } = await unread(files);
|
|
66
|
-
return { total: entries.length, messages: entries.filter((entry) => entry
|
|
110
|
+
return { total: entries.length, messages: entries.filter((entry) => isWakeEntry(entry)).length };
|
|
67
111
|
}
|
|
68
|
-
async function advanceCursor(files, expected, delivered) {
|
|
112
|
+
async function advanceCursor(files, expected, delivered, shown = false) {
|
|
69
113
|
const current = await readCursor(files);
|
|
70
114
|
if (current.deliveredCount !== expected.deliveredCount || current.lastDeliveredEventId !== expected.lastDeliveredEventId) return "conflict";
|
|
71
115
|
if (!delivered.length) return expected;
|
|
72
116
|
const entries = await readEntries(files);
|
|
73
117
|
const slice = entries.slice(expected.deliveredCount, expected.deliveredCount + delivered.length);
|
|
74
118
|
if (slice.length !== delivered.length || slice.some((entry, index) => entry.eventId !== delivered[index]?.eventId)) return "conflict";
|
|
75
|
-
const
|
|
119
|
+
const last = delivered[delivered.length - 1].eventId;
|
|
120
|
+
const shownEventId = shown ? last : current.shownEventId;
|
|
121
|
+
const next = { lastDeliveredEventId: last, deliveredCount: expected.deliveredCount + delivered.length, ...shownEventId ? { shownEventId } : {} };
|
|
76
122
|
await writeJsonAtomic(files.cursor, next);
|
|
77
123
|
return next;
|
|
78
124
|
}
|
|
@@ -208,11 +254,22 @@ function resolveChannel(list, ref) {
|
|
|
208
254
|
|
|
209
255
|
// src/activity.ts
|
|
210
256
|
init_define_KHALA_BUNDLE();
|
|
257
|
+
import * as fs3 from "node:fs/promises";
|
|
211
258
|
import path2 from "node:path";
|
|
212
259
|
async function readActivity(files) {
|
|
213
260
|
const activity = await readJson(path2.join(files.dir, "activity.json"));
|
|
214
261
|
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() };
|
|
215
262
|
}
|
|
263
|
+
var USAGE_LIMIT = "usage-limit.json";
|
|
264
|
+
async function markUsageLimit(files, now = () => /* @__PURE__ */ new Date()) {
|
|
265
|
+
await writeJsonAtomic(path2.join(files.dir, USAGE_LIMIT), { at: now().toISOString() });
|
|
266
|
+
}
|
|
267
|
+
async function clearUsageLimit(files) {
|
|
268
|
+
await fs3.rm(path2.join(files.dir, USAGE_LIMIT), { force: true });
|
|
269
|
+
}
|
|
270
|
+
async function usageLimited(dir) {
|
|
271
|
+
return await readJson(path2.join(dir, USAGE_LIMIT)) !== null;
|
|
272
|
+
}
|
|
216
273
|
async function writeActivity(files, state, now = () => /* @__PURE__ */ new Date()) {
|
|
217
274
|
const activity = { state, updatedAt: now().toISOString() };
|
|
218
275
|
await writeJsonAtomic(path2.join(files.dir, "activity.json"), activity);
|
|
@@ -220,6 +277,11 @@ async function writeActivity(files, state, now = () => /* @__PURE__ */ new Date(
|
|
|
220
277
|
}
|
|
221
278
|
|
|
222
279
|
export {
|
|
280
|
+
toEventInboxEntry,
|
|
281
|
+
createEventKeyFilter,
|
|
282
|
+
isWakeEntry,
|
|
283
|
+
mentions,
|
|
284
|
+
wakesAgent,
|
|
223
285
|
readEntries,
|
|
224
286
|
readCursor,
|
|
225
287
|
unread,
|
|
@@ -231,5 +293,8 @@ export {
|
|
|
231
293
|
migrateLegacy,
|
|
232
294
|
resolveChannel,
|
|
233
295
|
readActivity,
|
|
296
|
+
markUsageLimit,
|
|
297
|
+
clearUsageLimit,
|
|
298
|
+
usageLimited,
|
|
234
299
|
writeActivity
|
|
235
300
|
};
|
|
@@ -3,32 +3,33 @@ import {
|
|
|
3
3
|
WAKE_HARNESSES,
|
|
4
4
|
wakeDrivers,
|
|
5
5
|
wakeStatus
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-W6HM6F2U.mjs";
|
|
7
7
|
import {
|
|
8
8
|
adapterFor,
|
|
9
|
+
registerAntigravityWake,
|
|
9
10
|
resolveSources
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-5JSGA6OB.mjs";
|
|
11
12
|
import {
|
|
12
13
|
CURSOR_DEFAULT_SESSION,
|
|
13
14
|
updateWakeSettings
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-2AMWQ7RB.mjs";
|
|
15
16
|
import {
|
|
16
17
|
SESSION_ID_PATTERN,
|
|
17
18
|
filesForDir,
|
|
18
19
|
stateRoot
|
|
19
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-PN25BUQ4.mjs";
|
|
20
21
|
import {
|
|
21
22
|
resetWakeDriver
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-ZSKLNZWZ.mjs";
|
|
23
24
|
import {
|
|
24
25
|
init_define_KHALA_BUNDLE
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-EVT2DWNZ.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;
|