@staff0rd/assist 0.381.0 → 0.382.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/commands/sessions/web/bundle.js +72 -72
- package/dist/index.js +481 -296
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.382.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -432,10 +432,10 @@ function getTranscriptConfig() {
|
|
|
432
432
|
// src/shared/db/schema.ts
|
|
433
433
|
import {
|
|
434
434
|
foreignKey,
|
|
435
|
-
integer as
|
|
436
|
-
pgTable as
|
|
437
|
-
primaryKey as
|
|
438
|
-
text as
|
|
435
|
+
integer as integer9,
|
|
436
|
+
pgTable as pgTable9,
|
|
437
|
+
primaryKey as primaryKey6,
|
|
438
|
+
text as text8
|
|
439
439
|
} from "drizzle-orm/pg-core";
|
|
440
440
|
|
|
441
441
|
// src/shared/db/backups.ts
|
|
@@ -536,82 +536,96 @@ var phaseUsage = pgTable6(
|
|
|
536
536
|
(t) => [primaryKey3({ columns: [t.itemId, t.phaseIdx] })]
|
|
537
537
|
);
|
|
538
538
|
|
|
539
|
+
// src/shared/db/phaseUsageMessages.ts
|
|
540
|
+
import { integer as integer7, pgTable as pgTable7, primaryKey as primaryKey4, text as text6 } from "drizzle-orm/pg-core";
|
|
541
|
+
var phaseUsageMessages = pgTable7(
|
|
542
|
+
"phase_usage_messages",
|
|
543
|
+
{
|
|
544
|
+
itemId: integer7("item_id").notNull(),
|
|
545
|
+
phaseIdx: integer7("phase_idx").notNull(),
|
|
546
|
+
messageId: text6("message_id").notNull()
|
|
547
|
+
},
|
|
548
|
+
(t) => [primaryKey4({ columns: [t.itemId, t.phaseIdx, t.messageId] })]
|
|
549
|
+
);
|
|
550
|
+
|
|
539
551
|
// src/shared/db/usagePeaks.ts
|
|
540
552
|
import {
|
|
541
553
|
bigint as bigint3,
|
|
542
554
|
boolean as boolean2,
|
|
543
555
|
doublePrecision,
|
|
544
|
-
integer as
|
|
545
|
-
pgTable as
|
|
546
|
-
primaryKey as
|
|
547
|
-
text as
|
|
556
|
+
integer as integer8,
|
|
557
|
+
pgTable as pgTable8,
|
|
558
|
+
primaryKey as primaryKey5,
|
|
559
|
+
text as text7,
|
|
548
560
|
timestamp as timestamp4
|
|
549
561
|
} from "drizzle-orm/pg-core";
|
|
550
|
-
var usagePeaks =
|
|
562
|
+
var usagePeaks = pgTable8(
|
|
551
563
|
"usage_peaks",
|
|
552
564
|
{
|
|
553
|
-
window:
|
|
565
|
+
window: text7().$type().notNull(),
|
|
554
566
|
resetsAt: bigint3("resets_at", { mode: "number" }).notNull(),
|
|
555
|
-
segment:
|
|
567
|
+
segment: integer8().notNull().default(0),
|
|
556
568
|
usedPercentage: doublePrecision("used_percentage").notNull(),
|
|
557
569
|
resetDetected: boolean2("reset_detected").notNull().default(false),
|
|
570
|
+
tokensUp: bigint3("tokens_up", { mode: "number" }).notNull().default(0),
|
|
571
|
+
tokensDown: bigint3("tokens_down", { mode: "number" }).notNull().default(0),
|
|
558
572
|
createdAt: timestamp4("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
559
573
|
},
|
|
560
|
-
(t) => [
|
|
574
|
+
(t) => [primaryKey5({ columns: [t.window, t.resetsAt, t.segment] })]
|
|
561
575
|
);
|
|
562
576
|
|
|
563
577
|
// src/shared/db/schema.ts
|
|
564
|
-
var comments =
|
|
565
|
-
id:
|
|
566
|
-
itemId:
|
|
567
|
-
idx:
|
|
568
|
-
text:
|
|
569
|
-
phase:
|
|
570
|
-
timestamp:
|
|
571
|
-
type:
|
|
578
|
+
var comments = pgTable9("comments", {
|
|
579
|
+
id: integer9().generatedByDefaultAsIdentity().primaryKey(),
|
|
580
|
+
itemId: integer9("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
|
|
581
|
+
idx: integer9().notNull(),
|
|
582
|
+
text: text8().notNull(),
|
|
583
|
+
phase: integer9(),
|
|
584
|
+
timestamp: text8().notNull(),
|
|
585
|
+
type: text8().notNull().default("comment")
|
|
572
586
|
});
|
|
573
|
-
var links =
|
|
587
|
+
var links = pgTable9(
|
|
574
588
|
"links",
|
|
575
589
|
{
|
|
576
|
-
itemId:
|
|
577
|
-
type:
|
|
578
|
-
targetId:
|
|
590
|
+
itemId: integer9("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
|
|
591
|
+
type: text8().notNull(),
|
|
592
|
+
targetId: integer9("target_id").notNull()
|
|
579
593
|
},
|
|
580
|
-
(t) => [
|
|
594
|
+
(t) => [primaryKey6({ columns: [t.itemId, t.type, t.targetId] })]
|
|
581
595
|
);
|
|
582
|
-
var planPhases =
|
|
596
|
+
var planPhases = pgTable9(
|
|
583
597
|
"plan_phases",
|
|
584
598
|
{
|
|
585
|
-
itemId:
|
|
586
|
-
idx:
|
|
587
|
-
name:
|
|
588
|
-
manualChecks:
|
|
599
|
+
itemId: integer9("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
|
|
600
|
+
idx: integer9().notNull(),
|
|
601
|
+
name: text8().notNull(),
|
|
602
|
+
manualChecks: text8("manual_checks")
|
|
589
603
|
},
|
|
590
|
-
(t) => [
|
|
604
|
+
(t) => [primaryKey6({ columns: [t.itemId, t.idx] })]
|
|
591
605
|
);
|
|
592
|
-
var planTasks =
|
|
606
|
+
var planTasks = pgTable9(
|
|
593
607
|
"plan_tasks",
|
|
594
608
|
{
|
|
595
|
-
itemId:
|
|
596
|
-
phaseIdx:
|
|
597
|
-
idx:
|
|
598
|
-
task:
|
|
609
|
+
itemId: integer9("item_id").notNull(),
|
|
610
|
+
phaseIdx: integer9("phase_idx").notNull(),
|
|
611
|
+
idx: integer9().notNull(),
|
|
612
|
+
task: text8().notNull()
|
|
599
613
|
},
|
|
600
614
|
(t) => [
|
|
601
|
-
|
|
615
|
+
primaryKey6({ columns: [t.itemId, t.phaseIdx, t.idx] }),
|
|
602
616
|
foreignKey({
|
|
603
617
|
columns: [t.itemId, t.phaseIdx],
|
|
604
618
|
foreignColumns: [planPhases.itemId, planPhases.idx]
|
|
605
619
|
}).onDelete("cascade")
|
|
606
620
|
]
|
|
607
621
|
);
|
|
608
|
-
var metadata =
|
|
609
|
-
key:
|
|
610
|
-
value:
|
|
622
|
+
var metadata = pgTable9("metadata", {
|
|
623
|
+
key: text8().primaryKey(),
|
|
624
|
+
value: text8().notNull()
|
|
611
625
|
});
|
|
612
|
-
var feeds =
|
|
613
|
-
id:
|
|
614
|
-
url:
|
|
626
|
+
var feeds = pgTable9("feeds", {
|
|
627
|
+
id: integer9().generatedByDefaultAsIdentity().primaryKey(),
|
|
628
|
+
url: text8().notNull().unique()
|
|
615
629
|
});
|
|
616
630
|
var schema = {
|
|
617
631
|
items,
|
|
@@ -626,7 +640,8 @@ var schema = {
|
|
|
626
640
|
handovers,
|
|
627
641
|
usagePeaks,
|
|
628
642
|
backups,
|
|
629
|
-
phaseUsage
|
|
643
|
+
phaseUsage,
|
|
644
|
+
phaseUsageMessages
|
|
630
645
|
};
|
|
631
646
|
|
|
632
647
|
// src/commands/backlog/addFeed.ts
|
|
@@ -662,30 +677,27 @@ async function seedNewsFeeds(db) {
|
|
|
662
677
|
import { and as and2, eq as eq2 } from "drizzle-orm";
|
|
663
678
|
|
|
664
679
|
// src/shared/db/recordWindowPeak.ts
|
|
665
|
-
import {
|
|
680
|
+
import { sql } from "drizzle-orm";
|
|
681
|
+
|
|
682
|
+
// src/shared/db/applyReading.ts
|
|
683
|
+
import { and, eq, gt } from "drizzle-orm";
|
|
666
684
|
var RESET_DROP_THRESHOLD = 1;
|
|
667
685
|
var at = ({ window, resetsAt }, segment) => segment === void 0 ? and(eq(usagePeaks.window, window), eq(usagePeaks.resetsAt, resetsAt)) : and(
|
|
668
686
|
eq(usagePeaks.window, window),
|
|
669
687
|
eq(usagePeaks.resetsAt, resetsAt),
|
|
670
688
|
eq(usagePeaks.segment, segment)
|
|
671
689
|
);
|
|
672
|
-
var lock = ({ tx, window, resetsAt }) => tx.execute(
|
|
673
|
-
sql`SELECT pg_advisory_xact_lock(hashtextextended(${`${window}:${resetsAt}`}, 0))`
|
|
674
|
-
);
|
|
675
|
-
var load = (c) => c.tx.select().from(usagePeaks).where(at(c)).orderBy(usagePeaks.segment);
|
|
676
690
|
var insertSegment = (c, segment, usedPercentage) => c.tx.insert(usagePeaks).values({
|
|
677
691
|
window: c.window,
|
|
678
692
|
resetsAt: c.resetsAt,
|
|
679
693
|
segment,
|
|
680
694
|
usedPercentage
|
|
681
695
|
});
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
await c.tx.update(usagePeaks).set({ resetDetected: true }).where(at(c, active.segment));
|
|
688
|
-
await insertSegment(c, active.segment + 1, usedPercentage);
|
|
696
|
+
var load = (c) => c.tx.select().from(usagePeaks).where(at(c)).orderBy(usagePeaks.segment);
|
|
697
|
+
async function applyReading(c, usedPercentage) {
|
|
698
|
+
const segments = await load(c);
|
|
699
|
+
if (segments.length === 0) await insertSegment(c, 0, usedPercentage);
|
|
700
|
+
else await reconcile(c, segments, usedPercentage);
|
|
689
701
|
}
|
|
690
702
|
async function reconcile(c, segments, usedPercentage) {
|
|
691
703
|
const reached = segments.find((s) => usedPercentage >= s.usedPercentage);
|
|
@@ -698,13 +710,24 @@ async function reconcile(c, segments, usedPercentage) {
|
|
|
698
710
|
await openReset(c, active, usedPercentage);
|
|
699
711
|
}
|
|
700
712
|
}
|
|
713
|
+
async function collapseToReached(c, reached, usedPercentage) {
|
|
714
|
+
await c.tx.delete(usagePeaks).where(and(at(c), gt(usagePeaks.segment, reached.segment)));
|
|
715
|
+
await c.tx.update(usagePeaks).set({ usedPercentage, resetDetected: false }).where(at(c, reached.segment));
|
|
716
|
+
}
|
|
717
|
+
async function openReset(c, active, usedPercentage) {
|
|
718
|
+
await c.tx.update(usagePeaks).set({ resetDetected: true }).where(at(c, active.segment));
|
|
719
|
+
await insertSegment(c, active.segment + 1, usedPercentage);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// src/shared/db/recordWindowPeak.ts
|
|
723
|
+
var lock = ({ tx, window, resetsAt }) => tx.execute(
|
|
724
|
+
sql`SELECT pg_advisory_xact_lock(hashtextextended(${`${window}:${resetsAt}`}, 0))`
|
|
725
|
+
);
|
|
701
726
|
async function recordWindowPeak(db, window, resetsAt, usedPercentage) {
|
|
702
727
|
await db.transaction(async (tx) => {
|
|
703
728
|
const c = { tx, window, resetsAt };
|
|
704
729
|
await lock(c);
|
|
705
|
-
|
|
706
|
-
if (segments.length === 0) await insertSegment(c, 0, usedPercentage);
|
|
707
|
-
else await reconcile(c, segments, usedPercentage);
|
|
730
|
+
await applyReading(c, usedPercentage);
|
|
708
731
|
});
|
|
709
732
|
}
|
|
710
733
|
|
|
@@ -859,6 +882,8 @@ var SCHEMA = `
|
|
|
859
882
|
segment INTEGER NOT NULL DEFAULT 0,
|
|
860
883
|
used_percentage DOUBLE PRECISION NOT NULL,
|
|
861
884
|
reset_detected BOOLEAN NOT NULL DEFAULT false,
|
|
885
|
+
tokens_up BIGINT NOT NULL DEFAULT 0,
|
|
886
|
+
tokens_down BIGINT NOT NULL DEFAULT 0,
|
|
862
887
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
863
888
|
PRIMARY KEY ("window", resets_at, segment)
|
|
864
889
|
);
|
|
@@ -867,6 +892,8 @@ var SCHEMA = `
|
|
|
867
892
|
ALTER TABLE usage_peaks ADD COLUMN IF NOT EXISTS reset_detected BOOLEAN NOT NULL DEFAULT false;
|
|
868
893
|
ALTER TABLE usage_peaks ADD COLUMN IF NOT EXISTS segment INTEGER NOT NULL DEFAULT 0;
|
|
869
894
|
ALTER TABLE usage_peaks ADD COLUMN IF NOT EXISTS created_at TIMESTAMPTZ NOT NULL DEFAULT now();
|
|
895
|
+
ALTER TABLE usage_peaks ADD COLUMN IF NOT EXISTS tokens_up BIGINT NOT NULL DEFAULT 0;
|
|
896
|
+
ALTER TABLE usage_peaks ADD COLUMN IF NOT EXISTS tokens_down BIGINT NOT NULL DEFAULT 0;
|
|
870
897
|
|
|
871
898
|
-- Widen the primary key to include segment so a cycle can hold both its
|
|
872
899
|
-- pre-reset peak and its post-reset continuation. Idempotent: only fires
|
|
@@ -907,6 +934,16 @@ var SCHEMA = `
|
|
|
907
934
|
PRIMARY KEY (item_id, phase_idx)
|
|
908
935
|
);
|
|
909
936
|
|
|
937
|
+
ALTER TABLE phase_usage ADD COLUMN IF NOT EXISTS last_total_in BIGINT;
|
|
938
|
+
ALTER TABLE phase_usage ADD COLUMN IF NOT EXISTS last_total_out BIGINT;
|
|
939
|
+
|
|
940
|
+
CREATE TABLE IF NOT EXISTS phase_usage_messages (
|
|
941
|
+
item_id INTEGER NOT NULL REFERENCES items(id) ON DELETE CASCADE,
|
|
942
|
+
phase_idx INTEGER NOT NULL,
|
|
943
|
+
message_id TEXT NOT NULL,
|
|
944
|
+
PRIMARY KEY (item_id, phase_idx, message_id)
|
|
945
|
+
);
|
|
946
|
+
|
|
910
947
|
-- Git activity (branch/commit/PR) snapshotted for an item during a run. The
|
|
911
948
|
-- (item_id, kind, ref) primary key makes re-snapshotting the same ref a no-op
|
|
912
949
|
-- upsert rather than a duplicate row.
|
|
@@ -973,7 +1010,7 @@ function createPool() {
|
|
|
973
1010
|
return pool;
|
|
974
1011
|
}
|
|
975
1012
|
async function initSchema(pool) {
|
|
976
|
-
await ensureSchema((
|
|
1013
|
+
await ensureSchema((sql13) => pool.query(sql13));
|
|
977
1014
|
const orm = makeOrmFromPool(pool);
|
|
978
1015
|
await seedNewsFeeds(orm);
|
|
979
1016
|
await runUsagePeakCleanup(orm);
|
|
@@ -2564,8 +2601,8 @@ function isHashCommentFile(filePath) {
|
|
|
2564
2601
|
import fs13 from "fs";
|
|
2565
2602
|
|
|
2566
2603
|
// src/commands/verify/blockComments/collectHashComments.ts
|
|
2567
|
-
function blankNonNewline(
|
|
2568
|
-
return
|
|
2604
|
+
function blankNonNewline(text10) {
|
|
2605
|
+
return text10.replace(/[^\n]/g, " ");
|
|
2569
2606
|
}
|
|
2570
2607
|
function isHeaderLine(line) {
|
|
2571
2608
|
const trimmed = line.trim();
|
|
@@ -2642,23 +2679,23 @@ var MACHINE_DIRECTIVES = [
|
|
|
2642
2679
|
"@vitest-environment",
|
|
2643
2680
|
MAINTAINABILITY_OVERRIDE_MARKER
|
|
2644
2681
|
];
|
|
2645
|
-
function isCommentExempt(
|
|
2646
|
-
const lower =
|
|
2682
|
+
function isCommentExempt(text10) {
|
|
2683
|
+
const lower = text10.toLowerCase();
|
|
2647
2684
|
return MACHINE_DIRECTIVES.some((d) => lower.includes(d));
|
|
2648
2685
|
}
|
|
2649
2686
|
|
|
2650
2687
|
// src/commands/verify/blockComments/collectSourceFindings.ts
|
|
2651
|
-
function toSingleLine(
|
|
2652
|
-
return
|
|
2688
|
+
function toSingleLine(text10) {
|
|
2689
|
+
return text10.replace(/\s+/g, " ").trim();
|
|
2653
2690
|
}
|
|
2654
2691
|
function collectSourceFindings(file, lines, project) {
|
|
2655
2692
|
const findings = [];
|
|
2656
2693
|
const sourceFile = project.addSourceFileAtPath(file);
|
|
2657
|
-
for (const { pos, text:
|
|
2694
|
+
for (const { pos, text: text10 } of collectComments(sourceFile)) {
|
|
2658
2695
|
const { line } = sourceFile.getLineAndColumnAtPos(pos);
|
|
2659
2696
|
if (!lines.has(line)) continue;
|
|
2660
|
-
if (isCommentExempt(
|
|
2661
|
-
findings.push({ file, line, text: toSingleLine(
|
|
2697
|
+
if (isCommentExempt(text10)) continue;
|
|
2698
|
+
findings.push({ file, line, text: toSingleLine(text10) });
|
|
2662
2699
|
}
|
|
2663
2700
|
return findings;
|
|
2664
2701
|
}
|
|
@@ -2678,10 +2715,10 @@ function collectYamlComments(content) {
|
|
|
2678
2715
|
// src/commands/verify/blockComments/collectFileComments.ts
|
|
2679
2716
|
function toFindings(file, lines, raw, exempt) {
|
|
2680
2717
|
const findings = [];
|
|
2681
|
-
for (const { line, text:
|
|
2718
|
+
for (const { line, text: text10 } of raw) {
|
|
2682
2719
|
if (!lines.has(line)) continue;
|
|
2683
|
-
if (exempt && isCommentExempt(
|
|
2684
|
-
findings.push({ file, line, text:
|
|
2720
|
+
if (exempt && isCommentExempt(text10)) continue;
|
|
2721
|
+
findings.push({ file, line, text: text10.replace(/\s+/g, " ").trim() });
|
|
2685
2722
|
}
|
|
2686
2723
|
return findings;
|
|
2687
2724
|
}
|
|
@@ -2779,8 +2816,8 @@ function blockComments() {
|
|
|
2779
2816
|
process.exit(0);
|
|
2780
2817
|
}
|
|
2781
2818
|
console.log("Comments on changed lines:\n");
|
|
2782
|
-
for (const { file, line, text:
|
|
2783
|
-
console.log(`${file}:${line} \u2192 ${
|
|
2819
|
+
for (const { file, line, text: text10 } of findings) {
|
|
2820
|
+
console.log(`${file}:${line} \u2192 ${text10}`);
|
|
2784
2821
|
}
|
|
2785
2822
|
console.log(`
|
|
2786
2823
|
Total: ${findings.length} comment(s)`);
|
|
@@ -4053,8 +4090,8 @@ async function buildDump(tables, copyOut) {
|
|
|
4053
4090
|
// src/commands/backlog/dump/copyTableOut.ts
|
|
4054
4091
|
import { to as copyTo } from "pg-copy-streams";
|
|
4055
4092
|
async function copyTableOut(client, table) {
|
|
4056
|
-
const
|
|
4057
|
-
const stream = client.query(copyTo(
|
|
4093
|
+
const sql13 = `COPY ${table.name} (${table.columns.join(", ")}) TO STDOUT`;
|
|
4094
|
+
const stream = client.query(copyTo(sql13));
|
|
4058
4095
|
const chunks = [];
|
|
4059
4096
|
for await (const chunk of stream) {
|
|
4060
4097
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
@@ -4596,11 +4633,11 @@ import { promisify } from "util";
|
|
|
4596
4633
|
// src/shared/withSpinner.ts
|
|
4597
4634
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
4598
4635
|
var TICK_MS = 80;
|
|
4599
|
-
async function withSpinner(
|
|
4636
|
+
async function withSpinner(text10, task) {
|
|
4600
4637
|
if (!process.stderr.isTTY) return task();
|
|
4601
4638
|
let frame = 0;
|
|
4602
4639
|
const render = () => {
|
|
4603
|
-
process.stderr.write(`\r${SPINNER_FRAMES[frame]} ${
|
|
4640
|
+
process.stderr.write(`\r${SPINNER_FRAMES[frame]} ${text10}`);
|
|
4604
4641
|
};
|
|
4605
4642
|
render();
|
|
4606
4643
|
const timer = setInterval(() => {
|
|
@@ -4937,6 +4974,18 @@ function attachSubtasks(item, rel, id) {
|
|
|
4937
4974
|
if (subtasks.length > 0) item.subtasks = subtasks;
|
|
4938
4975
|
}
|
|
4939
4976
|
|
|
4977
|
+
// src/commands/backlog/sumPhaseUsage.ts
|
|
4978
|
+
function sumPhaseUsage(usage) {
|
|
4979
|
+
return usage.reduce(
|
|
4980
|
+
(total, u) => ({
|
|
4981
|
+
tokensUp: total.tokensUp + u.tokensUp,
|
|
4982
|
+
tokensDown: total.tokensDown + u.tokensDown,
|
|
4983
|
+
activeMs: total.activeMs + u.activeMs
|
|
4984
|
+
}),
|
|
4985
|
+
{ tokensUp: 0, tokensDown: 0, activeMs: 0 }
|
|
4986
|
+
);
|
|
4987
|
+
}
|
|
4988
|
+
|
|
4940
4989
|
// src/commands/backlog/attachUsage.ts
|
|
4941
4990
|
function rowToUsage(u) {
|
|
4942
4991
|
return {
|
|
@@ -4948,7 +4997,10 @@ function rowToUsage(u) {
|
|
|
4948
4997
|
}
|
|
4949
4998
|
function attachUsage(item, rel, id) {
|
|
4950
4999
|
const usage = (rel.usage.get(id) ?? []).map(rowToUsage);
|
|
4951
|
-
if (usage.length > 0)
|
|
5000
|
+
if (usage.length > 0) {
|
|
5001
|
+
item.phaseUsage = usage;
|
|
5002
|
+
item.usageTotal = sumPhaseUsage(usage);
|
|
5003
|
+
}
|
|
4952
5004
|
}
|
|
4953
5005
|
|
|
4954
5006
|
// src/commands/backlog/buildPlan.ts
|
|
@@ -5062,6 +5114,11 @@ var phaseUsageSchema = z3.strictObject({
|
|
|
5062
5114
|
tokensDown: z3.number(),
|
|
5063
5115
|
activeMs: z3.number()
|
|
5064
5116
|
});
|
|
5117
|
+
var phaseUsageTotalSchema = z3.strictObject({
|
|
5118
|
+
tokensUp: z3.number(),
|
|
5119
|
+
tokensDown: z3.number(),
|
|
5120
|
+
activeMs: z3.number()
|
|
5121
|
+
});
|
|
5065
5122
|
var subtaskStatusSchema = z3.enum(["todo", "in-progress", "done"]);
|
|
5066
5123
|
var subtaskSchema = z3.strictObject({
|
|
5067
5124
|
title: z3.string(),
|
|
@@ -5104,6 +5161,7 @@ var backlogItemSchema = z3.strictObject({
|
|
|
5104
5161
|
subtasks: z3.array(subtaskSchema).optional(),
|
|
5105
5162
|
links: z3.array(backlogLinkSchema).optional(),
|
|
5106
5163
|
phaseUsage: z3.array(phaseUsageSchema).optional(),
|
|
5164
|
+
usageTotal: phaseUsageTotalSchema.optional(),
|
|
5107
5165
|
gitRefs: z3.array(gitRefSchema).optional(),
|
|
5108
5166
|
origin: z3.string().optional(),
|
|
5109
5167
|
jiraKey: z3.string().optional()
|
|
@@ -6014,11 +6072,11 @@ import chalk45 from "chalk";
|
|
|
6014
6072
|
|
|
6015
6073
|
// src/commands/backlog/appendComment.ts
|
|
6016
6074
|
import { sql as sql4 } from "drizzle-orm";
|
|
6017
|
-
async function appendComment(orm, itemId2,
|
|
6075
|
+
async function appendComment(orm, itemId2, text10, opts = {}) {
|
|
6018
6076
|
await orm.insert(comments).values({
|
|
6019
6077
|
itemId: itemId2,
|
|
6020
6078
|
idx: sql4`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId2})`,
|
|
6021
|
-
text:
|
|
6079
|
+
text: text10,
|
|
6022
6080
|
phase: opts.phase ?? null,
|
|
6023
6081
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6024
6082
|
type: opts.type ?? "comment"
|
|
@@ -6121,7 +6179,7 @@ function formatComment(entry) {
|
|
|
6121
6179
|
// src/shared/renderMarkdownTerminal.ts
|
|
6122
6180
|
import { Marked } from "marked";
|
|
6123
6181
|
import { markedTerminal } from "marked-terminal";
|
|
6124
|
-
function renderMarkdownTerminal(
|
|
6182
|
+
function renderMarkdownTerminal(text10) {
|
|
6125
6183
|
const width = process.stdout.columns || 80;
|
|
6126
6184
|
const marked = new Marked(markedTerminal({ width, reflowText: true }));
|
|
6127
6185
|
marked.use({
|
|
@@ -6134,7 +6192,7 @@ function renderMarkdownTerminal(text9) {
|
|
|
6134
6192
|
}
|
|
6135
6193
|
}
|
|
6136
6194
|
});
|
|
6137
|
-
return marked.parse(
|
|
6195
|
+
return marked.parse(text10).trimEnd();
|
|
6138
6196
|
}
|
|
6139
6197
|
|
|
6140
6198
|
// src/commands/backlog/show/printActivity.ts
|
|
@@ -6154,9 +6212,9 @@ function groupActivityRefs(refs, commitLimit = ACTIVITY_COMMIT_LIMIT) {
|
|
|
6154
6212
|
}
|
|
6155
6213
|
|
|
6156
6214
|
// src/commands/backlog/show/printActivity.ts
|
|
6157
|
-
function printRef(label2,
|
|
6215
|
+
function printRef(label2, text10, ref) {
|
|
6158
6216
|
const url = ref.url ? ` ${chalk48.dim(ref.url)}` : "";
|
|
6159
|
-
console.log(` ${chalk48.cyan(label2)} ${
|
|
6217
|
+
console.log(` ${chalk48.cyan(label2)} ${text10}${url}`);
|
|
6160
6218
|
}
|
|
6161
6219
|
function printActivity(item) {
|
|
6162
6220
|
const { branches, commits: commits2, prs: prs2, hiddenCommits } = groupActivityRefs(
|
|
@@ -6605,12 +6663,57 @@ function createFallbackHandler(routes3, htmlHandler2, extra) {
|
|
|
6605
6663
|
import { eq as eq12 } from "drizzle-orm";
|
|
6606
6664
|
|
|
6607
6665
|
// src/commands/backlog/loadItemSummaries.ts
|
|
6608
|
-
import { asc as asc5, eq as eq11
|
|
6609
|
-
|
|
6610
|
-
|
|
6666
|
+
import { asc as asc5, eq as eq11 } from "drizzle-orm";
|
|
6667
|
+
|
|
6668
|
+
// src/commands/backlog/incompleteSubtaskCounts.ts
|
|
6669
|
+
import { ne, sql as sql5 } from "drizzle-orm";
|
|
6670
|
+
function incompleteSubtaskCounts(orm) {
|
|
6671
|
+
return orm.select({
|
|
6611
6672
|
itemId: itemSubtasks.itemId,
|
|
6612
6673
|
count: sql5`count(*)::int`.as("incomplete_subtasks")
|
|
6613
6674
|
}).from(itemSubtasks).where(ne(itemSubtasks.status, "done")).groupBy(itemSubtasks.itemId).as("incomplete_counts");
|
|
6675
|
+
}
|
|
6676
|
+
|
|
6677
|
+
// src/commands/backlog/phaseUsageTotals.ts
|
|
6678
|
+
import { sql as sql6 } from "drizzle-orm";
|
|
6679
|
+
function phaseUsageTotals(orm) {
|
|
6680
|
+
return orm.select({
|
|
6681
|
+
itemId: phaseUsage.itemId,
|
|
6682
|
+
tokensUp: sql6`sum(${phaseUsage.tokensUp})::bigint`.as(
|
|
6683
|
+
"total_tokens_up"
|
|
6684
|
+
),
|
|
6685
|
+
tokensDown: sql6`sum(${phaseUsage.tokensDown})::bigint`.as(
|
|
6686
|
+
"total_tokens_down"
|
|
6687
|
+
),
|
|
6688
|
+
activeMs: sql6`sum(${phaseUsage.activeMs})::bigint`.as(
|
|
6689
|
+
"total_active_ms"
|
|
6690
|
+
)
|
|
6691
|
+
}).from(phaseUsage).groupBy(phaseUsage.itemId).as("usage_totals");
|
|
6692
|
+
}
|
|
6693
|
+
|
|
6694
|
+
// src/commands/backlog/rowToItemSummary.ts
|
|
6695
|
+
function rowToItemSummary(row) {
|
|
6696
|
+
return {
|
|
6697
|
+
id: row.id,
|
|
6698
|
+
origin: row.origin,
|
|
6699
|
+
type: row.type,
|
|
6700
|
+
name: row.name,
|
|
6701
|
+
status: row.status,
|
|
6702
|
+
starred: row.starred,
|
|
6703
|
+
jiraKey: row.jiraKey ?? void 0,
|
|
6704
|
+
incompleteSubtasks: row.incompleteSubtasks ?? 0,
|
|
6705
|
+
usageTotal: row.tokensUp == null ? void 0 : {
|
|
6706
|
+
tokensUp: Number(row.tokensUp),
|
|
6707
|
+
tokensDown: Number(row.tokensDown),
|
|
6708
|
+
activeMs: Number(row.activeMs)
|
|
6709
|
+
}
|
|
6710
|
+
};
|
|
6711
|
+
}
|
|
6712
|
+
|
|
6713
|
+
// src/commands/backlog/loadItemSummaries.ts
|
|
6714
|
+
async function loadItemSummaries(orm, origin) {
|
|
6715
|
+
const incompleteCounts = incompleteSubtaskCounts(orm);
|
|
6716
|
+
const usageTotals = phaseUsageTotals(orm);
|
|
6614
6717
|
const rows = await orm.select({
|
|
6615
6718
|
id: items.id,
|
|
6616
6719
|
origin: items.origin,
|
|
@@ -6619,18 +6722,12 @@ async function loadItemSummaries(orm, origin) {
|
|
|
6619
6722
|
status: items.status,
|
|
6620
6723
|
starred: items.starred,
|
|
6621
6724
|
jiraKey: items.jiraKey,
|
|
6622
|
-
incompleteSubtasks: incompleteCounts.count
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
name: row.name,
|
|
6629
|
-
status: row.status,
|
|
6630
|
-
starred: row.starred,
|
|
6631
|
-
jiraKey: row.jiraKey ?? void 0,
|
|
6632
|
-
incompleteSubtasks: row.incompleteSubtasks ?? 0
|
|
6633
|
-
}));
|
|
6725
|
+
incompleteSubtasks: incompleteCounts.count,
|
|
6726
|
+
tokensUp: usageTotals.tokensUp,
|
|
6727
|
+
tokensDown: usageTotals.tokensDown,
|
|
6728
|
+
activeMs: usageTotals.activeMs
|
|
6729
|
+
}).from(items).leftJoin(incompleteCounts, eq11(incompleteCounts.itemId, items.id)).leftJoin(usageTotals, eq11(usageTotals.itemId, items.id)).where(origin === void 0 ? void 0 : eq11(items.origin, origin)).orderBy(asc5(items.id));
|
|
6730
|
+
return rows.map(rowToItemSummary);
|
|
6634
6731
|
}
|
|
6635
6732
|
|
|
6636
6733
|
// src/commands/backlog/loadBacklogSummaries.ts
|
|
@@ -7258,9 +7355,9 @@ function excerpt(xml, ...tags) {
|
|
|
7258
7355
|
for (const tag of tags) {
|
|
7259
7356
|
const raw = extractText(xml, tag);
|
|
7260
7357
|
if (!raw) continue;
|
|
7261
|
-
const
|
|
7262
|
-
if (
|
|
7263
|
-
return `${
|
|
7358
|
+
const text10 = stripHtml(raw);
|
|
7359
|
+
if (text10.length <= MAX_EXCERPT) return text10;
|
|
7360
|
+
return `${text10.slice(0, MAX_EXCERPT)}\u2026`;
|
|
7264
7361
|
}
|
|
7265
7362
|
return "";
|
|
7266
7363
|
}
|
|
@@ -8173,10 +8270,10 @@ function registerAssociateJiraCommand(cmd) {
|
|
|
8173
8270
|
|
|
8174
8271
|
// src/commands/backlog/comment/index.ts
|
|
8175
8272
|
import chalk63 from "chalk";
|
|
8176
|
-
async function comment(id,
|
|
8273
|
+
async function comment(id, text10) {
|
|
8177
8274
|
const found = await findOneItem(id);
|
|
8178
8275
|
if (!found) process.exit(1);
|
|
8179
|
-
await appendComment(found.orm, found.item.id,
|
|
8276
|
+
await appendComment(found.orm, found.item.id, text10);
|
|
8180
8277
|
console.log(
|
|
8181
8278
|
chalk63.green(`Comment added to item ${formatItemId(found.item.id)}.`)
|
|
8182
8279
|
);
|
|
@@ -8281,9 +8378,9 @@ function readLine(dump, start3) {
|
|
|
8281
8378
|
return { text: dump.subarray(start3, eol).toString("utf8"), next: eol + 1 };
|
|
8282
8379
|
}
|
|
8283
8380
|
function parseHeader(dump) {
|
|
8284
|
-
const { text:
|
|
8381
|
+
const { text: text10, next: next3 } = readLine(dump, 0);
|
|
8285
8382
|
try {
|
|
8286
|
-
return { header: JSON.parse(
|
|
8383
|
+
return { header: JSON.parse(text10), bodyStart: next3 };
|
|
8287
8384
|
} catch {
|
|
8288
8385
|
return invalid("header is not valid JSON.");
|
|
8289
8386
|
}
|
|
@@ -8292,9 +8389,9 @@ function parseSections(dump, bodyStart) {
|
|
|
8292
8389
|
const sections = /* @__PURE__ */ new Map();
|
|
8293
8390
|
let cursor = bodyStart;
|
|
8294
8391
|
while (cursor < dump.length) {
|
|
8295
|
-
const { text:
|
|
8296
|
-
const match =
|
|
8297
|
-
if (!match) invalid(`malformed table marker "${
|
|
8392
|
+
const { text: text10, next: next3 } = readLine(dump, cursor);
|
|
8393
|
+
const match = text10.match(/^@table (\S+) (\d+)$/);
|
|
8394
|
+
if (!match) invalid(`malformed table marker "${text10}".`);
|
|
8298
8395
|
const [, name, bytes] = match;
|
|
8299
8396
|
const end = next3 + Number(bytes);
|
|
8300
8397
|
if (end > dump.length) invalid(`section "${name}" overruns the dump.`);
|
|
@@ -8370,8 +8467,8 @@ async function readStdinBuffer() {
|
|
|
8370
8467
|
import { finished } from "stream/promises";
|
|
8371
8468
|
import { from as copyFrom } from "pg-copy-streams";
|
|
8372
8469
|
async function copyTableIn(client, table, data) {
|
|
8373
|
-
const
|
|
8374
|
-
const stream = client.query(copyFrom(
|
|
8470
|
+
const sql13 = `COPY ${table.name} (${table.columns.join(", ")}) FROM STDIN`;
|
|
8471
|
+
const stream = client.query(copyFrom(sql13));
|
|
8375
8472
|
stream.end(data);
|
|
8376
8473
|
await finished(stream);
|
|
8377
8474
|
}
|
|
@@ -8416,8 +8513,8 @@ async function replaceData(client, parsed) {
|
|
|
8416
8513
|
await copyTableIn(client, table, data);
|
|
8417
8514
|
}
|
|
8418
8515
|
for (const col of await introspectIdentityColumns(client)) {
|
|
8419
|
-
const { text:
|
|
8420
|
-
await client.query(
|
|
8516
|
+
const { text: text10, values } = resyncIdentitySql(col);
|
|
8517
|
+
await client.query(text10, values);
|
|
8421
8518
|
}
|
|
8422
8519
|
}
|
|
8423
8520
|
async function restore(client, parsed) {
|
|
@@ -8498,11 +8595,11 @@ async function insertPhaseAt(orm, itemId2, phaseIdx, name, tasks, manualChecks,
|
|
|
8498
8595
|
}
|
|
8499
8596
|
|
|
8500
8597
|
// src/commands/backlog/insertSubtask.ts
|
|
8501
|
-
import { sql as
|
|
8598
|
+
import { sql as sql7 } from "drizzle-orm";
|
|
8502
8599
|
async function insertSubtask(orm, itemId2, title, description) {
|
|
8503
8600
|
await orm.insert(itemSubtasks).values({
|
|
8504
8601
|
itemId: itemId2,
|
|
8505
|
-
idx:
|
|
8602
|
+
idx: sql7`(SELECT COALESCE(MAX(${itemSubtasks.idx}) + 1, 0) FROM ${itemSubtasks} WHERE ${itemSubtasks.itemId} = ${itemId2})`,
|
|
8506
8603
|
title,
|
|
8507
8604
|
description: description ?? null,
|
|
8508
8605
|
status: "todo"
|
|
@@ -10264,8 +10361,8 @@ var RAW_BUILTIN_DENIES = [
|
|
|
10264
10361
|
regex
|
|
10265
10362
|
}))
|
|
10266
10363
|
];
|
|
10267
|
-
function matchBuiltinDeny(
|
|
10268
|
-
return RAW_BUILTIN_DENIES.find((rule) => rule.regex.test(
|
|
10364
|
+
function matchBuiltinDeny(text10) {
|
|
10365
|
+
return RAW_BUILTIN_DENIES.find((rule) => rule.regex.test(text10));
|
|
10269
10366
|
}
|
|
10270
10367
|
function toDecision(rule) {
|
|
10271
10368
|
if (!rule) return void 0;
|
|
@@ -11005,8 +11102,8 @@ function formatHuman(cli, commands) {
|
|
|
11005
11102
|
`];
|
|
11006
11103
|
for (const cmd of sorted) {
|
|
11007
11104
|
const full = `${cli} ${cmd.path.join(" ")}`;
|
|
11008
|
-
const
|
|
11009
|
-
lines.push(`${prefix(classifyVerb(cmd.path))}${
|
|
11105
|
+
const text10 = cmd.description ? `${full} \u2014 ${cmd.description}` : full;
|
|
11106
|
+
lines.push(`${prefix(classifyVerb(cmd.path))}${text10}`);
|
|
11010
11107
|
}
|
|
11011
11108
|
return lines.join("\n");
|
|
11012
11109
|
}
|
|
@@ -11285,38 +11382,38 @@ import chalk108 from "chalk";
|
|
|
11285
11382
|
// src/commands/codeComment/validateCommentText.ts
|
|
11286
11383
|
var MAX_COMMENT_LENGTH = 50;
|
|
11287
11384
|
function validateCommentText(raw, isHash = false) {
|
|
11288
|
-
const
|
|
11289
|
-
if (/[\r\n]/.test(
|
|
11385
|
+
const text10 = isHash ? raw.replace(/^#\s?/, "") : raw.replace(/^\/\/\s?/, "");
|
|
11386
|
+
if (/[\r\n]/.test(text10)) {
|
|
11290
11387
|
return {
|
|
11291
11388
|
ok: false,
|
|
11292
11389
|
reason: "Comment must be a single line \u2014 multi-line comments are not allowed."
|
|
11293
11390
|
};
|
|
11294
11391
|
}
|
|
11295
|
-
if (!isHash && (
|
|
11392
|
+
if (!isHash && (text10.includes("/*") || text10.includes("*/"))) {
|
|
11296
11393
|
return {
|
|
11297
11394
|
ok: false,
|
|
11298
11395
|
reason: "Block comments (/* */) are not allowed \u2014 only single-line // comments."
|
|
11299
11396
|
};
|
|
11300
11397
|
}
|
|
11301
|
-
if (
|
|
11398
|
+
if (text10.length > MAX_COMMENT_LENGTH) {
|
|
11302
11399
|
return {
|
|
11303
11400
|
ok: false,
|
|
11304
|
-
reason: `Comment text is ${
|
|
11401
|
+
reason: `Comment text is ${text10.length} chars; the cap is ${MAX_COMMENT_LENGTH}. Make it shorter or, better, make the code self-documenting.`
|
|
11305
11402
|
};
|
|
11306
11403
|
}
|
|
11307
|
-
return { ok: true, text:
|
|
11404
|
+
return { ok: true, text: text10 };
|
|
11308
11405
|
}
|
|
11309
11406
|
|
|
11310
11407
|
// src/commands/codeComment/issuePin.ts
|
|
11311
11408
|
import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync24 } from "fs";
|
|
11312
11409
|
import { randomInt } from "crypto";
|
|
11313
|
-
function issuePin(file, lineNumber,
|
|
11410
|
+
function issuePin(file, lineNumber, text10) {
|
|
11314
11411
|
const pin = generatePin();
|
|
11315
11412
|
mkdirSync13(getRestrictedDir(), { recursive: true });
|
|
11316
11413
|
sweepRestrictedDir();
|
|
11317
11414
|
writeFileSync24(
|
|
11318
11415
|
getPinStatePath(pin),
|
|
11319
|
-
JSON.stringify({ pin, file, line: lineNumber, text:
|
|
11416
|
+
JSON.stringify({ pin, file, line: lineNumber, text: text10 })
|
|
11320
11417
|
);
|
|
11321
11418
|
return showNotification({
|
|
11322
11419
|
title: "assist code-comment pin",
|
|
@@ -11328,7 +11425,7 @@ function generatePin() {
|
|
|
11328
11425
|
}
|
|
11329
11426
|
|
|
11330
11427
|
// src/commands/codeComment/codeCommentSet.ts
|
|
11331
|
-
function codeCommentSet(file, line,
|
|
11428
|
+
function codeCommentSet(file, line, text10) {
|
|
11332
11429
|
const lineNumber = Number.parseInt(line, 10);
|
|
11333
11430
|
if (!Number.isInteger(lineNumber) || lineNumber < 1) {
|
|
11334
11431
|
console.error(chalk108.red(`Invalid line number: ${line}`));
|
|
@@ -11337,7 +11434,7 @@ function codeCommentSet(file, line, text9) {
|
|
|
11337
11434
|
}
|
|
11338
11435
|
const hash = isHashCommentFile(file);
|
|
11339
11436
|
const marker = hash ? "#" : "//";
|
|
11340
|
-
const validation = validateCommentText(
|
|
11437
|
+
const validation = validateCommentText(text10, hash);
|
|
11341
11438
|
if (!validation.ok) {
|
|
11342
11439
|
console.error(chalk108.red(`Refused: ${validation.reason}`));
|
|
11343
11440
|
console.error(chalk108.red("No pin issued."));
|
|
@@ -13344,12 +13441,12 @@ function isSourceFile(filePath) {
|
|
|
13344
13441
|
if (!filePath) return false;
|
|
13345
13442
|
return SOURCE_EXTENSIONS.some((ext) => filePath.endsWith(ext));
|
|
13346
13443
|
}
|
|
13347
|
-
function blankNonNewline2(
|
|
13348
|
-
return
|
|
13444
|
+
function blankNonNewline2(text10) {
|
|
13445
|
+
return text10.replace(/[^\n]/g, " ");
|
|
13349
13446
|
}
|
|
13350
|
-
function extractComments(
|
|
13447
|
+
function extractComments(text10) {
|
|
13351
13448
|
const comments3 = [];
|
|
13352
|
-
let work =
|
|
13449
|
+
let work = text10.replace(
|
|
13353
13450
|
/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`/g,
|
|
13354
13451
|
blankNonNewline2
|
|
13355
13452
|
);
|
|
@@ -13364,11 +13461,11 @@ function extractComments(text9) {
|
|
|
13364
13461
|
}
|
|
13365
13462
|
|
|
13366
13463
|
// src/commands/editHook/extractYamlComments.ts
|
|
13367
|
-
function blankNonNewline3(
|
|
13368
|
-
return
|
|
13464
|
+
function blankNonNewline3(text10) {
|
|
13465
|
+
return text10.replace(/[^\n]/g, " ");
|
|
13369
13466
|
}
|
|
13370
|
-
function extractYamlComments(
|
|
13371
|
-
const work =
|
|
13467
|
+
function extractYamlComments(text10) {
|
|
13468
|
+
const work = text10.replace(
|
|
13372
13469
|
/"(?:[^"\\]|\\.)*"|'(?:[^']|'')*'/g,
|
|
13373
13470
|
blankNonNewline3
|
|
13374
13471
|
);
|
|
@@ -13384,8 +13481,8 @@ function isHeaderLine2(line) {
|
|
|
13384
13481
|
const trimmed = line.trim();
|
|
13385
13482
|
return trimmed === "" || trimmed.startsWith("#");
|
|
13386
13483
|
}
|
|
13387
|
-
function extractShellComments(
|
|
13388
|
-
const lines =
|
|
13484
|
+
function extractShellComments(text10) {
|
|
13485
|
+
const lines = text10.split("\n");
|
|
13389
13486
|
let firstCodeLine = 0;
|
|
13390
13487
|
while (firstCodeLine < lines.length && isHeaderLine2(lines[firstCodeLine])) {
|
|
13391
13488
|
firstCodeLine++;
|
|
@@ -13755,9 +13852,9 @@ function registerGithub(program2) {
|
|
|
13755
13852
|
}
|
|
13756
13853
|
|
|
13757
13854
|
// src/commands/handover/countPendingHandovers.ts
|
|
13758
|
-
import { and as and16, eq as eq34, isNull, sql as
|
|
13855
|
+
import { and as and16, eq as eq34, isNull, sql as sql8 } from "drizzle-orm";
|
|
13759
13856
|
async function countPendingHandovers(orm, origin) {
|
|
13760
|
-
const [row] = await orm.select({ count:
|
|
13857
|
+
const [row] = await orm.select({ count: sql8`count(*)::int` }).from(handovers).where(and16(eq34(handovers.origin, origin), isNull(handovers.recalledAt)));
|
|
13761
13858
|
return row?.count ?? 0;
|
|
13762
13859
|
}
|
|
13763
13860
|
|
|
@@ -13980,9 +14077,9 @@ import chalk140 from "chalk";
|
|
|
13980
14077
|
|
|
13981
14078
|
// src/commands/jira/adfToText.ts
|
|
13982
14079
|
function renderInline(node) {
|
|
13983
|
-
const
|
|
13984
|
-
if (node.marks?.some((m) => m.type === "code")) return `\`${
|
|
13985
|
-
return
|
|
14080
|
+
const text10 = node.text ?? "";
|
|
14081
|
+
if (node.marks?.some((m) => m.type === "code")) return `\`${text10}\``;
|
|
14082
|
+
return text10;
|
|
13986
14083
|
}
|
|
13987
14084
|
function renderChildren(node, indent2) {
|
|
13988
14085
|
return renderNodes(node.content ?? [], indent2);
|
|
@@ -14024,8 +14121,8 @@ function isListNode(node) {
|
|
|
14024
14121
|
function renderListChild(child, indent2, pad, marker, isFirst) {
|
|
14025
14122
|
if (isListNode(child)) return renderNodes([child], indent2 + 1);
|
|
14026
14123
|
if (child.type !== "paragraph") return renderNode(child, indent2);
|
|
14027
|
-
const
|
|
14028
|
-
return isFirst ? `${pad}${marker} ${
|
|
14124
|
+
const text10 = renderChildren(child, indent2);
|
|
14125
|
+
return isFirst ? `${pad}${marker} ${text10}` : `${pad} ${text10}`;
|
|
14029
14126
|
}
|
|
14030
14127
|
function renderListItem(node, indent2, marker) {
|
|
14031
14128
|
const pad = " ".repeat(indent2);
|
|
@@ -14184,9 +14281,9 @@ function registerDescriptionLaunch(program2, name, slashCommand, description, al
|
|
|
14184
14281
|
"[description]",
|
|
14185
14282
|
`Text to forward to the /${slashCommand} slash command`
|
|
14186
14283
|
).description(description).option("--once", "Exit when the initial task completes").option("--resume-session <id>", RESUME_SESSION_FLAG).action(
|
|
14187
|
-
(
|
|
14284
|
+
(text10, opts) => launchMode(slashCommand, {
|
|
14188
14285
|
once: opts.once,
|
|
14189
|
-
description:
|
|
14286
|
+
description: text10,
|
|
14190
14287
|
resumeSessionId: opts.resumeSession
|
|
14191
14288
|
})
|
|
14192
14289
|
);
|
|
@@ -14688,8 +14785,8 @@ function dedupeLinks(links2) {
|
|
|
14688
14785
|
}
|
|
14689
14786
|
|
|
14690
14787
|
// src/commands/netcap/linkifyMentions.ts
|
|
14691
|
-
function linkifyMentions(
|
|
14692
|
-
let out =
|
|
14788
|
+
function linkifyMentions(text10, mentions) {
|
|
14789
|
+
let out = text10;
|
|
14693
14790
|
for (const m of mentions) {
|
|
14694
14791
|
if (m.name && out.includes(m.name)) {
|
|
14695
14792
|
out = out.replace(m.name, `[${m.name}](${m.url})`);
|
|
@@ -14716,13 +14813,13 @@ function resolveAuthor(mentionMap, author) {
|
|
|
14716
14813
|
return mentionMap.get(author) ?? { slug: author, url: profileUrl(author) };
|
|
14717
14814
|
}
|
|
14718
14815
|
function buildPost(raw, mentionMap, author) {
|
|
14719
|
-
const
|
|
14720
|
-
if (!
|
|
14816
|
+
const text10 = joinText(raw.text);
|
|
14817
|
+
if (!text10) return void 0;
|
|
14721
14818
|
const mentions = resolveMentions(raw, mentionMap, author);
|
|
14722
14819
|
const relatedPosts = [...new Set(raw.related)];
|
|
14723
14820
|
return {
|
|
14724
|
-
text:
|
|
14725
|
-
markdown: linkifyMentions(
|
|
14821
|
+
text: text10,
|
|
14822
|
+
markdown: linkifyMentions(text10, mentions),
|
|
14726
14823
|
mentions,
|
|
14727
14824
|
hashtags: [...new Set(raw.hashtags)],
|
|
14728
14825
|
links: dedupeLinks(raw.links),
|
|
@@ -14863,8 +14960,8 @@ function activityUrnOf(update3) {
|
|
|
14863
14960
|
return typeof urn === "string" ? urn : void 0;
|
|
14864
14961
|
}
|
|
14865
14962
|
function buildVoyagerPost(update3, profiles) {
|
|
14866
|
-
const
|
|
14867
|
-
if (!
|
|
14963
|
+
const text10 = commentaryText(update3);
|
|
14964
|
+
if (!text10) return void 0;
|
|
14868
14965
|
const author = resolveVoyagerAuthor(update3);
|
|
14869
14966
|
const { mentions, hashtags, links: links2 } = collectVoyagerAttributes(
|
|
14870
14967
|
update3,
|
|
@@ -14873,8 +14970,8 @@ function buildVoyagerPost(update3, profiles) {
|
|
|
14873
14970
|
);
|
|
14874
14971
|
const activityUrn = activityUrnOf(update3);
|
|
14875
14972
|
return {
|
|
14876
|
-
text:
|
|
14877
|
-
markdown: linkifyMentions(
|
|
14973
|
+
text: text10,
|
|
14974
|
+
markdown: linkifyMentions(text10, mentions),
|
|
14878
14975
|
mentions,
|
|
14879
14976
|
hashtags,
|
|
14880
14977
|
links: links2,
|
|
@@ -15378,8 +15475,8 @@ function isWallOfText(lines) {
|
|
|
15378
15475
|
if (lines.some(isListLine)) {
|
|
15379
15476
|
return false;
|
|
15380
15477
|
}
|
|
15381
|
-
const
|
|
15382
|
-
return
|
|
15478
|
+
const text10 = lines.join(" ").trim();
|
|
15479
|
+
return text10.length > MAX_PARAGRAPH_CHARS || countSentences(text10) > MAX_PARAGRAPH_SENTENCES;
|
|
15383
15480
|
}
|
|
15384
15481
|
function validatePrContent(title, body) {
|
|
15385
15482
|
if (title.toLowerCase().includes("claude")) {
|
|
@@ -17133,9 +17230,9 @@ function resolveImports(target, dependencies, sourceFile, statements = []) {
|
|
|
17133
17230
|
function extractTexts(target, allFunctions, statements) {
|
|
17134
17231
|
const stmtTexts = statements.map((v) => v.getFullText().trim());
|
|
17135
17232
|
const fnTexts = allFunctions.map((fn) => {
|
|
17136
|
-
const
|
|
17137
|
-
if (fn === target && !
|
|
17138
|
-
return
|
|
17233
|
+
const text10 = fn.getFullText().trim();
|
|
17234
|
+
if (fn === target && !text10.startsWith("export ")) return `export ${text10}`;
|
|
17235
|
+
return text10;
|
|
17139
17236
|
});
|
|
17140
17237
|
return [...stmtTexts, ...fnTexts];
|
|
17141
17238
|
}
|
|
@@ -18985,9 +19082,9 @@ var MultiSpinner = class {
|
|
|
18985
19082
|
elapsedPrefix: prefix2
|
|
18986
19083
|
});
|
|
18987
19084
|
}
|
|
18988
|
-
failRemaining(
|
|
19085
|
+
failRemaining(text10) {
|
|
18989
19086
|
for (const entry of this.entries) {
|
|
18990
|
-
if (entry.state === "running") this.resolve(entry, "failed",
|
|
19087
|
+
if (entry.state === "running") this.resolve(entry, "failed", text10);
|
|
18991
19088
|
}
|
|
18992
19089
|
}
|
|
18993
19090
|
add(entry) {
|
|
@@ -19000,14 +19097,14 @@ var MultiSpinner = class {
|
|
|
19000
19097
|
set text(value) {
|
|
19001
19098
|
entry.text = value;
|
|
19002
19099
|
},
|
|
19003
|
-
succeed: (
|
|
19004
|
-
fail: (
|
|
19100
|
+
succeed: (text10) => this.resolve(entry, "succeeded", text10),
|
|
19101
|
+
fail: (text10) => this.resolve(entry, "failed", text10)
|
|
19005
19102
|
};
|
|
19006
19103
|
}
|
|
19007
|
-
resolve(entry, state,
|
|
19104
|
+
resolve(entry, state, text10) {
|
|
19008
19105
|
if (entry.state !== "running") return;
|
|
19009
19106
|
entry.state = state;
|
|
19010
|
-
if (
|
|
19107
|
+
if (text10 !== void 0) entry.text = text10;
|
|
19011
19108
|
entry.elapsedStart = void 0;
|
|
19012
19109
|
this.render();
|
|
19013
19110
|
this.maybeFinish();
|
|
@@ -19082,12 +19179,12 @@ function skippedCodexResult(outputPath) {
|
|
|
19082
19179
|
// src/commands/review/formatReviewerFailure.ts
|
|
19083
19180
|
var FAST_FAIL_MS = 1e3;
|
|
19084
19181
|
var STDOUT_TAIL_LINES = 20;
|
|
19085
|
-
function indent(
|
|
19086
|
-
return
|
|
19182
|
+
function indent(text10) {
|
|
19183
|
+
return text10.split(/\r?\n/).map((line) => ` ${line}`);
|
|
19087
19184
|
}
|
|
19088
|
-
function tailLines(
|
|
19089
|
-
const lines =
|
|
19090
|
-
return lines.length <= maxLines ?
|
|
19185
|
+
function tailLines(text10, maxLines) {
|
|
19186
|
+
const lines = text10.split(/\r?\n/);
|
|
19187
|
+
return lines.length <= maxLines ? text10 : lines.slice(-maxLines).join("\n");
|
|
19091
19188
|
}
|
|
19092
19189
|
function isFastFail(input) {
|
|
19093
19190
|
return input.exitCode !== 0 && input.elapsedMs !== void 0 && input.elapsedMs < FAST_FAIL_MS;
|
|
@@ -20022,8 +20119,8 @@ function filterToSql(filter) {
|
|
|
20022
20119
|
// src/commands/seq/fetchSeqData.ts
|
|
20023
20120
|
function buildDataParams(filter, count8, from, to) {
|
|
20024
20121
|
const sqlFilter = filterToSql(filter);
|
|
20025
|
-
const
|
|
20026
|
-
const params = new URLSearchParams({ q:
|
|
20122
|
+
const sql13 = `select @Timestamp, @Level, @Exception, @Message from stream where ${sqlFilter} order by @Timestamp desc limit ${count8}`;
|
|
20123
|
+
const params = new URLSearchParams({ q: sql13 });
|
|
20027
20124
|
if (from) params.set("rangeStartUtc", from);
|
|
20028
20125
|
if (to) params.set("rangeEndUtc", to);
|
|
20029
20126
|
return params;
|
|
@@ -20284,26 +20381,26 @@ import chalk187 from "chalk";
|
|
|
20284
20381
|
// src/commands/sql/loadConnections.ts
|
|
20285
20382
|
function loadConnections3() {
|
|
20286
20383
|
const raw = loadGlobalConfigRaw();
|
|
20287
|
-
const
|
|
20288
|
-
return
|
|
20384
|
+
const sql13 = raw.sql;
|
|
20385
|
+
return sql13?.connections ?? [];
|
|
20289
20386
|
}
|
|
20290
20387
|
function saveConnections3(connections) {
|
|
20291
20388
|
const raw = loadGlobalConfigRaw();
|
|
20292
|
-
const
|
|
20293
|
-
|
|
20294
|
-
raw.sql =
|
|
20389
|
+
const sql13 = raw.sql ?? {};
|
|
20390
|
+
sql13.connections = connections;
|
|
20391
|
+
raw.sql = sql13;
|
|
20295
20392
|
saveGlobalConfig(raw);
|
|
20296
20393
|
}
|
|
20297
20394
|
function getDefaultConnection2() {
|
|
20298
20395
|
const raw = loadGlobalConfigRaw();
|
|
20299
|
-
const
|
|
20300
|
-
return
|
|
20396
|
+
const sql13 = raw.sql;
|
|
20397
|
+
return sql13?.defaultConnection;
|
|
20301
20398
|
}
|
|
20302
20399
|
function setDefaultConnection2(name) {
|
|
20303
20400
|
const raw = loadGlobalConfigRaw();
|
|
20304
|
-
const
|
|
20305
|
-
|
|
20306
|
-
raw.sql =
|
|
20401
|
+
const sql13 = raw.sql ?? {};
|
|
20402
|
+
sql13.defaultConnection = name;
|
|
20403
|
+
raw.sql = sql13;
|
|
20307
20404
|
saveGlobalConfig(raw);
|
|
20308
20405
|
}
|
|
20309
20406
|
|
|
@@ -20374,9 +20471,9 @@ function resolveConnection3(name) {
|
|
|
20374
20471
|
}
|
|
20375
20472
|
|
|
20376
20473
|
// src/commands/sql/sqlConnect.ts
|
|
20377
|
-
import
|
|
20474
|
+
import sql9 from "mssql";
|
|
20378
20475
|
async function sqlConnect(conn) {
|
|
20379
|
-
return await
|
|
20476
|
+
return await sql9.connect({
|
|
20380
20477
|
server: conn.server,
|
|
20381
20478
|
port: conn.port,
|
|
20382
20479
|
user: conn.user,
|
|
@@ -20453,11 +20550,11 @@ var MUTATION_PATTERN = new RegExp(
|
|
|
20453
20550
|
`\\b(${MUTATION_KEYWORDS.join("|")})\\b`,
|
|
20454
20551
|
"i"
|
|
20455
20552
|
);
|
|
20456
|
-
function stripComments(
|
|
20457
|
-
return
|
|
20553
|
+
function stripComments(sql13) {
|
|
20554
|
+
return sql13.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\n]*/g, " ");
|
|
20458
20555
|
}
|
|
20459
|
-
function isMutation(
|
|
20460
|
-
const stripped = stripComments(
|
|
20556
|
+
function isMutation(sql13) {
|
|
20557
|
+
const stripped = stripComments(sql13);
|
|
20461
20558
|
if (MUTATION_PATTERN.test(stripped)) return true;
|
|
20462
20559
|
return /\bSELECT\b[\s\S]+\bINTO\s+\w/i.test(stripped);
|
|
20463
20560
|
}
|
|
@@ -20656,8 +20753,8 @@ import {
|
|
|
20656
20753
|
import { basename as basename10, join as join51 } from "path";
|
|
20657
20754
|
|
|
20658
20755
|
// src/commands/transcript/cleanText.ts
|
|
20659
|
-
function cleanText(
|
|
20660
|
-
const words =
|
|
20756
|
+
function cleanText(text10) {
|
|
20757
|
+
const words = text10.split(/\s+/);
|
|
20661
20758
|
const cleaned = [];
|
|
20662
20759
|
for (let i = 0; i < words.length; i++) {
|
|
20663
20760
|
let isRepeat = false;
|
|
@@ -20677,8 +20774,8 @@ function cleanText(text9) {
|
|
|
20677
20774
|
}
|
|
20678
20775
|
|
|
20679
20776
|
// src/commands/transcript/convert/parseVtt/deduplicateCues/removeSubstringDuplicates.ts
|
|
20680
|
-
function normalizeText(
|
|
20681
|
-
return
|
|
20777
|
+
function normalizeText(text10) {
|
|
20778
|
+
return text10.toLowerCase().trim();
|
|
20682
20779
|
}
|
|
20683
20780
|
function checkSubstringRelation(textI, textJ) {
|
|
20684
20781
|
if (textI.includes(textJ) && textI.length > textJ.length)
|
|
@@ -20807,13 +20904,13 @@ function parseTimestampLine(line) {
|
|
|
20807
20904
|
return { startMs: parseTimestamp(startStr), endMs: parseTimestamp(endStr) };
|
|
20808
20905
|
}
|
|
20809
20906
|
function buildCue(startMs, endMs, fullText) {
|
|
20810
|
-
const { speaker, text:
|
|
20811
|
-
return
|
|
20907
|
+
const { speaker, text: text10 } = extractSpeaker(fullText);
|
|
20908
|
+
return text10 ? { startMs, endMs, speaker, text: text10 } : null;
|
|
20812
20909
|
}
|
|
20813
20910
|
function parseCueLine(lines, i) {
|
|
20814
20911
|
const { startMs, endMs } = parseTimestampLine(lines[i]);
|
|
20815
|
-
const { text:
|
|
20816
|
-
return { cue: buildCue(startMs, endMs,
|
|
20912
|
+
const { text: text10, nextIndex: nextIndex2 } = collectTextLines(lines, i + 1);
|
|
20913
|
+
return { cue: buildCue(startMs, endMs, text10), nextIndex: nextIndex2 };
|
|
20817
20914
|
}
|
|
20818
20915
|
function isCueSeparator(line) {
|
|
20819
20916
|
return line.trim().includes("-->");
|
|
@@ -21396,8 +21493,8 @@ async function exchangeToken(params) {
|
|
|
21396
21493
|
body: body.toString()
|
|
21397
21494
|
});
|
|
21398
21495
|
if (!response.ok) {
|
|
21399
|
-
const
|
|
21400
|
-
throw new Error(`Token exchange failed (${response.status}): ${
|
|
21496
|
+
const text10 = await response.text();
|
|
21497
|
+
throw new Error(`Token exchange failed (${response.status}): ${text10}`);
|
|
21401
21498
|
}
|
|
21402
21499
|
return response.json();
|
|
21403
21500
|
}
|
|
@@ -22531,10 +22628,22 @@ function broadcastSessions(sessions, clients, windowsSessions = [], active) {
|
|
|
22531
22628
|
});
|
|
22532
22629
|
}
|
|
22533
22630
|
|
|
22534
|
-
// src/shared/
|
|
22631
|
+
// src/shared/activeWindows.ts
|
|
22535
22632
|
var WINDOWS = ["five_hour", "seven_day"];
|
|
22536
|
-
|
|
22633
|
+
function activeWindows(rateLimits) {
|
|
22634
|
+
if (!rateLimits) return [];
|
|
22635
|
+
const out = [];
|
|
22537
22636
|
for (const window of WINDOWS) {
|
|
22637
|
+
const resetsAt = rateLimits[window]?.resets_at;
|
|
22638
|
+
if (typeof resetsAt === "number") out.push({ window, resetsAt });
|
|
22639
|
+
}
|
|
22640
|
+
return out;
|
|
22641
|
+
}
|
|
22642
|
+
|
|
22643
|
+
// src/shared/db/recordUsagePeak.ts
|
|
22644
|
+
var WINDOWS2 = ["five_hour", "seven_day"];
|
|
22645
|
+
async function recordUsagePeak(db, rateLimits) {
|
|
22646
|
+
for (const window of WINDOWS2) {
|
|
22538
22647
|
const w = rateLimits[window];
|
|
22539
22648
|
if (!w || typeof w.resets_at !== "number" || typeof w.used_percentage !== "number")
|
|
22540
22649
|
continue;
|
|
@@ -22567,6 +22676,9 @@ var ClientHub = class extends Set {
|
|
|
22567
22676
|
broadcast(this, { type: "limits", rateLimits });
|
|
22568
22677
|
this.persistPeak?.(rateLimits);
|
|
22569
22678
|
}
|
|
22679
|
+
currentWindows() {
|
|
22680
|
+
return activeWindows(this.latestLimits);
|
|
22681
|
+
}
|
|
22570
22682
|
greet(client) {
|
|
22571
22683
|
if (this.latestLimits) {
|
|
22572
22684
|
sendTo(client, { type: "limits", rateLimits: this.latestLimits });
|
|
@@ -22781,13 +22893,13 @@ function logSpawnedSession(session) {
|
|
|
22781
22893
|
}
|
|
22782
22894
|
|
|
22783
22895
|
// src/shared/db/recordPhaseActiveMs.ts
|
|
22784
|
-
import { sql as
|
|
22896
|
+
import { sql as sql10 } from "drizzle-orm";
|
|
22785
22897
|
async function recordPhaseActiveMs(db, itemId2, phaseIdx, activeMs) {
|
|
22786
22898
|
if (activeMs <= 0) return;
|
|
22787
22899
|
await db.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, activeMs }).onConflictDoUpdate({
|
|
22788
22900
|
target: [phaseUsage.itemId, phaseUsage.phaseIdx],
|
|
22789
22901
|
set: {
|
|
22790
|
-
activeMs:
|
|
22902
|
+
activeMs: sql10`${phaseUsage.activeMs} + excluded.active_ms`
|
|
22791
22903
|
}
|
|
22792
22904
|
});
|
|
22793
22905
|
}
|
|
@@ -22929,38 +23041,114 @@ function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
|
|
|
22929
23041
|
return (s, status2, exitCode) => applyStatusChange(s, status2, exitCode, dismiss, notify2, reuseForRun);
|
|
22930
23042
|
}
|
|
22931
23043
|
|
|
22932
|
-
// src/shared/db/
|
|
22933
|
-
import { sql as
|
|
22934
|
-
async function
|
|
22935
|
-
|
|
22936
|
-
|
|
22937
|
-
|
|
22938
|
-
|
|
22939
|
-
|
|
22940
|
-
|
|
22941
|
-
|
|
22942
|
-
|
|
23044
|
+
// src/shared/db/recordPhaseTranscriptUsage.ts
|
|
23045
|
+
import { sql as sql11 } from "drizzle-orm";
|
|
23046
|
+
async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
|
|
23047
|
+
const byId = /* @__PURE__ */ new Map();
|
|
23048
|
+
for (const r of responses) byId.set(r.messageId, r);
|
|
23049
|
+
const unique = [...byId.values()];
|
|
23050
|
+
if (unique.length === 0) return { tokensUp: 0, tokensDown: 0 };
|
|
23051
|
+
return db.transaction(async (tx) => {
|
|
23052
|
+
const inserted = await tx.insert(phaseUsageMessages).values(unique.map((r) => ({ itemId: itemId2, phaseIdx, messageId: r.messageId }))).onConflictDoNothing().returning({ messageId: phaseUsageMessages.messageId });
|
|
23053
|
+
let tokensUp = 0;
|
|
23054
|
+
let tokensDown = 0;
|
|
23055
|
+
for (const { messageId } of inserted) {
|
|
23056
|
+
const r = byId.get(messageId);
|
|
23057
|
+
if (!r) continue;
|
|
23058
|
+
tokensUp += r.outputTokens;
|
|
23059
|
+
tokensDown += r.inputTokens;
|
|
23060
|
+
}
|
|
23061
|
+
if (tokensUp <= 0 && tokensDown <= 0) return { tokensUp: 0, tokensDown: 0 };
|
|
23062
|
+
await tx.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, tokensUp, tokensDown }).onConflictDoUpdate({
|
|
23063
|
+
target: [phaseUsage.itemId, phaseUsage.phaseIdx],
|
|
23064
|
+
set: {
|
|
23065
|
+
tokensUp: sql11`${phaseUsage.tokensUp} + ${tokensUp}`,
|
|
23066
|
+
tokensDown: sql11`${phaseUsage.tokensDown} + ${tokensDown}`
|
|
23067
|
+
}
|
|
23068
|
+
});
|
|
23069
|
+
return { tokensUp, tokensDown };
|
|
22943
23070
|
});
|
|
22944
23071
|
}
|
|
22945
23072
|
|
|
23073
|
+
// src/shared/db/recordWindowTokens.ts
|
|
23074
|
+
import { and as and19, eq as eq37, sql as sql12 } from "drizzle-orm";
|
|
23075
|
+
async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
|
|
23076
|
+
if (tokensUp <= 0 && tokensDown <= 0) return;
|
|
23077
|
+
await db.update(usagePeaks).set({
|
|
23078
|
+
tokensUp: sql12`${usagePeaks.tokensUp} + ${tokensUp}`,
|
|
23079
|
+
tokensDown: sql12`${usagePeaks.tokensDown} + ${tokensDown}`
|
|
23080
|
+
}).where(
|
|
23081
|
+
and19(
|
|
23082
|
+
eq37(usagePeaks.window, window),
|
|
23083
|
+
eq37(usagePeaks.resetsAt, resetsAt),
|
|
23084
|
+
eq37(usagePeaks.segment, 0)
|
|
23085
|
+
)
|
|
23086
|
+
);
|
|
23087
|
+
}
|
|
23088
|
+
|
|
23089
|
+
// src/commands/sessions/shared/transcriptUsage.ts
|
|
23090
|
+
import * as fs31 from "fs";
|
|
23091
|
+
function transcriptUsage(lines) {
|
|
23092
|
+
const byId = /* @__PURE__ */ new Map();
|
|
23093
|
+
for (const line of lines) {
|
|
23094
|
+
if (!line.trim()) continue;
|
|
23095
|
+
let entry;
|
|
23096
|
+
try {
|
|
23097
|
+
entry = JSON.parse(line);
|
|
23098
|
+
} catch {
|
|
23099
|
+
continue;
|
|
23100
|
+
}
|
|
23101
|
+
if (entry.type !== "assistant") continue;
|
|
23102
|
+
const id = entry.message?.id;
|
|
23103
|
+
const usage = entry.message?.usage;
|
|
23104
|
+
if (!id || !usage) continue;
|
|
23105
|
+
byId.set(id, {
|
|
23106
|
+
messageId: id,
|
|
23107
|
+
inputTokens: usage.input_tokens ?? 0,
|
|
23108
|
+
outputTokens: usage.output_tokens ?? 0
|
|
23109
|
+
});
|
|
23110
|
+
}
|
|
23111
|
+
return [...byId.values()];
|
|
23112
|
+
}
|
|
23113
|
+
async function readTranscriptUsage(transcriptPath) {
|
|
23114
|
+
const content = await fs31.promises.readFile(transcriptPath, "utf8");
|
|
23115
|
+
return transcriptUsage(content.split("\n"));
|
|
23116
|
+
}
|
|
23117
|
+
|
|
22946
23118
|
// src/commands/sessions/daemon/persistPhaseTokens.ts
|
|
22947
|
-
async function persistPhaseTokens(itemId2, phaseIdx,
|
|
23119
|
+
async function persistPhaseTokens(itemId2, phaseIdx, transcriptPath, windows) {
|
|
22948
23120
|
try {
|
|
22949
23121
|
if (!process.env.ASSIST_DATABASE_URL && !loadConfig().database.url) return;
|
|
22950
|
-
|
|
23122
|
+
const responses = await readTranscriptUsage(transcriptPath);
|
|
23123
|
+
if (responses.length === 0) return;
|
|
23124
|
+
const db = await getDb();
|
|
23125
|
+
const { tokensUp, tokensDown } = await recordPhaseTranscriptUsage(
|
|
23126
|
+
db,
|
|
23127
|
+
itemId2,
|
|
23128
|
+
phaseIdx,
|
|
23129
|
+
responses
|
|
23130
|
+
);
|
|
23131
|
+
for (const { window, resetsAt } of windows) {
|
|
23132
|
+
await recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown);
|
|
23133
|
+
}
|
|
22951
23134
|
} catch (error) {
|
|
22952
23135
|
daemonLog(`phase-tokens persist failed: ${String(error)}`);
|
|
22953
23136
|
}
|
|
22954
23137
|
}
|
|
22955
23138
|
|
|
22956
23139
|
// src/commands/sessions/daemon/recordSessionUsage.ts
|
|
22957
|
-
function recordSessionUsage(sessions, claudeSessionId,
|
|
23140
|
+
function recordSessionUsage(sessions, claudeSessionId, transcriptPath, usedPct, windows) {
|
|
22958
23141
|
for (const session of sessions) {
|
|
22959
23142
|
if (session.claudeSessionId !== claudeSessionId) continue;
|
|
22960
23143
|
session.usedPct = usedPct;
|
|
22961
23144
|
const phase = sessionBacklogPhase(session);
|
|
22962
|
-
if (phase)
|
|
22963
|
-
void persistPhaseTokens(
|
|
23145
|
+
if (phase && transcriptPath)
|
|
23146
|
+
void persistPhaseTokens(
|
|
23147
|
+
phase.itemId,
|
|
23148
|
+
phase.phaseIdx,
|
|
23149
|
+
transcriptPath,
|
|
23150
|
+
windows
|
|
23151
|
+
);
|
|
22964
23152
|
return true;
|
|
22965
23153
|
}
|
|
22966
23154
|
return false;
|
|
@@ -22982,10 +23170,10 @@ function applyReviewPause(session, activity2) {
|
|
|
22982
23170
|
}
|
|
22983
23171
|
|
|
22984
23172
|
// src/shared/db/getPhaseActiveMs.ts
|
|
22985
|
-
import { and as
|
|
23173
|
+
import { and as and20, eq as eq38 } from "drizzle-orm";
|
|
22986
23174
|
async function getPhaseActiveMs(db, itemId2, phaseIdx) {
|
|
22987
23175
|
const [row] = await db.select({ activeMs: phaseUsage.activeMs }).from(phaseUsage).where(
|
|
22988
|
-
|
|
23176
|
+
and20(eq38(phaseUsage.itemId, itemId2), eq38(phaseUsage.phaseIdx, phaseIdx))
|
|
22989
23177
|
);
|
|
22990
23178
|
return row?.activeMs ?? 0;
|
|
22991
23179
|
}
|
|
@@ -24249,13 +24437,13 @@ var SessionManager = class {
|
|
|
24249
24437
|
}
|
|
24250
24438
|
/* why: the status line relays token totals keyed by Claude's session id; join
|
|
24251
24439
|
* it to the running backlog phase so the spend accumulates against that row. */
|
|
24252
|
-
recordUsage(claudeSessionId,
|
|
24440
|
+
recordUsage(claudeSessionId, transcriptPath, usedPct) {
|
|
24253
24441
|
if (recordSessionUsage(
|
|
24254
24442
|
this.sessions.values(),
|
|
24255
24443
|
claudeSessionId,
|
|
24256
|
-
|
|
24257
|
-
|
|
24258
|
-
|
|
24444
|
+
transcriptPath,
|
|
24445
|
+
usedPct,
|
|
24446
|
+
this.clients.currentWindows()
|
|
24259
24447
|
))
|
|
24260
24448
|
this.notify();
|
|
24261
24449
|
}
|
|
@@ -24279,12 +24467,12 @@ import * as net3 from "net";
|
|
|
24279
24467
|
import { createInterface as createInterface9 } from "readline";
|
|
24280
24468
|
|
|
24281
24469
|
// src/commands/sessions/shared/discoverSessions.ts
|
|
24282
|
-
import * as
|
|
24470
|
+
import * as fs33 from "fs";
|
|
24283
24471
|
import * as os from "os";
|
|
24284
24472
|
import * as path52 from "path";
|
|
24285
24473
|
|
|
24286
24474
|
// src/commands/sessions/shared/parseSessionFile.ts
|
|
24287
|
-
import * as
|
|
24475
|
+
import * as fs32 from "fs";
|
|
24288
24476
|
import * as path51 from "path";
|
|
24289
24477
|
|
|
24290
24478
|
// src/commands/sessions/shared/deriveHistoryFields.ts
|
|
@@ -24315,8 +24503,8 @@ function deriveSessionType(commandName, name) {
|
|
|
24315
24503
|
}
|
|
24316
24504
|
|
|
24317
24505
|
// src/commands/sessions/shared/backlogRunMarkers.ts
|
|
24318
|
-
function backlogRunMarkers(
|
|
24319
|
-
const match =
|
|
24506
|
+
function backlogRunMarkers(text10) {
|
|
24507
|
+
const match = text10.match(/backlog item a(\d+):[ \t]*([^\n]*)/);
|
|
24320
24508
|
if (!match) return { commandName: "", commandArgs: "" };
|
|
24321
24509
|
const title = match[2].trim();
|
|
24322
24510
|
return {
|
|
@@ -24370,11 +24558,11 @@ function messageText(entry) {
|
|
|
24370
24558
|
const content = msg?.content;
|
|
24371
24559
|
return typeof content === "string" ? content : Array.isArray(content) ? content.find((c) => c.type === "text")?.text ?? "" : "";
|
|
24372
24560
|
}
|
|
24373
|
-
function stripMarkers(
|
|
24374
|
-
return
|
|
24561
|
+
function stripMarkers(text10) {
|
|
24562
|
+
return text10.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
|
|
24375
24563
|
}
|
|
24376
|
-
function matchMarker(
|
|
24377
|
-
const match =
|
|
24564
|
+
function matchMarker(text10, tag) {
|
|
24565
|
+
const match = text10.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
|
|
24378
24566
|
return match ? match[1].trim() : "";
|
|
24379
24567
|
}
|
|
24380
24568
|
|
|
@@ -24382,10 +24570,10 @@ function matchMarker(text9, tag) {
|
|
|
24382
24570
|
async function parseSessionFile(filePath, origin = "wsl") {
|
|
24383
24571
|
let handle;
|
|
24384
24572
|
try {
|
|
24385
|
-
handle = await
|
|
24573
|
+
handle = await fs32.promises.open(filePath, "r");
|
|
24386
24574
|
const meta = extractSessionMeta(await readHeadLines(handle));
|
|
24387
24575
|
if (!meta.sessionId) return null;
|
|
24388
|
-
const timestamp5 = meta.timestamp || (await
|
|
24576
|
+
const timestamp5 = meta.timestamp || (await fs32.promises.stat(filePath)).mtime.toISOString();
|
|
24389
24577
|
return {
|
|
24390
24578
|
sessionId: meta.sessionId,
|
|
24391
24579
|
name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
|
|
@@ -24431,7 +24619,7 @@ async function discoverSessionJsonlPaths() {
|
|
|
24431
24619
|
sessionRoots().map(async ({ dir, origin }) => {
|
|
24432
24620
|
let projectDirs;
|
|
24433
24621
|
try {
|
|
24434
|
-
projectDirs = await
|
|
24622
|
+
projectDirs = await fs33.promises.readdir(dir);
|
|
24435
24623
|
} catch {
|
|
24436
24624
|
return;
|
|
24437
24625
|
}
|
|
@@ -24440,7 +24628,7 @@ async function discoverSessionJsonlPaths() {
|
|
|
24440
24628
|
const dirPath = path52.join(dir, dirName);
|
|
24441
24629
|
let entries;
|
|
24442
24630
|
try {
|
|
24443
|
-
entries = await
|
|
24631
|
+
entries = await fs33.promises.readdir(dirPath);
|
|
24444
24632
|
} catch {
|
|
24445
24633
|
return;
|
|
24446
24634
|
}
|
|
@@ -24473,7 +24661,7 @@ async function discoverSessions() {
|
|
|
24473
24661
|
}
|
|
24474
24662
|
|
|
24475
24663
|
// src/commands/sessions/shared/parseTranscript.ts
|
|
24476
|
-
import * as
|
|
24664
|
+
import * as fs34 from "fs";
|
|
24477
24665
|
|
|
24478
24666
|
// src/commands/sessions/shared/toolTarget.ts
|
|
24479
24667
|
function toolTarget(input) {
|
|
@@ -24492,17 +24680,17 @@ function entryMessages(entry) {
|
|
|
24492
24680
|
return [];
|
|
24493
24681
|
}
|
|
24494
24682
|
function userMessages(content) {
|
|
24495
|
-
if (typeof content === "string") return
|
|
24683
|
+
if (typeof content === "string") return text9("user", cleanUserText(content));
|
|
24496
24684
|
if (!Array.isArray(content)) return [];
|
|
24497
|
-
return content.filter((c) => c.type === "text").flatMap((c) =>
|
|
24685
|
+
return content.filter((c) => c.type === "text").flatMap((c) => text9("user", cleanUserText(c.text ?? "")));
|
|
24498
24686
|
}
|
|
24499
24687
|
function assistantMessages(content) {
|
|
24500
|
-
if (typeof content === "string") return
|
|
24688
|
+
if (typeof content === "string") return text9("assistant", content.trim());
|
|
24501
24689
|
if (!Array.isArray(content)) return [];
|
|
24502
24690
|
return content.flatMap((c) => assistantItem(c));
|
|
24503
24691
|
}
|
|
24504
24692
|
function assistantItem(c) {
|
|
24505
|
-
if (c.type === "text") return
|
|
24693
|
+
if (c.type === "text") return text9("assistant", (c.text ?? "").trim());
|
|
24506
24694
|
if (c.type === "tool_use")
|
|
24507
24695
|
return [
|
|
24508
24696
|
{
|
|
@@ -24513,7 +24701,7 @@ function assistantItem(c) {
|
|
|
24513
24701
|
];
|
|
24514
24702
|
return [];
|
|
24515
24703
|
}
|
|
24516
|
-
function
|
|
24704
|
+
function text9(role, value) {
|
|
24517
24705
|
return value ? [{ role, text: value }] : [];
|
|
24518
24706
|
}
|
|
24519
24707
|
function cleanUserText(value) {
|
|
@@ -24540,7 +24728,7 @@ async function parseTranscript(sessionId) {
|
|
|
24540
24728
|
const filePath = await findSessionJsonlPath(sessionId);
|
|
24541
24729
|
if (!filePath) return [];
|
|
24542
24730
|
try {
|
|
24543
|
-
const raw = await
|
|
24731
|
+
const raw = await fs34.promises.readFile(filePath, "utf8");
|
|
24544
24732
|
return parseTranscriptLines(raw.split("\n"));
|
|
24545
24733
|
} catch {
|
|
24546
24734
|
return [];
|
|
@@ -24638,8 +24826,7 @@ var messageHandlers = {
|
|
|
24638
24826
|
limits: (_client, m, d) => m.clients.updateLimits(d.rateLimits),
|
|
24639
24827
|
usage: (_client, m, d) => m.recordUsage(
|
|
24640
24828
|
d.claudeSessionId,
|
|
24641
|
-
d.
|
|
24642
|
-
d.totalOut,
|
|
24829
|
+
d.transcriptPath,
|
|
24643
24830
|
d.usedPct
|
|
24644
24831
|
),
|
|
24645
24832
|
input: routed(
|
|
@@ -24850,17 +25037,17 @@ function registerDaemon(program2) {
|
|
|
24850
25037
|
}
|
|
24851
25038
|
|
|
24852
25039
|
// src/commands/sessions/summarise/index.ts
|
|
24853
|
-
import * as
|
|
25040
|
+
import * as fs37 from "fs";
|
|
24854
25041
|
import chalk193 from "chalk";
|
|
24855
25042
|
|
|
24856
25043
|
// src/commands/sessions/summarise/shared.ts
|
|
24857
|
-
import * as
|
|
25044
|
+
import * as fs35 from "fs";
|
|
24858
25045
|
function writeSummary(jsonlPath2, summary) {
|
|
24859
|
-
|
|
25046
|
+
fs35.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
|
|
24860
25047
|
`, "utf8");
|
|
24861
25048
|
}
|
|
24862
25049
|
function hasSummary(jsonlPath2) {
|
|
24863
|
-
return
|
|
25050
|
+
return fs35.existsSync(summaryPathFor(jsonlPath2));
|
|
24864
25051
|
}
|
|
24865
25052
|
function summaryPathFor(jsonlPath2) {
|
|
24866
25053
|
return jsonlPath2.replace(/\.jsonl$/, ".summary");
|
|
@@ -24870,7 +25057,7 @@ function summaryPathFor(jsonlPath2) {
|
|
|
24870
25057
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
24871
25058
|
|
|
24872
25059
|
// src/commands/sessions/summarise/iterateUserMessages.ts
|
|
24873
|
-
import * as
|
|
25060
|
+
import * as fs36 from "fs";
|
|
24874
25061
|
|
|
24875
25062
|
// src/commands/sessions/summarise/parseUserLine.ts
|
|
24876
25063
|
function parseUserLine(line) {
|
|
@@ -24883,16 +25070,16 @@ function parseUserLine(line) {
|
|
|
24883
25070
|
if (entry.type !== "user") return void 0;
|
|
24884
25071
|
const msg = entry.message;
|
|
24885
25072
|
const c = msg?.content;
|
|
24886
|
-
let
|
|
25073
|
+
let text10;
|
|
24887
25074
|
if (typeof c === "string") {
|
|
24888
|
-
|
|
25075
|
+
text10 = c;
|
|
24889
25076
|
} else if (Array.isArray(c)) {
|
|
24890
25077
|
const collected = c.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n");
|
|
24891
|
-
|
|
25078
|
+
text10 = collected || void 0;
|
|
24892
25079
|
}
|
|
24893
|
-
if (!
|
|
25080
|
+
if (!text10) return void 0;
|
|
24894
25081
|
return {
|
|
24895
|
-
text:
|
|
25082
|
+
text: text10,
|
|
24896
25083
|
entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
|
|
24897
25084
|
};
|
|
24898
25085
|
}
|
|
@@ -24901,13 +25088,13 @@ function parseUserLine(line) {
|
|
|
24901
25088
|
function* iterateUserMessages(filePath, maxBytes = 65536) {
|
|
24902
25089
|
let content;
|
|
24903
25090
|
try {
|
|
24904
|
-
const fd =
|
|
25091
|
+
const fd = fs36.openSync(filePath, "r");
|
|
24905
25092
|
try {
|
|
24906
25093
|
const buf = Buffer.alloc(maxBytes);
|
|
24907
|
-
const bytesRead =
|
|
25094
|
+
const bytesRead = fs36.readSync(fd, buf, 0, buf.length, 0);
|
|
24908
25095
|
content = buf.toString("utf8", 0, bytesRead);
|
|
24909
25096
|
} finally {
|
|
24910
|
-
|
|
25097
|
+
fs36.closeSync(fd);
|
|
24911
25098
|
}
|
|
24912
25099
|
} catch {
|
|
24913
25100
|
return;
|
|
@@ -24921,13 +25108,13 @@ function* iterateUserMessages(filePath, maxBytes = 65536) {
|
|
|
24921
25108
|
|
|
24922
25109
|
// src/commands/sessions/summarise/extractFirstUserMessage.ts
|
|
24923
25110
|
function extractFirstUserMessage(filePath) {
|
|
24924
|
-
for (const
|
|
24925
|
-
return truncate3(
|
|
25111
|
+
for (const text10 of iterateUserMessages(filePath)) {
|
|
25112
|
+
return truncate3(text10);
|
|
24926
25113
|
}
|
|
24927
25114
|
return void 0;
|
|
24928
25115
|
}
|
|
24929
|
-
function truncate3(
|
|
24930
|
-
const trimmed =
|
|
25116
|
+
function truncate3(text10, maxChars = 500) {
|
|
25117
|
+
const trimmed = text10.trim();
|
|
24931
25118
|
if (trimmed.length <= maxChars) return trimmed;
|
|
24932
25119
|
return `${trimmed.slice(0, maxChars)}\u2026`;
|
|
24933
25120
|
}
|
|
@@ -24935,28 +25122,28 @@ function truncate3(text9, maxChars = 500) {
|
|
|
24935
25122
|
// src/commands/sessions/summarise/scanSessionBacklogRefs.ts
|
|
24936
25123
|
function scanSessionBacklogRefs(filePath) {
|
|
24937
25124
|
const ids = /* @__PURE__ */ new Set();
|
|
24938
|
-
for (const
|
|
24939
|
-
for (const id of extractBacklogIds(
|
|
25125
|
+
for (const text10 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
|
|
25126
|
+
for (const id of extractBacklogIds(text10)) {
|
|
24940
25127
|
ids.add(id);
|
|
24941
25128
|
}
|
|
24942
25129
|
}
|
|
24943
25130
|
return [...ids].sort((a, b) => a - b);
|
|
24944
25131
|
}
|
|
24945
|
-
function extractBacklogIds(
|
|
25132
|
+
function extractBacklogIds(text10) {
|
|
24946
25133
|
const ids = [];
|
|
24947
|
-
for (const m of
|
|
25134
|
+
for (const m of text10.matchAll(/backlog\s+run\s+a(\d+)/gi)) {
|
|
24948
25135
|
ids.push(Number.parseInt(m[1], 10));
|
|
24949
25136
|
}
|
|
24950
|
-
for (const m of
|
|
25137
|
+
for (const m of text10.matchAll(/backlog\s+(?:item\s+)?a(\d+)/gi)) {
|
|
24951
25138
|
ids.push(Number.parseInt(m[1], 10));
|
|
24952
25139
|
}
|
|
24953
|
-
for (const m of
|
|
25140
|
+
for (const m of text10.matchAll(/backlog\s+phase-done\s+a(\d+)/gi)) {
|
|
24954
25141
|
ids.push(Number.parseInt(m[1], 10));
|
|
24955
25142
|
}
|
|
24956
|
-
for (const m of
|
|
25143
|
+
for (const m of text10.matchAll(/backlog\s+comment\s+a(\d+)/gi)) {
|
|
24957
25144
|
ids.push(Number.parseInt(m[1], 10));
|
|
24958
25145
|
}
|
|
24959
|
-
for (const m of
|
|
25146
|
+
for (const m of text10.matchAll(/(?:^|[\s(])a(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
|
|
24960
25147
|
ids.push(Number.parseInt(m[1], 10));
|
|
24961
25148
|
}
|
|
24962
25149
|
return ids;
|
|
@@ -25027,7 +25214,7 @@ function selectCandidates(files, options2) {
|
|
|
25027
25214
|
const candidates = options2.force ? files : files.filter((f) => !hasSummary(f));
|
|
25028
25215
|
candidates.sort((a, b) => {
|
|
25029
25216
|
try {
|
|
25030
|
-
return
|
|
25217
|
+
return fs37.statSync(b).mtimeMs - fs37.statSync(a).mtimeMs;
|
|
25031
25218
|
} catch {
|
|
25032
25219
|
return 0;
|
|
25033
25220
|
}
|
|
@@ -25207,14 +25394,13 @@ async function relayRateLimits(rateLimits) {
|
|
|
25207
25394
|
}
|
|
25208
25395
|
|
|
25209
25396
|
// src/commands/relayUsage.ts
|
|
25210
|
-
async function relayUsage(claudeSessionId,
|
|
25397
|
+
async function relayUsage(claudeSessionId, transcriptPath, usedPct) {
|
|
25211
25398
|
if (!claudeSessionId) return;
|
|
25212
25399
|
try {
|
|
25213
25400
|
await sendToDaemon({
|
|
25214
25401
|
type: "usage",
|
|
25215
25402
|
claudeSessionId,
|
|
25216
|
-
|
|
25217
|
-
totalOut,
|
|
25403
|
+
transcriptPath,
|
|
25218
25404
|
usedPct
|
|
25219
25405
|
});
|
|
25220
25406
|
} catch {
|
|
@@ -25247,28 +25433,27 @@ async function statusLine() {
|
|
|
25247
25433
|
await relayRateLimits(data.rate_limits);
|
|
25248
25434
|
await relayUsage(
|
|
25249
25435
|
data.session_id,
|
|
25250
|
-
|
|
25251
|
-
totalOut,
|
|
25436
|
+
data.transcript_path,
|
|
25252
25437
|
data.context_window.used_percentage
|
|
25253
25438
|
);
|
|
25254
25439
|
}
|
|
25255
25440
|
|
|
25256
25441
|
// src/commands/sync.ts
|
|
25257
|
-
import * as
|
|
25442
|
+
import * as fs40 from "fs";
|
|
25258
25443
|
import * as os2 from "os";
|
|
25259
25444
|
import * as path56 from "path";
|
|
25260
25445
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
25261
25446
|
|
|
25262
25447
|
// src/commands/sync/syncClaudeMd.ts
|
|
25263
|
-
import * as
|
|
25448
|
+
import * as fs38 from "fs";
|
|
25264
25449
|
import * as path54 from "path";
|
|
25265
25450
|
import chalk196 from "chalk";
|
|
25266
25451
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
25267
25452
|
const source = path54.join(claudeDir, "CLAUDE.md");
|
|
25268
25453
|
const target = path54.join(targetBase, "CLAUDE.md");
|
|
25269
|
-
const sourceContent =
|
|
25270
|
-
if (
|
|
25271
|
-
const targetContent =
|
|
25454
|
+
const sourceContent = fs38.readFileSync(source, "utf8");
|
|
25455
|
+
if (fs38.existsSync(target)) {
|
|
25456
|
+
const targetContent = fs38.readFileSync(target, "utf8");
|
|
25272
25457
|
if (sourceContent !== targetContent) {
|
|
25273
25458
|
console.log(
|
|
25274
25459
|
chalk196.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
@@ -25285,21 +25470,21 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
25285
25470
|
}
|
|
25286
25471
|
}
|
|
25287
25472
|
}
|
|
25288
|
-
|
|
25473
|
+
fs38.copyFileSync(source, target);
|
|
25289
25474
|
console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
|
|
25290
25475
|
}
|
|
25291
25476
|
|
|
25292
25477
|
// src/commands/sync/syncSettings.ts
|
|
25293
|
-
import * as
|
|
25478
|
+
import * as fs39 from "fs";
|
|
25294
25479
|
import * as path55 from "path";
|
|
25295
25480
|
import chalk197 from "chalk";
|
|
25296
25481
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
25297
25482
|
const source = path55.join(claudeDir, "settings.json");
|
|
25298
25483
|
const target = path55.join(targetBase, "settings.json");
|
|
25299
|
-
const sourceContent =
|
|
25484
|
+
const sourceContent = fs39.readFileSync(source, "utf8");
|
|
25300
25485
|
const sourceSettings = JSON.parse(sourceContent);
|
|
25301
|
-
const targetExists =
|
|
25302
|
-
const targetContent = targetExists ?
|
|
25486
|
+
const targetExists = fs39.existsSync(target);
|
|
25487
|
+
const targetContent = targetExists ? fs39.readFileSync(target, "utf8") : "";
|
|
25303
25488
|
const preservedUserSettings = targetExists ? JSON.parse(targetContent) : {};
|
|
25304
25489
|
const mergedContent = JSON.stringify(
|
|
25305
25490
|
{ ...preservedUserSettings, ...sourceSettings },
|
|
@@ -25328,7 +25513,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
25328
25513
|
}
|
|
25329
25514
|
}
|
|
25330
25515
|
}
|
|
25331
|
-
|
|
25516
|
+
fs39.writeFileSync(target, mergedContent);
|
|
25332
25517
|
console.log("Copied settings.json to ~/.claude/settings.json");
|
|
25333
25518
|
}
|
|
25334
25519
|
|
|
@@ -25347,10 +25532,10 @@ async function sync(options2) {
|
|
|
25347
25532
|
function syncCommands(claudeDir, targetBase) {
|
|
25348
25533
|
const sourceDir = path56.join(claudeDir, "commands");
|
|
25349
25534
|
const targetDir = path56.join(targetBase, "commands");
|
|
25350
|
-
|
|
25351
|
-
const files =
|
|
25535
|
+
fs40.mkdirSync(targetDir, { recursive: true });
|
|
25536
|
+
const files = fs40.readdirSync(sourceDir);
|
|
25352
25537
|
for (const file of files) {
|
|
25353
|
-
|
|
25538
|
+
fs40.copyFileSync(path56.join(sourceDir, file), path56.join(targetDir, file));
|
|
25354
25539
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
25355
25540
|
}
|
|
25356
25541
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|