@cyber-dash-tech/revela 0.1.2 → 0.1.3
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/README.zh-CN.md +1 -1
- package/lib/config.ts +1 -1
- package/lib/design/designs.ts +97 -7
- package/lib/prompt-builder.ts +29 -50
- package/lib/qa/checks.ts +6 -49
- package/lib/qa/measure.ts +8 -7
- package/package.json +1 -1
- package/skill/SKILL.md +19 -195
- package/tools/designs.ts +21 -5
- package/designs/default/DESIGN.md +0 -1100
- package/designs/editorial-ribbon/DESIGN.md +0 -1092
- package/designs/minimal/DESIGN.md +0 -1079
package/skill/SKILL.md
CHANGED
|
@@ -136,8 +136,9 @@ Each axis gets its own dedicated agent with a focused brief. Launch ALL agents
|
|
|
136
136
|
in a single message (parallel Task tool calls).
|
|
137
137
|
|
|
138
138
|
**How to decompose:** Look at what the presentation needs to cover. Each major
|
|
139
|
-
entity, comparison dimension, or macro question is a separate axis.
|
|
140
|
-
|
|
139
|
+
entity, comparison dimension, or macro question is a separate axis. Decompose
|
|
140
|
+
based on topic breadth and the depth each axis warrants — a narrow topic may
|
|
141
|
+
need 2 axes; a complex comparison may need 4 or more. Typical decompositions:
|
|
141
142
|
|
|
142
143
|
| Topic type | Example axes |
|
|
143
144
|
|---|---|
|
|
@@ -146,38 +147,7 @@ decompositions:
|
|
|
146
147
|
| Investment thesis | Opportunity metrics, risk factors, comparable deals, macro trends |
|
|
147
148
|
| Product strategy | User research, competitor features, technology feasibility, go-to-market |
|
|
148
149
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
##### Invocation Example — Multi-Agent Parallel
|
|
152
|
-
|
|
153
|
-
For a topic like "Investment shift from OpenAI to Anthropic":
|
|
154
|
-
|
|
155
|
-
```
|
|
156
|
-
Agent 1 (Anthropic):
|
|
157
|
-
> Research Anthropic's trajectory for a presentation on AI investment shifts:
|
|
158
|
-
> - Funding history: Series rounds, valuations, key investors
|
|
159
|
-
> - Revenue and growth: run-rate, enterprise adoption, key products
|
|
160
|
-
> - Competitive advantages: safety positioning, developer tools, reliability
|
|
161
|
-
> Focus on 2025-2026 data. Write findings to researches/ai-investment-shift/
|
|
162
|
-
|
|
163
|
-
Agent 2 (OpenAI):
|
|
164
|
-
> Research OpenAI's challenges for a presentation on AI investment shifts:
|
|
165
|
-
> - Financial: burn rate, profitability timeline, cost structure
|
|
166
|
-
> - Operational: API reliability data, outage frequency, enterprise complaints
|
|
167
|
-
> - Governance: nonprofit conversion, leadership controversies, investor concerns
|
|
168
|
-
> Focus on 2025-2026 data. Write findings to researches/ai-investment-shift/
|
|
169
|
-
|
|
170
|
-
Agent 3 (Market & Capital Flow):
|
|
171
|
-
> Research AI industry capital flow for a presentation on AI investment shifts:
|
|
172
|
-
> - VC investment patterns: dual-backing trends, secondary market activity
|
|
173
|
-
> - Enterprise adoption: market share shifts, switching patterns
|
|
174
|
-
> - Macro trends: agentic AI adoption, market size projections
|
|
175
|
-
> Focus on 2025-2026 data. Write findings to researches/ai-investment-shift/
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
Launch all agents in **one message** using parallel Task tool calls. Each agent
|
|
179
|
-
runs independently and writes its own findings file:
|
|
180
|
-
`researches/{topic-slug}/{axis-name}.md`
|
|
150
|
+
Launch ALL agents in a single message (parallel Task tool calls).
|
|
181
151
|
|
|
182
152
|
Each agent's brief should specify:
|
|
183
153
|
- The topic slug (shared, e.g. `ai-investment-shift`)
|
|
@@ -192,20 +162,9 @@ each `.md` file. Each file contains structured `## Data`, `## Cases`,
|
|
|
192
162
|
Cross-reference agent findings with workspace documents (Layer 1). Flag any
|
|
193
163
|
contradictions.
|
|
194
164
|
|
|
195
|
-
##### Fallback — ONLY if Research Agent is Unavailable
|
|
196
|
-
|
|
197
|
-
If and only if the Task tool with `subagent_type: "revela-research"` is **not
|
|
198
|
-
available as a tool** (i.e., it does not exist in your tool list), fall back to
|
|
199
|
-
using `webfetch` directly on targeted URLs. Even in fallback mode, structure
|
|
200
|
-
your research by axis — do not run a single vague query.
|
|
201
|
-
|
|
202
|
-
Note: `websearch` is blocked by the Revela plugin when agents are available.
|
|
203
|
-
In fallback mode, use `webfetch` with specific URLs from your knowledge.
|
|
204
|
-
|
|
205
165
|
**Anti-pattern — NEVER do this:**
|
|
206
|
-
- Do NOT use `websearch` directly — it is blocked by the Revela plugin
|
|
207
|
-
|
|
208
|
-
URLs in fallback mode).
|
|
166
|
+
- Do NOT use `websearch` directly — it is blocked by the Revela plugin;
|
|
167
|
+
use research agents instead.
|
|
209
168
|
- Do NOT run a few quick searches, decide "that's enough data", and skip the
|
|
210
169
|
research agent. The agent's job is deep, systematic research — ad-hoc
|
|
211
170
|
fetches cannot replace it.
|
|
@@ -273,13 +232,15 @@ A 6-slide deck might be: Cover → Background → Content × 3 → Closing.
|
|
|
273
232
|
An 8-slide deck might be: Cover → TOC → Background → Content × 3 → Summary → Closing.
|
|
274
233
|
Never skip Cover, Background, or Closing regardless of slide count.
|
|
275
234
|
|
|
276
|
-
**Every `<section class="slide">` must include a `
|
|
235
|
+
**Every `<section class="slide">` must include a `slide-qa` attribute.** Set
|
|
236
|
+
`slide-qa="true"` for content-heavy layouts (those marked ✓ in the Layout Index
|
|
237
|
+
QA column of the active design). Set `slide-qa="false"` for structural or sparse
|
|
238
|
+
layouts (cover, TOC, closing, quote, summary, etc.). When unsure, use `"false"`.
|
|
277
239
|
|
|
278
|
-
|
|
240
|
+
Example: `<section class="slide" slide-qa="true" data-index="0">`
|
|
279
241
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
The layout QA system uses this to skip fill-ratio and spacing checks on structural slides that are intentionally sparse.
|
|
242
|
+
The layout QA system uses this to skip fill-ratio and spacing checks on slides
|
|
243
|
+
that are intentionally sparse.
|
|
283
244
|
|
|
284
245
|
### Domain Context
|
|
285
246
|
|
|
@@ -342,96 +303,17 @@ Follow these rules on every generation. They are non-negotiable.
|
|
|
342
303
|
|
|
343
304
|
### Inline Editing
|
|
344
305
|
|
|
345
|
-
**Always include inline editing** in every generated presentation.
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
Implementation rules:
|
|
350
|
-
|
|
351
|
-
- **JS-based hover activation** — attach `mouseenter` / `mouseleave` listeners
|
|
352
|
-
on editable elements. After a 400ms hover delay, show a subtle outline to
|
|
353
|
-
indicate editability. Click activates `contenteditable`. Click outside or
|
|
354
|
-
press Escape to deactivate.
|
|
355
|
-
- **Never** use CSS `~` sibling selector (breaks due to `pointer-events: none`
|
|
356
|
-
interrupting the hover chain).
|
|
357
|
-
- **Editable elements** — only text content: `h1, h2, h3, h4, p, span, li,
|
|
358
|
-
blockquote, cite` and design-specific text classes (`.card-title`, `.card-body`,
|
|
359
|
-
`.stat-number`, `.stat-label`, `.stat-desc`, `.step-title`, `.step-desc`).
|
|
360
|
-
Never make structural containers or images editable.
|
|
361
|
-
- **Hover style** — `outline: 1px dashed rgba(128,128,128,0.3)` on hover,
|
|
362
|
-
`outline: 2px solid rgba(59,130,246,0.5)` when actively editing. Keep it
|
|
363
|
-
subtle — must not interfere with the design aesthetic.
|
|
364
|
-
- **`window.getEditedHTML()`** — always define this global function. It returns
|
|
365
|
-
the full edited HTML (`'<!DOCTYPE html>\n' + document.documentElement.outerHTML`).
|
|
366
|
-
The parent frame calls this to retrieve the full edited HTML for saving.
|
|
367
|
-
|
|
368
|
-
Reference implementation (include in the `<script>` block after `SlidePresentation`):
|
|
369
|
-
|
|
370
|
-
```javascript
|
|
371
|
-
// --- Inline Editing ---
|
|
372
|
-
(function() {
|
|
373
|
-
const EDITABLE = 'h1,h2,h3,h4,p,span,li,blockquote,cite,' +
|
|
374
|
-
'.card-title,.card-body,.stat-number,.stat-label,.stat-desc,' +
|
|
375
|
-
'.step-title,.step-desc';
|
|
376
|
-
let hoverTimer = null;
|
|
377
|
-
let activeEl = null;
|
|
378
|
-
|
|
379
|
-
document.querySelectorAll(EDITABLE).forEach(el => {
|
|
380
|
-
el.addEventListener('mouseenter', () => {
|
|
381
|
-
hoverTimer = setTimeout(() => {
|
|
382
|
-
el.style.outline = '1px dashed rgba(128,128,128,0.3)';
|
|
383
|
-
el.style.cursor = 'text';
|
|
384
|
-
}, 400);
|
|
385
|
-
});
|
|
386
|
-
el.addEventListener('mouseleave', () => {
|
|
387
|
-
clearTimeout(hoverTimer);
|
|
388
|
-
if (el !== activeEl) {
|
|
389
|
-
el.style.outline = '';
|
|
390
|
-
el.style.cursor = '';
|
|
391
|
-
}
|
|
392
|
-
});
|
|
393
|
-
el.addEventListener('click', (e) => {
|
|
394
|
-
if (activeEl && activeEl !== el) {
|
|
395
|
-
activeEl.contentEditable = 'false';
|
|
396
|
-
activeEl.style.outline = '';
|
|
397
|
-
activeEl.style.cursor = '';
|
|
398
|
-
}
|
|
399
|
-
el.contentEditable = 'true';
|
|
400
|
-
el.style.outline = '2px solid rgba(59,130,246,0.5)';
|
|
401
|
-
el.style.cursor = 'text';
|
|
402
|
-
activeEl = el;
|
|
403
|
-
e.stopPropagation();
|
|
404
|
-
});
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
document.addEventListener('click', () => {
|
|
408
|
-
if (activeEl) {
|
|
409
|
-
activeEl.contentEditable = 'false';
|
|
410
|
-
activeEl.style.outline = '';
|
|
411
|
-
activeEl.style.cursor = '';
|
|
412
|
-
activeEl = null;
|
|
413
|
-
}
|
|
414
|
-
});
|
|
415
|
-
document.addEventListener('keydown', (e) => {
|
|
416
|
-
if (e.key === 'Escape' && activeEl) {
|
|
417
|
-
activeEl.contentEditable = 'false';
|
|
418
|
-
activeEl.style.outline = '';
|
|
419
|
-
activeEl.style.cursor = '';
|
|
420
|
-
activeEl = null;
|
|
421
|
-
}
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
window.getEditedHTML = () =>
|
|
425
|
-
'<!DOCTYPE html>\n' + document.documentElement.outerHTML;
|
|
426
|
-
})();
|
|
427
|
-
```
|
|
306
|
+
**Always include inline editing** in every generated presentation. The complete
|
|
307
|
+
reference implementation is provided in the active design's `@design:foundation`
|
|
308
|
+
section. Follow it exactly — pay attention to the hover-delay pattern, editable
|
|
309
|
+
element selector list, and `window.getEditedHTML()` definition.
|
|
428
310
|
|
|
429
311
|
### Image Rules
|
|
430
312
|
|
|
431
313
|
- Use direct file paths (`src="assets/logo.png"`) in HTML — not base64
|
|
432
314
|
- Always use the **original** file path in HTML `<img src>` for full-quality rendering
|
|
433
315
|
- Never repeat the same image on multiple slides (logos: title + closing only)
|
|
434
|
-
- Image compression is handled automatically by the server
|
|
316
|
+
- Image compression is handled automatically by the server
|
|
435
317
|
- **Use the active design's image components** (`.image-card`, `.card-img`, `.avatar`)
|
|
436
318
|
for displaying images — they provide proper rounded corners and cropping
|
|
437
319
|
|
|
@@ -615,62 +497,4 @@ The active design name is in the HTML comment at the top of this prompt:
|
|
|
615
497
|
The active design's complete visual specification — Component Library, Layout
|
|
616
498
|
Primitives, Composition Guide, and Data Visualization rules — is injected
|
|
617
499
|
below after the `---` separator. This is your sole visual reference for
|
|
618
|
-
generating slides.
|
|
619
|
-
|
|
620
|
-
---
|
|
621
|
-
|
|
622
|
-
## What Comes Next in This System Prompt
|
|
623
|
-
|
|
624
|
-
After the `---` separators below, two additional sections may appear:
|
|
625
|
-
|
|
626
|
-
1. **Domain definition** (if a domain other than "general" is active) — report
|
|
627
|
-
structure, AI logic rules, terminology, and visual preferences for the domain.
|
|
628
|
-
2. **Visual style** (from the active design) — colors, fonts, animation specifics,
|
|
629
|
-
layout variants. Apply it precisely — it overrides any default aesthetic preferences.
|
|
630
|
-
|
|
631
|
-
If only one `---` section follows, it is the visual style (no domain is active).
|
|
632
|
-
|
|
633
|
-
---
|
|
634
|
-
|
|
635
|
-
## File Access Rules
|
|
636
|
-
|
|
637
|
-
### How tools interact with files
|
|
638
|
-
|
|
639
|
-
The workspace `.ignore` file prevents binary formats from appearing in `grep`,
|
|
640
|
-
`glob`, and `list` results (these tools use ripgrep, which honours `.ignore`).
|
|
641
|
-
The `read` tool works by **direct file path** and is **not** affected by
|
|
642
|
-
`.ignore` — if you have a path, you can always `read` it.
|
|
643
|
-
|
|
644
|
-
### Documents
|
|
645
|
-
|
|
646
|
-
`.pdf` `.xlsx` `.xls` `.docx` `.doc` `.pptx` `.ppt` `.csv`
|
|
647
|
-
|
|
648
|
-
If the `extract` tool is available, use it to extract document content as clean
|
|
649
|
-
markdown text. **NEVER** use the `read` tool on PDF, Excel, Word, or PPT files
|
|
650
|
-
— their raw binary content will flood the context window.
|
|
651
|
-
|
|
652
|
-
If the `extract` tool is NOT available, use `read` only for text-based formats
|
|
653
|
-
(`.csv`, plain text). For binary document formats, inform the user and ask them
|
|
654
|
-
to provide the content in text form.
|
|
655
|
-
|
|
656
|
-
### Images
|
|
657
|
-
|
|
658
|
-
`.png` `.jpg` `.jpeg` `.gif` `.webp` `.bmp` `.tiff` `.tif` `.avif`
|
|
659
|
-
|
|
660
|
-
Use the `read` tool to view images directly (OpenCode returns them as visual
|
|
661
|
-
attachments). In HTML, always reference the original file path for full-quality
|
|
662
|
-
rendering:
|
|
663
|
-
|
|
664
|
-
```html
|
|
665
|
-
<img src="photos/screenshot.png" alt="...">
|
|
666
|
-
```
|
|
667
|
-
|
|
668
|
-
### Binary files — never access
|
|
669
|
-
|
|
670
|
-
These are excluded from all tools:
|
|
671
|
-
|
|
672
|
-
`.mp4` `.mov` `.avi` `.mkv` `.webm` `.m4v` `.wmv`
|
|
673
|
-
`.mp3` `.wav` `.ogg` `.flac` `.aac` `.m4a`
|
|
674
|
-
`.zip` `.tar` `.gz` `.bz2` `.7z` `.rar` `.tgz`
|
|
675
|
-
`.woff` `.woff2` `.ttf` `.otf` `.eot`
|
|
676
|
-
`.db` `.sqlite` `.sqlite3` `.bin` `.exe` `.dll` `.so` `.dylib`
|
|
500
|
+
generating slides.
|
package/tools/designs.ts
CHANGED
|
@@ -7,8 +7,10 @@ import {
|
|
|
7
7
|
removeDesign,
|
|
8
8
|
parseDesignSections,
|
|
9
9
|
generateComponentIndex,
|
|
10
|
+
generateLayoutIndex,
|
|
10
11
|
getDesignSection,
|
|
11
12
|
getDesignComponent,
|
|
13
|
+
getDesignLayout,
|
|
12
14
|
} from "../lib/design/designs"
|
|
13
15
|
import { buildPrompt } from "../lib/prompt-builder"
|
|
14
16
|
import { existsSync, readFileSync } from "fs"
|
|
@@ -23,7 +25,7 @@ export default tool({
|
|
|
23
25
|
"Use action 'activate' to switch to a different design (requires name). " +
|
|
24
26
|
"Use action 'install' to add a new design from a URL, local path, or github:user/repo shorthand (requires source). " +
|
|
25
27
|
"Use action 'remove' to uninstall a design (requires name). " +
|
|
26
|
-
"Use action 'read' to fetch on-demand design content: pass component (comma-separated names) to get full CSS/HTML for specific components, or section ('
|
|
28
|
+
"Use action 'read' to fetch on-demand design content: pass layout (comma-separated names) to get full HTML/CSS for specific layouts, pass component (comma-separated names) to get full CSS/HTML for specific components, or section ('chart-rules' | 'foundation' | 'layouts' | 'components') to get an entire section. Pass neither to get the Component Index table. " +
|
|
27
29
|
"After activating a new design, the system prompt is automatically rebuilt.",
|
|
28
30
|
args: {
|
|
29
31
|
action: tool.schema
|
|
@@ -39,6 +41,12 @@ export default tool({
|
|
|
39
41
|
.describe(
|
|
40
42
|
"Install source — URL, local path, github:user/repo. Required for install."
|
|
41
43
|
),
|
|
44
|
+
layout: tool.schema
|
|
45
|
+
.string()
|
|
46
|
+
.optional()
|
|
47
|
+
.describe(
|
|
48
|
+
"For action 'read': comma-separated layout name(s) to fetch (e.g. 'cover', 'two-col,card-grid')"
|
|
49
|
+
),
|
|
42
50
|
component: tool.schema
|
|
43
51
|
.string()
|
|
44
52
|
.optional()
|
|
@@ -49,7 +57,7 @@ export default tool({
|
|
|
49
57
|
.string()
|
|
50
58
|
.optional()
|
|
51
59
|
.describe(
|
|
52
|
-
"For action 'read': section name to fetch — '
|
|
60
|
+
"For action 'read': section name to fetch — 'chart-rules', 'foundation', 'rules', 'layouts', or 'components'"
|
|
53
61
|
),
|
|
54
62
|
},
|
|
55
63
|
async execute(args) {
|
|
@@ -96,13 +104,18 @@ export default tool({
|
|
|
96
104
|
}
|
|
97
105
|
const raw = readFileSync(mdPath, "utf-8")
|
|
98
106
|
const { body } = parseFrontmatter(raw)
|
|
99
|
-
const { components, hasMarkers } = parseDesignSections(body)
|
|
107
|
+
const { layouts, components, hasMarkers } = parseDesignSections(body)
|
|
100
108
|
|
|
101
109
|
if (!hasMarkers) {
|
|
102
110
|
// No markers — return full body
|
|
103
111
|
return body
|
|
104
112
|
}
|
|
105
113
|
|
|
114
|
+
// Specific layout(s) requested
|
|
115
|
+
if (args.layout) {
|
|
116
|
+
return getDesignLayout(args.layout, designName)
|
|
117
|
+
}
|
|
118
|
+
|
|
106
119
|
// Specific component(s) requested
|
|
107
120
|
if (args.component) {
|
|
108
121
|
return getDesignComponent(args.component, designName)
|
|
@@ -113,8 +126,11 @@ export default tool({
|
|
|
113
126
|
return getDesignSection(args.section, designName)
|
|
114
127
|
}
|
|
115
128
|
|
|
116
|
-
// Default: return Component Index
|
|
117
|
-
|
|
129
|
+
// Default: return Layout Index + Component Index
|
|
130
|
+
const li = generateLayoutIndex(layouts)
|
|
131
|
+
const ci = generateComponentIndex(components)
|
|
132
|
+
const parts = [li, ci].filter(Boolean)
|
|
133
|
+
return parts.join("\n\n---\n\n") || "(no layouts or components found)"
|
|
118
134
|
}
|
|
119
135
|
default:
|
|
120
136
|
return JSON.stringify({ error: `Unknown action: ${args.action}` })
|