@cyber-dash-tech/revela 0.3.0 → 0.4.0
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 +200 -9
- package/README.zh-CN.md +162 -9
- package/designs/summit/DESIGN.md +54 -51
- package/lib/agents/research-prompt.ts +1 -1
- package/lib/document-materials/extract.ts +139 -2
- package/lib/media/batch-save.ts +146 -0
- package/lib/media/download.ts +68 -0
- package/lib/media/save.ts +273 -0
- package/lib/media/types.ts +54 -0
- package/lib/research/image-leads.ts +175 -0
- package/package.json +1 -1
- package/plugin.ts +6 -0
- package/skill/SKILL.md +7 -1
- package/tools/extract-document-materials.ts +2 -2
- package/tools/media-batch-save.ts +25 -0
- package/tools/media-save.ts +40 -0
- package/tools/research-images-list.ts +34 -0
package/package.json
CHANGED
package/plugin.ts
CHANGED
|
@@ -47,6 +47,9 @@ import { handlePdf } from "./lib/commands/pdf"
|
|
|
47
47
|
import { handlePptx } from "./lib/commands/pptx"
|
|
48
48
|
import designsTool from "./tools/designs"
|
|
49
49
|
import domainsTool from "./tools/domains"
|
|
50
|
+
import mediaBatchSaveTool from "./tools/media-batch-save"
|
|
51
|
+
import mediaSaveTool from "./tools/media-save"
|
|
52
|
+
import researchImagesListTool from "./tools/research-images-list"
|
|
50
53
|
import researchSaveTool from "./tools/research-save"
|
|
51
54
|
import workspaceScanTool from "./tools/workspace-scan"
|
|
52
55
|
import extractDocumentMaterialsTool from "./tools/extract-document-materials"
|
|
@@ -229,6 +232,9 @@ const server: Plugin = (async (pluginCtx) => {
|
|
|
229
232
|
tool: {
|
|
230
233
|
"revela-designs": designsTool,
|
|
231
234
|
"revela-domains": domainsTool,
|
|
235
|
+
"revela-media-batch-save": mediaBatchSaveTool,
|
|
236
|
+
"revela-media-save": mediaSaveTool,
|
|
237
|
+
"revela-research-images-list": researchImagesListTool,
|
|
232
238
|
"revela-research-save": researchSaveTool,
|
|
233
239
|
"revela-workspace-scan": workspaceScanTool,
|
|
234
240
|
"revela-extract-document-materials": extractDocumentMaterialsTool,
|
package/skill/SKILL.md
CHANGED
|
@@ -427,6 +427,12 @@ element selector list, and `window.getEditedHTML()` definition.
|
|
|
427
427
|
|
|
428
428
|
### Image Rules
|
|
429
429
|
|
|
430
|
+
- When research findings contain image leads that should appear in the final deck,
|
|
431
|
+
first call `revela-research-images-list` to inspect structured candidates from
|
|
432
|
+
`researches/{slug}/*.md`. When multiple images are needed, prefer
|
|
433
|
+
`revela-media-batch-save` to save the selected candidates in one call. Use
|
|
434
|
+
`revela-media-save` for one-off cases. Then reference the returned local file
|
|
435
|
+
path in HTML. Do not use remote image URLs directly in final slides.
|
|
430
436
|
- Use direct file paths (`src="assets/logo.png"`) in HTML — not base64
|
|
431
437
|
- Always use the **original** file path in HTML `<img src>` for full-quality rendering
|
|
432
438
|
- Never repeat the same image on multiple slides (logos: title + closing only)
|
|
@@ -493,4 +499,4 @@ The active design name is in the HTML comment at the top of this prompt:
|
|
|
493
499
|
The active design's complete visual specification — Component Library, Layout
|
|
494
500
|
Primitives, Composition Guide, and Data Visualization rules — is injected
|
|
495
501
|
below after the `---` separator. This is your sole visual reference for
|
|
496
|
-
generating slides.
|
|
502
|
+
generating slides.
|
|
@@ -4,12 +4,12 @@ import { extractDocumentMaterials } from "../lib/document-materials/extract"
|
|
|
4
4
|
export default tool({
|
|
5
5
|
description:
|
|
6
6
|
"Extract reusable materials from a workspace document into a workspace-local cache. " +
|
|
7
|
-
"Supports pptx, docx, and xlsx. Produces a manifest plus extracted text, embedded images, and available slide/sheet mappings. " +
|
|
7
|
+
"Supports pdf, pptx, docx, and xlsx. Produces a manifest plus extracted text, embedded images, and available page/slide/sheet mappings. " +
|
|
8
8
|
"Unsupported file types are skipped instead of failing.",
|
|
9
9
|
args: {
|
|
10
10
|
file: tool.schema
|
|
11
11
|
.string()
|
|
12
|
-
.describe("Document path relative to workspace root. Supports pptx, docx, and xlsx; other file types are skipped."),
|
|
12
|
+
.describe("Document path relative to workspace root. Supports pdf, pptx, docx, and xlsx; other file types are skipped."),
|
|
13
13
|
},
|
|
14
14
|
async execute(args, context) {
|
|
15
15
|
const workspaceDir = context.directory ?? process.cwd()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin"
|
|
2
|
+
import { batchSaveMediaAssets } from "../lib/media/batch-save"
|
|
3
|
+
|
|
4
|
+
export default tool({
|
|
5
|
+
description:
|
|
6
|
+
"Save a selected batch of research-found image leads into workspace assets and update the media manifest. " +
|
|
7
|
+
"Use this after the primary agent has chosen multiple images from researches/{topic}/*.md.",
|
|
8
|
+
args: {
|
|
9
|
+
topic: tool.schema.string().describe("Topic slug shared by one presentation, e.g. 'ev-market'."),
|
|
10
|
+
items: tool.schema.array(tool.schema.object({
|
|
11
|
+
candidateId: tool.schema.string().describe("Stable candidate id returned by revela-research-images-list."),
|
|
12
|
+
description: tool.schema.string().describe("Candidate description from research findings."),
|
|
13
|
+
url: tool.schema.string().describe("Remote image URL to save."),
|
|
14
|
+
alt: tool.schema.string().optional().describe("Optional alt text."),
|
|
15
|
+
use: tool.schema.enum(["logo", "portrait", "screenshot"]).describe("Structured image use from research findings."),
|
|
16
|
+
sourceFile: tool.schema.string().optional().describe("Optional source research file path."),
|
|
17
|
+
intendedSection: tool.schema.string().optional().describe("Optional section override for this one item."),
|
|
18
|
+
})).describe("Explicitly selected image leads to save. This tool does not auto-select candidates."),
|
|
19
|
+
intendedSection: tool.schema.string().optional().describe("Optional default narrative section for all items in this batch."),
|
|
20
|
+
},
|
|
21
|
+
async execute(args, context) {
|
|
22
|
+
const workspaceDir = context.directory ?? process.cwd()
|
|
23
|
+
return JSON.stringify(await batchSaveMediaAssets(args, workspaceDir), null, 2)
|
|
24
|
+
},
|
|
25
|
+
})
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin"
|
|
2
|
+
import { saveMediaAsset } from "../lib/media/save"
|
|
3
|
+
|
|
4
|
+
export default tool({
|
|
5
|
+
description:
|
|
6
|
+
"Save one image asset into the workspace assets/ directory and update a media manifest. " +
|
|
7
|
+
"Supports either a sourceUrl or a sourcePath. Records both success and failure states. " +
|
|
8
|
+
"Use this when a research-found image or an existing local image should become a formal project asset.",
|
|
9
|
+
args: {
|
|
10
|
+
topic: tool.schema.string().describe("Topic slug shared by one presentation, e.g. 'ev-market'."),
|
|
11
|
+
id: tool.schema.string().describe("Stable asset id within the topic, e.g. 'tesla-logo-01'."),
|
|
12
|
+
type: tool.schema.enum(["image"]).describe("Asset type. Stage 1 only supports 'image'."),
|
|
13
|
+
purpose: tool.schema
|
|
14
|
+
.enum(["hero", "illustration", "portrait", "logo", "screenshot"])
|
|
15
|
+
.describe("Image purpose in the deck."),
|
|
16
|
+
brief: tool.schema.string().describe("One-sentence reason this image is needed."),
|
|
17
|
+
status: tool.schema
|
|
18
|
+
.enum(["success", "cannot-download", "invalid-url", "cannot-generate"])
|
|
19
|
+
.describe("'success' saves an image asset; other statuses record a failed attempt in the manifest."),
|
|
20
|
+
intendedSection: tool.schema.string().optional().describe("Optional narrative section such as 'market-overview'."),
|
|
21
|
+
sourcePath: tool.schema
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("Optional local image path, relative to the workspace root. Preferred when both sourcePath and sourceUrl are present."),
|
|
25
|
+
sourceUrl: tool.schema
|
|
26
|
+
.string()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe("Optional remote image URL to download when sourcePath is not provided."),
|
|
29
|
+
alt: tool.schema.string().optional().describe("Optional alt text for the image."),
|
|
30
|
+
notes: tool.schema.string().optional().describe("Optional usage notes for future slide generation."),
|
|
31
|
+
failureReason: tool.schema
|
|
32
|
+
.string()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("Required when status is not 'success'. Briefly explain why the image is unavailable."),
|
|
35
|
+
},
|
|
36
|
+
async execute(args, context) {
|
|
37
|
+
const workspaceDir = context.directory ?? process.cwd()
|
|
38
|
+
return JSON.stringify(await saveMediaAsset(args, workspaceDir), null, 2)
|
|
39
|
+
},
|
|
40
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin"
|
|
2
|
+
import { listResearchImageLeads } from "../lib/research/image-leads"
|
|
3
|
+
|
|
4
|
+
export default tool({
|
|
5
|
+
description:
|
|
6
|
+
"List structured image leads from researches/{topic}/*.md. " +
|
|
7
|
+
"Parses ## Images sections and returns candidate image records for the primary agent to review.",
|
|
8
|
+
args: {
|
|
9
|
+
topic: tool.schema.string().describe("Topic slug shared by one presentation, e.g. 'ev-market'."),
|
|
10
|
+
uses: tool.schema
|
|
11
|
+
.array(tool.schema.enum(["logo", "portrait", "screenshot", "unknown"]))
|
|
12
|
+
.optional()
|
|
13
|
+
.describe("Optional use filter, e.g. ['logo', 'portrait', 'screenshot']"),
|
|
14
|
+
axis: tool.schema
|
|
15
|
+
.array(tool.schema.string())
|
|
16
|
+
.optional()
|
|
17
|
+
.describe("Optional axis filter, e.g. ['tesla-profile', 'market-data']"),
|
|
18
|
+
},
|
|
19
|
+
async execute(args, context) {
|
|
20
|
+
const workspaceDir = context.directory ?? process.cwd()
|
|
21
|
+
const result = listResearchImageLeads(args.topic, workspaceDir, {
|
|
22
|
+
uses: args.uses,
|
|
23
|
+
axis: args.axis,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
return JSON.stringify({
|
|
27
|
+
ok: true,
|
|
28
|
+
topic: result.topic,
|
|
29
|
+
count: result.items.length,
|
|
30
|
+
items: result.items,
|
|
31
|
+
warnings: result.warnings,
|
|
32
|
+
}, null, 2)
|
|
33
|
+
},
|
|
34
|
+
})
|