opencode-prompt-expand 0.0.0-stage → 0.1.1
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/CHANGELOG.md +18 -0
- package/LICENSE +21 -0
- package/README.md +338 -2
- package/assets/bmc-qr.png +0 -0
- package/assets/featured.html +260 -0
- package/assets/featured.png +0 -0
- package/dist/config.js +76 -0
- package/dist/gui-experimental.cjs +61 -0
- package/dist/index.js +170 -0
- package/dist/model.js +104 -0
- package/dist/optimizer.js +86 -0
- package/dist/project-context.js +121 -0
- package/dist/prompts.js +109 -0
- package/dist/rpc.js +47 -0
- package/dist/types.js +1 -0
- package/docs/README.zh-CN.md +177 -0
- package/package.json +64 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.1
|
|
4
|
+
|
|
5
|
+
- Fix the npm package README so the English README is primary.
|
|
6
|
+
- Move the Chinese README to `docs/README.zh-CN.md`.
|
|
7
|
+
- Update the npm install instructions after the first publish.
|
|
8
|
+
|
|
9
|
+
## 0.1.0
|
|
10
|
+
|
|
11
|
+
- Initial OpenCode Desktop GUI plugin.
|
|
12
|
+
- Expand, regenerate, undo, restore, and version navigation commands.
|
|
13
|
+
- Composer pill for mounted sessions.
|
|
14
|
+
- Best-effort bottom button and DOM fallback for Home / new-session drafts.
|
|
15
|
+
- Settings page for mode, model, and project context.
|
|
16
|
+
- Project context from package.json, rule files, and git status.
|
|
17
|
+
- OpenAI/Claude-family prompt variants.
|
|
18
|
+
- Unit tests and a stubbed GUI smoke test.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,339 @@
|
|
|
1
|
-
#
|
|
1
|
+
# opencode-prompt-expand
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Expand a rough draft in the **OpenCode Desktop** composer into a structured prompt, in place.
|
|
6
|
+
|
|
7
|
+
The plugin is a small OpenCode Desktop extension: it reads the current draft, asks your own connected model to expand it, writes the result back into the composer, and leaves the send action to you. It never sends a message, never writes session history, and never proxies model credentials.
|
|
8
|
+
|
|
9
|
+
**Status:** `v0.1.1` experimental. The package is published on npm. The OpenCode Desktop GUI plugin API is still marked experimental upstream; pin the OpenCode version you test against.
|
|
10
|
+
|
|
11
|
+
[中文说明](docs/README.zh-CN.md)
|
|
12
|
+
|
|
13
|
+
**Who it is for:** OpenCode Desktop users who write natural-language prompts and want a more structured first draft without leaving the composer. It is not a TUI plugin and it does not send messages for you.
|
|
14
|
+
|
|
15
|
+
## What it does
|
|
16
|
+
|
|
17
|
+
- Turns vague requests into prompts with scope, constraints, output format, and acceptance criteria.
|
|
18
|
+
- Writes the result back into the composer so you can edit it before sending.
|
|
19
|
+
- Keeps up to five generated versions in memory for the current window.
|
|
20
|
+
- Adds toast actions for **Undo** and **Regenerate**.
|
|
21
|
+
- Can read a small, whitelisted set of project facts to make the expansion more specific.
|
|
22
|
+
- Supports a concise mode (~800 characters) and a full-expansion mode.
|
|
23
|
+
|
|
24
|
+
It does not:
|
|
25
|
+
|
|
26
|
+
- send the prompt
|
|
27
|
+
- modify session history
|
|
28
|
+
- read `.env`, keys, or source files
|
|
29
|
+
- call the plugin author's servers
|
|
30
|
+
|
|
31
|
+
## Requirements
|
|
32
|
+
|
|
33
|
+
- OpenCode Desktop **2.2.5** (the version this release was built and tested against)
|
|
34
|
+
- Node.js **^20.19.0 or >=22.12.0** and npm, if you build from source
|
|
35
|
+
- A provider/model connected in OpenCode. The plugin uses your own provider account (BYOK).
|
|
36
|
+
|
|
37
|
+
The TUI is not supported. The GUI composer API used here is only available in OpenCode Desktop.
|
|
38
|
+
|
|
39
|
+
## Install from GitHub
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git clone https://github.com/ConnorYyy/opencode-prompt-expand.git
|
|
43
|
+
cd opencode-prompt-expand
|
|
44
|
+
npm ci
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`npm ci` runs the `prepare` script, which builds `dist/`. You can also run `npm run build` explicitly.
|
|
48
|
+
|
|
49
|
+
The build produces:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
dist/index.js server part
|
|
53
|
+
dist/rpc.js RPC contract
|
|
54
|
+
dist/gui-experimental.cjs Desktop GUI bundle
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Add the plugin to the **global** OpenCode config. Desktop reads GUI plugins only from the global file:
|
|
58
|
+
|
|
59
|
+
- macOS / Linux: `~/.config/opencode/opencode.jsonc`
|
|
60
|
+
- Windows: `C:\Users\<you>\.config\opencode\opencode.jsonc`
|
|
61
|
+
|
|
62
|
+
```jsonc
|
|
63
|
+
{
|
|
64
|
+
"shell": "powershell",
|
|
65
|
+
"plugins": [
|
|
66
|
+
{
|
|
67
|
+
"package": "/absolute/path/to/opencode-prompt-expand",
|
|
68
|
+
"options": {
|
|
69
|
+
"mode": "concise",
|
|
70
|
+
"model": "auto",
|
|
71
|
+
"projectContext": true,
|
|
72
|
+
"timeoutMs": 30000
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
On Windows, use forward slashes or escaped backslashes in the path, for example:
|
|
80
|
+
|
|
81
|
+
```jsonc
|
|
82
|
+
"package": "D:/path/to/opencode-prompt-expand"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Then reload the Desktop window or restart OpenCode Desktop. The GUI bundle is loaded at window start; reloading only the server is not enough after a first install.
|
|
86
|
+
|
|
87
|
+
Confirm the install:
|
|
88
|
+
|
|
89
|
+
- **Settings > Extensions > Plugins** shows `prompt-expand` as enabled.
|
|
90
|
+
- The command palette has **Expand prompt**.
|
|
91
|
+
- A mounted session shows the `⚡ Expand Prompt` pill above the composer.
|
|
92
|
+
- Home / new-session drafts show the bottom `⚡ Expand Prompt` button (see below).
|
|
93
|
+
|
|
94
|
+
### Install from npm
|
|
95
|
+
|
|
96
|
+
Install it with the OpenCode CLI:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
opencode plugin add opencode-prompt-expand
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Pin a specific version when needed:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
opencode plugin add opencode-prompt-expand@0.1.1
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Then verify it is configured:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
opencode plugin list
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Package page: https://www.npmjs.com/package/opencode-prompt-expand
|
|
115
|
+
|
|
116
|
+
## Usage
|
|
117
|
+
|
|
118
|
+
1. Write a draft in the composer, for example:
|
|
119
|
+
`帮我做一个数据看板,包含筛选和导出`
|
|
120
|
+
2. Click `⚡ Expand Prompt`, run **Expand prompt** from the command palette, or type `/expand <text>`.
|
|
121
|
+
3. Wait for the model. The draft is replaced in place.
|
|
122
|
+
4. Review or edit the result, then press Enter yourself.
|
|
123
|
+
|
|
124
|
+
### Entry points
|
|
125
|
+
|
|
126
|
+
| Entry | How |
|
|
127
|
+
|---|---|
|
|
128
|
+
| Pill | Click `⚡ Expand Prompt` above a session composer |
|
|
129
|
+
| Draft button | On Home / new-session drafts, use the bottom `⚡ Expand Prompt` button |
|
|
130
|
+
| Command palette | Search `Expand prompt` |
|
|
131
|
+
| Slash command | `/expand <text>` |
|
|
132
|
+
| Regenerate | Toast action, or command palette **Regenerate prompt** |
|
|
133
|
+
| Restore original | Toast **Undo**, or command palette **Restore original prompt** |
|
|
134
|
+
| Previous / next version | Command palette **Previous expanded version** / **Next expanded version** |
|
|
135
|
+
| Toggle mode | Command palette **Toggle expansion mode** |
|
|
136
|
+
|
|
137
|
+
There are **no default keyboard shortcuts**. Commands are registered in **Settings > Shortcuts**; assign your own:
|
|
138
|
+
|
|
139
|
+
```text
|
|
140
|
+
prompt-expand.expand
|
|
141
|
+
prompt-expand.regenerate
|
|
142
|
+
prompt-expand.restore
|
|
143
|
+
prompt-expand.previous
|
|
144
|
+
prompt-expand.next
|
|
145
|
+
prompt-expand.mode
|
|
146
|
+
prompt-expand.settings
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Versions
|
|
150
|
+
|
|
151
|
+
- Up to 5 generated versions per draft, in memory for the current window.
|
|
152
|
+
- Editing the draft resets the version stack; the next expansion starts from the edited text.
|
|
153
|
+
- Toast actions are guarded: if you switched sessions or edited the text, Undo will not overwrite your changes.
|
|
154
|
+
- The failure toast includes the server `code` and `message` when available, so timeout, model, and validation failures are distinguishable.
|
|
155
|
+
|
|
156
|
+
## Home and new-session drafts
|
|
157
|
+
|
|
158
|
+
The official `ctx.screen.current()?.composer` API is `undefined` on Home and on a draft session; `Sessions.current()` is also `undefined` there. The session `ComposerPill` therefore cannot render before the first message creates a mounted session.
|
|
159
|
+
|
|
160
|
+
For those pages the plugin adds a bottom `⚡ Expand Prompt` button. Because no official draft composer API exists, it uses a **best-effort DOM adapter**:
|
|
161
|
+
|
|
162
|
+
- it finds the bottom-most visible `textarea`, text input, or contenteditable;
|
|
163
|
+
- it reads and writes that element directly;
|
|
164
|
+
- it only runs when there is no mounted session;
|
|
165
|
+
- it is hidden on Settings and other plugin pages.
|
|
166
|
+
|
|
167
|
+
Impact and limits:
|
|
168
|
+
|
|
169
|
+
- It is not an official OpenCode API and may break if the Desktop composer changes.
|
|
170
|
+
- It may fail on a complex rich-text composer or if the editor changes during the model call.
|
|
171
|
+
- `@` mentions and attachments are not supported on drafts.
|
|
172
|
+
- The draft has no composer model, so the model comes from the server default or your configured model.
|
|
173
|
+
- Disable it with `draftFallback: false` if you only want to expand in mounted sessions.
|
|
174
|
+
- After the first message creates a session, the normal composer pill is used.
|
|
175
|
+
|
|
176
|
+
## Settings
|
|
177
|
+
|
|
178
|
+
Open **Settings > Prompt Expand**, or run **Prompt Expand settings** from the command palette (command `prompt-expand.settings`).
|
|
179
|
+
|
|
180
|
+
| Setting | Description |
|
|
181
|
+
|---|---|
|
|
182
|
+
| Mode | `concise` (~800 chars) or `full` |
|
|
183
|
+
| Model | `auto`, `composer`, `provider/model`, or empty |
|
|
184
|
+
| Project context | Read `package.json`, rule files, and git status |
|
|
185
|
+
|
|
186
|
+
Settings persist through `Store.global`. An unset field, or a model field of `auto`, follows the `options` from `opencode.jsonc`; an explicit setting overrides it. This matters on Home/draft pages, where no composer model is available.
|
|
187
|
+
|
|
188
|
+
## Configuration
|
|
189
|
+
|
|
190
|
+
Options are passed through the plugin entry:
|
|
191
|
+
|
|
192
|
+
| Key | Default | Description |
|
|
193
|
+
|---|---|---|
|
|
194
|
+
| `model` | `"auto"` | `auto`, `composer`, or `"provider/model"` |
|
|
195
|
+
| `mode` | `"concise"` | `concise` / `full` |
|
|
196
|
+
| `maxRounds` | `5` | Total generations per draft, including v1 |
|
|
197
|
+
| `timeoutMs` | `30000` | Abort and leave the composer untouched after this long |
|
|
198
|
+
| `maxGrowth` | `5` | Reject output larger than `original × maxGrowth` **and** > 2000 chars |
|
|
199
|
+
| `minChars` | `10` | Below this, skip |
|
|
200
|
+
| `maxPromptChars` | `6000` | Above this, skip |
|
|
201
|
+
| `skipPatterns` | built-in | Array of regex strings; replaces the built-in list |
|
|
202
|
+
| `skipOnMentions` | `true` | Skip drafts containing `@path` |
|
|
203
|
+
| `projectContext` | `true` | Read project facts |
|
|
204
|
+
| `projectContextBudget` | `2048` | Character budget for injected context |
|
|
205
|
+
| `draftFallback` | `true` | Enable the DOM fallback on Home / new-session drafts |
|
|
206
|
+
| `prompts` | built-in | Map of glob → prompt; `*gpt*` and `*claude*` included |
|
|
207
|
+
|
|
208
|
+
### Model selection
|
|
209
|
+
|
|
210
|
+
- `composer` uses the model currently selected in the composer.
|
|
211
|
+
- `auto` prefers the composer model, then the session model, then the server default, then a cheap chat model.
|
|
212
|
+
- Explicit `provider/model` is used as-is.
|
|
213
|
+
|
|
214
|
+
If `auto` falls back to a free model and that model has hit its usage limit, set the model to `composer` or an explicit paid model.
|
|
215
|
+
|
|
216
|
+
The composer model is mapped from `{ providerID, modelID }` to the generation API's `{ providerID, id }`.
|
|
217
|
+
|
|
218
|
+
### Project context
|
|
219
|
+
|
|
220
|
+
Only these sources are read:
|
|
221
|
+
|
|
222
|
+
- `package.json` (name, description, dependency names)
|
|
223
|
+
- `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `.cursorrules`, `.windsurfrules`, `CONVENTIONS.md`, `.github/copilot-instructions.md`
|
|
224
|
+
- current branch and changed file names (filtered to exclude `node_modules/`)
|
|
225
|
+
|
|
226
|
+
The directory is resolved from the mounted session first, then the directory supplied by the Desktop window, then the plugin instance location. The result is cached for 5 minutes per directory and limited to `projectContextBudget` characters.
|
|
227
|
+
|
|
228
|
+
## Privacy and side effects
|
|
229
|
+
|
|
230
|
+
- The draft is sent only to the provider you connected in OpenCode.
|
|
231
|
+
- The plugin does not persist drafts, keys, or credentials.
|
|
232
|
+
- It does not send messages, write session history, or occupy the session context window.
|
|
233
|
+
- Project context never reads `.env`, `.pem`, `credentials*`, or source files.
|
|
234
|
+
- The plugin has no telemetry and no author-operated proxy.
|
|
235
|
+
|
|
236
|
+
## Development
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
npm ci
|
|
240
|
+
npm run typecheck
|
|
241
|
+
npm test
|
|
242
|
+
npm run build
|
|
243
|
+
npm run smoke:gui
|
|
244
|
+
npm run verify # typecheck + tests + build + GUI smoke
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
`src/index.ts` is the server part, `src/gui.tsx` is the Desktop GUI bundle, and `src/rpc.ts` is the shared contract.
|
|
248
|
+
|
|
249
|
+
`scripts/smoke-gui.cjs` loads the built GUI bundle with stubbed host modules and exercises expand, regenerate, undo, settings, pill, and the draft fallback slot.
|
|
250
|
+
|
|
251
|
+
### Project layout
|
|
252
|
+
|
|
253
|
+
```text
|
|
254
|
+
src/
|
|
255
|
+
├── index.ts server and RPC registration
|
|
256
|
+
├── rpc.ts RPC contract
|
|
257
|
+
├── gui.tsx Desktop GUI entry
|
|
258
|
+
├── gui/
|
|
259
|
+
│ ├── commands.ts command palette / slash commands
|
|
260
|
+
│ ├── controller.ts expand, regenerate, undo, versions
|
|
261
|
+
│ ├── draft.ts DOM fallback for Home / drafts
|
|
262
|
+
│ ├── failure.ts RPC error detail
|
|
263
|
+
│ ├── pill.ts composer pill
|
|
264
|
+
│ ├── settings.tsx settings page
|
|
265
|
+
│ └── state.ts per-session version stack
|
|
266
|
+
├── optimizer.ts bypass, cleaning, validation
|
|
267
|
+
├── prompts.ts default and model-family prompts
|
|
268
|
+
├── model.ts model selection
|
|
269
|
+
├── project-context.ts whitelist and budget
|
|
270
|
+
└── config.ts option resolution
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### CI
|
|
274
|
+
|
|
275
|
+
The repository includes a GitHub Actions workflow that runs `npm ci` and `npm run verify` on Windows and Ubuntu with Node 20.19 and 22.12.
|
|
276
|
+
|
|
277
|
+
## Limitations
|
|
278
|
+
|
|
279
|
+
- The Desktop GUI plugin API is experimental. Pin `@opencode/plugin` to the OpenCode version you run.
|
|
280
|
+
- The Home/draft DOM fallback is best-effort and not an official composer API.
|
|
281
|
+
- `composer.setText()` replaces text and keeps attachments, but it cannot rewrite `@` mention parts. Drafts containing `@path` are skipped.
|
|
282
|
+
- There is no TUI implementation.
|
|
283
|
+
- A slow model can exceed `timeoutMs`; raise it if your provider is slow.
|
|
284
|
+
|
|
285
|
+
## FAQ
|
|
286
|
+
|
|
287
|
+
### Is this a TUI plugin?
|
|
288
|
+
|
|
289
|
+
No. It uses the OpenCode Desktop GUI composer API. The terminal TUI is not supported.
|
|
290
|
+
|
|
291
|
+
### Does it send the prompt automatically?
|
|
292
|
+
|
|
293
|
+
No. The plugin only reads the composer, writes the expanded text back, and leaves Enter to you. It does not create session messages or write conversation history.
|
|
294
|
+
|
|
295
|
+
### Which model does it use?
|
|
296
|
+
|
|
297
|
+
By default, `auto` prefers the composer model, then the session model, then the server default, then a cheap chat model. You can also set `composer` or an explicit `provider/model` in settings.
|
|
298
|
+
|
|
299
|
+
### Why are there no default keyboard shortcuts?
|
|
300
|
+
|
|
301
|
+
Shortcuts are user-specific and can conflict with host bindings. The commands are registered in **Settings > Shortcuts**; assign the ones you want.
|
|
302
|
+
|
|
303
|
+
### Why does the new-session page use a bottom button instead of a composer pill?
|
|
304
|
+
|
|
305
|
+
OpenCode does not expose an official composer API on Home or draft sessions. The bottom button is a best-effort DOM fallback and is marked experimental. Once the first message creates a mounted session, the normal composer pill is used.
|
|
306
|
+
|
|
307
|
+
### Does it support `@` file mentions?
|
|
308
|
+
|
|
309
|
+
Drafts containing `@path` references are skipped because rewriting the text can desynchronize mention attachments. Plain email addresses are not treated as mentions.
|
|
310
|
+
|
|
311
|
+
### Does it store my prompts?
|
|
312
|
+
|
|
313
|
+
No. Drafts are not persisted by the plugin. The version stack is in memory for the current window only.
|
|
314
|
+
|
|
315
|
+
### What happens when expansion fails?
|
|
316
|
+
|
|
317
|
+
The original composer text is left unchanged. The toast includes the server `code` and `message` when available, such as timeout, model, or validation failure.
|
|
318
|
+
|
|
319
|
+
### Is it free?
|
|
320
|
+
|
|
321
|
+
The plugin is MIT-licensed. You pay your own model provider for generation; there is no author-operated proxy or telemetry.
|
|
322
|
+
|
|
323
|
+
### How is it different from a generic prompt optimizer?
|
|
324
|
+
|
|
325
|
+
It works inside the OpenCode Desktop composer, writes back in place, keeps a small version stack, and can use the model you already selected. It does not require copying prompts into another chat window.
|
|
326
|
+
|
|
327
|
+
## Sponsor
|
|
328
|
+
|
|
329
|
+
If this plugin saves you time, you can support maintenance and testing through Buy Me a Coffee:
|
|
330
|
+
|
|
331
|
+
[buymeacoffee.com/connory](https://buymeacoffee.com/connory)
|
|
332
|
+
|
|
333
|
+
[](https://buymeacoffee.com/connory)
|
|
334
|
+
|
|
335
|
+
Scan the QR code or use the link. Support is optional; the plugin remains MIT-licensed.
|
|
336
|
+
|
|
337
|
+
## License
|
|
338
|
+
|
|
339
|
+
MIT
|
|
Binary file
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=1080, initial-scale=1" />
|
|
6
|
+
<title>opencode-prompt-expand featured image</title>
|
|
7
|
+
<style>
|
|
8
|
+
* { box-sizing: border-box; }
|
|
9
|
+
html, body { margin: 0; width: 1080px; height: 1080px; overflow: hidden; }
|
|
10
|
+
body {
|
|
11
|
+
font-family: "Segoe UI", "Inter", Arial, sans-serif;
|
|
12
|
+
background: #080d19;
|
|
13
|
+
color: #f5f7ff;
|
|
14
|
+
-webkit-font-smoothing: antialiased;
|
|
15
|
+
}
|
|
16
|
+
.canvas {
|
|
17
|
+
position: relative;
|
|
18
|
+
width: 1080px;
|
|
19
|
+
height: 1080px;
|
|
20
|
+
padding: 64px 72px 54px;
|
|
21
|
+
overflow: hidden;
|
|
22
|
+
background:
|
|
23
|
+
radial-gradient(circle at 78% 18%, rgba(70, 130, 255, 0.20), transparent 34%),
|
|
24
|
+
radial-gradient(circle at 18% 78%, rgba(40, 220, 190, 0.13), transparent 32%),
|
|
25
|
+
linear-gradient(145deg, #0a1020 0%, #0b1224 52%, #070b14 100%);
|
|
26
|
+
}
|
|
27
|
+
.canvas::before {
|
|
28
|
+
content: "";
|
|
29
|
+
position: absolute;
|
|
30
|
+
inset: 0;
|
|
31
|
+
background-image:
|
|
32
|
+
linear-gradient(rgba(140, 170, 230, 0.045) 1px, transparent 1px),
|
|
33
|
+
linear-gradient(90deg, rgba(140, 170, 230, 0.045) 1px, transparent 1px);
|
|
34
|
+
background-size: 54px 54px;
|
|
35
|
+
mask-image: linear-gradient(to bottom, rgba(0,0,0,0.7), transparent 78%);
|
|
36
|
+
}
|
|
37
|
+
.glow {
|
|
38
|
+
position: absolute;
|
|
39
|
+
border-radius: 999px;
|
|
40
|
+
filter: blur(80px);
|
|
41
|
+
opacity: 0.5;
|
|
42
|
+
pointer-events: none;
|
|
43
|
+
}
|
|
44
|
+
.g1 { width: 420px; height: 420px; right: -120px; top: 40px; background: #245bff; }
|
|
45
|
+
.g2 { width: 360px; height: 360px; left: -140px; bottom: 20px; background: #16c7a7; opacity: 0.3; }
|
|
46
|
+
.top {
|
|
47
|
+
position: relative;
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
justify-content: space-between;
|
|
51
|
+
z-index: 2;
|
|
52
|
+
}
|
|
53
|
+
.badge {
|
|
54
|
+
display: inline-flex;
|
|
55
|
+
align-items: center;
|
|
56
|
+
gap: 12px;
|
|
57
|
+
padding: 12px 18px;
|
|
58
|
+
border: 1px solid rgba(120, 160, 230, 0.28);
|
|
59
|
+
background: rgba(16, 28, 52, 0.72);
|
|
60
|
+
border-radius: 999px;
|
|
61
|
+
font-size: 17px;
|
|
62
|
+
letter-spacing: 2.4px;
|
|
63
|
+
font-weight: 650;
|
|
64
|
+
color: #b9c9e9;
|
|
65
|
+
}
|
|
66
|
+
.dot {
|
|
67
|
+
width: 10px;
|
|
68
|
+
height: 10px;
|
|
69
|
+
border-radius: 50%;
|
|
70
|
+
background: #3ee0be;
|
|
71
|
+
box-shadow: 0 0 18px rgba(62, 224, 190, 0.9);
|
|
72
|
+
}
|
|
73
|
+
.version {
|
|
74
|
+
font-family: Consolas, "Cascadia Code", monospace;
|
|
75
|
+
font-size: 18px;
|
|
76
|
+
color: #7e91b8;
|
|
77
|
+
}
|
|
78
|
+
h1 {
|
|
79
|
+
position: relative;
|
|
80
|
+
z-index: 2;
|
|
81
|
+
margin: 54px 0 0;
|
|
82
|
+
font-size: 86px;
|
|
83
|
+
line-height: 0.98;
|
|
84
|
+
letter-spacing: -3.8px;
|
|
85
|
+
font-weight: 760;
|
|
86
|
+
}
|
|
87
|
+
h1 span {
|
|
88
|
+
color: #67e5ca;
|
|
89
|
+
text-shadow: 0 0 46px rgba(53, 220, 185, 0.24);
|
|
90
|
+
}
|
|
91
|
+
.tagline {
|
|
92
|
+
position: relative;
|
|
93
|
+
z-index: 2;
|
|
94
|
+
margin: 24px 0 0;
|
|
95
|
+
max-width: 820px;
|
|
96
|
+
font-size: 29px;
|
|
97
|
+
line-height: 1.35;
|
|
98
|
+
color: #a9b9d8;
|
|
99
|
+
letter-spacing: -0.3px;
|
|
100
|
+
}
|
|
101
|
+
.flow {
|
|
102
|
+
position: relative;
|
|
103
|
+
z-index: 2;
|
|
104
|
+
display: grid;
|
|
105
|
+
grid-template-columns: 1fr 104px 1.18fr;
|
|
106
|
+
gap: 12px;
|
|
107
|
+
align-items: center;
|
|
108
|
+
margin-top: 48px;
|
|
109
|
+
}
|
|
110
|
+
.card {
|
|
111
|
+
min-height: 300px;
|
|
112
|
+
border-radius: 26px;
|
|
113
|
+
padding: 26px 26px 22px;
|
|
114
|
+
border: 1px solid rgba(130, 165, 230, 0.22);
|
|
115
|
+
background: linear-gradient(180deg, rgba(24, 38, 68, 0.86), rgba(12, 20, 38, 0.88));
|
|
116
|
+
box-shadow: 0 22px 60px rgba(0, 0, 0, 0.32), inset 0 1px 0 rgba(255,255,255,0.05);
|
|
117
|
+
}
|
|
118
|
+
.card.result {
|
|
119
|
+
border-color: rgba(75, 225, 193, 0.35);
|
|
120
|
+
background: linear-gradient(180deg, rgba(18, 53, 62, 0.62), rgba(10, 26, 35, 0.9));
|
|
121
|
+
}
|
|
122
|
+
.label {
|
|
123
|
+
font-family: Consolas, "Cascadia Code", monospace;
|
|
124
|
+
font-size: 14px;
|
|
125
|
+
letter-spacing: 2.6px;
|
|
126
|
+
color: #8094bb;
|
|
127
|
+
margin-bottom: 20px;
|
|
128
|
+
}
|
|
129
|
+
.result .label { color: #64d9c0; }
|
|
130
|
+
.quote {
|
|
131
|
+
font-size: 31px;
|
|
132
|
+
line-height: 1.32;
|
|
133
|
+
color: #e7edff;
|
|
134
|
+
letter-spacing: -0.5px;
|
|
135
|
+
margin: 8px 0 18px;
|
|
136
|
+
}
|
|
137
|
+
.muted {
|
|
138
|
+
font-size: 17px;
|
|
139
|
+
color: #7386aa;
|
|
140
|
+
line-height: 1.4;
|
|
141
|
+
}
|
|
142
|
+
.rline {
|
|
143
|
+
display: flex;
|
|
144
|
+
align-items: center;
|
|
145
|
+
gap: 12px;
|
|
146
|
+
margin: 13px 0;
|
|
147
|
+
}
|
|
148
|
+
.check {
|
|
149
|
+
width: 24px;
|
|
150
|
+
height: 24px;
|
|
151
|
+
border-radius: 8px;
|
|
152
|
+
display: grid;
|
|
153
|
+
place-items: center;
|
|
154
|
+
background: rgba(58, 221, 187, 0.14);
|
|
155
|
+
border: 1px solid rgba(58, 221, 187, 0.35);
|
|
156
|
+
color: #64e5cb;
|
|
157
|
+
font-size: 15px;
|
|
158
|
+
font-weight: 800;
|
|
159
|
+
flex: none;
|
|
160
|
+
}
|
|
161
|
+
.bar {
|
|
162
|
+
height: 10px;
|
|
163
|
+
border-radius: 99px;
|
|
164
|
+
background: linear-gradient(90deg, rgba(109, 145, 210, 0.75), rgba(109, 145, 210, 0.28));
|
|
165
|
+
}
|
|
166
|
+
.w90 { width: 90%; }
|
|
167
|
+
.w74 { width: 74%; }
|
|
168
|
+
.w82 { width: 82%; }
|
|
169
|
+
.w60 { width: 60%; }
|
|
170
|
+
.w68 { width: 68%; }
|
|
171
|
+
.arrow {
|
|
172
|
+
display: flex;
|
|
173
|
+
flex-direction: column;
|
|
174
|
+
align-items: center;
|
|
175
|
+
gap: 10px;
|
|
176
|
+
}
|
|
177
|
+
.bolt {
|
|
178
|
+
width: 68px;
|
|
179
|
+
height: 68px;
|
|
180
|
+
border-radius: 22px;
|
|
181
|
+
display: grid;
|
|
182
|
+
place-items: center;
|
|
183
|
+
font-size: 36px;
|
|
184
|
+
background: linear-gradient(145deg, #47e3c5, #347dff);
|
|
185
|
+
color: #07111f;
|
|
186
|
+
box-shadow: 0 0 45px rgba(60, 220, 195, 0.28);
|
|
187
|
+
}
|
|
188
|
+
.arrow-line {
|
|
189
|
+
width: 2px;
|
|
190
|
+
height: 58px;
|
|
191
|
+
background: linear-gradient(to bottom, rgba(80, 225, 200, 0.7), rgba(80, 225, 200, 0));
|
|
192
|
+
}
|
|
193
|
+
.footer {
|
|
194
|
+
position: absolute;
|
|
195
|
+
z-index: 2;
|
|
196
|
+
left: 72px;
|
|
197
|
+
right: 72px;
|
|
198
|
+
bottom: 50px;
|
|
199
|
+
display: flex;
|
|
200
|
+
gap: 14px;
|
|
201
|
+
align-items: center;
|
|
202
|
+
font-family: Consolas, "Cascadia Code", monospace;
|
|
203
|
+
font-size: 16px;
|
|
204
|
+
color: #6d82a8;
|
|
205
|
+
letter-spacing: 0.4px;
|
|
206
|
+
}
|
|
207
|
+
.footer span {
|
|
208
|
+
padding: 7px 12px;
|
|
209
|
+
border-radius: 8px;
|
|
210
|
+
background: rgba(20, 34, 60, 0.62);
|
|
211
|
+
border: 1px solid rgba(120, 155, 220, 0.14);
|
|
212
|
+
}
|
|
213
|
+
.footer .accent { color: #67e5ca; }
|
|
214
|
+
</style>
|
|
215
|
+
</head>
|
|
216
|
+
<body>
|
|
217
|
+
<div class="canvas">
|
|
218
|
+
<div class="glow g1"></div>
|
|
219
|
+
<div class="glow g2"></div>
|
|
220
|
+
|
|
221
|
+
<div class="top">
|
|
222
|
+
<div class="badge"><span class="dot"></span> OPENCODE DESKTOP PLUGIN</div>
|
|
223
|
+
<div class="version">v0.1.0</div>
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
<h1>opencode-<br /><span>prompt-expand</span></h1>
|
|
227
|
+
<p class="tagline">Turn rough drafts into structured prompts — in place, in your composer.</p>
|
|
228
|
+
|
|
229
|
+
<div class="flow">
|
|
230
|
+
<div class="card draft">
|
|
231
|
+
<div class="label">DRAFT</div>
|
|
232
|
+
<div class="quote">“修一下登录的 bug”</div>
|
|
233
|
+
<div class="bar w82" style="margin-bottom:12px"></div>
|
|
234
|
+
<div class="bar w60" style="margin-bottom:22px"></div>
|
|
235
|
+
<div class="muted">vague · missing scope<br />no acceptance criteria</div>
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
<div class="arrow">
|
|
239
|
+
<div class="bolt">⚡</div>
|
|
240
|
+
<div class="arrow-line"></div>
|
|
241
|
+
</div>
|
|
242
|
+
|
|
243
|
+
<div class="card result">
|
|
244
|
+
<div class="label">EXPANDED</div>
|
|
245
|
+
<div class="rline"><span class="check">✓</span><div class="bar w90"></div></div>
|
|
246
|
+
<div class="rline"><span class="check">✓</span><div class="bar w74"></div></div>
|
|
247
|
+
<div class="rline"><span class="check">✓</span><div class="bar w82"></div></div>
|
|
248
|
+
<div class="rline"><span class="check">✓</span><div class="bar w68"></div></div>
|
|
249
|
+
<div class="muted" style="margin-top:18px">goal · scope · constraints<br />output · acceptance</div>
|
|
250
|
+
</div>
|
|
251
|
+
</div>
|
|
252
|
+
|
|
253
|
+
<div class="footer">
|
|
254
|
+
<span>MIT licensed</span>
|
|
255
|
+
<span>BYOK</span>
|
|
256
|
+
<span class="accent">never auto-sends</span>
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
259
|
+
</body>
|
|
260
|
+
</html>
|
|
Binary file
|