@osovv/vv-opencode 0.9.1 → 0.10.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.
@@ -0,0 +1,135 @@
1
+ // FILE: src/plugins/enhance/index.ts
2
+ // VERSION: 0.1.1
3
+ // START_MODULE_CONTRACT
4
+ // PURPOSE: Improve `/enhance` command UX by rewriting the TUI prompt instead of submitting command output parts directly when possible.
5
+ // SCOPE: Enhance command detection, prompt text extraction from command parts, TUI clear+append orchestration, and conservative fallback to default command behavior on API failure.
6
+ // DEPENDS: [@opencode-ai/plugin, @opencode-ai/sdk]
7
+ // LINKS: [M-PLUGIN-ENHANCE, V-M-PLUGIN-ENHANCE]
8
+ // ROLE: RUNTIME
9
+ // MAP_MODE: EXPORTS
10
+ // END_MODULE_CONTRACT
11
+ //
12
+ // START_MODULE_MAP
13
+ // EnhanceCommandPlugin - Intercepts `/enhance` command execution and rewrites the current TUI prompt via clear+append when available.
14
+ // END_MODULE_MAP
15
+ //
16
+ // START_CHANGE_SUMMARY
17
+ // LAST_CHANGE: [v0.1.1 - Added partial-failure recovery attempt that restores the original slash-command draft after clear+append failure.]
18
+ // END_CHANGE_SUMMARY
19
+ const ENHANCE_COMMAND = "enhance";
20
+ function getTuiClient(client) {
21
+ return client.tui;
22
+ }
23
+ // START_BLOCK_PROMPT_PART_EXTRACTION
24
+ function extractCommandPrompt(parts) {
25
+ const textSegments = [];
26
+ for (const part of parts) {
27
+ const text = part.text;
28
+ if (typeof text === "string") {
29
+ textSegments.push(text);
30
+ }
31
+ }
32
+ return textSegments.join("\n\n").trim();
33
+ }
34
+ // END_BLOCK_PROMPT_PART_EXTRACTION
35
+ // START_BLOCK_TUI_HELPERS
36
+ async function showToast(client, directory, variant, message) {
37
+ const tui = getTuiClient(client);
38
+ if (!tui?.showToast) {
39
+ return;
40
+ }
41
+ try {
42
+ await tui.showToast({
43
+ query: { directory },
44
+ body: {
45
+ title: "enhance",
46
+ message,
47
+ variant,
48
+ duration: 4_000,
49
+ },
50
+ });
51
+ }
52
+ catch {
53
+ // Toast display is best-effort only.
54
+ }
55
+ }
56
+ async function rewritePromptViaTui(client, directory, prompt, fallbackDraft) {
57
+ const tui = getTuiClient(client);
58
+ if (!tui?.clearPrompt || !tui.appendPrompt) {
59
+ return false;
60
+ }
61
+ let clearResult;
62
+ try {
63
+ clearResult = (await tui.clearPrompt({
64
+ query: { directory },
65
+ }));
66
+ }
67
+ catch {
68
+ return false;
69
+ }
70
+ if (clearResult.error) {
71
+ return false;
72
+ }
73
+ let appendResult;
74
+ try {
75
+ appendResult = (await tui.appendPrompt({
76
+ query: { directory },
77
+ body: {
78
+ text: prompt,
79
+ },
80
+ }));
81
+ }
82
+ catch {
83
+ await restoreFallbackDraft(tui, directory, fallbackDraft);
84
+ return false;
85
+ }
86
+ if (appendResult.error) {
87
+ await restoreFallbackDraft(tui, directory, fallbackDraft);
88
+ return false;
89
+ }
90
+ return true;
91
+ }
92
+ async function restoreFallbackDraft(tui, directory, fallbackDraft) {
93
+ if (!fallbackDraft.trim() || !tui.appendPrompt) {
94
+ return;
95
+ }
96
+ try {
97
+ await tui.appendPrompt({
98
+ query: { directory },
99
+ body: {
100
+ text: fallbackDraft,
101
+ },
102
+ });
103
+ }
104
+ catch {
105
+ // Recovery is best-effort only.
106
+ }
107
+ }
108
+ // END_BLOCK_TUI_HELPERS
109
+ // START_BLOCK_PLUGIN_ENTRY
110
+ export const EnhanceCommandPlugin = async ({ client, directory }) => {
111
+ return {
112
+ "command.execute.before": async (input, output) => {
113
+ if (input.command !== ENHANCE_COMMAND) {
114
+ return;
115
+ }
116
+ const prompt = extractCommandPrompt(output.parts);
117
+ if (!prompt) {
118
+ return;
119
+ }
120
+ const trimmedArguments = input.arguments.trim();
121
+ const fallbackDraft = trimmedArguments
122
+ ? `/${input.command} ${trimmedArguments}`
123
+ : `/${input.command}`;
124
+ const rewritten = await rewritePromptViaTui(client, directory, prompt, fallbackDraft);
125
+ if (!rewritten) {
126
+ await showToast(client, directory, "warning", "TUI prompt rewrite is unavailable; using default /enhance submit behavior.");
127
+ return;
128
+ }
129
+ output.parts = [];
130
+ await showToast(client, directory, "info", "Enhanced prompt inserted into chatbox. Review and press Enter to submit.");
131
+ },
132
+ };
133
+ };
134
+ // END_BLOCK_PLUGIN_ENTRY
135
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/enhance/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osovv/vv-opencode",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "Portable OpenCode workflow plugins, explicit memory, and CLI tooling.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -41,6 +41,10 @@
41
41
  "types": "./dist/plugins/memory/index.d.ts",
42
42
  "import": "./dist/plugins/memory/index.js"
43
43
  },
44
+ "./plugins/enhance": {
45
+ "types": "./dist/plugins/enhance/index.d.ts",
46
+ "import": "./dist/plugins/enhance/index.js"
47
+ },
44
48
  "./plugins/secrets-redaction": {
45
49
  "types": "./dist/plugins/secrets-redaction/index.d.ts",
46
50
  "import": "./dist/plugins/secrets-redaction/index.js"
@@ -54,7 +58,7 @@
54
58
  "fmt:check": "oxfmt --check src",
55
59
  "test": "bun test",
56
60
  "check": "bun run typecheck && bun run lint && bun run fmt:check && bun test",
57
- "pack:check": "bun run build && bun -e \"await import('./dist/plugins/guardian/index.js'); await import('./dist/plugins/memory/index.js')\" && npm pack --dry-run",
61
+ "pack:check": "bun run build && bun -e \"const root = await import('./dist/index.js'); if (!('EnhanceCommandPlugin' in root)) throw new Error('dist root export missing EnhanceCommandPlugin'); await import('./dist/plugins/guardian/index.js'); await import('./dist/plugins/memory/index.js'); await import('./dist/plugins/enhance/index.js')\" && npm pack --dry-run",
58
62
  "prepare": "lefthook install --force"
59
63
  },
60
64
  "dependencies": {