@cyber-dash-tech/revela 0.17.6 → 0.17.8
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 +53 -23
- package/README.zh-CN.md +53 -23
- package/bin/revela.ts +98 -0
- package/lib/edit/prompt.ts +6 -2
- package/lib/edit/server.ts +2 -2
- package/lib/inspect/prompt.ts +5 -1
- package/lib/refine/comment-requests.ts +77 -0
- package/lib/refine/open.ts +5 -2
- package/lib/refine/prompt-bridge.ts +219 -0
- package/lib/refine/qa-suppression.ts +41 -0
- package/lib/refine/server.ts +122 -34
- package/lib/runtime/index.ts +225 -0
- package/lib/runtime/research.ts +175 -0
- package/lib/runtime/review.ts +270 -0
- package/lib/runtime/story.ts +53 -0
- package/package.json +6 -1
- package/plugin.ts +4 -2
- package/plugins/revela/.codex-plugin/plugin.json +37 -0
- package/plugins/revela/.mcp.json +11 -0
- package/plugins/revela/assets/README.md +2 -0
- package/plugins/revela/hooks/hooks.json +28 -0
- package/plugins/revela/hooks/revela_guard.ts +10 -0
- package/plugins/revela/hooks/revela_post_write_notice.ts +18 -0
- package/plugins/revela/mcp/revela-server.ts +504 -0
- package/plugins/revela/mcp/runtime-resolver.ts +109 -0
- package/plugins/revela/skills/revela-design/SKILL.md +20 -0
- package/plugins/revela/skills/revela-domain/SKILL.md +18 -0
- package/plugins/revela/skills/revela-export/SKILL.md +21 -0
- package/plugins/revela/skills/revela-init/SKILL.md +36 -0
- package/plugins/revela/skills/revela-make-deck/SKILL.md +37 -0
- package/plugins/revela/skills/revela-research/SKILL.md +38 -0
- package/plugins/revela/skills/revela-review-deck/SKILL.md +33 -0
- package/plugins/revela/skills/revela-story/SKILL.md +24 -0
- package/tools/decks.ts +10 -78
- package/tools/research-save.ts +8 -72
package/README.md
CHANGED
|
@@ -2,19 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
**English** | [中文](README.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/@cyber-dash-tech/revela) [](LICENSE) [](https://www.npmjs.com/package/@cyber-dash-tech/revela) [](LICENSE) [](tests/) [](https://opencode.ai) [](https://bun.sh)
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<img src="assets/img/logo.png" alt="Revela" width="560" />
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
-
Revela
|
|
11
|
+
Revela works from [OpenCode](https://opencode.ai) and Codex to turn source materials, research, data, and intent into trusted, traceable, presentation-ready decision artifacts.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Its narrative workspace records the core elements needed to generate a brief or deck: audience, decision, claims, evidence, sources, risks, objections, and open gaps.
|
|
14
14
|
|
|
15
15
|
## Install
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
### OpenCode
|
|
18
|
+
|
|
19
|
+
Install Revela through `opencode.json` with the npm package `@cyber-dash-tech/revela`:
|
|
18
20
|
|
|
19
21
|
```json
|
|
20
22
|
{
|
|
@@ -27,6 +29,19 @@ Restart OpenCode.
|
|
|
27
29
|
|
|
28
30
|
To install globally, add the same entry to `~/.config/opencode/opencode.json`.
|
|
29
31
|
|
|
32
|
+
### Codex
|
|
33
|
+
|
|
34
|
+
Install Revela through the Codex Git marketplace:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
codex plugin marketplace add https://github.com/cyber-dash-tech/revela --ref v0.17.8
|
|
38
|
+
codex plugin add revela@revela
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Install from the full repository ref. Do not use a sparse checkout limited to `plugins/revela`; the Codex plugin resolves the shared runtime, built-in designs, and domains from the repository snapshot.
|
|
42
|
+
|
|
43
|
+
Start a new Codex thread after installing so Codex loads the Revela skills, MCP tools, and hooks.
|
|
44
|
+
|
|
30
45
|
## Built-In Designs
|
|
31
46
|
|
|
32
47
|
Revela includes built-in deck designs:
|
|
@@ -55,6 +70,8 @@ Switch designs with:
|
|
|
55
70
|
/revela design --use summit
|
|
56
71
|
```
|
|
57
72
|
|
|
73
|
+
In Codex, ask Revela to list or switch designs; the plugin uses the active design when making decks.
|
|
74
|
+
|
|
58
75
|
## Domains
|
|
59
76
|
|
|
60
77
|
Domains add topic-specific narrative guidance, such as consulting, product, or investor communication. Use them when you want Revela to adapt story framing to a specific context.
|
|
@@ -63,51 +80,64 @@ Domains add topic-specific narrative guidance, such as consulting, product, or i
|
|
|
63
80
|
/revela domain
|
|
64
81
|
```
|
|
65
82
|
|
|
66
|
-
|
|
83
|
+
In Codex, ask Revela to list or switch domains; the active domain guides narrative framing during init, research, and story work.
|
|
84
|
+
|
|
85
|
+
## Quick Start
|
|
67
86
|
|
|
68
|
-
|
|
87
|
+
Use these prompts in Codex from the workspace that contains your source materials.
|
|
88
|
+
|
|
89
|
+
1. Choose the narrative domain before authoring so Revela frames the audience, decision, risks, and objections for your context.
|
|
69
90
|
|
|
70
91
|
```text
|
|
71
|
-
|
|
92
|
+
Use Revela to list available domains, switch to the consulting domain, and use that framing for the narrative workflow.
|
|
72
93
|
```
|
|
73
94
|
|
|
74
|
-
2.
|
|
95
|
+
2. Choose the deck design before rendering so generated artifacts use the intended visual language.
|
|
75
96
|
|
|
76
97
|
```text
|
|
77
|
-
|
|
98
|
+
Use Revela to list available designs, switch to the summit design, and use it for the next deck.
|
|
78
99
|
```
|
|
79
100
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
3. Inspect the claim flow before rendering.
|
|
101
|
+
3. Initialize the narrative from local materials. Init grounds the narrative in the workspace and surfaces gaps; it does not replace the research step.
|
|
83
102
|
|
|
84
103
|
```text
|
|
85
|
-
|
|
104
|
+
Use Revela to initialize this workspace. Read the local materials, identify the audience, decision, thesis, claims, existing evidence, risks, objections, and gaps, then create or update the narrative vault.
|
|
86
105
|
```
|
|
87
106
|
|
|
88
|
-
|
|
107
|
+
4. Research the gaps and bind only source-supported evidence into the narrative.
|
|
89
108
|
|
|
90
|
-
|
|
109
|
+
```text
|
|
110
|
+
Use Revela research to inspect the current narrative gaps, derive research targets, gather or evaluate findings, save research under researches/, and bind only source-supported evidence back into the narrative vault.
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
5. Read Story before rendering to inspect the claim flow, evidence support, caveats, unsupported scope, and open gaps.
|
|
91
114
|
|
|
92
115
|
```text
|
|
93
|
-
|
|
116
|
+
Use Revela Story to show the current claim flow, evidence support, caveats, unsupported scope, and open gaps.
|
|
94
117
|
```
|
|
95
118
|
|
|
96
|
-
|
|
119
|
+
6. Make an HTML deck from the canonical narrative and deck plan.
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
Use Revela to make a deck from the current narrative. Create or update the deck plan, generate an HTML deck under decks/, run deck QA, and repair hard QA errors.
|
|
123
|
+
```
|
|
97
124
|
|
|
98
|
-
|
|
125
|
+
7. Review the generated deck for traceability, diagnostics, and targeted edits.
|
|
99
126
|
|
|
100
127
|
```text
|
|
101
|
-
|
|
128
|
+
Use Revela to review the generated deck. Open the Review UI for the HTML deck and also summarize diagnostics.
|
|
102
129
|
```
|
|
103
130
|
|
|
104
|
-
|
|
131
|
+
8. Export a PDF after deck QA passes.
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
Use Revela to export the deck to PDF.
|
|
135
|
+
```
|
|
105
136
|
|
|
106
|
-
|
|
137
|
+
9. Export an editable PPTX after deck QA passes.
|
|
107
138
|
|
|
108
139
|
```text
|
|
109
|
-
|
|
110
|
-
/revela export --deck pptx decks/example.html
|
|
140
|
+
Use Revela to export the deck to PPTX.
|
|
111
141
|
```
|
|
112
142
|
|
|
113
143
|
## Review A Deck
|
package/README.zh-CN.md
CHANGED
|
@@ -2,19 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) | **中文**
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/@cyber-dash-tech/revela) [](LICENSE) [](https://www.npmjs.com/package/@cyber-dash-tech/revela) [](LICENSE) [](tests/) [](https://opencode.ai) [](https://bun.sh)
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<img src="assets/img/logo.png" alt="Revela" width="560" />
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
-
Revela
|
|
11
|
+
Revela 可在 [OpenCode](https://opencode.ai) 和 Codex 中使用,把来源材料、调研、数据和用户意图转成可信、可追踪、可直接用于决策沟通的 narrative artifact。
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
它的 narrative workspace 会记录生成 brief 或 deck 所需的关键要素:受众、决策目标、论点、论据、资料来源、风险、潜在质疑和待补齐的信息。
|
|
14
14
|
|
|
15
15
|
## 安装
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
### OpenCode
|
|
18
|
+
|
|
19
|
+
通过 `opencode.json` 安装 npm package `@cyber-dash-tech/revela`:
|
|
18
20
|
|
|
19
21
|
```json
|
|
20
22
|
{
|
|
@@ -27,6 +29,19 @@ Revela 是一个 [OpenCode](https://opencode.ai) 插件,用来把本地材料
|
|
|
27
29
|
|
|
28
30
|
如果想全局安装,把同样配置写到 `~/.config/opencode/opencode.json`。
|
|
29
31
|
|
|
32
|
+
### Codex
|
|
33
|
+
|
|
34
|
+
通过 Codex Git marketplace 安装 Revela:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
codex plugin marketplace add https://github.com/cyber-dash-tech/revela --ref v0.17.8
|
|
38
|
+
codex plugin add revela@revela
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
请从完整仓库 ref 安装。不要使用仅包含 `plugins/revela` 的 sparse checkout;Codex plugin 会从仓库快照中解析 shared runtime、内置 designs 和 domains。
|
|
42
|
+
|
|
43
|
+
安装后开启一个新的 Codex thread,让 Codex 加载 Revela 的 skills、MCP tools 和 hooks。
|
|
44
|
+
|
|
30
45
|
## 内置设计
|
|
31
46
|
|
|
32
47
|
Revela 内置多个 deck design:
|
|
@@ -55,6 +70,8 @@ Revela 内置多个 deck design:
|
|
|
55
70
|
/revela design --use summit
|
|
56
71
|
```
|
|
57
72
|
|
|
73
|
+
在 Codex 中,可以直接让 Revela 列出或切换 design;生成 deck 时会使用 active design。
|
|
74
|
+
|
|
58
75
|
## Domains
|
|
59
76
|
|
|
60
77
|
Domain 提供特定场景的叙事 guidance,例如 consulting、product 或 investor communication。需要让 Revela 按具体沟通场景调整 story framing 时使用。
|
|
@@ -63,51 +80,64 @@ Domain 提供特定场景的叙事 guidance,例如 consulting、product 或 in
|
|
|
63
80
|
/revela domain
|
|
64
81
|
```
|
|
65
82
|
|
|
66
|
-
|
|
83
|
+
在 Codex 中,可以直接让 Revela 列出或切换 domain;active domain 会用于 init、research 和 story 阶段的叙事 framing。
|
|
84
|
+
|
|
85
|
+
## Quick Start
|
|
67
86
|
|
|
68
|
-
|
|
87
|
+
在包含来源材料的 workspace 中打开 Codex,然后按下面步骤逐条发送 prompt。
|
|
88
|
+
|
|
89
|
+
1. 先选择 domain,让 Revela 按你的沟通场景 framing 受众、决策、风险和潜在质疑。
|
|
69
90
|
|
|
70
91
|
```text
|
|
71
|
-
|
|
92
|
+
用 Revela 列出可用 domains,切换到 consulting domain,并把这个 framing 用在后续 narrative workflow 中。
|
|
72
93
|
```
|
|
73
94
|
|
|
74
|
-
2.
|
|
95
|
+
2. 再选择 design,让后续生成的 deck 使用指定视觉风格。
|
|
75
96
|
|
|
76
97
|
```text
|
|
77
|
-
|
|
98
|
+
用 Revela 列出可用 designs,切换到 summit design,并把它用于下一次 deck 生成。
|
|
78
99
|
```
|
|
79
100
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
3. 在生成 deck 前检查 claim flow。
|
|
101
|
+
3. 从本地材料初始化 narrative。Init 负责基于 workspace 做 grounding 并暴露 gap;它不替代 research 步骤。
|
|
83
102
|
|
|
84
103
|
```text
|
|
85
|
-
|
|
104
|
+
用 Revela 初始化这个 workspace。读取本地材料,识别受众、决策目标、thesis、claims、已有 evidence、risks、objections 和 gaps,然后创建或更新 narrative vault。
|
|
86
105
|
```
|
|
87
106
|
|
|
88
|
-
|
|
107
|
+
4. 针对 gap 做 research,并且只把来源明确支持的 evidence 绑定回 narrative。
|
|
89
108
|
|
|
90
|
-
|
|
109
|
+
```text
|
|
110
|
+
用 Revela research 检查当前 narrative gaps,生成 research targets,收集或评估 findings,把 research 保存到 researches/,并且只把有来源支撑的 evidence 绑定回 narrative vault。
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
5. 生成 deck 前先读 Story,检查 claim flow、证据支撑、caveats、unsupported scope 和 open gaps。
|
|
91
114
|
|
|
92
115
|
```text
|
|
93
|
-
|
|
116
|
+
用 Revela Story 展示当前 claim flow、evidence support、caveats、unsupported scope 和 open gaps。
|
|
94
117
|
```
|
|
95
118
|
|
|
96
|
-
|
|
119
|
+
6. 从 canonical narrative 和 deck plan 生成 HTML deck。
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
用 Revela 基于当前 narrative 制作 deck。创建或更新 deck plan,在 decks/ 下生成 HTML deck,运行 deck QA,并修复 hard QA errors。
|
|
123
|
+
```
|
|
97
124
|
|
|
98
|
-
|
|
125
|
+
7. Review 生成后的 deck,检查 traceability、diagnostics,并做定向修改。
|
|
99
126
|
|
|
100
127
|
```text
|
|
101
|
-
|
|
128
|
+
用 Revela review 生成好的 deck。打开这个 HTML deck 的 Review UI,并总结 diagnostics。
|
|
102
129
|
```
|
|
103
130
|
|
|
104
|
-
|
|
131
|
+
8. QA 通过后导出 PDF。
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
用 Revela 把 deck 导出为 PDF。
|
|
135
|
+
```
|
|
105
136
|
|
|
106
|
-
|
|
137
|
+
9. QA 通过后导出可编辑 PPTX。
|
|
107
138
|
|
|
108
139
|
```text
|
|
109
|
-
|
|
110
|
-
/revela export --deck pptx decks/example.html
|
|
140
|
+
用 Revela 把 deck 导出为 PPTX。
|
|
111
141
|
```
|
|
112
142
|
|
|
113
143
|
## Review Deck
|
package/bin/revela.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
type CommandResult = unknown | Promise<unknown>
|
|
4
|
+
|
|
5
|
+
const [argvCommand, ...args] = process.argv.slice(2)
|
|
6
|
+
const command = process.env.REVELA_CLI_COMMAND || argvCommand
|
|
7
|
+
|
|
8
|
+
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
9
|
+
printHelp()
|
|
10
|
+
process.exit(0)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (command === "mcp") {
|
|
14
|
+
await import("../plugins/revela/mcp/revela-server")
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
const runtime = await import("../lib/runtime/index")
|
|
18
|
+
const options = parseArgs(args)
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
let result: CommandResult
|
|
22
|
+
if (command === "doctor") result = runtime.doctor(options)
|
|
23
|
+
else if (command === "compile") result = runtime.compileNarrative(options)
|
|
24
|
+
else if (command === "markdown-qa") result = runtime.markdownQa(options)
|
|
25
|
+
else if (command === "deck-plan") result = runtime.readDeckPlan(options)
|
|
26
|
+
else if (command === "deck-foundation") result = runtime.createDeckFoundation(required(options, ["outputPath", "title", "language"]))
|
|
27
|
+
else if (command === "qa") result = runtime.runDeckQa(required(options, ["file"]))
|
|
28
|
+
else if (command === "review-read") result = runtime.reviewDeckRead(required(options, ["file"]))
|
|
29
|
+
else if (command === "export-pdf") result = runtime.exportPdf(required(options, ["file"]))
|
|
30
|
+
else if (command === "export-pptx") result = runtime.exportPptx(required(options, ["file"]))
|
|
31
|
+
else if (command === "design-list") result = runtime.designList()
|
|
32
|
+
else if (command === "design-read") result = runtime.designRead(options)
|
|
33
|
+
else if (command === "design-use") result = runtime.designActivate(required(options, ["name"]))
|
|
34
|
+
else if (command === "domain-list") result = runtime.domainList()
|
|
35
|
+
else if (command === "domain-read") result = runtime.domainRead(options)
|
|
36
|
+
else if (command === "domain-use") result = runtime.domainActivate(required(options, ["name"]))
|
|
37
|
+
else {
|
|
38
|
+
throw new Error(`Unknown command: ${command}`)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
process.stdout.write(`${JSON.stringify(await result, null, 2)}\n`)
|
|
42
|
+
} catch (e) {
|
|
43
|
+
process.stderr.write(`${e instanceof Error ? e.message : String(e)}\n`)
|
|
44
|
+
process.exit(1)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function parseArgs(values: string[]): Record<string, any> {
|
|
49
|
+
const result: Record<string, any> = {}
|
|
50
|
+
for (let i = 0; i < values.length; i++) {
|
|
51
|
+
const arg = values[i]
|
|
52
|
+
if (!arg.startsWith("--")) throw new Error(`Unexpected argument: ${arg}`)
|
|
53
|
+
const key = arg.slice(2)
|
|
54
|
+
const next = values[i + 1]
|
|
55
|
+
if (next === undefined || next.startsWith("--")) {
|
|
56
|
+
result[key] = true
|
|
57
|
+
continue
|
|
58
|
+
}
|
|
59
|
+
result[key] = parseValue(next)
|
|
60
|
+
i++
|
|
61
|
+
}
|
|
62
|
+
return result
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function parseValue(value: string): unknown {
|
|
66
|
+
if (value === "true") return true
|
|
67
|
+
if (value === "false") return false
|
|
68
|
+
return value
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function required(input: Record<string, any>, keys: string[]): Record<string, any> {
|
|
72
|
+
const missing = keys.filter((key) => input[key] === undefined || input[key] === "")
|
|
73
|
+
if (missing.length > 0) throw new Error(`Missing required option(s): ${missing.map((key) => `--${key}`).join(", ")}`)
|
|
74
|
+
return input
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function printHelp(): void {
|
|
78
|
+
process.stdout.write(`Revela CLI
|
|
79
|
+
|
|
80
|
+
Usage:
|
|
81
|
+
revela mcp
|
|
82
|
+
revela doctor [--workspaceRoot <path>]
|
|
83
|
+
revela compile [--workspaceRoot <path>]
|
|
84
|
+
revela markdown-qa [--workspaceRoot <path>] [--scope touched|affected|full] [--strictness authoring|readiness|render]
|
|
85
|
+
revela deck-plan [--workspaceRoot <path>]
|
|
86
|
+
revela deck-foundation --outputPath <path> --title <title> --language <tag> [--workspaceRoot <path>] [--designName <name>] [--mode create|repair] [--overwrite true]
|
|
87
|
+
revela qa --file <path> [--workspaceRoot <path>]
|
|
88
|
+
revela review-read --file <path> [--workspaceRoot <path>] [--format json|markdown]
|
|
89
|
+
revela export-pdf --file <path> [--workspaceRoot <path>]
|
|
90
|
+
revela export-pptx --file <path> [--workspaceRoot <path>]
|
|
91
|
+
revela design-list
|
|
92
|
+
revela design-read [--name <design>]
|
|
93
|
+
revela design-use --name <design>
|
|
94
|
+
revela domain-list
|
|
95
|
+
revela domain-read [--name <domain>]
|
|
96
|
+
revela domain-use --name <domain>
|
|
97
|
+
`)
|
|
98
|
+
}
|
package/lib/edit/prompt.ts
CHANGED
|
@@ -26,6 +26,7 @@ export interface EditCommentPayload extends EditSelectedElementPayload {
|
|
|
26
26
|
comments?: EditCommentDraftPayload[]
|
|
27
27
|
asset?: Record<string, unknown>
|
|
28
28
|
drop?: Record<string, unknown>
|
|
29
|
+
suppressAutomaticArtifactQa?: boolean
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
export function buildEditPrompt(payload: EditCommentPayload): string {
|
|
@@ -59,6 +60,10 @@ export function buildEditPrompt(payload: EditCommentPayload): string {
|
|
|
59
60
|
asset: payload.asset,
|
|
60
61
|
drop: payload.drop,
|
|
61
62
|
}
|
|
63
|
+
const qaInstruction = payload.suppressAutomaticArtifactQa
|
|
64
|
+
? `- Do not run artifact QA after this edit and do not keep editing just to satisfy post-write QA. The Review UI will refresh from the deck file version change; QA can be run later through an explicit Review, QA, or export workflow.`
|
|
65
|
+
: `- Artifact QA runs automatically after deck writes/patches/edits. It checks deck HTML contract, design component compliance, exact 1920x1080 slide geometry, scrollbars, element overflow, text clipping, and claim/evidence content-density warnings.
|
|
66
|
+
- If the tool result reports hard QA errors, fix them with the smallest targeted patch and let the post-write QA run again. Refine opens automatically only after hard errors pass; warnings such as thin claim/evidence substance do not block opening.`
|
|
62
67
|
|
|
63
68
|
return `The user left a visual edit comment on a Revela slide deck.
|
|
64
69
|
|
|
@@ -95,7 +100,6 @@ Instructions:
|
|
|
95
100
|
- For targeted artifact-level edits, patch ${"`decks/*.html`"} directly. Do not call ${"`revela-decks`"} action ${"`review`"} as a precondition, and do not let ${"`writeReadiness`"}, ${"`planReview`"}, or ${"`slide_plan_unconfirmed`"} block the patch.
|
|
96
101
|
- Do not patch or write ${"`DECKS.json`"} directly. If state must change, use the ${"`revela-decks`"} tool.
|
|
97
102
|
- Apply the edit to ${payload.file} with the smallest targeted HTML patch that satisfies the comment.
|
|
98
|
-
|
|
99
|
-
- If the tool result reports hard QA errors, fix them with the smallest targeted patch and let the post-write QA run again. Refine opens automatically only after hard errors pass; warnings such as thin claim/evidence substance do not block opening.
|
|
103
|
+
${qaInstruction}
|
|
100
104
|
- If the comment is ambiguous, ask one concise clarification question instead of guessing.`
|
|
101
105
|
}
|
package/lib/edit/server.ts
CHANGED
|
@@ -1003,8 +1003,8 @@ export function renderEditorShell(token: string): string {
|
|
|
1003
1003
|
if (status === 'updated') return 'Deck file updated';
|
|
1004
1004
|
if (status === 'stale') return 'Still waiting for deck file update';
|
|
1005
1005
|
if (status === 'failed') return 'Failed to send';
|
|
1006
|
-
if (status === 'sending') return 'Sending to
|
|
1007
|
-
return '
|
|
1006
|
+
if (status === 'sending') return 'Sending to Review agent...';
|
|
1007
|
+
return 'Sent to Review agent';
|
|
1008
1008
|
}
|
|
1009
1009
|
|
|
1010
1010
|
function targetFromPointer(event) {
|
package/lib/inspect/prompt.ts
CHANGED
|
@@ -6,9 +6,11 @@ export function buildInspectionPrompt(input: {
|
|
|
6
6
|
projection: InspectionPromptProjection
|
|
7
7
|
language?: string
|
|
8
8
|
comment?: string
|
|
9
|
+
delivery?: "tool" | "json"
|
|
9
10
|
}): string {
|
|
10
11
|
const language = normalizeInspectLanguage(input.language)
|
|
11
12
|
const comment = typeof input.comment === "string" && input.comment.trim() ? input.comment.trim() : ""
|
|
13
|
+
const delivery = input.delivery ?? "tool"
|
|
12
14
|
return `A user selected slide content in Revela Evidence Inspector. The selection may contain one referenced element, a whole slide, or multiple referenced elements selected with Cmd/Ctrl-click.
|
|
13
15
|
|
|
14
16
|
Target file: ${input.file}
|
|
@@ -20,7 +22,9 @@ Use the structured projection below to produce the final inspector cards. This i
|
|
|
20
22
|
|
|
21
23
|
Language boundary: the selected display language affects only human-readable card copy. Preserve all claim ids, canonical claim ids, evidence binding ids, source paths, findings files, URLs, numbers, quoted/source facts, caveats, artifact ids, and coverage statuses exactly as grounded in the projection. If the display language is Auto, use projection.deck.language when available; otherwise follow the user's/browser context or default to English.
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
${delivery === "json"
|
|
26
|
+
? "Return only a single JSON object that matches the final inspector result schema. Do not wrap it in Markdown. Do not call tools. Do not edit files."
|
|
27
|
+
: "Return the result only by calling the `revela-inspection-result` tool with this request id. Do not answer in chat."}
|
|
24
28
|
|
|
25
29
|
Required card model:
|
|
26
30
|
- User inspect comment: if present, answer it through the Purpose and Source cards first. If it asks about trust, provenance, evidence, factuality, or where a number came from, prioritize Source. If it asks why something is on the slide or what it is doing, prioritize Purpose.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export type CommentRequestStatus = "pending" | "completed" | "failed" | "expired"
|
|
2
|
+
|
|
3
|
+
export interface PendingCommentRequest {
|
|
4
|
+
requestId: string
|
|
5
|
+
status: CommentRequestStatus
|
|
6
|
+
deckVersion: string
|
|
7
|
+
createdAt: number
|
|
8
|
+
updatedAt: number
|
|
9
|
+
error?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const REQUEST_TTL_MS = 120 * 1000
|
|
13
|
+
const requests = new Map<string, PendingCommentRequest>()
|
|
14
|
+
|
|
15
|
+
export function createCommentRequest(input: {
|
|
16
|
+
requestId: string
|
|
17
|
+
deckVersion: string
|
|
18
|
+
}): PendingCommentRequest {
|
|
19
|
+
cleanupCommentRequests()
|
|
20
|
+
const now = Date.now()
|
|
21
|
+
const request: PendingCommentRequest = {
|
|
22
|
+
requestId: input.requestId,
|
|
23
|
+
status: "pending",
|
|
24
|
+
deckVersion: input.deckVersion,
|
|
25
|
+
createdAt: now,
|
|
26
|
+
updatedAt: now,
|
|
27
|
+
}
|
|
28
|
+
requests.set(input.requestId, request)
|
|
29
|
+
return request
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getCommentRequest(requestId: string): PendingCommentRequest | undefined {
|
|
33
|
+
cleanupCommentRequests()
|
|
34
|
+
const request = requests.get(requestId)
|
|
35
|
+
if (!request) return undefined
|
|
36
|
+
if (request.status === "pending" && Date.now() - request.createdAt > REQUEST_TTL_MS) {
|
|
37
|
+
request.status = "expired"
|
|
38
|
+
request.error = "Review agent timed out before completing the comment request."
|
|
39
|
+
request.updatedAt = Date.now()
|
|
40
|
+
}
|
|
41
|
+
return request
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function completeCommentRequest(requestId: string): PendingCommentRequest | undefined {
|
|
45
|
+
const request = getCommentRequest(requestId)
|
|
46
|
+
if (!request || request.status !== "pending") return request
|
|
47
|
+
request.status = "completed"
|
|
48
|
+
request.updatedAt = Date.now()
|
|
49
|
+
return request
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function failCommentRequest(requestId: string, error: string): PendingCommentRequest | undefined {
|
|
53
|
+
const request = getCommentRequest(requestId)
|
|
54
|
+
if (!request || request.status !== "pending") return request
|
|
55
|
+
request.status = "failed"
|
|
56
|
+
request.error = error
|
|
57
|
+
request.updatedAt = Date.now()
|
|
58
|
+
return request
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function cleanupCommentRequests(now = Date.now()): void {
|
|
62
|
+
for (const [requestId, request] of requests) {
|
|
63
|
+
if (request.status === "pending" && now - request.createdAt > REQUEST_TTL_MS) {
|
|
64
|
+
request.status = "expired"
|
|
65
|
+
request.error = "Review agent timed out before completing the comment request."
|
|
66
|
+
request.updatedAt = now
|
|
67
|
+
continue
|
|
68
|
+
}
|
|
69
|
+
if (request.status !== "pending" && now - request.updatedAt > REQUEST_TTL_MS) {
|
|
70
|
+
requests.delete(requestId)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function clearCommentRequestsForTests(): void {
|
|
76
|
+
requests.clear()
|
|
77
|
+
}
|
package/lib/refine/open.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { ensureEditableDeckState } from "../edit/deck-state"
|
|
|
8
8
|
import { openUrl } from "../edit/open"
|
|
9
9
|
import { resolveEditableDeck, type EditableDeck } from "../edit/resolve-deck"
|
|
10
10
|
import { buildPrompt } from "../prompt-builder"
|
|
11
|
+
import type { ReviewPromptBridge } from "./prompt-bridge"
|
|
11
12
|
import { startRefineServer, type RefineMode } from "./server"
|
|
12
13
|
|
|
13
14
|
export interface OpenRefineDeckResult {
|
|
@@ -27,12 +28,13 @@ export interface EnsureRefineDeckOpenResult extends OpenRefineDeckResult {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
export interface OpenRefineDeckOptions {
|
|
30
|
-
client
|
|
31
|
-
sessionID
|
|
31
|
+
client?: any
|
|
32
|
+
sessionID?: string
|
|
32
33
|
workspaceRoot: string
|
|
33
34
|
mode?: RefineMode
|
|
34
35
|
openBrowser?: boolean
|
|
35
36
|
openUrl?: (url: string) => void
|
|
37
|
+
promptBridge?: ReviewPromptBridge
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
export function openRefineDeck(target: string, options: OpenRefineDeckOptions): OpenRefineDeckResult {
|
|
@@ -70,6 +72,7 @@ function openRefineDeckInternal(
|
|
|
70
72
|
workspaceRoot: options.workspaceRoot,
|
|
71
73
|
deck,
|
|
72
74
|
mode,
|
|
75
|
+
promptBridge: options.promptBridge,
|
|
73
76
|
})
|
|
74
77
|
const url = `${refineServer.baseUrl}/refine?token=${encodeURIComponent(session.token)}`
|
|
75
78
|
const shouldOpen = options.openBrowser !== false && !(behavior.skipLiveSession && session.live)
|