@aexol/opencode-wizard 0.3.3 → 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.
Files changed (96) hide show
  1. package/dist/graphql-operations.d.ts +4 -0
  2. package/dist/graphql-operations.js +225 -0
  3. package/dist/graphql-operations.js.map +1 -0
  4. package/dist/plugin-tools.d.ts +64 -0
  5. package/dist/plugin-tools.js +57 -0
  6. package/dist/plugin-tools.js.map +1 -0
  7. package/dist/published-skills-system-note.d.ts +9 -0
  8. package/dist/published-skills-system-note.js +34 -0
  9. package/dist/published-skills-system-note.js.map +1 -0
  10. package/dist/published-skills-transform.d.ts +161 -0
  11. package/dist/published-skills-transform.js +238 -0
  12. package/dist/published-skills-transform.js.map +1 -0
  13. package/dist/server/auth-flow.d.ts +10 -0
  14. package/dist/server/auth-flow.js +215 -0
  15. package/dist/server/auth-flow.js.map +1 -0
  16. package/dist/server/auth-store.d.ts +19 -0
  17. package/dist/server/auth-store.js +177 -0
  18. package/dist/server/auth-store.js.map +1 -0
  19. package/dist/server/client.d.ts +51 -0
  20. package/dist/server/client.js +244 -0
  21. package/dist/server/client.js.map +1 -0
  22. package/dist/server/config.d.ts +2 -0
  23. package/dist/server/config.js +82 -0
  24. package/dist/server/config.js.map +1 -0
  25. package/dist/server/constants.d.ts +26 -0
  26. package/dist/server/constants.js +32 -0
  27. package/dist/server/constants.js.map +1 -0
  28. package/dist/server/path-utils.d.ts +2 -0
  29. package/dist/server/path-utils.js +8 -0
  30. package/dist/server/path-utils.js.map +1 -0
  31. package/dist/server/presence.d.ts +14 -0
  32. package/dist/server/presence.js +68 -0
  33. package/dist/server/presence.js.map +1 -0
  34. package/dist/server/runtime.d.ts +32 -0
  35. package/dist/server/runtime.js +1110 -0
  36. package/dist/server/runtime.js.map +1 -0
  37. package/dist/server/status.d.ts +27 -0
  38. package/dist/server/status.js +224 -0
  39. package/dist/server/status.js.map +1 -0
  40. package/dist/server/types.d.ts +321 -0
  41. package/dist/server/types.js +2 -0
  42. package/dist/server/types.js.map +1 -0
  43. package/dist/server/workspace.d.ts +15 -0
  44. package/dist/server/workspace.js +126 -0
  45. package/dist/server/workspace.js.map +1 -0
  46. package/dist/server.d.ts +4 -309
  47. package/dist/server.js +4 -2611
  48. package/dist/server.js.map +1 -1
  49. package/dist/smoke-published-skills.js +11 -9
  50. package/dist/smoke-published-skills.js.map +1 -1
  51. package/dist/tui/components/common.d.ts +15 -0
  52. package/dist/tui/components/common.js +81 -0
  53. package/dist/tui/components/common.js.map +1 -0
  54. package/dist/tui/components/preference-action-notice-row.d.ts +5 -0
  55. package/dist/tui/components/preference-action-notice-row.js +17 -0
  56. package/dist/tui/components/preference-action-notice-row.js.map +1 -0
  57. package/dist/tui/components/skill-catalog-row.d.ts +8 -0
  58. package/dist/tui/components/skill-catalog-row.js +124 -0
  59. package/dist/tui/components/skill-catalog-row.js.map +1 -0
  60. package/dist/tui/components/status-content.d.ts +14 -0
  61. package/dist/tui/components/status-content.js +131 -0
  62. package/dist/tui/components/status-content.js.map +1 -0
  63. package/dist/tui/components/wizard-skills-dialog-content.d.ts +9 -0
  64. package/dist/tui/components/wizard-skills-dialog-content.js +219 -0
  65. package/dist/tui/components/wizard-skills-dialog-content.js.map +1 -0
  66. package/dist/tui/components/wizard-skills-dialog.d.ts +7 -0
  67. package/dist/tui/components/wizard-skills-dialog.js +156 -0
  68. package/dist/tui/components/wizard-skills-dialog.js.map +1 -0
  69. package/dist/tui/constants.d.ts +8 -0
  70. package/dist/tui/constants.js +9 -0
  71. package/dist/tui/constants.js.map +1 -0
  72. package/dist/tui/formatting.d.ts +8 -0
  73. package/dist/tui/formatting.js +45 -0
  74. package/dist/tui/formatting.js.map +1 -0
  75. package/dist/tui/plugin.d.ts +2 -0
  76. package/dist/tui/plugin.js +26 -0
  77. package/dist/tui/plugin.js.map +1 -0
  78. package/dist/tui/rendering.d.ts +2 -0
  79. package/dist/tui/rendering.js +8 -0
  80. package/dist/tui/rendering.js.map +1 -0
  81. package/dist/tui/skill-helpers.d.ts +13 -0
  82. package/dist/tui/skill-helpers.js +49 -0
  83. package/dist/tui/skill-helpers.js.map +1 -0
  84. package/dist/tui/slots.d.ts +2 -0
  85. package/dist/tui/slots.js +56 -0
  86. package/dist/tui/slots.js.map +1 -0
  87. package/dist/tui/status.d.ts +2 -0
  88. package/dist/tui/status.js +21 -0
  89. package/dist/tui/status.js.map +1 -0
  90. package/dist/tui/types.d.ts +75 -0
  91. package/dist/tui/types.js +2 -0
  92. package/dist/tui/types.js.map +1 -0
  93. package/dist/tui.d.ts +1 -44
  94. package/dist/tui.js +2 -870
  95. package/dist/tui.js.map +1 -1
  96. 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,2 @@
1
+ import type { ResolvedConfig } from './types.js';
2
+ export declare const resolveConfig: (worktree: string) => Promise<ResolvedConfig>;
@@ -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":"AAAA,OAAOA,EAAE,MAAM,kBAAkB;AACjC,OAAOC,IAAI,MAAM,WAAW;AAC5B,SAASC,8BAA8B,QAAQ,cAAc;AAC7D,SAASC,mBAAmB,EAAEC,oBAAoB,QAAQ,gBAAgB;AAE1E,SAASC,qBAAqB,EAAEC,eAAe,QAAQ,iBAAiB;AAExE,MAAMC,gBAAgB,GAAIC,KAAa,IAAa;EAClD,MAAMC,YAAY,GAAGD,KAAK,CAACE,IAAI,CAAC,CAAC;EAEjC,IACGD,YAAY,CAACE,UAAU,CAAC,GAAG,CAAC,IAAIF,YAAY,CAACG,QAAQ,CAAC,GAAG,CAAC,IAC1DH,YAAY,CAACE,UAAU,CAAC,GAAG,CAAC,IAAIF,YAAY,CAACG,QAAQ,CAAC,GAAG,CAAE,EAC5D;IACA,OAAOH,YAAY,CAACI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;EAClC;EAEA,OAAOJ,YAAY;AACrB,CAAC;AAED,MAAMK,WAAW,GAAIC,GAAW,IAA0B;EACxD,MAAMC,MAAM,GAAG,IAAIC,GAAG,CAAiB,CAAC;EAExC,KAAK,MAAMC,IAAI,IAAIH,GAAG,CAACI,KAAK,CAAC,QAAQ,CAAC,EAAE;IACtC,MAAMC,WAAW,GAAGF,IAAI,CAACR,IAAI,CAAC,CAAC;IAC/B,IAAI,CAACU,WAAW,IAAIA,WAAW,CAACT,UAAU,CAAC,GAAG,CAAC,EAAE;IAEjD,MAAMU,cAAc,GAAGD,WAAW,CAACE,OAAO,CAAC,GAAG,CAAC;IAC/C,IAAID,cAAc,IAAI,CAAC,EAAE;IAEzB,MAAME,GAAG,GAAGH,WAAW,CAACP,KAAK,CAAC,CAAC,EAAEQ,cAAc,CAAC,CAACX,IAAI,CAAC,CAAC;IACvD,IAAI,CAACa,GAAG,EAAE;IAEV,MAAMC,QAAQ,GAAGJ,WAAW,CAACP,KAAK,CAACQ,cAAc,GAAG,CAAC,CAAC;IACtDL,MAAM,CAACS,GAAG,CAACF,GAAG,EAAEhB,gBAAgB,CAACiB,QAAQ,CAAC,CAAC;EAC7C;EAEA,OAAOR,MAAM;AACf,CAAC;AAED,MAAMU,cAAc,GAAG,MAAAA,CAAOC,cAAsB,EAAEC,QAAgB,KAA6B;EACjG,IAAIC,gBAAgB,GAAGxB,qBAAqB,CAACsB,cAAc,CAAC;EAE5D,OAAO,IAAI,EAAE;IACX,MAAMG,aAAa,GAAG7B,IAAI,CAAC8B,IAAI,CAACF,gBAAgB,EAAED,QAAQ,CAAC;IAE3D,IAAI;MACF,MAAM5B,EAAE,CAACgC,MAAM,CAACF,aAAa,CAAC;MAC9B,OAAOA,aAAa;IACtB,CAAC,CAAC,MAAM;MACN,MAAMG,eAAe,GAAGhC,IAAI,CAACiC,OAAO,CAACL,gBAAgB,CAAC;MACtD,IAAII,eAAe,KAAKJ,gBAAgB,EAAE,OAAO,IAAI;MACrDA,gBAAgB,GAAGI,eAAe;IACpC;EACF;AACF,CAAC;AAED,MAAME,kBAAkB,GAAG,MAAOR,cAAsB,IAAmC;EACzF,MAAMS,OAAO,GAAG,MAAMV,cAAc,CAACC,cAAc,EAAE,MAAM,CAAC;EAC5D,IAAI,CAACS,OAAO,EAAE,OAAO,IAAInB,GAAG,CAAiB,CAAC;EAE9C,IAAI;IACF,MAAMF,GAAG,GAAG,MAAMf,EAAE,CAACqC,QAAQ,CAACD,OAAO,EAAE,MAAM,CAAC;IAC9C,OAAOtB,WAAW,CAACC,GAAG,CAAC;EACzB,CAAC,CAAC,MAAM;IACN,OAAO,IAAIE,GAAG,CAAiB,CAAC;EAClC;AACF,CAAC;AAED,MAAMqB,oBAAoB,GAAG,MAAOC,QAAgB,IAAsB;EACxE,MAAMC,SAAS,GAAG,MAAML,kBAAkB,CAACI,QAAQ,CAAC;EAEpD,OAAOrC,8BAA8B,CAAC;IACpCuC,wBAAwB,EAAEC,OAAO,CAACC,GAAG,CAACC,8BAA8B;IACpEC,kBAAkB,EAAEL,SAAS,CAACM,GAAG,CAAC,gCAAgC;EACpE,CAAC,CAAC;AACJ,CAAC;AAED,MAAMC,2BAA2B,GAAGA,CAAA,KAAqB;EACvD,MAAMC,uBAAuB,GAAGN,OAAO,CAACC,GAAG,CAACM,qCAAqC,EAAEvC,IAAI,CAAC,CAAC;EACzF,IAAI,CAACsC,uBAAuB,EAAE,OAAO,IAAI;EACzC,OAAO1C,eAAe,CAAC0C,uBAAuB,CAAC;AACjD,CAAC;AAED,MAAME,4BAA4B,GAAIX,QAAgB,IAAa;EACjE,MAAMS,uBAAuB,GAAGD,2BAA2B,CAAC,CAAC;EAC7D,IAAIC,uBAAuB,EAAE,OAAOA,uBAAuB;EAC3D,OAAO1C,eAAe,CAACL,IAAI,CAACkD,QAAQ,CAAClD,IAAI,CAACmD,OAAO,CAACb,QAAQ,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,OAAO,MAAMc,aAAa,GAAG,MAAOd,QAAgB,IAA8B;EAChF,MAAMe,aAAa,GAAG,MAAMhB,oBAAoB,CAACC,QAAQ,CAAC;EAE1D,OAAO;IACLe,aAAa;IACbC,UAAU,EAAE,GAAGD,aAAa,UAAU;IACtCE,cAAc,EAAE,GAAGF,aAAa,oCAAoC;IACpEG,WAAW,EAAE,GAAGH,aAAa,+BAA+B;IAC5DI,UAAU,EAAE,GAAGJ,aAAa,8BAA8B;IAC1DN,uBAAuB,EAAED,2BAA2B,CAAC,CAAC;IACtDY,qBAAqB,EAAET,4BAA4B,CAACX,QAAQ,CAAC;IAC7DqB,iBAAiB,EAAExD,oBAAoB;IACvCyD,aAAa,EAAE1D,mBAAmB,CAAC;EACrC,CAAC;AACH,CAAC","ignoreList":[]}