@aexol/opencode-wizard 0.3.2 → 0.3.4
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 +4 -0
- package/dist/graphql-operations.d.ts +4 -0
- package/dist/graphql-operations.js +225 -0
- package/dist/graphql-operations.js.map +1 -0
- package/dist/plugin-tools.d.ts +64 -0
- package/dist/plugin-tools.js +57 -0
- package/dist/plugin-tools.js.map +1 -0
- package/dist/published-skills-system-note.d.ts +9 -0
- package/dist/published-skills-system-note.js +34 -0
- package/dist/published-skills-system-note.js.map +1 -0
- package/dist/published-skills-transform.d.ts +161 -0
- package/dist/published-skills-transform.js +238 -0
- package/dist/published-skills-transform.js.map +1 -0
- package/dist/server/auth-flow.d.ts +10 -0
- package/dist/server/auth-flow.js +215 -0
- package/dist/server/auth-flow.js.map +1 -0
- package/dist/server/auth-store.d.ts +19 -0
- package/dist/server/auth-store.js +177 -0
- package/dist/server/auth-store.js.map +1 -0
- package/dist/server/client.d.ts +51 -0
- package/dist/server/client.js +244 -0
- package/dist/server/client.js.map +1 -0
- package/dist/server/config.d.ts +2 -0
- package/dist/server/config.js +82 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/constants.d.ts +26 -0
- package/dist/server/constants.js +32 -0
- package/dist/server/constants.js.map +1 -0
- package/dist/server/path-utils.d.ts +2 -0
- package/dist/server/path-utils.js +8 -0
- package/dist/server/path-utils.js.map +1 -0
- package/dist/server/presence.d.ts +14 -0
- package/dist/server/presence.js +68 -0
- package/dist/server/presence.js.map +1 -0
- package/dist/server/runtime.d.ts +32 -0
- package/dist/server/runtime.js +1110 -0
- package/dist/server/runtime.js.map +1 -0
- package/dist/server/status.d.ts +27 -0
- package/dist/server/status.js +224 -0
- package/dist/server/status.js.map +1 -0
- package/dist/server/types.d.ts +321 -0
- package/dist/server/types.js +2 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server/workspace.d.ts +15 -0
- package/dist/server/workspace.js +126 -0
- package/dist/server/workspace.js.map +1 -0
- package/dist/server.d.ts +4 -304
- package/dist/server.js +4 -2489
- package/dist/server.js.map +1 -1
- package/dist/smoke-published-skills.js +11 -9
- package/dist/smoke-published-skills.js.map +1 -1
- package/dist/tui/components/common.d.ts +15 -0
- package/dist/tui/components/common.js +81 -0
- package/dist/tui/components/common.js.map +1 -0
- package/dist/tui/components/preference-action-notice-row.d.ts +5 -0
- package/dist/tui/components/preference-action-notice-row.js +17 -0
- package/dist/tui/components/preference-action-notice-row.js.map +1 -0
- package/dist/tui/components/skill-catalog-row.d.ts +8 -0
- package/dist/tui/components/skill-catalog-row.js +124 -0
- package/dist/tui/components/skill-catalog-row.js.map +1 -0
- package/dist/tui/components/status-content.d.ts +14 -0
- package/dist/tui/components/status-content.js +131 -0
- package/dist/tui/components/status-content.js.map +1 -0
- package/dist/tui/components/wizard-skills-dialog-content.d.ts +9 -0
- package/dist/tui/components/wizard-skills-dialog-content.js +219 -0
- package/dist/tui/components/wizard-skills-dialog-content.js.map +1 -0
- package/dist/tui/components/wizard-skills-dialog.d.ts +7 -0
- package/dist/tui/components/wizard-skills-dialog.js +156 -0
- package/dist/tui/components/wizard-skills-dialog.js.map +1 -0
- package/dist/tui/constants.d.ts +8 -0
- package/dist/tui/constants.js +9 -0
- package/dist/tui/constants.js.map +1 -0
- package/dist/tui/formatting.d.ts +8 -0
- package/dist/tui/formatting.js +45 -0
- package/dist/tui/formatting.js.map +1 -0
- package/dist/tui/plugin.d.ts +2 -0
- package/dist/tui/plugin.js +26 -0
- package/dist/tui/plugin.js.map +1 -0
- package/dist/tui/rendering.d.ts +2 -0
- package/dist/tui/rendering.js +8 -0
- package/dist/tui/rendering.js.map +1 -0
- package/dist/tui/skill-helpers.d.ts +13 -0
- package/dist/tui/skill-helpers.js +49 -0
- package/dist/tui/skill-helpers.js.map +1 -0
- package/dist/tui/slots.d.ts +2 -0
- package/dist/tui/slots.js +56 -0
- package/dist/tui/slots.js.map +1 -0
- package/dist/tui/status.d.ts +2 -0
- package/dist/tui/status.js +21 -0
- package/dist/tui/status.js.map +1 -0
- package/dist/tui/types.d.ts +75 -0
- package/dist/tui/types.js +2 -0
- package/dist/tui/types.js.map +1 -0
- package/dist/tui.d.ts +1 -44
- package/dist/tui.js +2 -870
- package/dist/tui.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { deleteFileIfExists, readJsonFile, writePrivateJsonFile } from '../storage.js';
|
|
3
|
+
import { LEGACY_AUTH_STATE_PATH, PLUGIN_ID, WORKSPACE_MAPPING_LIMIT } from './constants.js';
|
|
4
|
+
import { normalizeAbsolutePath, toWorkspaceSlug } from './path-utils.js';
|
|
5
|
+
export const isRecord = value => {
|
|
6
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
7
|
+
};
|
|
8
|
+
const isValidIsoDateString = value => {
|
|
9
|
+
return typeof value === 'string' && Number.isFinite(Date.parse(value));
|
|
10
|
+
};
|
|
11
|
+
const isAuthState = value => {
|
|
12
|
+
if (!isRecord(value)) return false;
|
|
13
|
+
return value.pluginId === PLUGIN_ID && typeof value.sessionToken === 'string' && isValidIsoDateString(value.expiresAt) && isValidIsoDateString(value.authenticatedAt) && typeof value.userId === 'string' && typeof value.email === 'string';
|
|
14
|
+
};
|
|
15
|
+
const readGlobalConfig = async configFile => {
|
|
16
|
+
const storedConfig = await readJsonFile(configFile);
|
|
17
|
+
if (isRecord(storedConfig)) return storedConfig;
|
|
18
|
+
return {};
|
|
19
|
+
};
|
|
20
|
+
const writeGlobalConfig = async (configFile, config) => {
|
|
21
|
+
await writePrivateJsonFile(configFile, config);
|
|
22
|
+
};
|
|
23
|
+
const withoutLegacyPublishedSkillPreferences = config => {
|
|
24
|
+
const {
|
|
25
|
+
publishedSkillPreferences,
|
|
26
|
+
ignoredPublishedSkills,
|
|
27
|
+
...safeConfig
|
|
28
|
+
} = config;
|
|
29
|
+
void publishedSkillPreferences;
|
|
30
|
+
void ignoredPublishedSkills;
|
|
31
|
+
return safeConfig;
|
|
32
|
+
};
|
|
33
|
+
const hasLegacyPublishedSkillPreferences = config => {
|
|
34
|
+
return Object.prototype.hasOwnProperty.call(config, 'publishedSkillPreferences') || Object.prototype.hasOwnProperty.call(config, 'ignoredPublishedSkills');
|
|
35
|
+
};
|
|
36
|
+
const isStoredWorkspaceSlugMapping = value => {
|
|
37
|
+
if (!isRecord(value)) return false;
|
|
38
|
+
const {
|
|
39
|
+
repositoryUrl,
|
|
40
|
+
repositoryRoot,
|
|
41
|
+
workspaceSlug,
|
|
42
|
+
updatedAt
|
|
43
|
+
} = value;
|
|
44
|
+
const hasValidRepositoryUrl = repositoryUrl === null || typeof repositoryUrl === 'string';
|
|
45
|
+
const hasValidRepositoryRoot = repositoryRoot === null || typeof repositoryRoot === 'string';
|
|
46
|
+
return hasValidRepositoryUrl && hasValidRepositoryRoot && typeof workspaceSlug === 'string' && workspaceSlug.trim().length > 0 && isValidIsoDateString(updatedAt);
|
|
47
|
+
};
|
|
48
|
+
const readWorkspaceSlugMappings = async configFile => {
|
|
49
|
+
const storedConfig = await readGlobalConfig(configFile);
|
|
50
|
+
const mappings = storedConfig.workspaceSlugMappings;
|
|
51
|
+
if (!Array.isArray(mappings)) return [];
|
|
52
|
+
return mappings.filter(isStoredWorkspaceSlugMapping).slice(0, WORKSPACE_MAPPING_LIMIT);
|
|
53
|
+
};
|
|
54
|
+
const writeWorkspaceSlugMappings = async (configFile, nextMappings) => {
|
|
55
|
+
const storedConfig = await readGlobalConfig(configFile);
|
|
56
|
+
await writeGlobalConfig(configFile, {
|
|
57
|
+
...withoutLegacyPublishedSkillPreferences(storedConfig),
|
|
58
|
+
workspaceSlugMappings: nextMappings.slice(0, WORKSPACE_MAPPING_LIMIT)
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
const normalizeStoredRepositoryRoot = value => {
|
|
62
|
+
if (!value) return null;
|
|
63
|
+
return normalizeAbsolutePath(value);
|
|
64
|
+
};
|
|
65
|
+
export const upsertWorkspaceSlugMapping = async ({
|
|
66
|
+
configFile,
|
|
67
|
+
repositoryUrl,
|
|
68
|
+
repositoryRoot,
|
|
69
|
+
workspaceSlug
|
|
70
|
+
}) => {
|
|
71
|
+
const normalizedWorkspaceSlug = toWorkspaceSlug(workspaceSlug);
|
|
72
|
+
if (!normalizedWorkspaceSlug) return;
|
|
73
|
+
const normalizedRepositoryRoot = normalizeStoredRepositoryRoot(repositoryRoot);
|
|
74
|
+
const existingMappings = await readWorkspaceSlugMappings(configFile);
|
|
75
|
+
const filteredMappings = existingMappings.filter(mapping => {
|
|
76
|
+
if (repositoryUrl && mapping.repositoryUrl === repositoryUrl) return false;
|
|
77
|
+
if (normalizedRepositoryRoot && normalizeStoredRepositoryRoot(mapping.repositoryRoot) === normalizedRepositoryRoot) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
});
|
|
82
|
+
await writeWorkspaceSlugMappings(configFile, [{
|
|
83
|
+
repositoryUrl,
|
|
84
|
+
repositoryRoot: normalizedRepositoryRoot,
|
|
85
|
+
workspaceSlug: normalizedWorkspaceSlug,
|
|
86
|
+
updatedAt: new Date().toISOString()
|
|
87
|
+
}, ...filteredMappings]);
|
|
88
|
+
};
|
|
89
|
+
export const findWorkspaceSlugMapping = async ({
|
|
90
|
+
configFile,
|
|
91
|
+
repositoryUrl,
|
|
92
|
+
repositoryRoot
|
|
93
|
+
}) => {
|
|
94
|
+
const normalizedRepositoryRoot = normalizeStoredRepositoryRoot(repositoryRoot);
|
|
95
|
+
const mappings = await readWorkspaceSlugMappings(configFile);
|
|
96
|
+
if (repositoryUrl) {
|
|
97
|
+
const repositoryMatch = mappings.find(mapping => mapping.repositoryUrl === repositoryUrl);
|
|
98
|
+
if (repositoryMatch) return repositoryMatch;
|
|
99
|
+
}
|
|
100
|
+
if (normalizedRepositoryRoot) {
|
|
101
|
+
const rootMatch = mappings.find(mapping => normalizeStoredRepositoryRoot(mapping.repositoryRoot) === normalizedRepositoryRoot);
|
|
102
|
+
if (rootMatch) return rootMatch;
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
};
|
|
106
|
+
export const readGlobalAuthState = async configFile => {
|
|
107
|
+
const storedConfig = await readGlobalConfig(configFile);
|
|
108
|
+
const storedAuthState = storedConfig.auth;
|
|
109
|
+
if (storedAuthState === undefined || storedAuthState === null) return null;
|
|
110
|
+
if (isAuthState(storedAuthState)) {
|
|
111
|
+
if (hasLegacyPublishedSkillPreferences(storedConfig)) {
|
|
112
|
+
await writeGlobalConfig(configFile, withoutLegacyPublishedSkillPreferences(storedConfig));
|
|
113
|
+
}
|
|
114
|
+
return storedAuthState;
|
|
115
|
+
}
|
|
116
|
+
await writeGlobalConfig(configFile, {
|
|
117
|
+
...withoutLegacyPublishedSkillPreferences(storedConfig),
|
|
118
|
+
auth: null
|
|
119
|
+
});
|
|
120
|
+
return null;
|
|
121
|
+
};
|
|
122
|
+
const readLegacyAuthState = async authStateFile => {
|
|
123
|
+
const storedAuthState = await readJsonFile(authStateFile);
|
|
124
|
+
if (storedAuthState === null) return null;
|
|
125
|
+
if (isAuthState(storedAuthState)) return storedAuthState;
|
|
126
|
+
await deleteFileIfExists(authStateFile);
|
|
127
|
+
return null;
|
|
128
|
+
};
|
|
129
|
+
export const writeAuthState = async (configFile, authState) => {
|
|
130
|
+
const storedConfig = await readGlobalConfig(configFile);
|
|
131
|
+
await writeGlobalConfig(configFile, {
|
|
132
|
+
...withoutLegacyPublishedSkillPreferences(storedConfig),
|
|
133
|
+
auth: authState
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
export const clearAuthState = async configFile => {
|
|
137
|
+
const storedConfig = await readGlobalConfig(configFile);
|
|
138
|
+
await writeGlobalConfig(configFile, {
|
|
139
|
+
...withoutLegacyPublishedSkillPreferences(storedConfig),
|
|
140
|
+
auth: null
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
export const toStoredUserKey = authState => {
|
|
144
|
+
if (authState?.userId) return authState.userId;
|
|
145
|
+
if (authState?.email) return authState.email.toLowerCase();
|
|
146
|
+
return 'anonymous';
|
|
147
|
+
};
|
|
148
|
+
export const toAuthState = session => ({
|
|
149
|
+
pluginId: PLUGIN_ID,
|
|
150
|
+
sessionToken: session.jwtToken,
|
|
151
|
+
expiresAt: session.expiresAt,
|
|
152
|
+
authenticatedAt: new Date().toISOString(),
|
|
153
|
+
userId: session.user.id,
|
|
154
|
+
email: session.user.email,
|
|
155
|
+
role: session.user.role ?? null
|
|
156
|
+
});
|
|
157
|
+
export const resolveStoredAuthState = async (worktree, config) => {
|
|
158
|
+
const authState = await readGlobalAuthState(config.authStatePath);
|
|
159
|
+
if (authState && Date.parse(authState.expiresAt) > Date.now()) {
|
|
160
|
+
return authState;
|
|
161
|
+
}
|
|
162
|
+
if (authState) {
|
|
163
|
+
await clearAuthState(config.authStatePath);
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
const legacyAuthStateFile = path.resolve(worktree, LEGACY_AUTH_STATE_PATH);
|
|
167
|
+
const legacyAuthState = await readLegacyAuthState(legacyAuthStateFile);
|
|
168
|
+
if (!legacyAuthState) return null;
|
|
169
|
+
if (Date.parse(legacyAuthState.expiresAt) <= Date.now()) {
|
|
170
|
+
await deleteFileIfExists(legacyAuthStateFile);
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
await writeAuthState(config.authStatePath, legacyAuthState);
|
|
174
|
+
await deleteFileIfExists(legacyAuthStateFile);
|
|
175
|
+
return legacyAuthState;
|
|
176
|
+
};
|
|
177
|
+
//# sourceMappingURL=auth-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["path","deleteFileIfExists","readJsonFile","writePrivateJsonFile","LEGACY_AUTH_STATE_PATH","PLUGIN_ID","WORKSPACE_MAPPING_LIMIT","normalizeAbsolutePath","toWorkspaceSlug","isRecord","value","Array","isArray","isValidIsoDateString","Number","isFinite","Date","parse","isAuthState","pluginId","sessionToken","expiresAt","authenticatedAt","userId","email","readGlobalConfig","configFile","storedConfig","writeGlobalConfig","config","withoutLegacyPublishedSkillPreferences","publishedSkillPreferences","ignoredPublishedSkills","safeConfig","hasLegacyPublishedSkillPreferences","Object","prototype","hasOwnProperty","call","isStoredWorkspaceSlugMapping","repositoryUrl","repositoryRoot","workspaceSlug","updatedAt","hasValidRepositoryUrl","hasValidRepositoryRoot","trim","length","readWorkspaceSlugMappings","mappings","workspaceSlugMappings","filter","slice","writeWorkspaceSlugMappings","nextMappings","normalizeStoredRepositoryRoot","upsertWorkspaceSlugMapping","normalizedWorkspaceSlug","normalizedRepositoryRoot","existingMappings","filteredMappings","mapping","toISOString","findWorkspaceSlugMapping","repositoryMatch","find","rootMatch","readGlobalAuthState","storedAuthState","auth","undefined","readLegacyAuthState","authStateFile","writeAuthState","authState","clearAuthState","toStoredUserKey","toLowerCase","toAuthState","session","jwtToken","user","id","role","resolveStoredAuthState","worktree","authStatePath","now","legacyAuthStateFile","resolve","legacyAuthState"],"sources":["../../src/server/auth-store.ts"],"sourcesContent":["import path from 'node:path';\nimport { deleteFileIfExists, readJsonFile, writePrivateJsonFile } from '../storage.js';\nimport { LEGACY_AUTH_STATE_PATH, PLUGIN_ID, WORKSPACE_MAPPING_LIMIT } from './constants.js';\nimport { normalizeAbsolutePath, toWorkspaceSlug } from './path-utils.js';\nimport type { AuthState, PluginSessionResponse, ResolvedConfig, StoredWorkspaceSlugMapping } from './types.js';\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> => {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n};\n\nconst isValidIsoDateString = (value: unknown): value is string => {\n return typeof value === 'string' && Number.isFinite(Date.parse(value));\n};\n\nconst isAuthState = (value: unknown): value is AuthState => {\n if (!isRecord(value)) return false;\n\n return (\n value.pluginId === PLUGIN_ID &&\n typeof value.sessionToken === 'string' &&\n isValidIsoDateString(value.expiresAt) &&\n isValidIsoDateString(value.authenticatedAt) &&\n typeof value.userId === 'string' &&\n typeof value.email === 'string'\n );\n};\n\nconst readGlobalConfig = async (configFile: string): Promise<Record<string, unknown>> => {\n const storedConfig = await readJsonFile(configFile);\n if (isRecord(storedConfig)) return storedConfig;\n return {};\n};\n\nconst writeGlobalConfig = async (configFile: string, config: Record<string, unknown>) => {\n await writePrivateJsonFile(configFile, config);\n};\n\nconst withoutLegacyPublishedSkillPreferences = (config: Record<string, unknown>): Record<string, unknown> => {\n const { publishedSkillPreferences, ignoredPublishedSkills, ...safeConfig } = config;\n void publishedSkillPreferences;\n void ignoredPublishedSkills;\n return safeConfig;\n};\n\nconst hasLegacyPublishedSkillPreferences = (config: Record<string, unknown>): boolean => {\n return (\n Object.prototype.hasOwnProperty.call(config, 'publishedSkillPreferences') ||\n Object.prototype.hasOwnProperty.call(config, 'ignoredPublishedSkills')\n );\n};\n\nconst isStoredWorkspaceSlugMapping = (value: unknown): value is StoredWorkspaceSlugMapping => {\n if (!isRecord(value)) return false;\n\n const { repositoryUrl, repositoryRoot, workspaceSlug, updatedAt } = value;\n const hasValidRepositoryUrl = repositoryUrl === null || typeof repositoryUrl === 'string';\n const hasValidRepositoryRoot = repositoryRoot === null || typeof repositoryRoot === 'string';\n\n return (\n hasValidRepositoryUrl &&\n hasValidRepositoryRoot &&\n typeof workspaceSlug === 'string' &&\n workspaceSlug.trim().length > 0 &&\n isValidIsoDateString(updatedAt)\n );\n};\n\nconst readWorkspaceSlugMappings = async (configFile: string): Promise<StoredWorkspaceSlugMapping[]> => {\n const storedConfig = await readGlobalConfig(configFile);\n const mappings = storedConfig.workspaceSlugMappings;\n if (!Array.isArray(mappings)) return [];\n\n return mappings.filter(isStoredWorkspaceSlugMapping).slice(0, WORKSPACE_MAPPING_LIMIT);\n};\n\nconst writeWorkspaceSlugMappings = async (\n configFile: string,\n nextMappings: StoredWorkspaceSlugMapping[],\n): Promise<void> => {\n const storedConfig = await readGlobalConfig(configFile);\n await writeGlobalConfig(configFile, {\n ...withoutLegacyPublishedSkillPreferences(storedConfig),\n workspaceSlugMappings: nextMappings.slice(0, WORKSPACE_MAPPING_LIMIT),\n });\n};\n\nconst normalizeStoredRepositoryRoot = (value: string | null): string | null => {\n if (!value) return null;\n return normalizeAbsolutePath(value);\n};\n\nexport const upsertWorkspaceSlugMapping = async ({\n configFile,\n repositoryUrl,\n repositoryRoot,\n workspaceSlug,\n}: {\n configFile: string;\n repositoryUrl: string | null;\n repositoryRoot: string | null;\n workspaceSlug: string;\n}): Promise<void> => {\n const normalizedWorkspaceSlug = toWorkspaceSlug(workspaceSlug);\n if (!normalizedWorkspaceSlug) return;\n\n const normalizedRepositoryRoot = normalizeStoredRepositoryRoot(repositoryRoot);\n const existingMappings = await readWorkspaceSlugMappings(configFile);\n const filteredMappings = existingMappings.filter((mapping) => {\n if (repositoryUrl && mapping.repositoryUrl === repositoryUrl) return false;\n if (normalizedRepositoryRoot && normalizeStoredRepositoryRoot(mapping.repositoryRoot) === normalizedRepositoryRoot) {\n return false;\n }\n return true;\n });\n\n await writeWorkspaceSlugMappings(configFile, [\n {\n repositoryUrl,\n repositoryRoot: normalizedRepositoryRoot,\n workspaceSlug: normalizedWorkspaceSlug,\n updatedAt: new Date().toISOString(),\n },\n ...filteredMappings,\n ]);\n};\n\nexport const findWorkspaceSlugMapping = async ({\n configFile,\n repositoryUrl,\n repositoryRoot,\n}: {\n configFile: string;\n repositoryUrl: string | null;\n repositoryRoot: string | null;\n}): Promise<StoredWorkspaceSlugMapping | null> => {\n const normalizedRepositoryRoot = normalizeStoredRepositoryRoot(repositoryRoot);\n const mappings = await readWorkspaceSlugMappings(configFile);\n\n if (repositoryUrl) {\n const repositoryMatch = mappings.find((mapping) => mapping.repositoryUrl === repositoryUrl);\n if (repositoryMatch) return repositoryMatch;\n }\n\n if (normalizedRepositoryRoot) {\n const rootMatch = mappings.find(\n (mapping) => normalizeStoredRepositoryRoot(mapping.repositoryRoot) === normalizedRepositoryRoot,\n );\n if (rootMatch) return rootMatch;\n }\n\n return null;\n};\n\nexport const readGlobalAuthState = async (configFile: string): Promise<AuthState | null> => {\n const storedConfig = await readGlobalConfig(configFile);\n const storedAuthState = storedConfig.auth;\n if (storedAuthState === undefined || storedAuthState === null) return null;\n if (isAuthState(storedAuthState)) {\n if (hasLegacyPublishedSkillPreferences(storedConfig)) {\n await writeGlobalConfig(configFile, withoutLegacyPublishedSkillPreferences(storedConfig));\n }\n return storedAuthState;\n }\n\n await writeGlobalConfig(configFile, {\n ...withoutLegacyPublishedSkillPreferences(storedConfig),\n auth: null,\n });\n return null;\n};\n\nconst readLegacyAuthState = async (authStateFile: string): Promise<AuthState | null> => {\n const storedAuthState = await readJsonFile(authStateFile);\n if (storedAuthState === null) return null;\n if (isAuthState(storedAuthState)) return storedAuthState;\n\n await deleteFileIfExists(authStateFile);\n return null;\n};\n\nexport const writeAuthState = async (configFile: string, authState: AuthState) => {\n const storedConfig = await readGlobalConfig(configFile);\n await writeGlobalConfig(configFile, {\n ...withoutLegacyPublishedSkillPreferences(storedConfig),\n auth: authState,\n });\n};\n\nexport const clearAuthState = async (configFile: string) => {\n const storedConfig = await readGlobalConfig(configFile);\n await writeGlobalConfig(configFile, {\n ...withoutLegacyPublishedSkillPreferences(storedConfig),\n auth: null,\n });\n};\n\nexport const toStoredUserKey = (authState: AuthState | null): string => {\n if (authState?.userId) return authState.userId;\n if (authState?.email) return authState.email.toLowerCase();\n return 'anonymous';\n};\n\nexport const toAuthState = (session: PluginSessionResponse['session']): AuthState => ({\n pluginId: PLUGIN_ID,\n sessionToken: session.jwtToken,\n expiresAt: session.expiresAt,\n authenticatedAt: new Date().toISOString(),\n userId: session.user.id,\n email: session.user.email,\n role: session.user.role ?? null,\n});\n\nexport const resolveStoredAuthState = async (worktree: string, config: ResolvedConfig): Promise<AuthState | null> => {\n const authState = await readGlobalAuthState(config.authStatePath);\n\n if (authState && Date.parse(authState.expiresAt) > Date.now()) {\n return authState;\n }\n\n if (authState) {\n await clearAuthState(config.authStatePath);\n return null;\n }\n\n const legacyAuthStateFile = path.resolve(worktree, LEGACY_AUTH_STATE_PATH);\n const legacyAuthState = await readLegacyAuthState(legacyAuthStateFile);\n\n if (!legacyAuthState) return null;\n\n if (Date.parse(legacyAuthState.expiresAt) <= Date.now()) {\n await deleteFileIfExists(legacyAuthStateFile);\n return null;\n }\n\n await writeAuthState(config.authStatePath, legacyAuthState);\n await deleteFileIfExists(legacyAuthStateFile);\n return legacyAuthState;\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { FetchResult, PublishedSkillArtifactDetailPayload, PublishedSkillArtifactDetailPurpose, ResolvedConfig, WorkspaceResolution } from './types.js';
|
|
2
|
+
export declare const fetchPublishedSkillsGraphQl: <TData>({ worktree, config, query, variables, signal, onAuthStateChanged, }: {
|
|
3
|
+
worktree: string;
|
|
4
|
+
config: ResolvedConfig;
|
|
5
|
+
query: string;
|
|
6
|
+
variables: Record<string, unknown>;
|
|
7
|
+
signal: AbortSignal;
|
|
8
|
+
onAuthStateChanged?: () => void;
|
|
9
|
+
}) => Promise<{
|
|
10
|
+
ok: true;
|
|
11
|
+
data: TData;
|
|
12
|
+
fetchedAt: string;
|
|
13
|
+
} | {
|
|
14
|
+
ok: false;
|
|
15
|
+
result: Extract<FetchResult, {
|
|
16
|
+
ok: false;
|
|
17
|
+
}>;
|
|
18
|
+
}>;
|
|
19
|
+
export declare const fetchPublishedSkillsCatalog: (worktree: string, config: ResolvedConfig, resolution: WorkspaceResolution, signal: AbortSignal, onAuthStateChanged?: () => void) => Promise<FetchResult>;
|
|
20
|
+
export declare const maybePersistWorkspaceSlugFromCatalog: ({ config, resolution, fetchResult, }: {
|
|
21
|
+
config: ResolvedConfig;
|
|
22
|
+
resolution: WorkspaceResolution;
|
|
23
|
+
fetchResult: FetchResult;
|
|
24
|
+
}) => Promise<void>;
|
|
25
|
+
export declare const fetchPublishedSkillDetail: ({ worktree, config, resolution, skillVersionId, signal, onAuthStateChanged, purpose, }: {
|
|
26
|
+
worktree: string;
|
|
27
|
+
config: ResolvedConfig;
|
|
28
|
+
resolution: WorkspaceResolution;
|
|
29
|
+
skillVersionId: string;
|
|
30
|
+
signal: AbortSignal;
|
|
31
|
+
onAuthStateChanged?: () => void;
|
|
32
|
+
purpose: PublishedSkillArtifactDetailPurpose;
|
|
33
|
+
}) => Promise<{
|
|
34
|
+
ok: true;
|
|
35
|
+
artifact: PublishedSkillArtifactDetailPayload;
|
|
36
|
+
} | {
|
|
37
|
+
ok: false;
|
|
38
|
+
result: {
|
|
39
|
+
ok: false;
|
|
40
|
+
status: "not_found";
|
|
41
|
+
authMode: "session";
|
|
42
|
+
message: string;
|
|
43
|
+
fetchedAt: string;
|
|
44
|
+
source: "network";
|
|
45
|
+
};
|
|
46
|
+
} | {
|
|
47
|
+
ok: false;
|
|
48
|
+
result: Extract<FetchResult, {
|
|
49
|
+
ok: false;
|
|
50
|
+
}>;
|
|
51
|
+
}>;
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { PUBLISHED_SKILL_DETAIL_QUERY, PUBLISHED_SKILLS_CATALOG_QUERY } from '../graphql-operations.js';
|
|
2
|
+
import { clearAuthState, resolveStoredAuthState, upsertWorkspaceSlugMapping } from './auth-store.js';
|
|
3
|
+
import { toWorkspaceSlug } from './path-utils.js';
|
|
4
|
+
import { toDeliveryInput } from './workspace.js';
|
|
5
|
+
const isUnauthorizedGraphQlMessage = message => {
|
|
6
|
+
const normalizedMessage = message.toLowerCase();
|
|
7
|
+
return normalizedMessage.includes('not authorized') || normalizedMessage.includes('unauthorized');
|
|
8
|
+
};
|
|
9
|
+
export const fetchPublishedSkillsGraphQl = async ({
|
|
10
|
+
worktree,
|
|
11
|
+
config,
|
|
12
|
+
query,
|
|
13
|
+
variables,
|
|
14
|
+
signal,
|
|
15
|
+
onAuthStateChanged
|
|
16
|
+
}) => {
|
|
17
|
+
const authState = await resolveStoredAuthState(worktree, config);
|
|
18
|
+
const fetchedAt = new Date().toISOString();
|
|
19
|
+
if (!authState) {
|
|
20
|
+
return {
|
|
21
|
+
ok: false,
|
|
22
|
+
result: {
|
|
23
|
+
ok: false,
|
|
24
|
+
status: 'missing_auth',
|
|
25
|
+
authMode: 'missing',
|
|
26
|
+
message: 'No plugin session is stored. Interactive opencode_wizard_published_skills_fetch can bootstrap browser login automatically when needed. Configured backend and GraphQL URLs are shown for visibility, but no GraphQL request was made because auth is missing.',
|
|
27
|
+
fetchedAt,
|
|
28
|
+
source: 'network'
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
let response;
|
|
33
|
+
try {
|
|
34
|
+
response = await fetch(config.graphqlUrl, {
|
|
35
|
+
method: 'POST',
|
|
36
|
+
headers: {
|
|
37
|
+
'content-type': 'application/json',
|
|
38
|
+
authorization: `Bearer ${authState.sessionToken}`
|
|
39
|
+
},
|
|
40
|
+
body: JSON.stringify({
|
|
41
|
+
query,
|
|
42
|
+
variables
|
|
43
|
+
}),
|
|
44
|
+
signal
|
|
45
|
+
});
|
|
46
|
+
} catch (error) {
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
result: {
|
|
50
|
+
ok: false,
|
|
51
|
+
status: 'request_failed',
|
|
52
|
+
authMode: 'session',
|
|
53
|
+
message: error instanceof Error ? error.message : 'Unknown fetch error',
|
|
54
|
+
fetchedAt,
|
|
55
|
+
source: 'network'
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (response.status === 401 || response.status === 403) {
|
|
60
|
+
await clearAuthState(config.authStatePath);
|
|
61
|
+
onAuthStateChanged?.();
|
|
62
|
+
return {
|
|
63
|
+
ok: false,
|
|
64
|
+
result: {
|
|
65
|
+
ok: false,
|
|
66
|
+
status: 'missing_auth',
|
|
67
|
+
authMode: 'session',
|
|
68
|
+
message: 'Stored plugin session was rejected by the backend. Retry opencode_wizard_published_skills_fetch to bootstrap a fresh browser login automatically.',
|
|
69
|
+
fetchedAt,
|
|
70
|
+
source: 'network'
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
return {
|
|
76
|
+
ok: false,
|
|
77
|
+
result: {
|
|
78
|
+
ok: false,
|
|
79
|
+
status: 'request_failed',
|
|
80
|
+
authMode: 'session',
|
|
81
|
+
message: `GraphQL request failed with HTTP ${response.status}.`,
|
|
82
|
+
fetchedAt,
|
|
83
|
+
source: 'network'
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
let body;
|
|
88
|
+
try {
|
|
89
|
+
body = await response.json();
|
|
90
|
+
} catch (error) {
|
|
91
|
+
return {
|
|
92
|
+
ok: false,
|
|
93
|
+
result: {
|
|
94
|
+
ok: false,
|
|
95
|
+
status: 'request_failed',
|
|
96
|
+
authMode: 'session',
|
|
97
|
+
message: `GraphQL response was not valid JSON: ${error instanceof Error ? error.message : 'Unknown parse error'}`,
|
|
98
|
+
fetchedAt,
|
|
99
|
+
source: 'network'
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (body.errors?.length) {
|
|
104
|
+
const message = body.errors.map(error => error.message).join('; ');
|
|
105
|
+
if (body.errors.some(error => isUnauthorizedGraphQlMessage(error.message))) {
|
|
106
|
+
await clearAuthState(config.authStatePath);
|
|
107
|
+
onAuthStateChanged?.();
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
result: {
|
|
111
|
+
ok: false,
|
|
112
|
+
status: 'missing_auth',
|
|
113
|
+
authMode: 'session',
|
|
114
|
+
message: 'Stored plugin session is no longer valid. Retry opencode_wizard_published_skills_fetch to bootstrap a fresh browser login automatically.',
|
|
115
|
+
fetchedAt,
|
|
116
|
+
source: 'network'
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
ok: false,
|
|
122
|
+
result: {
|
|
123
|
+
ok: false,
|
|
124
|
+
status: 'request_failed',
|
|
125
|
+
authMode: 'session',
|
|
126
|
+
message,
|
|
127
|
+
fetchedAt,
|
|
128
|
+
source: 'network'
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (!body.data) {
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
result: {
|
|
136
|
+
ok: false,
|
|
137
|
+
status: 'request_failed',
|
|
138
|
+
authMode: 'session',
|
|
139
|
+
message: 'GraphQL response did not include data.',
|
|
140
|
+
fetchedAt,
|
|
141
|
+
source: 'network'
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
ok: true,
|
|
147
|
+
data: body.data,
|
|
148
|
+
fetchedAt
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
export const fetchPublishedSkillsCatalog = async (worktree, config, resolution, signal, onAuthStateChanged) => {
|
|
152
|
+
const response = await fetchPublishedSkillsGraphQl({
|
|
153
|
+
worktree,
|
|
154
|
+
config,
|
|
155
|
+
query: PUBLISHED_SKILLS_CATALOG_QUERY,
|
|
156
|
+
variables: {
|
|
157
|
+
input: toDeliveryInput(resolution)
|
|
158
|
+
},
|
|
159
|
+
signal,
|
|
160
|
+
onAuthStateChanged
|
|
161
|
+
});
|
|
162
|
+
if (!response.ok) return response.result;
|
|
163
|
+
const payload = response.data.pluginPublishedSkills;
|
|
164
|
+
if (!payload) {
|
|
165
|
+
return {
|
|
166
|
+
ok: false,
|
|
167
|
+
status: 'request_failed',
|
|
168
|
+
authMode: 'session',
|
|
169
|
+
message: 'GraphQL response did not include pluginPublishedSkills.',
|
|
170
|
+
fetchedAt: response.fetchedAt,
|
|
171
|
+
source: 'network'
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
ok: true,
|
|
176
|
+
status: 'ready',
|
|
177
|
+
authMode: 'session',
|
|
178
|
+
payload,
|
|
179
|
+
fetchedAt: response.fetchedAt,
|
|
180
|
+
source: 'network'
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
export const maybePersistWorkspaceSlugFromCatalog = async ({
|
|
184
|
+
config,
|
|
185
|
+
resolution,
|
|
186
|
+
fetchResult
|
|
187
|
+
}) => {
|
|
188
|
+
if (!fetchResult.ok) return;
|
|
189
|
+
const backendWorkspaceSlug = fetchResult.payload.workspace?.slug?.trim();
|
|
190
|
+
if (!backendWorkspaceSlug) return;
|
|
191
|
+
const normalizedWorkspaceSlug = toWorkspaceSlug(backendWorkspaceSlug);
|
|
192
|
+
if (!normalizedWorkspaceSlug) return;
|
|
193
|
+
if (resolution.workspaceSlug === normalizedWorkspaceSlug && resolution.workspaceSlugSource !== 'fallback') return;
|
|
194
|
+
await upsertWorkspaceSlugMapping({
|
|
195
|
+
configFile: config.authStatePath,
|
|
196
|
+
repositoryUrl: resolution.repositoryUrl,
|
|
197
|
+
repositoryRoot: resolution.repositoryRoot,
|
|
198
|
+
workspaceSlug: normalizedWorkspaceSlug
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
export const fetchPublishedSkillDetail = async ({
|
|
202
|
+
worktree,
|
|
203
|
+
config,
|
|
204
|
+
resolution,
|
|
205
|
+
skillVersionId,
|
|
206
|
+
signal,
|
|
207
|
+
onAuthStateChanged,
|
|
208
|
+
purpose
|
|
209
|
+
}) => {
|
|
210
|
+
const response = await fetchPublishedSkillsGraphQl({
|
|
211
|
+
worktree,
|
|
212
|
+
config,
|
|
213
|
+
query: PUBLISHED_SKILL_DETAIL_QUERY,
|
|
214
|
+
variables: {
|
|
215
|
+
input: {
|
|
216
|
+
...toDeliveryInput(resolution),
|
|
217
|
+
skillVersionId,
|
|
218
|
+
purpose
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
signal,
|
|
222
|
+
onAuthStateChanged
|
|
223
|
+
});
|
|
224
|
+
if (!response.ok) return response;
|
|
225
|
+
const artifact = response.data.pluginPublishedSkillVersionArtifact;
|
|
226
|
+
if (!artifact) {
|
|
227
|
+
return {
|
|
228
|
+
ok: false,
|
|
229
|
+
result: {
|
|
230
|
+
ok: false,
|
|
231
|
+
status: 'not_found',
|
|
232
|
+
authMode: 'session',
|
|
233
|
+
message: 'Published skill detail is not effective for the current scope.',
|
|
234
|
+
fetchedAt: response.fetchedAt,
|
|
235
|
+
source: 'network'
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
ok: true,
|
|
241
|
+
artifact
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["PUBLISHED_SKILL_DETAIL_QUERY","PUBLISHED_SKILLS_CATALOG_QUERY","clearAuthState","resolveStoredAuthState","upsertWorkspaceSlugMapping","toWorkspaceSlug","toDeliveryInput","isUnauthorizedGraphQlMessage","message","normalizedMessage","toLowerCase","includes","fetchPublishedSkillsGraphQl","worktree","config","query","variables","signal","onAuthStateChanged","authState","fetchedAt","Date","toISOString","ok","result","status","authMode","source","response","fetch","graphqlUrl","method","headers","authorization","sessionToken","body","JSON","stringify","error","Error","authStatePath","json","errors","length","map","join","some","data","fetchPublishedSkillsCatalog","resolution","input","payload","pluginPublishedSkills","maybePersistWorkspaceSlugFromCatalog","fetchResult","backendWorkspaceSlug","workspace","slug","trim","normalizedWorkspaceSlug","workspaceSlug","workspaceSlugSource","configFile","repositoryUrl","repositoryRoot","fetchPublishedSkillDetail","skillVersionId","purpose","artifact","pluginPublishedSkillVersionArtifact"],"sources":["../../src/server/client.ts"],"sourcesContent":["import {\n PUBLISHED_SKILL_DETAIL_QUERY,\n PUBLISHED_SKILLS_CATALOG_QUERY,\n} from '../graphql-operations.js';\nimport { clearAuthState, resolveStoredAuthState, upsertWorkspaceSlugMapping } from './auth-store.js';\nimport { toWorkspaceSlug } from './path-utils.js';\nimport { toDeliveryInput } from './workspace.js';\nimport type {\n FetchResult,\n GraphQLResponse,\n PublishedSkillArtifactDetailPayload,\n PublishedSkillArtifactDetailPurpose,\n PublishedSkillCatalogResponse,\n PublishedSkillDetailResponse,\n ResolvedConfig,\n WorkspaceResolution,\n} from './types.js';\n\nconst isUnauthorizedGraphQlMessage = (message: string): boolean => {\n const normalizedMessage = message.toLowerCase();\n return normalizedMessage.includes('not authorized') || normalizedMessage.includes('unauthorized');\n};\n\nexport const fetchPublishedSkillsGraphQl = async <TData>({\n worktree,\n config,\n query,\n variables,\n signal,\n onAuthStateChanged,\n}: {\n worktree: string;\n config: ResolvedConfig;\n query: string;\n variables: Record<string, unknown>;\n signal: AbortSignal;\n onAuthStateChanged?: () => void;\n}): Promise<\n | { ok: true; data: TData; fetchedAt: string }\n | { ok: false; result: Extract<FetchResult, { ok: false }> }\n> => {\n const authState = await resolveStoredAuthState(worktree, config);\n const fetchedAt = new Date().toISOString();\n\n if (!authState) {\n return {\n ok: false,\n result: {\n ok: false,\n status: 'missing_auth',\n authMode: 'missing',\n message:\n 'No plugin session is stored. Interactive opencode_wizard_published_skills_fetch can bootstrap browser login automatically when needed. Configured backend and GraphQL URLs are shown for visibility, but no GraphQL request was made because auth is missing.',\n fetchedAt,\n source: 'network',\n },\n };\n }\n\n let response: Response;\n\n try {\n response = await fetch(config.graphqlUrl, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n authorization: `Bearer ${authState.sessionToken}`,\n },\n body: JSON.stringify({ query, variables }),\n signal,\n });\n } catch (error) {\n return {\n ok: false,\n result: {\n ok: false,\n status: 'request_failed',\n authMode: 'session',\n message: error instanceof Error ? error.message : 'Unknown fetch error',\n fetchedAt,\n source: 'network',\n },\n };\n }\n\n if (response.status === 401 || response.status === 403) {\n await clearAuthState(config.authStatePath);\n onAuthStateChanged?.();\n return {\n ok: false,\n result: {\n ok: false,\n status: 'missing_auth',\n authMode: 'session',\n message:\n 'Stored plugin session was rejected by the backend. Retry opencode_wizard_published_skills_fetch to bootstrap a fresh browser login automatically.',\n fetchedAt,\n source: 'network',\n },\n };\n }\n\n if (!response.ok) {\n return {\n ok: false,\n result: {\n ok: false,\n status: 'request_failed',\n authMode: 'session',\n message: `GraphQL request failed with HTTP ${response.status}.`,\n fetchedAt,\n source: 'network',\n },\n };\n }\n\n let body: GraphQLResponse<TData>;\n\n try {\n body = (await response.json()) as GraphQLResponse<TData>;\n } catch (error) {\n return {\n ok: false,\n result: {\n ok: false,\n status: 'request_failed',\n authMode: 'session',\n message: `GraphQL response was not valid JSON: ${error instanceof Error ? error.message : 'Unknown parse error'}`,\n fetchedAt,\n source: 'network',\n },\n };\n }\n\n if (body.errors?.length) {\n const message = body.errors.map((error) => error.message).join('; ');\n\n if (body.errors.some((error) => isUnauthorizedGraphQlMessage(error.message))) {\n await clearAuthState(config.authStatePath);\n onAuthStateChanged?.();\n return {\n ok: false,\n result: {\n ok: false,\n status: 'missing_auth',\n authMode: 'session',\n message:\n 'Stored plugin session is no longer valid. Retry opencode_wizard_published_skills_fetch to bootstrap a fresh browser login automatically.',\n fetchedAt,\n source: 'network',\n },\n };\n }\n\n return {\n ok: false,\n result: { ok: false, status: 'request_failed', authMode: 'session', message, fetchedAt, source: 'network' },\n };\n }\n\n if (!body.data) {\n return {\n ok: false,\n result: {\n ok: false,\n status: 'request_failed',\n authMode: 'session',\n message: 'GraphQL response did not include data.',\n fetchedAt,\n source: 'network',\n },\n };\n }\n\n return { ok: true, data: body.data, fetchedAt };\n};\n\nexport const fetchPublishedSkillsCatalog = async (\n worktree: string,\n config: ResolvedConfig,\n resolution: WorkspaceResolution,\n signal: AbortSignal,\n onAuthStateChanged?: () => void,\n): Promise<FetchResult> => {\n const response = await fetchPublishedSkillsGraphQl<PublishedSkillCatalogResponse>({\n worktree,\n config,\n query: PUBLISHED_SKILLS_CATALOG_QUERY,\n variables: { input: toDeliveryInput(resolution) },\n signal,\n onAuthStateChanged,\n });\n\n if (!response.ok) return response.result;\n\n const payload = response.data.pluginPublishedSkills;\n\n if (!payload) {\n return {\n ok: false,\n status: 'request_failed',\n authMode: 'session',\n message: 'GraphQL response did not include pluginPublishedSkills.',\n fetchedAt: response.fetchedAt,\n source: 'network',\n };\n }\n\n return {\n ok: true,\n status: 'ready',\n authMode: 'session',\n payload,\n fetchedAt: response.fetchedAt,\n source: 'network',\n };\n};\n\nexport const maybePersistWorkspaceSlugFromCatalog = async ({\n config,\n resolution,\n fetchResult,\n}: {\n config: ResolvedConfig;\n resolution: WorkspaceResolution;\n fetchResult: FetchResult;\n}): Promise<void> => {\n if (!fetchResult.ok) return;\n\n const backendWorkspaceSlug = fetchResult.payload.workspace?.slug?.trim();\n if (!backendWorkspaceSlug) return;\n\n const normalizedWorkspaceSlug = toWorkspaceSlug(backendWorkspaceSlug);\n if (!normalizedWorkspaceSlug) return;\n\n if (resolution.workspaceSlug === normalizedWorkspaceSlug && resolution.workspaceSlugSource !== 'fallback') return;\n\n await upsertWorkspaceSlugMapping({\n configFile: config.authStatePath,\n repositoryUrl: resolution.repositoryUrl,\n repositoryRoot: resolution.repositoryRoot,\n workspaceSlug: normalizedWorkspaceSlug,\n });\n};\n\nexport const fetchPublishedSkillDetail = async ({\n worktree,\n config,\n resolution,\n skillVersionId,\n signal,\n onAuthStateChanged,\n purpose,\n}: {\n worktree: string;\n config: ResolvedConfig;\n resolution: WorkspaceResolution;\n skillVersionId: string;\n signal: AbortSignal;\n onAuthStateChanged?: () => void;\n purpose: PublishedSkillArtifactDetailPurpose;\n}): Promise<\n | { ok: true; artifact: PublishedSkillArtifactDetailPayload }\n | {\n ok: false;\n result: {\n ok: false;\n status: 'not_found';\n authMode: 'session';\n message: string;\n fetchedAt: string;\n source: 'network';\n };\n }\n | { ok: false; result: Extract<FetchResult, { ok: false }> }\n> => {\n const response = await fetchPublishedSkillsGraphQl<PublishedSkillDetailResponse>({\n worktree,\n config,\n query: PUBLISHED_SKILL_DETAIL_QUERY,\n variables: {\n input: { ...toDeliveryInput(resolution), skillVersionId, purpose },\n },\n signal,\n onAuthStateChanged,\n });\n\n if (!response.ok) return response;\n\n const artifact = response.data.pluginPublishedSkillVersionArtifact;\n\n if (!artifact) {\n return {\n ok: false,\n result: {\n ok: false,\n status: 'not_found',\n authMode: 'session',\n message: 'Published skill detail is not effective for the current scope.',\n fetchedAt: response.fetchedAt,\n source: 'network',\n },\n };\n }\n\n return { ok: true, artifact };\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { resolveBackendOriginFromValues } from '../config.js';
|
|
4
|
+
import { getGlobalConfigPath, ROOT_SKILL_SEED_PATH } from './constants.js';
|
|
5
|
+
import { normalizeAbsolutePath, toWorkspaceSlug } from './path-utils.js';
|
|
6
|
+
const parseDotEnvValue = value => {
|
|
7
|
+
const trimmedValue = value.trim();
|
|
8
|
+
if (trimmedValue.startsWith('"') && trimmedValue.endsWith('"') || trimmedValue.startsWith("'") && trimmedValue.endsWith("'")) {
|
|
9
|
+
return trimmedValue.slice(1, -1);
|
|
10
|
+
}
|
|
11
|
+
return trimmedValue;
|
|
12
|
+
};
|
|
13
|
+
const parseDotEnv = raw => {
|
|
14
|
+
const values = new Map();
|
|
15
|
+
for (const line of raw.split(/\r?\n/u)) {
|
|
16
|
+
const trimmedLine = line.trim();
|
|
17
|
+
if (!trimmedLine || trimmedLine.startsWith('#')) continue;
|
|
18
|
+
const separatorIndex = trimmedLine.indexOf('=');
|
|
19
|
+
if (separatorIndex <= 0) continue;
|
|
20
|
+
const key = trimmedLine.slice(0, separatorIndex).trim();
|
|
21
|
+
if (!key) continue;
|
|
22
|
+
const rawValue = trimmedLine.slice(separatorIndex + 1);
|
|
23
|
+
values.set(key, parseDotEnvValue(rawValue));
|
|
24
|
+
}
|
|
25
|
+
return values;
|
|
26
|
+
};
|
|
27
|
+
const findUpwardFile = async (startDirectory, fileName) => {
|
|
28
|
+
let currentDirectory = normalizeAbsolutePath(startDirectory);
|
|
29
|
+
while (true) {
|
|
30
|
+
const candidatePath = path.join(currentDirectory, fileName);
|
|
31
|
+
try {
|
|
32
|
+
await fs.access(candidatePath);
|
|
33
|
+
return candidatePath;
|
|
34
|
+
} catch {
|
|
35
|
+
const parentDirectory = path.dirname(currentDirectory);
|
|
36
|
+
if (parentDirectory === currentDirectory) return null;
|
|
37
|
+
currentDirectory = parentDirectory;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const readLocalEnvValues = async startDirectory => {
|
|
42
|
+
const envPath = await findUpwardFile(startDirectory, '.env');
|
|
43
|
+
if (!envPath) return new Map();
|
|
44
|
+
try {
|
|
45
|
+
const raw = await fs.readFile(envPath, 'utf8');
|
|
46
|
+
return parseDotEnv(raw);
|
|
47
|
+
} catch {
|
|
48
|
+
return new Map();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const resolveBackendOrigin = async worktree => {
|
|
52
|
+
const envValues = await readLocalEnvValues(worktree);
|
|
53
|
+
return resolveBackendOriginFromValues({
|
|
54
|
+
environmentBackendOrigin: process.env.OPENCODE_WIZARD_BACKEND_ORIGIN,
|
|
55
|
+
localBackendOrigin: envValues.get('OPENCODE_WIZARD_BACKEND_ORIGIN')
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
const readConfiguredWorkspaceSlug = () => {
|
|
59
|
+
const configuredWorkspaceSlug = process.env.OPENCODE_WIZARD_SKILLS_WORKSPACE_SLUG?.trim();
|
|
60
|
+
if (!configuredWorkspaceSlug) return null;
|
|
61
|
+
return toWorkspaceSlug(configuredWorkspaceSlug);
|
|
62
|
+
};
|
|
63
|
+
const resolveFallbackWorkspaceSlug = worktree => {
|
|
64
|
+
const configuredWorkspaceSlug = readConfiguredWorkspaceSlug();
|
|
65
|
+
if (configuredWorkspaceSlug) return configuredWorkspaceSlug;
|
|
66
|
+
return toWorkspaceSlug(path.basename(path.resolve(worktree)));
|
|
67
|
+
};
|
|
68
|
+
export const resolveConfig = async worktree => {
|
|
69
|
+
const backendOrigin = await resolveBackendOrigin(worktree);
|
|
70
|
+
return {
|
|
71
|
+
backendOrigin,
|
|
72
|
+
graphqlUrl: `${backendOrigin}/graphql`,
|
|
73
|
+
authSessionUrl: `${backendOrigin}/api/opencode-plugin/oauth/session`,
|
|
74
|
+
presenceUrl: `${backendOrigin}/api/opencode-plugin/presence`,
|
|
75
|
+
actionsUrl: `${backendOrigin}/api/opencode-plugin/actions`,
|
|
76
|
+
configuredWorkspaceSlug: readConfiguredWorkspaceSlug(),
|
|
77
|
+
fallbackWorkspaceSlug: resolveFallbackWorkspaceSlug(worktree),
|
|
78
|
+
rootSkillSeedPath: ROOT_SKILL_SEED_PATH,
|
|
79
|
+
authStatePath: getGlobalConfigPath()
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["fs","path","resolveBackendOriginFromValues","getGlobalConfigPath","ROOT_SKILL_SEED_PATH","normalizeAbsolutePath","toWorkspaceSlug","parseDotEnvValue","value","trimmedValue","trim","startsWith","endsWith","slice","parseDotEnv","raw","values","Map","line","split","trimmedLine","separatorIndex","indexOf","key","rawValue","set","findUpwardFile","startDirectory","fileName","currentDirectory","candidatePath","join","access","parentDirectory","dirname","readLocalEnvValues","envPath","readFile","resolveBackendOrigin","worktree","envValues","environmentBackendOrigin","process","env","OPENCODE_WIZARD_BACKEND_ORIGIN","localBackendOrigin","get","readConfiguredWorkspaceSlug","configuredWorkspaceSlug","OPENCODE_WIZARD_SKILLS_WORKSPACE_SLUG","resolveFallbackWorkspaceSlug","basename","resolve","resolveConfig","backendOrigin","graphqlUrl","authSessionUrl","presenceUrl","actionsUrl","fallbackWorkspaceSlug","rootSkillSeedPath","authStatePath"],"sources":["../../src/server/config.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { resolveBackendOriginFromValues } from '../config.js';\nimport { getGlobalConfigPath, ROOT_SKILL_SEED_PATH } from './constants.js';\nimport type { ResolvedConfig } from './types.js';\nimport { normalizeAbsolutePath, toWorkspaceSlug } from './path-utils.js';\n\nconst parseDotEnvValue = (value: string): string => {\n const trimmedValue = value.trim();\n\n if (\n (trimmedValue.startsWith('\"') && trimmedValue.endsWith('\"')) ||\n (trimmedValue.startsWith(\"'\") && trimmedValue.endsWith(\"'\"))\n ) {\n return trimmedValue.slice(1, -1);\n }\n\n return trimmedValue;\n};\n\nconst parseDotEnv = (raw: string): Map<string, string> => {\n const values = new Map<string, string>();\n\n for (const line of raw.split(/\\r?\\n/u)) {\n const trimmedLine = line.trim();\n if (!trimmedLine || trimmedLine.startsWith('#')) continue;\n\n const separatorIndex = trimmedLine.indexOf('=');\n if (separatorIndex <= 0) continue;\n\n const key = trimmedLine.slice(0, separatorIndex).trim();\n if (!key) continue;\n\n const rawValue = trimmedLine.slice(separatorIndex + 1);\n values.set(key, parseDotEnvValue(rawValue));\n }\n\n return values;\n};\n\nconst findUpwardFile = async (startDirectory: string, fileName: string): Promise<string | null> => {\n let currentDirectory = normalizeAbsolutePath(startDirectory);\n\n while (true) {\n const candidatePath = path.join(currentDirectory, fileName);\n\n try {\n await fs.access(candidatePath);\n return candidatePath;\n } catch {\n const parentDirectory = path.dirname(currentDirectory);\n if (parentDirectory === currentDirectory) return null;\n currentDirectory = parentDirectory;\n }\n }\n};\n\nconst readLocalEnvValues = async (startDirectory: string): Promise<Map<string, string>> => {\n const envPath = await findUpwardFile(startDirectory, '.env');\n if (!envPath) return new Map<string, string>();\n\n try {\n const raw = await fs.readFile(envPath, 'utf8');\n return parseDotEnv(raw);\n } catch {\n return new Map<string, string>();\n }\n};\n\nconst resolveBackendOrigin = async (worktree: string): Promise<string> => {\n const envValues = await readLocalEnvValues(worktree);\n\n return resolveBackendOriginFromValues({\n environmentBackendOrigin: process.env.OPENCODE_WIZARD_BACKEND_ORIGIN,\n localBackendOrigin: envValues.get('OPENCODE_WIZARD_BACKEND_ORIGIN'),\n });\n};\n\nconst readConfiguredWorkspaceSlug = (): string | null => {\n const configuredWorkspaceSlug = process.env.OPENCODE_WIZARD_SKILLS_WORKSPACE_SLUG?.trim();\n if (!configuredWorkspaceSlug) return null;\n return toWorkspaceSlug(configuredWorkspaceSlug);\n};\n\nconst resolveFallbackWorkspaceSlug = (worktree: string): string => {\n const configuredWorkspaceSlug = readConfiguredWorkspaceSlug();\n if (configuredWorkspaceSlug) return configuredWorkspaceSlug;\n return toWorkspaceSlug(path.basename(path.resolve(worktree)));\n};\n\nexport const resolveConfig = async (worktree: string): Promise<ResolvedConfig> => {\n const backendOrigin = await resolveBackendOrigin(worktree);\n\n return {\n backendOrigin,\n graphqlUrl: `${backendOrigin}/graphql`,\n authSessionUrl: `${backendOrigin}/api/opencode-plugin/oauth/session`,\n presenceUrl: `${backendOrigin}/api/opencode-plugin/presence`,\n actionsUrl: `${backendOrigin}/api/opencode-plugin/actions`,\n configuredWorkspaceSlug: readConfiguredWorkspaceSlug(),\n fallbackWorkspaceSlug: resolveFallbackWorkspaceSlug(worktree),\n rootSkillSeedPath: ROOT_SKILL_SEED_PATH,\n authStatePath: getGlobalConfigPath(),\n };\n};\n"],"mappings":"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","ignoreList":[]}
|