@staff0rd/assist 0.381.0 → 0.382.1
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/claude/CLAUDE.md +4 -0
- package/dist/commands/sessions/web/bundle.js +72 -72
- package/dist/index.js +482 -305
- package/package.json +2 -10
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.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -27,15 +27,7 @@ var package_default = {
|
|
|
27
27
|
build: "tsup",
|
|
28
28
|
start: "node dist/index.js",
|
|
29
29
|
"check:types": "tsc --noEmit",
|
|
30
|
-
test: "vitest run"
|
|
31
|
-
"verify:lint": "oxlint --config .oxlintrc.json src",
|
|
32
|
-
"verify:format": "oxfmt .",
|
|
33
|
-
"verify:knip": "knip --no-progress --treat-config-hints-as-errors",
|
|
34
|
-
"verify:duplicate-code": 'jscpd --format typescript,tsx,python --exitCode 1 --ignore "**/*.test.*,**/.venv/**" -r consoleFull src',
|
|
35
|
-
"verify:test": "vitest run --changed --passWithNoTests --reporter dot",
|
|
36
|
-
"verify:config-keys": "tsx src/index.ts verify config-keys",
|
|
37
|
-
"verify:react-build": "esbuild src/commands/sessions/web/ui/App.tsx --bundle --minify --format=iife --target=es2020 --outfile=dist/commands/sessions/web/bundle.verify.js --jsx=automatic --jsx-import-source=react --define:process.env.NODE_ENV='production'",
|
|
38
|
-
"verify:circular-deps": "skott --displayMode=raw --showCircularDependencies --exitCodeOnCircularDependencies=1 src/index.ts"
|
|
30
|
+
test: "vitest run"
|
|
39
31
|
},
|
|
40
32
|
overrides: {
|
|
41
33
|
lodash: "^4.18.0",
|
|
@@ -432,10 +424,10 @@ function getTranscriptConfig() {
|
|
|
432
424
|
// src/shared/db/schema.ts
|
|
433
425
|
import {
|
|
434
426
|
foreignKey,
|
|
435
|
-
integer as
|
|
436
|
-
pgTable as
|
|
437
|
-
primaryKey as
|
|
438
|
-
text as
|
|
427
|
+
integer as integer9,
|
|
428
|
+
pgTable as pgTable9,
|
|
429
|
+
primaryKey as primaryKey6,
|
|
430
|
+
text as text8
|
|
439
431
|
} from "drizzle-orm/pg-core";
|
|
440
432
|
|
|
441
433
|
// src/shared/db/backups.ts
|
|
@@ -536,82 +528,96 @@ var phaseUsage = pgTable6(
|
|
|
536
528
|
(t) => [primaryKey3({ columns: [t.itemId, t.phaseIdx] })]
|
|
537
529
|
);
|
|
538
530
|
|
|
531
|
+
// src/shared/db/phaseUsageMessages.ts
|
|
532
|
+
import { integer as integer7, pgTable as pgTable7, primaryKey as primaryKey4, text as text6 } from "drizzle-orm/pg-core";
|
|
533
|
+
var phaseUsageMessages = pgTable7(
|
|
534
|
+
"phase_usage_messages",
|
|
535
|
+
{
|
|
536
|
+
itemId: integer7("item_id").notNull(),
|
|
537
|
+
phaseIdx: integer7("phase_idx").notNull(),
|
|
538
|
+
messageId: text6("message_id").notNull()
|
|
539
|
+
},
|
|
540
|
+
(t) => [primaryKey4({ columns: [t.itemId, t.phaseIdx, t.messageId] })]
|
|
541
|
+
);
|
|
542
|
+
|
|
539
543
|
// src/shared/db/usagePeaks.ts
|
|
540
544
|
import {
|
|
541
545
|
bigint as bigint3,
|
|
542
546
|
boolean as boolean2,
|
|
543
547
|
doublePrecision,
|
|
544
|
-
integer as
|
|
545
|
-
pgTable as
|
|
546
|
-
primaryKey as
|
|
547
|
-
text as
|
|
548
|
+
integer as integer8,
|
|
549
|
+
pgTable as pgTable8,
|
|
550
|
+
primaryKey as primaryKey5,
|
|
551
|
+
text as text7,
|
|
548
552
|
timestamp as timestamp4
|
|
549
553
|
} from "drizzle-orm/pg-core";
|
|
550
|
-
var usagePeaks =
|
|
554
|
+
var usagePeaks = pgTable8(
|
|
551
555
|
"usage_peaks",
|
|
552
556
|
{
|
|
553
|
-
window:
|
|
557
|
+
window: text7().$type().notNull(),
|
|
554
558
|
resetsAt: bigint3("resets_at", { mode: "number" }).notNull(),
|
|
555
|
-
segment:
|
|
559
|
+
segment: integer8().notNull().default(0),
|
|
556
560
|
usedPercentage: doublePrecision("used_percentage").notNull(),
|
|
557
561
|
resetDetected: boolean2("reset_detected").notNull().default(false),
|
|
562
|
+
tokensUp: bigint3("tokens_up", { mode: "number" }).notNull().default(0),
|
|
563
|
+
tokensDown: bigint3("tokens_down", { mode: "number" }).notNull().default(0),
|
|
558
564
|
createdAt: timestamp4("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
559
565
|
},
|
|
560
|
-
(t) => [
|
|
566
|
+
(t) => [primaryKey5({ columns: [t.window, t.resetsAt, t.segment] })]
|
|
561
567
|
);
|
|
562
568
|
|
|
563
569
|
// src/shared/db/schema.ts
|
|
564
|
-
var comments =
|
|
565
|
-
id:
|
|
566
|
-
itemId:
|
|
567
|
-
idx:
|
|
568
|
-
text:
|
|
569
|
-
phase:
|
|
570
|
-
timestamp:
|
|
571
|
-
type:
|
|
570
|
+
var comments = pgTable9("comments", {
|
|
571
|
+
id: integer9().generatedByDefaultAsIdentity().primaryKey(),
|
|
572
|
+
itemId: integer9("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
|
|
573
|
+
idx: integer9().notNull(),
|
|
574
|
+
text: text8().notNull(),
|
|
575
|
+
phase: integer9(),
|
|
576
|
+
timestamp: text8().notNull(),
|
|
577
|
+
type: text8().notNull().default("comment")
|
|
572
578
|
});
|
|
573
|
-
var links =
|
|
579
|
+
var links = pgTable9(
|
|
574
580
|
"links",
|
|
575
581
|
{
|
|
576
|
-
itemId:
|
|
577
|
-
type:
|
|
578
|
-
targetId:
|
|
582
|
+
itemId: integer9("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
|
|
583
|
+
type: text8().notNull(),
|
|
584
|
+
targetId: integer9("target_id").notNull()
|
|
579
585
|
},
|
|
580
|
-
(t) => [
|
|
586
|
+
(t) => [primaryKey6({ columns: [t.itemId, t.type, t.targetId] })]
|
|
581
587
|
);
|
|
582
|
-
var planPhases =
|
|
588
|
+
var planPhases = pgTable9(
|
|
583
589
|
"plan_phases",
|
|
584
590
|
{
|
|
585
|
-
itemId:
|
|
586
|
-
idx:
|
|
587
|
-
name:
|
|
588
|
-
manualChecks:
|
|
591
|
+
itemId: integer9("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
|
|
592
|
+
idx: integer9().notNull(),
|
|
593
|
+
name: text8().notNull(),
|
|
594
|
+
manualChecks: text8("manual_checks")
|
|
589
595
|
},
|
|
590
|
-
(t) => [
|
|
596
|
+
(t) => [primaryKey6({ columns: [t.itemId, t.idx] })]
|
|
591
597
|
);
|
|
592
|
-
var planTasks =
|
|
598
|
+
var planTasks = pgTable9(
|
|
593
599
|
"plan_tasks",
|
|
594
600
|
{
|
|
595
|
-
itemId:
|
|
596
|
-
phaseIdx:
|
|
597
|
-
idx:
|
|
598
|
-
task:
|
|
601
|
+
itemId: integer9("item_id").notNull(),
|
|
602
|
+
phaseIdx: integer9("phase_idx").notNull(),
|
|
603
|
+
idx: integer9().notNull(),
|
|
604
|
+
task: text8().notNull()
|
|
599
605
|
},
|
|
600
606
|
(t) => [
|
|
601
|
-
|
|
607
|
+
primaryKey6({ columns: [t.itemId, t.phaseIdx, t.idx] }),
|
|
602
608
|
foreignKey({
|
|
603
609
|
columns: [t.itemId, t.phaseIdx],
|
|
604
610
|
foreignColumns: [planPhases.itemId, planPhases.idx]
|
|
605
611
|
}).onDelete("cascade")
|
|
606
612
|
]
|
|
607
613
|
);
|
|
608
|
-
var metadata =
|
|
609
|
-
key:
|
|
610
|
-
value:
|
|
614
|
+
var metadata = pgTable9("metadata", {
|
|
615
|
+
key: text8().primaryKey(),
|
|
616
|
+
value: text8().notNull()
|
|
611
617
|
});
|
|
612
|
-
var feeds =
|
|
613
|
-
id:
|
|
614
|
-
url:
|
|
618
|
+
var feeds = pgTable9("feeds", {
|
|
619
|
+
id: integer9().generatedByDefaultAsIdentity().primaryKey(),
|
|
620
|
+
url: text8().notNull().unique()
|
|
615
621
|
});
|
|
616
622
|
var schema = {
|
|
617
623
|
items,
|
|
@@ -626,7 +632,8 @@ var schema = {
|
|
|
626
632
|
handovers,
|
|
627
633
|
usagePeaks,
|
|
628
634
|
backups,
|
|
629
|
-
phaseUsage
|
|
635
|
+
phaseUsage,
|
|
636
|
+
phaseUsageMessages
|
|
630
637
|
};
|
|
631
638
|
|
|
632
639
|
// src/commands/backlog/addFeed.ts
|
|
@@ -662,30 +669,27 @@ async function seedNewsFeeds(db) {
|
|
|
662
669
|
import { and as and2, eq as eq2 } from "drizzle-orm";
|
|
663
670
|
|
|
664
671
|
// src/shared/db/recordWindowPeak.ts
|
|
665
|
-
import {
|
|
672
|
+
import { sql } from "drizzle-orm";
|
|
673
|
+
|
|
674
|
+
// src/shared/db/applyReading.ts
|
|
675
|
+
import { and, eq, gt } from "drizzle-orm";
|
|
666
676
|
var RESET_DROP_THRESHOLD = 1;
|
|
667
677
|
var at = ({ window, resetsAt }, segment) => segment === void 0 ? and(eq(usagePeaks.window, window), eq(usagePeaks.resetsAt, resetsAt)) : and(
|
|
668
678
|
eq(usagePeaks.window, window),
|
|
669
679
|
eq(usagePeaks.resetsAt, resetsAt),
|
|
670
680
|
eq(usagePeaks.segment, segment)
|
|
671
681
|
);
|
|
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
682
|
var insertSegment = (c, segment, usedPercentage) => c.tx.insert(usagePeaks).values({
|
|
677
683
|
window: c.window,
|
|
678
684
|
resetsAt: c.resetsAt,
|
|
679
685
|
segment,
|
|
680
686
|
usedPercentage
|
|
681
687
|
});
|
|
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);
|
|
688
|
+
var load = (c) => c.tx.select().from(usagePeaks).where(at(c)).orderBy(usagePeaks.segment);
|
|
689
|
+
async function applyReading(c, usedPercentage) {
|
|
690
|
+
const segments = await load(c);
|
|
691
|
+
if (segments.length === 0) await insertSegment(c, 0, usedPercentage);
|
|
692
|
+
else await reconcile(c, segments, usedPercentage);
|
|
689
693
|
}
|
|
690
694
|
async function reconcile(c, segments, usedPercentage) {
|
|
691
695
|
const reached = segments.find((s) => usedPercentage >= s.usedPercentage);
|
|
@@ -698,13 +702,24 @@ async function reconcile(c, segments, usedPercentage) {
|
|
|
698
702
|
await openReset(c, active, usedPercentage);
|
|
699
703
|
}
|
|
700
704
|
}
|
|
705
|
+
async function collapseToReached(c, reached, usedPercentage) {
|
|
706
|
+
await c.tx.delete(usagePeaks).where(and(at(c), gt(usagePeaks.segment, reached.segment)));
|
|
707
|
+
await c.tx.update(usagePeaks).set({ usedPercentage, resetDetected: false }).where(at(c, reached.segment));
|
|
708
|
+
}
|
|
709
|
+
async function openReset(c, active, usedPercentage) {
|
|
710
|
+
await c.tx.update(usagePeaks).set({ resetDetected: true }).where(at(c, active.segment));
|
|
711
|
+
await insertSegment(c, active.segment + 1, usedPercentage);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// src/shared/db/recordWindowPeak.ts
|
|
715
|
+
var lock = ({ tx, window, resetsAt }) => tx.execute(
|
|
716
|
+
sql`SELECT pg_advisory_xact_lock(hashtextextended(${`${window}:${resetsAt}`}, 0))`
|
|
717
|
+
);
|
|
701
718
|
async function recordWindowPeak(db, window, resetsAt, usedPercentage) {
|
|
702
719
|
await db.transaction(async (tx) => {
|
|
703
720
|
const c = { tx, window, resetsAt };
|
|
704
721
|
await lock(c);
|
|
705
|
-
|
|
706
|
-
if (segments.length === 0) await insertSegment(c, 0, usedPercentage);
|
|
707
|
-
else await reconcile(c, segments, usedPercentage);
|
|
722
|
+
await applyReading(c, usedPercentage);
|
|
708
723
|
});
|
|
709
724
|
}
|
|
710
725
|
|
|
@@ -859,6 +874,8 @@ var SCHEMA = `
|
|
|
859
874
|
segment INTEGER NOT NULL DEFAULT 0,
|
|
860
875
|
used_percentage DOUBLE PRECISION NOT NULL,
|
|
861
876
|
reset_detected BOOLEAN NOT NULL DEFAULT false,
|
|
877
|
+
tokens_up BIGINT NOT NULL DEFAULT 0,
|
|
878
|
+
tokens_down BIGINT NOT NULL DEFAULT 0,
|
|
862
879
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
863
880
|
PRIMARY KEY ("window", resets_at, segment)
|
|
864
881
|
);
|
|
@@ -867,6 +884,8 @@ var SCHEMA = `
|
|
|
867
884
|
ALTER TABLE usage_peaks ADD COLUMN IF NOT EXISTS reset_detected BOOLEAN NOT NULL DEFAULT false;
|
|
868
885
|
ALTER TABLE usage_peaks ADD COLUMN IF NOT EXISTS segment INTEGER NOT NULL DEFAULT 0;
|
|
869
886
|
ALTER TABLE usage_peaks ADD COLUMN IF NOT EXISTS created_at TIMESTAMPTZ NOT NULL DEFAULT now();
|
|
887
|
+
ALTER TABLE usage_peaks ADD COLUMN IF NOT EXISTS tokens_up BIGINT NOT NULL DEFAULT 0;
|
|
888
|
+
ALTER TABLE usage_peaks ADD COLUMN IF NOT EXISTS tokens_down BIGINT NOT NULL DEFAULT 0;
|
|
870
889
|
|
|
871
890
|
-- Widen the primary key to include segment so a cycle can hold both its
|
|
872
891
|
-- pre-reset peak and its post-reset continuation. Idempotent: only fires
|
|
@@ -907,6 +926,16 @@ var SCHEMA = `
|
|
|
907
926
|
PRIMARY KEY (item_id, phase_idx)
|
|
908
927
|
);
|
|
909
928
|
|
|
929
|
+
ALTER TABLE phase_usage ADD COLUMN IF NOT EXISTS last_total_in BIGINT;
|
|
930
|
+
ALTER TABLE phase_usage ADD COLUMN IF NOT EXISTS last_total_out BIGINT;
|
|
931
|
+
|
|
932
|
+
CREATE TABLE IF NOT EXISTS phase_usage_messages (
|
|
933
|
+
item_id INTEGER NOT NULL REFERENCES items(id) ON DELETE CASCADE,
|
|
934
|
+
phase_idx INTEGER NOT NULL,
|
|
935
|
+
message_id TEXT NOT NULL,
|
|
936
|
+
PRIMARY KEY (item_id, phase_idx, message_id)
|
|
937
|
+
);
|
|
938
|
+
|
|
910
939
|
-- Git activity (branch/commit/PR) snapshotted for an item during a run. The
|
|
911
940
|
-- (item_id, kind, ref) primary key makes re-snapshotting the same ref a no-op
|
|
912
941
|
-- upsert rather than a duplicate row.
|
|
@@ -973,7 +1002,7 @@ function createPool() {
|
|
|
973
1002
|
return pool;
|
|
974
1003
|
}
|
|
975
1004
|
async function initSchema(pool) {
|
|
976
|
-
await ensureSchema((
|
|
1005
|
+
await ensureSchema((sql13) => pool.query(sql13));
|
|
977
1006
|
const orm = makeOrmFromPool(pool);
|
|
978
1007
|
await seedNewsFeeds(orm);
|
|
979
1008
|
await runUsagePeakCleanup(orm);
|
|
@@ -2564,8 +2593,8 @@ function isHashCommentFile(filePath) {
|
|
|
2564
2593
|
import fs13 from "fs";
|
|
2565
2594
|
|
|
2566
2595
|
// src/commands/verify/blockComments/collectHashComments.ts
|
|
2567
|
-
function blankNonNewline(
|
|
2568
|
-
return
|
|
2596
|
+
function blankNonNewline(text10) {
|
|
2597
|
+
return text10.replace(/[^\n]/g, " ");
|
|
2569
2598
|
}
|
|
2570
2599
|
function isHeaderLine(line) {
|
|
2571
2600
|
const trimmed = line.trim();
|
|
@@ -2642,23 +2671,23 @@ var MACHINE_DIRECTIVES = [
|
|
|
2642
2671
|
"@vitest-environment",
|
|
2643
2672
|
MAINTAINABILITY_OVERRIDE_MARKER
|
|
2644
2673
|
];
|
|
2645
|
-
function isCommentExempt(
|
|
2646
|
-
const lower =
|
|
2674
|
+
function isCommentExempt(text10) {
|
|
2675
|
+
const lower = text10.toLowerCase();
|
|
2647
2676
|
return MACHINE_DIRECTIVES.some((d) => lower.includes(d));
|
|
2648
2677
|
}
|
|
2649
2678
|
|
|
2650
2679
|
// src/commands/verify/blockComments/collectSourceFindings.ts
|
|
2651
|
-
function toSingleLine(
|
|
2652
|
-
return
|
|
2680
|
+
function toSingleLine(text10) {
|
|
2681
|
+
return text10.replace(/\s+/g, " ").trim();
|
|
2653
2682
|
}
|
|
2654
2683
|
function collectSourceFindings(file, lines, project) {
|
|
2655
2684
|
const findings = [];
|
|
2656
2685
|
const sourceFile = project.addSourceFileAtPath(file);
|
|
2657
|
-
for (const { pos, text:
|
|
2686
|
+
for (const { pos, text: text10 } of collectComments(sourceFile)) {
|
|
2658
2687
|
const { line } = sourceFile.getLineAndColumnAtPos(pos);
|
|
2659
2688
|
if (!lines.has(line)) continue;
|
|
2660
|
-
if (isCommentExempt(
|
|
2661
|
-
findings.push({ file, line, text: toSingleLine(
|
|
2689
|
+
if (isCommentExempt(text10)) continue;
|
|
2690
|
+
findings.push({ file, line, text: toSingleLine(text10) });
|
|
2662
2691
|
}
|
|
2663
2692
|
return findings;
|
|
2664
2693
|
}
|
|
@@ -2678,10 +2707,10 @@ function collectYamlComments(content) {
|
|
|
2678
2707
|
// src/commands/verify/blockComments/collectFileComments.ts
|
|
2679
2708
|
function toFindings(file, lines, raw, exempt) {
|
|
2680
2709
|
const findings = [];
|
|
2681
|
-
for (const { line, text:
|
|
2710
|
+
for (const { line, text: text10 } of raw) {
|
|
2682
2711
|
if (!lines.has(line)) continue;
|
|
2683
|
-
if (exempt && isCommentExempt(
|
|
2684
|
-
findings.push({ file, line, text:
|
|
2712
|
+
if (exempt && isCommentExempt(text10)) continue;
|
|
2713
|
+
findings.push({ file, line, text: text10.replace(/\s+/g, " ").trim() });
|
|
2685
2714
|
}
|
|
2686
2715
|
return findings;
|
|
2687
2716
|
}
|
|
@@ -2779,8 +2808,8 @@ function blockComments() {
|
|
|
2779
2808
|
process.exit(0);
|
|
2780
2809
|
}
|
|
2781
2810
|
console.log("Comments on changed lines:\n");
|
|
2782
|
-
for (const { file, line, text:
|
|
2783
|
-
console.log(`${file}:${line} \u2192 ${
|
|
2811
|
+
for (const { file, line, text: text10 } of findings) {
|
|
2812
|
+
console.log(`${file}:${line} \u2192 ${text10}`);
|
|
2784
2813
|
}
|
|
2785
2814
|
console.log(`
|
|
2786
2815
|
Total: ${findings.length} comment(s)`);
|
|
@@ -4053,8 +4082,8 @@ async function buildDump(tables, copyOut) {
|
|
|
4053
4082
|
// src/commands/backlog/dump/copyTableOut.ts
|
|
4054
4083
|
import { to as copyTo } from "pg-copy-streams";
|
|
4055
4084
|
async function copyTableOut(client, table) {
|
|
4056
|
-
const
|
|
4057
|
-
const stream = client.query(copyTo(
|
|
4085
|
+
const sql13 = `COPY ${table.name} (${table.columns.join(", ")}) TO STDOUT`;
|
|
4086
|
+
const stream = client.query(copyTo(sql13));
|
|
4058
4087
|
const chunks = [];
|
|
4059
4088
|
for await (const chunk of stream) {
|
|
4060
4089
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
@@ -4596,11 +4625,11 @@ import { promisify } from "util";
|
|
|
4596
4625
|
// src/shared/withSpinner.ts
|
|
4597
4626
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
4598
4627
|
var TICK_MS = 80;
|
|
4599
|
-
async function withSpinner(
|
|
4628
|
+
async function withSpinner(text10, task) {
|
|
4600
4629
|
if (!process.stderr.isTTY) return task();
|
|
4601
4630
|
let frame = 0;
|
|
4602
4631
|
const render = () => {
|
|
4603
|
-
process.stderr.write(`\r${SPINNER_FRAMES[frame]} ${
|
|
4632
|
+
process.stderr.write(`\r${SPINNER_FRAMES[frame]} ${text10}`);
|
|
4604
4633
|
};
|
|
4605
4634
|
render();
|
|
4606
4635
|
const timer = setInterval(() => {
|
|
@@ -4937,6 +4966,18 @@ function attachSubtasks(item, rel, id) {
|
|
|
4937
4966
|
if (subtasks.length > 0) item.subtasks = subtasks;
|
|
4938
4967
|
}
|
|
4939
4968
|
|
|
4969
|
+
// src/commands/backlog/sumPhaseUsage.ts
|
|
4970
|
+
function sumPhaseUsage(usage) {
|
|
4971
|
+
return usage.reduce(
|
|
4972
|
+
(total, u) => ({
|
|
4973
|
+
tokensUp: total.tokensUp + u.tokensUp,
|
|
4974
|
+
tokensDown: total.tokensDown + u.tokensDown,
|
|
4975
|
+
activeMs: total.activeMs + u.activeMs
|
|
4976
|
+
}),
|
|
4977
|
+
{ tokensUp: 0, tokensDown: 0, activeMs: 0 }
|
|
4978
|
+
);
|
|
4979
|
+
}
|
|
4980
|
+
|
|
4940
4981
|
// src/commands/backlog/attachUsage.ts
|
|
4941
4982
|
function rowToUsage(u) {
|
|
4942
4983
|
return {
|
|
@@ -4948,7 +4989,10 @@ function rowToUsage(u) {
|
|
|
4948
4989
|
}
|
|
4949
4990
|
function attachUsage(item, rel, id) {
|
|
4950
4991
|
const usage = (rel.usage.get(id) ?? []).map(rowToUsage);
|
|
4951
|
-
if (usage.length > 0)
|
|
4992
|
+
if (usage.length > 0) {
|
|
4993
|
+
item.phaseUsage = usage;
|
|
4994
|
+
item.usageTotal = sumPhaseUsage(usage);
|
|
4995
|
+
}
|
|
4952
4996
|
}
|
|
4953
4997
|
|
|
4954
4998
|
// src/commands/backlog/buildPlan.ts
|
|
@@ -5062,6 +5106,11 @@ var phaseUsageSchema = z3.strictObject({
|
|
|
5062
5106
|
tokensDown: z3.number(),
|
|
5063
5107
|
activeMs: z3.number()
|
|
5064
5108
|
});
|
|
5109
|
+
var phaseUsageTotalSchema = z3.strictObject({
|
|
5110
|
+
tokensUp: z3.number(),
|
|
5111
|
+
tokensDown: z3.number(),
|
|
5112
|
+
activeMs: z3.number()
|
|
5113
|
+
});
|
|
5065
5114
|
var subtaskStatusSchema = z3.enum(["todo", "in-progress", "done"]);
|
|
5066
5115
|
var subtaskSchema = z3.strictObject({
|
|
5067
5116
|
title: z3.string(),
|
|
@@ -5104,6 +5153,7 @@ var backlogItemSchema = z3.strictObject({
|
|
|
5104
5153
|
subtasks: z3.array(subtaskSchema).optional(),
|
|
5105
5154
|
links: z3.array(backlogLinkSchema).optional(),
|
|
5106
5155
|
phaseUsage: z3.array(phaseUsageSchema).optional(),
|
|
5156
|
+
usageTotal: phaseUsageTotalSchema.optional(),
|
|
5107
5157
|
gitRefs: z3.array(gitRefSchema).optional(),
|
|
5108
5158
|
origin: z3.string().optional(),
|
|
5109
5159
|
jiraKey: z3.string().optional()
|
|
@@ -6014,11 +6064,11 @@ import chalk45 from "chalk";
|
|
|
6014
6064
|
|
|
6015
6065
|
// src/commands/backlog/appendComment.ts
|
|
6016
6066
|
import { sql as sql4 } from "drizzle-orm";
|
|
6017
|
-
async function appendComment(orm, itemId2,
|
|
6067
|
+
async function appendComment(orm, itemId2, text10, opts = {}) {
|
|
6018
6068
|
await orm.insert(comments).values({
|
|
6019
6069
|
itemId: itemId2,
|
|
6020
6070
|
idx: sql4`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId2})`,
|
|
6021
|
-
text:
|
|
6071
|
+
text: text10,
|
|
6022
6072
|
phase: opts.phase ?? null,
|
|
6023
6073
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6024
6074
|
type: opts.type ?? "comment"
|
|
@@ -6121,7 +6171,7 @@ function formatComment(entry) {
|
|
|
6121
6171
|
// src/shared/renderMarkdownTerminal.ts
|
|
6122
6172
|
import { Marked } from "marked";
|
|
6123
6173
|
import { markedTerminal } from "marked-terminal";
|
|
6124
|
-
function renderMarkdownTerminal(
|
|
6174
|
+
function renderMarkdownTerminal(text10) {
|
|
6125
6175
|
const width = process.stdout.columns || 80;
|
|
6126
6176
|
const marked = new Marked(markedTerminal({ width, reflowText: true }));
|
|
6127
6177
|
marked.use({
|
|
@@ -6134,7 +6184,7 @@ function renderMarkdownTerminal(text9) {
|
|
|
6134
6184
|
}
|
|
6135
6185
|
}
|
|
6136
6186
|
});
|
|
6137
|
-
return marked.parse(
|
|
6187
|
+
return marked.parse(text10).trimEnd();
|
|
6138
6188
|
}
|
|
6139
6189
|
|
|
6140
6190
|
// src/commands/backlog/show/printActivity.ts
|
|
@@ -6154,9 +6204,9 @@ function groupActivityRefs(refs, commitLimit = ACTIVITY_COMMIT_LIMIT) {
|
|
|
6154
6204
|
}
|
|
6155
6205
|
|
|
6156
6206
|
// src/commands/backlog/show/printActivity.ts
|
|
6157
|
-
function printRef(label2,
|
|
6207
|
+
function printRef(label2, text10, ref) {
|
|
6158
6208
|
const url = ref.url ? ` ${chalk48.dim(ref.url)}` : "";
|
|
6159
|
-
console.log(` ${chalk48.cyan(label2)} ${
|
|
6209
|
+
console.log(` ${chalk48.cyan(label2)} ${text10}${url}`);
|
|
6160
6210
|
}
|
|
6161
6211
|
function printActivity(item) {
|
|
6162
6212
|
const { branches, commits: commits2, prs: prs2, hiddenCommits } = groupActivityRefs(
|
|
@@ -6605,12 +6655,57 @@ function createFallbackHandler(routes3, htmlHandler2, extra) {
|
|
|
6605
6655
|
import { eq as eq12 } from "drizzle-orm";
|
|
6606
6656
|
|
|
6607
6657
|
// src/commands/backlog/loadItemSummaries.ts
|
|
6608
|
-
import { asc as asc5, eq as eq11
|
|
6609
|
-
|
|
6610
|
-
|
|
6658
|
+
import { asc as asc5, eq as eq11 } from "drizzle-orm";
|
|
6659
|
+
|
|
6660
|
+
// src/commands/backlog/incompleteSubtaskCounts.ts
|
|
6661
|
+
import { ne, sql as sql5 } from "drizzle-orm";
|
|
6662
|
+
function incompleteSubtaskCounts(orm) {
|
|
6663
|
+
return orm.select({
|
|
6611
6664
|
itemId: itemSubtasks.itemId,
|
|
6612
6665
|
count: sql5`count(*)::int`.as("incomplete_subtasks")
|
|
6613
6666
|
}).from(itemSubtasks).where(ne(itemSubtasks.status, "done")).groupBy(itemSubtasks.itemId).as("incomplete_counts");
|
|
6667
|
+
}
|
|
6668
|
+
|
|
6669
|
+
// src/commands/backlog/phaseUsageTotals.ts
|
|
6670
|
+
import { sql as sql6 } from "drizzle-orm";
|
|
6671
|
+
function phaseUsageTotals(orm) {
|
|
6672
|
+
return orm.select({
|
|
6673
|
+
itemId: phaseUsage.itemId,
|
|
6674
|
+
tokensUp: sql6`sum(${phaseUsage.tokensUp})::bigint`.as(
|
|
6675
|
+
"total_tokens_up"
|
|
6676
|
+
),
|
|
6677
|
+
tokensDown: sql6`sum(${phaseUsage.tokensDown})::bigint`.as(
|
|
6678
|
+
"total_tokens_down"
|
|
6679
|
+
),
|
|
6680
|
+
activeMs: sql6`sum(${phaseUsage.activeMs})::bigint`.as(
|
|
6681
|
+
"total_active_ms"
|
|
6682
|
+
)
|
|
6683
|
+
}).from(phaseUsage).groupBy(phaseUsage.itemId).as("usage_totals");
|
|
6684
|
+
}
|
|
6685
|
+
|
|
6686
|
+
// src/commands/backlog/rowToItemSummary.ts
|
|
6687
|
+
function rowToItemSummary(row) {
|
|
6688
|
+
return {
|
|
6689
|
+
id: row.id,
|
|
6690
|
+
origin: row.origin,
|
|
6691
|
+
type: row.type,
|
|
6692
|
+
name: row.name,
|
|
6693
|
+
status: row.status,
|
|
6694
|
+
starred: row.starred,
|
|
6695
|
+
jiraKey: row.jiraKey ?? void 0,
|
|
6696
|
+
incompleteSubtasks: row.incompleteSubtasks ?? 0,
|
|
6697
|
+
usageTotal: row.tokensUp == null ? void 0 : {
|
|
6698
|
+
tokensUp: Number(row.tokensUp),
|
|
6699
|
+
tokensDown: Number(row.tokensDown),
|
|
6700
|
+
activeMs: Number(row.activeMs)
|
|
6701
|
+
}
|
|
6702
|
+
};
|
|
6703
|
+
}
|
|
6704
|
+
|
|
6705
|
+
// src/commands/backlog/loadItemSummaries.ts
|
|
6706
|
+
async function loadItemSummaries(orm, origin) {
|
|
6707
|
+
const incompleteCounts = incompleteSubtaskCounts(orm);
|
|
6708
|
+
const usageTotals = phaseUsageTotals(orm);
|
|
6614
6709
|
const rows = await orm.select({
|
|
6615
6710
|
id: items.id,
|
|
6616
6711
|
origin: items.origin,
|
|
@@ -6619,18 +6714,12 @@ async function loadItemSummaries(orm, origin) {
|
|
|
6619
6714
|
status: items.status,
|
|
6620
6715
|
starred: items.starred,
|
|
6621
6716
|
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
|
-
}));
|
|
6717
|
+
incompleteSubtasks: incompleteCounts.count,
|
|
6718
|
+
tokensUp: usageTotals.tokensUp,
|
|
6719
|
+
tokensDown: usageTotals.tokensDown,
|
|
6720
|
+
activeMs: usageTotals.activeMs
|
|
6721
|
+
}).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));
|
|
6722
|
+
return rows.map(rowToItemSummary);
|
|
6634
6723
|
}
|
|
6635
6724
|
|
|
6636
6725
|
// src/commands/backlog/loadBacklogSummaries.ts
|
|
@@ -7258,9 +7347,9 @@ function excerpt(xml, ...tags) {
|
|
|
7258
7347
|
for (const tag of tags) {
|
|
7259
7348
|
const raw = extractText(xml, tag);
|
|
7260
7349
|
if (!raw) continue;
|
|
7261
|
-
const
|
|
7262
|
-
if (
|
|
7263
|
-
return `${
|
|
7350
|
+
const text10 = stripHtml(raw);
|
|
7351
|
+
if (text10.length <= MAX_EXCERPT) return text10;
|
|
7352
|
+
return `${text10.slice(0, MAX_EXCERPT)}\u2026`;
|
|
7264
7353
|
}
|
|
7265
7354
|
return "";
|
|
7266
7355
|
}
|
|
@@ -8173,10 +8262,10 @@ function registerAssociateJiraCommand(cmd) {
|
|
|
8173
8262
|
|
|
8174
8263
|
// src/commands/backlog/comment/index.ts
|
|
8175
8264
|
import chalk63 from "chalk";
|
|
8176
|
-
async function comment(id,
|
|
8265
|
+
async function comment(id, text10) {
|
|
8177
8266
|
const found = await findOneItem(id);
|
|
8178
8267
|
if (!found) process.exit(1);
|
|
8179
|
-
await appendComment(found.orm, found.item.id,
|
|
8268
|
+
await appendComment(found.orm, found.item.id, text10);
|
|
8180
8269
|
console.log(
|
|
8181
8270
|
chalk63.green(`Comment added to item ${formatItemId(found.item.id)}.`)
|
|
8182
8271
|
);
|
|
@@ -8281,9 +8370,9 @@ function readLine(dump, start3) {
|
|
|
8281
8370
|
return { text: dump.subarray(start3, eol).toString("utf8"), next: eol + 1 };
|
|
8282
8371
|
}
|
|
8283
8372
|
function parseHeader(dump) {
|
|
8284
|
-
const { text:
|
|
8373
|
+
const { text: text10, next: next3 } = readLine(dump, 0);
|
|
8285
8374
|
try {
|
|
8286
|
-
return { header: JSON.parse(
|
|
8375
|
+
return { header: JSON.parse(text10), bodyStart: next3 };
|
|
8287
8376
|
} catch {
|
|
8288
8377
|
return invalid("header is not valid JSON.");
|
|
8289
8378
|
}
|
|
@@ -8292,9 +8381,9 @@ function parseSections(dump, bodyStart) {
|
|
|
8292
8381
|
const sections = /* @__PURE__ */ new Map();
|
|
8293
8382
|
let cursor = bodyStart;
|
|
8294
8383
|
while (cursor < dump.length) {
|
|
8295
|
-
const { text:
|
|
8296
|
-
const match =
|
|
8297
|
-
if (!match) invalid(`malformed table marker "${
|
|
8384
|
+
const { text: text10, next: next3 } = readLine(dump, cursor);
|
|
8385
|
+
const match = text10.match(/^@table (\S+) (\d+)$/);
|
|
8386
|
+
if (!match) invalid(`malformed table marker "${text10}".`);
|
|
8298
8387
|
const [, name, bytes] = match;
|
|
8299
8388
|
const end = next3 + Number(bytes);
|
|
8300
8389
|
if (end > dump.length) invalid(`section "${name}" overruns the dump.`);
|
|
@@ -8370,8 +8459,8 @@ async function readStdinBuffer() {
|
|
|
8370
8459
|
import { finished } from "stream/promises";
|
|
8371
8460
|
import { from as copyFrom } from "pg-copy-streams";
|
|
8372
8461
|
async function copyTableIn(client, table, data) {
|
|
8373
|
-
const
|
|
8374
|
-
const stream = client.query(copyFrom(
|
|
8462
|
+
const sql13 = `COPY ${table.name} (${table.columns.join(", ")}) FROM STDIN`;
|
|
8463
|
+
const stream = client.query(copyFrom(sql13));
|
|
8375
8464
|
stream.end(data);
|
|
8376
8465
|
await finished(stream);
|
|
8377
8466
|
}
|
|
@@ -8416,8 +8505,8 @@ async function replaceData(client, parsed) {
|
|
|
8416
8505
|
await copyTableIn(client, table, data);
|
|
8417
8506
|
}
|
|
8418
8507
|
for (const col of await introspectIdentityColumns(client)) {
|
|
8419
|
-
const { text:
|
|
8420
|
-
await client.query(
|
|
8508
|
+
const { text: text10, values } = resyncIdentitySql(col);
|
|
8509
|
+
await client.query(text10, values);
|
|
8421
8510
|
}
|
|
8422
8511
|
}
|
|
8423
8512
|
async function restore(client, parsed) {
|
|
@@ -8498,11 +8587,11 @@ async function insertPhaseAt(orm, itemId2, phaseIdx, name, tasks, manualChecks,
|
|
|
8498
8587
|
}
|
|
8499
8588
|
|
|
8500
8589
|
// src/commands/backlog/insertSubtask.ts
|
|
8501
|
-
import { sql as
|
|
8590
|
+
import { sql as sql7 } from "drizzle-orm";
|
|
8502
8591
|
async function insertSubtask(orm, itemId2, title, description) {
|
|
8503
8592
|
await orm.insert(itemSubtasks).values({
|
|
8504
8593
|
itemId: itemId2,
|
|
8505
|
-
idx:
|
|
8594
|
+
idx: sql7`(SELECT COALESCE(MAX(${itemSubtasks.idx}) + 1, 0) FROM ${itemSubtasks} WHERE ${itemSubtasks.itemId} = ${itemId2})`,
|
|
8506
8595
|
title,
|
|
8507
8596
|
description: description ?? null,
|
|
8508
8597
|
status: "todo"
|
|
@@ -10264,8 +10353,8 @@ var RAW_BUILTIN_DENIES = [
|
|
|
10264
10353
|
regex
|
|
10265
10354
|
}))
|
|
10266
10355
|
];
|
|
10267
|
-
function matchBuiltinDeny(
|
|
10268
|
-
return RAW_BUILTIN_DENIES.find((rule) => rule.regex.test(
|
|
10356
|
+
function matchBuiltinDeny(text10) {
|
|
10357
|
+
return RAW_BUILTIN_DENIES.find((rule) => rule.regex.test(text10));
|
|
10269
10358
|
}
|
|
10270
10359
|
function toDecision(rule) {
|
|
10271
10360
|
if (!rule) return void 0;
|
|
@@ -11005,8 +11094,8 @@ function formatHuman(cli, commands) {
|
|
|
11005
11094
|
`];
|
|
11006
11095
|
for (const cmd of sorted) {
|
|
11007
11096
|
const full = `${cli} ${cmd.path.join(" ")}`;
|
|
11008
|
-
const
|
|
11009
|
-
lines.push(`${prefix(classifyVerb(cmd.path))}${
|
|
11097
|
+
const text10 = cmd.description ? `${full} \u2014 ${cmd.description}` : full;
|
|
11098
|
+
lines.push(`${prefix(classifyVerb(cmd.path))}${text10}`);
|
|
11010
11099
|
}
|
|
11011
11100
|
return lines.join("\n");
|
|
11012
11101
|
}
|
|
@@ -11285,38 +11374,38 @@ import chalk108 from "chalk";
|
|
|
11285
11374
|
// src/commands/codeComment/validateCommentText.ts
|
|
11286
11375
|
var MAX_COMMENT_LENGTH = 50;
|
|
11287
11376
|
function validateCommentText(raw, isHash = false) {
|
|
11288
|
-
const
|
|
11289
|
-
if (/[\r\n]/.test(
|
|
11377
|
+
const text10 = isHash ? raw.replace(/^#\s?/, "") : raw.replace(/^\/\/\s?/, "");
|
|
11378
|
+
if (/[\r\n]/.test(text10)) {
|
|
11290
11379
|
return {
|
|
11291
11380
|
ok: false,
|
|
11292
11381
|
reason: "Comment must be a single line \u2014 multi-line comments are not allowed."
|
|
11293
11382
|
};
|
|
11294
11383
|
}
|
|
11295
|
-
if (!isHash && (
|
|
11384
|
+
if (!isHash && (text10.includes("/*") || text10.includes("*/"))) {
|
|
11296
11385
|
return {
|
|
11297
11386
|
ok: false,
|
|
11298
11387
|
reason: "Block comments (/* */) are not allowed \u2014 only single-line // comments."
|
|
11299
11388
|
};
|
|
11300
11389
|
}
|
|
11301
|
-
if (
|
|
11390
|
+
if (text10.length > MAX_COMMENT_LENGTH) {
|
|
11302
11391
|
return {
|
|
11303
11392
|
ok: false,
|
|
11304
|
-
reason: `Comment text is ${
|
|
11393
|
+
reason: `Comment text is ${text10.length} chars; the cap is ${MAX_COMMENT_LENGTH}. Make it shorter or, better, make the code self-documenting.`
|
|
11305
11394
|
};
|
|
11306
11395
|
}
|
|
11307
|
-
return { ok: true, text:
|
|
11396
|
+
return { ok: true, text: text10 };
|
|
11308
11397
|
}
|
|
11309
11398
|
|
|
11310
11399
|
// src/commands/codeComment/issuePin.ts
|
|
11311
11400
|
import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync24 } from "fs";
|
|
11312
11401
|
import { randomInt } from "crypto";
|
|
11313
|
-
function issuePin(file, lineNumber,
|
|
11402
|
+
function issuePin(file, lineNumber, text10) {
|
|
11314
11403
|
const pin = generatePin();
|
|
11315
11404
|
mkdirSync13(getRestrictedDir(), { recursive: true });
|
|
11316
11405
|
sweepRestrictedDir();
|
|
11317
11406
|
writeFileSync24(
|
|
11318
11407
|
getPinStatePath(pin),
|
|
11319
|
-
JSON.stringify({ pin, file, line: lineNumber, text:
|
|
11408
|
+
JSON.stringify({ pin, file, line: lineNumber, text: text10 })
|
|
11320
11409
|
);
|
|
11321
11410
|
return showNotification({
|
|
11322
11411
|
title: "assist code-comment pin",
|
|
@@ -11328,7 +11417,7 @@ function generatePin() {
|
|
|
11328
11417
|
}
|
|
11329
11418
|
|
|
11330
11419
|
// src/commands/codeComment/codeCommentSet.ts
|
|
11331
|
-
function codeCommentSet(file, line,
|
|
11420
|
+
function codeCommentSet(file, line, text10) {
|
|
11332
11421
|
const lineNumber = Number.parseInt(line, 10);
|
|
11333
11422
|
if (!Number.isInteger(lineNumber) || lineNumber < 1) {
|
|
11334
11423
|
console.error(chalk108.red(`Invalid line number: ${line}`));
|
|
@@ -11337,7 +11426,7 @@ function codeCommentSet(file, line, text9) {
|
|
|
11337
11426
|
}
|
|
11338
11427
|
const hash = isHashCommentFile(file);
|
|
11339
11428
|
const marker = hash ? "#" : "//";
|
|
11340
|
-
const validation = validateCommentText(
|
|
11429
|
+
const validation = validateCommentText(text10, hash);
|
|
11341
11430
|
if (!validation.ok) {
|
|
11342
11431
|
console.error(chalk108.red(`Refused: ${validation.reason}`));
|
|
11343
11432
|
console.error(chalk108.red("No pin issued."));
|
|
@@ -13344,12 +13433,12 @@ function isSourceFile(filePath) {
|
|
|
13344
13433
|
if (!filePath) return false;
|
|
13345
13434
|
return SOURCE_EXTENSIONS.some((ext) => filePath.endsWith(ext));
|
|
13346
13435
|
}
|
|
13347
|
-
function blankNonNewline2(
|
|
13348
|
-
return
|
|
13436
|
+
function blankNonNewline2(text10) {
|
|
13437
|
+
return text10.replace(/[^\n]/g, " ");
|
|
13349
13438
|
}
|
|
13350
|
-
function extractComments(
|
|
13439
|
+
function extractComments(text10) {
|
|
13351
13440
|
const comments3 = [];
|
|
13352
|
-
let work =
|
|
13441
|
+
let work = text10.replace(
|
|
13353
13442
|
/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`/g,
|
|
13354
13443
|
blankNonNewline2
|
|
13355
13444
|
);
|
|
@@ -13364,11 +13453,11 @@ function extractComments(text9) {
|
|
|
13364
13453
|
}
|
|
13365
13454
|
|
|
13366
13455
|
// src/commands/editHook/extractYamlComments.ts
|
|
13367
|
-
function blankNonNewline3(
|
|
13368
|
-
return
|
|
13456
|
+
function blankNonNewline3(text10) {
|
|
13457
|
+
return text10.replace(/[^\n]/g, " ");
|
|
13369
13458
|
}
|
|
13370
|
-
function extractYamlComments(
|
|
13371
|
-
const work =
|
|
13459
|
+
function extractYamlComments(text10) {
|
|
13460
|
+
const work = text10.replace(
|
|
13372
13461
|
/"(?:[^"\\]|\\.)*"|'(?:[^']|'')*'/g,
|
|
13373
13462
|
blankNonNewline3
|
|
13374
13463
|
);
|
|
@@ -13384,8 +13473,8 @@ function isHeaderLine2(line) {
|
|
|
13384
13473
|
const trimmed = line.trim();
|
|
13385
13474
|
return trimmed === "" || trimmed.startsWith("#");
|
|
13386
13475
|
}
|
|
13387
|
-
function extractShellComments(
|
|
13388
|
-
const lines =
|
|
13476
|
+
function extractShellComments(text10) {
|
|
13477
|
+
const lines = text10.split("\n");
|
|
13389
13478
|
let firstCodeLine = 0;
|
|
13390
13479
|
while (firstCodeLine < lines.length && isHeaderLine2(lines[firstCodeLine])) {
|
|
13391
13480
|
firstCodeLine++;
|
|
@@ -13755,9 +13844,9 @@ function registerGithub(program2) {
|
|
|
13755
13844
|
}
|
|
13756
13845
|
|
|
13757
13846
|
// src/commands/handover/countPendingHandovers.ts
|
|
13758
|
-
import { and as and16, eq as eq34, isNull, sql as
|
|
13847
|
+
import { and as and16, eq as eq34, isNull, sql as sql8 } from "drizzle-orm";
|
|
13759
13848
|
async function countPendingHandovers(orm, origin) {
|
|
13760
|
-
const [row] = await orm.select({ count:
|
|
13849
|
+
const [row] = await orm.select({ count: sql8`count(*)::int` }).from(handovers).where(and16(eq34(handovers.origin, origin), isNull(handovers.recalledAt)));
|
|
13761
13850
|
return row?.count ?? 0;
|
|
13762
13851
|
}
|
|
13763
13852
|
|
|
@@ -13980,9 +14069,9 @@ import chalk140 from "chalk";
|
|
|
13980
14069
|
|
|
13981
14070
|
// src/commands/jira/adfToText.ts
|
|
13982
14071
|
function renderInline(node) {
|
|
13983
|
-
const
|
|
13984
|
-
if (node.marks?.some((m) => m.type === "code")) return `\`${
|
|
13985
|
-
return
|
|
14072
|
+
const text10 = node.text ?? "";
|
|
14073
|
+
if (node.marks?.some((m) => m.type === "code")) return `\`${text10}\``;
|
|
14074
|
+
return text10;
|
|
13986
14075
|
}
|
|
13987
14076
|
function renderChildren(node, indent2) {
|
|
13988
14077
|
return renderNodes(node.content ?? [], indent2);
|
|
@@ -14024,8 +14113,8 @@ function isListNode(node) {
|
|
|
14024
14113
|
function renderListChild(child, indent2, pad, marker, isFirst) {
|
|
14025
14114
|
if (isListNode(child)) return renderNodes([child], indent2 + 1);
|
|
14026
14115
|
if (child.type !== "paragraph") return renderNode(child, indent2);
|
|
14027
|
-
const
|
|
14028
|
-
return isFirst ? `${pad}${marker} ${
|
|
14116
|
+
const text10 = renderChildren(child, indent2);
|
|
14117
|
+
return isFirst ? `${pad}${marker} ${text10}` : `${pad} ${text10}`;
|
|
14029
14118
|
}
|
|
14030
14119
|
function renderListItem(node, indent2, marker) {
|
|
14031
14120
|
const pad = " ".repeat(indent2);
|
|
@@ -14184,9 +14273,9 @@ function registerDescriptionLaunch(program2, name, slashCommand, description, al
|
|
|
14184
14273
|
"[description]",
|
|
14185
14274
|
`Text to forward to the /${slashCommand} slash command`
|
|
14186
14275
|
).description(description).option("--once", "Exit when the initial task completes").option("--resume-session <id>", RESUME_SESSION_FLAG).action(
|
|
14187
|
-
(
|
|
14276
|
+
(text10, opts) => launchMode(slashCommand, {
|
|
14188
14277
|
once: opts.once,
|
|
14189
|
-
description:
|
|
14278
|
+
description: text10,
|
|
14190
14279
|
resumeSessionId: opts.resumeSession
|
|
14191
14280
|
})
|
|
14192
14281
|
);
|
|
@@ -14688,8 +14777,8 @@ function dedupeLinks(links2) {
|
|
|
14688
14777
|
}
|
|
14689
14778
|
|
|
14690
14779
|
// src/commands/netcap/linkifyMentions.ts
|
|
14691
|
-
function linkifyMentions(
|
|
14692
|
-
let out =
|
|
14780
|
+
function linkifyMentions(text10, mentions) {
|
|
14781
|
+
let out = text10;
|
|
14693
14782
|
for (const m of mentions) {
|
|
14694
14783
|
if (m.name && out.includes(m.name)) {
|
|
14695
14784
|
out = out.replace(m.name, `[${m.name}](${m.url})`);
|
|
@@ -14716,13 +14805,13 @@ function resolveAuthor(mentionMap, author) {
|
|
|
14716
14805
|
return mentionMap.get(author) ?? { slug: author, url: profileUrl(author) };
|
|
14717
14806
|
}
|
|
14718
14807
|
function buildPost(raw, mentionMap, author) {
|
|
14719
|
-
const
|
|
14720
|
-
if (!
|
|
14808
|
+
const text10 = joinText(raw.text);
|
|
14809
|
+
if (!text10) return void 0;
|
|
14721
14810
|
const mentions = resolveMentions(raw, mentionMap, author);
|
|
14722
14811
|
const relatedPosts = [...new Set(raw.related)];
|
|
14723
14812
|
return {
|
|
14724
|
-
text:
|
|
14725
|
-
markdown: linkifyMentions(
|
|
14813
|
+
text: text10,
|
|
14814
|
+
markdown: linkifyMentions(text10, mentions),
|
|
14726
14815
|
mentions,
|
|
14727
14816
|
hashtags: [...new Set(raw.hashtags)],
|
|
14728
14817
|
links: dedupeLinks(raw.links),
|
|
@@ -14863,8 +14952,8 @@ function activityUrnOf(update3) {
|
|
|
14863
14952
|
return typeof urn === "string" ? urn : void 0;
|
|
14864
14953
|
}
|
|
14865
14954
|
function buildVoyagerPost(update3, profiles) {
|
|
14866
|
-
const
|
|
14867
|
-
if (!
|
|
14955
|
+
const text10 = commentaryText(update3);
|
|
14956
|
+
if (!text10) return void 0;
|
|
14868
14957
|
const author = resolveVoyagerAuthor(update3);
|
|
14869
14958
|
const { mentions, hashtags, links: links2 } = collectVoyagerAttributes(
|
|
14870
14959
|
update3,
|
|
@@ -14873,8 +14962,8 @@ function buildVoyagerPost(update3, profiles) {
|
|
|
14873
14962
|
);
|
|
14874
14963
|
const activityUrn = activityUrnOf(update3);
|
|
14875
14964
|
return {
|
|
14876
|
-
text:
|
|
14877
|
-
markdown: linkifyMentions(
|
|
14965
|
+
text: text10,
|
|
14966
|
+
markdown: linkifyMentions(text10, mentions),
|
|
14878
14967
|
mentions,
|
|
14879
14968
|
hashtags,
|
|
14880
14969
|
links: links2,
|
|
@@ -15378,8 +15467,8 @@ function isWallOfText(lines) {
|
|
|
15378
15467
|
if (lines.some(isListLine)) {
|
|
15379
15468
|
return false;
|
|
15380
15469
|
}
|
|
15381
|
-
const
|
|
15382
|
-
return
|
|
15470
|
+
const text10 = lines.join(" ").trim();
|
|
15471
|
+
return text10.length > MAX_PARAGRAPH_CHARS || countSentences(text10) > MAX_PARAGRAPH_SENTENCES;
|
|
15383
15472
|
}
|
|
15384
15473
|
function validatePrContent(title, body) {
|
|
15385
15474
|
if (title.toLowerCase().includes("claude")) {
|
|
@@ -17133,9 +17222,9 @@ function resolveImports(target, dependencies, sourceFile, statements = []) {
|
|
|
17133
17222
|
function extractTexts(target, allFunctions, statements) {
|
|
17134
17223
|
const stmtTexts = statements.map((v) => v.getFullText().trim());
|
|
17135
17224
|
const fnTexts = allFunctions.map((fn) => {
|
|
17136
|
-
const
|
|
17137
|
-
if (fn === target && !
|
|
17138
|
-
return
|
|
17225
|
+
const text10 = fn.getFullText().trim();
|
|
17226
|
+
if (fn === target && !text10.startsWith("export ")) return `export ${text10}`;
|
|
17227
|
+
return text10;
|
|
17139
17228
|
});
|
|
17140
17229
|
return [...stmtTexts, ...fnTexts];
|
|
17141
17230
|
}
|
|
@@ -18985,9 +19074,9 @@ var MultiSpinner = class {
|
|
|
18985
19074
|
elapsedPrefix: prefix2
|
|
18986
19075
|
});
|
|
18987
19076
|
}
|
|
18988
|
-
failRemaining(
|
|
19077
|
+
failRemaining(text10) {
|
|
18989
19078
|
for (const entry of this.entries) {
|
|
18990
|
-
if (entry.state === "running") this.resolve(entry, "failed",
|
|
19079
|
+
if (entry.state === "running") this.resolve(entry, "failed", text10);
|
|
18991
19080
|
}
|
|
18992
19081
|
}
|
|
18993
19082
|
add(entry) {
|
|
@@ -19000,14 +19089,14 @@ var MultiSpinner = class {
|
|
|
19000
19089
|
set text(value) {
|
|
19001
19090
|
entry.text = value;
|
|
19002
19091
|
},
|
|
19003
|
-
succeed: (
|
|
19004
|
-
fail: (
|
|
19092
|
+
succeed: (text10) => this.resolve(entry, "succeeded", text10),
|
|
19093
|
+
fail: (text10) => this.resolve(entry, "failed", text10)
|
|
19005
19094
|
};
|
|
19006
19095
|
}
|
|
19007
|
-
resolve(entry, state,
|
|
19096
|
+
resolve(entry, state, text10) {
|
|
19008
19097
|
if (entry.state !== "running") return;
|
|
19009
19098
|
entry.state = state;
|
|
19010
|
-
if (
|
|
19099
|
+
if (text10 !== void 0) entry.text = text10;
|
|
19011
19100
|
entry.elapsedStart = void 0;
|
|
19012
19101
|
this.render();
|
|
19013
19102
|
this.maybeFinish();
|
|
@@ -19082,12 +19171,12 @@ function skippedCodexResult(outputPath) {
|
|
|
19082
19171
|
// src/commands/review/formatReviewerFailure.ts
|
|
19083
19172
|
var FAST_FAIL_MS = 1e3;
|
|
19084
19173
|
var STDOUT_TAIL_LINES = 20;
|
|
19085
|
-
function indent(
|
|
19086
|
-
return
|
|
19174
|
+
function indent(text10) {
|
|
19175
|
+
return text10.split(/\r?\n/).map((line) => ` ${line}`);
|
|
19087
19176
|
}
|
|
19088
|
-
function tailLines(
|
|
19089
|
-
const lines =
|
|
19090
|
-
return lines.length <= maxLines ?
|
|
19177
|
+
function tailLines(text10, maxLines) {
|
|
19178
|
+
const lines = text10.split(/\r?\n/);
|
|
19179
|
+
return lines.length <= maxLines ? text10 : lines.slice(-maxLines).join("\n");
|
|
19091
19180
|
}
|
|
19092
19181
|
function isFastFail(input) {
|
|
19093
19182
|
return input.exitCode !== 0 && input.elapsedMs !== void 0 && input.elapsedMs < FAST_FAIL_MS;
|
|
@@ -20022,8 +20111,8 @@ function filterToSql(filter) {
|
|
|
20022
20111
|
// src/commands/seq/fetchSeqData.ts
|
|
20023
20112
|
function buildDataParams(filter, count8, from, to) {
|
|
20024
20113
|
const sqlFilter = filterToSql(filter);
|
|
20025
|
-
const
|
|
20026
|
-
const params = new URLSearchParams({ q:
|
|
20114
|
+
const sql13 = `select @Timestamp, @Level, @Exception, @Message from stream where ${sqlFilter} order by @Timestamp desc limit ${count8}`;
|
|
20115
|
+
const params = new URLSearchParams({ q: sql13 });
|
|
20027
20116
|
if (from) params.set("rangeStartUtc", from);
|
|
20028
20117
|
if (to) params.set("rangeEndUtc", to);
|
|
20029
20118
|
return params;
|
|
@@ -20284,26 +20373,26 @@ import chalk187 from "chalk";
|
|
|
20284
20373
|
// src/commands/sql/loadConnections.ts
|
|
20285
20374
|
function loadConnections3() {
|
|
20286
20375
|
const raw = loadGlobalConfigRaw();
|
|
20287
|
-
const
|
|
20288
|
-
return
|
|
20376
|
+
const sql13 = raw.sql;
|
|
20377
|
+
return sql13?.connections ?? [];
|
|
20289
20378
|
}
|
|
20290
20379
|
function saveConnections3(connections) {
|
|
20291
20380
|
const raw = loadGlobalConfigRaw();
|
|
20292
|
-
const
|
|
20293
|
-
|
|
20294
|
-
raw.sql =
|
|
20381
|
+
const sql13 = raw.sql ?? {};
|
|
20382
|
+
sql13.connections = connections;
|
|
20383
|
+
raw.sql = sql13;
|
|
20295
20384
|
saveGlobalConfig(raw);
|
|
20296
20385
|
}
|
|
20297
20386
|
function getDefaultConnection2() {
|
|
20298
20387
|
const raw = loadGlobalConfigRaw();
|
|
20299
|
-
const
|
|
20300
|
-
return
|
|
20388
|
+
const sql13 = raw.sql;
|
|
20389
|
+
return sql13?.defaultConnection;
|
|
20301
20390
|
}
|
|
20302
20391
|
function setDefaultConnection2(name) {
|
|
20303
20392
|
const raw = loadGlobalConfigRaw();
|
|
20304
|
-
const
|
|
20305
|
-
|
|
20306
|
-
raw.sql =
|
|
20393
|
+
const sql13 = raw.sql ?? {};
|
|
20394
|
+
sql13.defaultConnection = name;
|
|
20395
|
+
raw.sql = sql13;
|
|
20307
20396
|
saveGlobalConfig(raw);
|
|
20308
20397
|
}
|
|
20309
20398
|
|
|
@@ -20374,9 +20463,9 @@ function resolveConnection3(name) {
|
|
|
20374
20463
|
}
|
|
20375
20464
|
|
|
20376
20465
|
// src/commands/sql/sqlConnect.ts
|
|
20377
|
-
import
|
|
20466
|
+
import sql9 from "mssql";
|
|
20378
20467
|
async function sqlConnect(conn) {
|
|
20379
|
-
return await
|
|
20468
|
+
return await sql9.connect({
|
|
20380
20469
|
server: conn.server,
|
|
20381
20470
|
port: conn.port,
|
|
20382
20471
|
user: conn.user,
|
|
@@ -20453,11 +20542,11 @@ var MUTATION_PATTERN = new RegExp(
|
|
|
20453
20542
|
`\\b(${MUTATION_KEYWORDS.join("|")})\\b`,
|
|
20454
20543
|
"i"
|
|
20455
20544
|
);
|
|
20456
|
-
function stripComments(
|
|
20457
|
-
return
|
|
20545
|
+
function stripComments(sql13) {
|
|
20546
|
+
return sql13.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\n]*/g, " ");
|
|
20458
20547
|
}
|
|
20459
|
-
function isMutation(
|
|
20460
|
-
const stripped = stripComments(
|
|
20548
|
+
function isMutation(sql13) {
|
|
20549
|
+
const stripped = stripComments(sql13);
|
|
20461
20550
|
if (MUTATION_PATTERN.test(stripped)) return true;
|
|
20462
20551
|
return /\bSELECT\b[\s\S]+\bINTO\s+\w/i.test(stripped);
|
|
20463
20552
|
}
|
|
@@ -20656,8 +20745,8 @@ import {
|
|
|
20656
20745
|
import { basename as basename10, join as join51 } from "path";
|
|
20657
20746
|
|
|
20658
20747
|
// src/commands/transcript/cleanText.ts
|
|
20659
|
-
function cleanText(
|
|
20660
|
-
const words =
|
|
20748
|
+
function cleanText(text10) {
|
|
20749
|
+
const words = text10.split(/\s+/);
|
|
20661
20750
|
const cleaned = [];
|
|
20662
20751
|
for (let i = 0; i < words.length; i++) {
|
|
20663
20752
|
let isRepeat = false;
|
|
@@ -20677,8 +20766,8 @@ function cleanText(text9) {
|
|
|
20677
20766
|
}
|
|
20678
20767
|
|
|
20679
20768
|
// src/commands/transcript/convert/parseVtt/deduplicateCues/removeSubstringDuplicates.ts
|
|
20680
|
-
function normalizeText(
|
|
20681
|
-
return
|
|
20769
|
+
function normalizeText(text10) {
|
|
20770
|
+
return text10.toLowerCase().trim();
|
|
20682
20771
|
}
|
|
20683
20772
|
function checkSubstringRelation(textI, textJ) {
|
|
20684
20773
|
if (textI.includes(textJ) && textI.length > textJ.length)
|
|
@@ -20807,13 +20896,13 @@ function parseTimestampLine(line) {
|
|
|
20807
20896
|
return { startMs: parseTimestamp(startStr), endMs: parseTimestamp(endStr) };
|
|
20808
20897
|
}
|
|
20809
20898
|
function buildCue(startMs, endMs, fullText) {
|
|
20810
|
-
const { speaker, text:
|
|
20811
|
-
return
|
|
20899
|
+
const { speaker, text: text10 } = extractSpeaker(fullText);
|
|
20900
|
+
return text10 ? { startMs, endMs, speaker, text: text10 } : null;
|
|
20812
20901
|
}
|
|
20813
20902
|
function parseCueLine(lines, i) {
|
|
20814
20903
|
const { startMs, endMs } = parseTimestampLine(lines[i]);
|
|
20815
|
-
const { text:
|
|
20816
|
-
return { cue: buildCue(startMs, endMs,
|
|
20904
|
+
const { text: text10, nextIndex: nextIndex2 } = collectTextLines(lines, i + 1);
|
|
20905
|
+
return { cue: buildCue(startMs, endMs, text10), nextIndex: nextIndex2 };
|
|
20817
20906
|
}
|
|
20818
20907
|
function isCueSeparator(line) {
|
|
20819
20908
|
return line.trim().includes("-->");
|
|
@@ -21396,8 +21485,8 @@ async function exchangeToken(params) {
|
|
|
21396
21485
|
body: body.toString()
|
|
21397
21486
|
});
|
|
21398
21487
|
if (!response.ok) {
|
|
21399
|
-
const
|
|
21400
|
-
throw new Error(`Token exchange failed (${response.status}): ${
|
|
21488
|
+
const text10 = await response.text();
|
|
21489
|
+
throw new Error(`Token exchange failed (${response.status}): ${text10}`);
|
|
21401
21490
|
}
|
|
21402
21491
|
return response.json();
|
|
21403
21492
|
}
|
|
@@ -22531,10 +22620,22 @@ function broadcastSessions(sessions, clients, windowsSessions = [], active) {
|
|
|
22531
22620
|
});
|
|
22532
22621
|
}
|
|
22533
22622
|
|
|
22534
|
-
// src/shared/
|
|
22623
|
+
// src/shared/activeWindows.ts
|
|
22535
22624
|
var WINDOWS = ["five_hour", "seven_day"];
|
|
22536
|
-
|
|
22625
|
+
function activeWindows(rateLimits) {
|
|
22626
|
+
if (!rateLimits) return [];
|
|
22627
|
+
const out = [];
|
|
22537
22628
|
for (const window of WINDOWS) {
|
|
22629
|
+
const resetsAt = rateLimits[window]?.resets_at;
|
|
22630
|
+
if (typeof resetsAt === "number") out.push({ window, resetsAt });
|
|
22631
|
+
}
|
|
22632
|
+
return out;
|
|
22633
|
+
}
|
|
22634
|
+
|
|
22635
|
+
// src/shared/db/recordUsagePeak.ts
|
|
22636
|
+
var WINDOWS2 = ["five_hour", "seven_day"];
|
|
22637
|
+
async function recordUsagePeak(db, rateLimits) {
|
|
22638
|
+
for (const window of WINDOWS2) {
|
|
22538
22639
|
const w = rateLimits[window];
|
|
22539
22640
|
if (!w || typeof w.resets_at !== "number" || typeof w.used_percentage !== "number")
|
|
22540
22641
|
continue;
|
|
@@ -22567,6 +22668,9 @@ var ClientHub = class extends Set {
|
|
|
22567
22668
|
broadcast(this, { type: "limits", rateLimits });
|
|
22568
22669
|
this.persistPeak?.(rateLimits);
|
|
22569
22670
|
}
|
|
22671
|
+
currentWindows() {
|
|
22672
|
+
return activeWindows(this.latestLimits);
|
|
22673
|
+
}
|
|
22570
22674
|
greet(client) {
|
|
22571
22675
|
if (this.latestLimits) {
|
|
22572
22676
|
sendTo(client, { type: "limits", rateLimits: this.latestLimits });
|
|
@@ -22781,13 +22885,13 @@ function logSpawnedSession(session) {
|
|
|
22781
22885
|
}
|
|
22782
22886
|
|
|
22783
22887
|
// src/shared/db/recordPhaseActiveMs.ts
|
|
22784
|
-
import { sql as
|
|
22888
|
+
import { sql as sql10 } from "drizzle-orm";
|
|
22785
22889
|
async function recordPhaseActiveMs(db, itemId2, phaseIdx, activeMs) {
|
|
22786
22890
|
if (activeMs <= 0) return;
|
|
22787
22891
|
await db.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, activeMs }).onConflictDoUpdate({
|
|
22788
22892
|
target: [phaseUsage.itemId, phaseUsage.phaseIdx],
|
|
22789
22893
|
set: {
|
|
22790
|
-
activeMs:
|
|
22894
|
+
activeMs: sql10`${phaseUsage.activeMs} + excluded.active_ms`
|
|
22791
22895
|
}
|
|
22792
22896
|
});
|
|
22793
22897
|
}
|
|
@@ -22929,38 +23033,114 @@ function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
|
|
|
22929
23033
|
return (s, status2, exitCode) => applyStatusChange(s, status2, exitCode, dismiss, notify2, reuseForRun);
|
|
22930
23034
|
}
|
|
22931
23035
|
|
|
22932
|
-
// src/shared/db/
|
|
22933
|
-
import { sql as
|
|
22934
|
-
async function
|
|
22935
|
-
|
|
22936
|
-
|
|
22937
|
-
|
|
22938
|
-
|
|
22939
|
-
|
|
22940
|
-
|
|
22941
|
-
|
|
22942
|
-
|
|
23036
|
+
// src/shared/db/recordPhaseTranscriptUsage.ts
|
|
23037
|
+
import { sql as sql11 } from "drizzle-orm";
|
|
23038
|
+
async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
|
|
23039
|
+
const byId = /* @__PURE__ */ new Map();
|
|
23040
|
+
for (const r of responses) byId.set(r.messageId, r);
|
|
23041
|
+
const unique = [...byId.values()];
|
|
23042
|
+
if (unique.length === 0) return { tokensUp: 0, tokensDown: 0 };
|
|
23043
|
+
return db.transaction(async (tx) => {
|
|
23044
|
+
const inserted = await tx.insert(phaseUsageMessages).values(unique.map((r) => ({ itemId: itemId2, phaseIdx, messageId: r.messageId }))).onConflictDoNothing().returning({ messageId: phaseUsageMessages.messageId });
|
|
23045
|
+
let tokensUp = 0;
|
|
23046
|
+
let tokensDown = 0;
|
|
23047
|
+
for (const { messageId } of inserted) {
|
|
23048
|
+
const r = byId.get(messageId);
|
|
23049
|
+
if (!r) continue;
|
|
23050
|
+
tokensUp += r.outputTokens;
|
|
23051
|
+
tokensDown += r.inputTokens;
|
|
23052
|
+
}
|
|
23053
|
+
if (tokensUp <= 0 && tokensDown <= 0) return { tokensUp: 0, tokensDown: 0 };
|
|
23054
|
+
await tx.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, tokensUp, tokensDown }).onConflictDoUpdate({
|
|
23055
|
+
target: [phaseUsage.itemId, phaseUsage.phaseIdx],
|
|
23056
|
+
set: {
|
|
23057
|
+
tokensUp: sql11`${phaseUsage.tokensUp} + ${tokensUp}`,
|
|
23058
|
+
tokensDown: sql11`${phaseUsage.tokensDown} + ${tokensDown}`
|
|
23059
|
+
}
|
|
23060
|
+
});
|
|
23061
|
+
return { tokensUp, tokensDown };
|
|
22943
23062
|
});
|
|
22944
23063
|
}
|
|
22945
23064
|
|
|
23065
|
+
// src/shared/db/recordWindowTokens.ts
|
|
23066
|
+
import { and as and19, eq as eq37, sql as sql12 } from "drizzle-orm";
|
|
23067
|
+
async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
|
|
23068
|
+
if (tokensUp <= 0 && tokensDown <= 0) return;
|
|
23069
|
+
await db.update(usagePeaks).set({
|
|
23070
|
+
tokensUp: sql12`${usagePeaks.tokensUp} + ${tokensUp}`,
|
|
23071
|
+
tokensDown: sql12`${usagePeaks.tokensDown} + ${tokensDown}`
|
|
23072
|
+
}).where(
|
|
23073
|
+
and19(
|
|
23074
|
+
eq37(usagePeaks.window, window),
|
|
23075
|
+
eq37(usagePeaks.resetsAt, resetsAt),
|
|
23076
|
+
eq37(usagePeaks.segment, 0)
|
|
23077
|
+
)
|
|
23078
|
+
);
|
|
23079
|
+
}
|
|
23080
|
+
|
|
23081
|
+
// src/commands/sessions/shared/transcriptUsage.ts
|
|
23082
|
+
import * as fs31 from "fs";
|
|
23083
|
+
function transcriptUsage(lines) {
|
|
23084
|
+
const byId = /* @__PURE__ */ new Map();
|
|
23085
|
+
for (const line of lines) {
|
|
23086
|
+
if (!line.trim()) continue;
|
|
23087
|
+
let entry;
|
|
23088
|
+
try {
|
|
23089
|
+
entry = JSON.parse(line);
|
|
23090
|
+
} catch {
|
|
23091
|
+
continue;
|
|
23092
|
+
}
|
|
23093
|
+
if (entry.type !== "assistant") continue;
|
|
23094
|
+
const id = entry.message?.id;
|
|
23095
|
+
const usage = entry.message?.usage;
|
|
23096
|
+
if (!id || !usage) continue;
|
|
23097
|
+
byId.set(id, {
|
|
23098
|
+
messageId: id,
|
|
23099
|
+
inputTokens: usage.input_tokens ?? 0,
|
|
23100
|
+
outputTokens: usage.output_tokens ?? 0
|
|
23101
|
+
});
|
|
23102
|
+
}
|
|
23103
|
+
return [...byId.values()];
|
|
23104
|
+
}
|
|
23105
|
+
async function readTranscriptUsage(transcriptPath) {
|
|
23106
|
+
const content = await fs31.promises.readFile(transcriptPath, "utf8");
|
|
23107
|
+
return transcriptUsage(content.split("\n"));
|
|
23108
|
+
}
|
|
23109
|
+
|
|
22946
23110
|
// src/commands/sessions/daemon/persistPhaseTokens.ts
|
|
22947
|
-
async function persistPhaseTokens(itemId2, phaseIdx,
|
|
23111
|
+
async function persistPhaseTokens(itemId2, phaseIdx, transcriptPath, windows) {
|
|
22948
23112
|
try {
|
|
22949
23113
|
if (!process.env.ASSIST_DATABASE_URL && !loadConfig().database.url) return;
|
|
22950
|
-
|
|
23114
|
+
const responses = await readTranscriptUsage(transcriptPath);
|
|
23115
|
+
if (responses.length === 0) return;
|
|
23116
|
+
const db = await getDb();
|
|
23117
|
+
const { tokensUp, tokensDown } = await recordPhaseTranscriptUsage(
|
|
23118
|
+
db,
|
|
23119
|
+
itemId2,
|
|
23120
|
+
phaseIdx,
|
|
23121
|
+
responses
|
|
23122
|
+
);
|
|
23123
|
+
for (const { window, resetsAt } of windows) {
|
|
23124
|
+
await recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown);
|
|
23125
|
+
}
|
|
22951
23126
|
} catch (error) {
|
|
22952
23127
|
daemonLog(`phase-tokens persist failed: ${String(error)}`);
|
|
22953
23128
|
}
|
|
22954
23129
|
}
|
|
22955
23130
|
|
|
22956
23131
|
// src/commands/sessions/daemon/recordSessionUsage.ts
|
|
22957
|
-
function recordSessionUsage(sessions, claudeSessionId,
|
|
23132
|
+
function recordSessionUsage(sessions, claudeSessionId, transcriptPath, usedPct, windows) {
|
|
22958
23133
|
for (const session of sessions) {
|
|
22959
23134
|
if (session.claudeSessionId !== claudeSessionId) continue;
|
|
22960
23135
|
session.usedPct = usedPct;
|
|
22961
23136
|
const phase = sessionBacklogPhase(session);
|
|
22962
|
-
if (phase)
|
|
22963
|
-
void persistPhaseTokens(
|
|
23137
|
+
if (phase && transcriptPath)
|
|
23138
|
+
void persistPhaseTokens(
|
|
23139
|
+
phase.itemId,
|
|
23140
|
+
phase.phaseIdx,
|
|
23141
|
+
transcriptPath,
|
|
23142
|
+
windows
|
|
23143
|
+
);
|
|
22964
23144
|
return true;
|
|
22965
23145
|
}
|
|
22966
23146
|
return false;
|
|
@@ -22982,10 +23162,10 @@ function applyReviewPause(session, activity2) {
|
|
|
22982
23162
|
}
|
|
22983
23163
|
|
|
22984
23164
|
// src/shared/db/getPhaseActiveMs.ts
|
|
22985
|
-
import { and as
|
|
23165
|
+
import { and as and20, eq as eq38 } from "drizzle-orm";
|
|
22986
23166
|
async function getPhaseActiveMs(db, itemId2, phaseIdx) {
|
|
22987
23167
|
const [row] = await db.select({ activeMs: phaseUsage.activeMs }).from(phaseUsage).where(
|
|
22988
|
-
|
|
23168
|
+
and20(eq38(phaseUsage.itemId, itemId2), eq38(phaseUsage.phaseIdx, phaseIdx))
|
|
22989
23169
|
);
|
|
22990
23170
|
return row?.activeMs ?? 0;
|
|
22991
23171
|
}
|
|
@@ -24249,13 +24429,13 @@ var SessionManager = class {
|
|
|
24249
24429
|
}
|
|
24250
24430
|
/* why: the status line relays token totals keyed by Claude's session id; join
|
|
24251
24431
|
* it to the running backlog phase so the spend accumulates against that row. */
|
|
24252
|
-
recordUsage(claudeSessionId,
|
|
24432
|
+
recordUsage(claudeSessionId, transcriptPath, usedPct) {
|
|
24253
24433
|
if (recordSessionUsage(
|
|
24254
24434
|
this.sessions.values(),
|
|
24255
24435
|
claudeSessionId,
|
|
24256
|
-
|
|
24257
|
-
|
|
24258
|
-
|
|
24436
|
+
transcriptPath,
|
|
24437
|
+
usedPct,
|
|
24438
|
+
this.clients.currentWindows()
|
|
24259
24439
|
))
|
|
24260
24440
|
this.notify();
|
|
24261
24441
|
}
|
|
@@ -24279,12 +24459,12 @@ import * as net3 from "net";
|
|
|
24279
24459
|
import { createInterface as createInterface9 } from "readline";
|
|
24280
24460
|
|
|
24281
24461
|
// src/commands/sessions/shared/discoverSessions.ts
|
|
24282
|
-
import * as
|
|
24462
|
+
import * as fs33 from "fs";
|
|
24283
24463
|
import * as os from "os";
|
|
24284
24464
|
import * as path52 from "path";
|
|
24285
24465
|
|
|
24286
24466
|
// src/commands/sessions/shared/parseSessionFile.ts
|
|
24287
|
-
import * as
|
|
24467
|
+
import * as fs32 from "fs";
|
|
24288
24468
|
import * as path51 from "path";
|
|
24289
24469
|
|
|
24290
24470
|
// src/commands/sessions/shared/deriveHistoryFields.ts
|
|
@@ -24315,8 +24495,8 @@ function deriveSessionType(commandName, name) {
|
|
|
24315
24495
|
}
|
|
24316
24496
|
|
|
24317
24497
|
// src/commands/sessions/shared/backlogRunMarkers.ts
|
|
24318
|
-
function backlogRunMarkers(
|
|
24319
|
-
const match =
|
|
24498
|
+
function backlogRunMarkers(text10) {
|
|
24499
|
+
const match = text10.match(/backlog item a(\d+):[ \t]*([^\n]*)/);
|
|
24320
24500
|
if (!match) return { commandName: "", commandArgs: "" };
|
|
24321
24501
|
const title = match[2].trim();
|
|
24322
24502
|
return {
|
|
@@ -24370,11 +24550,11 @@ function messageText(entry) {
|
|
|
24370
24550
|
const content = msg?.content;
|
|
24371
24551
|
return typeof content === "string" ? content : Array.isArray(content) ? content.find((c) => c.type === "text")?.text ?? "" : "";
|
|
24372
24552
|
}
|
|
24373
|
-
function stripMarkers(
|
|
24374
|
-
return
|
|
24553
|
+
function stripMarkers(text10) {
|
|
24554
|
+
return text10.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
|
|
24375
24555
|
}
|
|
24376
|
-
function matchMarker(
|
|
24377
|
-
const match =
|
|
24556
|
+
function matchMarker(text10, tag) {
|
|
24557
|
+
const match = text10.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
|
|
24378
24558
|
return match ? match[1].trim() : "";
|
|
24379
24559
|
}
|
|
24380
24560
|
|
|
@@ -24382,10 +24562,10 @@ function matchMarker(text9, tag) {
|
|
|
24382
24562
|
async function parseSessionFile(filePath, origin = "wsl") {
|
|
24383
24563
|
let handle;
|
|
24384
24564
|
try {
|
|
24385
|
-
handle = await
|
|
24565
|
+
handle = await fs32.promises.open(filePath, "r");
|
|
24386
24566
|
const meta = extractSessionMeta(await readHeadLines(handle));
|
|
24387
24567
|
if (!meta.sessionId) return null;
|
|
24388
|
-
const timestamp5 = meta.timestamp || (await
|
|
24568
|
+
const timestamp5 = meta.timestamp || (await fs32.promises.stat(filePath)).mtime.toISOString();
|
|
24389
24569
|
return {
|
|
24390
24570
|
sessionId: meta.sessionId,
|
|
24391
24571
|
name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
|
|
@@ -24431,7 +24611,7 @@ async function discoverSessionJsonlPaths() {
|
|
|
24431
24611
|
sessionRoots().map(async ({ dir, origin }) => {
|
|
24432
24612
|
let projectDirs;
|
|
24433
24613
|
try {
|
|
24434
|
-
projectDirs = await
|
|
24614
|
+
projectDirs = await fs33.promises.readdir(dir);
|
|
24435
24615
|
} catch {
|
|
24436
24616
|
return;
|
|
24437
24617
|
}
|
|
@@ -24440,7 +24620,7 @@ async function discoverSessionJsonlPaths() {
|
|
|
24440
24620
|
const dirPath = path52.join(dir, dirName);
|
|
24441
24621
|
let entries;
|
|
24442
24622
|
try {
|
|
24443
|
-
entries = await
|
|
24623
|
+
entries = await fs33.promises.readdir(dirPath);
|
|
24444
24624
|
} catch {
|
|
24445
24625
|
return;
|
|
24446
24626
|
}
|
|
@@ -24473,7 +24653,7 @@ async function discoverSessions() {
|
|
|
24473
24653
|
}
|
|
24474
24654
|
|
|
24475
24655
|
// src/commands/sessions/shared/parseTranscript.ts
|
|
24476
|
-
import * as
|
|
24656
|
+
import * as fs34 from "fs";
|
|
24477
24657
|
|
|
24478
24658
|
// src/commands/sessions/shared/toolTarget.ts
|
|
24479
24659
|
function toolTarget(input) {
|
|
@@ -24492,17 +24672,17 @@ function entryMessages(entry) {
|
|
|
24492
24672
|
return [];
|
|
24493
24673
|
}
|
|
24494
24674
|
function userMessages(content) {
|
|
24495
|
-
if (typeof content === "string") return
|
|
24675
|
+
if (typeof content === "string") return text9("user", cleanUserText(content));
|
|
24496
24676
|
if (!Array.isArray(content)) return [];
|
|
24497
|
-
return content.filter((c) => c.type === "text").flatMap((c) =>
|
|
24677
|
+
return content.filter((c) => c.type === "text").flatMap((c) => text9("user", cleanUserText(c.text ?? "")));
|
|
24498
24678
|
}
|
|
24499
24679
|
function assistantMessages(content) {
|
|
24500
|
-
if (typeof content === "string") return
|
|
24680
|
+
if (typeof content === "string") return text9("assistant", content.trim());
|
|
24501
24681
|
if (!Array.isArray(content)) return [];
|
|
24502
24682
|
return content.flatMap((c) => assistantItem(c));
|
|
24503
24683
|
}
|
|
24504
24684
|
function assistantItem(c) {
|
|
24505
|
-
if (c.type === "text") return
|
|
24685
|
+
if (c.type === "text") return text9("assistant", (c.text ?? "").trim());
|
|
24506
24686
|
if (c.type === "tool_use")
|
|
24507
24687
|
return [
|
|
24508
24688
|
{
|
|
@@ -24513,7 +24693,7 @@ function assistantItem(c) {
|
|
|
24513
24693
|
];
|
|
24514
24694
|
return [];
|
|
24515
24695
|
}
|
|
24516
|
-
function
|
|
24696
|
+
function text9(role, value) {
|
|
24517
24697
|
return value ? [{ role, text: value }] : [];
|
|
24518
24698
|
}
|
|
24519
24699
|
function cleanUserText(value) {
|
|
@@ -24540,7 +24720,7 @@ async function parseTranscript(sessionId) {
|
|
|
24540
24720
|
const filePath = await findSessionJsonlPath(sessionId);
|
|
24541
24721
|
if (!filePath) return [];
|
|
24542
24722
|
try {
|
|
24543
|
-
const raw = await
|
|
24723
|
+
const raw = await fs34.promises.readFile(filePath, "utf8");
|
|
24544
24724
|
return parseTranscriptLines(raw.split("\n"));
|
|
24545
24725
|
} catch {
|
|
24546
24726
|
return [];
|
|
@@ -24638,8 +24818,7 @@ var messageHandlers = {
|
|
|
24638
24818
|
limits: (_client, m, d) => m.clients.updateLimits(d.rateLimits),
|
|
24639
24819
|
usage: (_client, m, d) => m.recordUsage(
|
|
24640
24820
|
d.claudeSessionId,
|
|
24641
|
-
d.
|
|
24642
|
-
d.totalOut,
|
|
24821
|
+
d.transcriptPath,
|
|
24643
24822
|
d.usedPct
|
|
24644
24823
|
),
|
|
24645
24824
|
input: routed(
|
|
@@ -24850,17 +25029,17 @@ function registerDaemon(program2) {
|
|
|
24850
25029
|
}
|
|
24851
25030
|
|
|
24852
25031
|
// src/commands/sessions/summarise/index.ts
|
|
24853
|
-
import * as
|
|
25032
|
+
import * as fs37 from "fs";
|
|
24854
25033
|
import chalk193 from "chalk";
|
|
24855
25034
|
|
|
24856
25035
|
// src/commands/sessions/summarise/shared.ts
|
|
24857
|
-
import * as
|
|
25036
|
+
import * as fs35 from "fs";
|
|
24858
25037
|
function writeSummary(jsonlPath2, summary) {
|
|
24859
|
-
|
|
25038
|
+
fs35.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
|
|
24860
25039
|
`, "utf8");
|
|
24861
25040
|
}
|
|
24862
25041
|
function hasSummary(jsonlPath2) {
|
|
24863
|
-
return
|
|
25042
|
+
return fs35.existsSync(summaryPathFor(jsonlPath2));
|
|
24864
25043
|
}
|
|
24865
25044
|
function summaryPathFor(jsonlPath2) {
|
|
24866
25045
|
return jsonlPath2.replace(/\.jsonl$/, ".summary");
|
|
@@ -24870,7 +25049,7 @@ function summaryPathFor(jsonlPath2) {
|
|
|
24870
25049
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
24871
25050
|
|
|
24872
25051
|
// src/commands/sessions/summarise/iterateUserMessages.ts
|
|
24873
|
-
import * as
|
|
25052
|
+
import * as fs36 from "fs";
|
|
24874
25053
|
|
|
24875
25054
|
// src/commands/sessions/summarise/parseUserLine.ts
|
|
24876
25055
|
function parseUserLine(line) {
|
|
@@ -24883,16 +25062,16 @@ function parseUserLine(line) {
|
|
|
24883
25062
|
if (entry.type !== "user") return void 0;
|
|
24884
25063
|
const msg = entry.message;
|
|
24885
25064
|
const c = msg?.content;
|
|
24886
|
-
let
|
|
25065
|
+
let text10;
|
|
24887
25066
|
if (typeof c === "string") {
|
|
24888
|
-
|
|
25067
|
+
text10 = c;
|
|
24889
25068
|
} else if (Array.isArray(c)) {
|
|
24890
25069
|
const collected = c.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n");
|
|
24891
|
-
|
|
25070
|
+
text10 = collected || void 0;
|
|
24892
25071
|
}
|
|
24893
|
-
if (!
|
|
25072
|
+
if (!text10) return void 0;
|
|
24894
25073
|
return {
|
|
24895
|
-
text:
|
|
25074
|
+
text: text10,
|
|
24896
25075
|
entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
|
|
24897
25076
|
};
|
|
24898
25077
|
}
|
|
@@ -24901,13 +25080,13 @@ function parseUserLine(line) {
|
|
|
24901
25080
|
function* iterateUserMessages(filePath, maxBytes = 65536) {
|
|
24902
25081
|
let content;
|
|
24903
25082
|
try {
|
|
24904
|
-
const fd =
|
|
25083
|
+
const fd = fs36.openSync(filePath, "r");
|
|
24905
25084
|
try {
|
|
24906
25085
|
const buf = Buffer.alloc(maxBytes);
|
|
24907
|
-
const bytesRead =
|
|
25086
|
+
const bytesRead = fs36.readSync(fd, buf, 0, buf.length, 0);
|
|
24908
25087
|
content = buf.toString("utf8", 0, bytesRead);
|
|
24909
25088
|
} finally {
|
|
24910
|
-
|
|
25089
|
+
fs36.closeSync(fd);
|
|
24911
25090
|
}
|
|
24912
25091
|
} catch {
|
|
24913
25092
|
return;
|
|
@@ -24921,13 +25100,13 @@ function* iterateUserMessages(filePath, maxBytes = 65536) {
|
|
|
24921
25100
|
|
|
24922
25101
|
// src/commands/sessions/summarise/extractFirstUserMessage.ts
|
|
24923
25102
|
function extractFirstUserMessage(filePath) {
|
|
24924
|
-
for (const
|
|
24925
|
-
return truncate3(
|
|
25103
|
+
for (const text10 of iterateUserMessages(filePath)) {
|
|
25104
|
+
return truncate3(text10);
|
|
24926
25105
|
}
|
|
24927
25106
|
return void 0;
|
|
24928
25107
|
}
|
|
24929
|
-
function truncate3(
|
|
24930
|
-
const trimmed =
|
|
25108
|
+
function truncate3(text10, maxChars = 500) {
|
|
25109
|
+
const trimmed = text10.trim();
|
|
24931
25110
|
if (trimmed.length <= maxChars) return trimmed;
|
|
24932
25111
|
return `${trimmed.slice(0, maxChars)}\u2026`;
|
|
24933
25112
|
}
|
|
@@ -24935,28 +25114,28 @@ function truncate3(text9, maxChars = 500) {
|
|
|
24935
25114
|
// src/commands/sessions/summarise/scanSessionBacklogRefs.ts
|
|
24936
25115
|
function scanSessionBacklogRefs(filePath) {
|
|
24937
25116
|
const ids = /* @__PURE__ */ new Set();
|
|
24938
|
-
for (const
|
|
24939
|
-
for (const id of extractBacklogIds(
|
|
25117
|
+
for (const text10 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
|
|
25118
|
+
for (const id of extractBacklogIds(text10)) {
|
|
24940
25119
|
ids.add(id);
|
|
24941
25120
|
}
|
|
24942
25121
|
}
|
|
24943
25122
|
return [...ids].sort((a, b) => a - b);
|
|
24944
25123
|
}
|
|
24945
|
-
function extractBacklogIds(
|
|
25124
|
+
function extractBacklogIds(text10) {
|
|
24946
25125
|
const ids = [];
|
|
24947
|
-
for (const m of
|
|
25126
|
+
for (const m of text10.matchAll(/backlog\s+run\s+a(\d+)/gi)) {
|
|
24948
25127
|
ids.push(Number.parseInt(m[1], 10));
|
|
24949
25128
|
}
|
|
24950
|
-
for (const m of
|
|
25129
|
+
for (const m of text10.matchAll(/backlog\s+(?:item\s+)?a(\d+)/gi)) {
|
|
24951
25130
|
ids.push(Number.parseInt(m[1], 10));
|
|
24952
25131
|
}
|
|
24953
|
-
for (const m of
|
|
25132
|
+
for (const m of text10.matchAll(/backlog\s+phase-done\s+a(\d+)/gi)) {
|
|
24954
25133
|
ids.push(Number.parseInt(m[1], 10));
|
|
24955
25134
|
}
|
|
24956
|
-
for (const m of
|
|
25135
|
+
for (const m of text10.matchAll(/backlog\s+comment\s+a(\d+)/gi)) {
|
|
24957
25136
|
ids.push(Number.parseInt(m[1], 10));
|
|
24958
25137
|
}
|
|
24959
|
-
for (const m of
|
|
25138
|
+
for (const m of text10.matchAll(/(?:^|[\s(])a(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
|
|
24960
25139
|
ids.push(Number.parseInt(m[1], 10));
|
|
24961
25140
|
}
|
|
24962
25141
|
return ids;
|
|
@@ -25027,7 +25206,7 @@ function selectCandidates(files, options2) {
|
|
|
25027
25206
|
const candidates = options2.force ? files : files.filter((f) => !hasSummary(f));
|
|
25028
25207
|
candidates.sort((a, b) => {
|
|
25029
25208
|
try {
|
|
25030
|
-
return
|
|
25209
|
+
return fs37.statSync(b).mtimeMs - fs37.statSync(a).mtimeMs;
|
|
25031
25210
|
} catch {
|
|
25032
25211
|
return 0;
|
|
25033
25212
|
}
|
|
@@ -25207,14 +25386,13 @@ async function relayRateLimits(rateLimits) {
|
|
|
25207
25386
|
}
|
|
25208
25387
|
|
|
25209
25388
|
// src/commands/relayUsage.ts
|
|
25210
|
-
async function relayUsage(claudeSessionId,
|
|
25389
|
+
async function relayUsage(claudeSessionId, transcriptPath, usedPct) {
|
|
25211
25390
|
if (!claudeSessionId) return;
|
|
25212
25391
|
try {
|
|
25213
25392
|
await sendToDaemon({
|
|
25214
25393
|
type: "usage",
|
|
25215
25394
|
claudeSessionId,
|
|
25216
|
-
|
|
25217
|
-
totalOut,
|
|
25395
|
+
transcriptPath,
|
|
25218
25396
|
usedPct
|
|
25219
25397
|
});
|
|
25220
25398
|
} catch {
|
|
@@ -25247,28 +25425,27 @@ async function statusLine() {
|
|
|
25247
25425
|
await relayRateLimits(data.rate_limits);
|
|
25248
25426
|
await relayUsage(
|
|
25249
25427
|
data.session_id,
|
|
25250
|
-
|
|
25251
|
-
totalOut,
|
|
25428
|
+
data.transcript_path,
|
|
25252
25429
|
data.context_window.used_percentage
|
|
25253
25430
|
);
|
|
25254
25431
|
}
|
|
25255
25432
|
|
|
25256
25433
|
// src/commands/sync.ts
|
|
25257
|
-
import * as
|
|
25434
|
+
import * as fs40 from "fs";
|
|
25258
25435
|
import * as os2 from "os";
|
|
25259
25436
|
import * as path56 from "path";
|
|
25260
25437
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
25261
25438
|
|
|
25262
25439
|
// src/commands/sync/syncClaudeMd.ts
|
|
25263
|
-
import * as
|
|
25440
|
+
import * as fs38 from "fs";
|
|
25264
25441
|
import * as path54 from "path";
|
|
25265
25442
|
import chalk196 from "chalk";
|
|
25266
25443
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
25267
25444
|
const source = path54.join(claudeDir, "CLAUDE.md");
|
|
25268
25445
|
const target = path54.join(targetBase, "CLAUDE.md");
|
|
25269
|
-
const sourceContent =
|
|
25270
|
-
if (
|
|
25271
|
-
const targetContent =
|
|
25446
|
+
const sourceContent = fs38.readFileSync(source, "utf8");
|
|
25447
|
+
if (fs38.existsSync(target)) {
|
|
25448
|
+
const targetContent = fs38.readFileSync(target, "utf8");
|
|
25272
25449
|
if (sourceContent !== targetContent) {
|
|
25273
25450
|
console.log(
|
|
25274
25451
|
chalk196.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
@@ -25285,21 +25462,21 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
25285
25462
|
}
|
|
25286
25463
|
}
|
|
25287
25464
|
}
|
|
25288
|
-
|
|
25465
|
+
fs38.copyFileSync(source, target);
|
|
25289
25466
|
console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
|
|
25290
25467
|
}
|
|
25291
25468
|
|
|
25292
25469
|
// src/commands/sync/syncSettings.ts
|
|
25293
|
-
import * as
|
|
25470
|
+
import * as fs39 from "fs";
|
|
25294
25471
|
import * as path55 from "path";
|
|
25295
25472
|
import chalk197 from "chalk";
|
|
25296
25473
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
25297
25474
|
const source = path55.join(claudeDir, "settings.json");
|
|
25298
25475
|
const target = path55.join(targetBase, "settings.json");
|
|
25299
|
-
const sourceContent =
|
|
25476
|
+
const sourceContent = fs39.readFileSync(source, "utf8");
|
|
25300
25477
|
const sourceSettings = JSON.parse(sourceContent);
|
|
25301
|
-
const targetExists =
|
|
25302
|
-
const targetContent = targetExists ?
|
|
25478
|
+
const targetExists = fs39.existsSync(target);
|
|
25479
|
+
const targetContent = targetExists ? fs39.readFileSync(target, "utf8") : "";
|
|
25303
25480
|
const preservedUserSettings = targetExists ? JSON.parse(targetContent) : {};
|
|
25304
25481
|
const mergedContent = JSON.stringify(
|
|
25305
25482
|
{ ...preservedUserSettings, ...sourceSettings },
|
|
@@ -25328,7 +25505,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
25328
25505
|
}
|
|
25329
25506
|
}
|
|
25330
25507
|
}
|
|
25331
|
-
|
|
25508
|
+
fs39.writeFileSync(target, mergedContent);
|
|
25332
25509
|
console.log("Copied settings.json to ~/.claude/settings.json");
|
|
25333
25510
|
}
|
|
25334
25511
|
|
|
@@ -25347,10 +25524,10 @@ async function sync(options2) {
|
|
|
25347
25524
|
function syncCommands(claudeDir, targetBase) {
|
|
25348
25525
|
const sourceDir = path56.join(claudeDir, "commands");
|
|
25349
25526
|
const targetDir = path56.join(targetBase, "commands");
|
|
25350
|
-
|
|
25351
|
-
const files =
|
|
25527
|
+
fs40.mkdirSync(targetDir, { recursive: true });
|
|
25528
|
+
const files = fs40.readdirSync(sourceDir);
|
|
25352
25529
|
for (const file of files) {
|
|
25353
|
-
|
|
25530
|
+
fs40.copyFileSync(path56.join(sourceDir, file), path56.join(targetDir, file));
|
|
25354
25531
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
25355
25532
|
}
|
|
25356
25533
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|