@nomad-e/bluma-cli 0.1.54 → 0.1.56
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/README.md +1 -1
- package/dist/main.js +185 -62
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
**BluMa** is a CLI-based model agent for advanced software engineering workflows. Built with React/Ink 5, it provides an interactive terminal interface for LLM-powered automation, code generation, refactoring, and task execution. Features persistent sessions, contextual reasoning, smart feedback, coordinator mode for worker orchestration, and extensible tools/skills architecture.
|
|
8
8
|
|
|
9
|
-
**Current Version:** 0.1.
|
|
9
|
+
**Current Version:** 0.1.55
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
package/dist/main.js
CHANGED
|
@@ -9930,6 +9930,51 @@ Since you are in an **isolated sandbox**, ALL tools are auto-approved:
|
|
|
9930
9930
|
- **Artifact delivery** - Save outputs with \\\`create_artifact\\\`, declare in attachments
|
|
9931
9931
|
- **Error transparency** - If something fails, explain why and propose alternatives
|
|
9932
9932
|
|
|
9933
|
+
### \u26A0\uFE0F CRITICAL: message Tool Usage Rules
|
|
9934
|
+
|
|
9935
|
+
The \\\`message\\\` tool has TWO types \u2014 use them CORRECTLY:
|
|
9936
|
+
|
|
9937
|
+
#### \\\`message_type: "info"\\\` \u2014 INFORMATION ONLY
|
|
9938
|
+
- **Purpose**: Report progress, status updates, discoveries, milestones
|
|
9939
|
+
- **Use when**: "Step 1/3 complete", "Found the data", "Processing..."
|
|
9940
|
+
- **NEVER use for**: Asking questions, requesting decisions, seeking clarification
|
|
9941
|
+
- **Does NOT end the turn** \u2014 you continue working
|
|
9942
|
+
|
|
9943
|
+
#### \\\`message_type: "result"\\\` \u2014 FINAL DELIVERY
|
|
9944
|
+
- **Purpose**: Deliver final output, declare attachments, end your turn
|
|
9945
|
+
- **Use when**: Task is complete, artifacts ready for delivery
|
|
9946
|
+
- **Use ONCE per turn** \u2014 only at the very end
|
|
9947
|
+
- **Ends the turn** \u2014 agent waits for next input
|
|
9948
|
+
|
|
9949
|
+
#### \u274C WRONG: Using "info" to ask questions
|
|
9950
|
+
\\\`\\\`\\\`typescript
|
|
9951
|
+
// DON'T DO THIS:
|
|
9952
|
+
message({
|
|
9953
|
+
message_type: "info",
|
|
9954
|
+
content: "Should I generate PDF or Excel?" // \u2190 WRONG! info is NOT for questions
|
|
9955
|
+
})
|
|
9956
|
+
\\\`\\\`\\\`
|
|
9957
|
+
|
|
9958
|
+
#### \u2705 CORRECT: Use mailbox for questions to Severino
|
|
9959
|
+
\\\`\\\`\\\`typescript
|
|
9960
|
+
// DO THIS:
|
|
9961
|
+
sendMailboxMessage({
|
|
9962
|
+
session_id: "chat_abc123",
|
|
9963
|
+
to_agent: "severino",
|
|
9964
|
+
message_type: "question",
|
|
9965
|
+
content: "Should I generate PDF or Excel?"
|
|
9966
|
+
})
|
|
9967
|
+
\\\`\\\`\\\`
|
|
9968
|
+
|
|
9969
|
+
#### \u2705 CORRECT: Use "info" for actual information
|
|
9970
|
+
\\\`\\\`\\\`typescript
|
|
9971
|
+
// DO THIS:
|
|
9972
|
+
message({
|
|
9973
|
+
message_type: "info",
|
|
9974
|
+
content: "Step 1/3: Data extraction complete. Processing..."
|
|
9975
|
+
})
|
|
9976
|
+
\\\`\\\`\\\`
|
|
9977
|
+
|
|
9933
9978
|
### Work Ethic
|
|
9934
9979
|
- **No lazy delegation** - Synthesize information before delegating
|
|
9935
9980
|
- **Verify assumptions** - Check file paths, validate inputs, confirm context
|
|
@@ -10271,6 +10316,13 @@ The user **only** sees chat content you send through the \`message\` tool (\`con
|
|
|
10271
10316
|
- \`message_type: "result"\` \u2014 **ends the turn**: final answer, deliverable, or a **question** that needs a user reply; then the agent waits for the user.
|
|
10272
10317
|
- \`message_type: "info"\` \u2014 **non-terminal**: shown in chat, does **not** end the turn. **Expected behavior:** call \`info\` **multiple times** in a single turn whenever there is something worth saying (even briefly). Under-using \`info\` is a **mistake** in this product.
|
|
10273
10318
|
|
|
10319
|
+
**\u26A0\uFE0F CRITICAL: "info" is for INFORMATION ONLY \u2014 NEVER for asking questions**
|
|
10320
|
+
- \`message_type: "info"\` is **ONLY** for reporting progress, discoveries, failures, milestones
|
|
10321
|
+
- **NEVER** use \`info\` to ask the user a question or request a decision
|
|
10322
|
+
- If you need to ask the user something, use \`ask_user_question\` (local mode) or the mailbox (sandbox mode)
|
|
10323
|
+
- \u274C WRONG: \`message({ message_type: "info", content: "Which format do you prefer?" })\`
|
|
10324
|
+
- \u2705 CORRECT: \`ask_user_question({ questions: [...] })\` or \`sendMailboxMessage({ message_type: "question", ... })\`
|
|
10325
|
+
|
|
10274
10326
|
**When to send \`info\`**
|
|
10275
10327
|
- Before long sequences (many reads, greps, refactors): one short line \u2014 intent and why.
|
|
10276
10328
|
- Right after **discoveries** (culprit file, likely cause, relevant API, pattern in codebase).
|
|
@@ -10280,7 +10332,7 @@ The user **only** sees chat content you send through the \`message\` tool (\`con
|
|
|
10280
10332
|
|
|
10281
10333
|
Reasoning streams (if any) do **not** replace \`info\` for user-visible narrative \u2014 see \`<reasoning_and_message_info>\`.
|
|
10282
10334
|
|
|
10283
|
-
If you need an answer from the user, use \`message\` with \`result
|
|
10335
|
+
If you need an answer from the user, use \`ask_user_question\` (local) or \`message\` with \`result\` (sandbox).
|
|
10284
10336
|
When addressing {username}: normalize handles (hyphens/underscores/dots \u2192 spaces, title case, strip trailing digits if any).
|
|
10285
10337
|
</messages>
|
|
10286
10338
|
|
|
@@ -11008,9 +11060,18 @@ function decideToolExecution(toolName) {
|
|
|
11008
11060
|
reason: "Unknown tool metadata; require confirmation by default."
|
|
11009
11061
|
};
|
|
11010
11062
|
}
|
|
11011
|
-
|
|
11063
|
+
if (policy.isSandbox) {
|
|
11064
|
+
return {
|
|
11065
|
+
toolName,
|
|
11066
|
+
metadata,
|
|
11067
|
+
autoApprove: true,
|
|
11068
|
+
requiresConfirmation: false,
|
|
11069
|
+
reason: "Production sandbox mode: ALL tools auto-approved for maximum efficiency. Isolated Docker container ensures safety."
|
|
11070
|
+
};
|
|
11071
|
+
}
|
|
11072
|
+
let autoApprove = metadata.autoApproveInLocal;
|
|
11012
11073
|
const { permissionMode } = getRuntimeConfig();
|
|
11013
|
-
if (permissionMode === "accept_edits" &&
|
|
11074
|
+
if (permissionMode === "accept_edits" && (toolName === "edit_tool" || toolName === "file_write")) {
|
|
11014
11075
|
autoApprove = true;
|
|
11015
11076
|
}
|
|
11016
11077
|
if (planModeForcesConfirmation(toolName)) {
|
|
@@ -11021,7 +11082,7 @@ function decideToolExecution(toolName) {
|
|
|
11021
11082
|
metadata,
|
|
11022
11083
|
autoApprove,
|
|
11023
11084
|
requiresConfirmation: !autoApprove,
|
|
11024
|
-
reason: autoApprove ?
|
|
11085
|
+
reason: autoApprove ? "Tool marked safe for local autonomous execution." : "Tool requires confirmation outside sandbox mode."
|
|
11025
11086
|
};
|
|
11026
11087
|
}
|
|
11027
11088
|
|
|
@@ -15929,11 +15990,12 @@ Run: npm i -g ${BLUMA_PACKAGE_NAME} to update.`;
|
|
|
15929
15990
|
}
|
|
15930
15991
|
}
|
|
15931
15992
|
|
|
15932
|
-
// src/app/ui/components/
|
|
15993
|
+
// src/app/ui/components/StartupUpdateGate.tsx
|
|
15933
15994
|
import { Box as Box17, Text as Text16 } from "ink";
|
|
15934
|
-
|
|
15995
|
+
|
|
15996
|
+
// src/app/ui/utils/update_message.ts
|
|
15935
15997
|
function parseUpdateMessage(msg) {
|
|
15936
|
-
const lines = msg.split(/\r?\n/).map((l) => l.trim());
|
|
15998
|
+
const lines = String(msg ?? "").split(/\r?\n/).map((l) => l.trim());
|
|
15937
15999
|
const first = lines[0] || "";
|
|
15938
16000
|
const hintLine = lines.slice(1).join(" ") || "";
|
|
15939
16001
|
const nameMatch = first.match(/Update available for\s+([^!]+)!/i);
|
|
@@ -15945,19 +16007,38 @@ function parseUpdateMessage(msg) {
|
|
|
15945
16007
|
hint: hintLine || void 0
|
|
15946
16008
|
};
|
|
15947
16009
|
}
|
|
15948
|
-
|
|
16010
|
+
function extractInstallCommand(hint) {
|
|
16011
|
+
if (!hint) return null;
|
|
16012
|
+
const match = hint.match(/Run:\s*(.+?)(?:\s+to update\.?)?$/i);
|
|
16013
|
+
return match?.[1]?.trim() || null;
|
|
16014
|
+
}
|
|
16015
|
+
|
|
16016
|
+
// src/app/ui/components/StartupUpdateGate.tsx
|
|
16017
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
16018
|
+
var StartupUpdateGate = ({
|
|
16019
|
+
message: message2
|
|
16020
|
+
}) => {
|
|
15949
16021
|
const { name, current, latest: latest2, hint } = parseUpdateMessage(message2);
|
|
15950
|
-
|
|
15951
|
-
|
|
15952
|
-
|
|
16022
|
+
const command = extractInstallCommand(hint);
|
|
16023
|
+
return /* @__PURE__ */ jsx18(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", paddingX: 1, paddingTop: 1, children: [
|
|
16024
|
+
/* @__PURE__ */ jsxs16(Box17, { marginBottom: 1, children: [
|
|
16025
|
+
/* @__PURE__ */ jsx18(Text16, { color: BLUMA_TERMINAL.orange, children: "\u273B " }),
|
|
16026
|
+
/* @__PURE__ */ jsx18(Text16, { color: BLUMA_TERMINAL.blue, bold: true, children: "Blu" }),
|
|
16027
|
+
/* @__PURE__ */ jsx18(Text16, { color: BLUMA_TERMINAL.magenta, bold: true, children: "Ma" }),
|
|
16028
|
+
/* @__PURE__ */ jsx18(Text16, { dimColor: true, children: " update gate" })
|
|
16029
|
+
] }),
|
|
16030
|
+
/* @__PURE__ */ jsx18(Text16, { bold: true, color: BLUMA_TERMINAL.claude, children: name || "New BluMa version available" }),
|
|
16031
|
+
current && latest2 ? /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
|
|
15953
16032
|
current,
|
|
15954
16033
|
" \u2192 ",
|
|
15955
16034
|
latest2
|
|
15956
|
-
] }) :
|
|
15957
|
-
|
|
16035
|
+
] }) : null,
|
|
16036
|
+
/* @__PURE__ */ jsx18(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text16, { dimColor: true, wrap: "wrap", children: command ? `Run this command to update:
|
|
16037
|
+
${command}` : hint || "An update is available for BluMa CLI." }) }),
|
|
16038
|
+
/* @__PURE__ */ jsx18(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text16, { color: BLUMA_TERMINAL.warn, bold: true, children: "Press Enter to continue" }) })
|
|
15958
16039
|
] }) });
|
|
15959
16040
|
};
|
|
15960
|
-
var
|
|
16041
|
+
var StartupUpdateGate_default = StartupUpdateGate;
|
|
15961
16042
|
|
|
15962
16043
|
// src/app/ui/components/ErrorMessage.tsx
|
|
15963
16044
|
import { Box as Box18, Text as Text17 } from "ink";
|
|
@@ -16549,6 +16630,10 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16549
16630
|
"Initializing agent..."
|
|
16550
16631
|
);
|
|
16551
16632
|
const [toolsCount, setToolsCount] = useState11(null);
|
|
16633
|
+
const [startupPhase, setStartupPhase] = useState11("checking");
|
|
16634
|
+
const [startupUpdateMessage, setStartupUpdateMessage] = useState11(
|
|
16635
|
+
null
|
|
16636
|
+
);
|
|
16552
16637
|
const [mcpStatus, setMcpStatus] = useState11(
|
|
16553
16638
|
"connecting"
|
|
16554
16639
|
);
|
|
@@ -16562,23 +16647,12 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16562
16647
|
const [pendingAskUserQuestions, setPendingAskUserQuestions] = useState11(null);
|
|
16563
16648
|
const [showWorkers, setShowWorkers] = useState11(false);
|
|
16564
16649
|
const [zoomedWorkerSession, setZoomedWorkerSession] = useState11(null);
|
|
16565
|
-
useInput6((input, key) => {
|
|
16566
|
-
if (key.ctrl && key.shift && input.toLowerCase() === "w") {
|
|
16567
|
-
setShowWorkers((prev) => !prev);
|
|
16568
|
-
}
|
|
16569
|
-
if (key.escape && showWorkers) {
|
|
16570
|
-
if (zoomedWorkerSession) {
|
|
16571
|
-
setZoomedWorkerSession(null);
|
|
16572
|
-
} else {
|
|
16573
|
-
setShowWorkers(false);
|
|
16574
|
-
}
|
|
16575
|
-
}
|
|
16576
|
-
});
|
|
16577
16650
|
const [isInitAgentActive, setIsInitAgentActive] = useState11(false);
|
|
16578
16651
|
const [liveToolName, setLiveToolName] = useState11(null);
|
|
16579
16652
|
const [liveToolArgs, setLiveToolArgs] = useState11(void 0);
|
|
16580
16653
|
const [isReasoning, setIsReasoning] = useState11(false);
|
|
16581
16654
|
const alwaysAcceptList = useRef6([]);
|
|
16655
|
+
const agentInitializationStartedRef = useRef6(false);
|
|
16582
16656
|
const workdir = process.cwd();
|
|
16583
16657
|
const turnStartedAtRef = useRef6(null);
|
|
16584
16658
|
const [processingStartMs, setProcessingStartMs] = useState11(null);
|
|
@@ -16612,6 +16686,33 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16612
16686
|
];
|
|
16613
16687
|
});
|
|
16614
16688
|
}, []);
|
|
16689
|
+
const startAgentInitialization = useCallback4(async () => {
|
|
16690
|
+
if (agentInitializationStartedRef.current) return;
|
|
16691
|
+
agentInitializationStartedRef.current = true;
|
|
16692
|
+
try {
|
|
16693
|
+
agentInstance.current = new Agent(sessionId, eventBus);
|
|
16694
|
+
await agentInstance.current.initialize();
|
|
16695
|
+
appendHookEvent({
|
|
16696
|
+
type: "session:init",
|
|
16697
|
+
sessionId,
|
|
16698
|
+
summary: "agent initialized"
|
|
16699
|
+
});
|
|
16700
|
+
eventBus.emit("backend_message", {
|
|
16701
|
+
type: "status",
|
|
16702
|
+
status: "mcp_connected",
|
|
16703
|
+
tools: agentInstance.current.getAvailableTools().length
|
|
16704
|
+
});
|
|
16705
|
+
setStartupPhase("ready");
|
|
16706
|
+
} catch (error) {
|
|
16707
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error during Agent initialization.";
|
|
16708
|
+
setStartupPhase("failed");
|
|
16709
|
+
setStatusMessage(errorMessage);
|
|
16710
|
+
eventBus.emit("backend_message", {
|
|
16711
|
+
type: "error",
|
|
16712
|
+
message: errorMessage
|
|
16713
|
+
});
|
|
16714
|
+
}
|
|
16715
|
+
}, [eventBus, sessionId]);
|
|
16615
16716
|
useEffect11(() => {
|
|
16616
16717
|
expandPreviewHotkeyBus.on("expand", appendExpandPreviewToHistory);
|
|
16617
16718
|
return () => {
|
|
@@ -16619,22 +16720,24 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16619
16720
|
};
|
|
16620
16721
|
}, [appendExpandPreviewToHistory]);
|
|
16621
16722
|
useEffect11(() => {
|
|
16622
|
-
if (process.env.CI || blumaUpdateRegistryCheckStarted)
|
|
16723
|
+
if (process.env.CI || blumaUpdateRegistryCheckStarted) {
|
|
16724
|
+
setStartupPhase("starting-agent");
|
|
16725
|
+
void startAgentInitialization();
|
|
16726
|
+
return;
|
|
16727
|
+
}
|
|
16623
16728
|
blumaUpdateRegistryCheckStarted = true;
|
|
16729
|
+
setStatusMessage("Checking for updates...");
|
|
16624
16730
|
void checkForUpdates().then((msg) => {
|
|
16625
|
-
if (!msg)
|
|
16626
|
-
|
|
16627
|
-
|
|
16628
|
-
return
|
|
16629
|
-
|
|
16630
|
-
|
|
16631
|
-
|
|
16632
|
-
|
|
16633
|
-
}
|
|
16634
|
-
];
|
|
16635
|
-
});
|
|
16731
|
+
if (!msg) {
|
|
16732
|
+
setStartupPhase("starting-agent");
|
|
16733
|
+
void startAgentInitialization();
|
|
16734
|
+
return;
|
|
16735
|
+
}
|
|
16736
|
+
setStartupUpdateMessage(msg);
|
|
16737
|
+
setStartupPhase("update-available");
|
|
16738
|
+
setStatusMessage("Update available");
|
|
16636
16739
|
});
|
|
16637
|
-
}, []);
|
|
16740
|
+
}, [startAgentInitialization]);
|
|
16638
16741
|
useEffect11(() => {
|
|
16639
16742
|
setHistory((prev) => {
|
|
16640
16743
|
const tail = prev.filter((h) => h.id !== HEADER_PANEL_HISTORY_ID);
|
|
@@ -16664,6 +16767,28 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16664
16767
|
];
|
|
16665
16768
|
});
|
|
16666
16769
|
}, [isProcessing, eventBus]);
|
|
16770
|
+
const continuePastUpdateGate = useCallback4(() => {
|
|
16771
|
+
if (startupPhase !== "update-available") return;
|
|
16772
|
+
setStartupPhase("starting-agent");
|
|
16773
|
+
setStatusMessage("Connecting to MCP...");
|
|
16774
|
+
void startAgentInitialization();
|
|
16775
|
+
}, [startupPhase, startAgentInitialization]);
|
|
16776
|
+
useInput6((input, key) => {
|
|
16777
|
+
if (startupPhase === "update-available" && (key.return || input === "\n" || input === "\r")) {
|
|
16778
|
+
continuePastUpdateGate();
|
|
16779
|
+
return;
|
|
16780
|
+
}
|
|
16781
|
+
if (key.ctrl && key.shift && input.toLowerCase() === "w") {
|
|
16782
|
+
setShowWorkers((prev) => !prev);
|
|
16783
|
+
}
|
|
16784
|
+
if (key.escape && showWorkers) {
|
|
16785
|
+
if (zoomedWorkerSession) {
|
|
16786
|
+
setZoomedWorkerSession(null);
|
|
16787
|
+
} else {
|
|
16788
|
+
setShowWorkers(false);
|
|
16789
|
+
}
|
|
16790
|
+
}
|
|
16791
|
+
});
|
|
16667
16792
|
const handleSubmit = useCallback4(
|
|
16668
16793
|
(text) => {
|
|
16669
16794
|
if (!text || !agentInstance.current) return;
|
|
@@ -16919,28 +17044,6 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
16919
17044
|
}
|
|
16920
17045
|
}, [history.length]);
|
|
16921
17046
|
useEffect11(() => {
|
|
16922
|
-
const initializeAgent = async () => {
|
|
16923
|
-
try {
|
|
16924
|
-
agentInstance.current = new Agent(sessionId, eventBus);
|
|
16925
|
-
await agentInstance.current.initialize();
|
|
16926
|
-
appendHookEvent({
|
|
16927
|
-
type: "session:init",
|
|
16928
|
-
sessionId,
|
|
16929
|
-
summary: "agent initialized"
|
|
16930
|
-
});
|
|
16931
|
-
eventBus.emit("backend_message", {
|
|
16932
|
-
type: "status",
|
|
16933
|
-
status: "mcp_connected",
|
|
16934
|
-
tools: agentInstance.current.getAvailableTools().length
|
|
16935
|
-
});
|
|
16936
|
-
} catch (error) {
|
|
16937
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error during Agent initialization.";
|
|
16938
|
-
eventBus.emit("backend_message", {
|
|
16939
|
-
type: "error",
|
|
16940
|
-
message: errorMessage
|
|
16941
|
-
});
|
|
16942
|
-
}
|
|
16943
|
-
};
|
|
16944
17047
|
const handleBackendMessage = (parsed) => {
|
|
16945
17048
|
try {
|
|
16946
17049
|
const appendTurnDurationIfAny = () => {
|
|
@@ -17195,7 +17298,6 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
17195
17298
|
uiEventBus.on("user_overlay", handleUiOverlay);
|
|
17196
17299
|
uiEventBus.on("input_notice", handleInputNotice);
|
|
17197
17300
|
eventBus.on("backend_message", handleBackendMessage);
|
|
17198
|
-
initializeAgent();
|
|
17199
17301
|
return () => {
|
|
17200
17302
|
uiEventBus.off("user_overlay", handleUiOverlay);
|
|
17201
17303
|
uiEventBus.off("input_notice", handleInputNotice);
|
|
@@ -17203,6 +17305,27 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
17203
17305
|
};
|
|
17204
17306
|
}, [eventBus, sessionId, handleConfirmation]);
|
|
17205
17307
|
const renderInteractiveComponent = () => {
|
|
17308
|
+
if (startupPhase === "checking") {
|
|
17309
|
+
return /* @__PURE__ */ jsx27(
|
|
17310
|
+
SessionInfoConnectingMCP_default,
|
|
17311
|
+
{
|
|
17312
|
+
workdir,
|
|
17313
|
+
statusMessage: statusMessage || "Checking for updates..."
|
|
17314
|
+
}
|
|
17315
|
+
);
|
|
17316
|
+
}
|
|
17317
|
+
if (startupPhase === "update-available" && startupUpdateMessage) {
|
|
17318
|
+
return /* @__PURE__ */ jsx27(StartupUpdateGate_default, { message: startupUpdateMessage });
|
|
17319
|
+
}
|
|
17320
|
+
if (startupPhase === "failed") {
|
|
17321
|
+
return /* @__PURE__ */ jsx27(Box26, { flexDirection: "column", children: /* @__PURE__ */ jsx27(
|
|
17322
|
+
ErrorMessage_default,
|
|
17323
|
+
{
|
|
17324
|
+
message: statusMessage || "Startup failed",
|
|
17325
|
+
hint: "Fix the error above and restart BluMa."
|
|
17326
|
+
}
|
|
17327
|
+
) });
|
|
17328
|
+
}
|
|
17206
17329
|
if (mcpStatus !== "connected") {
|
|
17207
17330
|
return /* @__PURE__ */ jsx27(
|
|
17208
17331
|
SessionInfoConnectingMCP_default,
|