@aexol/opencode-wizard 0.3.4 → 0.3.6
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 +11 -7
- package/dist/graphql-operations.d.ts +6 -2
- package/dist/graphql-operations.js +173 -156
- package/dist/graphql-operations.js.map +1 -1
- package/dist/plugin-tools.d.ts +37 -0
- package/dist/plugin-tools.js +58 -7
- package/dist/plugin-tools.js.map +1 -1
- package/dist/published-skills-system-note.js +3 -7
- package/dist/published-skills-system-note.js.map +1 -1
- package/dist/published-skills-terminology.d.ts +21 -0
- package/dist/published-skills-terminology.js +38 -0
- package/dist/published-skills-terminology.js.map +1 -0
- package/dist/published-skills-transform.d.ts +99 -2
- package/dist/published-skills-transform.js +91 -19
- package/dist/published-skills-transform.js.map +1 -1
- package/dist/server/auth-bootstrap.d.ts +7 -0
- package/dist/server/auth-bootstrap.js +89 -0
- package/dist/server/auth-bootstrap.js.map +1 -0
- package/dist/server/client.d.ts +30 -1
- package/dist/server/client.js +81 -1
- package/dist/server/client.js.map +1 -1
- package/dist/server/import-sources.d.ts +27 -0
- package/dist/server/import-sources.js +115 -0
- package/dist/server/import-sources.js.map +1 -0
- package/dist/server/preferences.d.ts +22 -0
- package/dist/server/preferences.js +121 -0
- package/dist/server/preferences.js.map +1 -0
- package/dist/server/runtime.d.ts +3 -22
- package/dist/server/runtime.js +567 -242
- package/dist/server/runtime.js.map +1 -1
- package/dist/server/types.d.ts +87 -0
- package/dist/server/types.js.map +1 -1
- package/dist/server.d.ts +1 -0
- package/dist/server.js +1 -0
- package/dist/server.js.map +1 -1
- package/dist/smoke-published-skills.js +4 -4
- package/dist/smoke-published-skills.js.map +1 -1
- package/dist/tui/components/common.d.ts +0 -1
- package/dist/tui/components/common.js +6 -29
- package/dist/tui/components/common.js.map +1 -1
- package/dist/tui/components/status-content.js +1 -1
- package/dist/tui/components/status-content.js.map +1 -1
- package/dist/tui/constants.d.ts +0 -5
- package/dist/tui/constants.js +0 -5
- package/dist/tui/constants.js.map +1 -1
- package/dist/tui/formatting.d.ts +0 -3
- package/dist/tui/formatting.js +1 -13
- package/dist/tui/formatting.js.map +1 -1
- package/dist/tui/skill-helpers.d.ts +1 -11
- package/dist/tui/skill-helpers.js +0 -41
- package/dist/tui/skill-helpers.js.map +1 -1
- package/dist/tui/slots.d.ts +1 -1
- package/dist/tui/slots.js +1 -24
- package/dist/tui/slots.js.map +1 -1
- package/dist/tui/status.js +2 -2
- package/dist/tui/status.js.map +1 -1
- package/dist/tui/types.d.ts +0 -19
- package/dist/tui/types.js.map +1 -1
- package/package.json +1 -1
- package/dist/tui/components/preference-action-notice-row.d.ts +0 -5
- package/dist/tui/components/preference-action-notice-row.js +0 -17
- package/dist/tui/components/preference-action-notice-row.js.map +0 -1
- package/dist/tui/components/skill-catalog-row.d.ts +0 -8
- package/dist/tui/components/skill-catalog-row.js +0 -124
- package/dist/tui/components/skill-catalog-row.js.map +0 -1
- package/dist/tui/components/wizard-skills-dialog-content.d.ts +0 -9
- package/dist/tui/components/wizard-skills-dialog-content.js +0 -219
- package/dist/tui/components/wizard-skills-dialog-content.js.map +0 -1
- package/dist/tui/components/wizard-skills-dialog.d.ts +0 -7
- package/dist/tui/components/wizard-skills-dialog.js +0 -156
- package/dist/tui/components/wizard-skills-dialog.js.map +0 -1
package/dist/server/runtime.js
CHANGED
|
@@ -1,226 +1,98 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { CREATE_OR_UPDATE_SKILL_FROM_MARKDOWN_MUTATION,
|
|
4
|
-
import { createPublishedSkillToolDefinitions } from '../plugin-tools.js';
|
|
5
|
-
import {
|
|
3
|
+
import { CREATE_OR_UPDATE_SKILL_FROM_MARKDOWN_MUTATION, IMPORT_WIZARD_ARTIFACT_SNAPSHOT_MUTATION, SET_WIZARD_ARTIFACT_PREFERENCE_MUTATION } from '../graphql-operations.js';
|
|
4
|
+
import { createPublishedSkillToolDefinitions, resolveAvailableTools } from '../plugin-tools.js';
|
|
5
|
+
import { resolveStoredAuthState, toAuthState, writeAuthState } from './auth-store.js';
|
|
6
6
|
import { resolveConfig } from './config.js';
|
|
7
7
|
export { resolveConfig } from './config.js';
|
|
8
8
|
import { createPluginSession, openBrowser, startLoginFlow } from './auth-flow.js';
|
|
9
|
-
import { fetchPublishedSkillDetail, fetchPublishedSkillsCatalog, fetchPublishedSkillsGraphQl, maybePersistWorkspaceSlugFromCatalog } from './client.js';
|
|
9
|
+
import { fetchPublishedSkillDetail, fetchPublishedSkillsCatalog, fetchPublishedSkillsGraphQl, fetchWizardArtifactDetail, fetchWizardArtifactsCatalog, maybePersistWorkspaceSlugFromCatalog } from './client.js';
|
|
10
10
|
import { normalizeAbsolutePath } from './path-utils.js';
|
|
11
11
|
import { emitPluginActionEvent, emitPresenceEvent } from './presence.js';
|
|
12
|
-
import { normalizeDirectoryArg, normalizeRepositoryPath, resolveWorkspace,
|
|
13
|
-
import { parseRequestedSkillArgs, selectPublishedSkills, toPublishedSkillDetail, toPublishedSkillSummary } from '../published-skills-transform.js';
|
|
14
|
-
import { CACHE_TTL_MS, LOGIN_TIMEOUT_MS, OIDC_CALLBACK_URL, PLUGIN_ID,
|
|
12
|
+
import { normalizeDirectoryArg, normalizeRepositoryPath, resolveWorkspace, toWorkspaceResolutionMetadata, toWorkspaceResolutionOutput } from './workspace.js';
|
|
13
|
+
import { parseRequestedSkillArgs, selectPublishedSkills, toPublishedSkillDetail, toPublishedSkillSummary, toWizardArtifactCatalog, toWizardArtifactDetail, toWizardArtifactSummary } from '../published-skills-transform.js';
|
|
14
|
+
import { CACHE_TTL_MS, LOGIN_TIMEOUT_MS, OIDC_CALLBACK_URL, PLUGIN_ID, PRESENCE_SHUTDOWN_SIGNALS, PRESENCE_SIGNAL_EXIT_CODES } from './constants.js';
|
|
15
15
|
export { PLUGIN_ID, NATIVE_SKILLS_URL_COMPATIBILITY } from './constants.js';
|
|
16
|
-
import { buildSystemNote, filterIgnoredPublishedSkills, resolvePluginStatusSnapshot, toAiFacingPluginStatusSnapshot, toFetchFailureOutput, toPluginStatusMetadata, toPublishedSkillCatalog
|
|
16
|
+
import { buildSystemNote, filterIgnoredPublishedSkills, resolvePluginStatusSnapshot, toAiFacingPluginStatusSnapshot, toFetchFailureOutput, toPluginStatusMetadata, toPublishedSkillCatalog } from './status.js';
|
|
17
|
+
import { createIdleLoginBootstrapSnapshot } from './auth-bootstrap.js';
|
|
18
|
+
import { fetchWizardArtifactImportSource, planWizardArtifactImport } from './import-sources.js';
|
|
19
|
+
import { getCatalogCacheKey, resolvePublishedSkillPreferenceCacheContext, setPublishedSkillIgnored, setPublishedSkillInstalled, toPublishedSkillPreferenceAction, toPublishedSkillPreferenceScope } from './preferences.js';
|
|
17
20
|
export { buildSystemNote, resolvePluginStatusSnapshot, toPluginAuthStateSummary, toPublishedSkillCatalog } from './status.js';
|
|
18
|
-
const createIdleLoginBootstrapSnapshot = () => ({
|
|
19
|
-
status: 'idle',
|
|
20
|
-
trigger: null,
|
|
21
|
-
startedAt: null,
|
|
22
|
-
expiresAt: null,
|
|
23
|
-
browserUrl: null,
|
|
24
|
-
browserOpenError: null,
|
|
25
|
-
email: null,
|
|
26
|
-
message: null
|
|
27
|
-
});
|
|
28
|
-
const STATUS_PATH_LOGIN_RETRY_COOLDOWN_MS = 60_000;
|
|
29
|
-
const statusPathLoginBootstrap = {
|
|
30
|
-
promise: null,
|
|
31
|
-
status: 'idle',
|
|
32
|
-
message: null,
|
|
33
|
-
failedAt: null
|
|
34
|
-
};
|
|
35
21
|
const importOpencodePluginModule = new Function('specifier', 'return import(specifier)');
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return normalized;
|
|
41
|
-
};
|
|
42
|
-
const toPublishedSkillPreferenceAction = value => {
|
|
43
|
-
const normalized = value.trim().toLowerCase();
|
|
44
|
-
if (normalized === 'install' || normalized === 'uninstall' || normalized === 'ignore' || normalized === 'unignore') {
|
|
45
|
-
return normalized;
|
|
46
|
-
}
|
|
47
|
-
throw new Error('Published skill preference action must be one of: install, uninstall, ignore, unignore.');
|
|
48
|
-
};
|
|
49
|
-
const toPublishedSkillPreferenceScope = (value, defaultScope) => {
|
|
50
|
-
if (!value) return defaultScope;
|
|
51
|
-
const normalized = value.trim().toLowerCase();
|
|
52
|
-
if (normalized === 'global' || normalized === 'project') return normalized;
|
|
53
|
-
throw new Error('Published skill preferenceScope must be either global or project.');
|
|
22
|
+
export { resolvePluginStatusSnapshotWithAuthBootstrap } from './auth-bootstrap.js';
|
|
23
|
+
export { setPublishedSkillIgnored, setPublishedSkillInstalled } from './preferences.js';
|
|
24
|
+
const getDetailCacheKey = (catalogCacheKey, skillVersionId) => {
|
|
25
|
+
return JSON.stringify([catalogCacheKey, skillVersionId]);
|
|
54
26
|
};
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
userKey: toStoredUserKey(authState),
|
|
59
|
-
preferenceVersion: publishedSkillPreferenceCacheVersion
|
|
60
|
-
};
|
|
27
|
+
const getDetailInflightKey = (catalogCacheKey, skillVersionId, purpose) => {
|
|
28
|
+
return JSON.stringify([catalogCacheKey, skillVersionId, purpose]);
|
|
61
29
|
};
|
|
62
|
-
const
|
|
63
|
-
|
|
30
|
+
const SUPPORTED_WIZARD_ARTIFACT_KINDS = ['SKILL', 'DESIGN_DOC'];
|
|
31
|
+
const DESIGN_DOC_UNSUPPORTED_MESSAGE = 'DESIGN_DOC is supported by generic wizard artifact persistence; use catalog/detail tools for assigned or installed documents.';
|
|
32
|
+
const toWizardArtifactKind = value => {
|
|
33
|
+
if (!value) return 'SKILL';
|
|
34
|
+
const normalized = value.trim().toUpperCase().replace(/[-\s]+/gu, '_');
|
|
35
|
+
if (normalized === 'SKILL') return 'SKILL';
|
|
36
|
+
if (normalized === 'DESIGN_DOC') return 'DESIGN_DOC';
|
|
37
|
+
return null;
|
|
64
38
|
};
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
39
|
+
const buildUnsupportedWizardArtifactOutput = ({
|
|
40
|
+
artifactKind,
|
|
41
|
+
directoryPath
|
|
42
|
+
}) => ({
|
|
43
|
+
output: JSON.stringify({
|
|
44
|
+
pluginId: PLUGIN_ID,
|
|
45
|
+
runtimeMode: 'tool_fetch_only',
|
|
46
|
+
status: artifactKind === 'DESIGN_DOC' ? 'unsupported' : 'bad_artifact_kind',
|
|
47
|
+
artifactKind,
|
|
48
|
+
supportedArtifactKinds: SUPPORTED_WIZARD_ARTIFACT_KINDS,
|
|
49
|
+
requestedDirectoryPath: directoryPath,
|
|
50
|
+
message: artifactKind === 'DESIGN_DOC' ? DESIGN_DOC_UNSUPPORTED_MESSAGE : 'Unsupported wizard artifact kind. Use SKILL or DESIGN_DOC.'
|
|
51
|
+
}, null, 2),
|
|
52
|
+
metadata: {
|
|
53
|
+
status: artifactKind === 'DESIGN_DOC' ? 'unsupported' : 'bad_artifact_kind',
|
|
54
|
+
artifactKind,
|
|
55
|
+
directoryPath
|
|
69
56
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
57
|
+
});
|
|
58
|
+
const withWizardArtifactEnvelope = (result, artifactKind) => {
|
|
59
|
+
if (!result || typeof result !== 'object' || !('output' in result)) return result;
|
|
60
|
+
const outputResult = result;
|
|
61
|
+
if (typeof outputResult.output !== 'string') return result;
|
|
62
|
+
try {
|
|
63
|
+
return {
|
|
64
|
+
...outputResult,
|
|
65
|
+
output: JSON.stringify({
|
|
66
|
+
...JSON.parse(outputResult.output),
|
|
67
|
+
artifactKind,
|
|
68
|
+
supportedArtifactKinds: SUPPORTED_WIZARD_ARTIFACT_KINDS,
|
|
69
|
+
compatibilityAliases: ['opencode_wizard_published_skills_fetch', 'opencode_wizard_published_skill_preference_set']
|
|
70
|
+
}, null, 2),
|
|
71
|
+
metadata: {
|
|
72
|
+
...(outputResult.metadata ?? {}),
|
|
73
|
+
artifactKind
|
|
87
74
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
redirectUri: OIDC_CALLBACK_URL,
|
|
92
|
-
config,
|
|
93
|
-
signal: loginSignal
|
|
94
|
-
});
|
|
95
|
-
const authState = toAuthState(pluginSession);
|
|
96
|
-
await writeAuthState(config.authStatePath, authState);
|
|
97
|
-
statusPathLoginBootstrap.status = 'authenticated';
|
|
98
|
-
statusPathLoginBootstrap.message = `Browser login completed successfully for ${authState.email}.`;
|
|
99
|
-
return authState;
|
|
100
|
-
} finally {
|
|
101
|
-
await loginStart.closeCallbackServer().catch(() => undefined);
|
|
102
|
-
}
|
|
103
|
-
})().catch(error => {
|
|
104
|
-
statusPathLoginBootstrap.status = 'failed';
|
|
105
|
-
statusPathLoginBootstrap.failedAt = Date.now();
|
|
106
|
-
statusPathLoginBootstrap.message = error instanceof Error ? error.message : 'Browser login failed.';
|
|
107
|
-
throw error;
|
|
108
|
-
}).finally(() => {
|
|
109
|
-
statusPathLoginBootstrap.promise = null;
|
|
110
|
-
});
|
|
111
|
-
statusPathLoginBootstrap.promise.catch(() => undefined);
|
|
112
|
-
};
|
|
113
|
-
export const resolvePluginStatusSnapshotWithAuthBootstrap = async ({
|
|
114
|
-
worktree,
|
|
115
|
-
directory,
|
|
116
|
-
signal
|
|
117
|
-
}) => {
|
|
118
|
-
const snapshot = await resolvePluginStatusSnapshot({
|
|
119
|
-
worktree,
|
|
120
|
-
directory,
|
|
121
|
-
signal
|
|
122
|
-
});
|
|
123
|
-
if (snapshot.status !== 'missing_auth') return snapshot;
|
|
124
|
-
const config = await resolveConfig(worktree);
|
|
125
|
-
startStatusPathLoginBootstrap(worktree, config);
|
|
126
|
-
if (statusPathLoginBootstrap.message) {
|
|
127
|
-
return withStatusMessage(snapshot, statusPathLoginBootstrap.message);
|
|
75
|
+
};
|
|
76
|
+
} catch {
|
|
77
|
+
return result;
|
|
128
78
|
}
|
|
129
|
-
return withStatusMessage(snapshot, 'Browser login is pending from the TUI/status path.');
|
|
130
79
|
};
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
return
|
|
80
|
+
const matchesWizardArtifactIdentifier = (item, identifier) => {
|
|
81
|
+
const normalizedIdentifier = identifier.trim().toLowerCase();
|
|
82
|
+
if (!normalizedIdentifier) return false;
|
|
83
|
+
if (item.artifact.slug.toLowerCase() === normalizedIdentifier) return true;
|
|
84
|
+
if (item.artifact.name.toLowerCase() === normalizedIdentifier) return true;
|
|
85
|
+
if (item.artifactVersion.frontmatterName.toLowerCase() === normalizedIdentifier) return true;
|
|
86
|
+
return item.artifactVersion.id.toLowerCase() === normalizedIdentifier;
|
|
134
87
|
};
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
config,
|
|
139
|
-
skillSlug,
|
|
140
|
-
preferenceScope,
|
|
141
|
-
installed,
|
|
142
|
-
ignored
|
|
143
|
-
}) => {
|
|
144
|
-
const workspaceResolution = await resolveWorkspace({
|
|
145
|
-
config,
|
|
146
|
-
directory
|
|
147
|
-
});
|
|
148
|
-
const response = await fetchPublishedSkillsGraphQl({
|
|
149
|
-
worktree,
|
|
150
|
-
config,
|
|
151
|
-
query: SET_PUBLISHED_SKILL_PREFERENCE_MUTATION,
|
|
152
|
-
variables: {
|
|
153
|
-
input: {
|
|
154
|
-
...toDeliveryInput(workspaceResolution),
|
|
155
|
-
skillSlug,
|
|
156
|
-
preferenceScope: toBackendPreferenceScope(preferenceScope),
|
|
157
|
-
installed,
|
|
158
|
-
ignored
|
|
159
|
-
}
|
|
160
|
-
},
|
|
161
|
-
signal: AbortSignal.timeout(PRESENCE_EVENT_TIMEOUT_MS)
|
|
162
|
-
});
|
|
163
|
-
if (!response.ok) {
|
|
164
|
-
throw new Error(response.result.message);
|
|
165
|
-
}
|
|
166
|
-
const preferences = response.data.setPublishedSkillPreference;
|
|
167
|
-
publishedSkillPreferenceCacheVersion += 1;
|
|
88
|
+
const selectWizardArtifacts = (items, identifiers) => {
|
|
89
|
+
const selectedItems = items.filter(item => identifiers.some(identifier => matchesWizardArtifactIdentifier(item, identifier)));
|
|
90
|
+
const missingIdentifiers = identifiers.filter(identifier => !selectedItems.some(item => matchesWizardArtifactIdentifier(item, identifier)));
|
|
168
91
|
return {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
ignoredSkillSlugs: preferences.ignoredSkills.map(item => item.skill.slug),
|
|
172
|
-
installedGlobalSkillSlugs: [],
|
|
173
|
-
installedWorkspaceSkillSlugs: []
|
|
92
|
+
selectedItems,
|
|
93
|
+
missingIdentifiers
|
|
174
94
|
};
|
|
175
95
|
};
|
|
176
|
-
export const setPublishedSkillIgnored = async ({
|
|
177
|
-
worktree,
|
|
178
|
-
directory,
|
|
179
|
-
skillSlug,
|
|
180
|
-
ignored,
|
|
181
|
-
preferenceScope
|
|
182
|
-
}) => {
|
|
183
|
-
const config = await resolveConfig(worktree);
|
|
184
|
-
const normalizedSkillSlug = toIgnoredSkillSlug(skillSlug);
|
|
185
|
-
if (!normalizedSkillSlug) {
|
|
186
|
-
throw new Error('Cannot toggle an empty published skill slug.');
|
|
187
|
-
}
|
|
188
|
-
return setPublishedSkillPreference({
|
|
189
|
-
worktree,
|
|
190
|
-
directory,
|
|
191
|
-
config,
|
|
192
|
-
skillSlug: normalizedSkillSlug,
|
|
193
|
-
preferenceScope: preferenceScope ?? 'project',
|
|
194
|
-
ignored
|
|
195
|
-
});
|
|
196
|
-
};
|
|
197
|
-
export const setPublishedSkillInstalled = async ({
|
|
198
|
-
worktree,
|
|
199
|
-
directory,
|
|
200
|
-
skillSlug,
|
|
201
|
-
installed,
|
|
202
|
-
preferenceScope
|
|
203
|
-
}) => {
|
|
204
|
-
const config = await resolveConfig(worktree);
|
|
205
|
-
const normalizedSkillSlug = toIgnoredSkillSlug(skillSlug);
|
|
206
|
-
if (!normalizedSkillSlug) {
|
|
207
|
-
throw new Error('Cannot toggle an empty published skill slug.');
|
|
208
|
-
}
|
|
209
|
-
return setPublishedSkillPreference({
|
|
210
|
-
worktree,
|
|
211
|
-
directory,
|
|
212
|
-
config,
|
|
213
|
-
skillSlug: normalizedSkillSlug,
|
|
214
|
-
preferenceScope,
|
|
215
|
-
installed
|
|
216
|
-
});
|
|
217
|
-
};
|
|
218
|
-
const getDetailCacheKey = (catalogCacheKey, skillVersionId) => {
|
|
219
|
-
return JSON.stringify([catalogCacheKey, skillVersionId]);
|
|
220
|
-
};
|
|
221
|
-
const getDetailInflightKey = (catalogCacheKey, skillVersionId, purpose) => {
|
|
222
|
-
return JSON.stringify([catalogCacheKey, skillVersionId, purpose]);
|
|
223
|
-
};
|
|
224
96
|
export const OpencodeWizardSkillsPlugin = async input => {
|
|
225
97
|
const {
|
|
226
98
|
tool
|
|
@@ -561,20 +433,6 @@ export const OpencodeWizardSkillsPlugin = async input => {
|
|
|
561
433
|
args,
|
|
562
434
|
context
|
|
563
435
|
}) => {
|
|
564
|
-
const authState = await resolveStoredAuthState(input.worktree, config);
|
|
565
|
-
if (!authState || authState.role !== 'ADMIN' && authState.role !== 'EDITOR') {
|
|
566
|
-
return {
|
|
567
|
-
output: JSON.stringify({
|
|
568
|
-
pluginId: PLUGIN_ID,
|
|
569
|
-
status: 'forbidden',
|
|
570
|
-
message: 'This tool requires ADMIN or EDITOR role. Your current session does not have the required permission.'
|
|
571
|
-
}, null, 2),
|
|
572
|
-
metadata: {
|
|
573
|
-
status: 'forbidden',
|
|
574
|
-
role: authState?.role ?? 'none'
|
|
575
|
-
}
|
|
576
|
-
};
|
|
577
|
-
}
|
|
578
436
|
const requestedDirectory = normalizeDirectoryArg(context.directory, args.directory);
|
|
579
437
|
const requestedSkills = parseRequestedSkillArgs(args);
|
|
580
438
|
const fetchActionDirectoryPath = normalizeRepositoryPath(workspacePath, requestedDirectory);
|
|
@@ -632,7 +490,11 @@ export const OpencodeWizardSkillsPlugin = async input => {
|
|
|
632
490
|
const selection = selectPublishedSkills(filteredPublishedSkillsResult.fetchResult.payload, requestedSkills);
|
|
633
491
|
const isSingleRequest = requestedSkills.length === 1;
|
|
634
492
|
if (requestedSkills.length === 0) {
|
|
635
|
-
const
|
|
493
|
+
const authState = await resolveStoredAuthState(input.worktree, config);
|
|
494
|
+
const catalog = {
|
|
495
|
+
...toPublishedSkillCatalog(filteredPublishedSkillsResult.fetchResult.payload),
|
|
496
|
+
availableTools: resolveAvailableTools(authState?.role ?? null)
|
|
497
|
+
};
|
|
636
498
|
context.metadata({
|
|
637
499
|
title: `opencode-wizard published skills catalog: ${catalog.publishedSkillCount} active`,
|
|
638
500
|
metadata: {
|
|
@@ -789,24 +651,241 @@ export const OpencodeWizardSkillsPlugin = async input => {
|
|
|
789
651
|
}
|
|
790
652
|
};
|
|
791
653
|
};
|
|
792
|
-
const
|
|
654
|
+
const executeWizardArtifactCatalogTool = async ({
|
|
793
655
|
args,
|
|
794
656
|
context
|
|
795
657
|
}) => {
|
|
796
|
-
const
|
|
797
|
-
|
|
658
|
+
const requestedDirectory = normalizeDirectoryArg(context.directory, args.directory);
|
|
659
|
+
const directoryPath = normalizeRepositoryPath(workspacePath, requestedDirectory);
|
|
660
|
+
const artifactKind = toWizardArtifactKind(args.artifactKind);
|
|
661
|
+
if (!artifactKind) {
|
|
662
|
+
return buildUnsupportedWizardArtifactOutput({
|
|
663
|
+
artifactKind: args.artifactKind ?? '',
|
|
664
|
+
directoryPath
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
if (artifactKind === 'DESIGN_DOC') {
|
|
668
|
+
const workspaceResolution = await resolveWorkspace({
|
|
669
|
+
config,
|
|
670
|
+
directory: requestedDirectory
|
|
671
|
+
});
|
|
672
|
+
const fetchResult = await fetchWizardArtifactsCatalog(input.worktree, config, workspaceResolution, artifactKind, context.abort, clearPublishedSkillState);
|
|
673
|
+
if (!fetchResult.ok) {
|
|
674
|
+
return {
|
|
675
|
+
output: JSON.stringify({
|
|
676
|
+
pluginId: PLUGIN_ID,
|
|
677
|
+
runtimeMode: 'tool_fetch_only',
|
|
678
|
+
status: fetchResult.status,
|
|
679
|
+
artifactKind,
|
|
680
|
+
requestedDirectoryPath: directoryPath,
|
|
681
|
+
workspaceResolution: toWorkspaceResolutionOutput(workspaceResolution),
|
|
682
|
+
message: fetchResult.message,
|
|
683
|
+
fetchedAt: fetchResult.fetchedAt,
|
|
684
|
+
source: fetchResult.source
|
|
685
|
+
}, null, 2),
|
|
686
|
+
metadata: {
|
|
687
|
+
status: fetchResult.status,
|
|
688
|
+
artifactKind,
|
|
689
|
+
directoryPath,
|
|
690
|
+
source: fetchResult.source
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
const authState = await resolveStoredAuthState(input.worktree, config);
|
|
695
|
+
const catalog = toWizardArtifactCatalog(fetchResult.payload, {
|
|
696
|
+
pluginId: PLUGIN_ID,
|
|
697
|
+
availableTools: resolveAvailableTools(authState?.role ?? null)
|
|
698
|
+
});
|
|
798
699
|
return {
|
|
799
700
|
output: JSON.stringify({
|
|
701
|
+
...catalog,
|
|
702
|
+
status: 'ready',
|
|
703
|
+
requestedDirectoryPath: directoryPath,
|
|
704
|
+
workspaceResolution: toWorkspaceResolutionOutput(workspaceResolution),
|
|
705
|
+
fetchedAt: fetchResult.fetchedAt,
|
|
706
|
+
source: fetchResult.source,
|
|
707
|
+
message: 'DESIGN_DOC catalog discovery only. Full DESIGN.md bodies/files require opencode_wizard_artifact_fetch with artifactKind DESIGN_DOC.'
|
|
708
|
+
}, null, 2),
|
|
709
|
+
metadata: {
|
|
710
|
+
status: 'ready',
|
|
711
|
+
artifactKind,
|
|
712
|
+
artifactCount: catalog.artifactCount.toString(),
|
|
713
|
+
...toWorkspaceResolutionMetadata(workspaceResolution),
|
|
714
|
+
source: fetchResult.source
|
|
715
|
+
}
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
const result = await executePublishedSkillsFetchTool({
|
|
719
|
+
args: {
|
|
720
|
+
directory: args.directory,
|
|
721
|
+
refresh: args.refresh
|
|
722
|
+
},
|
|
723
|
+
context
|
|
724
|
+
});
|
|
725
|
+
return withWizardArtifactEnvelope(result, artifactKind);
|
|
726
|
+
};
|
|
727
|
+
const executeWizardArtifactFetchTool = async ({
|
|
728
|
+
args,
|
|
729
|
+
context
|
|
730
|
+
}) => {
|
|
731
|
+
const requestedDirectory = normalizeDirectoryArg(context.directory, args.directory);
|
|
732
|
+
const directoryPath = normalizeRepositoryPath(workspacePath, requestedDirectory);
|
|
733
|
+
const artifactKind = toWizardArtifactKind(args.artifactKind);
|
|
734
|
+
if (!artifactKind) {
|
|
735
|
+
return buildUnsupportedWizardArtifactOutput({
|
|
736
|
+
artifactKind: args.artifactKind ?? '',
|
|
737
|
+
directoryPath
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
if (artifactKind === 'DESIGN_DOC') {
|
|
741
|
+
const requestedArtifacts = parseRequestedSkillArgs({
|
|
742
|
+
skill: args.artifact,
|
|
743
|
+
skills: args.artifacts
|
|
744
|
+
});
|
|
745
|
+
const workspaceResolution = await resolveWorkspace({
|
|
746
|
+
config,
|
|
747
|
+
directory: requestedDirectory
|
|
748
|
+
});
|
|
749
|
+
const fetchResult = await fetchWizardArtifactsCatalog(input.worktree, config, workspaceResolution, artifactKind, context.abort, clearPublishedSkillState);
|
|
750
|
+
if (!fetchResult.ok) {
|
|
751
|
+
return {
|
|
752
|
+
output: JSON.stringify({
|
|
753
|
+
pluginId: PLUGIN_ID,
|
|
754
|
+
runtimeMode: 'tool_fetch_only',
|
|
755
|
+
status: fetchResult.status,
|
|
756
|
+
artifactKind,
|
|
757
|
+
requestedDirectoryPath: directoryPath,
|
|
758
|
+
workspaceResolution: toWorkspaceResolutionOutput(workspaceResolution),
|
|
759
|
+
message: fetchResult.message,
|
|
760
|
+
fetchedAt: fetchResult.fetchedAt,
|
|
761
|
+
source: fetchResult.source
|
|
762
|
+
}, null, 2),
|
|
763
|
+
metadata: {
|
|
764
|
+
status: fetchResult.status,
|
|
765
|
+
artifactKind,
|
|
766
|
+
directoryPath,
|
|
767
|
+
source: fetchResult.source
|
|
768
|
+
}
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
const selection = selectWizardArtifacts(fetchResult.payload.artifacts, requestedArtifacts);
|
|
772
|
+
if (requestedArtifacts.length === 0) {
|
|
773
|
+
const authState = await resolveStoredAuthState(input.worktree, config);
|
|
774
|
+
const catalog = toWizardArtifactCatalog(fetchResult.payload, {
|
|
800
775
|
pluginId: PLUGIN_ID,
|
|
801
|
-
|
|
802
|
-
|
|
776
|
+
availableTools: resolveAvailableTools(authState?.role ?? null)
|
|
777
|
+
});
|
|
778
|
+
return {
|
|
779
|
+
output: JSON.stringify({
|
|
780
|
+
...catalog,
|
|
781
|
+
status: 'ready',
|
|
782
|
+
requestedDirectoryPath: directoryPath,
|
|
783
|
+
workspaceResolution: toWorkspaceResolutionOutput(workspaceResolution),
|
|
784
|
+
fetchedAt: fetchResult.fetchedAt,
|
|
785
|
+
source: fetchResult.source,
|
|
786
|
+
message: 'Provide artifact or artifacts to fetch DESIGN.md body/files.'
|
|
787
|
+
}, null, 2),
|
|
788
|
+
metadata: {
|
|
789
|
+
status: 'ready',
|
|
790
|
+
artifactKind,
|
|
791
|
+
...toWorkspaceResolutionMetadata(workspaceResolution)
|
|
792
|
+
}
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
if (selection.selectedItems.length === 0 && requestedArtifacts.length === 1) {
|
|
796
|
+
return {
|
|
797
|
+
output: JSON.stringify({
|
|
798
|
+
pluginId: PLUGIN_ID,
|
|
799
|
+
runtimeMode: 'tool_fetch_only',
|
|
800
|
+
status: 'not_found',
|
|
801
|
+
artifactKind,
|
|
802
|
+
requestedArtifact: requestedArtifacts[0],
|
|
803
|
+
availableArtifacts: fetchResult.payload.artifacts.map(toWizardArtifactSummary),
|
|
804
|
+
requestedDirectoryPath: directoryPath,
|
|
805
|
+
workspaceResolution: toWorkspaceResolutionOutput(workspaceResolution)
|
|
806
|
+
}, null, 2),
|
|
807
|
+
metadata: {
|
|
808
|
+
status: 'not_found',
|
|
809
|
+
artifactKind,
|
|
810
|
+
...toWorkspaceResolutionMetadata(workspaceResolution)
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
const detailResults = await Promise.all(selection.selectedItems.map(item => fetchWizardArtifactDetail({
|
|
815
|
+
worktree: input.worktree,
|
|
816
|
+
config,
|
|
817
|
+
resolution: workspaceResolution,
|
|
818
|
+
artifactKind,
|
|
819
|
+
artifactVersionId: item.artifactVersion.id,
|
|
820
|
+
signal: context.abort,
|
|
821
|
+
onAuthStateChanged: clearPublishedSkillState,
|
|
822
|
+
purpose: 'TOOL_FETCH'
|
|
823
|
+
})));
|
|
824
|
+
const failedDetail = detailResults.find(result => !result.ok);
|
|
825
|
+
if (failedDetail && !failedDetail.ok) {
|
|
826
|
+
return {
|
|
827
|
+
output: JSON.stringify({
|
|
828
|
+
pluginId: PLUGIN_ID,
|
|
829
|
+
runtimeMode: 'tool_fetch_only',
|
|
830
|
+
status: failedDetail.result.status,
|
|
831
|
+
artifactKind,
|
|
832
|
+
requestedDirectoryPath: directoryPath,
|
|
833
|
+
workspaceResolution: toWorkspaceResolutionOutput(workspaceResolution),
|
|
834
|
+
message: failedDetail.result.message,
|
|
835
|
+
fetchedAt: failedDetail.result.fetchedAt,
|
|
836
|
+
source: failedDetail.result.source
|
|
837
|
+
}, null, 2),
|
|
838
|
+
metadata: {
|
|
839
|
+
status: failedDetail.result.status,
|
|
840
|
+
artifactKind,
|
|
841
|
+
...toWorkspaceResolutionMetadata(workspaceResolution)
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
const details = detailResults.map((result, index) => {
|
|
846
|
+
if (!result.ok) throw new Error('Wizard artifact detail result unexpectedly missing after success guard.');
|
|
847
|
+
return toWizardArtifactDetail({
|
|
848
|
+
...selection.selectedItems[index],
|
|
849
|
+
artifactVersion: result.artifact
|
|
850
|
+
});
|
|
851
|
+
});
|
|
852
|
+
return {
|
|
853
|
+
output: JSON.stringify({
|
|
854
|
+
pluginId: PLUGIN_ID,
|
|
855
|
+
runtimeMode: 'tool_fetch_only',
|
|
856
|
+
artifactKind,
|
|
857
|
+
requestedDirectoryPath: directoryPath,
|
|
858
|
+
workspaceResolution: toWorkspaceResolutionOutput(workspaceResolution),
|
|
859
|
+
workspace: fetchResult.payload.workspace,
|
|
860
|
+
fetchedAt: fetchResult.fetchedAt,
|
|
861
|
+
source: fetchResult.source,
|
|
862
|
+
requestedArtifacts,
|
|
863
|
+
missingArtifacts: selection.missingIdentifiers,
|
|
864
|
+
artifacts: details
|
|
803
865
|
}, null, 2),
|
|
804
866
|
metadata: {
|
|
805
|
-
status: '
|
|
806
|
-
|
|
867
|
+
status: selection.missingIdentifiers.length > 0 ? 'partial' : 'ready',
|
|
868
|
+
artifactKind,
|
|
869
|
+
matchedCount: details.length.toString(),
|
|
870
|
+
...toWorkspaceResolutionMetadata(workspaceResolution)
|
|
807
871
|
}
|
|
808
872
|
};
|
|
809
873
|
}
|
|
874
|
+
const result = await executePublishedSkillsFetchTool({
|
|
875
|
+
args: {
|
|
876
|
+
skill: args.artifact,
|
|
877
|
+
skills: args.artifacts,
|
|
878
|
+
directory: args.directory,
|
|
879
|
+
refresh: args.refresh
|
|
880
|
+
},
|
|
881
|
+
context
|
|
882
|
+
});
|
|
883
|
+
return withWizardArtifactEnvelope(result, artifactKind);
|
|
884
|
+
};
|
|
885
|
+
const executeStatusTool = async ({
|
|
886
|
+
args,
|
|
887
|
+
context
|
|
888
|
+
}) => {
|
|
810
889
|
const requestedDirectory = normalizeDirectoryArg(context.directory, args.directory);
|
|
811
890
|
let snapshot = await resolvePluginStatusSnapshot({
|
|
812
891
|
worktree: input.worktree,
|
|
@@ -844,20 +923,6 @@ export const OpencodeWizardSkillsPlugin = async input => {
|
|
|
844
923
|
args,
|
|
845
924
|
context
|
|
846
925
|
}) => {
|
|
847
|
-
const authState = await resolveStoredAuthState(input.worktree, config);
|
|
848
|
-
if (!authState || authState.role !== 'ADMIN' && authState.role !== 'EDITOR') {
|
|
849
|
-
return {
|
|
850
|
-
output: JSON.stringify({
|
|
851
|
-
pluginId: PLUGIN_ID,
|
|
852
|
-
status: 'forbidden',
|
|
853
|
-
message: 'This tool requires ADMIN or EDITOR role. Your current session does not have the required permission.'
|
|
854
|
-
}, null, 2),
|
|
855
|
-
metadata: {
|
|
856
|
-
status: 'forbidden',
|
|
857
|
-
role: authState?.role ?? 'none'
|
|
858
|
-
}
|
|
859
|
-
};
|
|
860
|
-
}
|
|
861
926
|
const requestedDirectory = normalizeDirectoryArg(context.directory, args.directory);
|
|
862
927
|
const directoryPath = normalizeRepositoryPath(workspacePath, requestedDirectory);
|
|
863
928
|
lastInteractiveDirectoryPath = directoryPath;
|
|
@@ -882,7 +947,13 @@ export const OpencodeWizardSkillsPlugin = async input => {
|
|
|
882
947
|
signal: context.abort
|
|
883
948
|
});
|
|
884
949
|
if (!catalogResult.fetchResult.ok) {
|
|
885
|
-
|
|
950
|
+
await emitPreferenceOutcome('PREFERENCE_FAILED');
|
|
951
|
+
return toFetchFailureOutput({
|
|
952
|
+
worktree: input.worktree,
|
|
953
|
+
config,
|
|
954
|
+
publishedSkillsResult: catalogResult,
|
|
955
|
+
loginBootstrapSnapshot: loginBootstrap.snapshot
|
|
956
|
+
});
|
|
886
957
|
}
|
|
887
958
|
const selectableCatalogSkills = catalogResult.fetchResult.payload.catalogSkills.map(item => ({
|
|
888
959
|
...item,
|
|
@@ -941,8 +1012,132 @@ export const OpencodeWizardSkillsPlugin = async input => {
|
|
|
941
1012
|
};
|
|
942
1013
|
} catch (error) {
|
|
943
1014
|
await emitPreferenceOutcome('PREFERENCE_FAILED');
|
|
944
|
-
|
|
1015
|
+
const message = error instanceof Error ? error.message : 'Unknown published skill preference failure.';
|
|
1016
|
+
const metadata = {
|
|
1017
|
+
status: 'preference_failed',
|
|
1018
|
+
directoryPath
|
|
1019
|
+
};
|
|
1020
|
+
context.metadata({
|
|
1021
|
+
title: 'opencode-wizard published skill preference failed',
|
|
1022
|
+
metadata
|
|
1023
|
+
});
|
|
1024
|
+
return {
|
|
1025
|
+
output: JSON.stringify({
|
|
1026
|
+
pluginId: PLUGIN_ID,
|
|
1027
|
+
status: 'preference_failed',
|
|
1028
|
+
requestedIdentifier: requestedSkill,
|
|
1029
|
+
requestedDirectoryPath: directoryPath,
|
|
1030
|
+
message,
|
|
1031
|
+
guidance: 'The preference tool remains available. Check opencode_wizard_status for safe auth/catalog state, rerun fetch/status to bootstrap auth, and retry after catalog status is ready.'
|
|
1032
|
+
}, null, 2),
|
|
1033
|
+
metadata
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
};
|
|
1037
|
+
const executeWizardArtifactPreferenceTool = async ({
|
|
1038
|
+
args,
|
|
1039
|
+
context
|
|
1040
|
+
}) => {
|
|
1041
|
+
const requestedDirectory = normalizeDirectoryArg(context.directory, args.directory);
|
|
1042
|
+
const directoryPath = normalizeRepositoryPath(workspacePath, requestedDirectory);
|
|
1043
|
+
const artifactKind = toWizardArtifactKind(args.artifactKind);
|
|
1044
|
+
if (!artifactKind) {
|
|
1045
|
+
return buildUnsupportedWizardArtifactOutput({
|
|
1046
|
+
artifactKind: args.artifactKind ?? '',
|
|
1047
|
+
directoryPath
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
1050
|
+
if (artifactKind === 'DESIGN_DOC') {
|
|
1051
|
+
try {
|
|
1052
|
+
const action = toPublishedSkillPreferenceAction(args.action);
|
|
1053
|
+
const workspaceResolution = await resolveWorkspace({
|
|
1054
|
+
config,
|
|
1055
|
+
directory: requestedDirectory
|
|
1056
|
+
});
|
|
1057
|
+
const response = await fetchPublishedSkillsGraphQl({
|
|
1058
|
+
worktree: input.worktree,
|
|
1059
|
+
config,
|
|
1060
|
+
query: SET_WIZARD_ARTIFACT_PREFERENCE_MUTATION,
|
|
1061
|
+
variables: {
|
|
1062
|
+
input: {
|
|
1063
|
+
workspaceSlug: workspaceResolution.workspaceSlug,
|
|
1064
|
+
repositoryUrl: workspaceResolution.repositoryUrl,
|
|
1065
|
+
directoryPath: workspaceResolution.directoryPath,
|
|
1066
|
+
artifactKind,
|
|
1067
|
+
artifactSlug: args.artifact.trim(),
|
|
1068
|
+
preferenceScope: toPublishedSkillPreferenceScope(args.preferenceScope, 'project') === 'global' ? 'GLOBAL' : 'WORKSPACE',
|
|
1069
|
+
installed: action === 'install' ? true : action === 'uninstall' ? false : undefined,
|
|
1070
|
+
ignored: action === 'ignore' ? true : action === 'unignore' ? false : undefined
|
|
1071
|
+
}
|
|
1072
|
+
},
|
|
1073
|
+
signal: context.abort,
|
|
1074
|
+
onAuthStateChanged: clearPublishedSkillState
|
|
1075
|
+
});
|
|
1076
|
+
if (!response.ok) {
|
|
1077
|
+
return {
|
|
1078
|
+
output: JSON.stringify({
|
|
1079
|
+
pluginId: PLUGIN_ID,
|
|
1080
|
+
status: response.result.status,
|
|
1081
|
+
artifactKind,
|
|
1082
|
+
requestedIdentifier: args.artifact,
|
|
1083
|
+
requestedDirectoryPath: directoryPath,
|
|
1084
|
+
message: response.result.message,
|
|
1085
|
+
fetchedAt: response.result.fetchedAt,
|
|
1086
|
+
source: response.result.source
|
|
1087
|
+
}, null, 2),
|
|
1088
|
+
metadata: {
|
|
1089
|
+
status: response.result.status,
|
|
1090
|
+
artifactKind,
|
|
1091
|
+
directoryPath
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
return {
|
|
1096
|
+
output: JSON.stringify({
|
|
1097
|
+
pluginId: PLUGIN_ID,
|
|
1098
|
+
status: 'updated',
|
|
1099
|
+
artifactKind,
|
|
1100
|
+
requestedIdentifier: args.artifact,
|
|
1101
|
+
action,
|
|
1102
|
+
requestedDirectoryPath: directoryPath,
|
|
1103
|
+
preferenceState: response.data.setWizardArtifactPreference,
|
|
1104
|
+
message: 'Wizard artifact preference updated through the generic backend API.'
|
|
1105
|
+
}, null, 2),
|
|
1106
|
+
metadata: {
|
|
1107
|
+
status: 'updated',
|
|
1108
|
+
artifactKind,
|
|
1109
|
+
directoryPath,
|
|
1110
|
+
action
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
} catch (error) {
|
|
1114
|
+
return {
|
|
1115
|
+
output: JSON.stringify({
|
|
1116
|
+
pluginId: PLUGIN_ID,
|
|
1117
|
+
status: 'preference_failed',
|
|
1118
|
+
artifactKind,
|
|
1119
|
+
requestedIdentifier: args.artifact,
|
|
1120
|
+
requestedDirectoryPath: directoryPath,
|
|
1121
|
+
message: error instanceof Error ? error.message : 'Unknown wizard artifact preference failure.'
|
|
1122
|
+
}, null, 2),
|
|
1123
|
+
metadata: {
|
|
1124
|
+
status: 'preference_failed',
|
|
1125
|
+
artifactKind,
|
|
1126
|
+
directoryPath
|
|
1127
|
+
}
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
945
1130
|
}
|
|
1131
|
+
const result = await executePublishedSkillPreferenceTool({
|
|
1132
|
+
args: {
|
|
1133
|
+
skill: args.artifact,
|
|
1134
|
+
action: args.action,
|
|
1135
|
+
preferenceScope: args.preferenceScope,
|
|
1136
|
+
directory: args.directory
|
|
1137
|
+
},
|
|
1138
|
+
context
|
|
1139
|
+
});
|
|
1140
|
+
return withWizardArtifactEnvelope(result, artifactKind);
|
|
946
1141
|
};
|
|
947
1142
|
const executeEditorPublishSkillTool = async ({
|
|
948
1143
|
args,
|
|
@@ -1038,8 +1233,122 @@ export const OpencodeWizardSkillsPlugin = async input => {
|
|
|
1038
1233
|
}
|
|
1039
1234
|
};
|
|
1040
1235
|
};
|
|
1236
|
+
const executeWizardArtifactImportTool = async ({
|
|
1237
|
+
args,
|
|
1238
|
+
context
|
|
1239
|
+
}) => {
|
|
1240
|
+
const authState = await resolveStoredAuthState(input.worktree, config);
|
|
1241
|
+
const importPlan = planWizardArtifactImport({
|
|
1242
|
+
artifactKind: args.artifactKind,
|
|
1243
|
+
source: args.source,
|
|
1244
|
+
slug: args.slug,
|
|
1245
|
+
skill: args.skill
|
|
1246
|
+
});
|
|
1247
|
+
if (!authState || authState.role !== 'EDITOR') {
|
|
1248
|
+
return {
|
|
1249
|
+
output: JSON.stringify({
|
|
1250
|
+
pluginId: PLUGIN_ID,
|
|
1251
|
+
status: 'forbidden',
|
|
1252
|
+
artifactKind: importPlan.artifactKind,
|
|
1253
|
+
source: importPlan.source,
|
|
1254
|
+
message: 'This tool requires EDITOR role. Your current session does not have the required editor permission.'
|
|
1255
|
+
}, null, 2),
|
|
1256
|
+
metadata: {
|
|
1257
|
+
status: 'forbidden',
|
|
1258
|
+
role: authState?.role ?? 'none'
|
|
1259
|
+
}
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
const requestedDirectory = normalizeDirectoryArg(context.directory, args.directory);
|
|
1263
|
+
const directoryPath = normalizeRepositoryPath(workspacePath, requestedDirectory);
|
|
1264
|
+
lastInteractiveDirectoryPath = directoryPath;
|
|
1265
|
+
let importSource;
|
|
1266
|
+
try {
|
|
1267
|
+
importSource = await fetchWizardArtifactImportSource({
|
|
1268
|
+
artifactKind: args.artifactKind,
|
|
1269
|
+
source: args.source,
|
|
1270
|
+
slug: args.slug,
|
|
1271
|
+
skill: args.skill,
|
|
1272
|
+
signal: context.abort
|
|
1273
|
+
});
|
|
1274
|
+
} catch (error) {
|
|
1275
|
+
return {
|
|
1276
|
+
output: JSON.stringify({
|
|
1277
|
+
pluginId: PLUGIN_ID,
|
|
1278
|
+
status: 'source_fetch_failed',
|
|
1279
|
+
artifactKind: importPlan.artifactKind,
|
|
1280
|
+
source: importPlan.source,
|
|
1281
|
+
candidateUrls: importPlan.candidateUrls,
|
|
1282
|
+
message: error instanceof Error ? error.message : 'Unknown import source fetch failure.'
|
|
1283
|
+
}, null, 2),
|
|
1284
|
+
metadata: {
|
|
1285
|
+
status: 'source_fetch_failed',
|
|
1286
|
+
artifactKind: importPlan.artifactKind,
|
|
1287
|
+
directoryPath
|
|
1288
|
+
}
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
const response = await fetchPublishedSkillsGraphQl({
|
|
1292
|
+
worktree: input.worktree,
|
|
1293
|
+
config,
|
|
1294
|
+
query: IMPORT_WIZARD_ARTIFACT_SNAPSHOT_MUTATION,
|
|
1295
|
+
variables: {
|
|
1296
|
+
input: {
|
|
1297
|
+
artifactKind: importSource.artifactKind,
|
|
1298
|
+
slug: importSource.slug,
|
|
1299
|
+
name: args.name,
|
|
1300
|
+
summary: args.summary,
|
|
1301
|
+
markdownContent: importSource.markdownContent,
|
|
1302
|
+
source: importSource.fetchedUrl,
|
|
1303
|
+
sourceSnapshotRef: importSource.sourceRef
|
|
1304
|
+
}
|
|
1305
|
+
},
|
|
1306
|
+
signal: context.abort
|
|
1307
|
+
});
|
|
1308
|
+
if (!response.ok) {
|
|
1309
|
+
return {
|
|
1310
|
+
output: JSON.stringify({
|
|
1311
|
+
pluginId: PLUGIN_ID,
|
|
1312
|
+
status: 'request_failed',
|
|
1313
|
+
artifactKind: importSource.artifactKind,
|
|
1314
|
+
source: importSource.source,
|
|
1315
|
+
fetchedUrl: importSource.fetchedUrl,
|
|
1316
|
+
message: response.result.message
|
|
1317
|
+
}, null, 2),
|
|
1318
|
+
metadata: {
|
|
1319
|
+
status: 'request_failed',
|
|
1320
|
+
artifactKind: importSource.artifactKind,
|
|
1321
|
+
directoryPath
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1325
|
+
const payload = response.data.importWizardArtifactSnapshot;
|
|
1326
|
+
await scheduleInteractivePresenceStart();
|
|
1327
|
+
return {
|
|
1328
|
+
output: JSON.stringify({
|
|
1329
|
+
pluginId: PLUGIN_ID,
|
|
1330
|
+
status: payload.success ? 'imported' : 'import_failed',
|
|
1331
|
+
artifactKind: importSource.artifactKind,
|
|
1332
|
+
artifactSlug: payload.artifactSlug,
|
|
1333
|
+
artifactVersionId: payload.artifactVersionId,
|
|
1334
|
+
skillSlug: payload.skillSlug,
|
|
1335
|
+
skillVersionId: payload.skillVersionId,
|
|
1336
|
+
source: importSource.source,
|
|
1337
|
+
fetchedUrl: importSource.fetchedUrl,
|
|
1338
|
+
sourceSnapshotRef: importSource.sourceRef,
|
|
1339
|
+
errors: payload.errors,
|
|
1340
|
+
message: 'Imported backend artifact is now the wizard/plugin runtime authority; no project files were written.'
|
|
1341
|
+
}, null, 2),
|
|
1342
|
+
metadata: {
|
|
1343
|
+
status: payload.success ? 'imported' : 'import_failed',
|
|
1344
|
+
artifactKind: importSource.artifactKind,
|
|
1345
|
+
artifactSlug: payload.artifactSlug ?? '',
|
|
1346
|
+
artifactVersionId: payload.artifactVersionId ?? '',
|
|
1347
|
+
directoryPath
|
|
1348
|
+
}
|
|
1349
|
+
};
|
|
1350
|
+
};
|
|
1041
1351
|
const role = initialAuthState?.role ?? null;
|
|
1042
|
-
const hasSharedToolAccess = role === 'ADMIN' || role === 'EDITOR';
|
|
1043
1352
|
const isEditor = role === 'EDITOR';
|
|
1044
1353
|
const {
|
|
1045
1354
|
sharedTools,
|
|
@@ -1049,10 +1358,22 @@ export const OpencodeWizardSkillsPlugin = async input => {
|
|
|
1049
1358
|
args,
|
|
1050
1359
|
context
|
|
1051
1360
|
}),
|
|
1361
|
+
fetchWizardArtifactCatalog: (args, context) => executeWizardArtifactCatalogTool({
|
|
1362
|
+
args,
|
|
1363
|
+
context
|
|
1364
|
+
}),
|
|
1365
|
+
fetchWizardArtifacts: (args, context) => executeWizardArtifactFetchTool({
|
|
1366
|
+
args,
|
|
1367
|
+
context
|
|
1368
|
+
}),
|
|
1052
1369
|
updatePublishedSkillPreference: (args, context) => executePublishedSkillPreferenceTool({
|
|
1053
1370
|
args,
|
|
1054
1371
|
context
|
|
1055
1372
|
}),
|
|
1373
|
+
updateWizardArtifactPreference: (args, context) => executeWizardArtifactPreferenceTool({
|
|
1374
|
+
args,
|
|
1375
|
+
context
|
|
1376
|
+
}),
|
|
1056
1377
|
getStatus: (args, context) => executeStatusTool({
|
|
1057
1378
|
args,
|
|
1058
1379
|
context
|
|
@@ -1060,10 +1381,14 @@ export const OpencodeWizardSkillsPlugin = async input => {
|
|
|
1060
1381
|
publishEditorSkill: (args, context) => executeEditorPublishSkillTool({
|
|
1061
1382
|
args,
|
|
1062
1383
|
context
|
|
1384
|
+
}),
|
|
1385
|
+
importWizardArtifact: (args, context) => executeWizardArtifactImportTool({
|
|
1386
|
+
args,
|
|
1387
|
+
context
|
|
1063
1388
|
})
|
|
1064
1389
|
});
|
|
1065
1390
|
return {
|
|
1066
|
-
tool:
|
|
1391
|
+
tool: {
|
|
1067
1392
|
...sharedTools,
|
|
1068
1393
|
...(isEditor ? editorOnlyTools : {})
|
|
1069
1394
|
},
|