@staff0rd/assist 0.399.0 → 0.401.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 +89 -89
- package/dist/index.js +406 -256
- 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.401.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -429,7 +429,7 @@ function getTranscriptConfig() {
|
|
|
429
429
|
}
|
|
430
430
|
|
|
431
431
|
// src/shared/db/schema.ts
|
|
432
|
-
import { integer as
|
|
432
|
+
import { integer as integer15, pgTable as pgTable15, text as text15 } from "drizzle-orm/pg-core";
|
|
433
433
|
|
|
434
434
|
// src/shared/db/backups.ts
|
|
435
435
|
import { bigint, integer, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
|
@@ -562,74 +562,99 @@ var phaseCycleContext = pgTable8(
|
|
|
562
562
|
]
|
|
563
563
|
);
|
|
564
564
|
|
|
565
|
-
// src/shared/db/
|
|
565
|
+
// src/shared/db/phaseSessions.ts
|
|
566
566
|
import {
|
|
567
|
-
bigint as bigint3,
|
|
568
|
-
doublePrecision as doublePrecision2,
|
|
569
567
|
integer as integer9,
|
|
570
568
|
pgTable as pgTable9,
|
|
571
569
|
primaryKey as primaryKey5,
|
|
572
|
-
text as text9
|
|
570
|
+
text as text9,
|
|
571
|
+
timestamp as timestamp4
|
|
573
572
|
} from "drizzle-orm/pg-core";
|
|
574
|
-
var
|
|
575
|
-
"
|
|
573
|
+
var phaseSessions = pgTable9(
|
|
574
|
+
"phase_sessions",
|
|
576
575
|
{
|
|
577
|
-
itemId: integer9("item_id").notNull(),
|
|
576
|
+
itemId: integer9("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
|
|
578
577
|
phaseIdx: integer9("phase_idx").notNull(),
|
|
578
|
+
claudeSessionId: text9("claude_session_id").notNull(),
|
|
579
|
+
hostname: text9().notNull(),
|
|
580
|
+
osUser: text9("os_user").notNull(),
|
|
581
|
+
createdAt: timestamp4("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
582
|
+
},
|
|
583
|
+
(t) => [
|
|
584
|
+
primaryKey5({
|
|
585
|
+
columns: [t.itemId, t.phaseIdx, t.claudeSessionId]
|
|
586
|
+
})
|
|
587
|
+
]
|
|
588
|
+
);
|
|
589
|
+
|
|
590
|
+
// src/shared/db/phaseUsage.ts
|
|
591
|
+
import {
|
|
592
|
+
bigint as bigint3,
|
|
593
|
+
doublePrecision as doublePrecision2,
|
|
594
|
+
integer as integer10,
|
|
595
|
+
pgTable as pgTable10,
|
|
596
|
+
primaryKey as primaryKey6,
|
|
597
|
+
text as text10
|
|
598
|
+
} from "drizzle-orm/pg-core";
|
|
599
|
+
var phaseUsage = pgTable10(
|
|
600
|
+
"phase_usage",
|
|
601
|
+
{
|
|
602
|
+
itemId: integer10("item_id").notNull(),
|
|
603
|
+
phaseIdx: integer10("phase_idx").notNull(),
|
|
579
604
|
tokensUp: bigint3("tokens_up", { mode: "number" }).notNull().default(0),
|
|
580
605
|
tokensDown: bigint3("tokens_down", { mode: "number" }).notNull().default(0),
|
|
581
606
|
activeMs: bigint3("active_ms", { mode: "number" }).notNull().default(0),
|
|
582
607
|
peakContextPct: doublePrecision2("peak_context_pct").notNull().default(0),
|
|
583
608
|
lastTotalIn: bigint3("last_total_in", { mode: "number" }),
|
|
584
609
|
lastTotalOut: bigint3("last_total_out", { mode: "number" }),
|
|
585
|
-
claudeSessionId:
|
|
610
|
+
claudeSessionId: text10("claude_session_id")
|
|
586
611
|
},
|
|
587
|
-
(t) => [
|
|
612
|
+
(t) => [primaryKey6({ columns: [t.itemId, t.phaseIdx] })]
|
|
588
613
|
);
|
|
589
614
|
|
|
590
615
|
// src/shared/db/phaseUsageMessages.ts
|
|
591
|
-
import { integer as
|
|
592
|
-
var phaseUsageMessages =
|
|
616
|
+
import { integer as integer11, pgTable as pgTable11, primaryKey as primaryKey7, text as text11 } from "drizzle-orm/pg-core";
|
|
617
|
+
var phaseUsageMessages = pgTable11(
|
|
593
618
|
"phase_usage_messages",
|
|
594
619
|
{
|
|
595
|
-
itemId:
|
|
596
|
-
phaseIdx:
|
|
597
|
-
messageId:
|
|
620
|
+
itemId: integer11("item_id").notNull(),
|
|
621
|
+
phaseIdx: integer11("phase_idx").notNull(),
|
|
622
|
+
messageId: text11("message_id").notNull()
|
|
598
623
|
},
|
|
599
|
-
(t) => [
|
|
624
|
+
(t) => [primaryKey7({ columns: [t.itemId, t.phaseIdx, t.messageId] })]
|
|
600
625
|
);
|
|
601
626
|
|
|
602
627
|
// src/shared/db/planPhases.ts
|
|
603
|
-
import { integer as
|
|
604
|
-
var planPhases =
|
|
628
|
+
import { integer as integer12, pgTable as pgTable12, primaryKey as primaryKey8, text as text12 } from "drizzle-orm/pg-core";
|
|
629
|
+
var planPhases = pgTable12(
|
|
605
630
|
"plan_phases",
|
|
606
631
|
{
|
|
607
|
-
itemId:
|
|
608
|
-
idx:
|
|
609
|
-
name:
|
|
610
|
-
manualChecks:
|
|
632
|
+
itemId: integer12("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
|
|
633
|
+
idx: integer12().notNull(),
|
|
634
|
+
name: text12().notNull(),
|
|
635
|
+
manualChecks: text12("manual_checks")
|
|
611
636
|
},
|
|
612
|
-
(t) => [
|
|
637
|
+
(t) => [primaryKey8({ columns: [t.itemId, t.idx] })]
|
|
613
638
|
);
|
|
614
639
|
|
|
615
640
|
// src/shared/db/planTasks.ts
|
|
616
641
|
import {
|
|
617
642
|
foreignKey,
|
|
618
|
-
integer as
|
|
619
|
-
pgTable as
|
|
620
|
-
primaryKey as
|
|
621
|
-
text as
|
|
643
|
+
integer as integer13,
|
|
644
|
+
pgTable as pgTable13,
|
|
645
|
+
primaryKey as primaryKey9,
|
|
646
|
+
text as text13
|
|
622
647
|
} from "drizzle-orm/pg-core";
|
|
623
|
-
var planTasks =
|
|
648
|
+
var planTasks = pgTable13(
|
|
624
649
|
"plan_tasks",
|
|
625
650
|
{
|
|
626
|
-
itemId:
|
|
627
|
-
phaseIdx:
|
|
628
|
-
idx:
|
|
629
|
-
task:
|
|
651
|
+
itemId: integer13("item_id").notNull(),
|
|
652
|
+
phaseIdx: integer13("phase_idx").notNull(),
|
|
653
|
+
idx: integer13().notNull(),
|
|
654
|
+
task: text13().notNull()
|
|
630
655
|
},
|
|
631
656
|
(t) => [
|
|
632
|
-
|
|
657
|
+
primaryKey9({ columns: [t.itemId, t.phaseIdx, t.idx] }),
|
|
633
658
|
foreignKey({
|
|
634
659
|
columns: [t.itemId, t.phaseIdx],
|
|
635
660
|
foreignColumns: [planPhases.itemId, planPhases.idx]
|
|
@@ -642,35 +667,35 @@ import {
|
|
|
642
667
|
bigint as bigint4,
|
|
643
668
|
boolean as boolean2,
|
|
644
669
|
doublePrecision as doublePrecision3,
|
|
645
|
-
integer as
|
|
646
|
-
pgTable as
|
|
647
|
-
primaryKey as
|
|
648
|
-
text as
|
|
649
|
-
timestamp as
|
|
670
|
+
integer as integer14,
|
|
671
|
+
pgTable as pgTable14,
|
|
672
|
+
primaryKey as primaryKey10,
|
|
673
|
+
text as text14,
|
|
674
|
+
timestamp as timestamp5
|
|
650
675
|
} from "drizzle-orm/pg-core";
|
|
651
|
-
var usagePeaks =
|
|
676
|
+
var usagePeaks = pgTable14(
|
|
652
677
|
"usage_peaks",
|
|
653
678
|
{
|
|
654
|
-
window:
|
|
679
|
+
window: text14().$type().notNull(),
|
|
655
680
|
resetsAt: bigint4("resets_at", { mode: "number" }).notNull(),
|
|
656
|
-
segment:
|
|
681
|
+
segment: integer14().notNull().default(0),
|
|
657
682
|
usedPercentage: doublePrecision3("used_percentage").notNull(),
|
|
658
683
|
resetDetected: boolean2("reset_detected").notNull().default(false),
|
|
659
684
|
tokensUp: bigint4("tokens_up", { mode: "number" }).notNull().default(0),
|
|
660
685
|
tokensDown: bigint4("tokens_down", { mode: "number" }).notNull().default(0),
|
|
661
|
-
createdAt:
|
|
686
|
+
createdAt: timestamp5("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
662
687
|
},
|
|
663
|
-
(t) => [
|
|
688
|
+
(t) => [primaryKey10({ columns: [t.window, t.resetsAt, t.segment] })]
|
|
664
689
|
);
|
|
665
690
|
|
|
666
691
|
// src/shared/db/schema.ts
|
|
667
|
-
var metadata =
|
|
668
|
-
key:
|
|
669
|
-
value:
|
|
692
|
+
var metadata = pgTable15("metadata", {
|
|
693
|
+
key: text15().primaryKey(),
|
|
694
|
+
value: text15().notNull()
|
|
670
695
|
});
|
|
671
|
-
var feeds =
|
|
672
|
-
id:
|
|
673
|
-
url:
|
|
696
|
+
var feeds = pgTable15("feeds", {
|
|
697
|
+
id: integer15().generatedByDefaultAsIdentity().primaryKey(),
|
|
698
|
+
url: text15().notNull().unique()
|
|
674
699
|
});
|
|
675
700
|
var schema = {
|
|
676
701
|
items,
|
|
@@ -687,7 +712,8 @@ var schema = {
|
|
|
687
712
|
backups,
|
|
688
713
|
phaseUsage,
|
|
689
714
|
phaseUsageMessages,
|
|
690
|
-
phaseCycleContext
|
|
715
|
+
phaseCycleContext,
|
|
716
|
+
phaseSessions
|
|
691
717
|
};
|
|
692
718
|
|
|
693
719
|
// src/commands/backlog/addFeed.ts
|
|
@@ -1055,12 +1081,47 @@ var migration0004DropUsagePeaksContext = {
|
|
|
1055
1081
|
sql: sql5
|
|
1056
1082
|
};
|
|
1057
1083
|
|
|
1084
|
+
// src/shared/db/migrations/migration0005PhaseSessions.ts
|
|
1085
|
+
var sql6 = `
|
|
1086
|
+
CREATE TABLE IF NOT EXISTS phase_sessions (
|
|
1087
|
+
item_id INTEGER NOT NULL REFERENCES items(id) ON DELETE CASCADE,
|
|
1088
|
+
phase_idx INTEGER NOT NULL,
|
|
1089
|
+
claude_session_id TEXT NOT NULL,
|
|
1090
|
+
hostname TEXT NOT NULL,
|
|
1091
|
+
os_user TEXT NOT NULL,
|
|
1092
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
1093
|
+
PRIMARY KEY (item_id, phase_idx, claude_session_id)
|
|
1094
|
+
);
|
|
1095
|
+
`;
|
|
1096
|
+
var migration0005PhaseSessions = {
|
|
1097
|
+
id: 5,
|
|
1098
|
+
name: "phase-sessions",
|
|
1099
|
+
sql: sql6
|
|
1100
|
+
};
|
|
1101
|
+
|
|
1102
|
+
// src/shared/db/migrations/migration0006BackfillPhaseSessions.ts
|
|
1103
|
+
var sql7 = `
|
|
1104
|
+
INSERT INTO phase_sessions (item_id, phase_idx, claude_session_id, hostname, os_user)
|
|
1105
|
+
SELECT pu.item_id, pu.phase_idx, pu.claude_session_id, 'unknown', 'unknown'
|
|
1106
|
+
FROM phase_usage pu
|
|
1107
|
+
WHERE pu.claude_session_id IS NOT NULL
|
|
1108
|
+
AND EXISTS (SELECT 1 FROM items i WHERE i.id = pu.item_id)
|
|
1109
|
+
ON CONFLICT (item_id, phase_idx, claude_session_id) DO NOTHING;
|
|
1110
|
+
`;
|
|
1111
|
+
var migration0006BackfillPhaseSessions = {
|
|
1112
|
+
id: 6,
|
|
1113
|
+
name: "backfill-phase-sessions",
|
|
1114
|
+
sql: sql7
|
|
1115
|
+
};
|
|
1116
|
+
|
|
1058
1117
|
// src/shared/db/migrations/index.ts
|
|
1059
1118
|
var migrations = [
|
|
1060
1119
|
migration0001Baseline,
|
|
1061
1120
|
migration0002UsagePeaksContext,
|
|
1062
1121
|
migration0003PhaseCycleContext,
|
|
1063
|
-
migration0004DropUsagePeaksContext
|
|
1122
|
+
migration0004DropUsagePeaksContext,
|
|
1123
|
+
migration0005PhaseSessions,
|
|
1124
|
+
migration0006BackfillPhaseSessions
|
|
1064
1125
|
];
|
|
1065
1126
|
var latestMigrationId = migrations.reduce(
|
|
1066
1127
|
(max, m) => Math.max(max, m.id),
|
|
@@ -1143,8 +1204,8 @@ async function assertMigrationsInSync(exec3) {
|
|
|
1143
1204
|
// src/shared/db/migrations/MigrationExecutor.ts
|
|
1144
1205
|
function pgExecutor(queryable) {
|
|
1145
1206
|
return {
|
|
1146
|
-
exec: (
|
|
1147
|
-
query: async (
|
|
1207
|
+
exec: (sql23) => queryable.query(sql23),
|
|
1208
|
+
query: async (sql23, params) => (await queryable.query(sql23, params)).rows
|
|
1148
1209
|
};
|
|
1149
1210
|
}
|
|
1150
1211
|
|
|
@@ -2879,8 +2940,8 @@ function isBicepFile(filePath) {
|
|
|
2879
2940
|
}
|
|
2880
2941
|
|
|
2881
2942
|
// src/commands/verify/blockComments/collectBicepComments.ts
|
|
2882
|
-
function blankNonNewline(
|
|
2883
|
-
return
|
|
2943
|
+
function blankNonNewline(text17) {
|
|
2944
|
+
return text17.replace(/[^\n]/g, " ");
|
|
2884
2945
|
}
|
|
2885
2946
|
var STRING_LITERAL = /'''[\s\S]*?'''|'(?:[^'\\]|\\.)*'/g;
|
|
2886
2947
|
var BLOCK_COMMENT = /\/\*[\s\S]*?\*[/]/g;
|
|
@@ -2902,8 +2963,8 @@ function collectBicepComments(content) {
|
|
|
2902
2963
|
}
|
|
2903
2964
|
|
|
2904
2965
|
// src/commands/verify/blockComments/collectHashComments.ts
|
|
2905
|
-
function blankNonNewline2(
|
|
2906
|
-
return
|
|
2966
|
+
function blankNonNewline2(text17) {
|
|
2967
|
+
return text17.replace(/[^\n]/g, " ");
|
|
2907
2968
|
}
|
|
2908
2969
|
function isHeaderLine(line) {
|
|
2909
2970
|
const trimmed = line.trim();
|
|
@@ -2980,23 +3041,23 @@ var MACHINE_DIRECTIVES = [
|
|
|
2980
3041
|
"@vitest-environment",
|
|
2981
3042
|
MAINTAINABILITY_OVERRIDE_MARKER
|
|
2982
3043
|
];
|
|
2983
|
-
function isCommentExempt(
|
|
2984
|
-
const lower =
|
|
3044
|
+
function isCommentExempt(text17) {
|
|
3045
|
+
const lower = text17.toLowerCase();
|
|
2985
3046
|
return MACHINE_DIRECTIVES.some((d) => lower.includes(d));
|
|
2986
3047
|
}
|
|
2987
3048
|
|
|
2988
3049
|
// src/commands/verify/blockComments/collectSourceFindings.ts
|
|
2989
|
-
function toSingleLine(
|
|
2990
|
-
return
|
|
3050
|
+
function toSingleLine(text17) {
|
|
3051
|
+
return text17.replace(/\s+/g, " ").trim();
|
|
2991
3052
|
}
|
|
2992
3053
|
function collectSourceFindings(file, lines, project) {
|
|
2993
3054
|
const findings = [];
|
|
2994
3055
|
const sourceFile = project.addSourceFileAtPath(file);
|
|
2995
|
-
for (const { pos, text:
|
|
3056
|
+
for (const { pos, text: text17 } of collectComments(sourceFile)) {
|
|
2996
3057
|
const { line } = sourceFile.getLineAndColumnAtPos(pos);
|
|
2997
3058
|
if (!lines.has(line)) continue;
|
|
2998
|
-
if (isCommentExempt(
|
|
2999
|
-
findings.push({ file, line, text: toSingleLine(
|
|
3059
|
+
if (isCommentExempt(text17)) continue;
|
|
3060
|
+
findings.push({ file, line, text: toSingleLine(text17) });
|
|
3000
3061
|
}
|
|
3001
3062
|
return findings;
|
|
3002
3063
|
}
|
|
@@ -3016,10 +3077,10 @@ function collectYamlComments(content) {
|
|
|
3016
3077
|
// src/commands/verify/blockComments/collectFileComments.ts
|
|
3017
3078
|
function toFindings(file, lines, raw, exempt) {
|
|
3018
3079
|
const findings = [];
|
|
3019
|
-
for (const { line, text:
|
|
3080
|
+
for (const { line, text: text17 } of raw) {
|
|
3020
3081
|
if (!lines.has(line)) continue;
|
|
3021
|
-
if (exempt && isCommentExempt(
|
|
3022
|
-
findings.push({ file, line, text:
|
|
3082
|
+
if (exempt && isCommentExempt(text17)) continue;
|
|
3083
|
+
findings.push({ file, line, text: text17.replace(/\s+/g, " ").trim() });
|
|
3023
3084
|
}
|
|
3024
3085
|
return findings;
|
|
3025
3086
|
}
|
|
@@ -3121,8 +3182,8 @@ function blockComments() {
|
|
|
3121
3182
|
process.exit(0);
|
|
3122
3183
|
}
|
|
3123
3184
|
console.log("Comments on changed lines:\n");
|
|
3124
|
-
for (const { file, line, text:
|
|
3125
|
-
console.log(`${file}:${line} \u2192 ${
|
|
3185
|
+
for (const { file, line, text: text17 } of findings) {
|
|
3186
|
+
console.log(`${file}:${line} \u2192 ${text17}`);
|
|
3126
3187
|
}
|
|
3127
3188
|
console.log(`
|
|
3128
3189
|
Total: ${findings.length} comment(s)`);
|
|
@@ -4580,8 +4641,8 @@ async function buildDump(tables, copyOut) {
|
|
|
4580
4641
|
// src/commands/backlog/dump/copyTableOut.ts
|
|
4581
4642
|
import { to as copyTo } from "pg-copy-streams";
|
|
4582
4643
|
async function copyTableOut(client, table) {
|
|
4583
|
-
const
|
|
4584
|
-
const stream = client.query(copyTo(
|
|
4644
|
+
const sql23 = `COPY ${table.name} (${table.columns.join(", ")}) TO STDOUT`;
|
|
4645
|
+
const stream = client.query(copyTo(sql23));
|
|
4585
4646
|
const chunks = [];
|
|
4586
4647
|
for await (const chunk of stream) {
|
|
4587
4648
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
@@ -4693,8 +4754,8 @@ async function backup({ out }) {
|
|
|
4693
4754
|
const dir = expandTilde2(out ?? loadConfig().backup.dir);
|
|
4694
4755
|
await mkdir2(dir, { recursive: true });
|
|
4695
4756
|
const start3 = Date.now();
|
|
4696
|
-
const
|
|
4697
|
-
const filePath = resolve6(join11(dir, `backup-${
|
|
4757
|
+
const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
4758
|
+
const filePath = resolve6(join11(dir, `backup-${timestamp6}.dump`));
|
|
4698
4759
|
await exportBacklog(filePath);
|
|
4699
4760
|
const { size } = await stat(filePath);
|
|
4700
4761
|
const durationMs = Date.now() - start3;
|
|
@@ -5127,11 +5188,11 @@ import { promisify } from "util";
|
|
|
5127
5188
|
// src/shared/withSpinner.ts
|
|
5128
5189
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
5129
5190
|
var TICK_MS = 80;
|
|
5130
|
-
async function withSpinner(
|
|
5191
|
+
async function withSpinner(text17, task) {
|
|
5131
5192
|
if (!process.stderr.isTTY) return task();
|
|
5132
5193
|
let frame = 0;
|
|
5133
5194
|
const render = () => {
|
|
5134
|
-
process.stderr.write(`\r${SPINNER_FRAMES[frame]} ${
|
|
5195
|
+
process.stderr.write(`\r${SPINNER_FRAMES[frame]} ${text17}`);
|
|
5135
5196
|
};
|
|
5136
5197
|
render();
|
|
5137
5198
|
const timer = setInterval(() => {
|
|
@@ -5398,6 +5459,11 @@ var relationQueries = {
|
|
|
5398
5459
|
),
|
|
5399
5460
|
subtasks: (orm, ids) => orm.select().from(itemSubtasks).where(inArray(itemSubtasks.itemId, ids)).orderBy(asc2(itemSubtasks.itemId), asc2(itemSubtasks.idx)),
|
|
5400
5461
|
usage: (orm, ids) => orm.select().from(phaseUsage).where(inArray(phaseUsage.itemId, ids)).orderBy(asc2(phaseUsage.itemId), asc2(phaseUsage.phaseIdx)),
|
|
5462
|
+
sessions: (orm, ids) => orm.select().from(phaseSessions).where(inArray(phaseSessions.itemId, ids)).orderBy(
|
|
5463
|
+
asc2(phaseSessions.itemId),
|
|
5464
|
+
asc2(phaseSessions.phaseIdx),
|
|
5465
|
+
asc2(phaseSessions.createdAt)
|
|
5466
|
+
),
|
|
5401
5467
|
gitRefs: (orm, ids) => orm.select().from(itemGitRefs).where(inArray(itemGitRefs.itemId, ids)).orderBy(asc2(itemGitRefs.itemId), asc2(itemGitRefs.createdAt))
|
|
5402
5468
|
};
|
|
5403
5469
|
|
|
@@ -5416,6 +5482,7 @@ async function loadRelations(orm, ids, {
|
|
|
5416
5482
|
taskRows,
|
|
5417
5483
|
subtaskRows,
|
|
5418
5484
|
usageRows,
|
|
5485
|
+
sessionRows,
|
|
5419
5486
|
gitRefRows
|
|
5420
5487
|
] = await Promise.all([
|
|
5421
5488
|
includeComments ? relationQueries.comments(orm, ids) : [],
|
|
@@ -5424,6 +5491,7 @@ async function loadRelations(orm, ids, {
|
|
|
5424
5491
|
includeTasks ? relationQueries.tasks(orm, ids) : [],
|
|
5425
5492
|
includeSubtasks ? relationQueries.subtasks(orm, ids) : [],
|
|
5426
5493
|
includeUsage ? relationQueries.usage(orm, ids) : [],
|
|
5494
|
+
includeUsage ? relationQueries.sessions(orm, ids) : [],
|
|
5427
5495
|
includeGitRefs ? relationQueries.gitRefs(orm, ids) : []
|
|
5428
5496
|
]);
|
|
5429
5497
|
return {
|
|
@@ -5433,6 +5501,7 @@ async function loadRelations(orm, ids, {
|
|
|
5433
5501
|
tasks: groupByItem(taskRows),
|
|
5434
5502
|
subtasks: groupByItem(subtaskRows),
|
|
5435
5503
|
usage: groupByItem(usageRows),
|
|
5504
|
+
sessions: groupByItem(sessionRows),
|
|
5436
5505
|
gitRefs: groupByItem(gitRefRows)
|
|
5437
5506
|
};
|
|
5438
5507
|
}
|
|
@@ -5454,6 +5523,20 @@ function attachGitRefs(item, rel, id) {
|
|
|
5454
5523
|
if (gitRefs.length > 0) item.gitRefs = gitRefs;
|
|
5455
5524
|
}
|
|
5456
5525
|
|
|
5526
|
+
// src/commands/backlog/attachSessions.ts
|
|
5527
|
+
function rowToSession(s) {
|
|
5528
|
+
return {
|
|
5529
|
+
phaseIdx: s.phaseIdx,
|
|
5530
|
+
claudeSessionId: s.claudeSessionId,
|
|
5531
|
+
hostname: s.hostname,
|
|
5532
|
+
osUser: s.osUser
|
|
5533
|
+
};
|
|
5534
|
+
}
|
|
5535
|
+
function attachSessions(item, rel, id) {
|
|
5536
|
+
const sessions = (rel.sessions.get(id) ?? []).map(rowToSession);
|
|
5537
|
+
if (sessions.length > 0) item.phaseSessions = sessions;
|
|
5538
|
+
}
|
|
5539
|
+
|
|
5457
5540
|
// src/commands/backlog/attachSubtasks.ts
|
|
5458
5541
|
function rowToSubtask(s) {
|
|
5459
5542
|
const subtask = {
|
|
@@ -5573,6 +5656,7 @@ function rowToItem(row, rel) {
|
|
|
5573
5656
|
attachLinks(item, rel, row.id);
|
|
5574
5657
|
attachPlan(item, rel, row.id);
|
|
5575
5658
|
attachUsage(item, rel, row.id);
|
|
5659
|
+
attachSessions(item, rel, row.id);
|
|
5576
5660
|
attachGitRefs(item, rel, row.id);
|
|
5577
5661
|
return item;
|
|
5578
5662
|
}
|
|
@@ -5611,6 +5695,12 @@ var phaseUsageSchema = z3.strictObject({
|
|
|
5611
5695
|
activeMs: z3.number(),
|
|
5612
5696
|
peakContextPct: z3.number()
|
|
5613
5697
|
});
|
|
5698
|
+
var phaseSessionSchema = z3.strictObject({
|
|
5699
|
+
phaseIdx: z3.number(),
|
|
5700
|
+
claudeSessionId: z3.string(),
|
|
5701
|
+
hostname: z3.string(),
|
|
5702
|
+
osUser: z3.string()
|
|
5703
|
+
});
|
|
5614
5704
|
var phaseUsageTotalSchema = z3.strictObject({
|
|
5615
5705
|
tokensUp: z3.number(),
|
|
5616
5706
|
tokensDown: z3.number(),
|
|
@@ -5659,6 +5749,7 @@ var backlogItemSchema = z3.strictObject({
|
|
|
5659
5749
|
subtasks: z3.array(subtaskSchema).optional(),
|
|
5660
5750
|
links: z3.array(backlogLinkSchema).optional(),
|
|
5661
5751
|
phaseUsage: z3.array(phaseUsageSchema).optional(),
|
|
5752
|
+
phaseSessions: z3.array(phaseSessionSchema).optional(),
|
|
5662
5753
|
usageTotal: phaseUsageTotalSchema.optional(),
|
|
5663
5754
|
gitRefs: z3.array(gitRefSchema).optional(),
|
|
5664
5755
|
origin: z3.string().optional(),
|
|
@@ -5816,13 +5907,13 @@ async function loadItem(orm, id) {
|
|
|
5816
5907
|
}
|
|
5817
5908
|
|
|
5818
5909
|
// src/commands/backlog/saveAllItems.ts
|
|
5819
|
-
import { eq as eq7, sql as
|
|
5910
|
+
import { eq as eq7, sql as sql8 } from "drizzle-orm";
|
|
5820
5911
|
|
|
5821
5912
|
// src/commands/backlog/deleteItemRelations.ts
|
|
5822
5913
|
import { eq as eq6 } from "drizzle-orm";
|
|
5823
5914
|
|
|
5824
5915
|
// src/commands/backlog/searchItemIds.ts
|
|
5825
|
-
import { and as and3, asc as asc4, eq as eq8, ilike, or, sql as
|
|
5916
|
+
import { and as and3, asc as asc4, eq as eq8, ilike, or, sql as sql9 } from "drizzle-orm";
|
|
5826
5917
|
async function searchItemIds(orm, query, origin) {
|
|
5827
5918
|
const pattern2 = `%${query}%`;
|
|
5828
5919
|
const numberPattern = `%${query.replace(/^#/, "")}%`;
|
|
@@ -5836,7 +5927,7 @@ async function searchItemIds(orm, query, origin) {
|
|
|
5836
5927
|
ilike(items.jiraKey, pattern2),
|
|
5837
5928
|
ilike(comments.text, pattern2),
|
|
5838
5929
|
ilike(planPhases.name, pattern2),
|
|
5839
|
-
ilike(
|
|
5930
|
+
ilike(sql9`${items.id}::text`, numberPattern)
|
|
5840
5931
|
)
|
|
5841
5932
|
)
|
|
5842
5933
|
).orderBy(asc4(items.id));
|
|
@@ -5960,12 +6051,12 @@ async function findPhaseBySessionId(db, itemId2, claudeSessionId) {
|
|
|
5960
6051
|
}
|
|
5961
6052
|
|
|
5962
6053
|
// src/commands/backlog/appendComment.ts
|
|
5963
|
-
import { sql as
|
|
5964
|
-
async function appendComment(orm, itemId2,
|
|
6054
|
+
import { sql as sql10 } from "drizzle-orm";
|
|
6055
|
+
async function appendComment(orm, itemId2, text17, opts = {}) {
|
|
5965
6056
|
await orm.insert(comments).values({
|
|
5966
6057
|
itemId: itemId2,
|
|
5967
|
-
idx:
|
|
5968
|
-
text:
|
|
6058
|
+
idx: sql10`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId2})`,
|
|
6059
|
+
text: text17,
|
|
5969
6060
|
phase: opts.phase ?? null,
|
|
5970
6061
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5971
6062
|
type: opts.type ?? "comment"
|
|
@@ -6413,6 +6504,43 @@ function launchPhaseSession(item, phaseNumber, phase, phaseLabel2, claudeSession
|
|
|
6413
6504
|
);
|
|
6414
6505
|
}
|
|
6415
6506
|
|
|
6507
|
+
// src/commands/backlog/persistPhaseSession.ts
|
|
6508
|
+
import os from "os";
|
|
6509
|
+
|
|
6510
|
+
// src/shared/db/recordPhaseSession.ts
|
|
6511
|
+
import { sql as sql11 } from "drizzle-orm";
|
|
6512
|
+
async function recordPhaseSession(db, itemId2, phaseIdx, claudeSessionId, hostname, osUser) {
|
|
6513
|
+
await db.insert(phaseSessions).values({ itemId: itemId2, phaseIdx, claudeSessionId, hostname, osUser }).onConflictDoUpdate({
|
|
6514
|
+
target: [
|
|
6515
|
+
phaseSessions.itemId,
|
|
6516
|
+
phaseSessions.phaseIdx,
|
|
6517
|
+
phaseSessions.claudeSessionId
|
|
6518
|
+
],
|
|
6519
|
+
set: { hostname, osUser },
|
|
6520
|
+
setWhere: sql11`${phaseSessions.hostname} = 'unknown'`
|
|
6521
|
+
});
|
|
6522
|
+
}
|
|
6523
|
+
|
|
6524
|
+
// src/commands/backlog/persistPhaseSession.ts
|
|
6525
|
+
async function persistPhaseSession(itemId2, phaseIdx, claudeSessionId) {
|
|
6526
|
+
try {
|
|
6527
|
+
const { orm } = await getReady();
|
|
6528
|
+
await recordPhaseSession(
|
|
6529
|
+
orm,
|
|
6530
|
+
itemId2,
|
|
6531
|
+
phaseIdx,
|
|
6532
|
+
claudeSessionId,
|
|
6533
|
+
os.hostname(),
|
|
6534
|
+
os.userInfo().username
|
|
6535
|
+
);
|
|
6536
|
+
} catch (error) {
|
|
6537
|
+
console.error(
|
|
6538
|
+
`Failed to record phase session for item ${itemId2} phase ${phaseIdx}:`,
|
|
6539
|
+
error
|
|
6540
|
+
);
|
|
6541
|
+
}
|
|
6542
|
+
}
|
|
6543
|
+
|
|
6416
6544
|
// src/shared/db/recordPhaseSessionId.ts
|
|
6417
6545
|
async function recordPhaseSessionId(db, itemId2, phaseIdx, claudeSessionId) {
|
|
6418
6546
|
await db.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, claudeSessionId }).onConflictDoUpdate({
|
|
@@ -6557,7 +6685,7 @@ import * as path24 from "path";
|
|
|
6557
6685
|
|
|
6558
6686
|
// src/commands/sessions/shared/discoverSessions.ts
|
|
6559
6687
|
import * as fs17 from "fs";
|
|
6560
|
-
import * as
|
|
6688
|
+
import * as os2 from "os";
|
|
6561
6689
|
import * as path23 from "path";
|
|
6562
6690
|
|
|
6563
6691
|
// src/commands/sessions/shared/parseSessionFile.ts
|
|
@@ -6592,8 +6720,8 @@ function deriveSessionType(commandName, name) {
|
|
|
6592
6720
|
}
|
|
6593
6721
|
|
|
6594
6722
|
// src/commands/sessions/shared/backlogRunMarkers.ts
|
|
6595
|
-
function backlogRunMarkers(
|
|
6596
|
-
const match =
|
|
6723
|
+
function backlogRunMarkers(text17) {
|
|
6724
|
+
const match = text17.match(/backlog item a(\d+):[ \t]*([^\n]*)/);
|
|
6597
6725
|
if (!match) return { commandName: "", commandArgs: "" };
|
|
6598
6726
|
const title = match[2].trim();
|
|
6599
6727
|
return {
|
|
@@ -6606,7 +6734,7 @@ function backlogRunMarkers(text16) {
|
|
|
6606
6734
|
function extractSessionMeta(lines) {
|
|
6607
6735
|
let sessionId = "";
|
|
6608
6736
|
let cwd = "";
|
|
6609
|
-
let
|
|
6737
|
+
let timestamp6 = "";
|
|
6610
6738
|
let name = "";
|
|
6611
6739
|
let commandName = "";
|
|
6612
6740
|
let commandArgs = "";
|
|
@@ -6614,14 +6742,14 @@ function extractSessionMeta(lines) {
|
|
|
6614
6742
|
const entry = safeParse(line);
|
|
6615
6743
|
if (!entry) continue;
|
|
6616
6744
|
sessionId ||= strField(entry, "sessionId");
|
|
6617
|
-
|
|
6745
|
+
timestamp6 ||= strField(entry, "timestamp");
|
|
6618
6746
|
cwd ||= strField(entry, "cwd");
|
|
6619
6747
|
if (entry.type === "user" && !entry.isMeta) {
|
|
6620
6748
|
({ name, commandName, commandArgs } = parseFirstUserEntry(entry));
|
|
6621
6749
|
break;
|
|
6622
6750
|
}
|
|
6623
6751
|
}
|
|
6624
|
-
return { sessionId, cwd, timestamp:
|
|
6752
|
+
return { sessionId, cwd, timestamp: timestamp6, name, commandName, commandArgs };
|
|
6625
6753
|
}
|
|
6626
6754
|
function parseFirstUserEntry(entry) {
|
|
6627
6755
|
const raw = messageText(entry);
|
|
@@ -6647,11 +6775,11 @@ function messageText(entry) {
|
|
|
6647
6775
|
const content = msg?.content;
|
|
6648
6776
|
return typeof content === "string" ? content : Array.isArray(content) ? content.find((c) => c.type === "text")?.text ?? "" : "";
|
|
6649
6777
|
}
|
|
6650
|
-
function stripMarkers(
|
|
6651
|
-
return
|
|
6778
|
+
function stripMarkers(text17) {
|
|
6779
|
+
return text17.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
|
|
6652
6780
|
}
|
|
6653
|
-
function matchMarker(
|
|
6654
|
-
const match =
|
|
6781
|
+
function matchMarker(text17, tag) {
|
|
6782
|
+
const match = text17.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
|
|
6655
6783
|
return match ? match[1].trim() : "";
|
|
6656
6784
|
}
|
|
6657
6785
|
|
|
@@ -6662,13 +6790,13 @@ async function parseSessionFile(filePath, origin = "wsl") {
|
|
|
6662
6790
|
handle = await fs16.promises.open(filePath, "r");
|
|
6663
6791
|
const meta = extractSessionMeta(await readHeadLines(handle));
|
|
6664
6792
|
if (!meta.sessionId) return null;
|
|
6665
|
-
const
|
|
6793
|
+
const timestamp6 = meta.timestamp || (await fs16.promises.stat(filePath)).mtime.toISOString();
|
|
6666
6794
|
return {
|
|
6667
6795
|
sessionId: meta.sessionId,
|
|
6668
6796
|
name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
|
|
6669
6797
|
project: deriveProject(meta.cwd, filePath, origin),
|
|
6670
6798
|
cwd: meta.cwd,
|
|
6671
|
-
timestamp:
|
|
6799
|
+
timestamp: timestamp6,
|
|
6672
6800
|
origin,
|
|
6673
6801
|
...deriveHistoryFields(meta.commandName, meta.commandArgs, meta.name)
|
|
6674
6802
|
};
|
|
@@ -6696,7 +6824,7 @@ function dirNameToProject(filePath) {
|
|
|
6696
6824
|
// src/commands/sessions/shared/discoverSessions.ts
|
|
6697
6825
|
function sessionRoots() {
|
|
6698
6826
|
const roots = [
|
|
6699
|
-
{ dir: path23.join(
|
|
6827
|
+
{ dir: path23.join(os2.homedir(), ".claude", "projects"), origin: "wsl" }
|
|
6700
6828
|
];
|
|
6701
6829
|
const windowsRoot = loadConfig().sessions?.windowsProjectsRoot;
|
|
6702
6830
|
if (windowsRoot) roots.push({ dir: windowsRoot, origin: "windows" });
|
|
@@ -6811,6 +6939,7 @@ async function executePhase(item, phaseIndex, phases, spawnOptions, totalPhases
|
|
|
6811
6939
|
if (!resumeSessionId) {
|
|
6812
6940
|
await persistPhaseSessionId(item.id, phaseIndex, claudeSessionId);
|
|
6813
6941
|
}
|
|
6942
|
+
await persistPhaseSession(item.id, phaseIndex, claudeSessionId);
|
|
6814
6943
|
const exitCode = await launchPhaseSession(
|
|
6815
6944
|
item,
|
|
6816
6945
|
phaseNumber,
|
|
@@ -7113,7 +7242,7 @@ function formatComment(entry) {
|
|
|
7113
7242
|
// src/shared/renderMarkdownTerminal.ts
|
|
7114
7243
|
import { Marked } from "marked";
|
|
7115
7244
|
import { markedTerminal } from "marked-terminal";
|
|
7116
|
-
function renderMarkdownTerminal(
|
|
7245
|
+
function renderMarkdownTerminal(text17) {
|
|
7117
7246
|
const width = process.stdout.columns || 80;
|
|
7118
7247
|
const marked = new Marked(markedTerminal({ width, reflowText: true }));
|
|
7119
7248
|
marked.use({
|
|
@@ -7126,7 +7255,7 @@ function renderMarkdownTerminal(text16) {
|
|
|
7126
7255
|
}
|
|
7127
7256
|
}
|
|
7128
7257
|
});
|
|
7129
|
-
return marked.parse(
|
|
7258
|
+
return marked.parse(text17).trimEnd();
|
|
7130
7259
|
}
|
|
7131
7260
|
|
|
7132
7261
|
// src/commands/backlog/show/printActivity.ts
|
|
@@ -7146,9 +7275,9 @@ function groupActivityRefs(refs, commitLimit = ACTIVITY_COMMIT_LIMIT) {
|
|
|
7146
7275
|
}
|
|
7147
7276
|
|
|
7148
7277
|
// src/commands/backlog/show/printActivity.ts
|
|
7149
|
-
function printRef(label2,
|
|
7278
|
+
function printRef(label2, text17, ref) {
|
|
7150
7279
|
const url = ref.url ? ` ${chalk50.dim(ref.url)}` : "";
|
|
7151
|
-
console.log(` ${chalk50.cyan(label2)} ${
|
|
7280
|
+
console.log(` ${chalk50.cyan(label2)} ${text17}${url}`);
|
|
7152
7281
|
}
|
|
7153
7282
|
function printActivity(item) {
|
|
7154
7283
|
const { branches, commits: commits2, prs: prs2, hiddenCommits } = groupActivityRefs(
|
|
@@ -7238,17 +7367,38 @@ function phaseHeader(index3, name, isCurrent) {
|
|
|
7238
7367
|
const label2 = isCurrent ? chalk53.green.bold(`Phase ${phaseNumber}: ${name}`) : `${chalk53.bold(`Phase ${phaseNumber}:`)} ${name}`;
|
|
7239
7368
|
return `${marker}${label2}`;
|
|
7240
7369
|
}
|
|
7241
|
-
function
|
|
7370
|
+
function printPhaseSessions(sessions) {
|
|
7371
|
+
if (sessions.length === 0) return;
|
|
7372
|
+
console.log(` ${chalk53.dim("Sessions:")}`);
|
|
7373
|
+
for (const s of sessions) {
|
|
7374
|
+
console.log(
|
|
7375
|
+
` ${chalk53.dim(`- ${s.hostname} / ${s.osUser} / ${s.claudeSessionId}`)}`
|
|
7376
|
+
);
|
|
7377
|
+
}
|
|
7378
|
+
}
|
|
7379
|
+
function printPhase(phase, index3, isCurrent, sessions) {
|
|
7242
7380
|
console.log(phaseHeader(index3, phase.name, isCurrent));
|
|
7243
7381
|
printPhaseTasks(phase);
|
|
7382
|
+
printPhaseSessions(sessions);
|
|
7383
|
+
}
|
|
7384
|
+
function printReviewSessions(item, planLength) {
|
|
7385
|
+
const sessions = (item.phaseSessions ?? []).filter(
|
|
7386
|
+
(s) => s.phaseIdx >= planLength
|
|
7387
|
+
);
|
|
7388
|
+
if (sessions.length === 0) return;
|
|
7389
|
+
const isCurrent = item.currentPhase === planLength + 1;
|
|
7390
|
+
console.log(phaseHeader(planLength, REVIEW_PHASE_NAME, isCurrent));
|
|
7391
|
+
printPhaseSessions(sessions);
|
|
7244
7392
|
}
|
|
7245
7393
|
function printPlan(item) {
|
|
7246
7394
|
if (!item.plan || item.plan.length === 0) return;
|
|
7247
7395
|
console.log(chalk53.bold("Plan"));
|
|
7248
7396
|
for (const [i, phase] of item.plan.entries()) {
|
|
7249
7397
|
const isCurrent = item.currentPhase === i + 1;
|
|
7250
|
-
|
|
7398
|
+
const sessions = (item.phaseSessions ?? []).filter((s) => s.phaseIdx === i);
|
|
7399
|
+
printPhase(phase, i, isCurrent, sessions);
|
|
7251
7400
|
}
|
|
7401
|
+
printReviewSessions(item, item.plan.length);
|
|
7252
7402
|
console.log();
|
|
7253
7403
|
}
|
|
7254
7404
|
|
|
@@ -7600,29 +7750,29 @@ import { eq as eq13 } from "drizzle-orm";
|
|
|
7600
7750
|
import { asc as asc5, eq as eq12 } from "drizzle-orm";
|
|
7601
7751
|
|
|
7602
7752
|
// src/commands/backlog/incompleteSubtaskCounts.ts
|
|
7603
|
-
import { ne, sql as
|
|
7753
|
+
import { ne, sql as sql12 } from "drizzle-orm";
|
|
7604
7754
|
function incompleteSubtaskCounts(orm) {
|
|
7605
7755
|
return orm.select({
|
|
7606
7756
|
itemId: itemSubtasks.itemId,
|
|
7607
|
-
count:
|
|
7757
|
+
count: sql12`count(*)::int`.as("incomplete_subtasks")
|
|
7608
7758
|
}).from(itemSubtasks).where(ne(itemSubtasks.status, "done")).groupBy(itemSubtasks.itemId).as("incomplete_counts");
|
|
7609
7759
|
}
|
|
7610
7760
|
|
|
7611
7761
|
// src/commands/backlog/phaseUsageTotals.ts
|
|
7612
|
-
import { sql as
|
|
7762
|
+
import { sql as sql13 } from "drizzle-orm";
|
|
7613
7763
|
function phaseUsageTotals(orm) {
|
|
7614
7764
|
return orm.select({
|
|
7615
7765
|
itemId: phaseUsage.itemId,
|
|
7616
|
-
tokensUp:
|
|
7766
|
+
tokensUp: sql13`sum(${phaseUsage.tokensUp})::bigint`.as(
|
|
7617
7767
|
"total_tokens_up"
|
|
7618
7768
|
),
|
|
7619
|
-
tokensDown:
|
|
7769
|
+
tokensDown: sql13`sum(${phaseUsage.tokensDown})::bigint`.as(
|
|
7620
7770
|
"total_tokens_down"
|
|
7621
7771
|
),
|
|
7622
|
-
activeMs:
|
|
7772
|
+
activeMs: sql13`sum(${phaseUsage.activeMs})::bigint`.as(
|
|
7623
7773
|
"total_active_ms"
|
|
7624
7774
|
),
|
|
7625
|
-
peakContextPct:
|
|
7775
|
+
peakContextPct: sql13`max(${phaseUsage.peakContextPct})`.as(
|
|
7626
7776
|
"max_peak_context_pct"
|
|
7627
7777
|
)
|
|
7628
7778
|
}).from(phaseUsage).groupBy(phaseUsage.itemId).as("usage_totals");
|
|
@@ -8233,7 +8383,7 @@ function runGitStatus(cwd) {
|
|
|
8233
8383
|
}
|
|
8234
8384
|
|
|
8235
8385
|
// src/shared/harnesses.ts
|
|
8236
|
-
import * as
|
|
8386
|
+
import * as os3 from "os";
|
|
8237
8387
|
import * as path25 from "path";
|
|
8238
8388
|
|
|
8239
8389
|
// src/shared/checkCliAvailable.ts
|
|
@@ -8262,7 +8412,7 @@ var harnesses = {
|
|
|
8262
8412
|
claude: {
|
|
8263
8413
|
kind: "claude",
|
|
8264
8414
|
command: "claude",
|
|
8265
|
-
homeDir: path25.join(
|
|
8415
|
+
homeDir: path25.join(os3.homedir(), ".claude"),
|
|
8266
8416
|
sync: {
|
|
8267
8417
|
agentsFile: "CLAUDE.md",
|
|
8268
8418
|
commandDest: (name) => path25.join("commands", `${name}.md`)
|
|
@@ -8271,7 +8421,7 @@ var harnesses = {
|
|
|
8271
8421
|
codex: {
|
|
8272
8422
|
kind: "codex",
|
|
8273
8423
|
command: "codex",
|
|
8274
|
-
homeDir: path25.join(
|
|
8424
|
+
homeDir: path25.join(os3.homedir(), ".codex"),
|
|
8275
8425
|
sync: {
|
|
8276
8426
|
agentsFile: "AGENTS.md",
|
|
8277
8427
|
commandDest: (name) => path25.join("skills", name, "SKILL.md")
|
|
@@ -8280,7 +8430,7 @@ var harnesses = {
|
|
|
8280
8430
|
pi: {
|
|
8281
8431
|
kind: "pi",
|
|
8282
8432
|
command: "pi",
|
|
8283
|
-
homeDir: path25.join(
|
|
8433
|
+
homeDir: path25.join(os3.homedir(), ".pi", "agent"),
|
|
8284
8434
|
sync: {
|
|
8285
8435
|
agentsFile: "AGENTS.md",
|
|
8286
8436
|
commandDest: (name) => path25.join("prompts", `${name}.md`)
|
|
@@ -8380,9 +8530,9 @@ function excerpt(xml, ...tags) {
|
|
|
8380
8530
|
for (const tag of tags) {
|
|
8381
8531
|
const raw = extractText(xml, tag);
|
|
8382
8532
|
if (!raw) continue;
|
|
8383
|
-
const
|
|
8384
|
-
if (
|
|
8385
|
-
return `${
|
|
8533
|
+
const text17 = stripHtml(raw);
|
|
8534
|
+
if (text17.length <= MAX_EXCERPT) return text17;
|
|
8535
|
+
return `${text17.slice(0, MAX_EXCERPT)}\u2026`;
|
|
8386
8536
|
}
|
|
8387
8537
|
return "";
|
|
8388
8538
|
}
|
|
@@ -8460,12 +8610,12 @@ async function listNewsItems(_req, res) {
|
|
|
8460
8610
|
}
|
|
8461
8611
|
|
|
8462
8612
|
// src/shared/db/listUsagePeaks.ts
|
|
8463
|
-
import { and as and7, count, desc as desc2, eq as eq17, getTableColumns, sql as
|
|
8613
|
+
import { and as and7, count, desc as desc2, eq as eq17, getTableColumns, sql as sql14 } from "drizzle-orm";
|
|
8464
8614
|
async function listUsagePeaks(db, paging) {
|
|
8465
8615
|
const avgContext = db.select({
|
|
8466
8616
|
window: phaseCycleContext.window,
|
|
8467
8617
|
resetsAt: phaseCycleContext.resetsAt,
|
|
8468
|
-
avgContextPct:
|
|
8618
|
+
avgContextPct: sql14`cast(avg(${phaseCycleContext.peakContextPct}) as double precision)`.as(
|
|
8469
8619
|
"avg_context_pct"
|
|
8470
8620
|
),
|
|
8471
8621
|
phaseCount: count().as("phase_count")
|
|
@@ -9314,10 +9464,10 @@ function registerAssociateJiraCommand(cmd) {
|
|
|
9314
9464
|
|
|
9315
9465
|
// src/commands/backlog/comment/index.ts
|
|
9316
9466
|
import chalk65 from "chalk";
|
|
9317
|
-
async function comment(id,
|
|
9467
|
+
async function comment(id, text17) {
|
|
9318
9468
|
const found = await findOneItem(id);
|
|
9319
9469
|
if (!found) process.exit(1);
|
|
9320
|
-
await appendComment(found.orm, found.item.id,
|
|
9470
|
+
await appendComment(found.orm, found.item.id, text17);
|
|
9321
9471
|
console.log(
|
|
9322
9472
|
chalk65.green(`Comment added to item ${formatItemId(found.item.id)}.`)
|
|
9323
9473
|
);
|
|
@@ -9422,9 +9572,9 @@ function readLine(dump, start3) {
|
|
|
9422
9572
|
return { text: dump.subarray(start3, eol).toString("utf8"), next: eol + 1 };
|
|
9423
9573
|
}
|
|
9424
9574
|
function parseHeader(dump) {
|
|
9425
|
-
const { text:
|
|
9575
|
+
const { text: text17, next: next3 } = readLine(dump, 0);
|
|
9426
9576
|
try {
|
|
9427
|
-
return { header: JSON.parse(
|
|
9577
|
+
return { header: JSON.parse(text17), bodyStart: next3 };
|
|
9428
9578
|
} catch {
|
|
9429
9579
|
return invalid("header is not valid JSON.");
|
|
9430
9580
|
}
|
|
@@ -9433,9 +9583,9 @@ function parseSections(dump, bodyStart) {
|
|
|
9433
9583
|
const sections = /* @__PURE__ */ new Map();
|
|
9434
9584
|
let cursor = bodyStart;
|
|
9435
9585
|
while (cursor < dump.length) {
|
|
9436
|
-
const { text:
|
|
9437
|
-
const match =
|
|
9438
|
-
if (!match) invalid(`malformed table marker "${
|
|
9586
|
+
const { text: text17, next: next3 } = readLine(dump, cursor);
|
|
9587
|
+
const match = text17.match(/^@table (\S+) (\d+)$/);
|
|
9588
|
+
if (!match) invalid(`malformed table marker "${text17}".`);
|
|
9439
9589
|
const [, name, bytes] = match;
|
|
9440
9590
|
const end = next3 + Number(bytes);
|
|
9441
9591
|
if (end > dump.length) invalid(`section "${name}" overruns the dump.`);
|
|
@@ -9511,8 +9661,8 @@ async function readStdinBuffer() {
|
|
|
9511
9661
|
import { finished } from "stream/promises";
|
|
9512
9662
|
import { from as copyFrom } from "pg-copy-streams";
|
|
9513
9663
|
async function copyTableIn(client, table, data) {
|
|
9514
|
-
const
|
|
9515
|
-
const stream = client.query(copyFrom(
|
|
9664
|
+
const sql23 = `COPY ${table.name} (${table.columns.join(", ")}) FROM STDIN`;
|
|
9665
|
+
const stream = client.query(copyFrom(sql23));
|
|
9516
9666
|
stream.end(data);
|
|
9517
9667
|
await finished(stream);
|
|
9518
9668
|
}
|
|
@@ -9557,8 +9707,8 @@ async function replaceData(client, parsed) {
|
|
|
9557
9707
|
await copyTableIn(client, table, data);
|
|
9558
9708
|
}
|
|
9559
9709
|
for (const col of await introspectIdentityColumns(client)) {
|
|
9560
|
-
const { text:
|
|
9561
|
-
await client.query(
|
|
9710
|
+
const { text: text17, values } = resyncIdentitySql(col);
|
|
9711
|
+
await client.query(text17, values);
|
|
9562
9712
|
}
|
|
9563
9713
|
}
|
|
9564
9714
|
async function restore(client, parsed) {
|
|
@@ -9636,11 +9786,11 @@ async function insertPhaseAt(orm, itemId2, phaseIdx, name, tasks, manualChecks,
|
|
|
9636
9786
|
}
|
|
9637
9787
|
|
|
9638
9788
|
// src/commands/backlog/insertSubtask.ts
|
|
9639
|
-
import { sql as
|
|
9789
|
+
import { sql as sql15 } from "drizzle-orm";
|
|
9640
9790
|
async function insertSubtask(orm, itemId2, title, description) {
|
|
9641
9791
|
await orm.insert(itemSubtasks).values({
|
|
9642
9792
|
itemId: itemId2,
|
|
9643
|
-
idx:
|
|
9793
|
+
idx: sql15`(SELECT COALESCE(MAX(${itemSubtasks.idx}) + 1, 0) FROM ${itemSubtasks} WHERE ${itemSubtasks.itemId} = ${itemId2})`,
|
|
9644
9794
|
title,
|
|
9645
9795
|
description: description ?? null,
|
|
9646
9796
|
status: "todo"
|
|
@@ -11459,8 +11609,8 @@ var RAW_BUILTIN_DENIES = [
|
|
|
11459
11609
|
regex
|
|
11460
11610
|
}))
|
|
11461
11611
|
];
|
|
11462
|
-
function matchBuiltinDeny(
|
|
11463
|
-
return RAW_BUILTIN_DENIES.find((rule) => rule.regex.test(
|
|
11612
|
+
function matchBuiltinDeny(text17) {
|
|
11613
|
+
return RAW_BUILTIN_DENIES.find((rule) => rule.regex.test(text17));
|
|
11464
11614
|
}
|
|
11465
11615
|
function toDecision(rule) {
|
|
11466
11616
|
if (!rule) return void 0;
|
|
@@ -12181,8 +12331,8 @@ function formatHuman(cli, commands) {
|
|
|
12181
12331
|
`];
|
|
12182
12332
|
for (const cmd of sorted) {
|
|
12183
12333
|
const full = `${cli} ${cmd.path.join(" ")}`;
|
|
12184
|
-
const
|
|
12185
|
-
lines.push(`${prefix(classifyVerb(cmd.path))}${
|
|
12334
|
+
const text17 = cmd.description ? `${full} \u2014 ${cmd.description}` : full;
|
|
12335
|
+
lines.push(`${prefix(classifyVerb(cmd.path))}${text17}`);
|
|
12186
12336
|
}
|
|
12187
12337
|
return lines.join("\n");
|
|
12188
12338
|
}
|
|
@@ -12461,38 +12611,38 @@ import chalk110 from "chalk";
|
|
|
12461
12611
|
// src/commands/codeComment/validateCommentText.ts
|
|
12462
12612
|
var MAX_COMMENT_LENGTH = 50;
|
|
12463
12613
|
function validateCommentText(raw, isHash = false) {
|
|
12464
|
-
const
|
|
12465
|
-
if (/[\r\n]/.test(
|
|
12614
|
+
const text17 = isHash ? raw.replace(/^#\s?/, "") : raw.replace(/^\/\/\s?/, "");
|
|
12615
|
+
if (/[\r\n]/.test(text17)) {
|
|
12466
12616
|
return {
|
|
12467
12617
|
ok: false,
|
|
12468
12618
|
reason: "Comment must be a single line \u2014 multi-line comments are not allowed."
|
|
12469
12619
|
};
|
|
12470
12620
|
}
|
|
12471
|
-
if (!isHash && (
|
|
12621
|
+
if (!isHash && (text17.includes("/*") || text17.includes("*/"))) {
|
|
12472
12622
|
return {
|
|
12473
12623
|
ok: false,
|
|
12474
12624
|
reason: "Block comments (/* */) are not allowed \u2014 only single-line // comments."
|
|
12475
12625
|
};
|
|
12476
12626
|
}
|
|
12477
|
-
if (
|
|
12627
|
+
if (text17.length > MAX_COMMENT_LENGTH) {
|
|
12478
12628
|
return {
|
|
12479
12629
|
ok: false,
|
|
12480
|
-
reason: `Comment text is ${
|
|
12630
|
+
reason: `Comment text is ${text17.length} chars; the cap is ${MAX_COMMENT_LENGTH}. Make it shorter or, better, make the code self-documenting.`
|
|
12481
12631
|
};
|
|
12482
12632
|
}
|
|
12483
|
-
return { ok: true, text:
|
|
12633
|
+
return { ok: true, text: text17 };
|
|
12484
12634
|
}
|
|
12485
12635
|
|
|
12486
12636
|
// src/commands/codeComment/issuePin.ts
|
|
12487
12637
|
import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync25 } from "fs";
|
|
12488
12638
|
import { randomInt } from "crypto";
|
|
12489
|
-
function issuePin(file, lineNumber,
|
|
12639
|
+
function issuePin(file, lineNumber, text17) {
|
|
12490
12640
|
const pin = generatePin();
|
|
12491
12641
|
mkdirSync14(getRestrictedDir(), { recursive: true });
|
|
12492
12642
|
sweepRestrictedDir();
|
|
12493
12643
|
writeFileSync25(
|
|
12494
12644
|
getPinStatePath(pin),
|
|
12495
|
-
JSON.stringify({ pin, file, line: lineNumber, text:
|
|
12645
|
+
JSON.stringify({ pin, file, line: lineNumber, text: text17 })
|
|
12496
12646
|
);
|
|
12497
12647
|
return showNotification({
|
|
12498
12648
|
title: "assist code-comment pin",
|
|
@@ -12504,7 +12654,7 @@ function generatePin() {
|
|
|
12504
12654
|
}
|
|
12505
12655
|
|
|
12506
12656
|
// src/commands/codeComment/codeCommentSet.ts
|
|
12507
|
-
function codeCommentSet(file, line,
|
|
12657
|
+
function codeCommentSet(file, line, text17) {
|
|
12508
12658
|
const lineNumber = Number.parseInt(line, 10);
|
|
12509
12659
|
if (!Number.isInteger(lineNumber) || lineNumber < 1) {
|
|
12510
12660
|
console.error(chalk110.red(`Invalid line number: ${line}`));
|
|
@@ -12513,7 +12663,7 @@ function codeCommentSet(file, line, text16) {
|
|
|
12513
12663
|
}
|
|
12514
12664
|
const hash = isHashCommentFile(file);
|
|
12515
12665
|
const marker = hash ? "#" : "//";
|
|
12516
|
-
const validation = validateCommentText(
|
|
12666
|
+
const validation = validateCommentText(text17, hash);
|
|
12517
12667
|
if (!validation.ok) {
|
|
12518
12668
|
console.error(chalk110.red(`Refused: ${validation.reason}`));
|
|
12519
12669
|
console.error(chalk110.red("No pin issued."));
|
|
@@ -14648,12 +14798,12 @@ function isSourceFile(filePath) {
|
|
|
14648
14798
|
if (!filePath) return false;
|
|
14649
14799
|
return SOURCE_EXTENSIONS.some((ext) => filePath.endsWith(ext));
|
|
14650
14800
|
}
|
|
14651
|
-
function blankNonNewline3(
|
|
14652
|
-
return
|
|
14801
|
+
function blankNonNewline3(text17) {
|
|
14802
|
+
return text17.replace(/[^\n]/g, " ");
|
|
14653
14803
|
}
|
|
14654
|
-
function extractComments(
|
|
14804
|
+
function extractComments(text17) {
|
|
14655
14805
|
const comments3 = [];
|
|
14656
|
-
let work =
|
|
14806
|
+
let work = text17.replace(
|
|
14657
14807
|
/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`/g,
|
|
14658
14808
|
blankNonNewline3
|
|
14659
14809
|
);
|
|
@@ -14668,11 +14818,11 @@ function extractComments(text16) {
|
|
|
14668
14818
|
}
|
|
14669
14819
|
|
|
14670
14820
|
// src/commands/editHook/extractYamlComments.ts
|
|
14671
|
-
function blankNonNewline4(
|
|
14672
|
-
return
|
|
14821
|
+
function blankNonNewline4(text17) {
|
|
14822
|
+
return text17.replace(/[^\n]/g, " ");
|
|
14673
14823
|
}
|
|
14674
|
-
function extractYamlComments(
|
|
14675
|
-
const work =
|
|
14824
|
+
function extractYamlComments(text17) {
|
|
14825
|
+
const work = text17.replace(
|
|
14676
14826
|
/"(?:[^"\\]|\\.)*"|'(?:[^']|'')*'/g,
|
|
14677
14827
|
blankNonNewline4
|
|
14678
14828
|
);
|
|
@@ -14688,8 +14838,8 @@ function isHeaderLine2(line) {
|
|
|
14688
14838
|
const trimmed = line.trim();
|
|
14689
14839
|
return trimmed === "" || trimmed.startsWith("#");
|
|
14690
14840
|
}
|
|
14691
|
-
function extractShellComments(
|
|
14692
|
-
const lines =
|
|
14841
|
+
function extractShellComments(text17) {
|
|
14842
|
+
const lines = text17.split("\n");
|
|
14693
14843
|
let firstCodeLine = 0;
|
|
14694
14844
|
while (firstCodeLine < lines.length && isHeaderLine2(lines[firstCodeLine])) {
|
|
14695
14845
|
firstCodeLine++;
|
|
@@ -15059,9 +15209,9 @@ function registerGithub(program2) {
|
|
|
15059
15209
|
}
|
|
15060
15210
|
|
|
15061
15211
|
// src/commands/handover/countPendingHandovers.ts
|
|
15062
|
-
import { and as and18, eq as eq36, isNull, sql as
|
|
15212
|
+
import { and as and18, eq as eq36, isNull, sql as sql16 } from "drizzle-orm";
|
|
15063
15213
|
async function countPendingHandovers(orm, origin) {
|
|
15064
|
-
const [row] = await orm.select({ count:
|
|
15214
|
+
const [row] = await orm.select({ count: sql16`count(*)::int` }).from(handovers).where(and18(eq36(handovers.origin, origin), isNull(handovers.recalledAt)));
|
|
15065
15215
|
return row?.count ?? 0;
|
|
15066
15216
|
}
|
|
15067
15217
|
|
|
@@ -15284,9 +15434,9 @@ import chalk143 from "chalk";
|
|
|
15284
15434
|
|
|
15285
15435
|
// src/commands/jira/adfToText.ts
|
|
15286
15436
|
function renderInline(node) {
|
|
15287
|
-
const
|
|
15288
|
-
if (node.marks?.some((m) => m.type === "code")) return `\`${
|
|
15289
|
-
return
|
|
15437
|
+
const text17 = node.text ?? "";
|
|
15438
|
+
if (node.marks?.some((m) => m.type === "code")) return `\`${text17}\``;
|
|
15439
|
+
return text17;
|
|
15290
15440
|
}
|
|
15291
15441
|
function renderChildren(node, indent2) {
|
|
15292
15442
|
return renderNodes(node.content ?? [], indent2);
|
|
@@ -15328,8 +15478,8 @@ function isListNode(node) {
|
|
|
15328
15478
|
function renderListChild(child, indent2, pad, marker, isFirst) {
|
|
15329
15479
|
if (isListNode(child)) return renderNodes([child], indent2 + 1);
|
|
15330
15480
|
if (child.type !== "paragraph") return renderNode(child, indent2);
|
|
15331
|
-
const
|
|
15332
|
-
return isFirst ? `${pad}${marker} ${
|
|
15481
|
+
const text17 = renderChildren(child, indent2);
|
|
15482
|
+
return isFirst ? `${pad}${marker} ${text17}` : `${pad} ${text17}`;
|
|
15333
15483
|
}
|
|
15334
15484
|
function renderListItem(node, indent2, marker) {
|
|
15335
15485
|
const pad = " ".repeat(indent2);
|
|
@@ -15521,9 +15671,9 @@ function registerDescriptionLaunch(program2, name, slashCommand, description, al
|
|
|
15521
15671
|
"[description]",
|
|
15522
15672
|
`Text to forward to the /${slashCommand} slash command`
|
|
15523
15673
|
).description(description).option("--once", "Exit when the initial task completes").option("--resume-session <id>", RESUME_SESSION_FLAG).action(
|
|
15524
|
-
(
|
|
15674
|
+
(text17, opts) => launchMode(slashCommand, {
|
|
15525
15675
|
once: opts.once,
|
|
15526
|
-
description:
|
|
15676
|
+
description: text17,
|
|
15527
15677
|
resumeSessionId: opts.resumeSession
|
|
15528
15678
|
})
|
|
15529
15679
|
);
|
|
@@ -16020,8 +16170,8 @@ function dedupeLinks(links2) {
|
|
|
16020
16170
|
}
|
|
16021
16171
|
|
|
16022
16172
|
// src/commands/netcap/linkifyMentions.ts
|
|
16023
|
-
function linkifyMentions(
|
|
16024
|
-
let out =
|
|
16173
|
+
function linkifyMentions(text17, mentions) {
|
|
16174
|
+
let out = text17;
|
|
16025
16175
|
for (const m of mentions) {
|
|
16026
16176
|
if (m.name && out.includes(m.name)) {
|
|
16027
16177
|
out = out.replace(m.name, `[${m.name}](${m.url})`);
|
|
@@ -16048,13 +16198,13 @@ function resolveAuthor(mentionMap, author) {
|
|
|
16048
16198
|
return mentionMap.get(author) ?? { slug: author, url: profileUrl(author) };
|
|
16049
16199
|
}
|
|
16050
16200
|
function buildPost(raw, mentionMap, author) {
|
|
16051
|
-
const
|
|
16052
|
-
if (!
|
|
16201
|
+
const text17 = joinText(raw.text);
|
|
16202
|
+
if (!text17) return void 0;
|
|
16053
16203
|
const mentions = resolveMentions(raw, mentionMap, author);
|
|
16054
16204
|
const relatedPosts = [...new Set(raw.related)];
|
|
16055
16205
|
return {
|
|
16056
|
-
text:
|
|
16057
|
-
markdown: linkifyMentions(
|
|
16206
|
+
text: text17,
|
|
16207
|
+
markdown: linkifyMentions(text17, mentions),
|
|
16058
16208
|
mentions,
|
|
16059
16209
|
hashtags: [...new Set(raw.hashtags)],
|
|
16060
16210
|
links: dedupeLinks(raw.links),
|
|
@@ -16195,8 +16345,8 @@ function activityUrnOf(update3) {
|
|
|
16195
16345
|
return typeof urn === "string" ? urn : void 0;
|
|
16196
16346
|
}
|
|
16197
16347
|
function buildVoyagerPost(update3, profiles) {
|
|
16198
|
-
const
|
|
16199
|
-
if (!
|
|
16348
|
+
const text17 = commentaryText(update3);
|
|
16349
|
+
if (!text17) return void 0;
|
|
16200
16350
|
const author = resolveVoyagerAuthor(update3);
|
|
16201
16351
|
const { mentions, hashtags, links: links2 } = collectVoyagerAttributes(
|
|
16202
16352
|
update3,
|
|
@@ -16205,8 +16355,8 @@ function buildVoyagerPost(update3, profiles) {
|
|
|
16205
16355
|
);
|
|
16206
16356
|
const activityUrn = activityUrnOf(update3);
|
|
16207
16357
|
return {
|
|
16208
|
-
text:
|
|
16209
|
-
markdown: linkifyMentions(
|
|
16358
|
+
text: text17,
|
|
16359
|
+
markdown: linkifyMentions(text17, mentions),
|
|
16210
16360
|
mentions,
|
|
16211
16361
|
hashtags,
|
|
16212
16362
|
links: links2,
|
|
@@ -16747,8 +16897,8 @@ function isWallOfText(lines) {
|
|
|
16747
16897
|
if (lines.some(isListLine)) {
|
|
16748
16898
|
return false;
|
|
16749
16899
|
}
|
|
16750
|
-
const
|
|
16751
|
-
return
|
|
16900
|
+
const text17 = lines.join(" ").trim();
|
|
16901
|
+
return text17.length > MAX_PARAGRAPH_CHARS || countSentences(text17) > MAX_PARAGRAPH_SENTENCES;
|
|
16752
16902
|
}
|
|
16753
16903
|
function validatePrContent(title, body) {
|
|
16754
16904
|
if (title.toLowerCase().includes("claude")) {
|
|
@@ -18520,9 +18670,9 @@ function resolveImports(target, dependencies, sourceFile, statements = []) {
|
|
|
18520
18670
|
function extractTexts(target, allFunctions, statements) {
|
|
18521
18671
|
const stmtTexts = statements.map((v) => v.getFullText().trim());
|
|
18522
18672
|
const fnTexts = allFunctions.map((fn) => {
|
|
18523
|
-
const
|
|
18524
|
-
if (fn === target && !
|
|
18525
|
-
return
|
|
18673
|
+
const text17 = fn.getFullText().trim();
|
|
18674
|
+
if (fn === target && !text17.startsWith("export ")) return `export ${text17}`;
|
|
18675
|
+
return text17;
|
|
18526
18676
|
});
|
|
18527
18677
|
return [...stmtTexts, ...fnTexts];
|
|
18528
18678
|
}
|
|
@@ -20373,9 +20523,9 @@ var MultiSpinner = class {
|
|
|
20373
20523
|
elapsedPrefix: prefix2
|
|
20374
20524
|
});
|
|
20375
20525
|
}
|
|
20376
|
-
failRemaining(
|
|
20526
|
+
failRemaining(text17) {
|
|
20377
20527
|
for (const entry of this.entries) {
|
|
20378
|
-
if (entry.state === "running") this.resolve(entry, "failed",
|
|
20528
|
+
if (entry.state === "running") this.resolve(entry, "failed", text17);
|
|
20379
20529
|
}
|
|
20380
20530
|
}
|
|
20381
20531
|
add(entry) {
|
|
@@ -20388,14 +20538,14 @@ var MultiSpinner = class {
|
|
|
20388
20538
|
set text(value) {
|
|
20389
20539
|
entry.text = value;
|
|
20390
20540
|
},
|
|
20391
|
-
succeed: (
|
|
20392
|
-
fail: (
|
|
20541
|
+
succeed: (text17) => this.resolve(entry, "succeeded", text17),
|
|
20542
|
+
fail: (text17) => this.resolve(entry, "failed", text17)
|
|
20393
20543
|
};
|
|
20394
20544
|
}
|
|
20395
|
-
resolve(entry, state,
|
|
20545
|
+
resolve(entry, state, text17) {
|
|
20396
20546
|
if (entry.state !== "running") return;
|
|
20397
20547
|
entry.state = state;
|
|
20398
|
-
if (
|
|
20548
|
+
if (text17 !== void 0) entry.text = text17;
|
|
20399
20549
|
entry.elapsedStart = void 0;
|
|
20400
20550
|
this.render();
|
|
20401
20551
|
this.maybeFinish();
|
|
@@ -20470,12 +20620,12 @@ function skippedCodexResult(outputPath) {
|
|
|
20470
20620
|
// src/commands/review/formatReviewerFailure.ts
|
|
20471
20621
|
var FAST_FAIL_MS = 1e3;
|
|
20472
20622
|
var STDOUT_TAIL_LINES = 20;
|
|
20473
|
-
function indent(
|
|
20474
|
-
return
|
|
20623
|
+
function indent(text17) {
|
|
20624
|
+
return text17.split(/\r?\n/).map((line) => ` ${line}`);
|
|
20475
20625
|
}
|
|
20476
|
-
function tailLines(
|
|
20477
|
-
const lines =
|
|
20478
|
-
return lines.length <= maxLines ?
|
|
20626
|
+
function tailLines(text17, maxLines) {
|
|
20627
|
+
const lines = text17.split(/\r?\n/);
|
|
20628
|
+
return lines.length <= maxLines ? text17 : lines.slice(-maxLines).join("\n");
|
|
20479
20629
|
}
|
|
20480
20630
|
function isFastFail(input) {
|
|
20481
20631
|
return input.exitCode !== 0 && input.elapsedMs !== void 0 && input.elapsedMs < FAST_FAIL_MS;
|
|
@@ -21410,8 +21560,8 @@ function filterToSql(filter) {
|
|
|
21410
21560
|
// src/commands/seq/fetchSeqData.ts
|
|
21411
21561
|
function buildDataParams(filter, count7, from, to) {
|
|
21412
21562
|
const sqlFilter = filterToSql(filter);
|
|
21413
|
-
const
|
|
21414
|
-
const params = new URLSearchParams({ q:
|
|
21563
|
+
const sql23 = `select @Timestamp, @Level, @Exception, @Message from stream where ${sqlFilter} order by @Timestamp desc limit ${count7}`;
|
|
21564
|
+
const params = new URLSearchParams({ q: sql23 });
|
|
21415
21565
|
if (from) params.set("rangeStartUtc", from);
|
|
21416
21566
|
if (to) params.set("rangeEndUtc", to);
|
|
21417
21567
|
return params;
|
|
@@ -21672,26 +21822,26 @@ import chalk190 from "chalk";
|
|
|
21672
21822
|
// src/commands/sql/loadConnections.ts
|
|
21673
21823
|
function loadConnections3() {
|
|
21674
21824
|
const raw = loadGlobalConfigRaw();
|
|
21675
|
-
const
|
|
21676
|
-
return
|
|
21825
|
+
const sql23 = raw.sql;
|
|
21826
|
+
return sql23?.connections ?? [];
|
|
21677
21827
|
}
|
|
21678
21828
|
function saveConnections3(connections) {
|
|
21679
21829
|
const raw = loadGlobalConfigRaw();
|
|
21680
|
-
const
|
|
21681
|
-
|
|
21682
|
-
raw.sql =
|
|
21830
|
+
const sql23 = raw.sql ?? {};
|
|
21831
|
+
sql23.connections = connections;
|
|
21832
|
+
raw.sql = sql23;
|
|
21683
21833
|
saveGlobalConfig(raw);
|
|
21684
21834
|
}
|
|
21685
21835
|
function getDefaultConnection2() {
|
|
21686
21836
|
const raw = loadGlobalConfigRaw();
|
|
21687
|
-
const
|
|
21688
|
-
return
|
|
21837
|
+
const sql23 = raw.sql;
|
|
21838
|
+
return sql23?.defaultConnection;
|
|
21689
21839
|
}
|
|
21690
21840
|
function setDefaultConnection2(name) {
|
|
21691
21841
|
const raw = loadGlobalConfigRaw();
|
|
21692
|
-
const
|
|
21693
|
-
|
|
21694
|
-
raw.sql =
|
|
21842
|
+
const sql23 = raw.sql ?? {};
|
|
21843
|
+
sql23.defaultConnection = name;
|
|
21844
|
+
raw.sql = sql23;
|
|
21695
21845
|
saveGlobalConfig(raw);
|
|
21696
21846
|
}
|
|
21697
21847
|
|
|
@@ -21762,9 +21912,9 @@ function resolveConnection3(name) {
|
|
|
21762
21912
|
}
|
|
21763
21913
|
|
|
21764
21914
|
// src/commands/sql/sqlConnect.ts
|
|
21765
|
-
import
|
|
21915
|
+
import sql17 from "mssql";
|
|
21766
21916
|
async function sqlConnect(conn) {
|
|
21767
|
-
return await
|
|
21917
|
+
return await sql17.connect({
|
|
21768
21918
|
server: conn.server,
|
|
21769
21919
|
port: conn.port,
|
|
21770
21920
|
user: conn.user,
|
|
@@ -21841,11 +21991,11 @@ var MUTATION_PATTERN = new RegExp(
|
|
|
21841
21991
|
`\\b(${MUTATION_KEYWORDS.join("|")})\\b`,
|
|
21842
21992
|
"i"
|
|
21843
21993
|
);
|
|
21844
|
-
function stripComments(
|
|
21845
|
-
return
|
|
21994
|
+
function stripComments(sql23) {
|
|
21995
|
+
return sql23.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\n]*/g, " ");
|
|
21846
21996
|
}
|
|
21847
|
-
function isMutation(
|
|
21848
|
-
const stripped = stripComments(
|
|
21997
|
+
function isMutation(sql23) {
|
|
21998
|
+
const stripped = stripComments(sql23);
|
|
21849
21999
|
if (MUTATION_PATTERN.test(stripped)) return true;
|
|
21850
22000
|
return /\bSELECT\b[\s\S]+\bINTO\s+\w/i.test(stripped);
|
|
21851
22001
|
}
|
|
@@ -22044,8 +22194,8 @@ import {
|
|
|
22044
22194
|
import { basename as basename13, join as join54 } from "path";
|
|
22045
22195
|
|
|
22046
22196
|
// src/commands/transcript/cleanText.ts
|
|
22047
|
-
function cleanText(
|
|
22048
|
-
const words =
|
|
22197
|
+
function cleanText(text17) {
|
|
22198
|
+
const words = text17.split(/\s+/);
|
|
22049
22199
|
const cleaned = [];
|
|
22050
22200
|
for (let i = 0; i < words.length; i++) {
|
|
22051
22201
|
let isRepeat = false;
|
|
@@ -22065,8 +22215,8 @@ function cleanText(text16) {
|
|
|
22065
22215
|
}
|
|
22066
22216
|
|
|
22067
22217
|
// src/commands/transcript/convert/parseVtt/deduplicateCues/removeSubstringDuplicates.ts
|
|
22068
|
-
function normalizeText(
|
|
22069
|
-
return
|
|
22218
|
+
function normalizeText(text17) {
|
|
22219
|
+
return text17.toLowerCase().trim();
|
|
22070
22220
|
}
|
|
22071
22221
|
function checkSubstringRelation(textI, textJ) {
|
|
22072
22222
|
if (textI.includes(textJ) && textI.length > textJ.length)
|
|
@@ -22195,13 +22345,13 @@ function parseTimestampLine(line) {
|
|
|
22195
22345
|
return { startMs: parseTimestamp(startStr), endMs: parseTimestamp(endStr) };
|
|
22196
22346
|
}
|
|
22197
22347
|
function buildCue(startMs, endMs, fullText) {
|
|
22198
|
-
const { speaker, text:
|
|
22199
|
-
return
|
|
22348
|
+
const { speaker, text: text17 } = extractSpeaker(fullText);
|
|
22349
|
+
return text17 ? { startMs, endMs, speaker, text: text17 } : null;
|
|
22200
22350
|
}
|
|
22201
22351
|
function parseCueLine(lines, i) {
|
|
22202
22352
|
const { startMs, endMs } = parseTimestampLine(lines[i]);
|
|
22203
|
-
const { text:
|
|
22204
|
-
return { cue: buildCue(startMs, endMs,
|
|
22353
|
+
const { text: text17, nextIndex: nextIndex2 } = collectTextLines(lines, i + 1);
|
|
22354
|
+
return { cue: buildCue(startMs, endMs, text17), nextIndex: nextIndex2 };
|
|
22205
22355
|
}
|
|
22206
22356
|
function isCueSeparator(line) {
|
|
22207
22357
|
return line.trim().includes("-->");
|
|
@@ -22789,8 +22939,8 @@ async function exchangeToken(params) {
|
|
|
22789
22939
|
body: body.toString()
|
|
22790
22940
|
});
|
|
22791
22941
|
if (!response.ok) {
|
|
22792
|
-
const
|
|
22793
|
-
throw new Error(`Token exchange failed (${response.status}): ${
|
|
22942
|
+
const text17 = await response.text();
|
|
22943
|
+
throw new Error(`Token exchange failed (${response.status}): ${text17}`);
|
|
22794
22944
|
}
|
|
22795
22945
|
return response.json();
|
|
22796
22946
|
}
|
|
@@ -23533,8 +23683,8 @@ function buildOutputPath(outputDir, processName) {
|
|
|
23533
23683
|
if (!existsSync52(outputDir)) {
|
|
23534
23684
|
mkdirSync23(outputDir, { recursive: true });
|
|
23535
23685
|
}
|
|
23536
|
-
const
|
|
23537
|
-
return resolve15(outputDir, `${processName}-${
|
|
23686
|
+
const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
23687
|
+
return resolve15(outputDir, `${processName}-${timestamp6}.png`);
|
|
23538
23688
|
}
|
|
23539
23689
|
function runPowerShellScript(processName, outputPath) {
|
|
23540
23690
|
const scriptPath = join64(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
|
|
@@ -24196,13 +24346,13 @@ function drainSessions(sessions, onDrained) {
|
|
|
24196
24346
|
}
|
|
24197
24347
|
|
|
24198
24348
|
// src/shared/db/recordPhaseActiveMs.ts
|
|
24199
|
-
import { sql as
|
|
24349
|
+
import { sql as sql18 } from "drizzle-orm";
|
|
24200
24350
|
async function recordPhaseActiveMs(db, itemId2, phaseIdx, activeMs) {
|
|
24201
24351
|
if (activeMs <= 0) return;
|
|
24202
24352
|
await db.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, activeMs }).onConflictDoUpdate({
|
|
24203
24353
|
target: [phaseUsage.itemId, phaseUsage.phaseIdx],
|
|
24204
24354
|
set: {
|
|
24205
|
-
activeMs:
|
|
24355
|
+
activeMs: sql18`${phaseUsage.activeMs} + excluded.active_ms`
|
|
24206
24356
|
}
|
|
24207
24357
|
});
|
|
24208
24358
|
}
|
|
@@ -24394,7 +24544,7 @@ function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
|
|
|
24394
24544
|
}
|
|
24395
24545
|
|
|
24396
24546
|
// src/shared/db/recordPhaseCycleContext.ts
|
|
24397
|
-
import { sql as
|
|
24547
|
+
import { sql as sql19 } from "drizzle-orm";
|
|
24398
24548
|
async function recordPhaseCycleContext(db, itemId2, phaseIdx, window, resetsAt, pct) {
|
|
24399
24549
|
if (pct <= 0) return;
|
|
24400
24550
|
await db.insert(phaseCycleContext).values({ itemId: itemId2, phaseIdx, window, resetsAt, peakContextPct: pct }).onConflictDoUpdate({
|
|
@@ -24405,24 +24555,24 @@ async function recordPhaseCycleContext(db, itemId2, phaseIdx, window, resetsAt,
|
|
|
24405
24555
|
phaseCycleContext.resetsAt
|
|
24406
24556
|
],
|
|
24407
24557
|
set: {
|
|
24408
|
-
peakContextPct:
|
|
24558
|
+
peakContextPct: sql19`GREATEST(${phaseCycleContext.peakContextPct}, ${pct})`
|
|
24409
24559
|
}
|
|
24410
24560
|
});
|
|
24411
24561
|
}
|
|
24412
24562
|
|
|
24413
24563
|
// src/shared/db/recordPhasePeakContext.ts
|
|
24414
|
-
import { sql as
|
|
24564
|
+
import { sql as sql20 } from "drizzle-orm";
|
|
24415
24565
|
async function recordPhasePeakContext(db, itemId2, phaseIdx, pct) {
|
|
24416
24566
|
await db.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, peakContextPct: pct }).onConflictDoUpdate({
|
|
24417
24567
|
target: [phaseUsage.itemId, phaseUsage.phaseIdx],
|
|
24418
24568
|
set: {
|
|
24419
|
-
peakContextPct:
|
|
24569
|
+
peakContextPct: sql20`GREATEST(${phaseUsage.peakContextPct}, ${pct})`
|
|
24420
24570
|
}
|
|
24421
24571
|
});
|
|
24422
24572
|
}
|
|
24423
24573
|
|
|
24424
24574
|
// src/shared/db/recordPhaseTranscriptUsage.ts
|
|
24425
|
-
import { sql as
|
|
24575
|
+
import { sql as sql21 } from "drizzle-orm";
|
|
24426
24576
|
async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
|
|
24427
24577
|
const byId = /* @__PURE__ */ new Map();
|
|
24428
24578
|
for (const r of responses) byId.set(r.messageId, r);
|
|
@@ -24442,8 +24592,8 @@ async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
|
|
|
24442
24592
|
await tx.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, tokensUp, tokensDown }).onConflictDoUpdate({
|
|
24443
24593
|
target: [phaseUsage.itemId, phaseUsage.phaseIdx],
|
|
24444
24594
|
set: {
|
|
24445
|
-
tokensUp:
|
|
24446
|
-
tokensDown:
|
|
24595
|
+
tokensUp: sql21`${phaseUsage.tokensUp} + ${tokensUp}`,
|
|
24596
|
+
tokensDown: sql21`${phaseUsage.tokensDown} + ${tokensDown}`
|
|
24447
24597
|
}
|
|
24448
24598
|
});
|
|
24449
24599
|
return { tokensUp, tokensDown };
|
|
@@ -24451,12 +24601,12 @@ async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
|
|
|
24451
24601
|
}
|
|
24452
24602
|
|
|
24453
24603
|
// src/shared/db/recordWindowTokens.ts
|
|
24454
|
-
import { and as and21, eq as eq39, sql as
|
|
24604
|
+
import { and as and21, eq as eq39, sql as sql22 } from "drizzle-orm";
|
|
24455
24605
|
async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
|
|
24456
24606
|
if (tokensUp <= 0 && tokensDown <= 0) return;
|
|
24457
24607
|
await db.update(usagePeaks).set({
|
|
24458
|
-
tokensUp:
|
|
24459
|
-
tokensDown:
|
|
24608
|
+
tokensUp: sql22`${usagePeaks.tokensUp} + ${tokensUp}`,
|
|
24609
|
+
tokensDown: sql22`${usagePeaks.tokensDown} + ${tokensDown}`
|
|
24460
24610
|
}).where(
|
|
24461
24611
|
and21(
|
|
24462
24612
|
eq39(usagePeaks.window, window),
|
|
@@ -25968,17 +26118,17 @@ function entryMessages(entry) {
|
|
|
25968
26118
|
return [];
|
|
25969
26119
|
}
|
|
25970
26120
|
function userMessages(content) {
|
|
25971
|
-
if (typeof content === "string") return
|
|
26121
|
+
if (typeof content === "string") return text16("user", cleanUserText(content));
|
|
25972
26122
|
if (!Array.isArray(content)) return [];
|
|
25973
|
-
return content.filter((c) => c.type === "text").flatMap((c) =>
|
|
26123
|
+
return content.filter((c) => c.type === "text").flatMap((c) => text16("user", cleanUserText(c.text ?? "")));
|
|
25974
26124
|
}
|
|
25975
26125
|
function assistantMessages(content) {
|
|
25976
|
-
if (typeof content === "string") return
|
|
26126
|
+
if (typeof content === "string") return text16("assistant", content.trim());
|
|
25977
26127
|
if (!Array.isArray(content)) return [];
|
|
25978
26128
|
return content.flatMap((c) => assistantItem(c));
|
|
25979
26129
|
}
|
|
25980
26130
|
function assistantItem(c) {
|
|
25981
|
-
if (c.type === "text") return
|
|
26131
|
+
if (c.type === "text") return text16("assistant", (c.text ?? "").trim());
|
|
25982
26132
|
if (c.type === "tool_use")
|
|
25983
26133
|
return [
|
|
25984
26134
|
{
|
|
@@ -25989,7 +26139,7 @@ function assistantItem(c) {
|
|
|
25989
26139
|
];
|
|
25990
26140
|
return [];
|
|
25991
26141
|
}
|
|
25992
|
-
function
|
|
26142
|
+
function text16(role, value) {
|
|
25993
26143
|
return value ? [{ role, text: value }] : [];
|
|
25994
26144
|
}
|
|
25995
26145
|
function cleanUserText(value) {
|
|
@@ -26363,16 +26513,16 @@ function parseUserLine(line) {
|
|
|
26363
26513
|
if (entry.type !== "user") return void 0;
|
|
26364
26514
|
const msg = entry.message;
|
|
26365
26515
|
const c = msg?.content;
|
|
26366
|
-
let
|
|
26516
|
+
let text17;
|
|
26367
26517
|
if (typeof c === "string") {
|
|
26368
|
-
|
|
26518
|
+
text17 = c;
|
|
26369
26519
|
} else if (Array.isArray(c)) {
|
|
26370
26520
|
const collected = c.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n");
|
|
26371
|
-
|
|
26521
|
+
text17 = collected || void 0;
|
|
26372
26522
|
}
|
|
26373
|
-
if (!
|
|
26523
|
+
if (!text17) return void 0;
|
|
26374
26524
|
return {
|
|
26375
|
-
text:
|
|
26525
|
+
text: text17,
|
|
26376
26526
|
entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
|
|
26377
26527
|
};
|
|
26378
26528
|
}
|
|
@@ -26401,13 +26551,13 @@ function* iterateUserMessages(filePath, maxBytes = 65536) {
|
|
|
26401
26551
|
|
|
26402
26552
|
// src/commands/sessions/summarise/extractFirstUserMessage.ts
|
|
26403
26553
|
function extractFirstUserMessage(filePath) {
|
|
26404
|
-
for (const
|
|
26405
|
-
return truncate3(
|
|
26554
|
+
for (const text17 of iterateUserMessages(filePath)) {
|
|
26555
|
+
return truncate3(text17);
|
|
26406
26556
|
}
|
|
26407
26557
|
return void 0;
|
|
26408
26558
|
}
|
|
26409
|
-
function truncate3(
|
|
26410
|
-
const trimmed =
|
|
26559
|
+
function truncate3(text17, maxChars = 500) {
|
|
26560
|
+
const trimmed = text17.trim();
|
|
26411
26561
|
if (trimmed.length <= maxChars) return trimmed;
|
|
26412
26562
|
return `${trimmed.slice(0, maxChars)}\u2026`;
|
|
26413
26563
|
}
|
|
@@ -26415,28 +26565,28 @@ function truncate3(text16, maxChars = 500) {
|
|
|
26415
26565
|
// src/commands/sessions/summarise/scanSessionBacklogRefs.ts
|
|
26416
26566
|
function scanSessionBacklogRefs(filePath) {
|
|
26417
26567
|
const ids = /* @__PURE__ */ new Set();
|
|
26418
|
-
for (const
|
|
26419
|
-
for (const id of extractBacklogIds(
|
|
26568
|
+
for (const text17 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
|
|
26569
|
+
for (const id of extractBacklogIds(text17)) {
|
|
26420
26570
|
ids.add(id);
|
|
26421
26571
|
}
|
|
26422
26572
|
}
|
|
26423
26573
|
return [...ids].sort((a, b) => a - b);
|
|
26424
26574
|
}
|
|
26425
|
-
function extractBacklogIds(
|
|
26575
|
+
function extractBacklogIds(text17) {
|
|
26426
26576
|
const ids = [];
|
|
26427
|
-
for (const m of
|
|
26577
|
+
for (const m of text17.matchAll(/backlog\s+run\s+a(\d+)/gi)) {
|
|
26428
26578
|
ids.push(Number.parseInt(m[1], 10));
|
|
26429
26579
|
}
|
|
26430
|
-
for (const m of
|
|
26580
|
+
for (const m of text17.matchAll(/backlog\s+(?:item\s+)?a(\d+)/gi)) {
|
|
26431
26581
|
ids.push(Number.parseInt(m[1], 10));
|
|
26432
26582
|
}
|
|
26433
|
-
for (const m of
|
|
26583
|
+
for (const m of text17.matchAll(/backlog\s+phase-done\s+a(\d+)/gi)) {
|
|
26434
26584
|
ids.push(Number.parseInt(m[1], 10));
|
|
26435
26585
|
}
|
|
26436
|
-
for (const m of
|
|
26586
|
+
for (const m of text17.matchAll(/backlog\s+comment\s+a(\d+)/gi)) {
|
|
26437
26587
|
ids.push(Number.parseInt(m[1], 10));
|
|
26438
26588
|
}
|
|
26439
|
-
for (const m of
|
|
26589
|
+
for (const m of text17.matchAll(/(?:^|[\s(])a(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
|
|
26440
26590
|
ids.push(Number.parseInt(m[1], 10));
|
|
26441
26591
|
}
|
|
26442
26592
|
return ids;
|
|
@@ -26737,7 +26887,7 @@ async function statusLine() {
|
|
|
26737
26887
|
|
|
26738
26888
|
// src/commands/sync.ts
|
|
26739
26889
|
import * as fs45 from "fs";
|
|
26740
|
-
import * as
|
|
26890
|
+
import * as os4 from "os";
|
|
26741
26891
|
import * as path65 from "path";
|
|
26742
26892
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
26743
26893
|
|
|
@@ -26999,7 +27149,7 @@ async function sync(options2) {
|
|
|
26999
27149
|
const config = loadConfig();
|
|
27000
27150
|
const yes = options2?.yes ?? config.sync.autoConfirm;
|
|
27001
27151
|
const claudeDir = path65.join(__dirname7, "..", "claude");
|
|
27002
|
-
const targetBase = path65.join(
|
|
27152
|
+
const targetBase = path65.join(os4.homedir(), ".claude");
|
|
27003
27153
|
syncCommands(claudeDir, targetBase);
|
|
27004
27154
|
syncDesign(claudeDir, targetBase);
|
|
27005
27155
|
await syncSettings(claudeDir, targetBase, { yes });
|