@wrongstack/cli 0.8.2 → 0.8.4
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 +345 -121
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import * as
|
|
2
|
+
import * as path25 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, AutoApprovePermissionPolicy, makeLLMClassifier, resolveWstackPaths, DefaultSecretVault, migratePlaintextSecrets, DefaultConfigLoader, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, atomicWrite, DefaultPluginAPI, makeAgentSubagentRunner, NULL_FLEET_BUS, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, AGENTS_BY_PHASE, dispatchAgent, formatTodosList, emptyPlan, clearPlan, savePlan, formatPlanTemplates, getPlanTemplate, addPlanItem, formatPlan, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, DefaultTaskStore, TaskTracker, renderProgress, renderTaskGraph, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, pendingBtwCount, setBtwNote, InputBuilder, FsError, ERROR_CODES, projectHash, WrongStackError, defaultOrchestrator, decryptConfigSecrets, encryptConfigSecrets as encryptConfigSecrets$1, SpecVersioning, ParallelEternalEngine, allServers as allServers$1 } from '@wrongstack/core';
|
|
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, AutoApprovePermissionPolicy, makeLLMClassifier, resolveWstackPaths, DefaultSecretVault, migratePlaintextSecrets, DefaultConfigLoader, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, atomicWrite, DefaultPluginAPI, makeAgentSubagentRunner, NULL_FLEET_BUS, AutoPhaseRunner, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, AGENTS_BY_PHASE, dispatchAgent, formatTodosList, emptyPlan, clearPlan, savePlan, formatPlanTemplates, getPlanTemplate, addPlanItem, formatPlan, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, DefaultTaskStore, TaskTracker, renderProgress, renderTaskGraph, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, pendingBtwCount, setBtwNote, InputBuilder, FsError, ERROR_CODES, PhaseStore, projectHash, WrongStackError, defaultOrchestrator, decryptConfigSecrets, encryptConfigSecrets as encryptConfigSecrets$1, SpecVersioning, ParallelEternalEngine, allServers as allServers$1 } from '@wrongstack/core';
|
|
7
7
|
import { createRequire } from 'module';
|
|
8
|
-
import * as
|
|
9
|
-
import
|
|
8
|
+
import * as os7 from 'os';
|
|
9
|
+
import os7__default from 'os';
|
|
10
10
|
import * as crypto2 from 'crypto';
|
|
11
11
|
import { randomUUID } from 'crypto';
|
|
12
12
|
import { DefaultSecretVault as DefaultSecretVault$1, encryptConfigSecrets, isSecretField, decryptConfigSecrets as decryptConfigSecrets$1 } from '@wrongstack/core/security';
|
|
@@ -1398,7 +1398,7 @@ function sddHelp() {
|
|
|
1398
1398
|
async function gatherProjectContext(projectRoot) {
|
|
1399
1399
|
const parts = [];
|
|
1400
1400
|
try {
|
|
1401
|
-
const pkgPath =
|
|
1401
|
+
const pkgPath = path25.join(projectRoot, "package.json");
|
|
1402
1402
|
const pkgRaw = await fsp2.readFile(pkgPath, "utf8");
|
|
1403
1403
|
const pkg = JSON.parse(pkgRaw);
|
|
1404
1404
|
parts.push(`Project: ${String(pkg.name ?? "unknown")}`);
|
|
@@ -1414,13 +1414,13 @@ async function gatherProjectContext(projectRoot) {
|
|
|
1414
1414
|
} catch {
|
|
1415
1415
|
}
|
|
1416
1416
|
try {
|
|
1417
|
-
const tsconfigPath =
|
|
1417
|
+
const tsconfigPath = path25.join(projectRoot, "tsconfig.json");
|
|
1418
1418
|
await fsp2.access(tsconfigPath);
|
|
1419
1419
|
parts.push("Language: TypeScript");
|
|
1420
1420
|
} catch {
|
|
1421
1421
|
}
|
|
1422
1422
|
try {
|
|
1423
|
-
const srcDir =
|
|
1423
|
+
const srcDir = path25.join(projectRoot, "src");
|
|
1424
1424
|
const entries = await fsp2.readdir(srcDir, { withFileTypes: true });
|
|
1425
1425
|
const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
1426
1426
|
if (dirs.length > 0) {
|
|
@@ -1576,7 +1576,7 @@ __export(update_check_exports, {
|
|
|
1576
1576
|
getUpdateNotification: () => getUpdateNotification
|
|
1577
1577
|
});
|
|
1578
1578
|
function cachePath(homeFn = defaultHomeDir2) {
|
|
1579
|
-
return
|
|
1579
|
+
return path25.join(homeFn(), ".wrongstack", "update-cache.json");
|
|
1580
1580
|
}
|
|
1581
1581
|
function currentVersion() {
|
|
1582
1582
|
const req2 = createRequire(import.meta.url);
|
|
@@ -1613,7 +1613,7 @@ async function readCache(homeFn = defaultHomeDir2) {
|
|
|
1613
1613
|
}
|
|
1614
1614
|
async function writeCache(entry, homeFn = defaultHomeDir2) {
|
|
1615
1615
|
try {
|
|
1616
|
-
const dir =
|
|
1616
|
+
const dir = path25.dirname(cachePath(homeFn));
|
|
1617
1617
|
await fsp2.mkdir(dir, { recursive: true });
|
|
1618
1618
|
await fsp2.writeFile(cachePath(homeFn), JSON.stringify(entry, null, 2), "utf8");
|
|
1619
1619
|
} catch {
|
|
@@ -1686,7 +1686,7 @@ async function getUpdateNotification(signal, homeFn) {
|
|
|
1686
1686
|
var defaultHomeDir2, CACHE_TTL_MS;
|
|
1687
1687
|
var init_update_check = __esm({
|
|
1688
1688
|
"src/update-check.ts"() {
|
|
1689
|
-
defaultHomeDir2 = () =>
|
|
1689
|
+
defaultHomeDir2 = () => os7.homedir();
|
|
1690
1690
|
CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
1691
1691
|
}
|
|
1692
1692
|
});
|
|
@@ -2217,7 +2217,7 @@ async function runWebUI(opts) {
|
|
|
2217
2217
|
return {};
|
|
2218
2218
|
}
|
|
2219
2219
|
if (!parsed.providers) return {};
|
|
2220
|
-
const keyFile =
|
|
2220
|
+
const keyFile = path25.join(path25.dirname(opts.globalConfigPath), ".key");
|
|
2221
2221
|
const vault = new DefaultSecretVault$1({ keyFile });
|
|
2222
2222
|
return decryptConfigSecrets$1(parsed.providers, vault);
|
|
2223
2223
|
}
|
|
@@ -2250,7 +2250,7 @@ async function runWebUI(opts) {
|
|
|
2250
2250
|
parsed = {};
|
|
2251
2251
|
}
|
|
2252
2252
|
parsed.providers = providers;
|
|
2253
|
-
const keyFile =
|
|
2253
|
+
const keyFile = path25.join(path25.dirname(opts.globalConfigPath), ".key");
|
|
2254
2254
|
const vault = new DefaultSecretVault$1({ keyFile });
|
|
2255
2255
|
const encrypted = encryptConfigSecrets(parsed, vault);
|
|
2256
2256
|
await atomicWrite(opts.globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
@@ -2470,10 +2470,10 @@ async function detectPackageManager(root, declared) {
|
|
|
2470
2470
|
const name = declared.split("@")[0];
|
|
2471
2471
|
if (name) return name;
|
|
2472
2472
|
}
|
|
2473
|
-
if (await pathExists(
|
|
2474
|
-
if (await pathExists(
|
|
2475
|
-
if (await pathExists(
|
|
2476
|
-
if (await pathExists(
|
|
2473
|
+
if (await pathExists(path25.join(root, "pnpm-lock.yaml"))) return "pnpm";
|
|
2474
|
+
if (await pathExists(path25.join(root, "bun.lockb"))) return "bun";
|
|
2475
|
+
if (await pathExists(path25.join(root, "bun.lock"))) return "bun";
|
|
2476
|
+
if (await pathExists(path25.join(root, "yarn.lock"))) return "yarn";
|
|
2477
2477
|
return "npm";
|
|
2478
2478
|
}
|
|
2479
2479
|
function hasUsableScript(scripts, name) {
|
|
@@ -2494,7 +2494,7 @@ function parseMakeTargets(makefile) {
|
|
|
2494
2494
|
async function detectProjectFacts(root) {
|
|
2495
2495
|
const facts = { hints: [] };
|
|
2496
2496
|
try {
|
|
2497
|
-
const pkg = JSON.parse(await fsp2.readFile(
|
|
2497
|
+
const pkg = JSON.parse(await fsp2.readFile(path25.join(root, "package.json"), "utf8"));
|
|
2498
2498
|
const scripts = pkg.scripts ?? {};
|
|
2499
2499
|
const pm = await detectPackageManager(root, pkg.packageManager);
|
|
2500
2500
|
if (hasUsableScript(scripts, "build")) facts.build = `${pm} run build`;
|
|
@@ -2508,14 +2508,14 @@ async function detectProjectFacts(root) {
|
|
|
2508
2508
|
} catch {
|
|
2509
2509
|
}
|
|
2510
2510
|
try {
|
|
2511
|
-
if (!await pathExists(
|
|
2511
|
+
if (!await pathExists(path25.join(root, "pyproject.toml"))) throw new Error("not python");
|
|
2512
2512
|
facts.test ??= "pytest";
|
|
2513
2513
|
facts.lint ??= "ruff check .";
|
|
2514
2514
|
facts.hints.push("pyproject.toml");
|
|
2515
2515
|
} catch {
|
|
2516
2516
|
}
|
|
2517
2517
|
try {
|
|
2518
|
-
if (!await pathExists(
|
|
2518
|
+
if (!await pathExists(path25.join(root, "go.mod"))) throw new Error("not go");
|
|
2519
2519
|
facts.build ??= "go build ./...";
|
|
2520
2520
|
facts.test ??= "go test ./...";
|
|
2521
2521
|
facts.run ??= "go run .";
|
|
@@ -2523,7 +2523,7 @@ async function detectProjectFacts(root) {
|
|
|
2523
2523
|
} catch {
|
|
2524
2524
|
}
|
|
2525
2525
|
try {
|
|
2526
|
-
if (!await pathExists(
|
|
2526
|
+
if (!await pathExists(path25.join(root, "Cargo.toml"))) throw new Error("not rust");
|
|
2527
2527
|
facts.build ??= "cargo build";
|
|
2528
2528
|
facts.test ??= "cargo test";
|
|
2529
2529
|
facts.lint ??= "cargo clippy";
|
|
@@ -2532,7 +2532,7 @@ async function detectProjectFacts(root) {
|
|
|
2532
2532
|
} catch {
|
|
2533
2533
|
}
|
|
2534
2534
|
try {
|
|
2535
|
-
const makefile = await fsp2.readFile(
|
|
2535
|
+
const makefile = await fsp2.readFile(path25.join(root, "Makefile"), "utf8");
|
|
2536
2536
|
const targets = parseMakeTargets(makefile);
|
|
2537
2537
|
facts.build ??= targets.has("build") ? "make build" : "make";
|
|
2538
2538
|
if (targets.has("test")) facts.test ??= "make test";
|
|
@@ -3424,8 +3424,8 @@ function buildInitCommand(opts) {
|
|
|
3424
3424
|
name: "init",
|
|
3425
3425
|
description: "Create or update .wrongstack/AGENTS.md project context for the system prompt.",
|
|
3426
3426
|
async run(_args, ctx) {
|
|
3427
|
-
const dir =
|
|
3428
|
-
const file =
|
|
3427
|
+
const dir = path25.join(ctx.projectRoot, ".wrongstack");
|
|
3428
|
+
const file = path25.join(dir, "AGENTS.md");
|
|
3429
3429
|
const detected = await detectProjectFacts(ctx.projectRoot);
|
|
3430
3430
|
const body = renderAgentsTemplate(detected);
|
|
3431
3431
|
await fsp2.mkdir(dir, { recursive: true });
|
|
@@ -3616,18 +3616,18 @@ function stateBadge(state) {
|
|
|
3616
3616
|
return color.dim(state);
|
|
3617
3617
|
}
|
|
3618
3618
|
}
|
|
3619
|
-
async function readConfig(
|
|
3619
|
+
async function readConfig(path26) {
|
|
3620
3620
|
try {
|
|
3621
|
-
return JSON.parse(await fsp2.readFile(
|
|
3621
|
+
return JSON.parse(await fsp2.readFile(path26, "utf8"));
|
|
3622
3622
|
} catch {
|
|
3623
3623
|
return {};
|
|
3624
3624
|
}
|
|
3625
3625
|
}
|
|
3626
|
-
async function writeConfig(
|
|
3626
|
+
async function writeConfig(path26, cfg) {
|
|
3627
3627
|
const raw = JSON.stringify(cfg, null, 2);
|
|
3628
|
-
const tmp =
|
|
3628
|
+
const tmp = path26 + ".tmp";
|
|
3629
3629
|
await fsp2.writeFile(tmp, raw, "utf8");
|
|
3630
|
-
await fsp2.rename(tmp,
|
|
3630
|
+
await fsp2.rename(tmp, path26);
|
|
3631
3631
|
}
|
|
3632
3632
|
|
|
3633
3633
|
// src/slash-commands/mcp.ts
|
|
@@ -4894,7 +4894,7 @@ var DEFAULTS = {
|
|
|
4894
4894
|
cost: true
|
|
4895
4895
|
};
|
|
4896
4896
|
function resolveConfigPath() {
|
|
4897
|
-
return process.env[CONFIG_ENV] ??
|
|
4897
|
+
return process.env[CONFIG_ENV] ?? path25.join(process.env.HOME ?? "", ".wrongstack", "statusline.json");
|
|
4898
4898
|
}
|
|
4899
4899
|
async function loadStatuslineConfig() {
|
|
4900
4900
|
const p = resolveConfigPath();
|
|
@@ -4908,7 +4908,7 @@ async function loadStatuslineConfig() {
|
|
|
4908
4908
|
async function saveStatuslineConfig(cfg) {
|
|
4909
4909
|
const p = resolveConfigPath();
|
|
4910
4910
|
try {
|
|
4911
|
-
await fsp2.mkdir(
|
|
4911
|
+
await fsp2.mkdir(path25.dirname(p), { recursive: true });
|
|
4912
4912
|
await atomicWrite(p, JSON.stringify(cfg, null, 2));
|
|
4913
4913
|
} catch (err) {
|
|
4914
4914
|
throw new FsError({
|
|
@@ -5807,11 +5807,11 @@ When the error confidence is low (< 0.85) or the problem spans multiple files,
|
|
|
5807
5807
|
};
|
|
5808
5808
|
}
|
|
5809
5809
|
function makeInstaller(opts, projectRoot, global) {
|
|
5810
|
-
const globalRoot =
|
|
5810
|
+
const globalRoot = path25.join(os7.homedir(), ".wrongstack");
|
|
5811
5811
|
return new SkillInstaller({
|
|
5812
|
-
manifestPath:
|
|
5813
|
-
projectSkillsDir:
|
|
5814
|
-
globalSkillsDir:
|
|
5812
|
+
manifestPath: path25.join(globalRoot, "installed-skills.json"),
|
|
5813
|
+
projectSkillsDir: path25.join(projectRoot, ".wrongstack", "skills"),
|
|
5814
|
+
globalSkillsDir: path25.join(globalRoot, "skills"),
|
|
5815
5815
|
projectHash: projectHash(projectRoot),
|
|
5816
5816
|
skillLoader: opts.skillLoader
|
|
5817
5817
|
});
|
|
@@ -5967,6 +5967,229 @@ function buildSkillUninstallCommand(opts) {
|
|
|
5967
5967
|
}
|
|
5968
5968
|
};
|
|
5969
5969
|
}
|
|
5970
|
+
var currentRunner = null;
|
|
5971
|
+
var currentGraph = null;
|
|
5972
|
+
var DEFAULT_PHASES = [
|
|
5973
|
+
{
|
|
5974
|
+
name: "Discovery",
|
|
5975
|
+
description: "Requirements gathering and analysis",
|
|
5976
|
+
priority: "high",
|
|
5977
|
+
estimateHours: 2,
|
|
5978
|
+
parallelizable: false
|
|
5979
|
+
},
|
|
5980
|
+
{
|
|
5981
|
+
name: "Design",
|
|
5982
|
+
description: "Architecture and design decisions",
|
|
5983
|
+
priority: "critical",
|
|
5984
|
+
estimateHours: 4,
|
|
5985
|
+
parallelizable: false
|
|
5986
|
+
},
|
|
5987
|
+
{
|
|
5988
|
+
name: "Implementation",
|
|
5989
|
+
description: "Core feature development",
|
|
5990
|
+
priority: "critical",
|
|
5991
|
+
estimateHours: 12,
|
|
5992
|
+
parallelizable: false
|
|
5993
|
+
},
|
|
5994
|
+
{
|
|
5995
|
+
name: "Testing",
|
|
5996
|
+
description: "Unit, integration, and e2e tests",
|
|
5997
|
+
priority: "high",
|
|
5998
|
+
estimateHours: 6,
|
|
5999
|
+
parallelizable: true
|
|
6000
|
+
},
|
|
6001
|
+
{
|
|
6002
|
+
name: "Deployment",
|
|
6003
|
+
description: "Deploy to production",
|
|
6004
|
+
priority: "medium",
|
|
6005
|
+
estimateHours: 2,
|
|
6006
|
+
parallelizable: false
|
|
6007
|
+
}
|
|
6008
|
+
];
|
|
6009
|
+
function getStore() {
|
|
6010
|
+
const baseDir = path25.join(os7.homedir(), ".wrongstack", "autophase");
|
|
6011
|
+
return new PhaseStore({ baseDir });
|
|
6012
|
+
}
|
|
6013
|
+
function formatProgress(p) {
|
|
6014
|
+
const bars = "\u2588".repeat(Math.floor(p.percentComplete / 5)) + "\u2591".repeat(20 - Math.floor(p.percentComplete / 5));
|
|
6015
|
+
return [
|
|
6016
|
+
`
|
|
6017
|
+
\u{1F4CA} Progress: ${bars} ${p.percentComplete}%`,
|
|
6018
|
+
` \u{1F4CB} Phases: ${p.completed}/${p.totalPhases} done, ${p.running} running, ${p.pending} pending`,
|
|
6019
|
+
` \u2705 Tasks: ${p.completedTasks}/${p.totalTasks} completed`,
|
|
6020
|
+
` \u23F1\uFE0F Est: ${p.estimatedHours.toFixed(1)}h | Actual: ${p.actualHours.toFixed(1)}h`
|
|
6021
|
+
].join("\n");
|
|
6022
|
+
}
|
|
6023
|
+
function formatPhaseList(graph) {
|
|
6024
|
+
const phases = Array.from(graph.phases.values());
|
|
6025
|
+
const statusEmoji = {
|
|
6026
|
+
pending: "\u23F3",
|
|
6027
|
+
ready: "\u{1F51C}",
|
|
6028
|
+
running: "\u{1F504}",
|
|
6029
|
+
paused: "\u23F8\uFE0F",
|
|
6030
|
+
completed: "\u2705",
|
|
6031
|
+
failed: "\u274C",
|
|
6032
|
+
skipped: "\u23ED\uFE0F"
|
|
6033
|
+
};
|
|
6034
|
+
return phases.map((p, i) => {
|
|
6035
|
+
const emoji = statusEmoji[p.status] ?? "\u26AA";
|
|
6036
|
+
const progress = p.taskGraph.nodes.size > 0 ? `${Array.from(p.taskGraph.nodes.values()).filter((t) => t.status === "completed").length}/${p.taskGraph.nodes.size}` : "0/0";
|
|
6037
|
+
return ` ${i + 1}. ${emoji} ${p.name} (${p.status}) \u2014 ${progress} tasks`;
|
|
6038
|
+
}).join("\n");
|
|
6039
|
+
}
|
|
6040
|
+
var autophaseCommand = {
|
|
6041
|
+
name: "autophase",
|
|
6042
|
+
description: "Otonom faz tabanl\u0131 i\u015F ak\u0131\u015F\u0131 \u2014 projeyi fazlara b\xF6l ve otonom \xE7al\u0131\u015Ft\u0131r",
|
|
6043
|
+
argsHint: "[start|pause|resume|stop|status|list|load|save] [args...]",
|
|
6044
|
+
async run(args, _ctx) {
|
|
6045
|
+
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
6046
|
+
const sub = parts[0] ?? "status";
|
|
6047
|
+
const store = getStore();
|
|
6048
|
+
switch (sub) {
|
|
6049
|
+
case "start": {
|
|
6050
|
+
const title = parts.slice(1).join(" ") || "Untitled Project";
|
|
6051
|
+
const runLog = [];
|
|
6052
|
+
const log = (line) => runLog.push(line);
|
|
6053
|
+
log(`\u{1F680} AutoPhase ba\u015Flat\u0131l\u0131yor: ${title}`);
|
|
6054
|
+
currentRunner = new AutoPhaseRunner({
|
|
6055
|
+
title,
|
|
6056
|
+
phases: DEFAULT_PHASES,
|
|
6057
|
+
executeTask: async (task, phaseId) => {
|
|
6058
|
+
log(` [${phaseId}] Executing: ${task.title}`);
|
|
6059
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
6060
|
+
log(` [${phaseId}] \u2705 Completed: ${task.title}`);
|
|
6061
|
+
},
|
|
6062
|
+
onPhaseComplete: (phase) => {
|
|
6063
|
+
log(`\u2705 Phase tamamland\u0131: ${phase.name} (${phase.actualDurationMs ? (phase.actualDurationMs / 6e4).toFixed(1) : 0}m)`);
|
|
6064
|
+
},
|
|
6065
|
+
onPhaseFail: (phase, error) => {
|
|
6066
|
+
log(`\u274C Phase ba\u015Far\u0131s\u0131z: ${phase.name} \u2014 ${error.message}`);
|
|
6067
|
+
},
|
|
6068
|
+
onProgress: (progress) => {
|
|
6069
|
+
if (progress.percentComplete % 10 === 0) {
|
|
6070
|
+
log(formatProgress(progress));
|
|
6071
|
+
}
|
|
6072
|
+
},
|
|
6073
|
+
onComplete: (graph) => {
|
|
6074
|
+
log(`\u{1F389} T\xFCm fazlar tamamland\u0131! ${graph.title}`);
|
|
6075
|
+
},
|
|
6076
|
+
onFail: (_graph, phase, error) => {
|
|
6077
|
+
log(`\u{1F4A5} AutoPhase durdu: ${phase.name} \u2014 ${error.message}`);
|
|
6078
|
+
},
|
|
6079
|
+
autonomous: true,
|
|
6080
|
+
maxConcurrentPhases: 1,
|
|
6081
|
+
maxConcurrentTasks: 2
|
|
6082
|
+
});
|
|
6083
|
+
currentGraph = await currentRunner.start();
|
|
6084
|
+
await store.save(currentGraph);
|
|
6085
|
+
return {
|
|
6086
|
+
message: [
|
|
6087
|
+
`AutoPhase ba\u015Flat\u0131ld\u0131: **${title}**`,
|
|
6088
|
+
"",
|
|
6089
|
+
formatPhaseList(currentGraph),
|
|
6090
|
+
...runLog.length > 0 ? ["", "---", ...runLog] : []
|
|
6091
|
+
].join("\n")
|
|
6092
|
+
};
|
|
6093
|
+
}
|
|
6094
|
+
case "pause": {
|
|
6095
|
+
if (!currentRunner) {
|
|
6096
|
+
return { message: "\u274C Aktif AutoPhase yok. \xD6nce `/autophase start` \xE7al\u0131\u015Ft\u0131r\u0131n." };
|
|
6097
|
+
}
|
|
6098
|
+
currentRunner.pause();
|
|
6099
|
+
return { message: "\u23F8\uFE0F AutoPhase duraklat\u0131ld\u0131. Devam etmek i\xE7in `/autophase resume`" };
|
|
6100
|
+
}
|
|
6101
|
+
case "resume": {
|
|
6102
|
+
if (!currentRunner) {
|
|
6103
|
+
return { message: "\u274C Aktif AutoPhase yok. \xD6nce `/autophase start` \xE7al\u0131\u015Ft\u0131r\u0131n." };
|
|
6104
|
+
}
|
|
6105
|
+
currentRunner.resume();
|
|
6106
|
+
return { message: "\u25B6\uFE0F AutoPhase devam ediyor." };
|
|
6107
|
+
}
|
|
6108
|
+
case "stop": {
|
|
6109
|
+
if (!currentRunner) {
|
|
6110
|
+
return { message: "\u274C Aktif AutoPhase yok." };
|
|
6111
|
+
}
|
|
6112
|
+
currentRunner.stop();
|
|
6113
|
+
currentRunner = null;
|
|
6114
|
+
return { message: "\u{1F6D1} AutoPhase durduruldu." };
|
|
6115
|
+
}
|
|
6116
|
+
case "status": {
|
|
6117
|
+
if (!currentRunner || !currentGraph) {
|
|
6118
|
+
const graphs = await store.list();
|
|
6119
|
+
if (graphs.length === 0) {
|
|
6120
|
+
return { message: "Aktif AutoPhase yok. Ba\u015Flatmak i\xE7in `/autophase start [title]`" };
|
|
6121
|
+
}
|
|
6122
|
+
const list = graphs.slice(0, 5).map((g) => ` \u2022 ${g.title} (${g.status})`).join("\n");
|
|
6123
|
+
return { message: `Kay\u0131tl\u0131 AutoPhase projeleri:
|
|
6124
|
+
${list}` };
|
|
6125
|
+
}
|
|
6126
|
+
const progress = currentRunner.getProgress();
|
|
6127
|
+
const phaseList = formatPhaseList(currentGraph);
|
|
6128
|
+
return {
|
|
6129
|
+
message: [
|
|
6130
|
+
`**${currentGraph.title}**`,
|
|
6131
|
+
progress ? formatProgress(progress) : "",
|
|
6132
|
+
"",
|
|
6133
|
+
"**Fazlar:**",
|
|
6134
|
+
phaseList,
|
|
6135
|
+
"",
|
|
6136
|
+
currentRunner.isPaused() ? "\u23F8\uFE0F Duraklat\u0131ld\u0131" : currentRunner.isRunning() ? "\u{1F504} \xC7al\u0131\u015F\u0131yor" : "\u23F9\uFE0F Durdu"
|
|
6137
|
+
].join("\n")
|
|
6138
|
+
};
|
|
6139
|
+
}
|
|
6140
|
+
case "list": {
|
|
6141
|
+
const graphs = await store.list();
|
|
6142
|
+
if (graphs.length === 0) {
|
|
6143
|
+
return { message: "Kay\u0131tl\u0131 AutoPhase projesi yok." };
|
|
6144
|
+
}
|
|
6145
|
+
const list = graphs.map((g) => {
|
|
6146
|
+
const statusEmoji = g.status === "completed" ? "\u2705" : g.status === "in_progress" ? "\u{1F504}" : "\u23F3";
|
|
6147
|
+
return ` ${statusEmoji} ${g.title} (g\xFCncelleme: ${new Date(g.updatedAt).toLocaleDateString("tr-TR")})`;
|
|
6148
|
+
}).join("\n");
|
|
6149
|
+
return { message: `**Kay\u0131tl\u0131 Projeler:**
|
|
6150
|
+
${list}` };
|
|
6151
|
+
}
|
|
6152
|
+
case "load": {
|
|
6153
|
+
const graphId = parts[1];
|
|
6154
|
+
if (!graphId) {
|
|
6155
|
+
return { message: "\u274C Graph ID gerekli. Kullan\u0131m: `/autophase load <id>`" };
|
|
6156
|
+
}
|
|
6157
|
+
const graph = await store.load(graphId);
|
|
6158
|
+
if (!graph) {
|
|
6159
|
+
return { message: `\u274C Graph bulunamad\u0131: ${graphId}` };
|
|
6160
|
+
}
|
|
6161
|
+
currentGraph = graph;
|
|
6162
|
+
return {
|
|
6163
|
+
message: `**${graph.title}** y\xFCklendi.
|
|
6164
|
+
|
|
6165
|
+
${formatPhaseList(graph)}`
|
|
6166
|
+
};
|
|
6167
|
+
}
|
|
6168
|
+
case "save": {
|
|
6169
|
+
if (!currentGraph) {
|
|
6170
|
+
return { message: "\u274C Kaydedilecek aktif graph yok." };
|
|
6171
|
+
}
|
|
6172
|
+
await store.save(currentGraph);
|
|
6173
|
+
return { message: `\u2705 **${currentGraph.title}** kaydedildi.` };
|
|
6174
|
+
}
|
|
6175
|
+
default:
|
|
6176
|
+
return {
|
|
6177
|
+
message: [
|
|
6178
|
+
"**AutoPhase Komutlar\u0131:**",
|
|
6179
|
+
"",
|
|
6180
|
+
"`/autophase start [title]` \u2014 Yeni proje ba\u015Flat",
|
|
6181
|
+
"`/autophase pause` \u2014 Duraklat",
|
|
6182
|
+
"`/autophase resume` \u2014 Devam et",
|
|
6183
|
+
"`/autophase stop` \u2014 Durdur",
|
|
6184
|
+
"`/autophase status` \u2014 Durum g\xF6ster",
|
|
6185
|
+
"`/autophase list` \u2014 Kay\u0131tl\u0131 projeleri listele",
|
|
6186
|
+
"`/autophase load <id>` \u2014 Projeyi y\xFCkle",
|
|
6187
|
+
"`/autophase save` \u2014 Aktif projeyi kaydet"
|
|
6188
|
+
].join("\n")
|
|
6189
|
+
};
|
|
6190
|
+
}
|
|
6191
|
+
}
|
|
6192
|
+
};
|
|
5970
6193
|
|
|
5971
6194
|
// src/slash-commands/index.ts
|
|
5972
6195
|
function buildBuiltinSlashCommands(opts) {
|
|
@@ -6009,6 +6232,7 @@ function buildBuiltinSlashCommands(opts) {
|
|
|
6009
6232
|
buildPushCommand(),
|
|
6010
6233
|
buildSecurityCommand(opts),
|
|
6011
6234
|
buildFixCommand(opts),
|
|
6235
|
+
autophaseCommand,
|
|
6012
6236
|
buildStatuslineCommand({
|
|
6013
6237
|
cwd: opts.cwd,
|
|
6014
6238
|
hiddenItems: opts.statuslineHiddenItems ?? [],
|
|
@@ -6036,13 +6260,13 @@ var MANIFESTS = [
|
|
|
6036
6260
|
];
|
|
6037
6261
|
async function detectProjectKind(projectRoot) {
|
|
6038
6262
|
try {
|
|
6039
|
-
await fsp2.access(
|
|
6263
|
+
await fsp2.access(path25.join(projectRoot, ".wrongstack", "AGENTS.md"));
|
|
6040
6264
|
return "initialized";
|
|
6041
6265
|
} catch {
|
|
6042
6266
|
}
|
|
6043
6267
|
for (const m of MANIFESTS) {
|
|
6044
6268
|
try {
|
|
6045
|
-
await fsp2.access(
|
|
6269
|
+
await fsp2.access(path25.join(projectRoot, m));
|
|
6046
6270
|
return "project";
|
|
6047
6271
|
} catch {
|
|
6048
6272
|
}
|
|
@@ -6050,8 +6274,8 @@ async function detectProjectKind(projectRoot) {
|
|
|
6050
6274
|
return "empty";
|
|
6051
6275
|
}
|
|
6052
6276
|
async function scaffoldAgentsMd(projectRoot) {
|
|
6053
|
-
const dir =
|
|
6054
|
-
const file =
|
|
6277
|
+
const dir = path25.join(projectRoot, ".wrongstack");
|
|
6278
|
+
const file = path25.join(dir, "AGENTS.md");
|
|
6055
6279
|
const facts = await detectProjectFacts(projectRoot);
|
|
6056
6280
|
const body = renderAgentsTemplate(facts);
|
|
6057
6281
|
await fsp2.mkdir(dir, { recursive: true });
|
|
@@ -6064,7 +6288,7 @@ async function runProjectCheck(opts) {
|
|
|
6064
6288
|
if (kind === "initialized") {
|
|
6065
6289
|
renderer.write(
|
|
6066
6290
|
`
|
|
6067
|
-
${color.green("\u2713")} Project initialized ${color.dim(`(${
|
|
6291
|
+
${color.green("\u2713")} Project initialized ${color.dim(`(${path25.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
|
|
6068
6292
|
`
|
|
6069
6293
|
);
|
|
6070
6294
|
return true;
|
|
@@ -6095,7 +6319,7 @@ async function runProjectCheck(opts) {
|
|
|
6095
6319
|
}
|
|
6096
6320
|
return true;
|
|
6097
6321
|
}
|
|
6098
|
-
const gitDir =
|
|
6322
|
+
const gitDir = path25.join(projectRoot, ".git");
|
|
6099
6323
|
let hasGit = false;
|
|
6100
6324
|
try {
|
|
6101
6325
|
await fsp2.access(gitDir);
|
|
@@ -6220,10 +6444,10 @@ async function runLaunchPrompts(opts) {
|
|
|
6220
6444
|
return { mode, yolo, director, autonomy };
|
|
6221
6445
|
}
|
|
6222
6446
|
async function bootConfig(flags) {
|
|
6223
|
-
const cwd = typeof flags["cwd"] === "string" ?
|
|
6447
|
+
const cwd = typeof flags["cwd"] === "string" ? path25.resolve(flags["cwd"]) : process.cwd();
|
|
6224
6448
|
const pathResolver = new DefaultPathResolver(cwd);
|
|
6225
6449
|
const projectRoot = pathResolver.projectRoot;
|
|
6226
|
-
const userHome =
|
|
6450
|
+
const userHome = os7.homedir();
|
|
6227
6451
|
const wpaths = resolveWstackPaths({ projectRoot, userHome });
|
|
6228
6452
|
await ensureProjectMeta(wpaths, projectRoot);
|
|
6229
6453
|
const vault = new DefaultSecretVault({ keyFile: wpaths.secretsKey });
|
|
@@ -6287,7 +6511,7 @@ var ReadlineInputReader = class {
|
|
|
6287
6511
|
history = [];
|
|
6288
6512
|
pending = false;
|
|
6289
6513
|
constructor(opts = {}) {
|
|
6290
|
-
this.historyFile = opts.historyFile ??
|
|
6514
|
+
this.historyFile = opts.historyFile ?? path25.join(os7.homedir(), ".wrongstack", "history");
|
|
6291
6515
|
}
|
|
6292
6516
|
async loadHistory() {
|
|
6293
6517
|
try {
|
|
@@ -6299,7 +6523,7 @@ var ReadlineInputReader = class {
|
|
|
6299
6523
|
}
|
|
6300
6524
|
async saveHistory() {
|
|
6301
6525
|
try {
|
|
6302
|
-
await fsp2.mkdir(
|
|
6526
|
+
await fsp2.mkdir(path25.dirname(this.historyFile), { recursive: true });
|
|
6303
6527
|
await fsp2.writeFile(this.historyFile, this.history.slice(-1e3).join("\n"));
|
|
6304
6528
|
} catch {
|
|
6305
6529
|
}
|
|
@@ -6526,20 +6750,20 @@ function assertSafeToDelete(filename, parentDir) {
|
|
|
6526
6750
|
if (PROTECTED_BASENAMES.has(filename)) {
|
|
6527
6751
|
throw new Error(`Refusing to delete protected file: ${filename}`);
|
|
6528
6752
|
}
|
|
6529
|
-
if (filename !==
|
|
6753
|
+
if (filename !== path25.basename(filename)) {
|
|
6530
6754
|
throw new Error(`Refusing to delete path with traversal: ${filename}`);
|
|
6531
6755
|
}
|
|
6532
6756
|
if (!filename.startsWith("config.json.") || !filename.endsWith(".bak")) {
|
|
6533
6757
|
throw new Error(`Refusing to delete unknown file: ${filename}`);
|
|
6534
6758
|
}
|
|
6535
|
-
const resolvedParent =
|
|
6759
|
+
const resolvedParent = path25.resolve(parentDir);
|
|
6536
6760
|
if (!resolvedParent.endsWith(".wrongstack")) {
|
|
6537
6761
|
throw new Error(`Unexpected parent directory for bak prune: ${resolvedParent}`);
|
|
6538
6762
|
}
|
|
6539
6763
|
}
|
|
6540
6764
|
async function safeDelete(filePath) {
|
|
6541
|
-
const dir =
|
|
6542
|
-
const filename =
|
|
6765
|
+
const dir = path25.dirname(filePath);
|
|
6766
|
+
const filename = path25.basename(filePath);
|
|
6543
6767
|
try {
|
|
6544
6768
|
assertSafeToDelete(filename, dir);
|
|
6545
6769
|
await fsp2.unlink(filePath);
|
|
@@ -6582,18 +6806,18 @@ function diffSummary(oldCfg, newCfg) {
|
|
|
6582
6806
|
}
|
|
6583
6807
|
return changes.length > 0 ? changes.slice(0, 5).join(", ") : "no changes";
|
|
6584
6808
|
}
|
|
6585
|
-
var defaultHomeDir = () =>
|
|
6809
|
+
var defaultHomeDir = () => os7__default.homedir();
|
|
6586
6810
|
function historyDir(homeFn = defaultHomeDir) {
|
|
6587
|
-
return
|
|
6811
|
+
return path25.join(homeFn(), ".wrongstack", "config.history", "entries");
|
|
6588
6812
|
}
|
|
6589
6813
|
function historyIndexPath(homeFn = defaultHomeDir) {
|
|
6590
|
-
return
|
|
6814
|
+
return path25.join(homeFn(), ".wrongstack", "config.history", "index.json");
|
|
6591
6815
|
}
|
|
6592
6816
|
function configPath(homeFn = defaultHomeDir) {
|
|
6593
|
-
return
|
|
6817
|
+
return path25.join(homeFn(), ".wrongstack", "config.json");
|
|
6594
6818
|
}
|
|
6595
6819
|
function backupLastPath(homeFn = defaultHomeDir) {
|
|
6596
|
-
return
|
|
6820
|
+
return path25.join(homeFn(), ".wrongstack", "config.json.last");
|
|
6597
6821
|
}
|
|
6598
6822
|
function entryId(ts) {
|
|
6599
6823
|
return ts.replace(/[:.]/g, "-").slice(0, 19);
|
|
@@ -6648,17 +6872,17 @@ async function backupCurrent(homeFn = defaultHomeDir) {
|
|
|
6648
6872
|
}
|
|
6649
6873
|
if (content !== void 0) {
|
|
6650
6874
|
try {
|
|
6651
|
-
const bakPath =
|
|
6875
|
+
const bakPath = path25.join(homeFn(), ".wrongstack", `config.json.${ts}.bak`);
|
|
6652
6876
|
await atomicWrite(bakPath, content);
|
|
6653
6877
|
} catch {
|
|
6654
6878
|
}
|
|
6655
6879
|
}
|
|
6656
6880
|
try {
|
|
6657
|
-
const dir =
|
|
6881
|
+
const dir = path25.join(homeFn(), ".wrongstack");
|
|
6658
6882
|
const files = await fsp2.readdir(dir);
|
|
6659
6883
|
const baks = files.filter((f) => f.startsWith("config.json.") && f.endsWith(".bak")).sort().reverse();
|
|
6660
6884
|
for (const f of baks.slice(10)) {
|
|
6661
|
-
await safeDelete(
|
|
6885
|
+
await safeDelete(path25.join(dir, f));
|
|
6662
6886
|
}
|
|
6663
6887
|
} catch {
|
|
6664
6888
|
}
|
|
@@ -6676,7 +6900,7 @@ async function appendHistory(oldCfg, newCfg, description, homeFn = defaultHomeDi
|
|
|
6676
6900
|
};
|
|
6677
6901
|
try {
|
|
6678
6902
|
await fsp2.writeFile(
|
|
6679
|
-
|
|
6903
|
+
path25.join(historyDir(homeFn), `${id}.json`),
|
|
6680
6904
|
JSON.stringify(entry, null, 2),
|
|
6681
6905
|
"utf8"
|
|
6682
6906
|
);
|
|
@@ -6684,7 +6908,7 @@ async function appendHistory(oldCfg, newCfg, description, homeFn = defaultHomeDi
|
|
|
6684
6908
|
throw new FsError({
|
|
6685
6909
|
message: err instanceof Error ? err.message : String(err),
|
|
6686
6910
|
code: ERROR_CODES.FS_WRITE_FAILED,
|
|
6687
|
-
path:
|
|
6911
|
+
path: path25.join(historyDir(homeFn), `${id}.json`),
|
|
6688
6912
|
cause: err
|
|
6689
6913
|
});
|
|
6690
6914
|
}
|
|
@@ -6699,7 +6923,7 @@ async function listHistory(homeFn = defaultHomeDir) {
|
|
|
6699
6923
|
}
|
|
6700
6924
|
async function getHistoryEntry(id, homeFn = defaultHomeDir) {
|
|
6701
6925
|
try {
|
|
6702
|
-
const raw = await fsp2.readFile(
|
|
6926
|
+
const raw = await fsp2.readFile(path25.join(historyDir(homeFn), `${id}.json`), "utf8");
|
|
6703
6927
|
return JSON.parse(raw);
|
|
6704
6928
|
} catch {
|
|
6705
6929
|
return null;
|
|
@@ -7097,7 +7321,7 @@ function pickGroupIndex(opts) {
|
|
|
7097
7321
|
if (Number.isFinite(parsed)) current = wrap(parsed);
|
|
7098
7322
|
} catch {
|
|
7099
7323
|
}
|
|
7100
|
-
fs9.mkdirSync(
|
|
7324
|
+
fs9.mkdirSync(path25.dirname(opts.cursorFile), { recursive: true });
|
|
7101
7325
|
fs9.writeFileSync(opts.cursorFile, String(wrap(current + 1)));
|
|
7102
7326
|
return current;
|
|
7103
7327
|
} catch {
|
|
@@ -7433,14 +7657,14 @@ function summarize(value, name) {
|
|
|
7433
7657
|
if (typeof v === "object" && v !== null) {
|
|
7434
7658
|
const o = v;
|
|
7435
7659
|
if (name === "edit") {
|
|
7436
|
-
const
|
|
7660
|
+
const path26 = typeof o["path"] === "string" ? o["path"] : "";
|
|
7437
7661
|
const reps = typeof o["replacements"] === "number" ? o["replacements"] : 0;
|
|
7438
|
-
return `${
|
|
7662
|
+
return `${path26} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
|
|
7439
7663
|
}
|
|
7440
7664
|
if (name === "write") {
|
|
7441
|
-
const
|
|
7665
|
+
const path26 = typeof o["path"] === "string" ? o["path"] : "";
|
|
7442
7666
|
const bytes = typeof o["bytes"] === "number" ? o["bytes"] : void 0;
|
|
7443
|
-
return bytes !== void 0 ? `${
|
|
7667
|
+
return bytes !== void 0 ? `${path26} ${bytes}B` : path26;
|
|
7444
7668
|
}
|
|
7445
7669
|
if (typeof o["count"] === "number") {
|
|
7446
7670
|
return `${o["count"]} match${o["count"] === 1 ? "" : "es"}`;
|
|
@@ -8371,7 +8595,7 @@ var diagCmd = async (_args, deps) => {
|
|
|
8371
8595
|
` modelsCache: ${deps.paths.modelsCache}`,
|
|
8372
8596
|
` cacheAge: ${isFinite(age) ? `${Math.round(age / 60)}m` : "never"}`,
|
|
8373
8597
|
` node: ${process.version}`,
|
|
8374
|
-
` os: ${
|
|
8598
|
+
` os: ${os7.platform()} ${os7.release()}`,
|
|
8375
8599
|
` provider: ${cfg.provider ?? "<unset>"}`,
|
|
8376
8600
|
` model: ${cfg.model ?? "<unset>"}`,
|
|
8377
8601
|
` tools: ${deps.toolRegistry?.list().length ?? 0}`,
|
|
@@ -8450,7 +8674,7 @@ var doctorCmd = async (_args, deps) => {
|
|
|
8450
8674
|
}
|
|
8451
8675
|
try {
|
|
8452
8676
|
await fsp2.mkdir(deps.paths.projectSessions, { recursive: true });
|
|
8453
|
-
const probe =
|
|
8677
|
+
const probe = path25.join(deps.paths.projectSessions, `.probe-${Date.now()}`);
|
|
8454
8678
|
await fsp2.writeFile(probe, "");
|
|
8455
8679
|
await fsp2.unlink(probe);
|
|
8456
8680
|
checks.push({ name: "sessions writable", status: "ok", detail: deps.paths.projectSessions });
|
|
@@ -8553,8 +8777,8 @@ var exportCmd = async (args, deps) => {
|
|
|
8553
8777
|
return 1;
|
|
8554
8778
|
}
|
|
8555
8779
|
if (output) {
|
|
8556
|
-
await fsp2.mkdir(
|
|
8557
|
-
await fsp2.writeFile(
|
|
8780
|
+
await fsp2.mkdir(path25.dirname(path25.resolve(deps.cwd, output)), { recursive: true });
|
|
8781
|
+
await fsp2.writeFile(path25.resolve(deps.cwd, output), rendered, "utf8");
|
|
8558
8782
|
deps.renderer.write(`Wrote ${rendered.length} bytes to ${output}
|
|
8559
8783
|
`);
|
|
8560
8784
|
} else {
|
|
@@ -8627,8 +8851,8 @@ var initCmd = async (_args, deps) => {
|
|
|
8627
8851
|
const vault = new DefaultSecretVault$1({ keyFile: deps.paths.secretsKey });
|
|
8628
8852
|
const encrypted = encryptConfigSecrets(config, vault);
|
|
8629
8853
|
await atomicWrite(deps.paths.globalConfig, JSON.stringify(encrypted, null, 2));
|
|
8630
|
-
await fsp2.mkdir(
|
|
8631
|
-
const agentsFile =
|
|
8854
|
+
await fsp2.mkdir(path25.join(deps.projectRoot, ".wrongstack"), { recursive: true });
|
|
8855
|
+
const agentsFile = path25.join(deps.projectRoot, ".wrongstack", "AGENTS.md");
|
|
8632
8856
|
const projectFacts = await detectProjectFacts(deps.projectRoot);
|
|
8633
8857
|
await atomicWrite(agentsFile, renderAgentsTemplate(projectFacts));
|
|
8634
8858
|
deps.renderer.writeInfo(`Wrote ${deps.paths.globalConfig}`);
|
|
@@ -8934,7 +9158,7 @@ var usageCmd = async (_args, deps) => {
|
|
|
8934
9158
|
return 0;
|
|
8935
9159
|
};
|
|
8936
9160
|
var projectsCmd = async (_args, deps) => {
|
|
8937
|
-
const projectsRoot =
|
|
9161
|
+
const projectsRoot = path25.join(deps.paths.globalRoot, "projects");
|
|
8938
9162
|
try {
|
|
8939
9163
|
const entries = await fsp2.readdir(projectsRoot);
|
|
8940
9164
|
if (entries.length === 0) {
|
|
@@ -8944,7 +9168,7 @@ var projectsCmd = async (_args, deps) => {
|
|
|
8944
9168
|
for (const hash of entries) {
|
|
8945
9169
|
try {
|
|
8946
9170
|
const meta = JSON.parse(
|
|
8947
|
-
await fsp2.readFile(
|
|
9171
|
+
await fsp2.readFile(path25.join(projectsRoot, hash, "meta.json"), "utf8")
|
|
8948
9172
|
);
|
|
8949
9173
|
deps.renderer.write(
|
|
8950
9174
|
` ${color.dim(hash)} ${color.dim(meta.lastSeen ?? "")} ${meta.root ?? "?"}
|
|
@@ -9103,7 +9327,7 @@ async function listFleetRuns(deps) {
|
|
|
9103
9327
|
}
|
|
9104
9328
|
const runs = [];
|
|
9105
9329
|
for (const id of entries) {
|
|
9106
|
-
const runDir =
|
|
9330
|
+
const runDir = path25.join(deps.paths.projectSessions, id);
|
|
9107
9331
|
let stat3;
|
|
9108
9332
|
try {
|
|
9109
9333
|
stat3 = await fsp2.stat(runDir);
|
|
@@ -9116,17 +9340,17 @@ async function listFleetRuns(deps) {
|
|
|
9116
9340
|
let subagentCount = 0;
|
|
9117
9341
|
let subagentsDir;
|
|
9118
9342
|
try {
|
|
9119
|
-
await fsp2.access(
|
|
9343
|
+
await fsp2.access(path25.join(runDir, "fleet.json"));
|
|
9120
9344
|
manifest = true;
|
|
9121
9345
|
} catch {
|
|
9122
9346
|
}
|
|
9123
9347
|
try {
|
|
9124
|
-
await fsp2.access(
|
|
9348
|
+
await fsp2.access(path25.join(runDir, "checkpoint.json"));
|
|
9125
9349
|
checkpoint = true;
|
|
9126
9350
|
} catch {
|
|
9127
9351
|
}
|
|
9128
9352
|
try {
|
|
9129
|
-
subagentsDir =
|
|
9353
|
+
subagentsDir = path25.join(runDir, "subagents");
|
|
9130
9354
|
const files = await fsp2.readdir(subagentsDir);
|
|
9131
9355
|
subagentCount = files.filter((f) => f.endsWith(".jsonl")).length;
|
|
9132
9356
|
} catch {
|
|
@@ -9155,7 +9379,7 @@ async function listFleetRuns(deps) {
|
|
|
9155
9379
|
return 0;
|
|
9156
9380
|
}
|
|
9157
9381
|
async function showFleetRun(runId, deps) {
|
|
9158
|
-
const runDir =
|
|
9382
|
+
const runDir = path25.join(deps.paths.projectSessions, runId);
|
|
9159
9383
|
let stat3;
|
|
9160
9384
|
try {
|
|
9161
9385
|
stat3 = await fsp2.stat(runDir);
|
|
@@ -9172,7 +9396,7 @@ async function showFleetRun(runId, deps) {
|
|
|
9172
9396
|
deps.renderer.write(color.bold(`
|
|
9173
9397
|
Fleet Run: ${runId}
|
|
9174
9398
|
`) + "\n");
|
|
9175
|
-
const manifestPath =
|
|
9399
|
+
const manifestPath = path25.join(runDir, "fleet.json");
|
|
9176
9400
|
let manifestData = null;
|
|
9177
9401
|
try {
|
|
9178
9402
|
manifestData = await fsp2.readFile(manifestPath, "utf8");
|
|
@@ -9188,7 +9412,7 @@ Fleet Run: ${runId}
|
|
|
9188
9412
|
deps.renderer.write(` ${color.dim("\u25CB")} fleet.json \u2014 not found
|
|
9189
9413
|
`);
|
|
9190
9414
|
}
|
|
9191
|
-
const checkpointPath =
|
|
9415
|
+
const checkpointPath = path25.join(runDir, "checkpoint.json");
|
|
9192
9416
|
let checkpointData = null;
|
|
9193
9417
|
try {
|
|
9194
9418
|
checkpointData = await fsp2.readFile(checkpointPath, "utf8");
|
|
@@ -9235,7 +9459,7 @@ Fleet Run: ${runId}
|
|
|
9235
9459
|
} catch {
|
|
9236
9460
|
}
|
|
9237
9461
|
}
|
|
9238
|
-
const subagentsDir =
|
|
9462
|
+
const subagentsDir = path25.join(runDir, "subagents");
|
|
9239
9463
|
let subagentFiles = [];
|
|
9240
9464
|
try {
|
|
9241
9465
|
subagentFiles = await fsp2.readdir(subagentsDir);
|
|
@@ -9247,7 +9471,7 @@ Fleet Run: ${runId}
|
|
|
9247
9471
|
Subagent transcripts (${subagentFiles.length}):
|
|
9248
9472
|
`);
|
|
9249
9473
|
for (const f of subagentFiles.sort()) {
|
|
9250
|
-
const filePath =
|
|
9474
|
+
const filePath = path25.join(subagentsDir, f);
|
|
9251
9475
|
let size;
|
|
9252
9476
|
try {
|
|
9253
9477
|
const s = await fsp2.stat(filePath);
|
|
@@ -9264,7 +9488,7 @@ Fleet Run: ${runId}
|
|
|
9264
9488
|
${color.dim("\u25CB")} No subagent transcripts
|
|
9265
9489
|
`);
|
|
9266
9490
|
}
|
|
9267
|
-
const sharedDir =
|
|
9491
|
+
const sharedDir = path25.join(runDir, "shared");
|
|
9268
9492
|
try {
|
|
9269
9493
|
const files = await fsp2.readdir(sharedDir);
|
|
9270
9494
|
deps.renderer.write(`
|
|
@@ -9431,7 +9655,7 @@ function findSessionId(args) {
|
|
|
9431
9655
|
var rewindCmd = async (args, deps) => {
|
|
9432
9656
|
const flags = parseRewindFlags(args);
|
|
9433
9657
|
const wpaths = resolveWstackPaths({ projectRoot: deps.projectRoot });
|
|
9434
|
-
const sessionsDir =
|
|
9658
|
+
const sessionsDir = path25.join(wpaths.globalRoot, "sessions");
|
|
9435
9659
|
const rewind = new DefaultSessionRewinder(sessionsDir);
|
|
9436
9660
|
let sessionId = findSessionId(args);
|
|
9437
9661
|
if (!sessionId) {
|
|
@@ -9563,7 +9787,7 @@ var skillsCmd = async (_args, deps) => {
|
|
|
9563
9787
|
};
|
|
9564
9788
|
var versionCmd = async (_args, deps) => {
|
|
9565
9789
|
deps.renderer.write(
|
|
9566
|
-
`WrongStack ${CLI_VERSION} (apiVersion ${API_VERSION}, node ${process.version}, ${
|
|
9790
|
+
`WrongStack ${CLI_VERSION} (apiVersion ${API_VERSION}, node ${process.version}, ${os7.platform()})
|
|
9567
9791
|
`
|
|
9568
9792
|
);
|
|
9569
9793
|
return 0;
|
|
@@ -9668,7 +9892,7 @@ function resolveBundledSkillsDir() {
|
|
|
9668
9892
|
try {
|
|
9669
9893
|
const req2 = createRequire(import.meta.url);
|
|
9670
9894
|
const corePkg = req2.resolve("@wrongstack/core/package.json");
|
|
9671
|
-
return
|
|
9895
|
+
return path25.join(path25.dirname(corePkg), "skills");
|
|
9672
9896
|
} catch {
|
|
9673
9897
|
return void 0;
|
|
9674
9898
|
}
|
|
@@ -9830,7 +10054,7 @@ async function boot(argv) {
|
|
|
9830
10054
|
if (choices.director) flags["director"] = true;
|
|
9831
10055
|
flags["autonomy"] = choices.autonomy;
|
|
9832
10056
|
printLaunchHints(renderer, flags, {
|
|
9833
|
-
cursorFile:
|
|
10057
|
+
cursorFile: path25.join(wpaths.cacheDir, "hint-cursor")
|
|
9834
10058
|
});
|
|
9835
10059
|
}
|
|
9836
10060
|
return {
|
|
@@ -10861,7 +11085,7 @@ async function execute(deps) {
|
|
|
10861
11085
|
supportsVision,
|
|
10862
11086
|
attachments,
|
|
10863
11087
|
effectiveMaxContext,
|
|
10864
|
-
projectName:
|
|
11088
|
+
projectName: path25.basename(projectRoot) || void 0,
|
|
10865
11089
|
projectRoot,
|
|
10866
11090
|
getAutonomy,
|
|
10867
11091
|
onAutonomy,
|
|
@@ -10885,7 +11109,7 @@ async function execute(deps) {
|
|
|
10885
11109
|
supportsVision,
|
|
10886
11110
|
attachments,
|
|
10887
11111
|
effectiveMaxContext,
|
|
10888
|
-
projectName:
|
|
11112
|
+
projectName: path25.basename(projectRoot) || void 0,
|
|
10889
11113
|
getAutonomy,
|
|
10890
11114
|
onAutonomy,
|
|
10891
11115
|
getEternalEngine,
|
|
@@ -10989,7 +11213,7 @@ var MultiAgentHost = class {
|
|
|
10989
11213
|
doneCondition: { type: "all_tasks_done" },
|
|
10990
11214
|
maxConcurrent: this.opts.maxConcurrent ?? 4
|
|
10991
11215
|
};
|
|
10992
|
-
const defaultScratchpad = this.opts.sharedScratchpadPath || (this.opts.sessionsRoot && this.opts.directorRunId ?
|
|
11216
|
+
const defaultScratchpad = this.opts.sharedScratchpadPath || (this.opts.sessionsRoot && this.opts.directorRunId ? path25.join(this.opts.sessionsRoot, this.opts.directorRunId, "shared") : void 0);
|
|
10993
11217
|
this.director = new Director({
|
|
10994
11218
|
config: coordinatorConfig,
|
|
10995
11219
|
manifestPath: this.opts.manifestPath,
|
|
@@ -11234,7 +11458,7 @@ var MultiAgentHost = class {
|
|
|
11234
11458
|
model: opts?.model,
|
|
11235
11459
|
tools: opts?.tools
|
|
11236
11460
|
};
|
|
11237
|
-
const transcriptPath = this.sessionFactory ?
|
|
11461
|
+
const transcriptPath = this.sessionFactory ? path25.join(this.sessionFactory.dir, `${subagentConfig.name}.jsonl`) : void 0;
|
|
11238
11462
|
const { subagentId, taskId } = await this._spawnAndAssign(subagentConfig);
|
|
11239
11463
|
this.fleetManager?.addPendingTask(taskId, subagentId, description);
|
|
11240
11464
|
this.deps.events.emit("subagent.spawned", {
|
|
@@ -11377,16 +11601,16 @@ var MultiAgentHost = class {
|
|
|
11377
11601
|
if (this.director) return this.director;
|
|
11378
11602
|
this.opts.directorMode = true;
|
|
11379
11603
|
if (this.opts.fleetRoot && !this.opts.manifestPath) {
|
|
11380
|
-
this.opts.manifestPath =
|
|
11604
|
+
this.opts.manifestPath = path25.join(this.opts.fleetRoot, "fleet.json");
|
|
11381
11605
|
}
|
|
11382
11606
|
if (this.opts.fleetRoot && !this.opts.sharedScratchpadPath) {
|
|
11383
|
-
this.opts.sharedScratchpadPath =
|
|
11607
|
+
this.opts.sharedScratchpadPath = path25.join(this.opts.fleetRoot, "shared");
|
|
11384
11608
|
}
|
|
11385
11609
|
if (this.opts.fleetRoot && !this.opts.sessionsRoot) {
|
|
11386
|
-
this.opts.sessionsRoot =
|
|
11610
|
+
this.opts.sessionsRoot = path25.join(this.opts.fleetRoot, "subagents");
|
|
11387
11611
|
}
|
|
11388
11612
|
if (this.opts.fleetRoot && !this.opts.stateCheckpointPath) {
|
|
11389
|
-
this.opts.stateCheckpointPath =
|
|
11613
|
+
this.opts.stateCheckpointPath = path25.join(this.opts.fleetRoot, "director-state.json");
|
|
11390
11614
|
}
|
|
11391
11615
|
await this.ensureDirector();
|
|
11392
11616
|
return this.director ?? null;
|
|
@@ -11552,11 +11776,11 @@ var SessionStats = class {
|
|
|
11552
11776
|
if (e.name === "bash") this.bashCommands++;
|
|
11553
11777
|
else if (e.name === "fetch") this.fetches++;
|
|
11554
11778
|
if (!e.ok) return;
|
|
11555
|
-
const
|
|
11556
|
-
if (e.name === "read" &&
|
|
11557
|
-
else if (e.name === "edit" &&
|
|
11558
|
-
else if (e.name === "write" &&
|
|
11559
|
-
this.writtenPaths.add(
|
|
11779
|
+
const path26 = typeof input?.path === "string" ? input.path : void 0;
|
|
11780
|
+
if (e.name === "read" && path26) this.readPaths.add(path26);
|
|
11781
|
+
else if (e.name === "edit" && path26) this.editedPaths.add(path26);
|
|
11782
|
+
else if (e.name === "write" && path26) {
|
|
11783
|
+
this.writtenPaths.add(path26);
|
|
11560
11784
|
const content = typeof input?.content === "string" ? input.content : "";
|
|
11561
11785
|
this.bytesWritten += Buffer.byteLength(content, "utf8");
|
|
11562
11786
|
}
|
|
@@ -11844,7 +12068,7 @@ function setupMetrics(params) {
|
|
|
11844
12068
|
const dumpMetrics = () => {
|
|
11845
12069
|
if (!metricsSink) return;
|
|
11846
12070
|
try {
|
|
11847
|
-
const out =
|
|
12071
|
+
const out = path25.join(wpaths.projectSessions, "metrics.json");
|
|
11848
12072
|
const snap = metricsSink.snapshot();
|
|
11849
12073
|
writeFileSync(out, JSON.stringify(snap, null, 2));
|
|
11850
12074
|
} catch {
|
|
@@ -12035,12 +12259,12 @@ async function setupSession(params) {
|
|
|
12035
12259
|
}
|
|
12036
12260
|
const sessionRef = { current: session };
|
|
12037
12261
|
await recoveryLock.write(session.id).catch(() => void 0);
|
|
12038
|
-
const attachments = new DefaultAttachmentStore({ spoolDir:
|
|
12039
|
-
const queueStore = new QueueStore({ dir:
|
|
12262
|
+
const attachments = new DefaultAttachmentStore({ spoolDir: path25.join(wpaths.projectSessions, session.id, "attachments") });
|
|
12263
|
+
const queueStore = new QueueStore({ dir: path25.join(wpaths.projectSessions, session.id) });
|
|
12040
12264
|
const ctxSignal = new AbortController().signal;
|
|
12041
12265
|
const context = new Context({ systemPrompt, provider, session, signal: ctxSignal, tokenCounter, cwd, projectRoot, model: config.model });
|
|
12042
12266
|
if (restoredMessages.length > 0) context.state.replaceMessages(restoredMessages);
|
|
12043
|
-
const todosCheckpointPath =
|
|
12267
|
+
const todosCheckpointPath = path25.join(wpaths.projectSessions, `${session.id}.todos.json`);
|
|
12044
12268
|
if (resumeId) {
|
|
12045
12269
|
try {
|
|
12046
12270
|
const restoredTodos = await loadTodosCheckpoint(todosCheckpointPath);
|
|
@@ -12052,13 +12276,13 @@ async function setupSession(params) {
|
|
|
12052
12276
|
}
|
|
12053
12277
|
}
|
|
12054
12278
|
const detachTodosCheckpoint = attachTodosCheckpoint(context.state, todosCheckpointPath, session.id);
|
|
12055
|
-
const planPath =
|
|
12279
|
+
const planPath = path25.join(wpaths.projectSessions, `${session.id}.plan.json`);
|
|
12056
12280
|
context.state.setMeta("plan.path", planPath);
|
|
12057
12281
|
let dirState;
|
|
12058
12282
|
if (resumeId) {
|
|
12059
12283
|
try {
|
|
12060
|
-
const fleetRoot =
|
|
12061
|
-
dirState = await loadDirectorState(
|
|
12284
|
+
const fleetRoot = path25.join(wpaths.projectSessions, session.id);
|
|
12285
|
+
dirState = await loadDirectorState(path25.join(fleetRoot, "director-state.json"));
|
|
12062
12286
|
if (dirState) {
|
|
12063
12287
|
const tCounts = {};
|
|
12064
12288
|
for (const t of dirState.tasks) tCounts[t.status] = (tCounts[t.status] ?? 0) + 1;
|
|
@@ -12085,7 +12309,7 @@ function resolveBundledSkillsDir2() {
|
|
|
12085
12309
|
try {
|
|
12086
12310
|
const req2 = createRequire(import.meta.url);
|
|
12087
12311
|
const corePkg = req2.resolve("@wrongstack/core/package.json");
|
|
12088
|
-
return
|
|
12312
|
+
return path25.join(path25.dirname(corePkg), "skills");
|
|
12089
12313
|
} catch {
|
|
12090
12314
|
return void 0;
|
|
12091
12315
|
}
|
|
@@ -12185,7 +12409,7 @@ async function main(argv) {
|
|
|
12185
12409
|
modeId,
|
|
12186
12410
|
modePrompt,
|
|
12187
12411
|
modelCapabilities,
|
|
12188
|
-
planPath: () => sessionRef.current ?
|
|
12412
|
+
planPath: () => sessionRef.current ? path25.join(wpaths.projectSessions, `${sessionRef.current.id}.plan.json`) : void 0,
|
|
12189
12413
|
contributors: [
|
|
12190
12414
|
// Injects the ETERNAL AUTONOMY block when the user has activated
|
|
12191
12415
|
// `/autonomy eternal`. Without this, the per-iteration directive
|
|
@@ -12389,12 +12613,12 @@ async function main(argv) {
|
|
|
12389
12613
|
}
|
|
12390
12614
|
}
|
|
12391
12615
|
};
|
|
12392
|
-
const fleetRoot = directorMode ?
|
|
12393
|
-
const manifestPath = directorMode ? typeof process.env["WRONGSTACK_FLEET_MANIFEST"] === "string" ? process.env["WRONGSTACK_FLEET_MANIFEST"] :
|
|
12394
|
-
const sharedScratchpadPath = directorMode ?
|
|
12395
|
-
const subagentSessionsRoot = directorMode ?
|
|
12396
|
-
const stateCheckpointPath = directorMode ?
|
|
12397
|
-
const fleetRootForPromotion =
|
|
12616
|
+
const fleetRoot = directorMode ? path25.join(wpaths.projectSessions, session.id) : void 0;
|
|
12617
|
+
const manifestPath = directorMode ? typeof process.env["WRONGSTACK_FLEET_MANIFEST"] === "string" ? process.env["WRONGSTACK_FLEET_MANIFEST"] : path25.join(fleetRoot, "fleet.json") : void 0;
|
|
12618
|
+
const sharedScratchpadPath = directorMode ? path25.join(fleetRoot, "shared") : void 0;
|
|
12619
|
+
const subagentSessionsRoot = directorMode ? path25.join(fleetRoot, "subagents") : void 0;
|
|
12620
|
+
const stateCheckpointPath = directorMode ? path25.join(fleetRoot, "director-state.json") : void 0;
|
|
12621
|
+
const fleetRootForPromotion = path25.join(wpaths.projectSessions, session.id);
|
|
12398
12622
|
const multiAgentHost = new MultiAgentHost(
|
|
12399
12623
|
{
|
|
12400
12624
|
container,
|
|
@@ -12717,7 +12941,7 @@ async function main(argv) {
|
|
|
12717
12941
|
return director.spawn(cfg);
|
|
12718
12942
|
},
|
|
12719
12943
|
onFleetLog: async (subagentId, mode) => {
|
|
12720
|
-
const subagentsRoot =
|
|
12944
|
+
const subagentsRoot = path25.join(fleetRootForPromotion, "subagents");
|
|
12721
12945
|
let runDirs;
|
|
12722
12946
|
try {
|
|
12723
12947
|
runDirs = await fsp2.readdir(subagentsRoot);
|
|
@@ -12726,7 +12950,7 @@ async function main(argv) {
|
|
|
12726
12950
|
}
|
|
12727
12951
|
const found = [];
|
|
12728
12952
|
for (const runId of runDirs) {
|
|
12729
|
-
const runDir =
|
|
12953
|
+
const runDir = path25.join(subagentsRoot, runId);
|
|
12730
12954
|
let files;
|
|
12731
12955
|
try {
|
|
12732
12956
|
files = await fsp2.readdir(runDir);
|
|
@@ -12735,7 +12959,7 @@ async function main(argv) {
|
|
|
12735
12959
|
}
|
|
12736
12960
|
for (const f of files) {
|
|
12737
12961
|
if (!f.endsWith(".jsonl")) continue;
|
|
12738
|
-
const full =
|
|
12962
|
+
const full = path25.join(runDir, f);
|
|
12739
12963
|
try {
|
|
12740
12964
|
const stat3 = await fsp2.stat(full);
|
|
12741
12965
|
found.push({
|
|
@@ -12832,7 +13056,7 @@ async function main(argv) {
|
|
|
12832
13056
|
}
|
|
12833
13057
|
const dir = await multiAgentHost.ensureDirector();
|
|
12834
13058
|
if (!dir) return "Director is not available.";
|
|
12835
|
-
const dirStatePath =
|
|
13059
|
+
const dirStatePath = path25.join(fleetRootForPromotion, "director-state.json");
|
|
12836
13060
|
const prior = await loadDirectorState(dirStatePath);
|
|
12837
13061
|
if (!prior) {
|
|
12838
13062
|
return "No prior director-state.json found \u2014 nothing to retry.";
|
|
@@ -12903,9 +13127,9 @@ async function main(argv) {
|
|
|
12903
13127
|
for (const tool of director2.tools(FLEET_ROSTER)) {
|
|
12904
13128
|
toolRegistry.register(tool);
|
|
12905
13129
|
}
|
|
12906
|
-
const mp =
|
|
12907
|
-
const sp =
|
|
12908
|
-
const ss =
|
|
13130
|
+
const mp = path25.join(fleetRootForPromotion, "fleet.json");
|
|
13131
|
+
const sp = path25.join(fleetRootForPromotion, "shared");
|
|
13132
|
+
const ss = path25.join(fleetRootForPromotion, "subagents");
|
|
12909
13133
|
const lines = [
|
|
12910
13134
|
`${color.green("\u2713")} Promoted to director mode.`,
|
|
12911
13135
|
` Roster: ${Object.keys(FLEET_ROSTER).join(", ")}`,
|