@usebitl/cli 0.1.1 → 0.1.2
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/cli.mjs +14 -501
- package/package.json +1 -1
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,
|
|
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
|
|
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
|
|
1069
|
+
let str = "";
|
|
1405
1070
|
for (let i = 0; i < length; i++) {
|
|
1406
|
-
|
|
1071
|
+
str += chars[Math.floor(Math.random() * chars.length)];
|
|
1407
1072
|
}
|
|
1408
|
-
return
|
|
1073
|
+
return str;
|
|
1409
1074
|
}
|
|
1410
|
-
function esc(
|
|
1411
|
-
return JSON.stringify(
|
|
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(
|
|
1526
|
-
return
|
|
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(
|
|
1781
|
-
const units =
|
|
1782
|
-
if (!highSurrogate.test(
|
|
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 ((
|
|
1451
|
+
if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {
|
|
1787
1452
|
count--;
|
|
1788
1453
|
i++;
|
|
1789
1454
|
}
|
|
@@ -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
|
}
|