gsd-opencode 1.9.2 → 1.10.2
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/agents/gsd-debugger.md +5 -5
- package/agents/gsd-settings.md +476 -30
- package/bin/gsd-install.js +105 -0
- package/bin/gsd.js +352 -0
- package/{command → commands}/gsd/add-phase.md +1 -1
- package/{command → commands}/gsd/audit-milestone.md +1 -1
- package/{command → commands}/gsd/debug.md +3 -3
- package/{command → commands}/gsd/discuss-phase.md +1 -1
- package/{command → commands}/gsd/execute-phase.md +1 -1
- package/{command → commands}/gsd/list-phase-assumptions.md +1 -1
- package/{command → commands}/gsd/map-codebase.md +1 -1
- package/{command → commands}/gsd/new-milestone.md +1 -1
- package/{command → commands}/gsd/new-project.md +3 -3
- package/{command → commands}/gsd/plan-phase.md +2 -2
- package/{command → commands}/gsd/research-phase.md +1 -1
- package/{command → commands}/gsd/verify-work.md +1 -1
- package/get-shit-done/workflows/list-phase-assumptions.md +1 -1
- package/get-shit-done/workflows/verify-work.md +5 -5
- package/lib/constants.js +199 -0
- package/package.json +34 -20
- package/src/commands/check.js +329 -0
- package/src/commands/config.js +337 -0
- package/src/commands/install.js +608 -0
- package/src/commands/list.js +256 -0
- package/src/commands/repair.js +519 -0
- package/src/commands/uninstall.js +732 -0
- package/src/commands/update.js +444 -0
- package/src/services/backup-manager.js +585 -0
- package/src/services/config.js +262 -0
- package/src/services/file-ops.js +855 -0
- package/src/services/health-checker.js +475 -0
- package/src/services/manifest-manager.js +301 -0
- package/src/services/migration-service.js +831 -0
- package/src/services/repair-service.js +846 -0
- package/src/services/scope-manager.js +303 -0
- package/src/services/settings.js +553 -0
- package/src/services/structure-detector.js +240 -0
- package/src/services/update-service.js +863 -0
- package/src/utils/hash.js +71 -0
- package/src/utils/interactive.js +222 -0
- package/src/utils/logger.js +128 -0
- package/src/utils/npm-registry.js +255 -0
- package/src/utils/path-resolver.js +226 -0
- /package/{command → commands}/gsd/add-todo.md +0 -0
- /package/{command → commands}/gsd/check-todos.md +0 -0
- /package/{command → commands}/gsd/complete-milestone.md +0 -0
- /package/{command → commands}/gsd/help.md +0 -0
- /package/{command → commands}/gsd/insert-phase.md +0 -0
- /package/{command → commands}/gsd/pause-work.md +0 -0
- /package/{command → commands}/gsd/plan-milestone-gaps.md +0 -0
- /package/{command → commands}/gsd/progress.md +0 -0
- /package/{command → commands}/gsd/quick.md +0 -0
- /package/{command → commands}/gsd/remove-phase.md +0 -0
- /package/{command → commands}/gsd/resume-work.md +0 -0
- /package/{command → commands}/gsd/set-model.md +0 -0
- /package/{command → commands}/gsd/set-profile.md +0 -0
- /package/{command → commands}/gsd/settings.md +0 -0
- /package/{command → commands}/gsd/update.md +0 -0
- /package/{command → commands}/gsd/whats-new.md +0 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration manager for GSD-OpenCode installation state.
|
|
3
|
+
*
|
|
4
|
+
* This module provides persistent configuration management through the VERSION
|
|
5
|
+
* file, tracking installed versions and providing comprehensive installation
|
|
6
|
+
* information. Works in conjunction with ScopeManager to handle different
|
|
7
|
+
* installation scopes.
|
|
8
|
+
*
|
|
9
|
+
* All file operations are async and include proper error handling for common
|
|
10
|
+
* filesystem issues like permission errors and missing files.
|
|
11
|
+
*
|
|
12
|
+
* @module config
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import fs from 'fs/promises';
|
|
16
|
+
import path from 'path';
|
|
17
|
+
import { VERSION_FILE } from '../../lib/constants.js';
|
|
18
|
+
import { ScopeManager } from './scope-manager.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Manages configuration persistence and installation state.
|
|
22
|
+
*
|
|
23
|
+
* This class handles reading and writing the VERSION file, which tracks the
|
|
24
|
+
* installed version of GSD-OpenCode. It delegates path resolution to a
|
|
25
|
+
* ScopeManager instance, allowing it to work with both global and local
|
|
26
|
+
* installations seamlessly.
|
|
27
|
+
*
|
|
28
|
+
* @class ConfigManager
|
|
29
|
+
* @example
|
|
30
|
+
* const scope = new ScopeManager({ scope: 'global' });
|
|
31
|
+
* const config = new ConfigManager(scope);
|
|
32
|
+
*
|
|
33
|
+
* // Check installation status
|
|
34
|
+
* const info = await config.getInstallationInfo();
|
|
35
|
+
* console.log(info.installed); // true/false
|
|
36
|
+
* console.log(info.version); // '1.0.0' or null
|
|
37
|
+
* console.log(info.location); // '/home/user/.config/opencode'
|
|
38
|
+
* console.log(info.scope); // 'global'
|
|
39
|
+
*
|
|
40
|
+
* // Set version during installation
|
|
41
|
+
* await config.setVersion('1.0.0');
|
|
42
|
+
*/
|
|
43
|
+
export class ConfigManager {
|
|
44
|
+
/**
|
|
45
|
+
* Creates a new ConfigManager instance.
|
|
46
|
+
*
|
|
47
|
+
* @param {ScopeManager} scopeManager - ScopeManager instance for path resolution
|
|
48
|
+
* @throws {Error} If scopeManager is not provided or invalid
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* const scope = new ScopeManager({ scope: 'global' });
|
|
52
|
+
* const config = new ConfigManager(scope);
|
|
53
|
+
*/
|
|
54
|
+
constructor(scopeManager) {
|
|
55
|
+
if (!scopeManager) {
|
|
56
|
+
throw new Error('ScopeManager instance is required');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (typeof scopeManager.getTargetDir !== 'function') {
|
|
60
|
+
throw new Error('Invalid ScopeManager: missing getTargetDir method');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
this.scopeManager = scopeManager;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Gets the target installation directory.
|
|
68
|
+
*
|
|
69
|
+
* Delegates to the ScopeManager's getTargetDir method.
|
|
70
|
+
*
|
|
71
|
+
* @returns {string} Absolute path to the installation directory
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* const config = new ConfigManager(scope);
|
|
75
|
+
* config.getTargetDir(); // '/home/user/.config/opencode'
|
|
76
|
+
*/
|
|
77
|
+
getTargetDir() {
|
|
78
|
+
return this.scopeManager.getTargetDir();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Gets the full path to the VERSION file.
|
|
83
|
+
*
|
|
84
|
+
* Private helper method that constructs the path to the VERSION file
|
|
85
|
+
* in the target installation directory.
|
|
86
|
+
*
|
|
87
|
+
* @returns {string} Absolute path to VERSION file
|
|
88
|
+
* @private
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* const versionPath = config._getVersionPath();
|
|
92
|
+
* // Returns: '/home/user/.config/opencode/VERSION'
|
|
93
|
+
*/
|
|
94
|
+
_getVersionPath() {
|
|
95
|
+
return path.join(this.getTargetDir(), VERSION_FILE);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Checks if GSD-OpenCode is installed.
|
|
100
|
+
*
|
|
101
|
+
* Async version that checks for VERSION file existence. This is the
|
|
102
|
+
* preferred method for checking installation status in async contexts.
|
|
103
|
+
*
|
|
104
|
+
* @returns {Promise<boolean>} True if VERSION file exists
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* const config = new ConfigManager(scope);
|
|
108
|
+
* if (await config.isInstalled()) {
|
|
109
|
+
* console.log('Already installed');
|
|
110
|
+
* }
|
|
111
|
+
*/
|
|
112
|
+
async isInstalled() {
|
|
113
|
+
try {
|
|
114
|
+
await fs.access(this._getVersionPath(), fs.constants.F_OK);
|
|
115
|
+
return true;
|
|
116
|
+
} catch (error) {
|
|
117
|
+
if (error.code === 'ENOENT') {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
// For other errors (permissions, etc.), assume not installed
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Reads the installed version from the VERSION file.
|
|
127
|
+
*
|
|
128
|
+
* Returns the version string stored in the VERSION file, or null if
|
|
129
|
+
* the file doesn't exist or can't be read.
|
|
130
|
+
*
|
|
131
|
+
* @returns {Promise<string|null>} The installed version, or null if not installed
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* const config = new ConfigManager(scope);
|
|
135
|
+
* const version = await config.getVersion();
|
|
136
|
+
* if (version) {
|
|
137
|
+
* console.log(`Installed version: ${version}`);
|
|
138
|
+
* } else {
|
|
139
|
+
* console.log('Not installed');
|
|
140
|
+
* }
|
|
141
|
+
*/
|
|
142
|
+
async getVersion() {
|
|
143
|
+
try {
|
|
144
|
+
const content = await fs.readFile(this._getVersionPath(), 'utf-8');
|
|
145
|
+
return content.trim();
|
|
146
|
+
} catch (error) {
|
|
147
|
+
if (error.code === 'ENOENT') {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
if (error.code === 'EACCES') {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`Permission denied: Cannot read version file at ${this._getVersionPath()}. ` +
|
|
153
|
+
'Check file permissions or run with appropriate privileges.'
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
// Return null for any other error
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Writes the version to the VERSION file.
|
|
163
|
+
*
|
|
164
|
+
* Creates the target directory if it doesn't exist, then writes the
|
|
165
|
+
* version string to the VERSION file. Handles permission errors
|
|
166
|
+
* gracefully with helpful error messages.
|
|
167
|
+
*
|
|
168
|
+
* @param {string} version - Version string to write (e.g., '1.0.0')
|
|
169
|
+
* @returns {Promise<void>}
|
|
170
|
+
* @throws {Error} If directory cannot be created or file cannot be written
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* const config = new ConfigManager(scope);
|
|
174
|
+
* await config.setVersion('1.0.0');
|
|
175
|
+
* console.log('Version set successfully');
|
|
176
|
+
*/
|
|
177
|
+
async setVersion(version) {
|
|
178
|
+
if (!version || typeof version !== 'string') {
|
|
179
|
+
throw new Error('Version must be a non-empty string');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const targetDir = this.getTargetDir();
|
|
183
|
+
const versionPath = this._getVersionPath();
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
// Ensure target directory exists
|
|
187
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
188
|
+
|
|
189
|
+
// Write version file
|
|
190
|
+
await fs.writeFile(versionPath, version.trim(), 'utf-8');
|
|
191
|
+
} catch (error) {
|
|
192
|
+
if (error.code === 'EACCES') {
|
|
193
|
+
throw new Error(
|
|
194
|
+
`Permission denied: Cannot write version file to ${targetDir}. ` +
|
|
195
|
+
'Check directory permissions or run with appropriate privileges.'
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
if (error.code === 'ENOSPC') {
|
|
199
|
+
throw new Error(
|
|
200
|
+
`No space left on device: Cannot write version file to ${targetDir}. ` +
|
|
201
|
+
'Free up disk space and try again.'
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
throw new Error(
|
|
205
|
+
`Failed to write version file: ${error.message}`
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Gets comprehensive installation information.
|
|
212
|
+
*
|
|
213
|
+
* Returns an object containing all relevant installation details:
|
|
214
|
+
* whether GSD-OpenCode is installed, the installed version, the
|
|
215
|
+
* installation location, scope (global/local), and a display-friendly
|
|
216
|
+
* path prefix.
|
|
217
|
+
*
|
|
218
|
+
* @returns {Promise<Object>} Installation information object
|
|
219
|
+
* @property {boolean} installed - Whether GSD-OpenCode is installed
|
|
220
|
+
* @property {string|null} version - The installed version, or null
|
|
221
|
+
* @property {string} location - Absolute path to installation directory
|
|
222
|
+
* @property {string} scope - 'global' or 'local'
|
|
223
|
+
* @property {string} pathPrefix - Display-friendly path (e.g., '~/.config/opencode')
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* const config = new ConfigManager(scope);
|
|
227
|
+
* const info = await config.getInstallationInfo();
|
|
228
|
+
* console.log(info);
|
|
229
|
+
* // {
|
|
230
|
+
* // installed: true,
|
|
231
|
+
* // version: '1.0.0',
|
|
232
|
+
* // location: '/home/user/.config/opencode',
|
|
233
|
+
* // scope: 'global',
|
|
234
|
+
* // pathPrefix: '~/.config/opencode'
|
|
235
|
+
* // }
|
|
236
|
+
*/
|
|
237
|
+
async getInstallationInfo() {
|
|
238
|
+
const [installed, version] = await Promise.all([
|
|
239
|
+
this.isInstalled(),
|
|
240
|
+
this.getVersion()
|
|
241
|
+
]);
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
installed,
|
|
245
|
+
version,
|
|
246
|
+
location: this.getTargetDir(),
|
|
247
|
+
scope: this.scopeManager.getScope(),
|
|
248
|
+
pathPrefix: this.scopeManager.getPathPrefix()
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Default export for the config module.
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* import { ConfigManager } from './services/config.js';
|
|
258
|
+
* const config = new ConfigManager(scope);
|
|
259
|
+
*/
|
|
260
|
+
export default {
|
|
261
|
+
ConfigManager
|
|
262
|
+
};
|