@staff0rd/assist 0.299.1 → 0.301.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/README.md +1 -0
- package/claude/commands/strip-comments.md +53 -0
- package/claude/settings.json +3 -0
- package/dist/commands/sessions/web/bundle.js +72 -71
- package/dist/index.js +224 -148
- 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.301.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -1074,8 +1074,8 @@ var options = [
|
|
|
1074
1074
|
];
|
|
1075
1075
|
|
|
1076
1076
|
// src/commands/verify/init/getAvailableOptions/index.ts
|
|
1077
|
-
function resolveDescription(
|
|
1078
|
-
return typeof
|
|
1077
|
+
function resolveDescription(desc5, setup2) {
|
|
1078
|
+
return typeof desc5 === "function" ? desc5(setup2) : desc5;
|
|
1079
1079
|
}
|
|
1080
1080
|
function toVerifyOption(def, setup2) {
|
|
1081
1081
|
return {
|
|
@@ -1665,8 +1665,8 @@ var MACHINE_DIRECTIVES = [
|
|
|
1665
1665
|
"v8 ignore",
|
|
1666
1666
|
"c8 ignore"
|
|
1667
1667
|
];
|
|
1668
|
-
function isCommentExempt(
|
|
1669
|
-
const lower =
|
|
1668
|
+
function isCommentExempt(text5, markers) {
|
|
1669
|
+
const lower = text5.toLowerCase();
|
|
1670
1670
|
if (MACHINE_DIRECTIVES.some((d) => lower.includes(d))) return true;
|
|
1671
1671
|
return markers.some((m) => lower.includes(m.toLowerCase()));
|
|
1672
1672
|
}
|
|
@@ -1709,8 +1709,8 @@ function parseDiffAddedLines(diff2) {
|
|
|
1709
1709
|
|
|
1710
1710
|
// src/commands/verify/commentPolicy/findAddedComments.ts
|
|
1711
1711
|
var SOURCE_EXTENSIONS = [".ts", ".tsx", ".cts", ".mts", ".js", ".jsx"];
|
|
1712
|
-
function toSingleLine(
|
|
1713
|
-
return
|
|
1712
|
+
function toSingleLine(text5) {
|
|
1713
|
+
return text5.replace(/\s+/g, " ").trim();
|
|
1714
1714
|
}
|
|
1715
1715
|
function shouldScan(file, ignoreGlobs) {
|
|
1716
1716
|
if (!SOURCE_EXTENSIONS.some((ext) => file.endsWith(ext))) return false;
|
|
@@ -1731,11 +1731,11 @@ function findAddedComments(options2) {
|
|
|
1731
1731
|
for (const [file, lines] of addedLines) {
|
|
1732
1732
|
if (!shouldScan(file, options2.ignoreGlobs)) continue;
|
|
1733
1733
|
const sourceFile = project.addSourceFileAtPath(file);
|
|
1734
|
-
for (const { pos, text:
|
|
1734
|
+
for (const { pos, text: text5 } of collectComments(sourceFile)) {
|
|
1735
1735
|
const { line } = sourceFile.getLineAndColumnAtPos(pos);
|
|
1736
1736
|
if (!lines.has(line)) continue;
|
|
1737
|
-
if (isCommentExempt(
|
|
1738
|
-
findings.push({ file, line, text: toSingleLine(
|
|
1737
|
+
if (isCommentExempt(text5, options2.markers)) continue;
|
|
1738
|
+
findings.push({ file, line, text: toSingleLine(text5) });
|
|
1739
1739
|
}
|
|
1740
1740
|
}
|
|
1741
1741
|
findings.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
@@ -1754,8 +1754,8 @@ function commentPolicy() {
|
|
|
1754
1754
|
process.exit(0);
|
|
1755
1755
|
}
|
|
1756
1756
|
console.log("Comments added on changed lines:\n");
|
|
1757
|
-
for (const { file, line, text:
|
|
1758
|
-
console.log(`${file}:${line} \u2192 ${
|
|
1757
|
+
for (const { file, line, text: text5 } of findings) {
|
|
1758
|
+
console.log(`${file}:${line} \u2192 ${text5}`);
|
|
1759
1759
|
}
|
|
1760
1760
|
console.log(`
|
|
1761
1761
|
Total: ${findings.length} comment(s)`);
|
|
@@ -2865,9 +2865,9 @@ import {
|
|
|
2865
2865
|
foreignKey,
|
|
2866
2866
|
index as index2,
|
|
2867
2867
|
integer as integer2,
|
|
2868
|
-
pgTable as
|
|
2869
|
-
primaryKey,
|
|
2870
|
-
text as
|
|
2868
|
+
pgTable as pgTable3,
|
|
2869
|
+
primaryKey as primaryKey2,
|
|
2870
|
+
text as text3
|
|
2871
2871
|
} from "drizzle-orm/pg-core";
|
|
2872
2872
|
|
|
2873
2873
|
// src/shared/db/handovers.ts
|
|
@@ -2885,73 +2885,91 @@ var handovers = pgTable(
|
|
|
2885
2885
|
(t) => [index("handovers_origin_idx").on(t.origin)]
|
|
2886
2886
|
);
|
|
2887
2887
|
|
|
2888
|
+
// src/shared/db/usagePeaks.ts
|
|
2889
|
+
import {
|
|
2890
|
+
bigint,
|
|
2891
|
+
doublePrecision,
|
|
2892
|
+
pgTable as pgTable2,
|
|
2893
|
+
primaryKey,
|
|
2894
|
+
text as text2
|
|
2895
|
+
} from "drizzle-orm/pg-core";
|
|
2896
|
+
var usagePeaks = pgTable2(
|
|
2897
|
+
"usage_peaks",
|
|
2898
|
+
{
|
|
2899
|
+
window: text2().$type().notNull(),
|
|
2900
|
+
resetsAt: bigint("resets_at", { mode: "number" }).notNull(),
|
|
2901
|
+
usedPercentage: doublePrecision("used_percentage").notNull()
|
|
2902
|
+
},
|
|
2903
|
+
(t) => [primaryKey({ columns: [t.window, t.resetsAt] })]
|
|
2904
|
+
);
|
|
2905
|
+
|
|
2888
2906
|
// src/shared/db/schema.ts
|
|
2889
|
-
var items =
|
|
2907
|
+
var items = pgTable3(
|
|
2890
2908
|
"items",
|
|
2891
2909
|
{
|
|
2892
2910
|
id: integer2().generatedByDefaultAsIdentity().primaryKey(),
|
|
2893
|
-
origin:
|
|
2894
|
-
type:
|
|
2895
|
-
name:
|
|
2896
|
-
description:
|
|
2897
|
-
acceptanceCriteria:
|
|
2898
|
-
status:
|
|
2911
|
+
origin: text3().notNull(),
|
|
2912
|
+
type: text3().notNull().default("story"),
|
|
2913
|
+
name: text3().notNull(),
|
|
2914
|
+
description: text3(),
|
|
2915
|
+
acceptanceCriteria: text3("acceptance_criteria").notNull().default("[]"),
|
|
2916
|
+
status: text3().notNull().default("todo"),
|
|
2899
2917
|
currentPhase: integer2("current_phase"),
|
|
2900
2918
|
starred: boolean().notNull().default(false)
|
|
2901
2919
|
},
|
|
2902
2920
|
(t) => [index2("items_origin_idx").on(t.origin)]
|
|
2903
2921
|
);
|
|
2904
|
-
var comments =
|
|
2922
|
+
var comments = pgTable3("comments", {
|
|
2905
2923
|
id: integer2().generatedByDefaultAsIdentity().primaryKey(),
|
|
2906
2924
|
itemId: integer2("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
|
|
2907
2925
|
idx: integer2().notNull(),
|
|
2908
|
-
text:
|
|
2926
|
+
text: text3().notNull(),
|
|
2909
2927
|
phase: integer2(),
|
|
2910
|
-
timestamp:
|
|
2911
|
-
type:
|
|
2928
|
+
timestamp: text3().notNull(),
|
|
2929
|
+
type: text3().notNull().default("comment")
|
|
2912
2930
|
});
|
|
2913
|
-
var links =
|
|
2931
|
+
var links = pgTable3(
|
|
2914
2932
|
"links",
|
|
2915
2933
|
{
|
|
2916
2934
|
itemId: integer2("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
|
|
2917
|
-
type:
|
|
2935
|
+
type: text3().notNull(),
|
|
2918
2936
|
targetId: integer2("target_id").notNull()
|
|
2919
2937
|
},
|
|
2920
|
-
(t) => [
|
|
2938
|
+
(t) => [primaryKey2({ columns: [t.itemId, t.type, t.targetId] })]
|
|
2921
2939
|
);
|
|
2922
|
-
var planPhases =
|
|
2940
|
+
var planPhases = pgTable3(
|
|
2923
2941
|
"plan_phases",
|
|
2924
2942
|
{
|
|
2925
2943
|
itemId: integer2("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
|
|
2926
2944
|
idx: integer2().notNull(),
|
|
2927
|
-
name:
|
|
2928
|
-
manualChecks:
|
|
2945
|
+
name: text3().notNull(),
|
|
2946
|
+
manualChecks: text3("manual_checks")
|
|
2929
2947
|
},
|
|
2930
|
-
(t) => [
|
|
2948
|
+
(t) => [primaryKey2({ columns: [t.itemId, t.idx] })]
|
|
2931
2949
|
);
|
|
2932
|
-
var planTasks =
|
|
2950
|
+
var planTasks = pgTable3(
|
|
2933
2951
|
"plan_tasks",
|
|
2934
2952
|
{
|
|
2935
2953
|
itemId: integer2("item_id").notNull(),
|
|
2936
2954
|
phaseIdx: integer2("phase_idx").notNull(),
|
|
2937
2955
|
idx: integer2().notNull(),
|
|
2938
|
-
task:
|
|
2956
|
+
task: text3().notNull()
|
|
2939
2957
|
},
|
|
2940
2958
|
(t) => [
|
|
2941
|
-
|
|
2959
|
+
primaryKey2({ columns: [t.itemId, t.phaseIdx, t.idx] }),
|
|
2942
2960
|
foreignKey({
|
|
2943
2961
|
columns: [t.itemId, t.phaseIdx],
|
|
2944
2962
|
foreignColumns: [planPhases.itemId, planPhases.idx]
|
|
2945
2963
|
}).onDelete("cascade")
|
|
2946
2964
|
]
|
|
2947
2965
|
);
|
|
2948
|
-
var metadata =
|
|
2949
|
-
key:
|
|
2950
|
-
value:
|
|
2966
|
+
var metadata = pgTable3("metadata", {
|
|
2967
|
+
key: text3().primaryKey(),
|
|
2968
|
+
value: text3().notNull()
|
|
2951
2969
|
});
|
|
2952
|
-
var feeds =
|
|
2970
|
+
var feeds = pgTable3("feeds", {
|
|
2953
2971
|
id: integer2().generatedByDefaultAsIdentity().primaryKey(),
|
|
2954
|
-
url:
|
|
2972
|
+
url: text3().notNull().unique()
|
|
2955
2973
|
});
|
|
2956
2974
|
var schema = {
|
|
2957
2975
|
items,
|
|
@@ -2961,7 +2979,8 @@ var schema = {
|
|
|
2961
2979
|
planTasks,
|
|
2962
2980
|
metadata,
|
|
2963
2981
|
feeds,
|
|
2964
|
-
handovers
|
|
2982
|
+
handovers,
|
|
2983
|
+
usagePeaks
|
|
2965
2984
|
};
|
|
2966
2985
|
|
|
2967
2986
|
// src/commands/backlog/itemColumns.ts
|
|
@@ -3402,6 +3421,13 @@ var SCHEMA = `
|
|
|
3402
3421
|
);
|
|
3403
3422
|
|
|
3404
3423
|
CREATE INDEX IF NOT EXISTS handovers_origin_idx ON handovers (origin);
|
|
3424
|
+
|
|
3425
|
+
CREATE TABLE IF NOT EXISTS usage_peaks (
|
|
3426
|
+
"window" TEXT NOT NULL,
|
|
3427
|
+
resets_at BIGINT NOT NULL,
|
|
3428
|
+
used_percentage DOUBLE PRECISION NOT NULL,
|
|
3429
|
+
PRIMARY KEY ("window", resets_at)
|
|
3430
|
+
);
|
|
3405
3431
|
`;
|
|
3406
3432
|
async function ensureSchema(exec3) {
|
|
3407
3433
|
await exec3(SCHEMA);
|
|
@@ -3449,7 +3475,7 @@ function getDb() {
|
|
|
3449
3475
|
);
|
|
3450
3476
|
});
|
|
3451
3477
|
_pool = pool;
|
|
3452
|
-
await ensureSchema((
|
|
3478
|
+
await ensureSchema((sql6) => pool.query(sql6));
|
|
3453
3479
|
_orm = makeOrmFromPool(pool);
|
|
3454
3480
|
await seedNewsFeeds(_orm);
|
|
3455
3481
|
return _orm;
|
|
@@ -4217,11 +4243,11 @@ import chalk37 from "chalk";
|
|
|
4217
4243
|
|
|
4218
4244
|
// src/commands/backlog/appendComment.ts
|
|
4219
4245
|
import { sql as sql2 } from "drizzle-orm";
|
|
4220
|
-
async function appendComment(orm, itemId,
|
|
4246
|
+
async function appendComment(orm, itemId, text5, opts = {}) {
|
|
4221
4247
|
await orm.insert(comments).values({
|
|
4222
4248
|
itemId,
|
|
4223
4249
|
idx: sql2`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId})`,
|
|
4224
|
-
text:
|
|
4250
|
+
text: text5,
|
|
4225
4251
|
phase: opts.phase ?? null,
|
|
4226
4252
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4227
4253
|
type: opts.type ?? "comment"
|
|
@@ -5234,9 +5260,9 @@ function excerpt(xml, ...tags) {
|
|
|
5234
5260
|
for (const tag of tags) {
|
|
5235
5261
|
const raw = extractText(xml, tag);
|
|
5236
5262
|
if (!raw) continue;
|
|
5237
|
-
const
|
|
5238
|
-
if (
|
|
5239
|
-
return `${
|
|
5263
|
+
const text5 = stripHtml(raw);
|
|
5264
|
+
if (text5.length <= MAX_EXCERPT) return text5;
|
|
5265
|
+
return `${text5.slice(0, MAX_EXCERPT)}\u2026`;
|
|
5240
5266
|
}
|
|
5241
5267
|
return "";
|
|
5242
5268
|
}
|
|
@@ -5313,6 +5339,17 @@ async function listNewsItems(_req, res) {
|
|
|
5313
5339
|
respondJson(res, 200, cachedItems);
|
|
5314
5340
|
}
|
|
5315
5341
|
|
|
5342
|
+
// src/shared/db/listUsagePeaks.ts
|
|
5343
|
+
import { desc } from "drizzle-orm";
|
|
5344
|
+
async function listUsagePeaks(db) {
|
|
5345
|
+
return db.select().from(usagePeaks).orderBy(desc(usagePeaks.resetsAt), usagePeaks.window);
|
|
5346
|
+
}
|
|
5347
|
+
|
|
5348
|
+
// src/commands/sessions/web/listUsageHistory.ts
|
|
5349
|
+
async function listUsageHistory(_req, res) {
|
|
5350
|
+
respondJson(res, 200, await listUsagePeaks(await getDb()));
|
|
5351
|
+
}
|
|
5352
|
+
|
|
5316
5353
|
// src/commands/sessions/web/openInCode.ts
|
|
5317
5354
|
import { exec } from "child_process";
|
|
5318
5355
|
import { promisify as promisify2 } from "util";
|
|
@@ -5462,7 +5499,8 @@ var routes2 = {
|
|
|
5462
5499
|
"POST /api/restart": restartWeb,
|
|
5463
5500
|
"GET /api/github-url": githubUrl,
|
|
5464
5501
|
"GET /api/git-status": gitStatus,
|
|
5465
|
-
"GET /api/news/items": listNewsItems
|
|
5502
|
+
"GET /api/news/items": listNewsItems,
|
|
5503
|
+
"GET /api/usage/history": listUsageHistory
|
|
5466
5504
|
};
|
|
5467
5505
|
var handleRequest = createFallbackHandler(
|
|
5468
5506
|
routes2,
|
|
@@ -5877,10 +5915,10 @@ async function web2(options2) {
|
|
|
5877
5915
|
|
|
5878
5916
|
// src/commands/backlog/comment/index.ts
|
|
5879
5917
|
import chalk48 from "chalk";
|
|
5880
|
-
async function comment(id2,
|
|
5918
|
+
async function comment(id2, text5) {
|
|
5881
5919
|
const found = await findOneItem(id2);
|
|
5882
5920
|
if (!found) process.exit(1);
|
|
5883
|
-
await appendComment(found.orm, found.item.id,
|
|
5921
|
+
await appendComment(found.orm, found.item.id, text5);
|
|
5884
5922
|
console.log(chalk48.green(`Comment added to item #${id2}.`));
|
|
5885
5923
|
}
|
|
5886
5924
|
|
|
@@ -5993,8 +6031,8 @@ async function buildDump(copyOut) {
|
|
|
5993
6031
|
// src/commands/backlog/dump/copyTableOut.ts
|
|
5994
6032
|
import { to as copyTo } from "pg-copy-streams";
|
|
5995
6033
|
async function copyTableOut(client, table) {
|
|
5996
|
-
const
|
|
5997
|
-
const stream = client.query(copyTo(
|
|
6034
|
+
const sql6 = `COPY ${table.name} (${table.columns.join(", ")}) TO STDOUT`;
|
|
6035
|
+
const stream = client.query(copyTo(sql6));
|
|
5998
6036
|
const chunks = [];
|
|
5999
6037
|
for await (const chunk of stream) {
|
|
6000
6038
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
@@ -6050,9 +6088,9 @@ function readLine(dump, start3) {
|
|
|
6050
6088
|
return { text: dump.subarray(start3, eol).toString("utf8"), next: eol + 1 };
|
|
6051
6089
|
}
|
|
6052
6090
|
function parseHeader(dump) {
|
|
6053
|
-
const { text:
|
|
6091
|
+
const { text: text5, next: next3 } = readLine(dump, 0);
|
|
6054
6092
|
try {
|
|
6055
|
-
return { header: JSON.parse(
|
|
6093
|
+
return { header: JSON.parse(text5), bodyStart: next3 };
|
|
6056
6094
|
} catch {
|
|
6057
6095
|
return invalid("header is not valid JSON.");
|
|
6058
6096
|
}
|
|
@@ -6061,9 +6099,9 @@ function parseSections(dump, bodyStart) {
|
|
|
6061
6099
|
const sections = /* @__PURE__ */ new Map();
|
|
6062
6100
|
let cursor = bodyStart;
|
|
6063
6101
|
while (cursor < dump.length) {
|
|
6064
|
-
const { text:
|
|
6065
|
-
const match =
|
|
6066
|
-
if (!match) invalid(`malformed table marker "${
|
|
6102
|
+
const { text: text5, next: next3 } = readLine(dump, cursor);
|
|
6103
|
+
const match = text5.match(/^@table (\S+) (\d+)$/);
|
|
6104
|
+
if (!match) invalid(`malformed table marker "${text5}".`);
|
|
6067
6105
|
const [, name, bytes] = match;
|
|
6068
6106
|
const end = next3 + Number(bytes);
|
|
6069
6107
|
if (end > dump.length) invalid(`section "${name}" overruns the dump.`);
|
|
@@ -6144,8 +6182,8 @@ async function readStdinBuffer() {
|
|
|
6144
6182
|
import { finished } from "stream/promises";
|
|
6145
6183
|
import { from as copyFrom } from "pg-copy-streams";
|
|
6146
6184
|
async function copyTableIn(client, table, data) {
|
|
6147
|
-
const
|
|
6148
|
-
const stream = client.query(copyFrom(
|
|
6185
|
+
const sql6 = `COPY ${table.name} (${table.columns.join(", ")}) FROM STDIN`;
|
|
6186
|
+
const stream = client.query(copyFrom(sql6));
|
|
6149
6187
|
stream.end(data);
|
|
6150
6188
|
await finished(stream);
|
|
6151
6189
|
}
|
|
@@ -6314,9 +6352,9 @@ import chalk56 from "chalk";
|
|
|
6314
6352
|
import { count, eq as eq17 } from "drizzle-orm";
|
|
6315
6353
|
|
|
6316
6354
|
// src/commands/backlog/shiftPhasesUp.ts
|
|
6317
|
-
import { and as and3, desc, eq as eq16, gte } from "drizzle-orm";
|
|
6355
|
+
import { and as and3, desc as desc2, eq as eq16, gte } from "drizzle-orm";
|
|
6318
6356
|
async function shiftPhasesUp(db, itemId, fromIdx) {
|
|
6319
|
-
const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and3(eq16(planPhases.itemId, itemId), gte(planPhases.idx, fromIdx))).orderBy(
|
|
6357
|
+
const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and3(eq16(planPhases.itemId, itemId), gte(planPhases.idx, fromIdx))).orderBy(desc2(planPhases.idx));
|
|
6320
6358
|
for (const p of toShift) {
|
|
6321
6359
|
await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and3(eq16(planTasks.itemId, itemId), eq16(planTasks.phaseIdx, p.idx)));
|
|
6322
6360
|
await db.update(planPhases).set({ idx: p.idx + 1 }).where(and3(eq16(planPhases.itemId, itemId), eq16(planPhases.idx, p.idx)));
|
|
@@ -7191,8 +7229,8 @@ function applyAcMutations(current, options2) {
|
|
|
7191
7229
|
// src/commands/backlog/update/buildUpdateValues.ts
|
|
7192
7230
|
import chalk78 from "chalk";
|
|
7193
7231
|
function buildUpdateValues(options2) {
|
|
7194
|
-
const { name, desc:
|
|
7195
|
-
if (!name && !
|
|
7232
|
+
const { name, desc: desc5, type, ac } = options2;
|
|
7233
|
+
if (!name && !desc5 && !type && !ac) {
|
|
7196
7234
|
console.log(chalk78.red("Nothing to update. Provide at least one flag."));
|
|
7197
7235
|
process.exitCode = 1;
|
|
7198
7236
|
return void 0;
|
|
@@ -7208,8 +7246,8 @@ function buildUpdateValues(options2) {
|
|
|
7208
7246
|
set.name = name;
|
|
7209
7247
|
fieldNames.push("name");
|
|
7210
7248
|
}
|
|
7211
|
-
if (
|
|
7212
|
-
set.description =
|
|
7249
|
+
if (desc5) {
|
|
7250
|
+
set.description = desc5;
|
|
7213
7251
|
fieldNames.push("description");
|
|
7214
7252
|
}
|
|
7215
7253
|
if (type) {
|
|
@@ -8325,8 +8363,8 @@ function formatHuman(cli, commands) {
|
|
|
8325
8363
|
`];
|
|
8326
8364
|
for (const cmd of sorted) {
|
|
8327
8365
|
const full = `${cli} ${cmd.path.join(" ")}`;
|
|
8328
|
-
const
|
|
8329
|
-
lines.push(`${prefix(classifyVerb(cmd.path))}${
|
|
8366
|
+
const text5 = cmd.description ? `${full} \u2014 ${cmd.description}` : full;
|
|
8367
|
+
lines.push(`${prefix(classifyVerb(cmd.path))}${text5}`);
|
|
8330
8368
|
}
|
|
8331
8369
|
return lines.join("\n");
|
|
8332
8370
|
}
|
|
@@ -10722,13 +10760,13 @@ async function load(options2 = {}) {
|
|
|
10722
10760
|
}
|
|
10723
10761
|
|
|
10724
10762
|
// src/commands/handover/listPendingHandovers.ts
|
|
10725
|
-
import { and as and11, desc as
|
|
10763
|
+
import { and as and11, desc as desc3, eq as eq30, isNull as isNull2 } from "drizzle-orm";
|
|
10726
10764
|
async function listPendingHandovers(orm, origin) {
|
|
10727
10765
|
return orm.select({
|
|
10728
10766
|
id: handovers.id,
|
|
10729
10767
|
summary: handovers.summary,
|
|
10730
10768
|
createdAt: handovers.createdAt
|
|
10731
|
-
}).from(handovers).where(and11(eq30(handovers.origin, origin), isNull2(handovers.recalledAt))).orderBy(
|
|
10769
|
+
}).from(handovers).where(and11(eq30(handovers.origin, origin), isNull2(handovers.recalledAt))).orderBy(desc3(handovers.createdAt), desc3(handovers.id));
|
|
10732
10770
|
}
|
|
10733
10771
|
|
|
10734
10772
|
// src/commands/handover/printPendingHandovers.ts
|
|
@@ -10741,7 +10779,7 @@ async function printPendingHandovers() {
|
|
|
10741
10779
|
}
|
|
10742
10780
|
|
|
10743
10781
|
// src/commands/handover/recallHandover.ts
|
|
10744
|
-
import { and as and12, desc as
|
|
10782
|
+
import { and as and12, desc as desc4, eq as eq31, isNull as isNull3 } from "drizzle-orm";
|
|
10745
10783
|
async function recallHandover(orm, origin, id2) {
|
|
10746
10784
|
const [row] = await orm.select().from(handovers).where(
|
|
10747
10785
|
and12(
|
|
@@ -10749,7 +10787,7 @@ async function recallHandover(orm, origin, id2) {
|
|
|
10749
10787
|
isNull3(handovers.recalledAt),
|
|
10750
10788
|
...id2 === void 0 ? [] : [eq31(handovers.id, id2)]
|
|
10751
10789
|
)
|
|
10752
|
-
).orderBy(
|
|
10790
|
+
).orderBy(desc4(handovers.createdAt), desc4(handovers.id)).limit(1);
|
|
10753
10791
|
if (!row) return void 0;
|
|
10754
10792
|
await orm.update(handovers).set({ recalledAt: /* @__PURE__ */ new Date() }).where(eq31(handovers.id, row.id));
|
|
10755
10793
|
return row.content;
|
|
@@ -10805,9 +10843,9 @@ import chalk115 from "chalk";
|
|
|
10805
10843
|
|
|
10806
10844
|
// src/commands/jira/adfToText.ts
|
|
10807
10845
|
function renderInline(node) {
|
|
10808
|
-
const
|
|
10809
|
-
if (node.marks?.some((m) => m.type === "code")) return `\`${
|
|
10810
|
-
return
|
|
10846
|
+
const text5 = node.text ?? "";
|
|
10847
|
+
if (node.marks?.some((m) => m.type === "code")) return `\`${text5}\``;
|
|
10848
|
+
return text5;
|
|
10811
10849
|
}
|
|
10812
10850
|
function renderChildren(node, indent2) {
|
|
10813
10851
|
return renderNodes(node.content ?? [], indent2);
|
|
@@ -10849,8 +10887,8 @@ function isListNode(node) {
|
|
|
10849
10887
|
function renderListChild(child, indent2, pad, marker, isFirst) {
|
|
10850
10888
|
if (isListNode(child)) return renderNodes([child], indent2 + 1);
|
|
10851
10889
|
if (child.type !== "paragraph") return renderNode(child, indent2);
|
|
10852
|
-
const
|
|
10853
|
-
return isFirst ? `${pad}${marker} ${
|
|
10890
|
+
const text5 = renderChildren(child, indent2);
|
|
10891
|
+
return isFirst ? `${pad}${marker} ${text5}` : `${pad} ${text5}`;
|
|
10854
10892
|
}
|
|
10855
10893
|
function renderListItem(node, indent2, marker) {
|
|
10856
10894
|
const pad = " ".repeat(indent2);
|
|
@@ -11540,8 +11578,8 @@ function isWallOfText(lines) {
|
|
|
11540
11578
|
if (lines.some(isListLine)) {
|
|
11541
11579
|
return false;
|
|
11542
11580
|
}
|
|
11543
|
-
const
|
|
11544
|
-
return
|
|
11581
|
+
const text5 = lines.join(" ").trim();
|
|
11582
|
+
return text5.length > MAX_PARAGRAPH_CHARS || countSentences(text5) > MAX_PARAGRAPH_SENTENCES;
|
|
11545
11583
|
}
|
|
11546
11584
|
function validatePrContent(title, body) {
|
|
11547
11585
|
if (title.toLowerCase().includes("claude")) {
|
|
@@ -13202,9 +13240,9 @@ function resolveImports(target, dependencies, sourceFile, statements = []) {
|
|
|
13202
13240
|
function extractTexts(target, allFunctions, statements) {
|
|
13203
13241
|
const stmtTexts = statements.map((v) => v.getFullText().trim());
|
|
13204
13242
|
const fnTexts = allFunctions.map((fn) => {
|
|
13205
|
-
const
|
|
13206
|
-
if (fn === target && !
|
|
13207
|
-
return
|
|
13243
|
+
const text5 = fn.getFullText().trim();
|
|
13244
|
+
if (fn === target && !text5.startsWith("export ")) return `export ${text5}`;
|
|
13245
|
+
return text5;
|
|
13208
13246
|
});
|
|
13209
13247
|
return [...stmtTexts, ...fnTexts];
|
|
13210
13248
|
}
|
|
@@ -15040,9 +15078,9 @@ var MultiSpinner = class {
|
|
|
15040
15078
|
elapsedPrefix: prefix2
|
|
15041
15079
|
});
|
|
15042
15080
|
}
|
|
15043
|
-
failRemaining(
|
|
15081
|
+
failRemaining(text5) {
|
|
15044
15082
|
for (const entry of this.entries) {
|
|
15045
|
-
if (entry.state === "running") this.resolve(entry, "failed",
|
|
15083
|
+
if (entry.state === "running") this.resolve(entry, "failed", text5);
|
|
15046
15084
|
}
|
|
15047
15085
|
}
|
|
15048
15086
|
add(entry) {
|
|
@@ -15055,14 +15093,14 @@ var MultiSpinner = class {
|
|
|
15055
15093
|
set text(value) {
|
|
15056
15094
|
entry.text = value;
|
|
15057
15095
|
},
|
|
15058
|
-
succeed: (
|
|
15059
|
-
fail: (
|
|
15096
|
+
succeed: (text5) => this.resolve(entry, "succeeded", text5),
|
|
15097
|
+
fail: (text5) => this.resolve(entry, "failed", text5)
|
|
15060
15098
|
};
|
|
15061
15099
|
}
|
|
15062
|
-
resolve(entry, state,
|
|
15100
|
+
resolve(entry, state, text5) {
|
|
15063
15101
|
if (entry.state !== "running") return;
|
|
15064
15102
|
entry.state = state;
|
|
15065
|
-
if (
|
|
15103
|
+
if (text5 !== void 0) entry.text = text5;
|
|
15066
15104
|
entry.elapsedStart = void 0;
|
|
15067
15105
|
this.render();
|
|
15068
15106
|
this.maybeFinish();
|
|
@@ -15137,12 +15175,12 @@ function skippedCodexResult(outputPath) {
|
|
|
15137
15175
|
// src/commands/review/formatReviewerFailure.ts
|
|
15138
15176
|
var FAST_FAIL_MS = 1e3;
|
|
15139
15177
|
var STDOUT_TAIL_LINES = 20;
|
|
15140
|
-
function indent(
|
|
15141
|
-
return
|
|
15178
|
+
function indent(text5) {
|
|
15179
|
+
return text5.split(/\r?\n/).map((line) => ` ${line}`);
|
|
15142
15180
|
}
|
|
15143
|
-
function tailLines(
|
|
15144
|
-
const lines =
|
|
15145
|
-
return lines.length <= maxLines ?
|
|
15181
|
+
function tailLines(text5, maxLines) {
|
|
15182
|
+
const lines = text5.split(/\r?\n/);
|
|
15183
|
+
return lines.length <= maxLines ? text5 : lines.slice(-maxLines).join("\n");
|
|
15146
15184
|
}
|
|
15147
15185
|
function isFastFail(input) {
|
|
15148
15186
|
return input.exitCode !== 0 && input.elapsedMs !== void 0 && input.elapsedMs < FAST_FAIL_MS;
|
|
@@ -16062,8 +16100,8 @@ function filterToSql(filter) {
|
|
|
16062
16100
|
// src/commands/seq/fetchSeqData.ts
|
|
16063
16101
|
function buildDataParams(filter, count6, from, to) {
|
|
16064
16102
|
const sqlFilter = filterToSql(filter);
|
|
16065
|
-
const
|
|
16066
|
-
const params = new URLSearchParams({ q:
|
|
16103
|
+
const sql6 = `select @Timestamp, @Level, @Exception, @Message from stream where ${sqlFilter} order by @Timestamp desc limit ${count6}`;
|
|
16104
|
+
const params = new URLSearchParams({ q: sql6 });
|
|
16067
16105
|
if (from) params.set("rangeStartUtc", from);
|
|
16068
16106
|
if (to) params.set("rangeEndUtc", to);
|
|
16069
16107
|
return params;
|
|
@@ -16323,26 +16361,26 @@ import chalk159 from "chalk";
|
|
|
16323
16361
|
// src/commands/sql/loadConnections.ts
|
|
16324
16362
|
function loadConnections3() {
|
|
16325
16363
|
const raw = loadGlobalConfigRaw();
|
|
16326
|
-
const
|
|
16327
|
-
return
|
|
16364
|
+
const sql6 = raw.sql;
|
|
16365
|
+
return sql6?.connections ?? [];
|
|
16328
16366
|
}
|
|
16329
16367
|
function saveConnections3(connections) {
|
|
16330
16368
|
const raw = loadGlobalConfigRaw();
|
|
16331
|
-
const
|
|
16332
|
-
|
|
16333
|
-
raw.sql =
|
|
16369
|
+
const sql6 = raw.sql ?? {};
|
|
16370
|
+
sql6.connections = connections;
|
|
16371
|
+
raw.sql = sql6;
|
|
16334
16372
|
saveGlobalConfig(raw);
|
|
16335
16373
|
}
|
|
16336
16374
|
function getDefaultConnection2() {
|
|
16337
16375
|
const raw = loadGlobalConfigRaw();
|
|
16338
|
-
const
|
|
16339
|
-
return
|
|
16376
|
+
const sql6 = raw.sql;
|
|
16377
|
+
return sql6?.defaultConnection;
|
|
16340
16378
|
}
|
|
16341
16379
|
function setDefaultConnection2(name) {
|
|
16342
16380
|
const raw = loadGlobalConfigRaw();
|
|
16343
|
-
const
|
|
16344
|
-
|
|
16345
|
-
raw.sql =
|
|
16381
|
+
const sql6 = raw.sql ?? {};
|
|
16382
|
+
sql6.defaultConnection = name;
|
|
16383
|
+
raw.sql = sql6;
|
|
16346
16384
|
saveGlobalConfig(raw);
|
|
16347
16385
|
}
|
|
16348
16386
|
|
|
@@ -16478,11 +16516,11 @@ var MUTATION_PATTERN = new RegExp(
|
|
|
16478
16516
|
`\\b(${MUTATION_KEYWORDS.join("|")})\\b`,
|
|
16479
16517
|
"i"
|
|
16480
16518
|
);
|
|
16481
|
-
function stripComments(
|
|
16482
|
-
return
|
|
16519
|
+
function stripComments(sql6) {
|
|
16520
|
+
return sql6.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\n]*/g, " ");
|
|
16483
16521
|
}
|
|
16484
|
-
function isMutation(
|
|
16485
|
-
const stripped = stripComments(
|
|
16522
|
+
function isMutation(sql6) {
|
|
16523
|
+
const stripped = stripComments(sql6);
|
|
16486
16524
|
if (MUTATION_PATTERN.test(stripped)) return true;
|
|
16487
16525
|
return /\bSELECT\b[\s\S]+\bINTO\s+\w/i.test(stripped);
|
|
16488
16526
|
}
|
|
@@ -16778,8 +16816,8 @@ import { existsSync as existsSync38, mkdirSync as mkdirSync14, readFileSync as r
|
|
|
16778
16816
|
import { basename as basename9, dirname as dirname21, join as join41 } from "path";
|
|
16779
16817
|
|
|
16780
16818
|
// src/commands/transcript/cleanText.ts
|
|
16781
|
-
function cleanText(
|
|
16782
|
-
const words =
|
|
16819
|
+
function cleanText(text5) {
|
|
16820
|
+
const words = text5.split(/\s+/);
|
|
16783
16821
|
const cleaned = [];
|
|
16784
16822
|
for (let i = 0; i < words.length; i++) {
|
|
16785
16823
|
let isRepeat = false;
|
|
@@ -16799,8 +16837,8 @@ function cleanText(text4) {
|
|
|
16799
16837
|
}
|
|
16800
16838
|
|
|
16801
16839
|
// src/commands/transcript/format/processVttFile/parseVtt/deduplicateCues/removeSubstringDuplicates.ts
|
|
16802
|
-
function normalizeText(
|
|
16803
|
-
return
|
|
16840
|
+
function normalizeText(text5) {
|
|
16841
|
+
return text5.toLowerCase().trim();
|
|
16804
16842
|
}
|
|
16805
16843
|
function checkSubstringRelation(textI, textJ) {
|
|
16806
16844
|
if (textI.includes(textJ) && textI.length > textJ.length)
|
|
@@ -16929,13 +16967,13 @@ function parseTimestampLine(line) {
|
|
|
16929
16967
|
return { startMs: parseTimestamp(startStr), endMs: parseTimestamp(endStr) };
|
|
16930
16968
|
}
|
|
16931
16969
|
function buildCue(startMs, endMs, fullText) {
|
|
16932
|
-
const { speaker, text:
|
|
16933
|
-
return
|
|
16970
|
+
const { speaker, text: text5 } = extractSpeaker(fullText);
|
|
16971
|
+
return text5 ? { startMs, endMs, speaker, text: text5 } : null;
|
|
16934
16972
|
}
|
|
16935
16973
|
function parseCueLine(lines, i) {
|
|
16936
16974
|
const { startMs, endMs } = parseTimestampLine(lines[i]);
|
|
16937
|
-
const { text:
|
|
16938
|
-
return { cue: buildCue(startMs, endMs,
|
|
16975
|
+
const { text: text5, nextIndex: nextIndex2 } = collectTextLines(lines, i + 1);
|
|
16976
|
+
return { cue: buildCue(startMs, endMs, text5), nextIndex: nextIndex2 };
|
|
16939
16977
|
}
|
|
16940
16978
|
function isCueSeparator(line) {
|
|
16941
16979
|
return line.trim().includes("-->");
|
|
@@ -17604,8 +17642,8 @@ async function exchangeToken(params) {
|
|
|
17604
17642
|
body: body.toString()
|
|
17605
17643
|
});
|
|
17606
17644
|
if (!response.ok) {
|
|
17607
|
-
const
|
|
17608
|
-
throw new Error(`Token exchange failed (${response.status}): ${
|
|
17645
|
+
const text5 = await response.text();
|
|
17646
|
+
throw new Error(`Token exchange failed (${response.status}): ${text5}`);
|
|
17609
17647
|
}
|
|
17610
17648
|
return response.json();
|
|
17611
17649
|
}
|
|
@@ -18551,12 +18589,50 @@ function broadcastSessions(sessions, clients, windowsSessions = [], active) {
|
|
|
18551
18589
|
});
|
|
18552
18590
|
}
|
|
18553
18591
|
|
|
18592
|
+
// src/shared/db/recordUsagePeak.ts
|
|
18593
|
+
import { sql as sql5 } from "drizzle-orm";
|
|
18594
|
+
var WINDOWS = ["five_hour", "seven_day"];
|
|
18595
|
+
async function recordUsagePeak(db, rateLimits) {
|
|
18596
|
+
const rows = WINDOWS.flatMap((window) => {
|
|
18597
|
+
const w = rateLimits[window];
|
|
18598
|
+
if (!w) return [];
|
|
18599
|
+
if (typeof w.resets_at !== "number" || typeof w.used_percentage !== "number")
|
|
18600
|
+
return [];
|
|
18601
|
+
return [
|
|
18602
|
+
{ window, resetsAt: w.resets_at, usedPercentage: w.used_percentage }
|
|
18603
|
+
];
|
|
18604
|
+
});
|
|
18605
|
+
if (rows.length === 0) return;
|
|
18606
|
+
await db.insert(usagePeaks).values(rows).onConflictDoUpdate({
|
|
18607
|
+
target: [usagePeaks.window, usagePeaks.resetsAt],
|
|
18608
|
+
set: {
|
|
18609
|
+
usedPercentage: sql5`GREATEST(${usagePeaks.usedPercentage}, excluded.used_percentage)`
|
|
18610
|
+
}
|
|
18611
|
+
});
|
|
18612
|
+
}
|
|
18613
|
+
|
|
18614
|
+
// src/commands/sessions/daemon/persistUsagePeak.ts
|
|
18615
|
+
async function persistUsagePeak(rateLimits) {
|
|
18616
|
+
try {
|
|
18617
|
+
if (!process.env.ASSIST_DATABASE_URL && !loadConfig().database.url) return;
|
|
18618
|
+
await recordUsagePeak(await getDb(), rateLimits);
|
|
18619
|
+
} catch (error) {
|
|
18620
|
+
daemonLog(`usage-peak persist failed: ${String(error)}`);
|
|
18621
|
+
}
|
|
18622
|
+
}
|
|
18623
|
+
|
|
18554
18624
|
// src/commands/sessions/daemon/ClientHub.ts
|
|
18555
18625
|
var ClientHub = class extends Set {
|
|
18626
|
+
// why: the daemon injects a best-effort persister; left undefined elsewhere so `new ClientHub()` works and broadcasting never depends on it.
|
|
18627
|
+
constructor(persistPeak) {
|
|
18628
|
+
super();
|
|
18629
|
+
this.persistPeak = persistPeak;
|
|
18630
|
+
}
|
|
18556
18631
|
latestLimits;
|
|
18557
18632
|
updateLimits(rateLimits) {
|
|
18558
18633
|
this.latestLimits = rateLimits;
|
|
18559
18634
|
broadcast(this, { type: "limits", rateLimits });
|
|
18635
|
+
this.persistPeak?.(rateLimits);
|
|
18560
18636
|
}
|
|
18561
18637
|
greet(client) {
|
|
18562
18638
|
if (this.latestLimits) {
|
|
@@ -19540,8 +19616,8 @@ function deriveSessionType(commandName, name) {
|
|
|
19540
19616
|
}
|
|
19541
19617
|
|
|
19542
19618
|
// src/commands/sessions/shared/backlogRunMarkers.ts
|
|
19543
|
-
function backlogRunMarkers(
|
|
19544
|
-
const match =
|
|
19619
|
+
function backlogRunMarkers(text5) {
|
|
19620
|
+
const match = text5.match(/backlog item #(\d+):[ \t]*([^\n]*)/);
|
|
19545
19621
|
if (!match) return { commandName: "", commandArgs: "" };
|
|
19546
19622
|
const title = match[2].trim();
|
|
19547
19623
|
return {
|
|
@@ -19595,11 +19671,11 @@ function messageText(entry) {
|
|
|
19595
19671
|
const content = msg?.content;
|
|
19596
19672
|
return typeof content === "string" ? content : Array.isArray(content) ? content.find((c) => c.type === "text")?.text ?? "" : "";
|
|
19597
19673
|
}
|
|
19598
|
-
function stripMarkers(
|
|
19599
|
-
return
|
|
19674
|
+
function stripMarkers(text5) {
|
|
19675
|
+
return text5.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
|
|
19600
19676
|
}
|
|
19601
|
-
function matchMarker(
|
|
19602
|
-
const match =
|
|
19677
|
+
function matchMarker(text5, tag) {
|
|
19678
|
+
const match = text5.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
|
|
19603
19679
|
return match ? match[1].trim() : "";
|
|
19604
19680
|
}
|
|
19605
19681
|
|
|
@@ -19809,7 +19885,7 @@ var SessionManager = class {
|
|
|
19809
19885
|
sessions = /* @__PURE__ */ new Map();
|
|
19810
19886
|
// why: dispatch calls active.set() on card click; broadcasts include active.toJSON()
|
|
19811
19887
|
active = new ActiveSelection(() => this.notify());
|
|
19812
|
-
clients = new ClientHub();
|
|
19888
|
+
clients = new ClientHub(persistUsagePeak);
|
|
19813
19889
|
nextId = 1;
|
|
19814
19890
|
shuttingDown = false;
|
|
19815
19891
|
// why: dispatch calls windowsProxy.route() to forward windows-origin sessions
|
|
@@ -19921,17 +19997,17 @@ function entryMessages(entry) {
|
|
|
19921
19997
|
return [];
|
|
19922
19998
|
}
|
|
19923
19999
|
function userMessages(content) {
|
|
19924
|
-
if (typeof content === "string") return
|
|
20000
|
+
if (typeof content === "string") return text4("user", cleanUserText(content));
|
|
19925
20001
|
if (!Array.isArray(content)) return [];
|
|
19926
|
-
return content.filter((c) => c.type === "text").flatMap((c) =>
|
|
20002
|
+
return content.filter((c) => c.type === "text").flatMap((c) => text4("user", cleanUserText(c.text ?? "")));
|
|
19927
20003
|
}
|
|
19928
20004
|
function assistantMessages(content) {
|
|
19929
|
-
if (typeof content === "string") return
|
|
20005
|
+
if (typeof content === "string") return text4("assistant", content.trim());
|
|
19930
20006
|
if (!Array.isArray(content)) return [];
|
|
19931
20007
|
return content.flatMap((c) => assistantItem(c));
|
|
19932
20008
|
}
|
|
19933
20009
|
function assistantItem(c) {
|
|
19934
|
-
if (c.type === "text") return
|
|
20010
|
+
if (c.type === "text") return text4("assistant", (c.text ?? "").trim());
|
|
19935
20011
|
if (c.type === "tool_use")
|
|
19936
20012
|
return [
|
|
19937
20013
|
{
|
|
@@ -19942,7 +20018,7 @@ function assistantItem(c) {
|
|
|
19942
20018
|
];
|
|
19943
20019
|
return [];
|
|
19944
20020
|
}
|
|
19945
|
-
function
|
|
20021
|
+
function text4(role, value) {
|
|
19946
20022
|
return value ? [{ role, text: value }] : [];
|
|
19947
20023
|
}
|
|
19948
20024
|
function cleanUserText(value) {
|
|
@@ -20273,16 +20349,16 @@ function parseUserLine(line) {
|
|
|
20273
20349
|
if (entry.type !== "user") return void 0;
|
|
20274
20350
|
const msg = entry.message;
|
|
20275
20351
|
const c = msg?.content;
|
|
20276
|
-
let
|
|
20352
|
+
let text5;
|
|
20277
20353
|
if (typeof c === "string") {
|
|
20278
|
-
|
|
20354
|
+
text5 = c;
|
|
20279
20355
|
} else if (Array.isArray(c)) {
|
|
20280
20356
|
const collected = c.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n");
|
|
20281
|
-
|
|
20357
|
+
text5 = collected || void 0;
|
|
20282
20358
|
}
|
|
20283
|
-
if (!
|
|
20359
|
+
if (!text5) return void 0;
|
|
20284
20360
|
return {
|
|
20285
|
-
text:
|
|
20361
|
+
text: text5,
|
|
20286
20362
|
entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
|
|
20287
20363
|
};
|
|
20288
20364
|
}
|
|
@@ -20311,13 +20387,13 @@ function* iterateUserMessages(filePath, maxBytes = 65536) {
|
|
|
20311
20387
|
|
|
20312
20388
|
// src/commands/sessions/summarise/extractFirstUserMessage.ts
|
|
20313
20389
|
function extractFirstUserMessage(filePath) {
|
|
20314
|
-
for (const
|
|
20315
|
-
return truncate3(
|
|
20390
|
+
for (const text5 of iterateUserMessages(filePath)) {
|
|
20391
|
+
return truncate3(text5);
|
|
20316
20392
|
}
|
|
20317
20393
|
return void 0;
|
|
20318
20394
|
}
|
|
20319
|
-
function truncate3(
|
|
20320
|
-
const trimmed =
|
|
20395
|
+
function truncate3(text5, maxChars = 500) {
|
|
20396
|
+
const trimmed = text5.trim();
|
|
20321
20397
|
if (trimmed.length <= maxChars) return trimmed;
|
|
20322
20398
|
return `${trimmed.slice(0, maxChars)}\u2026`;
|
|
20323
20399
|
}
|
|
@@ -20325,28 +20401,28 @@ function truncate3(text4, maxChars = 500) {
|
|
|
20325
20401
|
// src/commands/sessions/summarise/scanSessionBacklogRefs.ts
|
|
20326
20402
|
function scanSessionBacklogRefs(filePath) {
|
|
20327
20403
|
const ids = /* @__PURE__ */ new Set();
|
|
20328
|
-
for (const
|
|
20329
|
-
for (const id2 of extractBacklogIds(
|
|
20404
|
+
for (const text5 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
|
|
20405
|
+
for (const id2 of extractBacklogIds(text5)) {
|
|
20330
20406
|
ids.add(id2);
|
|
20331
20407
|
}
|
|
20332
20408
|
}
|
|
20333
20409
|
return [...ids].sort((a, b) => a - b);
|
|
20334
20410
|
}
|
|
20335
|
-
function extractBacklogIds(
|
|
20411
|
+
function extractBacklogIds(text5) {
|
|
20336
20412
|
const ids = [];
|
|
20337
|
-
for (const m of
|
|
20413
|
+
for (const m of text5.matchAll(/backlog\s+run\s+(\d+)/gi)) {
|
|
20338
20414
|
ids.push(Number.parseInt(m[1], 10));
|
|
20339
20415
|
}
|
|
20340
|
-
for (const m of
|
|
20416
|
+
for (const m of text5.matchAll(/backlog\s+(?:item\s+)?#(\d+)/gi)) {
|
|
20341
20417
|
ids.push(Number.parseInt(m[1], 10));
|
|
20342
20418
|
}
|
|
20343
|
-
for (const m of
|
|
20419
|
+
for (const m of text5.matchAll(/backlog\s+phase-done\s+(\d+)/gi)) {
|
|
20344
20420
|
ids.push(Number.parseInt(m[1], 10));
|
|
20345
20421
|
}
|
|
20346
|
-
for (const m of
|
|
20422
|
+
for (const m of text5.matchAll(/backlog\s+comment\s+(\d+)/gi)) {
|
|
20347
20423
|
ids.push(Number.parseInt(m[1], 10));
|
|
20348
20424
|
}
|
|
20349
|
-
for (const m of
|
|
20425
|
+
for (const m of text5.matchAll(/(?:^|[\s(])#(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
|
|
20350
20426
|
ids.push(Number.parseInt(m[1], 10));
|
|
20351
20427
|
}
|
|
20352
20428
|
return ids;
|