@wrongstack/cli 0.6.3 → 0.6.5
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 +1202 -121
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import * as path23 from 'path';
|
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import * as fsp2 from 'fs/promises';
|
|
5
5
|
import { readdir, readFile } from 'fs/promises';
|
|
6
|
-
import { color, DefaultPathResolver, TOKENS, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, SlashCommandRegistry, createDelegateTool, FLEET_ROSTER, createMcpControlTool, EternalAutonomyEngine, DefaultLogger, DefaultModelsRegistry, ProviderRegistry, InMemoryMetricsSink, wireMetricsToEvents, DefaultHealthRegistry, startMetricsServer, RecoveryLock, DefaultAttachmentStore, QueueStore, Context, loadTodosCheckpoint, attachTodosCheckpoint, loadDirectorState, loadPlan, createDefaultPipelines, AutoCompactionMiddleware, estimateRequestTokens, Agent, loadPlugins, FleetManager, makeDirectorSessionFactory, Director, makeAgentSubagentRunner, NULL_FLEET_BUS, resolveWstackPaths, DefaultSecretVault, migratePlaintextSecrets, DefaultConfigLoader, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, atomicWrite, DefaultPluginAPI, AutoApprovePermissionPolicy, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, formatTodosList, emptyPlan, clearPlan, savePlan, formatPlanTemplates, getPlanTemplate, addPlanItem, formatPlan, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, SpecStore, TaskGraphStore, SpecVersioning, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, DefaultTaskStore, TaskTracker, loadGoal, goalFilePath, summarizeUsage,
|
|
6
|
+
import { color, DefaultPathResolver, TOKENS, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, SlashCommandRegistry, createDelegateTool, FLEET_ROSTER, createMcpControlTool, EternalAutonomyEngine, DefaultLogger, DefaultModelsRegistry, ProviderRegistry, InMemoryMetricsSink, wireMetricsToEvents, DefaultHealthRegistry, startMetricsServer, RecoveryLock, DefaultAttachmentStore, QueueStore, Context, loadTodosCheckpoint, attachTodosCheckpoint, loadDirectorState, loadPlan, createDefaultPipelines, AutoCompactionMiddleware, estimateRequestTokens, Agent, loadPlugins, FleetManager, makeDirectorSessionFactory, Director, makeAgentSubagentRunner, NULL_FLEET_BUS, resolveWstackPaths, DefaultSecretVault, migratePlaintextSecrets, DefaultConfigLoader, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, atomicWrite, DefaultPluginAPI, AutoApprovePermissionPolicy, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, formatTodosList, emptyPlan, clearPlan, savePlan, formatPlanTemplates, getPlanTemplate, addPlanItem, formatPlan, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, SpecStore, TaskGraphStore, SpecVersioning, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, DefaultTaskStore, TaskTracker, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, InputBuilder, projectHash, defaultOrchestrator, decryptConfigSecrets, encryptConfigSecrets as encryptConfigSecrets$1, ParallelEternalEngine, allServers as allServers$1 } from '@wrongstack/core';
|
|
7
7
|
import { createRequire } from 'module';
|
|
8
8
|
import * as os6 from 'os';
|
|
9
9
|
import os6__default from 'os';
|
|
@@ -1687,6 +1687,7 @@ ${diff}`;
|
|
|
1687
1687
|
// src/arg-parser.ts
|
|
1688
1688
|
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
1689
1689
|
"yolo",
|
|
1690
|
+
"force-all-yolo",
|
|
1690
1691
|
"verbose",
|
|
1691
1692
|
"trace",
|
|
1692
1693
|
"help",
|
|
@@ -2886,8 +2887,9 @@ function buildClearCommand(opts) {
|
|
|
2886
2887
|
" /clear",
|
|
2887
2888
|
"",
|
|
2888
2889
|
"Wipes everything in the current REPL state: messages, todos, read-file tracking,",
|
|
2889
|
-
"file mtimes, meta. Memory store entries (all scopes) are cleared too.
|
|
2890
|
-
"
|
|
2890
|
+
"file mtimes, meta. Memory store entries (all scopes) are cleared too. Chat",
|
|
2891
|
+
"history on disk is reset. The terminal is wiped.",
|
|
2892
|
+
"Use this when you want a fresh conversation without restarting `wstack`."
|
|
2891
2893
|
].join("\n"),
|
|
2892
2894
|
async run(_args, ctx) {
|
|
2893
2895
|
if (ctx) {
|
|
@@ -2897,6 +2899,12 @@ function buildClearCommand(opts) {
|
|
|
2897
2899
|
ctx.fileMtimes.clear();
|
|
2898
2900
|
for (const key of Object.keys(ctx.meta)) ctx.state.deleteMeta(key);
|
|
2899
2901
|
}
|
|
2902
|
+
if (ctx?.session) {
|
|
2903
|
+
await ctx.session.clearSession();
|
|
2904
|
+
}
|
|
2905
|
+
if (opts.sessionStore) {
|
|
2906
|
+
await opts.sessionStore.clearHistory(ctx?.session.id ?? "");
|
|
2907
|
+
}
|
|
2900
2908
|
await opts.memoryStore?.clear();
|
|
2901
2909
|
opts.onClear?.();
|
|
2902
2910
|
opts.renderer.clear();
|
|
@@ -3230,99 +3238,226 @@ function buildStatsCommand(opts) {
|
|
|
3230
3238
|
}
|
|
3231
3239
|
};
|
|
3232
3240
|
}
|
|
3233
|
-
|
|
3234
|
-
// src/slash-commands/fleet.ts
|
|
3235
3241
|
function buildFleetCommand(opts) {
|
|
3236
3242
|
return {
|
|
3237
3243
|
name: "fleet",
|
|
3238
|
-
description: "Inspect
|
|
3244
|
+
description: "Inspect and control the agent fleet (subagents, parallel slots).",
|
|
3239
3245
|
help: [
|
|
3240
3246
|
"Usage:",
|
|
3241
|
-
" /fleet
|
|
3242
|
-
" /fleet status
|
|
3243
|
-
" /fleet
|
|
3244
|
-
" /fleet
|
|
3245
|
-
" /fleet
|
|
3246
|
-
" /fleet
|
|
3247
|
-
" /fleet
|
|
3248
|
-
"
|
|
3249
|
-
"
|
|
3250
|
-
" /fleet retry all Re-assign every interrupted task at once.",
|
|
3251
|
-
" /fleet log List subagent transcripts available on disk.",
|
|
3252
|
-
" /fleet log <id> Print a compact summary of a subagent transcript.",
|
|
3253
|
-
" /fleet log <id> raw Dump the full per-subagent JSONL.",
|
|
3254
|
-
" /fleet stream on|off Show/hide subagent activity in the main history.",
|
|
3255
|
-
" /fleet help Show this help."
|
|
3247
|
+
" /fleet Show fleet status (default)",
|
|
3248
|
+
" /fleet status Same as /fleet (verbose status)",
|
|
3249
|
+
" /fleet spawn <role> [count] Spawn N subagents of a role (default 1)",
|
|
3250
|
+
" /fleet terminate <subagentId> Stop a specific subagent by id",
|
|
3251
|
+
" /fleet kill Stop all running subagents",
|
|
3252
|
+
" /fleet usage Token and cost breakdown across the fleet",
|
|
3253
|
+
" /fleet journal Show recent journal entries from /goal journal",
|
|
3254
|
+
"",
|
|
3255
|
+
"Works during /autonomy parallel mode and standalone director sessions."
|
|
3256
3256
|
].join("\n"),
|
|
3257
3257
|
async run(args) {
|
|
3258
|
-
|
|
3259
|
-
const
|
|
3260
|
-
const
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
}
|
|
3269
|
-
case "kill": {
|
|
3270
|
-
if (!target) return { message: "Usage: /fleet kill <subagent-id>" };
|
|
3271
|
-
return { message: await opts.onFleet("kill", target) };
|
|
3272
|
-
}
|
|
3273
|
-
case "concurrency": {
|
|
3274
|
-
return { message: await opts.onFleet("concurrency", target) };
|
|
3275
|
-
}
|
|
3276
|
-
case "retry": {
|
|
3277
|
-
if (!opts.onFleetRetry) {
|
|
3278
|
-
return { message: "Retry is only available when director mode is active." };
|
|
3258
|
+
const parts = args.trim().split(/\s+/);
|
|
3259
|
+
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
3260
|
+
const subargs = parts.slice(1);
|
|
3261
|
+
if (!cmd || cmd === "status" || cmd === "info" || cmd === "manifest") {
|
|
3262
|
+
if (opts.onFleetStatus) {
|
|
3263
|
+
const status = opts.onFleetStatus();
|
|
3264
|
+
if (!status) {
|
|
3265
|
+
const msg4 = `${color.amber("\u26A0 No fleet active.")} Start /autonomy parallel first, or pass --director to a session.`;
|
|
3266
|
+
opts.renderer.write(msg4);
|
|
3267
|
+
return { message: msg4 };
|
|
3279
3268
|
}
|
|
3280
|
-
const
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3269
|
+
const lines = [];
|
|
3270
|
+
lines.push(`${color.bold("Fleet Status")}`);
|
|
3271
|
+
lines.push(
|
|
3272
|
+
color.dim(
|
|
3273
|
+
` coordinator: ${status.coordinatorId} \xB7 pending: ${status.pendingTasks} \xB7 done: ${status.completedTasks}`
|
|
3274
|
+
)
|
|
3275
|
+
);
|
|
3276
|
+
if (status.subagents.length === 0) {
|
|
3277
|
+
lines.push(color.dim(" No active subagents."));
|
|
3278
|
+
} else {
|
|
3279
|
+
lines.push("");
|
|
3280
|
+
lines.push(
|
|
3281
|
+
` ${color.bold("ID").padEnd(36)} ${color.bold("NAME").padEnd(16)} ${color.bold("STATUS").padEnd(10)} ${color.bold("TASK")}`
|
|
3282
|
+
);
|
|
3283
|
+
lines.push(color.dim(" " + "\u2500".repeat(80)));
|
|
3284
|
+
for (const sa of status.subagents) {
|
|
3285
|
+
const id = sa.id?.padEnd(36) ?? "".padEnd(36);
|
|
3286
|
+
const name = (sa.name ?? "worker").padEnd(16);
|
|
3287
|
+
const statusColor = sa.status === "running" ? color.green(sa.status.padEnd(10)) : sa.status === "idle" ? color.dim(sa.status.padEnd(10)) : color.dim(sa.status.padEnd(10));
|
|
3288
|
+
const task = sa.currentTask ?? color.dim("\u2014");
|
|
3289
|
+
lines.push(` ${id} ${name} ${statusColor} ${task}`);
|
|
3290
|
+
}
|
|
3286
3291
|
}
|
|
3287
|
-
const
|
|
3288
|
-
|
|
3289
|
-
return { message:
|
|
3290
|
-
}
|
|
3291
|
-
|
|
3292
|
-
const
|
|
3293
|
-
|
|
3294
|
-
|
|
3292
|
+
const msg3 = lines.join("\n");
|
|
3293
|
+
opts.renderer.write(msg3);
|
|
3294
|
+
return { message: msg3 };
|
|
3295
|
+
}
|
|
3296
|
+
if (opts.onFleet) {
|
|
3297
|
+
const msg3 = await opts.onFleet(cmd || "status", void 0);
|
|
3298
|
+
return { message: msg3 };
|
|
3299
|
+
}
|
|
3300
|
+
const msg2 = `${color.amber("\u26A0 No fleet active.")} Start /autonomy parallel first, or pass --director to a session.`;
|
|
3301
|
+
opts.renderer.write(msg2);
|
|
3302
|
+
return { message: msg2 };
|
|
3303
|
+
}
|
|
3304
|
+
if (cmd === "usage" || cmd === "cost" || cmd === "tokens") {
|
|
3305
|
+
if (opts.onFleetUsage) {
|
|
3306
|
+
const usage = opts.onFleetUsage();
|
|
3307
|
+
if (!usage) {
|
|
3308
|
+
const msg4 = `${color.amber("\u26A0 No fleet usage data.")} Start /autonomy parallel first.`;
|
|
3309
|
+
opts.renderer.write(msg4);
|
|
3310
|
+
return { message: msg4 };
|
|
3295
3311
|
}
|
|
3296
|
-
const
|
|
3297
|
-
|
|
3298
|
-
|
|
3312
|
+
const totalCost = usage.total?.cost ?? 0;
|
|
3313
|
+
const totalIn = usage.total?.input ?? 0;
|
|
3314
|
+
const totalOut = usage.total?.output ?? 0;
|
|
3315
|
+
const lines = [];
|
|
3316
|
+
lines.push(`${color.bold("Fleet Usage")}`);
|
|
3317
|
+
lines.push(
|
|
3318
|
+
` ${color.dim("Total:")} ${color.green(`${totalCost.toFixed(4)}`)} \xB7 ${color.cyan(totalIn.toLocaleString())} in \xB7 ${color.cyan(totalOut.toLocaleString())} out`
|
|
3319
|
+
);
|
|
3320
|
+
const subagents = Object.values(usage.perSubagent);
|
|
3321
|
+
if (subagents.length > 0) {
|
|
3322
|
+
lines.push("");
|
|
3323
|
+
for (const sa of subagents) {
|
|
3324
|
+
const name = (sa.subagentId ?? "?").padEnd(20);
|
|
3325
|
+
const cost = `${(sa.cost ?? 0).toFixed(4)}`.padStart(10);
|
|
3326
|
+
const tokens = `${sa.input ?? 0} in / ${sa.output ?? 0} out`.padEnd(30);
|
|
3327
|
+
lines.push(` ${color.dim(name)} ${color.cyan(cost)} ${color.dim(tokens)}`);
|
|
3328
|
+
}
|
|
3299
3329
|
}
|
|
3300
|
-
|
|
3301
|
-
|
|
3330
|
+
const msg3 = lines.join("\n");
|
|
3331
|
+
opts.renderer.write(msg3);
|
|
3332
|
+
return { message: msg3 };
|
|
3333
|
+
}
|
|
3334
|
+
if (opts.onFleet) {
|
|
3335
|
+
const msg3 = await opts.onFleet("usage", void 0);
|
|
3336
|
+
return { message: msg3 };
|
|
3337
|
+
}
|
|
3338
|
+
const msg2 = `${color.amber("\u26A0 No fleet usage data.")} Start /autonomy parallel first.`;
|
|
3339
|
+
opts.renderer.write(msg2);
|
|
3340
|
+
return { message: msg2 };
|
|
3341
|
+
}
|
|
3342
|
+
if (cmd === "retry") {
|
|
3343
|
+
if (opts.onFleetRetry) {
|
|
3344
|
+
const targetId = subargs[0];
|
|
3345
|
+
const msg3 = await opts.onFleetRetry(targetId);
|
|
3346
|
+
return { message: msg3 };
|
|
3347
|
+
}
|
|
3348
|
+
if (opts.onFleet) {
|
|
3349
|
+
const msg3 = await opts.onFleet("retry", subargs[0]);
|
|
3350
|
+
return { message: msg3 };
|
|
3351
|
+
}
|
|
3352
|
+
const msg2 = `Retry is only available when director mode is active.`;
|
|
3353
|
+
opts.renderer.writeWarning(msg2);
|
|
3354
|
+
return { message: msg2 };
|
|
3355
|
+
}
|
|
3356
|
+
if (cmd === "journal" || cmd === "log") {
|
|
3357
|
+
if (opts.onFleetLog) {
|
|
3358
|
+
const subagentId = subargs[0];
|
|
3359
|
+
const mode = subargs[1] === "raw" ? "raw" : "summary";
|
|
3360
|
+
const msg3 = await opts.onFleetLog(subagentId, mode);
|
|
3361
|
+
return { message: msg3 };
|
|
3362
|
+
}
|
|
3363
|
+
if (opts.onFleet) {
|
|
3364
|
+
const msg3 = await opts.onFleet("log", subargs[0]);
|
|
3365
|
+
return { message: msg3 };
|
|
3366
|
+
}
|
|
3367
|
+
const msg2 = `${color.dim("No journal entries yet.")}`;
|
|
3368
|
+
opts.renderer.write(msg2);
|
|
3369
|
+
return { message: msg2 };
|
|
3370
|
+
}
|
|
3371
|
+
if (cmd === "kill" || cmd === "stop-all") {
|
|
3372
|
+
const targetId = subargs[0];
|
|
3373
|
+
if (!targetId) {
|
|
3374
|
+
const msg3 = `Usage: /fleet kill <subagent-id>`;
|
|
3375
|
+
opts.renderer.writeWarning(msg3);
|
|
3376
|
+
return { message: msg3 };
|
|
3377
|
+
}
|
|
3378
|
+
if (opts.onFleetKill) {
|
|
3379
|
+
const killed = opts.onFleetKill();
|
|
3380
|
+
const msg3 = `${color.red("\u2717 Killed")} ${killed} subagent(s).`;
|
|
3381
|
+
opts.renderer.write(msg3);
|
|
3382
|
+
return { message: msg3 };
|
|
3383
|
+
}
|
|
3384
|
+
if (opts.onFleet) {
|
|
3385
|
+
const msg3 = await opts.onFleet("kill", targetId);
|
|
3386
|
+
return { message: msg3 };
|
|
3387
|
+
}
|
|
3388
|
+
const msg2 = `${color.amber("\u26A0 /fleet kill is not wired in this session.")}`;
|
|
3389
|
+
opts.renderer.writeWarning(msg2);
|
|
3390
|
+
return { message: msg2 };
|
|
3391
|
+
}
|
|
3392
|
+
if (cmd === "terminate" || cmd === "stop") {
|
|
3393
|
+
const targetId = subargs[0];
|
|
3394
|
+
if (!targetId) {
|
|
3395
|
+
const msg2 = `${color.amber("\u26A0 /fleet terminate requires a subagentId.")} Use /fleet to see active ids.`;
|
|
3396
|
+
opts.renderer.writeWarning(msg2);
|
|
3397
|
+
return { message: msg2 };
|
|
3398
|
+
}
|
|
3399
|
+
if (!opts.onFleetTerminate) {
|
|
3400
|
+
const msg2 = `${color.amber("\u26A0 /fleet terminate is not wired in this session.")}`;
|
|
3401
|
+
opts.renderer.writeWarning(msg2);
|
|
3402
|
+
return { message: msg2 };
|
|
3403
|
+
}
|
|
3404
|
+
const ok = opts.onFleetTerminate(targetId);
|
|
3405
|
+
if (ok) {
|
|
3406
|
+
const msg2 = `${color.green("\u2713 Terminated")} subagent ${color.bold(targetId)}.`;
|
|
3407
|
+
opts.renderer.write(msg2);
|
|
3408
|
+
return { message: msg2 };
|
|
3409
|
+
} else {
|
|
3410
|
+
const msg2 = `${color.red("\u2717 Failed")} to terminate ${color.bold(targetId)}. Subagent may already be stopped.`;
|
|
3411
|
+
opts.renderer.writeWarning(msg2);
|
|
3412
|
+
return { message: msg2 };
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
if (cmd === "spawn" || cmd === "add") {
|
|
3416
|
+
const role = subargs[0] ?? "worker";
|
|
3417
|
+
const count = Math.min(16, Math.max(1, parseInt(subargs[1] ?? "1", 10) || 1));
|
|
3418
|
+
if (!opts.onFleetSpawn) {
|
|
3419
|
+
const msg3 = `${color.amber("\u26A0 /fleet spawn is not wired in this session.")}`;
|
|
3420
|
+
opts.renderer.writeWarning(msg3);
|
|
3421
|
+
return { message: msg3 };
|
|
3422
|
+
}
|
|
3423
|
+
const spawned = [];
|
|
3424
|
+
let msg2;
|
|
3425
|
+
for (let i = 0; i < count; i++) {
|
|
3426
|
+
try {
|
|
3427
|
+
const id = await opts.onFleetSpawn(role);
|
|
3428
|
+
spawned.push(id);
|
|
3429
|
+
} catch (err) {
|
|
3430
|
+
const msg3 = `${color.red("\u2717 Spawn failed")} for slot ${i + 1}: ${err instanceof Error ? err.message : String(err)}`;
|
|
3431
|
+
opts.renderer.writeWarning(msg3);
|
|
3302
3432
|
}
|
|
3303
|
-
const enabled = arg === "on";
|
|
3304
|
-
ctrl.setEnabled(enabled);
|
|
3305
|
-
ctrl.enabled = enabled;
|
|
3306
|
-
return { message: `Fleet streaming ${enabled ? "enabled" : "disabled"}.` };
|
|
3307
3433
|
}
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
}
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
}
|
|
3434
|
+
if (spawned.length === count) {
|
|
3435
|
+
msg2 = `${color.green("\u2713 Spawned")} ${count} subagent(s) of role ${color.bold(role)}.`;
|
|
3436
|
+
opts.renderer.write(msg2);
|
|
3437
|
+
} else {
|
|
3438
|
+
msg2 = `${color.amber("\u26A0 Spawned")} ${spawned.length}/${count} subagent(s). Check /fleet for details.`;
|
|
3439
|
+
opts.renderer.writeWarning(msg2);
|
|
3440
|
+
}
|
|
3441
|
+
return { message: msg2 };
|
|
3442
|
+
}
|
|
3443
|
+
if (cmd === "help" || cmd === "?") {
|
|
3444
|
+
const msg2 = [
|
|
3445
|
+
`${color.bold("Fleet Commands")}`,
|
|
3446
|
+
` ${color.dim("/fleet")} Show fleet status (default)`,
|
|
3447
|
+
` ${color.dim("/fleet status")} Same as /fleet (verbose status)`,
|
|
3448
|
+
` ${color.dim("/fleet spawn <role> [count]")} Spawn N subagents of a role (default 1)`,
|
|
3449
|
+
` ${color.dim("/fleet terminate <subagentId>")} Stop a specific subagent by id`,
|
|
3450
|
+
` ${color.dim("/fleet kill")} Stop all running subagents`,
|
|
3451
|
+
` ${color.dim("/fleet usage")} Token and cost breakdown across the fleet`,
|
|
3452
|
+
` ${color.dim("/fleet journal")} Show recent journal entries from /goal journal`
|
|
3453
|
+
].join("\n");
|
|
3454
|
+
opts.renderer.write(msg2);
|
|
3455
|
+
return { message: msg2 };
|
|
3325
3456
|
}
|
|
3457
|
+
const valid = ["status", "usage", "spawn", "terminate", "kill", "retry", "journal"];
|
|
3458
|
+
const msg = `Unknown subcommand "${cmd}". Valid subcommands: ${valid.join(", ")}. Run /fleet with no args to see status, or /fleet help for usage.`;
|
|
3459
|
+
opts.renderer.writeWarning(msg);
|
|
3460
|
+
return { message: msg };
|
|
3326
3461
|
}
|
|
3327
3462
|
};
|
|
3328
3463
|
}
|
|
@@ -4128,8 +4263,9 @@ function buildAutonomyCommand(opts) {
|
|
|
4128
4263
|
" /autonomy suggest Show next-step suggestions after each turn",
|
|
4129
4264
|
" /autonomy on Auto-continue \u2014 agent picks next step and proceeds",
|
|
4130
4265
|
" /autonomy eternal Sittin-sene mode \u2014 runs forever against /goal",
|
|
4266
|
+
" /autonomy parallel Parallel mode \u2014 4-8 agents per tick, fan-out parallelism",
|
|
4131
4267
|
" /autonomy stop Stop eternal mode (no-op for other modes)",
|
|
4132
|
-
" /autonomy toggle Cycle: off \u2192 suggest \u2192 auto \u2192 eternal \u2192 off",
|
|
4268
|
+
" /autonomy toggle Cycle: off \u2192 suggest \u2192 auto \u2192 eternal \u2192 parallel \u2192 off",
|
|
4133
4269
|
"",
|
|
4134
4270
|
"Modes:",
|
|
4135
4271
|
" off \u2014 Normal interactive mode. Agent stops and waits.",
|
|
@@ -4138,8 +4274,11 @@ function buildAutonomyCommand(opts) {
|
|
|
4138
4274
|
" Runs indefinitely until you press Esc or Ctrl+C.",
|
|
4139
4275
|
" eternal \u2014 Goal-driven sense/decide/execute/reflect loop. Requires /goal.",
|
|
4140
4276
|
" Force-enables YOLO. Runs until /autonomy stop or Ctrl+C twice.",
|
|
4277
|
+
" parallel \u2014 Fan-out 4\u20138 subagents per tick. Each tick decomposes the goal,",
|
|
4278
|
+
" spawns N agents, awaits results, aggregates. Requires /goal.",
|
|
4279
|
+
" Force-enables YOLO. Runs until /autonomy stop or Ctrl+C twice.",
|
|
4141
4280
|
"",
|
|
4142
|
-
"In auto/eternal modes the agent works autonomously. Press Esc to redirect,",
|
|
4281
|
+
"In auto/eternal/parallel modes the agent works autonomously. Press Esc to redirect,",
|
|
4143
4282
|
"Ctrl+C to stop the active iteration. /autonomy stop ends the eternal loop."
|
|
4144
4283
|
].join("\n"),
|
|
4145
4284
|
async run(args) {
|
|
@@ -4155,9 +4294,10 @@ function buildAutonomyCommand(opts) {
|
|
|
4155
4294
|
off: `${color.green("OFF")} ${color.dim("(agent stops after each turn)")}`,
|
|
4156
4295
|
suggest: `${color.cyan("SUGGEST")} ${color.dim("(shows next-step suggestions)")}`,
|
|
4157
4296
|
auto: `${color.yellow("AUTO")} ${color.dim("(self-driving \u2014 Esc to redirect, Ctrl+C to stop)")}`,
|
|
4158
|
-
eternal: `${color.red("ETERNAL")} ${color.dim("(sittin-sene \u2014 goal-driven, YOLO, until /autonomy stop)")}
|
|
4297
|
+
eternal: `${color.red("ETERNAL")} ${color.dim("(sittin-sene \u2014 goal-driven, YOLO, until /autonomy stop)")}`,
|
|
4298
|
+
"eternal-parallel": `${color.magenta("PARALLEL")} ${color.dim("(4-8 subagents per tick \u2014 fan-out, until /autonomy stop)")}`
|
|
4159
4299
|
};
|
|
4160
|
-
const lines = [`Autonomy mode: ${labels2[current]}`];
|
|
4300
|
+
const lines = [`Autonomy mode: ${labels2[current] ?? current}`];
|
|
4161
4301
|
try {
|
|
4162
4302
|
const goal = await loadGoal(goalFilePath(opts.projectRoot));
|
|
4163
4303
|
if (goal) {
|
|
@@ -4189,6 +4329,8 @@ function buildAutonomyCommand(opts) {
|
|
|
4189
4329
|
opts.renderer.writeWarning(msg3);
|
|
4190
4330
|
return { message: msg3 };
|
|
4191
4331
|
}
|
|
4332
|
+
opts.getEternalEngine?.()?.stop();
|
|
4333
|
+
opts.getParallelEngine?.()?.stop();
|
|
4192
4334
|
opts.onEternalStop();
|
|
4193
4335
|
opts.onAutonomy("off");
|
|
4194
4336
|
let summaryLine = "";
|
|
@@ -4206,7 +4348,7 @@ function buildAutonomyCommand(opts) {
|
|
|
4206
4348
|
}
|
|
4207
4349
|
} catch {
|
|
4208
4350
|
}
|
|
4209
|
-
const msg2 = `${color.amber("Eternal mode stop requested.")} The current iteration will finish, then the loop exits.${summaryLine}`;
|
|
4351
|
+
const msg2 = `${color.amber("Eternal/parallel mode stop requested.")} The current iteration will finish, then the loop exits.${summaryLine}`;
|
|
4210
4352
|
opts.renderer.write(msg2);
|
|
4211
4353
|
return { message: msg2 };
|
|
4212
4354
|
}
|
|
@@ -4219,19 +4361,27 @@ function buildAutonomyCommand(opts) {
|
|
|
4219
4361
|
newMode = "suggest";
|
|
4220
4362
|
} else if (arg === "eternal" || arg === "forever" || arg === "infinite" || arg === "sittinsene") {
|
|
4221
4363
|
newMode = "eternal";
|
|
4364
|
+
} else if (arg === "parallel" || arg === "eternal-parallel" || arg === "fanout") {
|
|
4365
|
+
newMode = "eternal-parallel";
|
|
4222
4366
|
} else if (arg === "toggle" || arg === "cycle") {
|
|
4223
4367
|
const current = opts.onAutonomy() ?? "off";
|
|
4224
4368
|
const cycle = ["off", "suggest", "auto", "eternal"];
|
|
4225
4369
|
newMode = cycle[(cycle.indexOf(current) + 1) % cycle.length] ?? "off";
|
|
4226
4370
|
} else {
|
|
4227
|
-
const msg2 = `Unknown argument: ${arg}. Use /autonomy on, off, suggest, eternal, stop, or toggle.`;
|
|
4371
|
+
const msg2 = `Unknown argument: ${arg}. Use /autonomy on, off, suggest, eternal, parallel, stop, or toggle.`;
|
|
4228
4372
|
opts.renderer.writeWarning(msg2);
|
|
4229
4373
|
return { message: msg2 };
|
|
4230
4374
|
}
|
|
4231
|
-
if (newMode === "eternal") {
|
|
4375
|
+
if (newMode === "eternal" || newMode === "eternal-parallel") {
|
|
4232
4376
|
const goal = await loadGoal(goalFilePath(opts.projectRoot));
|
|
4233
4377
|
if (!goal) {
|
|
4234
|
-
const msg3 = `${color.red("Eternal mode requires a goal.")} Run \`/goal set <mission>\` first.`;
|
|
4378
|
+
const msg3 = `${color.red("Eternal/parallel mode requires a goal.")} Run \`/goal set <mission>\` first.`;
|
|
4379
|
+
opts.renderer.writeWarning(msg3);
|
|
4380
|
+
return { message: msg3 };
|
|
4381
|
+
}
|
|
4382
|
+
const isStale = goal.iterations > 0 || goal.engineState === "running";
|
|
4383
|
+
if (isStale) {
|
|
4384
|
+
const msg3 = `${color.amber("Stale goal detected.")} Previous mission has ${goal.iterations} iterations (engineState: ${goal.engineState}). Clear it first: ${color.bold("/goal clear")}, then set a new one: ${color.bold("/goal set <mission>")}.`;
|
|
4235
4385
|
opts.renderer.writeWarning(msg3);
|
|
4236
4386
|
return { message: msg3 };
|
|
4237
4387
|
}
|
|
@@ -4242,14 +4392,15 @@ function buildAutonomyCommand(opts) {
|
|
|
4242
4392
|
}
|
|
4243
4393
|
if (opts.onYolo) opts.onYolo(true);
|
|
4244
4394
|
opts.onAutonomy(newMode);
|
|
4245
|
-
opts.onEternalStart();
|
|
4246
|
-
const
|
|
4395
|
+
opts.onEternalStart(newMode);
|
|
4396
|
+
const modeLabel = newMode === "eternal-parallel" ? `${color.magenta("PARALLEL")} mode` : `${color.red("ETERNAL")} mode`;
|
|
4397
|
+
const msg2 = `Autonomy mode: ${modeLabel} \u2014 engine launching against goal: ${color.bold(goal.goal)}
|
|
4247
4398
|
${color.dim("YOLO forced ON. Use /autonomy stop to end. Journal at /goal journal.")}`;
|
|
4248
4399
|
opts.renderer.write(msg2);
|
|
4249
4400
|
return { message: msg2 };
|
|
4250
4401
|
}
|
|
4251
4402
|
const previous = opts.onAutonomy();
|
|
4252
|
-
if (previous === "eternal" && opts.onEternalStop) {
|
|
4403
|
+
if ((previous === "eternal" || previous === "eternal-parallel") && opts.onEternalStop) {
|
|
4253
4404
|
opts.onEternalStop();
|
|
4254
4405
|
}
|
|
4255
4406
|
opts.onAutonomy(newMode);
|
|
@@ -4257,7 +4408,8 @@ ${color.dim("YOLO forced ON. Use /autonomy stop to end. Journal at /goal journal
|
|
|
4257
4408
|
off: `${color.green("OFF")} \u2014 agent stops after each turn`,
|
|
4258
4409
|
suggest: `${color.cyan("SUGGEST")} \u2014 shows next-step suggestions after each turn`,
|
|
4259
4410
|
auto: `${color.yellow("AUTO")} \u2014 self-driving, agent continues automatically`,
|
|
4260
|
-
eternal: `${color.red("ETERNAL")} \u2014 goal-driven sittin-sene loop
|
|
4411
|
+
eternal: `${color.red("ETERNAL")} \u2014 goal-driven sittin-sene loop`,
|
|
4412
|
+
"eternal-parallel": `${color.magenta("PARALLEL")} \u2014 fan-out 4-8 subagents per tick`
|
|
4261
4413
|
};
|
|
4262
4414
|
const msg = `Autonomy mode: ${labels[newMode]}`;
|
|
4263
4415
|
opts.renderer.write(msg);
|
|
@@ -4338,13 +4490,15 @@ ${color.dim(`Stored in ${goalPath} \u2014 Esc / /steer to redirect, Ctrl+C to st
|
|
|
4338
4490
|
opts.renderer.write(msg2);
|
|
4339
4491
|
return { message: msg2 };
|
|
4340
4492
|
}
|
|
4493
|
+
const abandoned = { ...existing, goalState: "abandoned" };
|
|
4494
|
+
await saveGoal(goalPath, abandoned);
|
|
4341
4495
|
const { unlink: unlink4 } = await import('fs/promises');
|
|
4342
4496
|
try {
|
|
4343
4497
|
await unlink4(goalPath);
|
|
4344
4498
|
} catch {
|
|
4345
4499
|
}
|
|
4346
4500
|
if (opts.onEternalStop) opts.onEternalStop();
|
|
4347
|
-
const msg = `${color.amber("Goal cleared.")}
|
|
4501
|
+
const msg = `${color.amber("Goal cleared.")} Previous goal marked abandoned; eternal mode will stop.`;
|
|
4348
4502
|
opts.renderer.write(msg);
|
|
4349
4503
|
return { message: msg };
|
|
4350
4504
|
}
|
|
@@ -4819,6 +4973,821 @@ function buildStatuslineCommand(deps) {
|
|
|
4819
4973
|
}
|
|
4820
4974
|
};
|
|
4821
4975
|
}
|
|
4976
|
+
|
|
4977
|
+
// src/slash-commands/fix-classifier.ts
|
|
4978
|
+
var TS = ["typescript-strict"];
|
|
4979
|
+
var BH = ["bug-hunter"];
|
|
4980
|
+
var SS = ["security-scanner"];
|
|
4981
|
+
var NM = ["node-modern"];
|
|
4982
|
+
var RM = ["react-modern"];
|
|
4983
|
+
var P = [
|
|
4984
|
+
// ── TypeScript ──────────────────────────────────────────────────────────────
|
|
4985
|
+
{
|
|
4986
|
+
pat: /\bTS\d+\b/,
|
|
4987
|
+
cat: "ts",
|
|
4988
|
+
sub: "typescript",
|
|
4989
|
+
lang: "typescript",
|
|
4990
|
+
hints: TS,
|
|
4991
|
+
detail: "TypeScript error",
|
|
4992
|
+
code: (m) => m[0],
|
|
4993
|
+
conf: 1
|
|
4994
|
+
},
|
|
4995
|
+
{
|
|
4996
|
+
pat: /\btypescript\b.*\berror\b|\berror\b.*\btypescript\b/i,
|
|
4997
|
+
cat: "ts",
|
|
4998
|
+
sub: "typescript",
|
|
4999
|
+
lang: "typescript",
|
|
5000
|
+
hints: TS,
|
|
5001
|
+
detail: "TypeScript error",
|
|
5002
|
+
conf: 0.9
|
|
5003
|
+
},
|
|
5004
|
+
{
|
|
5005
|
+
pat: /\b: any\b|\bas any\b/,
|
|
5006
|
+
cat: "ts",
|
|
5007
|
+
sub: "unsafe-any",
|
|
5008
|
+
lang: "typescript",
|
|
5009
|
+
hints: TS,
|
|
5010
|
+
detail: "Unsafe `any` cast \u2014 type safety violation",
|
|
5011
|
+
conf: 0.85
|
|
5012
|
+
},
|
|
5013
|
+
{
|
|
5014
|
+
pat: /\bnoimplicit|\bstrict\b.*\bcheck\b|\btsconfig\b/i,
|
|
5015
|
+
cat: "ts",
|
|
5016
|
+
sub: "strict-mode",
|
|
5017
|
+
lang: "typescript",
|
|
5018
|
+
hints: TS,
|
|
5019
|
+
detail: "TypeScript strict mode configuration issue",
|
|
5020
|
+
conf: 0.8
|
|
5021
|
+
},
|
|
5022
|
+
// ── Rust ───────────────────────────────────────────────────────────────────
|
|
5023
|
+
{
|
|
5024
|
+
pat: /\bE\d{4,}\b/,
|
|
5025
|
+
cat: "runtime",
|
|
5026
|
+
sub: "panic",
|
|
5027
|
+
lang: "rust",
|
|
5028
|
+
hints: BH,
|
|
5029
|
+
detail: "Rust error",
|
|
5030
|
+
conf: 1,
|
|
5031
|
+
code: (m) => m[0]
|
|
5032
|
+
},
|
|
5033
|
+
{
|
|
5034
|
+
pat: /\bthread.*panicked|panicked at /i,
|
|
5035
|
+
cat: "runtime",
|
|
5036
|
+
sub: "panic",
|
|
5037
|
+
lang: "rust",
|
|
5038
|
+
hints: BH,
|
|
5039
|
+
detail: "Rust panic",
|
|
5040
|
+
conf: 1
|
|
5041
|
+
},
|
|
5042
|
+
{
|
|
5043
|
+
pat: /\brustc.*error|compilation failed.*rust/i,
|
|
5044
|
+
cat: "compile",
|
|
5045
|
+
sub: "rust-compile",
|
|
5046
|
+
lang: "rust",
|
|
5047
|
+
hints: BH,
|
|
5048
|
+
detail: "Rust compiler error",
|
|
5049
|
+
conf: 1
|
|
5050
|
+
},
|
|
5051
|
+
// ── Go ──────────────────────────────────────────────────────────────────────
|
|
5052
|
+
{
|
|
5053
|
+
pat: /\bgo build\b.*fail|golang.*error/i,
|
|
5054
|
+
cat: "compile",
|
|
5055
|
+
sub: "go-compile",
|
|
5056
|
+
lang: "go",
|
|
5057
|
+
hints: BH,
|
|
5058
|
+
detail: "Go build error",
|
|
5059
|
+
conf: 0.95
|
|
5060
|
+
},
|
|
5061
|
+
{
|
|
5062
|
+
pat: /\bnil pointer|nil dereference|invalid memory address/i,
|
|
5063
|
+
cat: "runtime",
|
|
5064
|
+
sub: "nil-pointer",
|
|
5065
|
+
lang: "go",
|
|
5066
|
+
hints: BH,
|
|
5067
|
+
detail: "Go nil pointer dereference",
|
|
5068
|
+
conf: 0.9
|
|
5069
|
+
},
|
|
5070
|
+
// ── Python ────────────────────────────────────────────────────────────────
|
|
5071
|
+
{
|
|
5072
|
+
pat: /\btraceback \(most recent call last\)/i,
|
|
5073
|
+
cat: "runtime",
|
|
5074
|
+
sub: "python-traceback",
|
|
5075
|
+
lang: "python",
|
|
5076
|
+
hints: BH,
|
|
5077
|
+
detail: "Python runtime error / traceback",
|
|
5078
|
+
conf: 1
|
|
5079
|
+
},
|
|
5080
|
+
{
|
|
5081
|
+
pat: /\bpython.*error|python.*exception|modulenot founderror|importerror/i,
|
|
5082
|
+
cat: "runtime",
|
|
5083
|
+
sub: "python-traceback",
|
|
5084
|
+
lang: "python",
|
|
5085
|
+
hints: BH,
|
|
5086
|
+
detail: "Python runtime error",
|
|
5087
|
+
conf: 1
|
|
5088
|
+
},
|
|
5089
|
+
{
|
|
5090
|
+
pat: /\battributeerror\b|\btypeerror\b.*python|python.*type error/i,
|
|
5091
|
+
cat: "runtime",
|
|
5092
|
+
sub: "python-type",
|
|
5093
|
+
lang: "python",
|
|
5094
|
+
hints: BH,
|
|
5095
|
+
detail: "Python type/error",
|
|
5096
|
+
conf: 0.9
|
|
5097
|
+
},
|
|
5098
|
+
{
|
|
5099
|
+
pat: /\bpip install|requirement.*not found|package.*not found.*python/i,
|
|
5100
|
+
cat: "dep",
|
|
5101
|
+
sub: "python-dep",
|
|
5102
|
+
lang: "python",
|
|
5103
|
+
hints: BH,
|
|
5104
|
+
detail: "Python dependency error",
|
|
5105
|
+
conf: 0.9
|
|
5106
|
+
},
|
|
5107
|
+
{
|
|
5108
|
+
pat: /\bpylint|pyright|mypy.*error|flake8/i,
|
|
5109
|
+
cat: "lint",
|
|
5110
|
+
sub: "python-lint",
|
|
5111
|
+
lang: "python",
|
|
5112
|
+
hints: BH,
|
|
5113
|
+
detail: "Python linter error",
|
|
5114
|
+
conf: 0.85
|
|
5115
|
+
},
|
|
5116
|
+
// ── Ruby ──────────────────────────────────────────────────────────────────
|
|
5117
|
+
{
|
|
5118
|
+
pat: /\b(nomethoderror|noconversion|undefined method|private method|rbenv|rubygems)/i,
|
|
5119
|
+
cat: "runtime",
|
|
5120
|
+
sub: "ruby-error",
|
|
5121
|
+
lang: "ruby",
|
|
5122
|
+
hints: BH,
|
|
5123
|
+
detail: (m) => `Ruby error: ${m[1] ?? m[0]}`,
|
|
5124
|
+
conf: 0.9
|
|
5125
|
+
},
|
|
5126
|
+
{
|
|
5127
|
+
pat: /\bgem install|bundler.*error|gemspec.*error/i,
|
|
5128
|
+
cat: "dep",
|
|
5129
|
+
sub: "ruby-dep",
|
|
5130
|
+
lang: "ruby",
|
|
5131
|
+
hints: BH,
|
|
5132
|
+
detail: "Ruby gem/bundler error",
|
|
5133
|
+
conf: 0.85
|
|
5134
|
+
},
|
|
5135
|
+
// ── Java / Kotlin ────────────────────────────────────────────────────────
|
|
5136
|
+
{
|
|
5137
|
+
pat: /\bnullpointerexception|npe\b/i,
|
|
5138
|
+
cat: "runtime",
|
|
5139
|
+
sub: "null-pointer",
|
|
5140
|
+
lang: "java",
|
|
5141
|
+
hints: BH,
|
|
5142
|
+
detail: "NullPointerException",
|
|
5143
|
+
conf: 1
|
|
5144
|
+
},
|
|
5145
|
+
{
|
|
5146
|
+
pat: /\bjava\.lang\.|exception in thread|java\.util\.|java\.io\./i,
|
|
5147
|
+
cat: "runtime",
|
|
5148
|
+
sub: "java-exception",
|
|
5149
|
+
lang: "java",
|
|
5150
|
+
hints: BH,
|
|
5151
|
+
detail: "Java/Kotlin runtime exception",
|
|
5152
|
+
conf: 1
|
|
5153
|
+
},
|
|
5154
|
+
{
|
|
5155
|
+
pat: /\b(maven|gradle|ant).*error|dependency.*not found|compile.*fail.*java/i,
|
|
5156
|
+
cat: "dep",
|
|
5157
|
+
sub: "java-build",
|
|
5158
|
+
lang: "java",
|
|
5159
|
+
hints: BH,
|
|
5160
|
+
detail: "Java build/dependency error",
|
|
5161
|
+
conf: 0.9
|
|
5162
|
+
},
|
|
5163
|
+
{
|
|
5164
|
+
pat: /\bkotlin\b.*\berror\b|\bkotlin compiler\b/i,
|
|
5165
|
+
cat: "compile",
|
|
5166
|
+
sub: "kotlin-compile",
|
|
5167
|
+
lang: "kotlin",
|
|
5168
|
+
hints: BH,
|
|
5169
|
+
detail: "Kotlin compiler error",
|
|
5170
|
+
conf: 0.95
|
|
5171
|
+
},
|
|
5172
|
+
// ── C / C++ ─────────────────────────────────────────────────────────────
|
|
5173
|
+
{
|
|
5174
|
+
pat: /\bc\d+\b/i,
|
|
5175
|
+
cat: "compile",
|
|
5176
|
+
sub: "c-compile",
|
|
5177
|
+
lang: "c",
|
|
5178
|
+
hints: BH,
|
|
5179
|
+
detail: "C/C++ compiler error",
|
|
5180
|
+
conf: 1,
|
|
5181
|
+
code: (m) => m[0]
|
|
5182
|
+
},
|
|
5183
|
+
{
|
|
5184
|
+
pat: /\b(gcc|g\+\+|clang|msvc|visual studio).*error|fatal error c\d+/i,
|
|
5185
|
+
cat: "compile",
|
|
5186
|
+
sub: "c-compile",
|
|
5187
|
+
lang: "c",
|
|
5188
|
+
hints: BH,
|
|
5189
|
+
detail: "C/C++ compiler error",
|
|
5190
|
+
conf: 1
|
|
5191
|
+
},
|
|
5192
|
+
{
|
|
5193
|
+
pat: /\bsegmentation fault|segfault|sigsegv|core dumped/i,
|
|
5194
|
+
cat: "runtime",
|
|
5195
|
+
sub: "segfault",
|
|
5196
|
+
lang: "c",
|
|
5197
|
+
hints: BH,
|
|
5198
|
+
detail: "Segmentation fault (C/C++)",
|
|
5199
|
+
conf: 1
|
|
5200
|
+
},
|
|
5201
|
+
// ── C# ──────────────────────────────────────────────────────────────────
|
|
5202
|
+
{
|
|
5203
|
+
pat: /\b(csharp|dotnet|\.net).*error|cs\d+\b|nullable warning/i,
|
|
5204
|
+
cat: "compile",
|
|
5205
|
+
sub: "csharp-compile",
|
|
5206
|
+
lang: "csharp",
|
|
5207
|
+
hints: BH,
|
|
5208
|
+
detail: "C# / .NET compile error",
|
|
5209
|
+
conf: 0.9
|
|
5210
|
+
},
|
|
5211
|
+
// ── PHP ────────────────────────────────────────────────────────────────
|
|
5212
|
+
{
|
|
5213
|
+
pat: /\bphp.*error|fatal error.*php|parse error.*php/i,
|
|
5214
|
+
cat: "runtime",
|
|
5215
|
+
sub: "php-error",
|
|
5216
|
+
lang: "php",
|
|
5217
|
+
hints: BH,
|
|
5218
|
+
detail: "PHP runtime/parse error",
|
|
5219
|
+
conf: 1
|
|
5220
|
+
},
|
|
5221
|
+
// ── Scala ─────────────────────────────────────────────────────────────
|
|
5222
|
+
{
|
|
5223
|
+
pat: /\bscala.*error|type mismatch.*scala|could not find.*scala/i,
|
|
5224
|
+
cat: "compile",
|
|
5225
|
+
sub: "scala-compile",
|
|
5226
|
+
lang: "scala",
|
|
5227
|
+
hints: BH,
|
|
5228
|
+
detail: "Scala compile error",
|
|
5229
|
+
conf: 0.9
|
|
5230
|
+
},
|
|
5231
|
+
// ── Node.js / JavaScript Runtime ────────────────────────────────────────
|
|
5232
|
+
{
|
|
5233
|
+
pat: /\b(node:|node\.js|err_)/i,
|
|
5234
|
+
cat: "runtime",
|
|
5235
|
+
sub: "node-runtime",
|
|
5236
|
+
lang: "javascript",
|
|
5237
|
+
hints: NM,
|
|
5238
|
+
detail: "Node.js runtime error",
|
|
5239
|
+
conf: 1
|
|
5240
|
+
},
|
|
5241
|
+
{
|
|
5242
|
+
pat: /\bcannot read property|cannot set property|cannot call method/i,
|
|
5243
|
+
cat: "runtime",
|
|
5244
|
+
sub: "undefined-call",
|
|
5245
|
+
lang: "javascript",
|
|
5246
|
+
hints: NM,
|
|
5247
|
+
detail: "JavaScript undefined access error",
|
|
5248
|
+
conf: 0.95
|
|
5249
|
+
},
|
|
5250
|
+
{
|
|
5251
|
+
pat: /\beconnrefused|etimedout|enotfound|econnreset|dns lookup/i,
|
|
5252
|
+
cat: "infra",
|
|
5253
|
+
sub: "network",
|
|
5254
|
+
lang: "javascript",
|
|
5255
|
+
hints: NM,
|
|
5256
|
+
detail: "Node.js network error",
|
|
5257
|
+
conf: 0.95
|
|
5258
|
+
},
|
|
5259
|
+
{
|
|
5260
|
+
pat: /\beacces|eisdir|eperm/i,
|
|
5261
|
+
cat: "infra",
|
|
5262
|
+
sub: "file-system",
|
|
5263
|
+
lang: "javascript",
|
|
5264
|
+
hints: NM,
|
|
5265
|
+
detail: "File system / OS error",
|
|
5266
|
+
conf: 0.95
|
|
5267
|
+
},
|
|
5268
|
+
// ── React / Next.js ──────────────────────────────────────────────────────
|
|
5269
|
+
{
|
|
5270
|
+
pat: /\breact-dom|react\.development|invalid hook call/i,
|
|
5271
|
+
cat: "runtime",
|
|
5272
|
+
sub: "react-error",
|
|
5273
|
+
lang: "javascript",
|
|
5274
|
+
hints: RM,
|
|
5275
|
+
detail: "React runtime error",
|
|
5276
|
+
conf: 0.9
|
|
5277
|
+
},
|
|
5278
|
+
{
|
|
5279
|
+
pat: /\bnext\.js|nextjs|error in.*next|getstaticpaths|getserversideprops/i,
|
|
5280
|
+
cat: "runtime",
|
|
5281
|
+
sub: "nextjs-error",
|
|
5282
|
+
lang: "javascript",
|
|
5283
|
+
hints: RM,
|
|
5284
|
+
detail: "Next.js error",
|
|
5285
|
+
conf: 0.95
|
|
5286
|
+
},
|
|
5287
|
+
// ── Security — BEFORE generic catch-alls ─────────────────────────────
|
|
5288
|
+
{
|
|
5289
|
+
pat: /\b(sql injection|xss|csrf|injection)\b/i,
|
|
5290
|
+
cat: "security",
|
|
5291
|
+
sub: "injection",
|
|
5292
|
+
lang: void 0,
|
|
5293
|
+
hints: SS,
|
|
5294
|
+
detail: "Injection vulnerability",
|
|
5295
|
+
conf: 1
|
|
5296
|
+
},
|
|
5297
|
+
{
|
|
5298
|
+
pat: /\b(secret|apikey|api_key|token|password|credential|jwt)\b/i,
|
|
5299
|
+
cat: "security",
|
|
5300
|
+
sub: "secret-exposure",
|
|
5301
|
+
lang: void 0,
|
|
5302
|
+
hints: SS,
|
|
5303
|
+
detail: "Secret / credential exposure",
|
|
5304
|
+
conf: 1
|
|
5305
|
+
},
|
|
5306
|
+
{
|
|
5307
|
+
pat: /\b(eval|innerhtml|document\.write| dangerouslysetinnerhtml)\b/i,
|
|
5308
|
+
cat: "security",
|
|
5309
|
+
sub: "injection",
|
|
5310
|
+
lang: void 0,
|
|
5311
|
+
hints: SS,
|
|
5312
|
+
detail: "Injection vulnerability",
|
|
5313
|
+
conf: 1
|
|
5314
|
+
},
|
|
5315
|
+
{
|
|
5316
|
+
pat: /\bcors.*misconfig|access-control-allow-origin/i,
|
|
5317
|
+
cat: "security",
|
|
5318
|
+
sub: "cors-misconfig",
|
|
5319
|
+
lang: void 0,
|
|
5320
|
+
hints: SS,
|
|
5321
|
+
detail: "CORS misconfiguration",
|
|
5322
|
+
conf: 0.9
|
|
5323
|
+
},
|
|
5324
|
+
{
|
|
5325
|
+
pat: /\bapikey\b|\bapi_key\b|\bhardcoded\b.*\bkey\b/i,
|
|
5326
|
+
cat: "security",
|
|
5327
|
+
sub: "secret-exposure",
|
|
5328
|
+
lang: void 0,
|
|
5329
|
+
hints: SS,
|
|
5330
|
+
detail: "Secret / credential exposure",
|
|
5331
|
+
conf: 1
|
|
5332
|
+
},
|
|
5333
|
+
// ── Null/undefined access — BEFORE generic typeerror catch-all ─────────────
|
|
5334
|
+
{
|
|
5335
|
+
pat: /\b(null is not|null.*not.*function|undefined is not|is not a function)\b/i,
|
|
5336
|
+
cat: "runtime",
|
|
5337
|
+
sub: "null-undefined-access",
|
|
5338
|
+
lang: "javascript",
|
|
5339
|
+
hints: BH,
|
|
5340
|
+
detail: "Null/undefined access error",
|
|
5341
|
+
conf: 0.9
|
|
5342
|
+
},
|
|
5343
|
+
// ── Generic JS errors ────────────────────────────────────────────────
|
|
5344
|
+
{
|
|
5345
|
+
pat: /\b(typeerror|referenceerror|syntaxerror|urierror|rangeerror|evalerror)\b/i,
|
|
5346
|
+
cat: "runtime",
|
|
5347
|
+
sub: "js-error",
|
|
5348
|
+
lang: "javascript",
|
|
5349
|
+
hints: NM,
|
|
5350
|
+
detail: "JavaScript runtime error",
|
|
5351
|
+
conf: 0.95
|
|
5352
|
+
},
|
|
5353
|
+
// ── Dependency / Import ───────────────────────────────────────────────
|
|
5354
|
+
{
|
|
5355
|
+
pat: /\bcannot find module|modulenotfounderror|no such module|missing module/i,
|
|
5356
|
+
cat: "dep",
|
|
5357
|
+
sub: "module-not-found",
|
|
5358
|
+
lang: void 0,
|
|
5359
|
+
hints: BH,
|
|
5360
|
+
detail: "Module / import resolution failure",
|
|
5361
|
+
conf: 0.9
|
|
5362
|
+
},
|
|
5363
|
+
{
|
|
5364
|
+
pat: /\bfailed to resolve|resolves to|dependency.*not found/i,
|
|
5365
|
+
cat: "dep",
|
|
5366
|
+
sub: "module-not-found",
|
|
5367
|
+
lang: void 0,
|
|
5368
|
+
hints: BH,
|
|
5369
|
+
detail: "Dependency resolution failure",
|
|
5370
|
+
conf: 0.85
|
|
5371
|
+
},
|
|
5372
|
+
// ── Lint ────────────────────────────────────────────────────────────────
|
|
5373
|
+
{
|
|
5374
|
+
pat: /\b(lint|warning|eslint|prettier|ruff|pylint|golangci-lint).*(error|fail|warn)/i,
|
|
5375
|
+
cat: "lint",
|
|
5376
|
+
sub: "linter-error",
|
|
5377
|
+
lang: void 0,
|
|
5378
|
+
hints: BH,
|
|
5379
|
+
detail: "Linter error / warning",
|
|
5380
|
+
conf: 0.85
|
|
5381
|
+
},
|
|
5382
|
+
// ── Performance ────────────────────────────────────────────────────────
|
|
5383
|
+
{
|
|
5384
|
+
pat: /\b(memory leak|oom|out of memory|heap overflow|stack overflow|infinite loop|bottleneck|performance issue)\b/i,
|
|
5385
|
+
cat: "perf",
|
|
5386
|
+
sub: "performance-issue",
|
|
5387
|
+
lang: void 0,
|
|
5388
|
+
hints: BH,
|
|
5389
|
+
detail: "Performance / memory issue",
|
|
5390
|
+
conf: 0.85
|
|
5391
|
+
},
|
|
5392
|
+
// ── Logic / wrong behavior ─────────────────────────────────────────────
|
|
5393
|
+
{
|
|
5394
|
+
pat: /\b(wrong|incorrect|unexpected|silent fail|bug|defect|logic error)\b/i,
|
|
5395
|
+
cat: "logic",
|
|
5396
|
+
sub: "wrong-behavior",
|
|
5397
|
+
lang: void 0,
|
|
5398
|
+
hints: BH,
|
|
5399
|
+
detail: "Logic / behavioral bug",
|
|
5400
|
+
conf: 0.8
|
|
5401
|
+
},
|
|
5402
|
+
{
|
|
5403
|
+
pat: /\b(off.?by.?one|boundary error|index error)\b/i,
|
|
5404
|
+
cat: "logic",
|
|
5405
|
+
sub: "wrong-behavior",
|
|
5406
|
+
lang: void 0,
|
|
5407
|
+
hints: BH,
|
|
5408
|
+
detail: "Off-by-one error",
|
|
5409
|
+
conf: 0.9
|
|
5410
|
+
},
|
|
5411
|
+
// ── C memory-safety (specific, after generic memory leak patterns above) ─
|
|
5412
|
+
{
|
|
5413
|
+
pat: /\b(heap-buffer-overflow|use-after-free|double-free)\b/i,
|
|
5414
|
+
cat: "perf",
|
|
5415
|
+
sub: "memory-safety",
|
|
5416
|
+
lang: "c",
|
|
5417
|
+
hints: BH,
|
|
5418
|
+
detail: "Memory safety issue (C/C++)",
|
|
5419
|
+
conf: 1
|
|
5420
|
+
},
|
|
5421
|
+
// ── Infra — AFTER more specific categories ─────────────────────────────
|
|
5422
|
+
{
|
|
5423
|
+
pat: /\b(env|environment|config|dotenv|yml|yaml|json.*config|docker|k8s|kubernetes)\b/i,
|
|
5424
|
+
cat: "infra",
|
|
5425
|
+
sub: "config-error",
|
|
5426
|
+
lang: void 0,
|
|
5427
|
+
hints: BH,
|
|
5428
|
+
detail: "Infrastructure / configuration error",
|
|
5429
|
+
conf: 0.8
|
|
5430
|
+
},
|
|
5431
|
+
{
|
|
5432
|
+
pat: /\b(git.*conflict|merge conflict|rebase.*fail|branch.*error|git.*error)\b/i,
|
|
5433
|
+
cat: "infra",
|
|
5434
|
+
sub: "git-error",
|
|
5435
|
+
lang: void 0,
|
|
5436
|
+
hints: BH,
|
|
5437
|
+
detail: "Git error",
|
|
5438
|
+
conf: 0.9
|
|
5439
|
+
},
|
|
5440
|
+
{
|
|
5441
|
+
pat: /\b(ci.?cd|pipeline|github action|circleci|jenkins|gitlab ci)\b/i,
|
|
5442
|
+
cat: "infra",
|
|
5443
|
+
sub: "config-error",
|
|
5444
|
+
lang: void 0,
|
|
5445
|
+
hints: BH,
|
|
5446
|
+
detail: "CI/CD pipeline error",
|
|
5447
|
+
conf: 0.9
|
|
5448
|
+
}
|
|
5449
|
+
];
|
|
5450
|
+
function classifyError(input) {
|
|
5451
|
+
const s = input.trim();
|
|
5452
|
+
for (const p of P) {
|
|
5453
|
+
const m = p.pat.exec(s);
|
|
5454
|
+
if (!m) continue;
|
|
5455
|
+
const detailStr = typeof p.detail === "function" ? p.detail(m) : p.detail;
|
|
5456
|
+
return {
|
|
5457
|
+
category: p.cat,
|
|
5458
|
+
subcategory: p.sub,
|
|
5459
|
+
language: p.lang ?? "unknown",
|
|
5460
|
+
framework: p.fw,
|
|
5461
|
+
skillHints: p.hints,
|
|
5462
|
+
errorCode: p.code ? p.code(m) : extractCode(s),
|
|
5463
|
+
confidence: p.conf ?? 0.8,
|
|
5464
|
+
detail: detailStr
|
|
5465
|
+
};
|
|
5466
|
+
}
|
|
5467
|
+
return {
|
|
5468
|
+
category: "general",
|
|
5469
|
+
subcategory: "unknown",
|
|
5470
|
+
language: "unknown",
|
|
5471
|
+
skillHints: BH,
|
|
5472
|
+
confidence: 0.3,
|
|
5473
|
+
detail: "General problem (unclassified)"
|
|
5474
|
+
};
|
|
5475
|
+
}
|
|
5476
|
+
function extractCode(s) {
|
|
5477
|
+
const ts = /\bTS\d+\b|\bCS\d+\b/.exec(s);
|
|
5478
|
+
if (ts) return ts[0];
|
|
5479
|
+
const rust = /\bE\d{4,}\b/.exec(s);
|
|
5480
|
+
if (rust) return rust[0];
|
|
5481
|
+
const c = /\bc\d+\b/i.exec(s);
|
|
5482
|
+
if (c) return c[0];
|
|
5483
|
+
return void 0;
|
|
5484
|
+
}
|
|
5485
|
+
function needsSubagent(c) {
|
|
5486
|
+
return c.confidence < 0.85;
|
|
5487
|
+
}
|
|
5488
|
+
function isSimpleFix(c) {
|
|
5489
|
+
return c.category === "ts" && c.confidence >= 0.9 || c.category === "runtime" && c.subcategory === "null-undefined-access" && c.confidence >= 0.85;
|
|
5490
|
+
}
|
|
5491
|
+
|
|
5492
|
+
// src/slash-commands/fix.ts
|
|
5493
|
+
function buildDirective(cli, errorText) {
|
|
5494
|
+
const lang = cli.language === "unknown" ? "" : ` (language: ${cli.language})`;
|
|
5495
|
+
switch (cli.category) {
|
|
5496
|
+
case "ts":
|
|
5497
|
+
return [
|
|
5498
|
+
`## Fix: TypeScript Error${lang}`,
|
|
5499
|
+
"",
|
|
5500
|
+
"```",
|
|
5501
|
+
`${errorText}`,
|
|
5502
|
+
"```",
|
|
5503
|
+
"",
|
|
5504
|
+
"Your task:",
|
|
5505
|
+
`1. Search for the error location in the codebase (grep for the error code "${cli.errorCode ?? ""}" or relevant type names)`,
|
|
5506
|
+
"2. Read the source file(s)",
|
|
5507
|
+
"3. Identify the root cause",
|
|
5508
|
+
"4. Fix with strict types \u2014 no `as any` or `@ts-ignore`",
|
|
5509
|
+
"5. Verify with `typecheck` or `tsc --noEmit`"
|
|
5510
|
+
].join("\n");
|
|
5511
|
+
case "security":
|
|
5512
|
+
return [
|
|
5513
|
+
`## Fix: Security Issue${lang}`,
|
|
5514
|
+
"",
|
|
5515
|
+
"```",
|
|
5516
|
+
`${errorText}`,
|
|
5517
|
+
"```",
|
|
5518
|
+
"",
|
|
5519
|
+
"Your task:",
|
|
5520
|
+
"1. Locate the vulnerable code (grep for hardcoded secrets, eval, innerHTML, SQL concatenation)",
|
|
5521
|
+
"2. Classify severity: critical / high / medium",
|
|
5522
|
+
"3. Apply the fix:",
|
|
5523
|
+
" - Secrets \u2192 rotate + use env vars or a secret manager",
|
|
5524
|
+
" - Injection \u2192 parameterized queries, safe DOM APIs",
|
|
5525
|
+
" - Auth \u2192 fix token handling",
|
|
5526
|
+
'4. Check for similar issues: `grep -r "password" --include="*.ts"` etc.',
|
|
5527
|
+
"5. Run security scan if available"
|
|
5528
|
+
].join("\n");
|
|
5529
|
+
case "runtime":
|
|
5530
|
+
return [
|
|
5531
|
+
`## Fix: Runtime Error${lang}`,
|
|
5532
|
+
"",
|
|
5533
|
+
"```",
|
|
5534
|
+
`${errorText}`,
|
|
5535
|
+
"```",
|
|
5536
|
+
"",
|
|
5537
|
+
"Your task:",
|
|
5538
|
+
"1. Locate the crash site (grep for error message or stack trace context)",
|
|
5539
|
+
"2. Read the relevant file(s)",
|
|
5540
|
+
"3. Identify root cause: null/undefined access, async race, wrong type, etc.",
|
|
5541
|
+
"4. Fix the error",
|
|
5542
|
+
"5. Verify \u2014 re-run or typecheck"
|
|
5543
|
+
].join("\n");
|
|
5544
|
+
case "compile":
|
|
5545
|
+
return [
|
|
5546
|
+
`## Fix: Compiler Error${lang}`,
|
|
5547
|
+
"",
|
|
5548
|
+
"```",
|
|
5549
|
+
`${errorText}`,
|
|
5550
|
+
"```",
|
|
5551
|
+
"",
|
|
5552
|
+
"Your task:",
|
|
5553
|
+
"1. Locate the file(s) with compile errors",
|
|
5554
|
+
"2. Read the error output carefully",
|
|
5555
|
+
"3. Fix the compile error",
|
|
5556
|
+
"4. Re-compile to verify"
|
|
5557
|
+
].join("\n");
|
|
5558
|
+
case "dep":
|
|
5559
|
+
return [
|
|
5560
|
+
`## Fix: Dependency / Import Error${lang}`,
|
|
5561
|
+
"",
|
|
5562
|
+
"```",
|
|
5563
|
+
`${errorText}`,
|
|
5564
|
+
"```",
|
|
5565
|
+
"",
|
|
5566
|
+
"Your task:",
|
|
5567
|
+
"1. Identify the missing module or failed import",
|
|
5568
|
+
"2. Fix: install the package, add to imports, or correct the path",
|
|
5569
|
+
"3. Verify imports resolve"
|
|
5570
|
+
].join("\n");
|
|
5571
|
+
case "infra":
|
|
5572
|
+
return [
|
|
5573
|
+
`## Fix: Infrastructure / Config Error${lang}`,
|
|
5574
|
+
"",
|
|
5575
|
+
"```",
|
|
5576
|
+
`${errorText}`,
|
|
5577
|
+
"```",
|
|
5578
|
+
"",
|
|
5579
|
+
"Your task:",
|
|
5580
|
+
"1. Locate the config file or infrastructure setup",
|
|
5581
|
+
"2. Identify the misconfiguration",
|
|
5582
|
+
"3. Fix the config",
|
|
5583
|
+
"4. Verify"
|
|
5584
|
+
].join("\n");
|
|
5585
|
+
case "perf":
|
|
5586
|
+
return [
|
|
5587
|
+
`## Fix: Performance / Memory Issue${lang}`,
|
|
5588
|
+
"",
|
|
5589
|
+
"```",
|
|
5590
|
+
`${errorText}`,
|
|
5591
|
+
"```",
|
|
5592
|
+
"",
|
|
5593
|
+
"Your task:",
|
|
5594
|
+
"1. Profile or locate the bottleneck",
|
|
5595
|
+
"2. Identify root cause",
|
|
5596
|
+
"3. Fix: memoize, batch, lazy-load, remove leak, fix loop",
|
|
5597
|
+
"4. Verify performance improvement"
|
|
5598
|
+
].join("\n");
|
|
5599
|
+
default:
|
|
5600
|
+
return [
|
|
5601
|
+
`## Fix: Problem Reported${lang}`,
|
|
5602
|
+
"",
|
|
5603
|
+
"```",
|
|
5604
|
+
`${errorText}`,
|
|
5605
|
+
"```",
|
|
5606
|
+
"",
|
|
5607
|
+
"Your task:",
|
|
5608
|
+
"1. Analyze the problem description",
|
|
5609
|
+
"2. Locate relevant files",
|
|
5610
|
+
"3. Identify the root cause",
|
|
5611
|
+
"4. Apply the fix",
|
|
5612
|
+
"5. Verify the fix works"
|
|
5613
|
+
].join("\n");
|
|
5614
|
+
}
|
|
5615
|
+
}
|
|
5616
|
+
function delegateRoleFor(cli) {
|
|
5617
|
+
switch (cli.category) {
|
|
5618
|
+
case "ts":
|
|
5619
|
+
return "typescript-strict";
|
|
5620
|
+
case "security":
|
|
5621
|
+
return "security-scanner";
|
|
5622
|
+
case "perf":
|
|
5623
|
+
return "refactor-planner";
|
|
5624
|
+
default:
|
|
5625
|
+
return "bug-hunter";
|
|
5626
|
+
}
|
|
5627
|
+
}
|
|
5628
|
+
function skillLabel(skillHints) {
|
|
5629
|
+
return skillHints.map((s) => `\`${s}\``).join(", ");
|
|
5630
|
+
}
|
|
5631
|
+
function categoryLabel(cli) {
|
|
5632
|
+
if (cli.language !== "unknown" && cli.language !== "unknown") {
|
|
5633
|
+
return `${cli.subcategory} (${cli.category}, ${cli.language})`;
|
|
5634
|
+
}
|
|
5635
|
+
return `${cli.subcategory} (${cli.category})`;
|
|
5636
|
+
}
|
|
5637
|
+
function buildFixCommand(opts) {
|
|
5638
|
+
return {
|
|
5639
|
+
name: "fix",
|
|
5640
|
+
description: "Classify a bug/error (any language), activate the right skill, and fix it \u2014 inline or via subagent.",
|
|
5641
|
+
argsHint: "<error message or problem description>",
|
|
5642
|
+
help: `
|
|
5643
|
+
# /fix \u2014 Problem Solver
|
|
5644
|
+
|
|
5645
|
+
Classifies an error, bug, or problem description from **any language/framework**,
|
|
5646
|
+
activates the right skill, and drives a focused fix workflow.
|
|
5647
|
+
|
|
5648
|
+
## Usage
|
|
5649
|
+
|
|
5650
|
+
\`\`\`
|
|
5651
|
+
/fix <error message or problem description>
|
|
5652
|
+
\`\`\`
|
|
5653
|
+
|
|
5654
|
+
## Supported languages & frameworks
|
|
5655
|
+
|
|
5656
|
+
TypeScript, Rust, Go, Python, Ruby, Java, Kotlin, Swift, C/C++, C#,
|
|
5657
|
+
PHP, Scala, Perl, Haskell, Elixir, Node.js, React, Next.js, Vue, Angular,
|
|
5658
|
+
Docker, Git, CI/CD, and more.
|
|
5659
|
+
|
|
5660
|
+
## Classification \u2192 skill mapping
|
|
5661
|
+
|
|
5662
|
+
| Error type | Language(s) | Skill activated |
|
|
5663
|
+
|---------------------|--------------------------|-----------------------|
|
|
5664
|
+
| TypeScript | TypeScript | \`typescript-strict\` |
|
|
5665
|
+
| Runtime / crash | Any | \`bug-hunter\` |
|
|
5666
|
+
| Security / secrets | Any | \`security-scanner\` |
|
|
5667
|
+
| Compiler error | Rust, Go, C/C++, Python | \`bug-hunter\` |
|
|
5668
|
+
| Dependency / import | Any | \`bug-hunter\` |
|
|
5669
|
+
| Performance / leak | Any | \`bug-hunter\` + \`refactor-planner\` |
|
|
5670
|
+
| Infrastructure | Config, Docker, Git, CI | \`bug-hunter\` |
|
|
5671
|
+
| React / Next.js | JavaScript | \`react-modern\` |
|
|
5672
|
+
| Node.js | JavaScript | \`node-modern\` |
|
|
5673
|
+
|
|
5674
|
+
## Auto-delegation
|
|
5675
|
+
|
|
5676
|
+
When the error confidence is low (< 0.85) or the problem spans multiple files,
|
|
5677
|
+
\`/fix\` automatically delegates to the matching specialist subagent via the
|
|
5678
|
+
\`onFix\` callback. Set \`onFix\` in \`SlashCommandContext\` to enable this.
|
|
5679
|
+
|
|
5680
|
+
## Examples
|
|
5681
|
+
|
|
5682
|
+
\`\`\`
|
|
5683
|
+
/fix TS2345: Argument of type 'string | null' is not assignable
|
|
5684
|
+
/fix TypeError: Cannot read property 'map' of undefined
|
|
5685
|
+
/fix error[E0503]: expected something but found E0503 in src/lib.rs
|
|
5686
|
+
/fix Segmentation fault (core dumped) at main.rs:42
|
|
5687
|
+
/fix AttributeError: 'NoneType' object has no attribute 'encode' (Python)
|
|
5688
|
+
/fix react-dom.development.js:172 Error: Invalid hook call
|
|
5689
|
+
/fix Security: hardcoded API key in config.ts
|
|
5690
|
+
/fix ERRO1014: SQL injection vulnerability in query builder
|
|
5691
|
+
\`\`\`
|
|
5692
|
+
`,
|
|
5693
|
+
async run(args, _ctx) {
|
|
5694
|
+
const trimmed = args.trim();
|
|
5695
|
+
if (!trimmed) {
|
|
5696
|
+
return {
|
|
5697
|
+
message: [
|
|
5698
|
+
`${color.bold("/fix \u2014 Problem Solver")}`,
|
|
5699
|
+
"",
|
|
5700
|
+
"Classifies an error from any language/framework and activates the right skill.",
|
|
5701
|
+
"",
|
|
5702
|
+
"Usage:",
|
|
5703
|
+
" /fix <error message or problem description>",
|
|
5704
|
+
"",
|
|
5705
|
+
"Examples:",
|
|
5706
|
+
` /fix ${color.dim('TS2345: Argument of type "string | null" is not assignable')}`,
|
|
5707
|
+
` /fix ${color.dim("TypeError: Cannot read property 'map' of undefined")}`,
|
|
5708
|
+
` /fix ${color.dim("error[E0503]: expected something but found E0503 in src/lib.rs")}`,
|
|
5709
|
+
` /fix ${color.dim("AttributeError: 'NoneType' object has no attribute 'encode'")}`,
|
|
5710
|
+
` /fix ${color.dim("react-dom.development.js:172 Error: Invalid hook call")}`,
|
|
5711
|
+
` /fix ${color.dim("Security: hardcoded API key in config.ts")}`,
|
|
5712
|
+
"",
|
|
5713
|
+
"Run `/help fix` for full documentation."
|
|
5714
|
+
].join("\n")
|
|
5715
|
+
};
|
|
5716
|
+
}
|
|
5717
|
+
const cli = classifyError(trimmed);
|
|
5718
|
+
const delegate = needsSubagent(cli);
|
|
5719
|
+
const delegateRole = delegate ? delegateRoleFor(cli) : void 0;
|
|
5720
|
+
const metadata = {
|
|
5721
|
+
skillHints: cli.skillHints,
|
|
5722
|
+
delegateRequested: delegate,
|
|
5723
|
+
delegateRole
|
|
5724
|
+
};
|
|
5725
|
+
if (isSimpleFix(cli) || !delegate && opts.onFix) {
|
|
5726
|
+
const runText2 = [
|
|
5727
|
+
"",
|
|
5728
|
+
`${color.bold("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550 /fix \u2014 Problem Solver \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")}`,
|
|
5729
|
+
"",
|
|
5730
|
+
`**Classification:** ${categoryLabel(cli)}`,
|
|
5731
|
+
`**Confidence:** ${Math.round(cli.confidence * 100)}%`,
|
|
5732
|
+
`**Error code:** \`${cli.errorCode ?? "n/a"}\``,
|
|
5733
|
+
"",
|
|
5734
|
+
`**Skills activated:** ${skillLabel(cli.skillHints)}`,
|
|
5735
|
+
"",
|
|
5736
|
+
`**Next step:** ${delegate ? "Delegating to `" + delegateRole + "` subagent..." : "Applying inline fix..."}`,
|
|
5737
|
+
""
|
|
5738
|
+
].join("\n") + "\n---\n" + buildDirective(cli, trimmed);
|
|
5739
|
+
if (opts.onFix) {
|
|
5740
|
+
const injected = await opts.onFix(trimmed);
|
|
5741
|
+
if (injected?.message) {
|
|
5742
|
+
return {
|
|
5743
|
+
message: injected.message,
|
|
5744
|
+
runText: injected.runText ?? runText2,
|
|
5745
|
+
metadata
|
|
5746
|
+
};
|
|
5747
|
+
}
|
|
5748
|
+
}
|
|
5749
|
+
return { message: `${color.green("\u2713")} [${categoryLabel(cli)}] \u2014 Skills: ${skillLabel(cli.skillHints)}`, runText: runText2, metadata };
|
|
5750
|
+
}
|
|
5751
|
+
if (delegate && delegateRole) {
|
|
5752
|
+
const taskPrompt = [
|
|
5753
|
+
`${color.bold("/fix \u2014 Auto-delegated fix")}`,
|
|
5754
|
+
"",
|
|
5755
|
+
`**Problem classification:** ${categoryLabel(cli)} (confidence: ${Math.round(cli.confidence * 100)}%)`,
|
|
5756
|
+
`**Error code:** \`${cli.errorCode ?? "n/a"}\``,
|
|
5757
|
+
`**Skills activated:** ${skillLabel(cli.skillHints)}`,
|
|
5758
|
+
"",
|
|
5759
|
+
buildDirective(cli, trimmed)
|
|
5760
|
+
].join("\n");
|
|
5761
|
+
metadata.delegateTask = taskPrompt;
|
|
5762
|
+
const runText2 = [
|
|
5763
|
+
"",
|
|
5764
|
+
`${color.bold("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550 /fix \u2014 Auto-delegated \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")}`,
|
|
5765
|
+
"",
|
|
5766
|
+
`**Delegating to:** \`${delegateRole}\` subagent`,
|
|
5767
|
+
`**Classification:** ${categoryLabel(cli)}`,
|
|
5768
|
+
`**Confidence:** ${Math.round(cli.confidence * 100)}% \u2014 delegation triggered (confidence < 85%)`,
|
|
5769
|
+
`**Skills activated:** ${skillLabel(cli.skillHints)}`,
|
|
5770
|
+
"",
|
|
5771
|
+
"The specialist subagent will now fix the issue. Results will be reported when complete."
|
|
5772
|
+
].join("\n");
|
|
5773
|
+
return { message: `${color.green("\u2713")} Delegating to \`${delegateRole}\`...`, runText: runText2, metadata };
|
|
5774
|
+
}
|
|
5775
|
+
const runText = [
|
|
5776
|
+
"",
|
|
5777
|
+
`${color.bold("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550 /fix \u2014 Problem Solver \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")}`,
|
|
5778
|
+
"",
|
|
5779
|
+
`**Classification:** ${categoryLabel(cli)} (confidence: ${Math.round(cli.confidence * 100)}%)`,
|
|
5780
|
+
`**Skills activated:** ${skillLabel(cli.skillHints)}`,
|
|
5781
|
+
""
|
|
5782
|
+
].join("\n") + "\n---\n" + buildDirective(cli, trimmed);
|
|
5783
|
+
return {
|
|
5784
|
+
message: `${color.green("\u2713")} [${categoryLabel(cli)}] \u2014 Skills: ${skillLabel(cli.skillHints)}`,
|
|
5785
|
+
runText,
|
|
5786
|
+
metadata
|
|
5787
|
+
};
|
|
5788
|
+
}
|
|
5789
|
+
};
|
|
5790
|
+
}
|
|
4822
5791
|
function makeInstaller(opts, projectRoot, global) {
|
|
4823
5792
|
const globalRoot = path23.join(os6.homedir(), ".wrongstack");
|
|
4824
5793
|
return new SkillInstaller({
|
|
@@ -5020,6 +5989,7 @@ function buildBuiltinSlashCommands(opts) {
|
|
|
5020
5989
|
buildGitcheckCommand(),
|
|
5021
5990
|
buildPushCommand(),
|
|
5022
5991
|
buildSecurityCommand(opts),
|
|
5992
|
+
buildFixCommand(opts),
|
|
5023
5993
|
buildStatuslineCommand({
|
|
5024
5994
|
cwd: opts.cwd,
|
|
5025
5995
|
hiddenItems: opts.statuslineHiddenItems ?? [],
|
|
@@ -7474,22 +8444,22 @@ function fmtDuration(ms) {
|
|
|
7474
8444
|
const remMin = m - h * 60;
|
|
7475
8445
|
return `${h}h${remMin}m`;
|
|
7476
8446
|
}
|
|
7477
|
-
function fmtTaskResultLine(r,
|
|
8447
|
+
function fmtTaskResultLine(r, color38) {
|
|
7478
8448
|
const stats = `${r.iterations}it ${r.toolCalls}tc ${fmtDuration(r.durationMs)}`;
|
|
7479
8449
|
const errMsg = typeof r.error === "string" ? r.error : r.error?.message;
|
|
7480
8450
|
const errKind = typeof r.error === "object" ? r.error?.kind : void 0;
|
|
7481
8451
|
const errTail = errMsg ? ` \u2014 ${errMsg.replace(/\s+/g, " ").slice(0, 80)}${errMsg.length > 80 ? "\u2026" : ""}` : "";
|
|
7482
|
-
const errKindChip = errKind ?
|
|
7483
|
-
const errSnip = errMsg || errKind ? `${errKindChip}${
|
|
8452
|
+
const errKindChip = errKind ? color38.dim(` [${errKind}]`) : "";
|
|
8453
|
+
const errSnip = errMsg || errKind ? `${errKindChip}${color38.dim(errTail)}` : "";
|
|
7484
8454
|
switch (r.status) {
|
|
7485
8455
|
case "success":
|
|
7486
|
-
return { mark:
|
|
8456
|
+
return { mark: color38.green("\u2713"), stats, tail: "" };
|
|
7487
8457
|
case "timeout":
|
|
7488
|
-
return { mark:
|
|
8458
|
+
return { mark: color38.yellow("\u23F1"), stats: `${color38.yellow("timeout")} ${stats}`, tail: errSnip };
|
|
7489
8459
|
case "stopped":
|
|
7490
|
-
return { mark:
|
|
8460
|
+
return { mark: color38.dim("\u2298"), stats: `${color38.dim("stopped")} ${stats}`, tail: errSnip };
|
|
7491
8461
|
case "failed":
|
|
7492
|
-
return { mark:
|
|
8462
|
+
return { mark: color38.red("\u2717"), stats: `${color38.red("failed")} ${stats}`, tail: errSnip };
|
|
7493
8463
|
}
|
|
7494
8464
|
}
|
|
7495
8465
|
|
|
@@ -7662,10 +8632,12 @@ async function runRepl(opts) {
|
|
|
7662
8632
|
opts.renderer.writeWarning("Exiting.");
|
|
7663
8633
|
process.exit(130);
|
|
7664
8634
|
}
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
opts.
|
|
8635
|
+
if (opts.getAutonomy?.() === "eternal" || opts.getAutonomy?.() === "eternal-parallel") {
|
|
8636
|
+
opts.getEternalEngine?.()?.stop();
|
|
8637
|
+
opts.getParallelEngine?.()?.stop();
|
|
8638
|
+
opts.onAutonomy?.("off");
|
|
8639
|
+
opts.renderer.writeWarning("Engine stop requested. Press Ctrl+C again to exit.");
|
|
8640
|
+
interrupts = 0;
|
|
7669
8641
|
return;
|
|
7670
8642
|
}
|
|
7671
8643
|
if (activeCtrl) {
|
|
@@ -7714,6 +8686,39 @@ async function runRepl(opts) {
|
|
|
7714
8686
|
await new Promise((resolve4) => setTimeout(resolve4, 250));
|
|
7715
8687
|
continue;
|
|
7716
8688
|
}
|
|
8689
|
+
} else if (opts.getAutonomy?.() === "eternal-parallel") {
|
|
8690
|
+
const engine = opts.getParallelEngine?.();
|
|
8691
|
+
if (!engine) {
|
|
8692
|
+
opts.renderer.writeWarning("Parallel mode set but no engine wired \u2014 falling back to off.");
|
|
8693
|
+
} else {
|
|
8694
|
+
const beforeGoal = await loadGoalSafe(opts);
|
|
8695
|
+
const beforeIter = beforeGoal?.iterations ?? 0;
|
|
8696
|
+
opts.renderer.write(
|
|
8697
|
+
color.magenta(`
|
|
8698
|
+
\u21B3 [parallel #${beforeIter + 1}] launching fan-out\u2026
|
|
8699
|
+
`)
|
|
8700
|
+
);
|
|
8701
|
+
interrupts = 0;
|
|
8702
|
+
try {
|
|
8703
|
+
const ok = await engine.runOneIteration();
|
|
8704
|
+
const afterGoal = await loadGoalSafe(opts);
|
|
8705
|
+
const last = afterGoal?.journal[afterGoal.journal.length - 1];
|
|
8706
|
+
if (last) {
|
|
8707
|
+
const mark = last.status === "success" ? color.green("\u2713") : last.status === "failure" ? color.red("\u2717") : color.amber("\u2298");
|
|
8708
|
+
const tail = last.note ? color.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
|
|
8709
|
+
opts.renderer.write(
|
|
8710
|
+
` ${mark} ${color.dim(`#${last.iteration}`)} ${color.dim(`[${last.source}]`)} ${last.task}${tail}
|
|
8711
|
+
`
|
|
8712
|
+
);
|
|
8713
|
+
}
|
|
8714
|
+
} catch (err) {
|
|
8715
|
+
opts.renderer.writeError(
|
|
8716
|
+
`[parallel] ${err instanceof Error ? err.message : String(err)}`
|
|
8717
|
+
);
|
|
8718
|
+
}
|
|
8719
|
+
await new Promise((resolve4) => setTimeout(resolve4, 250));
|
|
8720
|
+
continue;
|
|
8721
|
+
}
|
|
7717
8722
|
}
|
|
7718
8723
|
let raw;
|
|
7719
8724
|
try {
|
|
@@ -8131,7 +9136,9 @@ async function execute(deps) {
|
|
|
8131
9136
|
setStatuslineHiddenItems,
|
|
8132
9137
|
getYolo,
|
|
8133
9138
|
getAutonomy,
|
|
9139
|
+
onAutonomy,
|
|
8134
9140
|
getEternalEngine,
|
|
9141
|
+
getParallelEngine,
|
|
8135
9142
|
subscribeEternalIteration,
|
|
8136
9143
|
skillLoader
|
|
8137
9144
|
} = deps;
|
|
@@ -8330,7 +9337,9 @@ async function execute(deps) {
|
|
|
8330
9337
|
projectName: path23.basename(projectRoot) || void 0,
|
|
8331
9338
|
projectRoot,
|
|
8332
9339
|
getAutonomy,
|
|
9340
|
+
onAutonomy,
|
|
8333
9341
|
getEternalEngine,
|
|
9342
|
+
getParallelEngine,
|
|
8334
9343
|
skillLoader
|
|
8335
9344
|
});
|
|
8336
9345
|
} finally {
|
|
@@ -8349,6 +9358,9 @@ async function execute(deps) {
|
|
|
8349
9358
|
effectiveMaxContext,
|
|
8350
9359
|
projectName: path23.basename(projectRoot) || void 0,
|
|
8351
9360
|
getAutonomy,
|
|
9361
|
+
onAutonomy,
|
|
9362
|
+
getEternalEngine,
|
|
9363
|
+
getParallelEngine,
|
|
8352
9364
|
skillLoader
|
|
8353
9365
|
});
|
|
8354
9366
|
}
|
|
@@ -8559,8 +9571,15 @@ var MultiAgentHost = class {
|
|
|
8559
9571
|
outputBytes: e.outputBytes
|
|
8560
9572
|
});
|
|
8561
9573
|
});
|
|
9574
|
+
const offSummaryBridge = events.on("subagent.iteration_summary", (e) => {
|
|
9575
|
+
hostEvents.emit("subagent.iteration_summary", {
|
|
9576
|
+
...e,
|
|
9577
|
+
subagentId: subCfg.id ?? subCfg.name ?? "subagent"
|
|
9578
|
+
});
|
|
9579
|
+
});
|
|
8562
9580
|
const dispose = async () => {
|
|
8563
9581
|
offToolBridge();
|
|
9582
|
+
offSummaryBridge();
|
|
8564
9583
|
try {
|
|
8565
9584
|
await subSession.close?.();
|
|
8566
9585
|
} catch {
|
|
@@ -9509,6 +10528,7 @@ async function main(argv) {
|
|
|
9509
10528
|
modelsRegistry,
|
|
9510
10529
|
permission: {
|
|
9511
10530
|
yolo: config.yolo,
|
|
10531
|
+
forceAllYolo: flags["force-all-yolo"] === true,
|
|
9512
10532
|
promptDelegate: makePromptDelegate(reader)
|
|
9513
10533
|
},
|
|
9514
10534
|
compactor: { preserveK: config.context.preserveK, eliseThreshold: config.context.eliseThreshold },
|
|
@@ -9746,6 +10766,7 @@ async function main(argv) {
|
|
|
9746
10766
|
let director = null;
|
|
9747
10767
|
let autonomyMode = "off";
|
|
9748
10768
|
let eternalEngine = null;
|
|
10769
|
+
let parallelEngine = null;
|
|
9749
10770
|
const eternalListeners = /* @__PURE__ */ new Set();
|
|
9750
10771
|
const broadcastEternalIteration = (entry) => {
|
|
9751
10772
|
for (const fn of eternalListeners) {
|
|
@@ -10016,6 +11037,48 @@ async function main(argv) {
|
|
|
10016
11037
|
}
|
|
10017
11038
|
return `Unknown fleet action: ${action}`;
|
|
10018
11039
|
},
|
|
11040
|
+
onFleetStatus: () => {
|
|
11041
|
+
if (!director) return null;
|
|
11042
|
+
return director.status();
|
|
11043
|
+
},
|
|
11044
|
+
onFleetUsage: () => {
|
|
11045
|
+
if (!director) return null;
|
|
11046
|
+
return director.snapshot();
|
|
11047
|
+
},
|
|
11048
|
+
onFleetKill: () => {
|
|
11049
|
+
if (!director) return 0;
|
|
11050
|
+
const s = director.status();
|
|
11051
|
+
let killed = 0;
|
|
11052
|
+
for (const sa of s.subagents) {
|
|
11053
|
+
if (sa.status === "running" || sa.status === "idle") {
|
|
11054
|
+
try {
|
|
11055
|
+
director.terminate(sa.id);
|
|
11056
|
+
killed++;
|
|
11057
|
+
} catch {
|
|
11058
|
+
}
|
|
11059
|
+
}
|
|
11060
|
+
}
|
|
11061
|
+
return killed;
|
|
11062
|
+
},
|
|
11063
|
+
onFleetTerminate: (subagentId) => {
|
|
11064
|
+
if (!director) return false;
|
|
11065
|
+
try {
|
|
11066
|
+
director.terminate(subagentId);
|
|
11067
|
+
return true;
|
|
11068
|
+
} catch {
|
|
11069
|
+
return false;
|
|
11070
|
+
}
|
|
11071
|
+
},
|
|
11072
|
+
onFleetSpawn: async (role) => {
|
|
11073
|
+
if (!director) throw new Error("No director active \u2014 start with --director or use /autonomy parallel.");
|
|
11074
|
+
const cfg = FLEET_ROSTER[role] ?? {
|
|
11075
|
+
id: `manual-${Date.now()}`,
|
|
11076
|
+
name: role,
|
|
11077
|
+
maxIterations: 50,
|
|
11078
|
+
maxToolCalls: 200
|
|
11079
|
+
};
|
|
11080
|
+
return director.spawn(cfg);
|
|
11081
|
+
},
|
|
10019
11082
|
onFleetLog: async (subagentId, mode) => {
|
|
10020
11083
|
const subagentsRoot = path23.join(fleetRootForPromotion, "subagents");
|
|
10021
11084
|
let runDirs;
|
|
@@ -10264,25 +11327,35 @@ Restart WrongStack to load or unload plugin code in this session.`;
|
|
|
10264
11327
|
}
|
|
10265
11328
|
return autonomyMode;
|
|
10266
11329
|
},
|
|
10267
|
-
onEternalStart: () => {
|
|
10268
|
-
|
|
10269
|
-
|
|
10270
|
-
|
|
10271
|
-
|
|
10272
|
-
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
|
|
10276
|
-
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
|
|
10280
|
-
|
|
11330
|
+
onEternalStart: (mode) => {
|
|
11331
|
+
const effectiveMode = mode ?? "eternal";
|
|
11332
|
+
if (effectiveMode === "eternal-parallel") {
|
|
11333
|
+
if (!parallelEngine) {
|
|
11334
|
+
parallelEngine = new ParallelEternalEngine({
|
|
11335
|
+
agent,
|
|
11336
|
+
projectRoot,
|
|
11337
|
+
compactor: container.resolve(TOKENS.Compactor),
|
|
11338
|
+
maxContextTokens: effectiveMaxContext > 0 ? effectiveMaxContext : void 0,
|
|
11339
|
+
onIteration: broadcastEternalIteration
|
|
11340
|
+
});
|
|
11341
|
+
}
|
|
11342
|
+
void parallelEngine.prime?.();
|
|
11343
|
+
} else {
|
|
11344
|
+
if (!eternalEngine) {
|
|
11345
|
+
eternalEngine = new EternalAutonomyEngine({
|
|
11346
|
+
agent,
|
|
11347
|
+
projectRoot,
|
|
11348
|
+
compactor: container.resolve(TOKENS.Compactor),
|
|
11349
|
+
maxContextTokens: effectiveMaxContext > 0 ? effectiveMaxContext : void 0,
|
|
11350
|
+
onIteration: broadcastEternalIteration
|
|
11351
|
+
});
|
|
11352
|
+
}
|
|
11353
|
+
void eternalEngine.prime();
|
|
10281
11354
|
}
|
|
10282
|
-
void eternalEngine.prime();
|
|
10283
11355
|
},
|
|
10284
11356
|
onEternalStop: () => {
|
|
10285
11357
|
eternalEngine?.stop();
|
|
11358
|
+
parallelEngine?.stop();
|
|
10286
11359
|
},
|
|
10287
11360
|
onExit: () => {
|
|
10288
11361
|
void mcpRegistry.stopAll();
|
|
@@ -10402,7 +11475,15 @@ Restart WrongStack to load or unload plugin code in this session.`;
|
|
|
10402
11475
|
return policy.getYolo();
|
|
10403
11476
|
},
|
|
10404
11477
|
getAutonomy: () => autonomyMode,
|
|
11478
|
+
onAutonomy: (setTo) => {
|
|
11479
|
+
if (setTo !== void 0) {
|
|
11480
|
+
autonomyMode = setTo;
|
|
11481
|
+
return setTo;
|
|
11482
|
+
}
|
|
11483
|
+
return autonomyMode;
|
|
11484
|
+
},
|
|
10405
11485
|
getEternalEngine: () => eternalEngine,
|
|
11486
|
+
getParallelEngine: () => parallelEngine,
|
|
10406
11487
|
subscribeEternalIteration: (fn) => {
|
|
10407
11488
|
eternalListeners.add(fn);
|
|
10408
11489
|
return () => eternalListeners.delete(fn);
|