nubos-pilot 0.1.0 → 0.2.1
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 +138 -16
- package/lib/install/runtimes-registry.cjs +197 -0
- package/lib/runtime/_contract.test.cjs +5 -1
- package/lib/runtime/_readline.cjs +44 -9
- 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,35 @@ 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 detectedIdx = Math.max(0, VALID_AGENTS.indexOf(detectedRuntime || 'claude'));
|
|
196
|
+
const picked = (await askUser({ type: 'multiselect',
|
|
197
|
+
question: yellow + 'Which runtime(s) would you like to install for?' + reset,
|
|
198
|
+
options: labels, default: [labels[detectedIdx]] })).value;
|
|
199
|
+
runtimes = Array.isArray(picked) && picked.length && typeof picked[0] === 'string'
|
|
200
|
+
&& picked[0].includes('(')
|
|
201
|
+
? picked.map((label) => {
|
|
202
|
+
const idx = labels.indexOf(label);
|
|
203
|
+
return VALID_AGENTS[idx];
|
|
204
|
+
})
|
|
205
|
+
: (Array.isArray(picked) ? picked : [picked]);
|
|
206
|
+
}
|
|
207
|
+
const runtime = runtimes[0];
|
|
130
208
|
const scope = f.scope || (await askUser({ type: 'select', question: 'Installation scope?',
|
|
131
209
|
options: VALID_SCOPES, default: 'local' })).value;
|
|
132
210
|
const model_profile = (await askUser({ type: 'select', question: 'Model-Profile?',
|
|
@@ -141,7 +219,7 @@ async function _runInitQuestions(detectedRuntime, askUser, flags) {
|
|
|
141
219
|
const plan_checker = (await askUser({ type: 'confirm', question: 'Enable plan_checker?', default: true })).value;
|
|
142
220
|
const verifier = (await askUser({ type: 'confirm', question: 'Enable verifier?', default: true })).value;
|
|
143
221
|
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,
|
|
222
|
+
return { runtime, runtimes, scope, mcp: !!f.mcp, model_profile, commit_docs, branching_strategy, phase_branch_template,
|
|
145
223
|
milestone_branch_template, parallelization, research, plan_checker, verifier, response_language };
|
|
146
224
|
}
|
|
147
225
|
|
|
@@ -157,7 +235,9 @@ function _repairCodexConfig() {
|
|
|
157
235
|
return true;
|
|
158
236
|
}
|
|
159
237
|
|
|
160
|
-
|
|
238
|
+
const LEGACY_AGENTS = new Set(['claude', 'codex', 'gemini', 'opencode']);
|
|
239
|
+
|
|
240
|
+
function _rewriteManagedMarkdown(projectRoot, runtimes) {
|
|
161
241
|
const claudePath = path.join(projectRoot, 'CLAUDE.md');
|
|
162
242
|
const agentsPath = path.join(projectRoot, 'AGENTS.md');
|
|
163
243
|
const geminiPath = path.join(projectRoot, 'GEMINI.md');
|
|
@@ -174,10 +254,12 @@ function _rewriteManagedMarkdown(projectRoot) {
|
|
|
174
254
|
} else if (claudeExists) {
|
|
175
255
|
agentsBase = agentsMdMod.generateAgentsMd(fs.readFileSync(claudePath, 'utf-8'), 'codex');
|
|
176
256
|
} else {
|
|
177
|
-
|
|
257
|
+
agentsBase = null;
|
|
258
|
+
}
|
|
259
|
+
if (agentsBase !== null) {
|
|
260
|
+
const agentsNext = managedBlockMod.rewriteBlock(agentsBase, MANAGED_BLOCK_INNER);
|
|
261
|
+
atomicWriteFileSync(agentsPath, agentsNext);
|
|
178
262
|
}
|
|
179
|
-
const agentsNext = managedBlockMod.rewriteBlock(agentsBase, MANAGED_BLOCK_INNER);
|
|
180
|
-
atomicWriteFileSync(agentsPath, agentsNext);
|
|
181
263
|
|
|
182
264
|
let geminiBase;
|
|
183
265
|
if (fs.existsSync(geminiPath)) {
|
|
@@ -185,10 +267,30 @@ function _rewriteManagedMarkdown(projectRoot) {
|
|
|
185
267
|
} else if (claudeExists) {
|
|
186
268
|
geminiBase = agentsMdMod.generateAgentsMd(fs.readFileSync(claudePath, 'utf-8'), 'gemini');
|
|
187
269
|
} else {
|
|
188
|
-
|
|
270
|
+
geminiBase = null;
|
|
271
|
+
}
|
|
272
|
+
if (geminiBase !== null) {
|
|
273
|
+
const geminiNext = managedBlockMod.rewriteBlock(geminiBase, MANAGED_BLOCK_INNER);
|
|
274
|
+
atomicWriteFileSync(geminiPath, geminiNext);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const extras = (runtimes || []).filter((id) => !LEGACY_AGENTS.has(id));
|
|
278
|
+
for (const id of extras) {
|
|
279
|
+
const meta = registryMod.getRuntimeMeta(id);
|
|
280
|
+
if (!meta) continue;
|
|
281
|
+
const targetPath = registryMod.runtimeAgentsPath(meta, 'local', projectRoot);
|
|
282
|
+
let base;
|
|
283
|
+
if (fs.existsSync(targetPath)) {
|
|
284
|
+
base = fs.readFileSync(targetPath, 'utf-8');
|
|
285
|
+
} else if (claudeExists) {
|
|
286
|
+
base = agentsMdMod.generateAgentsMd(fs.readFileSync(claudePath, 'utf-8'), 'codex');
|
|
287
|
+
} else {
|
|
288
|
+
base = '';
|
|
289
|
+
}
|
|
290
|
+
const next = managedBlockMod.rewriteBlock(base, MANAGED_BLOCK_INNER);
|
|
291
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
292
|
+
atomicWriteFileSync(targetPath, next);
|
|
189
293
|
}
|
|
190
|
-
const geminiNext = managedBlockMod.rewriteBlock(geminiBase, MANAGED_BLOCK_INNER);
|
|
191
|
-
atomicWriteFileSync(geminiPath, geminiNext);
|
|
192
294
|
}
|
|
193
295
|
|
|
194
296
|
async function runInstall(opts) {
|
|
@@ -208,6 +310,7 @@ async function runInstall(opts) {
|
|
|
208
310
|
|
|
209
311
|
async function _runInstallLocked(ctx) {
|
|
210
312
|
const { projectRoot, mode, dryRun, askUser, sourceDir, stateDir, flags } = ctx;
|
|
313
|
+
_printBanner();
|
|
211
314
|
console.error(cyan + '→ nubos-pilot install (mode=' + mode + ')' + reset);
|
|
212
315
|
|
|
213
316
|
const preliminaryScope = (flags && flags.scope) || _readExistingScope(projectRoot) || 'local';
|
|
@@ -335,7 +438,8 @@ async function _runInstallLocked(ctx) {
|
|
|
335
438
|
}
|
|
336
439
|
}
|
|
337
440
|
|
|
338
|
-
|
|
441
|
+
const selectedRuntimes = (initConfig && initConfig.runtimes) || (initConfig ? [initConfig.runtime] : []);
|
|
442
|
+
_rewriteManagedMarkdown(projectRoot, selectedRuntimes);
|
|
339
443
|
|
|
340
444
|
if (initConfig && initConfig.mcp && !dryRun) {
|
|
341
445
|
try {
|
|
@@ -413,8 +517,26 @@ function _runUninstallLocked(projectRoot) {
|
|
|
413
517
|
|
|
414
518
|
try { fs.rmdirSync(payloadDir); } catch { }
|
|
415
519
|
|
|
416
|
-
|
|
417
|
-
|
|
520
|
+
const cfgPath = path.join(_stateDirFor(projectRoot), 'config.json');
|
|
521
|
+
let installedRuntimes = [];
|
|
522
|
+
try {
|
|
523
|
+
const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf-8'));
|
|
524
|
+
installedRuntimes = cfg.runtimes || (cfg.runtime ? [cfg.runtime] : []);
|
|
525
|
+
} catch {}
|
|
526
|
+
|
|
527
|
+
const legacyFiles = ['CLAUDE.md', 'AGENTS.md', 'GEMINI.md'];
|
|
528
|
+
const extraFiles = [];
|
|
529
|
+
for (const id of installedRuntimes) {
|
|
530
|
+
if (LEGACY_AGENTS.has(id)) continue;
|
|
531
|
+
const meta = registryMod.getRuntimeMeta(id);
|
|
532
|
+
if (!meta) continue;
|
|
533
|
+
extraFiles.push(registryMod.runtimeAgentsPath(meta, 'local', projectRoot));
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const toStrip = legacyFiles
|
|
537
|
+
.map((n) => path.join(projectRoot, n))
|
|
538
|
+
.concat(extraFiles);
|
|
539
|
+
for (const p of toStrip) {
|
|
418
540
|
if (!fs.existsSync(p)) continue;
|
|
419
541
|
const stripped = managedBlockMod.stripBlock(fs.readFileSync(p, 'utf-8'));
|
|
420
542
|
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', () => {
|
|
@@ -51,7 +51,7 @@ function _parseAnswer(type, rawLine, options, def) {
|
|
|
51
51
|
}
|
|
52
52
|
if (type === 'multiselect') {
|
|
53
53
|
if (line === '' && def != null) return def;
|
|
54
|
-
const parts = line.split(
|
|
54
|
+
const parts = line.split(/[\s,]+/).map((s) => s.trim()).filter(Boolean);
|
|
55
55
|
const picks = [];
|
|
56
56
|
for (const p of parts) {
|
|
57
57
|
const n = Number(p);
|
|
@@ -88,6 +88,36 @@ function _parseAnswer(type, rawLine, options, def) {
|
|
|
88
88
|
);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
const NUBOS_BLUE = '\x1b[38;5;33m';
|
|
92
|
+
const ANSI_RESET = '\x1b[0m';
|
|
93
|
+
|
|
94
|
+
function _defaultDisplay(type, options, def) {
|
|
95
|
+
if (def == null) {
|
|
96
|
+
if (type === 'confirm') return '[y/n]';
|
|
97
|
+
return '';
|
|
98
|
+
}
|
|
99
|
+
if (type === 'confirm') {
|
|
100
|
+
if (def === true) return '[Y/n]';
|
|
101
|
+
if (def === false) return '[y/N]';
|
|
102
|
+
return '[y/n]';
|
|
103
|
+
}
|
|
104
|
+
if (type === 'select') {
|
|
105
|
+
if (options) {
|
|
106
|
+
const idx = options.indexOf(def);
|
|
107
|
+
if (idx >= 0) return '[' + (idx + 1) + ']';
|
|
108
|
+
}
|
|
109
|
+
return '[' + String(def) + ']';
|
|
110
|
+
}
|
|
111
|
+
if (type === 'multiselect') {
|
|
112
|
+
if (Array.isArray(def) && options) {
|
|
113
|
+
const idxs = def.map((v) => options.indexOf(v));
|
|
114
|
+
if (idxs.every((i) => i >= 0)) return '[' + idxs.map((i) => i + 1).join(',') + ']';
|
|
115
|
+
}
|
|
116
|
+
return '[' + (Array.isArray(def) ? def.join(',') : String(def)) + ']';
|
|
117
|
+
}
|
|
118
|
+
return '[' + String(def) + ']';
|
|
119
|
+
}
|
|
120
|
+
|
|
91
121
|
async function askUserReadline({ type, question, options, def }) {
|
|
92
122
|
const hasTTY = !!process.stdin.isTTY;
|
|
93
123
|
if (!hasTTY && !_readlineImpl) {
|
|
@@ -98,20 +128,25 @@ async function askUserReadline({ type, question, options, def }) {
|
|
|
98
128
|
{ question },
|
|
99
129
|
);
|
|
100
130
|
}
|
|
101
|
-
process.stderr.write(
|
|
131
|
+
process.stderr.write('\n');
|
|
132
|
+
process.stderr.write(' ' + question + '\n');
|
|
133
|
+
process.stderr.write('\n');
|
|
102
134
|
if (type === 'select' || type === 'multiselect') {
|
|
103
135
|
if (options) {
|
|
104
136
|
for (let i = 0; i < options.length; i++) {
|
|
105
|
-
process.stderr.write(
|
|
137
|
+
process.stderr.write(
|
|
138
|
+
' ' + NUBOS_BLUE + (i + 1) + ')' + ANSI_RESET + ' ' + String(options[i]) + '\n',
|
|
139
|
+
);
|
|
106
140
|
}
|
|
107
141
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
process.stderr.write('> ');
|
|
142
|
+
process.stderr.write('\n');
|
|
143
|
+
if (type === 'multiselect') {
|
|
144
|
+
process.stderr.write(' Select multiple: 1,2,6 or 1 2 6\n');
|
|
145
|
+
process.stderr.write('\n');
|
|
146
|
+
}
|
|
114
147
|
}
|
|
148
|
+
const marker = _defaultDisplay(type, options, def);
|
|
149
|
+
process.stderr.write(' Choice' + (marker ? ' ' + marker : '') + ': ');
|
|
115
150
|
const line = await _readOneLine();
|
|
116
151
|
return { value: _parseAnswer(type, line, options, def), source: 'readline' };
|
|
117
152
|
}
|
|
@@ -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
|
+
};
|