u-foo 2.5.14 → 3.0.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/package.json +1 -1
- package/src/agents/prompts/native/environment.js +20 -8
- package/src/code/agent.js +517 -112
- package/src/code/commands.js +77 -0
- package/src/code/context/artifactGc.js +292 -0
- package/src/code/context/artifactIndex.js +161 -0
- package/src/code/context/artifacts.js +183 -0
- package/src/code/context/assembler.js +703 -0
- package/src/code/context/executionSegment.js +292 -0
- package/src/code/context/index.js +28 -0
- package/src/code/context/planGraph.js +1410 -0
- package/src/code/context/planGraphService.js +857 -0
- package/src/code/context/planMode.js +398 -0
- package/src/code/context/planProjection.js +432 -0
- package/src/code/context/projectSnapshot.js +201 -0
- package/src/code/context/promptLayers.js +175 -0
- package/src/code/context/reducers.js +328 -0
- package/src/code/context/stableJson.js +29 -0
- package/src/code/context/stateCommit.js +414 -0
- package/src/code/context/toolRuntime.js +172 -0
- package/src/code/context/transcript.js +182 -0
- package/src/code/context/transcriptSync.js +106 -0
- package/src/code/context/userInteraction.js +457 -0
- package/src/code/context/userNudge.js +116 -0
- package/src/code/context/workingSet.js +323 -0
- package/src/code/dispatch.js +20 -1
- package/src/code/index.js +8 -0
- package/src/code/modelCommand.js +87 -0
- package/src/code/nativeRunner.js +625 -34
- package/src/code/repl.js +196 -50
- package/src/code/runtime/agentWakeup.js +58 -0
- package/src/code/runtime/graphOwner.js +41 -0
- package/src/code/runtime/graphYieldRouter.js +42 -0
- package/src/code/runtime/index.js +15 -0
- package/src/code/runtime/loopMailbox.js +124 -0
- package/src/code/runtime/runtimeEvents.js +39 -0
- package/src/code/runtime/taskControl.js +565 -0
- package/src/code/runtime/taskFocus.js +165 -0
- package/src/code/runtime/taskLoop.js +383 -0
- package/src/code/runtime/taskRun.js +187 -0
- package/src/code/runtime/toolProvenance.js +70 -0
- package/src/code/runtime/workspaceLease.js +208 -0
- package/src/code/sessionStore.js +217 -15
- package/src/code/skills/index.js +10 -0
- package/src/code/skills/injection.js +66 -3
- package/src/code/skills/loader.js +21 -0
- package/src/code/skills/manifest.js +87 -0
- package/src/code/skills/render.js +15 -1
- package/src/code/taskDecomposer.js +56 -2
- package/src/code/tools/artifactRead.js +40 -0
- package/src/code/tools/askUser.js +11 -0
- package/src/code/tools/planGraph.js +29 -0
- package/src/code/tui.js +2 -0
- package/src/code/usageStore.js +15 -0
- package/src/ui/format/index.js +285 -45
- package/src/ui/format/markdownRenderer.js +436 -71
- package/src/ui/ink/ChatApp.js +39 -8
- package/src/ui/ink/UcodeApp.js +592 -43
- package/src/ui/ink/chatLogModel.js +102 -21
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Plan mode: agent-runtime session posture (not part of the plan_graph engine).
|
|
5
|
+
*
|
|
6
|
+
* Plan Mode gates side-effect tools at the runtime boundary. The plan_graph
|
|
7
|
+
* engine remains available independently for structured execution.
|
|
8
|
+
*
|
|
9
|
+
* Surfaces (no agent tool toggle):
|
|
10
|
+
* - User: /plan on|off|show|hide|focus|debug|clear
|
|
11
|
+
* - Runtime: auto-enter after successful plan_graph create
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const { projectPlanView } = require("./planGraphService");
|
|
15
|
+
const {
|
|
16
|
+
buildPlanUiProjection,
|
|
17
|
+
setBandMode,
|
|
18
|
+
ensurePlanUiState,
|
|
19
|
+
getBandMode,
|
|
20
|
+
} = require("./planProjection");
|
|
21
|
+
|
|
22
|
+
function getBandModeSafe(executionState = null) {
|
|
23
|
+
return getBandMode(executionState);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function ensureExecutionState(sessionState = {}) {
|
|
27
|
+
const state = sessionState && typeof sessionState === "object" ? sessionState : {};
|
|
28
|
+
if (!state.executionState || typeof state.executionState !== "object") {
|
|
29
|
+
state.executionState = require("./executionSegment").emptyExecutionState();
|
|
30
|
+
}
|
|
31
|
+
if (typeof state.executionState.planMode !== "boolean") {
|
|
32
|
+
state.executionState.planMode = false;
|
|
33
|
+
}
|
|
34
|
+
if (!state.executionState.planModeSource) {
|
|
35
|
+
state.executionState.planModeSource = "";
|
|
36
|
+
}
|
|
37
|
+
return state;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function normalizePlanModeState(executionState = null) {
|
|
41
|
+
const state = executionState && typeof executionState === "object"
|
|
42
|
+
? executionState
|
|
43
|
+
: {};
|
|
44
|
+
if (typeof state.planMode !== "boolean") state.planMode = false;
|
|
45
|
+
if (typeof state.planModeSource !== "string") state.planModeSource = "";
|
|
46
|
+
return state;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function isPlanModeEnabled(executionState = null) {
|
|
50
|
+
return Boolean(executionState && executionState.planMode === true);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function getPlanModeSource(executionState = null) {
|
|
54
|
+
const state = normalizePlanModeState(executionState);
|
|
55
|
+
return String(state.planModeSource || "").trim().toLowerCase();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function setPlanMode(executionState = null, enabled = true, {
|
|
59
|
+
reason = "",
|
|
60
|
+
source = "",
|
|
61
|
+
} = {}) {
|
|
62
|
+
const state = normalizePlanModeState(executionState);
|
|
63
|
+
const next = Boolean(enabled);
|
|
64
|
+
const wasOn = state.planMode === true;
|
|
65
|
+
state.planMode = next;
|
|
66
|
+
if (next) {
|
|
67
|
+
if (!wasOn) state.planModeEnteredAt = new Date().toISOString();
|
|
68
|
+
state.planModeReason = String(reason || state.planModeReason || "").trim();
|
|
69
|
+
const src = String(source || "").trim().toLowerCase();
|
|
70
|
+
if (src === "user" || src === "auto") {
|
|
71
|
+
state.planModeSource = src;
|
|
72
|
+
} else if (!state.planModeSource) {
|
|
73
|
+
state.planModeSource = "auto";
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
state.planModeEnteredAt = "";
|
|
77
|
+
state.planModeReason = String(reason || "").trim();
|
|
78
|
+
state.planModeSource = "";
|
|
79
|
+
}
|
|
80
|
+
return state;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Enter Plan Mode after the agent successfully creates a plan graph.
|
|
85
|
+
* No-op if already enabled (preserves user source).
|
|
86
|
+
*/
|
|
87
|
+
function enterPlanModeAfterGraphCreate(executionState = null, {
|
|
88
|
+
reason = "plan_graph create",
|
|
89
|
+
} = {}) {
|
|
90
|
+
const state = normalizePlanModeState(executionState);
|
|
91
|
+
if (state.planMode) {
|
|
92
|
+
return { changed: false, planMode: true, source: state.planModeSource || "auto" };
|
|
93
|
+
}
|
|
94
|
+
setPlanMode(state, true, { reason, source: "auto" });
|
|
95
|
+
return { changed: true, planMode: true, source: "auto" };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function planHasNodes(executionState = null) {
|
|
99
|
+
const pg = executionState && executionState.planGraph;
|
|
100
|
+
return Boolean(pg && pg.graphId && Array.isArray(pg.nodes) && pg.nodes.length > 0);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function planModeBlocksDirectTool(tool = "", executionState = null) {
|
|
104
|
+
if (!isPlanModeEnabled(executionState)) return false;
|
|
105
|
+
const name = String(tool || "").trim().toLowerCase();
|
|
106
|
+
return name === "write" || name === "edit" || name === "bash";
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function statusMark(status = "") {
|
|
110
|
+
const value = String(status || "").trim().toLowerCase();
|
|
111
|
+
if (value === "succeeded") return "✓";
|
|
112
|
+
if (value === "failed" || value === "blocked" || value === "cancelled") return "✗";
|
|
113
|
+
if (value === "waiting_llm" || value === "waiting_approval" || value === "running") return "→";
|
|
114
|
+
if (value === "skipped") return "·";
|
|
115
|
+
return "○";
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function formatPlanTreeLines(planGraph = {}, { includeGenerated = true } = {}) {
|
|
119
|
+
const pg = planGraph && typeof planGraph === "object" ? planGraph : {};
|
|
120
|
+
const view = projectPlanView(pg);
|
|
121
|
+
if (view.length === 0) return ["(no plan graph yet — call plan_graph create)"];
|
|
122
|
+
|
|
123
|
+
const byId = new Map(view.map((node) => [node.id, node]));
|
|
124
|
+
const roots = view.filter((node) => !node.parentId && (!node.generated || node.type === "task"));
|
|
125
|
+
const lines = [];
|
|
126
|
+
|
|
127
|
+
function walk(node, depth) {
|
|
128
|
+
if (!node) return;
|
|
129
|
+
if (!includeGenerated && node.generated && node.type !== "task") return;
|
|
130
|
+
const indent = " ".repeat(depth);
|
|
131
|
+
const label = node.type === "tool"
|
|
132
|
+
? `${node.id}${node.tool ? `:${node.tool}` : ""}`
|
|
133
|
+
: (node.title || node.id);
|
|
134
|
+
const extra = node.type === "task" && node.execution === "aggregate"
|
|
135
|
+
? " [aggregate]"
|
|
136
|
+
: "";
|
|
137
|
+
lines.push(`${indent}${statusMark(node.status)} ${label}${extra}`);
|
|
138
|
+
for (const childId of node.children || []) {
|
|
139
|
+
walk(byId.get(childId), depth + 1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
for (const root of roots) walk(root, 0);
|
|
144
|
+
|
|
145
|
+
if (includeGenerated) {
|
|
146
|
+
for (const node of view) {
|
|
147
|
+
if (node.parentId) continue;
|
|
148
|
+
if (roots.some((root) => root.id === node.id)) continue;
|
|
149
|
+
walk(node, 0);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return lines.length > 0 ? lines : ["(empty plan)"];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function formatPlanModeStatus(executionState = null) {
|
|
157
|
+
const state = normalizePlanModeState(executionState);
|
|
158
|
+
const pg = state.planGraph && typeof state.planGraph === "object" ? state.planGraph : {};
|
|
159
|
+
const waiting = pg.waitingFor && pg.waitingFor.id
|
|
160
|
+
? `${pg.waitingFor.type}:${pg.waitingFor.id}`
|
|
161
|
+
: "-";
|
|
162
|
+
const source = getPlanModeSource(state) || "-";
|
|
163
|
+
const lines = [
|
|
164
|
+
`Plan mode: ${state.planMode ? "ON" : "OFF"} (source=${source})`,
|
|
165
|
+
`Graph: ${pg.graphId || "(none)"}`,
|
|
166
|
+
`Revisions: spec=${Number(pg.specRevision) || 0} state=${Number(pg.stateRevision) || 0}`,
|
|
167
|
+
`Waiting: ${waiting}`,
|
|
168
|
+
`Yield: ${pg.lastYieldReason || "-"}`,
|
|
169
|
+
"Plan:",
|
|
170
|
+
...formatPlanTreeLines(pg).map((line) => ` ${line}`),
|
|
171
|
+
];
|
|
172
|
+
if (state.planMode) {
|
|
173
|
+
lines.push("");
|
|
174
|
+
lines.push("Rules while ON:");
|
|
175
|
+
lines.push(" - Use plan_graph to create/expand/complete the plan");
|
|
176
|
+
lines.push(" - write / edit / bash are blocked as direct tools");
|
|
177
|
+
lines.push(" - read / artifact_read allowed for exploration");
|
|
178
|
+
lines.push(" - Runtime auto-advances ready tool nodes after plan_graph");
|
|
179
|
+
lines.push(" - User leaves with /plan off (agents cannot toggle Plan Mode)");
|
|
180
|
+
} else {
|
|
181
|
+
lines.push("");
|
|
182
|
+
lines.push("User can enable with /plan on. Creating a plan_graph also enables Plan Mode.");
|
|
183
|
+
lines.push("Simple multi-step tool calls do not need Plan Mode.");
|
|
184
|
+
}
|
|
185
|
+
return lines.join("\n");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Injected into turnDynamic so the model sees plan-mode constraints every turn.
|
|
190
|
+
*/
|
|
191
|
+
function renderPlanModeContext(executionState = null) {
|
|
192
|
+
if (!isPlanModeEnabled(executionState)) return "";
|
|
193
|
+
const pg = executionState.planGraph && typeof executionState.planGraph === "object"
|
|
194
|
+
? executionState.planGraph
|
|
195
|
+
: {};
|
|
196
|
+
const source = getPlanModeSource(executionState);
|
|
197
|
+
const hasPlan = planHasNodes(executionState);
|
|
198
|
+
const lines = [
|
|
199
|
+
"Plan Mode: ON",
|
|
200
|
+
];
|
|
201
|
+
|
|
202
|
+
if (source === "user" && !hasPlan) {
|
|
203
|
+
lines.push(
|
|
204
|
+
"The user enabled Plan Mode. You must plan before executing side effects.",
|
|
205
|
+
"First call plan_graph create with a small set of high-level tasks (progressive planning).",
|
|
206
|
+
"Do not call write/edit/bash directly until the plan exists and work is routed through it.",
|
|
207
|
+
);
|
|
208
|
+
} else if (source === "user") {
|
|
209
|
+
lines.push(
|
|
210
|
+
"The user enabled Plan Mode — keep work on the plan graph; expand/complete tasks deliberately.",
|
|
211
|
+
);
|
|
212
|
+
} else {
|
|
213
|
+
lines.push(
|
|
214
|
+
"Plan Mode was enabled automatically after plan_graph create.",
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
lines.push(
|
|
219
|
+
"Allowed direct tools: read, artifact_read, plan_graph, ask_user.",
|
|
220
|
+
"Blocked direct tools: write, edit, bash (route them as plan_graph tool nodes or task_loop).",
|
|
221
|
+
"Plan Mode constrains the Agent Loop only; running TaskLoops are not paused or reconfigured by /plan off.",
|
|
222
|
+
"Only the user can leave Plan Mode (/plan off). That does not cancel the graph or TaskRuns — use cancel_graph / control.cancel_task.",
|
|
223
|
+
"Workflow while ON:",
|
|
224
|
+
" 1) Ensure a plan_graph exists (create if missing)",
|
|
225
|
+
" 2) expand_node on the current ready/waiting task when needed",
|
|
226
|
+
" 3) Runtime executes ready tools / TaskLoops; continue from results",
|
|
227
|
+
" 4) control.complete_task (inline) or control.start_task (task_loop)",
|
|
228
|
+
"Do not mix plan_graph with data-plane tools in the same turn.",
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
if (pg.graphId) {
|
|
232
|
+
lines.push(`Active graph: ${pg.graphId} (specRev ${Number(pg.specRevision) || 0})`);
|
|
233
|
+
}
|
|
234
|
+
if (pg.waitingFor && pg.waitingFor.id) {
|
|
235
|
+
lines.push(`Currently waiting on: ${pg.waitingFor.type} ${pg.waitingFor.id}`
|
|
236
|
+
+ (pg.waitingFor.title || pg.waitingFor.objective
|
|
237
|
+
? ` — ${pg.waitingFor.title || pg.waitingFor.objective}`
|
|
238
|
+
: ""));
|
|
239
|
+
}
|
|
240
|
+
const tree = formatPlanTreeLines(pg);
|
|
241
|
+
if (tree.length > 0) {
|
|
242
|
+
lines.push("Current plan:");
|
|
243
|
+
for (const line of tree) lines.push(` ${line}`);
|
|
244
|
+
}
|
|
245
|
+
return lines.join("\n");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function applyUcodePlanCommand(sessionState = {}, result = {}) {
|
|
249
|
+
const action = String(result.action || "").trim().toLowerCase();
|
|
250
|
+
const state = ensureExecutionState(sessionState);
|
|
251
|
+
normalizePlanModeState(state.executionState);
|
|
252
|
+
ensurePlanUiState(state.executionState);
|
|
253
|
+
|
|
254
|
+
if (action === "show" || action === "" || action === "status") {
|
|
255
|
+
if (getBandModeSafe(state.executionState) === "hidden") {
|
|
256
|
+
setBandMode(state.executionState, "auto");
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
ok: true,
|
|
260
|
+
output: formatPlanModeStatus(state.executionState),
|
|
261
|
+
state,
|
|
262
|
+
planMode: state.executionState.planMode,
|
|
263
|
+
planUi: buildPlanUiProjection(state.executionState),
|
|
264
|
+
refreshPlanUi: true,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (action === "hide") {
|
|
269
|
+
setBandMode(state.executionState, "hidden");
|
|
270
|
+
return {
|
|
271
|
+
ok: true,
|
|
272
|
+
output: "Plan band hidden. Use /plan show to reveal it again.",
|
|
273
|
+
state,
|
|
274
|
+
planMode: state.executionState.planMode,
|
|
275
|
+
planUi: buildPlanUiProjection(state.executionState),
|
|
276
|
+
refreshPlanUi: true,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (action === "focus") {
|
|
281
|
+
setBandMode(state.executionState, "expanded");
|
|
282
|
+
const projection = buildPlanUiProjection(state.executionState);
|
|
283
|
+
const lines = projection.bandLines.length > 0
|
|
284
|
+
? projection.bandLines
|
|
285
|
+
: ["(no plan graph yet)"];
|
|
286
|
+
return {
|
|
287
|
+
ok: true,
|
|
288
|
+
output: ["Plan band: expanded", ...lines].join("\n"),
|
|
289
|
+
state,
|
|
290
|
+
planMode: state.executionState.planMode,
|
|
291
|
+
planUi: projection,
|
|
292
|
+
refreshPlanUi: true,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (action === "debug") {
|
|
297
|
+
setBandMode(state.executionState, "debug");
|
|
298
|
+
const projection = buildPlanUiProjection(state.executionState);
|
|
299
|
+
return {
|
|
300
|
+
ok: true,
|
|
301
|
+
output: ["Plan band: debug", ...projection.bandLines].join("\n"),
|
|
302
|
+
state,
|
|
303
|
+
planMode: state.executionState.planMode,
|
|
304
|
+
planUi: projection,
|
|
305
|
+
refreshPlanUi: true,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (action === "on" || action === "enable") {
|
|
310
|
+
const wasOn = isPlanModeEnabled(state.executionState);
|
|
311
|
+
setPlanMode(state.executionState, true, {
|
|
312
|
+
reason: "user /plan on",
|
|
313
|
+
source: "user",
|
|
314
|
+
});
|
|
315
|
+
const hasPlan = planHasNodes(state.executionState);
|
|
316
|
+
const lines = [
|
|
317
|
+
wasOn ? "Plan mode already ON." : "Plan mode: ON (user)",
|
|
318
|
+
"",
|
|
319
|
+
"Side-effect tools (write/edit/bash) are blocked as direct calls.",
|
|
320
|
+
hasPlan
|
|
321
|
+
? "Continue via plan_graph expand/control; Runtime advances ready tool nodes."
|
|
322
|
+
: "No plan yet — the agent will be prompted to create a plan_graph first.",
|
|
323
|
+
"Use /plan to inspect the tree, /plan off to leave.",
|
|
324
|
+
];
|
|
325
|
+
const tree = formatPlanTreeLines(state.executionState.planGraph || {});
|
|
326
|
+
if (tree[0] && !tree[0].startsWith("(no plan")) {
|
|
327
|
+
lines.push("", "Current plan:", ...tree.map((line) => ` ${line}`));
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
ok: true,
|
|
331
|
+
output: lines.join("\n"),
|
|
332
|
+
state,
|
|
333
|
+
planMode: true,
|
|
334
|
+
planUi: buildPlanUiProjection(state.executionState),
|
|
335
|
+
refreshPlanUi: true,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (action === "off" || action === "disable") {
|
|
340
|
+
setPlanMode(state.executionState, false, { reason: "user /plan off" });
|
|
341
|
+
return {
|
|
342
|
+
ok: true,
|
|
343
|
+
output: "Plan mode: OFF\nDirect write/edit/bash tools are allowed again.",
|
|
344
|
+
state,
|
|
345
|
+
planMode: false,
|
|
346
|
+
planUi: buildPlanUiProjection(state.executionState),
|
|
347
|
+
refreshPlanUi: true,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (action === "clear") {
|
|
352
|
+
const { runPlanGraphCommand } = require("./planGraphService");
|
|
353
|
+
const cleared = runPlanGraphCommand({ operation: "cancel_graph" }, {
|
|
354
|
+
executionState: state.executionState,
|
|
355
|
+
autoAdvance: false,
|
|
356
|
+
});
|
|
357
|
+
state.executionState = cleared.executionState || state.executionState;
|
|
358
|
+
const modeNote = isPlanModeEnabled(state.executionState)
|
|
359
|
+
? "Plan mode stays ON."
|
|
360
|
+
: "Plan mode is OFF.";
|
|
361
|
+
return {
|
|
362
|
+
ok: true,
|
|
363
|
+
output: `Plan graph cleared. ${modeNote}`,
|
|
364
|
+
state,
|
|
365
|
+
planMode: isPlanModeEnabled(state.executionState),
|
|
366
|
+
planUi: buildPlanUiProjection(state.executionState),
|
|
367
|
+
refreshPlanUi: true,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (action === "toggle") {
|
|
372
|
+
return applyUcodePlanCommand(state, {
|
|
373
|
+
action: isPlanModeEnabled(state.executionState) ? "off" : "on",
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return {
|
|
378
|
+
ok: false,
|
|
379
|
+
error: "usage: /plan [on|off|show|hide|focus|debug|clear]",
|
|
380
|
+
output: "usage: /plan [on|off|show|hide|focus|debug|clear]",
|
|
381
|
+
state,
|
|
382
|
+
planMode: isPlanModeEnabled(state.executionState),
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
module.exports = {
|
|
387
|
+
ensureExecutionState,
|
|
388
|
+
normalizePlanModeState,
|
|
389
|
+
isPlanModeEnabled,
|
|
390
|
+
getPlanModeSource,
|
|
391
|
+
setPlanMode,
|
|
392
|
+
enterPlanModeAfterGraphCreate,
|
|
393
|
+
planModeBlocksDirectTool,
|
|
394
|
+
formatPlanTreeLines,
|
|
395
|
+
formatPlanModeStatus,
|
|
396
|
+
renderPlanModeContext,
|
|
397
|
+
applyUcodePlanCommand,
|
|
398
|
+
};
|