@aexol/opencode-wizard 0.3.13 → 0.4.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.
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- import { CREATE_OR_UPDATE_SKILL_FROM_MARKDOWN_MUTATION, IMPORT_WIZARD_ARTIFACT_SNAPSHOT_MUTATION, SET_WIZARD_ARTIFACT_PREFERENCE_MUTATION } from '../graphql-operations.js';
3
+ import { BULK_CREATE_SKILL_ASSIGNMENTS_MUTATION, CREATE_OR_UPDATE_SKILL_FROM_MARKDOWN_MUTATION, EDITOR_SKILL_WORKSPACE_ASSIGNMENT_LOOKUP_QUERY, IMPORT_WIZARD_ARTIFACT_SNAPSHOT_MUTATION, SET_WIZARD_ARTIFACT_PREFERENCE_MUTATION } from '../graphql-operations.js';
4
4
  import { createPublishedSkillToolDefinitions, resolveAvailableTools } from '../plugin-tools.js';
5
5
  import { resolveStoredAuthState, toAuthState, writeAuthState } from './auth-store.js';
6
6
  import { resolveConfig } from './config.js';
@@ -537,7 +537,9 @@ export const OpencodeWizardSkillsPlugin = async input => {
537
537
  requestedDirectoryPath: directoryPath,
538
538
  workspaceResolution: toWorkspaceResolutionOutput(workspaceResolution),
539
539
  requestedSkillVersionId: item.skillVersion.id,
540
+ requestedArtifactVersionId: item.publishedArtifact.id,
540
541
  message: detailResult.result.message,
542
+ graphQlErrors: 'graphQlErrors' in detailResult.result ? detailResult.result.graphQlErrors : undefined,
541
543
  fetchedAt: detailResult.result.fetchedAt,
542
544
  source: detailResult.result.source
543
545
  }, null, 2),
@@ -1387,6 +1389,127 @@ export const OpencodeWizardSkillsPlugin = async input => {
1387
1389
  });
1388
1390
  return withWizardArtifactEnvelope(result, artifactKind);
1389
1391
  };
1392
+ const createEditorWorkspaceSkillAssignment = async ({
1393
+ skillSlug,
1394
+ skillVersionId,
1395
+ workspaceResolution,
1396
+ signal
1397
+ }) => {
1398
+ if (!skillSlug || !skillVersionId) {
1399
+ return {
1400
+ status: 'skipped',
1401
+ directoryPath: workspaceResolution.directoryPath,
1402
+ workspaceSlug: workspaceResolution.workspaceSlug,
1403
+ message: 'Skill creation did not return a skill slug or version id, so no workspace assignment was created.'
1404
+ };
1405
+ }
1406
+ if (!workspaceResolution.workspaceSlug) {
1407
+ return {
1408
+ status: 'skipped',
1409
+ directoryPath: workspaceResolution.directoryPath,
1410
+ workspaceSlug: null,
1411
+ message: 'No resolved workspace slug was available for this directory context.'
1412
+ };
1413
+ }
1414
+ const lookupResponse = await fetchPublishedSkillsGraphQl({
1415
+ worktree: input.worktree,
1416
+ config,
1417
+ query: EDITOR_SKILL_WORKSPACE_ASSIGNMENT_LOOKUP_QUERY,
1418
+ variables: {
1419
+ skillSlug,
1420
+ workspaceSlug: workspaceResolution.workspaceSlug
1421
+ },
1422
+ signal,
1423
+ operationName: 'editorSkillWorkspaceAssignmentLookup'
1424
+ });
1425
+ if (!lookupResponse.ok) {
1426
+ return {
1427
+ status: 'failed',
1428
+ directoryPath: workspaceResolution.directoryPath,
1429
+ workspaceSlug: workspaceResolution.workspaceSlug,
1430
+ message: lookupResponse.result.message
1431
+ };
1432
+ }
1433
+ const {
1434
+ skill,
1435
+ workspace
1436
+ } = lookupResponse.data.admin;
1437
+ if (!skill) {
1438
+ return {
1439
+ status: 'failed',
1440
+ directoryPath: workspaceResolution.directoryPath,
1441
+ workspaceSlug: workspaceResolution.workspaceSlug,
1442
+ message: `Created skill ${skillSlug} could not be resolved for workspace assignment.`
1443
+ };
1444
+ }
1445
+ if (!workspace) {
1446
+ return {
1447
+ status: 'skipped',
1448
+ directoryPath: workspaceResolution.directoryPath,
1449
+ workspaceSlug: workspaceResolution.workspaceSlug,
1450
+ message: `Resolved workspace ${workspaceResolution.workspaceSlug} was not found in the backend.`
1451
+ };
1452
+ }
1453
+ const assignmentResponse = await fetchPublishedSkillsGraphQl({
1454
+ worktree: input.worktree,
1455
+ config,
1456
+ query: BULK_CREATE_SKILL_ASSIGNMENTS_MUTATION,
1457
+ variables: {
1458
+ input: {
1459
+ scopePathAssignments: [{
1460
+ workspaceId: workspace.id,
1461
+ skillId: skill.id,
1462
+ skillVersionId,
1463
+ assignmentType: 'PATH',
1464
+ scopePath: workspaceResolution.directoryPath,
1465
+ includeChildren: true,
1466
+ status: 'ACTIVE',
1467
+ notes: 'Created by opencode-wizard editor skill publishing.'
1468
+ }]
1469
+ }
1470
+ },
1471
+ signal,
1472
+ operationName: 'bulkCreateSkillAssignments'
1473
+ });
1474
+ if (!assignmentResponse.ok) {
1475
+ return {
1476
+ status: 'failed',
1477
+ directoryPath: workspaceResolution.directoryPath,
1478
+ workspaceSlug: workspace.slug,
1479
+ workspaceId: workspace.id,
1480
+ message: assignmentResponse.result.message
1481
+ };
1482
+ }
1483
+ const assignmentResult = assignmentResponse.data.admin.bulkCreateSkillAssignments;
1484
+ const [createdAssignment] = assignmentResult.scopePathAssignments;
1485
+ if (createdAssignment) {
1486
+ return {
1487
+ status: 'created',
1488
+ directoryPath: workspaceResolution.directoryPath,
1489
+ workspaceSlug: workspace.slug,
1490
+ workspaceId: workspace.id,
1491
+ assignmentId: createdAssignment.id
1492
+ };
1493
+ }
1494
+ const [skippedAssignment] = assignmentResult.skippedScopePathAssignments;
1495
+ if (skippedAssignment) {
1496
+ return {
1497
+ status: 'already_exists',
1498
+ directoryPath: workspaceResolution.directoryPath,
1499
+ workspaceSlug: workspace.slug,
1500
+ workspaceId: workspace.id,
1501
+ assignmentId: skippedAssignment.id
1502
+ };
1503
+ }
1504
+ const conflictMessage = assignmentResult.conflicts.map(conflict => conflict.message).join('; ');
1505
+ return {
1506
+ status: 'failed',
1507
+ directoryPath: workspaceResolution.directoryPath,
1508
+ workspaceSlug: workspace.slug,
1509
+ workspaceId: workspace.id,
1510
+ message: conflictMessage || 'Workspace assignment was not created and no existing matching assignment was returned.'
1511
+ };
1512
+ };
1390
1513
  const executeEditorCreateOrUpdateSkillMarkdown = async ({
1391
1514
  markdownContent,
1392
1515
  context,
@@ -1413,7 +1536,11 @@ export const OpencodeWizardSkillsPlugin = async input => {
1413
1536
  throw new Error('Editor skill create/update requires non-empty markdownContent.');
1414
1537
  }
1415
1538
  const requestedDirectory = normalizeDirectoryArg(context.directory, undefined);
1416
- const directoryPath = normalizeRepositoryPath(workspacePath, requestedDirectory);
1539
+ const workspaceResolution = await resolveWorkspace({
1540
+ config,
1541
+ directory: requestedDirectory
1542
+ });
1543
+ const directoryPath = workspaceResolution.directoryPath;
1417
1544
  lastInteractiveDirectoryPath = directoryPath;
1418
1545
  const response = await fetchPublishedSkillsGraphQl({
1419
1546
  worktree: input.worktree,
@@ -1441,6 +1568,15 @@ export const OpencodeWizardSkillsPlugin = async input => {
1441
1568
  };
1442
1569
  }
1443
1570
  const payload = response.data.admin.createOrUpdateSkillFromMarkdown;
1571
+ const workspaceAssignment = payload.success ? await createEditorWorkspaceSkillAssignment({
1572
+ skillSlug: payload.skillSlug,
1573
+ skillVersionId: payload.skillVersionId,
1574
+ workspaceResolution,
1575
+ signal: context.abort
1576
+ }) : null;
1577
+ if (payload.success) {
1578
+ clearPublishedSkillState();
1579
+ }
1444
1580
  await scheduleInteractivePresenceStart();
1445
1581
  return {
1446
1582
  output: JSON.stringify({
@@ -1451,16 +1587,20 @@ export const OpencodeWizardSkillsPlugin = async input => {
1451
1587
  skillVersionId: payload.skillVersionId,
1452
1588
  artifactSlug: payload.artifactSlug,
1453
1589
  artifactVersionId: payload.artifactVersionId,
1590
+ workspaceAssignment,
1454
1591
  requestedDirectoryPath: directoryPath,
1592
+ workspaceResolution: toWorkspaceResolutionOutput(workspaceResolution),
1455
1593
  errors: payload.errors,
1456
- message: source === 'direct_markdown' ? 'Skill markdown was sent directly to the backend; no local seed file was required.' : 'Local seed SKILL.md was published through the backend skill markdown mutation.'
1594
+ message: source === 'direct_markdown' ? 'Skill markdown was sent directly to the backend; no local seed file was required. Workspace assignments are created when a backend workspace resolves for the directory.' : 'Local seed SKILL.md was published through the backend skill markdown mutation. Workspace assignments are created when a backend workspace resolves for the directory.'
1457
1595
  }, null, 2),
1458
1596
  metadata: {
1459
1597
  status: payload.success ? 'created_or_updated' : 'create_or_update_failed',
1460
1598
  skillSlug: payload.skillSlug,
1461
1599
  skillVersionId: payload.skillVersionId ?? '',
1462
1600
  source,
1463
- directoryPath
1601
+ directoryPath,
1602
+ workspaceAssignmentStatus: workspaceAssignment?.status ?? '',
1603
+ workspaceAssignmentId: workspaceAssignment?.assignmentId ?? ''
1464
1604
  }
1465
1605
  };
1466
1606
  };