@staff0rd/assist 0.363.0 → 0.365.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 +4 -1
- package/claude/commands/bug.md +18 -1
- package/claude/commands/draft.md +15 -2
- package/claude/commands/refine.md +3 -1
- package/claude/commands/subtask.md +6 -0
- package/dist/commands/sessions/web/bundle.js +76 -76
- package/dist/index.js +234 -120
- package/package.json +3 -2
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.365.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -55,6 +55,8 @@ var package_default = {
|
|
|
55
55
|
entities: "^7.0.1",
|
|
56
56
|
"is-wsl": "^3.1.0",
|
|
57
57
|
"log-update": "^8.0.0",
|
|
58
|
+
marked: "^15.0.12",
|
|
59
|
+
"marked-terminal": "^7.3.0",
|
|
58
60
|
minimatch: "^10.1.1",
|
|
59
61
|
mssql: "^12.5.0",
|
|
60
62
|
"node-notifier": "^10.0.1",
|
|
@@ -99,7 +101,6 @@ var package_default = {
|
|
|
99
101
|
jscpd: "^4.0.5",
|
|
100
102
|
jsdom: "^29.1.1",
|
|
101
103
|
knip: "^5.71.0",
|
|
102
|
-
marked: "^15.0.12",
|
|
103
104
|
oxfmt: "^0.54.0",
|
|
104
105
|
oxlint: "^1.69.0",
|
|
105
106
|
react: "^19.2.4",
|
|
@@ -254,7 +255,8 @@ var assistConfigSchema = z2.strictObject({
|
|
|
254
255
|
tokenExpiresAt: z2.number().optional()
|
|
255
256
|
}).optional(),
|
|
256
257
|
prs: z2.strictObject({
|
|
257
|
-
slack: z2.string()
|
|
258
|
+
slack: z2.string().optional(),
|
|
259
|
+
required: z2.boolean().default(false)
|
|
258
260
|
}).optional(),
|
|
259
261
|
run: z2.array(z2.union([runConfigSchema, runLinkSchema])).optional(),
|
|
260
262
|
subtasks: z2.array(
|
|
@@ -3120,7 +3122,7 @@ ${failed2.length} script(s) failed:`);
|
|
|
3120
3122
|
}
|
|
3121
3123
|
}
|
|
3122
3124
|
function runEntry(entry) {
|
|
3123
|
-
return new Promise((
|
|
3125
|
+
return new Promise((resolve18) => {
|
|
3124
3126
|
const startTime = Date.now();
|
|
3125
3127
|
const child = spawnCommand(
|
|
3126
3128
|
entry.fullCommand,
|
|
@@ -3132,7 +3134,7 @@ function runEntry(entry) {
|
|
|
3132
3134
|
child.on("close", (code) => {
|
|
3133
3135
|
const exitCode = code ?? 1;
|
|
3134
3136
|
flushIfFailed(exitCode, chunks);
|
|
3135
|
-
|
|
3137
|
+
resolve18({
|
|
3136
3138
|
script: entry.name,
|
|
3137
3139
|
code: exitCode,
|
|
3138
3140
|
durationMs: Date.now() - startTime
|
|
@@ -4266,8 +4268,8 @@ function spawnClaude(prompt, options2 = {}) {
|
|
|
4266
4268
|
stdio: "inherit",
|
|
4267
4269
|
env
|
|
4268
4270
|
});
|
|
4269
|
-
const done2 = new Promise((
|
|
4270
|
-
child.on("close", (code) =>
|
|
4271
|
+
const done2 = new Promise((resolve18, reject) => {
|
|
4272
|
+
child.on("close", (code) => resolve18(code ?? 0));
|
|
4271
4273
|
child.on("error", reject);
|
|
4272
4274
|
});
|
|
4273
4275
|
return { child, done: done2 };
|
|
@@ -4329,6 +4331,89 @@ function consumePause(itemId) {
|
|
|
4329
4331
|
return true;
|
|
4330
4332
|
}
|
|
4331
4333
|
|
|
4334
|
+
// src/commands/branch/createBranch.ts
|
|
4335
|
+
import { execSync as execSync21 } from "child_process";
|
|
4336
|
+
|
|
4337
|
+
// src/commands/branch/buildBranchName.ts
|
|
4338
|
+
function buildBranchName({
|
|
4339
|
+
prefix: prefix2,
|
|
4340
|
+
jira,
|
|
4341
|
+
slug
|
|
4342
|
+
}) {
|
|
4343
|
+
const segments = [];
|
|
4344
|
+
if (prefix2) segments.push(`${prefix2}/`);
|
|
4345
|
+
if (jira) segments.push(`${jira}-`);
|
|
4346
|
+
segments.push(slug);
|
|
4347
|
+
return segments.join("");
|
|
4348
|
+
}
|
|
4349
|
+
|
|
4350
|
+
// src/commands/branch/resolveDefaultBranch.ts
|
|
4351
|
+
import { execSync as execSync20 } from "child_process";
|
|
4352
|
+
var REMOTE_HEAD_REGEX = /^ref:\s+refs\/heads\/(\S+)\s+HEAD$/m;
|
|
4353
|
+
function resolveDefaultBranch(override, cwd) {
|
|
4354
|
+
if (override) return override;
|
|
4355
|
+
try {
|
|
4356
|
+
const output = execSync20("git ls-remote --symref origin HEAD", {
|
|
4357
|
+
encoding: "utf8",
|
|
4358
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
4359
|
+
cwd
|
|
4360
|
+
});
|
|
4361
|
+
const match = output.match(REMOTE_HEAD_REGEX);
|
|
4362
|
+
if (match) return match[1];
|
|
4363
|
+
} catch {
|
|
4364
|
+
}
|
|
4365
|
+
return "main";
|
|
4366
|
+
}
|
|
4367
|
+
|
|
4368
|
+
// src/commands/branch/createBranch.ts
|
|
4369
|
+
async function createBranch({
|
|
4370
|
+
slug,
|
|
4371
|
+
jira
|
|
4372
|
+
}) {
|
|
4373
|
+
const config = loadConfig();
|
|
4374
|
+
const branchName = buildBranchName({
|
|
4375
|
+
prefix: config.branch?.prefix,
|
|
4376
|
+
jira,
|
|
4377
|
+
slug
|
|
4378
|
+
});
|
|
4379
|
+
const defaultBranch = resolveDefaultBranch(config.branch?.defaultBranch);
|
|
4380
|
+
execSync21("git fetch", { stdio: "inherit" });
|
|
4381
|
+
execSync21(
|
|
4382
|
+
`git switch -c ${shellQuote(branchName)} ${shellQuote(`origin/${defaultBranch}`)}`,
|
|
4383
|
+
{ stdio: "inherit" }
|
|
4384
|
+
);
|
|
4385
|
+
await recordBranchActivity(branchName);
|
|
4386
|
+
return { branchName, defaultBranch };
|
|
4387
|
+
}
|
|
4388
|
+
async function recordBranchActivity(branchName) {
|
|
4389
|
+
if (resolveSessionItemId() === null) return;
|
|
4390
|
+
await recordSessionRefs([
|
|
4391
|
+
{ kind: "branch", ref: branchName, url: gitRefUrl("branch", branchName) }
|
|
4392
|
+
]);
|
|
4393
|
+
}
|
|
4394
|
+
|
|
4395
|
+
// src/commands/branch/deriveBranchSlug.ts
|
|
4396
|
+
function deriveBranchSlug(name) {
|
|
4397
|
+
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
4398
|
+
return slug || "story";
|
|
4399
|
+
}
|
|
4400
|
+
|
|
4401
|
+
// src/commands/backlog/ensureStoryBranch.ts
|
|
4402
|
+
async function ensureStoryBranch(item) {
|
|
4403
|
+
const config = loadConfig();
|
|
4404
|
+
if (!config.prs?.required) return;
|
|
4405
|
+
if (hasBranchRef(item)) return;
|
|
4406
|
+
process.env.ASSIST_BACKLOG_ITEM_ID = String(item.id);
|
|
4407
|
+
const slug = deriveBranchSlug(item.name);
|
|
4408
|
+
const { branchName } = await createBranch({ slug, jira: item.jiraKey });
|
|
4409
|
+
appendDaemonLog(
|
|
4410
|
+
`backlog run ${item.id}: prs.required set and no branch recorded; created ${branchName}`
|
|
4411
|
+
);
|
|
4412
|
+
}
|
|
4413
|
+
function hasBranchRef(item) {
|
|
4414
|
+
return (item.gitRefs ?? []).some((ref) => ref.kind === "branch");
|
|
4415
|
+
}
|
|
4416
|
+
|
|
4332
4417
|
// src/commands/backlog/shared.ts
|
|
4333
4418
|
import chalk37 from "chalk";
|
|
4334
4419
|
|
|
@@ -4354,11 +4439,11 @@ function backupLocalBacklogFiles(dir) {
|
|
|
4354
4439
|
}
|
|
4355
4440
|
|
|
4356
4441
|
// src/commands/backlog/gitPullBacklog.ts
|
|
4357
|
-
import { execSync as
|
|
4442
|
+
import { execSync as execSync22 } from "child_process";
|
|
4358
4443
|
import chalk35 from "chalk";
|
|
4359
4444
|
function gitPullBacklog(dir) {
|
|
4360
4445
|
try {
|
|
4361
|
-
|
|
4446
|
+
execSync22("git pull --ff-only", {
|
|
4362
4447
|
cwd: dir,
|
|
4363
4448
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4364
4449
|
});
|
|
@@ -5083,9 +5168,9 @@ Failed to launch Claude for ${context}: ${message}`)
|
|
|
5083
5168
|
// src/commands/sessions/daemon/connectToDaemon.ts
|
|
5084
5169
|
import * as net from "net";
|
|
5085
5170
|
function connectToDaemon() {
|
|
5086
|
-
return new Promise((
|
|
5171
|
+
return new Promise((resolve18, reject) => {
|
|
5087
5172
|
const socket = net.connect(daemonPaths.socket);
|
|
5088
|
-
socket.once("connect", () =>
|
|
5173
|
+
socket.once("connect", () => resolve18(socket));
|
|
5089
5174
|
socket.once("error", reject);
|
|
5090
5175
|
});
|
|
5091
5176
|
}
|
|
@@ -5532,6 +5617,7 @@ async function runOnce(item, startPhase, plan2, spawnOptions) {
|
|
|
5532
5617
|
async function run2(id2, spawnOptions) {
|
|
5533
5618
|
const prepared = await prepareRun(id2);
|
|
5534
5619
|
if (!prepared) return false;
|
|
5620
|
+
await ensureStoryBranch(prepared.item);
|
|
5535
5621
|
await setStatus(id2, "in-progress");
|
|
5536
5622
|
discardStalePause(prepared.item.id);
|
|
5537
5623
|
logProgress(id2, prepared);
|
|
@@ -5736,6 +5822,25 @@ function formatComment(entry) {
|
|
|
5736
5822
|
${entry.text}`;
|
|
5737
5823
|
}
|
|
5738
5824
|
|
|
5825
|
+
// src/shared/renderMarkdownTerminal.ts
|
|
5826
|
+
import { Marked } from "marked";
|
|
5827
|
+
import { markedTerminal } from "marked-terminal";
|
|
5828
|
+
function renderMarkdownTerminal(text9) {
|
|
5829
|
+
const width = process.stdout.columns || 80;
|
|
5830
|
+
const marked = new Marked(markedTerminal({ width, reflowText: true }));
|
|
5831
|
+
marked.use({
|
|
5832
|
+
renderer: {
|
|
5833
|
+
text(token) {
|
|
5834
|
+
if (token && typeof token === "object" && "tokens" in token && token.tokens) {
|
|
5835
|
+
return this.parser.parseInline(token.tokens);
|
|
5836
|
+
}
|
|
5837
|
+
return false;
|
|
5838
|
+
}
|
|
5839
|
+
}
|
|
5840
|
+
});
|
|
5841
|
+
return marked.parse(text9).trimEnd();
|
|
5842
|
+
}
|
|
5843
|
+
|
|
5739
5844
|
// src/commands/backlog/show/printActivity.ts
|
|
5740
5845
|
import chalk48 from "chalk";
|
|
5741
5846
|
|
|
@@ -5869,7 +5974,10 @@ function printSubtasks(item) {
|
|
|
5869
5974
|
const status2 = chalk52.dim(`[${subtask.status}]`);
|
|
5870
5975
|
console.log(` ${i + 1}. ${status2} ${subtask.title}`);
|
|
5871
5976
|
if (subtask.description) {
|
|
5872
|
-
|
|
5977
|
+
const rendered = renderMarkdownTerminal(subtask.description);
|
|
5978
|
+
for (const line of rendered.split("\n")) {
|
|
5979
|
+
console.log(` ${line}`);
|
|
5980
|
+
}
|
|
5873
5981
|
}
|
|
5874
5982
|
}
|
|
5875
5983
|
console.log();
|
|
@@ -5910,7 +6018,7 @@ async function show(id2) {
|
|
|
5910
6018
|
printHeader(item);
|
|
5911
6019
|
if (item.description) {
|
|
5912
6020
|
console.log(chalk53.bold("Description"));
|
|
5913
|
-
console.log(item.description);
|
|
6021
|
+
console.log(renderMarkdownTerminal(item.description));
|
|
5914
6022
|
console.log();
|
|
5915
6023
|
}
|
|
5916
6024
|
printAcceptanceCriteria(item.acceptanceCriteria);
|
|
@@ -5926,7 +6034,7 @@ import chalk59 from "chalk";
|
|
|
5926
6034
|
import { WebSocketServer } from "ws";
|
|
5927
6035
|
|
|
5928
6036
|
// src/shared/getInstallDir.ts
|
|
5929
|
-
import { execSync as
|
|
6037
|
+
import { execSync as execSync23 } from "child_process";
|
|
5930
6038
|
import { dirname as dirname16, resolve as resolve7 } from "path";
|
|
5931
6039
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5932
6040
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
@@ -5936,7 +6044,7 @@ function getInstallDir() {
|
|
|
5936
6044
|
}
|
|
5937
6045
|
function isGitRepo(dir) {
|
|
5938
6046
|
try {
|
|
5939
|
-
const result =
|
|
6047
|
+
const result = execSync23("git rev-parse --show-toplevel", {
|
|
5940
6048
|
cwd: dir,
|
|
5941
6049
|
stdio: "pipe"
|
|
5942
6050
|
}).toString().trim();
|
|
@@ -5953,11 +6061,11 @@ import {
|
|
|
5953
6061
|
import chalk54 from "chalk";
|
|
5954
6062
|
|
|
5955
6063
|
// src/lib/openBrowser.ts
|
|
5956
|
-
import { execSync as
|
|
6064
|
+
import { execSync as execSync24 } from "child_process";
|
|
5957
6065
|
function tryExec(commands) {
|
|
5958
6066
|
for (const cmd of commands) {
|
|
5959
6067
|
try {
|
|
5960
|
-
|
|
6068
|
+
execSync24(cmd, { stdio: "ignore" });
|
|
5961
6069
|
return true;
|
|
5962
6070
|
} catch {
|
|
5963
6071
|
}
|
|
@@ -6145,7 +6253,7 @@ function spawnDaemon(reason) {
|
|
|
6145
6253
|
child.unref();
|
|
6146
6254
|
}
|
|
6147
6255
|
function delay(ms) {
|
|
6148
|
-
return new Promise((
|
|
6256
|
+
return new Promise((resolve18) => setTimeout(resolve18, ms));
|
|
6149
6257
|
}
|
|
6150
6258
|
|
|
6151
6259
|
// src/shared/createBundleHandler.ts
|
|
@@ -6355,12 +6463,12 @@ async function loadVisibleItems(req) {
|
|
|
6355
6463
|
|
|
6356
6464
|
// src/commands/backlog/web/parseStatusBody.ts
|
|
6357
6465
|
function readBody(req) {
|
|
6358
|
-
return new Promise((
|
|
6466
|
+
return new Promise((resolve18, reject) => {
|
|
6359
6467
|
let body = "";
|
|
6360
6468
|
req.on("data", (chunk) => {
|
|
6361
6469
|
body += chunk.toString();
|
|
6362
6470
|
});
|
|
6363
|
-
req.on("end", () =>
|
|
6471
|
+
req.on("end", () => resolve18(body));
|
|
6364
6472
|
req.on("error", reject);
|
|
6365
6473
|
});
|
|
6366
6474
|
}
|
|
@@ -7107,17 +7215,17 @@ async function stopDaemon() {
|
|
|
7107
7215
|
}
|
|
7108
7216
|
}
|
|
7109
7217
|
function closedBeforeTimeout(socket) {
|
|
7110
|
-
return new Promise((
|
|
7218
|
+
return new Promise((resolve18) => {
|
|
7111
7219
|
const timer = setTimeout(() => {
|
|
7112
7220
|
socket.destroy();
|
|
7113
|
-
|
|
7221
|
+
resolve18(false);
|
|
7114
7222
|
}, STOP_TIMEOUT_MS);
|
|
7115
7223
|
socket.resume();
|
|
7116
7224
|
socket.on("error", () => {
|
|
7117
7225
|
});
|
|
7118
7226
|
socket.once("close", () => {
|
|
7119
7227
|
clearTimeout(timer);
|
|
7120
|
-
|
|
7228
|
+
resolve18(true);
|
|
7121
7229
|
});
|
|
7122
7230
|
});
|
|
7123
7231
|
}
|
|
@@ -7168,8 +7276,8 @@ async function restartWeb(req, res, deps2 = {}) {
|
|
|
7168
7276
|
respondJson(res, 400, { error: "Invalid target" });
|
|
7169
7277
|
return;
|
|
7170
7278
|
}
|
|
7171
|
-
await new Promise((
|
|
7172
|
-
res.once("finish",
|
|
7279
|
+
await new Promise((resolve18) => {
|
|
7280
|
+
res.once("finish", resolve18);
|
|
7173
7281
|
respondJson(res, 200, { ok: true });
|
|
7174
7282
|
});
|
|
7175
7283
|
if (target === "daemon" || target === "both") {
|
|
@@ -7618,12 +7726,12 @@ import chalk61 from "chalk";
|
|
|
7618
7726
|
import { eq as eq17 } from "drizzle-orm";
|
|
7619
7727
|
|
|
7620
7728
|
// src/commands/jira/fetchIssue.ts
|
|
7621
|
-
import { execSync as
|
|
7729
|
+
import { execSync as execSync25 } from "child_process";
|
|
7622
7730
|
import chalk60 from "chalk";
|
|
7623
7731
|
function fetchIssue(issueKey, fields) {
|
|
7624
7732
|
let result;
|
|
7625
7733
|
try {
|
|
7626
|
-
result =
|
|
7734
|
+
result = execSync25(
|
|
7627
7735
|
`acli jira workitem view ${issueKey} -f ${fields} --json`,
|
|
7628
7736
|
{ encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }
|
|
7629
7737
|
);
|
|
@@ -8225,7 +8333,10 @@ function registerItemCommands(cmd) {
|
|
|
8225
8333
|
"--status <type>",
|
|
8226
8334
|
"Filter by status (todo, in-progress, done, wontdo)"
|
|
8227
8335
|
).option("-a, --all", "Include done/wontdo items").option("--all-repos", "List items across all repositories").option("-v, --verbose", "Show all item details").action(list2);
|
|
8228
|
-
cmd.command("add").description("Add a new backlog item").option("--name <name>", "Item name").option("--type <type>", "Item type (story or bug)").option(
|
|
8336
|
+
cmd.command("add").description("Add a new backlog item").option("--name <name>", "Item name").option("--type <type>", "Item type (story or bug)").option(
|
|
8337
|
+
"--desc <description>",
|
|
8338
|
+
String.raw`Item description (Markdown supported; use \n for line breaks)`
|
|
8339
|
+
).option("--ac <criterion...>", "Acceptance criteria (repeatable)").action(add);
|
|
8229
8340
|
cmd.command("add-phase <id> <name>").description("Add a phase to an existing backlog item").option("--task <task...>", "Task description (repeatable)").option(
|
|
8230
8341
|
"--manual-check <check...>",
|
|
8231
8342
|
"Manual check description (repeatable)"
|
|
@@ -8848,7 +8959,8 @@ async function addSubtask(id2, options2) {
|
|
|
8848
8959
|
return;
|
|
8849
8960
|
}
|
|
8850
8961
|
const { orm, item } = found;
|
|
8851
|
-
|
|
8962
|
+
const description = options2.desc?.replaceAll(String.raw`\n`, "\n");
|
|
8963
|
+
await insertSubtask(orm, item.id, title, description);
|
|
8852
8964
|
console.log(chalk91.green(`Added sub-task to item #${id2}: ${title}`));
|
|
8853
8965
|
}
|
|
8854
8966
|
|
|
@@ -8897,7 +9009,10 @@ async function subtaskStatus(id2, index3, status2) {
|
|
|
8897
9009
|
|
|
8898
9010
|
// src/commands/backlog/registerSubtaskCommands.ts
|
|
8899
9011
|
function registerSubtaskCommands(cmd) {
|
|
8900
|
-
cmd.command("add-subtask <id>").description("Add a sub-task to an existing backlog item").requiredOption("--title <title>", "Sub-task title").option(
|
|
9012
|
+
cmd.command("add-subtask <id>").description("Add a sub-task to an existing backlog item").requiredOption("--title <title>", "Sub-task title").option(
|
|
9013
|
+
"--desc <description>",
|
|
9014
|
+
String.raw`Sub-task description (Markdown supported; use \n for line breaks)`
|
|
9015
|
+
).action(addSubtask);
|
|
8901
9016
|
cmd.command("subtask-status <id> <idx> <status>").description(
|
|
8902
9017
|
"Set a sub-task's status (todo, in-progress, done) by its 1-based index"
|
|
8903
9018
|
).action(subtaskStatus);
|
|
@@ -9272,7 +9387,7 @@ function buildUpdateValues(options2) {
|
|
|
9272
9387
|
fieldNames.push("name");
|
|
9273
9388
|
}
|
|
9274
9389
|
if (desc6) {
|
|
9275
|
-
set.description = desc6;
|
|
9390
|
+
set.description = desc6.replaceAll(String.raw`\n`, "\n");
|
|
9276
9391
|
fieldNames.push("description");
|
|
9277
9392
|
}
|
|
9278
9393
|
if (type) {
|
|
@@ -9320,7 +9435,10 @@ function collect2(value, previous) {
|
|
|
9320
9435
|
return [...previous, value];
|
|
9321
9436
|
}
|
|
9322
9437
|
function registerUpdateCommands(cmd) {
|
|
9323
|
-
cmd.command("update-field <id>").description("Update fields on a backlog item").option("--name <name>", "New item name").option(
|
|
9438
|
+
cmd.command("update-field <id>").description("Update fields on a backlog item").option("--name <name>", "New item name").option(
|
|
9439
|
+
"--desc <description>",
|
|
9440
|
+
String.raw`New description (Markdown supported; use \n for line breaks)`
|
|
9441
|
+
).option("--type <type>", "New type (story or bug)").option("--ac <criterion...>", "Replace acceptance criteria (repeatable)").option(
|
|
9324
9442
|
"--add-ac <text>",
|
|
9325
9443
|
"Append one acceptance criterion (repeatable)",
|
|
9326
9444
|
collect2,
|
|
@@ -9372,40 +9490,6 @@ function registerBacklog(program2) {
|
|
|
9372
9490
|
}
|
|
9373
9491
|
}
|
|
9374
9492
|
|
|
9375
|
-
// src/commands/branch/branch.ts
|
|
9376
|
-
import { execSync as execSync25 } from "child_process";
|
|
9377
|
-
|
|
9378
|
-
// src/commands/branch/buildBranchName.ts
|
|
9379
|
-
function buildBranchName({
|
|
9380
|
-
prefix: prefix2,
|
|
9381
|
-
jira,
|
|
9382
|
-
slug
|
|
9383
|
-
}) {
|
|
9384
|
-
const segments = [];
|
|
9385
|
-
if (prefix2) segments.push(`${prefix2}/`);
|
|
9386
|
-
if (jira) segments.push(`${jira}-`);
|
|
9387
|
-
segments.push(slug);
|
|
9388
|
-
return segments.join("");
|
|
9389
|
-
}
|
|
9390
|
-
|
|
9391
|
-
// src/commands/branch/resolveDefaultBranch.ts
|
|
9392
|
-
import { execSync as execSync24 } from "child_process";
|
|
9393
|
-
var REMOTE_HEAD_REGEX = /^ref:\s+refs\/heads\/(\S+)\s+HEAD$/m;
|
|
9394
|
-
function resolveDefaultBranch(override, cwd) {
|
|
9395
|
-
if (override) return override;
|
|
9396
|
-
try {
|
|
9397
|
-
const output = execSync24("git ls-remote --symref origin HEAD", {
|
|
9398
|
-
encoding: "utf8",
|
|
9399
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
9400
|
-
cwd
|
|
9401
|
-
});
|
|
9402
|
-
const match = output.match(REMOTE_HEAD_REGEX);
|
|
9403
|
-
if (match) return match[1];
|
|
9404
|
-
} catch {
|
|
9405
|
-
}
|
|
9406
|
-
return "main";
|
|
9407
|
-
}
|
|
9408
|
-
|
|
9409
9493
|
// src/commands/branch/validateSlug.ts
|
|
9410
9494
|
var KEBAB_CASE_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
9411
9495
|
var HASH_REF_REGEX = /#\d+/;
|
|
@@ -9433,23 +9517,14 @@ async function branch(slug, options2) {
|
|
|
9433
9517
|
console.error(`Error: ${slugError}`);
|
|
9434
9518
|
process.exit(1);
|
|
9435
9519
|
}
|
|
9436
|
-
const config = loadConfig();
|
|
9437
|
-
const branchName = buildBranchName({
|
|
9438
|
-
prefix: config.branch?.prefix,
|
|
9439
|
-
jira: options2.jira,
|
|
9440
|
-
slug
|
|
9441
|
-
});
|
|
9442
9520
|
try {
|
|
9443
|
-
const defaultBranch =
|
|
9444
|
-
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
{ stdio: "inherit" }
|
|
9448
|
-
);
|
|
9521
|
+
const { branchName, defaultBranch } = await createBranch({
|
|
9522
|
+
slug,
|
|
9523
|
+
jira: options2.jira
|
|
9524
|
+
});
|
|
9449
9525
|
console.log(
|
|
9450
9526
|
`Created and switched to ${branchName} (from origin/${defaultBranch})`
|
|
9451
9527
|
);
|
|
9452
|
-
await recordBranchActivity(branchName);
|
|
9453
9528
|
process.exit(0);
|
|
9454
9529
|
} catch (error) {
|
|
9455
9530
|
console.error(
|
|
@@ -9458,12 +9533,6 @@ async function branch(slug, options2) {
|
|
|
9458
9533
|
process.exit(1);
|
|
9459
9534
|
}
|
|
9460
9535
|
}
|
|
9461
|
-
async function recordBranchActivity(branchName) {
|
|
9462
|
-
if (resolveSessionItemId() === null) return;
|
|
9463
|
-
await recordSessionRefs([
|
|
9464
|
-
{ kind: "branch", ref: branchName, url: gitRefUrl("branch", branchName) }
|
|
9465
|
-
]);
|
|
9466
|
-
}
|
|
9467
9536
|
|
|
9468
9537
|
// src/commands/registerBranch.ts
|
|
9469
9538
|
function registerBranch(program2) {
|
|
@@ -10246,12 +10315,12 @@ function hasSubcommands(helpText) {
|
|
|
10246
10315
|
// src/commands/permitCliReads/runHelp.ts
|
|
10247
10316
|
import { exec as exec2 } from "child_process";
|
|
10248
10317
|
function runHelp(args) {
|
|
10249
|
-
return new Promise((
|
|
10318
|
+
return new Promise((resolve18) => {
|
|
10250
10319
|
exec2(
|
|
10251
10320
|
`${args.join(" ")} --help`,
|
|
10252
10321
|
{ encoding: "utf8", timeout: 3e4 },
|
|
10253
10322
|
(_err, stdout, stderr) => {
|
|
10254
|
-
|
|
10323
|
+
resolve18(stdout || stderr || "");
|
|
10255
10324
|
}
|
|
10256
10325
|
);
|
|
10257
10326
|
});
|
|
@@ -13890,25 +13959,25 @@ function isVisibleText(t) {
|
|
|
13890
13959
|
return /[a-zA-Z]{3,}/.test(t);
|
|
13891
13960
|
}
|
|
13892
13961
|
var isHashtag = (t) => /^#[A-Za-z0-9_]+$/.test(t);
|
|
13893
|
-
function collectRscText(v,
|
|
13962
|
+
function collectRscText(v, resolve18, sink2, seen) {
|
|
13894
13963
|
if (v == null) return;
|
|
13895
13964
|
if (typeof v === "string") {
|
|
13896
13965
|
if (isRscRef(v)) {
|
|
13897
13966
|
if (!seen.has(v)) {
|
|
13898
13967
|
seen.add(v);
|
|
13899
|
-
collectRscText(
|
|
13968
|
+
collectRscText(resolve18(v), resolve18, sink2, seen);
|
|
13900
13969
|
}
|
|
13901
13970
|
} else if (isHashtag(v)) sink2.hashtags.push(v);
|
|
13902
13971
|
else if (isVisibleText(v)) sink2.text.push(v);
|
|
13903
13972
|
return;
|
|
13904
13973
|
}
|
|
13905
13974
|
if (Array.isArray(v)) {
|
|
13906
|
-
for (const x of v) collectRscText(x,
|
|
13975
|
+
for (const x of v) collectRscText(x, resolve18, sink2, seen);
|
|
13907
13976
|
return;
|
|
13908
13977
|
}
|
|
13909
13978
|
if (typeof v === "object") {
|
|
13910
13979
|
for (const val of Object.values(v)) {
|
|
13911
|
-
collectRscText(val,
|
|
13980
|
+
collectRscText(val, resolve18, sink2, seen);
|
|
13912
13981
|
}
|
|
13913
13982
|
}
|
|
13914
13983
|
}
|
|
@@ -13940,7 +14009,7 @@ function visitObjects(root, fn) {
|
|
|
13940
14009
|
}
|
|
13941
14010
|
}
|
|
13942
14011
|
}
|
|
13943
|
-
function buildMentionMap(rows,
|
|
14012
|
+
function buildMentionMap(rows, resolve18) {
|
|
13944
14013
|
const map = /* @__PURE__ */ new Map();
|
|
13945
14014
|
visitObjects(rows, (o) => {
|
|
13946
14015
|
const url = profileActionUrl(o);
|
|
@@ -13948,7 +14017,7 @@ function buildMentionMap(rows, resolve17) {
|
|
|
13948
14017
|
const slug = slugFromProfileUrl(url);
|
|
13949
14018
|
if (!slug || map.has(slug)) return;
|
|
13950
14019
|
const sink2 = { text: [], hashtags: [] };
|
|
13951
|
-
collectRscText(o.children,
|
|
14020
|
+
collectRscText(o.children, resolve18, sink2, /* @__PURE__ */ new Set());
|
|
13952
14021
|
const name = sink2.text.join(" ").replace(/\s+/g, " ").trim();
|
|
13953
14022
|
map.set(slug, name ? { slug, name, url } : { slug, url });
|
|
13954
14023
|
});
|
|
@@ -14034,10 +14103,10 @@ function buildPost(raw, mentionMap, author) {
|
|
|
14034
14103
|
|
|
14035
14104
|
// src/commands/netcap/walkPostRow.ts
|
|
14036
14105
|
var isCommentary = (o) => asObject(o.viewTrackingSpecs)?.viewName === "feed-commentary";
|
|
14037
|
-
function walkPostRow(v,
|
|
14106
|
+
function walkPostRow(v, resolve18, raw) {
|
|
14038
14107
|
if (v == null || typeof v !== "object") return;
|
|
14039
14108
|
if (Array.isArray(v)) {
|
|
14040
|
-
for (const x of v) walkPostRow(x,
|
|
14109
|
+
for (const x of v) walkPostRow(x, resolve18, raw);
|
|
14041
14110
|
return;
|
|
14042
14111
|
}
|
|
14043
14112
|
const o = v;
|
|
@@ -14051,9 +14120,9 @@ function walkPostRow(v, resolve17, raw) {
|
|
|
14051
14120
|
}
|
|
14052
14121
|
if (isCommentary(o)) {
|
|
14053
14122
|
const sink2 = { text: raw.text, hashtags: raw.hashtags };
|
|
14054
|
-
collectRscText(o.children,
|
|
14123
|
+
collectRscText(o.children, resolve18, sink2, /* @__PURE__ */ new Set());
|
|
14055
14124
|
}
|
|
14056
|
-
for (const val of Object.values(o)) walkPostRow(val,
|
|
14125
|
+
for (const val of Object.values(o)) walkPostRow(val, resolve18, raw);
|
|
14057
14126
|
}
|
|
14058
14127
|
|
|
14059
14128
|
// src/commands/netcap/extractLinkedInPosts.ts
|
|
@@ -14067,8 +14136,8 @@ function findCommentaryRows(rows) {
|
|
|
14067
14136
|
}
|
|
14068
14137
|
function extractLinkedInPosts(flight, author = findAuthorSlug(flight)) {
|
|
14069
14138
|
const rows = parseRscRows(flight);
|
|
14070
|
-
const
|
|
14071
|
-
const mentionMap = buildMentionMap(rows,
|
|
14139
|
+
const resolve18 = makeRscResolver(rows);
|
|
14140
|
+
const mentionMap = buildMentionMap(rows, resolve18);
|
|
14072
14141
|
const posts = [];
|
|
14073
14142
|
for (const id2 of findCommentaryRows(rows)) {
|
|
14074
14143
|
const raw = {
|
|
@@ -14078,7 +14147,7 @@ function extractLinkedInPosts(flight, author = findAuthorSlug(flight)) {
|
|
|
14078
14147
|
links: [],
|
|
14079
14148
|
related: []
|
|
14080
14149
|
};
|
|
14081
|
-
walkPostRow(rows[id2],
|
|
14150
|
+
walkPostRow(rows[id2], resolve18, raw);
|
|
14082
14151
|
const post = buildPost(raw, mentionMap, author);
|
|
14083
14152
|
if (post) posts.push(post);
|
|
14084
14153
|
}
|
|
@@ -15957,7 +16026,7 @@ function getViolations(pattern2, options2 = {}, maxLines = DEFAULT_MAX_LINES) {
|
|
|
15957
16026
|
|
|
15958
16027
|
// src/commands/refactor/check/index.ts
|
|
15959
16028
|
function runScript(script, cwd) {
|
|
15960
|
-
return new Promise((
|
|
16029
|
+
return new Promise((resolve18) => {
|
|
15961
16030
|
const child = spawn5("npm", ["run", script], {
|
|
15962
16031
|
stdio: "pipe",
|
|
15963
16032
|
shell: true,
|
|
@@ -15971,7 +16040,7 @@ function runScript(script, cwd) {
|
|
|
15971
16040
|
output += data.toString();
|
|
15972
16041
|
});
|
|
15973
16042
|
child.on("close", (code) => {
|
|
15974
|
-
|
|
16043
|
+
resolve18({ script, code: code ?? 1, output });
|
|
15975
16044
|
});
|
|
15976
16045
|
});
|
|
15977
16046
|
}
|
|
@@ -18717,12 +18786,12 @@ function onCloseResult(ctx, code) {
|
|
|
18717
18786
|
return { ...closed, stderr: ctx.stderr.value, stdout: ctx.stdout.value };
|
|
18718
18787
|
}
|
|
18719
18788
|
function waitForChildExit(ctx) {
|
|
18720
|
-
return new Promise((
|
|
18789
|
+
return new Promise((resolve18) => {
|
|
18721
18790
|
let settled = false;
|
|
18722
18791
|
const settle = (result) => {
|
|
18723
18792
|
if (settled) return;
|
|
18724
18793
|
settled = true;
|
|
18725
|
-
|
|
18794
|
+
resolve18(result);
|
|
18726
18795
|
};
|
|
18727
18796
|
ctx.child.on("error", (err) => settle(onErrorResult(ctx, err)));
|
|
18728
18797
|
ctx.child.on("close", (code) => settle(onCloseResult(ctx, code)));
|
|
@@ -19799,9 +19868,9 @@ function createReadlineInterface() {
|
|
|
19799
19868
|
});
|
|
19800
19869
|
}
|
|
19801
19870
|
function askQuestion(rl, question) {
|
|
19802
|
-
return new Promise((
|
|
19871
|
+
return new Promise((resolve18) => {
|
|
19803
19872
|
rl.question(question, (answer) => {
|
|
19804
|
-
|
|
19873
|
+
resolve18(answer.trim());
|
|
19805
19874
|
});
|
|
19806
19875
|
});
|
|
19807
19876
|
}
|
|
@@ -20449,7 +20518,7 @@ function extractCode(url, expectedState) {
|
|
|
20449
20518
|
return code;
|
|
20450
20519
|
}
|
|
20451
20520
|
function waitForCallback(port, expectedState) {
|
|
20452
|
-
return new Promise((
|
|
20521
|
+
return new Promise((resolve18, reject) => {
|
|
20453
20522
|
const timeout = setTimeout(() => {
|
|
20454
20523
|
server.close();
|
|
20455
20524
|
reject(new Error("Authorization timed out after 120 seconds"));
|
|
@@ -20466,7 +20535,7 @@ function waitForCallback(port, expectedState) {
|
|
|
20466
20535
|
const code = extractCode(url, expectedState);
|
|
20467
20536
|
respondHtml(res, 200, "Authorization successful!");
|
|
20468
20537
|
server.close();
|
|
20469
|
-
|
|
20538
|
+
resolve18(code);
|
|
20470
20539
|
} catch (error) {
|
|
20471
20540
|
respondHtml(res, 400, error.message);
|
|
20472
20541
|
server.close();
|
|
@@ -21215,10 +21284,10 @@ var STATUS_TIMEOUT_MS = 5e3;
|
|
|
21215
21284
|
function queryDaemon(socket) {
|
|
21216
21285
|
socket.write(`${JSON.stringify({ type: "ping" })}
|
|
21217
21286
|
`);
|
|
21218
|
-
return new Promise((
|
|
21287
|
+
return new Promise((resolve18) => {
|
|
21219
21288
|
const result = { sessions: [] };
|
|
21220
21289
|
const pending = /* @__PURE__ */ new Set(["sessions", "pong"]);
|
|
21221
|
-
const timer = setTimeout(() =>
|
|
21290
|
+
const timer = setTimeout(() => resolve18(result), STATUS_TIMEOUT_MS);
|
|
21222
21291
|
const lines = createInterface5({ input: socket });
|
|
21223
21292
|
lines.on("error", () => {
|
|
21224
21293
|
});
|
|
@@ -21226,7 +21295,7 @@ function queryDaemon(socket) {
|
|
|
21226
21295
|
applyLine(result, pending, line);
|
|
21227
21296
|
if (pending.size === 0) {
|
|
21228
21297
|
clearTimeout(timer);
|
|
21229
|
-
|
|
21298
|
+
resolve18(result);
|
|
21230
21299
|
}
|
|
21231
21300
|
});
|
|
21232
21301
|
});
|
|
@@ -21412,8 +21481,8 @@ async function drainDaemon() {
|
|
|
21412
21481
|
function requestDrain(socket) {
|
|
21413
21482
|
socket.write(`${JSON.stringify({ type: "drain" })}
|
|
21414
21483
|
`);
|
|
21415
|
-
return new Promise((
|
|
21416
|
-
const timer = setTimeout(() =>
|
|
21484
|
+
return new Promise((resolve18) => {
|
|
21485
|
+
const timer = setTimeout(() => resolve18(0), DRAIN_TIMEOUT_MS);
|
|
21417
21486
|
const lines = createInterface6({ input: socket });
|
|
21418
21487
|
lines.on("error", () => {
|
|
21419
21488
|
});
|
|
@@ -21422,7 +21491,7 @@ function requestDrain(socket) {
|
|
|
21422
21491
|
const data = JSON.parse(line);
|
|
21423
21492
|
if (data.type === "drained") {
|
|
21424
21493
|
clearTimeout(timer);
|
|
21425
|
-
|
|
21494
|
+
resolve18(data.count ?? 0);
|
|
21426
21495
|
}
|
|
21427
21496
|
} catch {
|
|
21428
21497
|
}
|
|
@@ -22508,7 +22577,7 @@ function windowsDaemonHost() {
|
|
|
22508
22577
|
var CONNECT_TIMEOUT_MS = 2e3;
|
|
22509
22578
|
var KEEPALIVE_PROBE_MS = 1e4;
|
|
22510
22579
|
function connectToWindowsDaemon() {
|
|
22511
|
-
return new Promise((
|
|
22580
|
+
return new Promise((resolve18, reject) => {
|
|
22512
22581
|
const socket = net2.connect(windowsDaemonPort(), windowsDaemonHost());
|
|
22513
22582
|
socket.setTimeout(CONNECT_TIMEOUT_MS);
|
|
22514
22583
|
socket.once("timeout", () => {
|
|
@@ -22518,7 +22587,7 @@ function connectToWindowsDaemon() {
|
|
|
22518
22587
|
socket.once("connect", () => {
|
|
22519
22588
|
socket.setTimeout(0);
|
|
22520
22589
|
socket.setKeepAlive(true, KEEPALIVE_PROBE_MS);
|
|
22521
|
-
|
|
22590
|
+
resolve18(socket);
|
|
22522
22591
|
});
|
|
22523
22592
|
socket.once("error", reject);
|
|
22524
22593
|
});
|
|
@@ -22596,7 +22665,7 @@ async function waitForWindowsDaemon() {
|
|
|
22596
22665
|
);
|
|
22597
22666
|
}
|
|
22598
22667
|
function delay2(ms) {
|
|
22599
|
-
return new Promise((
|
|
22668
|
+
return new Promise((resolve18) => setTimeout(resolve18, ms));
|
|
22600
22669
|
}
|
|
22601
22670
|
|
|
22602
22671
|
// src/commands/sessions/daemon/defaultConnect.ts
|
|
@@ -22844,7 +22913,7 @@ async function healWindowsDaemon() {
|
|
|
22844
22913
|
daemonLog("windows daemon: auto-heal: stale daemon stopped");
|
|
22845
22914
|
}
|
|
22846
22915
|
function runOnWindowsHost(command, timeoutMs) {
|
|
22847
|
-
return new Promise((
|
|
22916
|
+
return new Promise((resolve18, reject) => {
|
|
22848
22917
|
const child = spawn11("pwsh.exe", ["-Command", command], {
|
|
22849
22918
|
stdio: ["ignore", "pipe", "pipe"]
|
|
22850
22919
|
});
|
|
@@ -22864,7 +22933,7 @@ function runOnWindowsHost(command, timeoutMs) {
|
|
|
22864
22933
|
});
|
|
22865
22934
|
child.on("exit", (code) => {
|
|
22866
22935
|
clearTimeout(timer);
|
|
22867
|
-
if (code === 0)
|
|
22936
|
+
if (code === 0) resolve18();
|
|
22868
22937
|
else
|
|
22869
22938
|
reject(
|
|
22870
22939
|
new Error(
|
|
@@ -24133,6 +24202,48 @@ function buildLimitsSegment(rateLimits) {
|
|
|
24133
24202
|
return ` | Limits - ${fiveHr}, ${sevenDay}`;
|
|
24134
24203
|
}
|
|
24135
24204
|
|
|
24205
|
+
// src/commands/readGitBranch.ts
|
|
24206
|
+
import { readFileSync as readFileSync47, statSync as statSync11 } from "fs";
|
|
24207
|
+
import { isAbsolute as isAbsolute2, join as join63, resolve as resolve16 } from "path";
|
|
24208
|
+
function resolveGitDir(cwd) {
|
|
24209
|
+
const dotGit = join63(cwd, ".git");
|
|
24210
|
+
let stat2;
|
|
24211
|
+
try {
|
|
24212
|
+
stat2 = statSync11(dotGit);
|
|
24213
|
+
} catch {
|
|
24214
|
+
return null;
|
|
24215
|
+
}
|
|
24216
|
+
if (stat2.isDirectory()) {
|
|
24217
|
+
return dotGit;
|
|
24218
|
+
}
|
|
24219
|
+
let contents;
|
|
24220
|
+
try {
|
|
24221
|
+
contents = readFileSync47(dotGit, "utf8");
|
|
24222
|
+
} catch {
|
|
24223
|
+
return null;
|
|
24224
|
+
}
|
|
24225
|
+
const match = /^gitdir:\s*(.+)$/m.exec(contents.trim());
|
|
24226
|
+
if (!match) {
|
|
24227
|
+
return null;
|
|
24228
|
+
}
|
|
24229
|
+
const gitDir = match[1].trim();
|
|
24230
|
+
return isAbsolute2(gitDir) ? gitDir : resolve16(cwd, gitDir);
|
|
24231
|
+
}
|
|
24232
|
+
function readGitBranch(cwd) {
|
|
24233
|
+
const gitDir = resolveGitDir(cwd);
|
|
24234
|
+
if (!gitDir) {
|
|
24235
|
+
return null;
|
|
24236
|
+
}
|
|
24237
|
+
let head;
|
|
24238
|
+
try {
|
|
24239
|
+
head = readFileSync47(join63(gitDir, "HEAD"), "utf8");
|
|
24240
|
+
} catch {
|
|
24241
|
+
return null;
|
|
24242
|
+
}
|
|
24243
|
+
const match = /^ref:\s*refs\/heads\/(.+)$/m.exec(head.trim());
|
|
24244
|
+
return match ? match[1] : null;
|
|
24245
|
+
}
|
|
24246
|
+
|
|
24136
24247
|
// src/commands/relayRateLimits.ts
|
|
24137
24248
|
async function relayRateLimits(rateLimits) {
|
|
24138
24249
|
if (!rateLimits) return;
|
|
@@ -24168,8 +24279,11 @@ async function statusLine() {
|
|
|
24168
24279
|
const model = data.model.display_name;
|
|
24169
24280
|
const { total_input_tokens: totalIn, total_output_tokens: totalOut } = data.context_window;
|
|
24170
24281
|
const usedPct = data.context_window.used_percentage ?? 0;
|
|
24282
|
+
const dir = data.workspace?.current_dir ?? data.cwd;
|
|
24283
|
+
const branch2 = dir ? readGitBranch(windowsCwdToWslPath(dir)) : null;
|
|
24284
|
+
const branchSegment = branch2 ? `\u{1F343}\uFE0F ${chalk191.cyan(branch2)} | ` : "";
|
|
24171
24285
|
console.log(
|
|
24172
|
-
`${model} | Tokens - ${formatNumber(totalOut)} \u2191 : ${formatNumber(totalIn)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
|
|
24286
|
+
`${branchSegment}${model} | Tokens - ${formatNumber(totalOut)} \u2191 : ${formatNumber(totalIn)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
|
|
24173
24287
|
);
|
|
24174
24288
|
await relayRateLimits(data.rate_limits);
|
|
24175
24289
|
await relayUsage(data.session_id, totalIn, totalOut);
|