@aexol/opencode-wizard 0.3.9 → 0.3.10

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
@@ -9,7 +9,7 @@
9
9
  - `./tui` → `dist/tui.js`
10
10
  - no generated runtime skill directory is published; the plugin stays fetch-only at runtime
11
11
  - native OpenCode `skills.urls` is treated as a public/static registry complement, not as the private wizard delivery authority
12
- - the TUI is a compact skill-management panel: it shows auth/catalog status, labelled active/available/ignored skills, shared command hints, and EDITOR-only authoring hints while mutations still run through guarded tools
12
+ - the TUI is a compact status panel: it shows backend URL, signed-in identity, role, and catalog counts while mutations still run through guarded tools
13
13
 
14
14
  ## Local development
15
15
 
@@ -46,7 +46,7 @@ Use `skills.urls` only for public registries that are intentionally cacheable by
46
46
 
47
47
  ## Catalog discovery and auth bootstrap
48
48
 
49
- Catalog discovery uses the backend-issued plugin session token stored at `~/.config/opencode/opencode-wizard.json` (`auth` field); the plugin does not persist or send Microsoft/Entra tokens to GraphQL. If no valid plugin session exists, no-arg `opencode_wizard_catalog_fetch`, compatibility no-arg `opencode_wizard_published_skills_fetch`, explicit `opencode_wizard_status`, and chat/system-context startup may start the browser Entra PKCE flow and exchange the callback for a fresh backend-issued plugin session. The TUI panel displays the resulting auth/catalog state and a compact labelled skill list derived from that status payload.
49
+ Catalog discovery uses the backend-issued plugin session token stored at `~/.config/opencode/opencode-wizard.json` (`auth` field); the plugin does not persist or send Microsoft/Entra tokens to GraphQL. If no valid plugin session exists, no-arg `opencode_wizard_catalog_fetch`, compatibility no-arg `opencode_wizard_published_skills_fetch`, explicit `opencode_wizard_status`, and chat/system-context startup may start the browser Entra PKCE flow and exchange the callback for a fresh backend-issued plugin session. The TUI panel displays the resulting backend URL, auth identity, role, and catalog counts from that status payload.
50
50
 
51
51
  The shared plugin tools `opencode_wizard_catalog_fetch`, `opencode_wizard_artifact_fetch`, `opencode_wizard_artifact_preference_set`, compatibility published-skill tools, and `opencode_wizard_status` are always exposed by the plugin. Missing auth, forbidden role, backend, or catalog problems are reported by tool output/status metadata instead of hiding these shared tools; only `opencode_wizard_editor_create_or_update_skill`, `opencode_wizard_editor_publish_skill`, and `opencode_wizard_artifact_import` stay editor-only.
52
52
 
@@ -58,7 +58,7 @@ Workspace delivery still follows the backend contract: the plugin sends `workspa
58
58
 
59
59
  Published skill fetches still support `refresh: true`, but normal cache entries now self-expire after 30 seconds and fetch/status payloads surface `source`, `workspaceSlug`, and `workspaceSlugSource` so stale-vs-refreshed behavior is visible without relying on manual cache deletion. Try `refresh: true` and report the tool-output auth/catalog/source/cache/workspace-resolution state before deleting `~/.cache/opencode/*`.
60
60
 
61
- Use `opencode_wizard_artifact_preference_set` or compatibility `opencode_wizard_published_skill_preference_set` for preference actions (`install`, `uninstall`, `ignore`, `unignore`); the TUI panel surfaces command/menu hints for those management flows but does not run preference mutations directly.
61
+ Use `opencode_wizard_artifact_preference_set` or compatibility `opencode_wizard_published_skill_preference_set` for preference actions (`install`, `uninstall`, `ignore`, `unignore`); the TUI panel stays read-only and does not run preference mutations directly.
62
62
 
63
63
  ## EDITOR skill creation flow
64
64
 
@@ -1,4 +1,4 @@
1
- import { type PublishedSkillsSuccessState } from './published-skills-transform.js';
1
+ import type { PublishedSkillsSuccessState } from './published-skills-transform.js';
2
2
  export declare const buildPublishedSkillsSystemNote: ({ workspace, directoryPath, catalog, details: _details, }: {
3
3
  workspace: {
4
4
  slug: string;
@@ -1,17 +1,4 @@
1
- import { isUserPublishedSkillAssignment } from './published-skills-transform.js';
2
- import { WIZARD_SCOPE_LABELS } from './published-skills-terminology.js';
3
1
  const SYSTEM_NOTE_SKILL_NAME_LIMIT = 10;
4
- const SYSTEM_NOTE_SKILL_DESCRIPTION_LIMIT = 140;
5
- const truncateText = (value, maxLength) => {
6
- const normalized = value.replace(/\s+/gu, ' ').trim();
7
- if (normalized.length <= maxLength) return normalized;
8
- return `${normalized.slice(0, Math.max(maxLength - 1, 0)).trimEnd()}…`;
9
- };
10
- const buildSkillCatalogLine = skill => {
11
- const description = truncateText(skill.whenToUse || skill.artifactDescription || skill.skillName || skill.skillSlug, SYSTEM_NOTE_SKILL_DESCRIPTION_LIMIT);
12
- const scopeLabel = isUserPublishedSkillAssignment(skill.assignmentSource) ? WIZARD_SCOPE_LABELS.user : WIZARD_SCOPE_LABELS[skill.contextKind] || WIZARD_SCOPE_LABELS.project;
13
- return `- ${skill.artifactName || skill.skillName} (${skill.skillSlug}, ${scopeLabel}): ${description}`;
14
- };
15
2
  export const buildPublishedSkillsSystemNote = ({
16
3
  workspace,
17
4
  directoryPath,
@@ -22,9 +9,6 @@ export const buildPublishedSkillsSystemNote = ({
22
9
  const renderedSkillNames = skillNames.length > 0 ? skillNames.slice(0, SYSTEM_NOTE_SKILL_NAME_LIMIT).join(', ') : 'none';
23
10
  const remainingCount = Math.max(skillNames.length - SYSTEM_NOTE_SKILL_NAME_LIMIT, 0);
24
11
  const renderedCountSuffix = remainingCount > 0 ? ` (+${remainingCount} more)` : '';
25
- const globalSkills = catalog.skills.filter(skill => skill.contextKind === 'global' && !isUserPublishedSkillAssignment(skill.assignmentSource)).slice(0, 8).map(buildSkillCatalogLine);
26
- const projectSkills = catalog.skills.filter(skill => skill.contextKind === 'project' && !isUserPublishedSkillAssignment(skill.assignmentSource)).slice(0, 5).map(buildSkillCatalogLine);
27
- const userSkills = catalog.skills.filter(skill => isUserPublishedSkillAssignment(skill.assignmentSource)).slice(0, 5).map(buildSkillCatalogLine);
28
- return [workspace ? `Workspace: ${workspace.slug}.` : 'Workspace not found; workspace-scoped wizard skills are unavailable.', `Current directory: ${directoryPath}.`, `Active wizard skills: ${renderedSkillNames}${renderedCountSuffix}.`, `Runtime: runtimeMode=${catalog.runtimeMode}; deliveryModel=${catalog.deliveryModel}; rootSkillSeedPath=${catalog.rootSkillSeedPath}.`, `Counts: ${catalog.assignmentCounts.global} wizard global, ${catalog.assignmentCounts.project} wizard project, ${catalog.assignmentCounts.user} wizard user, ${catalog.assignmentCounts.other} other.`, 'Wizard artifacts support artifact kinds `SKILL` and `DESIGN_DOC`; catalogs stay metadata-only and full bodies/files require explicit authenticated artifact fetch for the effective workspace/directory assignment.', 'Canonical wizard artifact tools are `opencode_wizard_catalog_fetch`, `opencode_wizard_artifact_fetch`, and `opencode_wizard_artifact_preference_set`; catalog output is metadata-only and detail/body/files require explicit artifact fetch.', 'Wizard-listed skills are backend-published and tool-fetch-only; MUST fetch the body via `opencode_wizard_published_skills_fetch` before use (`skills`/`skill` for multiple/single). Same-named native OpenCode skills or local `.opencode/skills` seed bodies are not authoritative for wizard-listed skills; fetched wizard bodies are authoritative.', 'Action recipe: call `opencode_wizard_published_skills_fetch` with no args for auth/catalog bootstrap, use `skill` or `skills` to fetch bodies, try `refresh: true` before deleting caches, and report tool-output auth/catalog/source/cache/workspace-resolution state when unavailable or stale.', 'Source/cache/workspace hints: fetch/status outputs surface `source`, cache TTL/freshness, and workspace-resolution metadata when available; do not infer wizard scope from native/local skill files.', globalSkills.length > 0 ? `Wizard global skills:\n${globalSkills.join('\n')}` : 'Wizard global skills: none.', projectSkills.length > 0 ? `Wizard project skills:\n${projectSkills.join('\n')}` : 'Wizard project skills: none.', userSkills.length > 0 ? `Wizard user skills:\n${userSkills.join('\n')}` : 'Wizard user skills: none.'].filter(Boolean).join(' ');
12
+ return [workspace ? `Workspace: ${workspace.slug}.` : 'Workspace not found; workspace-scoped wizard skills are unavailable.', `Current directory: ${directoryPath}.`, `Active wizard skills (${skillNames.length}): ${renderedSkillNames}${renderedCountSuffix}.`, 'Fetch rule: wizard-listed skill bodies are backend-published and tool-fetch-only; fetch bodies with `opencode_wizard_published_skills_fetch` before use.', 'Status hint: use no-arg fetch/status for auth and catalog state; pass `refresh: true` before cache deletion.'].filter(Boolean).join(' ');
29
13
  };
30
14
  //# sourceMappingURL=published-skills-system-note.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["isUserPublishedSkillAssignment","WIZARD_SCOPE_LABELS","SYSTEM_NOTE_SKILL_NAME_LIMIT","SYSTEM_NOTE_SKILL_DESCRIPTION_LIMIT","truncateText","value","maxLength","normalized","replace","trim","length","slice","Math","max","trimEnd","buildSkillCatalogLine","skill","description","whenToUse","artifactDescription","skillName","skillSlug","scopeLabel","assignmentSource","user","contextKind","project","artifactName","buildPublishedSkillsSystemNote","workspace","directoryPath","catalog","details","_details","skillNames","skills","map","renderedSkillNames","join","remainingCount","renderedCountSuffix","globalSkills","filter","projectSkills","userSkills","slug","runtimeMode","deliveryModel","rootSkillSeedPath","assignmentCounts","global","other","Boolean"],"sources":["../src/published-skills-system-note.ts"],"sourcesContent":["import {\n isUserPublishedSkillAssignment,\n type PublishedSkillsSuccessState,\n} from './published-skills-transform.js';\nimport { WIZARD_SCOPE_LABELS } from './published-skills-terminology.js';\n\nconst SYSTEM_NOTE_SKILL_NAME_LIMIT = 10;\nconst SYSTEM_NOTE_SKILL_DESCRIPTION_LIMIT = 140;\n\nconst truncateText = (value: string, maxLength: number): string => {\n const normalized = value.replace(/\\s+/gu, ' ').trim();\n if (normalized.length <= maxLength) return normalized;\n return `${normalized.slice(0, Math.max(maxLength - 1, 0)).trimEnd()}…`;\n};\n\nconst buildSkillCatalogLine = (skill: PublishedSkillsSuccessState['skills'][number]): string => {\n const description = truncateText(\n skill.whenToUse || skill.artifactDescription || skill.skillName || skill.skillSlug,\n SYSTEM_NOTE_SKILL_DESCRIPTION_LIMIT,\n );\n const scopeLabel = isUserPublishedSkillAssignment(skill.assignmentSource)\n ? WIZARD_SCOPE_LABELS.user\n : (WIZARD_SCOPE_LABELS[skill.contextKind] || WIZARD_SCOPE_LABELS.project);\n return `- ${skill.artifactName || skill.skillName} (${skill.skillSlug}, ${scopeLabel}): ${description}`;\n};\n\nexport const buildPublishedSkillsSystemNote = ({\n workspace,\n directoryPath,\n catalog,\n details: _details,\n}: {\n workspace: { slug: string } | null;\n directoryPath: string;\n catalog: PublishedSkillsSuccessState;\n details: unknown[];\n}): string => {\n const skillNames = catalog.skills.map((skill) => skill.artifactName || skill.skillName || skill.skillSlug);\n const renderedSkillNames =\n skillNames.length > 0 ? skillNames.slice(0, SYSTEM_NOTE_SKILL_NAME_LIMIT).join(', ') : 'none';\n const remainingCount = Math.max(skillNames.length - SYSTEM_NOTE_SKILL_NAME_LIMIT, 0);\n const renderedCountSuffix = remainingCount > 0 ? ` (+${remainingCount} more)` : '';\n const globalSkills = catalog.skills\n .filter((skill) => skill.contextKind === 'global' && !isUserPublishedSkillAssignment(skill.assignmentSource))\n .slice(0, 8)\n .map(buildSkillCatalogLine);\n const projectSkills = catalog.skills\n .filter((skill) => skill.contextKind === 'project' && !isUserPublishedSkillAssignment(skill.assignmentSource))\n .slice(0, 5)\n .map(buildSkillCatalogLine);\n const userSkills = catalog.skills\n .filter((skill) => isUserPublishedSkillAssignment(skill.assignmentSource))\n .slice(0, 5)\n .map(buildSkillCatalogLine);\n\n return [\n workspace ? `Workspace: ${workspace.slug}.` : 'Workspace not found; workspace-scoped wizard skills are unavailable.',\n `Current directory: ${directoryPath}.`,\n `Active wizard skills: ${renderedSkillNames}${renderedCountSuffix}.`,\n `Runtime: runtimeMode=${catalog.runtimeMode}; deliveryModel=${catalog.deliveryModel}; rootSkillSeedPath=${catalog.rootSkillSeedPath}.`,\n `Counts: ${catalog.assignmentCounts.global} wizard global, ${catalog.assignmentCounts.project} wizard project, ${catalog.assignmentCounts.user} wizard user, ${catalog.assignmentCounts.other} other.`,\n 'Wizard artifacts support artifact kinds `SKILL` and `DESIGN_DOC`; catalogs stay metadata-only and full bodies/files require explicit authenticated artifact fetch for the effective workspace/directory assignment.',\n 'Canonical wizard artifact tools are `opencode_wizard_catalog_fetch`, `opencode_wizard_artifact_fetch`, and `opencode_wizard_artifact_preference_set`; catalog output is metadata-only and detail/body/files require explicit artifact fetch.',\n 'Wizard-listed skills are backend-published and tool-fetch-only; MUST fetch the body via `opencode_wizard_published_skills_fetch` before use (`skills`/`skill` for multiple/single). Same-named native OpenCode skills or local `.opencode/skills` seed bodies are not authoritative for wizard-listed skills; fetched wizard bodies are authoritative.',\n 'Action recipe: call `opencode_wizard_published_skills_fetch` with no args for auth/catalog bootstrap, use `skill` or `skills` to fetch bodies, try `refresh: true` before deleting caches, and report tool-output auth/catalog/source/cache/workspace-resolution state when unavailable or stale.',\n 'Source/cache/workspace hints: fetch/status outputs surface `source`, cache TTL/freshness, and workspace-resolution metadata when available; do not infer wizard scope from native/local skill files.',\n globalSkills.length > 0 ? `Wizard global skills:\\n${globalSkills.join('\\n')}` : 'Wizard global skills: none.',\n projectSkills.length > 0 ? `Wizard project skills:\\n${projectSkills.join('\\n')}` : 'Wizard project skills: none.',\n userSkills.length > 0 ? `Wizard user skills:\\n${userSkills.join('\\n')}` : 'Wizard user skills: none.',\n ]\n .filter(Boolean)\n .join(' ');\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["SYSTEM_NOTE_SKILL_NAME_LIMIT","buildPublishedSkillsSystemNote","workspace","directoryPath","catalog","details","_details","skillNames","skills","map","skill","artifactName","skillName","skillSlug","renderedSkillNames","length","slice","join","remainingCount","Math","max","renderedCountSuffix","slug","filter","Boolean"],"sources":["../src/published-skills-system-note.ts"],"sourcesContent":["import type { PublishedSkillsSuccessState } from './published-skills-transform.js';\n\nconst SYSTEM_NOTE_SKILL_NAME_LIMIT = 10;\n\nexport const buildPublishedSkillsSystemNote = ({\n workspace,\n directoryPath,\n catalog,\n details: _details,\n}: {\n workspace: { slug: string } | null;\n directoryPath: string;\n catalog: PublishedSkillsSuccessState;\n details: unknown[];\n}): string => {\n const skillNames = catalog.skills.map((skill) => skill.artifactName || skill.skillName || skill.skillSlug);\n const renderedSkillNames =\n skillNames.length > 0 ? skillNames.slice(0, SYSTEM_NOTE_SKILL_NAME_LIMIT).join(', ') : 'none';\n const remainingCount = Math.max(skillNames.length - SYSTEM_NOTE_SKILL_NAME_LIMIT, 0);\n const renderedCountSuffix = remainingCount > 0 ? ` (+${remainingCount} more)` : '';\n\n return [\n workspace ? `Workspace: ${workspace.slug}.` : 'Workspace not found; workspace-scoped wizard skills are unavailable.',\n `Current directory: ${directoryPath}.`,\n `Active wizard skills (${skillNames.length}): ${renderedSkillNames}${renderedCountSuffix}.`,\n 'Fetch rule: wizard-listed skill bodies are backend-published and tool-fetch-only; fetch bodies with `opencode_wizard_published_skills_fetch` before use.',\n 'Status hint: use no-arg fetch/status for auth and catalog state; pass `refresh: true` before cache deletion.',\n ]\n .filter(Boolean)\n .join(' ');\n};\n"],"mappings":"AAEA,MAAMA,4BAA4B,GAAG,EAAE;AAEvC,OAAO,MAAMC,8BAA8B,GAAGA,CAAC;EAC7CC,SAAS;EACTC,aAAa;EACbC,OAAO;EACPC,OAAO,EAAEC;AAMX,CAAC,KAAa;EACZ,MAAMC,UAAU,GAAGH,OAAO,CAACI,MAAM,CAACC,GAAG,CAAEC,KAAK,IAAKA,KAAK,CAACC,YAAY,IAAID,KAAK,CAACE,SAAS,IAAIF,KAAK,CAACG,SAAS,CAAC;EAC1G,MAAMC,kBAAkB,GACtBP,UAAU,CAACQ,MAAM,GAAG,CAAC,GAAGR,UAAU,CAACS,KAAK,CAAC,CAAC,EAAEhB,4BAA4B,CAAC,CAACiB,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM;EAC/F,MAAMC,cAAc,GAAGC,IAAI,CAACC,GAAG,CAACb,UAAU,CAACQ,MAAM,GAAGf,4BAA4B,EAAE,CAAC,CAAC;EACpF,MAAMqB,mBAAmB,GAAGH,cAAc,GAAG,CAAC,GAAG,MAAMA,cAAc,QAAQ,GAAG,EAAE;EAElF,OAAO,CACLhB,SAAS,GAAG,cAAcA,SAAS,CAACoB,IAAI,GAAG,GAAG,sEAAsE,EACpH,sBAAsBnB,aAAa,GAAG,EACtC,yBAAyBI,UAAU,CAACQ,MAAM,MAAMD,kBAAkB,GAAGO,mBAAmB,GAAG,EAC3F,0JAA0J,EAC1J,8GAA8G,CAC/G,CACEE,MAAM,CAACC,OAAO,CAAC,CACfP,IAAI,CAAC,GAAG,CAAC;AACd,CAAC","ignoreList":[]}
@@ -131,6 +131,7 @@ export const OpencodeWizardSkillsPlugin = async input => {
131
131
  const detailInflight = new Map();
132
132
  const wizardArtifactDetailInflight = new Map();
133
133
  const initialAuthState = await resolveStoredAuthState(input.worktree, config);
134
+ const registeredTools = resolveAvailableTools(initialAuthState?.role ?? null);
134
135
  const loginBootstrap = {
135
136
  promise: null,
136
137
  snapshot: createIdleLoginBootstrapSnapshot()
@@ -578,11 +579,7 @@ export const OpencodeWizardSkillsPlugin = async input => {
578
579
  const selection = selectPublishedSkills(filteredPublishedSkillsResult.fetchResult.payload, requestedSkills);
579
580
  const isSingleRequest = requestedSkills.length === 1;
580
581
  if (requestedSkills.length === 0) {
581
- const authState = await resolveStoredAuthState(input.worktree, config);
582
- const catalog = {
583
- ...toPublishedSkillCatalog(filteredPublishedSkillsResult.fetchResult.payload),
584
- availableTools: resolveAvailableTools(authState?.role ?? null)
585
- };
582
+ const catalog = toPublishedSkillCatalog(filteredPublishedSkillsResult.fetchResult.payload, registeredTools);
586
583
  context.metadata({
587
584
  title: `opencode-wizard published skills catalog: ${catalog.publishedSkillCount} active`,
588
585
  metadata: {
@@ -781,10 +778,9 @@ export const OpencodeWizardSkillsPlugin = async input => {
781
778
  }
782
779
  };
783
780
  }
784
- const authState = await resolveStoredAuthState(input.worktree, config);
785
781
  const catalog = toWizardArtifactCatalog(fetchResult.payload, {
786
782
  pluginId: PLUGIN_ID,
787
- availableTools: resolveAvailableTools(authState?.role ?? null)
783
+ availableTools: registeredTools
788
784
  });
789
785
  const cacheCursor = getWizardArtifactCatalogCursor(fetchResult.payload.artifacts, toWizardArtifactCatalogCursorItems(fetchResult.payload.catalogArtifacts));
790
786
  return {
@@ -865,10 +861,9 @@ export const OpencodeWizardSkillsPlugin = async input => {
865
861
  }
866
862
  const selection = selectWizardArtifacts(fetchResult.payload.artifacts, requestedArtifacts);
867
863
  if (requestedArtifacts.length === 0) {
868
- const authState = await resolveStoredAuthState(input.worktree, config);
869
864
  const catalog = toWizardArtifactCatalog(fetchResult.payload, {
870
865
  pluginId: PLUGIN_ID,
871
- availableTools: resolveAvailableTools(authState?.role ?? null)
866
+ availableTools: registeredTools
872
867
  });
873
868
  const cacheCursor = getWizardArtifactCatalogCursor(fetchResult.payload.artifacts, toWizardArtifactCatalogCursorItems(fetchResult.payload.catalogArtifacts));
874
869
  return {
@@ -992,7 +987,8 @@ export const OpencodeWizardSkillsPlugin = async input => {
992
987
  let snapshot = await resolvePluginStatusSnapshot({
993
988
  worktree: input.worktree,
994
989
  directory: requestedDirectory,
995
- signal: context.abort
990
+ signal: context.abort,
991
+ registeredTools
996
992
  });
997
993
  if (snapshot.status === 'missing_auth') {
998
994
  try {
@@ -1002,7 +998,8 @@ export const OpencodeWizardSkillsPlugin = async input => {
1002
998
  snapshot = await resolvePluginStatusSnapshot({
1003
999
  worktree: input.worktree,
1004
1000
  directory: requestedDirectory,
1005
- signal: context.abort
1001
+ signal: context.abort,
1002
+ registeredTools
1006
1003
  });
1007
1004
  } catch {
1008
1005
  // Keep returning the safe missing-auth snapshot when interactive login is cancelled or fails.
@@ -1554,7 +1551,7 @@ export const OpencodeWizardSkillsPlugin = async input => {
1554
1551
  })
1555
1552
  });
1556
1553
  return {
1557
- tool: initialAuthState?.role === 'EDITOR' ? {
1554
+ tool: registeredTools.includes('opencode_wizard_editor_create_or_update_skill') ? {
1558
1555
  ...sharedTools,
1559
1556
  ...editorOnlyTools
1560
1557
  } : sharedTools,