@liriraid/agentflow-ai 1.0.10
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/LICENSE +21 -0
- package/README.md +79 -0
- package/bin/agentflow.mjs +332 -0
- package/orchestrator.js +1585 -0
- package/package.json +64 -0
- package/scripts/scaffold-agent-configs.mjs +100 -0
- package/scripts/scaffold-openspec-change.mjs +84 -0
- package/scripts/update-skill-registry.mjs +174 -0
- package/src/ink/app.mjs +240 -0
- package/src/ink/index.mjs +400 -0
- package/templates/en/.atl/skill-registry.md +27 -0
- package/templates/en/.claude/README.md +7 -0
- package/templates/en/.claude/skills/orchestrator-apply/SKILL.md +31 -0
- package/templates/en/.claude/skills/orchestrator-archive/SKILL.md +26 -0
- package/templates/en/.claude/skills/orchestrator-design/SKILL.md +27 -0
- package/templates/en/.claude/skills/orchestrator-explore/SKILL.md +29 -0
- package/templates/en/.claude/skills/orchestrator-init/SKILL.md +32 -0
- package/templates/en/.claude/skills/orchestrator-memory/SKILL.md +26 -0
- package/templates/en/.claude/skills/orchestrator-openspec/SKILL.md +35 -0
- package/templates/en/.claude/skills/orchestrator-propose/SKILL.md +26 -0
- package/templates/en/.claude/skills/orchestrator-queue-planning/SKILL.md +31 -0
- package/templates/en/.claude/skills/orchestrator-spec/SKILL.md +27 -0
- package/templates/en/.claude/skills/orchestrator-tasks/SKILL.md +27 -0
- package/templates/en/.claude/skills/orchestrator-verify/SKILL.md +27 -0
- package/templates/en/.codex/README.md +7 -0
- package/templates/en/.opencode/README.md +7 -0
- package/templates/en/AGENT-CONFIG.md +75 -0
- package/templates/en/CLAUDE.md +91 -0
- package/templates/en/ENGRAM.md +50 -0
- package/templates/en/ORCHESTRATOR.md +192 -0
- package/templates/en/PROJECT.md +70 -0
- package/templates/en/QUEUE.md +17 -0
- package/templates/en/README.md +188 -0
- package/templates/en/agents/ABACUS.md +36 -0
- package/templates/en/agents/BACKEND.md +37 -0
- package/templates/en/agents/CODEX.md +45 -0
- package/templates/en/agents/CURSOR.md +37 -0
- package/templates/en/agents/FRONTEND.md +36 -0
- package/templates/en/agents/GEMINI.md +37 -0
- package/templates/en/agents/OPENCODE.md +41 -0
- package/templates/en/docs/README.md +14 -0
- package/templates/en/docs/agents.md +33 -0
- package/templates/en/docs/architecture.md +43 -0
- package/templates/en/docs/components.md +14 -0
- package/templates/en/docs/engram.md +16 -0
- package/templates/en/docs/openspec.md +32 -0
- package/templates/en/docs/usage.md +66 -0
- package/templates/en/openspec/FLOW.md +24 -0
- package/templates/en/openspec/README.md +29 -0
- package/templates/en/openspec/changes/.gitkeep +1 -0
- package/templates/en/openspec/changes/archive/.gitkeep +1 -0
- package/templates/en/openspec/specs/.gitkeep +1 -0
- package/templates/en/openspec/templates/archive-report.md +21 -0
- package/templates/en/openspec/templates/change-metadata.yaml +9 -0
- package/templates/en/openspec/templates/design.md +26 -0
- package/templates/en/openspec/templates/proposal.md +27 -0
- package/templates/en/openspec/templates/spec.md +18 -0
- package/templates/en/openspec/templates/tasks.md +14 -0
- package/templates/en/openspec/templates/verify-report.md +21 -0
- package/templates/en/orchestrator.config.json +99 -0
- package/templates/es/.atl/skill-registry.md +133 -0
- package/templates/es/.claude/README.md +7 -0
- package/templates/es/.claude/skills/orchestrator-apply/SKILL.md +32 -0
- package/templates/es/.claude/skills/orchestrator-archive/SKILL.md +28 -0
- package/templates/es/.claude/skills/orchestrator-design/SKILL.md +32 -0
- package/templates/es/.claude/skills/orchestrator-explore/SKILL.md +31 -0
- package/templates/es/.claude/skills/orchestrator-init/SKILL.md +32 -0
- package/templates/es/.claude/skills/orchestrator-memory/SKILL.md +31 -0
- package/templates/es/.claude/skills/orchestrator-openspec/SKILL.md +55 -0
- package/templates/es/.claude/skills/orchestrator-propose/SKILL.md +33 -0
- package/templates/es/.claude/skills/orchestrator-queue-planning/SKILL.md +35 -0
- package/templates/es/.claude/skills/orchestrator-spec/SKILL.md +28 -0
- package/templates/es/.claude/skills/orchestrator-tasks/SKILL.md +32 -0
- package/templates/es/.claude/skills/orchestrator-verify/SKILL.md +31 -0
- package/templates/es/.codex/README.md +7 -0
- package/templates/es/.opencode/README.md +7 -0
- package/templates/es/AGENT-CONFIG.md +83 -0
- package/templates/es/CLAUDE.md +136 -0
- package/templates/es/ENGRAM.md +70 -0
- package/templates/es/ORCHESTRATOR.md +199 -0
- package/templates/es/PROJECT.md +237 -0
- package/templates/es/QUEUE.md +17 -0
- package/templates/es/README.md +568 -0
- package/templates/es/agents/ABACUS.md +25 -0
- package/templates/es/agents/BACKEND.md +28 -0
- package/templates/es/agents/CODEX.md +37 -0
- package/templates/es/agents/CURSOR.md +27 -0
- package/templates/es/agents/FRONTEND.md +29 -0
- package/templates/es/agents/GEMINI.md +26 -0
- package/templates/es/agents/OPENCODE.md +32 -0
- package/templates/es/docs/README.md +12 -0
- package/templates/es/docs/agents.md +57 -0
- package/templates/es/docs/architecture.md +41 -0
- package/templates/es/docs/components.md +33 -0
- package/templates/es/docs/engram.md +30 -0
- package/templates/es/docs/openspec.md +34 -0
- package/templates/es/docs/usage.md +54 -0
- package/templates/es/openspec/FLOW.md +139 -0
- package/templates/es/openspec/README.md +77 -0
- package/templates/es/openspec/changes/.gitkeep +1 -0
- package/templates/es/openspec/changes/archive/.gitkeep +1 -0
- package/templates/es/openspec/specs/.gitkeep +1 -0
- package/templates/es/openspec/templates/archive-report.md +23 -0
- package/templates/es/openspec/templates/change-metadata.yaml +9 -0
- package/templates/es/openspec/templates/design.md +33 -0
- package/templates/es/openspec/templates/proposal.md +36 -0
- package/templates/es/openspec/templates/spec.md +33 -0
- package/templates/es/openspec/templates/tasks.md +22 -0
- package/templates/es/openspec/templates/verify-report.md +24 -0
- package/templates/es/orchestrator.config.json +99 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LiriRaid
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# agentflow
|
|
2
|
+
|
|
3
|
+
Reusable multi-agent orchestration workspace for coding projects.
|
|
4
|
+
|
|
5
|
+
This package installs a CLI that creates a separate orchestrator workspace next to your real project. The generated workspace can be created in **English** or **Spanish**.
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
my-product-workspace/
|
|
9
|
+
my-product/ # real project, stays clean
|
|
10
|
+
orchestrator-my-product/ # generated orchestrator workspace
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm i -g @liriraid/agentflow
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Create a Workspace
|
|
20
|
+
|
|
21
|
+
Interactive language selection:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
agentflow init-workspace C:/code/my-project
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Direct language selection:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
agentflow init-workspace C:/code/my-project --lang en
|
|
31
|
+
agentflow init-workspace C:/code/mi-proyecto --lang es
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The selected language controls the generated workspace files:
|
|
35
|
+
|
|
36
|
+
- `ORCHESTRATOR.md`
|
|
37
|
+
- `CLAUDE.md`
|
|
38
|
+
- `QUEUE.md`
|
|
39
|
+
- `PROJECT.md`
|
|
40
|
+
- `README.md`
|
|
41
|
+
- `agents/`
|
|
42
|
+
- `docs/`
|
|
43
|
+
- `openspec/`
|
|
44
|
+
- `.claude/`
|
|
45
|
+
- `.codex/`
|
|
46
|
+
- `.opencode/`
|
|
47
|
+
- `.atl/`
|
|
48
|
+
- `orchestrator.config.json`
|
|
49
|
+
|
|
50
|
+
## Runtime
|
|
51
|
+
|
|
52
|
+
The package runtime remains language-aware through `workspaceLanguage` in the generated `orchestrator.config.json`.
|
|
53
|
+
|
|
54
|
+
Start the TUI from the generated orchestrator workspace:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cd C:/code/orchestrator-my-project
|
|
58
|
+
agentflow ink --paused
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Then open Claude Code in the same workspace and start with the prompt from that workspace's `ORCHESTRATOR.md`.
|
|
62
|
+
|
|
63
|
+
## What Gets Packaged
|
|
64
|
+
|
|
65
|
+
The npm package ships:
|
|
66
|
+
|
|
67
|
+
- `bin/`
|
|
68
|
+
- `src/`
|
|
69
|
+
- `scripts/`
|
|
70
|
+
- `templates/en/`
|
|
71
|
+
- `templates/es/`
|
|
72
|
+
- `orchestrator.js`
|
|
73
|
+
- `LICENSE`
|
|
74
|
+
|
|
75
|
+
The workspace docs and prompts live inside `templates/en` and `templates/es`; they are copied into the generated workspace based on the selected language.
|
|
76
|
+
|
|
77
|
+
## Acknowledgements
|
|
78
|
+
|
|
79
|
+
Inspired by [Orquestador-AI](https://github.com/ariellontero/Orquestador-AI) by Ariel Lontero (originally MIT). Built from scratch with a different architecture (Ink TUI, npm package, multi-language template system).
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import {fileURLToPath} from 'url';
|
|
6
|
+
import {spawn} from 'child_process';
|
|
7
|
+
import {createInterface} from 'readline/promises';
|
|
8
|
+
import {stdin as input, stdout as output} from 'process';
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const PACKAGE_ROOT = path.dirname(path.dirname(__filename));
|
|
12
|
+
const argv = process.argv.slice(2);
|
|
13
|
+
|
|
14
|
+
const TEMPLATE_PATHS = [
|
|
15
|
+
'README.md',
|
|
16
|
+
'ORCHESTRATOR.md',
|
|
17
|
+
'CLAUDE.md',
|
|
18
|
+
'ENGRAM.md',
|
|
19
|
+
'AGENT-CONFIG.md',
|
|
20
|
+
'PROJECT.md',
|
|
21
|
+
'.atl',
|
|
22
|
+
'docs',
|
|
23
|
+
'orchestrator.config.json',
|
|
24
|
+
'QUEUE.md',
|
|
25
|
+
'agents',
|
|
26
|
+
'openspec',
|
|
27
|
+
'.claude',
|
|
28
|
+
'.codex',
|
|
29
|
+
'.opencode'
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const RUNTIME_DIRS = ['logs', 'handoffs', 'progress', 'briefs'];
|
|
33
|
+
const SUPPORTED_LANGUAGES = new Set(['en', 'es']);
|
|
34
|
+
const DEFAULT_LANGUAGE = 'en';
|
|
35
|
+
const TEXT = {
|
|
36
|
+
es: {
|
|
37
|
+
unsupported: value => `Idioma no soportado: ${value}. Usa "en" o "es".`,
|
|
38
|
+
missingTemplate: language => `No existe el template de idioma: ${language}`,
|
|
39
|
+
installed: target => `Orquestador instalado en ${target}`,
|
|
40
|
+
language: language => `Idioma del workspace: ${language.toUpperCase()}`,
|
|
41
|
+
next: 'Siguiente paso recomendado:',
|
|
42
|
+
step1: '1. Edita orchestrator.config.json con rutas reales',
|
|
43
|
+
step2: '2. Revisa ORCHESTRATOR.md, CLAUDE.md y docs/',
|
|
44
|
+
step3: '3. Ejecuta: agentflow ink --paused',
|
|
45
|
+
invalidProject: projectPath => `Ruta de proyecto inválida: ${projectPath}`,
|
|
46
|
+
realProject: projectPath => `Proyecto real: ${projectPath}`,
|
|
47
|
+
workspace: workspaceDir => `Workspace del orquestador: ${workspaceDir}`,
|
|
48
|
+
sibling:
|
|
49
|
+
'Este workspace queda fuera del repo del proyecto, como sibling, para no ensuciarlo con archivos del orquestador.',
|
|
50
|
+
unknown: command => `Comando desconocido: ${command}`
|
|
51
|
+
},
|
|
52
|
+
en: {
|
|
53
|
+
unsupported: value => `Unsupported language: ${value}. Use "en" or "es".`,
|
|
54
|
+
missingTemplate: language => `Language template not found: ${language}`,
|
|
55
|
+
installed: target => `Orchestrator installed at ${target}`,
|
|
56
|
+
language: language => `Workspace language: ${language.toUpperCase()}`,
|
|
57
|
+
next: 'Recommended next steps:',
|
|
58
|
+
step1: '1. Edit orchestrator.config.json with real paths',
|
|
59
|
+
step2: '2. Review ORCHESTRATOR.md, CLAUDE.md, and docs/',
|
|
60
|
+
step3: '3. Run: agentflow ink --paused',
|
|
61
|
+
invalidProject: projectPath => `Invalid project path: ${projectPath}`,
|
|
62
|
+
realProject: projectPath => `Real project: ${projectPath}`,
|
|
63
|
+
workspace: workspaceDir => `Orchestrator workspace: ${workspaceDir}`,
|
|
64
|
+
sibling:
|
|
65
|
+
'This workspace stays next to the real project as a sibling, so orchestrator files do not pollute the product repo.',
|
|
66
|
+
unknown: command => `Unknown command: ${command}`
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
function printHelp() {
|
|
71
|
+
console.log(`
|
|
72
|
+
agentflow
|
|
73
|
+
|
|
74
|
+
Uso:
|
|
75
|
+
agentflow init [targetDir] [--project-name <name>] [--backend <path>] [--frontend <path>] [--lang <en|es>] [--force]
|
|
76
|
+
agentflow init-workspace <projectPath> [--workspace-name <name>] [--backend <path>] [--frontend <path>] [--lang <en|es>] [--force]
|
|
77
|
+
agentflow tui [--paused] [--yolo]
|
|
78
|
+
agentflow ink [--paused] [--yolo]
|
|
79
|
+
agentflow skills:registry
|
|
80
|
+
agentflow openspec:new <change-name>
|
|
81
|
+
agentflow agent-config:init
|
|
82
|
+
|
|
83
|
+
Ejemplos:
|
|
84
|
+
agentflow init . --project-name "Mi Proyecto" --lang es
|
|
85
|
+
agentflow init-workspace C:/code/mi-proyecto --lang en
|
|
86
|
+
agentflow tui --paused
|
|
87
|
+
agentflow ink
|
|
88
|
+
`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function parseFlags(args) {
|
|
92
|
+
const flags = {};
|
|
93
|
+
const rest = [];
|
|
94
|
+
|
|
95
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
96
|
+
const current = args[i];
|
|
97
|
+
if (!current.startsWith('--')) {
|
|
98
|
+
rest.push(current);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const key = current.slice(2);
|
|
103
|
+
const next = args[i + 1];
|
|
104
|
+
if (!next || next.startsWith('--')) {
|
|
105
|
+
flags[key] = true;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
flags[key] = next;
|
|
110
|
+
i += 1;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return {flags, rest};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function normalizeLanguage(value) {
|
|
117
|
+
if (!value || value === true) return null;
|
|
118
|
+
const normalized = String(value).trim().toLowerCase();
|
|
119
|
+
if (normalized === '1' || normalized === 'en' || normalized === 'english') return 'en';
|
|
120
|
+
if (normalized === '2' || normalized === 'es' || normalized === 'spanish' || normalized === 'espanol' || normalized === 'español') return 'es';
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function resolveLanguage(flagValue) {
|
|
125
|
+
const fromFlag = normalizeLanguage(flagValue);
|
|
126
|
+
if (fromFlag) return fromFlag;
|
|
127
|
+
|
|
128
|
+
if (flagValue && !fromFlag) {
|
|
129
|
+
console.warn(TEXT.es.unsupported(flagValue));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return DEFAULT_LANGUAGE;
|
|
133
|
+
|
|
134
|
+
const rl = createInterface({input, output});
|
|
135
|
+
try {
|
|
136
|
+
console.log('');
|
|
137
|
+
console.log('Selecciona el idioma del workspace / Select workspace language:');
|
|
138
|
+
console.log(' 1) EN - English (recommended for AI agents)');
|
|
139
|
+
console.log(' 2) ES - Español');
|
|
140
|
+
const answer = await rl.question(`Language [${DEFAULT_LANGUAGE}]: `);
|
|
141
|
+
return normalizeLanguage(answer) || DEFAULT_LANGUAGE;
|
|
142
|
+
} finally {
|
|
143
|
+
rl.close();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function ensureDir(dir) {
|
|
148
|
+
fs.mkdirSync(dir, {recursive: true});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function copyRecursive(source, target, force = false) {
|
|
152
|
+
const stats = fs.statSync(source);
|
|
153
|
+
|
|
154
|
+
if (stats.isDirectory()) {
|
|
155
|
+
if (path.basename(source) === 'node_modules') return;
|
|
156
|
+
ensureDir(target);
|
|
157
|
+
for (const entry of fs.readdirSync(source)) {
|
|
158
|
+
copyRecursive(path.join(source, entry), path.join(target, entry), force);
|
|
159
|
+
}
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (fs.existsSync(target) && !force) return;
|
|
164
|
+
ensureDir(path.dirname(target));
|
|
165
|
+
fs.copyFileSync(source, target);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function patchGitignore(targetDir) {
|
|
169
|
+
const gitignorePath = path.join(targetDir, '.gitignore');
|
|
170
|
+
const entries = ['.atl/', 'logs/', 'handoffs/', 'progress/', 'briefs/'];
|
|
171
|
+
|
|
172
|
+
let existing = '';
|
|
173
|
+
if (fs.existsSync(gitignorePath)) {
|
|
174
|
+
existing = fs.readFileSync(gitignorePath, 'utf8');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const toAdd = entries.filter(e => !existing.includes(e));
|
|
178
|
+
if (toAdd.length === 0) return;
|
|
179
|
+
|
|
180
|
+
const trailingNewline = existing.endsWith('\n') ? '' : '\n';
|
|
181
|
+
const block = `${trailingNewline}\n### agentflow\n${toAdd.join('\n')}\n`;
|
|
182
|
+
fs.writeFileSync(gitignorePath, existing + block, 'utf8');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function patchConfig(targetDir, options) {
|
|
186
|
+
const configPath = path.join(targetDir, 'orchestrator.config.json');
|
|
187
|
+
if (!fs.existsSync(configPath)) return;
|
|
188
|
+
|
|
189
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
190
|
+
const projectName = options.projectName || path.basename(path.resolve(targetDir)) || config.projectName;
|
|
191
|
+
config.projectName = projectName;
|
|
192
|
+
config.workspaceLanguage = options.language;
|
|
193
|
+
|
|
194
|
+
if (options.backend) {
|
|
195
|
+
config.repos.backend = options.backend;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (options.frontend) {
|
|
199
|
+
config.repos.frontend = options.frontend;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async function initProject(args) {
|
|
206
|
+
const {flags, rest} = parseFlags(args);
|
|
207
|
+
const targetDir = path.resolve(rest[0] || '.');
|
|
208
|
+
const force = Boolean(flags.force);
|
|
209
|
+
const language = await resolveLanguage(flags.lang);
|
|
210
|
+
const templateRoot = path.join(PACKAGE_ROOT, 'templates', language);
|
|
211
|
+
|
|
212
|
+
if (!fs.existsSync(templateRoot)) {
|
|
213
|
+
console.error(TEXT[language].missingTemplate(language));
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
ensureDir(targetDir);
|
|
218
|
+
|
|
219
|
+
for (const relativePath of TEMPLATE_PATHS) {
|
|
220
|
+
const source = path.join(templateRoot, relativePath);
|
|
221
|
+
if (!fs.existsSync(source)) continue;
|
|
222
|
+
const target = path.join(targetDir, relativePath);
|
|
223
|
+
copyRecursive(source, target, force);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
for (const dir of RUNTIME_DIRS) {
|
|
227
|
+
ensureDir(path.join(targetDir, dir));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
patchConfig(targetDir, {
|
|
231
|
+
projectName: flags['project-name'],
|
|
232
|
+
backend: flags.backend,
|
|
233
|
+
frontend: flags.frontend,
|
|
234
|
+
language
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
patchGitignore(targetDir);
|
|
238
|
+
|
|
239
|
+
const text = TEXT[language];
|
|
240
|
+
console.log(text.installed(targetDir));
|
|
241
|
+
console.log(text.language(language));
|
|
242
|
+
console.log(text.next);
|
|
243
|
+
console.log(text.step1);
|
|
244
|
+
console.log(text.step2);
|
|
245
|
+
console.log(text.step3);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async function initWorkspace(args) {
|
|
249
|
+
const {flags, rest} = parseFlags(args);
|
|
250
|
+
const projectPath = path.resolve(rest[0] || '.');
|
|
251
|
+
const language = await resolveLanguage(flags.lang);
|
|
252
|
+
|
|
253
|
+
if (!fs.existsSync(projectPath) || !fs.statSync(projectPath).isDirectory()) {
|
|
254
|
+
console.error(TEXT[language].invalidProject(projectPath));
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const projectName = flags['project-name'] || path.basename(projectPath);
|
|
259
|
+
const workspaceName = flags['workspace-name'] || `orchestrator-${projectName.toLowerCase().replace(/\s+/g, '-')}`;
|
|
260
|
+
const workspaceDir = path.join(path.dirname(projectPath), workspaceName);
|
|
261
|
+
|
|
262
|
+
await initProject([
|
|
263
|
+
workspaceDir,
|
|
264
|
+
'--project-name',
|
|
265
|
+
projectName,
|
|
266
|
+
'--lang',
|
|
267
|
+
language,
|
|
268
|
+
'--backend',
|
|
269
|
+
flags.backend || projectPath,
|
|
270
|
+
'--frontend',
|
|
271
|
+
flags.frontend || projectPath,
|
|
272
|
+
...(flags.force ? ['--force'] : [])
|
|
273
|
+
]);
|
|
274
|
+
|
|
275
|
+
console.log('');
|
|
276
|
+
console.log(TEXT[language].realProject(projectPath));
|
|
277
|
+
console.log(TEXT[language].workspace(workspaceDir));
|
|
278
|
+
console.log(TEXT[language].sibling);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function runNodeScript(relativeScript, args = []) {
|
|
282
|
+
const scriptPath = path.join(PACKAGE_ROOT, relativeScript);
|
|
283
|
+
const child = spawn(process.execPath, [scriptPath, ...args], {
|
|
284
|
+
cwd: process.cwd(),
|
|
285
|
+
env: {
|
|
286
|
+
...process.env,
|
|
287
|
+
ORCHESTRATOR_WORKSPACE: process.cwd(),
|
|
288
|
+
NODE_PATH: [path.join(PACKAGE_ROOT, 'node_modules'), process.env.NODE_PATH]
|
|
289
|
+
.filter(Boolean)
|
|
290
|
+
.join(path.delimiter)
|
|
291
|
+
},
|
|
292
|
+
stdio: 'inherit'
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
child.on('exit', code => process.exit(code ?? 0));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const command = argv[0];
|
|
299
|
+
|
|
300
|
+
switch (command) {
|
|
301
|
+
case undefined:
|
|
302
|
+
case 'help':
|
|
303
|
+
case '--help':
|
|
304
|
+
case '-h':
|
|
305
|
+
printHelp();
|
|
306
|
+
break;
|
|
307
|
+
case 'init':
|
|
308
|
+
await initProject(argv.slice(1));
|
|
309
|
+
break;
|
|
310
|
+
case 'init-workspace':
|
|
311
|
+
await initWorkspace(argv.slice(1));
|
|
312
|
+
break;
|
|
313
|
+
case 'tui':
|
|
314
|
+
runNodeScript('orchestrator.js', argv.slice(1));
|
|
315
|
+
break;
|
|
316
|
+
case 'ink':
|
|
317
|
+
runNodeScript(path.join('src', 'ink', 'index.mjs'), argv.slice(1));
|
|
318
|
+
break;
|
|
319
|
+
case 'skills:registry':
|
|
320
|
+
runNodeScript(path.join('scripts', 'update-skill-registry.mjs'));
|
|
321
|
+
break;
|
|
322
|
+
case 'openspec:new':
|
|
323
|
+
runNodeScript(path.join('scripts', 'scaffold-openspec-change.mjs'), argv.slice(1));
|
|
324
|
+
break;
|
|
325
|
+
case 'agent-config:init':
|
|
326
|
+
runNodeScript(path.join('scripts', 'scaffold-agent-configs.mjs'));
|
|
327
|
+
break;
|
|
328
|
+
default:
|
|
329
|
+
console.error(TEXT.es.unknown(command));
|
|
330
|
+
printHelp();
|
|
331
|
+
process.exit(1);
|
|
332
|
+
}
|