@staff0rd/assist 0.195.1 → 0.195.2
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/index.js +263 -270
- 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.195.
|
|
9
|
+
version: "0.195.2",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -92,7 +92,7 @@ var package_default = {
|
|
|
92
92
|
};
|
|
93
93
|
|
|
94
94
|
// src/commands/backlog/next.ts
|
|
95
|
-
import
|
|
95
|
+
import chalk8 from "chalk";
|
|
96
96
|
import enquirer2 from "enquirer";
|
|
97
97
|
|
|
98
98
|
// src/shared/exitOnCancel.ts
|
|
@@ -768,7 +768,7 @@ function findUnblockedTodos(items) {
|
|
|
768
768
|
}
|
|
769
769
|
|
|
770
770
|
// src/commands/backlog/run.ts
|
|
771
|
-
import
|
|
771
|
+
import chalk7 from "chalk";
|
|
772
772
|
|
|
773
773
|
// src/commands/backlog/buildCommentLines.ts
|
|
774
774
|
function buildCommentLines(comments2) {
|
|
@@ -887,7 +887,7 @@ function buildReviewPhase() {
|
|
|
887
887
|
}
|
|
888
888
|
|
|
889
889
|
// src/commands/backlog/executePhase.ts
|
|
890
|
-
import
|
|
890
|
+
import chalk5 from "chalk";
|
|
891
891
|
|
|
892
892
|
// src/commands/backlog/resolvePhaseResult.ts
|
|
893
893
|
import { existsSync as existsSync6, unlinkSync as unlinkSync2 } from "fs";
|
|
@@ -973,220 +973,8 @@ Phase ${phaseNumber} completed.`));
|
|
|
973
973
|
|
|
974
974
|
// src/commands/backlog/spawnClaude.ts
|
|
975
975
|
import { spawn } from "child_process";
|
|
976
|
-
|
|
977
|
-
// src/shared/loadConfig.ts
|
|
978
|
-
import { existsSync as existsSync8, writeFileSync as writeFileSync5 } from "fs";
|
|
979
|
-
import { homedir } from "os";
|
|
980
|
-
import { dirname, join as join7 } from "path";
|
|
981
|
-
import chalk5 from "chalk";
|
|
982
|
-
import { stringify as stringifyYaml } from "yaml";
|
|
983
|
-
|
|
984
|
-
// src/shared/loadRawYaml.ts
|
|
985
|
-
import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
|
|
986
|
-
import { parse as parseYaml2 } from "yaml";
|
|
987
|
-
function loadRawYaml(path52) {
|
|
988
|
-
if (!existsSync7(path52)) return {};
|
|
989
|
-
try {
|
|
990
|
-
const content = readFileSync6(path52, "utf-8");
|
|
991
|
-
return parseYaml2(content) || {};
|
|
992
|
-
} catch {
|
|
993
|
-
return {};
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
// src/shared/types.ts
|
|
998
|
-
import { z as z2 } from "zod";
|
|
999
|
-
var runParamSchema = z2.strictObject({
|
|
1000
|
-
name: z2.string(),
|
|
1001
|
-
required: z2.boolean().optional(),
|
|
1002
|
-
default: z2.string().optional(),
|
|
1003
|
-
description: z2.string().optional()
|
|
1004
|
-
});
|
|
1005
|
-
var runConfigSchema = z2.strictObject({
|
|
1006
|
-
name: z2.string(),
|
|
1007
|
-
command: z2.string(),
|
|
1008
|
-
args: z2.array(z2.string()).optional(),
|
|
1009
|
-
params: z2.array(runParamSchema).optional(),
|
|
1010
|
-
env: z2.record(z2.string(), z2.string()).optional(),
|
|
1011
|
-
filter: z2.string().optional(),
|
|
1012
|
-
pre: z2.array(z2.string()).optional(),
|
|
1013
|
-
cwd: z2.string().optional()
|
|
1014
|
-
});
|
|
1015
|
-
var runLinkSchema = z2.strictObject({
|
|
1016
|
-
link: z2.string(),
|
|
1017
|
-
prefix: z2.string()
|
|
1018
|
-
});
|
|
1019
|
-
var transcriptConfigSchema = z2.strictObject({
|
|
1020
|
-
vttDir: z2.string(),
|
|
1021
|
-
transcriptsDir: z2.string(),
|
|
1022
|
-
summaryDir: z2.string()
|
|
1023
|
-
});
|
|
1024
|
-
var DEFAULT_WAKE_WORDS = ["computer"];
|
|
1025
|
-
var DEFAULT_MODELS_DIR = "~/.assist/voice/models";
|
|
1026
|
-
var assistConfigSchema = z2.strictObject({
|
|
1027
|
-
commit: z2.strictObject({
|
|
1028
|
-
conventional: z2.boolean().default(false),
|
|
1029
|
-
pull: z2.boolean().default(false),
|
|
1030
|
-
push: z2.boolean().default(false)
|
|
1031
|
-
}).default({ conventional: false, pull: false, push: false }),
|
|
1032
|
-
devlog: z2.strictObject({
|
|
1033
|
-
name: z2.string().optional(),
|
|
1034
|
-
ignore: z2.array(z2.string()).optional(),
|
|
1035
|
-
skip: z2.record(z2.string(), z2.array(z2.string())).optional()
|
|
1036
|
-
}).optional(),
|
|
1037
|
-
notify: z2.strictObject({
|
|
1038
|
-
enabled: z2.boolean().default(true)
|
|
1039
|
-
}).default({ enabled: true }),
|
|
1040
|
-
complexity: z2.strictObject({
|
|
1041
|
-
ignore: z2.array(z2.string()).default(["**/*test.ts*"])
|
|
1042
|
-
}).default({ ignore: ["**/*test.ts*"] }),
|
|
1043
|
-
hardcodedColors: z2.strictObject({
|
|
1044
|
-
ignore: z2.array(z2.string()).default([])
|
|
1045
|
-
}).optional(),
|
|
1046
|
-
restructure: z2.strictObject({
|
|
1047
|
-
ignore: z2.array(z2.string()).default([])
|
|
1048
|
-
}).optional(),
|
|
1049
|
-
jira: z2.strictObject({
|
|
1050
|
-
acField: z2.string().default("customfield_11937")
|
|
1051
|
-
}).optional(),
|
|
1052
|
-
roam: z2.strictObject({
|
|
1053
|
-
clientId: z2.string(),
|
|
1054
|
-
clientSecret: z2.string(),
|
|
1055
|
-
accessToken: z2.string().optional(),
|
|
1056
|
-
refreshToken: z2.string().optional(),
|
|
1057
|
-
tokenExpiresAt: z2.number().optional()
|
|
1058
|
-
}).optional(),
|
|
1059
|
-
run: z2.array(z2.union([runConfigSchema, runLinkSchema])).optional(),
|
|
1060
|
-
transcript: transcriptConfigSchema.optional(),
|
|
1061
|
-
cliReadVerbs: z2.record(z2.string(), z2.array(z2.string())).optional(),
|
|
1062
|
-
news: z2.strictObject({
|
|
1063
|
-
feeds: z2.array(z2.string()).default([])
|
|
1064
|
-
}).default({ feeds: [] }),
|
|
1065
|
-
dotnet: z2.strictObject({
|
|
1066
|
-
inspect: z2.strictObject({
|
|
1067
|
-
suppress: z2.array(z2.string()).default([])
|
|
1068
|
-
}).default({ suppress: [] })
|
|
1069
|
-
}).optional(),
|
|
1070
|
-
ravendb: z2.strictObject({
|
|
1071
|
-
connections: z2.array(
|
|
1072
|
-
z2.strictObject({
|
|
1073
|
-
name: z2.string(),
|
|
1074
|
-
url: z2.string(),
|
|
1075
|
-
database: z2.string(),
|
|
1076
|
-
apiKeyRef: z2.string()
|
|
1077
|
-
})
|
|
1078
|
-
).default([]),
|
|
1079
|
-
defaultConnection: z2.string().optional()
|
|
1080
|
-
}).optional(),
|
|
1081
|
-
seq: z2.strictObject({
|
|
1082
|
-
connections: z2.array(
|
|
1083
|
-
z2.strictObject({
|
|
1084
|
-
name: z2.string(),
|
|
1085
|
-
url: z2.string(),
|
|
1086
|
-
apiToken: z2.string()
|
|
1087
|
-
})
|
|
1088
|
-
).default([]),
|
|
1089
|
-
defaultConnection: z2.string().optional()
|
|
1090
|
-
}).optional(),
|
|
1091
|
-
screenshot: z2.strictObject({
|
|
1092
|
-
outputDir: z2.string().default("./screenshots")
|
|
1093
|
-
}).default({ outputDir: "./screenshots" }),
|
|
1094
|
-
backlog: z2.strictObject({
|
|
1095
|
-
autoCommit: z2.boolean().default(false)
|
|
1096
|
-
}).default({ autoCommit: false }),
|
|
1097
|
-
deny: z2.array(
|
|
1098
|
-
z2.strictObject({
|
|
1099
|
-
pattern: z2.string(),
|
|
1100
|
-
message: z2.string()
|
|
1101
|
-
})
|
|
1102
|
-
).optional(),
|
|
1103
|
-
sync: z2.strictObject({
|
|
1104
|
-
autoConfirm: z2.boolean().default(false)
|
|
1105
|
-
}).default({ autoConfirm: false }),
|
|
1106
|
-
caveman: z2.boolean().default(true),
|
|
1107
|
-
voice: z2.strictObject({
|
|
1108
|
-
wakeWords: z2.array(z2.string()).default(DEFAULT_WAKE_WORDS),
|
|
1109
|
-
mic: z2.string().optional(),
|
|
1110
|
-
cwd: z2.string().optional(),
|
|
1111
|
-
modelsDir: z2.string().default(DEFAULT_MODELS_DIR),
|
|
1112
|
-
lockDir: z2.string().optional(),
|
|
1113
|
-
submitWindows: z2.array(z2.string()).optional(),
|
|
1114
|
-
models: z2.strictObject({
|
|
1115
|
-
vad: z2.string().optional(),
|
|
1116
|
-
smartTurn: z2.string().optional()
|
|
1117
|
-
}).default({})
|
|
1118
|
-
}).default({
|
|
1119
|
-
wakeWords: DEFAULT_WAKE_WORDS,
|
|
1120
|
-
modelsDir: DEFAULT_MODELS_DIR,
|
|
1121
|
-
models: {}
|
|
1122
|
-
})
|
|
1123
|
-
});
|
|
1124
|
-
function isRunLink(entry) {
|
|
1125
|
-
return "link" in entry;
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
// src/shared/loadConfig.ts
|
|
1129
|
-
function findConfigUp(startDir) {
|
|
1130
|
-
let current = startDir;
|
|
1131
|
-
while (current !== dirname(current)) {
|
|
1132
|
-
const claudePath = join7(current, ".claude", "assist.yml");
|
|
1133
|
-
if (existsSync8(claudePath)) return claudePath;
|
|
1134
|
-
const rootPath = join7(current, "assist.yml");
|
|
1135
|
-
if (existsSync8(rootPath)) return rootPath;
|
|
1136
|
-
current = dirname(current);
|
|
1137
|
-
}
|
|
1138
|
-
return null;
|
|
1139
|
-
}
|
|
1140
|
-
function getConfigPath() {
|
|
1141
|
-
const found = findConfigUp(process.cwd());
|
|
1142
|
-
if (found) return found;
|
|
1143
|
-
return join7(process.cwd(), "assist.yml");
|
|
1144
|
-
}
|
|
1145
|
-
function getGlobalConfigPath() {
|
|
1146
|
-
return join7(homedir(), ".assist.yml");
|
|
1147
|
-
}
|
|
1148
|
-
function getConfigDir() {
|
|
1149
|
-
return dirname(getConfigPath());
|
|
1150
|
-
}
|
|
1151
|
-
function loadConfig() {
|
|
1152
|
-
const globalRaw = loadRawYaml(getGlobalConfigPath());
|
|
1153
|
-
const projectRaw = loadRawYaml(getConfigPath());
|
|
1154
|
-
const merged = { ...globalRaw, ...projectRaw };
|
|
1155
|
-
return assistConfigSchema.parse(merged);
|
|
1156
|
-
}
|
|
1157
|
-
function loadProjectConfig() {
|
|
1158
|
-
return loadRawYaml(getConfigPath());
|
|
1159
|
-
}
|
|
1160
|
-
function loadGlobalConfigRaw() {
|
|
1161
|
-
return loadRawYaml(getGlobalConfigPath());
|
|
1162
|
-
}
|
|
1163
|
-
function saveGlobalConfig(config) {
|
|
1164
|
-
writeFileSync5(getGlobalConfigPath(), stringifyYaml(config, { lineWidth: 0 }));
|
|
1165
|
-
}
|
|
1166
|
-
function saveConfig(config) {
|
|
1167
|
-
const configPath = getConfigPath();
|
|
1168
|
-
writeFileSync5(configPath, stringifyYaml(config, { lineWidth: 0 }));
|
|
1169
|
-
}
|
|
1170
|
-
function getTranscriptConfig() {
|
|
1171
|
-
const config = loadConfig();
|
|
1172
|
-
if (!config.transcript) {
|
|
1173
|
-
console.error(
|
|
1174
|
-
chalk5.red(
|
|
1175
|
-
"Transcript directories not configured. Run 'assist transcript configure' first."
|
|
1176
|
-
)
|
|
1177
|
-
);
|
|
1178
|
-
process.exit(1);
|
|
1179
|
-
}
|
|
1180
|
-
return config.transcript;
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
// src/commands/backlog/spawnClaude.ts
|
|
1184
976
|
function spawnClaude(prompt, options2 = {}) {
|
|
1185
|
-
const
|
|
1186
|
-
const finalPrompt = config.caveman ? `/caveman:caveman
|
|
1187
|
-
|
|
1188
|
-
${prompt}` : prompt;
|
|
1189
|
-
const args = [finalPrompt];
|
|
977
|
+
const args = [prompt];
|
|
1190
978
|
if (options2.allowEdits) {
|
|
1191
979
|
args.push("--permission-mode", "acceptEdits");
|
|
1192
980
|
}
|
|
@@ -1201,11 +989,11 @@ ${prompt}` : prompt;
|
|
|
1201
989
|
}
|
|
1202
990
|
|
|
1203
991
|
// src/commands/backlog/watchForMarker.ts
|
|
1204
|
-
import { existsSync as
|
|
992
|
+
import { existsSync as existsSync7, unwatchFile, watchFile } from "fs";
|
|
1205
993
|
function watchForMarker(child) {
|
|
1206
994
|
const statusPath = getSignalPath();
|
|
1207
995
|
watchFile(statusPath, { interval: 1e3 }, () => {
|
|
1208
|
-
if (!
|
|
996
|
+
if (!existsSync7(statusPath)) return;
|
|
1209
997
|
const signal = readSignal();
|
|
1210
998
|
if (signal) {
|
|
1211
999
|
unwatchFile(statusPath);
|
|
@@ -1222,7 +1010,7 @@ async function executePhase(item, phaseIndex, phases, spawnOptions) {
|
|
|
1222
1010
|
const phase = phases[phaseIndex];
|
|
1223
1011
|
const phaseNumber = phaseIndex + 1;
|
|
1224
1012
|
console.log(
|
|
1225
|
-
|
|
1013
|
+
chalk5.bold(
|
|
1226
1014
|
`
|
|
1227
1015
|
--- Phase ${phaseNumber}/${phases.length}: ${phase.name} ---
|
|
1228
1016
|
`
|
|
@@ -1240,7 +1028,7 @@ async function executePhase(item, phaseIndex, phases, spawnOptions) {
|
|
|
1240
1028
|
}
|
|
1241
1029
|
|
|
1242
1030
|
// src/commands/backlog/prepareRun.ts
|
|
1243
|
-
import
|
|
1031
|
+
import chalk6 from "chalk";
|
|
1244
1032
|
|
|
1245
1033
|
// src/commands/backlog/resolvePlan.ts
|
|
1246
1034
|
function resolvePlan(item) {
|
|
@@ -1263,13 +1051,13 @@ function prepareRun(id) {
|
|
|
1263
1051
|
const plan2 = resolvePlan(item);
|
|
1264
1052
|
const startPhase = (item.currentPhase ?? 1) - 1;
|
|
1265
1053
|
if (item.status === "done") {
|
|
1266
|
-
console.log(
|
|
1054
|
+
console.log(chalk6.green(`Already done: #${id}: ${item.name}`));
|
|
1267
1055
|
return void 0;
|
|
1268
1056
|
}
|
|
1269
1057
|
if (startPhase > plan2.length) {
|
|
1270
1058
|
setStatus(id, "done");
|
|
1271
1059
|
console.log(
|
|
1272
|
-
|
|
1060
|
+
chalk6.green(`All phases already complete for #${id}: ${item.name}`)
|
|
1273
1061
|
);
|
|
1274
1062
|
return void 0;
|
|
1275
1063
|
}
|
|
@@ -1294,13 +1082,13 @@ async function run(id, spawnOptions) {
|
|
|
1294
1082
|
}
|
|
1295
1083
|
}
|
|
1296
1084
|
function logProgress(id, name, startPhase, total) {
|
|
1297
|
-
console.log(
|
|
1085
|
+
console.log(chalk7.bold(`Running plan for #${id}: ${name}`));
|
|
1298
1086
|
if (startPhase > 0) {
|
|
1299
1087
|
const phaseNumber = startPhase + 1;
|
|
1300
|
-
console.log(
|
|
1088
|
+
console.log(chalk7.dim(`Resuming from phase ${phaseNumber}/${total}
|
|
1301
1089
|
`));
|
|
1302
1090
|
} else {
|
|
1303
|
-
console.log(
|
|
1091
|
+
console.log(chalk7.dim(`${total} phase(s)
|
|
1304
1092
|
`));
|
|
1305
1093
|
}
|
|
1306
1094
|
}
|
|
@@ -1333,7 +1121,7 @@ async function runReview(item, plan2, spawnOptions) {
|
|
|
1333
1121
|
// src/commands/backlog/next.ts
|
|
1334
1122
|
function toChoice(item, items) {
|
|
1335
1123
|
const name = `${typeLabel(item.type)} #${item.id}: ${item.name}`;
|
|
1336
|
-
return isBlocked(item, items) ? { name, disabled:
|
|
1124
|
+
return isBlocked(item, items) ? { name, disabled: chalk8.red("[blocked]") } : { name };
|
|
1337
1125
|
}
|
|
1338
1126
|
async function selectItem(todo, items) {
|
|
1339
1127
|
const { selected } = await exitOnCancel(
|
|
@@ -1350,7 +1138,7 @@ async function pickItem(items, firstPick = false) {
|
|
|
1350
1138
|
const resumable = findResumable(items);
|
|
1351
1139
|
if (resumable) {
|
|
1352
1140
|
console.log(
|
|
1353
|
-
|
|
1141
|
+
chalk8.bold(
|
|
1354
1142
|
`Resuming in-progress item #${resumable.id}: ${resumable.name}`
|
|
1355
1143
|
)
|
|
1356
1144
|
);
|
|
@@ -1360,7 +1148,7 @@ async function pickItem(items, firstPick = false) {
|
|
|
1360
1148
|
if (!unblocked) return void 0;
|
|
1361
1149
|
if (firstPick && unblocked.length === 1) {
|
|
1362
1150
|
const item = unblocked[0];
|
|
1363
|
-
console.log(
|
|
1151
|
+
console.log(chalk8.bold(`Auto-selecting item #${item.id}: ${item.name}`));
|
|
1364
1152
|
return String(item.id);
|
|
1365
1153
|
}
|
|
1366
1154
|
const todo = items.filter((i) => i.status === "todo");
|
|
@@ -1378,7 +1166,7 @@ async function next(options2) {
|
|
|
1378
1166
|
}
|
|
1379
1167
|
|
|
1380
1168
|
// src/commands/backlog/phaseDone.ts
|
|
1381
|
-
import
|
|
1169
|
+
import chalk9 from "chalk";
|
|
1382
1170
|
|
|
1383
1171
|
// src/commands/backlog/addComment.ts
|
|
1384
1172
|
function addComment(item, text, phase) {
|
|
@@ -1413,7 +1201,7 @@ function phaseDone(id, phase, summary) {
|
|
|
1413
1201
|
});
|
|
1414
1202
|
const result = loadAndFindItem(id);
|
|
1415
1203
|
if (result?.item.status === "done") {
|
|
1416
|
-
console.log(
|
|
1204
|
+
console.log(chalk9.dim(`Item #${id} already done, skipping phase advance.`));
|
|
1417
1205
|
return;
|
|
1418
1206
|
}
|
|
1419
1207
|
if (result) {
|
|
@@ -1422,24 +1210,24 @@ function phaseDone(id, phase, summary) {
|
|
|
1422
1210
|
}
|
|
1423
1211
|
setCurrentPhase(id, phaseNumber + 1);
|
|
1424
1212
|
console.log(
|
|
1425
|
-
|
|
1213
|
+
chalk9.green(`Phase ${phaseNumber} of item #${id} marked as complete.`)
|
|
1426
1214
|
);
|
|
1427
1215
|
}
|
|
1428
1216
|
|
|
1429
1217
|
// src/commands/backlog/plan.ts
|
|
1430
|
-
import
|
|
1218
|
+
import chalk10 from "chalk";
|
|
1431
1219
|
function plan(id) {
|
|
1432
1220
|
const result = loadAndFindItem(id);
|
|
1433
1221
|
if (!result) return;
|
|
1434
1222
|
const { item } = result;
|
|
1435
1223
|
if (!item.plan || item.plan.length === 0) {
|
|
1436
|
-
console.log(
|
|
1224
|
+
console.log(chalk10.dim("No plan defined for this item."));
|
|
1437
1225
|
return;
|
|
1438
1226
|
}
|
|
1439
|
-
console.log(
|
|
1227
|
+
console.log(chalk10.bold(item.name));
|
|
1440
1228
|
console.log();
|
|
1441
1229
|
for (const [i, phase] of item.plan.entries()) {
|
|
1442
|
-
console.log(`${
|
|
1230
|
+
console.log(`${chalk10.bold(`Phase ${i + 1}:`)} ${phase.name}`);
|
|
1443
1231
|
for (const task of phase.tasks) {
|
|
1444
1232
|
console.log(` - ${task.task}`);
|
|
1445
1233
|
}
|
|
@@ -1448,35 +1236,35 @@ function plan(id) {
|
|
|
1448
1236
|
}
|
|
1449
1237
|
|
|
1450
1238
|
// src/commands/backlog/show/index.ts
|
|
1451
|
-
import
|
|
1239
|
+
import chalk14 from "chalk";
|
|
1452
1240
|
|
|
1453
1241
|
// src/commands/backlog/formatComment.ts
|
|
1454
|
-
import
|
|
1242
|
+
import chalk11 from "chalk";
|
|
1455
1243
|
function formatComment(entry) {
|
|
1456
|
-
const id = entry.id !== void 0 ?
|
|
1457
|
-
const tag = entry.type === "summary" ?
|
|
1458
|
-
const phase = entry.phase !== void 0 ?
|
|
1459
|
-
const time =
|
|
1244
|
+
const id = entry.id !== void 0 ? chalk11.dim(`#${entry.id} `) : "";
|
|
1245
|
+
const tag = entry.type === "summary" ? chalk11.magenta("[summary]") : chalk11.cyan("[comment]");
|
|
1246
|
+
const phase = entry.phase !== void 0 ? chalk11.dim(` (phase ${entry.phase})`) : "";
|
|
1247
|
+
const time = chalk11.dim(entry.timestamp);
|
|
1460
1248
|
return `${id}${tag}${phase} ${time}
|
|
1461
1249
|
${entry.text}`;
|
|
1462
1250
|
}
|
|
1463
1251
|
|
|
1464
1252
|
// src/commands/backlog/show/printLinks.ts
|
|
1465
|
-
import
|
|
1253
|
+
import chalk12 from "chalk";
|
|
1466
1254
|
function printLinks(item, items) {
|
|
1467
1255
|
const links = item.links ?? [];
|
|
1468
1256
|
if (links.length === 0) return;
|
|
1469
|
-
console.log(
|
|
1257
|
+
console.log(chalk12.bold("Links"));
|
|
1470
1258
|
for (const link3 of links) {
|
|
1471
1259
|
const target = items.find((i) => i.id === link3.targetId);
|
|
1472
|
-
const typeLabel2 = link3.type === "depends-on" ?
|
|
1260
|
+
const typeLabel2 = link3.type === "depends-on" ? chalk12.red("depends-on") : chalk12.blue("relates-to");
|
|
1473
1261
|
if (target) {
|
|
1474
1262
|
console.log(
|
|
1475
|
-
` ${typeLabel2} #${target.id} ${target.name} ${
|
|
1263
|
+
` ${typeLabel2} #${target.id} ${target.name} ${chalk12.dim(`(${target.status})`)}`
|
|
1476
1264
|
);
|
|
1477
1265
|
} else {
|
|
1478
1266
|
console.log(
|
|
1479
|
-
` ${typeLabel2} #${link3.targetId} ${
|
|
1267
|
+
` ${typeLabel2} #${link3.targetId} ${chalk12.dim("(not found)")}`
|
|
1480
1268
|
);
|
|
1481
1269
|
}
|
|
1482
1270
|
}
|
|
@@ -1484,15 +1272,15 @@ function printLinks(item, items) {
|
|
|
1484
1272
|
}
|
|
1485
1273
|
|
|
1486
1274
|
// src/commands/backlog/show/printPhaseTasks.ts
|
|
1487
|
-
import
|
|
1275
|
+
import chalk13 from "chalk";
|
|
1488
1276
|
function printPhaseTasks(phase) {
|
|
1489
1277
|
for (const task of phase.tasks) {
|
|
1490
1278
|
console.log(` - ${task.task}`);
|
|
1491
1279
|
}
|
|
1492
1280
|
if (phase.manualChecks && phase.manualChecks.length > 0) {
|
|
1493
|
-
console.log(` ${
|
|
1281
|
+
console.log(` ${chalk13.dim("Manual checks:")}`);
|
|
1494
1282
|
for (const check2 of phase.manualChecks) {
|
|
1495
|
-
console.log(` ${
|
|
1283
|
+
console.log(` ${chalk13.dim(`- ${check2}`)}`);
|
|
1496
1284
|
}
|
|
1497
1285
|
}
|
|
1498
1286
|
}
|
|
@@ -1500,7 +1288,7 @@ function printPhaseTasks(phase) {
|
|
|
1500
1288
|
// src/commands/backlog/show/index.ts
|
|
1501
1289
|
function printPlan(item) {
|
|
1502
1290
|
if (!item.plan || item.plan.length === 0) return;
|
|
1503
|
-
console.log(
|
|
1291
|
+
console.log(chalk14.bold("Plan"));
|
|
1504
1292
|
for (const [i, phase] of item.plan.entries()) {
|
|
1505
1293
|
const isCurrent = item.currentPhase === i + 1;
|
|
1506
1294
|
printPhase(phase, i, isCurrent);
|
|
@@ -1509,8 +1297,8 @@ function printPlan(item) {
|
|
|
1509
1297
|
}
|
|
1510
1298
|
function phaseHeader(index, name, isCurrent) {
|
|
1511
1299
|
const phaseNumber = index + 1;
|
|
1512
|
-
const marker = isCurrent ?
|
|
1513
|
-
const label2 = isCurrent ?
|
|
1300
|
+
const marker = isCurrent ? chalk14.green("\u25B6 ") : " ";
|
|
1301
|
+
const label2 = isCurrent ? chalk14.green.bold(`Phase ${phaseNumber}: ${name}`) : `${chalk14.bold(`Phase ${phaseNumber}:`)} ${name}`;
|
|
1514
1302
|
return `${marker}${label2}`;
|
|
1515
1303
|
}
|
|
1516
1304
|
function printPhase(phase, index, isCurrent) {
|
|
@@ -1518,15 +1306,15 @@ function printPhase(phase, index, isCurrent) {
|
|
|
1518
1306
|
printPhaseTasks(phase);
|
|
1519
1307
|
}
|
|
1520
1308
|
function printHeader(item) {
|
|
1521
|
-
console.log(
|
|
1309
|
+
console.log(chalk14.bold(`#${item.id} ${item.name}`));
|
|
1522
1310
|
console.log(
|
|
1523
|
-
`${
|
|
1311
|
+
`${chalk14.dim("Type:")} ${item.type} ${chalk14.dim("Status:")} ${item.status}`
|
|
1524
1312
|
);
|
|
1525
1313
|
console.log();
|
|
1526
1314
|
}
|
|
1527
1315
|
function printAcceptanceCriteria(criteria) {
|
|
1528
1316
|
if (criteria.length === 0) return;
|
|
1529
|
-
console.log(
|
|
1317
|
+
console.log(chalk14.bold("Acceptance Criteria"));
|
|
1530
1318
|
for (const [i, ac] of criteria.entries()) {
|
|
1531
1319
|
console.log(` ${i + 1}. ${ac}`);
|
|
1532
1320
|
}
|
|
@@ -1538,7 +1326,7 @@ function show(id) {
|
|
|
1538
1326
|
const { item, items } = result;
|
|
1539
1327
|
printHeader(item);
|
|
1540
1328
|
if (item.description) {
|
|
1541
|
-
console.log(
|
|
1329
|
+
console.log(chalk14.bold("Description"));
|
|
1542
1330
|
console.log(item.description);
|
|
1543
1331
|
console.log();
|
|
1544
1332
|
}
|
|
@@ -1550,7 +1338,7 @@ function show(id) {
|
|
|
1550
1338
|
function printComments(item) {
|
|
1551
1339
|
const entries = item.comments ?? [];
|
|
1552
1340
|
if (entries.length === 0) return;
|
|
1553
|
-
console.log(
|
|
1341
|
+
console.log(chalk14.bold("Comments"));
|
|
1554
1342
|
for (const entry of entries) {
|
|
1555
1343
|
console.log(` ${formatComment(entry)}`);
|
|
1556
1344
|
}
|
|
@@ -1559,23 +1347,23 @@ function printComments(item) {
|
|
|
1559
1347
|
|
|
1560
1348
|
// src/shared/web.ts
|
|
1561
1349
|
import { exec } from "child_process";
|
|
1562
|
-
import { readFileSync as
|
|
1350
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
1563
1351
|
import {
|
|
1564
1352
|
createServer
|
|
1565
1353
|
} from "http";
|
|
1566
|
-
import { dirname
|
|
1354
|
+
import { dirname, join as join7 } from "path";
|
|
1567
1355
|
import { fileURLToPath } from "url";
|
|
1568
|
-
import
|
|
1356
|
+
import chalk15 from "chalk";
|
|
1569
1357
|
function respondJson(res, status2, data) {
|
|
1570
1358
|
res.writeHead(status2, { "Content-Type": "application/json" });
|
|
1571
1359
|
res.end(JSON.stringify(data));
|
|
1572
1360
|
}
|
|
1573
1361
|
function createBundleHandler(importMetaUrl, bundlePath) {
|
|
1574
|
-
const dir =
|
|
1362
|
+
const dir = dirname(fileURLToPath(importMetaUrl));
|
|
1575
1363
|
let cache;
|
|
1576
1364
|
return (_req, res) => {
|
|
1577
1365
|
if (!cache) {
|
|
1578
|
-
cache =
|
|
1366
|
+
cache = readFileSync6(join7(dir, bundlePath), "utf-8");
|
|
1579
1367
|
}
|
|
1580
1368
|
res.writeHead(200, { "Content-Type": "application/javascript" });
|
|
1581
1369
|
res.end(cache);
|
|
@@ -1609,8 +1397,8 @@ function startWebServer(label2, port, handler) {
|
|
|
1609
1397
|
handler(req, res, port);
|
|
1610
1398
|
});
|
|
1611
1399
|
server.listen(port, () => {
|
|
1612
|
-
console.log(
|
|
1613
|
-
console.log(
|
|
1400
|
+
console.log(chalk15.green(`${label2}: ${url}`));
|
|
1401
|
+
console.log(chalk15.dim("Press Ctrl+C to stop"));
|
|
1614
1402
|
exec(`open ${url}`);
|
|
1615
1403
|
});
|
|
1616
1404
|
return server;
|
|
@@ -1825,7 +1613,7 @@ async function web(options2) {
|
|
|
1825
1613
|
}
|
|
1826
1614
|
|
|
1827
1615
|
// src/commands/backlog/launchMode.ts
|
|
1828
|
-
import
|
|
1616
|
+
import chalk16 from "chalk";
|
|
1829
1617
|
async function launchMode(slashCommand) {
|
|
1830
1618
|
process.env.ASSIST_SESSION_ID = String(process.pid);
|
|
1831
1619
|
const { child, done: done2 } = spawnClaude(`/${slashCommand}`, { allowEdits: true });
|
|
@@ -1835,13 +1623,13 @@ async function launchMode(slashCommand) {
|
|
|
1835
1623
|
const signal = readSignal();
|
|
1836
1624
|
cleanupSignal();
|
|
1837
1625
|
if (signal?.event === "next") {
|
|
1838
|
-
console.log(
|
|
1626
|
+
console.log(chalk16.bold("\nChaining into assist next...\n"));
|
|
1839
1627
|
await next({ allowEdits: true });
|
|
1840
1628
|
}
|
|
1841
1629
|
}
|
|
1842
1630
|
|
|
1843
1631
|
// src/commands/backlog/refine.ts
|
|
1844
|
-
import
|
|
1632
|
+
import chalk17 from "chalk";
|
|
1845
1633
|
import enquirer3 from "enquirer";
|
|
1846
1634
|
async function pickItemForRefine() {
|
|
1847
1635
|
const items = loadBacklog();
|
|
@@ -1849,12 +1637,12 @@ async function pickItemForRefine() {
|
|
|
1849
1637
|
(i) => i.status === "todo" || i.status === "in-progress"
|
|
1850
1638
|
);
|
|
1851
1639
|
if (active.length === 0) {
|
|
1852
|
-
console.log(
|
|
1640
|
+
console.log(chalk17.yellow("No active backlog items to refine."));
|
|
1853
1641
|
return void 0;
|
|
1854
1642
|
}
|
|
1855
1643
|
if (active.length === 1) {
|
|
1856
1644
|
const item = active[0];
|
|
1857
|
-
console.log(
|
|
1645
|
+
console.log(chalk17.bold(`Auto-selecting item #${item.id}: ${item.name}`));
|
|
1858
1646
|
return String(item.id);
|
|
1859
1647
|
}
|
|
1860
1648
|
const { selected } = await exitOnCancel(
|
|
@@ -1878,6 +1666,211 @@ async function refine(id) {
|
|
|
1878
1666
|
// src/commands/commit.ts
|
|
1879
1667
|
import { execSync } from "child_process";
|
|
1880
1668
|
|
|
1669
|
+
// src/shared/loadConfig.ts
|
|
1670
|
+
import { existsSync as existsSync9, writeFileSync as writeFileSync5 } from "fs";
|
|
1671
|
+
import { homedir } from "os";
|
|
1672
|
+
import { dirname as dirname2, join as join8 } from "path";
|
|
1673
|
+
import chalk18 from "chalk";
|
|
1674
|
+
import { stringify as stringifyYaml } from "yaml";
|
|
1675
|
+
|
|
1676
|
+
// src/shared/loadRawYaml.ts
|
|
1677
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
|
|
1678
|
+
import { parse as parseYaml2 } from "yaml";
|
|
1679
|
+
function loadRawYaml(path52) {
|
|
1680
|
+
if (!existsSync8(path52)) return {};
|
|
1681
|
+
try {
|
|
1682
|
+
const content = readFileSync7(path52, "utf-8");
|
|
1683
|
+
return parseYaml2(content) || {};
|
|
1684
|
+
} catch {
|
|
1685
|
+
return {};
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
// src/shared/types.ts
|
|
1690
|
+
import { z as z2 } from "zod";
|
|
1691
|
+
var runParamSchema = z2.strictObject({
|
|
1692
|
+
name: z2.string(),
|
|
1693
|
+
required: z2.boolean().optional(),
|
|
1694
|
+
default: z2.string().optional(),
|
|
1695
|
+
description: z2.string().optional()
|
|
1696
|
+
});
|
|
1697
|
+
var runConfigSchema = z2.strictObject({
|
|
1698
|
+
name: z2.string(),
|
|
1699
|
+
command: z2.string(),
|
|
1700
|
+
args: z2.array(z2.string()).optional(),
|
|
1701
|
+
params: z2.array(runParamSchema).optional(),
|
|
1702
|
+
env: z2.record(z2.string(), z2.string()).optional(),
|
|
1703
|
+
filter: z2.string().optional(),
|
|
1704
|
+
pre: z2.array(z2.string()).optional(),
|
|
1705
|
+
cwd: z2.string().optional()
|
|
1706
|
+
});
|
|
1707
|
+
var runLinkSchema = z2.strictObject({
|
|
1708
|
+
link: z2.string(),
|
|
1709
|
+
prefix: z2.string()
|
|
1710
|
+
});
|
|
1711
|
+
var transcriptConfigSchema = z2.strictObject({
|
|
1712
|
+
vttDir: z2.string(),
|
|
1713
|
+
transcriptsDir: z2.string(),
|
|
1714
|
+
summaryDir: z2.string()
|
|
1715
|
+
});
|
|
1716
|
+
var DEFAULT_WAKE_WORDS = ["computer"];
|
|
1717
|
+
var DEFAULT_MODELS_DIR = "~/.assist/voice/models";
|
|
1718
|
+
var assistConfigSchema = z2.strictObject({
|
|
1719
|
+
commit: z2.strictObject({
|
|
1720
|
+
conventional: z2.boolean().default(false),
|
|
1721
|
+
pull: z2.boolean().default(false),
|
|
1722
|
+
push: z2.boolean().default(false)
|
|
1723
|
+
}).default({ conventional: false, pull: false, push: false }),
|
|
1724
|
+
devlog: z2.strictObject({
|
|
1725
|
+
name: z2.string().optional(),
|
|
1726
|
+
ignore: z2.array(z2.string()).optional(),
|
|
1727
|
+
skip: z2.record(z2.string(), z2.array(z2.string())).optional()
|
|
1728
|
+
}).optional(),
|
|
1729
|
+
notify: z2.strictObject({
|
|
1730
|
+
enabled: z2.boolean().default(true)
|
|
1731
|
+
}).default({ enabled: true }),
|
|
1732
|
+
complexity: z2.strictObject({
|
|
1733
|
+
ignore: z2.array(z2.string()).default(["**/*test.ts*"])
|
|
1734
|
+
}).default({ ignore: ["**/*test.ts*"] }),
|
|
1735
|
+
hardcodedColors: z2.strictObject({
|
|
1736
|
+
ignore: z2.array(z2.string()).default([])
|
|
1737
|
+
}).optional(),
|
|
1738
|
+
restructure: z2.strictObject({
|
|
1739
|
+
ignore: z2.array(z2.string()).default([])
|
|
1740
|
+
}).optional(),
|
|
1741
|
+
jira: z2.strictObject({
|
|
1742
|
+
acField: z2.string().default("customfield_11937")
|
|
1743
|
+
}).optional(),
|
|
1744
|
+
roam: z2.strictObject({
|
|
1745
|
+
clientId: z2.string(),
|
|
1746
|
+
clientSecret: z2.string(),
|
|
1747
|
+
accessToken: z2.string().optional(),
|
|
1748
|
+
refreshToken: z2.string().optional(),
|
|
1749
|
+
tokenExpiresAt: z2.number().optional()
|
|
1750
|
+
}).optional(),
|
|
1751
|
+
run: z2.array(z2.union([runConfigSchema, runLinkSchema])).optional(),
|
|
1752
|
+
transcript: transcriptConfigSchema.optional(),
|
|
1753
|
+
cliReadVerbs: z2.record(z2.string(), z2.array(z2.string())).optional(),
|
|
1754
|
+
news: z2.strictObject({
|
|
1755
|
+
feeds: z2.array(z2.string()).default([])
|
|
1756
|
+
}).default({ feeds: [] }),
|
|
1757
|
+
dotnet: z2.strictObject({
|
|
1758
|
+
inspect: z2.strictObject({
|
|
1759
|
+
suppress: z2.array(z2.string()).default([])
|
|
1760
|
+
}).default({ suppress: [] })
|
|
1761
|
+
}).optional(),
|
|
1762
|
+
ravendb: z2.strictObject({
|
|
1763
|
+
connections: z2.array(
|
|
1764
|
+
z2.strictObject({
|
|
1765
|
+
name: z2.string(),
|
|
1766
|
+
url: z2.string(),
|
|
1767
|
+
database: z2.string(),
|
|
1768
|
+
apiKeyRef: z2.string()
|
|
1769
|
+
})
|
|
1770
|
+
).default([]),
|
|
1771
|
+
defaultConnection: z2.string().optional()
|
|
1772
|
+
}).optional(),
|
|
1773
|
+
seq: z2.strictObject({
|
|
1774
|
+
connections: z2.array(
|
|
1775
|
+
z2.strictObject({
|
|
1776
|
+
name: z2.string(),
|
|
1777
|
+
url: z2.string(),
|
|
1778
|
+
apiToken: z2.string()
|
|
1779
|
+
})
|
|
1780
|
+
).default([]),
|
|
1781
|
+
defaultConnection: z2.string().optional()
|
|
1782
|
+
}).optional(),
|
|
1783
|
+
screenshot: z2.strictObject({
|
|
1784
|
+
outputDir: z2.string().default("./screenshots")
|
|
1785
|
+
}).default({ outputDir: "./screenshots" }),
|
|
1786
|
+
backlog: z2.strictObject({
|
|
1787
|
+
autoCommit: z2.boolean().default(false)
|
|
1788
|
+
}).default({ autoCommit: false }),
|
|
1789
|
+
deny: z2.array(
|
|
1790
|
+
z2.strictObject({
|
|
1791
|
+
pattern: z2.string(),
|
|
1792
|
+
message: z2.string()
|
|
1793
|
+
})
|
|
1794
|
+
).optional(),
|
|
1795
|
+
sync: z2.strictObject({
|
|
1796
|
+
autoConfirm: z2.boolean().default(false)
|
|
1797
|
+
}).default({ autoConfirm: false }),
|
|
1798
|
+
voice: z2.strictObject({
|
|
1799
|
+
wakeWords: z2.array(z2.string()).default(DEFAULT_WAKE_WORDS),
|
|
1800
|
+
mic: z2.string().optional(),
|
|
1801
|
+
cwd: z2.string().optional(),
|
|
1802
|
+
modelsDir: z2.string().default(DEFAULT_MODELS_DIR),
|
|
1803
|
+
lockDir: z2.string().optional(),
|
|
1804
|
+
submitWindows: z2.array(z2.string()).optional(),
|
|
1805
|
+
models: z2.strictObject({
|
|
1806
|
+
vad: z2.string().optional(),
|
|
1807
|
+
smartTurn: z2.string().optional()
|
|
1808
|
+
}).default({})
|
|
1809
|
+
}).default({
|
|
1810
|
+
wakeWords: DEFAULT_WAKE_WORDS,
|
|
1811
|
+
modelsDir: DEFAULT_MODELS_DIR,
|
|
1812
|
+
models: {}
|
|
1813
|
+
})
|
|
1814
|
+
});
|
|
1815
|
+
function isRunLink(entry) {
|
|
1816
|
+
return "link" in entry;
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
// src/shared/loadConfig.ts
|
|
1820
|
+
function findConfigUp(startDir) {
|
|
1821
|
+
let current = startDir;
|
|
1822
|
+
while (current !== dirname2(current)) {
|
|
1823
|
+
const claudePath = join8(current, ".claude", "assist.yml");
|
|
1824
|
+
if (existsSync9(claudePath)) return claudePath;
|
|
1825
|
+
const rootPath = join8(current, "assist.yml");
|
|
1826
|
+
if (existsSync9(rootPath)) return rootPath;
|
|
1827
|
+
current = dirname2(current);
|
|
1828
|
+
}
|
|
1829
|
+
return null;
|
|
1830
|
+
}
|
|
1831
|
+
function getConfigPath() {
|
|
1832
|
+
const found = findConfigUp(process.cwd());
|
|
1833
|
+
if (found) return found;
|
|
1834
|
+
return join8(process.cwd(), "assist.yml");
|
|
1835
|
+
}
|
|
1836
|
+
function getGlobalConfigPath() {
|
|
1837
|
+
return join8(homedir(), ".assist.yml");
|
|
1838
|
+
}
|
|
1839
|
+
function getConfigDir() {
|
|
1840
|
+
return dirname2(getConfigPath());
|
|
1841
|
+
}
|
|
1842
|
+
function loadConfig() {
|
|
1843
|
+
const globalRaw = loadRawYaml(getGlobalConfigPath());
|
|
1844
|
+
const projectRaw = loadRawYaml(getConfigPath());
|
|
1845
|
+
const merged = { ...globalRaw, ...projectRaw };
|
|
1846
|
+
return assistConfigSchema.parse(merged);
|
|
1847
|
+
}
|
|
1848
|
+
function loadProjectConfig() {
|
|
1849
|
+
return loadRawYaml(getConfigPath());
|
|
1850
|
+
}
|
|
1851
|
+
function loadGlobalConfigRaw() {
|
|
1852
|
+
return loadRawYaml(getGlobalConfigPath());
|
|
1853
|
+
}
|
|
1854
|
+
function saveGlobalConfig(config) {
|
|
1855
|
+
writeFileSync5(getGlobalConfigPath(), stringifyYaml(config, { lineWidth: 0 }));
|
|
1856
|
+
}
|
|
1857
|
+
function saveConfig(config) {
|
|
1858
|
+
const configPath = getConfigPath();
|
|
1859
|
+
writeFileSync5(configPath, stringifyYaml(config, { lineWidth: 0 }));
|
|
1860
|
+
}
|
|
1861
|
+
function getTranscriptConfig() {
|
|
1862
|
+
const config = loadConfig();
|
|
1863
|
+
if (!config.transcript) {
|
|
1864
|
+
console.error(
|
|
1865
|
+
chalk18.red(
|
|
1866
|
+
"Transcript directories not configured. Run 'assist transcript configure' first."
|
|
1867
|
+
)
|
|
1868
|
+
);
|
|
1869
|
+
process.exit(1);
|
|
1870
|
+
}
|
|
1871
|
+
return config.transcript;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1881
1874
|
// src/shared/shellQuote.ts
|
|
1882
1875
|
function shellQuote(arg) {
|
|
1883
1876
|
if (/[^a-zA-Z0-9_./:=@%^+,-]/.test(arg)) {
|