@nomad-e/bluma-cli 0.1.57 → 0.1.59
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 +2 -2
- package/dist/config/native_tools.json +3 -3
- package/dist/config/skills/git-pr/SKILL.md +1 -1
- package/dist/config/skills/pdf/SKILL.md +153 -22
- package/dist/config/skills/pdf/scripts/__pycache__/create_report.cpython-312.pyc +0 -0
- package/dist/config/skills/pdf/scripts/create_report.py +607 -209
- package/dist/config/skills/pdf/scripts/merge_pdfs.py +1 -1
- package/dist/config/skills/skill-creator/SKILL.md +1 -1
- package/dist/main.js +117 -126
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ Merge multiple PDF files into a single output PDF.
|
|
|
3
3
|
|
|
4
4
|
Usage:
|
|
5
5
|
python merge_pdfs.py --output merged.pdf file1.pdf file2.pdf file3.pdf
|
|
6
|
-
python merge_pdfs.py --output
|
|
6
|
+
python merge_pdfs.py --output ./.bluma/artifacts/combined.pdf *.pdf
|
|
7
7
|
"""
|
|
8
8
|
import argparse
|
|
9
9
|
import sys
|
|
@@ -193,7 +193,7 @@ Example script header:
|
|
|
193
193
|
{description of what this script does}
|
|
194
194
|
|
|
195
195
|
Usage:
|
|
196
|
-
python {script_name}.py --input data.csv --output
|
|
196
|
+
python {script_name}.py --input data.csv --output ./.bluma/artifacts/result.pdf
|
|
197
197
|
"""
|
|
198
198
|
import argparse
|
|
199
199
|
```
|
package/dist/main.js
CHANGED
|
@@ -113,6 +113,20 @@ function isPathInsideWorkspace(targetPath, policy = getSandboxPolicy()) {
|
|
|
113
113
|
const relative = path6.relative(policy.workspaceRoot, resolved);
|
|
114
114
|
return relative === "" || !relative.startsWith("..") && !path6.isAbsolute(relative);
|
|
115
115
|
}
|
|
116
|
+
function redirectTopLevelArtifactsPath(resolvedAbsolute, workspaceRoot) {
|
|
117
|
+
const wr = path6.resolve(workspaceRoot);
|
|
118
|
+
const abs = path6.resolve(resolvedAbsolute);
|
|
119
|
+
const rel = path6.relative(wr, abs);
|
|
120
|
+
if (rel.startsWith("..") || path6.isAbsolute(rel)) {
|
|
121
|
+
return abs;
|
|
122
|
+
}
|
|
123
|
+
const segments = rel.split(path6.sep).filter((s) => s.length > 0);
|
|
124
|
+
if (segments.length === 0 || segments[0] !== "artifacts") {
|
|
125
|
+
return abs;
|
|
126
|
+
}
|
|
127
|
+
const tail = segments.slice(1);
|
|
128
|
+
return tail.length > 0 ? path6.join(wr, ".bluma", "artifacts", ...tail) : path6.join(wr, ".bluma", "artifacts");
|
|
129
|
+
}
|
|
116
130
|
function resolveWorkspacePath(inputPath, policy = getSandboxPolicy()) {
|
|
117
131
|
const candidate = path6.isAbsolute(inputPath) ? path6.resolve(inputPath) : path6.resolve(policy.workspaceRoot, inputPath);
|
|
118
132
|
if (policy.isSandbox && !isPathInsideWorkspace(candidate, policy)) {
|
|
@@ -120,7 +134,7 @@ function resolveWorkspacePath(inputPath, policy = getSandboxPolicy()) {
|
|
|
120
134
|
`Path "${inputPath}" escapes the sandbox workspace root ${policy.workspaceRoot}`
|
|
121
135
|
);
|
|
122
136
|
}
|
|
123
|
-
return candidate;
|
|
137
|
+
return redirectTopLevelArtifactsPath(candidate, policy.workspaceRoot);
|
|
124
138
|
}
|
|
125
139
|
function resolveCommandCwd(cwd, policy = getSandboxPolicy()) {
|
|
126
140
|
const base = cwd ? path6.resolve(cwd) : policy.workspaceRoot;
|
|
@@ -8519,10 +8533,16 @@ var AdvancedFeedbackSystem = class {
|
|
|
8519
8533
|
score: penalty,
|
|
8520
8534
|
message: "You are attempting a direct message without a tool_call. All replies must contain tool_call.",
|
|
8521
8535
|
correction: `
|
|
8522
|
-
|
|
8523
|
-
|
|
8524
|
-
|
|
8525
|
-
|
|
8536
|
+
## PROTOCOL VIOLATION \u2014 STOP WRITING PLAIN ASSISTANT TEXT
|
|
8537
|
+
|
|
8538
|
+
You streamed or returned **user-visible markdown as assistant content** instead of using the **\`message\` tool**. That is prohibited and **does not end the turn** \u2014 the runtime will loop until timeout.
|
|
8539
|
+
|
|
8540
|
+
Do this **immediately** in your next step (single tool call, no prose outside tools):
|
|
8541
|
+
|
|
8542
|
+
- Call **\`message\`** with **\`message_type\`: \`"result"\`**, put the user-facing summary in **\`content\`**, and put deliverable paths in **\`attachments\`** (absolute paths).
|
|
8543
|
+
|
|
8544
|
+
Do **not** repeat the same summary as plain assistant text again.
|
|
8545
|
+
PENALTY APPLIED: ${penalty.toFixed(1)} points deducted.
|
|
8526
8546
|
`.trim()
|
|
8527
8547
|
};
|
|
8528
8548
|
}
|
|
@@ -9945,6 +9965,7 @@ The \\\`message\\\` tool has TWO types \u2014 use them CORRECTLY:
|
|
|
9945
9965
|
- **Use when**: Task is complete, artifacts ready for delivery
|
|
9946
9966
|
- **Use ONCE per turn** \u2014 only at the very end
|
|
9947
9967
|
- **Ends the turn** \u2014 agent waits for next input
|
|
9968
|
+
- **CRITICAL:** Plain assistant markdown (streaming or not) **does not** end the worker or close the HTTP job \u2014 only a \\\`message\\\` tool call with \\\`message_type: "result"\\\` does. If you only write text in chat, the process loops until **timeout** (e.g. 300s).
|
|
9948
9969
|
|
|
9949
9970
|
#### \u274C WRONG: Using "info" to ask questions
|
|
9950
9971
|
\\\`\\\`\\\`typescript
|
|
@@ -10063,6 +10084,7 @@ You (Bluma):
|
|
|
10063
10084
|
|
|
10064
10085
|
- **Sandbox is safe** - You can't break the host system
|
|
10065
10086
|
- **But workspace matters** - Don't pollute /workspace with junk files
|
|
10087
|
+
- **Deliverables path** - Never use a top-level \`./artifacts/\` folder in the job root; use \`./.bluma/artifacts/\` (or the \`artifacts_dir\` from \`task_boundary\`). Shell redirects must use that path \u2014 \`file_write\` remaps \`artifacts/...\` to \`.bluma/artifacts/...\` automatically.
|
|
10066
10088
|
- **Clean up after yourself** - Remove temporary files when done
|
|
10067
10089
|
- **Respect session boundaries** - Stay in your session workspace
|
|
10068
10090
|
|
|
@@ -10288,6 +10310,10 @@ Auto-generated map (may be stale after pull/install). Confirm with tools before
|
|
|
10288
10310
|
<<<BLUMA_WORKSPACE_SNAPSHOT_BODY>>>
|
|
10289
10311
|
</workspace_snapshot>
|
|
10290
10312
|
|
|
10313
|
+
<deliverables>
|
|
10314
|
+
**Local and sandbox:** generated artifacts (reports, PDFs, exports, plans you attach) must live under \`<workdir>/.bluma/\` \u2014 use \`.bluma/artifacts/\` (or the \`artifacts_dir\` path returned by \`task_boundary\` after starting a task). Do **not** create a top-level \`./artifacts/\` folder in the project root. \`file_write\` / \`edit_tool\` / \`read_file_lines\` automatically remap \`artifacts/...\` \u2192 \`.bluma/artifacts/...\`. For \`shell_command\` redirects (\`>\` / \`>>\`), target \`.bluma/artifacts/...\` explicitly.
|
|
10315
|
+
</deliverables>
|
|
10316
|
+
|
|
10291
10317
|
<coding_memory>
|
|
10292
10318
|
Persistent store (~/.bluma/coding_memory.json). Do not invent entries: \`list\` / \`search\` if unsure. \`<coding_memory_snapshot>\` is bootstrap only \u2014 after add/update/remove, list or search again. Operations: add | list | search | update (id) | remove (id), one mutating call at a time.
|
|
10293
10319
|
</coding_memory>
|
|
@@ -10313,7 +10339,7 @@ Output is truncated (~30KB / ~200 lines); use head/tail or write to a file. Use
|
|
|
10313
10339
|
The user **only** sees chat content you send through the \`message\` tool (\`content\` as Markdown). Bare assistant text is **not** a substitute \u2014 **you should use \`message\` liberally**.
|
|
10314
10340
|
|
|
10315
10341
|
**Types**
|
|
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.
|
|
10342
|
+
- \`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. **Sandbox/worker:** only this stops the job; writing markdown as normal assistant output does **not** finish the task and can cause a **timeout loop**.
|
|
10317
10343
|
- \`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.
|
|
10318
10344
|
|
|
10319
10345
|
**\u26A0\uFE0F CRITICAL: "info" is for INFORMATION ONLY \u2014 NEVER for asking questions**
|
|
@@ -11449,6 +11475,8 @@ var BluMaAgent = class {
|
|
|
11449
11475
|
factorRouterTurnClosed = false;
|
|
11450
11476
|
/** Passos seguidos sem tool_calls nem texto visível (só raciocínio) — evita loop lento no mesmo turno. */
|
|
11451
11477
|
emptyAssistantReplySteps = 0;
|
|
11478
|
+
/** Passos seguidos com texto do assistente sem tool_calls (violação de protocolo) — evita loop até timeout do job. */
|
|
11479
|
+
directTextProtocolSteps = 0;
|
|
11452
11480
|
constructor(sessionId, eventBus, llm, mcpClient, feedbackSystem) {
|
|
11453
11481
|
this.sessionId = sessionId;
|
|
11454
11482
|
this.eventBus = eventBus;
|
|
@@ -11592,6 +11620,7 @@ var BluMaAgent = class {
|
|
|
11592
11620
|
const userContent = buildUserMessageContent(inputText, process.cwd());
|
|
11593
11621
|
this.history.push({ role: "user", content: userContent });
|
|
11594
11622
|
this.emptyAssistantReplySteps = 0;
|
|
11623
|
+
this.directTextProtocolSteps = 0;
|
|
11595
11624
|
this.eventBus.emit(
|
|
11596
11625
|
"backend_message",
|
|
11597
11626
|
buildTurnStartBackendMessage({
|
|
@@ -12149,6 +12178,7 @@ ${editData.error.display}`;
|
|
|
12149
12178
|
this.history.push(normalizedMessage);
|
|
12150
12179
|
if (normalizedMessage.tool_calls && normalizedMessage.tool_calls.length > 0) {
|
|
12151
12180
|
this.emptyAssistantReplySteps = 0;
|
|
12181
|
+
this.directTextProtocolSteps = 0;
|
|
12152
12182
|
const validToolCalls = normalizedMessage.tool_calls.filter(
|
|
12153
12183
|
(call) => ToolCallNormalizer.isValidToolCall(call)
|
|
12154
12184
|
);
|
|
@@ -12188,9 +12218,20 @@ ${editData.error.display}`;
|
|
|
12188
12218
|
}
|
|
12189
12219
|
} else if (trimmedText) {
|
|
12190
12220
|
this.emptyAssistantReplySteps = 0;
|
|
12221
|
+
this.directTextProtocolSteps += 1;
|
|
12222
|
+
const MAX_DIRECT_TEXT_PROTOCOL = 3;
|
|
12191
12223
|
if (!hasEmittedStart) {
|
|
12192
12224
|
this.eventBus.emit("backend_message", { type: "assistant_message", content: accumulatedContent });
|
|
12193
12225
|
}
|
|
12226
|
+
if (this.directTextProtocolSteps >= MAX_DIRECT_TEXT_PROTOCOL) {
|
|
12227
|
+
this.eventBus.emit("backend_message", {
|
|
12228
|
+
type: "error",
|
|
12229
|
+
message: 'Agent kept answering with plain assistant text instead of the `message` tool with message_type "result". Turn forcibly closed to avoid job timeout; fix prompts or model routing.'
|
|
12230
|
+
});
|
|
12231
|
+
await this.notifyFactorTurnEndIfNeeded("protocol_direct_text_exhausted");
|
|
12232
|
+
this.emitTurnCompleted();
|
|
12233
|
+
return;
|
|
12234
|
+
}
|
|
12194
12235
|
const feedback = this.feedbackSystem.generateFeedback({
|
|
12195
12236
|
event: "protocol_violation_direct_text",
|
|
12196
12237
|
details: { violationContent: accumulatedContent }
|
|
@@ -12226,6 +12267,7 @@ ${editData.error.display}`;
|
|
|
12226
12267
|
this.history.push(message2);
|
|
12227
12268
|
if (message2.tool_calls && message2.tool_calls.length > 0) {
|
|
12228
12269
|
this.emptyAssistantReplySteps = 0;
|
|
12270
|
+
this.directTextProtocolSteps = 0;
|
|
12229
12271
|
const validToolCalls = message2.tool_calls.filter(
|
|
12230
12272
|
(call) => ToolCallNormalizer.isValidToolCall(call)
|
|
12231
12273
|
);
|
|
@@ -12265,7 +12307,18 @@ ${editData.error.display}`;
|
|
|
12265
12307
|
}
|
|
12266
12308
|
} else if (typeof message2.content === "string" && message2.content.trim()) {
|
|
12267
12309
|
this.emptyAssistantReplySteps = 0;
|
|
12310
|
+
this.directTextProtocolSteps += 1;
|
|
12311
|
+
const MAX_DIRECT_TEXT_PROTOCOL = 3;
|
|
12268
12312
|
this.eventBus.emit("backend_message", { type: "assistant_message", content: message2.content });
|
|
12313
|
+
if (this.directTextProtocolSteps >= MAX_DIRECT_TEXT_PROTOCOL) {
|
|
12314
|
+
this.eventBus.emit("backend_message", {
|
|
12315
|
+
type: "error",
|
|
12316
|
+
message: 'Agent kept answering with plain assistant text instead of the `message` tool with message_type "result". Turn forcibly closed to avoid job timeout.'
|
|
12317
|
+
});
|
|
12318
|
+
await this.notifyFactorTurnEndIfNeeded("protocol_direct_text_exhausted");
|
|
12319
|
+
this.emitTurnCompleted();
|
|
12320
|
+
return;
|
|
12321
|
+
}
|
|
12269
12322
|
const feedback = this.feedbackSystem.generateFeedback({
|
|
12270
12323
|
event: "protocol_violation_direct_text",
|
|
12271
12324
|
details: { violationContent: message2.content }
|
|
@@ -15990,12 +16043,11 @@ Run: npm i -g ${BLUMA_PACKAGE_NAME} to update.`;
|
|
|
15990
16043
|
}
|
|
15991
16044
|
}
|
|
15992
16045
|
|
|
15993
|
-
// src/app/ui/components/
|
|
16046
|
+
// src/app/ui/components/UpdateNotice.tsx
|
|
15994
16047
|
import { Box as Box17, Text as Text16 } from "ink";
|
|
15995
|
-
|
|
15996
|
-
// src/app/ui/utils/update_message.ts
|
|
16048
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
15997
16049
|
function parseUpdateMessage(msg) {
|
|
15998
|
-
const lines =
|
|
16050
|
+
const lines = msg.split(/\r?\n/).map((l) => l.trim());
|
|
15999
16051
|
const first = lines[0] || "";
|
|
16000
16052
|
const hintLine = lines.slice(1).join(" ") || "";
|
|
16001
16053
|
const nameMatch = first.match(/Update available for\s+([^!]+)!/i);
|
|
@@ -16007,38 +16059,19 @@ function parseUpdateMessage(msg) {
|
|
|
16007
16059
|
hint: hintLine || void 0
|
|
16008
16060
|
};
|
|
16009
16061
|
}
|
|
16010
|
-
|
|
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
|
-
}) => {
|
|
16062
|
+
var UpdateNotice = ({ message: message2 }) => {
|
|
16021
16063
|
const { name, current, latest: latest2, hint } = parseUpdateMessage(message2);
|
|
16022
|
-
|
|
16023
|
-
|
|
16024
|
-
/* @__PURE__ */ jsxs16(
|
|
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: [
|
|
16064
|
+
return /* @__PURE__ */ jsx18(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", paddingLeft: 2, children: [
|
|
16065
|
+
name && current && latest2 ? /* @__PURE__ */ jsx18(Text16, { color: BLUMA_TERMINAL.claude, bold: true, children: name }) : null,
|
|
16066
|
+
name && current && latest2 ? /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
|
|
16032
16067
|
current,
|
|
16033
16068
|
" \u2192 ",
|
|
16034
16069
|
latest2
|
|
16035
|
-
] }) :
|
|
16036
|
-
/* @__PURE__ */ jsx18(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text16, { dimColor: true,
|
|
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" }) })
|
|
16070
|
+
] }) : /* @__PURE__ */ jsx18(Text16, { dimColor: true, children: message2 }),
|
|
16071
|
+
hint ? /* @__PURE__ */ jsx18(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text16, { dimColor: true, children: hint }) }) : null
|
|
16039
16072
|
] }) });
|
|
16040
16073
|
};
|
|
16041
|
-
var
|
|
16074
|
+
var UpdateNotice_default = UpdateNotice;
|
|
16042
16075
|
|
|
16043
16076
|
// src/app/ui/components/ErrorMessage.tsx
|
|
16044
16077
|
import { Box as Box18, Text as Text17 } from "ink";
|
|
@@ -16630,10 +16663,6 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16630
16663
|
"Initializing agent..."
|
|
16631
16664
|
);
|
|
16632
16665
|
const [toolsCount, setToolsCount] = useState11(null);
|
|
16633
|
-
const [startupPhase, setStartupPhase] = useState11("checking");
|
|
16634
|
-
const [startupUpdateMessage, setStartupUpdateMessage] = useState11(
|
|
16635
|
-
null
|
|
16636
|
-
);
|
|
16637
16666
|
const [mcpStatus, setMcpStatus] = useState11(
|
|
16638
16667
|
"connecting"
|
|
16639
16668
|
);
|
|
@@ -16647,12 +16676,23 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16647
16676
|
const [pendingAskUserQuestions, setPendingAskUserQuestions] = useState11(null);
|
|
16648
16677
|
const [showWorkers, setShowWorkers] = useState11(false);
|
|
16649
16678
|
const [zoomedWorkerSession, setZoomedWorkerSession] = useState11(null);
|
|
16679
|
+
useInput6((input, key) => {
|
|
16680
|
+
if (key.ctrl && key.shift && input.toLowerCase() === "w") {
|
|
16681
|
+
setShowWorkers((prev) => !prev);
|
|
16682
|
+
}
|
|
16683
|
+
if (key.escape && showWorkers) {
|
|
16684
|
+
if (zoomedWorkerSession) {
|
|
16685
|
+
setZoomedWorkerSession(null);
|
|
16686
|
+
} else {
|
|
16687
|
+
setShowWorkers(false);
|
|
16688
|
+
}
|
|
16689
|
+
}
|
|
16690
|
+
});
|
|
16650
16691
|
const [isInitAgentActive, setIsInitAgentActive] = useState11(false);
|
|
16651
16692
|
const [liveToolName, setLiveToolName] = useState11(null);
|
|
16652
16693
|
const [liveToolArgs, setLiveToolArgs] = useState11(void 0);
|
|
16653
16694
|
const [isReasoning, setIsReasoning] = useState11(false);
|
|
16654
16695
|
const alwaysAcceptList = useRef6([]);
|
|
16655
|
-
const agentInitializationStartedRef = useRef6(false);
|
|
16656
16696
|
const workdir = process.cwd();
|
|
16657
16697
|
const turnStartedAtRef = useRef6(null);
|
|
16658
16698
|
const [processingStartMs, setProcessingStartMs] = useState11(null);
|
|
@@ -16686,33 +16726,6 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16686
16726
|
];
|
|
16687
16727
|
});
|
|
16688
16728
|
}, []);
|
|
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]);
|
|
16716
16729
|
useEffect11(() => {
|
|
16717
16730
|
expandPreviewHotkeyBus.on("expand", appendExpandPreviewToHistory);
|
|
16718
16731
|
return () => {
|
|
@@ -16720,24 +16733,22 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16720
16733
|
};
|
|
16721
16734
|
}, [appendExpandPreviewToHistory]);
|
|
16722
16735
|
useEffect11(() => {
|
|
16723
|
-
if (process.env.CI || blumaUpdateRegistryCheckStarted)
|
|
16724
|
-
setStartupPhase("starting-agent");
|
|
16725
|
-
void startAgentInitialization();
|
|
16726
|
-
return;
|
|
16727
|
-
}
|
|
16736
|
+
if (process.env.CI || blumaUpdateRegistryCheckStarted) return;
|
|
16728
16737
|
blumaUpdateRegistryCheckStarted = true;
|
|
16729
|
-
setStatusMessage("Checking for updates...");
|
|
16730
16738
|
void checkForUpdates().then((msg) => {
|
|
16731
|
-
if (!msg)
|
|
16732
|
-
|
|
16733
|
-
|
|
16734
|
-
return
|
|
16735
|
-
|
|
16736
|
-
|
|
16737
|
-
|
|
16738
|
-
|
|
16739
|
+
if (!msg) return;
|
|
16740
|
+
setHistory((prev) => {
|
|
16741
|
+
const nextId2 = prev.length === 0 ? 1 : Math.max(...prev.map((h) => h.id), HEADER_PANEL_HISTORY_ID) + 1;
|
|
16742
|
+
return [
|
|
16743
|
+
...prev,
|
|
16744
|
+
{
|
|
16745
|
+
id: nextId2,
|
|
16746
|
+
component: /* @__PURE__ */ jsx27(UpdateNotice_default, { message: msg })
|
|
16747
|
+
}
|
|
16748
|
+
];
|
|
16749
|
+
});
|
|
16739
16750
|
});
|
|
16740
|
-
}, [
|
|
16751
|
+
}, []);
|
|
16741
16752
|
useEffect11(() => {
|
|
16742
16753
|
setHistory((prev) => {
|
|
16743
16754
|
const tail = prev.filter((h) => h.id !== HEADER_PANEL_HISTORY_ID);
|
|
@@ -16767,28 +16778,6 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
16767
16778
|
];
|
|
16768
16779
|
});
|
|
16769
16780
|
}, [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
|
-
});
|
|
16792
16781
|
const handleSubmit = useCallback4(
|
|
16793
16782
|
(text) => {
|
|
16794
16783
|
if (!text || !agentInstance.current) return;
|
|
@@ -17044,6 +17033,28 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
17044
17033
|
}
|
|
17045
17034
|
}, [history.length]);
|
|
17046
17035
|
useEffect11(() => {
|
|
17036
|
+
const initializeAgent = async () => {
|
|
17037
|
+
try {
|
|
17038
|
+
agentInstance.current = new Agent(sessionId, eventBus);
|
|
17039
|
+
await agentInstance.current.initialize();
|
|
17040
|
+
appendHookEvent({
|
|
17041
|
+
type: "session:init",
|
|
17042
|
+
sessionId,
|
|
17043
|
+
summary: "agent initialized"
|
|
17044
|
+
});
|
|
17045
|
+
eventBus.emit("backend_message", {
|
|
17046
|
+
type: "status",
|
|
17047
|
+
status: "mcp_connected",
|
|
17048
|
+
tools: agentInstance.current.getAvailableTools().length
|
|
17049
|
+
});
|
|
17050
|
+
} catch (error) {
|
|
17051
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error during Agent initialization.";
|
|
17052
|
+
eventBus.emit("backend_message", {
|
|
17053
|
+
type: "error",
|
|
17054
|
+
message: errorMessage
|
|
17055
|
+
});
|
|
17056
|
+
}
|
|
17057
|
+
};
|
|
17047
17058
|
const handleBackendMessage = (parsed) => {
|
|
17048
17059
|
try {
|
|
17049
17060
|
const appendTurnDurationIfAny = () => {
|
|
@@ -17298,6 +17309,7 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
17298
17309
|
uiEventBus.on("user_overlay", handleUiOverlay);
|
|
17299
17310
|
uiEventBus.on("input_notice", handleInputNotice);
|
|
17300
17311
|
eventBus.on("backend_message", handleBackendMessage);
|
|
17312
|
+
initializeAgent();
|
|
17301
17313
|
return () => {
|
|
17302
17314
|
uiEventBus.off("user_overlay", handleUiOverlay);
|
|
17303
17315
|
uiEventBus.off("input_notice", handleInputNotice);
|
|
@@ -17305,27 +17317,6 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
17305
17317
|
};
|
|
17306
17318
|
}, [eventBus, sessionId, handleConfirmation]);
|
|
17307
17319
|
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
|
-
}
|
|
17329
17320
|
if (mcpStatus !== "connected") {
|
|
17330
17321
|
return /* @__PURE__ */ jsx27(
|
|
17331
17322
|
SessionInfoConnectingMCP_default,
|