@wrongstack/cli 0.41.0 → 0.51.3
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/data/providers.json +22 -1
- package/dist/index.js +388 -277
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
package/dist/index.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import * as
|
|
2
|
+
import * as path8 from 'path';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import * as fsp3 from 'fs/promises';
|
|
5
|
-
import { color, writeErr, DefaultTaskStore, TaskTracker, renderProgress, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, renderTaskGraph, SpecVersioning, atomicWrite, DefaultPathResolver, TOKENS, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, SlashCommandRegistry, createDelegateTool, FLEET_ROSTER, createMcpControlTool, DefaultLogger, DefaultModelsRegistry, isStdinTTY, writeOut, runProviderWithRetry, ReplayLogStore, ReplayProviderRunner, ProviderRegistry, InMemoryMetricsSink, wireMetricsToEvents, DefaultHealthRegistry, startMetricsServer, RecoveryLock, DefaultAttachmentStore, QueueStore, Context, loadTodosCheckpoint, attachTodosCheckpoint, loadDirectorState, loadPlan, createDefaultPipelines, AutoCompactionMiddleware, estimateRequestTokensCalibrated, Agent, loadPlugins, FleetManager, makeDirectorSessionFactory, Director, makeFleetEmitTool, makeFleetStatusTool, resolveModelMatrix, AutoApprovePermissionPolicy, PhaseStore, AutoPhasePlanner, PhaseGraphBuilder, WorktreeManager, PhaseOrchestrator, makeLLMClassifier, ParallelEternalEngine, EternalAutonomyEngine, allServers as allServers$1,
|
|
5
|
+
import { color, writeErr, DefaultTaskStore, TaskTracker, renderProgress, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, renderTaskGraph, SpecVersioning, atomicWrite, DefaultPathResolver, TOKENS, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, SlashCommandRegistry, BrainDecisionQueue, ObservableBrainArbiter, HumanEscalatingBrainArbiter, DefaultBrainArbiter, createDelegateTool, FLEET_ROSTER, createMcpControlTool, DefaultLogger, DefaultModelsRegistry, isStdinTTY, writeOut, runProviderWithRetry, ReplayLogStore, ReplayProviderRunner, ProviderRegistry, InMemoryMetricsSink, wireMetricsToEvents, DefaultHealthRegistry, startMetricsServer, RecoveryLock, DefaultAttachmentStore, QueueStore, Context, loadTodosCheckpoint, attachTodosCheckpoint, loadDirectorState, loadPlan, createDefaultPipelines, AutoCompactionMiddleware, estimateRequestTokensCalibrated, Agent, loadPlugins, FleetManager, makeDirectorSessionFactory, Director, makeFleetEmitTool, makeFleetStatusTool, resolveModelMatrix, AutoApprovePermissionPolicy, PhaseStore, AutoPhasePlanner, PhaseGraphBuilder, WorktreeManager, PhaseOrchestrator, makeLLMClassifier, ParallelEternalEngine, EternalAutonomyEngine, allServers as allServers$1, bootConfig as bootConfig$1, setRawMode, DefaultSessionReader, resolveWstackPaths, ToolAuditLog, DefaultSessionRewinder, DefaultSessionStore, DefaultPluginAPI, makeAgentSubagentRunner, NULL_FLEET_BUS, buildChildEnv, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, AGENTS_BY_PHASE, dispatchAgent, formatTodosList, SessionRecovery, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, pendingBtwCount, setBtwNote, MATRIX_PHASE_KEYS, AGENT_CATALOG, matrixKeyKind, onResize, decryptConfigSecrets as decryptConfigSecrets$1, encryptConfigSecrets as encryptConfigSecrets$1, InputBuilder, FsError, ERROR_CODES } from '@wrongstack/core';
|
|
6
6
|
import { createRequire } from 'module';
|
|
7
|
-
import * as
|
|
8
|
-
import
|
|
7
|
+
import * as os2 from 'os';
|
|
8
|
+
import os2__default from 'os';
|
|
9
9
|
import * as crypto2 from 'crypto';
|
|
10
10
|
import { randomUUID } from 'crypto';
|
|
11
11
|
import { DefaultSecretVault, decryptConfigSecrets, encryptConfigSecrets, isSecretField } from '@wrongstack/core/security';
|
|
12
12
|
import { WebSocketServer, WebSocket } from 'ws';
|
|
13
13
|
import { MCPRegistry } from '@wrongstack/mcp';
|
|
14
|
-
import { buildProviderFactoriesFromRegistry, makeProviderFromConfig
|
|
14
|
+
import { capabilitiesFor, buildProviderFactoriesFromRegistry, makeProviderFromConfig } from '@wrongstack/providers';
|
|
15
15
|
import { createDefaultContainer, routeImagesForModel, readClipboardImage } from '@wrongstack/runtime';
|
|
16
16
|
import { builtinToolsPack, rememberTool, forgetTool } from '@wrongstack/tools';
|
|
17
17
|
import { fileURLToPath } from 'url';
|
|
18
18
|
import * as readline from 'readline';
|
|
19
|
-
import * as
|
|
19
|
+
import * as fs10 from 'fs';
|
|
20
20
|
import { writeFileSync, existsSync, readFileSync } from 'fs';
|
|
21
21
|
import { WrongStackACPServer } from '@wrongstack/acp/agent';
|
|
22
22
|
import { ACP_AGENT_COMMANDS, makeACPSubagentRunner, makeACPSubagentRunnerWithStop } from '@wrongstack/acp';
|
|
@@ -1395,7 +1395,7 @@ function sddHelp() {
|
|
|
1395
1395
|
async function gatherProjectContext2(projectRoot) {
|
|
1396
1396
|
const parts = [];
|
|
1397
1397
|
try {
|
|
1398
|
-
const pkgPath =
|
|
1398
|
+
const pkgPath = path8.join(projectRoot, "package.json");
|
|
1399
1399
|
const pkgRaw = await fsp3.readFile(pkgPath, "utf8");
|
|
1400
1400
|
const pkg = JSON.parse(pkgRaw);
|
|
1401
1401
|
parts.push(`Project: ${String(pkg.name ?? "unknown")}`);
|
|
@@ -1411,13 +1411,13 @@ async function gatherProjectContext2(projectRoot) {
|
|
|
1411
1411
|
} catch {
|
|
1412
1412
|
}
|
|
1413
1413
|
try {
|
|
1414
|
-
const tsconfigPath =
|
|
1414
|
+
const tsconfigPath = path8.join(projectRoot, "tsconfig.json");
|
|
1415
1415
|
await fsp3.access(tsconfigPath);
|
|
1416
1416
|
parts.push("Language: TypeScript");
|
|
1417
1417
|
} catch {
|
|
1418
1418
|
}
|
|
1419
1419
|
try {
|
|
1420
|
-
const srcDir =
|
|
1420
|
+
const srcDir = path8.join(projectRoot, "src");
|
|
1421
1421
|
const entries = await fsp3.readdir(srcDir, { withFileTypes: true });
|
|
1422
1422
|
const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
1423
1423
|
if (dirs.length > 0) {
|
|
@@ -1573,7 +1573,7 @@ __export(update_check_exports, {
|
|
|
1573
1573
|
getUpdateNotification: () => getUpdateNotification
|
|
1574
1574
|
});
|
|
1575
1575
|
function cachePath(homeFn = defaultHomeDir2) {
|
|
1576
|
-
return
|
|
1576
|
+
return path8.join(homeFn(), ".wrongstack", "update-cache.json");
|
|
1577
1577
|
}
|
|
1578
1578
|
function currentVersion() {
|
|
1579
1579
|
const req2 = createRequire(import.meta.url);
|
|
@@ -1610,7 +1610,7 @@ async function readCache(homeFn = defaultHomeDir2) {
|
|
|
1610
1610
|
}
|
|
1611
1611
|
async function writeCache(entry, homeFn = defaultHomeDir2) {
|
|
1612
1612
|
try {
|
|
1613
|
-
const dir =
|
|
1613
|
+
const dir = path8.dirname(cachePath(homeFn));
|
|
1614
1614
|
await fsp3.mkdir(dir, { recursive: true });
|
|
1615
1615
|
await fsp3.writeFile(cachePath(homeFn), JSON.stringify(entry, null, 2), "utf8");
|
|
1616
1616
|
} catch {
|
|
@@ -1683,7 +1683,7 @@ async function getUpdateNotification(signal, homeFn) {
|
|
|
1683
1683
|
var defaultHomeDir2, CACHE_TTL_MS;
|
|
1684
1684
|
var init_update_check = __esm({
|
|
1685
1685
|
"src/update-check.ts"() {
|
|
1686
|
-
defaultHomeDir2 = () =>
|
|
1686
|
+
defaultHomeDir2 = () => os2.homedir();
|
|
1687
1687
|
CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
1688
1688
|
}
|
|
1689
1689
|
});
|
|
@@ -1813,7 +1813,7 @@ async function runWebUI(opts) {
|
|
|
1813
1813
|
);
|
|
1814
1814
|
}
|
|
1815
1815
|
}
|
|
1816
|
-
return new Promise((
|
|
1816
|
+
return new Promise((resolve3) => {
|
|
1817
1817
|
wss.on("listening", () => {
|
|
1818
1818
|
console.log(`[WebUI] WebSocket server running on ws://127.0.0.1:${port}`);
|
|
1819
1819
|
setupEvents();
|
|
@@ -1914,7 +1914,7 @@ async function runWebUI(opts) {
|
|
|
1914
1914
|
clients.clear();
|
|
1915
1915
|
wss.close(() => {
|
|
1916
1916
|
console.log("[WebUI] Server stopped");
|
|
1917
|
-
|
|
1917
|
+
resolve3();
|
|
1918
1918
|
});
|
|
1919
1919
|
}
|
|
1920
1920
|
process.on("SIGINT", shutdown);
|
|
@@ -2231,7 +2231,7 @@ async function runWebUI(opts) {
|
|
|
2231
2231
|
return {};
|
|
2232
2232
|
}
|
|
2233
2233
|
if (!parsed.providers) return {};
|
|
2234
|
-
const keyFile =
|
|
2234
|
+
const keyFile = path8.join(path8.dirname(opts.globalConfigPath), ".key");
|
|
2235
2235
|
const vault = new DefaultSecretVault({ keyFile });
|
|
2236
2236
|
return decryptConfigSecrets(parsed.providers, vault);
|
|
2237
2237
|
}
|
|
@@ -2264,7 +2264,7 @@ async function runWebUI(opts) {
|
|
|
2264
2264
|
parsed = {};
|
|
2265
2265
|
}
|
|
2266
2266
|
parsed.providers = providers;
|
|
2267
|
-
const keyFile =
|
|
2267
|
+
const keyFile = path8.join(path8.dirname(opts.globalConfigPath), ".key");
|
|
2268
2268
|
const vault = new DefaultSecretVault({ keyFile });
|
|
2269
2269
|
const encrypted = encryptConfigSecrets(parsed, vault);
|
|
2270
2270
|
await atomicWrite(opts.globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
@@ -2338,6 +2338,34 @@ function makeProviderClassifier(provider, model) {
|
|
|
2338
2338
|
}
|
|
2339
2339
|
});
|
|
2340
2340
|
}
|
|
2341
|
+
async function resolveRuntimeMaxContext(input) {
|
|
2342
|
+
const explicitContext = positiveNumber(input.config.context?.effectiveMaxContext);
|
|
2343
|
+
if (explicitContext) return explicitContext;
|
|
2344
|
+
const providerConfig = input.runtimeProviderConfig ?? input.config.providers?.[input.providerId];
|
|
2345
|
+
const providerOverride = positiveNumber(readConfiguredMaxContext(providerConfig));
|
|
2346
|
+
if (providerOverride) return providerOverride;
|
|
2347
|
+
const topLevelBaseUrlApplies = input.providerId === input.config.provider;
|
|
2348
|
+
const hasCustomBaseUrl = Boolean(
|
|
2349
|
+
providerConfig?.baseUrl || topLevelBaseUrlApplies && input.config.baseUrl
|
|
2350
|
+
);
|
|
2351
|
+
if (input.modelsRegistry && !hasCustomBaseUrl) {
|
|
2352
|
+
const caps = await capabilitiesFor(input.modelsRegistry, input.providerId, input.modelId).catch(
|
|
2353
|
+
() => void 0
|
|
2354
|
+
);
|
|
2355
|
+
const catalogMax = positiveNumber(caps?.maxContext);
|
|
2356
|
+
if (catalogMax) return catalogMax;
|
|
2357
|
+
}
|
|
2358
|
+
return positiveNumber(input.provider.capabilities.maxContext) ?? 0;
|
|
2359
|
+
}
|
|
2360
|
+
function readConfiguredMaxContext(providerConfig) {
|
|
2361
|
+
if (!providerConfig || typeof providerConfig !== "object") return void 0;
|
|
2362
|
+
const capabilities = providerConfig.capabilities;
|
|
2363
|
+
if (!capabilities || typeof capabilities !== "object") return void 0;
|
|
2364
|
+
return capabilities.maxContext;
|
|
2365
|
+
}
|
|
2366
|
+
function positiveNumber(value) {
|
|
2367
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
2368
|
+
}
|
|
2341
2369
|
|
|
2342
2370
|
// src/arg-parser.ts
|
|
2343
2371
|
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
@@ -2485,10 +2513,10 @@ async function detectPackageManager(root, declared) {
|
|
|
2485
2513
|
const name = declared.split("@")[0];
|
|
2486
2514
|
if (name) return name;
|
|
2487
2515
|
}
|
|
2488
|
-
if (await pathExists(
|
|
2489
|
-
if (await pathExists(
|
|
2490
|
-
if (await pathExists(
|
|
2491
|
-
if (await pathExists(
|
|
2516
|
+
if (await pathExists(path8.join(root, "pnpm-lock.yaml"))) return "pnpm";
|
|
2517
|
+
if (await pathExists(path8.join(root, "bun.lockb"))) return "bun";
|
|
2518
|
+
if (await pathExists(path8.join(root, "bun.lock"))) return "bun";
|
|
2519
|
+
if (await pathExists(path8.join(root, "yarn.lock"))) return "yarn";
|
|
2492
2520
|
return "npm";
|
|
2493
2521
|
}
|
|
2494
2522
|
function hasUsableScript(scripts, name) {
|
|
@@ -2509,7 +2537,7 @@ function parseMakeTargets(makefile) {
|
|
|
2509
2537
|
async function detectProjectFacts(root) {
|
|
2510
2538
|
const facts = { hints: [] };
|
|
2511
2539
|
try {
|
|
2512
|
-
const pkg = JSON.parse(await fsp3.readFile(
|
|
2540
|
+
const pkg = JSON.parse(await fsp3.readFile(path8.join(root, "package.json"), "utf8"));
|
|
2513
2541
|
const scripts = pkg.scripts ?? {};
|
|
2514
2542
|
const pm = await detectPackageManager(root, pkg.packageManager);
|
|
2515
2543
|
if (hasUsableScript(scripts, "build")) facts.build = `${pm} run build`;
|
|
@@ -2523,14 +2551,14 @@ async function detectProjectFacts(root) {
|
|
|
2523
2551
|
} catch {
|
|
2524
2552
|
}
|
|
2525
2553
|
try {
|
|
2526
|
-
if (!await pathExists(
|
|
2554
|
+
if (!await pathExists(path8.join(root, "pyproject.toml"))) throw new Error("not python");
|
|
2527
2555
|
facts.test ??= "pytest";
|
|
2528
2556
|
facts.lint ??= "ruff check .";
|
|
2529
2557
|
facts.hints.push("pyproject.toml");
|
|
2530
2558
|
} catch {
|
|
2531
2559
|
}
|
|
2532
2560
|
try {
|
|
2533
|
-
if (!await pathExists(
|
|
2561
|
+
if (!await pathExists(path8.join(root, "go.mod"))) throw new Error("not go");
|
|
2534
2562
|
facts.build ??= "go build ./...";
|
|
2535
2563
|
facts.test ??= "go test ./...";
|
|
2536
2564
|
facts.run ??= "go run .";
|
|
@@ -2538,7 +2566,7 @@ async function detectProjectFacts(root) {
|
|
|
2538
2566
|
} catch {
|
|
2539
2567
|
}
|
|
2540
2568
|
try {
|
|
2541
|
-
if (!await pathExists(
|
|
2569
|
+
if (!await pathExists(path8.join(root, "Cargo.toml"))) throw new Error("not rust");
|
|
2542
2570
|
facts.build ??= "cargo build";
|
|
2543
2571
|
facts.test ??= "cargo test";
|
|
2544
2572
|
facts.lint ??= "cargo clippy";
|
|
@@ -2547,7 +2575,7 @@ async function detectProjectFacts(root) {
|
|
|
2547
2575
|
} catch {
|
|
2548
2576
|
}
|
|
2549
2577
|
try {
|
|
2550
|
-
const makefile = await fsp3.readFile(
|
|
2578
|
+
const makefile = await fsp3.readFile(path8.join(root, "Makefile"), "utf8");
|
|
2551
2579
|
const targets = parseMakeTargets(makefile);
|
|
2552
2580
|
facts.build ??= targets.has("build") ? "make build" : "make";
|
|
2553
2581
|
if (targets.has("test")) facts.test ??= "make test";
|
|
@@ -2729,8 +2757,16 @@ function buildAutonomyCommand(opts) {
|
|
|
2729
2757
|
const goal = await loadGoal(goalFilePath(opts.projectRoot));
|
|
2730
2758
|
if (goal) {
|
|
2731
2759
|
const u = summarizeUsage(goal);
|
|
2732
|
-
lines.push(
|
|
2733
|
-
|
|
2760
|
+
lines.push(
|
|
2761
|
+
color.dim(
|
|
2762
|
+
` Goal: ${goal.goal.length > 80 ? `${goal.goal.slice(0, 77)}\u2026` : goal.goal}`
|
|
2763
|
+
)
|
|
2764
|
+
);
|
|
2765
|
+
lines.push(
|
|
2766
|
+
color.dim(
|
|
2767
|
+
` Engine state: ${goal.engineState} \xB7 iterations: ${goal.iterations} \xB7 journal: ${goal.journal.length}`
|
|
2768
|
+
)
|
|
2769
|
+
);
|
|
2734
2770
|
if (u.iterationsWithUsage > 0) {
|
|
2735
2771
|
lines.push(
|
|
2736
2772
|
color.dim(
|
|
@@ -2741,7 +2777,9 @@ function buildAutonomyCommand(opts) {
|
|
|
2741
2777
|
const recent = goal.journal.slice(-10);
|
|
2742
2778
|
const failed = recent.filter((e) => e.status === "failure").length;
|
|
2743
2779
|
if (failed > 0) {
|
|
2744
|
-
lines.push(
|
|
2780
|
+
lines.push(
|
|
2781
|
+
color.amber(` Recent failures: ${failed} of last ${recent.length} iterations`)
|
|
2782
|
+
);
|
|
2745
2783
|
}
|
|
2746
2784
|
}
|
|
2747
2785
|
} catch {
|
|
@@ -2775,7 +2813,7 @@ function buildAutonomyCommand(opts) {
|
|
|
2775
2813
|
}
|
|
2776
2814
|
} catch {
|
|
2777
2815
|
}
|
|
2778
|
-
const msg2 = `${color.amber("Eternal/parallel mode stop requested.")}
|
|
2816
|
+
const msg2 = `${color.amber("Eternal/parallel mode stop requested.")} In-flight eternal work is cancelled; parallel fan-out stops after the current tick cleans up.${summaryLine}`;
|
|
2779
2817
|
opts.renderer.write(msg2);
|
|
2780
2818
|
return { message: msg2 };
|
|
2781
2819
|
}
|
|
@@ -2792,7 +2830,7 @@ function buildAutonomyCommand(opts) {
|
|
|
2792
2830
|
newMode = "eternal-parallel";
|
|
2793
2831
|
} else if (arg === "toggle" || arg === "cycle") {
|
|
2794
2832
|
const current = opts.onAutonomy() ?? "off";
|
|
2795
|
-
const cycle = ["off", "suggest", "auto", "eternal"];
|
|
2833
|
+
const cycle = ["off", "suggest", "auto", "eternal", "eternal-parallel"];
|
|
2796
2834
|
newMode = cycle[(cycle.indexOf(current) + 1) % cycle.length] ?? "off";
|
|
2797
2835
|
} else {
|
|
2798
2836
|
const msg2 = `Unknown argument: ${arg}. Use /autonomy on, off, suggest, eternal, parallel, stop, or toggle.`;
|
|
@@ -2907,7 +2945,7 @@ function formatPhaseList(graph) {
|
|
|
2907
2945
|
}
|
|
2908
2946
|
async function gatherProjectContext(projectRoot) {
|
|
2909
2947
|
try {
|
|
2910
|
-
const raw = await fsp3.readFile(
|
|
2948
|
+
const raw = await fsp3.readFile(path8.join(projectRoot, "package.json"), "utf8");
|
|
2911
2949
|
const pkg = JSON.parse(raw);
|
|
2912
2950
|
const parts = [
|
|
2913
2951
|
`Project: ${String(pkg.name ?? "unknown")}`,
|
|
@@ -4771,8 +4809,8 @@ function buildInitCommand(opts) {
|
|
|
4771
4809
|
name: "init",
|
|
4772
4810
|
description: "Create or update .wrongstack/AGENTS.md project context for the system prompt.",
|
|
4773
4811
|
async run(_args, ctx) {
|
|
4774
|
-
const dir =
|
|
4775
|
-
const file =
|
|
4812
|
+
const dir = path8.join(ctx.projectRoot, ".wrongstack");
|
|
4813
|
+
const file = path8.join(dir, "AGENTS.md");
|
|
4776
4814
|
const detected = await detectProjectFacts(ctx.projectRoot);
|
|
4777
4815
|
const body = renderAgentsTemplate(detected);
|
|
4778
4816
|
await fsp3.mkdir(dir, { recursive: true });
|
|
@@ -4963,18 +5001,18 @@ function stateBadge(state) {
|
|
|
4963
5001
|
return color.dim(state);
|
|
4964
5002
|
}
|
|
4965
5003
|
}
|
|
4966
|
-
async function readConfig(
|
|
5004
|
+
async function readConfig(path25) {
|
|
4967
5005
|
try {
|
|
4968
|
-
return JSON.parse(await fsp3.readFile(
|
|
5006
|
+
return JSON.parse(await fsp3.readFile(path25, "utf8"));
|
|
4969
5007
|
} catch {
|
|
4970
5008
|
return {};
|
|
4971
5009
|
}
|
|
4972
5010
|
}
|
|
4973
|
-
async function writeConfig(
|
|
5011
|
+
async function writeConfig(path25, cfg) {
|
|
4974
5012
|
const raw = JSON.stringify(cfg, null, 2);
|
|
4975
|
-
const tmp =
|
|
5013
|
+
const tmp = path25 + ".tmp";
|
|
4976
5014
|
await fsp3.writeFile(tmp, raw, "utf8");
|
|
4977
|
-
await fsp3.rename(tmp,
|
|
5015
|
+
await fsp3.rename(tmp, path25);
|
|
4978
5016
|
}
|
|
4979
5017
|
|
|
4980
5018
|
// src/slash-commands/mcp.ts
|
|
@@ -5854,7 +5892,7 @@ var DEFAULTS = {
|
|
|
5854
5892
|
cost: true
|
|
5855
5893
|
};
|
|
5856
5894
|
function resolveConfigPath() {
|
|
5857
|
-
return process.env[CONFIG_ENV] ??
|
|
5895
|
+
return process.env[CONFIG_ENV] ?? path8.join(process.env.HOME ?? "", ".wrongstack", "statusline.json");
|
|
5858
5896
|
}
|
|
5859
5897
|
async function loadStatuslineConfig() {
|
|
5860
5898
|
const p = resolveConfigPath();
|
|
@@ -5868,7 +5906,7 @@ async function loadStatuslineConfig() {
|
|
|
5868
5906
|
async function saveStatuslineConfig(cfg) {
|
|
5869
5907
|
const p = resolveConfigPath();
|
|
5870
5908
|
try {
|
|
5871
|
-
await fsp3.mkdir(
|
|
5909
|
+
await fsp3.mkdir(path8.dirname(p), { recursive: true });
|
|
5872
5910
|
await atomicWrite(p, JSON.stringify(cfg, null, 2));
|
|
5873
5911
|
} catch (err) {
|
|
5874
5912
|
throw new FsError({
|
|
@@ -6176,13 +6214,13 @@ var MANIFESTS = [
|
|
|
6176
6214
|
];
|
|
6177
6215
|
async function detectProjectKind(projectRoot) {
|
|
6178
6216
|
try {
|
|
6179
|
-
await fsp3.access(
|
|
6217
|
+
await fsp3.access(path8.join(projectRoot, ".wrongstack", "AGENTS.md"));
|
|
6180
6218
|
return "initialized";
|
|
6181
6219
|
} catch {
|
|
6182
6220
|
}
|
|
6183
6221
|
for (const m of MANIFESTS) {
|
|
6184
6222
|
try {
|
|
6185
|
-
await fsp3.access(
|
|
6223
|
+
await fsp3.access(path8.join(projectRoot, m));
|
|
6186
6224
|
return "project";
|
|
6187
6225
|
} catch {
|
|
6188
6226
|
}
|
|
@@ -6190,8 +6228,8 @@ async function detectProjectKind(projectRoot) {
|
|
|
6190
6228
|
return "empty";
|
|
6191
6229
|
}
|
|
6192
6230
|
async function scaffoldAgentsMd(projectRoot) {
|
|
6193
|
-
const dir =
|
|
6194
|
-
const file =
|
|
6231
|
+
const dir = path8.join(projectRoot, ".wrongstack");
|
|
6232
|
+
const file = path8.join(dir, "AGENTS.md");
|
|
6195
6233
|
const facts = await detectProjectFacts(projectRoot);
|
|
6196
6234
|
const body = renderAgentsTemplate(facts);
|
|
6197
6235
|
await fsp3.mkdir(dir, { recursive: true });
|
|
@@ -6204,7 +6242,7 @@ async function runProjectCheck(opts) {
|
|
|
6204
6242
|
if (kind === "initialized") {
|
|
6205
6243
|
renderer.write(
|
|
6206
6244
|
`
|
|
6207
|
-
${color.green("\u2713")} Project initialized ${color.dim(`(${
|
|
6245
|
+
${color.green("\u2713")} Project initialized ${color.dim(`(${path8.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
|
|
6208
6246
|
`
|
|
6209
6247
|
);
|
|
6210
6248
|
return true;
|
|
@@ -6235,7 +6273,7 @@ async function runProjectCheck(opts) {
|
|
|
6235
6273
|
}
|
|
6236
6274
|
return true;
|
|
6237
6275
|
}
|
|
6238
|
-
const gitDir =
|
|
6276
|
+
const gitDir = path8.join(projectRoot, ".git");
|
|
6239
6277
|
let hasGit = false;
|
|
6240
6278
|
try {
|
|
6241
6279
|
await fsp3.access(gitDir);
|
|
@@ -6258,10 +6296,10 @@ async function runProjectCheck(opts) {
|
|
|
6258
6296
|
if (answer2 === "y" || answer2 === "yes") {
|
|
6259
6297
|
try {
|
|
6260
6298
|
const { spawn: spawn3 } = await import('child_process');
|
|
6261
|
-
await new Promise((
|
|
6299
|
+
await new Promise((resolve3, reject) => {
|
|
6262
6300
|
const child = spawn3("git", ["init"], { cwd: projectRoot });
|
|
6263
6301
|
child.on("error", reject);
|
|
6264
|
-
child.on("close", (code) => code === 0 ?
|
|
6302
|
+
child.on("close", (code) => code === 0 ? resolve3() : reject(new Error(`git init failed with ${code}`)));
|
|
6265
6303
|
});
|
|
6266
6304
|
renderer.write(` ${color.green("\u2713")} Git repository initialized
|
|
6267
6305
|
`);
|
|
@@ -6360,78 +6398,21 @@ async function runLaunchPrompts(opts) {
|
|
|
6360
6398
|
return { mode, yolo, director, autonomy };
|
|
6361
6399
|
}
|
|
6362
6400
|
async function bootConfig(flags) {
|
|
6363
|
-
const
|
|
6364
|
-
const pathResolver =
|
|
6365
|
-
const projectRoot = pathResolver.projectRoot;
|
|
6366
|
-
const userHome = os3.homedir();
|
|
6367
|
-
const wpaths = resolveWstackPaths({ projectRoot, userHome });
|
|
6368
|
-
await ensureProjectMeta(wpaths, projectRoot);
|
|
6369
|
-
const vault = new DefaultSecretVault$1({ keyFile: wpaths.secretsKey });
|
|
6370
|
-
for (const file of [wpaths.globalConfig, wpaths.projectLocalConfig]) {
|
|
6371
|
-
try {
|
|
6372
|
-
const { migrated } = await migratePlaintextSecrets(file, vault);
|
|
6373
|
-
if (migrated > 0) {
|
|
6374
|
-
writeErr(`[wstack] Encrypted ${migrated} plaintext secret(s) in ${file}
|
|
6375
|
-
`);
|
|
6376
|
-
}
|
|
6377
|
-
} catch {
|
|
6378
|
-
}
|
|
6379
|
-
}
|
|
6380
|
-
const configLoader = new DefaultConfigLoader({ paths: wpaths, vault });
|
|
6381
|
-
let config = await configLoader.load({ cliFlags: flagsToConfigPatch(flags) });
|
|
6382
|
-
const syncConfig = await configLoader.loadSyncConfig();
|
|
6383
|
-
if (syncConfig) {
|
|
6384
|
-
config = Object.freeze({ ...config, sync: syncConfig });
|
|
6385
|
-
}
|
|
6401
|
+
const opts = { flags, appLabel: "wstack" };
|
|
6402
|
+
const { cwd, projectRoot, userHome, wpaths, pathResolver, config, vault } = await bootConfig$1(opts);
|
|
6386
6403
|
return {
|
|
6387
6404
|
paths: { cwd, projectRoot, userHome, wpaths, pathResolver },
|
|
6388
6405
|
config,
|
|
6389
6406
|
vault
|
|
6390
6407
|
};
|
|
6391
6408
|
}
|
|
6392
|
-
function flagsToConfigPatch(flags) {
|
|
6393
|
-
const patch = {};
|
|
6394
|
-
if (typeof flags["provider"] === "string") patch.provider = flags["provider"];
|
|
6395
|
-
if (typeof flags["model"] === "string") patch.model = flags["model"];
|
|
6396
|
-
if (typeof flags["cwd"] === "string") patch.cwd = flags["cwd"];
|
|
6397
|
-
if (typeof flags["log-level"] === "string") {
|
|
6398
|
-
patch.log = { level: flags["log-level"] };
|
|
6399
|
-
} else if (flags["verbose"]) {
|
|
6400
|
-
patch.log = { level: "debug" };
|
|
6401
|
-
} else if (flags["trace"]) {
|
|
6402
|
-
patch.log = { level: "trace" };
|
|
6403
|
-
}
|
|
6404
|
-
if (flags["yolo"]) patch.yolo = true;
|
|
6405
|
-
if (flags["no-features"]) {
|
|
6406
|
-
patch.features = {
|
|
6407
|
-
mcp: false,
|
|
6408
|
-
plugins: false,
|
|
6409
|
-
memory: false,
|
|
6410
|
-
modelsRegistry: false,
|
|
6411
|
-
skills: false
|
|
6412
|
-
};
|
|
6413
|
-
}
|
|
6414
|
-
return patch;
|
|
6415
|
-
}
|
|
6416
|
-
async function ensureProjectMeta(paths, projectRoot) {
|
|
6417
|
-
try {
|
|
6418
|
-
await fsp3.mkdir(paths.projectDir, { recursive: true });
|
|
6419
|
-
const meta = {
|
|
6420
|
-
hash: paths.projectHash,
|
|
6421
|
-
root: projectRoot,
|
|
6422
|
-
lastSeen: (/* @__PURE__ */ new Date()).toISOString()
|
|
6423
|
-
};
|
|
6424
|
-
await fsp3.writeFile(paths.projectMeta, JSON.stringify(meta, null, 2));
|
|
6425
|
-
} catch {
|
|
6426
|
-
}
|
|
6427
|
-
}
|
|
6428
6409
|
var ReadlineInputReader = class {
|
|
6429
6410
|
rl;
|
|
6430
6411
|
historyFile;
|
|
6431
6412
|
history = [];
|
|
6432
6413
|
pending = false;
|
|
6433
6414
|
constructor(opts = {}) {
|
|
6434
|
-
this.historyFile = opts.historyFile ??
|
|
6415
|
+
this.historyFile = opts.historyFile ?? path8.join(os2.homedir(), ".wrongstack", "history");
|
|
6435
6416
|
}
|
|
6436
6417
|
async loadHistory() {
|
|
6437
6418
|
try {
|
|
@@ -6443,7 +6424,7 @@ var ReadlineInputReader = class {
|
|
|
6443
6424
|
}
|
|
6444
6425
|
async saveHistory() {
|
|
6445
6426
|
try {
|
|
6446
|
-
await fsp3.mkdir(
|
|
6427
|
+
await fsp3.mkdir(path8.dirname(this.historyFile), { recursive: true });
|
|
6447
6428
|
await fsp3.writeFile(this.historyFile, this.history.slice(-1e3).join("\n"));
|
|
6448
6429
|
} catch {
|
|
6449
6430
|
}
|
|
@@ -6462,7 +6443,7 @@ var ReadlineInputReader = class {
|
|
|
6462
6443
|
async readLine(prompt) {
|
|
6463
6444
|
if (this.history.length === 0) await this.loadHistory();
|
|
6464
6445
|
while (this.pending) {
|
|
6465
|
-
await new Promise((
|
|
6446
|
+
await new Promise((resolve3) => setTimeout(resolve3, 50));
|
|
6466
6447
|
}
|
|
6467
6448
|
this.pending = true;
|
|
6468
6449
|
try {
|
|
@@ -6472,15 +6453,15 @@ var ReadlineInputReader = class {
|
|
|
6472
6453
|
this.rl = void 0;
|
|
6473
6454
|
}
|
|
6474
6455
|
const fresh = this.ensure();
|
|
6475
|
-
return new Promise((
|
|
6456
|
+
return new Promise((resolve3) => {
|
|
6476
6457
|
fresh.question(prompt ?? "> ", (line) => {
|
|
6477
6458
|
if (line.trim()) {
|
|
6478
6459
|
this.history.push(line);
|
|
6479
6460
|
void this.saveHistory();
|
|
6480
6461
|
}
|
|
6481
|
-
|
|
6462
|
+
resolve3(line);
|
|
6482
6463
|
});
|
|
6483
|
-
fresh.once("close", () =>
|
|
6464
|
+
fresh.once("close", () => resolve3(""));
|
|
6484
6465
|
}).then((result) => {
|
|
6485
6466
|
this.rl?.close();
|
|
6486
6467
|
this.rl = void 0;
|
|
@@ -6492,7 +6473,7 @@ var ReadlineInputReader = class {
|
|
|
6492
6473
|
}
|
|
6493
6474
|
async readKey(prompt, options) {
|
|
6494
6475
|
writeOut(prompt);
|
|
6495
|
-
return new Promise((
|
|
6476
|
+
return new Promise((resolve3) => {
|
|
6496
6477
|
const stdin = process.stdin;
|
|
6497
6478
|
const wasRaw = stdin.isRaw;
|
|
6498
6479
|
const wasPaused = stdin.isPaused();
|
|
@@ -6503,7 +6484,7 @@ var ReadlineInputReader = class {
|
|
|
6503
6484
|
if (key === "") {
|
|
6504
6485
|
cleanup();
|
|
6505
6486
|
writeOut("\n");
|
|
6506
|
-
|
|
6487
|
+
resolve3("");
|
|
6507
6488
|
return;
|
|
6508
6489
|
}
|
|
6509
6490
|
const opt = options.find(
|
|
@@ -6513,12 +6494,12 @@ var ReadlineInputReader = class {
|
|
|
6513
6494
|
cleanup();
|
|
6514
6495
|
writeOut(`${opt.key}
|
|
6515
6496
|
`);
|
|
6516
|
-
|
|
6497
|
+
resolve3(opt.value);
|
|
6517
6498
|
}
|
|
6518
6499
|
};
|
|
6519
6500
|
const onClose = () => {
|
|
6520
6501
|
cleanup();
|
|
6521
|
-
|
|
6502
|
+
resolve3("");
|
|
6522
6503
|
};
|
|
6523
6504
|
const cleanup = () => {
|
|
6524
6505
|
stdin.off("data", onData);
|
|
@@ -6546,7 +6527,7 @@ var ReadlineInputReader = class {
|
|
|
6546
6527
|
this.rl?.close();
|
|
6547
6528
|
this.rl = void 0;
|
|
6548
6529
|
writeOut(prompt);
|
|
6549
|
-
return new Promise((
|
|
6530
|
+
return new Promise((resolve3) => {
|
|
6550
6531
|
let buf = "";
|
|
6551
6532
|
const wasRaw = stdin.isRaw;
|
|
6552
6533
|
setRawMode(stdin, true);
|
|
@@ -6564,7 +6545,7 @@ var ReadlineInputReader = class {
|
|
|
6564
6545
|
cleanup();
|
|
6565
6546
|
writeOut(` ${dim(`[${buf.length} chars]`)}
|
|
6566
6547
|
`);
|
|
6567
|
-
|
|
6548
|
+
resolve3(buf);
|
|
6568
6549
|
return;
|
|
6569
6550
|
}
|
|
6570
6551
|
if (ch === "") {
|
|
@@ -6661,7 +6642,7 @@ async function buildPickableProviders(modelsRegistry, config) {
|
|
|
6661
6642
|
}
|
|
6662
6643
|
return out;
|
|
6663
6644
|
}
|
|
6664
|
-
var defaultUidFn = () =>
|
|
6645
|
+
var defaultUidFn = () => os2__default.userInfo().uid;
|
|
6665
6646
|
async function getFileUid(filePath) {
|
|
6666
6647
|
try {
|
|
6667
6648
|
const stat4 = await fsp3.stat(filePath);
|
|
@@ -6671,7 +6652,7 @@ async function getFileUid(filePath) {
|
|
|
6671
6652
|
}
|
|
6672
6653
|
}
|
|
6673
6654
|
async function checkConfigOwnership(homeFn, uidFn = defaultUidFn) {
|
|
6674
|
-
if (
|
|
6655
|
+
if (os2__default.platform() === "win32") return true;
|
|
6675
6656
|
const cfg = configPath(homeFn);
|
|
6676
6657
|
const fileUid = await getFileUid(cfg);
|
|
6677
6658
|
if (fileUid === void 0) return true;
|
|
@@ -6688,20 +6669,20 @@ function assertSafeToDelete(filename, parentDir) {
|
|
|
6688
6669
|
if (PROTECTED_BASENAMES.has(filename)) {
|
|
6689
6670
|
throw new Error(`Refusing to delete protected file: ${filename}`);
|
|
6690
6671
|
}
|
|
6691
|
-
if (filename !==
|
|
6672
|
+
if (filename !== path8.basename(filename)) {
|
|
6692
6673
|
throw new Error(`Refusing to delete path with traversal: ${filename}`);
|
|
6693
6674
|
}
|
|
6694
6675
|
if (!filename.startsWith("config.json.") || !filename.endsWith(".bak")) {
|
|
6695
6676
|
throw new Error(`Refusing to delete unknown file: ${filename}`);
|
|
6696
6677
|
}
|
|
6697
|
-
const resolvedParent =
|
|
6678
|
+
const resolvedParent = path8.resolve(parentDir);
|
|
6698
6679
|
if (!resolvedParent.endsWith(".wrongstack")) {
|
|
6699
6680
|
throw new Error(`Unexpected parent directory for bak prune: ${resolvedParent}`);
|
|
6700
6681
|
}
|
|
6701
6682
|
}
|
|
6702
6683
|
async function safeDelete(filePath) {
|
|
6703
|
-
const dir =
|
|
6704
|
-
const filename =
|
|
6684
|
+
const dir = path8.dirname(filePath);
|
|
6685
|
+
const filename = path8.basename(filePath);
|
|
6705
6686
|
try {
|
|
6706
6687
|
assertSafeToDelete(filename, dir);
|
|
6707
6688
|
await fsp3.unlink(filePath);
|
|
@@ -6744,18 +6725,18 @@ function diffSummary(oldCfg, newCfg) {
|
|
|
6744
6725
|
}
|
|
6745
6726
|
return changes.length > 0 ? changes.slice(0, 5).join(", ") : "no changes";
|
|
6746
6727
|
}
|
|
6747
|
-
var defaultHomeDir = () =>
|
|
6728
|
+
var defaultHomeDir = () => os2__default.homedir();
|
|
6748
6729
|
function historyDir(homeFn = defaultHomeDir) {
|
|
6749
|
-
return
|
|
6730
|
+
return path8.join(homeFn(), ".wrongstack", "config.history", "entries");
|
|
6750
6731
|
}
|
|
6751
6732
|
function historyIndexPath(homeFn = defaultHomeDir) {
|
|
6752
|
-
return
|
|
6733
|
+
return path8.join(homeFn(), ".wrongstack", "config.history", "index.json");
|
|
6753
6734
|
}
|
|
6754
6735
|
function configPath(homeFn = defaultHomeDir) {
|
|
6755
|
-
return
|
|
6736
|
+
return path8.join(homeFn(), ".wrongstack", "config.json");
|
|
6756
6737
|
}
|
|
6757
6738
|
function backupLastPath(homeFn = defaultHomeDir) {
|
|
6758
|
-
return
|
|
6739
|
+
return path8.join(homeFn(), ".wrongstack", "config.json.last");
|
|
6759
6740
|
}
|
|
6760
6741
|
function entryId(ts) {
|
|
6761
6742
|
return ts.replace(/[:.]/g, "-").slice(0, 19);
|
|
@@ -6810,17 +6791,17 @@ async function backupCurrent(homeFn = defaultHomeDir) {
|
|
|
6810
6791
|
}
|
|
6811
6792
|
if (content !== void 0) {
|
|
6812
6793
|
try {
|
|
6813
|
-
const bakPath =
|
|
6794
|
+
const bakPath = path8.join(homeFn(), ".wrongstack", `config.json.${ts}.bak`);
|
|
6814
6795
|
await atomicWrite(bakPath, content);
|
|
6815
6796
|
} catch {
|
|
6816
6797
|
}
|
|
6817
6798
|
}
|
|
6818
6799
|
try {
|
|
6819
|
-
const dir =
|
|
6800
|
+
const dir = path8.join(homeFn(), ".wrongstack");
|
|
6820
6801
|
const files = await fsp3.readdir(dir);
|
|
6821
6802
|
const baks = files.filter((f) => f.startsWith("config.json.") && f.endsWith(".bak")).sort().reverse();
|
|
6822
6803
|
for (const f of baks.slice(10)) {
|
|
6823
|
-
await safeDelete(
|
|
6804
|
+
await safeDelete(path8.join(dir, f));
|
|
6824
6805
|
}
|
|
6825
6806
|
} catch {
|
|
6826
6807
|
}
|
|
@@ -6838,7 +6819,7 @@ async function appendHistory(oldCfg, newCfg, description, homeFn = defaultHomeDi
|
|
|
6838
6819
|
};
|
|
6839
6820
|
try {
|
|
6840
6821
|
await fsp3.writeFile(
|
|
6841
|
-
|
|
6822
|
+
path8.join(historyDir(homeFn), `${id}.json`),
|
|
6842
6823
|
JSON.stringify(entry, null, 2),
|
|
6843
6824
|
"utf8"
|
|
6844
6825
|
);
|
|
@@ -6846,7 +6827,7 @@ async function appendHistory(oldCfg, newCfg, description, homeFn = defaultHomeDi
|
|
|
6846
6827
|
throw new FsError({
|
|
6847
6828
|
message: err instanceof Error ? err.message : String(err),
|
|
6848
6829
|
code: ERROR_CODES.FS_WRITE_FAILED,
|
|
6849
|
-
path:
|
|
6830
|
+
path: path8.join(historyDir(homeFn), `${id}.json`),
|
|
6850
6831
|
cause: err
|
|
6851
6832
|
});
|
|
6852
6833
|
}
|
|
@@ -6861,7 +6842,7 @@ async function listHistory(homeFn = defaultHomeDir) {
|
|
|
6861
6842
|
}
|
|
6862
6843
|
async function getHistoryEntry(id, homeFn = defaultHomeDir) {
|
|
6863
6844
|
try {
|
|
6864
|
-
const raw = await fsp3.readFile(
|
|
6845
|
+
const raw = await fsp3.readFile(path8.join(historyDir(homeFn), `${id}.json`), "utf8");
|
|
6865
6846
|
return JSON.parse(raw);
|
|
6866
6847
|
} catch {
|
|
6867
6848
|
return null;
|
|
@@ -6927,10 +6908,10 @@ var theme = { primary: color.amber };
|
|
|
6927
6908
|
async function saveToGlobalConfig(configPath2, provider, model, homeFn = () => process.env.HOME ?? __require("os").homedir()) {
|
|
6928
6909
|
try {
|
|
6929
6910
|
const { atomicWrite: atomicWrite10 } = await import('@wrongstack/core');
|
|
6930
|
-
const
|
|
6911
|
+
const fs22 = await import('fs/promises');
|
|
6931
6912
|
let existing = {};
|
|
6932
6913
|
try {
|
|
6933
|
-
const raw = await
|
|
6914
|
+
const raw = await fs22.readFile(configPath2, "utf8");
|
|
6934
6915
|
existing = JSON.parse(raw);
|
|
6935
6916
|
} catch {
|
|
6936
6917
|
}
|
|
@@ -7261,12 +7242,12 @@ function pickGroupIndex(opts) {
|
|
|
7261
7242
|
try {
|
|
7262
7243
|
let current = 0;
|
|
7263
7244
|
try {
|
|
7264
|
-
const parsed = Number.parseInt(
|
|
7245
|
+
const parsed = Number.parseInt(fs10.readFileSync(opts.cursorFile, "utf8").trim(), 10);
|
|
7265
7246
|
if (Number.isFinite(parsed)) current = wrap(parsed);
|
|
7266
7247
|
} catch {
|
|
7267
7248
|
}
|
|
7268
|
-
|
|
7269
|
-
|
|
7249
|
+
fs10.mkdirSync(path8.dirname(opts.cursorFile), { recursive: true });
|
|
7250
|
+
fs10.writeFileSync(opts.cursorFile, String(wrap(current + 1)));
|
|
7270
7251
|
return current;
|
|
7271
7252
|
} catch {
|
|
7272
7253
|
}
|
|
@@ -7601,14 +7582,14 @@ function summarize(value, name) {
|
|
|
7601
7582
|
if (typeof v === "object" && v !== null) {
|
|
7602
7583
|
const o = v;
|
|
7603
7584
|
if (name === "edit") {
|
|
7604
|
-
const
|
|
7585
|
+
const path25 = typeof o["path"] === "string" ? o["path"] : "";
|
|
7605
7586
|
const reps = typeof o["replacements"] === "number" ? o["replacements"] : 0;
|
|
7606
|
-
return `${
|
|
7587
|
+
return `${path25} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
|
|
7607
7588
|
}
|
|
7608
7589
|
if (name === "write") {
|
|
7609
|
-
const
|
|
7590
|
+
const path25 = typeof o["path"] === "string" ? o["path"] : "";
|
|
7610
7591
|
const bytes = typeof o["bytes"] === "number" ? o["bytes"] : void 0;
|
|
7611
|
-
return bytes !== void 0 ? `${
|
|
7592
|
+
return bytes !== void 0 ? `${path25} ${bytes}B` : path25;
|
|
7612
7593
|
}
|
|
7613
7594
|
if (typeof o["count"] === "number") {
|
|
7614
7595
|
return `${o["count"]} match${o["count"] === 1 ? "" : "es"}`;
|
|
@@ -8468,7 +8449,7 @@ var updateCmd = async (args, deps) => {
|
|
|
8468
8449
|
deps.renderer.write(`Updating wrongstack from v${info.current} to v${info.latest}...
|
|
8469
8450
|
`);
|
|
8470
8451
|
try {
|
|
8471
|
-
const result = await new Promise((
|
|
8452
|
+
const result = await new Promise((resolve3, reject) => {
|
|
8472
8453
|
const child = spawn("npm", ["install", "-g", "wrongstack@latest"], {
|
|
8473
8454
|
cwd,
|
|
8474
8455
|
stdio: "pipe"
|
|
@@ -8478,7 +8459,7 @@ var updateCmd = async (args, deps) => {
|
|
|
8478
8459
|
_stderr += d;
|
|
8479
8460
|
});
|
|
8480
8461
|
child.on("error", reject);
|
|
8481
|
-
child.on("close", (code) =>
|
|
8462
|
+
child.on("close", (code) => resolve3({ code: code ?? 0 }));
|
|
8482
8463
|
});
|
|
8483
8464
|
if (result.code === 0) {
|
|
8484
8465
|
deps.renderer.write(`
|
|
@@ -8539,7 +8520,7 @@ var diagCmd = async (_args, deps) => {
|
|
|
8539
8520
|
` modelsCache: ${deps.paths.modelsCache}`,
|
|
8540
8521
|
` cacheAge: ${isFinite(age) ? `${Math.round(age / 60)}m` : "never"}`,
|
|
8541
8522
|
` node: ${process.version}`,
|
|
8542
|
-
` os: ${
|
|
8523
|
+
` os: ${os2.platform()} ${os2.release()}`,
|
|
8543
8524
|
` provider: ${cfg.provider ?? "<unset>"}`,
|
|
8544
8525
|
` model: ${cfg.model ?? "<unset>"}`,
|
|
8545
8526
|
` tools: ${deps.toolRegistry?.list().length ?? 0}`,
|
|
@@ -8618,7 +8599,7 @@ var doctorCmd = async (_args, deps) => {
|
|
|
8618
8599
|
}
|
|
8619
8600
|
try {
|
|
8620
8601
|
await fsp3.mkdir(deps.paths.projectSessions, { recursive: true });
|
|
8621
|
-
const probe =
|
|
8602
|
+
const probe = path8.join(deps.paths.projectSessions, `.probe-${Date.now()}`);
|
|
8622
8603
|
await fsp3.writeFile(probe, "");
|
|
8623
8604
|
await fsp3.unlink(probe);
|
|
8624
8605
|
checks.push({ name: "sessions writable", status: "ok", detail: deps.paths.projectSessions });
|
|
@@ -8721,8 +8702,8 @@ var exportCmd = async (args, deps) => {
|
|
|
8721
8702
|
return 1;
|
|
8722
8703
|
}
|
|
8723
8704
|
if (output) {
|
|
8724
|
-
await fsp3.mkdir(
|
|
8725
|
-
await fsp3.writeFile(
|
|
8705
|
+
await fsp3.mkdir(path8.dirname(path8.resolve(deps.cwd, output)), { recursive: true });
|
|
8706
|
+
await fsp3.writeFile(path8.resolve(deps.cwd, output), rendered, "utf8");
|
|
8726
8707
|
deps.renderer.write(`Wrote ${rendered.length} bytes to ${output}
|
|
8727
8708
|
`);
|
|
8728
8709
|
} else {
|
|
@@ -8795,8 +8776,8 @@ var initCmd = async (_args, deps) => {
|
|
|
8795
8776
|
const vault = new DefaultSecretVault({ keyFile: deps.paths.secretsKey });
|
|
8796
8777
|
const encrypted = encryptConfigSecrets(config, vault);
|
|
8797
8778
|
await atomicWrite(deps.paths.globalConfig, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
8798
|
-
await fsp3.mkdir(
|
|
8799
|
-
const agentsFile =
|
|
8779
|
+
await fsp3.mkdir(path8.join(deps.projectRoot, ".wrongstack"), { recursive: true });
|
|
8780
|
+
const agentsFile = path8.join(deps.projectRoot, ".wrongstack", "AGENTS.md");
|
|
8800
8781
|
const projectFacts = await detectProjectFacts(deps.projectRoot);
|
|
8801
8782
|
await atomicWrite(agentsFile, renderAgentsTemplate(projectFacts));
|
|
8802
8783
|
deps.renderer.writeInfo(`Wrote ${deps.paths.globalConfig}`);
|
|
@@ -9102,7 +9083,7 @@ var usageCmd = async (_args, deps) => {
|
|
|
9102
9083
|
return 0;
|
|
9103
9084
|
};
|
|
9104
9085
|
var projectsCmd = async (_args, deps) => {
|
|
9105
|
-
const projectsRoot =
|
|
9086
|
+
const projectsRoot = path8.join(deps.paths.globalRoot, "projects");
|
|
9106
9087
|
try {
|
|
9107
9088
|
const entries = await fsp3.readdir(projectsRoot);
|
|
9108
9089
|
if (entries.length === 0) {
|
|
@@ -9112,7 +9093,7 @@ var projectsCmd = async (_args, deps) => {
|
|
|
9112
9093
|
for (const hash of entries) {
|
|
9113
9094
|
try {
|
|
9114
9095
|
const meta = JSON.parse(
|
|
9115
|
-
await fsp3.readFile(
|
|
9096
|
+
await fsp3.readFile(path8.join(projectsRoot, hash, "meta.json"), "utf8")
|
|
9116
9097
|
);
|
|
9117
9098
|
deps.renderer.write(
|
|
9118
9099
|
` ${color.dim(hash)} ${color.dim(meta.lastSeen ?? "")} ${meta.root ?? "?"}
|
|
@@ -9271,7 +9252,7 @@ async function listFleetRuns(deps) {
|
|
|
9271
9252
|
}
|
|
9272
9253
|
const runs = [];
|
|
9273
9254
|
for (const id of entries) {
|
|
9274
|
-
const runDir =
|
|
9255
|
+
const runDir = path8.join(deps.paths.projectSessions, id);
|
|
9275
9256
|
let stat4;
|
|
9276
9257
|
try {
|
|
9277
9258
|
stat4 = await fsp3.stat(runDir);
|
|
@@ -9284,17 +9265,17 @@ async function listFleetRuns(deps) {
|
|
|
9284
9265
|
let subagentCount = 0;
|
|
9285
9266
|
let subagentsDir;
|
|
9286
9267
|
try {
|
|
9287
|
-
await fsp3.access(
|
|
9268
|
+
await fsp3.access(path8.join(runDir, "fleet.json"));
|
|
9288
9269
|
manifest = true;
|
|
9289
9270
|
} catch {
|
|
9290
9271
|
}
|
|
9291
9272
|
try {
|
|
9292
|
-
await fsp3.access(
|
|
9273
|
+
await fsp3.access(path8.join(runDir, "checkpoint.json"));
|
|
9293
9274
|
checkpoint = true;
|
|
9294
9275
|
} catch {
|
|
9295
9276
|
}
|
|
9296
9277
|
try {
|
|
9297
|
-
subagentsDir =
|
|
9278
|
+
subagentsDir = path8.join(runDir, "subagents");
|
|
9298
9279
|
const files = await fsp3.readdir(subagentsDir);
|
|
9299
9280
|
subagentCount = files.filter((f) => f.endsWith(".jsonl")).length;
|
|
9300
9281
|
} catch {
|
|
@@ -9323,7 +9304,7 @@ async function listFleetRuns(deps) {
|
|
|
9323
9304
|
return 0;
|
|
9324
9305
|
}
|
|
9325
9306
|
async function showFleetRun(runId, deps) {
|
|
9326
|
-
const runDir =
|
|
9307
|
+
const runDir = path8.join(deps.paths.projectSessions, runId);
|
|
9327
9308
|
let stat4;
|
|
9328
9309
|
try {
|
|
9329
9310
|
stat4 = await fsp3.stat(runDir);
|
|
@@ -9340,7 +9321,7 @@ async function showFleetRun(runId, deps) {
|
|
|
9340
9321
|
deps.renderer.write(color.bold(`
|
|
9341
9322
|
Fleet Run: ${runId}
|
|
9342
9323
|
`) + "\n");
|
|
9343
|
-
const manifestPath =
|
|
9324
|
+
const manifestPath = path8.join(runDir, "fleet.json");
|
|
9344
9325
|
let manifestData = null;
|
|
9345
9326
|
try {
|
|
9346
9327
|
manifestData = await fsp3.readFile(manifestPath, "utf8");
|
|
@@ -9356,7 +9337,7 @@ Fleet Run: ${runId}
|
|
|
9356
9337
|
deps.renderer.write(` ${color.dim("\u25CB")} fleet.json \u2014 not found
|
|
9357
9338
|
`);
|
|
9358
9339
|
}
|
|
9359
|
-
const checkpointPath =
|
|
9340
|
+
const checkpointPath = path8.join(runDir, "checkpoint.json");
|
|
9360
9341
|
let checkpointData = null;
|
|
9361
9342
|
try {
|
|
9362
9343
|
checkpointData = await fsp3.readFile(checkpointPath, "utf8");
|
|
@@ -9403,7 +9384,7 @@ Fleet Run: ${runId}
|
|
|
9403
9384
|
} catch {
|
|
9404
9385
|
}
|
|
9405
9386
|
}
|
|
9406
|
-
const subagentsDir =
|
|
9387
|
+
const subagentsDir = path8.join(runDir, "subagents");
|
|
9407
9388
|
let subagentFiles = [];
|
|
9408
9389
|
try {
|
|
9409
9390
|
subagentFiles = await fsp3.readdir(subagentsDir);
|
|
@@ -9415,7 +9396,7 @@ Fleet Run: ${runId}
|
|
|
9415
9396
|
Subagent transcripts (${subagentFiles.length}):
|
|
9416
9397
|
`);
|
|
9417
9398
|
for (const f of subagentFiles.sort()) {
|
|
9418
|
-
const filePath =
|
|
9399
|
+
const filePath = path8.join(subagentsDir, f);
|
|
9419
9400
|
let size;
|
|
9420
9401
|
try {
|
|
9421
9402
|
const s = await fsp3.stat(filePath);
|
|
@@ -9432,7 +9413,7 @@ Fleet Run: ${runId}
|
|
|
9432
9413
|
${color.dim("\u25CB")} No subagent transcripts
|
|
9433
9414
|
`);
|
|
9434
9415
|
}
|
|
9435
|
-
const sharedDir =
|
|
9416
|
+
const sharedDir = path8.join(runDir, "shared");
|
|
9436
9417
|
try {
|
|
9437
9418
|
const files = await fsp3.readdir(sharedDir);
|
|
9438
9419
|
deps.renderer.write(`
|
|
@@ -9599,7 +9580,7 @@ function findSessionId(args) {
|
|
|
9599
9580
|
var rewindCmd = async (args, deps) => {
|
|
9600
9581
|
const flags = parseRewindFlags(args);
|
|
9601
9582
|
const wpaths = resolveWstackPaths({ projectRoot: deps.projectRoot });
|
|
9602
|
-
const sessionsDir =
|
|
9583
|
+
const sessionsDir = path8.join(wpaths.globalRoot, "sessions");
|
|
9603
9584
|
const rewind = new DefaultSessionRewinder(sessionsDir, deps.projectRoot);
|
|
9604
9585
|
let sessionId = findSessionId(args);
|
|
9605
9586
|
if (!sessionId) {
|
|
@@ -9834,10 +9815,10 @@ var auditCmd = async (args, deps) => {
|
|
|
9834
9815
|
return verify.ok ? 0 : 1;
|
|
9835
9816
|
};
|
|
9836
9817
|
async function listAudits(log, dir, deps) {
|
|
9837
|
-
const
|
|
9818
|
+
const fs22 = await import('fs/promises');
|
|
9838
9819
|
let entries;
|
|
9839
9820
|
try {
|
|
9840
|
-
entries = await
|
|
9821
|
+
entries = await fs22.readdir(dir);
|
|
9841
9822
|
} catch {
|
|
9842
9823
|
deps.renderer.write(
|
|
9843
9824
|
color.dim(`No sessions dir found at ${dir}. Run a session first.`) + "\n"
|
|
@@ -9892,7 +9873,7 @@ var skillsCmd = async (_args, deps) => {
|
|
|
9892
9873
|
};
|
|
9893
9874
|
var versionCmd = async (_args, deps) => {
|
|
9894
9875
|
deps.renderer.write(
|
|
9895
|
-
`WrongStack ${CLI_VERSION} (apiVersion ${API_VERSION}, node ${process.version}, ${
|
|
9876
|
+
`WrongStack ${CLI_VERSION} (apiVersion ${API_VERSION}, node ${process.version}, ${os2.platform()})
|
|
9896
9877
|
`
|
|
9897
9878
|
);
|
|
9898
9879
|
return 0;
|
|
@@ -10007,7 +9988,7 @@ function resolveBundledSkillsDir() {
|
|
|
10007
9988
|
try {
|
|
10008
9989
|
const req2 = createRequire(import.meta.url);
|
|
10009
9990
|
const corePkg = req2.resolve("@wrongstack/core/package.json");
|
|
10010
|
-
return
|
|
9991
|
+
return path8.join(path8.dirname(corePkg), "skills");
|
|
10011
9992
|
} catch {
|
|
10012
9993
|
return void 0;
|
|
10013
9994
|
}
|
|
@@ -10038,7 +10019,12 @@ async function boot(argv) {
|
|
|
10038
10019
|
const reader = new ReadlineInputReader({ historyFile: wpaths.historyFile });
|
|
10039
10020
|
const modelsRegistry = new DefaultModelsRegistry({
|
|
10040
10021
|
cacheFile: wpaths.modelsCache,
|
|
10041
|
-
|
|
10022
|
+
// Force a refresh attempt once per CLI process. Model metadata changes faster
|
|
10023
|
+
// than releases (new model ids, corrected context windows), and stale cache
|
|
10024
|
+
// here directly affects runtime behavior like context bars and compaction.
|
|
10025
|
+
// If the network is unavailable, DefaultModelsRegistry still falls back to
|
|
10026
|
+
// stale cache or the bundled overlay instead of failing startup.
|
|
10027
|
+
ttlSeconds: 0,
|
|
10042
10028
|
// Curated overlay merged on top of models.dev: fetched from GitHub raw for
|
|
10043
10029
|
// freshness, with the bundled file as the offline floor.
|
|
10044
10030
|
overlayUrl: GITHUB_PROVIDERS_OVERLAY_URL,
|
|
@@ -10143,7 +10129,8 @@ async function boot(argv) {
|
|
|
10143
10129
|
else if (flags["no-director"] === true) directorPinned = false;
|
|
10144
10130
|
let autonomyPinned;
|
|
10145
10131
|
if (flags["no-autonomy"] === true) autonomyPinned = "off";
|
|
10146
|
-
else if (flags["eternal"] === true)
|
|
10132
|
+
else if (flags["eternal"] === true)
|
|
10133
|
+
autonomyPinned = "off";
|
|
10147
10134
|
else if (typeof flags["autonomy"] === "string") {
|
|
10148
10135
|
const v = flags["autonomy"].toLowerCase();
|
|
10149
10136
|
autonomyPinned = v === "off" || v === "no" || v === "false" ? "off" : "auto";
|
|
@@ -10178,7 +10165,7 @@ async function boot(argv) {
|
|
|
10178
10165
|
if (choices.director) flags["director"] = true;
|
|
10179
10166
|
flags["autonomy"] = choices.autonomy;
|
|
10180
10167
|
printLaunchHints(renderer, flags, {
|
|
10181
|
-
cursorFile:
|
|
10168
|
+
cursorFile: path8.join(wpaths.cacheDir, "hint-cursor")
|
|
10182
10169
|
});
|
|
10183
10170
|
}
|
|
10184
10171
|
return {
|
|
@@ -10556,7 +10543,7 @@ async function runRepl(opts) {
|
|
|
10556
10543
|
`[eternal] ${err instanceof Error ? err.message : String(err)}`
|
|
10557
10544
|
);
|
|
10558
10545
|
}
|
|
10559
|
-
await new Promise((
|
|
10546
|
+
await new Promise((resolve3) => setTimeout(resolve3, 250));
|
|
10560
10547
|
continue;
|
|
10561
10548
|
}
|
|
10562
10549
|
} else if (opts.getAutonomy?.() === "eternal-parallel") {
|
|
@@ -10602,7 +10589,7 @@ async function runRepl(opts) {
|
|
|
10602
10589
|
`[parallel] ${err instanceof Error ? err.message : String(err)}`
|
|
10603
10590
|
);
|
|
10604
10591
|
}
|
|
10605
|
-
await new Promise((
|
|
10592
|
+
await new Promise((resolve3) => setTimeout(resolve3, 250));
|
|
10606
10593
|
continue;
|
|
10607
10594
|
}
|
|
10608
10595
|
}
|
|
@@ -11256,6 +11243,11 @@ async function execute(deps) {
|
|
|
11256
11243
|
"phase.taskCompleted",
|
|
11257
11244
|
"phase.taskFailed",
|
|
11258
11245
|
"phase.taskRetrying",
|
|
11246
|
+
"phase.verifying",
|
|
11247
|
+
"phase.verifyFailed",
|
|
11248
|
+
"phase.repairing",
|
|
11249
|
+
"phase.conflictResolving",
|
|
11250
|
+
"phase.conflictResolved",
|
|
11259
11251
|
"autonomous.tick",
|
|
11260
11252
|
"graph.completed",
|
|
11261
11253
|
"graph.failed",
|
|
@@ -11383,10 +11375,18 @@ async function execute(deps) {
|
|
|
11383
11375
|
return getActiveSDDContext2();
|
|
11384
11376
|
},
|
|
11385
11377
|
onSDDOutput: async (output) => {
|
|
11386
|
-
const {
|
|
11378
|
+
const {
|
|
11379
|
+
trySaveSpecFromAIOutput: trySaveSpecFromAIOutput2,
|
|
11380
|
+
trySaveImplementationPlan: trySaveImplementationPlan2,
|
|
11381
|
+
trySaveTasksFromAIOutput: trySaveTasksFromAIOutput2,
|
|
11382
|
+
autoDetectTaskCompletion: autoDetectTaskCompletion2,
|
|
11383
|
+
getTaskProgress: getTaskProgress2,
|
|
11384
|
+
getActiveSDDPhase: getActiveSDDPhase2
|
|
11385
|
+
} = (init_sdd(), __toCommonJS(sdd_exports));
|
|
11387
11386
|
const messages = [];
|
|
11388
11387
|
const specSaved = await trySaveSpecFromAIOutput2(output);
|
|
11389
|
-
if (specSaved)
|
|
11388
|
+
if (specSaved)
|
|
11389
|
+
messages.push("\u2713 Spec detected and saved! Use /sdd approve to continue.");
|
|
11390
11390
|
const planSaved = trySaveImplementationPlan2(output);
|
|
11391
11391
|
if (planSaved) messages.push("\u2713 Implementation plan saved!");
|
|
11392
11392
|
const tasksSaved = await trySaveTasksFromAIOutput2(output);
|
|
@@ -11401,7 +11401,9 @@ async function execute(deps) {
|
|
|
11401
11401
|
if (autoCompleted > 0) {
|
|
11402
11402
|
const progress = getTaskProgress2();
|
|
11403
11403
|
if (progress) {
|
|
11404
|
-
messages.push(
|
|
11404
|
+
messages.push(
|
|
11405
|
+
`\u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`
|
|
11406
|
+
);
|
|
11405
11407
|
}
|
|
11406
11408
|
}
|
|
11407
11409
|
}
|
|
@@ -11433,7 +11435,7 @@ async function execute(deps) {
|
|
|
11433
11435
|
supportsVision,
|
|
11434
11436
|
attachments,
|
|
11435
11437
|
effectiveMaxContext,
|
|
11436
|
-
projectName:
|
|
11438
|
+
projectName: path8.basename(projectRoot) || void 0,
|
|
11437
11439
|
projectRoot,
|
|
11438
11440
|
getAutonomy,
|
|
11439
11441
|
onAutonomy,
|
|
@@ -11461,7 +11463,7 @@ async function execute(deps) {
|
|
|
11461
11463
|
supportsVision,
|
|
11462
11464
|
attachments,
|
|
11463
11465
|
effectiveMaxContext,
|
|
11464
|
-
projectName:
|
|
11466
|
+
projectName: path8.basename(projectRoot) || void 0,
|
|
11465
11467
|
getAutonomy,
|
|
11466
11468
|
onAutonomy,
|
|
11467
11469
|
getNextPredict,
|
|
@@ -11562,7 +11564,8 @@ var MultiAgentHost = class {
|
|
|
11562
11564
|
directorBudget: this.opts.directorBudget,
|
|
11563
11565
|
manifestDebounceMs: 2e3,
|
|
11564
11566
|
checkpointDebounceMs: this.opts.checkpointDebounceMs ?? 250,
|
|
11565
|
-
maxSpawnDepth: 5
|
|
11567
|
+
maxSpawnDepth: 5,
|
|
11568
|
+
maxContext: this.opts.getLeaderMaxContext
|
|
11566
11569
|
});
|
|
11567
11570
|
this.fleetManager = fleetManager;
|
|
11568
11571
|
if (this.opts.sessionsRoot && !this.sessionFactory) {
|
|
@@ -11576,7 +11579,7 @@ var MultiAgentHost = class {
|
|
|
11576
11579
|
doneCondition: { type: "all_tasks_done" },
|
|
11577
11580
|
maxConcurrent: this.opts.maxConcurrent ?? 4
|
|
11578
11581
|
};
|
|
11579
|
-
const defaultScratchpad = this.opts.sharedScratchpadPath || (this.opts.sessionsRoot && this.opts.directorRunId ?
|
|
11582
|
+
const defaultScratchpad = this.opts.sharedScratchpadPath || (this.opts.sessionsRoot && this.opts.directorRunId ? path8.join(this.opts.sessionsRoot, this.opts.directorRunId, "shared") : void 0);
|
|
11580
11583
|
this.director = new Director({
|
|
11581
11584
|
config: coordinatorConfig,
|
|
11582
11585
|
manifestPath: this.opts.manifestPath,
|
|
@@ -11589,11 +11592,13 @@ var MultiAgentHost = class {
|
|
|
11589
11592
|
sessionsRoot: this.opts.sessionsRoot,
|
|
11590
11593
|
directorRunId: this.opts.directorRunId,
|
|
11591
11594
|
maxSpawnDepth: 5,
|
|
11595
|
+
maxContext: this.opts.getLeaderMaxContext,
|
|
11592
11596
|
// Live getter (not a snapshot) so a mid-session `/setmodel` takes
|
|
11593
11597
|
// effect on the next spawn — the director is built lazily + once.
|
|
11594
11598
|
modelMatrix: () => this.deps.configStore.get().modelMatrix,
|
|
11595
|
-
fleetManager
|
|
11599
|
+
fleetManager,
|
|
11596
11600
|
// pass so director.fleetManager is never undefined
|
|
11601
|
+
brain: this.opts.brain
|
|
11597
11602
|
});
|
|
11598
11603
|
this.director.on("task.completed", ({ task, result }) => {
|
|
11599
11604
|
this.fleetManager?.removePendingTask(task.id);
|
|
@@ -11779,9 +11784,18 @@ var MultiAgentHost = class {
|
|
|
11779
11784
|
subagentId: subCfg.id ?? subCfg.name ?? "subagent"
|
|
11780
11785
|
});
|
|
11781
11786
|
});
|
|
11787
|
+
const offCtxBridge = events.on("ctx.pct", (e) => {
|
|
11788
|
+
hostEvents.emit("subagent.ctx_pct", {
|
|
11789
|
+
subagentId: subCfg.id ?? subCfg.name ?? "subagent",
|
|
11790
|
+
load: e.load,
|
|
11791
|
+
tokens: e.tokens,
|
|
11792
|
+
maxContext: e.maxContext
|
|
11793
|
+
});
|
|
11794
|
+
});
|
|
11782
11795
|
const dispose = async () => {
|
|
11783
11796
|
offToolBridge();
|
|
11784
11797
|
offSummaryBridge();
|
|
11798
|
+
offCtxBridge();
|
|
11785
11799
|
try {
|
|
11786
11800
|
await subSession.close?.();
|
|
11787
11801
|
} catch {
|
|
@@ -11815,22 +11829,28 @@ var MultiAgentHost = class {
|
|
|
11815
11829
|
* use the leader and the calling code can decide to error later).
|
|
11816
11830
|
*/
|
|
11817
11831
|
async buildSubagentProvider(config, overrideId, model) {
|
|
11818
|
-
const
|
|
11832
|
+
const requestedProviderId = overrideId ?? config.provider;
|
|
11833
|
+
const providerId = requestedProviderId === config.provider || config.providers?.[requestedProviderId] !== void 0 || this.deps.providerRegistry.has(requestedProviderId) ? requestedProviderId : config.provider;
|
|
11819
11834
|
const newCfg = config.providers?.[providerId] ?? {
|
|
11820
11835
|
type: providerId,
|
|
11821
11836
|
apiKey: config.apiKey,
|
|
11822
11837
|
baseUrl: config.baseUrl
|
|
11823
11838
|
};
|
|
11824
|
-
const
|
|
11839
|
+
const cfgWithType = {
|
|
11825
11840
|
...newCfg,
|
|
11826
11841
|
type: providerId
|
|
11827
|
-
}
|
|
11842
|
+
};
|
|
11843
|
+
const provider = this.deps.providerRegistry.has(providerId) ? this.deps.providerRegistry.create(cfgWithType) : makeProviderFromConfig(providerId, cfgWithType);
|
|
11828
11844
|
if (this.deps.modelsRegistry) {
|
|
11829
11845
|
const resolvedModel = model ?? config.model;
|
|
11830
|
-
const
|
|
11831
|
-
|
|
11832
|
-
|
|
11833
|
-
|
|
11846
|
+
const mc = await resolveRuntimeMaxContext({
|
|
11847
|
+
modelsRegistry: this.deps.modelsRegistry,
|
|
11848
|
+
config,
|
|
11849
|
+
provider,
|
|
11850
|
+
runtimeProviderConfig: cfgWithType,
|
|
11851
|
+
providerId,
|
|
11852
|
+
modelId: resolvedModel
|
|
11853
|
+
});
|
|
11834
11854
|
if (mc && mc > 0) provider.capabilities.maxContext = mc;
|
|
11835
11855
|
}
|
|
11836
11856
|
return provider;
|
|
@@ -12025,16 +12045,16 @@ var MultiAgentHost = class {
|
|
|
12025
12045
|
if (this.director) return this.director;
|
|
12026
12046
|
this.opts.directorMode = true;
|
|
12027
12047
|
if (this.opts.fleetRoot && !this.opts.manifestPath) {
|
|
12028
|
-
this.opts.manifestPath =
|
|
12048
|
+
this.opts.manifestPath = path8.join(this.opts.fleetRoot, "fleet.json");
|
|
12029
12049
|
}
|
|
12030
12050
|
if (this.opts.fleetRoot && !this.opts.sharedScratchpadPath) {
|
|
12031
|
-
this.opts.sharedScratchpadPath =
|
|
12051
|
+
this.opts.sharedScratchpadPath = path8.join(this.opts.fleetRoot, "shared");
|
|
12032
12052
|
}
|
|
12033
12053
|
if (this.opts.fleetRoot && !this.opts.sessionsRoot) {
|
|
12034
|
-
this.opts.sessionsRoot =
|
|
12054
|
+
this.opts.sessionsRoot = path8.join(this.opts.fleetRoot, "subagents");
|
|
12035
12055
|
}
|
|
12036
12056
|
if (this.opts.fleetRoot && !this.opts.stateCheckpointPath) {
|
|
12037
|
-
this.opts.stateCheckpointPath =
|
|
12057
|
+
this.opts.stateCheckpointPath = path8.join(this.opts.fleetRoot, "director-state.json");
|
|
12038
12058
|
}
|
|
12039
12059
|
await this.ensureDirector();
|
|
12040
12060
|
return this.director ?? null;
|
|
@@ -12220,11 +12240,11 @@ var SessionStats = class {
|
|
|
12220
12240
|
if (e.name === "bash") this.bashCommands++;
|
|
12221
12241
|
else if (e.name === "fetch") this.fetches++;
|
|
12222
12242
|
if (!e.ok) return;
|
|
12223
|
-
const
|
|
12224
|
-
if (e.name === "read" &&
|
|
12225
|
-
else if (e.name === "edit" &&
|
|
12226
|
-
else if (e.name === "write" &&
|
|
12227
|
-
this.writtenPaths.add(
|
|
12243
|
+
const path25 = typeof input?.path === "string" ? input.path : void 0;
|
|
12244
|
+
if (e.name === "read" && path25) this.readPaths.add(path25);
|
|
12245
|
+
else if (e.name === "edit" && path25) this.editedPaths.add(path25);
|
|
12246
|
+
else if (e.name === "write" && path25) {
|
|
12247
|
+
this.writtenPaths.add(path25);
|
|
12228
12248
|
const content = typeof input?.content === "string" ? input.content : "";
|
|
12229
12249
|
this.bytesWritten += Buffer.byteLength(content, "utf8");
|
|
12230
12250
|
}
|
|
@@ -12330,7 +12350,7 @@ function samplePaths(set) {
|
|
|
12330
12350
|
}
|
|
12331
12351
|
var WORKTREE_PHASE_CONCURRENCY = 4;
|
|
12332
12352
|
function gitText(args, cwd) {
|
|
12333
|
-
return new Promise((
|
|
12353
|
+
return new Promise((resolve3) => {
|
|
12334
12354
|
let out = "";
|
|
12335
12355
|
const child = spawn("git", args, {
|
|
12336
12356
|
cwd,
|
|
@@ -12343,8 +12363,8 @@ function gitText(args, cwd) {
|
|
|
12343
12363
|
child.stderr?.on("data", (c) => {
|
|
12344
12364
|
out += c.toString();
|
|
12345
12365
|
});
|
|
12346
|
-
child.on("error", () =>
|
|
12347
|
-
child.on("close", (code) =>
|
|
12366
|
+
child.on("error", () => resolve3({ code: 1, out }));
|
|
12367
|
+
child.on("close", (code) => resolve3({ code: code ?? 1, out: out.trim() }));
|
|
12348
12368
|
});
|
|
12349
12369
|
}
|
|
12350
12370
|
async function isGitRepo(cwd) {
|
|
@@ -12352,7 +12372,7 @@ async function isGitRepo(cwd) {
|
|
|
12352
12372
|
return code === 0 && out.trim() === "true";
|
|
12353
12373
|
}
|
|
12354
12374
|
function runCmd(cmd, args, cwd, shell = false) {
|
|
12355
|
-
return new Promise((
|
|
12375
|
+
return new Promise((resolve3) => {
|
|
12356
12376
|
let out = "";
|
|
12357
12377
|
const child = spawn(cmd, args, {
|
|
12358
12378
|
cwd,
|
|
@@ -12366,8 +12386,8 @@ function runCmd(cmd, args, cwd, shell = false) {
|
|
|
12366
12386
|
child.stderr?.on("data", (c) => {
|
|
12367
12387
|
out += c.toString();
|
|
12368
12388
|
});
|
|
12369
|
-
child.on("error", (e) =>
|
|
12370
|
-
child.on("close", (code) =>
|
|
12389
|
+
child.on("error", (e) => resolve3({ code: 1, out: `${out}${String(e)}` }));
|
|
12390
|
+
child.on("close", (code) => resolve3({ code: code ?? 1, out: out.trim() }));
|
|
12371
12391
|
});
|
|
12372
12392
|
}
|
|
12373
12393
|
function detectPackageManager2(root) {
|
|
@@ -12572,6 +12592,7 @@ ${res.out}` };
|
|
|
12572
12592
|
return false;
|
|
12573
12593
|
}
|
|
12574
12594
|
} : void 0,
|
|
12595
|
+
brain: deps.brain,
|
|
12575
12596
|
onPhaseComplete: (phase) => {
|
|
12576
12597
|
log(`\u2705 Phase completed: ${phase.name}`);
|
|
12577
12598
|
void persist(graph);
|
|
@@ -12593,11 +12614,20 @@ ${res.out}` };
|
|
|
12593
12614
|
});
|
|
12594
12615
|
const onUntyped = deps.events.on;
|
|
12595
12616
|
const offUntyped = deps.events.off;
|
|
12617
|
+
const finalizeActiveRun = () => {
|
|
12618
|
+
if (active?.graph.id !== graph.id) return;
|
|
12619
|
+
active.unsubscribe();
|
|
12620
|
+
active = null;
|
|
12621
|
+
};
|
|
12596
12622
|
const onDone = () => {
|
|
12597
12623
|
log(`\u{1F389} AutoPhase complete: ${graph.title}`);
|
|
12598
12624
|
void persist(graph);
|
|
12625
|
+
finalizeActiveRun();
|
|
12626
|
+
};
|
|
12627
|
+
const onFailed = () => {
|
|
12628
|
+
void persist(graph);
|
|
12629
|
+
finalizeActiveRun();
|
|
12599
12630
|
};
|
|
12600
|
-
const onFailed = () => void persist(graph);
|
|
12601
12631
|
onUntyped("graph.completed", onDone);
|
|
12602
12632
|
onUntyped("graph.failed", onFailed);
|
|
12603
12633
|
const unsubscribe = () => {
|
|
@@ -12607,6 +12637,8 @@ ${res.out}` };
|
|
|
12607
12637
|
active = { graph, orchestrator, abort, unsubscribe };
|
|
12608
12638
|
void orchestrator.start().catch((err) => {
|
|
12609
12639
|
log(`\u{1F4A5} AutoPhase aborted: ${err instanceof Error ? err.message : String(err)}`);
|
|
12640
|
+
void persist(graph);
|
|
12641
|
+
finalizeActiveRun();
|
|
12610
12642
|
});
|
|
12611
12643
|
return { ok: true, graph };
|
|
12612
12644
|
},
|
|
@@ -12781,9 +12813,25 @@ function setupPipelines(params) {
|
|
|
12781
12813
|
return pipelines;
|
|
12782
12814
|
}
|
|
12783
12815
|
async function setupCompaction(params) {
|
|
12784
|
-
const {
|
|
12785
|
-
|
|
12786
|
-
|
|
12816
|
+
const {
|
|
12817
|
+
compactor,
|
|
12818
|
+
events,
|
|
12819
|
+
modelsRegistry,
|
|
12820
|
+
context,
|
|
12821
|
+
config,
|
|
12822
|
+
provider,
|
|
12823
|
+
pipelines,
|
|
12824
|
+
fullConfig,
|
|
12825
|
+
sessionWriter,
|
|
12826
|
+
sessionBridge: providedBridge
|
|
12827
|
+
} = params;
|
|
12828
|
+
const effectiveMaxContext = await resolveRuntimeMaxContext({
|
|
12829
|
+
modelsRegistry,
|
|
12830
|
+
config,
|
|
12831
|
+
provider,
|
|
12832
|
+
providerId: config.provider ?? provider.id,
|
|
12833
|
+
modelId: config.model ?? context.model
|
|
12834
|
+
});
|
|
12787
12835
|
let autoCompactor;
|
|
12788
12836
|
if (config.context.autoCompact !== false) {
|
|
12789
12837
|
const auditLevel = resolveAuditLevel(fullConfig ?? config);
|
|
@@ -12872,7 +12920,7 @@ function setupMetrics(params) {
|
|
|
12872
12920
|
const dumpMetrics = () => {
|
|
12873
12921
|
if (!metricsSink) return;
|
|
12874
12922
|
try {
|
|
12875
|
-
const out =
|
|
12923
|
+
const out = path8.join(wpaths.projectSessions, "metrics.json");
|
|
12876
12924
|
const snap = metricsSink.snapshot();
|
|
12877
12925
|
writeFileSync(out, JSON.stringify(snap, null, 2));
|
|
12878
12926
|
} catch {
|
|
@@ -13131,12 +13179,12 @@ async function setupSession(params) {
|
|
|
13131
13179
|
}
|
|
13132
13180
|
const sessionRef = { current: session };
|
|
13133
13181
|
await recoveryLock.write(session.id).catch(() => void 0);
|
|
13134
|
-
const attachments = new DefaultAttachmentStore({ spoolDir:
|
|
13135
|
-
const queueStore = new QueueStore({ dir:
|
|
13182
|
+
const attachments = new DefaultAttachmentStore({ spoolDir: path8.join(wpaths.projectSessions, session.id, "attachments") });
|
|
13183
|
+
const queueStore = new QueueStore({ dir: path8.join(wpaths.projectSessions, session.id) });
|
|
13136
13184
|
const ctxSignal = new AbortController().signal;
|
|
13137
13185
|
const context = new Context({ systemPrompt, provider, session, signal: ctxSignal, tokenCounter, cwd, projectRoot, model: config.model });
|
|
13138
13186
|
if (restoredMessages.length > 0) context.state.replaceMessages(restoredMessages);
|
|
13139
|
-
const todosCheckpointPath =
|
|
13187
|
+
const todosCheckpointPath = path8.join(wpaths.projectSessions, `${session.id}.todos.json`);
|
|
13140
13188
|
if (resumeId) {
|
|
13141
13189
|
try {
|
|
13142
13190
|
const restoredTodos = await loadTodosCheckpoint(todosCheckpointPath);
|
|
@@ -13148,13 +13196,13 @@ async function setupSession(params) {
|
|
|
13148
13196
|
}
|
|
13149
13197
|
}
|
|
13150
13198
|
const detachTodosCheckpoint = attachTodosCheckpoint(context.state, todosCheckpointPath, session.id);
|
|
13151
|
-
const planPath =
|
|
13199
|
+
const planPath = path8.join(wpaths.projectSessions, `${session.id}.plan.json`);
|
|
13152
13200
|
context.state.setMeta("plan.path", planPath);
|
|
13153
13201
|
let dirState;
|
|
13154
13202
|
if (resumeId) {
|
|
13155
13203
|
try {
|
|
13156
|
-
const fleetRoot =
|
|
13157
|
-
dirState = await loadDirectorState(
|
|
13204
|
+
const fleetRoot = path8.join(wpaths.projectSessions, session.id);
|
|
13205
|
+
dirState = await loadDirectorState(path8.join(fleetRoot, "director-state.json"));
|
|
13158
13206
|
if (dirState) {
|
|
13159
13207
|
const tCounts = {};
|
|
13160
13208
|
for (const t of dirState.tasks) tCounts[t.status] = (tCounts[t.status] ?? 0) + 1;
|
|
@@ -13179,7 +13227,7 @@ function resolveBundledSkillsDir2() {
|
|
|
13179
13227
|
try {
|
|
13180
13228
|
const req2 = createRequire(import.meta.url);
|
|
13181
13229
|
const corePkg = req2.resolve("@wrongstack/core/package.json");
|
|
13182
|
-
return
|
|
13230
|
+
return path8.join(path8.dirname(corePkg), "skills");
|
|
13183
13231
|
} catch {
|
|
13184
13232
|
return void 0;
|
|
13185
13233
|
}
|
|
@@ -13304,7 +13352,6 @@ var resolveSessionLoggingConfig = (cfg) => ({
|
|
|
13304
13352
|
}
|
|
13305
13353
|
}
|
|
13306
13354
|
});
|
|
13307
|
-
var stageListeners = /* @__PURE__ */ new Set();
|
|
13308
13355
|
async function main(argv) {
|
|
13309
13356
|
const ctx = await boot(argv);
|
|
13310
13357
|
if (typeof ctx === "number") return ctx;
|
|
@@ -13334,7 +13381,10 @@ async function main(argv) {
|
|
|
13334
13381
|
forceAllYolo: flags["force-all-yolo"] === true,
|
|
13335
13382
|
promptDelegate: makePromptDelegate(reader)
|
|
13336
13383
|
},
|
|
13337
|
-
compactor: {
|
|
13384
|
+
compactor: {
|
|
13385
|
+
preserveK: config.context.preserveK,
|
|
13386
|
+
eliseThreshold: config.context.eliseThreshold
|
|
13387
|
+
},
|
|
13338
13388
|
bundledSkillsDir: config.features.skills ? resolveBundledSkillsDir2() : void 0
|
|
13339
13389
|
});
|
|
13340
13390
|
const replayFlag = flags["replay"];
|
|
@@ -13349,9 +13399,7 @@ async function main(argv) {
|
|
|
13349
13399
|
mode,
|
|
13350
13400
|
logger
|
|
13351
13401
|
});
|
|
13352
|
-
logger.info(
|
|
13353
|
-
`replay: ProviderRunner bound in '${mode}' mode for session ${sessionId}`
|
|
13354
|
-
);
|
|
13402
|
+
logger.info(`replay: ProviderRunner bound in '${mode}' mode for session ${sessionId}`);
|
|
13355
13403
|
}
|
|
13356
13404
|
const configStore = container.resolve(TOKENS.ConfigStore);
|
|
13357
13405
|
container.bind(TOKENS.PathResolver, () => pathResolver);
|
|
@@ -13375,12 +13423,15 @@ async function main(argv) {
|
|
|
13375
13423
|
}
|
|
13376
13424
|
const modeId = activeMode?.id ?? "default";
|
|
13377
13425
|
const modePrompt = activeMode?.prompt ?? "";
|
|
13378
|
-
const resolvedModel = await
|
|
13379
|
-
|
|
13380
|
-
|
|
13381
|
-
|
|
13382
|
-
|
|
13383
|
-
|
|
13426
|
+
const [resolvedCaps, resolvedModel] = await Promise.all([
|
|
13427
|
+
capabilitiesFor(modelsRegistry, provider.id, config.model).catch(() => void 0),
|
|
13428
|
+
modelsRegistry.getModel(config.provider, config.model).catch(() => void 0)
|
|
13429
|
+
]);
|
|
13430
|
+
const modelCapabilities = resolvedCaps ? {
|
|
13431
|
+
maxContextTokens: resolvedCaps.maxContext,
|
|
13432
|
+
supportsTools: resolvedCaps.tools,
|
|
13433
|
+
supportsVision: resolvedCaps.vision,
|
|
13434
|
+
supportsReasoning: resolvedModel?.capabilities.reasoning ?? false
|
|
13384
13435
|
} : void 0;
|
|
13385
13436
|
const memoryStore = container.resolve(TOKENS.MemoryStore);
|
|
13386
13437
|
const skillLoader = container.resolve(TOKENS.SkillLoader);
|
|
@@ -13396,15 +13447,15 @@ async function main(argv) {
|
|
|
13396
13447
|
modeId,
|
|
13397
13448
|
modePrompt,
|
|
13398
13449
|
modelCapabilities,
|
|
13399
|
-
planPath: () => sessionRef.current ?
|
|
13450
|
+
planPath: () => sessionRef.current ? path8.join(wpaths.projectSessions, `${sessionRef.current.id}.plan.json`) : void 0,
|
|
13400
13451
|
contributors: [
|
|
13401
13452
|
// Injects the ETERNAL AUTONOMY block when the user has activated
|
|
13402
|
-
//
|
|
13403
|
-
// is the only place the model sees the rules — compaction
|
|
13404
|
-
// drop it and the model forgets it's in autonomy mode.
|
|
13453
|
+
// a long-running autonomy engine. Without this, the per-iteration
|
|
13454
|
+
// directive is the only place the model sees the rules — compaction
|
|
13455
|
+
// can drop it and the model forgets it's in autonomy mode.
|
|
13405
13456
|
makeAutonomyPromptContributor({
|
|
13406
13457
|
goalPath: goalPathForPrompt,
|
|
13407
|
-
enabled: () => autonomyModeRef.current === "eternal"
|
|
13458
|
+
enabled: () => autonomyModeRef.current === "eternal" || autonomyModeRef.current === "eternal-parallel"
|
|
13408
13459
|
})
|
|
13409
13460
|
]
|
|
13410
13461
|
})
|
|
@@ -13421,7 +13472,13 @@ async function main(argv) {
|
|
|
13421
13472
|
const events = new EventBus();
|
|
13422
13473
|
events.setLogger(logger);
|
|
13423
13474
|
const { metricsSink, healthRegistry } = (() => {
|
|
13424
|
-
const ms = setupMetrics({
|
|
13475
|
+
const ms = setupMetrics({
|
|
13476
|
+
flags,
|
|
13477
|
+
wpaths,
|
|
13478
|
+
events,
|
|
13479
|
+
logger,
|
|
13480
|
+
config: { provider: config.provider, model: config.model }
|
|
13481
|
+
});
|
|
13425
13482
|
return ms;
|
|
13426
13483
|
})();
|
|
13427
13484
|
const spinner = new Spinner();
|
|
@@ -13587,7 +13644,7 @@ async function main(argv) {
|
|
|
13587
13644
|
});
|
|
13588
13645
|
const pipelines = setupPipelines({ events, logger });
|
|
13589
13646
|
const compactor = container.resolve(TOKENS.Compactor);
|
|
13590
|
-
const
|
|
13647
|
+
const compactionSetup = await setupCompaction({
|
|
13591
13648
|
compactor,
|
|
13592
13649
|
events,
|
|
13593
13650
|
modelsRegistry,
|
|
@@ -13599,18 +13656,39 @@ async function main(argv) {
|
|
|
13599
13656
|
sessionBridge
|
|
13600
13657
|
// share the same bridge for consistent audit logging (compaction + errors + future)
|
|
13601
13658
|
});
|
|
13602
|
-
|
|
13603
|
-
|
|
13604
|
-
|
|
13605
|
-
|
|
13606
|
-
|
|
13659
|
+
let effectiveMaxContext = compactionSetup.effectiveMaxContext;
|
|
13660
|
+
context.provider.capabilities.maxContext = effectiveMaxContext;
|
|
13661
|
+
const { autoCompactor } = compactionSetup;
|
|
13662
|
+
const refreshMaxContext = async (providerId, modelId, runtimeProviderConfig) => {
|
|
13663
|
+
const mc = await resolveRuntimeMaxContext({
|
|
13664
|
+
modelsRegistry,
|
|
13665
|
+
config,
|
|
13666
|
+
provider: context.provider,
|
|
13667
|
+
runtimeProviderConfig,
|
|
13668
|
+
providerId,
|
|
13669
|
+
modelId
|
|
13670
|
+
});
|
|
13671
|
+
effectiveMaxContext = mc > 0 ? mc : 2e5;
|
|
13672
|
+
context.provider.capabilities.maxContext = effectiveMaxContext;
|
|
13673
|
+
autoCompactor?.setMaxContext(effectiveMaxContext);
|
|
13674
|
+
events.emit("ctx.max_context", { providerId, modelId, maxContext: effectiveMaxContext });
|
|
13675
|
+
updateSpinnerContext();
|
|
13607
13676
|
};
|
|
13608
13677
|
const updateSpinnerContext = () => {
|
|
13609
13678
|
if (effectiveMaxContext > 0 && lastInputTokens > 0) {
|
|
13610
13679
|
spinner.setContext({ used: lastInputTokens, max: effectiveMaxContext });
|
|
13611
13680
|
} else spinner.setContext(void 0);
|
|
13612
13681
|
};
|
|
13613
|
-
const agent = createAgent({
|
|
13682
|
+
const agent = createAgent({
|
|
13683
|
+
container,
|
|
13684
|
+
tools: toolRegistry,
|
|
13685
|
+
providers: providerRegistry,
|
|
13686
|
+
events,
|
|
13687
|
+
pipelines,
|
|
13688
|
+
context,
|
|
13689
|
+
config,
|
|
13690
|
+
confirmAwaiter: makeConfirmAwaiter(reader)
|
|
13691
|
+
});
|
|
13614
13692
|
const mcpRegistry = new MCPRegistry({ toolRegistry, events, log: logger });
|
|
13615
13693
|
if (config.features.mcp) {
|
|
13616
13694
|
for (const cfg of Object.values(config.mcpServers ?? {})) {
|
|
@@ -13655,7 +13733,7 @@ async function main(argv) {
|
|
|
13655
13733
|
context.model = modelId;
|
|
13656
13734
|
config = patchConfig(config, { provider: providerId, model: modelId });
|
|
13657
13735
|
configStore.update({ provider: providerId, model: modelId });
|
|
13658
|
-
void refreshMaxContext(resolvedProviderId, modelId);
|
|
13736
|
+
void refreshMaxContext(resolvedProviderId, modelId, cfgWithType);
|
|
13659
13737
|
return null;
|
|
13660
13738
|
} catch (err) {
|
|
13661
13739
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -13684,12 +13762,26 @@ async function main(argv) {
|
|
|
13684
13762
|
}
|
|
13685
13763
|
}
|
|
13686
13764
|
};
|
|
13687
|
-
const
|
|
13688
|
-
const
|
|
13689
|
-
|
|
13690
|
-
|
|
13691
|
-
|
|
13692
|
-
|
|
13765
|
+
const stageListeners = /* @__PURE__ */ new Set();
|
|
13766
|
+
const broadcastAutonomyStage = (stage) => {
|
|
13767
|
+
for (const fn of stageListeners) {
|
|
13768
|
+
try {
|
|
13769
|
+
fn(stage);
|
|
13770
|
+
} catch {
|
|
13771
|
+
}
|
|
13772
|
+
}
|
|
13773
|
+
};
|
|
13774
|
+
const fleetRoot = directorMode ? path8.join(wpaths.projectSessions, session.id) : void 0;
|
|
13775
|
+
const manifestPath = directorMode ? typeof process.env["WRONGSTACK_FLEET_MANIFEST"] === "string" ? process.env["WRONGSTACK_FLEET_MANIFEST"] : path8.join(fleetRoot, "fleet.json") : void 0;
|
|
13776
|
+
const sharedScratchpadPath = directorMode ? path8.join(fleetRoot, "shared") : void 0;
|
|
13777
|
+
const subagentSessionsRoot = directorMode ? path8.join(fleetRoot, "subagents") : void 0;
|
|
13778
|
+
const stateCheckpointPath = directorMode ? path8.join(fleetRoot, "director-state.json") : void 0;
|
|
13779
|
+
const fleetRootForPromotion = path8.join(wpaths.projectSessions, session.id);
|
|
13780
|
+
const brainQueue = new BrainDecisionQueue(events);
|
|
13781
|
+
const brain = new ObservableBrainArbiter(
|
|
13782
|
+
new HumanEscalatingBrainArbiter(new DefaultBrainArbiter(), brainQueue),
|
|
13783
|
+
events
|
|
13784
|
+
);
|
|
13693
13785
|
const multiAgentHost = new MultiAgentHost(
|
|
13694
13786
|
{
|
|
13695
13787
|
container,
|
|
@@ -13714,7 +13806,9 @@ async function main(argv) {
|
|
|
13714
13806
|
fleetRoot: fleetRootForPromotion,
|
|
13715
13807
|
stateCheckpointPath,
|
|
13716
13808
|
sessionWriter: session,
|
|
13717
|
-
maxConcurrent
|
|
13809
|
+
maxConcurrent,
|
|
13810
|
+
getLeaderMaxContext: () => effectiveMaxContext,
|
|
13811
|
+
brain
|
|
13718
13812
|
}
|
|
13719
13813
|
);
|
|
13720
13814
|
toolRegistry.register(
|
|
@@ -13785,6 +13879,7 @@ async function main(argv) {
|
|
|
13785
13879
|
events,
|
|
13786
13880
|
storeDir: wpaths.projectAutophase,
|
|
13787
13881
|
projectRoot,
|
|
13882
|
+
brain,
|
|
13788
13883
|
log: (line) => renderer.write(`${line}
|
|
13789
13884
|
`)
|
|
13790
13885
|
});
|
|
@@ -13881,7 +13976,9 @@ async function main(argv) {
|
|
|
13881
13976
|
for (const a of s.live) {
|
|
13882
13977
|
if (a.status === "running" || a.status === "idle") {
|
|
13883
13978
|
const task = a.task ? ` \u2014 ${a.task.slice(0, 60)}` : "";
|
|
13884
|
-
lines.push(
|
|
13979
|
+
lines.push(
|
|
13980
|
+
` ${STATUS_ICON[a.status] ?? "?"} ${a.subagentId.slice(0, 8)} ${a.status}${task}`
|
|
13981
|
+
);
|
|
13885
13982
|
}
|
|
13886
13983
|
}
|
|
13887
13984
|
for (const p of s.pending) {
|
|
@@ -14015,7 +14112,8 @@ async function main(argv) {
|
|
|
14015
14112
|
}
|
|
14016
14113
|
},
|
|
14017
14114
|
onFleetSpawn: async (role) => {
|
|
14018
|
-
if (!director)
|
|
14115
|
+
if (!director)
|
|
14116
|
+
throw new Error("No director active \u2014 start with --director or use /autonomy parallel.");
|
|
14019
14117
|
const cfg = FLEET_ROSTER[role] ?? {
|
|
14020
14118
|
id: `manual-${Date.now()}`,
|
|
14021
14119
|
name: role,
|
|
@@ -14025,7 +14123,7 @@ async function main(argv) {
|
|
|
14025
14123
|
return director.spawn(cfg);
|
|
14026
14124
|
},
|
|
14027
14125
|
onFleetLog: async (subagentId, mode) => {
|
|
14028
|
-
const subagentsRoot =
|
|
14126
|
+
const subagentsRoot = path8.join(fleetRootForPromotion, "subagents");
|
|
14029
14127
|
let runDirs;
|
|
14030
14128
|
try {
|
|
14031
14129
|
runDirs = await fsp3.readdir(subagentsRoot);
|
|
@@ -14034,7 +14132,7 @@ async function main(argv) {
|
|
|
14034
14132
|
}
|
|
14035
14133
|
const found = [];
|
|
14036
14134
|
for (const runId of runDirs) {
|
|
14037
|
-
const runDir =
|
|
14135
|
+
const runDir = path8.join(subagentsRoot, runId);
|
|
14038
14136
|
let files;
|
|
14039
14137
|
try {
|
|
14040
14138
|
files = await fsp3.readdir(runDir);
|
|
@@ -14043,7 +14141,7 @@ async function main(argv) {
|
|
|
14043
14141
|
}
|
|
14044
14142
|
for (const f of files) {
|
|
14045
14143
|
if (!f.endsWith(".jsonl")) continue;
|
|
14046
|
-
const full =
|
|
14144
|
+
const full = path8.join(runDir, f);
|
|
14047
14145
|
try {
|
|
14048
14146
|
const stat4 = await fsp3.stat(full);
|
|
14049
14147
|
found.push({
|
|
@@ -14068,7 +14166,9 @@ async function main(argv) {
|
|
|
14068
14166
|
` ${color.cyan(t2.subagentId.padEnd(18))} ${color.dim(t2.runId.slice(0, 18))} ${color.dim(`${(t2.size / 1024).toFixed(1)} KB`)}`
|
|
14069
14167
|
);
|
|
14070
14168
|
}
|
|
14071
|
-
lines2.push(
|
|
14169
|
+
lines2.push(
|
|
14170
|
+
"Use `/fleet log <subagentId>` for a summary, or append `raw` for the full JSONL."
|
|
14171
|
+
);
|
|
14072
14172
|
return lines2.join("\n");
|
|
14073
14173
|
}
|
|
14074
14174
|
const matches = found.filter(
|
|
@@ -14097,7 +14197,9 @@ async function main(argv) {
|
|
|
14097
14197
|
const ev = JSON.parse(line);
|
|
14098
14198
|
counts[ev.type] = (counts[ev.type] ?? 0) + 1;
|
|
14099
14199
|
if (ev.type === "user_input" && !firstUser) {
|
|
14100
|
-
const txt = typeof ev.content === "string" ? ev.content : Array.isArray(ev.content) ? ev.content.filter(
|
|
14200
|
+
const txt = typeof ev.content === "string" ? ev.content : Array.isArray(ev.content) ? ev.content.filter(
|
|
14201
|
+
(b) => b.type === "text"
|
|
14202
|
+
).map((b) => b.text).join(" ") : "";
|
|
14101
14203
|
firstUser = txt.slice(0, 120);
|
|
14102
14204
|
}
|
|
14103
14205
|
if (ev.type === "llm_response") {
|
|
@@ -14140,7 +14242,7 @@ async function main(argv) {
|
|
|
14140
14242
|
}
|
|
14141
14243
|
const dir = await multiAgentHost.ensureDirector();
|
|
14142
14244
|
if (!dir) return "Director is not available.";
|
|
14143
|
-
const dirStatePath =
|
|
14245
|
+
const dirStatePath = path8.join(fleetRootForPromotion, "director-state.json");
|
|
14144
14246
|
const prior = await loadDirectorState(dirStatePath);
|
|
14145
14247
|
if (!prior) {
|
|
14146
14248
|
return "No prior director-state.json found \u2014 nothing to retry.";
|
|
@@ -14165,9 +14267,7 @@ async function main(argv) {
|
|
|
14165
14267
|
lines.push("Run `/fleet retry <taskId>` or `/fleet retry all` to re-assign.");
|
|
14166
14268
|
return lines.join("\n");
|
|
14167
14269
|
}
|
|
14168
|
-
const targets = taskId === "all" ? interrupted : interrupted.filter(
|
|
14169
|
-
(t) => t.taskId === taskId || t.taskId.startsWith(taskId)
|
|
14170
|
-
);
|
|
14270
|
+
const targets = taskId === "all" ? interrupted : interrupted.filter((t) => t.taskId === taskId || t.taskId.startsWith(taskId));
|
|
14171
14271
|
if (targets.length === 0) {
|
|
14172
14272
|
return `No interrupted task matched "${taskId}".`;
|
|
14173
14273
|
}
|
|
@@ -14211,9 +14311,9 @@ async function main(argv) {
|
|
|
14211
14311
|
for (const tool of director2.tools(FLEET_ROSTER)) {
|
|
14212
14312
|
toolRegistry.register(tool);
|
|
14213
14313
|
}
|
|
14214
|
-
const mp =
|
|
14215
|
-
const sp =
|
|
14216
|
-
const ss =
|
|
14314
|
+
const mp = path8.join(fleetRootForPromotion, "fleet.json");
|
|
14315
|
+
const sp = path8.join(fleetRootForPromotion, "shared");
|
|
14316
|
+
const ss = path8.join(fleetRootForPromotion, "subagents");
|
|
14217
14317
|
const lines = [
|
|
14218
14318
|
`${color.green("\u2713")} Promoted to director mode.`,
|
|
14219
14319
|
` Roster: ${Object.keys(FLEET_ROSTER).join(", ")}`,
|
|
@@ -14284,17 +14384,19 @@ Restart WrongStack to load or unload plugin code in this session.`;
|
|
|
14284
14384
|
const effectiveMode = mode ?? "eternal";
|
|
14285
14385
|
if (effectiveMode === "eternal-parallel") {
|
|
14286
14386
|
if (!parallelEngine) {
|
|
14287
|
-
|
|
14387
|
+
const parallelOptions = {
|
|
14288
14388
|
agent,
|
|
14289
14389
|
projectRoot,
|
|
14290
14390
|
compactor: container.resolve(TOKENS.Compactor),
|
|
14291
14391
|
maxContextTokens: effectiveMaxContext > 0 ? effectiveMaxContext : void 0,
|
|
14292
14392
|
onIteration: broadcastEternalIteration,
|
|
14393
|
+
onStage: broadcastAutonomyStage,
|
|
14293
14394
|
// Real per-role factory: each dispatched slot runs as a fresh,
|
|
14294
14395
|
// isolated agent with the role's filtered tools + persona prompt
|
|
14295
14396
|
// (instead of sharing the leader agent's Context).
|
|
14296
14397
|
subagentFactory: multiAgentHost.makeSubagentFactory(config)
|
|
14297
|
-
}
|
|
14398
|
+
};
|
|
14399
|
+
parallelEngine = new ParallelEternalEngine(parallelOptions);
|
|
14298
14400
|
}
|
|
14299
14401
|
void parallelEngine.prime?.();
|
|
14300
14402
|
} else {
|
|
@@ -14304,7 +14406,8 @@ Restart WrongStack to load or unload plugin code in this session.`;
|
|
|
14304
14406
|
projectRoot,
|
|
14305
14407
|
compactor: container.resolve(TOKENS.Compactor),
|
|
14306
14408
|
maxContextTokens: effectiveMaxContext > 0 ? effectiveMaxContext : void 0,
|
|
14307
|
-
onIteration: broadcastEternalIteration
|
|
14409
|
+
onIteration: broadcastEternalIteration,
|
|
14410
|
+
onStage: broadcastAutonomyStage
|
|
14308
14411
|
});
|
|
14309
14412
|
}
|
|
14310
14413
|
void eternalEngine.prime();
|
|
@@ -14315,20 +14418,26 @@ Restart WrongStack to load or unload plugin code in this session.`;
|
|
|
14315
14418
|
parallelEngine?.stop();
|
|
14316
14419
|
},
|
|
14317
14420
|
onExit: () => {
|
|
14421
|
+
brainQueue.dispose();
|
|
14318
14422
|
void mcpRegistry.stopAll();
|
|
14319
14423
|
},
|
|
14320
14424
|
onBeforeExit: async () => {
|
|
14321
14425
|
const { spawn: spawn3 } = await import('child_process');
|
|
14322
14426
|
const cwd2 = projectRoot;
|
|
14323
|
-
const statusResult = await new Promise(
|
|
14324
|
-
|
|
14325
|
-
|
|
14326
|
-
|
|
14327
|
-
|
|
14328
|
-
|
|
14329
|
-
|
|
14330
|
-
|
|
14331
|
-
|
|
14427
|
+
const statusResult = await new Promise(
|
|
14428
|
+
(resolve3, reject) => {
|
|
14429
|
+
const child = spawn3("git", ["status", "--porcelain"], {
|
|
14430
|
+
cwd: cwd2,
|
|
14431
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
14432
|
+
});
|
|
14433
|
+
let stdout = "";
|
|
14434
|
+
child.stdout?.on("data", (d) => {
|
|
14435
|
+
stdout += d;
|
|
14436
|
+
});
|
|
14437
|
+
child.on("error", reject);
|
|
14438
|
+
child.on("close", (code) => resolve3({ stdout, code: code ?? 0 }));
|
|
14439
|
+
}
|
|
14440
|
+
);
|
|
14332
14441
|
if (statusResult.stdout.trim().length > 0) {
|
|
14333
14442
|
const lines = statusResult.stdout.split("\n").filter(Boolean);
|
|
14334
14443
|
return {
|
|
@@ -14405,8 +14514,10 @@ Restart WrongStack to load or unload plugin code in this session.`;
|
|
|
14405
14514
|
parallelSlots: opts?.parallelSlots,
|
|
14406
14515
|
subagentFactory,
|
|
14407
14516
|
onProgress: (p) => {
|
|
14408
|
-
renderer.write(
|
|
14409
|
-
`
|
|
14517
|
+
renderer.write(
|
|
14518
|
+
` \u2591 wave ${p.wave + 1} \xB7 ${p.completed}/${p.total} tasks \xB7 ${p.percent}% done
|
|
14519
|
+
`
|
|
14520
|
+
);
|
|
14410
14521
|
}
|
|
14411
14522
|
});
|
|
14412
14523
|
globalThis.__sddParallelRun = run;
|