khala-cli 0.4.2 → 0.4.5
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-T6RZE5IQ.mjs → chunk-6LC66VHK.mjs} +10 -7
- package/dist/chunk-7G2G4E4U.mjs +236 -0
- package/dist/chunk-AUJEUKVM.mjs +121 -0
- package/dist/{chunk-NUS6M27N.mjs → chunk-EW22K3JO.mjs} +445 -199
- package/dist/chunk-EXHCVFVH.mjs +26 -0
- package/dist/{chunk-CDHHFC6C.mjs → chunk-H46OG22B.mjs} +22 -6
- package/dist/{chunk-YP45XTOH.mjs → chunk-HB3UGIZG.mjs} +5 -5
- package/dist/chunk-IR3VN2ID.mjs +52 -0
- package/dist/{chunk-B5BFL7OD.mjs → chunk-KCJFSVDN.mjs} +55 -4
- package/dist/{chunk-K4MDSFHU.mjs → chunk-MBLP7LQJ.mjs} +103 -38
- package/dist/{chunk-RW3DXWNC.mjs → chunk-OLZ62X7S.mjs} +1 -1
- package/dist/chunk-P5CP32X2.mjs +170 -0
- package/dist/{chunk-A3LJU4JA.mjs → chunk-PXKGKVGW.mjs} +1 -1
- package/dist/{chunk-7MQAMABY.mjs → chunk-RSDOTTZQ.mjs} +4 -4
- package/dist/chunk-SN3STAO2.mjs +190 -0
- package/dist/{chunk-MHZWR4A3.mjs → chunk-SQXDATEC.mjs} +1 -1
- package/dist/chunk-T7YRVE43.mjs +238 -0
- package/dist/{chunk-BZ53MZEE.mjs → chunk-TZKEQIHP.mjs} +8 -4
- package/dist/{chunk-46PTKRZC.mjs → chunk-V4Y26O4R.mjs} +171 -113
- package/dist/chunk-V7M27QLT.mjs +21 -0
- package/dist/{chunk-2OO725IZ.mjs → chunk-Y2DRTRBJ.mjs} +3 -3
- package/dist/{chunk-JRZZVTQ4.mjs → chunk-Y4WVILEJ.mjs} +94 -10
- package/dist/khala.mjs +12 -10
- package/dist/web/assets/apple-touch-icon-Du9V6qit.png +0 -0
- package/dist/web/assets/favicon-16x16-D5waNSZD.png +0 -0
- package/dist/web/assets/favicon-32x32-B9Ubw1Dx.png +0 -0
- package/dist/web/assets/favicon-zCD0pKtT.ico +0 -0
- package/dist/web/assets/local-C1vz22ps.js +9 -0
- package/dist/web/assets/local-DdjwMERJ.css +1 -0
- package/dist/web/index.html +7 -2
- package/package.json +1 -1
- package/dist/chunk-N6LMHR7P.mjs +0 -455
- package/dist/chunk-U5ZMOPUK.mjs +0 -149
- package/dist/web/assets/local-CVA9799w.js +0 -9
- package/dist/web/assets/local-DHYvcQG0.css +0 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
WATCH_USAGE,
|
|
4
|
+
mentions,
|
|
5
|
+
monitorArmed,
|
|
6
|
+
run,
|
|
7
|
+
watchSession
|
|
8
|
+
} from "./chunk-7G2G4E4U.mjs";
|
|
9
|
+
import "./chunk-T7YRVE43.mjs";
|
|
10
|
+
import "./chunk-VUE2DDYY.mjs";
|
|
11
|
+
import "./chunk-KCJFSVDN.mjs";
|
|
12
|
+
import "./chunk-AUJEUKVM.mjs";
|
|
13
|
+
import "./chunk-SN3STAO2.mjs";
|
|
14
|
+
import "./chunk-PXKGKVGW.mjs";
|
|
15
|
+
export {
|
|
16
|
+
WATCH_USAGE,
|
|
17
|
+
run as default,
|
|
18
|
+
mentions,
|
|
19
|
+
monitorArmed,
|
|
20
|
+
watchSession
|
|
21
|
+
};
|
|
@@ -4,17 +4,17 @@ import {
|
|
|
4
4
|
MODEL_NAMES,
|
|
5
5
|
checkName,
|
|
6
6
|
isDefaultAgentName
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-TZKEQIHP.mjs";
|
|
8
8
|
import {
|
|
9
9
|
StateError,
|
|
10
10
|
readJson,
|
|
11
11
|
stateRoot,
|
|
12
12
|
writeJsonAtomic
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-KCJFSVDN.mjs";
|
|
14
14
|
import {
|
|
15
15
|
HARNESSES,
|
|
16
16
|
validateAgentName
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-SN3STAO2.mjs";
|
|
18
18
|
|
|
19
19
|
// src/local/identity.ts
|
|
20
20
|
import * as fs from "node:fs/promises";
|
|
@@ -2,13 +2,16 @@ import { createRequire as __khalaCreateRequire } from 'node:module'; const requi
|
|
|
2
2
|
import "./chunk-5GLTKWJ5.mjs";
|
|
3
3
|
import {
|
|
4
4
|
CHANNEL_EVENT_TYPE,
|
|
5
|
-
LISTENING_MODE_COMMAND_TYPE,
|
|
6
|
-
LISTENING_MODE_MEMBER_KEY,
|
|
7
5
|
encodeChannelEvent,
|
|
8
|
-
memberListeningMode,
|
|
9
6
|
memberRenameContent
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import
|
|
7
|
+
} from "./chunk-P5CP32X2.mjs";
|
|
8
|
+
import {
|
|
9
|
+
LISTENING_MODE_COMMAND_TYPE,
|
|
10
|
+
LISTENING_MODE_MEMBER_KEY,
|
|
11
|
+
memberListeningMode
|
|
12
|
+
} from "./chunk-AUJEUKVM.mjs";
|
|
13
|
+
import "./chunk-SN3STAO2.mjs";
|
|
14
|
+
import "./chunk-PXKGKVGW.mjs";
|
|
12
15
|
|
|
13
16
|
// src/matrix/session.ts
|
|
14
17
|
import { createClient, ClientEvent, RoomEvent, MatrixEventEvent, SyncState, Direction, Method, EventType } from "matrix-js-sdk";
|
|
@@ -36,6 +39,7 @@ async function createAgentMatrixSession(creds, opts) {
|
|
|
36
39
|
const log = (line) => opts?.log?.(line);
|
|
37
40
|
const client = createClient({ baseUrl: creds.homeserver, userId: creds.userId, accessToken: creds.accessToken, deviceId: creds.deviceId });
|
|
38
41
|
const handlers = /* @__PURE__ */ new Set();
|
|
42
|
+
const ended = /* @__PURE__ */ new Set();
|
|
39
43
|
const modeHandlers = /* @__PURE__ */ new Set();
|
|
40
44
|
const inviters = /* @__PURE__ */ new Map();
|
|
41
45
|
const emitted = /* @__PURE__ */ new Set();
|
|
@@ -86,7 +90,45 @@ async function createAgentMatrixSession(creds, opts) {
|
|
|
86
90
|
void client.decryptEventIfNeeded(event).then(() => deliver(event), () => log("live_decryption_failed"));
|
|
87
91
|
};
|
|
88
92
|
const decrypted = (event) => deliver(event);
|
|
89
|
-
const syncLog = (state) =>
|
|
93
|
+
const syncLog = (state, _previous, data) => {
|
|
94
|
+
log(`sync_state=${state}`);
|
|
95
|
+
if (state === SyncState.Error && joinedRoom && matrixCode(data?.error) === "M_UNKNOWN_TOKEN") {
|
|
96
|
+
void checkEnded("unauthorized");
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const matrixCode = (error) => typeof error === "object" && error !== null && "errcode" in error ? error.errcode : void 0;
|
|
100
|
+
let checkingEnded;
|
|
101
|
+
let pendingEndReason;
|
|
102
|
+
const checkEnded = (fallback) => {
|
|
103
|
+
if (stopped) return Promise.resolve();
|
|
104
|
+
if (fallback) pendingEndReason = fallback;
|
|
105
|
+
if (checkingEnded) return checkingEnded;
|
|
106
|
+
checkingEnded = (async () => {
|
|
107
|
+
let removed = false;
|
|
108
|
+
try {
|
|
109
|
+
removed = await opts?.checkRemoved?.() ?? false;
|
|
110
|
+
} catch {
|
|
111
|
+
}
|
|
112
|
+
if (removed) end("removed");
|
|
113
|
+
else if (pendingEndReason) end(pendingEndReason);
|
|
114
|
+
})().finally(() => {
|
|
115
|
+
checkingEnded = void 0;
|
|
116
|
+
pendingEndReason = void 0;
|
|
117
|
+
});
|
|
118
|
+
return checkingEnded;
|
|
119
|
+
};
|
|
120
|
+
const guarded = async (roomId, operation) => {
|
|
121
|
+
if (stopped) throw new Error("session_stopped");
|
|
122
|
+
try {
|
|
123
|
+
return await operation();
|
|
124
|
+
} catch (error) {
|
|
125
|
+
const code = matrixCode(error);
|
|
126
|
+
if (roomId === joinedRoom && (code === "M_FORBIDDEN" || code === "M_UNKNOWN_TOKEN")) {
|
|
127
|
+
await checkEnded(code === "M_UNKNOWN_TOKEN" ? "unauthorized" : void 0);
|
|
128
|
+
}
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
90
132
|
const wait = (subscribe, ready, timeoutMs, error) => {
|
|
91
133
|
if (stopped) return Promise.reject(new Error("session_stopped"));
|
|
92
134
|
if (ready()) return Promise.resolve();
|
|
@@ -117,11 +159,29 @@ async function createAgentMatrixSession(creds, opts) {
|
|
|
117
159
|
client.removeListener(RoomEvent.Timeline, timeline);
|
|
118
160
|
client.removeListener(MatrixEventEvent.Decrypted, decrypted);
|
|
119
161
|
client.removeListener(ClientEvent.Sync, syncLog);
|
|
162
|
+
client.removeListener(RoomEvent.MyMembership, membershipEnded);
|
|
120
163
|
for (const cancel of [...cancellations]) cancel();
|
|
121
164
|
liveEvents.clear();
|
|
122
165
|
emitted.clear();
|
|
123
166
|
handlers.clear();
|
|
124
167
|
modeHandlers.clear();
|
|
168
|
+
ended.clear();
|
|
169
|
+
};
|
|
170
|
+
const membershipEnded = (room, membership) => {
|
|
171
|
+
if (stopped || room.roomId !== joinedRoom || !["leave", "ban"].includes(membership)) return;
|
|
172
|
+
end("removed");
|
|
173
|
+
};
|
|
174
|
+
const end = (reason) => {
|
|
175
|
+
if (stopped) return;
|
|
176
|
+
const listeners = [...ended];
|
|
177
|
+
void stop();
|
|
178
|
+
for (const handler of listeners) {
|
|
179
|
+
try {
|
|
180
|
+
handler(reason);
|
|
181
|
+
} catch {
|
|
182
|
+
log("ended_handler_error");
|
|
183
|
+
}
|
|
184
|
+
}
|
|
125
185
|
};
|
|
126
186
|
try {
|
|
127
187
|
await client.initRustCrypto({ useIndexedDB: false });
|
|
@@ -167,6 +227,12 @@ async function createAgentMatrixSession(creds, opts) {
|
|
|
167
227
|
}, ready, timeoutMs, error);
|
|
168
228
|
return {
|
|
169
229
|
userId: creds.userId,
|
|
230
|
+
onEnded(handler) {
|
|
231
|
+
if (!stopped) ended.add(handler);
|
|
232
|
+
return () => {
|
|
233
|
+
ended.delete(handler);
|
|
234
|
+
};
|
|
235
|
+
},
|
|
170
236
|
listeningMode: (roomId) => memberListeningMode(client.getRoom(roomId)?.currentState.getStateEvents("m.room.member", creds.userId)?.getContent()),
|
|
171
237
|
inviter(roomId) {
|
|
172
238
|
return inviters.get(roomId);
|
|
@@ -178,6 +244,7 @@ async function createAgentMatrixSession(creds, opts) {
|
|
|
178
244
|
};
|
|
179
245
|
},
|
|
180
246
|
async publishListeningMode(roomId, mode, signal) {
|
|
247
|
+
if (stopped) throw new Error("session_stopped");
|
|
181
248
|
const content = client.getRoom(roomId)?.currentState.getStateEvents("m.room.member", creds.userId)?.getContent();
|
|
182
249
|
if (!content) throw new Error("join_state_unavailable");
|
|
183
250
|
const next = { ...content, membership: "join", [LISTENING_MODE_MEMBER_KEY]: mode };
|
|
@@ -217,18 +284,20 @@ async function createAgentMatrixSession(creds, opts) {
|
|
|
217
284
|
await client.sendStateEvent(roomId, EventType.RoomMember, content, creds.userId);
|
|
218
285
|
}
|
|
219
286
|
joinTimes.set(roomId, membership === "join" ? rejoinedAt : ownJoin.getTs());
|
|
287
|
+
if (!joinedRoom) client.on(RoomEvent.MyMembership, membershipEnded);
|
|
220
288
|
joinedRoom = roomId;
|
|
221
289
|
for (const event of liveEvents) {
|
|
222
290
|
if (event.getRoomId() === roomId) deliver(event);
|
|
223
291
|
}
|
|
224
292
|
},
|
|
225
293
|
async history(roomId, limit, before) {
|
|
294
|
+
if (stopped) throw new Error("session_stopped");
|
|
226
295
|
let token = null;
|
|
227
296
|
if (before !== void 0) {
|
|
228
|
-
const context = await client.http.authedRequest(Method.Get, `/rooms/${encodeURIComponent(roomId)}/context/${encodeURIComponent(before)}`, { limit: "0" });
|
|
297
|
+
const context = await guarded(roomId, () => client.http.authedRequest(Method.Get, `/rooms/${encodeURIComponent(roomId)}/context/${encodeURIComponent(before)}`, { limit: "0" }));
|
|
229
298
|
token = context.start;
|
|
230
299
|
}
|
|
231
|
-
const res = await client.createMessagesRequest(roomId, token, limit, Direction.Backward);
|
|
300
|
+
const res = await guarded(roomId, () => client.createMessagesRequest(roomId, token, limit, Direction.Backward));
|
|
232
301
|
const messages = [];
|
|
233
302
|
let undecryptable = 0;
|
|
234
303
|
for (const raw of res.chunk) {
|
|
@@ -239,6 +308,19 @@ async function createAgentMatrixSession(creds, opts) {
|
|
|
239
308
|
}
|
|
240
309
|
if (event.getType() === "m.room.encrypted" || event.isDecryptionFailure()) {
|
|
241
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
|
+
}
|
|
242
324
|
continue;
|
|
243
325
|
}
|
|
244
326
|
const m = message(event);
|
|
@@ -250,11 +332,13 @@ async function createAgentMatrixSession(creds, opts) {
|
|
|
250
332
|
return typeof res.end === "string" && oldest ? { messages, nextBefore: oldest.eventId } : { messages };
|
|
251
333
|
},
|
|
252
334
|
async send(roomId, text) {
|
|
253
|
-
|
|
335
|
+
if (stopped) throw new Error("session_stopped");
|
|
336
|
+
const res = await guarded(roomId, () => client.sendTextMessage(roomId, text));
|
|
254
337
|
return { eventId: res.event_id };
|
|
255
338
|
},
|
|
256
339
|
async sendChannelEvent(roomId, content, txnId) {
|
|
257
|
-
|
|
340
|
+
if (stopped) throw new Error("session_stopped");
|
|
341
|
+
const res = await guarded(roomId, () => client.sendEvent(roomId, CHANNEL_EVENT_TYPE, content, txnId));
|
|
258
342
|
return { eventId: res.event_id };
|
|
259
343
|
},
|
|
260
344
|
roomName(roomId) {
|
package/dist/khala.mjs
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
KHALA_AGENT_VERSION
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-SQXDATEC.mjs";
|
|
6
|
+
import "./chunk-OLZ62X7S.mjs";
|
|
7
|
+
import "./chunk-PXKGKVGW.mjs";
|
|
8
8
|
|
|
9
9
|
// src/cli.ts
|
|
10
10
|
var HOOK_NAME = /^[a-z][a-z0-9-]{0,31}$/;
|
|
11
11
|
var STDIN_CAP = 1024 * 1024;
|
|
12
|
-
var USAGE = "usage: khala mcp | khala hook <name> | khala local <command> | khala install codex | khala install cursor | khala --version";
|
|
12
|
+
var USAGE = "usage: khala mcp | khala watch [--harness claude|codex|cursor --session <id>] | khala hook <name> | khala local <command> | khala install codex | khala install cursor | khala --version";
|
|
13
13
|
async function readStdin() {
|
|
14
14
|
if (process.stdin.isTTY) return "";
|
|
15
15
|
const chunks = [];
|
|
@@ -31,7 +31,7 @@ async function runCli(argv, modules) {
|
|
|
31
31
|
console.log(KHALA_AGENT_VERSION);
|
|
32
32
|
return 0;
|
|
33
33
|
}
|
|
34
|
-
if (cmd === "mcp" || cmd === "install") {
|
|
34
|
+
if (cmd === "mcp" || cmd === "install" || cmd === "watch") {
|
|
35
35
|
const load = modules[cmd]();
|
|
36
36
|
if (!load) {
|
|
37
37
|
console.error(`khala: ${cmd} not available`);
|
|
@@ -78,12 +78,14 @@ async function runCli(argv, modules) {
|
|
|
78
78
|
|
|
79
79
|
// src/cli-bundle.ts
|
|
80
80
|
var hooks = {
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
"session-start": () => import("./chunk-EXHCVFVH.mjs"),
|
|
82
|
+
deliver: () => import("./chunk-MBLP7LQJ.mjs"),
|
|
83
|
+
"claude-wake": () => import("./chunk-H46OG22B.mjs")
|
|
83
84
|
};
|
|
84
85
|
process.exitCode = await runCli(process.argv.slice(2), {
|
|
85
|
-
mcp: () => () => import("./chunk-
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
mcp: () => () => import("./chunk-EW22K3JO.mjs"),
|
|
87
|
+
watch: () => () => import("./chunk-V7M27QLT.mjs"),
|
|
88
|
+
local: () => () => import("./chunk-V4Y26O4R.mjs"),
|
|
89
|
+
install: () => () => import("./chunk-RSDOTTZQ.mjs"),
|
|
88
90
|
hook: (name) => Object.hasOwn(hooks, name) ? hooks[name] : void 0
|
|
89
91
|
});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|