@bike4mind/cli 0.6.1 → 0.8.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/{ConfigStore-Dt6utdSA.mjs → ConfigStore-Bj1IOvWn.mjs} +32 -5
- package/dist/commands/doctorCommand.mjs +1 -1
- package/dist/commands/headlessCommand.mjs +3 -3
- package/dist/commands/mcpCommand.mjs +1 -1
- package/dist/commands/updateCommand.mjs +1 -1
- package/dist/index.mjs +243 -27
- package/dist/store-44C_Fvdb.mjs +3 -0
- package/dist/{store-B7-LLvvx.mjs → store-B0ImnWR4.mjs} +24 -2
- package/dist/{tools-BUs_OkJc.mjs → tools-Dg1HL5PO.mjs} +443 -30
- package/dist/{updateChecker-D-xoVcN3.mjs → updateChecker-Bbkc_8IL.mjs} +1 -1
- package/package.json +7 -6
- package/dist/store-B_ILRSdP.mjs +0 -3
|
@@ -862,9 +862,27 @@ const GenericCreditDeductTransaction = BaseCreditTransaction.extend({
|
|
|
862
862
|
*/
|
|
863
863
|
userId: z.string().optional(),
|
|
864
864
|
/**
|
|
865
|
-
*
|
|
865
|
+
* Reason/source for the transaction. Use GenericDeductReasons for new callers.
|
|
866
866
|
*/
|
|
867
|
-
reason: z.
|
|
867
|
+
reason: z.enum([
|
|
868
|
+
"dispute_clawback",
|
|
869
|
+
"refund_clawback",
|
|
870
|
+
"payment_failed_clawback",
|
|
871
|
+
"notebook_curation",
|
|
872
|
+
"manual",
|
|
873
|
+
"admin_adjustment",
|
|
874
|
+
"refund_adjustment"
|
|
875
|
+
]).optional(),
|
|
876
|
+
/**
|
|
877
|
+
* Stripe dispute ID — set for dispute clawback transactions.
|
|
878
|
+
* Used for idempotency (unique sparse index prevents duplicate clawbacks).
|
|
879
|
+
*/
|
|
880
|
+
stripeDisputeId: z.string().optional(),
|
|
881
|
+
/**
|
|
882
|
+
* Stripe refund ID — set for refund clawback transactions.
|
|
883
|
+
* Used for idempotency (unique sparse index prevents duplicate clawbacks).
|
|
884
|
+
*/
|
|
885
|
+
stripeRefundId: z.string().optional()
|
|
868
886
|
});
|
|
869
887
|
const TextGenerationUsageTransaction = BaseCreditTransaction.extend({
|
|
870
888
|
type: z.literal("text_generation_usage"),
|
|
@@ -8829,7 +8847,14 @@ const CliConfigSchema = z.object({
|
|
|
8829
8847
|
maxIterations: z.number().nullable().prefault(10),
|
|
8830
8848
|
enableSkillTool: z.boolean().optional().prefault(true),
|
|
8831
8849
|
enableDynamicAgentCreation: z.boolean().optional().prefault(false),
|
|
8832
|
-
enableCoordinatorMode: z.boolean().optional().prefault(false)
|
|
8850
|
+
enableCoordinatorMode: z.boolean().optional().prefault(false),
|
|
8851
|
+
/**
|
|
8852
|
+
* System-prompt variant. 'current' uses the elaborate behavioral-scaffolding
|
|
8853
|
+
* prompt; 'minimal' uses a pi-style short prompt. See apps/cli/src/core/prompts.ts.
|
|
8854
|
+
* Defaults to 'current' for backward compatibility; switch via /config or by
|
|
8855
|
+
* editing the config file directly.
|
|
8856
|
+
*/
|
|
8857
|
+
promptVariant: z.enum(["current", "minimal"]).optional().prefault("current")
|
|
8833
8858
|
}),
|
|
8834
8859
|
tools: z.object({
|
|
8835
8860
|
enabled: z.array(z.string()),
|
|
@@ -8862,7 +8887,8 @@ const ProjectConfigSchema = z.object({
|
|
|
8862
8887
|
exportFormat: z.enum(["markdown", "json"]).optional(),
|
|
8863
8888
|
enableSkillTool: z.boolean().optional(),
|
|
8864
8889
|
enableDynamicAgentCreation: z.boolean().optional(),
|
|
8865
|
-
enableCoordinatorMode: z.boolean().optional()
|
|
8890
|
+
enableCoordinatorMode: z.boolean().optional(),
|
|
8891
|
+
promptVariant: z.enum(["current", "minimal"]).optional()
|
|
8866
8892
|
}).optional(),
|
|
8867
8893
|
sandbox: PartialSandboxConfigSchema,
|
|
8868
8894
|
additionalDirectories: z.array(z.string()).optional()
|
|
@@ -8912,7 +8938,8 @@ const DEFAULT_CONFIG = {
|
|
|
8912
8938
|
maxIterations: 10,
|
|
8913
8939
|
enableSkillTool: true,
|
|
8914
8940
|
enableDynamicAgentCreation: false,
|
|
8915
|
-
enableCoordinatorMode: false
|
|
8941
|
+
enableCoordinatorMode: false,
|
|
8942
|
+
promptVariant: "current"
|
|
8916
8943
|
},
|
|
8917
8944
|
tools: {
|
|
8918
8945
|
enabled: [],
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as version, n as compareSemver, r as fetchLatestVersion } from "../updateChecker-
|
|
2
|
+
import { a as version, n as compareSemver, r as fetchLatestVersion } from "../updateChecker-Bbkc_8IL.mjs";
|
|
3
3
|
import { execSync } from "child_process";
|
|
4
4
|
import { constants, existsSync, promises } from "fs";
|
|
5
5
|
import { homedir } from "os";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { n as logger, t as ConfigStore } from "../ConfigStore-
|
|
2
|
+
import { C as WebSocketToolExecutor, D as ServerLlmBackend, E as WebSocketLlmBackend, F as PermissionManager, I as generateCliTools, M as loadContextFiles, N as getApiUrl, O as McpManager, Q as CheckpointStore, S as ApiClient, T as FallbackLlmBackend, W as setWebSocketToolExecutor, X as ReActAgent, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createAgentDelegateTool, b as createSkillTool, d as createFindDefinitionTool, et as SessionStore, f as createTodoStore, g as BackgroundAgentManager, h as createBackgroundAgentTools, m as createCoordinateTaskTool, p as createWriteTodosTool, q as buildSystemPrompt, u as createGetFileStructureTool, v as AgentStore, w as WebSocketConnectionManager, y as SubagentOrchestrator } from "../tools-Dg1HL5PO.mjs";
|
|
3
|
+
import { n as logger, t as ConfigStore } from "../ConfigStore-Bj1IOvWn.mjs";
|
|
4
4
|
import { t as DEFAULT_SANDBOX_CONFIG } from "../types-DBEjF9YS.mjs";
|
|
5
5
|
import { t as createSandboxRuntime } from "../SandboxRuntimeAdapter-C1B4t20N.mjs";
|
|
6
6
|
import { t as SandboxOrchestrator } from "../SandboxOrchestrator-BEW3rqYi.mjs";
|
|
@@ -193,7 +193,7 @@ async function handleHeadlessCommand(options) {
|
|
|
193
193
|
...mcpTools,
|
|
194
194
|
...cliTools
|
|
195
195
|
];
|
|
196
|
-
const systemPrompt =
|
|
196
|
+
const systemPrompt = buildSystemPrompt(config.preferences.promptVariant ?? "current", {
|
|
197
197
|
contextContent: contextResult.mergedContent,
|
|
198
198
|
agentStore,
|
|
199
199
|
customCommands: customCommandStore.getAllCommands(),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as version, i as forceCheckForUpdate } from "../updateChecker-
|
|
2
|
+
import { a as version, i as forceCheckForUpdate } from "../updateChecker-Bbkc_8IL.mjs";
|
|
3
3
|
import { execSync } from "child_process";
|
|
4
4
|
//#region src/commands/updateCommand.ts
|
|
5
5
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as useCliStore, t as selectActiveBackgroundAgents } from "./store-
|
|
3
|
-
import { $ as
|
|
4
|
-
import { Mt as validateNotebookPath$1, g as ChatModels, jt as validateJupyterKernelName, m as CREDIT_DEDUCT_TRANSACTION_TYPES, n as logger, t as ConfigStore } from "./ConfigStore-
|
|
5
|
-
import { a as version, t as checkForUpdate } from "./updateChecker-
|
|
2
|
+
import { n as useCliStore, t as selectActiveBackgroundAgents } from "./store-B0ImnWR4.mjs";
|
|
3
|
+
import { $ as CommandHistoryStore, A as formatStep, B as DEFAULT_RETRY_CONFIG, C as WebSocketToolExecutor, D as ServerLlmBackend, E as WebSocketLlmBackend, F as PermissionManager, G as OllamaBackend, H as clearFeatureModuleTools, I as generateCliTools, J as buildSkillsPromptSection, K as getPlanModeFilePath, L as ALWAYS_DENIED_FOR_AGENTS, M as loadContextFiles, N as getApiUrl, O as McpManager, P as getEnvironmentName, Q as CheckpointStore, R as DEFAULT_AGENT_MODEL, S as ApiClient, T as FallbackLlmBackend, U as registerFeatureModuleTools, V as DEFAULT_THOROUGHNESS, W as setWebSocketToolExecutor, X as ReActAgent, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createAgentDelegateTool, a as createBlockerTools, at as mergeCommands, b as createSkillTool, c as createDecisionStore, ct as warmFileCache, d as createFindDefinitionTool, et as SessionStore, f as createTodoStore, g as BackgroundAgentManager, h as createBackgroundAgentTools, i as createBlockerStore, it as searchCommands, j as extractCompactInstructions, k as substituteArguments, l as formatDecisionsOutput, m as createCoordinateTaskTool, n as createReviewGateTool, nt as hasFileReferences, o as formatBlockersOutput, ot as formatFileSize, p as createWriteTodosTool, q as buildSystemPrompt, r as formatReviewGatesOutput, rt as processFileReferences, s as createDecisionLogTool, st as searchFiles, t as createReviewGateStore, tt as OAuthClient, u as createGetFileStructureTool, v as AgentStore, w as WebSocketConnectionManager, x as parseAgentConfig, y as SubagentOrchestrator, z as DEFAULT_MAX_ITERATIONS } from "./tools-Dg1HL5PO.mjs";
|
|
4
|
+
import { Mt as validateNotebookPath$1, g as ChatModels, jt as validateJupyterKernelName, m as CREDIT_DEDUCT_TRANSACTION_TYPES, n as logger, t as ConfigStore } from "./ConfigStore-Bj1IOvWn.mjs";
|
|
5
|
+
import { a as version, t as checkForUpdate } from "./updateChecker-Bbkc_8IL.mjs";
|
|
6
6
|
import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
7
7
|
import { Box, Static, Text, render, useApp, useInput } from "ink";
|
|
8
8
|
import { execSync } from "child_process";
|
|
@@ -25,16 +25,19 @@ import { get_encoding } from "tiktoken";
|
|
|
25
25
|
import WsWebSocket from "ws";
|
|
26
26
|
//#region src/components/StatusBar.tsx
|
|
27
27
|
const StatusBar = React.memo(function StatusBar({ sessionName, model, tokenUsage, creditsUsage }) {
|
|
28
|
-
const
|
|
28
|
+
const interactionMode = useCliStore((state) => state.interactionMode);
|
|
29
29
|
return /* @__PURE__ */ React.createElement(Box, {
|
|
30
30
|
flexDirection: "row",
|
|
31
31
|
justifyContent: "space-between",
|
|
32
32
|
width: "100%",
|
|
33
33
|
paddingX: 1
|
|
34
|
-
}, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, sessionName), /* @__PURE__ */ React.createElement(Box, { gap: 2 },
|
|
34
|
+
}, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, sessionName), /* @__PURE__ */ React.createElement(Box, { gap: 2 }, interactionMode === "auto-accept" && /* @__PURE__ */ React.createElement(Text, {
|
|
35
35
|
color: "green",
|
|
36
36
|
bold: true
|
|
37
|
-
}, "AUTO ACCEPT: Edits"),
|
|
37
|
+
}, "AUTO ACCEPT: Edits"), interactionMode === "plan" && /* @__PURE__ */ React.createElement(Text, {
|
|
38
|
+
color: "yellow",
|
|
39
|
+
bold: true
|
|
40
|
+
}, "PLAN MODE"), tokenUsage > 0 && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, tokenUsage.toLocaleString(), " tokens"), creditsUsage !== void 0 && creditsUsage > 0 && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, creditsUsage.toLocaleString(), " ", creditsUsage === 1 ? "credit" : "credits"), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, model)));
|
|
38
41
|
});
|
|
39
42
|
/**
|
|
40
43
|
* Maximum paste size in characters (~500KB) to prevent memory issues
|
|
@@ -1274,6 +1277,138 @@ function UserQuestionPrompt({ payload, onResponse }) {
|
|
|
1274
1277
|
})), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, isOnOther ? "Type your answer, Enter to submit, or arrow keys to go back" : isMulti ? "Press 1-" + options.length + ", Space to toggle, Enter to confirm" : "Press 1-" + options.length + ", or arrow keys + Enter")));
|
|
1275
1278
|
}
|
|
1276
1279
|
//#endregion
|
|
1280
|
+
//#region src/components/ReviewGatePrompt.tsx
|
|
1281
|
+
const ITEMS = [
|
|
1282
|
+
{
|
|
1283
|
+
label: "✓ Approve",
|
|
1284
|
+
decision: "approved",
|
|
1285
|
+
withNote: false
|
|
1286
|
+
},
|
|
1287
|
+
{
|
|
1288
|
+
label: "✓ Approve with note...",
|
|
1289
|
+
decision: "approved",
|
|
1290
|
+
withNote: true
|
|
1291
|
+
},
|
|
1292
|
+
{
|
|
1293
|
+
label: "✗ Reject",
|
|
1294
|
+
decision: "rejected",
|
|
1295
|
+
withNote: false
|
|
1296
|
+
},
|
|
1297
|
+
{
|
|
1298
|
+
label: "✗ Reject with note...",
|
|
1299
|
+
decision: "rejected",
|
|
1300
|
+
withNote: true
|
|
1301
|
+
}
|
|
1302
|
+
];
|
|
1303
|
+
/**
|
|
1304
|
+
* Review gate prompt component.
|
|
1305
|
+
*
|
|
1306
|
+
* Pauses the agent and asks the user to explicitly approve or reject a
|
|
1307
|
+
* significant decision. An optional free-text note can be attached to either
|
|
1308
|
+
* decision via the dedicated "...with note..." actions.
|
|
1309
|
+
*
|
|
1310
|
+
* Keyboard:
|
|
1311
|
+
* - 1–4: shortcut for each action
|
|
1312
|
+
* - y: Approve (no note); n: Reject (no note)
|
|
1313
|
+
* - ↑/↓: navigate; Enter: confirm selection
|
|
1314
|
+
* - When a "with note..." action is selected, an inline text input appears.
|
|
1315
|
+
* Type the note and press Enter to submit. Use ↑/↓ to switch to a no-note
|
|
1316
|
+
* action without losing the typed note.
|
|
1317
|
+
*/
|
|
1318
|
+
function ReviewGatePrompt({ description, options, recommendation, onResponse }) {
|
|
1319
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
1320
|
+
const [note, setNote] = useState("");
|
|
1321
|
+
const [responded, setResponded] = useState(false);
|
|
1322
|
+
const submit = useCallback((item, noteText) => {
|
|
1323
|
+
if (responded) return;
|
|
1324
|
+
setResponded(true);
|
|
1325
|
+
const trimmed = noteText.trim();
|
|
1326
|
+
onResponse({
|
|
1327
|
+
decision: item.decision,
|
|
1328
|
+
note: trimmed.length > 0 ? trimmed : void 0
|
|
1329
|
+
});
|
|
1330
|
+
}, [responded, onResponse]);
|
|
1331
|
+
const selectedItem = ITEMS[selectedIndex];
|
|
1332
|
+
const noteMode = selectedItem.withNote;
|
|
1333
|
+
const handleConfirm = useCallback(() => {
|
|
1334
|
+
if (selectedItem.withNote && note.trim().length === 0) return;
|
|
1335
|
+
submit(selectedItem, note);
|
|
1336
|
+
}, [
|
|
1337
|
+
selectedItem,
|
|
1338
|
+
note,
|
|
1339
|
+
submit
|
|
1340
|
+
]);
|
|
1341
|
+
useInput((input, key) => {
|
|
1342
|
+
if (responded) return;
|
|
1343
|
+
if (key.upArrow) {
|
|
1344
|
+
setSelectedIndex((i) => i > 0 ? i - 1 : ITEMS.length - 1);
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
if (key.downArrow) {
|
|
1348
|
+
setSelectedIndex((i) => i < ITEMS.length - 1 ? i + 1 : 0);
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
if (noteMode) return;
|
|
1352
|
+
const num = parseInt(input, 10);
|
|
1353
|
+
if (num >= 1 && num <= ITEMS.length) {
|
|
1354
|
+
const item = ITEMS[num - 1];
|
|
1355
|
+
setSelectedIndex(num - 1);
|
|
1356
|
+
if (!item.withNote) submit(item, "");
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
if (input.toLowerCase() === "y") {
|
|
1360
|
+
submit(ITEMS[0], "");
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
if (input.toLowerCase() === "n") {
|
|
1364
|
+
submit(ITEMS[2], "");
|
|
1365
|
+
return;
|
|
1366
|
+
}
|
|
1367
|
+
if (key.return) handleConfirm();
|
|
1368
|
+
}, { isActive: !responded });
|
|
1369
|
+
if (responded) return null;
|
|
1370
|
+
return /* @__PURE__ */ React.createElement(Box, {
|
|
1371
|
+
flexDirection: "column",
|
|
1372
|
+
borderStyle: "bold",
|
|
1373
|
+
borderColor: "magenta",
|
|
1374
|
+
padding: 1,
|
|
1375
|
+
marginY: 1
|
|
1376
|
+
}, /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, {
|
|
1377
|
+
bold: true,
|
|
1378
|
+
color: "magenta"
|
|
1379
|
+
}, "🛑 Review Gate")), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, description)), recommendation && /* @__PURE__ */ React.createElement(Box, {
|
|
1380
|
+
marginTop: 1,
|
|
1381
|
+
flexDirection: "column"
|
|
1382
|
+
}, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Recommendation:"), /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, recommendation))), options && options.length > 0 && /* @__PURE__ */ React.createElement(Box, {
|
|
1383
|
+
marginTop: 1,
|
|
1384
|
+
flexDirection: "column"
|
|
1385
|
+
}, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Options:"), /* @__PURE__ */ React.createElement(Box, {
|
|
1386
|
+
paddingLeft: 2,
|
|
1387
|
+
flexDirection: "column"
|
|
1388
|
+
}, options.map((opt, idx) => /* @__PURE__ */ React.createElement(Text, {
|
|
1389
|
+
key: idx,
|
|
1390
|
+
dimColor: true
|
|
1391
|
+
}, "• ", opt)))), /* @__PURE__ */ React.createElement(Box, {
|
|
1392
|
+
marginTop: 1,
|
|
1393
|
+
flexDirection: "column"
|
|
1394
|
+
}, ITEMS.map((item, index) => {
|
|
1395
|
+
const isHighlighted = index === selectedIndex;
|
|
1396
|
+
const color = item.decision === "approved" ? "green" : "red";
|
|
1397
|
+
return /* @__PURE__ */ React.createElement(Box, { key: item.label }, /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, index + 1, "."), /* @__PURE__ */ React.createElement(Text, {
|
|
1398
|
+
color: isHighlighted ? color : void 0,
|
|
1399
|
+
bold: isHighlighted
|
|
1400
|
+
}, isHighlighted ? " ❯ " : " ", item.label));
|
|
1401
|
+
})), noteMode && /* @__PURE__ */ React.createElement(Box, {
|
|
1402
|
+
marginTop: 1,
|
|
1403
|
+
flexDirection: "column"
|
|
1404
|
+
}, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Note:"), /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2 }, /* @__PURE__ */ React.createElement(TextInput, {
|
|
1405
|
+
value: note,
|
|
1406
|
+
onChange: setNote,
|
|
1407
|
+
onSubmit: handleConfirm,
|
|
1408
|
+
placeholder: "Type a note and press Enter…"
|
|
1409
|
+
}))), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, noteMode ? note.trim().length === 0 ? "Note required — type a note + Enter to submit, ↑↓ to switch action" : "Type note + Enter to submit, ↑↓ to switch action" : "Press 1-4, y/n, or ↑↓ + Enter")));
|
|
1410
|
+
}
|
|
1411
|
+
//#endregion
|
|
1277
1412
|
//#region src/components/ConfigEditor.tsx
|
|
1278
1413
|
/**
|
|
1279
1414
|
* Max iterations options: 10, 20, 30, 40, 50, Infinite (null)
|
|
@@ -1886,7 +2021,7 @@ const MessageItem = React.memo(function MessageItem({ message }) {
|
|
|
1886
2021
|
});
|
|
1887
2022
|
//#endregion
|
|
1888
2023
|
//#region src/components/App.tsx
|
|
1889
|
-
function App({ onMessage, onBackgroundCompletion, onCommand, onBashCommand, onPermissionResponse, onUserQuestionResponse, onImageDetected, commandHistory = [], commands = [], config, availableModels = [], onSaveConfig, prefillInput, onPrefillConsumed, mcpManager }) {
|
|
2024
|
+
function App({ onMessage, onBackgroundCompletion, onCommand, onBashCommand, onPermissionResponse, onUserQuestionResponse, onReviewGateResponse, onImageDetected, commandHistory = [], commands = [], config, availableModels = [], onSaveConfig, prefillInput, onPrefillConsumed, mcpManager }) {
|
|
1890
2025
|
const messages = useCliStore((state) => state.session?.messages || []);
|
|
1891
2026
|
const pendingMessages = useCliStore((state) => state.pendingMessages);
|
|
1892
2027
|
const sessionName = useCliStore((state) => state.session?.name || "New Session");
|
|
@@ -1896,6 +2031,7 @@ function App({ onMessage, onBackgroundCompletion, onCommand, onBashCommand, onPe
|
|
|
1896
2031
|
const isThinking = useCliStore((state) => state.isThinking);
|
|
1897
2032
|
const permissionPrompt = useCliStore((state) => state.permissionPrompt);
|
|
1898
2033
|
const userQuestionPrompt = useCliStore((state) => state.userQuestionPrompt);
|
|
2034
|
+
const reviewGatePrompt = useCliStore((state) => state.reviewGatePrompt);
|
|
1899
2035
|
const showConfigEditor = useCliStore((state) => state.showConfigEditor);
|
|
1900
2036
|
const setShowConfigEditor = useCliStore((state) => state.setShowConfigEditor);
|
|
1901
2037
|
const showMcpViewer = useCliStore((state) => state.showMcpViewer);
|
|
@@ -1915,9 +2051,9 @@ function App({ onMessage, onBackgroundCompletion, onCommand, onBashCommand, onPe
|
|
|
1915
2051
|
setPendingBackgroundTrigger,
|
|
1916
2052
|
onBackgroundCompletion
|
|
1917
2053
|
]);
|
|
1918
|
-
const
|
|
2054
|
+
const cycleInteractionMode = useCliStore((state) => state.cycleInteractionMode);
|
|
1919
2055
|
useInput((_input, key) => {
|
|
1920
|
-
if (key.tab && key.shift)
|
|
2056
|
+
if (key.tab && key.shift) cycleInteractionMode();
|
|
1921
2057
|
});
|
|
1922
2058
|
const [isBashMode, setIsBashMode] = useState(false);
|
|
1923
2059
|
const handleSubmit = React.useCallback(async (input) => {
|
|
@@ -1988,7 +2124,16 @@ function App({ onMessage, onBackgroundCompletion, onCommand, onBashCommand, onPe
|
|
|
1988
2124
|
}, /* @__PURE__ */ React.createElement(UserQuestionPrompt, {
|
|
1989
2125
|
payload: userQuestionPrompt.payload,
|
|
1990
2126
|
onResponse: (response) => onUserQuestionResponse(response, userQuestionPrompt.id)
|
|
1991
|
-
})),
|
|
2127
|
+
})), reviewGatePrompt && /* @__PURE__ */ React.createElement(Box, {
|
|
2128
|
+
key: reviewGatePrompt.id,
|
|
2129
|
+
flexDirection: "column",
|
|
2130
|
+
paddingX: 1
|
|
2131
|
+
}, /* @__PURE__ */ React.createElement(ReviewGatePrompt, {
|
|
2132
|
+
description: reviewGatePrompt.description,
|
|
2133
|
+
options: reviewGatePrompt.options,
|
|
2134
|
+
recommendation: reviewGatePrompt.recommendation,
|
|
2135
|
+
onResponse: (response) => onReviewGateResponse(response, reviewGatePrompt.id)
|
|
2136
|
+
})), !permissionPrompt && !userQuestionPrompt && !reviewGatePrompt && /* @__PURE__ */ React.createElement(AgentThinking, null), /* @__PURE__ */ React.createElement(BackgroundAgentStatus, null), /* @__PURE__ */ React.createElement(CompletedGroupNotification, null), exitRequested && /* @__PURE__ */ React.createElement(Box, {
|
|
1992
2137
|
paddingX: 1,
|
|
1993
2138
|
marginBottom: 1
|
|
1994
2139
|
}, /* @__PURE__ */ React.createElement(Text, {
|
|
@@ -2002,7 +2147,7 @@ function App({ onMessage, onBackgroundCompletion, onCommand, onBashCommand, onPe
|
|
|
2002
2147
|
onSubmit: handleSubmit,
|
|
2003
2148
|
onBashCommand,
|
|
2004
2149
|
onImageDetected,
|
|
2005
|
-
disabled: isThinking || !!permissionPrompt || !!userQuestionPrompt,
|
|
2150
|
+
disabled: isThinking || !!permissionPrompt || !!userQuestionPrompt || !!reviewGatePrompt,
|
|
2006
2151
|
history: commandHistory,
|
|
2007
2152
|
commands,
|
|
2008
2153
|
prefillInput,
|
|
@@ -2469,7 +2614,7 @@ function buildCompactionPrompt(messages, options = {}) {
|
|
|
2469
2614
|
function createCompactedSession(originalSession, summary, preservedMessages) {
|
|
2470
2615
|
const summaryMessage = {
|
|
2471
2616
|
id: v4(),
|
|
2472
|
-
role: "
|
|
2617
|
+
role: "user",
|
|
2473
2618
|
content: `[Previous conversation summary]\n\n${summary}`,
|
|
2474
2619
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2475
2620
|
};
|
|
@@ -5235,10 +5380,13 @@ function CliApp() {
|
|
|
5235
5380
|
const imageStoreInitPromise = useRef(null);
|
|
5236
5381
|
const decisionStoreRef = useRef(createDecisionStore());
|
|
5237
5382
|
const blockerStoreRef = useRef(createBlockerStore());
|
|
5383
|
+
const reviewGateStoreRef = useRef(createReviewGateStore());
|
|
5238
5384
|
const setStoreSession = useCliStore((state) => state.setSession);
|
|
5239
5385
|
const enqueuePermissionPrompt = useCliStore((state) => state.enqueuePermissionPrompt);
|
|
5240
5386
|
const enqueueUserQuestionPrompt = useCliStore((state) => state.enqueueUserQuestionPrompt);
|
|
5241
5387
|
const dequeueUserQuestionPrompt = useCliStore((state) => state.dequeueUserQuestionPrompt);
|
|
5388
|
+
const enqueueReviewGatePrompt = useCliStore((state) => state.enqueueReviewGatePrompt);
|
|
5389
|
+
const dequeueReviewGatePrompt = useCliStore((state) => state.dequeueReviewGatePrompt);
|
|
5242
5390
|
const setShowConfigEditor = useCliStore((state) => state.setShowConfigEditor);
|
|
5243
5391
|
const setShowMcpViewer = useCliStore((state) => state.setShowMcpViewer);
|
|
5244
5392
|
const setExitRequested = useCliStore((state) => state.setExitRequested);
|
|
@@ -5628,6 +5776,22 @@ function CliApp() {
|
|
|
5628
5776
|
});
|
|
5629
5777
|
});
|
|
5630
5778
|
};
|
|
5779
|
+
const reviewGateFn = (params) => {
|
|
5780
|
+
return new Promise((resolve) => {
|
|
5781
|
+
enqueueReviewGatePrompt({
|
|
5782
|
+
id: params.id,
|
|
5783
|
+
description: params.description,
|
|
5784
|
+
options: params.options,
|
|
5785
|
+
recommendation: params.recommendation,
|
|
5786
|
+
resolve
|
|
5787
|
+
});
|
|
5788
|
+
bridgePresence.emitEvent({
|
|
5789
|
+
type: "status",
|
|
5790
|
+
status: "awaiting_input",
|
|
5791
|
+
text: `Review gate: ${params.description}`.slice(0, 240)
|
|
5792
|
+
});
|
|
5793
|
+
});
|
|
5794
|
+
};
|
|
5631
5795
|
const agentContext = {
|
|
5632
5796
|
currentAgent: null,
|
|
5633
5797
|
observationQueue: []
|
|
@@ -5681,12 +5845,15 @@ function CliApp() {
|
|
|
5681
5845
|
const writeTodosTool = createWriteTodosTool(createTodoStore());
|
|
5682
5846
|
const decisionLogTool = createDecisionLogTool(decisionStoreRef.current);
|
|
5683
5847
|
const blockerTools = createBlockerTools(blockerStoreRef.current);
|
|
5848
|
+
const reviewGateTool = createReviewGateTool(reviewGateStoreRef.current, reviewGateFn);
|
|
5684
5849
|
if (newSession.metadata.workflow) {
|
|
5685
5850
|
decisionStoreRef.current.decisions = [...newSession.metadata.workflow.decisions];
|
|
5686
5851
|
blockerStoreRef.current.blockers = [...newSession.metadata.workflow.blockers];
|
|
5852
|
+
reviewGateStoreRef.current.reviewGates = [...newSession.metadata.workflow.reviewGates ?? []];
|
|
5687
5853
|
} else {
|
|
5688
5854
|
decisionStoreRef.current.decisions = [];
|
|
5689
5855
|
blockerStoreRef.current.blockers = [];
|
|
5856
|
+
reviewGateStoreRef.current.reviewGates = [];
|
|
5690
5857
|
}
|
|
5691
5858
|
const enableSkillTool = config.preferences.enableSkillTool !== false;
|
|
5692
5859
|
const skillTool = enableSkillTool ? createSkillTool({
|
|
@@ -5707,6 +5874,7 @@ function CliApp() {
|
|
|
5707
5874
|
writeTodosTool,
|
|
5708
5875
|
decisionLogTool,
|
|
5709
5876
|
...blockerTools,
|
|
5877
|
+
reviewGateTool,
|
|
5710
5878
|
findDefinitionTool,
|
|
5711
5879
|
getFileStructureTool
|
|
5712
5880
|
];
|
|
@@ -5741,15 +5909,18 @@ function CliApp() {
|
|
|
5741
5909
|
if (contextResult.projectContext) startupLog.push(`📄 Project context: ${contextResult.projectContext.filename}`);
|
|
5742
5910
|
for (const error of contextResult.errors) startupLog.push(`⚠️ Context file error: ${error}`);
|
|
5743
5911
|
const featureModulePrompts = featureRegistry.getSystemPromptSections();
|
|
5744
|
-
const
|
|
5912
|
+
const promptVariant = config.preferences.promptVariant ?? "current";
|
|
5913
|
+
const buildPromptForMode = (mode) => buildSystemPrompt(promptVariant, {
|
|
5745
5914
|
contextContent: contextResult.mergedContent,
|
|
5746
5915
|
agentStore,
|
|
5747
5916
|
customCommands: state.customCommandStore.getAllCommands(),
|
|
5748
5917
|
enableSkillTool,
|
|
5749
5918
|
enableDynamicAgentCreation: config.preferences.enableDynamicAgentCreation === true,
|
|
5750
5919
|
additionalDirectories,
|
|
5751
|
-
featureModulePrompts: featureModulePrompts || void 0
|
|
5920
|
+
featureModulePrompts: featureModulePrompts || void 0,
|
|
5921
|
+
planModeFilePath: mode === "plan" ? getPlanModeFilePath(newSession.id) : void 0
|
|
5752
5922
|
});
|
|
5923
|
+
const cliSystemPrompt = buildPromptForMode(useCliStore.getState().interactionMode);
|
|
5753
5924
|
const maxIterations = config.preferences.maxIterations === null ? 999999 : config.preferences.maxIterations;
|
|
5754
5925
|
const agent = new ReActAgent({
|
|
5755
5926
|
userId: config.userId,
|
|
@@ -5763,6 +5934,14 @@ function CliApp() {
|
|
|
5763
5934
|
systemPrompt: cliSystemPrompt
|
|
5764
5935
|
});
|
|
5765
5936
|
agentContext.currentAgent = agent;
|
|
5937
|
+
const agentInternalContext = agent.context;
|
|
5938
|
+
let lastInteractionMode = useCliStore.getState().interactionMode;
|
|
5939
|
+
useCliStore.subscribe((s) => {
|
|
5940
|
+
if (s.interactionMode === lastInteractionMode) return;
|
|
5941
|
+
lastInteractionMode = s.interactionMode;
|
|
5942
|
+
if (agentContext.currentAgent !== agent) return;
|
|
5943
|
+
agentInternalContext.systemPrompt = buildPromptForMode(s.interactionMode);
|
|
5944
|
+
});
|
|
5766
5945
|
agent.observationQueue = agentContext.observationQueue;
|
|
5767
5946
|
const stepHandler = (step) => {
|
|
5768
5947
|
const { pendingMessages, updatePendingMessage } = useCliStore.getState();
|
|
@@ -5980,6 +6159,14 @@ function CliApp() {
|
|
|
5980
6159
|
});
|
|
5981
6160
|
return;
|
|
5982
6161
|
}
|
|
6162
|
+
if (s.reviewGatePrompt) {
|
|
6163
|
+
bridgePresence.emitEvent({
|
|
6164
|
+
type: "status",
|
|
6165
|
+
status: "awaiting_input",
|
|
6166
|
+
text: `Review gate: ${s.reviewGatePrompt.description}`.slice(0, 240)
|
|
6167
|
+
});
|
|
6168
|
+
return;
|
|
6169
|
+
}
|
|
5983
6170
|
const abort = abortControllerRef.current;
|
|
5984
6171
|
if (!abort || abort.signal.aborted) return;
|
|
5985
6172
|
bridgePresence.emitEvent({
|
|
@@ -6137,11 +6324,11 @@ function CliApp() {
|
|
|
6137
6324
|
totalTokens: currentSession.metadata.totalTokens + result.completionInfo.totalTokens,
|
|
6138
6325
|
totalCredits: (currentSession.metadata.totalCredits || 0) + (result.completionInfo.totalCredits || 0),
|
|
6139
6326
|
toolCallCount: currentSession.metadata.toolCallCount + successfulToolCalls,
|
|
6140
|
-
workflow: decisionStoreRef.current.decisions.length > 0 || blockerStoreRef.current.blockers.length > 0 ? {
|
|
6327
|
+
workflow: decisionStoreRef.current.decisions.length > 0 || blockerStoreRef.current.blockers.length > 0 || reviewGateStoreRef.current.reviewGates.length > 0 ? {
|
|
6141
6328
|
decisions: decisionStoreRef.current.decisions,
|
|
6142
6329
|
blockers: blockerStoreRef.current.blockers,
|
|
6143
6330
|
handoff: currentSession.metadata.workflow?.handoff,
|
|
6144
|
-
reviewGates:
|
|
6331
|
+
reviewGates: reviewGateStoreRef.current.reviewGates
|
|
6145
6332
|
} : currentSession.metadata.workflow
|
|
6146
6333
|
}
|
|
6147
6334
|
};
|
|
@@ -6255,7 +6442,7 @@ function CliApp() {
|
|
|
6255
6442
|
if (config?.preferences.autoCompact !== false && activeSession.messages.length >= 6) {
|
|
6256
6443
|
const tokenCounter = getTokenCounter();
|
|
6257
6444
|
const threshold = tokenCounter.getContextWindow(activeSession.model, state.availableModels) * .8;
|
|
6258
|
-
const systemPrompt =
|
|
6445
|
+
const systemPrompt = buildSystemPrompt(config?.preferences.promptVariant ?? "current", {
|
|
6259
6446
|
contextContent: state.contextContent,
|
|
6260
6447
|
agentStore: state.agentStore || void 0,
|
|
6261
6448
|
customCommands: state.customCommandStore.getAllCommands(),
|
|
@@ -6653,7 +6840,7 @@ function CliApp() {
|
|
|
6653
6840
|
decisions: decisionStoreRef.current.decisions,
|
|
6654
6841
|
blockers: blockerStoreRef.current.blockers,
|
|
6655
6842
|
handoff,
|
|
6656
|
-
reviewGates:
|
|
6843
|
+
reviewGates: reviewGateStoreRef.current.reviewGates
|
|
6657
6844
|
};
|
|
6658
6845
|
return handoff;
|
|
6659
6846
|
} catch (err) {
|
|
@@ -6798,11 +6985,11 @@ Multi-line Input:
|
|
|
6798
6985
|
}
|
|
6799
6986
|
const sessionName = args.join(" ") || state.session.name;
|
|
6800
6987
|
state.session.name = sessionName;
|
|
6801
|
-
if (decisionStoreRef.current.decisions.length > 0 || blockerStoreRef.current.blockers.length > 0) state.session.metadata.workflow = {
|
|
6988
|
+
if (decisionStoreRef.current.decisions.length > 0 || blockerStoreRef.current.blockers.length > 0 || reviewGateStoreRef.current.reviewGates.length > 0) state.session.metadata.workflow = {
|
|
6802
6989
|
decisions: decisionStoreRef.current.decisions,
|
|
6803
6990
|
blockers: blockerStoreRef.current.blockers,
|
|
6804
6991
|
handoff: state.session.metadata.workflow?.handoff,
|
|
6805
|
-
reviewGates:
|
|
6992
|
+
reviewGates: reviewGateStoreRef.current.reviewGates
|
|
6806
6993
|
};
|
|
6807
6994
|
const handoff = await generateHandoff(state.session);
|
|
6808
6995
|
await state.sessionStore.save(state.session);
|
|
@@ -7084,6 +7271,17 @@ Multi-line Input:
|
|
|
7084
7271
|
}));
|
|
7085
7272
|
setStoreSession(newSession);
|
|
7086
7273
|
useCliStore.getState().clearPendingMessages();
|
|
7274
|
+
const staleGate = useCliStore.getState().reviewGatePrompt;
|
|
7275
|
+
if (staleGate) {
|
|
7276
|
+
dequeueReviewGatePrompt();
|
|
7277
|
+
staleGate.resolve({
|
|
7278
|
+
decision: "rejected",
|
|
7279
|
+
note: "Session cleared."
|
|
7280
|
+
});
|
|
7281
|
+
}
|
|
7282
|
+
queueMicrotask(() => {
|
|
7283
|
+
reviewGateStoreRef.current.reviewGates = [];
|
|
7284
|
+
});
|
|
7087
7285
|
usageCache = null;
|
|
7088
7286
|
console.log("New session started.");
|
|
7089
7287
|
console.log(`\n📝 Session: ${newSession.name} | 🤖 Model: ${newSession.model} | 📊 Tokens: 0\n`);
|
|
@@ -7309,7 +7507,8 @@ Multi-line Input:
|
|
|
7309
7507
|
}
|
|
7310
7508
|
const tokenCounter = getTokenCounter();
|
|
7311
7509
|
const contextWindow = tokenCounter.getContextWindow(state.session.model, state.availableModels);
|
|
7312
|
-
const
|
|
7510
|
+
const variantForCount = state.config?.preferences.promptVariant ?? "current";
|
|
7511
|
+
const corePromptTokens = tokenCounter.countTokens(buildSystemPrompt(variantForCount));
|
|
7313
7512
|
const projectContextTokens = state.contextContent ? tokenCounter.countTokens(state.contextContent) : 0;
|
|
7314
7513
|
const commands = state.customCommandStore.getAllCommands();
|
|
7315
7514
|
const skillsSection = buildSkillsPromptSection(commands);
|
|
@@ -7318,7 +7517,7 @@ Multi-line Input:
|
|
|
7318
7517
|
const mcpTools = state.mcpManager?.getTools() || [];
|
|
7319
7518
|
const mcpToolsTokens = tokenCounter.countToolSchemaTokens(mcpTools);
|
|
7320
7519
|
const mcpToolCount = state.mcpManager?.getToolCount() || [];
|
|
7321
|
-
const systemPrompt =
|
|
7520
|
+
const systemPrompt = buildSystemPrompt(variantForCount, {
|
|
7322
7521
|
contextContent: state.contextContent,
|
|
7323
7522
|
agentStore: state.agentStore || void 0,
|
|
7324
7523
|
customCommands: commands,
|
|
@@ -7778,6 +7977,11 @@ Multi-line Input:
|
|
|
7778
7977
|
console.log(formatBlockersOutput(blockerStoreRef.current.blockers));
|
|
7779
7978
|
console.log("");
|
|
7780
7979
|
break;
|
|
7980
|
+
case "review-gates":
|
|
7981
|
+
console.log("\n🛑 Review Gates\n");
|
|
7982
|
+
console.log(formatReviewGatesOutput(reviewGateStoreRef.current.reviewGates));
|
|
7983
|
+
console.log("");
|
|
7984
|
+
break;
|
|
7781
7985
|
case "handoff": {
|
|
7782
7986
|
if (!state.session) {
|
|
7783
7987
|
console.log("No active session");
|
|
@@ -7891,14 +8095,16 @@ Multi-line Input:
|
|
|
7891
8095
|
const newFeatureTools = newFeatureRegistry.getAllTools();
|
|
7892
8096
|
agentContext.tools = [...baseTools, ...newFeatureTools];
|
|
7893
8097
|
const newFeaturePrompts = newFeatureRegistry.getSystemPromptSections();
|
|
7894
|
-
|
|
8098
|
+
const planFilePathForRebuild = useCliStore.getState().interactionMode === "plan" && state.session ? getPlanModeFilePath(state.session.id) : void 0;
|
|
8099
|
+
agentContext.systemPrompt = buildSystemPrompt(updatedConfig.preferences.promptVariant ?? "current", {
|
|
7895
8100
|
contextContent: state.contextContent,
|
|
7896
8101
|
agentStore: state.agentStore || void 0,
|
|
7897
8102
|
customCommands: state.customCommandStore.getAllCommands(),
|
|
7898
8103
|
enableSkillTool: updatedConfig.preferences.enableSkillTool !== false,
|
|
7899
8104
|
enableDynamicAgentCreation: updatedConfig.preferences.enableDynamicAgentCreation === true,
|
|
7900
8105
|
additionalDirectories: state.additionalDirectories,
|
|
7901
|
-
featureModulePrompts: newFeaturePrompts || void 0
|
|
8106
|
+
featureModulePrompts: newFeaturePrompts || void 0,
|
|
8107
|
+
planModeFilePath: planFilePathForRebuild
|
|
7902
8108
|
});
|
|
7903
8109
|
const moduleNames = newFeatureRegistry.getModuleNames();
|
|
7904
8110
|
if (moduleNames.length > 0) console.error(`\n\x1b[36m🏰 Feature modules hot-reloaded: ${moduleNames.join(", ")}\x1b[0m`);
|
|
@@ -8037,8 +8243,15 @@ Multi-line Input:
|
|
|
8037
8243
|
onUserQuestionResponse: (response, promptId) => {
|
|
8038
8244
|
const currentPrompt = useCliStore.getState().userQuestionPrompt;
|
|
8039
8245
|
if (currentPrompt?.id !== promptId) return;
|
|
8040
|
-
currentPrompt.resolve(response);
|
|
8041
8246
|
dequeueUserQuestionPrompt();
|
|
8247
|
+
currentPrompt.resolve(response);
|
|
8248
|
+
emitNextAwaitingStatus();
|
|
8249
|
+
},
|
|
8250
|
+
onReviewGateResponse: (response, promptId) => {
|
|
8251
|
+
const currentPrompt = useCliStore.getState().reviewGatePrompt;
|
|
8252
|
+
if (currentPrompt?.id !== promptId) return;
|
|
8253
|
+
dequeueReviewGatePrompt();
|
|
8254
|
+
currentPrompt.resolve(response);
|
|
8042
8255
|
emitNextAwaitingStatus();
|
|
8043
8256
|
}
|
|
8044
8257
|
});
|
|
@@ -8049,6 +8262,9 @@ try {
|
|
|
8049
8262
|
} catch {}
|
|
8050
8263
|
if (import.meta.url.includes("/src/") || process.env.NODE_ENV === "development") logger.debug("🔧 Running in development mode (using TypeScript source)\n");
|
|
8051
8264
|
warmFileCache();
|
|
8052
|
-
render(/* @__PURE__ */ React.createElement(CliApp, null), {
|
|
8265
|
+
render(/* @__PURE__ */ React.createElement(CliApp, null), {
|
|
8266
|
+
exitOnCtrlC: false,
|
|
8267
|
+
alternateScreen: true
|
|
8268
|
+
});
|
|
8053
8269
|
//#endregion
|
|
8054
8270
|
export {};
|
|
@@ -3,6 +3,14 @@ import { create } from "zustand";
|
|
|
3
3
|
//#region src/store/index.ts
|
|
4
4
|
/** Active job statuses (jobs still in progress) */
|
|
5
5
|
const ACTIVE_STATUSES = new Set(["running", "queued"]);
|
|
6
|
+
const INTERACTION_MODE_CYCLE = [
|
|
7
|
+
"normal",
|
|
8
|
+
"auto-accept",
|
|
9
|
+
"plan"
|
|
10
|
+
];
|
|
11
|
+
function nextInteractionMode(current) {
|
|
12
|
+
return INTERACTION_MODE_CYCLE[(INTERACTION_MODE_CYCLE.indexOf(current) + 1) % INTERACTION_MODE_CYCLE.length];
|
|
13
|
+
}
|
|
6
14
|
/** Check if a job status is active (running or queued) */
|
|
7
15
|
function isActiveStatus(status) {
|
|
8
16
|
return ACTIVE_STATUSES.has(status);
|
|
@@ -105,12 +113,26 @@ const useCliStore = create((set) => ({
|
|
|
105
113
|
userQuestionQueue: rest
|
|
106
114
|
};
|
|
107
115
|
}),
|
|
116
|
+
reviewGatePrompt: null,
|
|
117
|
+
reviewGateQueue: [],
|
|
118
|
+
enqueueReviewGatePrompt: (prompt) => set((state) => {
|
|
119
|
+
if (!state.reviewGatePrompt) return { reviewGatePrompt: prompt };
|
|
120
|
+
return { reviewGateQueue: [...state.reviewGateQueue, prompt] };
|
|
121
|
+
}),
|
|
122
|
+
dequeueReviewGatePrompt: () => set((state) => {
|
|
123
|
+
const [next, ...rest] = state.reviewGateQueue;
|
|
124
|
+
return {
|
|
125
|
+
reviewGatePrompt: next ?? null,
|
|
126
|
+
reviewGateQueue: rest
|
|
127
|
+
};
|
|
128
|
+
}),
|
|
108
129
|
showConfigEditor: false,
|
|
109
130
|
setShowConfigEditor: (show) => set({ showConfigEditor: show }),
|
|
110
131
|
showMcpViewer: false,
|
|
111
132
|
setShowMcpViewer: (show) => set({ showMcpViewer: show }),
|
|
112
|
-
|
|
113
|
-
|
|
133
|
+
interactionMode: "normal",
|
|
134
|
+
cycleInteractionMode: () => set((state) => ({ interactionMode: nextInteractionMode(state.interactionMode) })),
|
|
135
|
+
setInteractionMode: (mode) => set({ interactionMode: mode }),
|
|
114
136
|
exitRequested: false,
|
|
115
137
|
setExitRequested: (requested) => set({ exitRequested: requested }),
|
|
116
138
|
backgroundAgents: [],
|