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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
ensureHelper
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-HB3UGIZG.mjs";
|
|
5
5
|
import {
|
|
6
6
|
KhalaClientError,
|
|
7
7
|
LOCAL_LONG_POLL_MAX_S,
|
|
@@ -16,16 +16,19 @@ import {
|
|
|
16
16
|
decodeLocalNameContent,
|
|
17
17
|
decodeLocalSendResult,
|
|
18
18
|
localRoomPath
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-TZKEQIHP.mjs";
|
|
20
|
+
import "./chunk-OLZ62X7S.mjs";
|
|
21
21
|
import "./chunk-5GLTKWJ5.mjs";
|
|
22
22
|
import {
|
|
23
23
|
CHANNEL_EVENT_TYPE,
|
|
24
|
-
LISTENING_MODE_COMMAND_TYPE,
|
|
25
24
|
memberRenameContent
|
|
26
|
-
} from "./chunk-
|
|
27
|
-
import "./chunk-
|
|
28
|
-
import
|
|
25
|
+
} from "./chunk-P5CP32X2.mjs";
|
|
26
|
+
import "./chunk-KCJFSVDN.mjs";
|
|
27
|
+
import {
|
|
28
|
+
LISTENING_MODE_COMMAND_TYPE
|
|
29
|
+
} from "./chunk-AUJEUKVM.mjs";
|
|
30
|
+
import "./chunk-SN3STAO2.mjs";
|
|
31
|
+
import "./chunk-PXKGKVGW.mjs";
|
|
29
32
|
|
|
30
33
|
// src/local/session.ts
|
|
31
34
|
import { randomUUID } from "node:crypto";
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
listChannels,
|
|
4
|
+
readCursor,
|
|
5
|
+
readEntries,
|
|
6
|
+
readListeningMode
|
|
7
|
+
} from "./chunk-T7YRVE43.mjs";
|
|
8
|
+
import {
|
|
9
|
+
CURSOR_WORKSPACE_ENV,
|
|
10
|
+
cursorSessionId
|
|
11
|
+
} from "./chunk-VUE2DDYY.mjs";
|
|
12
|
+
import {
|
|
13
|
+
SESSION_ID_PATTERN,
|
|
14
|
+
readJson,
|
|
15
|
+
readStatus,
|
|
16
|
+
sessionFiles,
|
|
17
|
+
writeJsonAtomic
|
|
18
|
+
} from "./chunk-KCJFSVDN.mjs";
|
|
19
|
+
import {
|
|
20
|
+
HARNESSES
|
|
21
|
+
} from "./chunk-SN3STAO2.mjs";
|
|
22
|
+
|
|
23
|
+
// src/watch.ts
|
|
24
|
+
import * as fs from "node:fs/promises";
|
|
25
|
+
import { watch as watchDirectory } from "node:fs";
|
|
26
|
+
import path from "node:path";
|
|
27
|
+
import { randomUUID } from "node:crypto";
|
|
28
|
+
|
|
29
|
+
// src/mcp/session-id.ts
|
|
30
|
+
var isHarness = (value) => HARNESSES.includes(value);
|
|
31
|
+
function resolveHarness(argv, env) {
|
|
32
|
+
const index = argv.indexOf("--harness");
|
|
33
|
+
if (index !== -1) {
|
|
34
|
+
const value = argv[index + 1];
|
|
35
|
+
return isHarness(value) ? value : "invalid";
|
|
36
|
+
}
|
|
37
|
+
if (isHarness(env.KHALA_MCP_HARNESS)) return env.KHALA_MCP_HARNESS;
|
|
38
|
+
return env.CLAUDE_CODE_SESSION_ID !== void 0 ? "claude" : "codex";
|
|
39
|
+
}
|
|
40
|
+
function resolveSessionId(harness, meta, env) {
|
|
41
|
+
const value = harness === "claude" ? env.CLAUDE_CODE_SESSION_ID : harness === "cursor" ? cursorSessionId(env[CURSOR_WORKSPACE_ENV]) : typeof meta?.threadId === "string" ? meta.threadId : env.CODEX_THREAD_ID;
|
|
42
|
+
return typeof value === "string" && value.match(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/)?.[0] === value ? value : null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/watch.ts
|
|
46
|
+
var MARKER = "monitor.json";
|
|
47
|
+
var OBSERVATION = "monitor-cursor.json";
|
|
48
|
+
var NONCE_PATTERN = /^[a-f0-9-]{36}$/;
|
|
49
|
+
var leaseFile = (files, nonce) => path.join(files.dir, `monitor-${nonce}.json`);
|
|
50
|
+
async function monitorArmed(files) {
|
|
51
|
+
const owner = await readJson(path.join(files.dir, MARKER));
|
|
52
|
+
if (!owner || !Number.isSafeInteger(owner.pid) || owner.pid <= 0 || typeof owner.nonce !== "string" || !NONCE_PATTERN.test(owner.nonce)) return false;
|
|
53
|
+
if ((await readJson(leaseFile(files, owner.nonce)))?.nonce !== owner.nonce) return false;
|
|
54
|
+
try {
|
|
55
|
+
process.kill(owner.pid, 0);
|
|
56
|
+
return true;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
return error.code === "EPERM";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function mentions(entry, name) {
|
|
62
|
+
if (!name) return false;
|
|
63
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
64
|
+
return new RegExp(`(?<![\\p{L}\\p{N}_])@?${escaped}(?![\\p{L}\\p{N}_])`, "iu").test(entry.body);
|
|
65
|
+
}
|
|
66
|
+
function channelLabel(name) {
|
|
67
|
+
return Array.from(name.replace(/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/gu, " ").trim()).slice(0, 80).join("");
|
|
68
|
+
}
|
|
69
|
+
async function watchSession(files, io) {
|
|
70
|
+
const nonce = randomUUID();
|
|
71
|
+
let watcher;
|
|
72
|
+
let timer;
|
|
73
|
+
let running;
|
|
74
|
+
let dirty = false;
|
|
75
|
+
let done = false;
|
|
76
|
+
let code = 0;
|
|
77
|
+
let finish;
|
|
78
|
+
const finished = new Promise((resolve) => {
|
|
79
|
+
finish = resolve;
|
|
80
|
+
});
|
|
81
|
+
const stop = (exit = 0) => {
|
|
82
|
+
done = true;
|
|
83
|
+
code = exit;
|
|
84
|
+
watcher?.close();
|
|
85
|
+
clearInterval(timer);
|
|
86
|
+
finish();
|
|
87
|
+
};
|
|
88
|
+
const abort = () => stop();
|
|
89
|
+
try {
|
|
90
|
+
const status = await readStatus(files);
|
|
91
|
+
const initialSession = await readJson(files.session);
|
|
92
|
+
if (!["connected", "send_failed"].includes(status?.state ?? "") || !initialSession && !(await listChannels(files)).length) return 0;
|
|
93
|
+
const initialDelivered = /* @__PURE__ */ new Map();
|
|
94
|
+
const seedBaseline = async (target, session) => {
|
|
95
|
+
initialDelivered.set(target.dir, {
|
|
96
|
+
identity: JSON.stringify([session.roomId, session.userId]),
|
|
97
|
+
cursor: await readCursor(target)
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
if (initialSession) await seedBaseline(files, initialSession);
|
|
101
|
+
for (const channel of await listChannels(files)) {
|
|
102
|
+
const session = await readJson(channel.files.session);
|
|
103
|
+
if (session) await seedBaseline(channel.files, session);
|
|
104
|
+
}
|
|
105
|
+
const evaluate = async () => {
|
|
106
|
+
const ownsSession = async () => {
|
|
107
|
+
const owner = await readJson(path.join(files.dir, MARKER));
|
|
108
|
+
const status2 = await readJson(files.status);
|
|
109
|
+
return owner?.nonce === nonce && !["disconnected", "closed"].includes(status2?.state ?? "");
|
|
110
|
+
};
|
|
111
|
+
if (!await ownsSession()) {
|
|
112
|
+
stop();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
for (const channel of await listChannels(files)) {
|
|
116
|
+
const target = channel.files;
|
|
117
|
+
const session = await readJson(target.session);
|
|
118
|
+
const status2 = await readStatus(target);
|
|
119
|
+
if (!session || session.roomId !== channel.roomId || typeof session.userId !== "string" || !["connected", "send_failed"].includes(status2?.state ?? "")) continue;
|
|
120
|
+
const identity = JSON.stringify([session.roomId, session.userId]);
|
|
121
|
+
if (initialDelivered.get(target.dir)?.identity !== identity) {
|
|
122
|
+
await seedBaseline(target, session);
|
|
123
|
+
}
|
|
124
|
+
const mode = await readListeningMode(target);
|
|
125
|
+
const entries = await readEntries(target);
|
|
126
|
+
const observed = await readJson(path.join(target.dir, OBSERVATION));
|
|
127
|
+
const position = observed?.userId === session.userId && observed?.roomId === session.roomId && Number.isSafeInteger(observed.count) && observed.count >= 0 && observed.count <= entries.length && (observed.count === 0 || entries[observed.count - 1]?.eventId === observed.lastEventId) ? observed.count : 0;
|
|
128
|
+
const baseline = initialDelivered.get(target.dir).cursor;
|
|
129
|
+
const initialCount = baseline.deliveredCount === 0 || entries[baseline.deliveredCount - 1]?.eventId === baseline.lastDeliveredEventId ? baseline.deliveredCount : 0;
|
|
130
|
+
const fresh = entries.slice(Math.max(initialCount, position));
|
|
131
|
+
const latestMode = await readListeningMode(target);
|
|
132
|
+
const latestSession = await readJson(target.session);
|
|
133
|
+
const latestStatus = await readStatus(target);
|
|
134
|
+
if (!await ownsSession()) {
|
|
135
|
+
stop();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (latestSession?.userId !== session.userId || latestSession?.roomId !== session.roomId || !["connected", "send_failed"].includes(latestStatus?.state ?? "")) continue;
|
|
139
|
+
const messages = fresh.filter((entry) => entry.kind === "message" && entry.sender !== session.userId && entry.roomId === session.roomId);
|
|
140
|
+
if (!done && mode !== "async" && latestMode !== "async" && messages.length) {
|
|
141
|
+
const count = messages.filter((entry) => mentions(entry, latestStatus?.displayName)).length;
|
|
142
|
+
io.write(`khala: ${messages.length} new message${messages.length === 1 ? "" : "s"} in #${channelLabel(latestStatus?.channelName ?? channel.channelName ?? "channel")} (${count} mentions you)
|
|
143
|
+
`);
|
|
144
|
+
}
|
|
145
|
+
if (position !== entries.length && !done && await ownsSession() && JSON.stringify(await readJson(target.session)) === JSON.stringify(latestSession)) {
|
|
146
|
+
try {
|
|
147
|
+
await writeJsonAtomic(path.join(target.dir, OBSERVATION), {
|
|
148
|
+
userId: session.userId,
|
|
149
|
+
roomId: session.roomId,
|
|
150
|
+
count: entries.length,
|
|
151
|
+
lastEventId: entries.at(-1)?.eventId ?? null
|
|
152
|
+
});
|
|
153
|
+
} catch (error) {
|
|
154
|
+
if (await readJson(target.session)) throw error;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
const notify = () => {
|
|
160
|
+
if (done) return;
|
|
161
|
+
dirty = true;
|
|
162
|
+
if (running) return;
|
|
163
|
+
running = (async () => {
|
|
164
|
+
do {
|
|
165
|
+
dirty = false;
|
|
166
|
+
await evaluate();
|
|
167
|
+
} while (dirty && !done);
|
|
168
|
+
})().catch(() => stop(1)).finally(() => {
|
|
169
|
+
running = void 0;
|
|
170
|
+
if (dirty && !done) notify();
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
await writeJsonAtomic(leaseFile(files, nonce), { nonce, pid: process.pid });
|
|
174
|
+
await writeJsonAtomic(path.join(files.dir, MARKER), { nonce, pid: process.pid });
|
|
175
|
+
watcher = watchDirectory(files.dir, (_event, filename) => {
|
|
176
|
+
if (filename === null || [MARKER, "inbox.jsonl", "cursor.json", "mode.json", "session.json", "status.json"].includes(String(filename))) notify();
|
|
177
|
+
});
|
|
178
|
+
watcher.on("error", () => stop(1));
|
|
179
|
+
timer = setInterval(notify, 100);
|
|
180
|
+
io.signal.addEventListener("abort", abort, { once: true });
|
|
181
|
+
if (io.signal.aborted) stop();
|
|
182
|
+
else notify();
|
|
183
|
+
await finished;
|
|
184
|
+
await running;
|
|
185
|
+
return code;
|
|
186
|
+
} finally {
|
|
187
|
+
clearInterval(timer);
|
|
188
|
+
watcher?.close();
|
|
189
|
+
io.signal.removeEventListener("abort", abort);
|
|
190
|
+
await fs.unlink(leaseFile(files, nonce)).catch((error) => {
|
|
191
|
+
if (error.code !== "ENOENT") throw error;
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
var WATCH_USAGE = "usage: khala watch [--harness claude|codex|cursor --session <id>]";
|
|
196
|
+
async function run(argv) {
|
|
197
|
+
if (argv.length === 1 && ["--help", "-h"].includes(argv[0])) {
|
|
198
|
+
console.log(WATCH_USAGE);
|
|
199
|
+
return 0;
|
|
200
|
+
}
|
|
201
|
+
const invalid = (reason) => {
|
|
202
|
+
console.error(`khala: ${reason}
|
|
203
|
+
${WATCH_USAGE}`);
|
|
204
|
+
return 1;
|
|
205
|
+
};
|
|
206
|
+
if (argv.length !== 0 && !(argv.length === 2 && argv[0] === "--session") && !(argv.length === 4 && argv[0] === "--harness" && argv[2] === "--session")) return invalid("invalid_arguments");
|
|
207
|
+
const harness = resolveHarness(argv, process.env);
|
|
208
|
+
if (harness === "invalid") return invalid("invalid_harness");
|
|
209
|
+
const index = argv.indexOf("--session");
|
|
210
|
+
const id = index === -1 ? resolveSessionId(harness, void 0, process.env) : argv[index + 1];
|
|
211
|
+
if (!id) return invalid("session_unknown");
|
|
212
|
+
if (!SESSION_ID_PATTERN.test(id)) return invalid("invalid_session_id");
|
|
213
|
+
const files = sessionFiles(harness, id, process.env);
|
|
214
|
+
const controller = new AbortController();
|
|
215
|
+
const stop = () => controller.abort();
|
|
216
|
+
process.once("SIGTERM", stop);
|
|
217
|
+
process.once("SIGINT", stop);
|
|
218
|
+
try {
|
|
219
|
+
return await watchSession(files, { write: (line) => {
|
|
220
|
+
process.stdout.write(line);
|
|
221
|
+
}, signal: controller.signal });
|
|
222
|
+
} finally {
|
|
223
|
+
process.removeListener("SIGTERM", stop);
|
|
224
|
+
process.removeListener("SIGINT", stop);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export {
|
|
229
|
+
resolveHarness,
|
|
230
|
+
resolveSessionId,
|
|
231
|
+
monitorArmed,
|
|
232
|
+
mentions,
|
|
233
|
+
watchSession,
|
|
234
|
+
WATCH_USAGE,
|
|
235
|
+
run
|
|
236
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
decodeWith,
|
|
4
|
+
literal,
|
|
5
|
+
object,
|
|
6
|
+
readMatrixUserId,
|
|
7
|
+
version
|
|
8
|
+
} from "./chunk-SN3STAO2.mjs";
|
|
9
|
+
|
|
10
|
+
// ../contracts/src/delivery/decode.ts
|
|
11
|
+
var MAX_IDENTIFIER_BYTES = 512;
|
|
12
|
+
var DecodeFailure = class extends Error {
|
|
13
|
+
code;
|
|
14
|
+
field;
|
|
15
|
+
constructor(field, code) {
|
|
16
|
+
super(`${field || "<root>"}: ${code}`);
|
|
17
|
+
this.name = "DecodeFailure";
|
|
18
|
+
this.code = code;
|
|
19
|
+
this.field = field;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
function fail(field, code) {
|
|
23
|
+
throw new DecodeFailure(field, code);
|
|
24
|
+
}
|
|
25
|
+
function decodeWith2(read) {
|
|
26
|
+
try {
|
|
27
|
+
return { ok: true, value: read() };
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (error instanceof DecodeFailure) return { ok: false, code: error.code, field: error.field };
|
|
30
|
+
return { ok: false, code: "invalid_field", field: "" };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function utf8Length(value) {
|
|
34
|
+
let bytes = 0;
|
|
35
|
+
for (const character of value) {
|
|
36
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
37
|
+
if (codePoint < 128) bytes += 1;
|
|
38
|
+
else if (codePoint < 2048) bytes += 2;
|
|
39
|
+
else if (codePoint < 65536) bytes += 3;
|
|
40
|
+
else bytes += 4;
|
|
41
|
+
}
|
|
42
|
+
return bytes;
|
|
43
|
+
}
|
|
44
|
+
function isWellFormed(value) {
|
|
45
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
46
|
+
const unit = value.charCodeAt(index);
|
|
47
|
+
if (unit >= 55296 && unit <= 56319) {
|
|
48
|
+
const next = value.charCodeAt(index + 1);
|
|
49
|
+
if (!(next >= 56320 && next <= 57343)) return false;
|
|
50
|
+
index += 1;
|
|
51
|
+
} else if (unit >= 56320 && unit <= 57343) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
var CONTROL = /[\u0000-\u001f\u007f-\u009f]/;
|
|
58
|
+
function identifier(input, field) {
|
|
59
|
+
if (typeof input !== "string") fail(field, "invalid_field");
|
|
60
|
+
if (!isWellFormed(input) || input.length === 0 || CONTROL.test(input)) fail(field, "invalid_field");
|
|
61
|
+
if (utf8Length(input) > MAX_IDENTIFIER_BYTES) fail(field, "limit_exceeded");
|
|
62
|
+
return input;
|
|
63
|
+
}
|
|
64
|
+
function literal2(input, field, allowed) {
|
|
65
|
+
if (!allowed.includes(input)) fail(field, "invalid_field");
|
|
66
|
+
return input;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ../contracts/src/delivery/ids.ts
|
|
70
|
+
function readId(input, field) {
|
|
71
|
+
return identifier(input, field);
|
|
72
|
+
}
|
|
73
|
+
var idDecoder = () => (input) => decodeWith2(() => readId(input, ""));
|
|
74
|
+
var decodeOwnerId = idDecoder();
|
|
75
|
+
var decodeParticipantId = idDecoder();
|
|
76
|
+
var decodeDeviceId = idDecoder();
|
|
77
|
+
var decodeBindingId = idDecoder();
|
|
78
|
+
var decodeRoomId = idDecoder();
|
|
79
|
+
var decodeEventId = idDecoder();
|
|
80
|
+
var decodeCommandId = idDecoder();
|
|
81
|
+
var decodeReleaseId = idDecoder();
|
|
82
|
+
var decodeReceiptId = idDecoder();
|
|
83
|
+
var decodeAuthorizationId = idDecoder();
|
|
84
|
+
var decodeOperationId = idDecoder();
|
|
85
|
+
var decodeCausalRootId = idDecoder();
|
|
86
|
+
|
|
87
|
+
// ../contracts/src/delivery/listening-mode.ts
|
|
88
|
+
var LISTENING_MODES = ["steer", "sync", "async"];
|
|
89
|
+
function decodeListeningMode(input) {
|
|
90
|
+
return decodeWith2(() => literal2(input, "", LISTENING_MODES));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ../contracts/src/m1/listening-mode.ts
|
|
94
|
+
var LISTENING_MODE_COMMAND_TYPE = "com.khala.listening_mode.v1";
|
|
95
|
+
var LISTENING_MODE_MEMBER_KEY = "com.khala.listening_mode";
|
|
96
|
+
var DEFAULT_LISTENING_MODE = "sync";
|
|
97
|
+
function decodeListeningModeCommand(input) {
|
|
98
|
+
return decodeWith(() => {
|
|
99
|
+
const r = object(input, "", ["v", "agent", "mode"]);
|
|
100
|
+
return {
|
|
101
|
+
v: version(r.field("v"), r.at("v")),
|
|
102
|
+
agent: readMatrixUserId(r.field("agent"), r.at("agent")),
|
|
103
|
+
mode: literal(r.field("mode"), r.at("mode"), LISTENING_MODES)
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function memberListeningMode(content) {
|
|
108
|
+
const value = typeof content === "object" && content !== null ? content[LISTENING_MODE_MEMBER_KEY] : void 0;
|
|
109
|
+
const decoded = decodeListeningMode(value);
|
|
110
|
+
return decoded.ok ? decoded.value : DEFAULT_LISTENING_MODE;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export {
|
|
114
|
+
LISTENING_MODES,
|
|
115
|
+
decodeListeningMode,
|
|
116
|
+
LISTENING_MODE_COMMAND_TYPE,
|
|
117
|
+
LISTENING_MODE_MEMBER_KEY,
|
|
118
|
+
DEFAULT_LISTENING_MODE,
|
|
119
|
+
decodeListeningModeCommand,
|
|
120
|
+
memberListeningMode
|
|
121
|
+
};
|