@nomad-e/bluma-cli 0.1.38 → 0.1.40
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/config/skills/xlsx/SKILL.md +38 -4
- package/dist/main.js +73 -42
- package/package.json +3 -3
|
@@ -5,10 +5,12 @@ description: >
|
|
|
5
5
|
Triggers: open, read, edit, create, fix, or convert .xlsx, .xlsm, .csv,
|
|
6
6
|
or .tsv files — including adding columns, computing formulas, formatting,
|
|
7
7
|
charting, cleaning messy data, restructuring tabular data, or building
|
|
8
|
-
financial models.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
financial models. Prefer normal Excel formulas in cells (visible in the
|
|
9
|
+
formula bar, human-auditable), not hidden logic or pasted numeric results.
|
|
10
|
+
Also trigger when the user references a spreadsheet by name or path and
|
|
11
|
+
wants something done to it. The deliverable must be a spreadsheet file.
|
|
12
|
+
Do NOT trigger when the primary deliverable is a Word document, HTML
|
|
13
|
+
report, or standalone script.
|
|
12
14
|
license: Proprietary. LICENSE.txt has complete terms
|
|
13
15
|
---
|
|
14
16
|
|
|
@@ -20,6 +22,28 @@ license: Proprietary. LICENSE.txt has complete terms
|
|
|
20
22
|
> formula so the spreadsheet stays dynamic. Never compute in Python and
|
|
21
23
|
> paste the result into a cell.
|
|
22
24
|
|
|
25
|
+
### Human-readable formulas — everything visible in Excel
|
|
26
|
+
|
|
27
|
+
The workbook must behave like one a **human analyst** would open and audit:
|
|
28
|
+
|
|
29
|
+
- **Visible in the formula bar:** Any cell that depends on other cells MUST
|
|
30
|
+
store a real Excel formula (string starting with `=`). When the user
|
|
31
|
+
selects the cell, they see the formula — not a magic number that was
|
|
32
|
+
computed offline.
|
|
33
|
+
- **No “black box” outputs:** Do not replace formulas with static values
|
|
34
|
+
except for true inputs (assumptions, imported facts). Intermediate and
|
|
35
|
+
final calculated columns = formulas referencing cells/sheets.
|
|
36
|
+
- **Readable structure:** Prefer clear, conventional functions (`SUM`,
|
|
37
|
+
`AVERAGE`, `IF`, `SUMIF`, `XLOOKUP`/`VLOOKUP`, etc.) and broken-out
|
|
38
|
+
helper columns over one impenetrable mega-formula, when that makes the
|
|
39
|
+
model easier to follow — same as a careful human would build.
|
|
40
|
+
- **Auditable trail:** Another person should trace “this total → those
|
|
41
|
+
lines → those inputs” using only Excel (Show Formulas / following
|
|
42
|
+
references), without reading Python.
|
|
43
|
+
- **openpyxl:** Assign formulas as strings, e.g. `ws['D2'] = '=B2*C2'`, so
|
|
44
|
+
they remain formulas in the saved file. Never save a workbook opened with
|
|
45
|
+
`data_only=True` if you need formulas preserved (see Reading section).
|
|
46
|
+
|
|
23
47
|
## Output Quality Standards
|
|
24
48
|
|
|
25
49
|
### Professional Appearance
|
|
@@ -135,6 +159,16 @@ ws['B10'] = '=SUM(B2:B9)'
|
|
|
135
159
|
This applies to ALL calculations: totals, averages, percentages,
|
|
136
160
|
growth rates, ratios, conditional aggregations.
|
|
137
161
|
|
|
162
|
+
### Visibility checklist (model must self-verify)
|
|
163
|
+
|
|
164
|
+
- Opening the file in Excel/LibreOffice: calculated cells show **formulas**
|
|
165
|
+
in the formula bar, not only final numbers with no `=`.
|
|
166
|
+
- Totals, subtotals, ratios, and lookups reference **cell addresses** or
|
|
167
|
+
structured ranges — not constants copied from a script.
|
|
168
|
+
- If the user asked for “Excel they can trust,” err on the side of **more
|
|
169
|
+
rows/columns with simpler formulas** rather than fewer cells with opaque
|
|
170
|
+
nested functions.
|
|
171
|
+
|
|
138
172
|
### Common Formula Patterns
|
|
139
173
|
|
|
140
174
|
| Operation | Formula |
|
package/dist/main.js
CHANGED
|
@@ -9261,21 +9261,23 @@ var SlashCommands = ({
|
|
|
9261
9261
|
var SlashCommands_default = SlashCommands;
|
|
9262
9262
|
|
|
9263
9263
|
// src/app/agent/utils/update_check.ts
|
|
9264
|
-
import
|
|
9264
|
+
import latestVersion from "latest-version";
|
|
9265
|
+
import semverGt from "semver/functions/gt.js";
|
|
9266
|
+
import semverValid from "semver/functions/valid.js";
|
|
9265
9267
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
9266
9268
|
import path21 from "path";
|
|
9267
9269
|
import fs17 from "fs";
|
|
9268
9270
|
var BLUMA_PACKAGE_NAME = "@nomad-e/bluma-cli";
|
|
9269
9271
|
function findBlumaPackageJson(startDir) {
|
|
9270
9272
|
let dir = startDir;
|
|
9271
|
-
for (let i = 0; i <
|
|
9273
|
+
for (let i = 0; i < 12; i++) {
|
|
9272
9274
|
const candidate = path21.join(dir, "package.json");
|
|
9273
9275
|
if (fs17.existsSync(candidate)) {
|
|
9274
9276
|
try {
|
|
9275
9277
|
const raw = fs17.readFileSync(candidate, "utf8");
|
|
9276
9278
|
const parsed = JSON.parse(raw);
|
|
9277
9279
|
if (parsed?.name === BLUMA_PACKAGE_NAME && parsed?.version) {
|
|
9278
|
-
return { name: parsed.name, version: parsed.version };
|
|
9280
|
+
return { name: parsed.name, version: String(parsed.version) };
|
|
9279
9281
|
}
|
|
9280
9282
|
} catch {
|
|
9281
9283
|
}
|
|
@@ -9286,41 +9288,67 @@ function findBlumaPackageJson(startDir) {
|
|
|
9286
9288
|
}
|
|
9287
9289
|
return null;
|
|
9288
9290
|
}
|
|
9291
|
+
function resolveInstalledBlumaPackage() {
|
|
9292
|
+
const tried = /* @__PURE__ */ new Set();
|
|
9293
|
+
const tryFrom = (dir) => {
|
|
9294
|
+
const abs = path21.resolve(dir);
|
|
9295
|
+
if (tried.has(abs)) return null;
|
|
9296
|
+
tried.add(abs);
|
|
9297
|
+
return findBlumaPackageJson(abs);
|
|
9298
|
+
};
|
|
9299
|
+
try {
|
|
9300
|
+
const fromBundle = tryFrom(path21.dirname(fileURLToPath4(import.meta.url)));
|
|
9301
|
+
if (fromBundle) return fromBundle;
|
|
9302
|
+
} catch {
|
|
9303
|
+
}
|
|
9304
|
+
const argv1 = process.argv[1];
|
|
9305
|
+
if (argv1 && !argv1.startsWith("-")) {
|
|
9306
|
+
try {
|
|
9307
|
+
let resolved = argv1;
|
|
9308
|
+
if (path21.isAbsolute(argv1) && fs17.existsSync(argv1)) {
|
|
9309
|
+
resolved = fs17.realpathSync(argv1);
|
|
9310
|
+
} else {
|
|
9311
|
+
resolved = path21.resolve(process.cwd(), argv1);
|
|
9312
|
+
}
|
|
9313
|
+
const fromArgv = tryFrom(path21.dirname(resolved));
|
|
9314
|
+
if (fromArgv) return fromArgv;
|
|
9315
|
+
} catch {
|
|
9316
|
+
}
|
|
9317
|
+
}
|
|
9318
|
+
return null;
|
|
9319
|
+
}
|
|
9289
9320
|
async function checkForUpdates() {
|
|
9290
9321
|
try {
|
|
9291
9322
|
if (process.env.BLUMA_FORCE_UPDATE_MSG) {
|
|
9292
9323
|
return String(process.env.BLUMA_FORCE_UPDATE_MSG);
|
|
9293
9324
|
}
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
if (binPath && fs17.existsSync(binPath)) {
|
|
9297
|
-
pkg = findBlumaPackageJson(path21.dirname(binPath));
|
|
9325
|
+
if (process.env.CI) {
|
|
9326
|
+
return null;
|
|
9298
9327
|
}
|
|
9328
|
+
const pkg = resolveInstalledBlumaPackage();
|
|
9299
9329
|
if (!pkg) {
|
|
9300
|
-
|
|
9301
|
-
const __dirname = path21.dirname(__filename);
|
|
9302
|
-
pkg = findBlumaPackageJson(__dirname);
|
|
9330
|
+
return null;
|
|
9303
9331
|
}
|
|
9304
|
-
|
|
9332
|
+
const cur = pkg.version.trim();
|
|
9333
|
+
if (!semverValid(cur)) {
|
|
9305
9334
|
return null;
|
|
9306
9335
|
}
|
|
9307
|
-
|
|
9308
|
-
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9312
|
-
shouldNotifyInNpmScript: true
|
|
9313
|
-
});
|
|
9314
|
-
if (notifier.update && !isCI) {
|
|
9315
|
-
const cur = notifier.update.current;
|
|
9316
|
-
const lat = notifier.update.latest;
|
|
9317
|
-
if (cur && lat && cur !== lat) {
|
|
9318
|
-
return `Update available for BluMa CLI! ${cur} \u2192 ${lat}
|
|
9319
|
-
Run: npm i -g ${BLUMA_PACKAGE_NAME} to update.`;
|
|
9320
|
-
}
|
|
9336
|
+
let latRaw;
|
|
9337
|
+
try {
|
|
9338
|
+
latRaw = await latestVersion(BLUMA_PACKAGE_NAME);
|
|
9339
|
+
} catch {
|
|
9340
|
+
return null;
|
|
9321
9341
|
}
|
|
9322
|
-
|
|
9323
|
-
|
|
9342
|
+
const lat = String(latRaw).trim();
|
|
9343
|
+
if (!semverValid(lat)) {
|
|
9344
|
+
return null;
|
|
9345
|
+
}
|
|
9346
|
+
if (!semverGt(lat, cur)) {
|
|
9347
|
+
return null;
|
|
9348
|
+
}
|
|
9349
|
+
return `Update available for BluMa CLI! ${cur} \u2192 ${lat}
|
|
9350
|
+
Run: npm i -g ${BLUMA_PACKAGE_NAME} to update.`;
|
|
9351
|
+
} catch {
|
|
9324
9352
|
return null;
|
|
9325
9353
|
}
|
|
9326
9354
|
}
|
|
@@ -9513,6 +9541,7 @@ var ExpandedPreviewBlock = memo11(ExpandedPreviewBlockComponent);
|
|
|
9513
9541
|
|
|
9514
9542
|
// src/app/ui/App.tsx
|
|
9515
9543
|
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
9544
|
+
var blumaUpdateRegistryCheckStarted = false;
|
|
9516
9545
|
var SAFE_AUTO_APPROVE_TOOLS = [
|
|
9517
9546
|
// Comunicação/UI
|
|
9518
9547
|
"message",
|
|
@@ -9584,7 +9613,6 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
9584
9613
|
const [recentActivityLine, setRecentActivityLine] = useState6(null);
|
|
9585
9614
|
const alwaysAcceptList = useRef5([]);
|
|
9586
9615
|
const workdir = process.cwd();
|
|
9587
|
-
const updateCheckRan = useRef5(false);
|
|
9588
9616
|
const turnStartedAtRef = useRef5(null);
|
|
9589
9617
|
const appendExpandPreviewToHistory = useCallback3(() => {
|
|
9590
9618
|
const p = peekLatestExpandable();
|
|
@@ -9614,6 +9642,23 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
9614
9642
|
expandPreviewHotkeyBus.off("expand", appendExpandPreviewToHistory);
|
|
9615
9643
|
};
|
|
9616
9644
|
}, [appendExpandPreviewToHistory]);
|
|
9645
|
+
useEffect7(() => {
|
|
9646
|
+
if (process.env.CI || blumaUpdateRegistryCheckStarted) return;
|
|
9647
|
+
blumaUpdateRegistryCheckStarted = true;
|
|
9648
|
+
void checkForUpdates().then((msg) => {
|
|
9649
|
+
if (!msg) return;
|
|
9650
|
+
setHistory((prev) => {
|
|
9651
|
+
const nextId3 = prev.length === 0 ? 1 : Math.max(...prev.map((h) => h.id), HEADER_PANEL_HISTORY_ID) + 1;
|
|
9652
|
+
return [
|
|
9653
|
+
...prev,
|
|
9654
|
+
{
|
|
9655
|
+
id: nextId3,
|
|
9656
|
+
component: /* @__PURE__ */ jsx20(UpdateNotice_default, { message: msg })
|
|
9657
|
+
}
|
|
9658
|
+
];
|
|
9659
|
+
});
|
|
9660
|
+
});
|
|
9661
|
+
}, []);
|
|
9617
9662
|
useEffect7(() => {
|
|
9618
9663
|
setHistory((prev) => {
|
|
9619
9664
|
const tail = prev.filter((h) => h.id !== HEADER_PANEL_HISTORY_ID);
|
|
@@ -9874,20 +9919,6 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
9874
9919
|
setToolsCount(parsed.tools);
|
|
9875
9920
|
setMcpStatus("connected");
|
|
9876
9921
|
setIsProcessing(false);
|
|
9877
|
-
if (!updateCheckRan.current) {
|
|
9878
|
-
updateCheckRan.current = true;
|
|
9879
|
-
Promise.resolve().then(() => checkForUpdates()).then((msg) => {
|
|
9880
|
-
if (msg) {
|
|
9881
|
-
setHistory((prev) => [
|
|
9882
|
-
...prev,
|
|
9883
|
-
{
|
|
9884
|
-
id: prev.length,
|
|
9885
|
-
component: /* @__PURE__ */ jsx20(UpdateNotice_default, { message: msg })
|
|
9886
|
-
}
|
|
9887
|
-
]);
|
|
9888
|
-
}
|
|
9889
|
-
}).catch(() => void 0);
|
|
9890
|
-
}
|
|
9891
9922
|
return;
|
|
9892
9923
|
}
|
|
9893
9924
|
if (parsed.type === "error") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nomad-e/bluma-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.40",
|
|
4
4
|
"description": "BluMa independent agent for automation and advanced software engineering.",
|
|
5
5
|
"author": "Alex Fonseca",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"@types/jest": "^30.0.0",
|
|
16
16
|
"@types/node": "^20.14.2",
|
|
17
17
|
"@types/react": "^18.3.3",
|
|
18
|
-
"@types/update-notifier": "^6.0.8",
|
|
19
18
|
"@types/uuid": "^9.0.8",
|
|
20
19
|
"babel-jest": "^30.0.5",
|
|
21
20
|
"babel-plugin-transform-import-meta": "^2.3.3",
|
|
@@ -52,11 +51,12 @@
|
|
|
52
51
|
"ink-spinner": "^5.0.0",
|
|
53
52
|
"ink-text-input": "^6.0.0",
|
|
54
53
|
"js-tiktoken": "^1.0.21",
|
|
54
|
+
"latest-version": "^9.0.0",
|
|
55
55
|
"marked": "^16.1.2",
|
|
56
56
|
"openai": "^4.47.3",
|
|
57
57
|
"react-devtools-core": "^4.28.5",
|
|
58
58
|
"read-package-up": "^11.0.0",
|
|
59
|
-
"
|
|
59
|
+
"semver": "^7.7.4",
|
|
60
60
|
"uuid": "^9.0.1"
|
|
61
61
|
},
|
|
62
62
|
"files": [
|