@cyber-dash-tech/revela 0.1.3 → 0.1.4
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 -3
- package/README.zh-CN.md +2 -3
- package/lib/agents/research-prompt.ts +7 -3
- package/lib/log.ts +3 -2
- package/package.json +1 -1
- package/plugin.ts +15 -14
- package/skill/SKILL.md +4 -3
- package/tools/workspace-scan.ts +17 -2
package/README.md
CHANGED
|
@@ -102,9 +102,8 @@ Three designs are bundled. Switch with `/revela designs <name>`.
|
|
|
102
102
|
|
|
103
103
|
| Name | Description | Preview |
|
|
104
104
|
|---|---|---|
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `editorial-ribbon` | Bold editorial layout — accent ribbons, strong headlines, high visual impact |  |
|
|
105
|
+
| `aurora` | Dark executive style — deep navy/slate, sharp typography, ECharts data visualization |  |
|
|
106
|
+
| `summit` | Editorial outdoor annual-report theme |  |
|
|
108
107
|
|
|
109
108
|
---
|
|
110
109
|
|
package/README.zh-CN.md
CHANGED
|
@@ -133,9 +133,8 @@ OPENCODE_ENABLE_EXA=1 opencode
|
|
|
133
133
|
|
|
134
134
|
| 名称 | 说明 | 预览 |
|
|
135
135
|
|---|---|---|
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `editorial-ribbon` | 大胆的编辑版式 —— 强调色横幅,醒目标题,高视觉冲击力 |  |
|
|
136
|
+
| `aurora` | 颜色主题 — 极光, 高饱和度, ECharts 数据可视化 |  |
|
|
137
|
+
| `summit` | 极简主义 - 户外,适合有丰富插图,Echart 数据可视化 |  |
|
|
139
138
|
|
|
140
139
|
---
|
|
141
140
|
|
|
@@ -53,9 +53,13 @@ Formulate **3–6 targeted search queries** for your specific axis, covering:
|
|
|
53
53
|
|
|
54
54
|
For Chinese topics: search in **both Chinese and English**.
|
|
55
55
|
|
|
56
|
-
Use
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
Use **\`websearch\`** for broad keyword queries to find relevant pages, reports,
|
|
57
|
+
and data. Then use **\`webfetch\`** to retrieve specific pages for depth.
|
|
58
|
+
|
|
59
|
+
Search strategy:
|
|
60
|
+
- Start with \`websearch\` to discover relevant URLs (market reports, company pages, news)
|
|
61
|
+
- Follow up with \`webfetch\` on the most promising URLs for full content
|
|
62
|
+
- For Chinese topics: run \`websearch\` queries in both Chinese and English
|
|
59
63
|
|
|
60
64
|
---
|
|
61
65
|
|
package/lib/log.ts
CHANGED
|
@@ -17,8 +17,9 @@ export const log = new Logger({
|
|
|
17
17
|
type: "json",
|
|
18
18
|
hideLogPositionForProduction: true,
|
|
19
19
|
overwrite: {
|
|
20
|
-
transportJSON: (
|
|
21
|
-
|
|
20
|
+
transportJSON: (_logObj: unknown) => {
|
|
21
|
+
// Silenced: revela runs as an OpenCode plugin; writing to stderr
|
|
22
|
+
// pollutes the host terminal. Logs are intentionally suppressed.
|
|
22
23
|
},
|
|
23
24
|
},
|
|
24
25
|
})
|
package/package.json
CHANGED
package/plugin.ts
CHANGED
|
@@ -111,6 +111,7 @@ const server: Plugin = (async (pluginCtx) => {
|
|
|
111
111
|
// Permissions: read-only on edit/bash; write allowed to create researches/ files.
|
|
112
112
|
// No model override — inherits from the calling primary agent.
|
|
113
113
|
opencodeConfig.agent ??= {}
|
|
114
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
114
115
|
opencodeConfig.agent["revela-research"] = {
|
|
115
116
|
description: "Revela research agent — searches and collects raw materials for presentations",
|
|
116
117
|
mode: "subagent",
|
|
@@ -123,7 +124,19 @@ const server: Plugin = (async (pluginCtx) => {
|
|
|
123
124
|
"ls": "allow",
|
|
124
125
|
},
|
|
125
126
|
webfetch: "allow",
|
|
126
|
-
},
|
|
127
|
+
} as any,
|
|
128
|
+
}
|
|
129
|
+
// Give revela-research explicit websearch allow (overrides global deny below)
|
|
130
|
+
;(opencodeConfig.agent["revela-research"].permission as any).websearch = "allow"
|
|
131
|
+
|
|
132
|
+
// Block websearch for the primary agent globally.
|
|
133
|
+
// permission.ask hook is not triggered by OpenCode (no R.trigger call in binary).
|
|
134
|
+
// tool.execute.before throw is swallowed (trigger().catch(()=>{})).
|
|
135
|
+
// The only working mechanism is the config-level permission ruleset.
|
|
136
|
+
// revela-research agent overrides this with websearch: "allow" above.
|
|
137
|
+
opencodeConfig.permission ??= {}
|
|
138
|
+
if (!(opencodeConfig.permission as Record<string, unknown>)["websearch"]) {
|
|
139
|
+
;(opencodeConfig.permission as Record<string, unknown>)["websearch"] = "deny"
|
|
127
140
|
}
|
|
128
141
|
},
|
|
129
142
|
|
|
@@ -283,22 +296,10 @@ const server: Plugin = (async (pluginCtx) => {
|
|
|
283
296
|
// ── Pre-read: intercept binary files before read executes ──────────────
|
|
284
297
|
// Handles DOCX/PPTX/XLSX — read tool would Effect.fail on these.
|
|
285
298
|
// Extracts text → writes temp .txt → redirects args.filePath.
|
|
286
|
-
//
|
|
287
|
-
// Also blocks websearch for the primary agent — websearch must be delegated
|
|
288
|
-
// to the revela-research subagent. Use webfetch for specific URLs instead.
|
|
289
299
|
"tool.execute.before": async (input, output) => {
|
|
300
|
+
log.info("[hook] tool.execute.before fired", { tool: input.tool, enabled: ctx.enabled, isResearch: ctx.isResearchAgent })
|
|
290
301
|
if (!ctx.enabled) return
|
|
291
302
|
|
|
292
|
-
// ── Block websearch for primary agent ──────────────────────────────
|
|
293
|
-
if (input.tool === "websearch" && !ctx.isResearchAgent) {
|
|
294
|
-
throw new Error(
|
|
295
|
-
"[revela] websearch is not available for the primary agent. " +
|
|
296
|
-
"Delegate web research to the revela-research subagent via the Task tool — " +
|
|
297
|
-
"it searches systematically and saves structured findings for reuse across sessions. " +
|
|
298
|
-
"Use the webfetch tool if you need to read a specific URL directly.",
|
|
299
|
-
)
|
|
300
|
-
}
|
|
301
|
-
|
|
302
303
|
if (input.tool !== "read") return
|
|
303
304
|
try {
|
|
304
305
|
await preRead(output.args)
|
package/skill/SKILL.md
CHANGED
|
@@ -125,9 +125,10 @@ extracts text from binary formats (PDF, Excel, Word, PowerPoint) — just call
|
|
|
125
125
|
with `subagent_type: "revela-research"`) is available.** It is the primary
|
|
126
126
|
research workhorse — not an optional enhancement.
|
|
127
127
|
|
|
128
|
-
The research agent searches the web
|
|
129
|
-
|
|
130
|
-
file `researches/{topic-slug}/{axis-name}.md`
|
|
128
|
+
The research agent searches the web using `websearch` for broad discovery and
|
|
129
|
+
`webfetch` for depth on specific pages, reads workspace documents, and writes
|
|
130
|
+
structured findings to a single file `researches/{topic-slug}/{axis-name}.md`
|
|
131
|
+
in the workspace.
|
|
131
132
|
|
|
132
133
|
##### Parallelization Rule
|
|
133
134
|
|
package/tools/workspace-scan.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { tool } from "@opencode-ai/plugin"
|
|
2
2
|
import { readdirSync, statSync, existsSync } from "fs"
|
|
3
|
-
import { join, relative, extname } from "path"
|
|
3
|
+
import { join, relative, extname, resolve, sep, isAbsolute } from "path"
|
|
4
4
|
|
|
5
5
|
const DOC_EXTENSIONS = new Set([
|
|
6
6
|
".pdf", ".docx", ".doc", ".xlsx", ".xls",
|
|
@@ -113,7 +113,22 @@ export default tool({
|
|
|
113
113
|
async execute(args, context) {
|
|
114
114
|
try {
|
|
115
115
|
const workspaceDir = context.directory ?? process.cwd()
|
|
116
|
-
|
|
116
|
+
|
|
117
|
+
// Validate and resolve scanRoot — must stay within workspaceDir
|
|
118
|
+
let scanRoot = workspaceDir
|
|
119
|
+
if (args.path) {
|
|
120
|
+
if (isAbsolute(args.path)) {
|
|
121
|
+
return JSON.stringify({ error: "path must be relative to workspace root" })
|
|
122
|
+
}
|
|
123
|
+
const candidate = join(workspaceDir, args.path)
|
|
124
|
+
const resolvedCandidate = resolve(candidate)
|
|
125
|
+
const resolvedWorkspace = resolve(workspaceDir)
|
|
126
|
+
if (resolvedCandidate !== resolvedWorkspace && !resolvedCandidate.startsWith(resolvedWorkspace + sep)) {
|
|
127
|
+
return JSON.stringify({ error: "path must be within workspace" })
|
|
128
|
+
}
|
|
129
|
+
scanRoot = candidate
|
|
130
|
+
}
|
|
131
|
+
|
|
117
132
|
const maxDepth = args.max_depth ?? 6
|
|
118
133
|
|
|
119
134
|
if (!existsSync(scanRoot)) {
|