nubos-pilot 0.1.0 → 0.2.0
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/bin/install.js +137 -16
- package/lib/install/runtimes-registry.cjs +197 -0
- package/lib/runtime/_contract.test.cjs +5 -1
- package/lib/runtime/antigravity.cjs +35 -0
- package/lib/runtime/augment.cjs +35 -0
- package/lib/runtime/cline.cjs +35 -0
- package/lib/runtime/codebuddy.cjs +35 -0
- package/lib/runtime/copilot.cjs +35 -0
- package/lib/runtime/cursor.cjs +35 -0
- package/lib/runtime/index.cjs +5 -1
- package/lib/runtime/index.test.cjs +10 -4
- package/lib/runtime/kilo.cjs +35 -0
- package/lib/runtime/qwen.cjs +35 -0
- package/lib/runtime/trae.cjs +35 -0
- package/lib/runtime/windsurf.cjs +35 -0
- package/package.json +1 -1
package/bin/install.js
CHANGED
|
@@ -14,9 +14,37 @@ const agentsMdMod = require('../lib/install/agents-md.cjs');
|
|
|
14
14
|
const codexTomlMod = require('../lib/install/codex-toml.cjs');
|
|
15
15
|
const runtimeDetectMod = require('../lib/install/runtime-detect.cjs');
|
|
16
16
|
const backupMod = require('../lib/install/backup.cjs');
|
|
17
|
+
const registryMod = require('../lib/install/runtimes-registry.cjs');
|
|
17
18
|
|
|
18
19
|
const cyan = '\x1b[36m', green = '\x1b[32m', yellow = '\x1b[33m',
|
|
19
|
-
red = '\x1b[31m',
|
|
20
|
+
red = '\x1b[31m', blue = '\x1b[38;5;33m',
|
|
21
|
+
dim = '\x1b[2m', bold = '\x1b[1m', reset = '\x1b[0m';
|
|
22
|
+
|
|
23
|
+
const LOGO = [
|
|
24
|
+
' ███╗ ██╗██╗ ██╗██████╗ ██████╗ ███████╗',
|
|
25
|
+
' ████╗ ██║██║ ██║██╔══██╗██╔═══██╗██╔════╝',
|
|
26
|
+
' ██╔██╗ ██║██║ ██║██████╔╝██║ ██║███████╗',
|
|
27
|
+
' ██║╚██╗██║██║ ██║██╔══██╗██║ ██║╚════██║',
|
|
28
|
+
' ██║ ╚████║╚██████╔╝██████╔╝╚██████╔╝███████║',
|
|
29
|
+
' ╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝',
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
function _printBanner() {
|
|
33
|
+
let pkgVersion = '0.0.0';
|
|
34
|
+
let pkgDesc = '';
|
|
35
|
+
try {
|
|
36
|
+
const pkg = require('../package.json');
|
|
37
|
+
pkgVersion = String(pkg.version || '0.0.0');
|
|
38
|
+
pkgDesc = String(pkg.description || '');
|
|
39
|
+
} catch {}
|
|
40
|
+
process.stderr.write('\n');
|
|
41
|
+
for (const line of LOGO) process.stderr.write(blue + line + reset + '\n');
|
|
42
|
+
process.stderr.write('\n');
|
|
43
|
+
process.stderr.write(' ' + bold + blue + 'Nubos Pilot' + reset
|
|
44
|
+
+ dim + ' v' + pkgVersion + reset + '\n');
|
|
45
|
+
if (pkgDesc) process.stderr.write(' ' + dim + pkgDesc + reset + '\n');
|
|
46
|
+
process.stderr.write('\n');
|
|
47
|
+
}
|
|
20
48
|
|
|
21
49
|
const PAYLOAD_SUBPATH = path.join('.claude', 'nubos-pilot');
|
|
22
50
|
const STATE_SUBPATH = '.nubos-pilot';
|
|
@@ -38,16 +66,26 @@ const MANAGED_BLOCK_INNER =
|
|
|
38
66
|
+ ' for planning and execution.\n\nRun `npx nubos-pilot doctor`'
|
|
39
67
|
+ ' to check install integrity.';
|
|
40
68
|
|
|
41
|
-
const VALID_AGENTS =
|
|
69
|
+
const VALID_AGENTS = registryMod.listRuntimeIds();
|
|
42
70
|
const VALID_SCOPES = ['local', 'global'];
|
|
43
71
|
|
|
72
|
+
function _parseAgentsFlag(value) {
|
|
73
|
+
return String(value || '')
|
|
74
|
+
.split(/[,\s]+/)
|
|
75
|
+
.map((s) => s.trim())
|
|
76
|
+
.filter(Boolean);
|
|
77
|
+
}
|
|
78
|
+
|
|
44
79
|
function parseInstallFlags(args) {
|
|
45
|
-
const flags = { agent: null, scope: null, mcp: false, yes: false };
|
|
80
|
+
const flags = { agent: null, agents: null, scope: null, mcp: false, yes: false };
|
|
46
81
|
const rest = [];
|
|
47
82
|
for (let i = 0; i < args.length; i++) {
|
|
48
83
|
const a = args[i];
|
|
49
84
|
if (a === '--agent' || a === '-a') { flags.agent = args[++i] || null; continue; }
|
|
50
85
|
if (a.startsWith('--agent=')) { flags.agent = a.slice('--agent='.length); continue; }
|
|
86
|
+
if (a === '--agents') { flags.agents = _parseAgentsFlag(args[++i]); continue; }
|
|
87
|
+
if (a.startsWith('--agents=')) { flags.agents = _parseAgentsFlag(a.slice('--agents='.length)); continue; }
|
|
88
|
+
if (a === '--all') { flags.agents = VALID_AGENTS.slice(); continue; }
|
|
51
89
|
if (a === '--scope' || a === '-s') { flags.scope = args[++i] || null; continue; }
|
|
52
90
|
if (a.startsWith('--scope=')) { flags.scope = a.slice('--scope='.length); continue; }
|
|
53
91
|
if (a === '--mcp') { flags.mcp = true; continue; }
|
|
@@ -59,6 +97,21 @@ function parseInstallFlags(args) {
|
|
|
59
97
|
'--agent must be one of: ' + VALID_AGENTS.join(', '),
|
|
60
98
|
{ flag: '--agent', got: flags.agent });
|
|
61
99
|
}
|
|
100
|
+
if (flags.agents !== null) {
|
|
101
|
+
for (const a of flags.agents) {
|
|
102
|
+
if (!VALID_AGENTS.includes(a)) {
|
|
103
|
+
throw new NubosPilotError('invalid-flag',
|
|
104
|
+
'--agents values must be one of: ' + VALID_AGENTS.join(', '),
|
|
105
|
+
{ flag: '--agents', got: a });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (flags.agents.length === 0) {
|
|
109
|
+
throw new NubosPilotError('invalid-flag',
|
|
110
|
+
'--agents requires at least one value',
|
|
111
|
+
{ flag: '--agents' });
|
|
112
|
+
}
|
|
113
|
+
if (!flags.agent) flags.agent = flags.agents[0];
|
|
114
|
+
}
|
|
62
115
|
if (flags.scope !== null && !VALID_SCOPES.includes(flags.scope)) {
|
|
63
116
|
throw new NubosPilotError('invalid-flag',
|
|
64
117
|
'--scope must be one of: ' + VALID_SCOPES.join(', '),
|
|
@@ -123,10 +176,34 @@ function _copyTree(src, dst) {
|
|
|
123
176
|
}
|
|
124
177
|
}
|
|
125
178
|
|
|
179
|
+
function _runtimeSelectLabels() {
|
|
180
|
+
return registryMod.RUNTIMES.map((r) => {
|
|
181
|
+
const home = registryMod.runtimeGlobalDir(r).replace(process.env.HOME || '', '~');
|
|
182
|
+
return r.label + ' (' + home + ')';
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
126
186
|
async function _runInitQuestions(detectedRuntime, askUser, flags) {
|
|
127
187
|
const f = flags || {};
|
|
128
|
-
|
|
129
|
-
|
|
188
|
+
let runtimes;
|
|
189
|
+
if (f.agents && f.agents.length) {
|
|
190
|
+
runtimes = f.agents.slice();
|
|
191
|
+
} else if (f.agent) {
|
|
192
|
+
runtimes = [f.agent];
|
|
193
|
+
} else {
|
|
194
|
+
const labels = _runtimeSelectLabels();
|
|
195
|
+
const picked = (await askUser({ type: 'multiselect',
|
|
196
|
+
question: yellow + 'Which runtime(s) would you like to install for?' + reset,
|
|
197
|
+
options: labels, default: [(detectedRuntime || 'claude')] })).value;
|
|
198
|
+
runtimes = Array.isArray(picked) && picked.length && typeof picked[0] === 'string'
|
|
199
|
+
&& picked[0].includes('(')
|
|
200
|
+
? picked.map((label) => {
|
|
201
|
+
const idx = labels.indexOf(label);
|
|
202
|
+
return VALID_AGENTS[idx];
|
|
203
|
+
})
|
|
204
|
+
: (Array.isArray(picked) ? picked : [picked]);
|
|
205
|
+
}
|
|
206
|
+
const runtime = runtimes[0];
|
|
130
207
|
const scope = f.scope || (await askUser({ type: 'select', question: 'Installation scope?',
|
|
131
208
|
options: VALID_SCOPES, default: 'local' })).value;
|
|
132
209
|
const model_profile = (await askUser({ type: 'select', question: 'Model-Profile?',
|
|
@@ -141,7 +218,7 @@ async function _runInitQuestions(detectedRuntime, askUser, flags) {
|
|
|
141
218
|
const plan_checker = (await askUser({ type: 'confirm', question: 'Enable plan_checker?', default: true })).value;
|
|
142
219
|
const verifier = (await askUser({ type: 'confirm', question: 'Enable verifier?', default: true })).value;
|
|
143
220
|
const response_language = (await askUser({ type: 'input', question: 'Response language (ISO-639 code)?', default: 'en' })).value;
|
|
144
|
-
return { runtime, scope, mcp: !!f.mcp, model_profile, commit_docs, branching_strategy, phase_branch_template,
|
|
221
|
+
return { runtime, runtimes, scope, mcp: !!f.mcp, model_profile, commit_docs, branching_strategy, phase_branch_template,
|
|
145
222
|
milestone_branch_template, parallelization, research, plan_checker, verifier, response_language };
|
|
146
223
|
}
|
|
147
224
|
|
|
@@ -157,7 +234,9 @@ function _repairCodexConfig() {
|
|
|
157
234
|
return true;
|
|
158
235
|
}
|
|
159
236
|
|
|
160
|
-
|
|
237
|
+
const LEGACY_AGENTS = new Set(['claude', 'codex', 'gemini', 'opencode']);
|
|
238
|
+
|
|
239
|
+
function _rewriteManagedMarkdown(projectRoot, runtimes) {
|
|
161
240
|
const claudePath = path.join(projectRoot, 'CLAUDE.md');
|
|
162
241
|
const agentsPath = path.join(projectRoot, 'AGENTS.md');
|
|
163
242
|
const geminiPath = path.join(projectRoot, 'GEMINI.md');
|
|
@@ -174,10 +253,12 @@ function _rewriteManagedMarkdown(projectRoot) {
|
|
|
174
253
|
} else if (claudeExists) {
|
|
175
254
|
agentsBase = agentsMdMod.generateAgentsMd(fs.readFileSync(claudePath, 'utf-8'), 'codex');
|
|
176
255
|
} else {
|
|
177
|
-
|
|
256
|
+
agentsBase = null;
|
|
257
|
+
}
|
|
258
|
+
if (agentsBase !== null) {
|
|
259
|
+
const agentsNext = managedBlockMod.rewriteBlock(agentsBase, MANAGED_BLOCK_INNER);
|
|
260
|
+
atomicWriteFileSync(agentsPath, agentsNext);
|
|
178
261
|
}
|
|
179
|
-
const agentsNext = managedBlockMod.rewriteBlock(agentsBase, MANAGED_BLOCK_INNER);
|
|
180
|
-
atomicWriteFileSync(agentsPath, agentsNext);
|
|
181
262
|
|
|
182
263
|
let geminiBase;
|
|
183
264
|
if (fs.existsSync(geminiPath)) {
|
|
@@ -185,10 +266,30 @@ function _rewriteManagedMarkdown(projectRoot) {
|
|
|
185
266
|
} else if (claudeExists) {
|
|
186
267
|
geminiBase = agentsMdMod.generateAgentsMd(fs.readFileSync(claudePath, 'utf-8'), 'gemini');
|
|
187
268
|
} else {
|
|
188
|
-
|
|
269
|
+
geminiBase = null;
|
|
270
|
+
}
|
|
271
|
+
if (geminiBase !== null) {
|
|
272
|
+
const geminiNext = managedBlockMod.rewriteBlock(geminiBase, MANAGED_BLOCK_INNER);
|
|
273
|
+
atomicWriteFileSync(geminiPath, geminiNext);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const extras = (runtimes || []).filter((id) => !LEGACY_AGENTS.has(id));
|
|
277
|
+
for (const id of extras) {
|
|
278
|
+
const meta = registryMod.getRuntimeMeta(id);
|
|
279
|
+
if (!meta) continue;
|
|
280
|
+
const targetPath = registryMod.runtimeAgentsPath(meta, 'local', projectRoot);
|
|
281
|
+
let base;
|
|
282
|
+
if (fs.existsSync(targetPath)) {
|
|
283
|
+
base = fs.readFileSync(targetPath, 'utf-8');
|
|
284
|
+
} else if (claudeExists) {
|
|
285
|
+
base = agentsMdMod.generateAgentsMd(fs.readFileSync(claudePath, 'utf-8'), 'codex');
|
|
286
|
+
} else {
|
|
287
|
+
base = '';
|
|
288
|
+
}
|
|
289
|
+
const next = managedBlockMod.rewriteBlock(base, MANAGED_BLOCK_INNER);
|
|
290
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
291
|
+
atomicWriteFileSync(targetPath, next);
|
|
189
292
|
}
|
|
190
|
-
const geminiNext = managedBlockMod.rewriteBlock(geminiBase, MANAGED_BLOCK_INNER);
|
|
191
|
-
atomicWriteFileSync(geminiPath, geminiNext);
|
|
192
293
|
}
|
|
193
294
|
|
|
194
295
|
async function runInstall(opts) {
|
|
@@ -208,6 +309,7 @@ async function runInstall(opts) {
|
|
|
208
309
|
|
|
209
310
|
async function _runInstallLocked(ctx) {
|
|
210
311
|
const { projectRoot, mode, dryRun, askUser, sourceDir, stateDir, flags } = ctx;
|
|
312
|
+
_printBanner();
|
|
211
313
|
console.error(cyan + '→ nubos-pilot install (mode=' + mode + ')' + reset);
|
|
212
314
|
|
|
213
315
|
const preliminaryScope = (flags && flags.scope) || _readExistingScope(projectRoot) || 'local';
|
|
@@ -335,7 +437,8 @@ async function _runInstallLocked(ctx) {
|
|
|
335
437
|
}
|
|
336
438
|
}
|
|
337
439
|
|
|
338
|
-
|
|
440
|
+
const selectedRuntimes = (initConfig && initConfig.runtimes) || (initConfig ? [initConfig.runtime] : []);
|
|
441
|
+
_rewriteManagedMarkdown(projectRoot, selectedRuntimes);
|
|
339
442
|
|
|
340
443
|
if (initConfig && initConfig.mcp && !dryRun) {
|
|
341
444
|
try {
|
|
@@ -413,8 +516,26 @@ function _runUninstallLocked(projectRoot) {
|
|
|
413
516
|
|
|
414
517
|
try { fs.rmdirSync(payloadDir); } catch { }
|
|
415
518
|
|
|
416
|
-
|
|
417
|
-
|
|
519
|
+
const cfgPath = path.join(_stateDirFor(projectRoot), 'config.json');
|
|
520
|
+
let installedRuntimes = [];
|
|
521
|
+
try {
|
|
522
|
+
const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf-8'));
|
|
523
|
+
installedRuntimes = cfg.runtimes || (cfg.runtime ? [cfg.runtime] : []);
|
|
524
|
+
} catch {}
|
|
525
|
+
|
|
526
|
+
const legacyFiles = ['CLAUDE.md', 'AGENTS.md', 'GEMINI.md'];
|
|
527
|
+
const extraFiles = [];
|
|
528
|
+
for (const id of installedRuntimes) {
|
|
529
|
+
if (LEGACY_AGENTS.has(id)) continue;
|
|
530
|
+
const meta = registryMod.getRuntimeMeta(id);
|
|
531
|
+
if (!meta) continue;
|
|
532
|
+
extraFiles.push(registryMod.runtimeAgentsPath(meta, 'local', projectRoot));
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const toStrip = legacyFiles
|
|
536
|
+
.map((n) => path.join(projectRoot, n))
|
|
537
|
+
.concat(extraFiles);
|
|
538
|
+
for (const p of toStrip) {
|
|
418
539
|
if (!fs.existsSync(p)) continue;
|
|
419
540
|
const stripped = managedBlockMod.stripBlock(fs.readFileSync(p, 'utf-8'));
|
|
420
541
|
if (!stripped || !stripped.trim()) {
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const os = require('node:os');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
|
|
6
|
+
const RUNTIMES = [
|
|
7
|
+
{
|
|
8
|
+
id: 'claude',
|
|
9
|
+
label: 'Claude Code',
|
|
10
|
+
localDir: '.claude',
|
|
11
|
+
globalDir: ['.claude'],
|
|
12
|
+
envConfigDir: 'CLAUDE_CONFIG_DIR',
|
|
13
|
+
agentsMd: 'CLAUDE.md',
|
|
14
|
+
agentsMdScope: 'project',
|
|
15
|
+
payloadSubdir: 'nubos-pilot',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'antigravity',
|
|
19
|
+
label: 'Antigravity',
|
|
20
|
+
localDir: '.agent',
|
|
21
|
+
globalDir: ['.gemini', 'antigravity'],
|
|
22
|
+
envConfigDir: 'ANTIGRAVITY_CONFIG_DIR',
|
|
23
|
+
agentsMd: 'AGENTS.md',
|
|
24
|
+
agentsMdScope: 'project',
|
|
25
|
+
payloadSubdir: 'nubos-pilot',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: 'augment',
|
|
29
|
+
label: 'Augment',
|
|
30
|
+
localDir: '.augment',
|
|
31
|
+
globalDir: ['.augment'],
|
|
32
|
+
envConfigDir: 'AUGMENT_CONFIG_DIR',
|
|
33
|
+
agentsMd: 'AGENTS.md',
|
|
34
|
+
agentsMdScope: 'project',
|
|
35
|
+
payloadSubdir: 'nubos-pilot',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: 'cline',
|
|
39
|
+
label: 'Cline',
|
|
40
|
+
localDir: '.',
|
|
41
|
+
globalDir: ['.cline'],
|
|
42
|
+
envConfigDir: 'CLINE_CONFIG_DIR',
|
|
43
|
+
agentsMd: '.clinerules',
|
|
44
|
+
agentsMdScope: 'project',
|
|
45
|
+
payloadSubdir: '.clinerules-nubos-pilot',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'codebuddy',
|
|
49
|
+
label: 'CodeBuddy',
|
|
50
|
+
localDir: '.codebuddy',
|
|
51
|
+
globalDir: ['.codebuddy'],
|
|
52
|
+
envConfigDir: 'CODEBUDDY_CONFIG_DIR',
|
|
53
|
+
agentsMd: 'AGENTS.md',
|
|
54
|
+
agentsMdScope: 'project',
|
|
55
|
+
payloadSubdir: 'nubos-pilot',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'codex',
|
|
59
|
+
label: 'Codex',
|
|
60
|
+
localDir: '.codex',
|
|
61
|
+
globalDir: ['.codex'],
|
|
62
|
+
envConfigDir: 'CODEX_HOME',
|
|
63
|
+
agentsMd: 'AGENTS.md',
|
|
64
|
+
agentsMdScope: 'project',
|
|
65
|
+
payloadSubdir: 'nubos-pilot',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: 'copilot',
|
|
69
|
+
label: 'Copilot',
|
|
70
|
+
localDir: '.github',
|
|
71
|
+
globalDir: ['.copilot'],
|
|
72
|
+
envConfigDir: 'COPILOT_CONFIG_DIR',
|
|
73
|
+
agentsMd: 'copilot-instructions.md',
|
|
74
|
+
agentsMdScope: 'dir',
|
|
75
|
+
payloadSubdir: 'nubos-pilot',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: 'cursor',
|
|
79
|
+
label: 'Cursor',
|
|
80
|
+
localDir: '.cursor',
|
|
81
|
+
globalDir: ['.cursor'],
|
|
82
|
+
envConfigDir: 'CURSOR_CONFIG_DIR',
|
|
83
|
+
agentsMd: 'rules/nubos-pilot.mdc',
|
|
84
|
+
agentsMdScope: 'dir',
|
|
85
|
+
payloadSubdir: 'nubos-pilot',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: 'gemini',
|
|
89
|
+
label: 'Gemini',
|
|
90
|
+
localDir: '.gemini',
|
|
91
|
+
globalDir: ['.gemini'],
|
|
92
|
+
envConfigDir: 'GEMINI_CONFIG_DIR',
|
|
93
|
+
agentsMd: 'GEMINI.md',
|
|
94
|
+
agentsMdScope: 'project',
|
|
95
|
+
payloadSubdir: 'nubos-pilot',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: 'kilo',
|
|
99
|
+
label: 'Kilo',
|
|
100
|
+
localDir: '.kilo',
|
|
101
|
+
globalDir: ['.config', 'kilo'],
|
|
102
|
+
envConfigDir: 'KILO_CONFIG_DIR',
|
|
103
|
+
agentsMd: 'AGENTS.md',
|
|
104
|
+
agentsMdScope: 'project',
|
|
105
|
+
payloadSubdir: 'nubos-pilot',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: 'opencode',
|
|
109
|
+
label: 'OpenCode',
|
|
110
|
+
localDir: '.opencode',
|
|
111
|
+
globalDir: ['.config', 'opencode'],
|
|
112
|
+
envConfigDir: 'OPENCODE_CONFIG_DIR',
|
|
113
|
+
agentsMd: 'AGENTS.md',
|
|
114
|
+
agentsMdScope: 'dir',
|
|
115
|
+
payloadSubdir: 'nubos-pilot',
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: 'qwen',
|
|
119
|
+
label: 'Qwen Code',
|
|
120
|
+
localDir: '.qwen',
|
|
121
|
+
globalDir: ['.qwen'],
|
|
122
|
+
envConfigDir: 'QWEN_CONFIG_DIR',
|
|
123
|
+
agentsMd: 'AGENTS.md',
|
|
124
|
+
agentsMdScope: 'project',
|
|
125
|
+
payloadSubdir: 'nubos-pilot',
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: 'trae',
|
|
129
|
+
label: 'Trae',
|
|
130
|
+
localDir: '.trae',
|
|
131
|
+
globalDir: ['.trae'],
|
|
132
|
+
envConfigDir: 'TRAE_CONFIG_DIR',
|
|
133
|
+
agentsMd: 'AGENTS.md',
|
|
134
|
+
agentsMdScope: 'project',
|
|
135
|
+
payloadSubdir: 'nubos-pilot',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: 'windsurf',
|
|
139
|
+
label: 'Windsurf',
|
|
140
|
+
localDir: '.windsurf',
|
|
141
|
+
globalDir: ['.codeium', 'windsurf'],
|
|
142
|
+
envConfigDir: 'WINDSURF_CONFIG_DIR',
|
|
143
|
+
agentsMd: '.windsurfrules',
|
|
144
|
+
agentsMdScope: 'project',
|
|
145
|
+
payloadSubdir: '.windsurf-nubos-pilot',
|
|
146
|
+
},
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
const RUNTIME_INDEX = new Map(RUNTIMES.map((r) => [r.id, r]));
|
|
150
|
+
|
|
151
|
+
function listRuntimeIds() {
|
|
152
|
+
return RUNTIMES.map((r) => r.id);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function getRuntimeMeta(id) {
|
|
156
|
+
return RUNTIME_INDEX.get(id) || null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function runtimeGlobalDir(meta) {
|
|
160
|
+
if (meta.envConfigDir && process.env[meta.envConfigDir]) {
|
|
161
|
+
const v = process.env[meta.envConfigDir];
|
|
162
|
+
return v.startsWith('~') ? path.join(os.homedir(), v.slice(1)) : v;
|
|
163
|
+
}
|
|
164
|
+
return path.join(os.homedir(), ...(meta.globalDir || [meta.localDir]));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function runtimeLocalDir(meta, projectRoot) {
|
|
168
|
+
return path.join(projectRoot, meta.localDir || '.');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function runtimeConfigDir(meta, scope, projectRoot) {
|
|
172
|
+
return scope === 'global'
|
|
173
|
+
? runtimeGlobalDir(meta)
|
|
174
|
+
: runtimeLocalDir(meta, projectRoot);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function runtimePayloadDir(meta, scope, projectRoot) {
|
|
178
|
+
return path.join(runtimeConfigDir(meta, scope, projectRoot), meta.payloadSubdir);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function runtimeAgentsPath(meta, scope, projectRoot) {
|
|
182
|
+
if (meta.agentsMdScope === 'dir') {
|
|
183
|
+
return path.join(runtimeConfigDir(meta, scope, projectRoot), meta.agentsMd);
|
|
184
|
+
}
|
|
185
|
+
return path.join(projectRoot, meta.agentsMd);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
module.exports = {
|
|
189
|
+
RUNTIMES,
|
|
190
|
+
listRuntimeIds,
|
|
191
|
+
getRuntimeMeta,
|
|
192
|
+
runtimeGlobalDir,
|
|
193
|
+
runtimeLocalDir,
|
|
194
|
+
runtimeConfigDir,
|
|
195
|
+
runtimePayloadDir,
|
|
196
|
+
runtimeAgentsPath,
|
|
197
|
+
};
|
|
@@ -6,7 +6,11 @@ const REQUIRED_KEYS = ['name', 'detectHints', 'capabilities', 'paths', 'askUser'
|
|
|
6
6
|
const CAP_KEYS = ['askUserQuestion', 'slashCommands', 'agentsMd', 'textMode', 'modelResolution'];
|
|
7
7
|
const VALID_TEXT_MODE = ['auto', 'force', 'off'];
|
|
8
8
|
const VALID_MODEL_RES = ['explicit', 'inherit', 'profile'];
|
|
9
|
-
const VALID_AGENTS_MD = [
|
|
9
|
+
const VALID_AGENTS_MD = [
|
|
10
|
+
null, 'AGENTS.md', 'GEMINI.md', 'CLAUDE.md',
|
|
11
|
+
'.clinerules', '.windsurfrules',
|
|
12
|
+
'rules/nubos-pilot.mdc', 'copilot-instructions.md',
|
|
13
|
+
];
|
|
10
14
|
|
|
11
15
|
for (const name of listRuntimes()) {
|
|
12
16
|
test('RT-contract(' + name + '): exports all required keys', () => {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const { askUserReadline } = require('./_readline.cjs');
|
|
2
|
+
|
|
3
|
+
async function askUser(spec) {
|
|
4
|
+
return askUserReadline({
|
|
5
|
+
type: spec && spec.type,
|
|
6
|
+
question: spec && spec.question,
|
|
7
|
+
options: spec && spec.options,
|
|
8
|
+
def: spec ? spec.default : undefined,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
name: 'antigravity',
|
|
14
|
+
detectHints: {
|
|
15
|
+
env: ['ANTIGRAVITY_CONFIG_DIR'],
|
|
16
|
+
pathBinary: 'antigravity',
|
|
17
|
+
diskMarkers: ['.agent/', '.gemini/antigravity/'],
|
|
18
|
+
},
|
|
19
|
+
capabilities: {
|
|
20
|
+
askUserQuestion: false,
|
|
21
|
+
slashCommands: false,
|
|
22
|
+
agentsMd: 'AGENTS.md',
|
|
23
|
+
textMode: 'auto',
|
|
24
|
+
modelResolution: 'inherit',
|
|
25
|
+
},
|
|
26
|
+
paths: {
|
|
27
|
+
payload: '.agent/nubos-pilot/',
|
|
28
|
+
config: null,
|
|
29
|
+
agentsMd: 'AGENTS.md',
|
|
30
|
+
},
|
|
31
|
+
runtimeNotice:
|
|
32
|
+
'> **Runtime-Hinweis:** Diese Datei wird von Antigravity konsumiert. '
|
|
33
|
+
+ 'Interaktive Prompts laufen über readline (stderr).',
|
|
34
|
+
askUser,
|
|
35
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const { askUserReadline } = require('./_readline.cjs');
|
|
2
|
+
|
|
3
|
+
async function askUser(spec) {
|
|
4
|
+
return askUserReadline({
|
|
5
|
+
type: spec && spec.type,
|
|
6
|
+
question: spec && spec.question,
|
|
7
|
+
options: spec && spec.options,
|
|
8
|
+
def: spec ? spec.default : undefined,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
name: 'augment',
|
|
14
|
+
detectHints: {
|
|
15
|
+
env: ['AUGMENT_CONFIG_DIR'],
|
|
16
|
+
pathBinary: 'augment',
|
|
17
|
+
diskMarkers: ['.augment/'],
|
|
18
|
+
},
|
|
19
|
+
capabilities: {
|
|
20
|
+
askUserQuestion: false,
|
|
21
|
+
slashCommands: false,
|
|
22
|
+
agentsMd: 'AGENTS.md',
|
|
23
|
+
textMode: 'auto',
|
|
24
|
+
modelResolution: 'inherit',
|
|
25
|
+
},
|
|
26
|
+
paths: {
|
|
27
|
+
payload: '.augment/nubos-pilot/',
|
|
28
|
+
config: null,
|
|
29
|
+
agentsMd: 'AGENTS.md',
|
|
30
|
+
},
|
|
31
|
+
runtimeNotice:
|
|
32
|
+
'> **Runtime-Hinweis:** Diese Datei wird von Augment konsumiert. '
|
|
33
|
+
+ 'Interaktive Prompts laufen über readline (stderr).',
|
|
34
|
+
askUser,
|
|
35
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const { askUserReadline } = require('./_readline.cjs');
|
|
2
|
+
|
|
3
|
+
async function askUser(spec) {
|
|
4
|
+
return askUserReadline({
|
|
5
|
+
type: spec && spec.type,
|
|
6
|
+
question: spec && spec.question,
|
|
7
|
+
options: spec && spec.options,
|
|
8
|
+
def: spec ? spec.default : undefined,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
name: 'cline',
|
|
14
|
+
detectHints: {
|
|
15
|
+
env: ['CLINE_CONFIG_DIR'],
|
|
16
|
+
pathBinary: 'cline',
|
|
17
|
+
diskMarkers: ['.clinerules'],
|
|
18
|
+
},
|
|
19
|
+
capabilities: {
|
|
20
|
+
askUserQuestion: false,
|
|
21
|
+
slashCommands: false,
|
|
22
|
+
agentsMd: '.clinerules',
|
|
23
|
+
textMode: 'auto',
|
|
24
|
+
modelResolution: 'inherit',
|
|
25
|
+
},
|
|
26
|
+
paths: {
|
|
27
|
+
payload: '.clinerules-nubos-pilot/',
|
|
28
|
+
config: null,
|
|
29
|
+
agentsMd: '.clinerules',
|
|
30
|
+
},
|
|
31
|
+
runtimeNotice:
|
|
32
|
+
'> **Runtime-Hinweis:** Diese Datei (.clinerules) wird von Cline konsumiert. '
|
|
33
|
+
+ 'Interaktive Prompts laufen über readline (stderr).',
|
|
34
|
+
askUser,
|
|
35
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const { askUserReadline } = require('./_readline.cjs');
|
|
2
|
+
|
|
3
|
+
async function askUser(spec) {
|
|
4
|
+
return askUserReadline({
|
|
5
|
+
type: spec && spec.type,
|
|
6
|
+
question: spec && spec.question,
|
|
7
|
+
options: spec && spec.options,
|
|
8
|
+
def: spec ? spec.default : undefined,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
name: 'codebuddy',
|
|
14
|
+
detectHints: {
|
|
15
|
+
env: ['CODEBUDDY_CONFIG_DIR'],
|
|
16
|
+
pathBinary: 'codebuddy',
|
|
17
|
+
diskMarkers: ['.codebuddy/'],
|
|
18
|
+
},
|
|
19
|
+
capabilities: {
|
|
20
|
+
askUserQuestion: false,
|
|
21
|
+
slashCommands: false,
|
|
22
|
+
agentsMd: 'AGENTS.md',
|
|
23
|
+
textMode: 'auto',
|
|
24
|
+
modelResolution: 'inherit',
|
|
25
|
+
},
|
|
26
|
+
paths: {
|
|
27
|
+
payload: '.codebuddy/nubos-pilot/',
|
|
28
|
+
config: null,
|
|
29
|
+
agentsMd: 'AGENTS.md',
|
|
30
|
+
},
|
|
31
|
+
runtimeNotice:
|
|
32
|
+
'> **Runtime-Hinweis:** Diese Datei wird von CodeBuddy konsumiert. '
|
|
33
|
+
+ 'Interaktive Prompts laufen über readline (stderr).',
|
|
34
|
+
askUser,
|
|
35
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const { askUserReadline } = require('./_readline.cjs');
|
|
2
|
+
|
|
3
|
+
async function askUser(spec) {
|
|
4
|
+
return askUserReadline({
|
|
5
|
+
type: spec && spec.type,
|
|
6
|
+
question: spec && spec.question,
|
|
7
|
+
options: spec && spec.options,
|
|
8
|
+
def: spec ? spec.default : undefined,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
name: 'copilot',
|
|
14
|
+
detectHints: {
|
|
15
|
+
env: ['COPILOT_CONFIG_DIR'],
|
|
16
|
+
pathBinary: 'copilot',
|
|
17
|
+
diskMarkers: ['.github/copilot-instructions.md', '.copilot/'],
|
|
18
|
+
},
|
|
19
|
+
capabilities: {
|
|
20
|
+
askUserQuestion: false,
|
|
21
|
+
slashCommands: false,
|
|
22
|
+
agentsMd: 'copilot-instructions.md',
|
|
23
|
+
textMode: 'auto',
|
|
24
|
+
modelResolution: 'inherit',
|
|
25
|
+
},
|
|
26
|
+
paths: {
|
|
27
|
+
payload: '.github/nubos-pilot/',
|
|
28
|
+
config: null,
|
|
29
|
+
agentsMd: '.github/copilot-instructions.md',
|
|
30
|
+
},
|
|
31
|
+
runtimeNotice:
|
|
32
|
+
'> **Runtime-Hinweis:** Diese Datei (.github/copilot-instructions.md) wird von GitHub Copilot konsumiert. '
|
|
33
|
+
+ 'Interaktive Prompts laufen über readline (stderr).',
|
|
34
|
+
askUser,
|
|
35
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const { askUserReadline } = require('./_readline.cjs');
|
|
2
|
+
|
|
3
|
+
async function askUser(spec) {
|
|
4
|
+
return askUserReadline({
|
|
5
|
+
type: spec && spec.type,
|
|
6
|
+
question: spec && spec.question,
|
|
7
|
+
options: spec && spec.options,
|
|
8
|
+
def: spec ? spec.default : undefined,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
name: 'cursor',
|
|
14
|
+
detectHints: {
|
|
15
|
+
env: ['CURSOR_CONFIG_DIR'],
|
|
16
|
+
pathBinary: 'cursor',
|
|
17
|
+
diskMarkers: ['.cursor/', '.cursorrules'],
|
|
18
|
+
},
|
|
19
|
+
capabilities: {
|
|
20
|
+
askUserQuestion: false,
|
|
21
|
+
slashCommands: false,
|
|
22
|
+
agentsMd: 'rules/nubos-pilot.mdc',
|
|
23
|
+
textMode: 'auto',
|
|
24
|
+
modelResolution: 'inherit',
|
|
25
|
+
},
|
|
26
|
+
paths: {
|
|
27
|
+
payload: '.cursor/nubos-pilot/',
|
|
28
|
+
config: null,
|
|
29
|
+
agentsMd: '.cursor/rules/nubos-pilot.mdc',
|
|
30
|
+
},
|
|
31
|
+
runtimeNotice:
|
|
32
|
+
'> **Runtime-Hinweis:** Diese Datei (.cursor/rules/nubos-pilot.mdc) wird von Cursor konsumiert. '
|
|
33
|
+
+ 'Interaktive Prompts laufen über readline (stderr).',
|
|
34
|
+
askUser,
|
|
35
|
+
};
|
package/lib/runtime/index.cjs
CHANGED
|
@@ -3,7 +3,11 @@ const path = require('node:path');
|
|
|
3
3
|
const { NubosPilotError } = require('../core.cjs');
|
|
4
4
|
const { getRuntime: _askuserGetRuntime } = require('../askuser.cjs');
|
|
5
5
|
|
|
6
|
-
const KNOWN_RUNTIMES = [
|
|
6
|
+
const KNOWN_RUNTIMES = [
|
|
7
|
+
'claude', 'antigravity', 'augment', 'cline', 'codebuddy',
|
|
8
|
+
'codex', 'copilot', 'cursor', 'gemini', 'kilo',
|
|
9
|
+
'opencode', 'qwen', 'trae', 'windsurf',
|
|
10
|
+
];
|
|
7
11
|
|
|
8
12
|
function listRuntimes() {
|
|
9
13
|
return KNOWN_RUNTIMES.slice();
|
|
@@ -47,15 +47,21 @@ function writeConfig(cwd, json) {
|
|
|
47
47
|
fs.writeFileSync(path.join(dir, 'config.json'), JSON.stringify(json), 'utf-8');
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
const EXPECTED_RUNTIMES = [
|
|
51
|
+
'claude', 'antigravity', 'augment', 'cline', 'codebuddy',
|
|
52
|
+
'codex', 'copilot', 'cursor', 'gemini', 'kilo',
|
|
53
|
+
'opencode', 'qwen', 'trae', 'windsurf',
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
test('RTI-1: listRuntimes returns 14 known runtimes in canonical order', () => {
|
|
57
|
+
assert.deepEqual(rt.listRuntimes(), EXPECTED_RUNTIMES);
|
|
52
58
|
});
|
|
53
59
|
|
|
54
60
|
test('RTI-2: listRuntimes returns defensive copy — mutation does not leak', () => {
|
|
55
61
|
const a = rt.listRuntimes();
|
|
56
62
|
a.push('pwned');
|
|
57
63
|
const b = rt.listRuntimes();
|
|
58
|
-
assert.deepEqual(b,
|
|
64
|
+
assert.deepEqual(b, EXPECTED_RUNTIMES);
|
|
59
65
|
});
|
|
60
66
|
|
|
61
67
|
test('RTI-3: getAdapter("nonexistent") throws NubosPilotError with code runtime-unknown', () => {
|
|
@@ -71,7 +77,7 @@ test('RTI-4: getAdapter unknown-runtime error details.known lists KNOWN_RUNTIMES
|
|
|
71
77
|
assert.fail('should throw');
|
|
72
78
|
} catch (err) {
|
|
73
79
|
assert.equal(err.code, 'runtime-unknown');
|
|
74
|
-
assert.deepEqual(err.details.known,
|
|
80
|
+
assert.deepEqual(err.details.known, EXPECTED_RUNTIMES);
|
|
75
81
|
assert.equal(err.details.name, 'mystery');
|
|
76
82
|
}
|
|
77
83
|
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const { askUserReadline } = require('./_readline.cjs');
|
|
2
|
+
|
|
3
|
+
async function askUser(spec) {
|
|
4
|
+
return askUserReadline({
|
|
5
|
+
type: spec && spec.type,
|
|
6
|
+
question: spec && spec.question,
|
|
7
|
+
options: spec && spec.options,
|
|
8
|
+
def: spec ? spec.default : undefined,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
name: 'kilo',
|
|
14
|
+
detectHints: {
|
|
15
|
+
env: ['KILO_CONFIG_DIR'],
|
|
16
|
+
pathBinary: 'kilo',
|
|
17
|
+
diskMarkers: ['.kilo/', '.config/kilo/'],
|
|
18
|
+
},
|
|
19
|
+
capabilities: {
|
|
20
|
+
askUserQuestion: false,
|
|
21
|
+
slashCommands: false,
|
|
22
|
+
agentsMd: 'AGENTS.md',
|
|
23
|
+
textMode: 'auto',
|
|
24
|
+
modelResolution: 'inherit',
|
|
25
|
+
},
|
|
26
|
+
paths: {
|
|
27
|
+
payload: '.kilo/nubos-pilot/',
|
|
28
|
+
config: null,
|
|
29
|
+
agentsMd: 'AGENTS.md',
|
|
30
|
+
},
|
|
31
|
+
runtimeNotice:
|
|
32
|
+
'> **Runtime-Hinweis:** Diese Datei wird von Kilo konsumiert. '
|
|
33
|
+
+ 'Interaktive Prompts laufen über readline (stderr).',
|
|
34
|
+
askUser,
|
|
35
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const { askUserReadline } = require('./_readline.cjs');
|
|
2
|
+
|
|
3
|
+
async function askUser(spec) {
|
|
4
|
+
return askUserReadline({
|
|
5
|
+
type: spec && spec.type,
|
|
6
|
+
question: spec && spec.question,
|
|
7
|
+
options: spec && spec.options,
|
|
8
|
+
def: spec ? spec.default : undefined,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
name: 'qwen',
|
|
14
|
+
detectHints: {
|
|
15
|
+
env: ['QWEN_CONFIG_DIR'],
|
|
16
|
+
pathBinary: 'qwen',
|
|
17
|
+
diskMarkers: ['.qwen/'],
|
|
18
|
+
},
|
|
19
|
+
capabilities: {
|
|
20
|
+
askUserQuestion: false,
|
|
21
|
+
slashCommands: false,
|
|
22
|
+
agentsMd: 'AGENTS.md',
|
|
23
|
+
textMode: 'auto',
|
|
24
|
+
modelResolution: 'inherit',
|
|
25
|
+
},
|
|
26
|
+
paths: {
|
|
27
|
+
payload: '.qwen/nubos-pilot/',
|
|
28
|
+
config: null,
|
|
29
|
+
agentsMd: 'AGENTS.md',
|
|
30
|
+
},
|
|
31
|
+
runtimeNotice:
|
|
32
|
+
'> **Runtime-Hinweis:** Diese Datei wird von Qwen Code konsumiert. '
|
|
33
|
+
+ 'Interaktive Prompts laufen über readline (stderr).',
|
|
34
|
+
askUser,
|
|
35
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const { askUserReadline } = require('./_readline.cjs');
|
|
2
|
+
|
|
3
|
+
async function askUser(spec) {
|
|
4
|
+
return askUserReadline({
|
|
5
|
+
type: spec && spec.type,
|
|
6
|
+
question: spec && spec.question,
|
|
7
|
+
options: spec && spec.options,
|
|
8
|
+
def: spec ? spec.default : undefined,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
name: 'trae',
|
|
14
|
+
detectHints: {
|
|
15
|
+
env: ['TRAE_CONFIG_DIR'],
|
|
16
|
+
pathBinary: 'trae',
|
|
17
|
+
diskMarkers: ['.trae/'],
|
|
18
|
+
},
|
|
19
|
+
capabilities: {
|
|
20
|
+
askUserQuestion: false,
|
|
21
|
+
slashCommands: false,
|
|
22
|
+
agentsMd: 'AGENTS.md',
|
|
23
|
+
textMode: 'auto',
|
|
24
|
+
modelResolution: 'inherit',
|
|
25
|
+
},
|
|
26
|
+
paths: {
|
|
27
|
+
payload: '.trae/nubos-pilot/',
|
|
28
|
+
config: null,
|
|
29
|
+
agentsMd: 'AGENTS.md',
|
|
30
|
+
},
|
|
31
|
+
runtimeNotice:
|
|
32
|
+
'> **Runtime-Hinweis:** Diese Datei wird von Trae konsumiert. '
|
|
33
|
+
+ 'Interaktive Prompts laufen über readline (stderr).',
|
|
34
|
+
askUser,
|
|
35
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const { askUserReadline } = require('./_readline.cjs');
|
|
2
|
+
|
|
3
|
+
async function askUser(spec) {
|
|
4
|
+
return askUserReadline({
|
|
5
|
+
type: spec && spec.type,
|
|
6
|
+
question: spec && spec.question,
|
|
7
|
+
options: spec && spec.options,
|
|
8
|
+
def: spec ? spec.default : undefined,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
name: 'windsurf',
|
|
14
|
+
detectHints: {
|
|
15
|
+
env: ['WINDSURF_CONFIG_DIR'],
|
|
16
|
+
pathBinary: 'windsurf',
|
|
17
|
+
diskMarkers: ['.windsurf/', '.windsurfrules', '.codeium/windsurf/'],
|
|
18
|
+
},
|
|
19
|
+
capabilities: {
|
|
20
|
+
askUserQuestion: false,
|
|
21
|
+
slashCommands: false,
|
|
22
|
+
agentsMd: '.windsurfrules',
|
|
23
|
+
textMode: 'auto',
|
|
24
|
+
modelResolution: 'inherit',
|
|
25
|
+
},
|
|
26
|
+
paths: {
|
|
27
|
+
payload: '.windsurf-nubos-pilot/',
|
|
28
|
+
config: null,
|
|
29
|
+
agentsMd: '.windsurfrules',
|
|
30
|
+
},
|
|
31
|
+
runtimeNotice:
|
|
32
|
+
'> **Runtime-Hinweis:** Diese Datei (.windsurfrules) wird von Windsurf konsumiert. '
|
|
33
|
+
+ 'Interaktive Prompts laufen über readline (stderr).',
|
|
34
|
+
askUser,
|
|
35
|
+
};
|