@usebitl/cli 0.1.1 → 0.1.3

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.
@@ -314,7 +314,7 @@ var sessionKey = (source, sessionId) => `${source}:${sessionId}`;
314
314
 
315
315
  // ../../shared/src/prepare.ts
316
316
  var WIRE_VERSION = 2;
317
- var TEXT_LIMIT = 500;
317
+ var TEXT_LIMIT = 1e4;
318
318
  var TITLE_LIMIT = 80;
319
319
  var clip = (s, max = TEXT_LIMIT) => {
320
320
  const t = s.trim();
package/dist/cli.mjs CHANGED
@@ -6,15 +6,12 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // ../src/index.ts
9
- import { randomUUID } from "node:crypto";
10
9
  import { homedir as homedir3 } from "node:os";
11
10
  import { join as join4, resolve as resolve2 } from "node:path";
12
11
 
13
12
  // ../../shared/src/crypto.ts
14
13
  var MASTER_KEY_BYTES = 32;
15
14
  var VERSION = "v1";
16
- var PAD_BLOCK = 32;
17
- var TAG_BYTES = 16;
18
15
  var SEALED_PATTERN = /^v1\.[A-Za-z0-9_-]{8}\.[A-Za-z0-9_-]{16}\.[A-Za-z0-9_-]+$/;
19
16
  var INBOX_SEALED_PATTERN = /^s1\.[A-Za-z0-9_-]{87}\.[A-Za-z0-9_-]{16}\.[A-Za-z0-9_-]+$/;
20
17
  var subtle = () => globalThis.crypto.subtle;
@@ -35,18 +32,12 @@ var info = (name) => ({ name: "HKDF", hash: "SHA-256", salt: new Uint8Array(0),
35
32
  async function deriveKeys(master) {
36
33
  if (master.length !== MASTER_KEY_BYTES) throw new Error(`\uD0A4 \uAE38\uC774\uAC00 ${MASTER_KEY_BYTES}\uBC14\uC774\uD2B8\uAC00 \uC544\uB2D9\uB2C8\uB2E4`);
37
34
  const base = await subtle().importKey("raw", new Uint8Array(master), "HKDF", false, ["deriveKey", "deriveBits"]);
38
- const [enc, tag2, kidBits] = await Promise.all([
35
+ const [enc, tag, kidBits] = await Promise.all([
39
36
  subtle().deriveKey(info("enc"), base, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]),
40
37
  subtle().deriveKey(info("tag"), base, { name: "HMAC", hash: "SHA-256", length: 256 }, false, ["sign"]),
41
38
  subtle().deriveBits(info("kid"), base, 48)
42
39
  ]);
43
- return { enc, tag: tag2, kid: toBase64Url(new Uint8Array(kidBits)), master: new Uint8Array(master) };
44
- }
45
- function pad(bytes) {
46
- const out = new Uint8Array(Math.ceil((bytes.length + 1) / PAD_BLOCK) * PAD_BLOCK);
47
- out.set(bytes);
48
- out[bytes.length] = 128;
49
- return out;
40
+ return { enc, tag, kid: toBase64Url(new Uint8Array(kidBits)), master: new Uint8Array(master) };
50
41
  }
51
42
  function unpad(bytes) {
52
43
  let i = bytes.length - 1;
@@ -54,11 +45,6 @@ function unpad(bytes) {
54
45
  if (i < 0 || bytes[i] !== 128) throw new Error("invalid padding");
55
46
  return bytes.subarray(0, i);
56
47
  }
57
- async function seal(keys, plaintext, aad) {
58
- const iv = globalThis.crypto.getRandomValues(new Uint8Array(12));
59
- const ct = await subtle().encrypt({ name: "AES-GCM", iv, additionalData: utf8.encode(aad) }, keys.enc, pad(utf8.encode(plaintext)));
60
- return `${VERSION}.${keys.kid}.${toBase64Url(iv)}.${toBase64Url(new Uint8Array(ct))}`;
61
- }
62
48
  async function open(keys, sealed, aad) {
63
49
  if (sealed.startsWith("s1.")) {
64
50
  if (!keys.inbox) throw new Error("no inbox key");
@@ -103,14 +89,6 @@ async function openInbox(privateKey, sealed, aad) {
103
89
  );
104
90
  return fromUtf8.decode(unpad(new Uint8Array(pt)));
105
91
  }
106
- async function tag(keys, value) {
107
- const mac3 = await subtle().sign("HMAC", keys.tag, utf8.encode(value));
108
- return toBase64Url(new Uint8Array(mac3).subarray(0, TAG_BYTES));
109
- }
110
- var sealerFor = (keys) => ({
111
- seal: (plaintext, aad) => seal(keys, plaintext, aad),
112
- tag: (value) => tag(keys, value)
113
- });
114
92
  async function keysFromBase64Url(master) {
115
93
  return deriveKeys(fromBase64Url(master.trim()));
116
94
  }
@@ -153,262 +131,6 @@ var WAITING_REASONS = [
153
131
  "other"
154
132
  ];
155
133
 
156
- // ../../shared/src/normalize.ts
157
- var str = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
158
- var oneLine = (s, max = 120) => {
159
- const flat = s.replace(/\s+/g, " ").trim();
160
- return flat.length > max ? `${flat.slice(0, max - 1)}\u2026` : flat;
161
- };
162
- function commandText(v) {
163
- if (!Array.isArray(v)) return str(v);
164
- const parts = v.filter((x) => typeof x === "string");
165
- const shell = parts.length === 3 && /^-l?c$/.test(parts[1] ?? "");
166
- return str(shell ? parts[2] : parts.join(" "));
167
- }
168
- function summarizeToolInput(input2) {
169
- if (!input2 || typeof input2 !== "object") return void 0;
170
- const i = input2;
171
- const first = (list, key) => Array.isArray(list) ? str(list[0]?.[key]) : void 0;
172
- const pick2 = commandText(i.command) ?? str(i.file_path) ?? str(i.path) ?? str(i.pattern) ?? str(i.url) ?? str(i.query) ?? str(i.description) ?? str(i.prompt) ?? first(i.questions, "question") ?? str(i.plan) ?? // ExitPlanMode: { plan }
173
- // Codex webrun: { search_query: [{ q }] } 또는 { weather: [{ location }] }
174
- first(i.search_query, "q") ?? first(i.weather, "location");
175
- return pick2 ? oneLine(pick2) : void 0;
176
- }
177
- var USER_BLOCKING_TOOLS = {
178
- AskUserQuestion: "question",
179
- ExitPlanMode: "plan"
180
- };
181
- function waitingFromNotification(kind) {
182
- switch (kind) {
183
- case "permission_prompt":
184
- return "permission";
185
- case "idle_prompt":
186
- return "idle";
187
- case "elicitation_dialog":
188
- case "elicitation_url_dialog":
189
- return "elicitation";
190
- case "agent_needs_input":
191
- return "input";
192
- default:
193
- return void 0;
194
- }
195
- }
196
- function normalizeHook(source, raw, receivedAt) {
197
- const nativeType = str(raw.hook_event_name);
198
- const sessionId = str(raw.session_id);
199
- if (!nativeType || !sessionId) return null;
200
- let type = "notice";
201
- let text;
202
- let waitingReason;
203
- let tool;
204
- const toolInfo = (failed) => {
205
- const name = str(raw.tool_name);
206
- if (!name) return void 0;
207
- return {
208
- name,
209
- useId: str(raw.tool_use_id),
210
- summary: summarizeToolInput(raw.tool_input),
211
- ...failed ? { failed } : {}
212
- };
213
- };
214
- switch (nativeType) {
215
- case "SessionStart":
216
- type = "session_start";
217
- break;
218
- case "SessionEnd":
219
- type = "session_end";
220
- break;
221
- case "UserPromptSubmit":
222
- type = "prompt";
223
- text = str(raw.user_prompt) ?? str(raw.prompt);
224
- break;
225
- case "PreToolUse": {
226
- tool = toolInfo();
227
- const reason = tool && USER_BLOCKING_TOOLS[tool.name];
228
- type = reason ? "waiting" : "tool_start";
229
- waitingReason = reason;
230
- break;
231
- }
232
- case "PostToolUse":
233
- type = "tool_end";
234
- tool = toolInfo();
235
- break;
236
- case "PostToolUseFailure":
237
- type = "tool_end";
238
- tool = toolInfo(true);
239
- text = str(raw.error_message);
240
- break;
241
- case "PermissionRequest":
242
- type = "waiting";
243
- waitingReason = "permission";
244
- tool = toolInfo();
245
- break;
246
- case "Notification": {
247
- const kind = str(raw.notification_type);
248
- waitingReason = waitingFromNotification(kind);
249
- type = waitingReason ? "waiting" : "notice";
250
- text = str(raw.message);
251
- break;
252
- }
253
- case "Stop":
254
- case "Interrupt":
255
- type = "turn_end";
256
- text = str(raw.last_assistant_message);
257
- break;
258
- case "StopFailure":
259
- type = "error";
260
- text = str(raw.error_message) ?? str(raw.error_type);
261
- break;
262
- case "SubagentStart":
263
- type = "subagent_start";
264
- text = str(raw.task_description);
265
- break;
266
- case "SubagentStop":
267
- type = "subagent_end";
268
- text = str(raw.last_assistant_message);
269
- break;
270
- default:
271
- type = "notice";
272
- }
273
- return {
274
- source,
275
- sessionId,
276
- type,
277
- nativeType,
278
- at: receivedAt,
279
- cwd: str(raw.cwd),
280
- turnId: str(raw.turn_id) ?? str(raw.prompt_id),
281
- agentId: str(raw.agent_id),
282
- agentType: str(raw.agent_type),
283
- tool,
284
- text,
285
- waitingReason,
286
- transcriptPath: str(raw.transcript_path),
287
- model: str(raw.model),
288
- raw
289
- };
290
- }
291
- function normalizeCodexNotify(raw, receivedAt) {
292
- const nativeType = str(raw.type);
293
- const sessionId = str(raw["thread-id"]);
294
- if (!nativeType || !sessionId) return null;
295
- return {
296
- source: "codex",
297
- sessionId,
298
- type: nativeType === "agent-turn-complete" ? "turn_end" : "notice",
299
- nativeType,
300
- at: receivedAt,
301
- cwd: str(raw.cwd),
302
- turnId: str(raw["turn-id"]),
303
- text: str(raw["last-assistant-message"]),
304
- raw
305
- };
306
- }
307
- function agyTool(call, failed) {
308
- const name = str(call?.name);
309
- if (!name) return void 0;
310
- const args = call?.args ?? {};
311
- const summary = str(args.CommandLine) ?? summarizeToolInput(args) ?? str(args.toolSummary);
312
- return { name, summary: summary && oneLine(summary), ...failed ? { failed } : {} };
313
- }
314
- function normalizeAntigravity(raw, receivedAt) {
315
- const nativeType = str(raw.hook_event_name);
316
- const sessionId = str(raw.conversationId);
317
- if (!nativeType || !sessionId) return null;
318
- let type;
319
- let text;
320
- let tool;
321
- let waitingReason;
322
- const call = raw.toolCall;
323
- const error62 = str(raw.error);
324
- switch (nativeType) {
325
- case "PreInvocation":
326
- if (raw.invocationNum !== 0) return null;
327
- type = "prompt";
328
- text = str(raw.prompt);
329
- break;
330
- case "PreToolUse":
331
- tool = agyTool(call);
332
- if (!tool) return null;
333
- type = "tool_start";
334
- break;
335
- case "PostToolUse":
336
- tool = agyTool(call, !!error62);
337
- if (!tool) return null;
338
- type = "tool_end";
339
- text = error62;
340
- break;
341
- case "Stop":
342
- type = error62 ? "error" : "turn_end";
343
- text = error62 ?? str(raw.last_assistant_message);
344
- break;
345
- // 아래 둘은 agy 가 아니라 bitl-agy-watch.mjs 가 대화 DB 의 단계 상태를 보고 만든다
346
- case "bitl:PermissionWaiting":
347
- type = "waiting";
348
- waitingReason = "permission";
349
- tool = agyTool(call);
350
- break;
351
- case "bitl:PermissionResolved":
352
- type = "progress";
353
- break;
354
- default:
355
- return null;
356
- }
357
- const workspaces = Array.isArray(raw.workspacePaths) ? raw.workspacePaths : [];
358
- return {
359
- source: "antigravity",
360
- sessionId,
361
- type,
362
- nativeType,
363
- at: receivedAt,
364
- cwd: str(workspaces[0]),
365
- tool,
366
- text,
367
- waitingReason,
368
- transcriptPath: str(raw.transcriptPath),
369
- model: str(raw.modelName),
370
- raw
371
- };
372
- }
373
- var REPORT_EVENTS = ["start", "progress", "waiting", "done", "error", "end"];
374
- var REPORT_TYPE = {
375
- start: "prompt",
376
- progress: "progress",
377
- waiting: "waiting",
378
- done: "turn_end",
379
- error: "error",
380
- end: "session_end"
381
- };
382
- function normalizeReport(source, raw, receivedAt) {
383
- const event = str(raw.event);
384
- const sessionId = str(raw.session_id);
385
- if (!event || !sessionId || !(event in REPORT_TYPE)) return null;
386
- const title = str(raw.title);
387
- const detail = str(raw.detail);
388
- return {
389
- source,
390
- sessionId,
391
- type: REPORT_TYPE[event],
392
- nativeType: `report:${event}`,
393
- at: receivedAt,
394
- cwd: str(raw.cwd),
395
- // start 는 제목이 곧 지시 내용, 나머지는 상세 설명
396
- text: event === "start" ? title ?? detail : detail,
397
- request: str(raw.request),
398
- waitingReason: event === "waiting" ? "input" : void 0,
399
- raw
400
- };
401
- }
402
- function normalizeRecord(rec) {
403
- const at = rec.receivedAt && !Number.isNaN(Date.parse(rec.receivedAt)) ? new Date(rec.receivedAt).toISOString() : (/* @__PURE__ */ new Date()).toISOString();
404
- if (rec.source === "codex-notify") return normalizeCodexNotify(rec.payload, at);
405
- if (rec.source === "antigravity") return normalizeAntigravity(rec.payload, at);
406
- if (!AGENT_SOURCES.includes(rec.source)) return null;
407
- const source = rec.source;
408
- const isReport = typeof rec.payload.event === "string" && rec.payload.hook_event_name === void 0;
409
- return isReport ? normalizeReport(source, rec.payload, at) : normalizeHook(source, rec.payload, at);
410
- }
411
-
412
134
  // ../../shared/src/pairing.ts
413
135
  var subtle2 = () => globalThis.crypto.subtle;
414
136
  var utf82 = new TextEncoder();
@@ -459,7 +181,6 @@ async function unwrapMasterKey(wrapped, ownPrivate, peerPublic, pairingId) {
459
181
  }
460
182
 
461
183
  // ../../shared/src/session.ts
462
- var sessionKey = (source, sessionId) => `${source}:${sessionId}`;
463
184
  var displayTitle = (s) => s.aiTitle ?? s.title ?? s.project ?? (s.locked ? "\u{1F512} \uC774 \uAE30\uAE30\uC758 \uD0A4\uB85C \uC5F4 \uC218 \uC5C6\uC74C" : "(\uC81C\uBAA9 \uC5C6\uC74C)");
464
185
 
465
186
  // ../../shared/src/prepare.ts
@@ -482,62 +203,6 @@ var EVENT_CONTENT_FIELDS = [
482
203
  "aiTitle",
483
204
  "model"
484
205
  ];
485
- var TEXT_LIMIT = 500;
486
- var TITLE_LIMIT = 80;
487
- var clip = (s, max = TEXT_LIMIT) => {
488
- const t = s.trim();
489
- return t.length > max ? `${t.slice(0, max - 1)}\u2026` : t;
490
- };
491
- var carriesContext = (e) => e.type === "session_start" || e.type === "prompt" || e.type === "turn_end" || e.nativeType === "CwdChanged";
492
- function activityOf(e) {
493
- if (!e.tool) return void 0;
494
- const base = e.tool.summary ? `${e.tool.name}: ${e.tool.summary}` : e.tool.name;
495
- return e.agentId && e.agentType ? `[${e.agentType}] ${base}` : base;
496
- }
497
- function splitEvent(e, extra = {}) {
498
- const newCwd = e.nativeType === "CwdChanged" && typeof e.raw.new_cwd === "string" ? e.raw.new_cwd : void 0;
499
- const signal = {
500
- source: e.source,
501
- sessionId: e.sessionId,
502
- type: e.type,
503
- nativeType: e.nativeType,
504
- at: e.at,
505
- turnId: e.turnId,
506
- agentId: e.agentId,
507
- agentNamed: e.agentId || e.agentType !== void 0 ? Boolean(e.agentType) : void 0,
508
- waitingReason: e.waitingReason,
509
- toolFailed: e.tool?.failed || void 0
510
- };
511
- const content = {
512
- title: e.type === "prompt" && e.text ? oneLine(e.text, TITLE_LIMIT) : void 0,
513
- text: e.text ? clip(e.text) : void 0,
514
- request: e.request ? clip(e.request) : void 0,
515
- activity: activityOf(e),
516
- tool: e.tool?.name,
517
- toolSummary: e.tool?.summary,
518
- agentType: e.agentType || void 0,
519
- cwd: newCwd ?? (carriesContext(e) ? e.cwd : void 0),
520
- model: e.model,
521
- ...extra
522
- };
523
- const tagSource = e.type === "prompt" ? e.request ?? e.text : e.request;
524
- return { signal: dropUndefined(signal), content: dropUndefined(content), tagSource };
525
- }
526
- function dropUndefined(o) {
527
- return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0 && v !== ""));
528
- }
529
- async function prepareRecord(e, sealer, extra = {}) {
530
- const { signal, content, tagSource } = splitEvent(e, extra);
531
- const aad = sessionKey(e.source, e.sessionId);
532
- const sealed = {};
533
- await Promise.all(
534
- Object.entries(content).map(async ([k, v]) => {
535
- sealed[k] = await sealer.seal(v, aad);
536
- })
537
- );
538
- if (tagSource) signal.requestTag = await sealer.tag(tagSource);
539
- return { v: WIRE_VERSION, signal, content: sealed };
540
- }
541
206
 
542
207
  // ../../shared/src/view.ts
543
208
  async function tryOpen(keys, sealed, aad) {
@@ -1401,14 +1066,14 @@ function promiseAllObject(promisesObj) {
1401
1066
  }
1402
1067
  function randomString(length = 10) {
1403
1068
  const chars = "abcdefghijklmnopqrstuvwxyz";
1404
- let str2 = "";
1069
+ let str = "";
1405
1070
  for (let i = 0; i < length; i++) {
1406
- str2 += chars[Math.floor(Math.random() * chars.length)];
1071
+ str += chars[Math.floor(Math.random() * chars.length)];
1407
1072
  }
1408
- return str2;
1073
+ return str;
1409
1074
  }
1410
- function esc(str2) {
1411
- return JSON.stringify(str2);
1075
+ function esc(str) {
1076
+ return JSON.stringify(str);
1412
1077
  }
1413
1078
  function slugify(input2) {
1414
1079
  return input2.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
@@ -1522,8 +1187,8 @@ var primitiveTypes = /* @__PURE__ */ new Set([
1522
1187
  "symbol",
1523
1188
  "undefined"
1524
1189
  ]);
1525
- function escapeRegex(str2) {
1526
- return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1190
+ function escapeRegex(str) {
1191
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1527
1192
  }
1528
1193
  function clone(inst, def, params) {
1529
1194
  const cl = new inst._zod.constr(def ?? inst._zod.def);
@@ -1777,13 +1442,13 @@ function getSizableOrigin(input2) {
1777
1442
  return "unknown";
1778
1443
  }
1779
1444
  var highSurrogate = /[\uD800-\uDBFF]/;
1780
- function codePointLength(str2) {
1781
- const units = str2.length;
1782
- if (!highSurrogate.test(str2))
1445
+ function codePointLength(str) {
1446
+ const units = str.length;
1447
+ if (!highSurrogate.test(str))
1783
1448
  return units;
1784
1449
  let count = units;
1785
1450
  for (let i = 0; i < units - 1; i++) {
1786
- if ((str2.charCodeAt(i) & 64512) === 55296 && (str2.charCodeAt(i + 1) & 64512) === 56320) {
1451
+ if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {
1787
1452
  count--;
1788
1453
  i++;
1789
1454
  }
@@ -20270,7 +19935,7 @@ var AgentEvent = external_exports.object({
20270
19935
  });
20271
19936
 
20272
19937
  // ../../shared/src/wire.ts
20273
- var SealedValue = external_exports.string().max(8e3).regex(SEALED_PATTERN);
19938
+ var SealedValue = external_exports.string().max(64e3).regex(SEALED_PATTERN);
20274
19939
  var id = external_exports.string().min(1).max(200);
20275
19940
  var SignalSchema = external_exports.object({
20276
19941
  source: AgentSource,
@@ -20292,51 +19957,7 @@ var WireRecordSchema = external_exports.object({
20292
19957
  });
20293
19958
 
20294
19959
  // ../../shared/src/node/antigravity.ts
20295
- import { readFile, stat } from "node:fs/promises";
20296
19960
  var MAX_TRANSCRIPT_BYTES = 20 * 1024 * 1024;
20297
- var RETRY_MS = 150;
20298
- var RETRIES = 6;
20299
- async function readSteps(path) {
20300
- try {
20301
- if ((await stat(path)).size > MAX_TRANSCRIPT_BYTES) return [];
20302
- const steps = [];
20303
- for (const line of (await readFile(path, "utf8")).split("\n")) {
20304
- if (!line.trim()) continue;
20305
- try {
20306
- steps.push(JSON.parse(line));
20307
- } catch {
20308
- }
20309
- }
20310
- return steps;
20311
- } catch {
20312
- return [];
20313
- }
20314
- }
20315
- function userRequestText(content) {
20316
- const m = /<USER_REQUEST>\s*([\s\S]*?)\s*<\/USER_REQUEST>/.exec(content);
20317
- return (m?.[1] ?? content).trim();
20318
- }
20319
- async function fillAntigravityText(payload) {
20320
- const path = typeof payload.transcriptPath === "string" ? payload.transcriptPath : void 0;
20321
- const event = payload.hook_event_name;
20322
- if (!path) return payload;
20323
- if (event === "PreInvocation" && payload.invocationNum === 0 && payload.prompt === void 0) {
20324
- const index = typeof payload.initialNumSteps === "number" ? payload.initialNumSteps - 1 : void 0;
20325
- for (let i = 0; i <= RETRIES; i++) {
20326
- const steps = await readSteps(path);
20327
- const input2 = steps.filter((s) => s.type === "USER_INPUT" && (index === void 0 || s.step_index === index)).at(-1);
20328
- if (typeof input2?.content === "string") return { ...payload, prompt: userRequestText(input2.content) };
20329
- await new Promise((r) => setTimeout(r, RETRY_MS));
20330
- }
20331
- return payload;
20332
- }
20333
- if (event === "Stop" && payload.last_assistant_message === void 0) {
20334
- const steps = await readSteps(path);
20335
- const reply = steps.filter((s) => s.type === "PLANNER_RESPONSE" && typeof s.content === "string" && s.content.trim()).at(-1);
20336
- return reply ? { ...payload, last_assistant_message: reply.content.trim() } : payload;
20337
- }
20338
- return payload;
20339
- }
20340
19961
 
20341
19962
  // ../../shared/src/node/cloud.ts
20342
19963
  import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
@@ -20410,95 +20031,11 @@ function resolveTarget(home = bitlHome()) {
20410
20031
  }
20411
20032
 
20412
20033
  // ../../shared/src/node/enrich.ts
20413
- import { execFile } from "node:child_process";
20414
- import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
20415
- import { basename } from "node:path";
20416
- var BRANCH_TTL_MS = 6e4;
20417
20034
  var MAX_TRANSCRIPT_BYTES2 = 20 * 1024 * 1024;
20418
- var branchCache = /* @__PURE__ */ new Map();
20419
- function gitBranch(cwd) {
20420
- const hit = branchCache.get(cwd);
20421
- if (hit && Date.now() - hit.at < BRANCH_TTL_MS) return Promise.resolve(hit.branch);
20422
- return new Promise((resolve3) => {
20423
- execFile("git", ["-C", cwd, "branch", "--show-current"], { timeout: 2e3, windowsHide: true }, (err, stdout) => {
20424
- const branch = err ? void 0 : stdout.trim() || void 0;
20425
- branchCache.set(cwd, { at: Date.now(), branch });
20426
- resolve3(branch);
20427
- });
20428
- });
20429
- }
20430
- async function aiTitleFromTranscript(path) {
20431
- try {
20432
- if ((await stat2(path)).size > MAX_TRANSCRIPT_BYTES2) return void 0;
20433
- const text = await readFile2(path, "utf8");
20434
- let title;
20435
- for (const line of text.split("\n")) {
20436
- if (!line.includes('"ai-title"')) continue;
20437
- try {
20438
- const rec = JSON.parse(line);
20439
- if (rec.type === "ai-title" && rec.aiTitle) title = rec.aiTitle;
20440
- } catch {
20441
- }
20442
- }
20443
- return title;
20444
- } catch {
20445
- return void 0;
20446
- }
20447
- }
20448
- function gitRoot(cwd) {
20449
- const hit = rootCache.get(cwd);
20450
- if (hit && Date.now() - hit.at < BRANCH_TTL_MS) return Promise.resolve(hit.root);
20451
- return new Promise((resolve3) => {
20452
- execFile("git", ["-C", cwd, "rev-parse", "--show-toplevel"], { timeout: 2e3, windowsHide: true }, (err, stdout) => {
20453
- const root = err ? void 0 : stdout.trim() || void 0;
20454
- rootCache.set(cwd, { at: Date.now(), root });
20455
- resolve3(root);
20456
- });
20457
- });
20458
- }
20459
- var rootCache = /* @__PURE__ */ new Map();
20460
- async function projectName(cwd) {
20461
- const root = await gitRoot(cwd);
20462
- return basename((root ?? cwd).replace(/[\\/]+$/, ""));
20463
- }
20464
- async function enrichEvent(e) {
20465
- const extra = {};
20466
- const newCwd = e.nativeType === "CwdChanged" && typeof e.raw.new_cwd === "string" ? e.raw.new_cwd : void 0;
20467
- const cwd = newCwd ?? e.cwd;
20468
- const tasks = [];
20469
- if (cwd && carriesContext(e)) {
20470
- tasks.push(
20471
- Promise.all([gitBranch(cwd), projectName(cwd)]).then(([branch, project]) => {
20472
- if (branch) extra.gitBranch = branch;
20473
- extra.project = project;
20474
- })
20475
- );
20476
- }
20477
- if (e.source === "claude-code" && e.transcriptPath && (e.type === "prompt" || e.type === "turn_end")) {
20478
- tasks.push(
20479
- aiTitleFromTranscript(e.transcriptPath).then((title) => {
20480
- if (title) extra.aiTitle = title;
20481
- })
20482
- );
20483
- }
20484
- await Promise.all(tasks.map((t) => t.catch(() => {
20485
- })));
20486
- return extra;
20487
- }
20488
20035
 
20489
20036
  // ../../shared/src/node/approve.ts
20490
20037
  var DEFAULT_APPROVAL_WAIT_MS = 10 * 6e4;
20491
20038
 
20492
- // ../../shared/src/node/index.ts
20493
- async function prepareRaw(rec, opts = {}) {
20494
- const filled = rec.source === "antigravity" && opts.enrich !== false ? { ...rec, payload: await fillAntigravityText(rec.payload) } : rec;
20495
- const e = normalizeRecord(filled);
20496
- if (!e) return null;
20497
- const extra = opts.enrich === false ? {} : await enrichEvent(e);
20498
- const keys = opts.keys ?? await loadKeys(opts.home ?? bitlHome());
20499
- return prepareRecord(e, sealerFor(keys), extra);
20500
- }
20501
-
20502
20039
  // ../src/index.ts
20503
20040
  import { readFileSync as readFileSync4 } from "node:fs";
20504
20041
 
@@ -20780,10 +20317,7 @@ var USAGE = [
20780
20317
  ` bitl uninstall <claude|codex|antigravity${CLOUD_ONLY ? "" : "|claude-desktop"}> [--project D]`,
20781
20318
  "",
20782
20319
  " bitl remote [on|off] \uC6D0\uACA9 \uC2B9\uC778: \uCF1C\uBA74 Claude Code \uC758 \uAD8C\uD55C \uC694\uCCAD\uC744 \uD734\uB300\uD3F0\xB7\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uD5C8\uC6A9\xB7\uAC70\uBD80",
20783
- " \u2014 \uD130\uBBF8\uB110\xB7\uBE0C\uB77C\uC6B0\uC800\xB7\uD734\uB300\uD3F0 \uC911 \uBA3C\uC800 \uB2F5\uD55C \uCABD\uC774 \uC801\uC6A9\uB41C\uB2E4 (\uD3F0\uC758 \uB2F5\uC740 \uCD5C\uB300 10\uBD84 \uAE30\uB2E4\uB9BC)",
20784
- "",
20785
- ' bitl add "\uC791\uC5C5 \uC81C\uBAA9" [--detail \uC124\uBA85] \uC218\uB3D9 \uC791\uC5C5 \uB4F1\uB85D (id \uCD9C\uB825)',
20786
- ` bitl report <id> <${REPORT_EVENTS.join("|")}> [\uC124\uBA85]`
20320
+ " \u2014 \uD130\uBBF8\uB110\xB7\uBE0C\uB77C\uC6B0\uC800\xB7\uD734\uB300\uD3F0 \uC911 \uBA3C\uC800 \uB2F5\uD55C \uCABD\uC774 \uC801\uC6A9\uB41C\uB2E4 (\uD3F0\uC758 \uB2F5\uC740 \uCD5C\uB300 10\uBD84 \uAE30\uB2E4\uB9BC)"
20787
20321
  ].join("\n");
20788
20322
  var serverUrl = () => process.env.BITL_URL ?? `http://127.0.0.1:${process.env.BITL_PORT ?? 7777}`;
20789
20323
  function option(args, name) {
@@ -20808,10 +20342,6 @@ async function request(path, init = {}) {
20808
20342
  if (res.status === 401) throw new Error("\uC774 PC \uC758 \uC5F0\uACB0\uC774 \uB04A\uACBC\uC2B5\uB2C8\uB2E4 (\uAE30\uAE30\uAC00 \uC81C\uAC70\uB428). bitl logout \uD6C4 bitl login \uC73C\uB85C \uB2E4\uC2DC \uC5F0\uACB0\uD558\uC138\uC694.");
20809
20343
  return res;
20810
20344
  }
20811
- async function report(payload) {
20812
- const record2 = await prepareRaw({ source: "manual", payload }, { keys: await resolveTarget().keys() });
20813
- return (await request("/api/events", { body: record2 })).json();
20814
- }
20815
20345
  var boardUrl = (override) => (override?.trim() || process.env.BITL_PUBLIC_URL?.trim() || readCloudConfig()?.url || serverUrl()).replace(/\/+$/, "");
20816
20346
  var masterForPair = () => readCloudConfig() ? readFileSync4(cloudKeyPath(), "utf8").trim() : loadOrCreateMasterKey();
20817
20347
  var pairUrl = (base) => `${boardUrl(base)}/#key=${masterForPair()}`;
@@ -20925,23 +20455,6 @@ async function main(argv) {
20925
20455
  case "remote":
20926
20456
  case "away":
20927
20457
  return away(rest[0]);
20928
- case "add": {
20929
- const detail = option(rest, "--detail");
20930
- const title = rest.join(" ").trim();
20931
- if (!title) throw new Error('\uC791\uC5C5 \uC81C\uBAA9\uC744 \uC785\uB825\uD558\uC138\uC694: bitl add "\uC791\uC5C5 \uC81C\uBAA9"');
20932
- const id2 = randomUUID().slice(0, 8);
20933
- await report({ session_id: id2, event: "start", title, detail, cwd: process.cwd() });
20934
- console.log(`\uB4F1\uB85D: ${id2} ${title}`);
20935
- console.log(` \uC644\uB8CC\uD560 \uB54C: bitl report ${id2} done`);
20936
- return;
20937
- }
20938
- case "report": {
20939
- const [id2, event, ...detail] = rest;
20940
- if (!id2 || !REPORT_EVENTS.includes(event)) throw new Error(`\uC0AC\uC6A9\uBC95: bitl report <id> <${REPORT_EVENTS.join("|")}> [\uC124\uBA85]`);
20941
- await report({ session_id: id2, event, detail: detail.join(" ") || void 0 });
20942
- console.log(`\uBCF4\uACE0: ${id2} \u2192 ${event}`);
20943
- return;
20944
- }
20945
20458
  default:
20946
20459
  console.log(USAGE);
20947
20460
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usebitl/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "BITL CLI — connect Claude Code, Codex and Antigravity to usebitl.com and stay in the loop of every agent you run",
5
5
  "type": "module",
6
6
  "bin": {