khala-cli 0.4.9 → 0.4.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/THIRD_PARTY_NOTICES.txt +28 -0
  2. package/dist/{chunk-NIX5F4LT.mjs → chunk-2AMWQ7RB.mjs} +330 -66
  3. package/dist/{chunk-PAJ4JJPV.mjs → chunk-3E5DH3Y6.mjs} +43 -6
  4. package/dist/{chunk-NGSYOVQ4.mjs → chunk-4BP7V3OP.mjs} +2 -2
  5. package/dist/{chunk-TEFOQXBK.mjs → chunk-4BZQ4GVW.mjs} +3 -3
  6. package/dist/{chunk-ITFD3JZS.mjs → chunk-5JSGA6OB.mjs} +424 -78
  7. package/dist/{chunk-QKWEZXR3.mjs → chunk-6AQVW5W7.mjs} +12 -4
  8. package/dist/{chunk-UK5GJO4Y.mjs → chunk-6J2PUM7L.mjs} +6 -5
  9. package/dist/{chunk-P3YIN7G7.mjs → chunk-6SUV3EW6.mjs} +11 -10
  10. package/dist/{chunk-GSZADJMW.mjs → chunk-ARIDZOTI.mjs} +309 -81
  11. package/dist/chunk-C2WEDMAF.mjs +15 -0
  12. package/dist/{chunk-DJM23SIU.mjs → chunk-CHC4VZF5.mjs} +7 -8
  13. package/dist/{chunk-BLCRVRIK.mjs → chunk-CKLCR5G4.mjs} +456 -87
  14. package/dist/{chunk-7R3EIDGR.mjs → chunk-EVT2DWNZ.mjs} +1 -1
  15. package/dist/{chunk-KMLXOPBQ.mjs → chunk-FJVVSKZ3.mjs} +4 -2
  16. package/dist/{chunk-3KDOTR54.mjs → chunk-G3NMB4PY.mjs} +1 -1
  17. package/dist/{chunk-SSO5RFOX.mjs → chunk-HHEZVPRR.mjs} +1 -1
  18. package/dist/{chunk-BV45NK7K.mjs → chunk-JKOJQTFT.mjs} +100 -6
  19. package/dist/{chunk-T7IL7V7Q.mjs → chunk-NDMFD5IM.mjs} +13 -10
  20. package/dist/{chunk-TANCKTDK.mjs → chunk-OEV5DFLW.mjs} +70 -5
  21. package/dist/{chunk-BEO7WIIM.mjs → chunk-OIZ4R5H7.mjs} +28 -8
  22. package/dist/{chunk-FZEH2IXZ.mjs → chunk-PJKI7SRI.mjs} +176 -26
  23. package/dist/{chunk-NPSQNCOY.mjs → chunk-PN25BUQ4.mjs} +13 -4
  24. package/dist/{chunk-3R6HFSLL.mjs → chunk-QDPJ4VT2.mjs} +92 -38
  25. package/dist/{chunk-FO5GXCST.mjs → chunk-SRZTHCXP.mjs} +5 -5
  26. package/dist/{chunk-LBT47HLZ.mjs → chunk-TSK3HJEG.mjs} +10 -9
  27. package/dist/{chunk-6BO3JSUP.mjs → chunk-UX34IVN5.mjs} +2 -2
  28. package/dist/{chunk-V4F3SYKW.mjs → chunk-VAC3JTAV.mjs} +25 -17
  29. package/dist/{chunk-PDZ5Z5ZE.mjs → chunk-VDZK4LW3.mjs} +24 -9
  30. package/dist/chunk-W6HM6F2U.mjs +901 -0
  31. package/dist/{chunk-WDOHRV3D.mjs → chunk-WPNMWNCL.mjs} +14 -14
  32. package/dist/chunk-WUDXHF2Q.mjs +14 -0
  33. package/dist/{chunk-XBQDIKB5.mjs → chunk-WZJ6DQJV.mjs} +9 -8
  34. package/dist/{chunk-ANSR4IAW.mjs → chunk-XR625T3I.mjs} +2 -2
  35. package/dist/{chunk-K7V7X6WU.mjs → chunk-ZSKLNZWZ.mjs} +21 -4
  36. package/dist/iterm2_send.py +56 -0
  37. package/dist/khala.mjs +11 -11
  38. package/dist/web/assets/local-CSPuGnH2.css +1 -0
  39. package/dist/web/assets/local-Dtyxaacx.js +9 -0
  40. package/dist/web/index.html +2 -2
  41. package/package.json +1 -1
  42. package/dist/chunk-47XNLAJG.mjs +0 -38
  43. package/dist/chunk-XUCWSYVS.mjs +0 -148
  44. package/dist/web/assets/local-CFzRHZpB.js +0 -9
  45. package/dist/web/assets/local-ciypUFoK.css +0 -1
@@ -45,7 +45,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
45
45
  var define_KHALA_BUNDLE_default;
46
46
  var init_define_KHALA_BUNDLE = __esm({
47
47
  "<define:__KHALA_BUNDLE__>"() {
48
- define_KHALA_BUNDLE_default = { name: "khala-cli", version: "0.4.9" };
48
+ define_KHALA_BUNDLE_default = { name: "khala-cli", version: "0.4.10" };
49
49
  }
50
50
  });
51
51
 
@@ -1,16 +1,18 @@
1
1
  import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
2
2
  import {
3
3
  cancelAttempt,
4
+ confirmWakeText,
4
5
  failAttempt,
5
6
  readWakeState,
6
7
  recordAttempt,
7
8
  resetWakeDriver,
8
9
  settleAttempts,
9
10
  takeWakeDisableNotices
10
- } from "./chunk-K7V7X6WU.mjs";
11
- import "./chunk-7R3EIDGR.mjs";
11
+ } from "./chunk-ZSKLNZWZ.mjs";
12
+ import "./chunk-EVT2DWNZ.mjs";
12
13
  export {
13
14
  cancelAttempt,
15
+ confirmWakeText,
14
16
  failAttempt,
15
17
  readWakeState,
16
18
  recordAttempt,
@@ -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-7R3EIDGR.mjs";
5
+ } from "./chunk-EVT2DWNZ.mjs";
6
6
 
7
7
  // src/bundle.ts
8
8
  init_define_KHALA_BUNDLE();
@@ -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-7R3EIDGR.mjs";
4
+ } from "./chunk-EVT2DWNZ.mjs";
5
5
 
6
6
  // src/events/member-rename.ts
7
7
  init_define_KHALA_BUNDLE();
@@ -5,20 +5,22 @@ import {
5
5
  fail,
6
6
  label,
7
7
  literal,
8
+ object,
8
9
  safeInteger,
9
10
  utcTimestamp,
10
11
  utf8Length,
11
12
  version
12
- } from "./chunk-NPSQNCOY.mjs";
13
+ } from "./chunk-PN25BUQ4.mjs";
13
14
  import {
14
15
  init_define_KHALA_BUNDLE
15
- } from "./chunk-7R3EIDGR.mjs";
16
+ } from "./chunk-EVT2DWNZ.mjs";
16
17
 
17
18
  // ../contracts/src/m1/channel-event.ts
18
19
  init_define_KHALA_BUNDLE();
19
20
  var CHANNEL_EVENT_TYPE = "com.khala.event.v1";
20
21
  var CHANNEL_EVENT_STATUSES = ["info", "pending", "success", "failure", "attention"];
21
22
  var MAX_CHANNEL_EVENT_BYTES = 4096;
23
+ var COORDINATION_KINDS = ["handoff", "handoff_ack", "verdict", "claim", "release", "note"];
22
24
  function record(input, path) {
23
25
  if (typeof input !== "object" || input === null || Array.isArray(input)) fail(path, "not_object");
24
26
  const prototype = Object.getPrototypeOf(input);
@@ -76,10 +78,66 @@ function decodeChannelEvent(raw) {
76
78
  ...r.has("url") ? { url: readUrl(r.field("url")) } : {},
77
79
  ...r.has("occurred_at") ? { occurred_at: utcTimestamp(r.field("occurred_at"), "occurred_at") } : {},
78
80
  ...r.has("source") ? { source: readSource(r.field("source")) } : {},
79
- ...r.has("key") ? { key: nonempty(label(r.field("key"), "key", 200), "key") } : {}
81
+ ...r.has("key") ? { key: nonempty(label(r.field("key"), "key", 200), "key") } : {},
82
+ // Older senders may use these kind names without data: such events stay plain events.
83
+ ...r.has("data") && isCoordinationKind(kind) ? { data: readData(kind, r.field("data")) } : {}
80
84
  };
81
85
  }));
82
86
  }
87
+ function isCoordinationKind(kind) {
88
+ return COORDINATION_KINDS.includes(kind);
89
+ }
90
+ var short = (input, path) => display(input, path, 256, 64);
91
+ var reason = (input, path) => display(input, path, 800, 200);
92
+ function readData(kind, input) {
93
+ const fields = {
94
+ handoff: ["ticket", "from", "to", "reason", "state"],
95
+ handoff_ack: ["ticket"],
96
+ verdict: ["pr", "verdict", "reason"],
97
+ claim: ["key"],
98
+ release: ["key"],
99
+ note: ["key", "value"]
100
+ }[kind];
101
+ const r = object(input, "data", fields);
102
+ const read = (key) => {
103
+ const value = r.field(key);
104
+ switch (key) {
105
+ case "pr": {
106
+ const pr = safeInteger(value, r.at(key));
107
+ if (pr === 0) fail(r.at(key), "invalid_value");
108
+ return pr;
109
+ }
110
+ case "verdict":
111
+ return literal(value, r.at(key), ["approved", "changes_requested"]);
112
+ case "reason":
113
+ return reason(value, r.at(key));
114
+ case "key":
115
+ return nonempty(label(value, r.at(key), 128), r.at(key));
116
+ // An empty value clears the note.
117
+ case "value":
118
+ return typeof value === "string" && value === "" ? "" : reason(value, r.at(key));
119
+ default:
120
+ return short(value, r.at(key));
121
+ }
122
+ };
123
+ return Object.fromEntries(fields.map((key) => [key, read(key)]));
124
+ }
125
+ function coordinationSummary(kind, d) {
126
+ switch (kind) {
127
+ case "handoff":
128
+ return `handoff ${d.ticket} ${d.from} \u2192 ${d.to} (${d.state}): ${d.reason}`;
129
+ case "handoff_ack":
130
+ return `handoff ${d.ticket} acknowledged`;
131
+ case "verdict":
132
+ return `PR #${d.pr} ${d.verdict === "approved" ? "approved" : "changes requested"}: ${d.reason}`;
133
+ case "claim":
134
+ return `claimed ${d.key}`;
135
+ case "release":
136
+ return `released ${d.key}`;
137
+ case "note":
138
+ return d.value === "" ? `note ${d.key} cleared` : `note ${d.key} = ${d.value}`;
139
+ }
140
+ }
83
141
  function readSubject(input) {
84
142
  const r = record(input, "subject");
85
143
  let pr;
@@ -127,8 +185,23 @@ function formatChannelEventLine(content) {
127
185
  function encodeChannelEvent(input) {
128
186
  return safely(() => {
129
187
  const checked = decodeWith(() => {
130
- record(input, "");
131
- return { ...input, v: 1, body: "" };
188
+ const r = record(input, "");
189
+ const raw = input;
190
+ const kind = raw.kind;
191
+ if (typeof kind !== "string" || !isCoordinationKind(kind)) {
192
+ if (r.has("data")) fail("data", "invalid_value");
193
+ return { ...raw, v: 1, body: "" };
194
+ }
195
+ const data = readData(kind, r.field("data"));
196
+ const derived = coordinationSummary(kind, data);
197
+ return {
198
+ ...raw,
199
+ v: 1,
200
+ body: "",
201
+ data,
202
+ ...r.has("summary") ? {} : { summary: [...derived].length > 200 ? [...derived].slice(0, 199).join("") + "\u2026" : derived },
203
+ ...r.has("status") || kind !== "verdict" ? {} : { status: data.verdict === "approved" ? "success" : "attention" }
204
+ };
132
205
  });
133
206
  if (!checked.ok) return checked;
134
207
  const decoded = decodeChannelEvent(checked.value);
@@ -163,6 +236,26 @@ function statusFor(content) {
163
236
  return content.kind.startsWith("agent.attention.") && !content.kind.endsWith(".resolved") ? "attention" : "info";
164
237
  }
165
238
  }
239
+ function foldCoordination(events) {
240
+ const handoffs = /* @__PURE__ */ new Map();
241
+ const claims = /* @__PURE__ */ new Map();
242
+ const notes = /* @__PURE__ */ new Map();
243
+ for (const { sender, by, at, content: { kind, data } } of events) {
244
+ if (!data) continue;
245
+ const s = (key) => String(data[key]);
246
+ if (kind === "handoff") {
247
+ handoffs.delete(s("ticket"));
248
+ handoffs.set(s("ticket"), { ticket: s("ticket"), from: s("from"), to: s("to"), reason: s("reason"), state: s("state"), by, at });
249
+ } else if (kind === "handoff_ack") handoffs.delete(s("ticket"));
250
+ else if (kind === "claim" && !claims.has(s("key"))) claims.set(s("key"), { key: s("key"), by, sender, at });
251
+ else if (kind === "release" && claims.get(s("key"))?.sender === sender) claims.delete(s("key"));
252
+ else if (kind === "note") {
253
+ notes.delete(s("key"));
254
+ if (s("value") !== "") notes.set(s("key"), s("value"));
255
+ }
256
+ }
257
+ return { openHandoffs: [...handoffs.values()], activeClaims: [...claims.values()], notes: Object.fromEntries(notes) };
258
+ }
166
259
 
167
260
  export {
168
261
  CHANNEL_EVENT_TYPE,
@@ -170,5 +263,6 @@ export {
170
263
  formatChannelEventLine,
171
264
  encodeChannelEvent,
172
265
  memberRenameContent,
173
- statusFor
266
+ statusFor,
267
+ foldCoordination
174
268
  };
@@ -14,21 +14,21 @@ import {
14
14
  decodeLocalSendResult,
15
15
  ensureHelper,
16
16
  localRoomPath
17
- } from "./chunk-FO5GXCST.mjs";
18
- import "./chunk-SSO5RFOX.mjs";
17
+ } from "./chunk-SRZTHCXP.mjs";
18
+ import "./chunk-HHEZVPRR.mjs";
19
+ import "./chunk-XR625T3I.mjs";
20
+ import "./chunk-G3NMB4PY.mjs";
21
+ import {
22
+ LISTENING_MODE_COMMAND_TYPE
23
+ } from "./chunk-4BP7V3OP.mjs";
19
24
  import {
20
25
  CHANNEL_EVENT_TYPE,
21
26
  memberRenameContent
22
- } from "./chunk-BV45NK7K.mjs";
23
- import "./chunk-ANSR4IAW.mjs";
24
- import "./chunk-3KDOTR54.mjs";
25
- import {
26
- LISTENING_MODE_COMMAND_TYPE
27
- } from "./chunk-NGSYOVQ4.mjs";
28
- import "./chunk-NPSQNCOY.mjs";
27
+ } from "./chunk-JKOJQTFT.mjs";
28
+ import "./chunk-PN25BUQ4.mjs";
29
29
  import {
30
30
  init_define_KHALA_BUNDLE
31
- } from "./chunk-7R3EIDGR.mjs";
31
+ } from "./chunk-EVT2DWNZ.mjs";
32
32
 
33
33
  // src/local/session.ts
34
34
  init_define_KHALA_BUNDLE();
@@ -124,6 +124,7 @@ async function createLocalSession(creds, opts = {}) {
124
124
  let name;
125
125
  let invitedBy;
126
126
  let after = 0;
127
+ let joinedAt;
127
128
  function check(roomId) {
128
129
  if (stopped) throw new Error("session_stopped");
129
130
  if (roomId !== creds.roomId) throw new Error("unknown_room");
@@ -323,6 +324,7 @@ async function createLocalSession(creds, opts = {}) {
323
324
  joining ??= (async () => {
324
325
  const result = decoded(await withHelper(() => request("POST", "join", {})), decodeLocalJoined);
325
326
  after = result.seq;
327
+ joinedAt = result.ts;
326
328
  await me();
327
329
  const members = decoded(await withHelper(() => request("GET", "members?wire=2")), decodeLocalMembersResponse);
328
330
  check(roomId);
@@ -340,6 +342,7 @@ async function createLocalSession(creds, opts = {}) {
340
342
  joining = void 0;
341
343
  }
342
344
  },
345
+ joinedAt: (roomId) => roomId === creds.roomId ? joinedAt : void 0,
343
346
  async history(roomId, limit, before) {
344
347
  check(roomId);
345
348
  const page = decoded(await withHelper(() => request("GET", `messages?wire=2&limit=${limit}${before !== void 0 ? `&before=${encodeURIComponent(before)}` : ""}`)), decodeLocalHistoryPage);
@@ -1,4 +1,8 @@
1
1
  import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
2
+ import {
3
+ decodeChannelEvent,
4
+ formatChannelEventLine
5
+ } from "./chunk-JKOJQTFT.mjs";
2
6
  import {
3
7
  StateError,
4
8
  channelFiles,
@@ -10,10 +14,50 @@ import {
10
14
  stateKey,
11
15
  writeJsonAtomic,
12
16
  writeStateFile
13
- } from "./chunk-NPSQNCOY.mjs";
17
+ } from "./chunk-PN25BUQ4.mjs";
14
18
  import {
15
19
  init_define_KHALA_BUNDLE
16
- } from "./chunk-7R3EIDGR.mjs";
20
+ } from "./chunk-EVT2DWNZ.mjs";
21
+
22
+ // src/events/receive.ts
23
+ init_define_KHALA_BUNDLE();
24
+ function toEventInboxEntry(base, rawContent, you) {
25
+ const decoded = decodeChannelEvent(rawContent);
26
+ if (!decoded.ok) return null;
27
+ const content = decoded.value;
28
+ const to = content.kind === "handoff" ? String(content.data?.to ?? "").replace(/^@/u, "").toLowerCase() : "";
29
+ return {
30
+ entry: {
31
+ ...base,
32
+ kind: "event",
33
+ body: formatChannelEventLine(content) + (content.url ? " " + content.url : ""),
34
+ eventKind: content.kind,
35
+ ...content.data ? { data: content.data } : {},
36
+ ...to && to === you?.toLowerCase() ? { mention: true } : {}
37
+ },
38
+ ...content.key !== void 0 ? { key: content.key } : {}
39
+ };
40
+ }
41
+ function createEventKeyFilter() {
42
+ const seen = /* @__PURE__ */ new Set();
43
+ return (key) => {
44
+ if (key === void 0) return true;
45
+ if (seen.has(key)) return false;
46
+ seen.add(key);
47
+ return true;
48
+ };
49
+ }
50
+ function isWakeEntry(entry) {
51
+ return entry.kind === "message" || entry.mention === true;
52
+ }
53
+ function mentions(entry, name) {
54
+ if (!name) return false;
55
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
56
+ return new RegExp(`(?<![\\p{L}\\p{N}_])@?${escaped}(?![\\p{L}\\p{N}_])`, "iu").test(entry.body);
57
+ }
58
+ function wakesAgent(entry, mode, you) {
59
+ return isWakeEntry(entry) && (mode !== "sync" || entry.senderKind !== "agent" || entry.mention === true || mentions(entry, you));
60
+ }
17
61
 
18
62
  // src/inbox.ts
19
63
  init_define_KHALA_BUNDLE();
@@ -63,16 +107,18 @@ async function unread(files) {
63
107
  }
64
108
  async function unreadCounts(files) {
65
109
  const { entries } = await unread(files);
66
- return { total: entries.length, messages: entries.filter((entry) => entry.kind === "message").length };
110
+ return { total: entries.length, messages: entries.filter((entry) => isWakeEntry(entry)).length };
67
111
  }
68
- async function advanceCursor(files, expected, delivered) {
112
+ async function advanceCursor(files, expected, delivered, shown = false) {
69
113
  const current = await readCursor(files);
70
114
  if (current.deliveredCount !== expected.deliveredCount || current.lastDeliveredEventId !== expected.lastDeliveredEventId) return "conflict";
71
115
  if (!delivered.length) return expected;
72
116
  const entries = await readEntries(files);
73
117
  const slice = entries.slice(expected.deliveredCount, expected.deliveredCount + delivered.length);
74
118
  if (slice.length !== delivered.length || slice.some((entry, index) => entry.eventId !== delivered[index]?.eventId)) return "conflict";
75
- const next = { lastDeliveredEventId: delivered[delivered.length - 1].eventId, deliveredCount: expected.deliveredCount + delivered.length };
119
+ const last = delivered[delivered.length - 1].eventId;
120
+ const shownEventId = shown ? last : current.shownEventId;
121
+ const next = { lastDeliveredEventId: last, deliveredCount: expected.deliveredCount + delivered.length, ...shownEventId ? { shownEventId } : {} };
76
122
  await writeJsonAtomic(files.cursor, next);
77
123
  return next;
78
124
  }
@@ -208,11 +254,22 @@ function resolveChannel(list, ref) {
208
254
 
209
255
  // src/activity.ts
210
256
  init_define_KHALA_BUNDLE();
257
+ import * as fs3 from "node:fs/promises";
211
258
  import path2 from "node:path";
212
259
  async function readActivity(files) {
213
260
  const activity = await readJson(path2.join(files.dir, "activity.json"));
214
261
  return activity && ["idle", "busy"].includes(activity.state) && typeof activity.updatedAt === "string" && Number.isFinite(Date.parse(activity.updatedAt)) ? activity : { state: "busy", updatedAt: (/* @__PURE__ */ new Date(0)).toISOString() };
215
262
  }
263
+ var USAGE_LIMIT = "usage-limit.json";
264
+ async function markUsageLimit(files, now = () => /* @__PURE__ */ new Date()) {
265
+ await writeJsonAtomic(path2.join(files.dir, USAGE_LIMIT), { at: now().toISOString() });
266
+ }
267
+ async function clearUsageLimit(files) {
268
+ await fs3.rm(path2.join(files.dir, USAGE_LIMIT), { force: true });
269
+ }
270
+ async function usageLimited(dir) {
271
+ return await readJson(path2.join(dir, USAGE_LIMIT)) !== null;
272
+ }
216
273
  async function writeActivity(files, state, now = () => /* @__PURE__ */ new Date()) {
217
274
  const activity = { state, updatedAt: now().toISOString() };
218
275
  await writeJsonAtomic(path2.join(files.dir, "activity.json"), activity);
@@ -220,6 +277,11 @@ async function writeActivity(files, state, now = () => /* @__PURE__ */ new Date(
220
277
  }
221
278
 
222
279
  export {
280
+ toEventInboxEntry,
281
+ createEventKeyFilter,
282
+ isWakeEntry,
283
+ mentions,
284
+ wakesAgent,
223
285
  readEntries,
224
286
  readCursor,
225
287
  unread,
@@ -231,5 +293,8 @@ export {
231
293
  migrateLegacy,
232
294
  resolveChannel,
233
295
  readActivity,
296
+ markUsageLimit,
297
+ clearUsageLimit,
298
+ usageLimited,
234
299
  writeActivity
235
300
  };
@@ -3,32 +3,33 @@ import {
3
3
  WAKE_HARNESSES,
4
4
  wakeDrivers,
5
5
  wakeStatus
6
- } from "./chunk-XUCWSYVS.mjs";
6
+ } from "./chunk-W6HM6F2U.mjs";
7
7
  import {
8
8
  adapterFor,
9
+ registerAntigravityWake,
9
10
  resolveSources
10
- } from "./chunk-ITFD3JZS.mjs";
11
+ } from "./chunk-5JSGA6OB.mjs";
11
12
  import {
12
13
  CURSOR_DEFAULT_SESSION,
13
14
  updateWakeSettings
14
- } from "./chunk-NIX5F4LT.mjs";
15
+ } from "./chunk-2AMWQ7RB.mjs";
15
16
  import {
16
17
  SESSION_ID_PATTERN,
17
18
  filesForDir,
18
19
  stateRoot
19
- } from "./chunk-NPSQNCOY.mjs";
20
+ } from "./chunk-PN25BUQ4.mjs";
20
21
  import {
21
22
  resetWakeDriver
22
- } from "./chunk-K7V7X6WU.mjs";
23
+ } from "./chunk-ZSKLNZWZ.mjs";
23
24
  import {
24
25
  init_define_KHALA_BUNDLE
25
- } from "./chunk-7R3EIDGR.mjs";
26
+ } from "./chunk-EVT2DWNZ.mjs";
26
27
 
27
28
  // src/wake/cli.ts
28
29
  init_define_KHALA_BUNDLE();
29
30
  import * as fs from "node:fs/promises";
30
31
  import path from "node:path";
31
- var WAKE_USAGE = "usage: khala wake on|off|status [--driver <d>] [--harness <id>] [--json]";
32
+ var WAKE_USAGE = "usage: khala wake on|off|status|register [--driver <d>] [--harness <id>] [--json]";
32
33
  async function sessionIds(harness, env) {
33
34
  try {
34
35
  return (await fs.readdir(path.join(stateRoot(env), harness), { withFileTypes: true })).filter((entry) => entry.isDirectory() && SESSION_ID_PATTERN.test(entry.name)).map((entry) => entry.name);
@@ -53,10 +54,15 @@ async function setWake(harness, drivers, on, env) {
53
54
  }
54
55
  });
55
56
  if (on) for (const id of await sessionIds(harness, env)) {
56
- for (const driver of drivers) await resetWakeDriver(filesForDir(path.join(root, harness, id)).dir, driver);
57
+ for (const driver of drivers) {
58
+ const dir = filesForDir(path.join(root, harness, id)).dir;
59
+ await resetWakeDriver(dir, driver);
60
+ if (harness === "qwen" && driver === "socket") await fs.rm(path.join(dir, "qwen-receipt.json"), { force: true });
61
+ }
57
62
  }
58
63
  }
59
64
  function consentLine(harness, drivers, on) {
65
+ if (harness === "antigravity" && on) return `Idle wake is on (${drivers.join(", ")}): native wake preserves drafts; terminal fallback requires an empty prompt. Wake and Sync continuation use billed model turns. Run \`khala wake off --harness antigravity\` to turn it off.`;
60
66
  return on ? `Idle wake is on (${drivers.join(", ")}): Khala may send a fixed wake line into this agent's existing session when messages wait and ${harness === "muse" ? "the session is idle (through Muse\u2019s native monitor)" : "the prompt is empty"}. Run \`khala wake off --harness ${harness}\` to turn it off.` : `Idle wake is off for ${drivers.join(", ")}. Run \`khala wake on --harness ${harness}\` to turn it on.`;
61
67
  }
62
68
  async function currentSessionId(harness, env) {
@@ -85,6 +91,20 @@ async function runWake(argv, deps = {}) {
85
91
  return 2;
86
92
  }
87
93
  }
94
+ if (command === "register") {
95
+ if (harness !== "antigravity" || driver || json) {
96
+ err(WAKE_USAGE);
97
+ return 2;
98
+ }
99
+ try {
100
+ await registerAntigravityWake(env);
101
+ out("Registered Antigravity native wake for this session.");
102
+ return 0;
103
+ } catch {
104
+ err("khala: Antigravity wake registration unavailable; run this command through the agent shell.");
105
+ return 1;
106
+ }
107
+ }
88
108
  if (!["on", "off", "status"].includes(command ?? "")) {
89
109
  err(WAKE_USAGE);
90
110
  return 2;