@aexol/opencode-wizard 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,16 +1,19 @@
1
1
  # @aexol/opencode-wizard
2
2
 
3
- `@aexol/opencode-wizard` is a separately releasable OpenCode server plugin package for fetching published skills from the opencode-wizard backend runtime.
3
+ `@aexol/opencode-wizard` is a separately releasable OpenCode plugin package for fetching published skills from the opencode-wizard backend runtime and surfacing plugin status in the TUI.
4
4
 
5
5
  ## Package target
6
6
 
7
- - `oc-plugin: ["server"]`
7
+ - `oc-plugin: ["server", "tui"]`
8
8
  - `./server` → `dist/server.js`
9
+ - `./tui` → `dist/tui.js`
9
10
  - no generated runtime skill directory is published; the plugin stays fetch-only at runtime
11
+ - native OpenCode `skills.urls` is treated as a public/static registry complement, not as the private wizard delivery authority
12
+ - the TUI shows loaded plugins, current paths, backend/auth status without tokens, available tools, `skills.urls` guidance, the backend-published GLOBAL/PROJECT delivery model, policy labels, and catalog counts/names when passive fetch succeeds
10
13
 
11
14
  ## Local development
12
15
 
13
- This monorepo still path-loads the same package from `./plugin/opencode-wizard-skills` during local OpenCode development.
16
+ This monorepo still path-loads the same package from `./plugin/opencode-wizard` during local OpenCode development.
14
17
 
15
18
  Backend origin resolution keeps local-first behavior only when the plugin is executing from a local module path/check-out. In that case it still prefers repo `.env`/`PORT`, then `APP_URL`, then falls back to `http://localhost:8080`. For the packaged/published plugin, the same config values still win when present, but the fallback origin is `https://opencode-wizard.aexol.work`.
16
19
 
@@ -34,11 +37,27 @@ OpenCode server/plugin host can install the published package by package name in
34
37
 
35
38
  For repo-local development, continue using the local path-based config already documented in this repository.
36
39
 
40
+ ## Native `skills.urls` compatibility
41
+
42
+ OpenCode's native `skills.urls` support downloads public/static skill registries from base URLs that expose an `index.json` and file paths under that base URL. Current support has no plugin session/header integration, so it must not be pointed at private opencode-wizard skill delivery.
43
+
44
+ Use `skills.urls` only for public registries that are intentionally cacheable by OpenCode. Private workspace-scoped wizard skills remain authenticated and directory-scoped through `opencode_wizard_published_skills_fetch`.
45
+
46
+ ## Catalog discovery and auth bootstrap
47
+
48
+ On chat/system-context startup, the plugin attempts to load the catalog automatically with the stored plugin session at `plugin/opencode-wizard/.generated/auth-state.json`. If no valid plugin session exists, startup stays passive and reports that interactive fetch will bootstrap browser login when needed; it does not open the browser from system context.
49
+
50
+ Call `opencode_wizard_published_skills_fetch` without `skill` or `skills` to manually bootstrap plugin login if needed and return catalog-only discovery output for the current directory scope.
51
+
52
+ No-arg discovery returns published skill summaries, assignment counts split into `global` and `project`, policy metadata, and no markdown bodies. Existing `skill` and `skills` calls still fetch one or more full skill body/detail payloads by slug, artifact name, or skill name.
53
+
54
+ `GLOBAL_CONTEXT` skills are active context skills and are not meant to be installed per project. `PROJECT_INSTALLABLE` skills are gallery/installable skills that may be attached globally or to a workspace/path through assignment records; those assignments remain the source of truth for what is active in a catalog response.
55
+
37
56
  ## Release flow
38
57
 
39
- 1. Bump `version` in `plugin/opencode-wizard-skills/package.json`.
40
- 2. Run `npm run plugin:skills:release:check` from the repo root.
41
- 3. If you are following the repo release-tag convention, create Git tag `plugin-opencode-wizard-skills-v<version>`.
58
+ 1. Bump `version` in `plugin/opencode-wizard/package.json`.
59
+ 2. Run `npm run plugin:release:check` from the repo root.
60
+ 3. If you are following the repo release-tag convention, create Git tag `plugin-opencode-wizard-v<version>`.
42
61
  4. Push the release commit/tag so GitLab can run the shared npm public publish job.
43
62
 
44
- The CI publish job comes from `ci/templates/node/npm-publish-public.yml`, stays manual on the repo `deploy` stage, runs from `plugin/opencode-wizard-skills` via `APP_ROOT`, builds the package with `npm run build --if-present`, deletes the inherited `@aexol` GitLab registry override, and then publishes `@aexol/opencode-wizard` with `npm publish --access public --registry https://registry.npmjs.org/`.
63
+ The CI publish job comes from `ci/templates/node/npm-publish-public.yml`, stays manual on the repo `deploy` stage, runs from `plugin/opencode-wizard` via `APP_ROOT`, builds the package with `npm run build --if-present`, deletes the inherited `@aexol` GitLab registry override, and then publishes `@aexol/opencode-wizard` with `npm publish --access public --registry https://registry.npmjs.org/`.
package/dist/server.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type Plugin } from '@opencode-ai/plugin';
1
+ export declare const PLUGIN_ID = "opencode-wizard";
2
2
  type ResolvedConfig = {
3
3
  backendOrigin: string;
4
4
  graphqlUrl: string;
@@ -9,7 +9,15 @@ type ResolvedConfig = {
9
9
  rootSkillSeedPath: string;
10
10
  authStatePath: string;
11
11
  };
12
- type PublishedSkillCatalogPayload = {
12
+ type WorkspaceResolution = {
13
+ requestedDirectory: string;
14
+ repositoryRoot: string;
15
+ repositoryUrl: string | null;
16
+ fallbackWorkspaceSlug: string | null;
17
+ directoryPath: string;
18
+ cacheKey: string;
19
+ };
20
+ export type PublishedSkillCatalogPayload = {
13
21
  workspace: {
14
22
  id: string;
15
23
  slug: string;
@@ -21,7 +29,7 @@ type PublishedSkillCatalogPayload = {
21
29
  directoryPath: string;
22
30
  skills: PublishedSkillCatalogItem[];
23
31
  };
24
- type PublishedSkillCatalogItem = {
32
+ export type PublishedSkillCatalogItem = {
25
33
  assignmentSource: string;
26
34
  assignmentType: string;
27
35
  scopePath: string;
@@ -31,7 +39,9 @@ type PublishedSkillCatalogItem = {
31
39
  slug: string;
32
40
  name: string;
33
41
  summary?: string | null;
42
+ whenToUse?: string | null;
34
43
  status: string;
44
+ installPolicy: PublishedSkillInstallPolicy;
35
45
  tags: PublishedSkillTag[];
36
46
  };
37
47
  skillVersion: {
@@ -73,17 +83,42 @@ type PublishedSkillTagSummary = {
73
83
  description: string | null;
74
84
  facet: PublishedSkillFacetSummary | null;
75
85
  };
76
- type PublishedSkillDetailItem = PublishedSkillCatalogItem & {
86
+ type PublishedSkillInstallPolicy = 'GLOBAL_CONTEXT' | 'PROJECT_INSTALLABLE';
87
+ export type PublishedSkillDetailItem = PublishedSkillCatalogItem & {
77
88
  publishedArtifact: PublishedSkillCatalogItem['publishedArtifact'] & {
78
89
  markdownBody: string;
79
90
  renderedContent: string;
80
91
  };
81
92
  };
93
+ type AuthState = {
94
+ pluginId: string;
95
+ sessionToken: string;
96
+ expiresAt: string;
97
+ authenticatedAt: string;
98
+ userId: string;
99
+ email: string;
100
+ };
101
+ type FetchResult = {
102
+ ok: true;
103
+ status: 'ready';
104
+ authMode: 'session';
105
+ payload: PublishedSkillCatalogPayload;
106
+ fetchedAt: string;
107
+ source: 'network' | 'cache';
108
+ } | {
109
+ ok: false;
110
+ status: 'missing_auth' | 'request_failed';
111
+ authMode: 'missing' | 'session';
112
+ message: string;
113
+ fetchedAt: string;
114
+ source: 'network' | 'cache';
115
+ };
82
116
  type PublishedSkillSummary = {
83
117
  skillSlug: string;
84
118
  skillName: string;
85
119
  artifactName: string;
86
120
  artifactDescription: string;
121
+ whenToUse: string | null;
87
122
  version: string;
88
123
  assignmentSource: string;
89
124
  assignmentType: string;
@@ -93,6 +128,9 @@ type PublishedSkillSummary = {
93
128
  publishedAt: string;
94
129
  identifiers: string[];
95
130
  tags: PublishedSkillTagSummary[];
131
+ contextKind: 'global' | 'project';
132
+ installPolicy: PublishedSkillInstallPolicy;
133
+ policyLabel: string;
96
134
  };
97
135
  type PublishedSkillDetail = PublishedSkillSummary & {
98
136
  skillId: string;
@@ -102,17 +140,69 @@ type PublishedSkillDetail = PublishedSkillSummary & {
102
140
  markdownBody: string;
103
141
  renderedContent: string;
104
142
  };
143
+ type OpencodePluginServerInput = {
144
+ worktree: string;
145
+ directory: string;
146
+ };
147
+ type OpencodePluginSystemTransformOutput = {
148
+ system: string[];
149
+ };
150
+ type OpencodePluginServer = (input: OpencodePluginServerInput) => Promise<{
151
+ tool: Record<string, unknown>;
152
+ 'experimental.chat.system.transform': (hookInput: unknown, output: OpencodePluginSystemTransformOutput) => Promise<void>;
153
+ }>;
105
154
  type PublishedSkillsSuccessState = {
106
155
  pluginId: string;
107
156
  runtimeMode: 'tool_fetch_only';
157
+ deliveryModel: 'backend_published_global_project_assignments';
108
158
  workspace: PublishedSkillCatalogPayload['workspace'];
109
159
  directoryPath: string;
110
160
  rootSkillSeedPath: string;
111
161
  availableTools: string[];
112
162
  publishedSkillCount: number;
163
+ assignmentCounts: {
164
+ global: number;
165
+ project: number;
166
+ other: number;
167
+ };
113
168
  facets: PublishedSkillFacetSummary[];
114
169
  skills: PublishedSkillSummary[];
115
170
  };
171
+ export declare const AVAILABLE_PUBLISHED_SKILL_TOOLS: string[];
172
+ export type NativeSkillsUrlCompatibility = {
173
+ configKey: 'skills.urls';
174
+ deliveryMode: 'public_static_registry';
175
+ wizardPrivateDelivery: 'authenticated_scoped_fetch_tool';
176
+ authSupport: 'none';
177
+ guidance: string;
178
+ };
179
+ export declare const NATIVE_SKILLS_URL_COMPATIBILITY: NativeSkillsUrlCompatibility;
180
+ export type PluginAuthStateSummary = {
181
+ status: 'missing' | 'authenticated';
182
+ email: string | null;
183
+ userId: string | null;
184
+ authenticatedAt: string | null;
185
+ expiresAt: string | null;
186
+ };
187
+ export type PluginStatusSnapshot = {
188
+ pluginId: string;
189
+ runtimeMode: 'tool_fetch_only';
190
+ nativeSkillsUrlCompatibility: NativeSkillsUrlCompatibility;
191
+ backendOrigin: string;
192
+ graphqlUrl: string;
193
+ fallbackWorkspaceSlug: string;
194
+ workspaceResolution: ReturnType<typeof toWorkspaceResolutionOutput>;
195
+ rootSkillSeedPath: string;
196
+ authStatePath: string;
197
+ authState: PluginAuthStateSummary;
198
+ status: FetchResult['status'];
199
+ authMode: FetchResult['authMode'];
200
+ fetchedAt: string;
201
+ source: FetchResult['source'];
202
+ availableTools: typeof AVAILABLE_PUBLISHED_SKILL_TOOLS;
203
+ message: string | null;
204
+ catalog: PublishedSkillsSuccessState | null;
205
+ };
116
206
  export declare const resolveConfig: (worktree: string) => Promise<ResolvedConfig>;
117
207
  export declare const buildSkillMarkdown: (item: PublishedSkillDetailItem) => string;
118
208
  export declare const toPublishedSkillDetail: (item: PublishedSkillDetailItem) => PublishedSkillDetail;
@@ -123,8 +213,21 @@ export declare const selectPublishedSkills: <TItem extends PublishedSkillCatalog
123
213
  selectedItems: TItem[];
124
214
  missingIdentifiers: string[];
125
215
  };
216
+ declare const toWorkspaceResolutionOutput: (resolution: WorkspaceResolution) => {
217
+ requestedDirectory: string;
218
+ repositoryRoot: string;
219
+ repositoryUrl: string | null;
220
+ fallbackWorkspaceSlug: string | null;
221
+ directoryPath: string;
222
+ };
223
+ export declare const toPluginAuthStateSummary: (authState: AuthState | null) => PluginAuthStateSummary;
224
+ export declare const resolvePluginStatusSnapshot: ({ worktree, directory, signal, }: {
225
+ worktree: string;
226
+ directory: string;
227
+ signal: AbortSignal;
228
+ }) => Promise<PluginStatusSnapshot>;
126
229
  declare const _default: {
127
230
  id: string;
128
- server: Plugin;
231
+ server: OpencodePluginServer;
129
232
  };
130
233
  export default _default;