berget 2.2.7 → 2.2.9
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/.github/workflows/publish.yml +6 -6
- package/.github/workflows/test.yml +1 -1
- package/.prettierrc +5 -3
- package/dist/index.js +24 -25
- package/dist/package.json +7 -3
- package/dist/src/agents/app.js +8 -8
- package/dist/src/agents/backend.js +3 -3
- package/dist/src/agents/devops.js +8 -8
- package/dist/src/agents/frontend.js +3 -3
- package/dist/src/agents/fullstack.js +3 -3
- package/dist/src/agents/index.js +18 -18
- package/dist/src/agents/quality.js +8 -8
- package/dist/src/agents/security.js +8 -8
- package/dist/src/client.js +115 -127
- package/dist/src/commands/api-keys.js +181 -202
- package/dist/src/commands/auth.js +16 -25
- package/dist/src/commands/autocomplete.js +8 -8
- package/dist/src/commands/billing.js +10 -19
- package/dist/src/commands/chat.js +139 -170
- package/dist/src/commands/clusters.js +21 -30
- package/dist/src/commands/code/__tests__/auth-sync.test.js +189 -186
- package/dist/src/commands/code/__tests__/fake-api-key-service.js +3 -13
- package/dist/src/commands/code/__tests__/fake-auth-service.js +21 -29
- package/dist/src/commands/code/__tests__/fake-command-runner.js +22 -33
- package/dist/src/commands/code/__tests__/fake-file-store.js +19 -41
- package/dist/src/commands/code/__tests__/fake-prompter.js +81 -97
- package/dist/src/commands/code/__tests__/setup-flow.test.js +295 -295
- package/dist/src/commands/code/adapters/clack-prompter.js +15 -32
- package/dist/src/commands/code/adapters/fs-file-store.js +25 -44
- package/dist/src/commands/code/adapters/spawn-command-runner.js +27 -41
- package/dist/src/commands/code/auth-sync.js +215 -228
- package/dist/src/commands/code/errors.js +15 -12
- package/dist/src/commands/code/setup.js +390 -425
- package/dist/src/commands/code.js +279 -294
- package/dist/src/commands/index.js +5 -5
- package/dist/src/commands/models.js +16 -25
- package/dist/src/commands/users.js +9 -18
- package/dist/src/constants/command-structure.js +138 -138
- package/dist/src/services/api-key-service.js +132 -152
- package/dist/src/services/auth-service.js +81 -95
- package/dist/src/services/browser-auth.js +121 -131
- package/dist/src/services/chat-service.js +369 -386
- package/dist/src/services/cluster-service.js +47 -62
- package/dist/src/services/collaborator-service.js +9 -21
- package/dist/src/services/flux-service.js +13 -25
- package/dist/src/services/helm-service.js +9 -21
- package/dist/src/services/kubectl-service.js +15 -29
- package/dist/src/utils/config-checker.js +8 -8
- package/dist/src/utils/config-loader.js +109 -109
- package/dist/src/utils/default-api-key.js +129 -139
- package/dist/src/utils/env-manager.js +55 -66
- package/dist/src/utils/error-handler.js +62 -62
- package/dist/src/utils/logger.js +74 -67
- package/dist/src/utils/markdown-renderer.js +28 -28
- package/dist/src/utils/opencode-validator.js +67 -69
- package/dist/src/utils/token-manager.js +67 -65
- package/dist/tests/commands/chat.test.js +30 -39
- package/dist/tests/commands/code.test.js +186 -195
- package/dist/tests/utils/config-loader.test.js +107 -107
- package/dist/tests/utils/env-manager.test.js +81 -90
- package/dist/tests/utils/opencode-validator.test.js +42 -41
- package/dist/vitest.config.js +1 -1
- package/eslint.config.mjs +65 -30
- package/index.ts +30 -31
- package/package.json +7 -3
- package/src/agents/app.ts +9 -9
- package/src/agents/backend.ts +4 -4
- package/src/agents/devops.ts +9 -9
- package/src/agents/frontend.ts +4 -4
- package/src/agents/fullstack.ts +4 -4
- package/src/agents/index.ts +27 -25
- package/src/agents/quality.ts +9 -9
- package/src/agents/security.ts +9 -9
- package/src/agents/types.ts +10 -10
- package/src/client.ts +85 -77
- package/src/commands/api-keys.ts +180 -185
- package/src/commands/auth.ts +15 -14
- package/src/commands/autocomplete.ts +10 -10
- package/src/commands/billing.ts +13 -12
- package/src/commands/chat.ts +145 -142
- package/src/commands/clusters.ts +20 -19
- package/src/commands/code/__tests__/auth-sync.test.ts +176 -175
- package/src/commands/code/__tests__/fake-api-key-service.ts +2 -2
- package/src/commands/code/__tests__/fake-auth-service.ts +18 -18
- package/src/commands/code/__tests__/fake-command-runner.ts +28 -22
- package/src/commands/code/__tests__/fake-file-store.ts +15 -15
- package/src/commands/code/__tests__/fake-prompter.ts +86 -85
- package/src/commands/code/__tests__/setup-flow.test.ts +253 -251
- package/src/commands/code/adapters/clack-prompter.ts +32 -30
- package/src/commands/code/adapters/fs-file-store.ts +18 -17
- package/src/commands/code/adapters/spawn-command-runner.ts +20 -15
- package/src/commands/code/auth-sync.ts +210 -210
- package/src/commands/code/errors.ts +11 -11
- package/src/commands/code/ports/auth-services.ts +7 -7
- package/src/commands/code/ports/command-runner.ts +2 -2
- package/src/commands/code/ports/file-store.ts +3 -3
- package/src/commands/code/ports/prompter.ts +13 -13
- package/src/commands/code/setup.ts +408 -406
- package/src/commands/code.ts +288 -287
- package/src/commands/index.ts +11 -10
- package/src/commands/models.ts +19 -18
- package/src/commands/users.ts +11 -10
- package/src/constants/command-structure.ts +159 -159
- package/src/services/api-key-service.ts +85 -85
- package/src/services/auth-service.ts +55 -54
- package/src/services/browser-auth.ts +62 -62
- package/src/services/chat-service.ts +170 -171
- package/src/services/cluster-service.ts +28 -28
- package/src/services/collaborator-service.ts +6 -6
- package/src/services/flux-service.ts +17 -17
- package/src/services/helm-service.ts +11 -11
- package/src/services/kubectl-service.ts +12 -12
- package/src/types/api.d.ts +1933 -1933
- package/src/types/json.d.ts +1 -1
- package/src/utils/config-checker.ts +7 -7
- package/src/utils/config-loader.ts +130 -129
- package/src/utils/default-api-key.ts +81 -80
- package/src/utils/env-manager.ts +37 -37
- package/src/utils/error-handler.ts +64 -64
- package/src/utils/logger.ts +72 -66
- package/src/utils/markdown-renderer.ts +28 -28
- package/src/utils/opencode-validator.ts +72 -71
- package/src/utils/token-manager.ts +69 -68
- package/tests/commands/chat.test.ts +32 -31
- package/tests/commands/code.test.ts +182 -181
- package/tests/utils/config-loader.test.ts +111 -110
- package/tests/utils/env-manager.test.ts +83 -79
- package/tests/utils/opencode-validator.test.ts +43 -42
- package/tsconfig.json +2 -1
- package/vitest.config.ts +2 -2
|
@@ -22,202 +22,57 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
27
|
};
|
|
37
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
29
|
exports.registerCodeCommands = void 0;
|
|
39
30
|
const chalk_1 = __importDefault(require("chalk"));
|
|
40
|
-
const
|
|
31
|
+
const node_child_process_1 = require("node:child_process");
|
|
32
|
+
const fs = __importStar(require("node:fs"));
|
|
33
|
+
const promises_1 = require("node:fs/promises");
|
|
34
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
35
|
+
const node_readline_1 = __importDefault(require("node:readline"));
|
|
41
36
|
const command_structure_1 = require("../constants/command-structure");
|
|
42
37
|
const error_handler_1 = require("../utils/error-handler");
|
|
43
38
|
const setup_1 = require("./code/setup");
|
|
44
|
-
const fs = __importStar(require("fs"));
|
|
45
|
-
const promises_1 = require("fs/promises");
|
|
46
|
-
const path_1 = __importDefault(require("path"));
|
|
47
|
-
const child_process_1 = require("child_process");
|
|
48
|
-
/**
|
|
49
|
-
* Check if current directory has git
|
|
50
|
-
*/
|
|
51
|
-
function hasGit() {
|
|
52
|
-
try {
|
|
53
|
-
return fs.existsSync(path_1.default.join(process.cwd(), ".git"));
|
|
54
|
-
}
|
|
55
|
-
catch (_a) {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Helper function to get user confirmation
|
|
61
|
-
*/
|
|
62
|
-
function confirm(question, autoYes = false) {
|
|
63
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
-
if (autoYes) {
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
return new Promise(resolve => {
|
|
68
|
-
const rl = readline_1.default.createInterface({
|
|
69
|
-
input: process.stdin,
|
|
70
|
-
output: process.stdout,
|
|
71
|
-
});
|
|
72
|
-
rl.question(question, answer => {
|
|
73
|
-
rl.close();
|
|
74
|
-
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes" || answer === "");
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Get project name from current directory or package.json
|
|
81
|
-
*/
|
|
82
|
-
function getProjectName() {
|
|
83
|
-
try {
|
|
84
|
-
const packageJsonPath = path_1.default.join(process.cwd(), "package.json");
|
|
85
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
86
|
-
const packageJsonContent = fs.readFileSync(packageJsonPath, "utf8");
|
|
87
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
88
|
-
return packageJson.name || path_1.default.basename(process.cwd());
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
catch (_a) {
|
|
92
|
-
// Ignore error and fallback to directory name
|
|
93
|
-
}
|
|
94
|
-
return path_1.default.basename(process.cwd());
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Get the path to the bundled agent templates directory
|
|
98
|
-
*/
|
|
99
|
-
function getAgentTemplatesDir() {
|
|
100
|
-
return path_1.default.resolve(__dirname, "../../templates/agents");
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Check if opencode is installed
|
|
104
|
-
*/
|
|
105
|
-
function checkOpencodeInstalled() {
|
|
106
|
-
return new Promise(resolve => {
|
|
107
|
-
const child = (0, child_process_1.spawn)("which", ["opencode"], {
|
|
108
|
-
stdio: "pipe",
|
|
109
|
-
});
|
|
110
|
-
child.on("close", code => {
|
|
111
|
-
resolve(code === 0);
|
|
112
|
-
});
|
|
113
|
-
child.on("error", () => {
|
|
114
|
-
resolve(false);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Install opencode via npm
|
|
120
|
-
*/
|
|
121
|
-
function installOpencode() {
|
|
122
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
123
|
-
console.log(chalk_1.default.cyan("Installing OpenCode via npm..."));
|
|
124
|
-
try {
|
|
125
|
-
yield new Promise((resolve, reject) => {
|
|
126
|
-
const install = (0, child_process_1.spawn)("npm", ["install", "-g", "opencode-ai@1.3"], {
|
|
127
|
-
stdio: "inherit",
|
|
128
|
-
});
|
|
129
|
-
install.on("close", code => {
|
|
130
|
-
if (code === 0) {
|
|
131
|
-
console.log(chalk_1.default.green("✓ OpenCode installed successfully!"));
|
|
132
|
-
resolve();
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
reject(new Error(`Installation failed with code ${code}`));
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
install.on("error", reject);
|
|
139
|
-
});
|
|
140
|
-
// Verify installation
|
|
141
|
-
const opencodeInstalled = yield checkOpencodeInstalled();
|
|
142
|
-
if (!opencodeInstalled) {
|
|
143
|
-
console.log(chalk_1.default.yellow("Installation completed but opencode command not found."));
|
|
144
|
-
console.log(chalk_1.default.yellow("You may need to restart your terminal or check your PATH."));
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
return true;
|
|
148
|
-
}
|
|
149
|
-
catch (error) {
|
|
150
|
-
console.error(chalk_1.default.red("Failed to install OpenCode:"));
|
|
151
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
152
|
-
console.log(chalk_1.default.blue("\nAlternative installation methods:"));
|
|
153
|
-
console.log(chalk_1.default.blue(" curl -fsSL https://opencode.ai/install | sh"));
|
|
154
|
-
console.log(chalk_1.default.blue(" Or visit: https://opencode.ai/docs"));
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Ensure opencode is installed, offering to install if not
|
|
161
|
-
*/
|
|
162
|
-
function ensureOpencodeInstalled(autoYes = false) {
|
|
163
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
164
|
-
let opencodeInstalled = yield checkOpencodeInstalled();
|
|
165
|
-
if (!opencodeInstalled) {
|
|
166
|
-
if (!autoYes) {
|
|
167
|
-
console.log(chalk_1.default.red("OpenCode is not installed."));
|
|
168
|
-
console.log(chalk_1.default.blue("OpenCode is required for the AI coding assistant."));
|
|
169
|
-
}
|
|
170
|
-
if (yield confirm("Would you like to install OpenCode automatically? (Y/n): ", autoYes)) {
|
|
171
|
-
opencodeInstalled = yield installOpencode();
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
if (!autoYes) {
|
|
175
|
-
console.log(chalk_1.default.blue("\nInstallation cancelled."));
|
|
176
|
-
console.log(chalk_1.default.blue("To install manually: curl -fsSL https://opencode.ai/install | bash"));
|
|
177
|
-
console.log(chalk_1.default.blue("Or visit: https://opencode.ai/docs"));
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return opencodeInstalled;
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
39
|
/**
|
|
185
40
|
* Register code commands
|
|
186
41
|
*/
|
|
187
42
|
function registerCodeCommands(program) {
|
|
188
43
|
const code = program
|
|
189
44
|
.command(command_structure_1.COMMAND_GROUPS.CODE)
|
|
190
|
-
.description(
|
|
45
|
+
.description('AI-powered coding assistant with OpenCode');
|
|
191
46
|
if (process.env.BERGET_EXPERIMENTAL) {
|
|
192
47
|
code
|
|
193
|
-
.command(
|
|
194
|
-
.description(
|
|
195
|
-
.action(() =>
|
|
48
|
+
.command('setup')
|
|
49
|
+
.description('Interactive setup for Berget AI coding tools')
|
|
50
|
+
.action(async () => {
|
|
196
51
|
try {
|
|
197
|
-
|
|
52
|
+
await (0, setup_1.runSetupCommand)();
|
|
198
53
|
}
|
|
199
54
|
catch (error) {
|
|
200
|
-
(0, error_handler_1.handleError)(
|
|
55
|
+
(0, error_handler_1.handleError)('Setup failed', error);
|
|
201
56
|
}
|
|
202
|
-
})
|
|
57
|
+
});
|
|
203
58
|
}
|
|
204
59
|
code
|
|
205
60
|
.command(command_structure_1.SUBCOMMANDS.CODE.INIT)
|
|
206
|
-
.description(
|
|
207
|
-
.option(
|
|
208
|
-
.option(
|
|
209
|
-
.option(
|
|
210
|
-
.action((options) =>
|
|
61
|
+
.description('Initialize project for AI coding assistant')
|
|
62
|
+
.option('-n, --name <name>', 'Project name (defaults to directory name)')
|
|
63
|
+
.option('-f, --force', 'Overwrite existing configuration')
|
|
64
|
+
.option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
|
|
65
|
+
.action(async (options) => {
|
|
211
66
|
try {
|
|
212
67
|
const projectName = options.name || getProjectName();
|
|
213
|
-
const configPath =
|
|
68
|
+
const configPath = node_path_1.default.join(process.cwd(), 'opencode.json');
|
|
214
69
|
// Check if already initialized
|
|
215
70
|
if (fs.existsSync(configPath) && !options.force) {
|
|
216
71
|
if (!options.yes) {
|
|
217
|
-
console.log(chalk_1.default.yellow(
|
|
72
|
+
console.log(chalk_1.default.yellow('Project already initialized for OpenCode.'));
|
|
218
73
|
console.log(chalk_1.default.dim(`Config file: ${configPath}`));
|
|
219
74
|
}
|
|
220
|
-
if (
|
|
75
|
+
if (await confirm('Do you want to reinitialize? (Y/n): ', options.yes)) {
|
|
221
76
|
// Continue with reinitialization
|
|
222
77
|
}
|
|
223
78
|
else {
|
|
@@ -225,109 +80,109 @@ function registerCodeCommands(program) {
|
|
|
225
80
|
}
|
|
226
81
|
}
|
|
227
82
|
// Ensure opencode is installed
|
|
228
|
-
if (!(
|
|
83
|
+
if (!(await ensureOpencodeInstalled(options.yes))) {
|
|
229
84
|
return;
|
|
230
85
|
}
|
|
231
86
|
console.log(chalk_1.default.cyan(`Initializing OpenCode for project: ${projectName}`));
|
|
232
87
|
const config = {
|
|
233
|
-
$schema:
|
|
234
|
-
plugin: [
|
|
88
|
+
$schema: 'https://opencode.ai/config.json',
|
|
89
|
+
plugin: ['@bergetai/opencode-auth@1.0.16'],
|
|
235
90
|
};
|
|
236
|
-
const agentsDir =
|
|
91
|
+
const agentsDir = node_path_1.default.join(process.cwd(), '.opencode', 'agents');
|
|
237
92
|
const templatesDir = getAgentTemplatesDir();
|
|
238
93
|
if (!options.yes) {
|
|
239
|
-
console.log(chalk_1.default.blue(
|
|
94
|
+
console.log(chalk_1.default.blue('\nAbout to create configuration files:'));
|
|
240
95
|
console.log(chalk_1.default.dim(`Config: ${configPath}`));
|
|
241
96
|
console.log(chalk_1.default.dim(`Agents: ${agentsDir}/`));
|
|
242
|
-
console.log(chalk_1.default.dim(
|
|
97
|
+
console.log(chalk_1.default.dim('This will configure OpenCode with the Berget auth plugin.'));
|
|
243
98
|
}
|
|
244
|
-
if (
|
|
99
|
+
if (await confirm('\nCreate configuration files? (Y/n): ', options.yes)) {
|
|
245
100
|
try {
|
|
246
|
-
|
|
247
|
-
console.log(chalk_1.default.green(
|
|
248
|
-
console.log(chalk_1.default.dim(
|
|
101
|
+
await (0, promises_1.writeFile)(configPath, JSON.stringify(config, null, 2));
|
|
102
|
+
console.log(chalk_1.default.green('✓ Created opencode.json'));
|
|
103
|
+
console.log(chalk_1.default.dim(' Plugin: @bergetai/opencode-auth'));
|
|
249
104
|
fs.mkdirSync(agentsDir, { recursive: true });
|
|
250
|
-
const templateFiles = fs.readdirSync(templatesDir).filter(f => f.endsWith(
|
|
105
|
+
const templateFiles = fs.readdirSync(templatesDir).filter((f) => f.endsWith('.md'));
|
|
251
106
|
for (const file of templateFiles) {
|
|
252
|
-
const
|
|
253
|
-
const
|
|
254
|
-
fs.copyFileSync(
|
|
107
|
+
const source = node_path_1.default.join(templatesDir, file);
|
|
108
|
+
const destination = node_path_1.default.join(agentsDir, file);
|
|
109
|
+
fs.copyFileSync(source, destination);
|
|
255
110
|
}
|
|
256
111
|
console.log(chalk_1.default.green(`✓ Created ${templateFiles.length} agent definitions in .opencode/agents/`));
|
|
257
112
|
}
|
|
258
113
|
catch (error) {
|
|
259
|
-
console.error(chalk_1.default.red(
|
|
260
|
-
(0, error_handler_1.handleError)(
|
|
114
|
+
console.error(chalk_1.default.red('Failed to create config files:'));
|
|
115
|
+
(0, error_handler_1.handleError)('Config file creation failed', error);
|
|
261
116
|
return;
|
|
262
117
|
}
|
|
263
118
|
}
|
|
264
119
|
else {
|
|
265
|
-
console.log(chalk_1.default.yellow(
|
|
120
|
+
console.log(chalk_1.default.yellow('Configuration file creation cancelled.'));
|
|
266
121
|
return;
|
|
267
122
|
}
|
|
268
|
-
console.log(chalk_1.default.green(
|
|
269
|
-
console.log(chalk_1.default.blue(
|
|
270
|
-
console.log(chalk_1.default.cyan(
|
|
271
|
-
console.log(chalk_1.default.cyan(
|
|
272
|
-
console.log(chalk_1.default.cyan(
|
|
123
|
+
console.log(chalk_1.default.green('\n✅ Project initialized successfully!'));
|
|
124
|
+
console.log(chalk_1.default.blue('\nNext steps:'));
|
|
125
|
+
console.log(chalk_1.default.cyan(' 1. Run: opencode'));
|
|
126
|
+
console.log(chalk_1.default.cyan(' 2. Type: /connect'));
|
|
127
|
+
console.log(chalk_1.default.cyan(' 3. Choose your auth method:'));
|
|
273
128
|
console.log(chalk_1.default.dim(' • "Login with Berget" — Berget Code team members (SSO)'));
|
|
274
129
|
console.log(chalk_1.default.dim(' • "Enter API Key" — API key users (console.berget.ai)'));
|
|
275
130
|
}
|
|
276
131
|
catch (error) {
|
|
277
|
-
(0, error_handler_1.handleError)(
|
|
132
|
+
(0, error_handler_1.handleError)('Failed to initialize project', error);
|
|
278
133
|
}
|
|
279
|
-
})
|
|
134
|
+
});
|
|
280
135
|
code
|
|
281
136
|
.command(command_structure_1.SUBCOMMANDS.CODE.RUN)
|
|
282
|
-
.description(
|
|
283
|
-
.argument(
|
|
284
|
-
.option(
|
|
285
|
-
.option(
|
|
286
|
-
.option(
|
|
287
|
-
.option(
|
|
288
|
-
.action((prompt, options) =>
|
|
137
|
+
.description('Run AI coding assistant')
|
|
138
|
+
.argument('[prompt]', 'Prompt to send directly to OpenCode')
|
|
139
|
+
.option('-m, --model <model>', 'Model to use (overrides config)')
|
|
140
|
+
.option('-a, --analysis', 'Use fast analysis model for context building')
|
|
141
|
+
.option('--no-config', 'Run without loading project config')
|
|
142
|
+
.option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
|
|
143
|
+
.action(async (prompt, options) => {
|
|
289
144
|
try {
|
|
290
|
-
const configPath =
|
|
145
|
+
const configPath = node_path_1.default.join(process.cwd(), 'opencode.json');
|
|
291
146
|
// Ensure opencode is installed
|
|
292
|
-
if (!(
|
|
147
|
+
if (!(await ensureOpencodeInstalled(options.yes))) {
|
|
293
148
|
return;
|
|
294
149
|
}
|
|
295
150
|
let config = null;
|
|
296
151
|
if (!options.noConfig && fs.existsSync(configPath)) {
|
|
297
152
|
try {
|
|
298
|
-
const configContent =
|
|
153
|
+
const configContent = await (0, promises_1.readFile)(configPath, 'utf8');
|
|
299
154
|
config = JSON.parse(configContent);
|
|
300
155
|
console.log(chalk_1.default.dim(`Loaded config for project: ${config.projectName}`));
|
|
301
156
|
console.log(chalk_1.default.dim(`Models: Analysis=${config.analysisModel}, Build=${config.buildModel}`));
|
|
302
157
|
}
|
|
303
|
-
catch
|
|
304
|
-
console.log(chalk_1.default.yellow(
|
|
158
|
+
catch {
|
|
159
|
+
console.log(chalk_1.default.yellow('Warning: Failed to load opencode.json'));
|
|
305
160
|
}
|
|
306
161
|
}
|
|
307
162
|
if (!config) {
|
|
308
|
-
console.log(chalk_1.default.yellow(
|
|
163
|
+
console.log(chalk_1.default.yellow('No project configuration found.'));
|
|
309
164
|
console.log(chalk_1.default.blue(`Run ${chalk_1.default.bold(`berget ${command_structure_1.COMMAND_GROUPS.CODE} ${command_structure_1.SUBCOMMANDS.CODE.INIT}`)} first.`));
|
|
310
165
|
return;
|
|
311
166
|
}
|
|
312
167
|
// Prepare opencode command
|
|
313
|
-
const
|
|
314
|
-
const
|
|
168
|
+
const environment = { ...process.env };
|
|
169
|
+
const opencodeArguments = [];
|
|
315
170
|
// Read --stage and --local from root program options
|
|
316
171
|
// (these flags are registered at program level, not subcommand level)
|
|
317
|
-
const isStage = process.argv.includes(
|
|
318
|
-
const isLocal = process.argv.includes(
|
|
172
|
+
const isStage = process.argv.includes('--stage');
|
|
173
|
+
const isLocal = process.argv.includes('--local');
|
|
319
174
|
if (isStage) {
|
|
320
|
-
console.log(chalk_1.default.cyan(
|
|
321
|
-
|
|
322
|
-
|
|
175
|
+
console.log(chalk_1.default.cyan('Using Berget stage environment'));
|
|
176
|
+
environment.BERGET_API_URL = 'https://api.stage.berget.ai';
|
|
177
|
+
environment.BERGET_INFERENCE_URL = 'https://api.stage.berget.ai/v1';
|
|
323
178
|
}
|
|
324
179
|
else if (isLocal) {
|
|
325
|
-
console.log(chalk_1.default.cyan(
|
|
326
|
-
|
|
327
|
-
|
|
180
|
+
console.log(chalk_1.default.cyan('Using local development environment'));
|
|
181
|
+
environment.BERGET_API_URL = 'http://localhost:3000';
|
|
182
|
+
environment.BERGET_INFERENCE_URL = 'http://localhost:3000/v1';
|
|
328
183
|
}
|
|
329
184
|
if (prompt) {
|
|
330
|
-
|
|
185
|
+
opencodeArguments.push('run', prompt);
|
|
331
186
|
}
|
|
332
187
|
// Choose model based on analysis flag or override
|
|
333
188
|
let selectedModel = options.model || config.buildModel;
|
|
@@ -335,116 +190,116 @@ function registerCodeCommands(program) {
|
|
|
335
190
|
selectedModel = config.analysisModel;
|
|
336
191
|
}
|
|
337
192
|
if (selectedModel) {
|
|
338
|
-
|
|
193
|
+
opencodeArguments.push('--model', selectedModel);
|
|
339
194
|
}
|
|
340
|
-
console.log(chalk_1.default.cyan(
|
|
195
|
+
console.log(chalk_1.default.cyan('Starting OpenCode...'));
|
|
341
196
|
// Spawn opencode process
|
|
342
|
-
const opencode = (0,
|
|
343
|
-
|
|
344
|
-
|
|
197
|
+
const opencode = (0, node_child_process_1.spawn)('opencode', opencodeArguments, {
|
|
198
|
+
env: environment,
|
|
199
|
+
stdio: 'inherit',
|
|
345
200
|
});
|
|
346
|
-
opencode.on(
|
|
201
|
+
opencode.on('close', (code) => {
|
|
347
202
|
if (code !== 0) {
|
|
348
203
|
console.log(chalk_1.default.red(`OpenCode exited with code ${code}`));
|
|
349
204
|
}
|
|
350
205
|
});
|
|
351
|
-
opencode.on(
|
|
352
|
-
console.error(chalk_1.default.red(
|
|
206
|
+
opencode.on('error', (error) => {
|
|
207
|
+
console.error(chalk_1.default.red('Failed to start OpenCode:'));
|
|
353
208
|
console.error(error.message);
|
|
354
209
|
});
|
|
355
210
|
}
|
|
356
211
|
catch (error) {
|
|
357
|
-
(0, error_handler_1.handleError)(
|
|
212
|
+
(0, error_handler_1.handleError)('Failed to run OpenCode', error);
|
|
358
213
|
}
|
|
359
|
-
})
|
|
214
|
+
});
|
|
360
215
|
code
|
|
361
216
|
.command(command_structure_1.SUBCOMMANDS.CODE.SERVE)
|
|
362
|
-
.description(
|
|
363
|
-
.option(
|
|
364
|
-
.option(
|
|
365
|
-
.option(
|
|
366
|
-
.action((options) =>
|
|
217
|
+
.description('Start OpenCode web server')
|
|
218
|
+
.option('-p, --port <port>', 'Port to run the server on (default: 3000)')
|
|
219
|
+
.option('-h, --host <host>', 'Host to bind the server to (default: localhost)')
|
|
220
|
+
.option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
|
|
221
|
+
.action(async (options) => {
|
|
367
222
|
try {
|
|
368
223
|
// Ensure opencode is installed
|
|
369
|
-
if (!(
|
|
224
|
+
if (!(await ensureOpencodeInstalled(options.yes))) {
|
|
370
225
|
return;
|
|
371
226
|
}
|
|
372
|
-
console.log(chalk_1.default.cyan(
|
|
227
|
+
console.log(chalk_1.default.cyan('🚀 Starting OpenCode web server...'));
|
|
373
228
|
// Prepare opencode serve command
|
|
374
|
-
const
|
|
229
|
+
const serveArguments = ['serve'];
|
|
375
230
|
if (options.port) {
|
|
376
|
-
|
|
231
|
+
serveArguments.push('--port', options.port);
|
|
377
232
|
}
|
|
378
233
|
if (options.host) {
|
|
379
|
-
|
|
234
|
+
serveArguments.push('--host', options.host);
|
|
380
235
|
}
|
|
381
236
|
// Spawn opencode serve process
|
|
382
|
-
const opencode = (0,
|
|
383
|
-
stdio:
|
|
237
|
+
const opencode = (0, node_child_process_1.spawn)('opencode', serveArguments, {
|
|
238
|
+
stdio: 'inherit',
|
|
384
239
|
});
|
|
385
|
-
opencode.on(
|
|
240
|
+
opencode.on('close', (code) => {
|
|
386
241
|
if (code !== 0) {
|
|
387
242
|
console.log(chalk_1.default.red(`OpenCode server exited with code ${code}`));
|
|
388
243
|
}
|
|
389
244
|
});
|
|
390
|
-
opencode.on(
|
|
391
|
-
console.error(chalk_1.default.red(
|
|
245
|
+
opencode.on('error', (error) => {
|
|
246
|
+
console.error(chalk_1.default.red('Failed to start OpenCode server:'));
|
|
392
247
|
console.error(error.message);
|
|
393
248
|
});
|
|
394
249
|
}
|
|
395
250
|
catch (error) {
|
|
396
|
-
(0, error_handler_1.handleError)(
|
|
251
|
+
(0, error_handler_1.handleError)('Failed to start OpenCode server', error);
|
|
397
252
|
}
|
|
398
|
-
})
|
|
253
|
+
});
|
|
399
254
|
code
|
|
400
255
|
.command(command_structure_1.SUBCOMMANDS.CODE.UPDATE)
|
|
401
|
-
.description(
|
|
402
|
-
.option(
|
|
403
|
-
.option(
|
|
404
|
-
.action((options) =>
|
|
256
|
+
.description('Update OpenCode and agents to latest versions')
|
|
257
|
+
.option('-f, --force', 'Force update even if already latest')
|
|
258
|
+
.option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
|
|
259
|
+
.action(async (options) => {
|
|
405
260
|
try {
|
|
406
|
-
console.log(chalk_1.default.cyan(
|
|
261
|
+
console.log(chalk_1.default.cyan('🔄 Updating OpenCode configuration...'));
|
|
407
262
|
// Ensure opencode is installed first
|
|
408
|
-
if (!(
|
|
263
|
+
if (!(await ensureOpencodeInstalled(options.yes))) {
|
|
409
264
|
return;
|
|
410
265
|
}
|
|
411
|
-
const configPath =
|
|
266
|
+
const configPath = node_path_1.default.join(process.cwd(), 'opencode.json');
|
|
412
267
|
// Check if project is initialized
|
|
413
268
|
if (!fs.existsSync(configPath)) {
|
|
414
|
-
console.log(chalk_1.default.red(
|
|
269
|
+
console.log(chalk_1.default.red('❌ No OpenCode configuration found.'));
|
|
415
270
|
console.log(chalk_1.default.blue(`Run ${chalk_1.default.bold(`berget ${command_structure_1.COMMAND_GROUPS.CODE} ${command_structure_1.SUBCOMMANDS.CODE.INIT}`)} first.`));
|
|
416
271
|
return;
|
|
417
272
|
}
|
|
418
273
|
// Read current configuration
|
|
419
274
|
let currentConfig;
|
|
420
275
|
try {
|
|
421
|
-
const configContent =
|
|
276
|
+
const configContent = await (0, promises_1.readFile)(configPath, 'utf8');
|
|
422
277
|
currentConfig = JSON.parse(configContent);
|
|
423
278
|
}
|
|
424
279
|
catch (error) {
|
|
425
|
-
console.error(chalk_1.default.red(
|
|
426
|
-
(0, error_handler_1.handleError)(
|
|
280
|
+
console.error(chalk_1.default.red('Failed to read current opencode.json:'));
|
|
281
|
+
(0, error_handler_1.handleError)('Config read failed', error);
|
|
427
282
|
return;
|
|
428
283
|
}
|
|
429
|
-
console.log(chalk_1.default.blue(
|
|
284
|
+
console.log(chalk_1.default.blue('📋 Current configuration:'));
|
|
430
285
|
if (currentConfig.model) {
|
|
431
286
|
console.log(chalk_1.default.dim(` Model: ${currentConfig.model}`));
|
|
432
287
|
}
|
|
433
|
-
const agentsDir =
|
|
288
|
+
const agentsDir = node_path_1.default.join(process.cwd(), '.opencode', 'agents');
|
|
434
289
|
const templatesDir = getAgentTemplatesDir();
|
|
435
|
-
const templateFiles = fs.readdirSync(templatesDir).filter(f => f.endsWith(
|
|
290
|
+
const templateFiles = fs.readdirSync(templatesDir).filter((f) => f.endsWith('.md'));
|
|
436
291
|
// Check if agent definitions need updating
|
|
437
292
|
let agentsNeedUpdate = false;
|
|
438
293
|
for (const file of templateFiles) {
|
|
439
|
-
const
|
|
440
|
-
const
|
|
441
|
-
if (!fs.existsSync(
|
|
294
|
+
const source = node_path_1.default.join(templatesDir, file);
|
|
295
|
+
const destination = node_path_1.default.join(agentsDir, file);
|
|
296
|
+
if (!fs.existsSync(destination)) {
|
|
442
297
|
agentsNeedUpdate = true;
|
|
443
298
|
break;
|
|
444
299
|
}
|
|
445
|
-
const
|
|
446
|
-
const
|
|
447
|
-
if (
|
|
300
|
+
const sourceContent = fs.readFileSync(source, 'utf8');
|
|
301
|
+
const destinationContent = fs.readFileSync(destination, 'utf8');
|
|
302
|
+
if (sourceContent !== destinationContent) {
|
|
448
303
|
agentsNeedUpdate = true;
|
|
449
304
|
break;
|
|
450
305
|
}
|
|
@@ -452,55 +307,55 @@ function registerCodeCommands(program) {
|
|
|
452
307
|
// Check if opencode.json still has inline agent config (needs migration)
|
|
453
308
|
const needsMigration = !!currentConfig.agent;
|
|
454
309
|
if (!agentsNeedUpdate && !needsMigration && !options.force) {
|
|
455
|
-
console.log(chalk_1.default.green(
|
|
310
|
+
console.log(chalk_1.default.green('✅ Already using the latest configuration!'));
|
|
456
311
|
return;
|
|
457
312
|
}
|
|
458
313
|
if (agentsNeedUpdate || needsMigration) {
|
|
459
|
-
console.log(chalk_1.default.blue(
|
|
314
|
+
console.log(chalk_1.default.blue('\n🔄 Updates available:'));
|
|
460
315
|
if (needsMigration) {
|
|
461
|
-
console.log(chalk_1.default.cyan(
|
|
316
|
+
console.log(chalk_1.default.cyan(' • Migrate agents from opencode.json to .opencode/agents/'));
|
|
462
317
|
}
|
|
463
318
|
if (agentsNeedUpdate) {
|
|
464
|
-
console.log(chalk_1.default.cyan(
|
|
319
|
+
console.log(chalk_1.default.cyan(' • Latest agent prompts and improvements'));
|
|
465
320
|
}
|
|
466
321
|
}
|
|
467
322
|
if (options.force) {
|
|
468
|
-
console.log(chalk_1.default.yellow(
|
|
323
|
+
console.log(chalk_1.default.yellow('🔧 Force update requested'));
|
|
469
324
|
}
|
|
470
325
|
if (!options.yes) {
|
|
471
|
-
console.log(chalk_1.default.blue(
|
|
326
|
+
console.log(chalk_1.default.blue('\nThis will update your agent definitions and OpenCode configuration.'));
|
|
472
327
|
const hasGitRepo = hasGit();
|
|
473
|
-
if (
|
|
474
|
-
console.log(chalk_1.default.
|
|
328
|
+
if (hasGitRepo) {
|
|
329
|
+
console.log(chalk_1.default.green('✓ Git repository detected - changes are tracked'));
|
|
475
330
|
}
|
|
476
331
|
else {
|
|
477
|
-
console.log(chalk_1.default.
|
|
332
|
+
console.log(chalk_1.default.yellow('⚠️ No .git repository detected - backup will be created'));
|
|
478
333
|
}
|
|
479
334
|
}
|
|
480
|
-
if (
|
|
335
|
+
if (await confirm('\nProceed with update? (Y/n): ', options.yes)) {
|
|
481
336
|
try {
|
|
482
337
|
let backupPath = null;
|
|
483
338
|
if (!hasGit()) {
|
|
484
339
|
backupPath = `${configPath}.backup.${Date.now()}`;
|
|
485
|
-
|
|
486
|
-
console.log(chalk_1.default.green(`✓ Backed up current config to ${
|
|
340
|
+
await (0, promises_1.writeFile)(backupPath, JSON.stringify(currentConfig, null, 2));
|
|
341
|
+
console.log(chalk_1.default.green(`✓ Backed up current config to ${node_path_1.default.basename(backupPath)}`));
|
|
487
342
|
}
|
|
488
343
|
// Remove inline agent section from opencode.json if present
|
|
489
344
|
if (currentConfig.agent) {
|
|
490
345
|
delete currentConfig.agent;
|
|
491
|
-
|
|
492
|
-
console.log(chalk_1.default.green(
|
|
346
|
+
await (0, promises_1.writeFile)(configPath, JSON.stringify(currentConfig, null, 2));
|
|
347
|
+
console.log(chalk_1.default.green('✓ Removed inline agent config from opencode.json'));
|
|
493
348
|
}
|
|
494
349
|
// Sync agent markdown files from templates
|
|
495
350
|
fs.mkdirSync(agentsDir, { recursive: true });
|
|
496
351
|
let updatedCount = 0;
|
|
497
352
|
for (const file of templateFiles) {
|
|
498
|
-
const
|
|
499
|
-
const
|
|
500
|
-
const agentName =
|
|
501
|
-
if (!fs.existsSync(
|
|
502
|
-
fs.readFileSync(
|
|
503
|
-
fs.copyFileSync(
|
|
353
|
+
const source = node_path_1.default.join(templatesDir, file);
|
|
354
|
+
const destination = node_path_1.default.join(agentsDir, file);
|
|
355
|
+
const agentName = node_path_1.default.basename(file, '.md');
|
|
356
|
+
if (!fs.existsSync(destination) ||
|
|
357
|
+
fs.readFileSync(source, 'utf8') !== fs.readFileSync(destination, 'utf8')) {
|
|
358
|
+
fs.copyFileSync(source, destination);
|
|
504
359
|
updatedCount++;
|
|
505
360
|
console.log(chalk_1.default.cyan(` • Updated agent: ${agentName}`));
|
|
506
361
|
}
|
|
@@ -509,7 +364,7 @@ function registerCodeCommands(program) {
|
|
|
509
364
|
console.log(chalk_1.default.green(`✓ Updated ${updatedCount} agent definition(s)`));
|
|
510
365
|
}
|
|
511
366
|
// Update AGENTS.md if it doesn't exist
|
|
512
|
-
const agentsMdPath =
|
|
367
|
+
const agentsMdPath = node_path_1.default.join(process.cwd(), 'AGENTS.md');
|
|
513
368
|
if (!fs.existsSync(agentsMdPath)) {
|
|
514
369
|
const agentsMdContent = `# Berget Code Agents
|
|
515
370
|
|
|
@@ -560,30 +415,160 @@ See https://opencode.ai/docs/agents/ for available options.
|
|
|
560
415
|
|
|
561
416
|
*Updated by berget code update*
|
|
562
417
|
`;
|
|
563
|
-
|
|
564
|
-
console.log(chalk_1.default.green(
|
|
418
|
+
await (0, promises_1.writeFile)(agentsMdPath, agentsMdContent);
|
|
419
|
+
console.log(chalk_1.default.green('✓ Created AGENTS.md documentation'));
|
|
565
420
|
}
|
|
566
|
-
console.log(chalk_1.default.green(
|
|
421
|
+
console.log(chalk_1.default.green('\n✅ Update completed successfully!'));
|
|
567
422
|
}
|
|
568
423
|
catch (error) {
|
|
569
|
-
console.error(chalk_1.default.red(
|
|
570
|
-
(0, error_handler_1.handleError)(
|
|
424
|
+
console.error(chalk_1.default.red('Failed to update configuration:'));
|
|
425
|
+
(0, error_handler_1.handleError)('Update failed', error);
|
|
571
426
|
try {
|
|
572
|
-
|
|
573
|
-
console.log(chalk_1.default.yellow(
|
|
427
|
+
await (0, promises_1.writeFile)(configPath, JSON.stringify(currentConfig, null, 2));
|
|
428
|
+
console.log(chalk_1.default.yellow('📁 Restored original configuration from backup'));
|
|
574
429
|
}
|
|
575
|
-
catch
|
|
576
|
-
console.error(chalk_1.default.red(
|
|
430
|
+
catch {
|
|
431
|
+
console.error(chalk_1.default.red('Failed to restore backup:'));
|
|
577
432
|
}
|
|
578
433
|
}
|
|
579
434
|
}
|
|
580
435
|
else {
|
|
581
|
-
console.log(chalk_1.default.yellow(
|
|
436
|
+
console.log(chalk_1.default.yellow('Update cancelled.'));
|
|
582
437
|
}
|
|
583
438
|
}
|
|
584
|
-
catch
|
|
585
|
-
console.error(chalk_1.default.red(
|
|
439
|
+
catch {
|
|
440
|
+
console.error(chalk_1.default.red('Failed to update OpenCode configuration'));
|
|
586
441
|
}
|
|
587
|
-
})
|
|
442
|
+
});
|
|
588
443
|
}
|
|
589
444
|
exports.registerCodeCommands = registerCodeCommands;
|
|
445
|
+
/**
|
|
446
|
+
* Check if opencode is installed
|
|
447
|
+
*/
|
|
448
|
+
function checkOpencodeInstalled() {
|
|
449
|
+
return new Promise((resolve) => {
|
|
450
|
+
const child = (0, node_child_process_1.spawn)('which', ['opencode'], {
|
|
451
|
+
stdio: 'pipe',
|
|
452
|
+
});
|
|
453
|
+
child.on('close', (code) => {
|
|
454
|
+
resolve(code === 0);
|
|
455
|
+
});
|
|
456
|
+
child.on('error', () => {
|
|
457
|
+
resolve(false);
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Helper function to get user confirmation
|
|
463
|
+
*/
|
|
464
|
+
async function confirm(question, autoYes = false) {
|
|
465
|
+
if (autoYes) {
|
|
466
|
+
return true;
|
|
467
|
+
}
|
|
468
|
+
return new Promise((resolve) => {
|
|
469
|
+
const rl = node_readline_1.default.createInterface({
|
|
470
|
+
input: process.stdin,
|
|
471
|
+
output: process.stdout,
|
|
472
|
+
});
|
|
473
|
+
rl.question(question, (answer) => {
|
|
474
|
+
rl.close();
|
|
475
|
+
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes' || answer === '');
|
|
476
|
+
});
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Ensure opencode is installed, offering to install if not
|
|
481
|
+
*/
|
|
482
|
+
async function ensureOpencodeInstalled(autoYes = false) {
|
|
483
|
+
let opencodeInstalled = await checkOpencodeInstalled();
|
|
484
|
+
if (!opencodeInstalled) {
|
|
485
|
+
if (!autoYes) {
|
|
486
|
+
console.log(chalk_1.default.red('OpenCode is not installed.'));
|
|
487
|
+
console.log(chalk_1.default.blue('OpenCode is required for the AI coding assistant.'));
|
|
488
|
+
}
|
|
489
|
+
if (await confirm('Would you like to install OpenCode automatically? (Y/n): ', autoYes)) {
|
|
490
|
+
opencodeInstalled = await installOpencode();
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
if (!autoYes) {
|
|
494
|
+
console.log(chalk_1.default.blue('\nInstallation cancelled.'));
|
|
495
|
+
console.log(chalk_1.default.blue('To install manually: curl -fsSL https://opencode.ai/install | bash'));
|
|
496
|
+
console.log(chalk_1.default.blue('Or visit: https://opencode.ai/docs'));
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
return opencodeInstalled;
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Get the path to the bundled agent templates directory
|
|
504
|
+
*/
|
|
505
|
+
function getAgentTemplatesDir() {
|
|
506
|
+
return node_path_1.default.resolve(__dirname, '../../templates/agents');
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Get project name from current directory or package.json
|
|
510
|
+
*/
|
|
511
|
+
function getProjectName() {
|
|
512
|
+
try {
|
|
513
|
+
const packageJsonPath = node_path_1.default.join(process.cwd(), 'package.json');
|
|
514
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
515
|
+
const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
|
|
516
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
517
|
+
return packageJson.name || node_path_1.default.basename(process.cwd());
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
catch {
|
|
521
|
+
// Ignore error and fallback to directory name
|
|
522
|
+
}
|
|
523
|
+
return node_path_1.default.basename(process.cwd());
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Check if current directory has git
|
|
527
|
+
*/
|
|
528
|
+
function hasGit() {
|
|
529
|
+
try {
|
|
530
|
+
return fs.existsSync(node_path_1.default.join(process.cwd(), '.git'));
|
|
531
|
+
}
|
|
532
|
+
catch {
|
|
533
|
+
return false;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Install opencode via npm
|
|
538
|
+
*/
|
|
539
|
+
async function installOpencode() {
|
|
540
|
+
console.log(chalk_1.default.cyan('Installing OpenCode via npm...'));
|
|
541
|
+
try {
|
|
542
|
+
await new Promise((resolve, reject) => {
|
|
543
|
+
const install = (0, node_child_process_1.spawn)('npm', ['install', '-g', 'opencode-ai@1.3'], {
|
|
544
|
+
stdio: 'inherit',
|
|
545
|
+
});
|
|
546
|
+
install.on('close', (code) => {
|
|
547
|
+
if (code === 0) {
|
|
548
|
+
console.log(chalk_1.default.green('✓ OpenCode installed successfully!'));
|
|
549
|
+
resolve();
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
reject(new Error(`Installation failed with code ${code}`));
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
install.on('error', reject);
|
|
556
|
+
});
|
|
557
|
+
// Verify installation
|
|
558
|
+
const opencodeInstalled = await checkOpencodeInstalled();
|
|
559
|
+
if (!opencodeInstalled) {
|
|
560
|
+
console.log(chalk_1.default.yellow('Installation completed but opencode command not found.'));
|
|
561
|
+
console.log(chalk_1.default.yellow('You may need to restart your terminal or check your PATH.'));
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
return true;
|
|
565
|
+
}
|
|
566
|
+
catch (error) {
|
|
567
|
+
console.error(chalk_1.default.red('Failed to install OpenCode:'));
|
|
568
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
569
|
+
console.log(chalk_1.default.blue('\nAlternative installation methods:'));
|
|
570
|
+
console.log(chalk_1.default.blue(' curl -fsSL https://opencode.ai/install | sh'));
|
|
571
|
+
console.log(chalk_1.default.blue(' Or visit: https://opencode.ai/docs'));
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
}
|