@aexol/opencode-wizard 0.1.16 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.d.ts CHANGED
@@ -65,8 +65,18 @@ export type PublishedSkillCatalogItem = {
65
65
  frontmatterDescription: string;
66
66
  checksum: string;
67
67
  publishedAt: string;
68
+ fileCount: number;
68
69
  };
69
70
  };
71
+ type PublishedSkillArtifactFilePayload = {
72
+ id: string;
73
+ relativePath: string;
74
+ contentType: string;
75
+ content: string;
76
+ checksum: string;
77
+ size: number;
78
+ sortOrder: number;
79
+ };
70
80
  type PublishedSkillFacet = {
71
81
  id: string;
72
82
  slug: string;
@@ -96,6 +106,7 @@ export type PublishedSkillDetailItem = PublishedSkillCatalogItem & {
96
106
  publishedArtifact: PublishedSkillCatalogItem['publishedArtifact'] & {
97
107
  markdownBody: string;
98
108
  renderedContent: string;
109
+ files: PublishedSkillArtifactFilePayload[];
99
110
  };
100
111
  };
101
112
  type AuthState = {
@@ -134,10 +145,12 @@ type PublishedSkillSummary = {
134
145
  includeChildren: boolean | null;
135
146
  checksum: string;
136
147
  publishedAt: string;
148
+ fileCount: number;
137
149
  identifiers: string[];
138
150
  tags: PublishedSkillTagSummary[];
139
151
  contextKind: 'global' | 'project' | 'installable';
140
152
  installPolicy: PublishedSkillInstallPolicy;
153
+ assignmentLabel: string;
141
154
  policyLabel: string;
142
155
  };
143
156
  type PublishedSkillDetail = PublishedSkillSummary & {
@@ -147,6 +160,8 @@ type PublishedSkillDetail = PublishedSkillSummary & {
147
160
  markdownDocument: string;
148
161
  markdownBody: string;
149
162
  renderedContent: string;
163
+ files: PublishedSkillArtifactFilePayload[];
164
+ resources: PublishedSkillArtifactFilePayload[];
150
165
  };
151
166
  type OpencodePluginServerInput = {
152
167
  worktree: string;
@@ -171,6 +186,7 @@ type PublishedSkillsSuccessState = {
171
186
  assignmentCounts: {
172
187
  global: number;
173
188
  project: number;
189
+ user: number;
174
190
  other: number;
175
191
  };
176
192
  facets: PublishedSkillFacetSummary[];
package/dist/server.js CHANGED
@@ -114,6 +114,7 @@ const PUBLISHED_SKILLS_CATALOG_QUERY = `
114
114
  frontmatterDescription
115
115
  checksum
116
116
  publishedAt
117
+ fileCount
117
118
  }
118
119
  }
119
120
  catalogSkills {
@@ -151,6 +152,7 @@ const PUBLISHED_SKILLS_CATALOG_QUERY = `
151
152
  frontmatterDescription
152
153
  checksum
153
154
  publishedAt
155
+ fileCount
154
156
  }
155
157
  }
156
158
  userPreferences {
@@ -195,6 +197,7 @@ const PUBLISHED_SKILLS_CATALOG_QUERY = `
195
197
  frontmatterDescription
196
198
  checksum
197
199
  publishedAt
200
+ fileCount
198
201
  }
199
202
  }
200
203
  }
@@ -245,6 +248,7 @@ const SET_PUBLISHED_SKILL_PREFERENCE_MUTATION = `
245
248
  frontmatterDescription
246
249
  checksum
247
250
  publishedAt
251
+ fileCount
248
252
  }
249
253
  }
250
254
  }
@@ -260,6 +264,16 @@ const PUBLISHED_SKILL_DETAIL_QUERY = `
260
264
  renderedContent
261
265
  checksum
262
266
  publishedAt
267
+ fileCount
268
+ files {
269
+ id
270
+ relativePath
271
+ contentType
272
+ content
273
+ checksum
274
+ size
275
+ sortOrder
276
+ }
263
277
  }
264
278
  }
265
279
  `;
@@ -601,7 +615,22 @@ const getPublishedSkillFacets = items => {
601
615
  }
602
616
  return [...facetsBySlug.values()].sort((left, right) => left.slug.localeCompare(right.slug));
603
617
  };
618
+ const isUserPublishedSkillAssignment = assignmentSource => assignmentSource === 'USER' || assignmentSource === 'USER_GLOBAL' || assignmentSource === 'USER_WORKSPACE';
619
+ const getPublishedSkillAssignmentLabel = assignmentSource => {
620
+ if (assignmentSource === 'GLOBAL') return 'GLOBAL SCOPE assignment';
621
+ if (assignmentSource === 'WORKSPACE') return 'PROJECT SCOPE assignment';
622
+ if (assignmentSource === 'USER_GLOBAL') return 'USER SCOPE preference (global target)';
623
+ if (assignmentSource === 'USER_WORKSPACE') return 'USER SCOPE preference (project target)';
624
+ if (assignmentSource === 'USER') return 'USER SCOPE assignment';
625
+ return `${assignmentSource.toUpperCase().replace(/_/gu, ' ')} assignment`;
626
+ };
604
627
  const getPublishedSkillAssignmentCounts = items => items.reduce((counts, item) => {
628
+ if (isUserPublishedSkillAssignment(item.assignmentSource)) {
629
+ return {
630
+ ...counts,
631
+ user: counts.user + 1
632
+ };
633
+ }
605
634
  if (item.assignmentSource === 'GLOBAL') {
606
635
  return {
607
636
  ...counts,
@@ -621,17 +650,22 @@ const getPublishedSkillAssignmentCounts = items => items.reduce((counts, item) =
621
650
  }, {
622
651
  global: 0,
623
652
  project: 0,
653
+ user: 0,
624
654
  other: 0
625
655
  });
626
656
  const getSkillContextKind = item => {
627
657
  if (item.assignmentSource === 'GLOBAL' || item.assignmentSource === 'USER_GLOBAL') return 'global';
628
658
  return 'project';
629
659
  };
630
- const getSkillPolicyLabel = (policy, contextKind) => {
660
+ const getSkillPolicyLabel = (policy, contextKind, assignmentSource) => {
661
+ if (isUserPublishedSkillAssignment(assignmentSource) && policy === 'GLOBAL_CONTEXT') {
662
+ return 'GLOBAL_CONTEXT · active USER SCOPE context';
663
+ }
664
+ if (isUserPublishedSkillAssignment(assignmentSource)) return 'PROJECT_INSTALLABLE · active USER SCOPE preference';
631
665
  if (policy === 'GLOBAL_CONTEXT') return 'GLOBAL_CONTEXT · active context only, not project-installable';
632
666
  if (contextKind === 'installable') return 'PROJECT_INSTALLABLE · available to install';
633
- if (contextKind === 'global') return 'PROJECT_INSTALLABLE · active global assignment';
634
- return 'PROJECT_INSTALLABLE · active project/workspace assignment';
667
+ if (contextKind === 'global') return 'PROJECT_INSTALLABLE · active GLOBAL SCOPE assignment';
668
+ return 'PROJECT_INSTALLABLE · active PROJECT SCOPE assignment';
635
669
  };
636
670
  const toPublishedSkillSummary = item => {
637
671
  const contextKind = getSkillContextKind(item);
@@ -648,11 +682,13 @@ const toPublishedSkillSummary = item => {
648
682
  includeChildren: item.includeChildren ?? null,
649
683
  checksum: item.publishedArtifact.checksum,
650
684
  publishedAt: item.publishedArtifact.publishedAt,
685
+ fileCount: item.publishedArtifact.fileCount,
651
686
  identifiers: getSkillIdentifiers(item),
652
687
  tags: item.skill.tags.map(toPublishedSkillTagSummary),
653
688
  contextKind,
654
689
  installPolicy: item.skill.installPolicy,
655
- policyLabel: getSkillPolicyLabel(item.skill.installPolicy, contextKind)
690
+ assignmentLabel: getPublishedSkillAssignmentLabel(item.assignmentSource),
691
+ policyLabel: getSkillPolicyLabel(item.skill.installPolicy, contextKind, item.assignmentSource)
656
692
  };
657
693
  };
658
694
  export const toPublishedSkillDetail = item => ({
@@ -662,7 +698,9 @@ export const toPublishedSkillDetail = item => ({
662
698
  artifactId: item.publishedArtifact.id,
663
699
  markdownDocument: buildSkillMarkdown(item),
664
700
  markdownBody: item.publishedArtifact.markdownBody,
665
- renderedContent: item.publishedArtifact.renderedContent
701
+ renderedContent: item.publishedArtifact.renderedContent,
702
+ files: item.publishedArtifact.files,
703
+ resources: item.publishedArtifact.files.filter(file => file.relativePath !== 'SKILL.md')
666
704
  });
667
705
  const toInstallableSkillSummary = item => ({
668
706
  skillSlug: item.skill.slug,
@@ -677,6 +715,7 @@ const toInstallableSkillSummary = item => ({
677
715
  includeChildren: true,
678
716
  checksum: item.publishedArtifact.checksum,
679
717
  publishedAt: item.publishedArtifact.publishedAt,
718
+ fileCount: item.publishedArtifact.fileCount,
680
719
  identifiers: getSkillIdentifiers({
681
720
  ...item,
682
721
  assignmentSource: 'CATALOG',
@@ -687,7 +726,8 @@ const toInstallableSkillSummary = item => ({
687
726
  tags: item.skill.tags.map(toPublishedSkillTagSummary),
688
727
  contextKind: 'installable',
689
728
  installPolicy: item.skill.installPolicy,
690
- policyLabel: getSkillPolicyLabel(item.skill.installPolicy, 'installable')
729
+ assignmentLabel: 'catalog skill',
730
+ policyLabel: getSkillPolicyLabel(item.skill.installPolicy, 'installable', 'CATALOG')
691
731
  });
692
732
  export const toPublishedSkillCatalog = payload => ({
693
733
  pluginId: PLUGIN_ID,
@@ -800,7 +840,9 @@ const truncateText = (value, maxLength) => {
800
840
  };
801
841
  const buildSkillCatalogLine = skill => {
802
842
  const description = truncateText(skill.whenToUse || skill.artifactDescription || skill.skillName || skill.skillSlug, SYSTEM_NOTE_SKILL_DESCRIPTION_LIMIT);
803
- return `- ${skill.artifactName || skill.skillName} (${skill.skillSlug}, ${skill.contextKind.toUpperCase()}): ${description}`;
843
+ const scopeLabel = isUserPublishedSkillAssignment(skill.assignmentSource) ? 'USER SCOPE' : skill.contextKind === 'global' ? 'GLOBAL SCOPE' : 'PROJECT SCOPE';
844
+ const assignmentLabel = skill.assignmentSource.toLowerCase().replace(/_/gu, ' ');
845
+ return `- ${skill.artifactName || skill.skillName} (${skill.skillSlug}, ${assignmentLabel} assignment) [${scopeLabel}]: ${description}`;
804
846
  };
805
847
  const buildSkillDetailSnippetLine = detail => {
806
848
  const body = detail.markdownBody || detail.renderedContent || detail.markdownDocument;
@@ -813,11 +855,12 @@ export const buildSystemNote = (result, config, details) => {
813
855
  const renderedSkillNames = skillNames.length > 0 ? skillNames.slice(0, SYSTEM_NOTE_SKILL_NAME_LIMIT).join(', ') : 'none';
814
856
  const remainingCount = Math.max(skillNames.length - SYSTEM_NOTE_SKILL_NAME_LIMIT, 0);
815
857
  const renderedCountSuffix = remainingCount > 0 ? ` (+${remainingCount} more)` : '';
816
- const globalSkills = catalog.skills.filter(skill => skill.contextKind === 'global').slice(0, 8).map(buildSkillCatalogLine);
817
- const projectSkills = catalog.skills.filter(skill => skill.contextKind === 'project').slice(0, 5).map(buildSkillCatalogLine);
858
+ const globalSkills = catalog.skills.filter(skill => skill.contextKind === 'global' && !isUserPublishedSkillAssignment(skill.assignmentSource)).slice(0, 8).map(buildSkillCatalogLine);
859
+ const projectSkills = catalog.skills.filter(skill => skill.contextKind === 'project' && !isUserPublishedSkillAssignment(skill.assignmentSource)).slice(0, 5).map(buildSkillCatalogLine);
860
+ const userSkills = catalog.skills.filter(skill => isUserPublishedSkillAssignment(skill.assignmentSource)).slice(0, 5).map(buildSkillCatalogLine);
818
861
  const detailLines = details.slice(0, SYSTEM_NOTE_DETAIL_LIMIT).map(buildSkillDetailSnippetLine);
819
862
  const detailBlock = detailLines.length > 0 ? ` Loaded body snippets (capped):\n${truncateText(detailLines.join('\n'), SYSTEM_NOTE_DETAIL_CHAR_LIMIT)}` : '';
820
- return [result.fetchResult.payload.workspace ? `Prefer opencode-wizard backend-published fetched skill bodies for scoped/private wizard skills in workspace ${result.fetchResult.payload.workspace.slug}.` : 'Prefer opencode-wizard backend-published global fetched skill bodies; workspace-specific skills are unavailable because the workspace was not found.', `Current directory: ${result.directoryPath}.`, `Published skills for this scope: ${renderedSkillNames}${renderedCountSuffix}; counts: ${catalog.assignmentCounts.global} global, ${catalog.assignmentCounts.project} project, ${catalog.assignmentCounts.other} other.`, 'Use catalog whenToUse guidance to decide applicability; when it matches the task, fetch full bodies with opencode_wizard_published_skills_fetch and prefer those fetched bodies for current scoped/private wizard guidance.', 'GLOBAL_CONTEXT skills are active context skills and are not project-installable; PROJECT_INSTALLABLE skills can be assigned globally or to project/workspace scopes; assignment rows decide which skills are active here.', globalSkills.length > 0 ? `Global context skills:\n${globalSkills.join('\n')}` : 'Global context skills: none.', projectSkills.length > 0 ? `Project-scoped active skills:\n${projectSkills.join('\n')}` : 'Project-scoped active skills: none.', detailBlock, 'Local/native sources can still complement wizard skills: .opencode/skills is source seed content, skills.urls is a public/static complement, and backend-published fetched bodies are preferred for private/scoped wizard guidance.', `Root source seed path remains seed/source content: ${config.rootSkillSeedPath}/**.`].filter(line => line.length > 0).join(' ');
863
+ return [result.fetchResult.payload.workspace ? `Prefer opencode-wizard backend-published fetched skill bodies for scoped/private wizard skills in workspace ${result.fetchResult.payload.workspace.slug}.` : 'Prefer opencode-wizard backend-published global fetched skill bodies; workspace-specific skills are unavailable because the workspace was not found.', `Current directory: ${result.directoryPath}.`, `Published skills for this scope: ${renderedSkillNames}${renderedCountSuffix}; counts: ${catalog.assignmentCounts.global} global, ${catalog.assignmentCounts.project} workspace, ${catalog.assignmentCounts.user} user, ${catalog.assignmentCounts.other} other (GLOBAL SCOPE: ${catalog.assignmentCounts.global}, PROJECT SCOPE: ${catalog.assignmentCounts.project}, USER SCOPE: ${catalog.assignmentCounts.user}).`, 'Use catalog whenToUse guidance to decide applicability; when it matches the task, fetch full bodies with opencode_wizard_published_skills_fetch and prefer those fetched bodies for current scoped/private wizard guidance.', 'GLOBAL_CONTEXT skills are active context skills and are not project-installable; PROJECT_INSTALLABLE skills can be assigned to GLOBAL SCOPE, PROJECT SCOPE, or USER SCOPE; assignment rows decide which scope is active here.', globalSkills.length > 0 ? `GLOBAL SCOPE / Global context skills:\n${globalSkills.join('\n')}` : 'GLOBAL SCOPE / Global context skills: none.', projectSkills.length > 0 ? `PROJECT SCOPE / Project-scoped active skills:\n${projectSkills.join('\n')}` : 'PROJECT SCOPE / Project-scoped active skills: none.', userSkills.length > 0 ? `USER SCOPE / User-scoped active skills:\n${userSkills.join('\n')}` : 'USER SCOPE / User-scoped active skills: none.', detailBlock, 'Local/native sources can still complement wizard skills: .opencode/skills is source seed content, skills.urls is a public/static complement, and backend-published fetched bodies are preferred for private/scoped wizard guidance.', `Root source seed path remains seed/source content: ${config.rootSkillSeedPath}/**.`].filter(line => line.length > 0).join(' ');
821
864
  };
822
865
  const toWorkspaceResolutionOutput = resolution => ({
823
866
  requestedDirectory: resolution.requestedDirectory,
@@ -2263,6 +2306,7 @@ const OpencodeWizardSkillsPlugin = async input => {
2263
2306
  publishedSkillCount: catalog.publishedSkillCount.toString(),
2264
2307
  globalAssignmentCount: catalog.assignmentCounts.global.toString(),
2265
2308
  projectAssignmentCount: catalog.assignmentCounts.project.toString(),
2309
+ userAssignmentCount: catalog.assignmentCounts.user.toString(),
2266
2310
  ignoredSkillCount: filteredPublishedSkillsResult.ignoreState.ignoredSkillSlugs.length.toString()
2267
2311
  }
2268
2312
  });
@@ -2285,6 +2329,9 @@ const OpencodeWizardSkillsPlugin = async input => {
2285
2329
  status: 'ready',
2286
2330
  ...toWorkspaceResolutionMetadata(filteredPublishedSkillsResult.workspaceResolution),
2287
2331
  publishedSkillCount: catalog.publishedSkillCount.toString(),
2332
+ globalAssignmentCount: catalog.assignmentCounts.global.toString(),
2333
+ projectAssignmentCount: catalog.assignmentCounts.project.toString(),
2334
+ userAssignmentCount: catalog.assignmentCounts.user.toString(),
2288
2335
  ignoredSkillCount: filteredPublishedSkillsResult.ignoreState.ignoredSkillSlugs.length.toString()
2289
2336
  }
2290
2337
  };