@wrongstack/cli 0.63.4 → 0.66.13
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 +229 -79
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
package/dist/index.js
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
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, DefaultSecretScrubber, atomicWrite, DefaultPathResolver, TOKENS, mergeCustomModelDefs, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, HookRegistry, HookRunner, 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, resolveContextWindowPolicy, 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, ProviderError, makeAgentSubagentRunner, NULL_FLEET_BUS, buildChildEnv, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, AGENTS_BY_PHASE, dispatchAgent, formatTodosList, SessionRecovery, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, pendingBtwCount, setBtwNote, MATRIX_PHASE_KEYS, AGENT_CATALOG, matrixKeyKind, onResize, ERROR_CODES, decryptConfigSecrets as decryptConfigSecrets$1, encryptConfigSecrets as encryptConfigSecrets$1, InputBuilder, FsError } from '@wrongstack/core';
|
|
5
|
+
import { color, writeErr, DefaultTaskStore, TaskTracker, renderProgress, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, renderTaskGraph, SpecVersioning, DefaultSecretScrubber, atomicWrite, DefaultPathResolver, TOKENS, mergeCustomModelDefs, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, resolveSessionLoggingConfig, createSessionEventBridge, HookRegistry, HookRunner, 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, resolveContextWindowPolicy, resolveAuditLevel, 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, ProviderError, makeAgentSubagentRunner, NULL_FLEET_BUS, buildChildEnv, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, AGENTS_BY_PHASE, dispatchAgent, formatTodosList, SessionRecovery, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, pendingBtwCount, setBtwNote, MATRIX_PHASE_KEYS, AGENT_CATALOG, matrixKeyKind, onResize, ERROR_CODES, decryptConfigSecrets as decryptConfigSecrets$1, encryptConfigSecrets as encryptConfigSecrets$1, InputBuilder, FsError } from '@wrongstack/core';
|
|
6
6
|
import { createRequire } from 'module';
|
|
7
7
|
import * as os2 from 'os';
|
|
8
8
|
import os2__default from 'os';
|
|
9
9
|
import * as crypto2 from 'crypto';
|
|
10
10
|
import { randomUUID } from 'crypto';
|
|
11
|
+
import { findFreePort, createHttpServer, openBrowser, registerInstance, unregisterInstance } from '@wrongstack/webui/server';
|
|
11
12
|
import { DefaultSecretVault, decryptConfigSecrets, encryptConfigSecrets, isSecretField } from '@wrongstack/core/security';
|
|
12
13
|
import { WebSocketServer, WebSocket } from 'ws';
|
|
13
14
|
import { MCPRegistry, MCPServer, serveHttp, serveStdio } from '@wrongstack/mcp';
|
|
@@ -1694,13 +1695,63 @@ __export(webui_server_exports, {
|
|
|
1694
1695
|
runWebUI: () => runWebUI
|
|
1695
1696
|
});
|
|
1696
1697
|
async function runWebUI(opts) {
|
|
1697
|
-
const
|
|
1698
|
+
const host = "127.0.0.1";
|
|
1699
|
+
const requestedWsPort = opts.port ?? 3457;
|
|
1700
|
+
const requestedHttpPort = opts.httpPort ?? 3456;
|
|
1701
|
+
const strictPort = process.env["WEBUI_STRICT_PORT"] === "1" || process.env["WEBUI_STRICT_PORT"] === "true";
|
|
1702
|
+
let httpPort = requestedHttpPort;
|
|
1703
|
+
let wsPort = requestedWsPort;
|
|
1704
|
+
if (!strictPort) {
|
|
1705
|
+
httpPort = await findFreePort(host, requestedHttpPort);
|
|
1706
|
+
wsPort = await findFreePort(host, requestedWsPort, { exclude: /* @__PURE__ */ new Set([httpPort]) });
|
|
1707
|
+
}
|
|
1708
|
+
const port = wsPort;
|
|
1709
|
+
const rateLimitMax = Number.parseInt(process.env["WEBUI_RATE_LIMIT"] ?? "0", 10);
|
|
1698
1710
|
const clients = /* @__PURE__ */ new Map();
|
|
1711
|
+
const pendingConfirms = /* @__PURE__ */ new Map();
|
|
1699
1712
|
const secretScrubber = new DefaultSecretScrubber();
|
|
1700
1713
|
let abortController = null;
|
|
1701
1714
|
const authToken = crypto2.randomBytes(16).toString("hex");
|
|
1702
|
-
const wss = new WebSocketServer({ port, host
|
|
1703
|
-
console.log(`[WebUI] WebSocket server starting on ws
|
|
1715
|
+
const wss = new WebSocketServer({ port, host, maxPayload: 1 * 1024 * 1024 });
|
|
1716
|
+
console.log(`[WebUI] WebSocket server starting on ws://${host}:${port}`);
|
|
1717
|
+
let httpServer = null;
|
|
1718
|
+
try {
|
|
1719
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
1720
|
+
const serverEntry = requireFromHere.resolve("@wrongstack/webui/server");
|
|
1721
|
+
const distDir = path8.resolve(path8.dirname(serverEntry), "..");
|
|
1722
|
+
httpServer = createHttpServer({ host, distDir, wsPort });
|
|
1723
|
+
const openUrl = `http://${host}:${httpPort}`;
|
|
1724
|
+
httpServer.listen(httpPort, host, () => {
|
|
1725
|
+
console.log(
|
|
1726
|
+
`
|
|
1727
|
+
\u25B8 WebUI ready \u2014 open \x1B[1m${openUrl}\x1B[0m in your browser
|
|
1728
|
+
(same agent as this terminal \xB7 ws:${wsPort})
|
|
1729
|
+
`
|
|
1730
|
+
);
|
|
1731
|
+
if (opts.open) openBrowser(openUrl);
|
|
1732
|
+
});
|
|
1733
|
+
} catch (err) {
|
|
1734
|
+
console.warn(
|
|
1735
|
+
`[WebUI] Frontend not served (run \`pnpm --filter @wrongstack/webui build\`): ${err instanceof Error ? err.message : String(err)}. WS bridge still active on ws://${host}:${wsPort}.`
|
|
1736
|
+
);
|
|
1737
|
+
}
|
|
1738
|
+
const registryBaseDir = opts.globalConfigPath ? path8.dirname(opts.globalConfigPath) : void 0;
|
|
1739
|
+
if (opts.projectRoot) {
|
|
1740
|
+
void registerInstance(
|
|
1741
|
+
{
|
|
1742
|
+
pid: process.pid,
|
|
1743
|
+
httpPort,
|
|
1744
|
+
wsPort,
|
|
1745
|
+
host,
|
|
1746
|
+
projectRoot: opts.projectRoot,
|
|
1747
|
+
projectName: path8.basename(opts.projectRoot) || opts.projectRoot,
|
|
1748
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1749
|
+
url: `http://${host}:${httpPort}`
|
|
1750
|
+
},
|
|
1751
|
+
registryBaseDir
|
|
1752
|
+
).catch(() => {
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1704
1755
|
const eventUnsubscribers = [];
|
|
1705
1756
|
function setupEvents() {
|
|
1706
1757
|
for (const unsub of eventUnsubscribers) unsub();
|
|
@@ -1794,6 +1845,88 @@ async function runWebUI(opts) {
|
|
|
1794
1845
|
});
|
|
1795
1846
|
})
|
|
1796
1847
|
);
|
|
1848
|
+
eventUnsubscribers.push(
|
|
1849
|
+
opts.events.on("tool.confirm_needed", (e) => {
|
|
1850
|
+
const id = e.toolUseId ?? `confirm_${Date.now()}`;
|
|
1851
|
+
pendingConfirms.set(id, e.resolve);
|
|
1852
|
+
broadcast({
|
|
1853
|
+
type: "tool.confirm_needed",
|
|
1854
|
+
payload: {
|
|
1855
|
+
id,
|
|
1856
|
+
toolName: e.tool?.name ?? "unknown",
|
|
1857
|
+
input: secretScrubber.scrubObject(e.input),
|
|
1858
|
+
suggestedPattern: e.suggestedPattern
|
|
1859
|
+
}
|
|
1860
|
+
});
|
|
1861
|
+
})
|
|
1862
|
+
);
|
|
1863
|
+
const forwardSubagent = (kind, payload) => broadcast({ type: "subagent.event", payload: { kind, ...payload } });
|
|
1864
|
+
eventUnsubscribers.push(
|
|
1865
|
+
opts.events.on(
|
|
1866
|
+
"subagent.spawned",
|
|
1867
|
+
(e) => forwardSubagent("spawned", {
|
|
1868
|
+
subagentId: e.subagentId,
|
|
1869
|
+
taskId: e.taskId,
|
|
1870
|
+
name: e.name,
|
|
1871
|
+
provider: e.provider,
|
|
1872
|
+
model: e.model,
|
|
1873
|
+
description: e.description
|
|
1874
|
+
})
|
|
1875
|
+
),
|
|
1876
|
+
opts.events.on(
|
|
1877
|
+
"subagent.task_started",
|
|
1878
|
+
(e) => forwardSubagent("task_started", {
|
|
1879
|
+
subagentId: e.subagentId,
|
|
1880
|
+
taskId: e.taskId,
|
|
1881
|
+
description: e.description
|
|
1882
|
+
})
|
|
1883
|
+
),
|
|
1884
|
+
opts.events.on(
|
|
1885
|
+
"subagent.tool_executed",
|
|
1886
|
+
(e) => forwardSubagent("tool_executed", {
|
|
1887
|
+
subagentId: e.subagentId,
|
|
1888
|
+
toolName: e.name,
|
|
1889
|
+
durationMs: e.durationMs,
|
|
1890
|
+
ok: e.ok
|
|
1891
|
+
})
|
|
1892
|
+
),
|
|
1893
|
+
opts.events.on(
|
|
1894
|
+
"subagent.iteration_summary",
|
|
1895
|
+
(e) => forwardSubagent("iteration_summary", {
|
|
1896
|
+
subagentId: e.subagentId,
|
|
1897
|
+
iteration: e.iteration,
|
|
1898
|
+
toolCalls: e.toolCalls,
|
|
1899
|
+
costUsd: e.costUsd,
|
|
1900
|
+
currentTool: e.currentTool
|
|
1901
|
+
})
|
|
1902
|
+
),
|
|
1903
|
+
opts.events.on(
|
|
1904
|
+
"subagent.budget_extended",
|
|
1905
|
+
(e) => forwardSubagent("budget_extended", {
|
|
1906
|
+
subagentId: e.subagentId,
|
|
1907
|
+
totalExtensions: e.totalExtensions
|
|
1908
|
+
})
|
|
1909
|
+
),
|
|
1910
|
+
opts.events.on(
|
|
1911
|
+
"subagent.ctx_pct",
|
|
1912
|
+
(e) => forwardSubagent("ctx_pct", {
|
|
1913
|
+
subagentId: e.subagentId,
|
|
1914
|
+
load: e.load,
|
|
1915
|
+
tokens: e.tokens,
|
|
1916
|
+
maxContext: e.maxContext
|
|
1917
|
+
})
|
|
1918
|
+
),
|
|
1919
|
+
opts.events.on(
|
|
1920
|
+
"subagent.task_completed",
|
|
1921
|
+
(e) => forwardSubagent("task_completed", {
|
|
1922
|
+
subagentId: e.subagentId,
|
|
1923
|
+
status: e.status,
|
|
1924
|
+
iterations: e.iterations,
|
|
1925
|
+
toolCalls: e.toolCalls,
|
|
1926
|
+
error: e.error ? { kind: e.error.kind, message: e.error.message } : void 0
|
|
1927
|
+
})
|
|
1928
|
+
)
|
|
1929
|
+
);
|
|
1797
1930
|
if (opts.subscribeEternalIteration) {
|
|
1798
1931
|
eventUnsubscribers.push(
|
|
1799
1932
|
opts.subscribeEternalIteration((entry) => {
|
|
@@ -1814,10 +1947,11 @@ async function runWebUI(opts) {
|
|
|
1814
1947
|
);
|
|
1815
1948
|
}
|
|
1816
1949
|
}
|
|
1817
|
-
return new Promise((
|
|
1950
|
+
return new Promise((resolve4) => {
|
|
1818
1951
|
wss.on("listening", () => {
|
|
1819
|
-
console.log(`[WebUI] WebSocket server running on ws
|
|
1952
|
+
console.log(`[WebUI] WebSocket server running on ws://${host}:${port}`);
|
|
1820
1953
|
setupEvents();
|
|
1954
|
+
opts.onListening?.({ httpPort, wsPort, host });
|
|
1821
1955
|
});
|
|
1822
1956
|
wss.on("connection", (ws, req2) => {
|
|
1823
1957
|
const isLoopback = (hostname) => hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]";
|
|
@@ -1870,17 +2004,19 @@ async function runWebUI(opts) {
|
|
|
1870
2004
|
let msgCount = 0;
|
|
1871
2005
|
let windowResetAt = Date.now() + 6e4;
|
|
1872
2006
|
ws.on("message", async (data) => {
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
2007
|
+
if (rateLimitMax > 0) {
|
|
2008
|
+
const now = Date.now();
|
|
2009
|
+
if (now > windowResetAt) {
|
|
2010
|
+
msgCount = 0;
|
|
2011
|
+
windowResetAt = now + 6e4;
|
|
2012
|
+
}
|
|
2013
|
+
if (++msgCount > rateLimitMax) {
|
|
2014
|
+
send(ws, {
|
|
2015
|
+
type: "error",
|
|
2016
|
+
payload: { phase: "rate_limit", message: "Too many messages. Please wait." }
|
|
2017
|
+
});
|
|
2018
|
+
return;
|
|
2019
|
+
}
|
|
1884
2020
|
}
|
|
1885
2021
|
try {
|
|
1886
2022
|
const msg = JSON.parse(data.toString());
|
|
@@ -1892,6 +2028,12 @@ async function runWebUI(opts) {
|
|
|
1892
2028
|
ws.on("close", () => {
|
|
1893
2029
|
console.log("[WebUI] Client disconnected");
|
|
1894
2030
|
clients.delete(ws);
|
|
2031
|
+
if (clients.size === 0 && pendingConfirms.size > 0) {
|
|
2032
|
+
for (const [id, resolve5] of pendingConfirms) {
|
|
2033
|
+
resolve5("no");
|
|
2034
|
+
pendingConfirms.delete(id);
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
1895
2037
|
});
|
|
1896
2038
|
send(ws, {
|
|
1897
2039
|
type: "session.start",
|
|
@@ -1913,9 +2055,12 @@ async function runWebUI(opts) {
|
|
|
1913
2055
|
ws.close();
|
|
1914
2056
|
}
|
|
1915
2057
|
clients.clear();
|
|
2058
|
+
void unregisterInstance(process.pid, registryBaseDir).catch(() => {
|
|
2059
|
+
});
|
|
2060
|
+
httpServer?.close();
|
|
1916
2061
|
wss.close(() => {
|
|
1917
2062
|
console.log("[WebUI] Server stopped");
|
|
1918
|
-
|
|
2063
|
+
resolve4();
|
|
1919
2064
|
});
|
|
1920
2065
|
}
|
|
1921
2066
|
process.on("SIGINT", shutdown);
|
|
@@ -1940,6 +2085,15 @@ async function runWebUI(opts) {
|
|
|
1940
2085
|
case "ping":
|
|
1941
2086
|
send(ws, { type: "pong", payload: {} });
|
|
1942
2087
|
break;
|
|
2088
|
+
case "tool.confirm_result": {
|
|
2089
|
+
const { id, decision } = msg.payload;
|
|
2090
|
+
const resolve4 = pendingConfirms.get(id);
|
|
2091
|
+
if (resolve4) {
|
|
2092
|
+
pendingConfirms.delete(id);
|
|
2093
|
+
resolve4(decision);
|
|
2094
|
+
}
|
|
2095
|
+
break;
|
|
2096
|
+
}
|
|
1943
2097
|
case "providers.list":
|
|
1944
2098
|
await handleProvidersList(ws);
|
|
1945
2099
|
break;
|
|
@@ -2396,6 +2550,7 @@ function positiveNumber(value) {
|
|
|
2396
2550
|
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
2397
2551
|
"yolo",
|
|
2398
2552
|
"yolo-destructive",
|
|
2553
|
+
"confirm-destructive",
|
|
2399
2554
|
"force-all-yolo",
|
|
2400
2555
|
"verbose",
|
|
2401
2556
|
"trace",
|
|
@@ -2414,6 +2569,7 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
2414
2569
|
"prompt",
|
|
2415
2570
|
"metrics",
|
|
2416
2571
|
"webui",
|
|
2572
|
+
"open",
|
|
2417
2573
|
"no-check",
|
|
2418
2574
|
"no-models-refresh",
|
|
2419
2575
|
"director",
|
|
@@ -6529,13 +6685,13 @@ function buildYoloCommand(opts) {
|
|
|
6529
6685
|
description: "Toggle or query YOLO (auto-approve) mode.",
|
|
6530
6686
|
help: [
|
|
6531
6687
|
"Usage:",
|
|
6532
|
-
" /yolo
|
|
6533
|
-
" /yolo on
|
|
6534
|
-
" /yolo off
|
|
6535
|
-
" /yolo
|
|
6688
|
+
" /yolo Show current YOLO status",
|
|
6689
|
+
" /yolo on Enable YOLO mode (auto-approve all tool calls)",
|
|
6690
|
+
" /yolo off Disable YOLO mode (restore permission prompts)",
|
|
6691
|
+
" /yolo destructive Toggle destructive confirmation gate (YOLO mode only)",
|
|
6536
6692
|
"",
|
|
6537
|
-
"YOLO mode auto-approves
|
|
6538
|
-
"
|
|
6693
|
+
"YOLO mode auto-approves everything, including destructive calls.",
|
|
6694
|
+
"Use /yolo destructive to re-enable confirmation for risky operations."
|
|
6539
6695
|
].join("\n"),
|
|
6540
6696
|
async run(args) {
|
|
6541
6697
|
const arg = args.trim().toLowerCase();
|
|
@@ -6717,10 +6873,10 @@ async function runProjectCheck(opts) {
|
|
|
6717
6873
|
if (answer2 === "y" || answer2 === "yes") {
|
|
6718
6874
|
try {
|
|
6719
6875
|
const { spawn: spawn3 } = await import('child_process');
|
|
6720
|
-
await new Promise((
|
|
6876
|
+
await new Promise((resolve4, reject) => {
|
|
6721
6877
|
const child = spawn3("git", ["init"], { cwd: projectRoot });
|
|
6722
6878
|
child.on("error", reject);
|
|
6723
|
-
child.on("close", (code) => code === 0 ?
|
|
6879
|
+
child.on("close", (code) => code === 0 ? resolve4() : reject(new Error(`git init failed with ${code}`)));
|
|
6724
6880
|
});
|
|
6725
6881
|
renderer.write(` ${color.green("\u2713")} Git repository initialized
|
|
6726
6882
|
`);
|
|
@@ -6864,7 +7020,7 @@ var ReadlineInputReader = class {
|
|
|
6864
7020
|
async readLine(prompt) {
|
|
6865
7021
|
if (this.history.length === 0) await this.loadHistory();
|
|
6866
7022
|
while (this.pending) {
|
|
6867
|
-
await new Promise((
|
|
7023
|
+
await new Promise((resolve4) => setTimeout(resolve4, 50));
|
|
6868
7024
|
}
|
|
6869
7025
|
this.pending = true;
|
|
6870
7026
|
try {
|
|
@@ -6874,15 +7030,15 @@ var ReadlineInputReader = class {
|
|
|
6874
7030
|
this.rl = void 0;
|
|
6875
7031
|
}
|
|
6876
7032
|
const fresh = this.ensure();
|
|
6877
|
-
return new Promise((
|
|
7033
|
+
return new Promise((resolve4) => {
|
|
6878
7034
|
fresh.question(prompt ?? "> ", (line) => {
|
|
6879
7035
|
if (line.trim()) {
|
|
6880
7036
|
this.history.push(line);
|
|
6881
7037
|
void this.saveHistory();
|
|
6882
7038
|
}
|
|
6883
|
-
|
|
7039
|
+
resolve4(line);
|
|
6884
7040
|
});
|
|
6885
|
-
fresh.once("close", () =>
|
|
7041
|
+
fresh.once("close", () => resolve4(""));
|
|
6886
7042
|
}).then((result) => {
|
|
6887
7043
|
this.rl?.close();
|
|
6888
7044
|
this.rl = void 0;
|
|
@@ -6894,7 +7050,7 @@ var ReadlineInputReader = class {
|
|
|
6894
7050
|
}
|
|
6895
7051
|
async readKey(prompt, options) {
|
|
6896
7052
|
writeOut(prompt);
|
|
6897
|
-
return new Promise((
|
|
7053
|
+
return new Promise((resolve4) => {
|
|
6898
7054
|
const stdin = process.stdin;
|
|
6899
7055
|
const wasRaw = stdin.isRaw;
|
|
6900
7056
|
const wasPaused = stdin.isPaused();
|
|
@@ -6905,7 +7061,7 @@ var ReadlineInputReader = class {
|
|
|
6905
7061
|
if (key === "") {
|
|
6906
7062
|
cleanup();
|
|
6907
7063
|
writeOut("\n");
|
|
6908
|
-
|
|
7064
|
+
resolve4("");
|
|
6909
7065
|
return;
|
|
6910
7066
|
}
|
|
6911
7067
|
const opt = options.find(
|
|
@@ -6915,12 +7071,12 @@ var ReadlineInputReader = class {
|
|
|
6915
7071
|
cleanup();
|
|
6916
7072
|
writeOut(`${opt.key}
|
|
6917
7073
|
`);
|
|
6918
|
-
|
|
7074
|
+
resolve4(opt.value);
|
|
6919
7075
|
}
|
|
6920
7076
|
};
|
|
6921
7077
|
const onClose = () => {
|
|
6922
7078
|
cleanup();
|
|
6923
|
-
|
|
7079
|
+
resolve4("");
|
|
6924
7080
|
};
|
|
6925
7081
|
const cleanup = () => {
|
|
6926
7082
|
stdin.off("data", onData);
|
|
@@ -6948,7 +7104,7 @@ var ReadlineInputReader = class {
|
|
|
6948
7104
|
this.rl?.close();
|
|
6949
7105
|
this.rl = void 0;
|
|
6950
7106
|
writeOut(prompt);
|
|
6951
|
-
return new Promise((
|
|
7107
|
+
return new Promise((resolve4) => {
|
|
6952
7108
|
let buf = "";
|
|
6953
7109
|
const wasRaw = stdin.isRaw;
|
|
6954
7110
|
setRawMode(stdin, true);
|
|
@@ -6966,7 +7122,7 @@ var ReadlineInputReader = class {
|
|
|
6966
7122
|
cleanup();
|
|
6967
7123
|
writeOut(` ${dim(`[${buf.length} chars]`)}
|
|
6968
7124
|
`);
|
|
6969
|
-
|
|
7125
|
+
resolve4(buf);
|
|
6970
7126
|
return;
|
|
6971
7127
|
}
|
|
6972
7128
|
if (ch === "") {
|
|
@@ -8870,8 +9026,9 @@ var updateCmd = async (args, deps) => {
|
|
|
8870
9026
|
deps.renderer.write(`Updating wrongstack from v${info.current} to v${info.latest}...
|
|
8871
9027
|
`);
|
|
8872
9028
|
try {
|
|
8873
|
-
const result = await new Promise((
|
|
8874
|
-
const
|
|
9029
|
+
const result = await new Promise((resolve4, reject) => {
|
|
9030
|
+
const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
9031
|
+
const child = spawn(npmCommand, ["install", "-g", "wrongstack@latest"], {
|
|
8875
9032
|
cwd,
|
|
8876
9033
|
stdio: "pipe"
|
|
8877
9034
|
});
|
|
@@ -8880,7 +9037,7 @@ var updateCmd = async (args, deps) => {
|
|
|
8880
9037
|
_stderr += d;
|
|
8881
9038
|
});
|
|
8882
9039
|
child.on("error", reject);
|
|
8883
|
-
child.on("close", (code) =>
|
|
9040
|
+
child.on("close", (code) => resolve4({ code: code ?? 0 }));
|
|
8884
9041
|
});
|
|
8885
9042
|
if (result.code === 0) {
|
|
8886
9043
|
deps.renderer.write(`
|
|
@@ -9337,8 +9494,8 @@ async function serveMcpStdio(deps) {
|
|
|
9337
9494
|
log(
|
|
9338
9495
|
`wrongstack MCP server ready at ${handle2.url} \u2014 exposing ${allowed.length} tool(s) (${mode})${token ? " [token auth]" : ""}.`
|
|
9339
9496
|
);
|
|
9340
|
-
await new Promise((
|
|
9341
|
-
const stop = () =>
|
|
9497
|
+
await new Promise((resolve4) => {
|
|
9498
|
+
const stop = () => resolve4();
|
|
9342
9499
|
process.once("SIGINT", stop);
|
|
9343
9500
|
process.once("SIGTERM", stop);
|
|
9344
9501
|
});
|
|
@@ -10700,10 +10857,13 @@ var helpCmd = async (_args, deps) => {
|
|
|
10700
10857
|
" wstack version Print version",
|
|
10701
10858
|
"",
|
|
10702
10859
|
color.bold("Common flags"),
|
|
10703
|
-
" --yolo Auto-approve
|
|
10704
|
-
" --
|
|
10705
|
-
" --
|
|
10860
|
+
" --yolo Auto-approve all tool calls (including destructive)",
|
|
10861
|
+
" --confirm-destructive In YOLO mode, still prompt for destructive operations",
|
|
10862
|
+
" --yolo-destructive Deprecated \u2014 YOLO now auto-approves everything by default",
|
|
10706
10863
|
" --tui / --no-tui Force or disable TUI mode",
|
|
10864
|
+
" --webui [--port <n>] [--open] Serve the browser UI + WS bridge (prints a URL,",
|
|
10865
|
+
" --open pops the browser; shares this terminal's",
|
|
10866
|
+
" agent; auto-picks free ports)",
|
|
10707
10867
|
' --eternal "<mission>" Start an eternal-autonomy loop',
|
|
10708
10868
|
" --no-hints Hide launch hints"
|
|
10709
10869
|
];
|
|
@@ -10932,6 +11092,10 @@ async function boot(argv) {
|
|
|
10932
11092
|
return 2;
|
|
10933
11093
|
}
|
|
10934
11094
|
}
|
|
11095
|
+
if (flags["webui"]) {
|
|
11096
|
+
flags["tui"] = false;
|
|
11097
|
+
flags["no-tui"] = true;
|
|
11098
|
+
}
|
|
10935
11099
|
if (isInteractiveTTY) {
|
|
10936
11100
|
let modePinned;
|
|
10937
11101
|
if (flags["no-tui"]) modePinned = "repl";
|
|
@@ -11370,7 +11534,7 @@ async function runRepl(opts) {
|
|
|
11370
11534
|
`[eternal] ${err instanceof Error ? err.message : String(err)}`
|
|
11371
11535
|
);
|
|
11372
11536
|
}
|
|
11373
|
-
await new Promise((
|
|
11537
|
+
await new Promise((resolve4) => setTimeout(resolve4, 250));
|
|
11374
11538
|
continue;
|
|
11375
11539
|
}
|
|
11376
11540
|
} else if (opts.getAutonomy?.() === "eternal-parallel") {
|
|
@@ -11416,7 +11580,7 @@ async function runRepl(opts) {
|
|
|
11416
11580
|
`[parallel] ${err instanceof Error ? err.message : String(err)}`
|
|
11417
11581
|
);
|
|
11418
11582
|
}
|
|
11419
|
-
await new Promise((
|
|
11583
|
+
await new Promise((resolve4) => setTimeout(resolve4, 250));
|
|
11420
11584
|
continue;
|
|
11421
11585
|
}
|
|
11422
11586
|
}
|
|
@@ -12066,7 +12230,7 @@ async function execute(deps) {
|
|
|
12066
12230
|
) + "\n"
|
|
12067
12231
|
);
|
|
12068
12232
|
}
|
|
12069
|
-
} else if (flags.tui && !flags["no-tui"]) {
|
|
12233
|
+
} else if (flags.tui && !flags["no-tui"] && !flags.webui) {
|
|
12070
12234
|
agent.disableInteractiveConfirmation();
|
|
12071
12235
|
const { runTui } = await import('@wrongstack/tui');
|
|
12072
12236
|
renderer.setSilent(true);
|
|
@@ -12255,12 +12419,15 @@ async function execute(deps) {
|
|
|
12255
12419
|
renderer.setSilent(false);
|
|
12256
12420
|
}
|
|
12257
12421
|
} else if (flags.webui) {
|
|
12422
|
+
agent.disableInteractiveConfirmation();
|
|
12258
12423
|
const { runWebUI: runWebUI2 } = await Promise.resolve().then(() => (init_webui_server(), webui_server_exports));
|
|
12259
12424
|
const webuiPromise = runWebUI2({
|
|
12260
12425
|
agent,
|
|
12261
12426
|
events,
|
|
12262
12427
|
session,
|
|
12263
12428
|
port: Number.parseInt(String(flags.port ?? "3457"), 10),
|
|
12429
|
+
projectRoot,
|
|
12430
|
+
open: !!flags.open,
|
|
12264
12431
|
modelsRegistry,
|
|
12265
12432
|
globalConfigPath: wpaths.globalConfig,
|
|
12266
12433
|
subscribeEternalIteration
|
|
@@ -13191,7 +13358,7 @@ function samplePaths(set) {
|
|
|
13191
13358
|
}
|
|
13192
13359
|
var WORKTREE_PHASE_CONCURRENCY = 4;
|
|
13193
13360
|
function gitText(args, cwd) {
|
|
13194
|
-
return new Promise((
|
|
13361
|
+
return new Promise((resolve4) => {
|
|
13195
13362
|
let out = "";
|
|
13196
13363
|
const child = spawn("git", args, {
|
|
13197
13364
|
cwd,
|
|
@@ -13204,8 +13371,8 @@ function gitText(args, cwd) {
|
|
|
13204
13371
|
child.stderr?.on("data", (c) => {
|
|
13205
13372
|
out += c.toString();
|
|
13206
13373
|
});
|
|
13207
|
-
child.on("error", () =>
|
|
13208
|
-
child.on("close", (code) =>
|
|
13374
|
+
child.on("error", () => resolve4({ code: 1, out }));
|
|
13375
|
+
child.on("close", (code) => resolve4({ code: code ?? 1, out: out.trim() }));
|
|
13209
13376
|
});
|
|
13210
13377
|
}
|
|
13211
13378
|
async function isGitRepo(cwd) {
|
|
@@ -13213,7 +13380,7 @@ async function isGitRepo(cwd) {
|
|
|
13213
13380
|
return code === 0 && out.trim() === "true";
|
|
13214
13381
|
}
|
|
13215
13382
|
function runCmd(cmd, args, cwd, shell = false) {
|
|
13216
|
-
return new Promise((
|
|
13383
|
+
return new Promise((resolve4) => {
|
|
13217
13384
|
let out = "";
|
|
13218
13385
|
const child = spawn(cmd, args, {
|
|
13219
13386
|
cwd,
|
|
@@ -13227,8 +13394,8 @@ function runCmd(cmd, args, cwd, shell = false) {
|
|
|
13227
13394
|
child.stderr?.on("data", (c) => {
|
|
13228
13395
|
out += c.toString();
|
|
13229
13396
|
});
|
|
13230
|
-
child.on("error", (e) =>
|
|
13231
|
-
child.on("close", (code) =>
|
|
13397
|
+
child.on("error", (e) => resolve4({ code: 1, out: `${out}${String(e)}` }));
|
|
13398
|
+
child.on("close", (code) => resolve4({ code: code ?? 1, out: out.trim() }));
|
|
13232
13399
|
});
|
|
13233
13400
|
}
|
|
13234
13401
|
function detectPackageManager2(root) {
|
|
@@ -13621,13 +13788,6 @@ function renderProgress3(ratio, width) {
|
|
|
13621
13788
|
const capped = Math.min(width, filled);
|
|
13622
13789
|
return FILLED2.repeat(capped) + EMPTY2.repeat(width - capped);
|
|
13623
13790
|
}
|
|
13624
|
-
var createSessionEventBridge = (_writer, level) => ({
|
|
13625
|
-
append: async (_e) => {
|
|
13626
|
-
},
|
|
13627
|
-
level: level ?? "standard",
|
|
13628
|
-
allows: () => true
|
|
13629
|
-
});
|
|
13630
|
-
var resolveAuditLevel = (cfg) => cfg?.session?.auditLevel ?? "standard";
|
|
13631
13791
|
function setupPipelines(params) {
|
|
13632
13792
|
const { events, logger } = params;
|
|
13633
13793
|
const pipelines = createDefaultPipelines();
|
|
@@ -14316,21 +14476,6 @@ async function launchEternalFromFlag(deps) {
|
|
|
14316
14476
|
}
|
|
14317
14477
|
|
|
14318
14478
|
// src/index.ts
|
|
14319
|
-
var createSessionEventBridge2 = (_writer, level, _opts) => ({
|
|
14320
|
-
append: async (_e) => {
|
|
14321
|
-
},
|
|
14322
|
-
level: level ?? "standard",
|
|
14323
|
-
allows: () => true
|
|
14324
|
-
});
|
|
14325
|
-
var resolveAuditLevel2 = (cfg) => cfg?.session?.auditLevel ?? "standard";
|
|
14326
|
-
var resolveSessionLoggingConfig = (cfg) => ({
|
|
14327
|
-
auditLevel: resolveAuditLevel2(cfg),
|
|
14328
|
-
sampling: {
|
|
14329
|
-
toolProgress: {
|
|
14330
|
-
sampleRate: cfg?.session?.sampling?.toolProgress?.sampleRate ?? 8
|
|
14331
|
-
}
|
|
14332
|
-
}
|
|
14333
|
-
});
|
|
14334
14479
|
async function main(argv) {
|
|
14335
14480
|
const ctx = await boot(argv);
|
|
14336
14481
|
if (typeof ctx === "number") return ctx;
|
|
@@ -14358,6 +14503,7 @@ async function main(argv) {
|
|
|
14358
14503
|
permission: {
|
|
14359
14504
|
yolo: config.yolo,
|
|
14360
14505
|
yoloDestructive: flags["yolo-destructive"] === true || flags["force-all-yolo"] === true,
|
|
14506
|
+
confirmDestructive: flags["confirm-destructive"] === true,
|
|
14361
14507
|
promptDelegate: makePromptDelegate(reader)
|
|
14362
14508
|
},
|
|
14363
14509
|
compactor: {
|
|
@@ -14548,9 +14694,13 @@ async function main(argv) {
|
|
|
14548
14694
|
const detachTodosCheckpoint = sessResult.detachTodosCheckpoint;
|
|
14549
14695
|
const priorFleetState = sessResult.priorFleetState;
|
|
14550
14696
|
const sessionConfig = resolveSessionLoggingConfig(config);
|
|
14551
|
-
const sessionBridge =
|
|
14697
|
+
const sessionBridge = createSessionEventBridge(
|
|
14552
14698
|
session,
|
|
14553
|
-
sessionConfig.auditLevel
|
|
14699
|
+
sessionConfig.auditLevel,
|
|
14700
|
+
{
|
|
14701
|
+
sampling: sessionConfig.sampling
|
|
14702
|
+
}
|
|
14703
|
+
);
|
|
14554
14704
|
const stats = new SessionStats(events, tokenCounter);
|
|
14555
14705
|
const errorRing = [];
|
|
14556
14706
|
events.on("error", (e) => {
|
|
@@ -15460,7 +15610,7 @@ Restart WrongStack to load or unload plugin code in this session.`;
|
|
|
15460
15610
|
const { spawn: spawn3 } = await import('child_process');
|
|
15461
15611
|
const cwd2 = projectRoot;
|
|
15462
15612
|
const statusResult = await new Promise(
|
|
15463
|
-
(
|
|
15613
|
+
(resolve4, reject) => {
|
|
15464
15614
|
const child = spawn3("git", ["status", "--porcelain"], {
|
|
15465
15615
|
cwd: cwd2,
|
|
15466
15616
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -15470,7 +15620,7 @@ Restart WrongStack to load or unload plugin code in this session.`;
|
|
|
15470
15620
|
stdout += d;
|
|
15471
15621
|
});
|
|
15472
15622
|
child.on("error", reject);
|
|
15473
|
-
child.on("close", (code) =>
|
|
15623
|
+
child.on("close", (code) => resolve4({ stdout, code: code ?? 0 }));
|
|
15474
15624
|
}
|
|
15475
15625
|
);
|
|
15476
15626
|
if (statusResult.stdout.trim().length > 0) {
|