@fitlab-ai/agent-infra 0.5.9 → 0.6.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/README.md +200 -8
- package/README.zh-CN.md +176 -8
- package/bin/{cli.js → cli.ts} +23 -19
- package/dist/bin/cli.js +116 -0
- package/dist/lib/defaults.json +61 -0
- package/dist/lib/init.js +238 -0
- package/dist/lib/log.js +18 -0
- package/dist/lib/merge.js +747 -0
- package/dist/lib/paths.js +18 -0
- package/dist/lib/prompt.js +85 -0
- package/dist/lib/render.js +139 -0
- package/dist/lib/sandbox/commands/create.js +1173 -0
- package/dist/lib/sandbox/commands/enter.js +98 -0
- package/dist/lib/sandbox/commands/ls.js +93 -0
- package/dist/lib/sandbox/commands/rebuild.js +101 -0
- package/dist/lib/sandbox/commands/refresh.js +85 -0
- package/dist/lib/sandbox/commands/rm.js +226 -0
- package/dist/lib/sandbox/commands/vm.js +144 -0
- package/dist/lib/sandbox/config.js +85 -0
- package/dist/lib/sandbox/constants.js +104 -0
- package/dist/lib/sandbox/credentials.js +437 -0
- package/dist/lib/sandbox/dockerfile.js +76 -0
- package/dist/lib/sandbox/dotfiles.js +170 -0
- package/dist/lib/sandbox/engine.js +155 -0
- package/dist/lib/sandbox/engines/colima.js +64 -0
- package/dist/lib/sandbox/engines/docker-desktop.js +27 -0
- package/dist/lib/sandbox/engines/index.js +25 -0
- package/dist/lib/sandbox/engines/native.js +96 -0
- package/dist/lib/sandbox/engines/orbstack.js +63 -0
- package/dist/lib/sandbox/engines/selinux.js +48 -0
- package/dist/lib/sandbox/engines/wsl2-paths.js +47 -0
- package/dist/lib/sandbox/engines/wsl2.js +57 -0
- package/dist/lib/sandbox/index.js +70 -0
- package/dist/lib/sandbox/runtimes/ai-tools.dockerfile +39 -0
- package/dist/lib/sandbox/runtimes/base.dockerfile +178 -0
- package/dist/lib/sandbox/runtimes/java17.dockerfile +3 -0
- package/dist/lib/sandbox/runtimes/java21.dockerfile +3 -0
- package/dist/lib/sandbox/runtimes/node20.dockerfile +3 -0
- package/dist/lib/sandbox/runtimes/node22.dockerfile +3 -0
- package/dist/lib/sandbox/runtimes/python3.dockerfile +3 -0
- package/dist/lib/sandbox/shell.js +148 -0
- package/dist/lib/sandbox/task-resolver.js +35 -0
- package/dist/lib/sandbox/tools.js +115 -0
- package/dist/lib/update.js +186 -0
- package/dist/lib/version.js +5 -0
- package/dist/package.json +5 -0
- package/lib/{init.js → init.ts} +64 -20
- package/lib/{log.js → log.ts} +4 -4
- package/lib/{merge.js → merge.ts} +129 -63
- package/lib/paths.ts +18 -0
- package/lib/{prompt.js → prompt.ts} +12 -12
- package/lib/{render.js → render.ts} +30 -17
- package/lib/sandbox/commands/create.ts +1507 -0
- package/lib/sandbox/commands/enter.ts +115 -0
- package/lib/sandbox/commands/{ls.js → ls.ts} +41 -10
- package/lib/sandbox/commands/rebuild.ts +135 -0
- package/lib/sandbox/commands/refresh.ts +128 -0
- package/lib/sandbox/commands/{rm.js → rm.ts} +71 -21
- package/lib/sandbox/commands/{vm.js → vm.ts} +62 -15
- package/lib/sandbox/config.ts +133 -0
- package/lib/sandbox/{constants.js → constants.ts} +41 -17
- package/lib/sandbox/credentials.ts +634 -0
- package/lib/sandbox/{dockerfile.js → dockerfile.ts} +13 -6
- package/lib/sandbox/dotfiles.ts +236 -0
- package/lib/sandbox/engine.ts +231 -0
- package/lib/sandbox/engines/colima.ts +81 -0
- package/lib/sandbox/engines/docker-desktop.ts +36 -0
- package/lib/sandbox/engines/index.ts +74 -0
- package/lib/sandbox/engines/native.ts +131 -0
- package/lib/sandbox/engines/orbstack.ts +78 -0
- package/lib/sandbox/engines/selinux.ts +66 -0
- package/lib/sandbox/engines/wsl2-paths.ts +65 -0
- package/lib/sandbox/engines/wsl2.ts +74 -0
- package/lib/sandbox/{index.js → index.ts} +17 -8
- package/lib/sandbox/runtimes/ai-tools.dockerfile +14 -1
- package/lib/sandbox/runtimes/base.dockerfile +116 -1
- package/lib/sandbox/shell.ts +186 -0
- package/lib/sandbox/{task-resolver.js → task-resolver.ts} +6 -6
- package/lib/sandbox/{tools.js → tools.ts} +33 -29
- package/lib/{update.js → update.ts} +33 -10
- package/package.json +22 -12
- package/templates/.agents/rules/create-issue.github.en.md +2 -4
- package/templates/.agents/rules/create-issue.github.zh-CN.md +2 -4
- package/templates/.agents/rules/issue-pr-commands.github.en.md +29 -0
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +29 -0
- package/templates/.agents/scripts/{platform-adapters/find-existing-task.github.js → find-existing-task.js} +22 -79
- package/templates/.agents/scripts/platform-adapters/platform-sync.github.js +26 -41
- package/templates/.agents/skills/create-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-issue/SKILL.en.md +6 -8
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +6 -8
- package/lib/paths.js +0 -9
- package/lib/sandbox/commands/create.js +0 -1174
- package/lib/sandbox/commands/enter.js +0 -79
- package/lib/sandbox/commands/rebuild.js +0 -102
- package/lib/sandbox/config.js +0 -84
- package/lib/sandbox/engine.js +0 -256
- package/lib/sandbox/shell.js +0 -122
- package/templates/.agents/scripts/platform-adapters/find-existing-task.js +0 -5
- /package/lib/{version.js → version.ts} +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
function resolveTemplateDir() {
|
|
4
|
+
const candidates = [
|
|
5
|
+
// Source checkout: lib/paths.ts -> repo-root/templates.
|
|
6
|
+
new URL('../templates', import.meta.url),
|
|
7
|
+
// Installed package: dist/lib/paths.js -> package-root/templates.
|
|
8
|
+
new URL('../../templates', import.meta.url)
|
|
9
|
+
];
|
|
10
|
+
for (const candidate of candidates) {
|
|
11
|
+
const bundledDir = fileURLToPath(candidate);
|
|
12
|
+
if (fs.existsSync(bundledDir))
|
|
13
|
+
return bundledDir;
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
export { resolveTemplateDir };
|
|
18
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import readline from 'node:readline';
|
|
2
|
+
import { ask } from "./log.js";
|
|
3
|
+
let _rl = null;
|
|
4
|
+
let _lines = [];
|
|
5
|
+
let _lineResolve = null;
|
|
6
|
+
let _stdinDone = false;
|
|
7
|
+
function setupInterface() {
|
|
8
|
+
if (_rl || _stdinDone)
|
|
9
|
+
return;
|
|
10
|
+
_rl = readline.createInterface({
|
|
11
|
+
input: process.stdin,
|
|
12
|
+
terminal: false
|
|
13
|
+
});
|
|
14
|
+
_rl.on('line', (line) => {
|
|
15
|
+
if (_lineResolve) {
|
|
16
|
+
const resolve = _lineResolve;
|
|
17
|
+
_lineResolve = null;
|
|
18
|
+
resolve(line);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
_lines.push(line);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
_rl.on('close', () => {
|
|
25
|
+
_stdinDone = true;
|
|
26
|
+
_rl = null;
|
|
27
|
+
if (_lineResolve) {
|
|
28
|
+
const resolve = _lineResolve;
|
|
29
|
+
_lineResolve = null;
|
|
30
|
+
resolve(null);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function nextLine() {
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
if (_lines.length > 0) {
|
|
37
|
+
resolve(_lines.shift() ?? null);
|
|
38
|
+
}
|
|
39
|
+
else if (_stdinDone) {
|
|
40
|
+
resolve(null);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
_lineResolve = resolve;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async function prompt(question, defaultValue) {
|
|
48
|
+
const label = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
|
|
49
|
+
ask(label);
|
|
50
|
+
setupInterface();
|
|
51
|
+
const line = await nextLine();
|
|
52
|
+
if (line === null) {
|
|
53
|
+
return defaultValue || '';
|
|
54
|
+
}
|
|
55
|
+
return line.trim() || defaultValue || '';
|
|
56
|
+
}
|
|
57
|
+
async function select(question, choices, defaultValue) {
|
|
58
|
+
const defaultIndex = defaultValue === undefined ? -1 : choices.indexOf(defaultValue);
|
|
59
|
+
process.stdout.write(` ${question}:\n`);
|
|
60
|
+
choices.forEach((choice, index) => {
|
|
61
|
+
const suffix = index === defaultIndex ? ' (default)' : '';
|
|
62
|
+
process.stdout.write(` ${index + 1}) ${choice}${suffix}\n`);
|
|
63
|
+
});
|
|
64
|
+
ask(defaultIndex >= 0 ? `Select [${defaultIndex + 1}]: ` : 'Select: ');
|
|
65
|
+
setupInterface();
|
|
66
|
+
const line = await nextLine();
|
|
67
|
+
if (line === null || line.trim() === '') {
|
|
68
|
+
return defaultValue || choices[0] || '';
|
|
69
|
+
}
|
|
70
|
+
const trimmed = line.trim();
|
|
71
|
+
const selectedIndex = Number.parseInt(trimmed, 10);
|
|
72
|
+
if (String(selectedIndex) === trimmed && selectedIndex >= 1 && selectedIndex <= choices.length) {
|
|
73
|
+
return choices[selectedIndex - 1] ?? '';
|
|
74
|
+
}
|
|
75
|
+
return trimmed;
|
|
76
|
+
}
|
|
77
|
+
function closePrompt() {
|
|
78
|
+
if (_rl) {
|
|
79
|
+
_rl.close();
|
|
80
|
+
_rl = null;
|
|
81
|
+
_stdinDone = true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export { prompt, select, closePrompt };
|
|
85
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
// Add a new identifier here only after shipping matching .{platform}. template variants.
|
|
4
|
+
const KNOWN_PLATFORMS = new Set(['github']);
|
|
5
|
+
const KNOWN_LANGUAGES = new Set(['en', 'zh-CN']);
|
|
6
|
+
function renderFile(src, dst, replacements) {
|
|
7
|
+
if (!fs.existsSync(src)) {
|
|
8
|
+
throw new Error(`Template file not found: ${src}`);
|
|
9
|
+
}
|
|
10
|
+
let content = fs.readFileSync(src, 'utf8');
|
|
11
|
+
content = content
|
|
12
|
+
.replace(/\{\{project\}\}/g, replacements.project)
|
|
13
|
+
.replace(/\{\{org\}\}/g, replacements.org || '');
|
|
14
|
+
const dir = path.dirname(dst);
|
|
15
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
16
|
+
fs.writeFileSync(dst, content, 'utf8');
|
|
17
|
+
}
|
|
18
|
+
function copyFile(src, dst) {
|
|
19
|
+
if (!fs.existsSync(src)) {
|
|
20
|
+
throw new Error(`Template file not found: ${src}`);
|
|
21
|
+
}
|
|
22
|
+
const dir = path.dirname(dst);
|
|
23
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
24
|
+
fs.copyFileSync(src, dst);
|
|
25
|
+
try {
|
|
26
|
+
fs.chmodSync(dst, fs.statSync(src).mode);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Ignore permission sync failures on unsupported filesystems.
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function walkFiles(dir) {
|
|
33
|
+
const results = [];
|
|
34
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
35
|
+
const entryPath = path.join(dir, entry.name);
|
|
36
|
+
if (entry.isDirectory()) {
|
|
37
|
+
results.push(...walkFiles(entryPath));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
results.push(entryPath);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return results;
|
|
44
|
+
}
|
|
45
|
+
function containsPlaceholders(src) {
|
|
46
|
+
const content = fs.readFileSync(src, 'utf8');
|
|
47
|
+
return content.includes('{{project}}') || content.includes('{{org}}');
|
|
48
|
+
}
|
|
49
|
+
function variantExt(relativePath) {
|
|
50
|
+
return path.extname(relativePath);
|
|
51
|
+
}
|
|
52
|
+
function variantBase(relativePath) {
|
|
53
|
+
const ext = variantExt(relativePath);
|
|
54
|
+
return relativePath.slice(0, -ext.length);
|
|
55
|
+
}
|
|
56
|
+
function withVariant(relativePath, variant) {
|
|
57
|
+
const ext = variantExt(relativePath);
|
|
58
|
+
const base = variantBase(relativePath);
|
|
59
|
+
return `${base}.${variant}${ext}`;
|
|
60
|
+
}
|
|
61
|
+
function stripVariant(relativePath, variant) {
|
|
62
|
+
return relativePath.replace(new RegExp(`\\.${variant.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\.`), '.');
|
|
63
|
+
}
|
|
64
|
+
function isPlatformVariant(relativePath, platform) {
|
|
65
|
+
const platforms = new Set([...KNOWN_PLATFORMS, platform]);
|
|
66
|
+
for (const candidate of platforms) {
|
|
67
|
+
if (relativePath.includes(`.${candidate}.`)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
function isLangVariant(relativePath) {
|
|
74
|
+
for (const lang of KNOWN_LANGUAGES) {
|
|
75
|
+
if (relativePath.includes(`.${lang}.`)) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
function langSelect(relativePaths, language) {
|
|
82
|
+
const selected = new Map();
|
|
83
|
+
for (const relativePath of relativePaths) {
|
|
84
|
+
if (relativePath.includes(`.${language}.`)) {
|
|
85
|
+
selected.set(stripVariant(relativePath, language), relativePath);
|
|
86
|
+
}
|
|
87
|
+
else if (!isLangVariant(relativePath)) {
|
|
88
|
+
if (!selected.has(relativePath)) {
|
|
89
|
+
selected.set(relativePath, relativePath);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return selected;
|
|
94
|
+
}
|
|
95
|
+
function platformSelect(entries, platform) {
|
|
96
|
+
const selected = new Map();
|
|
97
|
+
for (const [relativePath, src] of entries) {
|
|
98
|
+
if (!relativePath.includes(`.${platform}.`)) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
selected.set(stripVariant(relativePath, platform), src);
|
|
102
|
+
}
|
|
103
|
+
for (const [relativePath, src] of entries) {
|
|
104
|
+
if (selected.has(relativePath)) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (isPlatformVariant(relativePath, platform)) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
selected.set(relativePath, src);
|
|
111
|
+
}
|
|
112
|
+
return selected;
|
|
113
|
+
}
|
|
114
|
+
function selectLocalizedFiles(srcDir, language, platform = 'github') {
|
|
115
|
+
const relativePaths = walkFiles(srcDir).map((src) => path.relative(srcDir, src));
|
|
116
|
+
return platformSelect(langSelect(relativePaths, language), platform);
|
|
117
|
+
}
|
|
118
|
+
function copySkillDir(srcDir, dstDir, replacements, language, platform = 'github') {
|
|
119
|
+
if (!fs.existsSync(srcDir)) {
|
|
120
|
+
throw new Error(`Template directory not found: ${srcDir}`);
|
|
121
|
+
}
|
|
122
|
+
for (const [relativePath, selectedRelativePath] of selectLocalizedFiles(srcDir, language, platform)) {
|
|
123
|
+
const src = path.join(srcDir, selectedRelativePath);
|
|
124
|
+
const dst = path.join(dstDir, relativePath);
|
|
125
|
+
if (containsPlaceholders(src)) {
|
|
126
|
+
renderFile(src, dst, replacements);
|
|
127
|
+
try {
|
|
128
|
+
fs.chmodSync(dst, fs.statSync(src).mode);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// Ignore permission sync failures on unsupported filesystems.
|
|
132
|
+
}
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
copyFile(src, dst);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
export { renderFile, copyFile, copySkillDir, KNOWN_PLATFORMS };
|
|
139
|
+
//# sourceMappingURL=render.js.map
|