@nomad-e/bluma-cli 0.1.55 → 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 +120 -58
- 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
|
@@ -15990,11 +15990,12 @@ Run: npm i -g ${BLUMA_PACKAGE_NAME} to update.`;
|
|
|
15990
15990
|
}
|
|
15991
15991
|
}
|
|
15992
15992
|
|
|
15993
|
-
// src/app/ui/components/
|
|
15993
|
+
// src/app/ui/components/StartupUpdateGate.tsx
|
|
15994
15994
|
import { Box as Box17, Text as Text16 } from "ink";
|
|
15995
|
-
|
|
15995
|
+
|
|
15996
|
+
// src/app/ui/utils/update_message.ts
|
|
15996
15997
|
function parseUpdateMessage(msg) {
|
|
15997
|
-
const lines = msg.split(/\r?\n/).map((l) => l.trim());
|
|
15998
|
+
const lines = String(msg ?? "").split(/\r?\n/).map((l) => l.trim());
|
|
15998
15999
|
const first = lines[0] || "";
|
|
15999
16000
|
const hintLine = lines.slice(1).join(" ") || "";
|
|
16000
16001
|
const nameMatch = first.match(/Update available for\s+([^!]+)!/i);
|
|
@@ -16006,19 +16007,38 @@ function parseUpdateMessage(msg) {
|
|
|
16006
16007
|
hint: hintLine || void 0
|
|
16007
16008
|
};
|
|
16008
16009
|
}
|
|
16009
|
-
|
|
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
|
+
}) => {
|
|
16010
16021
|
const { name, current, latest: latest2, hint } = parseUpdateMessage(message2);
|
|
16011
|
-
|
|
16012
|
-
|
|
16013
|
-
|
|
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: [
|
|
16014
16032
|
current,
|
|
16015
16033
|
" \u2192 ",
|
|
16016
16034
|
latest2
|
|
16017
|
-
] }) :
|
|
16018
|
-
|
|
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" }) })
|
|
16019
16039
|
] }) });
|
|
16020
16040
|
};
|
|
16021
|
-
var
|
|
16041
|
+
var StartupUpdateGate_default = StartupUpdateGate;
|
|
16022
16042
|
|
|
16023
16043
|
// src/app/ui/components/ErrorMessage.tsx
|
|
16024
16044
|
import { Box as Box18, Text as Text17 } from "ink";
|
|
@@ -16610,6 +16630,10 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16610
16630
|
"Initializing agent..."
|
|
16611
16631
|
);
|
|
16612
16632
|
const [toolsCount, setToolsCount] = useState11(null);
|
|
16633
|
+
const [startupPhase, setStartupPhase] = useState11("checking");
|
|
16634
|
+
const [startupUpdateMessage, setStartupUpdateMessage] = useState11(
|
|
16635
|
+
null
|
|
16636
|
+
);
|
|
16613
16637
|
const [mcpStatus, setMcpStatus] = useState11(
|
|
16614
16638
|
"connecting"
|
|
16615
16639
|
);
|
|
@@ -16623,23 +16647,12 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16623
16647
|
const [pendingAskUserQuestions, setPendingAskUserQuestions] = useState11(null);
|
|
16624
16648
|
const [showWorkers, setShowWorkers] = useState11(false);
|
|
16625
16649
|
const [zoomedWorkerSession, setZoomedWorkerSession] = useState11(null);
|
|
16626
|
-
useInput6((input, key) => {
|
|
16627
|
-
if (key.ctrl && key.shift && input.toLowerCase() === "w") {
|
|
16628
|
-
setShowWorkers((prev) => !prev);
|
|
16629
|
-
}
|
|
16630
|
-
if (key.escape && showWorkers) {
|
|
16631
|
-
if (zoomedWorkerSession) {
|
|
16632
|
-
setZoomedWorkerSession(null);
|
|
16633
|
-
} else {
|
|
16634
|
-
setShowWorkers(false);
|
|
16635
|
-
}
|
|
16636
|
-
}
|
|
16637
|
-
});
|
|
16638
16650
|
const [isInitAgentActive, setIsInitAgentActive] = useState11(false);
|
|
16639
16651
|
const [liveToolName, setLiveToolName] = useState11(null);
|
|
16640
16652
|
const [liveToolArgs, setLiveToolArgs] = useState11(void 0);
|
|
16641
16653
|
const [isReasoning, setIsReasoning] = useState11(false);
|
|
16642
16654
|
const alwaysAcceptList = useRef6([]);
|
|
16655
|
+
const agentInitializationStartedRef = useRef6(false);
|
|
16643
16656
|
const workdir = process.cwd();
|
|
16644
16657
|
const turnStartedAtRef = useRef6(null);
|
|
16645
16658
|
const [processingStartMs, setProcessingStartMs] = useState11(null);
|
|
@@ -16673,6 +16686,33 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16673
16686
|
];
|
|
16674
16687
|
});
|
|
16675
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]);
|
|
16676
16716
|
useEffect11(() => {
|
|
16677
16717
|
expandPreviewHotkeyBus.on("expand", appendExpandPreviewToHistory);
|
|
16678
16718
|
return () => {
|
|
@@ -16680,22 +16720,24 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16680
16720
|
};
|
|
16681
16721
|
}, [appendExpandPreviewToHistory]);
|
|
16682
16722
|
useEffect11(() => {
|
|
16683
|
-
if (process.env.CI || blumaUpdateRegistryCheckStarted)
|
|
16723
|
+
if (process.env.CI || blumaUpdateRegistryCheckStarted) {
|
|
16724
|
+
setStartupPhase("starting-agent");
|
|
16725
|
+
void startAgentInitialization();
|
|
16726
|
+
return;
|
|
16727
|
+
}
|
|
16684
16728
|
blumaUpdateRegistryCheckStarted = true;
|
|
16729
|
+
setStatusMessage("Checking for updates...");
|
|
16685
16730
|
void checkForUpdates().then((msg) => {
|
|
16686
|
-
if (!msg)
|
|
16687
|
-
|
|
16688
|
-
|
|
16689
|
-
return
|
|
16690
|
-
|
|
16691
|
-
|
|
16692
|
-
|
|
16693
|
-
|
|
16694
|
-
}
|
|
16695
|
-
];
|
|
16696
|
-
});
|
|
16731
|
+
if (!msg) {
|
|
16732
|
+
setStartupPhase("starting-agent");
|
|
16733
|
+
void startAgentInitialization();
|
|
16734
|
+
return;
|
|
16735
|
+
}
|
|
16736
|
+
setStartupUpdateMessage(msg);
|
|
16737
|
+
setStartupPhase("update-available");
|
|
16738
|
+
setStatusMessage("Update available");
|
|
16697
16739
|
});
|
|
16698
|
-
}, []);
|
|
16740
|
+
}, [startAgentInitialization]);
|
|
16699
16741
|
useEffect11(() => {
|
|
16700
16742
|
setHistory((prev) => {
|
|
16701
16743
|
const tail = prev.filter((h) => h.id !== HEADER_PANEL_HISTORY_ID);
|
|
@@ -16725,6 +16767,28 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16725
16767
|
];
|
|
16726
16768
|
});
|
|
16727
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
|
+
});
|
|
16728
16792
|
const handleSubmit = useCallback4(
|
|
16729
16793
|
(text) => {
|
|
16730
16794
|
if (!text || !agentInstance.current) return;
|
|
@@ -16980,28 +17044,6 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
16980
17044
|
}
|
|
16981
17045
|
}, [history.length]);
|
|
16982
17046
|
useEffect11(() => {
|
|
16983
|
-
const initializeAgent = async () => {
|
|
16984
|
-
try {
|
|
16985
|
-
agentInstance.current = new Agent(sessionId, eventBus);
|
|
16986
|
-
await agentInstance.current.initialize();
|
|
16987
|
-
appendHookEvent({
|
|
16988
|
-
type: "session:init",
|
|
16989
|
-
sessionId,
|
|
16990
|
-
summary: "agent initialized"
|
|
16991
|
-
});
|
|
16992
|
-
eventBus.emit("backend_message", {
|
|
16993
|
-
type: "status",
|
|
16994
|
-
status: "mcp_connected",
|
|
16995
|
-
tools: agentInstance.current.getAvailableTools().length
|
|
16996
|
-
});
|
|
16997
|
-
} catch (error) {
|
|
16998
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error during Agent initialization.";
|
|
16999
|
-
eventBus.emit("backend_message", {
|
|
17000
|
-
type: "error",
|
|
17001
|
-
message: errorMessage
|
|
17002
|
-
});
|
|
17003
|
-
}
|
|
17004
|
-
};
|
|
17005
17047
|
const handleBackendMessage = (parsed) => {
|
|
17006
17048
|
try {
|
|
17007
17049
|
const appendTurnDurationIfAny = () => {
|
|
@@ -17256,7 +17298,6 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
17256
17298
|
uiEventBus.on("user_overlay", handleUiOverlay);
|
|
17257
17299
|
uiEventBus.on("input_notice", handleInputNotice);
|
|
17258
17300
|
eventBus.on("backend_message", handleBackendMessage);
|
|
17259
|
-
initializeAgent();
|
|
17260
17301
|
return () => {
|
|
17261
17302
|
uiEventBus.off("user_overlay", handleUiOverlay);
|
|
17262
17303
|
uiEventBus.off("input_notice", handleInputNotice);
|
|
@@ -17264,6 +17305,27 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
17264
17305
|
};
|
|
17265
17306
|
}, [eventBus, sessionId, handleConfirmation]);
|
|
17266
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
|
+
}
|
|
17267
17329
|
if (mcpStatus !== "connected") {
|
|
17268
17330
|
return /* @__PURE__ */ jsx27(
|
|
17269
17331
|
SessionInfoConnectingMCP_default,
|