@osovv/vv-opencode 1.7.0 → 2.0.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.
Files changed (98) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +23 -2
  3. package/dist/commands/preset.js +1 -1
  4. package/dist/commands/preset.js.map +1 -1
  5. package/dist/index.d.ts +7 -11
  6. package/dist/index.js +53 -20
  7. package/dist/index.js.map +1 -1
  8. package/dist/plugins/analytics/index.d.ts +2 -0
  9. package/dist/plugins/analytics/index.js +13 -2
  10. package/dist/plugins/analytics/index.js.map +1 -1
  11. package/dist/plugins/analytics/v2.d.ts +21 -0
  12. package/dist/plugins/analytics/v2.js +133 -0
  13. package/dist/plugins/analytics/v2.js.map +1 -0
  14. package/dist/plugins/guardian/index.d.ts +46 -0
  15. package/dist/plugins/guardian/index.js +21 -6
  16. package/dist/plugins/guardian/index.js.map +1 -1
  17. package/dist/plugins/guardian/v2.d.ts +13 -0
  18. package/dist/plugins/guardian/v2.js +204 -0
  19. package/dist/plugins/guardian/v2.js.map +1 -0
  20. package/dist/plugins/hashline-edit/index.d.ts +33 -1
  21. package/dist/plugins/hashline-edit/index.js +38 -14
  22. package/dist/plugins/hashline-edit/index.js.map +1 -1
  23. package/dist/plugins/hashline-edit/schemas.d.ts +7 -7
  24. package/dist/plugins/hashline-edit/v2.d.ts +12 -0
  25. package/dist/plugins/hashline-edit/v2.js +145 -0
  26. package/dist/plugins/hashline-edit/v2.js.map +1 -0
  27. package/dist/plugins/model-roles/index.d.ts +2 -0
  28. package/dist/plugins/model-roles/index.js +13 -2
  29. package/dist/plugins/model-roles/index.js.map +1 -1
  30. package/dist/plugins/model-roles/v2.d.ts +24 -0
  31. package/dist/plugins/model-roles/v2.js +274 -0
  32. package/dist/plugins/model-roles/v2.js.map +1 -0
  33. package/dist/plugins/peak-hours/index.d.ts +3 -0
  34. package/dist/plugins/peak-hours/index.js +15 -3
  35. package/dist/plugins/peak-hours/index.js.map +1 -1
  36. package/dist/plugins/peak-hours/v2.d.ts +12 -0
  37. package/dist/plugins/peak-hours/v2.js +99 -0
  38. package/dist/plugins/peak-hours/v2.js.map +1 -0
  39. package/dist/plugins/secrets-redaction/index.d.ts +7 -0
  40. package/dist/plugins/secrets-redaction/index.js +17 -4
  41. package/dist/plugins/secrets-redaction/index.js.map +1 -1
  42. package/dist/plugins/secrets-redaction/v2.d.ts +19 -0
  43. package/dist/plugins/secrets-redaction/v2.js +138 -0
  44. package/dist/plugins/secrets-redaction/v2.js.map +1 -0
  45. package/dist/plugins/spec-guard/index.d.ts +2 -0
  46. package/dist/plugins/spec-guard/index.js +13 -2
  47. package/dist/plugins/spec-guard/index.js.map +1 -1
  48. package/dist/plugins/spec-guard/v2.d.ts +12 -0
  49. package/dist/plugins/spec-guard/v2.js +139 -0
  50. package/dist/plugins/spec-guard/v2.js.map +1 -0
  51. package/dist/plugins/system-context-injection/agent-contexts.d.ts +5 -0
  52. package/dist/plugins/system-context-injection/agent-contexts.js +164 -0
  53. package/dist/plugins/system-context-injection/agent-contexts.js.map +1 -0
  54. package/dist/plugins/system-context-injection/index.d.ts +2 -0
  55. package/dist/plugins/system-context-injection/index.js +16 -146
  56. package/dist/plugins/system-context-injection/index.js.map +1 -1
  57. package/dist/plugins/system-context-injection/v2.d.ts +13 -0
  58. package/dist/plugins/system-context-injection/v2.js +60 -0
  59. package/dist/plugins/system-context-injection/v2.js.map +1 -0
  60. package/dist/plugins/tool-history-compaction/index.d.ts +2 -0
  61. package/dist/plugins/tool-history-compaction/index.js +13 -2
  62. package/dist/plugins/tool-history-compaction/index.js.map +1 -1
  63. package/dist/plugins/tool-history-compaction/v2.d.ts +11 -0
  64. package/dist/plugins/tool-history-compaction/v2.js +56 -0
  65. package/dist/plugins/tool-history-compaction/v2.js.map +1 -0
  66. package/dist/plugins/v2-runtime/config-watcher.d.ts +26 -0
  67. package/dist/plugins/v2-runtime/config-watcher.js +111 -0
  68. package/dist/plugins/v2-runtime/config-watcher.js.map +1 -0
  69. package/dist/plugins/v2-runtime/index.d.ts +50 -0
  70. package/dist/plugins/v2-runtime/index.js +114 -0
  71. package/dist/plugins/v2-runtime/index.js.map +1 -0
  72. package/dist/plugins/v2-runtime/location-config.d.ts +51 -0
  73. package/dist/plugins/v2-runtime/location-config.js +91 -0
  74. package/dist/plugins/v2-runtime/location-config.js.map +1 -0
  75. package/dist/plugins/v2-runtime/setup.d.ts +48 -0
  76. package/dist/plugins/v2-runtime/setup.js +174 -0
  77. package/dist/plugins/v2-runtime/setup.js.map +1 -0
  78. package/dist/plugins/web-tools/index.d.ts +2 -0
  79. package/dist/plugins/web-tools/index.js +13 -2
  80. package/dist/plugins/web-tools/index.js.map +1 -1
  81. package/dist/plugins/web-tools/v2.d.ts +11 -0
  82. package/dist/plugins/web-tools/v2.js +99 -0
  83. package/dist/plugins/web-tools/v2.js.map +1 -0
  84. package/dist/plugins/workflow/index.d.ts +2 -0
  85. package/dist/plugins/workflow/index.js +13 -2
  86. package/dist/plugins/workflow/index.js.map +1 -1
  87. package/dist/plugins/workflow/results.d.ts +16 -16
  88. package/dist/plugins/workflow/v2.d.ts +76 -0
  89. package/dist/plugins/workflow/v2.js +283 -0
  90. package/dist/plugins/workflow/v2.js.map +1 -0
  91. package/dist/tui.d.ts +1 -0
  92. package/dist/tui.js +41 -6
  93. package/dist/tui.js.map +1 -1
  94. package/package.json +13 -5
  95. package/schemas/vvoc/v3.json +1 -1
  96. package/server.js +7 -0
  97. package/templates/skills/vv-execute/references/tool-contracts.md +1 -1
  98. package/tui.js +7 -0
@@ -0,0 +1,76 @@
1
+ import type { Plugin as V2Plugin } from "@opencode/plugin";
2
+ import type { V2AdapterContext } from "../v2-runtime/setup.js";
3
+ /**
4
+ * A v1-shaped client built on v2 domains. Session lookups map onto
5
+ * ctx.session, logging degrades to console, and the repair continuation
6
+ * prompt is unsupported under the v2 prompt shape and throws so the
7
+ * bounded continuation path fails closed exactly like a failed continuation.
8
+ */
9
+ export declare function createWorkflowClientShim(adapter: V2AdapterContext): {
10
+ app: {
11
+ log: () => Promise<void>;
12
+ };
13
+ session: {
14
+ get: (input: {
15
+ path: {
16
+ id: string;
17
+ };
18
+ }) => Promise<{
19
+ data: import("@opencode/client").SessionInfo;
20
+ }>;
21
+ message: (input: {
22
+ path: {
23
+ id: string;
24
+ messageID: string;
25
+ };
26
+ }) => Promise<{
27
+ data: {
28
+ id?: string;
29
+ };
30
+ error?: undefined;
31
+ } | {
32
+ data: undefined;
33
+ error: {
34
+ name: string;
35
+ };
36
+ }>;
37
+ prompt: (_input: unknown) => Promise<never>;
38
+ };
39
+ };
40
+ /**
41
+ * Map v2 subagent launch arguments onto the v1 task shape the launch
42
+ * validation consumes: agent becomes subagent_type, the v2 resume sessionID
43
+ * becomes task_id, and background passes through. The v1 reader fields stay
44
+ * authoritative so every eligibility rule applies unchanged.
45
+ */
46
+ export declare function adaptSubagentLaunchArgs(input: unknown): unknown;
47
+ /**
48
+ * Translate one v2 server event into the v1 event shape the shared workflow
49
+ * event handler consumes, or undefined when the event carries no workflow
50
+ * meaning.
51
+ *
52
+ * Mappings (verified against the v2 event schemas):
53
+ * - session.inbox.enqueued with a user item becomes message.updated with a
54
+ * user message info, driving child-prompt freshness observation.
55
+ * - session.tool.failed and session.tool.progress become message.part.updated
56
+ * task-tool part states, driving live delegated binding taints and the
57
+ * confirmed host-terminal-error failed-attempt path; the binding lookup
58
+ * inside the handler stays fail-closed for unmatched identities.
59
+ * - session.deleted maps directly, driving store and persistence cleanup.
60
+ */
61
+ export declare function mapV2EventToV1Shape(event: unknown): {
62
+ type: string;
63
+ properties: Record<string, unknown>;
64
+ } | undefined;
65
+ /**
66
+ * Bridge the workflow surface onto the v2 runtime.
67
+ *
68
+ * The v1 factory runs once with the shimmed client; its returned hook object
69
+ * is routed onto v2 domains: tools publish with their strict JSON Schema
70
+ * inputs, before and after guards run as v2 tool hooks with the launcher
71
+ * renamed from task to subagent, and the profile guidance appends through
72
+ * the session context hook. Protocol parsing stays fail-closed: envelope
73
+ * shapes the shared parser does not recognize reject the attempt, never
74
+ * accept it.
75
+ */
76
+ export declare function setupWorkflowV2(adapter: V2AdapterContext): Promise<V2Plugin.Cleanup | void>;
@@ -0,0 +1,283 @@
1
+ // FILE: src/plugins/workflow/v2.ts
2
+ // VERSION: 1.0.0
3
+ // START_MODULE_CONTRACT
4
+ // PURPOSE: Run the complete workflow enforcement surface on the OpenCode v2 runtime by bridging the v1 plugin factory's hooks and tools onto v2 domains.
5
+ // SCOPE: v2 setup only: instantiate the v1 factory once with a shimmed client, register its five tools with their strict JSON Schema inputs through the tool transform, route execute.before and execute.after through v2 tool hooks with subagent-launch argument adaptation (v2 names the launcher subagent with agent and sessionID fields), append the profile guidance through the session context hook, and keep every fail-closed guarantee of the shared protocol unchanged.
6
+ // DEPENDS: [@opencode/plugin, src/lib/config-layers.ts, src/plugins/workflow/index.ts, src/plugins/v2-runtime/setup.ts]
7
+ // LINKS: [M-PLUGIN-WORKFLOW, V-M-PLUGIN-WORKFLOW, M-WORKFLOW-PROTOCOL, M-PLUGIN-V2-RUNTIME]
8
+ // ROLE: RUNTIME
9
+ // MAP_MODE: EXPORTS
10
+ // END_MODULE_CONTRACT
11
+ //
12
+ // START_MODULE_MAP
13
+ // setupWorkflowV2 - Bridge the full workflow surface onto one OpenCode v2 plugin context.
14
+ // createWorkflowClientShim - v1-shaped client over v2 domains for the workflow authorization and repair surfaces.
15
+ // adaptSubagentLaunchArgs - Map v2 subagent tool arguments onto the v1 task launch shape.
16
+ // mapV2EventToV1Shape - Translate v2 server events into the v1 event shapes the shared handler consumes.
17
+ // END_MODULE_MAP
18
+ //
19
+ // START_CHANGE_SUMMARY
20
+ // LAST_CHANGE: [C-OPENCODE-V2-MIGRATION T-005 - Bridged the workflow enforcement surface onto v2 tool, session, and event domains.]
21
+ // END_CHANGE_SUMMARY
22
+ import { WorkflowPlugin } from "./index.js";
23
+ // START_BLOCK_CREATE_WORKFLOW_CLIENT_SHIM
24
+ /**
25
+ * A v1-shaped client built on v2 domains. Session lookups map onto
26
+ * ctx.session, logging degrades to console, and the repair continuation
27
+ * prompt is unsupported under the v2 prompt shape and throws so the
28
+ * bounded continuation path fails closed exactly like a failed continuation.
29
+ */
30
+ export function createWorkflowClientShim(adapter) {
31
+ return {
32
+ app: {
33
+ log: async () => { },
34
+ },
35
+ session: {
36
+ get: async (input) => {
37
+ const data = await adapter.ctx.session.get({ sessionID: input.path.id });
38
+ return { data };
39
+ },
40
+ message: async (input) => {
41
+ try {
42
+ const messages = await adapter.ctx.session.context({ sessionID: input.path.id });
43
+ const hit = messages.find((message) => message.id === input.path.messageID);
44
+ return hit ? { data: hit } : { data: undefined, error: { name: "NotFound" } };
45
+ }
46
+ catch {
47
+ return { data: undefined, error: { name: "NotFound" } };
48
+ }
49
+ },
50
+ prompt: async (_input) => {
51
+ throw new Error("workflow continuation prompt is not available on the v2 runtime");
52
+ },
53
+ },
54
+ };
55
+ }
56
+ // END_BLOCK_CREATE_WORKFLOW_CLIENT_SHIM
57
+ // START_BLOCK_ADAPT_SUBAGENT_LAUNCH_ARGS
58
+ /**
59
+ * Map v2 subagent launch arguments onto the v1 task shape the launch
60
+ * validation consumes: agent becomes subagent_type, the v2 resume sessionID
61
+ * becomes task_id, and background passes through. The v1 reader fields stay
62
+ * authoritative so every eligibility rule applies unchanged.
63
+ */
64
+ export function adaptSubagentLaunchArgs(input) {
65
+ if (!input || typeof input !== "object")
66
+ return input;
67
+ const record = input;
68
+ return {
69
+ ...record,
70
+ ...(typeof record.agent === "string" ? { subagent_type: record.agent } : {}),
71
+ ...(typeof record.sessionID === "string" ? { task_id: record.sessionID } : {}),
72
+ };
73
+ }
74
+ // END_BLOCK_ADAPT_SUBAGENT_LAUNCH_ARGS
75
+ // START_BLOCK_MAP_V2_EVENT_TO_V1_SHAPES
76
+ /**
77
+ * Translate one v2 server event into the v1 event shape the shared workflow
78
+ * event handler consumes, or undefined when the event carries no workflow
79
+ * meaning.
80
+ *
81
+ * Mappings (verified against the v2 event schemas):
82
+ * - session.inbox.enqueued with a user item becomes message.updated with a
83
+ * user message info, driving child-prompt freshness observation.
84
+ * - session.tool.failed and session.tool.progress become message.part.updated
85
+ * task-tool part states, driving live delegated binding taints and the
86
+ * confirmed host-terminal-error failed-attempt path; the binding lookup
87
+ * inside the handler stays fail-closed for unmatched identities.
88
+ * - session.deleted maps directly, driving store and persistence cleanup.
89
+ */
90
+ export function mapV2EventToV1Shape(event) {
91
+ const typed = event;
92
+ const data = typed?.data ?? {};
93
+ switch (typed?.type) {
94
+ case "session.inbox.enqueued": {
95
+ const item = data.item;
96
+ if (item?.type === "user" &&
97
+ typeof item.sessionID === "string" &&
98
+ typeof item.id === "string") {
99
+ return {
100
+ type: "message.updated",
101
+ properties: { info: { role: "user", sessionID: item.sessionID, id: item.id } },
102
+ };
103
+ }
104
+ return undefined;
105
+ }
106
+ case "session.tool.failed":
107
+ case "session.tool.progress": {
108
+ const sessionID = typeof data.sessionID === "string" ? data.sessionID : undefined;
109
+ const callID = typeof data.id === "string" ? data.id : undefined;
110
+ if (!sessionID || !callID)
111
+ return undefined;
112
+ const isError = typed.type === "session.tool.failed";
113
+ const metadata = data.metadata && typeof data.metadata === "object"
114
+ ? data.metadata
115
+ : undefined;
116
+ const rawError = data.error;
117
+ const errorText = typeof rawError === "string"
118
+ ? rawError
119
+ : rawError && typeof rawError.message === "string"
120
+ ? rawError.message
121
+ : undefined;
122
+ return {
123
+ type: "message.part.updated",
124
+ properties: {
125
+ part: {
126
+ type: "tool",
127
+ tool: "task",
128
+ sessionID,
129
+ callID,
130
+ state: {
131
+ status: isError ? "error" : "running",
132
+ ...(errorText !== undefined ? { error: errorText } : {}),
133
+ ...(metadata ? { metadata } : {}),
134
+ },
135
+ },
136
+ },
137
+ };
138
+ }
139
+ case "session.deleted": {
140
+ if (typeof data.sessionID !== "string")
141
+ return undefined;
142
+ return { type: "session.deleted", properties: { sessionID: data.sessionID } };
143
+ }
144
+ default:
145
+ return undefined;
146
+ }
147
+ }
148
+ // END_BLOCK_MAP_V2_EVENT_TO_V1_SHAPES
149
+ // START_BLOCK_SETUP_WORKFLOW_V2
150
+ /**
151
+ * Bridge the workflow surface onto the v2 runtime.
152
+ *
153
+ * The v1 factory runs once with the shimmed client; its returned hook object
154
+ * is routed onto v2 domains: tools publish with their strict JSON Schema
155
+ * inputs, before and after guards run as v2 tool hooks with the launcher
156
+ * renamed from task to subagent, and the profile guidance appends through
157
+ * the session context hook. Protocol parsing stays fail-closed: envelope
158
+ * shapes the shared parser does not recognize reject the attempt, never
159
+ * accept it.
160
+ */
161
+ export async function setupWorkflowV2(adapter) {
162
+ const directory = adapter.ctx.location.directory;
163
+ const hooks = (await WorkflowPlugin({
164
+ client: createWorkflowClientShim(adapter),
165
+ project: { id: directory, directory },
166
+ directory,
167
+ worktree: directory,
168
+ experimental_workspace: { register: () => { } },
169
+ serverUrl: new URL("http://127.0.0.1:1"),
170
+ $: {},
171
+ }));
172
+ if (!hooks)
173
+ return undefined;
174
+ const cleanups = [];
175
+ // Tools: publish each v1 tool entry with its contract JSON Schema input.
176
+ const toolEntries = (hooks.tool ?? {});
177
+ const { workflowToolContracts } = await import("./input-validation.js");
178
+ const toolRegistration = await adapter.ctx.tool.transform((editor) => {
179
+ for (const [name, entry] of Object.entries(toolEntries)) {
180
+ const contract = workflowToolContracts.find((item) => item.toolId === name);
181
+ editor.add({
182
+ name,
183
+ description: entry.description,
184
+ input: (contract?.inputJsonSchema ?? { type: "object" }),
185
+ execute: (async (input, context) => {
186
+ const result = await entry.execute(input, {
187
+ sessionID: context.sessionID,
188
+ agent: context.agent,
189
+ abort: context.signal,
190
+ });
191
+ return { content: typeof result === "string" ? result : JSON.stringify(result) };
192
+ }),
193
+ });
194
+ }
195
+ });
196
+ cleanups.push(() => toolRegistration.dispose());
197
+ // Owned validation plus task-launch tracking on execute.before.
198
+ const beforeHook = await adapter.ctx.tool.hook("execute.before", (event) => {
199
+ const tool = String(event.tool) === "subagent" ? "task" : String(event.tool);
200
+ const args = String(event.tool) === "subagent" ? adaptSubagentLaunchArgs(event.input) : event.input;
201
+ const before = hooks["tool.execute.before"];
202
+ if (!before)
203
+ return;
204
+ return before({ tool, sessionID: event.sessionID, callID: event.id, agent: event.agent }, { args });
205
+ });
206
+ cleanups.push(() => beforeHook.dispose());
207
+ // Delegated result tracking on execute.after.
208
+ const afterHook = await adapter.ctx.tool.hook("execute.after", (event) => {
209
+ if (event.status !== "completed")
210
+ return;
211
+ const tool = String(event.tool) === "subagent" ? "task" : String(event.tool);
212
+ const args = String(event.tool) === "subagent" ? adaptSubagentLaunchArgs(event.input) : event.input;
213
+ const result = event.result;
214
+ const output = typeof result.content === "string"
215
+ ? result.content
216
+ : Array.isArray(result.content)
217
+ ? result.content.map((part) => part.text ?? "").join("\n")
218
+ : "";
219
+ const after = hooks["tool.execute.after"];
220
+ if (!after)
221
+ return;
222
+ return after({ tool, sessionID: event.sessionID, callID: event.id, agent: event.agent, args }, { output, metadata: {} });
223
+ });
224
+ cleanups.push(() => afterHook.dispose());
225
+ // Profile guidance through the session context hook.
226
+ const chatMessage = hooks["chat.message"];
227
+ if (chatMessage) {
228
+ const contextHook = await adapter.ctx.session.hook("context", (event) => {
229
+ const message = {
230
+ agent: event.agent,
231
+ system: event.system
232
+ .filter((part) => part.type === "text")
233
+ .map((part) => part.text)
234
+ .join("\n\n"),
235
+ };
236
+ const before = message.system;
237
+ const result = chatMessage({}, { message });
238
+ if (result instanceof Promise) {
239
+ return result.then(() => {
240
+ if (typeof message.system === "string" && message.system !== before) {
241
+ event.system.length = 0;
242
+ event.system.push({ type: "text", text: message.system });
243
+ }
244
+ });
245
+ }
246
+ return undefined;
247
+ });
248
+ cleanups.push(() => contextHook.dispose());
249
+ }
250
+ // Event bridge: route the v2 server events the shared handler consumes.
251
+ const eventHandler = hooks.event;
252
+ if (eventHandler) {
253
+ const controller = new AbortController();
254
+ void (async () => {
255
+ try {
256
+ for await (const evt of adapter.ctx.event.subscribe({ signal: controller.signal })) {
257
+ const located = evt;
258
+ if (located.location?.directory && located.location.directory !== directory)
259
+ continue;
260
+ const shaped = mapV2EventToV1Shape(evt);
261
+ if (!shaped)
262
+ continue;
263
+ try {
264
+ await eventHandler({ event: shaped });
265
+ }
266
+ catch (error) {
267
+ console.warn(`[vvoc][workflow] bridged event failed: ${String(error)}`);
268
+ }
269
+ }
270
+ }
271
+ catch {
272
+ // Stream failures never break the host.
273
+ }
274
+ })();
275
+ cleanups.push(async () => controller.abort());
276
+ }
277
+ return async () => {
278
+ for (const dispose of cleanups.reverse())
279
+ await dispose();
280
+ };
281
+ }
282
+ // END_BLOCK_SETUP_WORKFLOW_V2
283
+ //# sourceMappingURL=v2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2.js","sourceRoot":"","sources":["../../../src/plugins/workflow/v2.ts"],"names":[],"mappings":"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"}
package/dist/tui.d.ts CHANGED
@@ -3,5 +3,6 @@ import { ContextTuiPlugin } from "./tui/context/plugin.js";
3
3
  export { ContextTuiPlugin };
4
4
  declare const plugin: TuiPluginModule & {
5
5
  id: string;
6
+ setup?: (context: unknown) => Promise<void> | void;
6
7
  };
7
8
  export default plugin;
package/dist/tui.js CHANGED
@@ -1,21 +1,21 @@
1
1
  // FILE: src/tui.tsx
2
- // VERSION: 1.2.0
2
+ // VERSION: 2.0.0
3
3
  // START_MODULE_CONTRACT
4
- // PURPOSE: Publish the default @osovv/vv-opencode/tui module containing the managed context inspector, analytics indicator, branding footer, and peak-hours banner.
5
- // SCOPE: Stable TUI package entrypoint and module identity only.
6
- // DEPENDS: [@opencode-ai/plugin/tui, @opencode-ai/plugin, src/tui/context/plugin.ts, src/tui/analytics/indicator.tsx, src/tui/branding/footer.tsx, src/tui/peak-hours/banner.tsx]
4
+ // PURPOSE: Publish the dual-runtime TUI entrypoint: the full v1 context inspector, analytics indicator, branding footer, and peak-hours banner through tui(), and the v2 CLI plugin registration for /context through setup().
5
+ // SCOPE: Stable TUI package entrypoint and dual runtime identity only; feature registration stays in the focused modules.
6
+ // DEPENDS: [@opencode-ai/plugin/tui, @opencode/plugin/tui, src/tui/context/plugin.ts, src/tui/analytics/indicator.tsx, src/tui/branding/footer.tsx, src/tui/peak-hours/banner.tsx]
7
7
  // LINKS: [M-PLUGIN-CONTEXT-TUI, M-TUI-ANALYTICS-INDICATOR, M-TUI-BRANDING-FOOTER, M-TUI-PEAK-HOURS-BANNER, V-M-PLUGIN-CONTEXT-TUI]
8
8
  // ROLE: BARREL
9
9
  // MAP_MODE: SUMMARY
10
10
  // END_MODULE_CONTRACT
11
11
  //
12
12
  // START_MODULE_MAP
13
- // default - OpenCode TUI plugin module registering /context, the analytics indicator, the branding footer, and the peak-hours banner.
13
+ // default - Dual TUI entrypoint: v2 setup() registers the /context command, v1 tui() registers the full inspector, indicator, footer, and banner.
14
14
  // ContextTuiPlugin - Named TUI plugin factory for direct consumers and tests.
15
15
  // END_MODULE_MAP
16
16
  //
17
17
  // START_CHANGE_SUMMARY
18
- // LAST_CHANGE: [C-PLUGIN-PEAK-HOURS - Registered the app_bottom peak-hours banner alongside the indicator and footer.]
18
+ // LAST_CHANGE: [C-OPENCODE-V2-MIGRATION T-007 - Added the v2 CLI plugin setup registering /context beside the unchanged v1 TUI module.]
19
19
  // END_CHANGE_SUMMARY
20
20
  import { ContextTuiPlugin } from "./tui/context/plugin.js";
21
21
  import { registerAnalyticsIndicator } from "./tui/analytics/indicator.js";
@@ -46,6 +46,41 @@ const plugin = {
46
46
  // Fail-soft: banner unavailable for this session.
47
47
  }
48
48
  },
49
+ // START_BLOCK_V2_TUI_SETUP
50
+ // OpenCode v2 loads the same entrypoint through setup() with the CLI plugin
51
+ // context. The v2 surface registers the /context slash command; the full
52
+ // inspector components port onto the v2 dialog and router surfaces in a
53
+ // follow-up release and this command keeps the entry point honest.
54
+ async setup(context) {
55
+ const ctx = context;
56
+ try {
57
+ ctx.keymap.layer(() => ({
58
+ mode: "global",
59
+ commands: [
60
+ {
61
+ id: "vvoc.context",
62
+ title: "vvoc context inspector",
63
+ slash: { name: "context" },
64
+ palette: true,
65
+ run: async () => {
66
+ const directory = ctx.data?.location?.default?.()?.directory ?? "unknown location";
67
+ await ctx.ui.dialog.alert({
68
+ title: "vvoc /context",
69
+ message: `OpenCode v2 runtime (host ${ctx.app?.version ?? "unknown"}).\n` +
70
+ `Location: ${directory}\n` +
71
+ "The full v2 context inspector ships in the next vvoc release; " +
72
+ "server-side analytics, model roles, and guidance stay active.",
73
+ });
74
+ },
75
+ },
76
+ ],
77
+ }));
78
+ }
79
+ catch {
80
+ // Fail-soft: the v2 TUI host may not expose keymap layers yet.
81
+ }
82
+ },
83
+ // END_BLOCK_V2_TUI_SETUP
49
84
  };
50
85
  // END_BLOCK_TUI_MODULE
51
86
  export default plugin;
package/dist/tui.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tui.js","sourceRoot":"","sources":["../src/tui.tsx"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,iBAAiB;AACjB,wBAAwB;AACxB,sKAAsK;AACtK,mEAAmE;AACnE,oLAAoL;AACpL,qIAAqI;AACrI,iBAAiB;AACjB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,wIAAwI;AACxI,gFAAgF;AAChF,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,yHAAyH;AACzH,qBAAqB;AAGrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAErE,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAE5B,yBAAyB;AACzB,MAAM,MAAM,GAAqC;IAC/C,EAAE,EAAE,cAAc;IAClB,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAChC,MAAM,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,0BAA0B,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;QACD,IAAI,CAAC;YACH,sBAAsB,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;QACD,IAAI,CAAC;YACH,MAAM,uBAAuB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;IACH,CAAC;CACF,CAAC;AACF,uBAAuB;AAEvB,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"tui.js","sourceRoot":"","sources":["../src/tui.tsx"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,iBAAiB;AACjB,wBAAwB;AACxB,iOAAiO;AACjO,4HAA4H;AAC5H,qLAAqL;AACrL,qIAAqI;AACrI,iBAAiB;AACjB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,oJAAoJ;AACpJ,gFAAgF;AAChF,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,0IAA0I;AAC1I,qBAAqB;AAGrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAErE,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAE5B,yBAAyB;AACzB,MAAM,MAAM,GACV;IACE,EAAE,EAAE,cAAc;IAClB,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAChC,MAAM,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,0BAA0B,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;QACD,IAAI,CAAC;YACH,sBAAsB,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;QACD,IAAI,CAAC;YACH,MAAM,uBAAuB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;IACH,CAAC;IACD,2BAA2B;IAC3B,4EAA4E;IAC5E,yEAAyE;IACzE,wEAAwE;IACxE,mEAAmE;IACnE,KAAK,CAAC,KAAK,CAAC,OAAO;QACjB,MAAM,GAAG,GAAG,OAaX,CAAC;QACF,IAAI,CAAC;YACH,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;gBACtB,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE;oBACR;wBACE,EAAE,EAAE,cAAc;wBAClB,KAAK,EAAE,wBAAwB;wBAC/B,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;wBAC1B,OAAO,EAAE,IAAI;wBACb,GAAG,EAAE,KAAK,IAAI,EAAE;4BACd,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,IAAI,kBAAkB,CAAC;4BACnF,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC;gCACxB,KAAK,EAAE,eAAe;gCACtB,OAAO,EACL,6BAA6B,GAAG,CAAC,GAAG,EAAE,OAAO,IAAI,SAAS,MAAM;oCAChE,aAAa,SAAS,IAAI;oCAC1B,gEAAgE;oCAChE,+DAA+D;6BAClE,CAAC,CAAC;wBACL,CAAC;qBACF;iBACF;aACF,CAAC,CAAC,CAAC;QACN,CAAC;QAAC,MAAM,CAAC;YACP,+DAA+D;QACjE,CAAC;IACH,CAAC;IACD,yBAAyB;CAC1B,CAAC;AACJ,uBAAuB;AAEvB,eAAe,MAAM,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osovv/vv-opencode",
3
- "version": "1.7.0",
3
+ "version": "2.0.1",
4
4
  "description": "An opinionated agentic development layer for OpenCode — spec-first when it matters, review-driven execution, portable model roles, safer tools, and long-run safety.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -34,6 +34,8 @@
34
34
  "dist",
35
35
  "schemas",
36
36
  "templates",
37
+ "server.js",
38
+ "tui.js",
37
39
  "README.md",
38
40
  "CHANGELOG.md"
39
41
  ],
@@ -42,6 +44,10 @@
42
44
  "types": "./dist/index.d.ts",
43
45
  "import": "./dist/index.js"
44
46
  },
47
+ "./server": {
48
+ "types": "./dist/index.d.ts",
49
+ "import": "./dist/index.js"
50
+ },
45
51
  "./tui": {
46
52
  "types": "./dist/tui.d.ts",
47
53
  "import": "./dist/tui.js"
@@ -104,16 +110,18 @@
104
110
  "contracts:host": "bun scripts/check-tool-contracts-host.ts",
105
111
  "test": "bun test",
106
112
  "check": "bun run typecheck && bun run lint && bun run fmt:check && bun run grace:check && bun run contracts:check && bun test",
107
- "pack:check": "bun run build && bun -e \"const root = await import('./dist/index.js'); if (!('GuardianPlugin' in root)) throw new Error('dist root export missing GuardianPlugin'); if (!('HashlineEditPlugin' in root)) throw new Error('dist root export missing HashlineEditPlugin'); if (!('ModelRolesPlugin' in root)) throw new Error('dist root export missing ModelRolesPlugin'); if (!('SystemContextInjectionPlugin' in root)) throw new Error('dist root export missing SystemContextInjectionPlugin'); if (!('WorkflowPlugin' in root)) throw new Error('dist root export missing WorkflowPlugin'); if (!('SecretsRedactionPlugin' in root)) throw new Error('dist root export missing SecretsRedactionPlugin'); if (!('WebToolsPlugin' in root)) throw new Error('dist root export missing WebToolsPlugin'); if (!('AnalyticsPlugin' in root)) throw new Error('dist root export missing AnalyticsPlugin'); if (!('PeakHoursPlugin' in root)) throw new Error('dist root export missing PeakHoursPlugin'); if (!('SpecGuardPlugin' in root)) throw new Error('dist root export missing SpecGuardPlugin'); const tui = await import('./dist/tui.js'); if (!tui.default || typeof tui.default.tui !== 'function') throw new Error('dist TUI export missing default tui module'); await import('./dist/plugins/guardian/index.js'); await import('./dist/plugins/hashline-edit/index.js'); await import('./dist/plugins/model-roles/index.js'); await import('./dist/plugins/system-context-injection/index.js'); await import('./dist/plugins/workflow/index.js'); await import('./dist/plugins/secrets-redaction/index.js'); await import('./dist/plugins/web-tools/index.js'); await import('./dist/plugins/analytics/index.js'); await import('./dist/plugins/peak-hours/index.js'); await import('./dist/plugins/spec-guard/index.js')\" && bun scripts/check-tool-contracts.ts --packed",
113
+ "pack:check": "bun run build && bun -e \"const root = await import('./dist/index.js'); const d = root.default; if (!d || d.id !== 'vvoc' || typeof d.setup !== 'function' || typeof d.server !== 'function') throw new Error('dist root export missing dual default entrypoint (id/setup/server)'); const pluginIds = ['vvoc.guardian','vvoc.hashline-edit','vvoc.model-roles','vvoc.system-context-injection','vvoc.workflow','vvoc.secrets-redaction','vvoc.web-tools','vvoc.tool-history-compaction','vvoc.analytics','vvoc.peak-hours','vvoc.spec-guard']; const subpaths = ['guardian','hashline-edit','model-roles','system-context-injection','workflow','secrets-redaction','web-tools','tool-history-compaction','analytics','peak-hours','spec-guard']; for (const s of subpaths) { const m = await import('./dist/plugins/' + s + '/index.js'); const e = m.default; if (!e || typeof e.id !== 'string' || typeof e.setup !== 'function' || typeof e.server !== 'function') throw new Error('dist subpath ' + s + ' missing dual default entrypoint'); if (!pluginIds.includes(e.id)) throw new Error('dist subpath ' + s + ' has unexpected id ' + e.id); } const tui = await import('./dist/tui.js'); if (!tui.default || typeof tui.default.tui !== 'function') throw new Error('dist TUI export missing default tui module')\" && bun scripts/check-tool-contracts.ts --packed",
108
114
  "tui:local": "bun scripts/tui-local.ts",
115
+ "e2e:v2": "bun scripts/e2e-v2.ts",
109
116
  "release:check": "bun scripts/release-check.ts",
110
117
  "release:bump": "bun scripts/release-bump.ts",
111
118
  "prepare": "lefthook install --force"
112
119
  },
113
120
  "dependencies": {
114
121
  "@clack/prompts": "^1.2.0",
115
- "@opencode-ai/plugin": "1.18.2",
116
- "@opencode-ai/sdk": "1.18.2",
122
+ "@opencode-ai/plugin": "1.18.32",
123
+ "@opencode-ai/sdk": "1.18.32",
124
+ "@opencode/plugin": "2.0.18",
117
125
  "ajv": "^8.17.1",
118
126
  "citty": "0.2.2",
119
127
  "htmlparser2": "^12.0.0",
@@ -144,7 +152,7 @@
144
152
  },
145
153
  "engines": {
146
154
  "bun": ">=1.3.8",
147
- "opencode": ">=1.18.2"
155
+ "opencode": ">=1.18.29"
148
156
  },
149
157
  "packageManager": "bun@1.3.8",
150
158
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://cdn.jsdelivr.net/npm/@osovv/vv-opencode@1.7.0/schemas/vvoc/v3.json",
3
+ "$id": "https://cdn.jsdelivr.net/npm/@osovv/vv-opencode@2.0.1/schemas/vvoc/v3.json",
4
4
  "title": "vvoc config",
5
5
  "description": "Canonical vvoc configuration document.",
6
6
  "type": "object",
package/server.js ADDED
@@ -0,0 +1,7 @@
1
+ // FILE: server.js
2
+ // VERSION: 1.0.0
3
+ // OpenCode v2 resolves directory-scoped plugin targets through a literal
4
+ // `server` module next to the package manifest before consulting the exports
5
+ // map. This shim re-exports the dual-runtime default entrypoint so both the
6
+ // file-path and npm-specifier loading styles reach the same plugin.
7
+ export { default } from "./dist/index.js";
@@ -2,7 +2,7 @@
2
2
 
3
3
  Generated from the pure tool catalog. Do not edit by hand; run `bun run contracts:generate`.
4
4
 
5
- - Package: `@osovv/vv-opencode@1.7.0`
5
+ - Package: `@osovv/vv-opencode@2.0.1`
6
6
  - Tool contract revision: `1`
7
7
  - Reference path: `templates/skills/vv-execute/references/tool-contracts.md`
8
8
  - Current model-facing size: descriptions 8794 bytes, published input schemas 22572 bytes
package/tui.js ADDED
@@ -0,0 +1,7 @@
1
+ // FILE: tui.js
2
+ // VERSION: 1.0.0
3
+ // OpenCode v2 resolves the CLI/TUI plugin entrypoint of directory-scoped
4
+ // plugin targets through a literal `tui` module next to the package manifest.
5
+ // This shim re-exports the dual-runtime default TUI entrypoint so the
6
+ // file-path and npm-specifier loading styles stay equivalent.
7
+ export { default } from "./dist/tui.js";