@nomad-e/bluma-cli 0.1.58 → 0.1.60

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 CHANGED
@@ -6,6 +6,8 @@
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
+ > **Credit:** BluMa was conceived and architected by **Alex Fonseca**.
10
+
9
11
  **Current Version:** 0.1.55
10
12
 
11
13
  ---
@@ -295,8 +297,8 @@ BluMa includes **40+ built-in tools** organized by category:
295
297
  | `task_get` | Get one task by id |
296
298
  | `task_update` | Update task fields |
297
299
  | `task_stop` | Cancel a task |
298
- | `create_artifact` | Save documents to `~/.bluma/artifacts/` |
299
- | `read_artifact` | Retrieve saved artifacts |
300
+ | `create_artifact` | Save documents under `<workspace>/.bluma/artifacts/<session>/` (see `task_boundary` → `artifacts_dir`) |
301
+ | `read_artifact` | Read artifacts from the current session directory under `.bluma/artifacts/` |
300
302
 
301
303
  ### Knowledge & Research
302
304
  | Tool | Description |
@@ -777,7 +779,7 @@ Apache 2.0 — see [LICENSE](LICENSE) for details.
777
779
 
778
780
  - **Issues**: [GitHub Issues](https://github.com/nomad-e/bluma-cli/issues)
779
781
  - **Documentation**: This README + `docs/` directory
780
- - **Author**: Alex Fonseca
782
+ - **Author & Architect**: Alex Fonseca (conceived and architected BluMa)
781
783
  - **npm Package**: [@nomad-e/bluma-cli](https://www.npmjs.com/package/@nomad-e/bluma-cli)
782
784
 
783
785
  ### Runtime Modules (v0.1.41+)
@@ -252,7 +252,7 @@
252
252
  "items": {
253
253
  "type": "string"
254
254
  },
255
- "description": "Optional file paths (absolute) to deliver as artifacts/attachments. In sandbox mode, put generated files under ./artifacts/ and include full paths here."
255
+ "description": "Optional file paths (absolute) to deliver as attachments. Put generated files under ./.bluma/artifacts/ (or paths returned by task_boundary / create_artifact); never a top-level ./artifacts/ folder tools remap that to .bluma/artifacts/."
256
256
  }
257
257
  },
258
258
  "required": [
@@ -701,7 +701,7 @@
701
701
  "type": "function",
702
702
  "function": {
703
703
  "name": "create_artifact",
704
- "description": "Create or update an artifact file in the artifacts directory (~/.bluma/artifacts/). Use this to save implementation plans, walkthroughs, notes, or any document the user should review. Supports markdown files.",
704
+ "description": "Create or update an artifact under the workspace .bluma/artifacts/<session>/ directory (see task_boundary artifacts_dir). Use for plans, walkthroughs, notes, or deliverables. Not the same as ~/.bluma.",
705
705
  "parameters": {
706
706
  "type": "object",
707
707
  "properties": {
@@ -725,7 +725,7 @@
725
725
  "type": "function",
726
726
  "function": {
727
727
  "name": "read_artifact",
728
- "description": "Read an existing artifact file from the artifacts directory. Use this to retrieve previously saved plans, walkthroughs, or notes.",
728
+ "description": "Read an artifact from the current session artifacts directory (.bluma/artifacts/<session>/). Use to retrieve plans or notes saved with create_artifact in this task.",
729
729
  "parameters": {
730
730
  "type": "object",
731
731
  "properties": {
@@ -104,7 +104,7 @@ feat(pdf): add CSV-to-PDF report generation
104
104
 
105
105
  Implement create_report.py script that reads CSV data and produces
106
106
  a formatted PDF report using reportlab. Supports custom titles and
107
- outputs to the artifacts directory.
107
+ outputs to `.bluma/artifacts/` in the workspace.
108
108
 
109
109
  - Added scripts/create_report.py with argparse CLI
110
110
  - Table styling with header highlighting and grid borders
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: pdf
3
3
  description: >
4
- Use this skill for any task involving PDF files. Triggers include: creating
5
- new PDFs from scratch, reading or extracting text and tables from PDFs,
6
- merging or splitting PDFs, rotating pages, adding watermarks, encrypting or
7
- decrypting PDFs, filling PDF forms, extracting images, and OCR on scanned
8
- PDFs. Use whenever the user mentions .pdf, "create a report", "generate a
9
- document", "extract from PDF", "merge PDFs", or any PDF-related task.
4
+ Use for any PDF task. For **new business/executive reports**, prefer
5
+ `create_report.py --from-json`: invest effort in **rich, well-structured JSON**
6
+ (clear sections, tight copy, sparse callouts, scannable tables) the template
7
+ already supplies a **modern, restrained** layout; shallow JSON wastes that
8
+ design. Ad-hoc ReportLab snippets produce amateur PDFs. Also: extract/merge/
9
+ OCR/forms. Triggers: .pdf, relatório, report, generate document, merge PDF.
10
10
  license: Proprietary. LICENSE.txt has complete terms
11
11
  ---
12
12
 
@@ -18,6 +18,114 @@ license: Proprietary. LICENSE.txt has complete terms
18
18
  > design agency, not a script. Typography, spacing, color, and hierarchy are
19
19
  > not optional — they are the foundation of a credible document.
20
20
 
21
+ ## MANDATORY workflow — new multi-page reports (read first)
22
+
23
+ Ad-hoc 30-line ReportLab scripts are the #1 cause of “cheap PDF” output (no
24
+ cover hierarchy, ugly tables, random margins). **Do not do that** for anything
25
+ the user will share externally.
26
+
27
+ **Preferred (deliverable quality locked in):**
28
+
29
+ 1. Build a UTF-8 JSON file with `title`, optional `subtitle` / `author`, and
30
+ `sections[]` (`num`, `title`, `blocks[]`). Follow the **JSON quality**
31
+ section below — not only the schema (see **Available Scripts** for types).
32
+ 2. Run: `python /absolute/path/to/scripts/create_report.py --from-json
33
+ your.json --output .bluma/artifacts/your.pdf` (or the path in `artifacts_dir` from `task_boundary`)
34
+ 3. Attach that **absolute** path as the deliverable. Do **not** paste huge
35
+ ReportLab source into the chat unless the user explicitly wants code.
36
+
37
+ **Acceptable alternative:** copy `create_report.py` and edit only data / story
38
+ assembly — keep the same colors, margins, `cover_story`, `section`, `pro_table`,
39
+ `callout`, and `onFirstPage` / `onLaterPages` callbacks.
40
+
41
+ **Hard no (reads as unprofessional):** default ReportLab styles; wall of text
42
+ with no cover; tables without a styled header row; margins under 2cm; emoji in
43
+ corporate PDFs (font/rendering inconsistency); “nota rodapé” as raw
44
+ `canvas.drawString` for body paragraphs instead of `Paragraph` styles.
45
+
46
+ ## JSON quality — make the PDF look “designed”, not “filled in”
47
+
48
+ The `--from-json` pipeline already applies a **clean, modern, understated**
49
+ visual system (slate palette, one accent, generous margins, one chapter per
50
+ page by default). **Exaggerated styling is not available and not desired** —
51
+ quality comes from **editorial structure and copy**, not from shouting.
52
+
53
+ When you author JSON, treat it like briefing a human designer:
54
+
55
+ ### Cover metadata (`title`, `subtitle`, `author`)
56
+
57
+ - **`title`**: specific and scannable (e.g. “Relatório de atividade — Agiweb”),
58
+ not a generic “Relatório”. Length is OK; the script balances line breaks.
59
+ - **`subtitle`**: one line that states **scope or period** (what this PDF is
60
+ for). Avoid marketing fluff.
61
+ - **`author`**: organisation or product name the reader recognises; avoid
62
+ “Generated by AI” unless the user asked for it.
63
+
64
+ ### Sections (`num`, `title`, `blocks`)
65
+
66
+ - Aim for **roughly 4–8 sections** for a typical executive note; merge thin
67
+ sections instead of many one-paragraph chapters.
68
+ - **Section titles**: concrete noun phrases (“Módulos ativos”, “Estado
69
+ operacional”) — not “Parte 2” or “Informações”.
70
+ - **Order inside a section** (good rhythm):
71
+ 1. One or two **`paragraph`** blocks that set context (2–4 short sentences,
72
+ one main idea each; use `\n` only for a deliberate second paragraph).
73
+ 2. Optionally an **`h2`** for a sub-topic if the section has two distinct
74
+ ideas.
75
+ 3. **`bullets`** or **`table`** — not both back-to-back unless the second is
76
+ clearly “detail” after the first.
77
+ 4. At most **one `callout`** per section, only for a decision, risk, or
78
+ single takeaway — not for every bullet.
79
+
80
+ ### `paragraph`
81
+
82
+ - Prefer **facts, numbers, names** over vague adjectives (“significativo”,
83
+ “muito importante”). Write in the **same language** as the user’s request.
84
+ - Do not paste huge URLs or stack traces; summarise.
85
+
86
+ ### `bullets`
87
+
88
+ - **Parallel wording** (all start with a verb, or all are noun phrases).
89
+ - **~3–8 items** per list in the body; move long enumerations to a **table** or
90
+ an appendix section.
91
+ - One line per item when possible; trim redundant words.
92
+
93
+ ### `table`
94
+
95
+ - Prefer **2–5 columns**; headers are **short labels** (“Módulo”, “Estado”, not
96
+ sentences).
97
+ - Rows must be **readable at a glance**; paraphrase long statuses instead of
98
+ dumping raw log lines.
99
+ - Omit `col_widths` unless you need to weight columns; the generator normalises
100
+ widths.
101
+
102
+ ### `callout` (`variant`: `info` | `warning`)
103
+
104
+ - **Info**: synthesis, definition, or “how to read this document”.
105
+ - **Warning**: real risk, compliance, or “requires action” — not routine stats.
106
+ - **Title**: 2–5 words; **text**: 1–3 sentences. **Never** stack two callouts in
107
+ a row.
108
+
109
+ ### `h2`
110
+
111
+ - Use sparingly inside long sections; keeps hierarchy without visual noise.
112
+
113
+ ### `page_break_per_section`
114
+
115
+ - Default **`true`** for multi-topic reports (calm, one chapter per page).
116
+ - Set **`false`** only for a short, single-thread document where breaks would
117
+ feel wasteful.
118
+
119
+ ### Restraint checklist (before you run the script)
120
+
121
+ - [ ] Every section has at least one **substantive** `paragraph`, not only
122
+ bullets.
123
+ - [ ] No more than **one callout** per section unless the user explicitly wants
124
+ more.
125
+ - [ ] Tables are **small and meaningful**; no “spreadsheet dump”.
126
+ - [ ] No duplicated content between sumário-level titles and body.
127
+ - [ ] Tone is **professional and calm** — the layout already carries authority.
128
+
21
129
  ## MANDATORY: Professional Style System
22
130
 
23
131
  Every PDF you create MUST use a consistent design system. Define these at the
@@ -29,17 +137,19 @@ top of every script BEFORE building any content.
29
137
  from reportlab.lib.colors import HexColor
30
138
 
31
139
  COLORS = {
32
- 'primary': HexColor('#1B2A4A'), # Dark navy titles, headers
33
- 'secondary': HexColor('#2C5F8A'), # Steel blue subtitles, accents
34
- 'accent': HexColor('#E67E22'), # Warm orange highlights, callouts
35
- 'text': HexColor('#2D3436'), # Near-blackbody text
36
- 'text_light': HexColor('#636E72'), # Gray — captions, footnotes
37
- 'bg_light': HexColor('#F8F9FA'), # Light gray — callout backgrounds
38
- 'bg_accent': HexColor('#EBF5FB'), # Light blue — info boxes
39
- 'border': HexColor('#BDC3C7'), # Subtle border
140
+ # Keep in sync with scripts/create_report.py when editing custom code
141
+ 'primary': HexColor('#0F172A'), # Slatetitles, table headers
142
+ 'secondary': HexColor('#334155'), # Slatesubtitles, rules
143
+ 'accent': HexColor('#C2410C'), # Burnt orange rules, emphasis
144
+ 'muted': HexColor('#64748B'),
145
+ 'text': HexColor('#1E293B'),
146
+ 'text_light': HexColor('#64748B'),
147
+ 'bg_light': HexColor('#F1F5F9'),
148
+ 'bg_accent': HexColor('#E0F2FE'),
149
+ 'border': HexColor('#CBD5E1'),
40
150
  'white': HexColor('#FFFFFF'),
41
- 'success': HexColor('#27AE60'), # Green — positive indicators
42
- 'danger': HexColor('#E74C3C'), # Red — warnings
151
+ 'success': HexColor('#15803D'),
152
+ 'danger': HexColor('#B91C1C'),
43
153
  }
44
154
  ```
45
155
 
@@ -272,11 +382,11 @@ def add_section(story, number, title):
272
382
  def add_callout(story, title, text, box_type='info'):
273
383
  bg = COLORS['bg_accent'] if box_type == 'info' else COLORS['bg_light']
274
384
  border = COLORS['secondary'] if box_type == 'info' else COLORS['accent']
275
- icon = '💡' if box_type == 'info' else '⚠️'
385
+ label = 'Information' if box_type == 'info' else 'Warning'
276
386
 
277
387
  content = [
278
388
  [Paragraph(
279
- f"<b>{icon} {title}</b>",
389
+ f"<b>{label} {title}</b>",
280
390
  ParagraphStyle('CalloutTitle', fontName=FONT_BOLD,
281
391
  fontSize=10, textColor=COLORS['primary'],
282
392
  spaceAfter=4)
@@ -384,8 +494,12 @@ add_table(story,
384
494
  [['Revenue', '$1.2M', '+15%'], ['Users', '50K', '+22%']],
385
495
  )
386
496
 
387
- doc.build(story, onFirstPage=lambda c, d: None,
388
- onLaterPages=header_footer)
497
+ def cover_canvas(canvas_obj, doc):
498
+ """Page 1 only: brand bar / rules. See create_report.py draw_cover_canvas."""
499
+ pass
500
+
501
+ # First page = cover art; later pages = header + footer
502
+ doc.build(story, onFirstPage=cover_canvas, onLaterPages=header_footer)
389
503
  ```
390
504
 
391
505
  ## Design Rules (MANDATORY)
@@ -399,7 +513,9 @@ doc.build(story, onFirstPage=lambda c, d: None,
399
513
  7. **Spacing**: Generous whitespace. Use `Spacer` between sections
400
514
  8. **Cover page**: Every document with 3+ pages MUST have a cover page
401
515
  9. **Headers/Footers**: Every multi-page document MUST have page numbers
402
- 10. **No raw `drawString`**: Use `Paragraph` with styles for all text
516
+ 10. **Body text**: use `Paragraph` + styles, never raw `drawString` for
517
+ paragraphs. **Exception:** minimal `drawString` in `onFirstPage` /
518
+ `onLaterPages` canvas callbacks for running title and page numbers only.
403
519
  11. **Alignment**: Body text justified, titles centered, code left-aligned
404
520
  12. **Callout boxes**: Use for key insights, warnings, important notes
405
521
  13. **Section dividers**: Use `HRFlowable` or colored bars between major sections
@@ -498,5 +614,20 @@ for i, img in enumerate(images):
498
614
 
499
615
  ## Available Scripts
500
616
 
501
- - create_report.py: Professional report template with cover, TOC, styled sections
617
+ - **create_report.py** default: demo PDF; **production:** `--from-json FILE`
618
+ - Before writing JSON, follow **“JSON quality”** (this file) so content matches
619
+ the clean template — schema alone is not enough.
620
+ - Schema (top-level keys): `title` (str), `subtitle` (optional str),
621
+ `author` (optional str), `page_break_per_section` (optional bool, default
622
+ `true` — cada capítulo começa em página nova), `sections` (array).
623
+ - Each section: `num` (int), `title` (str), `blocks` (array).
624
+ - Each block: `type` is one of:
625
+ - `paragraph` — `{ "type": "paragraph", "text": "..." }` (use `\n` for line breaks)
626
+ - `h2` — `{ "type": "h2", "text": "..." }`
627
+ - `callout` — `{ "type": "callout", "title": "...", "text": "...", "variant": "info"|"warning" }`
628
+ - `bullets` — `{ "type": "bullets", "items": ["...", "..."] }`
629
+ - `table` — `{ "type": "table", "headers": [...], "rows": [[...],...], "col_widths": null or [pt,...] }`
630
+ - `spacer` — `{ "type": "spacer", "pt": 12 }`
631
+ - Plain text in JSON is XML-escaped automatically; do not embed ReportLab HTML
632
+ unless you generate JSON from trusted code that already escapes markup.
502
633
  - merge_pdfs.py: Merge multiple PDFs into one