@wrongstack/cli 0.73.1 → 0.77.0
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 +513 -81
- package/dist/index.js.map +1 -1
- package/package.json +12 -11
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { color, writeErr, renderProgress, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, DefaultTaskStore, TaskTracker, renderTaskGraph, DefaultSecretScrubber, atomicWrite, DefaultPathResolver, TOKENS, mergeCustomModelDefs, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, resolveSessionLoggingConfig, createSessionEventBridge, HookRegistry, HookRunner, SlashCommandRegistry, BrainDecisionQueue, ObservableBrainArbiter, HumanEscalatingBrainArbiter, DefaultBrainArbiter, createDelegateTool, FLEET_ROSTER, createMcpControlTool, SpecVersioning, 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, DEFAULT_SUBAGENT_BASELINE, 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,
|
|
2
|
+
import { color, writeErr, renderProgress, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, DefaultTaskStore, TaskTracker, renderTaskGraph, DefaultSecretScrubber, atomicWrite, DefaultPathResolver, TOKENS, mergeCustomModelDefs, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, resolveSessionLoggingConfig, createSessionEventBridge, HookRegistry, HookRunner, SlashCommandRegistry, BrainDecisionQueue, ObservableBrainArbiter, HumanEscalatingBrainArbiter, DefaultBrainArbiter, createDelegateTool, FLEET_ROSTER, createMcpControlTool, SpecVersioning, 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, DEFAULT_SUBAGENT_BASELINE, AutoApprovePermissionPolicy, PhaseStore, AutoPhasePlanner, PhaseGraphBuilder, WorktreeManager, PhaseOrchestrator, makeLLMClassifier, ParallelEternalEngine, EternalAutonomyEngine, allServers as allServers$1, decryptConfigSecrets as decryptConfigSecrets$1, encryptConfigSecrets as encryptConfigSecrets$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, InputBuilder, FsError } from '@wrongstack/core';
|
|
3
3
|
import * as path8 from 'path';
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import * as fsp4 from 'fs/promises';
|
|
@@ -3836,6 +3836,141 @@ function buildStatsCommand(opts) {
|
|
|
3836
3836
|
}
|
|
3837
3837
|
};
|
|
3838
3838
|
}
|
|
3839
|
+
async function persistAutonomySetting(deps, mutator) {
|
|
3840
|
+
let raw;
|
|
3841
|
+
let fileExists = true;
|
|
3842
|
+
try {
|
|
3843
|
+
raw = await fsp4.readFile(deps.globalConfigPath, "utf8");
|
|
3844
|
+
} catch (err) {
|
|
3845
|
+
if (err.code !== "ENOENT") {
|
|
3846
|
+
throw new Error(`Could not read ${deps.globalConfigPath}: ${err.message}`);
|
|
3847
|
+
}
|
|
3848
|
+
fileExists = false;
|
|
3849
|
+
raw = "{}";
|
|
3850
|
+
}
|
|
3851
|
+
let parsed;
|
|
3852
|
+
try {
|
|
3853
|
+
parsed = JSON.parse(raw);
|
|
3854
|
+
} catch (err) {
|
|
3855
|
+
if (fileExists) {
|
|
3856
|
+
throw new Error(`Config at ${deps.globalConfigPath} is not valid JSON: ${err.message}`);
|
|
3857
|
+
}
|
|
3858
|
+
parsed = {};
|
|
3859
|
+
}
|
|
3860
|
+
const decrypted = decryptConfigSecrets$1(parsed, deps.vault);
|
|
3861
|
+
const autonomy = decrypted.autonomy ?? {};
|
|
3862
|
+
mutator(autonomy);
|
|
3863
|
+
decrypted.autonomy = autonomy;
|
|
3864
|
+
const encrypted = encryptConfigSecrets$1(decrypted, deps.vault);
|
|
3865
|
+
await atomicWrite(deps.globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
3866
|
+
deps.configStore.update({ autonomy: decrypted.autonomy });
|
|
3867
|
+
}
|
|
3868
|
+
async function persistTelegramConfig(deps, mutator) {
|
|
3869
|
+
let raw;
|
|
3870
|
+
let fileExists = true;
|
|
3871
|
+
try {
|
|
3872
|
+
raw = await fsp4.readFile(deps.globalConfigPath, "utf8");
|
|
3873
|
+
} catch (err) {
|
|
3874
|
+
if (err.code !== "ENOENT") {
|
|
3875
|
+
throw new Error(`Could not read ${deps.globalConfigPath}: ${err.message}`);
|
|
3876
|
+
}
|
|
3877
|
+
fileExists = false;
|
|
3878
|
+
raw = "{}";
|
|
3879
|
+
}
|
|
3880
|
+
let parsed;
|
|
3881
|
+
try {
|
|
3882
|
+
parsed = JSON.parse(raw);
|
|
3883
|
+
} catch (err) {
|
|
3884
|
+
if (fileExists) {
|
|
3885
|
+
throw new Error(`Config at ${deps.globalConfigPath} is not valid JSON: ${err.message}`);
|
|
3886
|
+
}
|
|
3887
|
+
parsed = {};
|
|
3888
|
+
}
|
|
3889
|
+
const decrypted = decryptConfigSecrets$1(parsed, deps.vault);
|
|
3890
|
+
const extensions = decrypted.extensions ?? {};
|
|
3891
|
+
const telegram = extensions.telegram ?? {};
|
|
3892
|
+
mutator(telegram);
|
|
3893
|
+
extensions.telegram = telegram;
|
|
3894
|
+
decrypted.extensions = extensions;
|
|
3895
|
+
const encrypted = encryptConfigSecrets$1(decrypted, deps.vault);
|
|
3896
|
+
await atomicWrite(deps.globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
3897
|
+
deps.configStore.update({ extensions: decrypted.extensions });
|
|
3898
|
+
}
|
|
3899
|
+
|
|
3900
|
+
// src/slash-commands/enhance.ts
|
|
3901
|
+
var noOpVault = {
|
|
3902
|
+
encrypt: (v) => v,
|
|
3903
|
+
decrypt: (v) => v,
|
|
3904
|
+
isEncrypted: () => false
|
|
3905
|
+
};
|
|
3906
|
+
function buildEnhanceCommand(opts) {
|
|
3907
|
+
const controller = opts.enhanceController;
|
|
3908
|
+
return {
|
|
3909
|
+
name: "enhance",
|
|
3910
|
+
description: 'Toggle prompt refinement ("did you mean this?") before sending.',
|
|
3911
|
+
help: [
|
|
3912
|
+
"Usage:",
|
|
3913
|
+
" /enhance Show current prompt-refinement status",
|
|
3914
|
+
" /enhance on Enable \u2014 refine free-text prompts before sending",
|
|
3915
|
+
" /enhance off Disable \u2014 send prompts verbatim",
|
|
3916
|
+
" /enhance toggle Flip the current state",
|
|
3917
|
+
"",
|
|
3918
|
+
"When on, each free-text message is rewritten into a clearer instruction",
|
|
3919
|
+
"by a separate LLM call and briefly previewed (auto-sends after a short",
|
|
3920
|
+
"countdown; Enter sends now, Esc keeps your original, e edits). Persisted",
|
|
3921
|
+
"to ~/.wrongstack/config.json (autonomy.enhance)."
|
|
3922
|
+
].join("\n"),
|
|
3923
|
+
async run(args) {
|
|
3924
|
+
if (!controller) {
|
|
3925
|
+
const msg2 = "Prompt refinement is not available in this session.";
|
|
3926
|
+
opts.renderer.writeWarning(msg2);
|
|
3927
|
+
return { message: msg2 };
|
|
3928
|
+
}
|
|
3929
|
+
const arg = args.trim().toLowerCase();
|
|
3930
|
+
if (!arg) {
|
|
3931
|
+
const status = controller.enabled ? `${color.cyan("ON")} ${color.dim("(prompts are refined before sending)")}` : `${color.green("OFF")} ${color.dim("(prompts are sent verbatim)")}`;
|
|
3932
|
+
const msg2 = `Prompt refinement: ${status}`;
|
|
3933
|
+
opts.renderer.write(msg2);
|
|
3934
|
+
return { message: msg2 };
|
|
3935
|
+
}
|
|
3936
|
+
let newState;
|
|
3937
|
+
if (arg === "on" || arg === "enable" || arg === "true" || arg === "1") {
|
|
3938
|
+
newState = true;
|
|
3939
|
+
} else if (arg === "off" || arg === "disable" || arg === "false" || arg === "0") {
|
|
3940
|
+
newState = false;
|
|
3941
|
+
} else if (arg === "toggle") {
|
|
3942
|
+
newState = !controller.enabled;
|
|
3943
|
+
} else {
|
|
3944
|
+
const msg2 = `Unknown argument: ${arg}. Use /enhance on, /enhance off, or /enhance toggle.`;
|
|
3945
|
+
opts.renderer.writeWarning(msg2);
|
|
3946
|
+
return { message: msg2 };
|
|
3947
|
+
}
|
|
3948
|
+
controller.setEnabled(newState);
|
|
3949
|
+
if (opts.configStore && opts.paths) {
|
|
3950
|
+
try {
|
|
3951
|
+
await persistAutonomySetting(
|
|
3952
|
+
{
|
|
3953
|
+
configStore: opts.configStore,
|
|
3954
|
+
globalConfigPath: opts.paths.globalConfig,
|
|
3955
|
+
vault: noOpVault
|
|
3956
|
+
},
|
|
3957
|
+
(autonomy) => {
|
|
3958
|
+
autonomy.enhance = newState;
|
|
3959
|
+
}
|
|
3960
|
+
);
|
|
3961
|
+
} catch (err) {
|
|
3962
|
+
opts.renderer.writeWarning(
|
|
3963
|
+
`Toggle applied for this session but could not be saved: ${err.message}`
|
|
3964
|
+
);
|
|
3965
|
+
}
|
|
3966
|
+
}
|
|
3967
|
+
const label = newState ? `${color.cyan("ENABLED")} \u2014 free-text prompts will be refined before sending` : `${color.green("DISABLED")} \u2014 prompts are sent verbatim`;
|
|
3968
|
+
const msg = `Prompt refinement: ${label}`;
|
|
3969
|
+
opts.renderer.write(msg);
|
|
3970
|
+
return { message: msg };
|
|
3971
|
+
}
|
|
3972
|
+
};
|
|
3973
|
+
}
|
|
3839
3974
|
|
|
3840
3975
|
// src/slash-commands/fix-classifier.ts
|
|
3841
3976
|
var TS = ["typescript-strict"];
|
|
@@ -5557,7 +5692,7 @@ function buildModeCommand(opts) {
|
|
|
5557
5692
|
" /mode brief Switch to brief mode",
|
|
5558
5693
|
" /mode teach Switch to teach mode"
|
|
5559
5694
|
].join("\n"),
|
|
5560
|
-
async run(args,
|
|
5695
|
+
async run(args, ctx) {
|
|
5561
5696
|
const modeStore = opts.modeStore;
|
|
5562
5697
|
if (!modeStore) {
|
|
5563
5698
|
return { message: "Mode store not available in this context." };
|
|
@@ -5571,6 +5706,7 @@ function buildModeCommand(opts) {
|
|
|
5571
5706
|
return { message: "Mode selection cancelled." };
|
|
5572
5707
|
}
|
|
5573
5708
|
await modeStore.setActiveMode(selected.id);
|
|
5709
|
+
ctx?.state?.setMeta?.("mode", selected.id);
|
|
5574
5710
|
return {
|
|
5575
5711
|
message: `Switched to "${selected.name}" mode.
|
|
5576
5712
|
${selected.description}`
|
|
@@ -5590,6 +5726,7 @@ ${selected.description}`
|
|
|
5590
5726
|
return { message: `Unknown mode "${target}". Available: ${available}` };
|
|
5591
5727
|
}
|
|
5592
5728
|
await modeStore.setActiveMode(targetMode.id);
|
|
5729
|
+
ctx?.state?.setMeta?.("mode", targetMode.id);
|
|
5593
5730
|
return {
|
|
5594
5731
|
message: `Switched to "${targetMode.name}" mode.
|
|
5595
5732
|
${targetMode.description}`
|
|
@@ -5597,7 +5734,7 @@ ${targetMode.description}`
|
|
|
5597
5734
|
}
|
|
5598
5735
|
};
|
|
5599
5736
|
}
|
|
5600
|
-
var
|
|
5737
|
+
var noOpVault2 = {
|
|
5601
5738
|
encrypt: (v) => v,
|
|
5602
5739
|
decrypt: (v) => v,
|
|
5603
5740
|
isEncrypted: () => false
|
|
@@ -5620,9 +5757,9 @@ async function patchGlobalConfig(globalConfigPath, mutate) {
|
|
|
5620
5757
|
}
|
|
5621
5758
|
parsed = {};
|
|
5622
5759
|
}
|
|
5623
|
-
const decrypted = decryptConfigSecrets$1(parsed,
|
|
5760
|
+
const decrypted = decryptConfigSecrets$1(parsed, noOpVault2);
|
|
5624
5761
|
mutate(decrypted);
|
|
5625
|
-
const encrypted = encryptConfigSecrets$1(decrypted,
|
|
5762
|
+
const encrypted = encryptConfigSecrets$1(decrypted, noOpVault2);
|
|
5626
5763
|
await atomicWrite(globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
5627
5764
|
return decrypted;
|
|
5628
5765
|
}
|
|
@@ -6072,7 +6209,7 @@ function summariseEvent(ev) {
|
|
|
6072
6209
|
return color.dim("\u2026");
|
|
6073
6210
|
}
|
|
6074
6211
|
}
|
|
6075
|
-
var
|
|
6212
|
+
var noOpVault3 = {
|
|
6076
6213
|
encrypt: (v) => v,
|
|
6077
6214
|
decrypt: (v) => v,
|
|
6078
6215
|
isEncrypted: () => false
|
|
@@ -6124,9 +6261,9 @@ async function patchGlobalConfig2(globalConfigPath, mutate) {
|
|
|
6124
6261
|
throw new Error(`Config at ${globalConfigPath} is not valid JSON: ${err.message}`);
|
|
6125
6262
|
parsed = {};
|
|
6126
6263
|
}
|
|
6127
|
-
const decrypted = decryptConfigSecrets$1(parsed,
|
|
6264
|
+
const decrypted = decryptConfigSecrets$1(parsed, noOpVault3);
|
|
6128
6265
|
mutate(decrypted);
|
|
6129
|
-
const encrypted = encryptConfigSecrets$1(decrypted,
|
|
6266
|
+
const encrypted = encryptConfigSecrets$1(decrypted, noOpVault3);
|
|
6130
6267
|
await atomicWrite(globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
6131
6268
|
return decrypted;
|
|
6132
6269
|
}
|
|
@@ -6286,38 +6423,7 @@ function buildSetModelCommand(opts) {
|
|
|
6286
6423
|
}
|
|
6287
6424
|
};
|
|
6288
6425
|
}
|
|
6289
|
-
|
|
6290
|
-
let raw;
|
|
6291
|
-
let fileExists = true;
|
|
6292
|
-
try {
|
|
6293
|
-
raw = await fsp4.readFile(deps.globalConfigPath, "utf8");
|
|
6294
|
-
} catch (err) {
|
|
6295
|
-
if (err.code !== "ENOENT") {
|
|
6296
|
-
throw new Error(`Could not read ${deps.globalConfigPath}: ${err.message}`);
|
|
6297
|
-
}
|
|
6298
|
-
fileExists = false;
|
|
6299
|
-
raw = "{}";
|
|
6300
|
-
}
|
|
6301
|
-
let parsed;
|
|
6302
|
-
try {
|
|
6303
|
-
parsed = JSON.parse(raw);
|
|
6304
|
-
} catch (err) {
|
|
6305
|
-
if (fileExists) {
|
|
6306
|
-
throw new Error(`Config at ${deps.globalConfigPath} is not valid JSON: ${err.message}`);
|
|
6307
|
-
}
|
|
6308
|
-
parsed = {};
|
|
6309
|
-
}
|
|
6310
|
-
const decrypted = decryptConfigSecrets$1(parsed, deps.vault);
|
|
6311
|
-
const autonomy = decrypted.autonomy ?? {};
|
|
6312
|
-
mutator(autonomy);
|
|
6313
|
-
decrypted.autonomy = autonomy;
|
|
6314
|
-
const encrypted = encryptConfigSecrets$1(decrypted, deps.vault);
|
|
6315
|
-
await atomicWrite(deps.globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
6316
|
-
deps.configStore.update({ autonomy: decrypted.autonomy });
|
|
6317
|
-
}
|
|
6318
|
-
|
|
6319
|
-
// src/slash-commands/settings.ts
|
|
6320
|
-
var noOpVault3 = {
|
|
6426
|
+
var noOpVault4 = {
|
|
6321
6427
|
encrypt: (v) => v,
|
|
6322
6428
|
decrypt: (v) => v,
|
|
6323
6429
|
isEncrypted: () => false
|
|
@@ -6382,7 +6488,7 @@ function buildSettingsCommand(opts) {
|
|
|
6382
6488
|
const persistDeps = {
|
|
6383
6489
|
configStore: opts.configStore,
|
|
6384
6490
|
globalConfigPath: opts.paths.globalConfig,
|
|
6385
|
-
vault:
|
|
6491
|
+
vault: noOpVault4
|
|
6386
6492
|
};
|
|
6387
6493
|
try {
|
|
6388
6494
|
if (sub === "delay") {
|
|
@@ -6426,6 +6532,157 @@ function buildSettingsCommand(opts) {
|
|
|
6426
6532
|
}
|
|
6427
6533
|
};
|
|
6428
6534
|
}
|
|
6535
|
+
var noOpVault5 = {
|
|
6536
|
+
encrypt: (v) => v,
|
|
6537
|
+
decrypt: (v) => v,
|
|
6538
|
+
isEncrypted: () => false
|
|
6539
|
+
};
|
|
6540
|
+
var HELP = [
|
|
6541
|
+
"Usage:",
|
|
6542
|
+
" /telegram-setup Show setup instructions",
|
|
6543
|
+
" /telegram-setup <botToken> Validate and save bot token",
|
|
6544
|
+
" /telegram-setup <botToken> <chatId> Save token and default chat ID",
|
|
6545
|
+
"",
|
|
6546
|
+
"Aliases: /tg-setup",
|
|
6547
|
+
"",
|
|
6548
|
+
"Quick start:",
|
|
6549
|
+
" 1. Message @BotFather on Telegram \u2192 /newbot \u2192 copy the token",
|
|
6550
|
+
" 2. Message your new bot, then visit:",
|
|
6551
|
+
" https://api.telegram.org/bot<TOKEN>/getUpdates",
|
|
6552
|
+
" Copy the chat.id from the JSON response.",
|
|
6553
|
+
" 3. Run: /telegram-setup <botToken> <chatId>",
|
|
6554
|
+
" 4. Restart WrongStack to activate the plugin."
|
|
6555
|
+
].join("\n");
|
|
6556
|
+
function buildTelegramSetupCommand(opts) {
|
|
6557
|
+
return {
|
|
6558
|
+
name: "telegram-setup",
|
|
6559
|
+
aliases: ["tg-setup"],
|
|
6560
|
+
description: "Configure Telegram bot token and default chat. /telegram-setup <token> [chatId]",
|
|
6561
|
+
argsHint: "[botToken] [chatId]",
|
|
6562
|
+
help: HELP,
|
|
6563
|
+
async run(args) {
|
|
6564
|
+
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
6565
|
+
const sub = (parts[0] ?? "").toLowerCase();
|
|
6566
|
+
if (sub === "help" || sub === "--help" || sub === "-h") {
|
|
6567
|
+
return { message: HELP };
|
|
6568
|
+
}
|
|
6569
|
+
if (!sub) {
|
|
6570
|
+
const config = opts.configStore.get();
|
|
6571
|
+
const hasTelegram = (config.plugins ?? []).some((p) => {
|
|
6572
|
+
const name = typeof p === "string" ? p : p.name;
|
|
6573
|
+
return name === "@wrongstack/telegram" || name === "telegram";
|
|
6574
|
+
});
|
|
6575
|
+
const lines = [
|
|
6576
|
+
`${color.bold("Telegram Setup")}`,
|
|
6577
|
+
""
|
|
6578
|
+
];
|
|
6579
|
+
if (!hasTelegram) {
|
|
6580
|
+
lines.push(
|
|
6581
|
+
`${color.amber("\u26A0")} Telegram plugin is not installed.`,
|
|
6582
|
+
` Run: ${color.cyan("/plugin install telegram")}`,
|
|
6583
|
+
` Then run ${color.cyan("/telegram-setup <botToken>")} to configure it.`,
|
|
6584
|
+
""
|
|
6585
|
+
);
|
|
6586
|
+
}
|
|
6587
|
+
lines.push(
|
|
6588
|
+
"1. Create a bot: message @BotFather \u2192 /newbot \u2192 copy the token",
|
|
6589
|
+
"2. Get your chat ID: message your bot, then open in browser:",
|
|
6590
|
+
` ${color.dim("https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates")}`,
|
|
6591
|
+
" Find chat.id in the JSON response.",
|
|
6592
|
+
"3. Configure: /telegram-setup <botToken> <chatId>",
|
|
6593
|
+
"4. Restart WrongStack."
|
|
6594
|
+
);
|
|
6595
|
+
return { message: lines.join("\n") };
|
|
6596
|
+
}
|
|
6597
|
+
const botToken = parts[0];
|
|
6598
|
+
const chatId = parts[1];
|
|
6599
|
+
if (!/^\d+:[A-Za-z0-9_-]+$/.test(botToken)) {
|
|
6600
|
+
return {
|
|
6601
|
+
message: [
|
|
6602
|
+
`${color.red("\u2717")} Invalid token format.`,
|
|
6603
|
+
`Expected: ${color.dim("123456789:ABCdefGHIjkl...")}`,
|
|
6604
|
+
`Got: ${botToken.slice(0, 20)}...`,
|
|
6605
|
+
"",
|
|
6606
|
+
"Get a valid token from @BotFather on Telegram."
|
|
6607
|
+
].join("\n")
|
|
6608
|
+
};
|
|
6609
|
+
}
|
|
6610
|
+
let botInfo;
|
|
6611
|
+
try {
|
|
6612
|
+
const res = await fetch(`https://api.telegram.org/bot${botToken}/getMe`, {
|
|
6613
|
+
signal: AbortSignal.timeout(1e4)
|
|
6614
|
+
});
|
|
6615
|
+
botInfo = await res.json();
|
|
6616
|
+
} catch (err) {
|
|
6617
|
+
return {
|
|
6618
|
+
message: [
|
|
6619
|
+
`${color.red("\u2717")} Could not reach Telegram API.`,
|
|
6620
|
+
`Error: ${err.message}`,
|
|
6621
|
+
"",
|
|
6622
|
+
"Check your network connection and try again."
|
|
6623
|
+
].join("\n")
|
|
6624
|
+
};
|
|
6625
|
+
}
|
|
6626
|
+
if (!botInfo.ok || !botInfo.result) {
|
|
6627
|
+
return {
|
|
6628
|
+
message: [
|
|
6629
|
+
`${color.red("\u2717")} Invalid bot token.`,
|
|
6630
|
+
`Telegram says: ${botInfo.description ?? "Unknown error"}`,
|
|
6631
|
+
"",
|
|
6632
|
+
"Get a valid token from @BotFather on Telegram."
|
|
6633
|
+
].join("\n")
|
|
6634
|
+
};
|
|
6635
|
+
}
|
|
6636
|
+
const bot = botInfo.result;
|
|
6637
|
+
const persistDeps = {
|
|
6638
|
+
configStore: opts.configStore,
|
|
6639
|
+
globalConfigPath: opts.paths?.globalConfig ?? "",
|
|
6640
|
+
vault: noOpVault5
|
|
6641
|
+
};
|
|
6642
|
+
if (!persistDeps.globalConfigPath) {
|
|
6643
|
+
return {
|
|
6644
|
+
message: `${color.red("\u2717")} Config path not available. Cannot persist settings.`
|
|
6645
|
+
};
|
|
6646
|
+
}
|
|
6647
|
+
try {
|
|
6648
|
+
await persistTelegramConfig(persistDeps, (telegram) => {
|
|
6649
|
+
telegram.botToken = botToken;
|
|
6650
|
+
if (chatId) {
|
|
6651
|
+
telegram.notifyChatId = /^\d+$/.test(chatId) ? Number(chatId) : chatId;
|
|
6652
|
+
}
|
|
6653
|
+
if (telegram.notifyOnSessionEnd === void 0) {
|
|
6654
|
+
telegram.notifyOnSessionEnd = true;
|
|
6655
|
+
}
|
|
6656
|
+
});
|
|
6657
|
+
const chatLine = chatId ? `
|
|
6658
|
+
Default chat: ${color.green(chatId)}` : `
|
|
6659
|
+
${color.dim("No default chat set. You can add it later: /telegram-setup <token> <chatId>")}`;
|
|
6660
|
+
return {
|
|
6661
|
+
message: [
|
|
6662
|
+
`${color.green("\u2713")} Telegram configured successfully!`,
|
|
6663
|
+
"",
|
|
6664
|
+
`Bot: ${color.bold(`@${bot.username ?? bot.first_name}`)} ${color.dim(`(id=${bot.id})`)}`,
|
|
6665
|
+
`Name: ${bot.first_name}`,
|
|
6666
|
+
chatLine,
|
|
6667
|
+
"",
|
|
6668
|
+
`${color.amber("\u26A0")} Restart WrongStack for the plugin to pick up the new config.`,
|
|
6669
|
+
"",
|
|
6670
|
+
"After restart, try:",
|
|
6671
|
+
` ${color.cyan("/telegram:status")} \u2014 check bot connection`,
|
|
6672
|
+
` ${color.cyan("/telegram:send")} \u2014 send a test message`
|
|
6673
|
+
].join("\n")
|
|
6674
|
+
};
|
|
6675
|
+
} catch (err) {
|
|
6676
|
+
return {
|
|
6677
|
+
message: [
|
|
6678
|
+
`${color.red("\u2717")} Failed to save config.`,
|
|
6679
|
+
`Error: ${err.message}`
|
|
6680
|
+
].join("\n")
|
|
6681
|
+
};
|
|
6682
|
+
}
|
|
6683
|
+
}
|
|
6684
|
+
};
|
|
6685
|
+
}
|
|
6429
6686
|
|
|
6430
6687
|
// src/slash-commands/spawn-agents.ts
|
|
6431
6688
|
function buildSpawnCommand(opts) {
|
|
@@ -6609,10 +6866,24 @@ function buildStatuslineCommand(deps) {
|
|
|
6609
6866
|
}
|
|
6610
6867
|
};
|
|
6611
6868
|
}
|
|
6869
|
+
function findTodo(todos, query) {
|
|
6870
|
+
const asIndex = Number.parseInt(query, 10);
|
|
6871
|
+
if (!Number.isNaN(asIndex)) {
|
|
6872
|
+
const idx = asIndex - 1;
|
|
6873
|
+
const item = todos[idx];
|
|
6874
|
+
if (item) return { idx, item };
|
|
6875
|
+
}
|
|
6876
|
+
const byId = todos.findIndex((t) => t.id === query);
|
|
6877
|
+
if (byId >= 0) return { idx: byId, item: todos[byId] };
|
|
6878
|
+
const q = query.toLowerCase();
|
|
6879
|
+
const byContent = todos.findIndex((t) => t.content.toLowerCase().includes(q));
|
|
6880
|
+
if (byContent >= 0) return { idx: byContent, item: todos[byContent] };
|
|
6881
|
+
return null;
|
|
6882
|
+
}
|
|
6612
6883
|
function buildTodosCommand(opts) {
|
|
6613
6884
|
return {
|
|
6614
6885
|
name: "todos",
|
|
6615
|
-
description: "Inspect or edit the live todo list: /todos [show|clear|add
|
|
6886
|
+
description: "Inspect or edit the live todo list: /todos [show|clear|add|done|remove|rm <id|index>]",
|
|
6616
6887
|
async run(args) {
|
|
6617
6888
|
const ctx = opts.context;
|
|
6618
6889
|
if (!ctx) return { message: "No active context." };
|
|
@@ -6626,36 +6897,50 @@ function buildTodosCommand(opts) {
|
|
|
6626
6897
|
}
|
|
6627
6898
|
case "clear": {
|
|
6628
6899
|
const n = ctx.todos.length;
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
};
|
|
6900
|
+
if (n === 0) return { message: "Todos were already empty." };
|
|
6901
|
+
ctx.state.replaceTodos([]);
|
|
6902
|
+
return { message: `Cleared ${n} todo${n === 1 ? "" : "s"}.` };
|
|
6633
6903
|
}
|
|
6634
6904
|
case "add": {
|
|
6635
6905
|
if (!restJoined) return { message: "Usage: /todos add <text>" };
|
|
6636
|
-
|
|
6906
|
+
const item = {
|
|
6637
6907
|
id: `todo_${Date.now()}_${randomUUID().slice(0, 7)}`,
|
|
6638
6908
|
content: restJoined,
|
|
6639
6909
|
status: "pending"
|
|
6640
|
-
}
|
|
6910
|
+
};
|
|
6911
|
+
ctx.state.replaceTodos([...ctx.todos, item]);
|
|
6641
6912
|
return { message: `Added: ${restJoined}` };
|
|
6642
6913
|
}
|
|
6643
6914
|
case "done":
|
|
6644
6915
|
case "complete": {
|
|
6645
6916
|
if (!restJoined) return { message: "Usage: /todos done <id|index>" };
|
|
6646
|
-
const
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6917
|
+
const found = findTodo(ctx.todos, restJoined);
|
|
6918
|
+
if (!found) return { message: `No todo matched "${restJoined}".` };
|
|
6919
|
+
const doneItem = { ...found.item, status: "completed" };
|
|
6920
|
+
const nextTodos = [
|
|
6921
|
+
...ctx.todos.slice(0, found.idx),
|
|
6922
|
+
doneItem,
|
|
6923
|
+
...ctx.todos.slice(found.idx + 1)
|
|
6924
|
+
];
|
|
6925
|
+
ctx.state.replaceTodos(nextTodos);
|
|
6926
|
+
return { message: `Marked done: ${doneItem.content}` };
|
|
6927
|
+
}
|
|
6928
|
+
case "remove":
|
|
6929
|
+
case "rm":
|
|
6930
|
+
case "delete": {
|
|
6931
|
+
if (!restJoined) return { message: "Usage: /todos remove <id|index>" };
|
|
6932
|
+
const found = findTodo(ctx.todos, restJoined);
|
|
6933
|
+
if (!found) return { message: `No todo matched "${restJoined}".` };
|
|
6934
|
+
const nextTodos = [
|
|
6935
|
+
...ctx.todos.slice(0, found.idx),
|
|
6936
|
+
...ctx.todos.slice(found.idx + 1)
|
|
6937
|
+
];
|
|
6938
|
+
ctx.state.replaceTodos(nextTodos);
|
|
6939
|
+
return { message: `Removed: ${found.item.content}` };
|
|
6655
6940
|
}
|
|
6656
6941
|
default:
|
|
6657
6942
|
return {
|
|
6658
|
-
message: `Unknown subcommand "${verb}". Try: show | clear | add <text> | done <id|index>`
|
|
6943
|
+
message: `Unknown subcommand "${verb}". Try: show | clear | add <text> | done <id|index> | remove <id|index>`
|
|
6659
6944
|
};
|
|
6660
6945
|
}
|
|
6661
6946
|
}
|
|
@@ -6790,6 +7075,7 @@ function buildBuiltinSlashCommands(opts) {
|
|
|
6790
7075
|
buildAgentsCommand(opts),
|
|
6791
7076
|
buildDirectorCommand(opts),
|
|
6792
7077
|
buildFleetCommand(opts),
|
|
7078
|
+
buildEnhanceCommand(opts),
|
|
6793
7079
|
buildMemoryCommand(opts),
|
|
6794
7080
|
buildTodosCommand(opts),
|
|
6795
7081
|
buildSddCommand(opts),
|
|
@@ -6806,6 +7092,7 @@ function buildBuiltinSlashCommands(opts) {
|
|
|
6806
7092
|
buildAutoPhaseCommand(opts),
|
|
6807
7093
|
buildWorktreeCommand(opts),
|
|
6808
7094
|
buildSettingsCommand(opts),
|
|
7095
|
+
buildTelegramSetupCommand(opts),
|
|
6809
7096
|
buildSetModelCommand(opts),
|
|
6810
7097
|
buildModelsCommand(opts),
|
|
6811
7098
|
buildCollabCommand(opts),
|
|
@@ -6859,7 +7146,7 @@ async function scaffoldAgentsMd(projectRoot) {
|
|
|
6859
7146
|
return file;
|
|
6860
7147
|
}
|
|
6861
7148
|
async function runProjectCheck(opts) {
|
|
6862
|
-
const { projectRoot, renderer, reader } = opts;
|
|
7149
|
+
const { projectRoot, cwd, renderer, reader } = opts;
|
|
6863
7150
|
const kind = await detectProjectKind(projectRoot);
|
|
6864
7151
|
if (kind === "initialized") {
|
|
6865
7152
|
renderer.write(
|
|
@@ -6919,7 +7206,7 @@ async function runProjectCheck(opts) {
|
|
|
6919
7206
|
try {
|
|
6920
7207
|
const { spawn: spawn3 } = await import('child_process');
|
|
6921
7208
|
await new Promise((resolve5, reject) => {
|
|
6922
|
-
const child = spawn3("git", ["init"], { cwd
|
|
7209
|
+
const child = spawn3("git", ["init"], { cwd });
|
|
6923
7210
|
child.on("error", reject);
|
|
6924
7211
|
child.on("close", (code) => code === 0 ? resolve5() : reject(new Error(`git init failed with ${code}`)));
|
|
6925
7212
|
});
|
|
@@ -7590,11 +7877,11 @@ async function restoreLast(homeFn = defaultHomeDir) {
|
|
|
7590
7877
|
var theme = { primary: color.amber };
|
|
7591
7878
|
async function saveToGlobalConfig(configPath2, provider, model, homeFn = () => process.env.HOME ?? os2__default.homedir()) {
|
|
7592
7879
|
try {
|
|
7593
|
-
const { atomicWrite:
|
|
7594
|
-
const
|
|
7880
|
+
const { atomicWrite: atomicWrite15 } = await import('@wrongstack/core');
|
|
7881
|
+
const fs27 = await import('fs/promises');
|
|
7595
7882
|
let existing = {};
|
|
7596
7883
|
try {
|
|
7597
|
-
const raw = await
|
|
7884
|
+
const raw = await fs27.readFile(configPath2, "utf8");
|
|
7598
7885
|
existing = JSON.parse(raw);
|
|
7599
7886
|
} catch {
|
|
7600
7887
|
}
|
|
@@ -7606,7 +7893,7 @@ async function saveToGlobalConfig(configPath2, provider, model, homeFn = () => p
|
|
|
7606
7893
|
} catch (err) {
|
|
7607
7894
|
console.warn("[picker] backupCurrent failed:", err);
|
|
7608
7895
|
}
|
|
7609
|
-
await
|
|
7896
|
+
await atomicWrite15(configPath2, JSON.stringify(existing, null, 2), { mode: 384 });
|
|
7610
7897
|
try {
|
|
7611
7898
|
await appendHistory(
|
|
7612
7899
|
oldCfg,
|
|
@@ -10854,10 +11141,10 @@ var auditCmd = async (args, deps) => {
|
|
|
10854
11141
|
return verify.ok ? 0 : 1;
|
|
10855
11142
|
};
|
|
10856
11143
|
async function listAudits(log, dir, deps) {
|
|
10857
|
-
const
|
|
11144
|
+
const fs27 = await import('fs/promises');
|
|
10858
11145
|
let entries;
|
|
10859
11146
|
try {
|
|
10860
|
-
entries = await
|
|
11147
|
+
entries = await fs27.readdir(dir);
|
|
10861
11148
|
} catch {
|
|
10862
11149
|
deps.renderer.write(
|
|
10863
11150
|
color.dim(`No sessions dir found at ${dir}. Run a session first.`) + "\n"
|
|
@@ -11008,22 +11295,22 @@ function fmtDuration(ms) {
|
|
|
11008
11295
|
const remMin = m - h * 60;
|
|
11009
11296
|
return `${h}h${remMin}m`;
|
|
11010
11297
|
}
|
|
11011
|
-
function fmtTaskResultLine(r,
|
|
11298
|
+
function fmtTaskResultLine(r, color51) {
|
|
11012
11299
|
const stats = `${r.iterations}it ${r.toolCalls}tc ${fmtDuration(r.durationMs)}`;
|
|
11013
11300
|
const errMsg = typeof r.error === "string" ? r.error : r.error?.message;
|
|
11014
11301
|
const errKind = typeof r.error === "object" ? r.error?.kind : void 0;
|
|
11015
11302
|
const errTail = errMsg ? ` \u2014 ${errMsg.replace(/\s+/g, " ").slice(0, 80)}${errMsg.length > 80 ? "\u2026" : ""}` : "";
|
|
11016
|
-
const errKindChip = errKind ?
|
|
11017
|
-
const errSnip = errMsg || errKind ? `${errKindChip}${
|
|
11303
|
+
const errKindChip = errKind ? color51.dim(` [${errKind}]`) : "";
|
|
11304
|
+
const errSnip = errMsg || errKind ? `${errKindChip}${color51.dim(errTail)}` : "";
|
|
11018
11305
|
switch (r.status) {
|
|
11019
11306
|
case "success":
|
|
11020
|
-
return { mark:
|
|
11307
|
+
return { mark: color51.green("\u2713"), stats, tail: "" };
|
|
11021
11308
|
case "timeout":
|
|
11022
|
-
return { mark:
|
|
11309
|
+
return { mark: color51.yellow("\u23F1"), stats: `${color51.yellow("timeout")} ${stats}`, tail: errSnip };
|
|
11023
11310
|
case "stopped":
|
|
11024
|
-
return { mark:
|
|
11311
|
+
return { mark: color51.dim("\u2298"), stats: `${color51.dim("stopped")} ${stats}`, tail: errSnip };
|
|
11025
11312
|
case "failed":
|
|
11026
|
-
return { mark:
|
|
11313
|
+
return { mark: color51.red("\u2717"), stats: `${color51.red("failed")} ${stats}`, tail: errSnip };
|
|
11027
11314
|
}
|
|
11028
11315
|
}
|
|
11029
11316
|
|
|
@@ -11067,7 +11354,15 @@ async function boot(argv) {
|
|
|
11067
11354
|
const { paths, config: _config, vault } = bootResult;
|
|
11068
11355
|
let config = _config;
|
|
11069
11356
|
const { cwd, projectRoot, userHome, wpaths, pathResolver } = paths;
|
|
11070
|
-
const logger = new DefaultLogger({
|
|
11357
|
+
const logger = new DefaultLogger({
|
|
11358
|
+
level: config.log.level,
|
|
11359
|
+
file: wpaths.logFile,
|
|
11360
|
+
// Suppress stderr output in TUI mode: plugin/library log messages
|
|
11361
|
+
// (e.g. Telegram "getUpdates failed") write directly to stderr and
|
|
11362
|
+
// bypass Ink, which breaks the Static/live boundary in non-altScreen
|
|
11363
|
+
// mode. Logs still go to the disk file for post-hoc debugging.
|
|
11364
|
+
stderr: !flags.tui
|
|
11365
|
+
});
|
|
11071
11366
|
const renderer = new TerminalRenderer();
|
|
11072
11367
|
const reader = new ReadlineInputReader({ historyFile: wpaths.historyFile });
|
|
11073
11368
|
const modelsRegistry = new DefaultModelsRegistry({
|
|
@@ -11137,7 +11432,7 @@ async function boot(argv) {
|
|
|
11137
11432
|
const isSingleShot = positional.length > 0 || typeof flags["prompt"] === "string";
|
|
11138
11433
|
const isInteractiveTTY = isStdinTTY() && !isSingleShot;
|
|
11139
11434
|
if (isInteractiveTTY) {
|
|
11140
|
-
const cont = await runProjectCheck({ projectRoot, renderer, reader });
|
|
11435
|
+
const cont = await runProjectCheck({ projectRoot, cwd, renderer, reader });
|
|
11141
11436
|
if (!cont) {
|
|
11142
11437
|
await reader.close();
|
|
11143
11438
|
return 0;
|
|
@@ -12252,6 +12547,7 @@ async function execute(deps) {
|
|
|
12252
12547
|
director,
|
|
12253
12548
|
fleetRoster,
|
|
12254
12549
|
fleetStreamController,
|
|
12550
|
+
enhanceController,
|
|
12255
12551
|
statuslineHiddenItems,
|
|
12256
12552
|
setStatuslineHiddenItems,
|
|
12257
12553
|
agentsMonitorController,
|
|
@@ -12263,7 +12559,8 @@ async function execute(deps) {
|
|
|
12263
12559
|
getParallelEngine,
|
|
12264
12560
|
subscribeEternalIteration,
|
|
12265
12561
|
subscribeEternalStage,
|
|
12266
|
-
skillLoader
|
|
12562
|
+
skillLoader,
|
|
12563
|
+
modeId
|
|
12267
12564
|
} = deps;
|
|
12268
12565
|
let code = 0;
|
|
12269
12566
|
let fleetStatusLine = null;
|
|
@@ -12462,10 +12759,31 @@ async function execute(deps) {
|
|
|
12462
12759
|
return null;
|
|
12463
12760
|
},
|
|
12464
12761
|
getSettings: () => {
|
|
12465
|
-
const
|
|
12762
|
+
const cfg = configStore.get();
|
|
12763
|
+
const autonomy = cfg.autonomy;
|
|
12466
12764
|
const rawMode = autonomy?.defaultMode;
|
|
12467
12765
|
const mode = rawMode === "suggest" || rawMode === "auto" ? rawMode : "off";
|
|
12468
|
-
return {
|
|
12766
|
+
return {
|
|
12767
|
+
mode,
|
|
12768
|
+
delayMs: autonomy?.autoProceedDelayMs ?? 45e3,
|
|
12769
|
+
titleAnimation: autonomy?.terminalTitleAnimation !== false,
|
|
12770
|
+
yolo: autonomy?.yolo ?? false,
|
|
12771
|
+
streamFleet: autonomy?.streamFleet !== false,
|
|
12772
|
+
chime: autonomy?.chime ?? false,
|
|
12773
|
+
confirmExit: autonomy?.confirmExit !== false,
|
|
12774
|
+
nextPrediction: cfg.nextPrediction ?? false,
|
|
12775
|
+
featureMcp: cfg.features?.mcp !== false,
|
|
12776
|
+
featurePlugins: cfg.features?.plugins !== false,
|
|
12777
|
+
featureMemory: cfg.features?.memory !== false,
|
|
12778
|
+
featureSkills: cfg.features?.skills !== false,
|
|
12779
|
+
featureModelsRegistry: cfg.features?.modelsRegistry !== false,
|
|
12780
|
+
contextAutoCompact: cfg.context?.autoCompact !== false,
|
|
12781
|
+
contextStrategy: cfg.context?.strategy ?? "hybrid",
|
|
12782
|
+
logLevel: cfg.log?.level ?? "info",
|
|
12783
|
+
auditLevel: cfg.session?.auditLevel ?? "standard",
|
|
12784
|
+
indexOnStart: cfg.indexing?.onSessionStart !== false,
|
|
12785
|
+
maxIterations: cfg.tools?.maxIterations ?? 500
|
|
12786
|
+
};
|
|
12469
12787
|
},
|
|
12470
12788
|
async saveSettings(s) {
|
|
12471
12789
|
try {
|
|
@@ -12478,14 +12796,84 @@ async function execute(deps) {
|
|
|
12478
12796
|
(autonomy) => {
|
|
12479
12797
|
autonomy.defaultMode = s.mode;
|
|
12480
12798
|
autonomy.autoProceedDelayMs = s.delayMs;
|
|
12799
|
+
const a = autonomy;
|
|
12800
|
+
a["terminalTitleAnimation"] = s.titleAnimation ?? true;
|
|
12801
|
+
a["yolo"] = s.yolo ?? false;
|
|
12802
|
+
a["streamFleet"] = s.streamFleet ?? true;
|
|
12803
|
+
a["chime"] = s.chime ?? false;
|
|
12804
|
+
a["confirmExit"] = s.confirmExit ?? true;
|
|
12481
12805
|
}
|
|
12482
12806
|
);
|
|
12807
|
+
if (s.featureMcp !== void 0 || s.featurePlugins !== void 0 || s.featureMemory !== void 0 || s.featureSkills !== void 0 || s.featureModelsRegistry !== void 0 || s.contextAutoCompact !== void 0 || s.contextStrategy !== void 0 || s.logLevel !== void 0 || s.auditLevel !== void 0 || s.indexOnStart !== void 0 || s.maxIterations !== void 0 || s.nextPrediction !== void 0) {
|
|
12808
|
+
const raw = await fsp4.readFile(wpaths.globalConfig, "utf8").catch(() => "{}");
|
|
12809
|
+
const parsed = JSON.parse(raw);
|
|
12810
|
+
const vault = { encrypt: (v) => v, decrypt: (v) => v, isEncrypted: () => false };
|
|
12811
|
+
const decrypted = decryptConfigSecrets$1(parsed, vault);
|
|
12812
|
+
if (s.nextPrediction !== void 0) {
|
|
12813
|
+
decrypted.nextPrediction = s.nextPrediction;
|
|
12814
|
+
}
|
|
12815
|
+
if (s.featureMcp !== void 0 || s.featurePlugins !== void 0 || s.featureMemory !== void 0 || s.featureSkills !== void 0 || s.featureModelsRegistry !== void 0) {
|
|
12816
|
+
const feats = decrypted.features ?? {};
|
|
12817
|
+
if (s.featureMcp !== void 0) feats.mcp = s.featureMcp;
|
|
12818
|
+
if (s.featurePlugins !== void 0) feats.plugins = s.featurePlugins;
|
|
12819
|
+
if (s.featureMemory !== void 0) feats.memory = s.featureMemory;
|
|
12820
|
+
if (s.featureSkills !== void 0) feats.skills = s.featureSkills;
|
|
12821
|
+
if (s.featureModelsRegistry !== void 0) feats.modelsRegistry = s.featureModelsRegistry;
|
|
12822
|
+
decrypted.features = feats;
|
|
12823
|
+
}
|
|
12824
|
+
if (s.contextAutoCompact !== void 0 || s.contextStrategy !== void 0) {
|
|
12825
|
+
const ctx = decrypted.context ?? {};
|
|
12826
|
+
if (s.contextAutoCompact !== void 0) ctx.autoCompact = s.contextAutoCompact;
|
|
12827
|
+
if (s.contextStrategy !== void 0) ctx.strategy = s.contextStrategy;
|
|
12828
|
+
decrypted.context = ctx;
|
|
12829
|
+
}
|
|
12830
|
+
if (s.logLevel !== void 0) {
|
|
12831
|
+
const log = decrypted.log ?? {};
|
|
12832
|
+
log.level = s.logLevel;
|
|
12833
|
+
decrypted.log = log;
|
|
12834
|
+
}
|
|
12835
|
+
if (s.auditLevel !== void 0) {
|
|
12836
|
+
const sess = decrypted.session ?? {};
|
|
12837
|
+
sess.auditLevel = s.auditLevel;
|
|
12838
|
+
decrypted.session = sess;
|
|
12839
|
+
}
|
|
12840
|
+
if (s.indexOnStart !== void 0) {
|
|
12841
|
+
const idx = decrypted.indexing ?? {};
|
|
12842
|
+
idx.onSessionStart = s.indexOnStart;
|
|
12843
|
+
decrypted.indexing = idx;
|
|
12844
|
+
}
|
|
12845
|
+
if (s.maxIterations !== void 0) {
|
|
12846
|
+
const tools = decrypted.tools ?? {};
|
|
12847
|
+
tools.maxIterations = s.maxIterations;
|
|
12848
|
+
decrypted.tools = tools;
|
|
12849
|
+
}
|
|
12850
|
+
const encrypted = encryptConfigSecrets$1(decrypted, vault);
|
|
12851
|
+
await atomicWrite(wpaths.globalConfig, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
12852
|
+
configStore.update({
|
|
12853
|
+
...s.nextPrediction !== void 0 ? { nextPrediction: s.nextPrediction } : {},
|
|
12854
|
+
...s.featureMcp !== void 0 || s.featurePlugins !== void 0 || s.featureMemory !== void 0 || s.featureSkills !== void 0 || s.featureModelsRegistry !== void 0 ? { features: decrypted.features } : {},
|
|
12855
|
+
...s.contextAutoCompact !== void 0 || s.contextStrategy !== void 0 ? { context: decrypted.context } : {},
|
|
12856
|
+
...s.logLevel !== void 0 ? { log: decrypted.log } : {},
|
|
12857
|
+
...s.auditLevel !== void 0 ? { session: decrypted.session } : {},
|
|
12858
|
+
...s.indexOnStart !== void 0 ? { indexing: decrypted.indexing } : {},
|
|
12859
|
+
...s.maxIterations !== void 0 ? { tools: decrypted.tools } : {}
|
|
12860
|
+
});
|
|
12861
|
+
}
|
|
12862
|
+
if (s.streamFleet !== void 0) {
|
|
12863
|
+
fleetStreamController?.setEnabled(s.streamFleet);
|
|
12864
|
+
}
|
|
12483
12865
|
return null;
|
|
12484
12866
|
} catch (err) {
|
|
12485
12867
|
return err instanceof Error ? err.message : String(err);
|
|
12486
12868
|
}
|
|
12487
12869
|
},
|
|
12488
12870
|
effectiveMaxContext,
|
|
12871
|
+
// Terminal title animation: read from config (default on).
|
|
12872
|
+
titleAnimation: config.autonomy?.["terminalTitleAnimation"] ?? true,
|
|
12873
|
+
// Completion chime: terminal bell when agent finishes.
|
|
12874
|
+
chime: config.autonomy?.["chime"] ?? false,
|
|
12875
|
+
// Confirm before exit: show "confirm exit" prompt on Ctrl+C.
|
|
12876
|
+
confirmExit: config.autonomy?.["confirmExit"] ?? true,
|
|
12489
12877
|
// Default OFF so the terminal's native scrollback works for chat
|
|
12490
12878
|
// history out of the box. Users who hit resize/overlay-leak
|
|
12491
12879
|
// artifacts can opt back into alt-screen with `--alt-screen`.
|
|
@@ -12503,6 +12891,7 @@ async function execute(deps) {
|
|
|
12503
12891
|
dispatch({ type: "resetContextChip" });
|
|
12504
12892
|
},
|
|
12505
12893
|
fleetStreamController,
|
|
12894
|
+
enhanceController,
|
|
12506
12895
|
statuslineHiddenItems,
|
|
12507
12896
|
setStatuslineHiddenItems,
|
|
12508
12897
|
agentsMonitorController,
|
|
@@ -12547,6 +12936,11 @@ async function execute(deps) {
|
|
|
12547
12936
|
}
|
|
12548
12937
|
}
|
|
12549
12938
|
return messages;
|
|
12939
|
+
},
|
|
12940
|
+
modeLabel: modeId,
|
|
12941
|
+
getModeLabel: () => {
|
|
12942
|
+
const metaMode = context.meta?.["mode"];
|
|
12943
|
+
return typeof metaMode === "string" ? metaMode : modeId ?? "default";
|
|
12550
12944
|
}
|
|
12551
12945
|
});
|
|
12552
12946
|
} finally {
|
|
@@ -14345,7 +14739,22 @@ var BUILTIN_PLUGIN_FACTORIES = [
|
|
|
14345
14739
|
async () => {
|
|
14346
14740
|
const { createPlanPlugin } = await import('@wrongstack/core');
|
|
14347
14741
|
return createPlanPlugin();
|
|
14348
|
-
}
|
|
14742
|
+
},
|
|
14743
|
+
// ── Workspace plugins (@wrongstack/plugins subpath exports) ──────────
|
|
14744
|
+
async () => (await import('@wrongstack/plugins/cost-tracker')).default,
|
|
14745
|
+
async () => (await import('@wrongstack/plugins/json-path')).default,
|
|
14746
|
+
async () => (await import('@wrongstack/plugins/web-search')).default,
|
|
14747
|
+
async () => (await import('@wrongstack/plugins/file-watcher')).default,
|
|
14748
|
+
async () => (await import('@wrongstack/plugins/git-autocommit')).default,
|
|
14749
|
+
async () => (await import('@wrongstack/plugins/auto-doc')).default,
|
|
14750
|
+
async () => (await import('@wrongstack/plugins/shell-check')).default,
|
|
14751
|
+
async () => (await import('@wrongstack/plugins/cron')).default,
|
|
14752
|
+
async () => (await import('@wrongstack/plugins/template-engine')).default,
|
|
14753
|
+
async () => (await import('@wrongstack/plugins/semver-bump')).default,
|
|
14754
|
+
// ── LSP plugin ──────────────────────────────────────────────────────
|
|
14755
|
+
async () => (await import('@wrongstack/plug-lsp')).default,
|
|
14756
|
+
// ── Telegram plugin ─────────────────────────────────────────────────
|
|
14757
|
+
async () => (await import('@wrongstack/telegram')).default
|
|
14349
14758
|
];
|
|
14350
14759
|
async function setupPlugins(params) {
|
|
14351
14760
|
const {
|
|
@@ -14951,6 +15360,17 @@ async function main(argv) {
|
|
|
14951
15360
|
}).catch(() => {
|
|
14952
15361
|
});
|
|
14953
15362
|
});
|
|
15363
|
+
const tuiOwnsScreen = flags.tui === true && flags["no-tui"] !== true;
|
|
15364
|
+
if (!tuiOwnsScreen) {
|
|
15365
|
+
events.on("delegate.started", (e) => {
|
|
15366
|
+
const task = e.task.length > 100 ? `${e.task.slice(0, 99)}\u2026` : e.task;
|
|
15367
|
+
renderer.writeInfo(`\u{1F91D} Delegating \u2192 ${e.target}: ${task}`);
|
|
15368
|
+
});
|
|
15369
|
+
events.on("delegate.completed", (e) => {
|
|
15370
|
+
const cost = e.costUsd && e.costUsd > 0 ? ` \xB7 $${e.costUsd.toFixed(3)}` : "";
|
|
15371
|
+
renderer.writeInfo(`${e.ok ? "\u2705" : "\u274C"} ${e.summary}${cost}`);
|
|
15372
|
+
});
|
|
15373
|
+
}
|
|
14954
15374
|
events.on("tool.progress", (e) => {
|
|
14955
15375
|
sessionBridge.append({
|
|
14956
15376
|
type: "tool_progress",
|
|
@@ -15199,7 +15619,10 @@ async function main(argv) {
|
|
|
15199
15619
|
// this, a subagent that hit its iteration cap returns an empty
|
|
15200
15620
|
// result and the host LLM has no idea what work was done.
|
|
15201
15621
|
sessionsRoot: subagentSessionsRoot,
|
|
15202
|
-
directorRunId: session.id
|
|
15622
|
+
directorRunId: session.id,
|
|
15623
|
+
// Host bus so `delegate` can emit start/finish events that the TUI,
|
|
15624
|
+
// plain CLI, and Telegram bridge render as readable lines.
|
|
15625
|
+
events
|
|
15203
15626
|
})
|
|
15204
15627
|
);
|
|
15205
15628
|
toolRegistry.register(
|
|
@@ -15231,6 +15654,12 @@ async function main(argv) {
|
|
|
15231
15654
|
this.enabled = enabled;
|
|
15232
15655
|
}
|
|
15233
15656
|
};
|
|
15657
|
+
const enhanceController = {
|
|
15658
|
+
enabled: config.autonomy?.["enhance"] ?? true,
|
|
15659
|
+
setEnabled(enabled) {
|
|
15660
|
+
this.enabled = enabled;
|
|
15661
|
+
}
|
|
15662
|
+
};
|
|
15234
15663
|
const statuslineConfigDeps = {
|
|
15235
15664
|
get: () => loadStatuslineConfig(),
|
|
15236
15665
|
set: (cfg) => saveStatuslineConfig(cfg)
|
|
@@ -15281,6 +15710,7 @@ async function main(argv) {
|
|
|
15281
15710
|
planPath,
|
|
15282
15711
|
modeStore,
|
|
15283
15712
|
fleetStreamController,
|
|
15713
|
+
enhanceController,
|
|
15284
15714
|
llmProvider: provider,
|
|
15285
15715
|
llmModel: config.model,
|
|
15286
15716
|
statuslineConfig: statuslineConfigDeps,
|
|
@@ -15994,6 +16424,7 @@ Restart WrongStack to load or unload plugin code in this session.`;
|
|
|
15994
16424
|
director: director ?? null,
|
|
15995
16425
|
fleetRoster: FLEET_ROSTER,
|
|
15996
16426
|
fleetStreamController,
|
|
16427
|
+
enhanceController,
|
|
15997
16428
|
statuslineHiddenItems,
|
|
15998
16429
|
setStatuslineHiddenItems,
|
|
15999
16430
|
getYolo: () => {
|
|
@@ -16019,7 +16450,8 @@ Restart WrongStack to load or unload plugin code in this session.`;
|
|
|
16019
16450
|
stageListeners.add(fn);
|
|
16020
16451
|
return () => stageListeners.delete(fn);
|
|
16021
16452
|
},
|
|
16022
|
-
skillLoader: config.features.skills ? skillLoader : void 0
|
|
16453
|
+
skillLoader: config.features.skills ? skillLoader : void 0,
|
|
16454
|
+
modeId
|
|
16023
16455
|
});
|
|
16024
16456
|
}
|
|
16025
16457
|
var isMain = import.meta.url === `file://${process.argv[1]?.replace(/\\/g, "/")}` || process.argv[1]?.endsWith("/cli/dist/index.js") || process.argv[1]?.endsWith("\\cli\\dist\\index.js");
|