@4pm/cli 1.25.0 → 1.27.0
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/index.js +142 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28557,11 +28557,12 @@ function fetchWhoami(serverUrl, hashcode3) {
|
|
|
28557
28557
|
function selfUnlink(serverUrl, hashcode3) {
|
|
28558
28558
|
return post(serverUrl, "/machine-links/self-unlink", { hashcode3 });
|
|
28559
28559
|
}
|
|
28560
|
-
async function fetchCliVersion(serverUrl) {
|
|
28560
|
+
async function fetchCliVersion(serverUrl, version) {
|
|
28561
28561
|
const ctrl = new AbortController();
|
|
28562
28562
|
const timer = setTimeout(() => ctrl.abort(), 2e4);
|
|
28563
28563
|
try {
|
|
28564
|
-
const
|
|
28564
|
+
const query = version ? `?version=${encodeURIComponent(version)}` : "";
|
|
28565
|
+
const res = await fetch(`${serverUrl}/meta/cli-version${query}`, { signal: ctrl.signal });
|
|
28565
28566
|
return unwrap(res);
|
|
28566
28567
|
} finally {
|
|
28567
28568
|
clearTimeout(timer);
|
|
@@ -28798,6 +28799,8 @@ var en_default = {
|
|
|
28798
28799
|
"update.updating": "Updating {from} \u2192 {to}\u2026",
|
|
28799
28800
|
"update.checkVersionFailed": "Could not check cli version: {error}",
|
|
28800
28801
|
"update.newVersionAutoUpdateOff": "A new version {latest} is available (running {current}) \u2014 autoUpdate is off.",
|
|
28802
|
+
"update.unsupportedSoon": "cli {current} stops being supported on {date} \u2014 update before then (4pm update).",
|
|
28803
|
+
"update.policyNote": "Note from 4PM: {note}",
|
|
28801
28804
|
"update.applying": "{kind} cli update {from} \u2192 {to}\u2026",
|
|
28802
28805
|
"update.kindMandatory": "Mandatory",
|
|
28803
28806
|
"update.kindAutomatic": "Automatic",
|
|
@@ -28981,6 +28984,8 @@ var vi_default = {
|
|
|
28981
28984
|
"update.updating": "\u0110ang c\u1EADp nh\u1EADt {from} \u2192 {to}\u2026",
|
|
28982
28985
|
"update.checkVersionFailed": "Kh\xF4ng th\u1EC3 ki\u1EC3m tra phi\xEAn b\u1EA3n cli: {error}",
|
|
28983
28986
|
"update.newVersionAutoUpdateOff": "C\xF3 phi\xEAn b\u1EA3n m\u1EDBi {latest} (\u0111ang ch\u1EA1y {current}) \u2014 autoUpdate \u0111ang t\u1EAFt.",
|
|
28987
|
+
"update.unsupportedSoon": "cli {current} s\u1EBD ng\u1EEBng \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3 t\u1EEB {date} \u2014 h\xE3y c\u1EADp nh\u1EADt tr\u01B0\u1EDBc ng\xE0y \u0111\xF3 (4pm update).",
|
|
28988
|
+
"update.policyNote": "Ghi ch\xFA t\u1EEB 4PM: {note}",
|
|
28984
28989
|
"update.applying": "C\u1EADp nh\u1EADt cli {kind} {from} \u2192 {to}\u2026",
|
|
28985
28990
|
"update.kindMandatory": "b\u1EAFt bu\u1ED9c",
|
|
28986
28991
|
"update.kindAutomatic": "t\u1EF1 \u0111\u1ED9ng",
|
|
@@ -29164,6 +29169,8 @@ var ja_default = {
|
|
|
29164
29169
|
"update.updating": "\u66F4\u65B0\u4E2D {from} \u2192 {to}\u2026",
|
|
29165
29170
|
"update.checkVersionFailed": "cli \u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F: {error}",
|
|
29166
29171
|
"update.newVersionAutoUpdateOff": "\u65B0\u3057\u3044\u30D0\u30FC\u30B8\u30E7\u30F3 {latest} \u304C\u5229\u7528\u53EF\u80FD\u3067\u3059\uFF08\u5B9F\u884C\u4E2D {current}\uFF09\u2014 autoUpdate \u306F\u30AA\u30D5\u3067\u3059\u3002",
|
|
29172
|
+
"update.unsupportedSoon": "cli {current} \u306F {date} \u306B\u30B5\u30DD\u30FC\u30C8\u304C\u7D42\u4E86\u3057\u307E\u3059 \u2014 \u305D\u308C\u307E\u3067\u306B\u66F4\u65B0\u3057\u3066\u304F\u3060\u3055\u3044\uFF084pm update\uFF09\u3002",
|
|
29173
|
+
"update.policyNote": "4PM \u304B\u3089\u306E\u304A\u77E5\u3089\u305B: {note}",
|
|
29167
29174
|
"update.applying": "{kind} \u306E cli \u66F4\u65B0 {from} \u2192 {to}\u2026",
|
|
29168
29175
|
"update.kindMandatory": "\u5FC5\u9808",
|
|
29169
29176
|
"update.kindAutomatic": "\u81EA\u52D5",
|
|
@@ -29347,6 +29354,8 @@ var zh_default = {
|
|
|
29347
29354
|
"update.updating": "\u6B63\u5728\u66F4\u65B0 {from} \u2192 {to}\u2026",
|
|
29348
29355
|
"update.checkVersionFailed": "\u65E0\u6CD5\u68C0\u67E5 cli \u7248\u672C\uFF1A{error}",
|
|
29349
29356
|
"update.newVersionAutoUpdateOff": "\u6709\u65B0\u7248\u672C {latest} \u53EF\u7528\uFF08\u5F53\u524D\u8FD0\u884C {current}\uFF09\u2014 autoUpdate \u5DF2\u5173\u95ED\u3002",
|
|
29357
|
+
"update.unsupportedSoon": "cli {current} \u5C06\u4E8E {date} \u505C\u6B62\u652F\u6301 \u2014 \u8BF7\u5728\u6B64\u4E4B\u524D\u66F4\u65B0\uFF084pm update\uFF09\u3002",
|
|
29358
|
+
"update.policyNote": "\u6765\u81EA 4PM \u7684\u8BF4\u660E\uFF1A{note}",
|
|
29350
29359
|
"update.applying": "{kind} cli \u66F4\u65B0 {from} \u2192 {to}\u2026",
|
|
29351
29360
|
"update.kindMandatory": "\u5F3A\u5236",
|
|
29352
29361
|
"update.kindAutomatic": "\u81EA\u52A8",
|
|
@@ -32701,12 +32710,18 @@ async function checkAndUpdate(serverUrl, autoUpdate) {
|
|
|
32701
32710
|
if (CLI_VERSION.startsWith("0.0.0")) return { action: "none" };
|
|
32702
32711
|
let meta;
|
|
32703
32712
|
try {
|
|
32704
|
-
meta = await fetchCliVersion(serverUrl);
|
|
32713
|
+
meta = await fetchCliVersion(serverUrl, CLI_VERSION);
|
|
32705
32714
|
} catch (err) {
|
|
32706
32715
|
console.warn(t("update.checkVersionFailed", { error: String(err) }));
|
|
32707
32716
|
return { action: "none" };
|
|
32708
32717
|
}
|
|
32709
|
-
const mandatory = compareSemver(CLI_VERSION, meta.minSupported) < 0;
|
|
32718
|
+
const mandatory = compareSemver(CLI_VERSION, meta.minSupported) < 0 || meta.status === "unsupported";
|
|
32719
|
+
if (meta.status === "warning" && meta.unsupportedFrom) {
|
|
32720
|
+
console.warn(t("update.unsupportedSoon", { current: CLI_VERSION, date: meta.unsupportedFrom.slice(0, 10) }));
|
|
32721
|
+
if (meta.note) console.warn(t("update.policyNote", { note: meta.note }));
|
|
32722
|
+
} else if (meta.status === "unsupported" && meta.note) {
|
|
32723
|
+
console.warn(t("update.policyNote", { note: meta.note }));
|
|
32724
|
+
}
|
|
32710
32725
|
const outdated = shouldUpdateTo(CLI_VERSION, meta.latest);
|
|
32711
32726
|
if (!outdated) return { action: "none" };
|
|
32712
32727
|
if (!mandatory && !autoUpdate) {
|
|
@@ -37255,6 +37270,67 @@ var agentToolsWriteRequestSchema = external_exports.object({
|
|
|
37255
37270
|
permissions: agentToolsPermissionsSchema
|
|
37256
37271
|
});
|
|
37257
37272
|
|
|
37273
|
+
// vendor/@4pm/dto/meta.ts
|
|
37274
|
+
var cliVersionString = external_exports.string().trim().regex(/^\d+\.\d+\.\d+([-+][0-9A-Za-z.-]+)?$/);
|
|
37275
|
+
var setCliMinVersionRequestSchema = external_exports.object({
|
|
37276
|
+
minSupported: cliVersionString.nullable(),
|
|
37277
|
+
disconnect: external_exports.boolean().optional()
|
|
37278
|
+
});
|
|
37279
|
+
var setCliVersionOverrideRequestSchema = external_exports.object({
|
|
37280
|
+
status: external_exports.enum(["supported", "warning", "unsupported"]),
|
|
37281
|
+
unsupportedFrom: external_exports.string().datetime({ offset: true }).nullable().optional(),
|
|
37282
|
+
note: external_exports.string().max(500).optional(),
|
|
37283
|
+
disconnect: external_exports.boolean().optional()
|
|
37284
|
+
});
|
|
37285
|
+
|
|
37286
|
+
// vendor/@4pm/dto/storage.ts
|
|
37287
|
+
var STORAGE_KINDS = [
|
|
37288
|
+
"messageText",
|
|
37289
|
+
"postText",
|
|
37290
|
+
"commentText",
|
|
37291
|
+
"memoText",
|
|
37292
|
+
"messageImages",
|
|
37293
|
+
"messageFiles",
|
|
37294
|
+
"postImages",
|
|
37295
|
+
"postFiles",
|
|
37296
|
+
"commentImages",
|
|
37297
|
+
"commentFiles",
|
|
37298
|
+
"memoImages",
|
|
37299
|
+
"memoFiles",
|
|
37300
|
+
"templates",
|
|
37301
|
+
"aiDocImages",
|
|
37302
|
+
"artifacts",
|
|
37303
|
+
"commandHistory"
|
|
37304
|
+
];
|
|
37305
|
+
var COMMUNITY_STORAGE_KINDS = [
|
|
37306
|
+
"messageText",
|
|
37307
|
+
"postText",
|
|
37308
|
+
"commentText",
|
|
37309
|
+
"messageImages",
|
|
37310
|
+
"messageFiles",
|
|
37311
|
+
"postImages",
|
|
37312
|
+
"postFiles",
|
|
37313
|
+
"commentImages",
|
|
37314
|
+
"commentFiles"
|
|
37315
|
+
];
|
|
37316
|
+
var SERVER_CLEARABLE_STORAGE_KINDS = [
|
|
37317
|
+
"memoText",
|
|
37318
|
+
"memoImages",
|
|
37319
|
+
"memoFiles",
|
|
37320
|
+
"templates",
|
|
37321
|
+
"commandHistory"
|
|
37322
|
+
];
|
|
37323
|
+
var CLEARABLE_STORAGE_KINDS = [
|
|
37324
|
+
...COMMUNITY_STORAGE_KINDS,
|
|
37325
|
+
...SERVER_CLEARABLE_STORAGE_KINDS
|
|
37326
|
+
];
|
|
37327
|
+
var storageClearRequestSchema = external_exports.object({
|
|
37328
|
+
kinds: external_exports.array(external_exports.enum(STORAGE_KINDS)).min(1).max(STORAGE_KINDS.length),
|
|
37329
|
+
before: external_exports.string().datetime({ offset: true }),
|
|
37330
|
+
/** org-0009 / community-0015 only — must equal the org name. */
|
|
37331
|
+
confirm: external_exports.string().max(200).optional()
|
|
37332
|
+
});
|
|
37333
|
+
|
|
37258
37334
|
// vendor/@4pm/dto/org.ts
|
|
37259
37335
|
var CLI_SETTINGS_BOUNDS = {
|
|
37260
37336
|
reconnectMaxBackoffSec: { min: 5, max: 60 },
|
|
@@ -37274,6 +37350,8 @@ var TEMPLATE_KINDS = ["report", "est", "wbs", "proposal", "feasibility"];
|
|
|
37274
37350
|
// vendor/@4pm/dto/project.ts
|
|
37275
37351
|
var listProjectsQuerySchema = baseRequestSchema.extend({
|
|
37276
37352
|
pinned: pinnedFilterSchema,
|
|
37353
|
+
/** Only projects this team is attached to (project-0001; the public v1 list — ADR-0364). */
|
|
37354
|
+
teamId: external_exports.string().uuid().optional(),
|
|
37277
37355
|
/** ADMIN-only Trash: list soft-deleted projects (ADR-0109). */
|
|
37278
37356
|
deleted: deletedFilterSchema
|
|
37279
37357
|
});
|
|
@@ -38370,6 +38448,9 @@ var WsChannels = {
|
|
|
38370
38448
|
QUOTA_CHECK: "quota.check",
|
|
38371
38449
|
// cli → server (reply): per-org concurrent AI-run slot — acquire / renew / release (ADR-0359)
|
|
38372
38450
|
RUN_SLOT: "run.slot",
|
|
38451
|
+
// cli → server (reply): read / add the org's monthly autonomous-book counters — USER_TODO / USER_QA /
|
|
38452
|
+
// AI_TODO rows vs `autonomousRequestsPerMonth` (ADR-0365)
|
|
38453
|
+
AUTONOMOUS_BOOK_USAGE: "autonomous.bookUsage",
|
|
38373
38454
|
USAGE_REPORT: "usage.report",
|
|
38374
38455
|
// cli → server: Claude subscription usage snapshot (5h / weekly — ADR-0072)
|
|
38375
38456
|
MACHINE_USAGE: "machine.usage",
|
|
@@ -40447,6 +40528,14 @@ function tableRowsById(md) {
|
|
|
40447
40528
|
}
|
|
40448
40529
|
return rows;
|
|
40449
40530
|
}
|
|
40531
|
+
var CAPPED_BOOK_FILES = { USER_TODO: "USER_TODO.md", USER_QA: "USER_QA.md", AI_TODO: "AI_TODO.md" };
|
|
40532
|
+
async function cappedBookIds(root) {
|
|
40533
|
+
const out = {};
|
|
40534
|
+
for (const [book, file] of Object.entries(CAPPED_BOOK_FILES)) {
|
|
40535
|
+
out[book] = new Set(tableRowsById(await readText(join17(root, file))).keys());
|
|
40536
|
+
}
|
|
40537
|
+
return out;
|
|
40538
|
+
}
|
|
40450
40539
|
function tickScript(root) {
|
|
40451
40540
|
return join17(root, TICK_REL);
|
|
40452
40541
|
}
|
|
@@ -40538,6 +40627,7 @@ async function uninstallCron(root) {
|
|
|
40538
40627
|
await crontabSet(kept.join("\n"));
|
|
40539
40628
|
}
|
|
40540
40629
|
async function writeAutonomous(root, profileDir2, req, by) {
|
|
40630
|
+
let added;
|
|
40541
40631
|
try {
|
|
40542
40632
|
switch (req.kind) {
|
|
40543
40633
|
case "settings": {
|
|
@@ -40582,6 +40672,7 @@ async function writeAutonomous(root, profileDir2, req, by) {
|
|
|
40582
40672
|
const row = `| ${id} | | | ${tableCell(req.content)} |
|
|
40583
40673
|
`;
|
|
40584
40674
|
await writeFile4(join17(root, BOOK_FILES.userTodo), cur.replace(/\s*$/, "\n") + row, "utf8");
|
|
40675
|
+
added = 1;
|
|
40585
40676
|
const authors = await readJsonMap(join17(root, AUTHORS_REL));
|
|
40586
40677
|
authors[id] = { by, byLabel: req.byLabel ?? by, at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
40587
40678
|
await writeFile4(join17(root, AUTHORS_REL), JSON.stringify(authors, null, 2) + "\n", "utf8");
|
|
@@ -40594,8 +40685,10 @@ async function writeAutonomous(root, profileDir2, req, by) {
|
|
|
40594
40685
|
const authors = await readJsonMap(join17(root, AUTHORS_REL));
|
|
40595
40686
|
const at2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
40596
40687
|
const byLabel = req.byLabel ?? by;
|
|
40688
|
+
added = 0;
|
|
40597
40689
|
for (const [id, cells] of next) {
|
|
40598
40690
|
if (prev.get(id) !== cells) authors[id] = { by, byLabel, at: at2 };
|
|
40691
|
+
if (!prev.has(id)) added += 1;
|
|
40599
40692
|
}
|
|
40600
40693
|
await writeFile4(join17(root, file), req.content, "utf8");
|
|
40601
40694
|
await writeFile4(join17(root, AUTHORS_REL), JSON.stringify(authors, null, 2) + "\n", "utf8");
|
|
@@ -40607,7 +40700,7 @@ async function writeAutonomous(root, profileDir2, req, by) {
|
|
|
40607
40700
|
break;
|
|
40608
40701
|
}
|
|
40609
40702
|
}
|
|
40610
|
-
return { ok: true, status: await getAutonomousStatus(root, profileDir2) };
|
|
40703
|
+
return { ok: true, status: await getAutonomousStatus(root, profileDir2), ...added !== void 0 ? { added } : {} };
|
|
40611
40704
|
} catch (err) {
|
|
40612
40705
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
40613
40706
|
}
|
|
@@ -41682,6 +41775,7 @@ async function acquireRunSlot(ctx, onQueued, signal) {
|
|
|
41682
41775
|
}
|
|
41683
41776
|
return { kind: "granted", handle, queued: ticket !== void 0 };
|
|
41684
41777
|
}
|
|
41778
|
+
if ("denied" in reply) return { kind: "denied", reason: reply.denied };
|
|
41685
41779
|
ticket = reply.ticket;
|
|
41686
41780
|
limit = reply.limit;
|
|
41687
41781
|
if (reply.position !== lastPosition) {
|
|
@@ -41996,6 +42090,13 @@ ${guardedPrompt}`;
|
|
|
41996
42090
|
const text = `RUN_QUEUE_TIMEOUT: waited 30 min for a free run slot (plan limit ${slot.limit} parallel runs) \u2014 not run`;
|
|
41997
42091
|
ctx.bus.push({ source: origin, kind: "log", text, level: "warn" });
|
|
41998
42092
|
ctx.send(WsChannels.COMMAND_OUTPUT, { commandId, seq: seq++, chunk: `${text}
|
|
42093
|
+
`, log: true });
|
|
42094
|
+
result = { exitCode: 1, workedDir: null, workedKey: null, workedCmd: null, usage: { tokens: 0, input: 0, output: 0, cacheRead: 0, cacheCreation: 0 }, sessionId: "" };
|
|
42095
|
+
} else if (slot.kind === "denied") {
|
|
42096
|
+
neverStarted = true;
|
|
42097
|
+
const text = "STORAGE_QUOTA_EXCEEDED: the organization's hosted storage is full \u2014 clear storage in Settings \u203A Storage, then retry";
|
|
42098
|
+
ctx.bus.push({ source: origin, kind: "log", text, level: "warn" });
|
|
42099
|
+
ctx.send(WsChannels.COMMAND_OUTPUT, { commandId, seq: seq++, chunk: `${text}
|
|
41999
42100
|
`, log: true });
|
|
42000
42101
|
result = { exitCode: 1, workedDir: null, workedKey: null, workedCmd: null, usage: { tokens: 0, input: 0, output: 0, cacheRead: 0, cacheCreation: 0 }, sessionId: "" };
|
|
42001
42102
|
} else if (slot.kind === "cancelled") {
|
|
@@ -42320,12 +42421,17 @@ function rejectByReview(ctx, commandId, origin, prompt, reasons) {
|
|
|
42320
42421
|
import { randomUUID } from "crypto";
|
|
42321
42422
|
import { appendFile as appendFile2, mkdir as mkdir3, readFile as readFile5, readdir as readdir2, rm as rm2, stat } from "fs/promises";
|
|
42322
42423
|
import { join as join20 } from "path";
|
|
42323
|
-
function buildAutonomousCyclePrompt() {
|
|
42424
|
+
function buildAutonomousCyclePrompt(opts = {}) {
|
|
42425
|
+
const capNote = opts.intakeBlocked ? `
|
|
42426
|
+
|
|
42427
|
+
**Step 2 is DISABLED this cycle** \u2014 the organization reached its monthly plan limit for new \`AI_TODO\` /
|
|
42428
|
+
\`USER_QA\` rows. Do NOT add any row to \`AI_TODO.md\` or \`USER_QA.md\`; skip Step 2 entirely and continue
|
|
42429
|
+
with the already-approved work.` : "";
|
|
42324
42430
|
return `You are running UNATTENDED as the 4PM autonomous cycle (headless, one tick). Do EXACTLY ONE small
|
|
42325
42431
|
work cycle with the steps below, then STOP. Keep each cycle to ONE small task so you never run out of
|
|
42326
42432
|
tokens mid-way. If a step fails, append a row to the **Incidents** table of \`AI_DONE.md\` and STOP \u2014
|
|
42327
42433
|
do not push on. Write all books/docs/code in the language the project's \`CLAUDE.md\` specifies (default
|
|
42328
|
-
English)
|
|
42434
|
+
English).${capNote}
|
|
42329
42435
|
|
|
42330
42436
|
## Books & approval (MUST read the approvals file)
|
|
42331
42437
|
The five "book" files at the project root \u2014 \`USER_TODO.md\`, \`USER_QA.md\`, \`AI_TODO.md\`,
|
|
@@ -42459,8 +42565,16 @@ async function runAutonomousCycle(ctx) {
|
|
|
42459
42565
|
await log(`[run] cycle (tick ${hist.ticks.count}/${today})`);
|
|
42460
42566
|
const commandId = randomUUID();
|
|
42461
42567
|
const override = cfg.model ? { model: cfg.model } : void 0;
|
|
42568
|
+
const usage = await readBookUsage(ctx);
|
|
42569
|
+
const intakeBlocked = ["AI_TODO", "USER_QA"].some((b2) => {
|
|
42570
|
+
const c = usage?.books[b2];
|
|
42571
|
+
return !!c && c.limit !== null && c.used >= c.limit;
|
|
42572
|
+
});
|
|
42573
|
+
if (intakeBlocked) await log("[cap] monthly AI_TODO/USER_QA limit reached \u2014 intake skipped this cycle");
|
|
42574
|
+
const booksBefore = await cappedBookIds(root);
|
|
42462
42575
|
try {
|
|
42463
|
-
await runAiPrompt(ctx, buildAutonomousCyclePrompt(), commandId, "local", false, void 0, override, false, true);
|
|
42576
|
+
await runAiPrompt(ctx, buildAutonomousCyclePrompt({ intakeBlocked }), commandId, "local", false, void 0, override, false, true);
|
|
42577
|
+
await reportNewBookRows(ctx, root, booksBefore);
|
|
42464
42578
|
hist = await readHistories(root);
|
|
42465
42579
|
hist.consecutiveFails = 0;
|
|
42466
42580
|
await recordRun(root, hist, "success", "cycle complete", today);
|
|
@@ -42468,6 +42582,7 @@ async function runAutonomousCycle(ctx) {
|
|
|
42468
42582
|
ctx.bus.autonomousDone(true);
|
|
42469
42583
|
} catch (err) {
|
|
42470
42584
|
const msg = err instanceof Error ? err.message : String(err);
|
|
42585
|
+
await reportNewBookRows(ctx, root, booksBefore);
|
|
42471
42586
|
hist = await readHistories(root);
|
|
42472
42587
|
hist.consecutiveFails += 1;
|
|
42473
42588
|
await recordRun(root, hist, "failure", msg, today);
|
|
@@ -42484,6 +42599,25 @@ async function runAutonomousCycle(ctx) {
|
|
|
42484
42599
|
running.delete(root);
|
|
42485
42600
|
}
|
|
42486
42601
|
}
|
|
42602
|
+
async function readBookUsage(ctx) {
|
|
42603
|
+
try {
|
|
42604
|
+
return await ctx.request(WsChannels.AUTONOMOUS_BOOK_USAGE, {});
|
|
42605
|
+
} catch {
|
|
42606
|
+
return null;
|
|
42607
|
+
}
|
|
42608
|
+
}
|
|
42609
|
+
async function reportNewBookRows(ctx, root, before) {
|
|
42610
|
+
try {
|
|
42611
|
+
const after = await cappedBookIds(root);
|
|
42612
|
+
const added = {};
|
|
42613
|
+
for (const book of Object.keys(after)) {
|
|
42614
|
+
const n = [...after[book]].filter((id) => !before[book].has(id)).length;
|
|
42615
|
+
if (n > 0) added[book] = n;
|
|
42616
|
+
}
|
|
42617
|
+
if (Object.keys(added).length > 0) await ctx.request(WsChannels.AUTONOMOUS_BOOK_USAGE, { added });
|
|
42618
|
+
} catch {
|
|
42619
|
+
}
|
|
42620
|
+
}
|
|
42487
42621
|
async function dayLog(root, line) {
|
|
42488
42622
|
try {
|
|
42489
42623
|
const dir2 = join20(root, ".claude", "logs");
|