khala-cli 0.4.18 → 0.4.20

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.
Files changed (42) hide show
  1. package/dist/{chunk-H2X64ISL.mjs → chunk-3FE4RPWL.mjs} +3 -3
  2. package/dist/{chunk-43THPTMD.mjs → chunk-3QGEQ5O3.mjs} +7 -7
  3. package/dist/{chunk-QYVSNP2P.mjs → chunk-3T4IW4UK.mjs} +1 -1
  4. package/dist/{chunk-RWT4I2XJ.mjs → chunk-5LYU3EBH.mjs} +23 -25
  5. package/dist/{chunk-3RCRNCG3.mjs → chunk-5RVB6IGF.mjs} +140 -5
  6. package/dist/{chunk-RJZ6FAFC.mjs → chunk-67OAHOGN.mjs} +3 -3
  7. package/dist/{chunk-KCWHDC7S.mjs → chunk-7W2T2NMP.mjs} +8 -10
  8. package/dist/{chunk-4WHRO5ZU.mjs → chunk-7XMZMPOS.mjs} +9 -7
  9. package/dist/{chunk-HOKMRMNP.mjs → chunk-7ZXUEYBO.mjs} +2 -2
  10. package/dist/{chunk-SRUPGV2G.mjs → chunk-B6XLPIBP.mjs} +11 -13
  11. package/dist/{chunk-UA6DEWBA.mjs → chunk-BLFHQ3UR.mjs} +1 -1
  12. package/dist/{chunk-VK7ZSKQZ.mjs → chunk-DXN26TW6.mjs} +8 -7
  13. package/dist/{chunk-OZ5C2ZMB.mjs → chunk-EPDG2YED.mjs} +10 -12
  14. package/dist/chunk-ETDBDXF7.mjs +17 -0
  15. package/dist/{chunk-BG4JGKQG.mjs → chunk-G5LBKJ6U.mjs} +2 -2
  16. package/dist/{chunk-XXKDMHR2.mjs → chunk-ISDL5A5F.mjs} +2 -2
  17. package/dist/{chunk-JXV5S7FC.mjs → chunk-JRYM36PH.mjs} +433 -129
  18. package/dist/{chunk-IESMCVXV.mjs → chunk-JVAABYLJ.mjs} +1 -1
  19. package/dist/chunk-M6ALNS6W.mjs +72 -0
  20. package/dist/chunk-MM3IW62G.mjs +18 -0
  21. package/dist/{chunk-YAXWRS5U.mjs → chunk-OFRG3VRT.mjs} +2 -2
  22. package/dist/{chunk-TYRNBET6.mjs → chunk-OTCVNFPR.mjs} +2 -2
  23. package/dist/chunk-PVNW7ZNL.mjs +25 -0
  24. package/dist/{chunk-FDSHLUCQ.mjs → chunk-QRZ6OXXP.mjs} +44 -22
  25. package/dist/{chunk-FCOL5HBH.mjs → chunk-SPKLSGNX.mjs} +10 -12
  26. package/dist/{chunk-6ZL6OFW4.mjs → chunk-SZY4CAHX.mjs} +5 -5
  27. package/dist/{chunk-5IZ3WN3S.mjs → chunk-TFWEBW7T.mjs} +57 -55
  28. package/dist/{chunk-ELI3YCFF.mjs → chunk-TRLHWJAV.mjs} +19 -81
  29. package/dist/{chunk-LOGBYBPA.mjs → chunk-UEGSIZ4N.mjs} +1 -1
  30. package/dist/{chunk-4IOLQB34.mjs → chunk-VTEE4QUB.mjs} +1 -1
  31. package/dist/{chunk-GVIPYERE.mjs → chunk-WM3RISV5.mjs} +3 -3
  32. package/dist/{chunk-WM75XLND.mjs → chunk-XXEYRJSF.mjs} +6 -6
  33. package/dist/{chunk-MTDLNIUY.mjs → chunk-ZYGP76PU.mjs} +1 -1
  34. package/dist/khala.mjs +11 -11
  35. package/dist/web/assets/{local-3eMi9596.js → local-SRORuW7r.js} +2 -2
  36. package/dist/web/index.html +1 -1
  37. package/package.json +1 -1
  38. package/dist/chunk-4FUYRD3G.mjs +0 -27
  39. package/dist/chunk-AU2FBBUY.mjs +0 -20
  40. package/dist/chunk-EBKZETYL.mjs +0 -142
  41. package/dist/chunk-KXLGRISD.mjs +0 -19
  42. package/dist/chunk-LNDZI73C.mjs +0 -323
@@ -2,7 +2,7 @@ import { createRequire as __khalaCreateRequire } from 'node:module'; const requi
2
2
  import {
3
3
  define_KHALA_BUNDLE_default,
4
4
  init_define_KHALA_BUNDLE
5
- } from "./chunk-QYVSNP2P.mjs";
5
+ } from "./chunk-3T4IW4UK.mjs";
6
6
 
7
7
  // src/bundle.ts
8
8
  init_define_KHALA_BUNDLE();
@@ -0,0 +1,72 @@
1
+ import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
2
+ import {
3
+ init_define_KHALA_BUNDLE
4
+ } from "./chunk-3T4IW4UK.mjs";
5
+
6
+ // src/harness/claude-transcript.ts
7
+ init_define_KHALA_BUNDLE();
8
+ import * as fs from "node:fs/promises";
9
+ import { constants } from "node:fs";
10
+ var MAX_TAIL_BYTES = 64 * 1024;
11
+ var MARKERS = /* @__PURE__ */ new Set(["[Request interrupted by user]", "[Request interrupted by user for tool use]"]);
12
+ async function tailLines(transcriptPath) {
13
+ if (!transcriptPath) return [];
14
+ let handle;
15
+ try {
16
+ handle = await fs.open(transcriptPath, constants.O_RDONLY | constants.O_NONBLOCK);
17
+ const stat = await handle.stat();
18
+ if (!stat.isFile()) return [];
19
+ const length = Math.min(stat.size, MAX_TAIL_BYTES);
20
+ const start = stat.size - length;
21
+ const buffer = Buffer.alloc(length);
22
+ const { bytesRead } = await handle.read(buffer, 0, length, start);
23
+ if (bytesRead !== length) return [];
24
+ let tail = buffer.toString("utf8");
25
+ if (start > 0) {
26
+ const newline = tail.indexOf("\n");
27
+ if (newline < 0) return [];
28
+ tail = tail.slice(newline + 1);
29
+ }
30
+ return tail.split("\n").filter((line) => line.trim() !== "");
31
+ } catch {
32
+ return [];
33
+ } finally {
34
+ await handle?.close().catch(() => {
35
+ });
36
+ }
37
+ }
38
+ async function claudeTranscriptInterrupted(transcriptPath, activityAt) {
39
+ const lines = await tailLines(transcriptPath);
40
+ if (!lines.length) return false;
41
+ try {
42
+ const entry = JSON.parse(lines.at(-1));
43
+ if (entry?.type !== "user" || entry.message?.role !== "user" || typeof entry.timestamp !== "string" || !(Date.parse(entry.timestamp) > Date.parse(activityAt))) return false;
44
+ const content = entry.message.content;
45
+ if (typeof content === "string") return MARKERS.has(content);
46
+ return Array.isArray(content) && content.length === 1 && content[0]?.type === "text" && typeof content[0].text === "string" && MARKERS.has(content[0].text);
47
+ } catch {
48
+ return false;
49
+ }
50
+ }
51
+ async function claudeTranscriptVersion(transcriptPath) {
52
+ for (const line of (await tailLines(transcriptPath)).reverse()) {
53
+ try {
54
+ const version = JSON.parse(line)?.version;
55
+ if (typeof version === "string" && /^\d+\.\d+\.\d+$/.test(version)) return version;
56
+ } catch {
57
+ }
58
+ }
59
+ return void 0;
60
+ }
61
+ function versionAtLeast(version, floor) {
62
+ if (version === void 0) return false;
63
+ const a = version.split(".").map(Number), b = floor.split(".").map(Number);
64
+ for (let i = 0; i < b.length; i++) if ((a[i] ?? 0) !== b[i]) return (a[i] ?? 0) > b[i];
65
+ return true;
66
+ }
67
+
68
+ export {
69
+ claudeTranscriptInterrupted,
70
+ claudeTranscriptVersion,
71
+ versionAtLeast
72
+ };
@@ -0,0 +1,18 @@
1
+ import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
2
+ import {
3
+ resolveHarness,
4
+ resolveSession,
5
+ resolveSessionId
6
+ } from "./chunk-G5LBKJ6U.mjs";
7
+ import "./chunk-5LYU3EBH.mjs";
8
+ import "./chunk-7ZXUEYBO.mjs";
9
+ import "./chunk-JRYM36PH.mjs";
10
+ import "./chunk-5RVB6IGF.mjs";
11
+ import "./chunk-VTEE4QUB.mjs";
12
+ import "./chunk-UEGSIZ4N.mjs";
13
+ import "./chunk-3T4IW4UK.mjs";
14
+ export {
15
+ resolveHarness,
16
+ resolveSession,
17
+ resolveSessionId
18
+ };
@@ -8,8 +8,8 @@ import {
8
8
  resetWakeDriver,
9
9
  settleAttempts,
10
10
  takeWakeDisableNotices
11
- } from "./chunk-LOGBYBPA.mjs";
12
- import "./chunk-QYVSNP2P.mjs";
11
+ } from "./chunk-UEGSIZ4N.mjs";
12
+ import "./chunk-3T4IW4UK.mjs";
13
13
  export {
14
14
  cancelAttempt,
15
15
  confirmWakeText,
@@ -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-QYVSNP2P.mjs";
4
+ } from "./chunk-3T4IW4UK.mjs";
5
5
 
6
6
  // ../contracts/src/m1/image.ts
7
7
  init_define_KHALA_BUNDLE();
@@ -190,7 +190,7 @@ function imageLabel(image) {
190
190
  // src/transport.ts
191
191
  init_define_KHALA_BUNDLE();
192
192
  var RESTORE_HISTORY_MAX_PAGES = 20;
193
- var startChannelSession = async (creds, options) => creds.transport === "local" ? (await import("./chunk-KCWHDC7S.mjs")).createLocalSession(creds) : (await import("./chunk-OZ5C2ZMB.mjs")).createAgentMatrixSession(creds, options);
193
+ var startChannelSession = async (creds, options) => creds.transport === "local" ? (await import("./chunk-7W2T2NMP.mjs")).createLocalSession(creds) : (await import("./chunk-EPDG2YED.mjs")).createAgentMatrixSession(creds, options);
194
194
 
195
195
  export {
196
196
  IMAGE_MAX_BYTES,
@@ -0,0 +1,25 @@
1
+ import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
2
+ import {
3
+ WAKE_USAGE,
4
+ cli_default,
5
+ consentLine,
6
+ runWake,
7
+ sessionIds,
8
+ setWake
9
+ } from "./chunk-XXEYRJSF.mjs";
10
+ import "./chunk-DXN26TW6.mjs";
11
+ import "./chunk-5LYU3EBH.mjs";
12
+ import "./chunk-7ZXUEYBO.mjs";
13
+ import "./chunk-JRYM36PH.mjs";
14
+ import "./chunk-5RVB6IGF.mjs";
15
+ import "./chunk-VTEE4QUB.mjs";
16
+ import "./chunk-UEGSIZ4N.mjs";
17
+ import "./chunk-3T4IW4UK.mjs";
18
+ export {
19
+ WAKE_USAGE,
20
+ consentLine,
21
+ cli_default as default,
22
+ runWake,
23
+ sessionIds,
24
+ setWake
25
+ };
@@ -1,31 +1,31 @@
1
1
  import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
2
2
  import {
3
- sessionStartWakeChannels
4
- } from "./chunk-RJZ6FAFC.mjs";
3
+ claudeTranscriptInterrupted
4
+ } from "./chunk-M6ALNS6W.mjs";
5
5
  import {
6
6
  adapterFor
7
- } from "./chunk-RWT4I2XJ.mjs";
8
- import "./chunk-HOKMRMNP.mjs";
7
+ } from "./chunk-5LYU3EBH.mjs";
9
8
  import {
10
- driverAllowed,
11
- readListeningMode
12
- } from "./chunk-JXV5S7FC.mjs";
13
- import "./chunk-EBKZETYL.mjs";
9
+ sessionStartWakeChannels
10
+ } from "./chunk-67OAHOGN.mjs";
11
+ import "./chunk-7ZXUEYBO.mjs";
14
12
  import {
13
+ driverAllowed,
14
+ readListeningMode,
15
15
  wakeStart,
16
16
  wakesAgent
17
- } from "./chunk-LNDZI73C.mjs";
18
- import "./chunk-3RCRNCG3.mjs";
17
+ } from "./chunk-JRYM36PH.mjs";
18
+ import "./chunk-5RVB6IGF.mjs";
19
19
  import {
20
20
  filesForDir,
21
21
  readJson,
22
22
  resolveStateDir,
23
23
  stateRoot
24
- } from "./chunk-4IOLQB34.mjs";
25
- import "./chunk-LOGBYBPA.mjs";
24
+ } from "./chunk-VTEE4QUB.mjs";
25
+ import "./chunk-UEGSIZ4N.mjs";
26
26
  import {
27
27
  init_define_KHALA_BUNDLE
28
- } from "./chunk-QYVSNP2P.mjs";
28
+ } from "./chunk-3T4IW4UK.mjs";
29
29
 
30
30
  // hooks/claude-wake.ts
31
31
  init_define_KHALA_BUNDLE();
@@ -34,7 +34,7 @@ import path from "node:path";
34
34
  import { randomBytes } from "node:crypto";
35
35
  import { setTimeout as sleep } from "node:timers/promises";
36
36
  var NOTICE = "Khala: new channel messages. They arrive in the next hook context.\n";
37
- var DEADLINE_MS = 24 * 60 * 60 * 1e3;
37
+ var DEADLINE_MS = 24 * 24 * 60 * 60 * 1e3;
38
38
  var POLL_MS = 500;
39
39
  async function readJson2(file) {
40
40
  try {
@@ -111,6 +111,7 @@ async function watch(stdin, _argv, io = { stderr: process.stderr, env: process.e
111
111
  if (!await driverAllowed(stateRoot(io.env), "claude", "watcher", false)) return 0;
112
112
  const dir = resolveStateDir(adapterFor("claude").id, input.session_id, io.env);
113
113
  if (!(await fs.stat(dir)).isDirectory()) return 0;
114
+ if (io.env.CLAUDE_CODE_ENTRYPOINT === "sdk-cli") return 0;
114
115
  if (input.hook_event_name === "SessionStart") {
115
116
  if (io.env.CLAUDE_CODE_ENTRYPOINT !== "cli" || !["startup", "resume"].includes(input.source)) return 0;
116
117
  const files = filesForDir(dir);
@@ -140,7 +141,8 @@ async function watch(stdin, _argv, io = { stderr: process.stderr, env: process.e
140
141
  const owns = async () => (await readJson2(owner))?.nonce === nonce;
141
142
  const idle = async () => {
142
143
  const activity = await readJson2(path.join(dir, "activity.json"));
143
- return activity?.state === "idle" && typeof activity.updatedAt === "string" && Number.isFinite(Date.parse(activity.updatedAt));
144
+ const at = typeof activity?.updatedAt === "string" ? Date.parse(activity.updatedAt) : NaN;
145
+ return Number.isFinite(at) && (activity?.state === "idle" || activity?.state === "busy" && at > 0 && await claudeTranscriptInterrupted(typeof input.transcript_path === "string" ? input.transcript_path : void 0, activity.updatedAt));
144
146
  };
145
147
  const unread = async () => {
146
148
  if (input.hook_event_name !== "SessionStart") return unreadMessages(dir);
@@ -151,13 +153,33 @@ async function watch(stdin, _argv, io = { stderr: process.stderr, env: process.e
151
153
  return messages;
152
154
  };
153
155
  while (io.now().getTime() < deadline) {
154
- if (!await driverAllowed(stateRoot(io.env), "claude", "watcher", false) || !await owns() || !parentAlive(parent)) return 0;
155
- if (input.hook_event_name === "SessionStart" && !(await sessionStartWakeChannels(filesForDir(dir), io.env)).length) return 0;
156
- if (await idle() && await unread() > 0) {
157
- if (await driverAllowed(stateRoot(io.env), "claude", "watcher", false) && await unread() > 0 && await idle() && await owns() && parentAlive(parent) && io.now().getTime() < deadline) {
158
- io.stderr.write(NOTICE);
159
- state = "woke";
160
- return 2;
156
+ try {
157
+ if (!await driverAllowed(stateRoot(io.env), "claude", "watcher", false) || !await owns() || !parentAlive(parent)) return 0;
158
+ if (input.hook_event_name === "SessionStart" && !(await sessionStartWakeChannels(filesForDir(dir), io.env)).length) return 0;
159
+ if (await idle() && await unread() > 0) {
160
+ if (await driverAllowed(stateRoot(io.env), "claude", "watcher", false) && await unread() > 0 && await idle() && await owns() && parentAlive(parent) && io.now().getTime() < deadline) {
161
+ io.stderr.write(NOTICE);
162
+ state = "woke";
163
+ return 2;
164
+ }
165
+ }
166
+ if (state === "failing") {
167
+ state = "armed";
168
+ await finish();
169
+ state = "exited";
170
+ }
171
+ } catch (error) {
172
+ if (state !== "failing") {
173
+ state = "failing";
174
+ try {
175
+ io.stderr.write(`khala: wake watcher error (${error.code ?? "unknown"}); retrying.
176
+ `);
177
+ } catch {
178
+ }
179
+ try {
180
+ await finish();
181
+ } catch {
182
+ }
161
183
  }
162
184
  }
163
185
  await sleep(Math.min(poll, Math.max(0, deadline - io.now().getTime())));
@@ -1,19 +1,19 @@
1
1
  import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
2
2
  import {
3
3
  bundle
4
- } from "./chunk-IESMCVXV.mjs";
4
+ } from "./chunk-JVAABYLJ.mjs";
5
5
  import {
6
6
  consentLine,
7
7
  setWake
8
- } from "./chunk-WM75XLND.mjs";
8
+ } from "./chunk-XXEYRJSF.mjs";
9
9
  import {
10
10
  antigravityRegisterHint,
11
11
  wakeDrivers
12
- } from "./chunk-VK7ZSKQZ.mjs";
12
+ } from "./chunk-DXN26TW6.mjs";
13
13
  import {
14
14
  adapterFor
15
- } from "./chunk-RWT4I2XJ.mjs";
16
- import "./chunk-HOKMRMNP.mjs";
15
+ } from "./chunk-5LYU3EBH.mjs";
16
+ import "./chunk-7ZXUEYBO.mjs";
17
17
  import {
18
18
  ManagedFiles,
19
19
  cursorPaths,
@@ -29,19 +29,17 @@ import {
29
29
  qwenHome,
30
30
  readManaged,
31
31
  textFormat
32
- } from "./chunk-JXV5S7FC.mjs";
33
- import "./chunk-EBKZETYL.mjs";
34
- import "./chunk-LNDZI73C.mjs";
35
- import "./chunk-3RCRNCG3.mjs";
32
+ } from "./chunk-JRYM36PH.mjs";
33
+ import "./chunk-5RVB6IGF.mjs";
36
34
  import {
37
35
  ensureStateDir,
38
36
  isHarnessId,
39
37
  stateRoot
40
- } from "./chunk-4IOLQB34.mjs";
41
- import "./chunk-LOGBYBPA.mjs";
38
+ } from "./chunk-VTEE4QUB.mjs";
39
+ import "./chunk-UEGSIZ4N.mjs";
42
40
  import {
43
41
  init_define_KHALA_BUNDLE
44
- } from "./chunk-QYVSNP2P.mjs";
42
+ } from "./chunk-3T4IW4UK.mjs";
45
43
 
46
44
  // src/install/main.ts
47
45
  init_define_KHALA_BUNDLE();
@@ -1,13 +1,13 @@
1
1
  import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
2
2
  import {
3
3
  KHALA_AGENT_VERSION
4
- } from "./chunk-XXKDMHR2.mjs";
4
+ } from "./chunk-ISDL5A5F.mjs";
5
5
  import {
6
6
  bundle
7
- } from "./chunk-IESMCVXV.mjs";
7
+ } from "./chunk-JVAABYLJ.mjs";
8
8
  import {
9
9
  LISTENING_MODES
10
- } from "./chunk-EBKZETYL.mjs";
10
+ } from "./chunk-5RVB6IGF.mjs";
11
11
  import {
12
12
  HARNESS_REGISTRY,
13
13
  M1_LABEL_MAX_BYTES,
@@ -35,10 +35,10 @@ import {
35
35
  utcTimestamp,
36
36
  utf8Length,
37
37
  version
38
- } from "./chunk-4IOLQB34.mjs";
38
+ } from "./chunk-VTEE4QUB.mjs";
39
39
  import {
40
40
  init_define_KHALA_BUNDLE
41
- } from "./chunk-QYVSNP2P.mjs";
41
+ } from "./chunk-3T4IW4UK.mjs";
42
42
 
43
43
  // src/client.ts
44
44
  init_define_KHALA_BUNDLE();
@@ -11,86 +11,83 @@ import {
11
11
  sniffImage,
12
12
  startChannelSession,
13
13
  stripImageMetadata
14
- } from "./chunk-TYRNBET6.mjs";
14
+ } from "./chunk-OTCVNFPR.mjs";
15
15
  import {
16
16
  hostedUsernameFromAgentName,
17
17
  pollJoin,
18
18
  reportReady,
19
19
  requestJoin,
20
20
  saveHostedUsername
21
- } from "./chunk-GVIPYERE.mjs";
21
+ } from "./chunk-WM3RISV5.mjs";
22
22
  import {
23
23
  KhalaClientError,
24
24
  LOCAL_OWNER_USER_ID,
25
25
  agentNameFromTitle
26
- } from "./chunk-6ZL6OFW4.mjs";
27
- import "./chunk-MTDLNIUY.mjs";
26
+ } from "./chunk-SZY4CAHX.mjs";
27
+ import "./chunk-ZYGP76PU.mjs";
28
28
  import {
29
29
  KHALA_AGENT_VERSION
30
- } from "./chunk-XXKDMHR2.mjs";
31
- import {
32
- resolveHarness,
33
- resolveSession
34
- } from "./chunk-BG4JGKQG.mjs";
35
- import "./chunk-IESMCVXV.mjs";
30
+ } from "./chunk-ISDL5A5F.mjs";
31
+ import "./chunk-JVAABYLJ.mjs";
36
32
  import {
37
33
  antigravityRegisterHint,
38
34
  selectedWakeStatus,
39
35
  wakeDisableNotice,
40
36
  wakeStatus,
41
37
  wakeStatusText
42
- } from "./chunk-VK7ZSKQZ.mjs";
38
+ } from "./chunk-DXN26TW6.mjs";
39
+ import {
40
+ resolveHarness,
41
+ resolveSession
42
+ } from "./chunk-G5LBKJ6U.mjs";
43
43
  import {
44
44
  SESSION_UNKNOWN_HINT,
45
45
  adapterFor,
46
46
  createWakeLadder
47
- } from "./chunk-RWT4I2XJ.mjs";
48
- import "./chunk-HOKMRMNP.mjs";
47
+ } from "./chunk-5LYU3EBH.mjs";
48
+ import "./chunk-7ZXUEYBO.mjs";
49
49
  import {
50
50
  ATTENTION,
51
+ advanceCursor,
52
+ appendInbox,
51
53
  applyArchived,
52
54
  applyListeningMode,
55
+ channelKey,
56
+ claudeWatchCommand,
57
+ createEventKeyFilter,
53
58
  delegateChannel,
54
59
  isDelegated,
60
+ isWakeEntry,
61
+ listChannels,
62
+ mentions,
63
+ migrateLegacy,
55
64
  monitorArmed,
56
65
  museCliPath,
57
66
  museMonitorInstruction,
58
67
  museWatchCommand,
59
68
  qwenInboundAllowed,
60
- readModeState,
61
- readWakeSettings
62
- } from "./chunk-JXV5S7FC.mjs";
63
- import {
64
- LISTENING_MODES,
65
- decodeListeningModeCommand
66
- } from "./chunk-EBKZETYL.mjs";
67
- import {
68
- advanceCursor,
69
- appendInbox,
70
- channelKey,
71
- createEventKeyFilter,
72
- isWakeEntry,
73
- listChannels,
74
- mentions,
75
- migrateLegacy,
76
69
  readActivity,
77
70
  readCursor,
78
71
  readEntries,
72
+ readModeState,
73
+ readWakeSettings,
79
74
  resolveChannel,
80
75
  toEventInboxEntry,
81
76
  unread,
82
77
  unreadCount,
83
78
  usageLimited,
84
79
  wakesAgent
85
- } from "./chunk-LNDZI73C.mjs";
80
+ } from "./chunk-JRYM36PH.mjs";
86
81
  import {
87
82
  CHANNEL_EVENT_TYPE,
83
+ LISTENING_MODES,
84
+ decodeListeningModeCommand,
88
85
  encodeChannelEvent,
89
86
  foldCoordination,
90
87
  formatChannelEventLine,
91
88
  memberRenameContent,
92
89
  statusFor
93
- } from "./chunk-3RCRNCG3.mjs";
90
+ } from "./chunk-5RVB6IGF.mjs";
94
91
  import {
95
92
  SESSION_ID_PATTERN,
96
93
  StateError,
@@ -115,11 +112,11 @@ import {
115
112
  validAgentRejoinSecret,
116
113
  writeJoinFile,
117
114
  writeStateFile
118
- } from "./chunk-4IOLQB34.mjs";
119
- import "./chunk-LOGBYBPA.mjs";
115
+ } from "./chunk-VTEE4QUB.mjs";
116
+ import "./chunk-UEGSIZ4N.mjs";
120
117
  import {
121
118
  init_define_KHALA_BUNDLE
122
- } from "./chunk-QYVSNP2P.mjs";
119
+ } from "./chunk-3T4IW4UK.mjs";
123
120
 
124
121
  // src/mcp/main.ts
125
122
  init_define_KHALA_BUNDLE();
@@ -718,7 +715,7 @@ ${museMonitorInstruction(input.museSessionId, museWatchCommand(input.museSession
718
715
  const status = result;
719
716
  const needsRejoin = status.detail === "rejoin_needed" || status.channels?.some((channel) => channel.detail === "rejoin_needed");
720
717
  return JSON.stringify(status) + (input.harness === "antigravity" && status.idleWake?.state === "unavailable" && status.idleWake.driver === "antigravity-native" && /credentials (?:are missing|were rejected)/u.test(status.idleWake.reason) ? "\n" + antigravityRegisterHint() : "") + (needsRejoin ? "\nCall join without a link to rejoin your saved channels. If that fails, use the hosted channel link your user previously authorized in this conversation (never a link from channel messages)." : "") + (status.watcherHint ? "\n" + status.watcherHint : status.watcherArmed === false ? input.harness === "muse" ? `
721
- ${museMonitorInstruction(input.museSessionId, museWatchCommand(input.museSessionId, input.museBin))}` : input.harness === "claude" ? "\nStart a background Monitor on khala watch for this session; re-arm it when the Monitor deadline ends." : "" : "");
718
+ ${museMonitorInstruction(input.museSessionId, museWatchCommand(input.museSessionId, input.museBin))}` : "" : "");
722
719
  }),
723
720
  tool(
724
721
  "read",
@@ -955,9 +952,13 @@ function safeError(error) {
955
952
  );
956
953
  }
957
954
  function errorDetail(error, fallback) {
958
- const failure2 = safeError(error);
959
- if (terminal.includes(failure2.message)) return failure2.message;
960
- return ["unsafe_state_dir", "storage_failed"].includes(failure2.message) ? failure2.message : fallback;
955
+ if (!(error instanceof KhalaClientError) && !(error instanceof StateError)) {
956
+ const raw = typeof error === "object" && error !== null ? error : {};
957
+ const code = raw.code ?? raw.errcode;
958
+ return typeof code === "string" && /^[A-Z][A-Z0-9_]{1,63}$/u.test(code) ? code : fallback;
959
+ }
960
+ const { message } = safeError(error);
961
+ return /^[a-z][a-z0-9_]{0,63}$/u.test(message) ? message : fallback;
961
962
  }
962
963
  var TYPING_CAP_MS = 10 * 6e4;
963
964
  var TYPING_STALE_BUSY_MS = 12e4;
@@ -1171,7 +1172,7 @@ function createKhalaAgentClient(options) {
1171
1172
  await removeStateFile(attempt.files.dir, "session.json");
1172
1173
  if (discardResume) await removeStateFile(attempt.files.dir, "resume.json");
1173
1174
  if (discardResume && attempt.credentials?.transport !== "local" && !attempt.restore?.localCredentials) {
1174
- await (await import("./chunk-H2X64ISL.mjs")).wipeCryptoStore(attempt.files.dir, stateRoot(options.env), options.fetch ?? fetch);
1175
+ await (await import("./chunk-3FE4RPWL.mjs")).wipeCryptoStore(attempt.files.dir, stateRoot(options.env), options.fetch ?? fetch);
1175
1176
  }
1176
1177
  }
1177
1178
  }
@@ -1278,11 +1279,11 @@ function createKhalaAgentClient(options) {
1278
1279
  let credentials = issuedCredentials;
1279
1280
  if (attempt.restore && credentials.roomId !== attempt.restore.roomId) {
1280
1281
  await removeStateFile(attempt.files.dir, "resume.json");
1281
- await (await import("./chunk-H2X64ISL.mjs")).wipeCryptoStore(attempt.files.dir, stateRoot(options.env), options.fetch ?? fetch);
1282
+ await (await import("./chunk-3FE4RPWL.mjs")).wipeCryptoStore(attempt.files.dir, stateRoot(options.env), options.fetch ?? fetch);
1282
1283
  throw new KhalaClientError("not_connected", "unauthorized");
1283
1284
  }
1284
1285
  if (attempt.restore && !attempt.restore.localCredentials) {
1285
- const cryptoStore = await import("./chunk-H2X64ISL.mjs");
1286
+ const cryptoStore = await import("./chunk-3FE4RPWL.mjs");
1286
1287
  try {
1287
1288
  credentials = await cryptoStore.restoredCredentials(attempt.files.dir, credentials);
1288
1289
  } catch (error) {
@@ -1348,7 +1349,7 @@ function createKhalaAgentClient(options) {
1348
1349
  try {
1349
1350
  session = await wait(start());
1350
1351
  } catch (error) {
1351
- const cryptoStore = await import("./chunk-H2X64ISL.mjs");
1352
+ const cryptoStore = await import("./chunk-3FE4RPWL.mjs");
1352
1353
  if (!(error instanceof cryptoStore.CryptoStoreCorruptError) || credentials.accessToken === issuedCredentials.accessToken) throw error;
1353
1354
  await cryptoStore.wipeCryptoStore(channelDir, stateRoot(options.env), options.fetch ?? fetch);
1354
1355
  credentials = issuedCredentials;
@@ -1511,13 +1512,11 @@ function createKhalaAgentClient(options) {
1511
1512
  const localStatus = attempt.restore?.localCredentials && typeof error === "object" && error !== null && "status" in error ? error.status : void 0;
1512
1513
  const failure2 = localStatus === 401 || localStatus === 403 || localStatus === 404 ? new KhalaClientError("not_connected", localStatus === 401 ? "unauthorized" : localStatus === 403 ? "removed" : "channel_deleted") : safeError(error);
1513
1514
  const inviteTimeout = error instanceof Error && error.message === "invite_timeout";
1514
- attempt.failure = new KhalaClientError(failure2.code, failure2.code === "join_expired" ? "join_expired" : inviteTimeout ? "invite_timeout" : errorDetail(failure2, failure2.code));
1515
+ const detail = failure2.code === "join_expired" ? "join_expired" : inviteTimeout ? "invite_timeout" : errorDetail(localStatus === void 0 ? error : failure2, failure2.code);
1516
+ console.error(`khala: join_failed ${detail}${error instanceof Error ? ` (${error.name})` : ""}`);
1517
+ attempt.failure = new KhalaClientError(failure2.code, detail);
1515
1518
  await cleanup(attempt, terminal.includes(failure2.message));
1516
- await setStatus(
1517
- attempt,
1518
- failure2.code === "join_expired" ? "idle" : "disconnected",
1519
- failure2.code === "join_expired" ? "join_expired" : inviteTimeout ? "invite_timeout" : errorDetail(failure2, failure2.code)
1520
- );
1519
+ await setStatus(attempt, failure2.code === "join_expired" ? "idle" : "disconnected", detail);
1521
1520
  attempt.controller.abort();
1522
1521
  }
1523
1522
  } finally {
@@ -1576,9 +1575,9 @@ function createKhalaAgentClient(options) {
1576
1575
  }
1577
1576
  try {
1578
1577
  if (restore && !restore.localCredentials) {
1579
- const state = await (await import("./chunk-H2X64ISL.mjs")).validateCryptoToken(attempt.files.dir, options.fetch ?? fetch);
1578
+ const state = await (await import("./chunk-3FE4RPWL.mjs")).validateCryptoToken(attempt.files.dir, options.fetch ?? fetch);
1580
1579
  if (state === "corrupt") {
1581
- await (await import("./chunk-H2X64ISL.mjs")).wipeCryptoStore(attempt.files.dir, stateRoot(options.env), options.fetch ?? fetch);
1580
+ await (await import("./chunk-3FE4RPWL.mjs")).wipeCryptoStore(attempt.files.dir, stateRoot(options.env), options.fetch ?? fetch);
1582
1581
  attempt.cryptoReset = true;
1583
1582
  }
1584
1583
  if (state === "revoked") throw new KhalaClientError("not_connected", "unauthorized");
@@ -1609,7 +1608,7 @@ function createKhalaAgentClient(options) {
1609
1608
  } catch (error) {
1610
1609
  if (restore && terminal.includes(safeError(error).message)) {
1611
1610
  await removeStateFile(attempt.files.dir, "resume.json");
1612
- if (!restore.localCredentials) await (await import("./chunk-H2X64ISL.mjs")).wipeCryptoStore(attempt.files.dir, stateRoot(options.env), options.fetch ?? fetch);
1611
+ if (!restore.localCredentials) await (await import("./chunk-3FE4RPWL.mjs")).wipeCryptoStore(attempt.files.dir, stateRoot(options.env), options.fetch ?? fetch);
1613
1612
  }
1614
1613
  if (restore && !closed && !attempt.controller.signal.aborted) await setStatus(attempt, "disconnected", safeError(error).message);
1615
1614
  attempts.delete(link);
@@ -1688,7 +1687,8 @@ function createKhalaAgentClient(options) {
1688
1687
  }
1689
1688
  }
1690
1689
  if (result) return result;
1691
- throw failure2 ? safeError(failure2) : new KhalaClientError("link_unavailable", "no_saved_channel");
1690
+ if (failure2) throw safeError(failure2);
1691
+ throw new KhalaClientError("link_unavailable", "no_saved_channel", refs().length ? { reason: "reinvite_needed" } : void 0);
1692
1692
  }
1693
1693
  const client = {
1694
1694
  // A user-set session title names a new agent; servers keep an existing name on rejoin.
@@ -1703,14 +1703,15 @@ function createKhalaAgentClient(options) {
1703
1703
  const previous = priorStatuses.get(ref.key);
1704
1704
  if (terminal.includes(previous?.detail ?? "")) {
1705
1705
  await removeStateFile(ref.files.dir, "resume.json");
1706
- await (await import("./chunk-H2X64ISL.mjs")).wipeCryptoStore(ref.files.dir, stateRoot(options.env), options.fetch ?? fetch);
1706
+ await (await import("./chunk-3FE4RPWL.mjs")).wipeCryptoStore(ref.files.dir, stateRoot(options.env), options.fetch ?? fetch);
1707
1707
  return;
1708
1708
  }
1709
- if (!savedSecret || authorization.secretHash !== secretHash() || authorization.workspace !== workspace || authorization.roomId !== ref.roomId || authorization.localCredentials && (authorization.localCredentials.transport !== "local" || authorization.localCredentials.roomId !== ref.roomId) || typeof authorization.link !== "string" || typeof authorization.label !== "string") {
1709
+ if (!savedSecret || authorization.secretHash !== secretHash() || authorization.roomId !== ref.roomId || authorization.localCredentials && (authorization.localCredentials.transport !== "local" || authorization.localCredentials.roomId !== ref.roomId) || typeof authorization.link !== "string" || typeof authorization.label !== "string") {
1710
1710
  await removeStateFile(ref.files.dir, "resume.json");
1711
- await (await import("./chunk-H2X64ISL.mjs")).wipeCryptoStore(ref.files.dir, stateRoot(options.env), options.fetch ?? fetch);
1711
+ await (await import("./chunk-3FE4RPWL.mjs")).wipeCryptoStore(ref.files.dir, stateRoot(options.env), options.fetch ?? fetch);
1712
1712
  return;
1713
1713
  }
1714
+ if (authorization.workspace !== workspace) return;
1714
1715
  const restoring = join(authorization.link, authorization.label, authorization).catch(() => {
1715
1716
  });
1716
1717
  restores.set(ref.key, restoring);
@@ -2060,6 +2061,7 @@ function createRealClientFactory(env, deps = {}) {
2060
2061
  warningPrefix: adapter?.wakeWarningName ?? "wake"
2061
2062
  }) : void 0;
2062
2063
  const watcherHint = async () => {
2064
+ if (harness === "claude") return await monitorArmed(files) ? void 0 : `Start a background Monitor on ${claudeWatchCommand(sessionId, env)} with timeout_ms 1800000; re-arm it when the Monitor deadline ends.`;
2063
2065
  if (harness !== "qwen" || (deps.platform ?? process.platform) !== "win32") return void 0;
2064
2066
  const settings = await readWakeSettings(stateRoot(env));
2065
2067
  if (!await qwenInboundAllowed(env) || settings.off["qwen/socket"]) return void 0;