@opencode/plugin 0.0.0-reserved → 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 (116) hide show
  1. package/dist/app.d.ts +5 -0
  2. package/dist/app.js +0 -0
  3. package/dist/effect/agent.d.ts +15 -0
  4. package/dist/effect/agent.js +0 -0
  5. package/dist/effect/aisdk.d.ts +20 -0
  6. package/dist/effect/aisdk.js +0 -0
  7. package/dist/effect/catalog.d.ts +33 -0
  8. package/dist/effect/catalog.js +2 -0
  9. package/dist/effect/command.d.ts +23 -0
  10. package/dist/effect/command.js +0 -0
  11. package/dist/effect/event.d.ts +3 -0
  12. package/dist/effect/event.js +0 -0
  13. package/dist/effect/index.d.ts +18 -0
  14. package/dist/effect/index.js +17 -0
  15. package/dist/effect/integration.d.ts +80 -0
  16. package/dist/effect/integration.js +2 -0
  17. package/dist/effect/mcp.d.ts +15 -0
  18. package/dist/effect/mcp.js +0 -0
  19. package/dist/effect/permission.d.ts +21 -0
  20. package/dist/effect/permission.js +0 -0
  21. package/dist/effect/plugin.d.ts +56 -0
  22. package/dist/effect/plugin.js +3 -0
  23. package/dist/effect/reference.d.ts +14 -0
  24. package/dist/effect/reference.js +0 -0
  25. package/dist/effect/registration.d.ts +13 -0
  26. package/dist/effect/registration.js +0 -0
  27. package/dist/effect/rpc.d.ts +19 -0
  28. package/dist/effect/rpc.js +0 -0
  29. package/dist/effect/session.d.ts +107 -0
  30. package/dist/effect/session.js +0 -0
  31. package/dist/effect/shell.d.ts +14 -0
  32. package/dist/effect/shell.js +0 -0
  33. package/dist/effect/skill.d.ts +15 -0
  34. package/dist/effect/skill.js +1 -0
  35. package/dist/effect/storage.d.ts +8 -0
  36. package/dist/effect/storage.js +0 -0
  37. package/dist/effect/tool.d.ts +52 -0
  38. package/dist/effect/tool.js +1 -0
  39. package/dist/effect/vcs.d.ts +41 -0
  40. package/dist/effect/vcs.js +0 -0
  41. package/dist/effect/websearch.d.ts +20 -0
  42. package/dist/effect/websearch.js +0 -0
  43. package/dist/effect/worktree.d.ts +18 -0
  44. package/dist/effect/worktree.js +0 -0
  45. package/dist/host.d.ts +12 -0
  46. package/dist/host.js +33 -0
  47. package/dist/options.d.ts +1 -0
  48. package/dist/options.js +0 -0
  49. package/dist/promise/adapter.d.ts +12 -0
  50. package/dist/promise/adapter.js +444 -0
  51. package/dist/promise/agent.d.ts +15 -0
  52. package/dist/promise/agent.js +0 -0
  53. package/dist/promise/aisdk.d.ts +20 -0
  54. package/dist/promise/aisdk.js +0 -0
  55. package/dist/promise/catalog.d.ts +33 -0
  56. package/dist/promise/catalog.js +0 -0
  57. package/dist/promise/command.d.ts +22 -0
  58. package/dist/promise/command.js +0 -0
  59. package/dist/promise/event.d.ts +3 -0
  60. package/dist/promise/event.js +0 -0
  61. package/dist/promise/index.d.ts +19 -0
  62. package/dist/promise/index.js +17 -0
  63. package/dist/promise/integration.d.ts +79 -0
  64. package/dist/promise/integration.js +2 -0
  65. package/dist/promise/mcp.d.ts +15 -0
  66. package/dist/promise/mcp.js +0 -0
  67. package/dist/promise/permission.d.ts +21 -0
  68. package/dist/promise/permission.js +0 -0
  69. package/dist/promise/plugin.d.ts +57 -0
  70. package/dist/promise/plugin.js +3 -0
  71. package/dist/promise/reference.d.ts +13 -0
  72. package/dist/promise/reference.js +0 -0
  73. package/dist/promise/registration.d.ts +12 -0
  74. package/dist/promise/registration.js +0 -0
  75. package/dist/promise/rpc.d.ts +22 -0
  76. package/dist/promise/rpc.js +0 -0
  77. package/dist/promise/session.d.ts +107 -0
  78. package/dist/promise/session.js +0 -0
  79. package/dist/promise/shell.d.ts +14 -0
  80. package/dist/promise/shell.js +0 -0
  81. package/dist/promise/skill.d.ts +15 -0
  82. package/dist/promise/skill.js +0 -0
  83. package/dist/promise/storage.d.ts +8 -0
  84. package/dist/promise/storage.js +0 -0
  85. package/dist/promise/tool.d.ts +56 -0
  86. package/dist/promise/tool.js +2 -0
  87. package/dist/promise/types.d.ts +3 -0
  88. package/dist/promise/types.js +0 -0
  89. package/dist/promise/vcs.d.ts +50 -0
  90. package/dist/promise/vcs.js +0 -0
  91. package/dist/promise/websearch.d.ts +21 -0
  92. package/dist/promise/websearch.js +0 -0
  93. package/dist/promise/worktree.d.ts +23 -0
  94. package/dist/promise/worktree.js +0 -0
  95. package/dist/rpc.d.ts +1 -0
  96. package/dist/rpc.js +1 -0
  97. package/dist/source.bun.d.ts +4 -0
  98. package/dist/source.bun.js +62 -0
  99. package/dist/source.d.ts +8 -0
  100. package/dist/source.js +59 -0
  101. package/dist/source.node.d.ts +5 -0
  102. package/dist/source.node.js +45 -0
  103. package/dist/storage.d.ts +14 -0
  104. package/dist/storage.js +0 -0
  105. package/dist/tui/context.d.ts +458 -0
  106. package/dist/tui/context.js +0 -0
  107. package/dist/tui/index.d.ts +2 -0
  108. package/dist/tui/index.js +2 -0
  109. package/dist/tui/plugin.d.ts +8 -0
  110. package/dist/tui/plugin.js +3 -0
  111. package/dist/tui/solid.d.ts +7 -0
  112. package/dist/tui/solid.js +16 -0
  113. package/dist/worktree.d.ts +18 -0
  114. package/dist/worktree.js +0 -0
  115. package/package.json +83 -11
  116. package/README.md +0 -5
@@ -0,0 +1,458 @@
1
+ import type { AgentInfo, CommandInfo, FormCancelInput, FormInfo, FormReplyInput, IntegrationInfo, LocationRef, McpResource, McpServer, ModelInfo, OpenCodeClient, OpenCodeEvent, PermissionSavedInfo, PermissionRequest, Project, ProviderInfo, ReferenceInfo, SessionInfo, SessionMessageInfo, SessionInboxInfo, ShellInfo, SkillInfo, VcsInfo } from "@opencode/client";
2
+ import type { ResolvedTheme } from "@opencode/theme/tui";
3
+ import type { CliRenderer, KeyEvent, MarkdownCodeBlockRenderer, Renderable } from "@opentui/core";
4
+ import type { JSX } from "@opentui/solid";
5
+ import type { Store } from "solid-js/store";
6
+ export interface Storage {
7
+ /**
8
+ * Durable JSON state: persisted to disk, survives hot reloads and TUI
9
+ * restarts, and stays live-synced across running TUI instances.
10
+ */
11
+ store<Value extends object>(key: string, options: {
12
+ readonly initial: Value;
13
+ }): readonly [Store<Value>, (mutation: (draft: Value) => void) => Promise<void>];
14
+ /**
15
+ * Ephemeral in-memory state: survives plugin hot reloads (old and new
16
+ * generations share the same live store) and is gone when the TUI exits.
17
+ * Updates are synchronous and values need not be JSON-serializable.
18
+ */
19
+ memory<Value extends object>(key: string, options: {
20
+ readonly initial: Value;
21
+ }): readonly [Store<Value>, (mutation: (draft: Value) => void) => void];
22
+ }
23
+ interface LocationCollection<Value> {
24
+ list(location?: LocationRef): Value[] | undefined;
25
+ sync(location?: LocationRef): Promise<void>;
26
+ invalidate(location?: LocationRef): void;
27
+ }
28
+ type OpenCodeEventMap = {
29
+ [Type in OpenCodeEvent["type"]]: Extract<OpenCodeEvent, {
30
+ type: Type;
31
+ }>;
32
+ };
33
+ export interface Data {
34
+ readonly on: <Type extends OpenCodeEvent["type"]>(type: Type, handler: (event: OpenCodeEventMap[Type]) => void) => () => void;
35
+ readonly listen: (handler: (event: {
36
+ details: OpenCodeEvent;
37
+ }) => void) => () => void;
38
+ readonly session: {
39
+ list(): SessionInfo[];
40
+ get(sessionID: string): SessionInfo | undefined;
41
+ root(sessionID: string): string;
42
+ family(sessionID: string): string[];
43
+ cost(sessionID: string): number;
44
+ status(sessionID: string): "idle" | "running";
45
+ readonly pending: {
46
+ list(sessionID: string): SessionInboxInfo[];
47
+ sync(sessionID: string): Promise<void>;
48
+ invalidate(sessionID: string): void;
49
+ };
50
+ sync(sessionID: string): Promise<void>;
51
+ invalidate(sessionID: string): void;
52
+ readonly message: {
53
+ list(sessionID: string): SessionMessageInfo[];
54
+ get(sessionID: string, messageID: string): SessionMessageInfo | undefined;
55
+ sync(sessionID: string): Promise<void>;
56
+ invalidate(sessionID: string): void;
57
+ };
58
+ readonly permission: {
59
+ list(sessionID: string): PermissionRequest[] | undefined;
60
+ sync(sessionID: string): Promise<void>;
61
+ invalidate(sessionID: string): void;
62
+ };
63
+ readonly form: {
64
+ list(sessionID: string, location?: LocationRef): Array<FormInfo & {
65
+ readonly location?: LocationRef;
66
+ }> | undefined;
67
+ sync(sessionID: string, location?: LocationRef): Promise<void>;
68
+ invalidate(sessionID: string, location?: LocationRef): void;
69
+ reply(input: FormReplyInput, location?: LocationRef): Promise<void>;
70
+ cancel(input: FormCancelInput, location?: LocationRef): Promise<void>;
71
+ };
72
+ };
73
+ readonly project: {
74
+ list(): Project[];
75
+ get(projectID: string): Project | undefined;
76
+ sync(): Promise<void>;
77
+ invalidate(): void;
78
+ readonly permission: {
79
+ list(projectID: string): PermissionSavedInfo[] | undefined;
80
+ sync(projectID: string): Promise<void>;
81
+ invalidate(projectID: string): void;
82
+ };
83
+ };
84
+ readonly shell: {
85
+ list(location?: LocationRef): ShellInfo[];
86
+ get(id: string): ShellInfo | undefined;
87
+ sync(location?: LocationRef): Promise<void>;
88
+ invalidate(location?: LocationRef): void;
89
+ };
90
+ readonly location: {
91
+ default(): LocationRef;
92
+ sync(location?: LocationRef): Promise<void>;
93
+ invalidate(location?: LocationRef): void;
94
+ readonly vcs: {
95
+ info(location?: LocationRef): VcsInfo | undefined;
96
+ sync(location?: LocationRef): Promise<void>;
97
+ invalidate(location?: LocationRef): void;
98
+ };
99
+ readonly agent: LocationCollection<AgentInfo>;
100
+ readonly command: LocationCollection<CommandInfo>;
101
+ readonly integration: LocationCollection<IntegrationInfo>;
102
+ readonly mcp: {
103
+ readonly server: LocationCollection<McpServer>;
104
+ readonly resource: LocationCollection<McpResource>;
105
+ };
106
+ readonly model: LocationCollection<ModelInfo>;
107
+ readonly provider: LocationCollection<ProviderInfo>;
108
+ readonly reference: LocationCollection<ReferenceInfo>;
109
+ readonly skill: LocationCollection<SkillInfo>;
110
+ };
111
+ }
112
+ export type Route = {
113
+ readonly type: "home";
114
+ } | {
115
+ readonly type: "session";
116
+ readonly sessionID: string;
117
+ } | {
118
+ readonly type: "plugin";
119
+ readonly id: string;
120
+ readonly name: string;
121
+ readonly data?: Record<string, any>;
122
+ };
123
+ export type Destination = Route | Omit<Extract<Route, {
124
+ readonly type: "plugin";
125
+ }>, "id">;
126
+ export interface Page {
127
+ readonly name: string;
128
+ readonly render: (input: {
129
+ readonly data?: Record<string, any>;
130
+ }) => JSX.Element;
131
+ }
132
+ type PromptFooterInput = {
133
+ readonly sessionID?: string;
134
+ readonly mode: "normal" | "shell";
135
+ readonly showDetails: boolean;
136
+ };
137
+ export type PanelPresentation = "panel" | "fullscreen";
138
+ /** Client-local state of the selected session panel. The host owns its layout and input scope. */
139
+ export interface PanelInput {
140
+ /** Selected content name, set by ui.panel.open. Contributions decide whether to render it. */
141
+ readonly name: string;
142
+ readonly sessionID: string;
143
+ readonly width: number;
144
+ readonly presentation: PanelPresentation;
145
+ readonly focused: boolean;
146
+ readonly focus: () => void;
147
+ readonly close: () => void;
148
+ readonly toggleFullscreen: () => void;
149
+ }
150
+ /**
151
+ * The host UI's slot tree. Every path is one slot: a named boundary a plugin
152
+ * may render around, inside, or take over. Paths are absolute and
153
+ * dot-separated, and a path contains every path it prefixes — replacing
154
+ * `prompt.footer` owns everything under `prompt.footer.*`.
155
+ *
156
+ * Each slot publishes an input: reactive props passed to every claim render
157
+ * targeting it. Inputs carry only what the SDK cannot answer — instance
158
+ * identity and client-local state. Paths and their inputs are documented
159
+ * API: coarse, few, and kept stable across host refactors.
160
+ */
161
+ export interface SlotMap {
162
+ readonly app: Readonly<Record<string, never>>;
163
+ readonly "home.footer": Readonly<Record<string, never>>;
164
+ readonly "prompt.footer": PromptFooterInput;
165
+ readonly "prompt.footer.status": PromptFooterInput;
166
+ readonly "prompt.footer.file": PromptFooterInput;
167
+ readonly "session.composer.top": {
168
+ readonly sessionID: string;
169
+ };
170
+ readonly "session.panel": PanelInput;
171
+ readonly "sidebar.content": {
172
+ readonly sessionID: string;
173
+ };
174
+ readonly "sidebar.footer": {
175
+ readonly sessionID: string;
176
+ };
177
+ }
178
+ export type SlotPath = keyof SlotMap;
179
+ /**
180
+ * One contribution to the slot tree. Exactly one placement key names an
181
+ * absolute target path:
182
+ * - `prepend` / `append`: first/last inside the target's boundary
183
+ * - `before` / `after`: siblings adjacent to the target, outside its boundary
184
+ * - `replace`: take over the target. The boundary itself survives — siblings
185
+ * anchored `before`/`after` it still compose — but the original content and
186
+ * every claim inside the boundary are suppressed and recorded, never
187
+ * silently dropped. At the same target the last-enabled claim wins; an
188
+ * ancestor replacement beats a descendant one regardless of enable order.
189
+ *
190
+ * A claim aimed at a path the host no longer publishes degrades: additive
191
+ * claims append to the nearest surviving ancestor, replacements are
192
+ * suppressed. Several claims at one anchor coexist in plugin enable order.
193
+ *
194
+ * `render` receives the target slot's input, reactively. The `?: never`
195
+ * fields make the variants mutually exclusive: a claim with two placement
196
+ * keys is a type error, not a silent priority pick.
197
+ */
198
+ export type SlotClaim<Path extends SlotPath = SlotPath> = Path extends SlotPath ? {
199
+ readonly render: (input: SlotMap[Path]) => JSX.Element;
200
+ } & ({
201
+ readonly prepend: Path;
202
+ readonly append?: never;
203
+ readonly before?: never;
204
+ readonly after?: never;
205
+ readonly replace?: never;
206
+ } | {
207
+ readonly append: Path;
208
+ readonly prepend?: never;
209
+ readonly before?: never;
210
+ readonly after?: never;
211
+ readonly replace?: never;
212
+ } | {
213
+ readonly before: Path;
214
+ readonly prepend?: never;
215
+ readonly append?: never;
216
+ readonly after?: never;
217
+ readonly replace?: never;
218
+ } | {
219
+ readonly after: Path;
220
+ readonly prepend?: never;
221
+ readonly append?: never;
222
+ readonly before?: never;
223
+ readonly replace?: never;
224
+ } | {
225
+ readonly replace: Path;
226
+ readonly prepend?: never;
227
+ readonly append?: never;
228
+ readonly before?: never;
229
+ readonly after?: never;
230
+ }) : never;
231
+ export interface App {
232
+ readonly version: string;
233
+ readonly channel: string;
234
+ }
235
+ export type ToastVariant = "info" | "success" | "warning" | "error";
236
+ export interface ToastOptions {
237
+ readonly title?: string;
238
+ readonly message: string;
239
+ readonly variant?: ToastVariant;
240
+ readonly duration?: number;
241
+ }
242
+ export interface Toast {
243
+ show(options: ToastOptions): void;
244
+ }
245
+ export type AttentionWhen = "always" | "focused" | "blurred";
246
+ export type AttentionSoundName = "default" | "question" | "permission" | "error" | "done" | "subagent_done";
247
+ export type AttentionNotification = boolean | {
248
+ readonly when?: AttentionWhen;
249
+ };
250
+ export type AttentionSound = boolean | {
251
+ readonly name?: AttentionSoundName;
252
+ readonly volume?: number;
253
+ readonly when?: AttentionWhen;
254
+ };
255
+ export interface AttentionNotifyOptions {
256
+ readonly title?: string;
257
+ readonly message: string;
258
+ readonly notification?: AttentionNotification;
259
+ readonly sound?: AttentionSound;
260
+ }
261
+ export type AttentionNotifySkipReason = "attention_disabled" | "empty_message" | "blurred" | "focused" | "focus_unknown" | "renderer_destroyed";
262
+ export interface AttentionNotifyResult {
263
+ readonly ok: boolean;
264
+ readonly notification: boolean;
265
+ readonly sound: boolean;
266
+ readonly skipped?: AttentionNotifySkipReason;
267
+ }
268
+ export interface Attention {
269
+ notify(options: AttentionNotifyOptions): Promise<AttentionNotifyResult>;
270
+ }
271
+ export type DialogSize = "medium" | "large" | "xlarge";
272
+ export interface DialogOptions {
273
+ readonly size?: DialogSize;
274
+ readonly centered?: boolean;
275
+ }
276
+ export interface DialogAlertOptions {
277
+ readonly title: string;
278
+ readonly message: string;
279
+ }
280
+ export interface DialogConfirmOptions {
281
+ readonly title: string;
282
+ readonly message: string;
283
+ readonly label?: {
284
+ readonly confirm?: string;
285
+ readonly cancel?: string;
286
+ };
287
+ }
288
+ export interface DialogPromptOptions {
289
+ readonly title: string;
290
+ readonly description?: string;
291
+ readonly placeholder?: string;
292
+ readonly value?: string;
293
+ }
294
+ export interface DialogSelectOption<Value> {
295
+ readonly title: string;
296
+ readonly value: Value;
297
+ readonly description?: string;
298
+ readonly footer?: string;
299
+ readonly category?: string;
300
+ readonly disabled?: boolean;
301
+ }
302
+ export interface DialogSelectOptions<Value> {
303
+ readonly title: string;
304
+ readonly placeholder?: string;
305
+ readonly options: readonly DialogSelectOption<Value>[];
306
+ readonly current?: Value;
307
+ }
308
+ export interface Dialog {
309
+ /** Shows a dialog. */
310
+ show(render: () => JSX.Element, onClose?: () => void): void;
311
+ /** Sets the active dialog's presentation options. */
312
+ set(options: DialogOptions): void;
313
+ /** Closes the active dialog. */
314
+ clear(): void;
315
+ alert(options: DialogAlertOptions): Promise<void>;
316
+ confirm(options: DialogConfirmOptions): Promise<boolean | undefined>;
317
+ prompt(options: DialogPromptOptions): Promise<string | undefined>;
318
+ select<Value>(options: DialogSelectOptions<Value>): Promise<Value | undefined>;
319
+ }
320
+ export interface KeymapCommand {
321
+ /** Stable command and config keybind identifier. Omit for an inline command. */
322
+ readonly id?: string;
323
+ /** Optional label used by command discovery and keyboard-help UI. */
324
+ readonly title?: string;
325
+ /** Optional longer description. */
326
+ readonly description?: string;
327
+ /** Groups the command in discovery and keyboard-help UI. */
328
+ readonly group?: string;
329
+ /** Enables or disables the command. */
330
+ readonly enabled?: boolean | (() => boolean);
331
+ /** Configures automatic binding, or disables it for a named command. */
332
+ readonly bind?: false | string;
333
+ /** Adds a named command to the command palette. */
334
+ readonly palette?: true;
335
+ /** Adds a named command to prompt slash completion. */
336
+ readonly slash?: {
337
+ readonly name: string;
338
+ readonly aliases?: string[];
339
+ /** Keeps the slash command in the prompt and passes its raw input to run. */
340
+ readonly arguments?: true;
341
+ };
342
+ /** Promotes the command in discovery UI. */
343
+ readonly suggested?: boolean | (() => boolean);
344
+ /** Executes the command. Keyboard dispatch includes its event; programmatic dispatch does not. Return false to continue. */
345
+ readonly run: (input?: string, event?: KeyEvent) => void | false | Promise<void>;
346
+ }
347
+ export interface KeymapLayer {
348
+ /** Limits the layer to one OpenCode input mode. Use global to opt out; defaults to base. */
349
+ readonly mode?: string;
350
+ /** Enables or disables the complete layer. */
351
+ readonly enabled?: boolean | (() => boolean);
352
+ /** Limits the layer to a focused renderable. */
353
+ readonly target?: () => Renderable | null | undefined;
354
+ /** Resolves conflicts with other active layers. */
355
+ readonly priority?: number;
356
+ /** Commands owned by this layer. */
357
+ readonly commands?: readonly KeymapCommand[];
358
+ /** IDs of commands whose configured bindings should be active in this layer. */
359
+ readonly bindings?: readonly string[];
360
+ }
361
+ export interface KeymapPending {
362
+ readonly key: string;
363
+ readonly token?: string;
364
+ }
365
+ export interface KeymapActive {
366
+ readonly key: string;
367
+ readonly title?: string;
368
+ readonly description?: string;
369
+ readonly group?: string;
370
+ readonly continues: boolean;
371
+ }
372
+ export interface Keymap {
373
+ /** Creates a reactive keymap layer owned by the calling component. */
374
+ layer(input: () => KeymapLayer): void;
375
+ /** Dispatches a reachable command by ID. */
376
+ dispatch(id: string, input?: string): void;
377
+ /** Returns every formatted shortcut for a registered command. */
378
+ shortcuts(id: string): readonly string[];
379
+ /** Returns the currently reachable commands. Reactive when read in a Solid computation. */
380
+ commands(): readonly KeymapCommand[];
381
+ /** Returns the pending key sequence. Reactive when read in a Solid computation. */
382
+ pending(): readonly KeymapPending[];
383
+ /** Returns bindings reachable from the pending key sequence. Reactive when read in a Solid computation. */
384
+ active(): readonly KeymapActive[];
385
+ /** Controls mutually exclusive OpenCode input modes. */
386
+ readonly mode: {
387
+ /** Returns the active mode. */
388
+ current(): string;
389
+ /** Pushes a mode until the returned cleanup is called. */
390
+ push(mode: string): () => void;
391
+ };
392
+ }
393
+ export interface UI {
394
+ readonly dialog: Dialog;
395
+ readonly toast: Toast;
396
+ readonly format: {
397
+ path(value: string): string;
398
+ };
399
+ readonly router: {
400
+ register(page: Page): () => void;
401
+ navigate(destination: Destination): void;
402
+ current(): Route;
403
+ };
404
+ readonly panel: {
405
+ /** Opens the session.panel slot in the current session. */
406
+ open(name: string, options?: {
407
+ readonly presentation?: PanelPresentation;
408
+ }): boolean;
409
+ /** Closes this plugin's active panel. Other plugins' panels are unaffected. */
410
+ close(): void;
411
+ /** This plugin's active panel, if any. Reactive when read in a Solid computation. */
412
+ current(): {
413
+ readonly name: string;
414
+ readonly sessionID: string;
415
+ } | undefined;
416
+ };
417
+ readonly tabs: {
418
+ /** Returns whether session tabs are enabled for this TUI. */
419
+ enabled(): boolean;
420
+ /** Returns the currently open root-session tabs. Reactive when read in a Solid computation. */
421
+ list(): readonly {
422
+ readonly sessionID: string;
423
+ readonly title?: string;
424
+ readonly active: boolean;
425
+ readonly busy: boolean;
426
+ readonly attention: boolean;
427
+ readonly unread?: "activity" | "error";
428
+ }[];
429
+ /** Opens a tab for a session without focusing it. Returns false when tabs are disabled. */
430
+ open(sessionID: string): boolean;
431
+ /** Opens a tab when needed, then focuses it. Returns false when tabs are disabled. */
432
+ focus(sessionID: string): boolean;
433
+ /** Moves an open tab to an index and returns false when it is not open. */
434
+ move(sessionID: string, index: number): boolean;
435
+ /** Closes an open tab, or the active tab when omitted, and returns false when no tab matched. */
436
+ close(sessionID?: string): boolean;
437
+ };
438
+ /** Claims a place in the slot tree; see SlotClaim. */
439
+ readonly slot: (claim: SlotClaim) => () => void;
440
+ }
441
+ export interface Context {
442
+ readonly options: Readonly<Record<string, any>>;
443
+ readonly location: LocationRef | undefined;
444
+ readonly app: App;
445
+ readonly renderer: CliRenderer;
446
+ readonly client: OpenCodeClient;
447
+ readonly data: Data;
448
+ readonly attention: Attention;
449
+ readonly theme: ResolvedTheme;
450
+ readonly themeMode: "dark" | "light";
451
+ readonly markdown: {
452
+ registerCodeBlockRenderer(language: string, render: MarkdownCodeBlockRenderer): () => void;
453
+ };
454
+ readonly keymap: Keymap;
455
+ readonly storage: Storage;
456
+ readonly ui: UI;
457
+ }
458
+ export {};
File without changes
@@ -0,0 +1,2 @@
1
+ export * as Plugin from "./plugin.js";
2
+ export { PluginContextProvider, usePlugin } from "./solid.js";
@@ -0,0 +1,2 @@
1
+ export * as Plugin from "./plugin.js";
2
+ export { PluginContextProvider, usePlugin } from "./solid.js";
@@ -0,0 +1,8 @@
1
+ import type { Context } from "./context.js";
2
+ export type { Context };
3
+ export type Cleanup = () => Promise<void> | void;
4
+ export interface Definition {
5
+ readonly id: string;
6
+ readonly setup: (context: Context) => Promise<Cleanup | void> | Cleanup | void;
7
+ }
8
+ export declare function define(plugin: Definition): Definition;
@@ -0,0 +1,3 @@
1
+ export function define(plugin) {
2
+ return plugin;
3
+ }
@@ -0,0 +1,7 @@
1
+ import { type JSX } from "solid-js";
2
+ import type { Context } from "./context.js";
3
+ export declare function PluginContextProvider(props: {
4
+ readonly value: Context;
5
+ readonly children: JSX.Element;
6
+ }): JSX.Element;
7
+ export declare function usePlugin(): Context;
@@ -0,0 +1,16 @@
1
+ import { createComponent, createContext, useContext } from "solid-js";
2
+ const PluginContext = createContext();
3
+ export function PluginContextProvider(props) {
4
+ return createComponent(PluginContext.Provider, {
5
+ value: props.value,
6
+ get children() {
7
+ return props.children;
8
+ },
9
+ });
10
+ }
11
+ export function usePlugin() {
12
+ const context = useContext(PluginContext);
13
+ if (!context)
14
+ throw new Error("PluginContextProvider is missing");
15
+ return context;
16
+ }
@@ -0,0 +1,18 @@
1
+ export interface WorktreeCreateInput {
2
+ readonly sourceDirectory: string;
3
+ /** Suggested destination after naming and collision handling. Strategies may return a different directory. */
4
+ readonly directory: string;
5
+ /** Starting ref, not the name of a new branch. Reject unsupported refs rather than ignoring them. */
6
+ readonly branch?: string;
7
+ }
8
+ export interface WorktreeRemoveInput {
9
+ readonly directory: string;
10
+ readonly force: boolean;
11
+ }
12
+ export interface WorktreeResult {
13
+ /** Actual directory created by the strategy, used for inventory and startup commands. */
14
+ readonly directory: string;
15
+ }
16
+ export interface WorktreeEntry extends WorktreeResult {
17
+ readonly type: "root" | "worktree";
18
+ }
File without changes
package/package.json CHANGED
@@ -1,15 +1,87 @@
1
1
  {
2
+ "$schema": "https://json.schemastore.org/package.json",
2
3
  "name": "@opencode/plugin",
3
- "version": "0.0.0-reserved",
4
- "description": "OpenCode package bootstrap — not a functional release",
4
+ "version": "2.0.1",
5
+ "type": "module",
5
6
  "license": "MIT",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/anomalyco/opencode.git"
9
- },
10
- "publishConfig": {
11
- "registry": "https://registry.npmjs.org",
12
- "access": "public",
13
- "tag": "reserved"
7
+ "scripts": {
8
+ "test": "bun test --only-failures",
9
+ "typecheck": "tsgo --noEmit",
10
+ "build": "tsc -p tsconfig.build.json"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/promise/index.js",
15
+ "types": "./dist/promise/index.d.ts"
16
+ },
17
+ "./effect": {
18
+ "import": "./dist/effect/index.js",
19
+ "types": "./dist/effect/index.d.ts"
20
+ },
21
+ "./host": {
22
+ "import": "./dist/host.js",
23
+ "types": "./dist/host.d.ts"
24
+ },
25
+ "./tui": {
26
+ "import": "./dist/tui/index.js",
27
+ "types": "./dist/tui/index.d.ts"
28
+ },
29
+ "./*": {
30
+ "import": "./dist/*.js",
31
+ "types": "./dist/*.d.ts"
32
+ }
33
+ },
34
+ "imports": {
35
+ "#plugin-source": {
36
+ "bun": "./dist/source.bun.js",
37
+ "node": "./dist/source.node.js",
38
+ "default": "./dist/source.node.js"
39
+ }
40
+ },
41
+ "files": [
42
+ "dist"
43
+ ],
44
+ "dependencies": {
45
+ "@ai-sdk/provider": "3.0.8",
46
+ "@opencode/ai": "2.0.1",
47
+ "@opencode/client": "2.0.1",
48
+ "@opencode/protocol": "2.0.1",
49
+ "@opencode/schema": "2.0.1",
50
+ "@opencode/util": "2.0.1",
51
+ "@standard-schema/spec": "1.1.0",
52
+ "effect": "4.0.0-rc.112",
53
+ "zod": "4.1.8"
54
+ },
55
+ "peerDependencies": {
56
+ "@opencode/theme": "2.0.1",
57
+ "@opentui/core": ">=0.5.10",
58
+ "@opentui/solid": ">=0.5.10",
59
+ "solid-js": ">=1.9.0"
60
+ },
61
+ "peerDependenciesMeta": {
62
+ "@opencode/theme": {
63
+ "optional": true
64
+ },
65
+ "@opentui/core": {
66
+ "optional": true
67
+ },
68
+ "@opentui/solid": {
69
+ "optional": true
70
+ },
71
+ "solid-js": {
72
+ "optional": true
73
+ }
74
+ },
75
+ "devDependencies": {
76
+ "@opencode/theme": "2.0.1",
77
+ "@opentui/core": "0.5.10",
78
+ "@opentui/solid": "0.5.10",
79
+ "@tsconfig/bun": "1.0.9",
80
+ "@tsconfig/node22": "22.0.2",
81
+ "@types/bun": "1.4.0",
82
+ "@types/node": "24.12.2",
83
+ "solid-js": "1.9.15",
84
+ "typescript": "5.8.2",
85
+ "@typescript/native-preview": "7.0.0-dev.20251207.1"
14
86
  }
15
- }
87
+ }
package/README.md DELETED
@@ -1,5 +0,0 @@
1
- # @opencode/plugin
2
-
3
- Bootstrap placeholder for the official [OpenCode](https://opencode.ai) release pipeline.
4
-
5
- This version contains no implementation or executable. Do not use it as a functional release.