khala-cli 0.4.8 → 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/README.md +4 -4
- package/dist/THIRD_PARTY_NOTICES.txt +809 -0
- package/dist/chunk-2AMWQ7RB.mjs +1127 -0
- package/dist/chunk-3E5DH3Y6.mjs +9864 -0
- package/dist/{chunk-IQJQ4RF5.mjs → chunk-4BP7V3OP.mjs} +12 -1
- package/dist/{chunk-FV32AQTC.mjs → chunk-4BZQ4GVW.mjs} +10 -6
- package/dist/chunk-5JSGA6OB.mjs +1483 -0
- package/dist/chunk-6AQVW5W7.mjs +60 -0
- package/dist/{chunk-W6R4UJUQ.mjs → chunk-6J2PUM7L.mjs} +16 -9
- package/dist/chunk-6SUV3EW6.mjs +27 -0
- package/dist/{chunk-RNDUFTBF.mjs → chunk-ARIDZOTI.mjs} +499 -115
- package/dist/chunk-C2WEDMAF.mjs +15 -0
- package/dist/{chunk-Z4JF2M5C.mjs → chunk-CHC4VZF5.mjs} +9 -9
- package/dist/chunk-CKLCR5G4.mjs +1369 -0
- package/dist/chunk-EVT2DWNZ.mjs +58 -0
- package/dist/chunk-FJVVSKZ3.mjs +22 -0
- package/dist/{chunk-APMWDF6B.mjs → chunk-G3NMB4PY.mjs} +4 -2
- package/dist/chunk-HHEZVPRR.mjs +7 -0
- package/dist/{chunk-54XFVSEC.mjs → chunk-JKOJQTFT.mjs} +103 -5
- package/dist/{chunk-ZJ4W7P33.mjs → chunk-NDMFD5IM.mjs} +15 -10
- package/dist/{chunk-VKQ3KUYO.mjs → chunk-OEV5DFLW.mjs} +77 -7
- package/dist/chunk-OIZ4R5H7.mjs +173 -0
- package/dist/{chunk-CJTCU755.mjs → chunk-PJKI7SRI.mjs} +256 -26
- package/dist/chunk-PN25BUQ4.mjs +599 -0
- package/dist/chunk-QDPJ4VT2.mjs +432 -0
- package/dist/{chunk-2DHIAFEV.mjs → chunk-SRZTHCXP.mjs} +24 -10
- package/dist/chunk-TSK3HJEG.mjs +20 -0
- package/dist/chunk-UX34IVN5.mjs +33 -0
- package/dist/{chunk-BKLW2SPG.mjs → chunk-VAC3JTAV.mjs} +34 -17
- package/dist/{chunk-VAI7IUI4.mjs → chunk-VDZK4LW3.mjs} +30 -12
- package/dist/chunk-W6HM6F2U.mjs +901 -0
- package/dist/{chunk-H3K4GA2P.mjs → chunk-WPNMWNCL.mjs} +33 -21
- package/dist/chunk-WUDXHF2Q.mjs +14 -0
- package/dist/chunk-WZJ6DQJV.mjs +19 -0
- package/dist/{chunk-5LIE5GUU.mjs → chunk-XR625T3I.mjs} +5 -1
- package/dist/chunk-ZSKLNZWZ.mjs +224 -0
- package/dist/iterm2_send.py +56 -0
- package/dist/khala.mjs +20 -13
- 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 +5 -3
- package/dist/chunk-2VCAW4GH.mjs +0 -34
- package/dist/chunk-5BQTYU66.mjs +0 -886
- package/dist/chunk-5GLTKWJ5.mjs +0 -1
- package/dist/chunk-5PUQT3YS.mjs +0 -569
- package/dist/chunk-7HBRFY3Z.mjs +0 -8
- package/dist/chunk-CBPLCCRZ.mjs +0 -191
- package/dist/chunk-FH34B3I3.mjs +0 -235
- package/dist/chunk-NKX3SLS7.mjs +0 -227
- package/dist/chunk-VUSV2ADL.mjs +0 -267
- package/dist/web/assets/local-BQl2KrE1.js +0 -9
- package/dist/web/assets/local-OwDq47O4.css +0 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res, err) => function __init() {
|
|
9
|
+
if (err) throw err[0];
|
|
10
|
+
try {
|
|
11
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw err = [e], e;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
17
|
+
try {
|
|
18
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
throw mod = 0, e;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
var __export = (target, all) => {
|
|
24
|
+
for (var name in all)
|
|
25
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
26
|
+
};
|
|
27
|
+
var __copyProps = (to, from, except, desc) => {
|
|
28
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
29
|
+
for (let key of __getOwnPropNames(from))
|
|
30
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
31
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
32
|
+
}
|
|
33
|
+
return to;
|
|
34
|
+
};
|
|
35
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
36
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
37
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
38
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
39
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
40
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
41
|
+
mod
|
|
42
|
+
));
|
|
43
|
+
|
|
44
|
+
// <define:__KHALA_BUNDLE__>
|
|
45
|
+
var define_KHALA_BUNDLE_default;
|
|
46
|
+
var init_define_KHALA_BUNDLE = __esm({
|
|
47
|
+
"<define:__KHALA_BUNDLE__>"() {
|
|
48
|
+
define_KHALA_BUNDLE_default = { name: "khala-cli", version: "0.4.10" };
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
__commonJS,
|
|
54
|
+
__export,
|
|
55
|
+
__toESM,
|
|
56
|
+
init_define_KHALA_BUNDLE,
|
|
57
|
+
define_KHALA_BUNDLE_default
|
|
58
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
cancelAttempt,
|
|
4
|
+
confirmWakeText,
|
|
5
|
+
failAttempt,
|
|
6
|
+
readWakeState,
|
|
7
|
+
recordAttempt,
|
|
8
|
+
resetWakeDriver,
|
|
9
|
+
settleAttempts,
|
|
10
|
+
takeWakeDisableNotices
|
|
11
|
+
} from "./chunk-ZSKLNZWZ.mjs";
|
|
12
|
+
import "./chunk-EVT2DWNZ.mjs";
|
|
13
|
+
export {
|
|
14
|
+
cancelAttempt,
|
|
15
|
+
confirmWakeText,
|
|
16
|
+
failAttempt,
|
|
17
|
+
readWakeState,
|
|
18
|
+
recordAttempt,
|
|
19
|
+
resetWakeDriver,
|
|
20
|
+
settleAttempts,
|
|
21
|
+
takeWakeDisableNotices
|
|
22
|
+
};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
-
define_KHALA_BUNDLE_default
|
|
4
|
-
|
|
3
|
+
define_KHALA_BUNDLE_default,
|
|
4
|
+
init_define_KHALA_BUNDLE
|
|
5
|
+
} from "./chunk-EVT2DWNZ.mjs";
|
|
5
6
|
|
|
6
7
|
// src/bundle.ts
|
|
8
|
+
init_define_KHALA_BUNDLE();
|
|
7
9
|
var bundle = typeof define_KHALA_BUNDLE_default === "undefined" ? void 0 : define_KHALA_BUNDLE_default;
|
|
8
10
|
|
|
9
11
|
export {
|
|
@@ -5,16 +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";
|
|
14
|
+
import {
|
|
15
|
+
init_define_KHALA_BUNDLE
|
|
16
|
+
} from "./chunk-EVT2DWNZ.mjs";
|
|
13
17
|
|
|
14
18
|
// ../contracts/src/m1/channel-event.ts
|
|
19
|
+
init_define_KHALA_BUNDLE();
|
|
15
20
|
var CHANNEL_EVENT_TYPE = "com.khala.event.v1";
|
|
16
21
|
var CHANNEL_EVENT_STATUSES = ["info", "pending", "success", "failure", "attention"];
|
|
17
22
|
var MAX_CHANNEL_EVENT_BYTES = 4096;
|
|
23
|
+
var COORDINATION_KINDS = ["handoff", "handoff_ack", "verdict", "claim", "release", "note"];
|
|
18
24
|
function record(input, path) {
|
|
19
25
|
if (typeof input !== "object" || input === null || Array.isArray(input)) fail(path, "not_object");
|
|
20
26
|
const prototype = Object.getPrototypeOf(input);
|
|
@@ -72,10 +78,66 @@ function decodeChannelEvent(raw) {
|
|
|
72
78
|
...r.has("url") ? { url: readUrl(r.field("url")) } : {},
|
|
73
79
|
...r.has("occurred_at") ? { occurred_at: utcTimestamp(r.field("occurred_at"), "occurred_at") } : {},
|
|
74
80
|
...r.has("source") ? { source: readSource(r.field("source")) } : {},
|
|
75
|
-
...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")) } : {}
|
|
76
84
|
};
|
|
77
85
|
}));
|
|
78
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
|
+
}
|
|
79
141
|
function readSubject(input) {
|
|
80
142
|
const r = record(input, "subject");
|
|
81
143
|
let pr;
|
|
@@ -123,8 +185,23 @@ function formatChannelEventLine(content) {
|
|
|
123
185
|
function encodeChannelEvent(input) {
|
|
124
186
|
return safely(() => {
|
|
125
187
|
const checked = decodeWith(() => {
|
|
126
|
-
record(input, "");
|
|
127
|
-
|
|
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
|
+
};
|
|
128
205
|
});
|
|
129
206
|
if (!checked.ok) return checked;
|
|
130
207
|
const decoded = decodeChannelEvent(checked.value);
|
|
@@ -159,6 +236,26 @@ function statusFor(content) {
|
|
|
159
236
|
return content.kind.startsWith("agent.attention.") && !content.kind.endsWith(".resolved") ? "attention" : "info";
|
|
160
237
|
}
|
|
161
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
|
+
}
|
|
162
259
|
|
|
163
260
|
export {
|
|
164
261
|
CHANNEL_EVENT_TYPE,
|
|
@@ -166,5 +263,6 @@ export {
|
|
|
166
263
|
formatChannelEventLine,
|
|
167
264
|
encodeChannelEvent,
|
|
168
265
|
memberRenameContent,
|
|
169
|
-
statusFor
|
|
266
|
+
statusFor,
|
|
267
|
+
foldCoordination
|
|
170
268
|
};
|
|
@@ -14,22 +14,24 @@ import {
|
|
|
14
14
|
decodeLocalSendResult,
|
|
15
15
|
ensureHelper,
|
|
16
16
|
localRoomPath
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
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";
|
|
21
24
|
import {
|
|
22
25
|
CHANNEL_EVENT_TYPE,
|
|
23
26
|
memberRenameContent
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
27
|
+
} from "./chunk-JKOJQTFT.mjs";
|
|
28
|
+
import "./chunk-PN25BUQ4.mjs";
|
|
26
29
|
import {
|
|
27
|
-
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import "./chunk-NKX3SLS7.mjs";
|
|
30
|
-
import "./chunk-7HBRFY3Z.mjs";
|
|
30
|
+
init_define_KHALA_BUNDLE
|
|
31
|
+
} from "./chunk-EVT2DWNZ.mjs";
|
|
31
32
|
|
|
32
33
|
// src/local/session.ts
|
|
34
|
+
init_define_KHALA_BUNDLE();
|
|
33
35
|
import { randomUUID } from "node:crypto";
|
|
34
36
|
var LocalCallError = class extends Error {
|
|
35
37
|
constructor(status, code) {
|
|
@@ -122,6 +124,7 @@ async function createLocalSession(creds, opts = {}) {
|
|
|
122
124
|
let name;
|
|
123
125
|
let invitedBy;
|
|
124
126
|
let after = 0;
|
|
127
|
+
let joinedAt;
|
|
125
128
|
function check(roomId) {
|
|
126
129
|
if (stopped) throw new Error("session_stopped");
|
|
127
130
|
if (roomId !== creds.roomId) throw new Error("unknown_room");
|
|
@@ -321,6 +324,7 @@ async function createLocalSession(creds, opts = {}) {
|
|
|
321
324
|
joining ??= (async () => {
|
|
322
325
|
const result = decoded(await withHelper(() => request("POST", "join", {})), decodeLocalJoined);
|
|
323
326
|
after = result.seq;
|
|
327
|
+
joinedAt = result.ts;
|
|
324
328
|
await me();
|
|
325
329
|
const members = decoded(await withHelper(() => request("GET", "members?wire=2")), decodeLocalMembersResponse);
|
|
326
330
|
check(roomId);
|
|
@@ -338,6 +342,7 @@ async function createLocalSession(creds, opts = {}) {
|
|
|
338
342
|
joining = void 0;
|
|
339
343
|
}
|
|
340
344
|
},
|
|
345
|
+
joinedAt: (roomId) => roomId === creds.roomId ? joinedAt : void 0,
|
|
341
346
|
async history(roomId, limit, before) {
|
|
342
347
|
check(roomId);
|
|
343
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,
|
|
@@ -6,14 +10,57 @@ import {
|
|
|
6
10
|
ensureStateDir,
|
|
7
11
|
filesForDir,
|
|
8
12
|
readJson,
|
|
9
|
-
readStatus,
|
|
10
13
|
removeStateFile,
|
|
11
14
|
stateKey,
|
|
12
15
|
writeJsonAtomic,
|
|
13
16
|
writeStateFile
|
|
14
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-PN25BUQ4.mjs";
|
|
18
|
+
import {
|
|
19
|
+
init_define_KHALA_BUNDLE
|
|
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
|
+
}
|
|
15
61
|
|
|
16
62
|
// src/inbox.ts
|
|
63
|
+
init_define_KHALA_BUNDLE();
|
|
17
64
|
import * as fs from "node:fs/promises";
|
|
18
65
|
async function readEntries(files) {
|
|
19
66
|
let content;
|
|
@@ -60,16 +107,18 @@ async function unread(files) {
|
|
|
60
107
|
}
|
|
61
108
|
async function unreadCounts(files) {
|
|
62
109
|
const { entries } = await unread(files);
|
|
63
|
-
return { total: entries.length, messages: entries.filter((entry) => entry
|
|
110
|
+
return { total: entries.length, messages: entries.filter((entry) => isWakeEntry(entry)).length };
|
|
64
111
|
}
|
|
65
|
-
async function advanceCursor(files, expected, delivered) {
|
|
112
|
+
async function advanceCursor(files, expected, delivered, shown = false) {
|
|
66
113
|
const current = await readCursor(files);
|
|
67
114
|
if (current.deliveredCount !== expected.deliveredCount || current.lastDeliveredEventId !== expected.lastDeliveredEventId) return "conflict";
|
|
68
115
|
if (!delivered.length) return expected;
|
|
69
116
|
const entries = await readEntries(files);
|
|
70
117
|
const slice = entries.slice(expected.deliveredCount, expected.deliveredCount + delivered.length);
|
|
71
118
|
if (slice.length !== delivered.length || slice.some((entry, index) => entry.eventId !== delivered[index]?.eventId)) return "conflict";
|
|
72
|
-
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 } : {} };
|
|
73
122
|
await writeJsonAtomic(files.cursor, next);
|
|
74
123
|
return next;
|
|
75
124
|
}
|
|
@@ -81,6 +130,7 @@ function unreadCount(dir) {
|
|
|
81
130
|
}
|
|
82
131
|
|
|
83
132
|
// src/channels.ts
|
|
133
|
+
init_define_KHALA_BUNDLE();
|
|
84
134
|
import * as fs2 from "node:fs/promises";
|
|
85
135
|
import path from "node:path";
|
|
86
136
|
function channelKey(roomId2) {
|
|
@@ -134,7 +184,7 @@ async function listChannels(files) {
|
|
|
134
184
|
if (await exists(files.inbox)) {
|
|
135
185
|
const id = await legacyRoomId(files);
|
|
136
186
|
if (id) {
|
|
137
|
-
const status = await
|
|
187
|
+
const status = await readJson(files.status);
|
|
138
188
|
channels.push({ key: channelKey(id), roomId: id, ...typeof status?.channelName === "string" ? { channelName: status.channelName } : {}, files, legacy: true });
|
|
139
189
|
}
|
|
140
190
|
}
|
|
@@ -161,7 +211,7 @@ async function migrateLegacy(files) {
|
|
|
161
211
|
console.warn(`Khala cursor migration: conflicting cursors for ${id}; using earlier position ${safe.deliveredCount} to avoid skipping messages (legacy=${legacyCursor.deliveredCount}, channel=${channelCursor.deliveredCount}).`);
|
|
162
212
|
}
|
|
163
213
|
}
|
|
164
|
-
const status = await
|
|
214
|
+
const status = await readJson(files.status);
|
|
165
215
|
const metadata = await readJson(path.join(nested.dir, "channel.json"));
|
|
166
216
|
if (!metadata || roomId(metadata) !== id) {
|
|
167
217
|
await writeStateFile(nested.dir, "channel.json", {
|
|
@@ -203,11 +253,23 @@ function resolveChannel(list, ref) {
|
|
|
203
253
|
}
|
|
204
254
|
|
|
205
255
|
// src/activity.ts
|
|
256
|
+
init_define_KHALA_BUNDLE();
|
|
257
|
+
import * as fs3 from "node:fs/promises";
|
|
206
258
|
import path2 from "node:path";
|
|
207
259
|
async function readActivity(files) {
|
|
208
260
|
const activity = await readJson(path2.join(files.dir, "activity.json"));
|
|
209
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() };
|
|
210
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
|
+
}
|
|
211
273
|
async function writeActivity(files, state, now = () => /* @__PURE__ */ new Date()) {
|
|
212
274
|
const activity = { state, updatedAt: now().toISOString() };
|
|
213
275
|
await writeJsonAtomic(path2.join(files.dir, "activity.json"), activity);
|
|
@@ -215,6 +277,11 @@ async function writeActivity(files, state, now = () => /* @__PURE__ */ new Date(
|
|
|
215
277
|
}
|
|
216
278
|
|
|
217
279
|
export {
|
|
280
|
+
toEventInboxEntry,
|
|
281
|
+
createEventKeyFilter,
|
|
282
|
+
isWakeEntry,
|
|
283
|
+
mentions,
|
|
284
|
+
wakesAgent,
|
|
218
285
|
readEntries,
|
|
219
286
|
readCursor,
|
|
220
287
|
unread,
|
|
@@ -226,5 +293,8 @@ export {
|
|
|
226
293
|
migrateLegacy,
|
|
227
294
|
resolveChannel,
|
|
228
295
|
readActivity,
|
|
296
|
+
markUsageLimit,
|
|
297
|
+
clearUsageLimit,
|
|
298
|
+
usageLimited,
|
|
229
299
|
writeActivity
|
|
230
300
|
};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
WAKE_HARNESSES,
|
|
4
|
+
wakeDrivers,
|
|
5
|
+
wakeStatus
|
|
6
|
+
} from "./chunk-W6HM6F2U.mjs";
|
|
7
|
+
import {
|
|
8
|
+
adapterFor,
|
|
9
|
+
registerAntigravityWake,
|
|
10
|
+
resolveSources
|
|
11
|
+
} from "./chunk-5JSGA6OB.mjs";
|
|
12
|
+
import {
|
|
13
|
+
CURSOR_DEFAULT_SESSION,
|
|
14
|
+
updateWakeSettings
|
|
15
|
+
} from "./chunk-2AMWQ7RB.mjs";
|
|
16
|
+
import {
|
|
17
|
+
SESSION_ID_PATTERN,
|
|
18
|
+
filesForDir,
|
|
19
|
+
stateRoot
|
|
20
|
+
} from "./chunk-PN25BUQ4.mjs";
|
|
21
|
+
import {
|
|
22
|
+
resetWakeDriver
|
|
23
|
+
} from "./chunk-ZSKLNZWZ.mjs";
|
|
24
|
+
import {
|
|
25
|
+
init_define_KHALA_BUNDLE
|
|
26
|
+
} from "./chunk-EVT2DWNZ.mjs";
|
|
27
|
+
|
|
28
|
+
// src/wake/cli.ts
|
|
29
|
+
init_define_KHALA_BUNDLE();
|
|
30
|
+
import * as fs from "node:fs/promises";
|
|
31
|
+
import path from "node:path";
|
|
32
|
+
var WAKE_USAGE = "usage: khala wake on|off|status|register [--driver <d>] [--harness <id>] [--json]";
|
|
33
|
+
async function sessionIds(harness, env) {
|
|
34
|
+
try {
|
|
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);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error.code === "ENOENT") return [];
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function setWake(harness, drivers, on, env) {
|
|
42
|
+
const root = stateRoot(env);
|
|
43
|
+
const at = (/* @__PURE__ */ new Date()).toISOString();
|
|
44
|
+
await updateWakeSettings(root, (settings) => {
|
|
45
|
+
for (const driver of drivers) {
|
|
46
|
+
const key = `${harness}/${driver}`;
|
|
47
|
+
if (on) {
|
|
48
|
+
settings.consent[key] = { at };
|
|
49
|
+
delete settings.off[key];
|
|
50
|
+
} else {
|
|
51
|
+
delete settings.consent[key];
|
|
52
|
+
settings.off[key] = { at };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
if (on) for (const id of await sessionIds(harness, env)) {
|
|
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
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
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.`;
|
|
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.`;
|
|
67
|
+
}
|
|
68
|
+
async function currentSessionId(harness, env) {
|
|
69
|
+
const adapter = adapterFor(harness);
|
|
70
|
+
if (!adapter) return void 0;
|
|
71
|
+
const session = await resolveSources(adapter.sessionSources.filter((source) => source.kind !== "process"), void 0, env, { harness: adapter.id });
|
|
72
|
+
return session?.sessionId !== CURSOR_DEFAULT_SESSION ? session?.sessionId : void 0;
|
|
73
|
+
}
|
|
74
|
+
async function runWake(argv, deps = {}) {
|
|
75
|
+
const env = deps.env ?? process.env;
|
|
76
|
+
const out = deps.stdout ?? console.log;
|
|
77
|
+
const err = deps.stderr ?? console.error;
|
|
78
|
+
const [command, ...flags] = argv;
|
|
79
|
+
let harness;
|
|
80
|
+
let driver;
|
|
81
|
+
let json = false;
|
|
82
|
+
for (let i = 0; i < flags.length; i++) {
|
|
83
|
+
const flag = flags[i];
|
|
84
|
+
if (flag === "--json") json = true;
|
|
85
|
+
else if ((flag === "--harness" || flag === "--driver") && flags[i + 1] && !flags[i + 1].startsWith("--")) {
|
|
86
|
+
const value = flags[++i];
|
|
87
|
+
if (flag === "--harness") harness = value;
|
|
88
|
+
else driver = value;
|
|
89
|
+
} else {
|
|
90
|
+
err(WAKE_USAGE);
|
|
91
|
+
return 2;
|
|
92
|
+
}
|
|
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
|
+
}
|
|
108
|
+
if (!["on", "off", "status"].includes(command ?? "")) {
|
|
109
|
+
err(WAKE_USAGE);
|
|
110
|
+
return 2;
|
|
111
|
+
}
|
|
112
|
+
if (harness && !WAKE_HARNESSES.includes(harness)) {
|
|
113
|
+
err(`Unknown harness ${harness}. Valid harnesses: ${WAKE_HARNESSES.join(", ")}`);
|
|
114
|
+
return 2;
|
|
115
|
+
}
|
|
116
|
+
const candidates = harness ? [harness] : WAKE_HARNESSES;
|
|
117
|
+
const valid = [...new Set(candidates.flatMap((id) => wakeDrivers(id).map((item) => item.id)))];
|
|
118
|
+
if (driver && !valid.includes(driver)) {
|
|
119
|
+
err(`Unknown driver ${driver}. Valid drivers: ${valid.join(", ") || "none"}`);
|
|
120
|
+
return 2;
|
|
121
|
+
}
|
|
122
|
+
if (!harness && command !== "status") {
|
|
123
|
+
for (const id of WAKE_HARNESSES) {
|
|
124
|
+
if (await currentSessionId(id, env) !== void 0) {
|
|
125
|
+
harness = id;
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (!harness && driver) {
|
|
130
|
+
const matches = WAKE_HARNESSES.filter((id) => wakeDrivers(id).some((item) => item.id === driver));
|
|
131
|
+
if (matches.length === 1) harness = matches[0];
|
|
132
|
+
}
|
|
133
|
+
if (!harness) {
|
|
134
|
+
err(`Select --harness. Valid harnesses: ${WAKE_HARNESSES.join(", ")}`);
|
|
135
|
+
return 2;
|
|
136
|
+
}
|
|
137
|
+
if (driver && !wakeDrivers(harness).some((item) => item.id === driver)) {
|
|
138
|
+
err(`Unknown driver ${driver}. Valid drivers: ${wakeDrivers(harness).map((item) => item.id).join(", ") || "none"}`);
|
|
139
|
+
return 2;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const harnesses = harness ? [harness] : WAKE_HARNESSES;
|
|
143
|
+
if (command === "status") {
|
|
144
|
+
const rows = [];
|
|
145
|
+
for (const id of harnesses) {
|
|
146
|
+
const sessionId = await currentSessionId(id, env);
|
|
147
|
+
rows.push(...await wakeStatus(id, { env, ...sessionId ? { files: filesForDir(path.join(stateRoot(env), id, sessionId)), sessionId } : {} }));
|
|
148
|
+
}
|
|
149
|
+
const selected = driver ? rows.filter((row) => row.driver === driver) : rows;
|
|
150
|
+
out(json ? JSON.stringify(selected) : selected.map((row) => `${row.harness} ${row.driver} ${row.rung} ${row.state} ${row.reason}${row.remedy ? ` ${row.remedy}` : ""}${row.note ? ` ${row.note}` : ""}`).join("\n"));
|
|
151
|
+
} else {
|
|
152
|
+
const all = wakeDrivers(harness);
|
|
153
|
+
const selected = driver ? [driver] : command === "on" ? [all.find((item) => item.optIn)?.id ?? all[0]?.id].filter((id) => !!id) : all.map((item) => item.id);
|
|
154
|
+
if (!selected.length) {
|
|
155
|
+
err(`No wake drivers for ${harness}.`);
|
|
156
|
+
return 2;
|
|
157
|
+
}
|
|
158
|
+
await setWake(harness, selected, command === "on", env);
|
|
159
|
+
const message = consentLine(harness, selected, command === "on");
|
|
160
|
+
out(json ? JSON.stringify({ harness, drivers: selected, on: command === "on", message }) : message);
|
|
161
|
+
}
|
|
162
|
+
return 0;
|
|
163
|
+
}
|
|
164
|
+
var cli_default = runWake;
|
|
165
|
+
|
|
166
|
+
export {
|
|
167
|
+
WAKE_USAGE,
|
|
168
|
+
sessionIds,
|
|
169
|
+
setWake,
|
|
170
|
+
consentLine,
|
|
171
|
+
runWake,
|
|
172
|
+
cli_default
|
|
173
|
+
};
|