@wrongstack/cli 0.272.0 → 0.272.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +383 -71
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { color, writeErr, loadPlugins, renderProgress, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, expectDefined, DefaultTaskStore, TaskTracker, renderTaskGraph, withFileLock, resolveHqDataDir, ensureHqFirstRunAuthFile, DEFAULT_HQ_REDACTION_POLICY, watchHqAuthFile, parseHqFrame, HQ_PROTOCOL_VERSION, parseHqEventPayload, scrubAndTruncateHqPreview, DefaultSecretScrubber, projectHash, wstackGlobalRoot, TOKENS, ToolRegistry,
|
|
2
|
+
import { color, writeErr, loadPlugins, renderProgress, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, expectDefined, DefaultTaskStore, TaskTracker, renderTaskGraph, withFileLock, resolveHqDataDir, ensureHqFirstRunAuthFile, DEFAULT_HQ_REDACTION_POLICY, watchHqAuthFile, parseHqFrame, HQ_PROTOCOL_VERSION, parseHqEventPayload, scrubAndTruncateHqPreview, DefaultSecretScrubber, projectHash, wstackGlobalRoot, TOKENS, ToolRegistry, GlobalMailbox, resolveSessionLoggingConfig, createSessionEventBridge, HookRegistry, HookRunner, normalizeTokenSavingTier, SlashCommandRegistry, attachDepWatcherBridge, SessionMemoryConsolidator, BrainDecisionQueue, ObservableBrainArbiter, HumanEscalatingBrainArbiter, createTieredBrainArbiter, DefaultBrainArbiter, BrainMonitor, mailboxSessionTag, createDelegateTool, FLEET_ROSTER, createMcpControlTool, startTechStackConsumer, startPackageOutdatedWatcher, recordFileAction, createAutonomyBrain, DefaultPluginAPI, SpecVersioning, buildTranscriptFromEvents, DEFAULT_CONTEXT_WINDOW_MODE_ID, resolveProjectDir, recentTextTurns, gatedEnhancerReasoning, enhanceUserPrompt, projectSlug, DefaultSystemPromptBuilder, mutateTasks, loadTasks, resolveContextWindowPolicy, repairToolUseAdjacency, mutatePlan, setPlanItemStatus, getPlanTemplate, loadPlan, emptyPlan, addPlanItem, savePlan, resolveProviderModelList, DefaultLogger, DefaultModelsRegistry, isStdinTTY, atomicWrite, DefaultPathResolver, EventBus, runProviderWithRetry, ReplayLogStore, ReplayProviderRunner, mergeCustomModelDefs, makeAutonomyPromptContributor, createContextManagerTool, makeMailboxTool, makeMailSendTool, makeMailInboxTool, InMemoryMetricsSink, wireMetricsToEvents, DefaultHealthRegistry, startMetricsServer, createHqPublisherFromEnv, DEFAULT_SESSION_PRUNE_DAYS, RecoveryLock, DefaultAttachmentStore, Context, QueueStore, loadTodosCheckpoint, attachTodosCheckpoint, loadDirectorState, createDefaultPipelines, applyModelRuntime, resolveAuditLevel, AutoCompactionMiddleware, estimateRequestTokensCalibrated, Agent, FleetManager, makeDirectorSessionFactory, Director, makeFleetEmitTool, makeFleetStatusTool, AdaptiveConcurrencyController, resolveModelMatrix, DEFAULT_SUBAGENT_BASELINE, AutoApprovePermissionPolicy, WIDE_SUBAGENT_CAPABILITIES, PhaseStore, AutoPhasePlanner, PhaseGraphBuilder, WorktreeManager, PhaseOrchestrator, makeLLMClassifier, writeOut, ParallelEternalEngine, EternalAutonomyEngine, allServers as allServers$1, CHIMERA_REVIEW_PROMPT, setQueuedMessagesSnapshot, DefaultSessionRewinder, bootConfig as bootConfig$1, setOutputLineGuard, setRawMode, DefaultSessionReader, resolveWstackPaths, ToolAuditLog, DefaultSessionStore as DefaultSessionStore$1, ProviderRegistry, StreamHangError, ProviderError, makeAgentSubagentRunner, NULL_FLEET_BUS, buildChildEnv, formatContextWindowModeList, getContextWindowMode, AGENT_CATALOG, dispatchAgent, noOpVault, formatTodosList, formatTaskList, formatTaskProgress, formatPlan, SessionRecovery, loadGoal, goalFilePath, summarizeUsage, saveGoal, formatGoal, emptyGoal, buildGoalPreamble, pendingBtwCount, setBtwNote, readHqRuntimeFileSync, resolveHqConfig, MATRIX_PHASE_KEYS, matrixKeyKind, phaseForRole, onResize, InputBuilder, DefaultSecretVault, decryptConfigSecrets as decryptConfigSecrets$1, encryptConfigSecrets as encryptConfigSecrets$1, HQ_AUTH_FILE_VERSION, FsError, ERROR_CODES, truncate, estimateMessageTokens, AGENTS_BY_PHASE, validateAgainstSchema, ConfigError, resolveMailboxIdentity, AutonomousCoordinator, mutateHqAuthFile, mintHqToken, readHqAuthFile, DefaultTokenCounter, isSecretField as isSecretField$1, startSessionTelemetryBridge } from '@wrongstack/core';
|
|
3
3
|
import * as fs4 from 'fs/promises';
|
|
4
4
|
import { decryptConfigSecrets, encryptConfigSecrets, DefaultSecretVault as DefaultSecretVault$1, isSecretField } from '@wrongstack/core/security';
|
|
5
5
|
import * as path4 from 'path';
|
|
@@ -19,7 +19,7 @@ import { getProcessRegistry, builtinToolsPack, rememberTool, forgetTool, searchM
|
|
|
19
19
|
import { DefaultSessionStore } from '@wrongstack/core/storage';
|
|
20
20
|
import { probeLocalLlm } from '@wrongstack/runtime/probe';
|
|
21
21
|
import * as fs3 from 'fs';
|
|
22
|
-
import { watch, writeFileSync, existsSync, readFileSync } from 'fs';
|
|
22
|
+
import { watch, writeFileSync, existsSync, realpathSync, readFileSync } from 'fs';
|
|
23
23
|
import { SkillInstaller } from '@wrongstack/core/skills';
|
|
24
24
|
import { spawn, execFile, execFileSync } from 'child_process';
|
|
25
25
|
import { MCPRegistry, MCPServer, serveHttp, serveStdio } from '@wrongstack/mcp';
|
|
@@ -3040,6 +3040,8 @@ var init_hq_dashboard_html = __esm({
|
|
|
3040
3040
|
.acard-stream { margin-top: 8px; font-size: 11px; color: var(--muted); background: var(--inset); border: 1px solid var(--border); border-radius: 8px; padding: 6px 8px; font-family: ui-monospace, monospace; max-height: 58px; overflow: hidden; white-space: pre-wrap; word-break: break-word; }
|
|
3041
3041
|
.acard-meta { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 9px; font-size: 10.5px; color: var(--dim); font-variant-numeric: tabular-nums; }
|
|
3042
3042
|
.acard-meta .mut { color: var(--dim); }
|
|
3043
|
+
.acard-meta .warm { color: var(--amber); }
|
|
3044
|
+
.acard-meta .hot { color: var(--red); }
|
|
3043
3045
|
.ctxbar { margin-top: 9px; height: 4px; border-radius: 999px; background: var(--inset); overflow: hidden; }
|
|
3044
3046
|
.ctxbar-fill { height: 100%; background: var(--accent); border-radius: 999px; transition: width 0.3s ease; }
|
|
3045
3047
|
.ctxbar-fill.warm { background: var(--amber); }
|
|
@@ -3082,7 +3084,7 @@ var init_hq_dashboard_html = __esm({
|
|
|
3082
3084
|
.fnode.terminal.k-repl { border-left-color: var(--amber); }
|
|
3083
3085
|
.fnode.terminal.k-webui { border-left-color: var(--accent); }
|
|
3084
3086
|
.fnode.terminal.k-cli { border-left-color: var(--cyan); }
|
|
3085
|
-
.fnode.agent { width:
|
|
3087
|
+
.fnode.agent { width: 220px; }
|
|
3086
3088
|
.fnode.agent.s-running, .fnode.agent.s-streaming { border-color: var(--green); box-shadow: 0 0 0 1px rgba(63,185,80,0.25), 0 10px 22px rgba(0,0,0,0.4); animation: pulse 1.8s ease-in-out infinite; }
|
|
3087
3089
|
.fnode.agent.s-waiting_user { border-color: var(--amber); }
|
|
3088
3090
|
.fnode.agent.s-error { border-color: var(--red); }
|
|
@@ -3164,6 +3166,7 @@ function withTok(p){ var u = new URL(p, location.href); var t = tokenStr(); if (
|
|
|
3164
3166
|
function shortId(s){ if(!s) return '\u2014'; s=String(s); return s.length>16 ? s.slice(0,8)+'\u2026'+s.slice(-5) : s; }
|
|
3165
3167
|
function fmtTime(iso){ if(!iso) return ''; var d=new Date(iso); return isNaN(d.getTime())?'':d.toLocaleTimeString(); }
|
|
3166
3168
|
function fmtAgo(iso){ if(!iso) return ''; var d=new Date(iso).getTime(); if(isNaN(d)) return ''; var s=Math.max(0,Math.floor((Date.now()-d)/1000)); if(s<5) return 'now'; if(s<60) return s+'s ago'; var m=Math.floor(s/60); if(m<60) return m+'m ago'; var hh=Math.floor(m/60); if(hh<24) return hh+'h ago'; return Math.floor(hh/24)+'d ago'; }
|
|
3169
|
+
function fmtElapsed(iso){ if(!iso) return ''; var d=new Date(iso).getTime(); if(isNaN(d)) return ''; var s=Math.max(0,Math.floor((Date.now()-d)/1000)); if(s<60) return s+'s'; var m=Math.floor(s/60); if(m<60) return m+'m '+(s%60)+'s'; var h=Math.floor(m/60); if(h<24) return h+'h '+(m%60)+'m'; return Math.floor(h/24)+'d '+(h%24)+'h'; }
|
|
3167
3170
|
function fmtNum(n){ n=Number(n)||0; if(n>=1e6) return (n/1e6).toFixed(1)+'M'; if(n>=1e3) return (n/1e3).toFixed(1)+'k'; return String(n); }
|
|
3168
3171
|
function esc(s){ if(s==null) return ''; return String(s); }
|
|
3169
3172
|
|
|
@@ -3298,19 +3301,60 @@ function machineKey(hostname, machineId){
|
|
|
3298
3301
|
function buildTree(snap){
|
|
3299
3302
|
var sessions = (snap && snap.liveSessions) || [];
|
|
3300
3303
|
var machines = (snap && snap.machines) || [];
|
|
3304
|
+
var clients = (snap && snap.clients) || [];
|
|
3305
|
+
var projects = (snap && snap.projects) || [];
|
|
3301
3306
|
var mMap = {};
|
|
3307
|
+
var pMap = {};
|
|
3308
|
+
projects.forEach(function(p){ if(p && p.projectId) pMap[p.projectId] = p; });
|
|
3302
3309
|
function ensure(hostname, machineId){
|
|
3303
3310
|
var key = machineKey(hostname, machineId);
|
|
3304
3311
|
if(!mMap[key]) mMap[key] = { key: key, machineId: machineId || key, hostname: (hostname && String(hostname).trim()) || machineId || 'machine', projects: {}, sessionCount: 0, agentCount: 0 };
|
|
3305
3312
|
return mMap[key];
|
|
3306
3313
|
}
|
|
3314
|
+
function ensureProject(mm, pid, seed){
|
|
3315
|
+
if(!mm.projects[pid]) mm.projects[pid] = {
|
|
3316
|
+
projectId: pid,
|
|
3317
|
+
projectName: (seed && (seed.projectName || seed.projectId)) || pid,
|
|
3318
|
+
gitBranch: seed && seed.gitBranch,
|
|
3319
|
+
terminals: []
|
|
3320
|
+
};
|
|
3321
|
+
return mm.projects[pid];
|
|
3322
|
+
}
|
|
3307
3323
|
sessions.forEach(function(s){
|
|
3308
3324
|
var mm = ensure(s.hostname, s.machineId);
|
|
3309
3325
|
mm.sessionCount++;
|
|
3310
3326
|
mm.agentCount += (s.agents ? s.agents.length : 0);
|
|
3311
3327
|
var pid = s.projectId || 'unknown';
|
|
3312
|
-
|
|
3313
|
-
|
|
3328
|
+
ensureProject(mm, pid, s).terminals.push(s);
|
|
3329
|
+
});
|
|
3330
|
+
clients.forEach(function(c){
|
|
3331
|
+
var alreadyRepresented = sessions.some(function(s){
|
|
3332
|
+
return s.projectId === c.projectId &&
|
|
3333
|
+
String(s.clientKind||'') === String(c.kind||'') &&
|
|
3334
|
+
(!c.pid || !s.pid || c.pid === s.pid);
|
|
3335
|
+
});
|
|
3336
|
+
if(alreadyRepresented) return;
|
|
3337
|
+
var project = pMap[c.projectId] || {};
|
|
3338
|
+
var mm = ensure(c.hostname, c.machineId);
|
|
3339
|
+
mm.sessionCount++;
|
|
3340
|
+
var terminal = {
|
|
3341
|
+
sessionId: 'client:' + (c.clientId || c.projectId || 'unknown'),
|
|
3342
|
+
clientKind: c.kind || 'cli',
|
|
3343
|
+
machineId: c.machineId,
|
|
3344
|
+
hostname: c.hostname,
|
|
3345
|
+
projectId: c.projectId || 'unknown',
|
|
3346
|
+
projectName: project.projectName || c.projectId || 'unknown',
|
|
3347
|
+
projectRoot: project.projectRootDisplay || '',
|
|
3348
|
+
gitBranch: project.gitBranch,
|
|
3349
|
+
status: c.connected ? 'active' : 'stale',
|
|
3350
|
+
startedAt: c.connectedAt,
|
|
3351
|
+
lastActivityAt: c.lastSeenAt,
|
|
3352
|
+
pid: c.pid,
|
|
3353
|
+
agentCount: 0,
|
|
3354
|
+
agents: [],
|
|
3355
|
+
synthetic: true
|
|
3356
|
+
};
|
|
3357
|
+
ensureProject(mm, terminal.projectId, terminal).terminals.push(terminal);
|
|
3314
3358
|
});
|
|
3315
3359
|
// Include machines that have a connected client but no live session yet.
|
|
3316
3360
|
machines.forEach(function(m){ ensure(m.hostname, m.machineId); });
|
|
@@ -3379,21 +3423,26 @@ function projNode(id, p, machine){
|
|
|
3379
3423
|
});
|
|
3380
3424
|
}
|
|
3381
3425
|
function termNode(id, t, sel){
|
|
3426
|
+
var synthetic = !!t.synthetic;
|
|
3382
3427
|
return fleetNode(id, 'terminal', {
|
|
3383
3428
|
termKind: t.clientKind, status: t.status, icon: kindIcon(t.clientKind),
|
|
3384
3429
|
label: (t.clientKind||'cli').toUpperCase() + ' \xB7 ' + shortId(t.sessionId),
|
|
3385
|
-
sub: t.status + (t.pid ? (' \xB7 pid '+t.pid) : ''),
|
|
3386
|
-
chips: [ (t.agentCount||(t.agents?t.agents.length:0))+' agents' ],
|
|
3387
|
-
clickable:
|
|
3388
|
-
onClick: function(){ selectSession(t.sessionId); }
|
|
3430
|
+
sub: t.status + (t.pid ? (' \xB7 pid '+t.pid) : '') + (synthetic ? ' \xB7 waiting for session telemetry' : ''),
|
|
3431
|
+
chips: synthetic ? ['connected', '0 agents'] : [ (t.agentCount||(t.agents?t.agents.length:0))+' agents' ],
|
|
3432
|
+
clickable: !synthetic, selected: !synthetic && !!(sel && sel.sessionId === t.sessionId && !sel.agentId),
|
|
3433
|
+
onClick: synthetic ? undefined : function(){ selectSession(t.sessionId); }
|
|
3389
3434
|
});
|
|
3390
3435
|
}
|
|
3391
3436
|
function agentNode(id, a, t, sel){
|
|
3392
3437
|
var chips = [];
|
|
3438
|
+
var ctx = typeof a.ctxPct==='number' ? Math.max(0, Math.min(100, a.ctxPct)) : null;
|
|
3439
|
+
var active = a.status==='running'||a.status==='streaming'||a.status==='waiting_user';
|
|
3393
3440
|
if(a.currentTool) chips.push('\u2699 '+a.currentTool);
|
|
3441
|
+
if(a.model) chips.push(a.model);
|
|
3442
|
+
if(ctx!=null) chips.push('ctx '+ctx+'%');
|
|
3443
|
+
if(a.startedAt) chips.push((active?'run ':'last ')+fmtElapsed(a.startedAt));
|
|
3394
3444
|
chips.push((a.iterations||0)+' it');
|
|
3395
3445
|
if(typeof a.costUsd === 'number' && a.costUsd > 0) chips.push('$'+a.costUsd.toFixed(2));
|
|
3396
|
-
if(a.model) chips.push(a.model);
|
|
3397
3446
|
return fleetNode(id, 'agent', {
|
|
3398
3447
|
status: a.status, label: a.name || a.id,
|
|
3399
3448
|
sub: a.status + (a.partialText ? (' \xB7 '+String(a.partialText).slice(0,44)) : ''),
|
|
@@ -3406,7 +3455,7 @@ function kindIcon(k){ return k==='tui'?'\u{1F5B3}':k==='webui'?'\u{1F310}':k==='
|
|
|
3406
3455
|
function miniColor(n){ var k=n.data&&n.data.kind; return k==='machine'?'#a371f7':k==='project'?'#58a6ff':k==='agent'?'#3fb950':'#39d0d8'; }
|
|
3407
3456
|
|
|
3408
3457
|
// Node footprints (width \xD7 height) for dagre sizing.
|
|
3409
|
-
var NODE_SIZE = { machine: [220, 78], project: [220, 78], terminal: [220, 70], agent: [
|
|
3458
|
+
var NODE_SIZE = { machine: [220, 78], project: [220, 78], terminal: [220, 70], agent: [230, 92] };
|
|
3410
3459
|
// Auto-layout the logical nodes into a clean tree using dagre.
|
|
3411
3460
|
function layoutTree(nodes, edges, dir, dagre){
|
|
3412
3461
|
if(!dagre || !nodes.length) return nodes;
|
|
@@ -3702,13 +3751,16 @@ async function boot(){
|
|
|
3702
3751
|
var a = p.a, s = p.s, sel = Store.selected;
|
|
3703
3752
|
var seld = sel && sel.sessionId===s.sessionId && sel.agentId===a.id;
|
|
3704
3753
|
var meta = [];
|
|
3754
|
+
var active = a.status==='running'||a.status==='streaming'||a.status==='waiting_user';
|
|
3755
|
+
var ctx = typeof a.ctxPct==='number' ? Math.max(0, Math.min(100, a.ctxPct)) : null;
|
|
3756
|
+
if(a.model) meta.push(h('span', { key:'md', className:'mut' }, 'model '+a.model));
|
|
3757
|
+
if(ctx!=null) meta.push(h('span', { key:'cx', className: ctx>=85?'hot':ctx>=60?'warm':'mut' }, 'ctx '+ctx+'%'));
|
|
3758
|
+
if(a.startedAt) meta.push(h('span', { key:'rt', className:'mut' }, (active?'run ':'last run ')+fmtElapsed(a.startedAt)));
|
|
3705
3759
|
meta.push(h('span', { key:'it' }, (a.iterations||0)+' it'));
|
|
3706
3760
|
if(a.toolCalls!=null) meta.push(h('span', { key:'tc' }, (a.toolCalls||0)+' tools'));
|
|
3707
3761
|
if(a.tokensIn||a.tokensOut) meta.push(h('span', { key:'tk' }, fmtNum((a.tokensIn||0)+(a.tokensOut||0))+' tok'));
|
|
3708
3762
|
if(typeof a.costUsd==='number' && a.costUsd>0) meta.push(h('span', { key:'co' }, '$'+a.costUsd.toFixed(3)));
|
|
3709
|
-
if(a.model) meta.push(h('span', { key:'md', className:'mut' }, a.model));
|
|
3710
3763
|
if(a.lastActivityAt) meta.push(h('span', { key:'ag', className:'mut' }, fmtAgo(a.lastActivityAt)));
|
|
3711
|
-
var ctx = typeof a.ctxPct==='number' ? Math.max(0, Math.min(100, a.ctxPct)) : null;
|
|
3712
3764
|
return h('div', { className: 'acard s-'+(a.status||'idle')+(seld?' selected':''), onClick: function(){ selectSession(s.sessionId, a.id); } },
|
|
3713
3765
|
h('div', { className: 'acard-top' },
|
|
3714
3766
|
h('span', { className: 'dot '+(a.status||'idle') }),
|
|
@@ -3832,6 +3884,10 @@ async function boot(){
|
|
|
3832
3884
|
var streaming = ag && (ag.status==='streaming' || ag.status==='running');
|
|
3833
3885
|
var liveText = streaming && ag.partialText ? String(ag.partialText) : '';
|
|
3834
3886
|
var liveTool = streaming && ag.currentTool ? ag.currentTool : '';
|
|
3887
|
+
var agBits = [];
|
|
3888
|
+
if(ag && ag.model) agBits.push('model '+ag.model);
|
|
3889
|
+
if(ag && typeof ag.ctxPct==='number') agBits.push('ctx '+Math.max(0, Math.min(100, ag.ctxPct))+'%');
|
|
3890
|
+
if(ag && ag.startedAt) agBits.push((streaming?'run ':'last run ')+fmtElapsed(ag.startedAt));
|
|
3835
3891
|
|
|
3836
3892
|
// Keep pinned to the bottom while new content streams in, unless the user
|
|
3837
3893
|
// has scrolled up to read history.
|
|
@@ -3840,7 +3896,8 @@ async function boot(){
|
|
|
3840
3896
|
}, [entries.length, liveText, liveTool, sel && sel.sessionId, sel && sel.agentId]);
|
|
3841
3897
|
function onScroll(){ var el = bodyRef.current; if(!el) return; stickRef.current = (el.scrollHeight - el.scrollTop - el.clientHeight) < 40; }
|
|
3842
3898
|
|
|
3843
|
-
var
|
|
3899
|
+
var baseMeta = isSub ? (entries.length + ' messages' + (streaming?' \xB7 live':'')) : ((tc && tc.total!=null ? (tc.total+' turns') : '') + (tc && tc.source ? (' \xB7 '+tc.source) : ''));
|
|
3900
|
+
var metaText = (agBits.length ? (agBits.join(' \xB7 ') + (baseMeta ? ' \xB7 ' : '')) : '') + baseMeta;
|
|
3844
3901
|
var bodyEls = [];
|
|
3845
3902
|
if(!isSub && tc && tc.loading && !entries.length && !liveText){ bodyEls.push(h('div', { key:'l', className: 'loading' }, 'Loading full chat history\u2026')); }
|
|
3846
3903
|
else if(!entries.length && !liveText){ bodyEls.push(h('div', { key:'e', className: 'side-empty' }, isSub ? ('No messages from ' + (ag?ag.name:'this subagent') + ' yet \u2014 its conversation streams here live as it works.') : ((tc&&tc.error)?'Could not load history.':'No transcript yet for this terminal.'))); }
|
|
@@ -3937,9 +3994,15 @@ function renderFallback(){
|
|
|
3937
3994
|
html += '<div style="margin:6px 0 4px;color:var(--accent)">\u{1F4C1} '+escAttr(p.projectName)+(p.gitBranch?(' \u2387 '+escAttr(p.gitBranch)):'')+'</div>';
|
|
3938
3995
|
p.terminals.forEach(function(term){
|
|
3939
3996
|
html += '<div style="margin:2px 0 2px 14px">';
|
|
3940
|
-
html += '<
|
|
3997
|
+
if(term.synthetic) html += '<span style="color:var(--cyan)">\u25B7 '+escAttr((term.clientKind||'cli').toUpperCase())+' \xB7 '+escAttr(shortId(term.sessionId))+'</span> <span class="pill">'+escAttr(term.status)+'</span> <span class="pill">waiting for session telemetry</span>';
|
|
3998
|
+
else html += '<a href="#" data-sid="'+escAttr(term.sessionId)+'" style="color:var(--cyan);text-decoration:none">\u25B7 '+escAttr((term.clientKind||'cli').toUpperCase())+' \xB7 '+escAttr(shortId(term.sessionId))+'</a> <span class="pill">'+escAttr(term.status)+'</span>';
|
|
3941
3999
|
(term.agents||[]).forEach(function(a){
|
|
3942
|
-
|
|
4000
|
+
var active = a.status==='running'||a.status==='streaming'||a.status==='waiting_user';
|
|
4001
|
+
var extra = '';
|
|
4002
|
+
if(a.model) extra += ' <span class="pill">model '+escAttr(a.model)+'</span>';
|
|
4003
|
+
if(typeof a.ctxPct==='number') extra += ' <span class="pill">ctx '+escAttr(Math.max(0, Math.min(100, a.ctxPct)))+'%</span>';
|
|
4004
|
+
if(a.startedAt) extra += ' <span class="pill">'+escAttr(active?'run ':'last ')+escAttr(fmtElapsed(a.startedAt))+'</span>';
|
|
4005
|
+
html += '<div style="margin-left:22px;color:var(--muted)"><a href="#" data-sid="'+escAttr(term.sessionId)+'" data-aid="'+escAttr(a.id)+'" style="color:var(--text);text-decoration:none"><span class="dot '+escAttr(a.status||'idle')+'"></span> '+escAttr(a.name||a.id)+'</a> <span class="pill">'+escAttr(a.status)+'</span>'+(a.currentTool?(' <span class="pill">\u2699 '+escAttr(a.currentTool)+'</span>'):'')+extra+'</div>';
|
|
3943
4006
|
});
|
|
3944
4007
|
html += '</div>';
|
|
3945
4008
|
});
|
|
@@ -5058,6 +5121,70 @@ var init_update_check = __esm({
|
|
|
5058
5121
|
CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
5059
5122
|
}
|
|
5060
5123
|
});
|
|
5124
|
+
function nodeWsSocketFactory(url) {
|
|
5125
|
+
return new WebSocket(url);
|
|
5126
|
+
}
|
|
5127
|
+
function createCliHqPublisher(options) {
|
|
5128
|
+
return createHqPublisherFromEnv({
|
|
5129
|
+
...options,
|
|
5130
|
+
socketFactory: options.socketFactory ?? nodeWsSocketFactory
|
|
5131
|
+
});
|
|
5132
|
+
}
|
|
5133
|
+
function hqExplicitlyDisabled(options) {
|
|
5134
|
+
const envEnabled = process.env["WRONGSTACK_HQ_ENABLED"]?.trim();
|
|
5135
|
+
if (envEnabled !== void 0 && envEnabled.length > 0) return envEnabled === "0";
|
|
5136
|
+
if (options.config?.enabled !== void 0) return options.config.enabled === false;
|
|
5137
|
+
return options.appConfig?.hq?.enabled === false;
|
|
5138
|
+
}
|
|
5139
|
+
function resolvedHqConnectionKey(options) {
|
|
5140
|
+
if (options.config !== void 0) {
|
|
5141
|
+
return options.config.enabled === false ? void 0 : `${options.config.url}
|
|
5142
|
+
${options.config.token ?? ""}`;
|
|
5143
|
+
}
|
|
5144
|
+
const config = resolveHqConfig({ config: options.appConfig?.hq });
|
|
5145
|
+
return config === void 0 ? void 0 : `${config.url}
|
|
5146
|
+
${config.token ?? ""}`;
|
|
5147
|
+
}
|
|
5148
|
+
function startCliHqConnection(options) {
|
|
5149
|
+
let publisher;
|
|
5150
|
+
let publisherKey;
|
|
5151
|
+
let timer;
|
|
5152
|
+
const tryConnect = () => {
|
|
5153
|
+
const nextKey = resolvedHqConnectionKey(options);
|
|
5154
|
+
if (nextKey === void 0) return;
|
|
5155
|
+
if (publisher !== void 0 && publisherKey === nextKey) return;
|
|
5156
|
+
publisher?.close();
|
|
5157
|
+
publisher = void 0;
|
|
5158
|
+
publisherKey = void 0;
|
|
5159
|
+
const next = createCliHqPublisher(options);
|
|
5160
|
+
if (next === void 0) return;
|
|
5161
|
+
publisher = next;
|
|
5162
|
+
publisherKey = nextKey;
|
|
5163
|
+
next.connect();
|
|
5164
|
+
options.onConnect?.(next);
|
|
5165
|
+
};
|
|
5166
|
+
tryConnect();
|
|
5167
|
+
if (!hqExplicitlyDisabled(options)) {
|
|
5168
|
+
timer = setInterval(tryConnect, options.retryIntervalMs ?? 2500);
|
|
5169
|
+
timer.unref?.();
|
|
5170
|
+
}
|
|
5171
|
+
return {
|
|
5172
|
+
getPublisher: () => publisher,
|
|
5173
|
+
stop: () => {
|
|
5174
|
+
if (timer !== void 0) {
|
|
5175
|
+
clearInterval(timer);
|
|
5176
|
+
timer = void 0;
|
|
5177
|
+
}
|
|
5178
|
+
publisher?.close();
|
|
5179
|
+
publisher = void 0;
|
|
5180
|
+
publisherKey = void 0;
|
|
5181
|
+
}
|
|
5182
|
+
};
|
|
5183
|
+
}
|
|
5184
|
+
var init_hq_publisher = __esm({
|
|
5185
|
+
"src/hq-publisher.ts"() {
|
|
5186
|
+
}
|
|
5187
|
+
});
|
|
5061
5188
|
|
|
5062
5189
|
// src/webui-server/cost-helpers.ts
|
|
5063
5190
|
function getCostRates(model) {
|
|
@@ -7168,33 +7295,40 @@ async function runWebUI(opts) {
|
|
|
7168
7295
|
let webuiClientId = null;
|
|
7169
7296
|
let webuiHeartbeatTimer = null;
|
|
7170
7297
|
let stopWebuiHqBridge;
|
|
7298
|
+
let webuiHqConnection;
|
|
7171
7299
|
const CLIENT_HEARTBEAT_MS = 15e3;
|
|
7172
7300
|
const registerWebuiClient = async () => {
|
|
7173
7301
|
if (!opts.projectRoot) return null;
|
|
7174
7302
|
try {
|
|
7175
|
-
const
|
|
7176
|
-
const
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7303
|
+
const projectRoot = opts.projectRoot;
|
|
7304
|
+
const projectDir = resolveProjectDir(projectRoot, wstackGlobalRoot());
|
|
7305
|
+
webuiHqConnection = startCliHqConnection({
|
|
7306
|
+
clientKind: "webui",
|
|
7307
|
+
projectRoot,
|
|
7308
|
+
projectName: path4.basename(projectRoot),
|
|
7309
|
+
appConfig: opts.appConfig,
|
|
7310
|
+
onConnect: (publisher) => {
|
|
7311
|
+
stopWebuiHqBridge?.();
|
|
7312
|
+
stopWebuiHqBridge = void 0;
|
|
7313
|
+
void import('@wrongstack/core').then(({ startSessionTelemetryBridge: startSessionTelemetryBridge2 }) => {
|
|
7314
|
+
stopWebuiHqBridge = startSessionTelemetryBridge2({
|
|
7315
|
+
publisher,
|
|
7316
|
+
events: opts.events,
|
|
7317
|
+
sessionId: opts.session.id,
|
|
7318
|
+
projectRoot,
|
|
7319
|
+
projectName: path4.basename(projectRoot),
|
|
7320
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7321
|
+
});
|
|
7322
|
+
}).catch(() => {
|
|
7188
7323
|
});
|
|
7189
|
-
} catch {
|
|
7190
7324
|
}
|
|
7191
|
-
}
|
|
7192
|
-
const mailbox = new GlobalMailbox(projectDir, opts.events,
|
|
7325
|
+
});
|
|
7326
|
+
const mailbox = new GlobalMailbox(projectDir, opts.events, () => webuiHqConnection?.getPublisher());
|
|
7193
7327
|
webuiClientId = `webui@${crypto2.randomUUID().slice(0, 8)}`;
|
|
7194
7328
|
const projectName = opts.projectRoot ? path4.basename(opts.projectRoot) : "unknown";
|
|
7195
7329
|
await mailbox.registerClient({
|
|
7196
7330
|
clientId: webuiClientId,
|
|
7197
|
-
sessionId:
|
|
7331
|
+
sessionId: projectRoot,
|
|
7198
7332
|
name: `WebUI [${projectName}]`,
|
|
7199
7333
|
source: "webui",
|
|
7200
7334
|
pid: process.pid
|
|
@@ -7218,6 +7352,8 @@ async function runWebUI(opts) {
|
|
|
7218
7352
|
stopWebuiHqBridge();
|
|
7219
7353
|
stopWebuiHqBridge = void 0;
|
|
7220
7354
|
}
|
|
7355
|
+
webuiHqConnection?.stop();
|
|
7356
|
+
webuiHqConnection = void 0;
|
|
7221
7357
|
};
|
|
7222
7358
|
registerWebuiClient();
|
|
7223
7359
|
const wsToken = generateAuthToken();
|
|
@@ -8768,6 +8904,7 @@ ${text}` : text;
|
|
|
8768
8904
|
}
|
|
8769
8905
|
var init_webui_server = __esm({
|
|
8770
8906
|
"src/webui-server.ts"() {
|
|
8907
|
+
init_hq_publisher();
|
|
8771
8908
|
init_cost_helpers();
|
|
8772
8909
|
init_prefs_seeding();
|
|
8773
8910
|
init_lifecycle();
|
|
@@ -21054,11 +21191,24 @@ function buildBadges(chosen) {
|
|
|
21054
21191
|
return badges;
|
|
21055
21192
|
}
|
|
21056
21193
|
async function persistLaunchChoices(configPath2, choices) {
|
|
21194
|
+
let fileExists2 = false;
|
|
21195
|
+
try {
|
|
21196
|
+
await fs4.access(configPath2);
|
|
21197
|
+
fileExists2 = true;
|
|
21198
|
+
} catch {
|
|
21199
|
+
}
|
|
21057
21200
|
let existing = {};
|
|
21058
21201
|
try {
|
|
21059
21202
|
const raw = await fs4.readFile(configPath2, "utf8");
|
|
21060
21203
|
existing = JSON.parse(raw);
|
|
21061
|
-
} catch {
|
|
21204
|
+
} catch (err) {
|
|
21205
|
+
if (fileExists2) {
|
|
21206
|
+
throw new Error(
|
|
21207
|
+
`Refusing to overwrite corrupt config at ${configPath2} (${err.message}). Fix or move the file aside before retrying.`,
|
|
21208
|
+
{ cause: err }
|
|
21209
|
+
);
|
|
21210
|
+
}
|
|
21211
|
+
existing = {};
|
|
21062
21212
|
}
|
|
21063
21213
|
existing.yolo = choices.yolo;
|
|
21064
21214
|
existing.launch = {
|
|
@@ -22430,8 +22580,8 @@ function startLoopbackServer(expectedState) {
|
|
|
22430
22580
|
function openBrowser(url) {
|
|
22431
22581
|
try {
|
|
22432
22582
|
const platform3 = process.platform;
|
|
22433
|
-
const { command, args } = platform3 === "win32" ? { command: "cmd", args: ["/c", "start", "", url] } : platform3 === "darwin" ? { command: "open", args: [url] } : { command: "xdg-open", args: [url] };
|
|
22434
|
-
const child = spawn(
|
|
22583
|
+
const { command: command2, args } = platform3 === "win32" ? { command: "cmd", args: ["/c", "start", "", url] } : platform3 === "darwin" ? { command: "open", args: [url] } : { command: "xdg-open", args: [url] };
|
|
22584
|
+
const child = spawn(command2, args, { stdio: "ignore", windowsHide: true });
|
|
22435
22585
|
child.on("error", () => {
|
|
22436
22586
|
});
|
|
22437
22587
|
child.unref();
|
|
@@ -22563,8 +22713,8 @@ var COPILOT_PROVIDER_ID = "github-copilot";
|
|
|
22563
22713
|
function openBrowser2(url) {
|
|
22564
22714
|
try {
|
|
22565
22715
|
const platform3 = process.platform;
|
|
22566
|
-
const { command, args } = platform3 === "win32" ? { command: "cmd", args: ["/c", "start", "", url] } : platform3 === "darwin" ? { command: "open", args: [url] } : { command: "xdg-open", args: [url] };
|
|
22567
|
-
const child = spawn(
|
|
22716
|
+
const { command: command2, args } = platform3 === "win32" ? { command: "cmd", args: ["/c", "start", "", url] } : platform3 === "darwin" ? { command: "open", args: [url] } : { command: "xdg-open", args: [url] };
|
|
22717
|
+
const child = spawn(command2, args, { stdio: "ignore", windowsHide: true });
|
|
22568
22718
|
child.on("error", () => {
|
|
22569
22719
|
});
|
|
22570
22720
|
child.unref();
|
|
@@ -22931,8 +23081,8 @@ function startLoopbackServer2(state) {
|
|
|
22931
23081
|
function openBrowser3(url) {
|
|
22932
23082
|
try {
|
|
22933
23083
|
const platform3 = process.platform;
|
|
22934
|
-
const { command, args } = platform3 === "win32" ? { command: "cmd", args: ["/c", "start", "", url] } : platform3 === "darwin" ? { command: "open", args: [url] } : { command: "xdg-open", args: [url] };
|
|
22935
|
-
const child = spawn(
|
|
23084
|
+
const { command: command2, args } = platform3 === "win32" ? { command: "cmd", args: ["/c", "start", "", url] } : platform3 === "darwin" ? { command: "open", args: [url] } : { command: "xdg-open", args: [url] };
|
|
23085
|
+
const child = spawn(command2, args, { stdio: "ignore", windowsHide: true });
|
|
22936
23086
|
child.on("error", () => {
|
|
22937
23087
|
});
|
|
22938
23088
|
child.unref();
|
|
@@ -26858,9 +27008,15 @@ var skillsCmd = async (_args, deps) => {
|
|
|
26858
27008
|
init_update_check();
|
|
26859
27009
|
var updateCmd = async (args, deps) => {
|
|
26860
27010
|
const cwd = deps.cwd;
|
|
26861
|
-
const
|
|
27011
|
+
const parsed = parseUpdateArgs(args);
|
|
27012
|
+
if (parsed.error) {
|
|
27013
|
+
deps.renderer.write(`${parsed.error}
|
|
27014
|
+
`);
|
|
27015
|
+
deps.renderer.write("Usage: wrongstack update [--check-only] [--pm npm|pnpm|yarn|bun]\n");
|
|
27016
|
+
return 1;
|
|
27017
|
+
}
|
|
26862
27018
|
const info = await checkForUpdate();
|
|
26863
|
-
if (checkOnly) {
|
|
27019
|
+
if (parsed.checkOnly) {
|
|
26864
27020
|
if (info.outdated) {
|
|
26865
27021
|
deps.renderer.write(`Update available: v${info.current} \u2192 v${info.latest}
|
|
26866
27022
|
`);
|
|
@@ -26875,40 +27031,58 @@ var updateCmd = async (args, deps) => {
|
|
|
26875
27031
|
`);
|
|
26876
27032
|
return 0;
|
|
26877
27033
|
}
|
|
27034
|
+
const packageManager = parsed.packageManager ?? detectUpdatePackageManager();
|
|
27035
|
+
const updateCommand = buildUpdateCommand(packageManager);
|
|
26878
27036
|
deps.renderer.write(`Updating wrongstack from v${info.current} to v${info.latest}...
|
|
27037
|
+
`);
|
|
27038
|
+
deps.renderer.write(`Running: ${updateCommand.display}
|
|
26879
27039
|
`);
|
|
26880
27040
|
try {
|
|
26881
|
-
const result = await new Promise(
|
|
26882
|
-
|
|
26883
|
-
|
|
26884
|
-
|
|
26885
|
-
|
|
26886
|
-
|
|
26887
|
-
|
|
26888
|
-
|
|
26889
|
-
|
|
26890
|
-
|
|
26891
|
-
|
|
26892
|
-
|
|
26893
|
-
|
|
26894
|
-
|
|
26895
|
-
|
|
27041
|
+
const result = await new Promise(
|
|
27042
|
+
(resolve13, reject) => {
|
|
27043
|
+
const child = spawn(updateCommand.executable, updateCommand.args, {
|
|
27044
|
+
cwd,
|
|
27045
|
+
stdio: "pipe",
|
|
27046
|
+
signal: AbortSignal.timeout(12e4),
|
|
27047
|
+
windowsHide: true
|
|
27048
|
+
});
|
|
27049
|
+
let stdout = "";
|
|
27050
|
+
let stderr = "";
|
|
27051
|
+
child.stdout?.on("data", (d) => {
|
|
27052
|
+
stdout += d;
|
|
27053
|
+
});
|
|
27054
|
+
child.stderr?.on("data", (d) => {
|
|
27055
|
+
stderr += d;
|
|
27056
|
+
});
|
|
27057
|
+
child.on("error", reject);
|
|
27058
|
+
child.on("close", (code) => resolve13({ code: code ?? 0, stdout, stderr }));
|
|
27059
|
+
}
|
|
27060
|
+
);
|
|
26896
27061
|
if (result.code === 0) {
|
|
26897
27062
|
deps.renderer.write(
|
|
26898
27063
|
`
|
|
26899
27064
|
Updated to v${info.latest}. Restart wrongstack to use the new version.
|
|
26900
27065
|
`
|
|
26901
27066
|
);
|
|
27067
|
+
const warning = installWarningSummary(`${result.stderr}
|
|
27068
|
+
${result.stdout}`);
|
|
27069
|
+
if (warning) deps.renderer.write(`
|
|
27070
|
+
${warning}
|
|
27071
|
+
`);
|
|
26902
27072
|
} else {
|
|
26903
27073
|
deps.renderer.write(`
|
|
26904
27074
|
Update failed with exit code ${result.code}.
|
|
26905
27075
|
`);
|
|
26906
|
-
const detail = result.stderr
|
|
27076
|
+
const detail = `${result.stderr}
|
|
27077
|
+
${result.stdout}`.trim();
|
|
26907
27078
|
if (detail) deps.renderer.write(`
|
|
26908
27079
|
${detail}
|
|
26909
27080
|
`);
|
|
26910
27081
|
deps.renderer.write(
|
|
26911
|
-
|
|
27082
|
+
`
|
|
27083
|
+
Try the matching global update command manually:
|
|
27084
|
+
${updateCommand.display}
|
|
27085
|
+
` + otherManagerCommands(packageManager)
|
|
26912
27086
|
);
|
|
26913
27087
|
}
|
|
26914
27088
|
return result.code;
|
|
@@ -26916,7 +27090,7 @@ ${detail}
|
|
|
26916
27090
|
const msg = err instanceof Error ? err.message : String(err);
|
|
26917
27091
|
if (msg.includes("ENOENT")) {
|
|
26918
27092
|
deps.renderer.write(`
|
|
26919
|
-
Update failed:
|
|
27093
|
+
Update failed: ${packageManager} not found in PATH.
|
|
26920
27094
|
`);
|
|
26921
27095
|
return 1;
|
|
26922
27096
|
}
|
|
@@ -26926,6 +27100,100 @@ Update failed: ${msg}
|
|
|
26926
27100
|
return 1;
|
|
26927
27101
|
}
|
|
26928
27102
|
};
|
|
27103
|
+
function parseUpdateArgs(args) {
|
|
27104
|
+
let checkOnly = false;
|
|
27105
|
+
let packageManager;
|
|
27106
|
+
for (let i = 0; i < args.length; i++) {
|
|
27107
|
+
const arg = args[i];
|
|
27108
|
+
if (arg === void 0) continue;
|
|
27109
|
+
if (arg === "--check-only" || arg === "-c") {
|
|
27110
|
+
checkOnly = true;
|
|
27111
|
+
continue;
|
|
27112
|
+
}
|
|
27113
|
+
if (arg === "--pm" || arg === "--package-manager") {
|
|
27114
|
+
const value = args[++i];
|
|
27115
|
+
const pm = parsePackageManager(value);
|
|
27116
|
+
if (!pm)
|
|
27117
|
+
return {
|
|
27118
|
+
checkOnly,
|
|
27119
|
+
packageManager,
|
|
27120
|
+
error: `Invalid package manager: ${value ?? "<missing>"}`
|
|
27121
|
+
};
|
|
27122
|
+
packageManager = pm;
|
|
27123
|
+
continue;
|
|
27124
|
+
}
|
|
27125
|
+
const pmEq = arg.match(/^--(?:pm|package-manager)=(.+)$/)?.[1];
|
|
27126
|
+
if (pmEq) {
|
|
27127
|
+
const pm = parsePackageManager(pmEq);
|
|
27128
|
+
if (!pm) return { checkOnly, packageManager, error: `Invalid package manager: ${pmEq}` };
|
|
27129
|
+
packageManager = pm;
|
|
27130
|
+
continue;
|
|
27131
|
+
}
|
|
27132
|
+
const shorthand = arg.match(/^--(npm|pnpm|yarn|bun)$/)?.[1];
|
|
27133
|
+
if (shorthand) {
|
|
27134
|
+
packageManager = shorthand;
|
|
27135
|
+
}
|
|
27136
|
+
}
|
|
27137
|
+
return { checkOnly, packageManager, error: void 0 };
|
|
27138
|
+
}
|
|
27139
|
+
function parsePackageManager(value) {
|
|
27140
|
+
if (value === "npm" || value === "pnpm" || value === "yarn" || value === "bun") return value;
|
|
27141
|
+
return void 0;
|
|
27142
|
+
}
|
|
27143
|
+
function detectUpdatePackageManager(env = process.env, argv = process.argv) {
|
|
27144
|
+
const forced = parsePackageManager(env.WRONGSTACK_UPDATE_PM);
|
|
27145
|
+
if (forced) return forced;
|
|
27146
|
+
const userAgent = env.npm_config_user_agent ?? "";
|
|
27147
|
+
if (/\bpnpm\//i.test(userAgent)) return "pnpm";
|
|
27148
|
+
if (/\byarn\//i.test(userAgent)) return "yarn";
|
|
27149
|
+
if (/\bbun\//i.test(userAgent)) return "bun";
|
|
27150
|
+
if (/\bnpm\//i.test(userAgent)) return "npm";
|
|
27151
|
+
const execPath = `${env.npm_execpath ?? ""} ${argv[1] ?? ""}`;
|
|
27152
|
+
const realPaths = [env.npm_execpath, argv[1]].filter((p) => typeof p === "string" && p.length > 0).map((p) => {
|
|
27153
|
+
try {
|
|
27154
|
+
return existsSync(p) ? realpathSync(p) : p;
|
|
27155
|
+
} catch {
|
|
27156
|
+
return p;
|
|
27157
|
+
}
|
|
27158
|
+
}).join(" ");
|
|
27159
|
+
const hint = `${execPath} ${realPaths}`.replace(/\\/g, "/").toLowerCase();
|
|
27160
|
+
if (hint.includes("/pnpm/") || hint.includes("/.pnpm/") || hint.includes("pnpm-global"))
|
|
27161
|
+
return "pnpm";
|
|
27162
|
+
if (hint.includes("/yarn/") || hint.includes("/.yarn/")) return "yarn";
|
|
27163
|
+
if (hint.includes("/bun/") || hint.includes("/.bun/")) return "bun";
|
|
27164
|
+
return "npm";
|
|
27165
|
+
}
|
|
27166
|
+
function buildUpdateCommand(packageManager) {
|
|
27167
|
+
switch (packageManager) {
|
|
27168
|
+
case "pnpm":
|
|
27169
|
+
return command(packageManager, ["add", "-g", "wrongstack@latest"]);
|
|
27170
|
+
case "yarn":
|
|
27171
|
+
return command(packageManager, ["global", "add", "wrongstack@latest"]);
|
|
27172
|
+
case "bun":
|
|
27173
|
+
return command(packageManager, ["add", "-g", "wrongstack@latest"]);
|
|
27174
|
+
case "npm":
|
|
27175
|
+
return command(packageManager, ["install", "-g", "wrongstack@latest"]);
|
|
27176
|
+
}
|
|
27177
|
+
}
|
|
27178
|
+
function command(pm, args) {
|
|
27179
|
+
const executable = process.platform === "win32" && pm !== "bun" ? `${pm}.cmd` : pm;
|
|
27180
|
+
return {
|
|
27181
|
+
executable,
|
|
27182
|
+
args,
|
|
27183
|
+
display: `${pm} ${args.join(" ")}`
|
|
27184
|
+
};
|
|
27185
|
+
}
|
|
27186
|
+
function otherManagerCommands(selected) {
|
|
27187
|
+
const commands = ["npm", "pnpm", "yarn", "bun"].filter((pm) => pm !== selected).map((pm) => ` ${buildUpdateCommand(pm).display}`);
|
|
27188
|
+
return commands.length > 0 ? `
|
|
27189
|
+
Other package managers:
|
|
27190
|
+
${commands.join("\n")}
|
|
27191
|
+
` : "";
|
|
27192
|
+
}
|
|
27193
|
+
function installWarningSummary(output) {
|
|
27194
|
+
if (!/allow-scripts|allowScripts/i.test(output)) return null;
|
|
27195
|
+
return "Install completed, but npm reported blocked lifecycle scripts. If a native optional feature is missing, rerun the update with npm script approval for the named package.";
|
|
27196
|
+
}
|
|
26929
27197
|
var versionCmd = async (_args, deps) => {
|
|
26930
27198
|
deps.renderer.write(
|
|
26931
27199
|
`WrongStack ${CLI_VERSION} (apiVersion ${API_VERSION}, node ${process.version}, ${os.platform()})
|
|
@@ -29243,6 +29511,7 @@ async function predictNextTasks(input, opts) {
|
|
|
29243
29511
|
|
|
29244
29512
|
// src/execution.ts
|
|
29245
29513
|
init_provider_config_utils();
|
|
29514
|
+
init_hq_publisher();
|
|
29246
29515
|
init_sdd();
|
|
29247
29516
|
init_utils();
|
|
29248
29517
|
var DEFAULT_MAX_CONSECUTIVE_AUTO_PROCEED = 50;
|
|
@@ -29297,9 +29566,8 @@ async function runRepl(opts) {
|
|
|
29297
29566
|
const replProjectRoot = opts.projectRoot ?? process.cwd();
|
|
29298
29567
|
const projectDir = resolveProjectDir(replProjectRoot, wstackGlobalRoot());
|
|
29299
29568
|
const clientId = `repl@${crypto2.randomUUID().slice(0, 8)}`;
|
|
29300
|
-
const
|
|
29301
|
-
|
|
29302
|
-
const clientMailbox = new GlobalMailbox(projectDir, void 0, hqPublisher);
|
|
29569
|
+
const hqConnection = startCliHqConnection({ clientKind: "repl", projectRoot: replProjectRoot, projectName: path4.basename(replProjectRoot), appConfig: opts.appConfig });
|
|
29570
|
+
const clientMailbox = new GlobalMailbox(projectDir, void 0, () => hqConnection.getPublisher());
|
|
29303
29571
|
let clientHeartbeat;
|
|
29304
29572
|
clientMailbox.registerClient({
|
|
29305
29573
|
clientId,
|
|
@@ -29879,6 +30147,7 @@ ${color.dim(lines)}
|
|
|
29879
30147
|
await opts.reader.close().catch(() => {
|
|
29880
30148
|
});
|
|
29881
30149
|
clearInterval(clientHeartbeat);
|
|
30150
|
+
hqConnection.stop();
|
|
29882
30151
|
opts.onDestroy?.();
|
|
29883
30152
|
}
|
|
29884
30153
|
}
|
|
@@ -30775,6 +31044,9 @@ async function execute(deps) {
|
|
|
30775
31044
|
return code;
|
|
30776
31045
|
}
|
|
30777
31046
|
|
|
31047
|
+
// src/cli-main.ts
|
|
31048
|
+
init_hq_publisher();
|
|
31049
|
+
|
|
30778
31050
|
// src/hooks-wiring.ts
|
|
30779
31051
|
var HookBlockedError = class extends Error {
|
|
30780
31052
|
constructor(reason) {
|
|
@@ -30879,6 +31151,10 @@ var MultiAgentHost = class _MultiAgentHost {
|
|
|
30879
31151
|
acpRunnerCache = /* @__PURE__ */ new Map();
|
|
30880
31152
|
acpRunnerAccessOrder = [];
|
|
30881
31153
|
static ACP_CACHE_MAX = 20;
|
|
31154
|
+
/** Adaptive concurrency controller — created in buildDirector() when config has
|
|
31155
|
+
* adaptiveConcurrency.enabled = true. Monitors FleetBus for 429 errors and
|
|
31156
|
+
* automatically adjusts maxConcurrent to prevent rate limiting. */
|
|
31157
|
+
adaptiveConcurrencyController;
|
|
30882
31158
|
/**
|
|
30883
31159
|
* Force the lazy build path to run *now* and return the live Director,
|
|
30884
31160
|
* or null when director mode is off. Used by the CLI to register the
|
|
@@ -31040,6 +31316,14 @@ var MultiAgentHost = class _MultiAgentHost {
|
|
|
31040
31316
|
this.coordinatorOffHandle = () => coordinator.off("task.assigned", coordinatorTaskAssignedHandler);
|
|
31041
31317
|
this.fleetEmitTool = makeFleetEmitTool(this.director);
|
|
31042
31318
|
this.fleetStatusTool = makeFleetStatusTool(this.director);
|
|
31319
|
+
const adaptiveConfig = this.deps.configStore.get().adaptiveConcurrency;
|
|
31320
|
+
if (adaptiveConfig?.enabled) {
|
|
31321
|
+
this.adaptiveConcurrencyController = new AdaptiveConcurrencyController(
|
|
31322
|
+
this.director.fleet,
|
|
31323
|
+
(n) => coordinator.setMaxConcurrent(n),
|
|
31324
|
+
adaptiveConfig
|
|
31325
|
+
);
|
|
31326
|
+
}
|
|
31043
31327
|
const runner = await this.buildSubagentRunner(config);
|
|
31044
31328
|
if (!this.directorRunnerSet) {
|
|
31045
31329
|
this.getCoordinator().setRunner(runner);
|
|
@@ -31693,6 +31977,8 @@ Start your heartbeat loop now.`,
|
|
|
31693
31977
|
this.directorOffHandles.length = 0;
|
|
31694
31978
|
this.coordinatorOffHandle?.();
|
|
31695
31979
|
this.coordinatorOffHandle = null;
|
|
31980
|
+
this.adaptiveConcurrencyController?.dispose();
|
|
31981
|
+
this.adaptiveConcurrencyController = void 0;
|
|
31696
31982
|
if (this.director) {
|
|
31697
31983
|
await this.director.shutdown();
|
|
31698
31984
|
}
|
|
@@ -32810,7 +33096,7 @@ async function main(argv) {
|
|
|
32810
33096
|
const promptBuilder = container.resolve(TOKENS.SystemPromptBuilder);
|
|
32811
33097
|
let onlineAgents = [];
|
|
32812
33098
|
try {
|
|
32813
|
-
const hqPublisher2 =
|
|
33099
|
+
const hqPublisher2 = createCliHqPublisher({ clientKind: tuiOwnsScreen ? "tui" : "cli", projectRoot, projectName: path4.basename(projectRoot), appConfig: config });
|
|
32814
33100
|
hqPublisher2?.connect();
|
|
32815
33101
|
if (hqPublisher2) teardownHandlers.push(() => hqPublisher2.close());
|
|
32816
33102
|
const systemMailbox = new GlobalMailbox(wpaths.projectDir, void 0, hqPublisher2);
|
|
@@ -33353,19 +33639,45 @@ async function main(argv) {
|
|
|
33353
33639
|
outcome: e.intervened ? "steered the agent" : "observed (no action)"
|
|
33354
33640
|
});
|
|
33355
33641
|
});
|
|
33356
|
-
|
|
33357
|
-
|
|
33358
|
-
|
|
33359
|
-
|
|
33642
|
+
let hqPublisher;
|
|
33643
|
+
let stopHqSessionBridge;
|
|
33644
|
+
const hqConnection = startCliHqConnection({
|
|
33645
|
+
clientKind: tuiOwnsScreen ? "tui" : "cli",
|
|
33646
|
+
projectRoot,
|
|
33647
|
+
projectName: path4.basename(projectRoot),
|
|
33648
|
+
appConfig: config,
|
|
33649
|
+
onConnect: (publisher) => {
|
|
33650
|
+
hqPublisher = publisher;
|
|
33651
|
+
stopHqSessionBridge?.();
|
|
33652
|
+
stopHqSessionBridge = void 0;
|
|
33653
|
+
try {
|
|
33654
|
+
stopHqSessionBridge = startSessionTelemetryBridge({
|
|
33655
|
+
publisher,
|
|
33656
|
+
events,
|
|
33657
|
+
sessionId: session.id,
|
|
33658
|
+
projectRoot,
|
|
33659
|
+
projectName: path4.basename(projectRoot),
|
|
33660
|
+
globalRoot: wpaths.globalRoot,
|
|
33661
|
+
initialAgents: tracker?.getAgents(),
|
|
33662
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
33663
|
+
});
|
|
33664
|
+
} catch {
|
|
33665
|
+
}
|
|
33666
|
+
}
|
|
33667
|
+
});
|
|
33668
|
+
hqPublisher = hqConnection.getPublisher();
|
|
33669
|
+
teardownHandlers.push(() => stopHqSessionBridge?.());
|
|
33670
|
+
teardownHandlers.push(() => hqConnection.stop());
|
|
33671
|
+
if (agentMonitor) {
|
|
33360
33672
|
const offMsg = events.on("agent.timeline.message", (payload) => {
|
|
33361
33673
|
try {
|
|
33362
|
-
hqPublisher
|
|
33674
|
+
hqPublisher?.publishEvent({ type: "agent.message", payload, timestamp: payload.ts });
|
|
33363
33675
|
} catch {
|
|
33364
33676
|
}
|
|
33365
33677
|
});
|
|
33366
33678
|
const offStatus = events.on("agent.status_changed", (payload) => {
|
|
33367
33679
|
try {
|
|
33368
|
-
hqPublisher
|
|
33680
|
+
hqPublisher?.publishEvent({ type: "agent.status", payload, timestamp: payload.ts });
|
|
33369
33681
|
} catch {
|
|
33370
33682
|
}
|
|
33371
33683
|
});
|
|
@@ -33374,7 +33686,7 @@ async function main(argv) {
|
|
|
33374
33686
|
offStatus();
|
|
33375
33687
|
});
|
|
33376
33688
|
}
|
|
33377
|
-
const brainMailbox = new GlobalMailbox(wpaths.projectDir, events, hqPublisher);
|
|
33689
|
+
const brainMailbox = new GlobalMailbox(wpaths.projectDir, events, () => hqPublisher);
|
|
33378
33690
|
const brainMonitor = new BrainMonitor({
|
|
33379
33691
|
events,
|
|
33380
33692
|
brain,
|