aios-lite 0.1.2 → 0.1.4
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/CHANGELOG.md +26 -0
- package/README.md +6 -1
- package/docs/en/i18n.md +10 -0
- package/package.json +1 -1
- package/src/agents.js +13 -6
- package/src/cli.js +12 -0
- package/src/commands/agents.js +43 -9
- package/src/commands/doctor.js +45 -5
- package/src/commands/locale-apply.js +43 -0
- package/src/commands/setup-context.js +13 -3
- package/src/commands/smoke.js +151 -0
- package/src/constants.js +14 -0
- package/src/doctor.js +69 -1
- package/src/i18n/messages/en.js +37 -8
- package/src/locales.js +82 -0
- package/template/.aios-lite/agents/setup.md +5 -1
- package/template/.aios-lite/config.md +7 -0
- package/template/.aios-lite/locales/en/agents/analyst.md +26 -0
- package/template/.aios-lite/locales/en/agents/architect.md +22 -0
- package/template/.aios-lite/locales/en/agents/dev.md +18 -0
- package/template/.aios-lite/locales/en/agents/orchestrator.md +15 -0
- package/template/.aios-lite/locales/en/agents/pm.md +21 -0
- package/template/.aios-lite/locales/en/agents/qa.md +22 -0
- package/template/.aios-lite/locales/en/agents/setup.md +71 -0
- package/template/.aios-lite/locales/pt-BR/agents/analyst.md +19 -0
- package/template/.aios-lite/locales/pt-BR/agents/architect.md +20 -0
- package/template/.aios-lite/locales/pt-BR/agents/dev.md +20 -0
- package/template/.aios-lite/locales/pt-BR/agents/orchestrator.md +18 -0
- package/template/.aios-lite/locales/pt-BR/agents/pm.md +16 -0
- package/template/.aios-lite/locales/pt-BR/agents/qa.md +16 -0
- package/template/.aios-lite/locales/pt-BR/agents/setup.md +33 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.1.4] - Unreleased
|
|
6
|
+
### Added
|
|
7
|
+
- New command:
|
|
8
|
+
- `aios-lite test:smoke [workspace-path] [--lang=en|pt-BR] [--keep]`
|
|
9
|
+
- New smoke test suite: `tests/smoke.test.js`.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- `doctor` now supports safe remediation mode:
|
|
13
|
+
- `aios-lite doctor --fix`
|
|
14
|
+
- `aios-lite doctor --fix --dry-run`
|
|
15
|
+
- `setup:context` and setup templates now default `aios_lite_version` to `0.1.4`.
|
|
16
|
+
|
|
17
|
+
## [0.1.3] - 2026-03-01
|
|
18
|
+
### Added
|
|
19
|
+
- Localized agent prompt packs:
|
|
20
|
+
- `.aios-lite/locales/en/agents/*.md`
|
|
21
|
+
- `.aios-lite/locales/pt-BR/agents/*.md`
|
|
22
|
+
- New command:
|
|
23
|
+
- `aios-lite locale:apply [path] [--lang=en|pt-BR] [--dry-run]`
|
|
24
|
+
- Agent path resolution now supports locale-aware prompts with fallback to active agent paths.
|
|
25
|
+
- New locale test suite: `tests/locales.test.js`.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- `setup:context` now applies localized agent prompts based on `conversation_language`.
|
|
29
|
+
- Documentation updated for locale pack workflow.
|
|
30
|
+
|
|
5
31
|
## [0.1.2] - 2026-03-01
|
|
6
32
|
### Added
|
|
7
33
|
- New commands:
|
package/README.md
CHANGED
|
@@ -15,12 +15,14 @@ npx aios-lite install
|
|
|
15
15
|
- `aios-lite install [path]`
|
|
16
16
|
- `aios-lite update [path]`
|
|
17
17
|
- `aios-lite info [path]`
|
|
18
|
-
- `aios-lite doctor [path]`
|
|
18
|
+
- `aios-lite doctor [path] [--fix] [--dry-run]`
|
|
19
19
|
- `aios-lite i18n:add <locale>`
|
|
20
20
|
- `aios-lite setup:context [path]`
|
|
21
21
|
- `aios-lite agents`
|
|
22
22
|
- `aios-lite agent:prompt <agent> [--tool=codex|claude|gemini|opencode]`
|
|
23
23
|
- `aios-lite context:validate [path]`
|
|
24
|
+
- `aios-lite locale:apply [path] [--lang=en|pt-BR]`
|
|
25
|
+
- `aios-lite test:smoke [workspace-path] [--lang=en|pt-BR] [--keep]`
|
|
24
26
|
|
|
25
27
|
## Agent usage helper
|
|
26
28
|
If your AI CLI does not show a visual agent picker, use:
|
|
@@ -28,6 +30,9 @@ If your AI CLI does not show a visual agent picker, use:
|
|
|
28
30
|
```bash
|
|
29
31
|
aios-lite agents
|
|
30
32
|
aios-lite agent:prompt setup --tool=codex
|
|
33
|
+
aios-lite locale:apply --lang=pt-BR
|
|
34
|
+
aios-lite doctor --fix
|
|
35
|
+
aios-lite test:smoke --lang=pt-BR
|
|
31
36
|
```
|
|
32
37
|
|
|
33
38
|
## i18n
|
package/docs/en/i18n.md
CHANGED
|
@@ -7,6 +7,7 @@ AIOS Lite CLI supports localization through message dictionaries.
|
|
|
7
7
|
- `src/i18n/index.js` resolves locale and fallback behavior.
|
|
8
8
|
- Commands use translation keys instead of hardcoded strings.
|
|
9
9
|
- Agent templates read `conversation_language` from `.aios-lite/context/project.context.md` and should use it for interaction/output language.
|
|
10
|
+
- Localized agent packs live in `.aios-lite/locales/<locale>/agents/` and can be applied to active prompts with `aios-lite locale:apply`.
|
|
10
11
|
|
|
11
12
|
## Runtime selection
|
|
12
13
|
- CLI option: `--locale=en`
|
|
@@ -18,6 +19,15 @@ AIOS Lite CLI supports localization through message dictionaries.
|
|
|
18
19
|
aios-lite i18n:add fr
|
|
19
20
|
```
|
|
20
21
|
|
|
22
|
+
## Apply localized agent prompts
|
|
23
|
+
```bash
|
|
24
|
+
# Use language from project.context.md
|
|
25
|
+
aios-lite locale:apply
|
|
26
|
+
|
|
27
|
+
# Or force a locale
|
|
28
|
+
aios-lite locale:apply --lang=pt-BR
|
|
29
|
+
```
|
|
30
|
+
|
|
21
31
|
## Add a new locale
|
|
22
32
|
1. Run `aios-lite i18n:add <locale>`.
|
|
23
33
|
2. Replace English strings in `src/i18n/messages/<locale>.js`.
|
package/package.json
CHANGED
package/src/agents.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { AGENT_DEFINITIONS } = require('./constants');
|
|
4
|
+
const { getLocalizedAgentPath } = require('./locales');
|
|
4
5
|
|
|
5
6
|
function normalizeAgentName(input) {
|
|
6
7
|
return String(input || '')
|
|
@@ -18,32 +19,38 @@ function listAgentDefinitions() {
|
|
|
18
19
|
return [...AGENT_DEFINITIONS];
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
function
|
|
22
|
+
function resolveInstructionPath(agent, locale) {
|
|
23
|
+
if (!locale) return agent.path;
|
|
24
|
+
return getLocalizedAgentPath(agent.id, locale);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function buildAgentPrompt(agent, tool, options = {}) {
|
|
22
28
|
const safeTool = String(tool || 'codex').toLowerCase();
|
|
29
|
+
const instructionPath = options.instructionPath || agent.path;
|
|
23
30
|
const dependencyText =
|
|
24
31
|
agent.dependsOn.length > 0
|
|
25
32
|
? `Check required context files first: ${agent.dependsOn.join(', ')}.`
|
|
26
33
|
: 'No prerequisite context files are required.';
|
|
27
34
|
|
|
28
35
|
if (safeTool === 'claude') {
|
|
29
|
-
return `Read ${
|
|
36
|
+
return `Read ${instructionPath} and execute ${agent.command}. ${dependencyText} Write output to ${agent.output}.`;
|
|
30
37
|
}
|
|
31
38
|
|
|
32
39
|
if (safeTool === 'gemini') {
|
|
33
|
-
return `Run the Gemini command mapped to ${
|
|
40
|
+
return `Run the Gemini command mapped to ${instructionPath} and execute ${agent.command}. ${dependencyText} Save result to ${agent.output}.`;
|
|
34
41
|
}
|
|
35
42
|
|
|
36
43
|
if (safeTool === 'opencode') {
|
|
37
|
-
return `Use agent "${agent.id}" from ${
|
|
44
|
+
return `Use agent "${agent.id}" from ${instructionPath}. ${dependencyText} Save output to ${agent.output}.`;
|
|
38
45
|
}
|
|
39
46
|
|
|
40
|
-
return `Read AGENTS.md and execute ${agent.command} using ${
|
|
47
|
+
return `Read AGENTS.md and execute ${agent.command} using ${instructionPath}. ${dependencyText} Save output to ${agent.output}.`;
|
|
41
48
|
}
|
|
42
49
|
|
|
43
50
|
module.exports = {
|
|
44
51
|
normalizeAgentName,
|
|
45
52
|
getAgentDefinition,
|
|
46
53
|
listAgentDefinitions,
|
|
54
|
+
resolveInstructionPath,
|
|
47
55
|
buildAgentPrompt
|
|
48
56
|
};
|
|
49
|
-
|
package/src/cli.js
CHANGED
|
@@ -11,6 +11,8 @@ const { runI18nAdd } = require('./commands/i18n-add');
|
|
|
11
11
|
const { runAgentsList, runAgentPrompt } = require('./commands/agents');
|
|
12
12
|
const { runContextValidate } = require('./commands/context-validate');
|
|
13
13
|
const { runSetupContext } = require('./commands/setup-context');
|
|
14
|
+
const { runLocaleApply } = require('./commands/locale-apply');
|
|
15
|
+
const { runSmokeTest } = require('./commands/smoke');
|
|
14
16
|
|
|
15
17
|
function printHelp(t) {
|
|
16
18
|
console.log(`${t('cli.title')}\n`);
|
|
@@ -25,6 +27,8 @@ function printHelp(t) {
|
|
|
25
27
|
console.log(` ${t('cli.help_agent_prompt')}`);
|
|
26
28
|
console.log(` ${t('cli.help_context_validate')}`);
|
|
27
29
|
console.log(` ${t('cli.help_setup_context')}`);
|
|
30
|
+
console.log(` ${t('cli.help_locale_apply')}`);
|
|
31
|
+
console.log(` ${t('cli.help_test_smoke')}`);
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
async function main() {
|
|
@@ -84,6 +88,14 @@ async function main() {
|
|
|
84
88
|
await runSetupContext({ args, options, logger, t });
|
|
85
89
|
return;
|
|
86
90
|
}
|
|
91
|
+
if (command === 'locale:apply' || command === 'locale-apply') {
|
|
92
|
+
await runLocaleApply({ args, options, logger, t });
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (command === 'test:smoke' || command === 'test-smoke') {
|
|
96
|
+
await runSmokeTest({ args, options, logger, t });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
87
99
|
|
|
88
100
|
logger.error(`${t('cli.unknown_command', { command })}\n`);
|
|
89
101
|
printHelp(t);
|
package/src/commands/agents.js
CHANGED
|
@@ -1,19 +1,51 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const {
|
|
5
|
+
listAgentDefinitions,
|
|
6
|
+
getAgentDefinition,
|
|
7
|
+
resolveInstructionPath,
|
|
8
|
+
buildAgentPrompt
|
|
9
|
+
} = require('../agents');
|
|
10
|
+
const { resolveAgentLocale } = require('../locales');
|
|
11
|
+
const { validateProjectContextFile } = require('../context');
|
|
12
|
+
const { exists } = require('../utils');
|
|
4
13
|
|
|
5
|
-
async function
|
|
14
|
+
async function resolveLocaleForTarget(targetDir, options) {
|
|
15
|
+
const fromOption = options.language || options.lang;
|
|
16
|
+
if (fromOption) return resolveAgentLocale(fromOption);
|
|
17
|
+
|
|
18
|
+
const context = await validateProjectContextFile(targetDir);
|
|
19
|
+
if (context.parsed && context.data && context.data.conversation_language) {
|
|
20
|
+
return resolveAgentLocale(context.data.conversation_language);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return 'en';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function resolveExistingInstructionPath(targetDir, agent, locale) {
|
|
27
|
+
const candidate = resolveInstructionPath(agent, locale);
|
|
28
|
+
const candidateAbs = path.join(targetDir, candidate);
|
|
29
|
+
if (await exists(candidateAbs)) return candidate;
|
|
30
|
+
return agent.path;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function runAgentsList({ args, options, logger, t }) {
|
|
34
|
+
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
35
|
+
const locale = await resolveLocaleForTarget(targetDir, options);
|
|
6
36
|
const agents = listAgentDefinitions();
|
|
7
|
-
logger.log(t('agents.list_title'));
|
|
37
|
+
logger.log(t('agents.list_title', { locale }));
|
|
8
38
|
for (const agent of agents) {
|
|
9
39
|
const deps = agent.dependsOn.length > 0 ? agent.dependsOn.join(', ') : t('agents.none');
|
|
40
|
+
const instructionPath = await resolveExistingInstructionPath(targetDir, agent, locale);
|
|
10
41
|
logger.log(`- ${agent.command} (${agent.id})`);
|
|
11
|
-
logger.log(` ${t('agents.path')}: ${
|
|
42
|
+
logger.log(` ${t('agents.path')}: ${instructionPath}`);
|
|
43
|
+
logger.log(` ${t('agents.active_path')}: ${agent.path}`);
|
|
12
44
|
logger.log(` ${t('agents.depends')}: ${deps}`);
|
|
13
45
|
logger.log(` ${t('agents.output')}: ${agent.output}`);
|
|
14
46
|
}
|
|
15
47
|
|
|
16
|
-
return { count: agents.length, agents };
|
|
48
|
+
return { count: agents.length, agents, locale };
|
|
17
49
|
}
|
|
18
50
|
|
|
19
51
|
async function runAgentPrompt({ args, options, logger, t }) {
|
|
@@ -27,17 +59,19 @@ async function runAgentPrompt({ args, options, logger, t }) {
|
|
|
27
59
|
throw new Error(t('agents.prompt_unknown_agent', { agent: name }));
|
|
28
60
|
}
|
|
29
61
|
|
|
62
|
+
const targetDir = path.resolve(process.cwd(), args[1] || '.');
|
|
63
|
+
const locale = await resolveLocaleForTarget(targetDir, options);
|
|
64
|
+
const instructionPath = await resolveExistingInstructionPath(targetDir, agent, locale);
|
|
30
65
|
const tool = options.tool || 'codex';
|
|
31
|
-
const prompt = buildAgentPrompt(agent, tool);
|
|
66
|
+
const prompt = buildAgentPrompt(agent, tool, { instructionPath });
|
|
32
67
|
|
|
33
|
-
logger.log(t('agents.prompt_title', { agent: agent.id, tool }));
|
|
68
|
+
logger.log(t('agents.prompt_title', { agent: agent.id, tool, locale }));
|
|
34
69
|
logger.log(prompt);
|
|
35
70
|
|
|
36
|
-
return { agent: agent.id, tool, prompt };
|
|
71
|
+
return { agent: agent.id, tool, locale, prompt };
|
|
37
72
|
}
|
|
38
73
|
|
|
39
74
|
module.exports = {
|
|
40
75
|
runAgentsList,
|
|
41
76
|
runAgentPrompt
|
|
42
77
|
};
|
|
43
|
-
|
package/src/commands/doctor.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const path = require('node:path');
|
|
4
|
-
const { runDoctor } = require('../doctor');
|
|
5
|
-
|
|
6
|
-
async function runDoctorCommand({ args, logger, t }) {
|
|
7
|
-
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
8
|
-
const report = await runDoctor(targetDir);
|
|
4
|
+
const { runDoctor, applyDoctorFixes } = require('../doctor');
|
|
9
5
|
|
|
6
|
+
function printDoctorChecks(report, logger, t) {
|
|
10
7
|
for (const check of report.checks) {
|
|
11
8
|
const icon = check.ok ? t('doctor.ok') : t('doctor.fail');
|
|
12
9
|
logger.log(`[${icon}] ${t(check.key, check.params)}`);
|
|
@@ -14,6 +11,49 @@ async function runDoctorCommand({ args, logger, t }) {
|
|
|
14
11
|
logger.log(` ${t('doctor.hint_prefix', { hint: t(check.hintKey) })}`);
|
|
15
12
|
}
|
|
16
13
|
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function printFixAction(action, logger, t, dryRun) {
|
|
17
|
+
logger.log(`- ${t(`doctor.fix_action_${action.id}`)}`);
|
|
18
|
+
if (action.skipped) {
|
|
19
|
+
logger.log(` ${t('doctor.fix_not_applicable')}`);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
logger.log(` ${t('doctor.fix_target_count', { count: action.missingCount || action.count || 0 })}`);
|
|
23
|
+
logger.log(
|
|
24
|
+
` ${t(dryRun ? 'doctor.fix_planned_count' : 'doctor.fix_applied_count', {
|
|
25
|
+
count: action.count || 0
|
|
26
|
+
})}`
|
|
27
|
+
);
|
|
28
|
+
if (action.locale) {
|
|
29
|
+
logger.log(` ${t('doctor.fix_locale', { locale: action.locale })}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function runDoctorCommand({ args, options = {}, logger, t }) {
|
|
34
|
+
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
35
|
+
const fix = Boolean(options.fix);
|
|
36
|
+
const dryRun = Boolean(options['dry-run']);
|
|
37
|
+
|
|
38
|
+
let report = await runDoctor(targetDir);
|
|
39
|
+
|
|
40
|
+
if (fix) {
|
|
41
|
+
logger.log(dryRun ? t('doctor.fix_start_dry_run') : t('doctor.fix_start'));
|
|
42
|
+
const fixResult = await applyDoctorFixes(targetDir, report, { dryRun });
|
|
43
|
+
for (const action of fixResult.actions) {
|
|
44
|
+
printFixAction(action, logger, t, dryRun);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
logger.log(
|
|
48
|
+
dryRun
|
|
49
|
+
? t('doctor.fix_summary_dry_run', { count: fixResult.changedCount })
|
|
50
|
+
: t('doctor.fix_summary', { count: fixResult.changedCount })
|
|
51
|
+
);
|
|
52
|
+
logger.log('');
|
|
53
|
+
report = await runDoctor(targetDir);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
printDoctorChecks(report, logger, t);
|
|
17
57
|
|
|
18
58
|
if (!report.ok) {
|
|
19
59
|
logger.log(`\n${t('doctor.diagnosis_fail', { count: report.failedCount })}`);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const { applyAgentLocale, resolveAgentLocale } = require('../locales');
|
|
5
|
+
const { validateProjectContextFile } = require('../context');
|
|
6
|
+
|
|
7
|
+
async function runLocaleApply({ args, options, logger, t }) {
|
|
8
|
+
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
9
|
+
const dryRun = Boolean(options['dry-run']);
|
|
10
|
+
|
|
11
|
+
let requestedLanguage = options.language || options.lang || '';
|
|
12
|
+
if (!requestedLanguage) {
|
|
13
|
+
const context = await validateProjectContextFile(targetDir);
|
|
14
|
+
if (context.parsed && context.data && context.data.conversation_language) {
|
|
15
|
+
requestedLanguage = context.data.conversation_language;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const locale = resolveAgentLocale(requestedLanguage || 'en');
|
|
20
|
+
const result = await applyAgentLocale(targetDir, locale, { dryRun });
|
|
21
|
+
|
|
22
|
+
logger.log(
|
|
23
|
+
dryRun
|
|
24
|
+
? t('locale_apply.dry_run_applied', { locale: result.locale })
|
|
25
|
+
: t('locale_apply.applied', { locale: result.locale })
|
|
26
|
+
);
|
|
27
|
+
logger.log(t('locale_apply.copied_count', { count: result.copied.length }));
|
|
28
|
+
|
|
29
|
+
if (result.missing.length > 0) {
|
|
30
|
+
logger.log(t('locale_apply.missing_count', { count: result.missing.length }));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for (const item of result.copied) {
|
|
34
|
+
logger.log(`- ${item.source} -> ${item.target}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
runLocaleApply
|
|
42
|
+
};
|
|
43
|
+
|
|
@@ -9,6 +9,7 @@ const {
|
|
|
9
9
|
renderProjectContext,
|
|
10
10
|
writeProjectContext
|
|
11
11
|
} = require('../context-writer');
|
|
12
|
+
const { applyAgentLocale } = require('../locales');
|
|
12
13
|
|
|
13
14
|
function resolveOption(options, name, fallback = '') {
|
|
14
15
|
return options[name] !== undefined ? String(options[name]) : fallback;
|
|
@@ -52,7 +53,7 @@ async function runSetupContext({ args, options, logger, t }) {
|
|
|
52
53
|
email: resolveOption(options, 'email', ''),
|
|
53
54
|
payments: resolveOption(options, 'payments', ''),
|
|
54
55
|
installCommands: resolveOption(options, 'install-commands', ''),
|
|
55
|
-
aiosLiteVersion: resolveOption(options, 'aios-lite-version', '0.1.
|
|
56
|
+
aiosLiteVersion: resolveOption(options, 'aios-lite-version', '0.1.4')
|
|
56
57
|
};
|
|
57
58
|
|
|
58
59
|
let userTypesCount = Number(options['user-types'] || 1);
|
|
@@ -105,6 +106,9 @@ async function runSetupContext({ args, options, logger, t }) {
|
|
|
105
106
|
|
|
106
107
|
const content = renderProjectContext(data);
|
|
107
108
|
const filePath = await writeProjectContext(targetDir, content);
|
|
109
|
+
const localeApplyResult = await applyAgentLocale(targetDir, data.conversationLanguage, {
|
|
110
|
+
dryRun: false
|
|
111
|
+
});
|
|
108
112
|
|
|
109
113
|
logger.log(t('setup_context.written', { path: filePath }));
|
|
110
114
|
logger.log(
|
|
@@ -113,15 +117,21 @@ async function runSetupContext({ args, options, logger, t }) {
|
|
|
113
117
|
score: classificationResult.score
|
|
114
118
|
})
|
|
115
119
|
);
|
|
120
|
+
logger.log(
|
|
121
|
+
t('setup_context.locale_applied', {
|
|
122
|
+
locale: localeApplyResult.locale,
|
|
123
|
+
count: localeApplyResult.copied.length
|
|
124
|
+
})
|
|
125
|
+
);
|
|
116
126
|
|
|
117
127
|
return {
|
|
118
128
|
filePath,
|
|
119
129
|
data,
|
|
120
|
-
classificationScore: classificationResult.score
|
|
130
|
+
classificationScore: classificationResult.score,
|
|
131
|
+
localeApplyResult
|
|
121
132
|
};
|
|
122
133
|
}
|
|
123
134
|
|
|
124
135
|
module.exports = {
|
|
125
136
|
runSetupContext
|
|
126
137
|
};
|
|
127
|
-
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs/promises');
|
|
4
|
+
const os = require('node:os');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
const { ensureDir } = require('../utils');
|
|
7
|
+
const { runInstall } = require('./install');
|
|
8
|
+
const { runSetupContext } = require('./setup-context');
|
|
9
|
+
const { runLocaleApply } = require('./locale-apply');
|
|
10
|
+
const { runAgentsList, runAgentPrompt } = require('./agents');
|
|
11
|
+
const { runContextValidate } = require('./context-validate');
|
|
12
|
+
const { runDoctor } = require('../doctor');
|
|
13
|
+
const { runUpdate } = require('./update');
|
|
14
|
+
|
|
15
|
+
function createQuietLogger() {
|
|
16
|
+
return {
|
|
17
|
+
log() {},
|
|
18
|
+
error() {}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function assertStep(condition, message) {
|
|
23
|
+
if (!condition) {
|
|
24
|
+
throw new Error(message);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function runSmokeTest({ args, options, logger, t }) {
|
|
29
|
+
const language = String(options.language || options.lang || 'en');
|
|
30
|
+
const keep = Boolean(options.keep);
|
|
31
|
+
const baseDir = path.resolve(process.cwd(), args[0] || os.tmpdir());
|
|
32
|
+
await ensureDir(baseDir);
|
|
33
|
+
|
|
34
|
+
const workspaceRoot = await fs.mkdtemp(path.join(baseDir, 'aios-lite-smoke-'));
|
|
35
|
+
const projectDir = path.join(workspaceRoot, 'demo');
|
|
36
|
+
await ensureDir(projectDir);
|
|
37
|
+
|
|
38
|
+
const steps = [];
|
|
39
|
+
const quietLogger = createQuietLogger();
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
logger.log(t('smoke.start', { projectDir }));
|
|
43
|
+
|
|
44
|
+
const installResult = await runInstall({
|
|
45
|
+
args: [projectDir],
|
|
46
|
+
options: {},
|
|
47
|
+
logger: quietLogger,
|
|
48
|
+
t
|
|
49
|
+
});
|
|
50
|
+
assertStep(installResult.copied.length > 0, 'install copied zero files');
|
|
51
|
+
steps.push('install');
|
|
52
|
+
logger.log(t('smoke.step_ok', { step: 'install' }));
|
|
53
|
+
|
|
54
|
+
const setupResult = await runSetupContext({
|
|
55
|
+
args: [projectDir],
|
|
56
|
+
options: {
|
|
57
|
+
defaults: true,
|
|
58
|
+
'project-name': 'demo',
|
|
59
|
+
'project-type': 'web_app',
|
|
60
|
+
profile: 'developer',
|
|
61
|
+
framework: 'Node',
|
|
62
|
+
'framework-installed': true,
|
|
63
|
+
language
|
|
64
|
+
},
|
|
65
|
+
logger: quietLogger,
|
|
66
|
+
t
|
|
67
|
+
});
|
|
68
|
+
assertStep(Boolean(setupResult.filePath), 'setup:context did not write context file');
|
|
69
|
+
steps.push('setup:context');
|
|
70
|
+
logger.log(t('smoke.step_ok', { step: 'setup:context' }));
|
|
71
|
+
|
|
72
|
+
const localeResult = await runLocaleApply({
|
|
73
|
+
args: [projectDir],
|
|
74
|
+
options: { lang: language },
|
|
75
|
+
logger: quietLogger,
|
|
76
|
+
t
|
|
77
|
+
});
|
|
78
|
+
assertStep(localeResult.copied.length > 0, 'locale:apply copied zero files');
|
|
79
|
+
steps.push('locale:apply');
|
|
80
|
+
logger.log(t('smoke.step_ok', { step: 'locale:apply' }));
|
|
81
|
+
|
|
82
|
+
const agentsResult = await runAgentsList({
|
|
83
|
+
args: [projectDir],
|
|
84
|
+
options: { lang: language },
|
|
85
|
+
logger: quietLogger,
|
|
86
|
+
t
|
|
87
|
+
});
|
|
88
|
+
assertStep(agentsResult.count >= 7, 'agents command returned unexpected agent count');
|
|
89
|
+
steps.push('agents');
|
|
90
|
+
logger.log(t('smoke.step_ok', { step: 'agents' }));
|
|
91
|
+
|
|
92
|
+
const promptResult = await runAgentPrompt({
|
|
93
|
+
args: ['setup', projectDir],
|
|
94
|
+
options: { tool: 'codex', lang: language },
|
|
95
|
+
logger: quietLogger,
|
|
96
|
+
t
|
|
97
|
+
});
|
|
98
|
+
assertStep(
|
|
99
|
+
promptResult.prompt.includes('.aios-lite'),
|
|
100
|
+
'agent:prompt did not include expected path information'
|
|
101
|
+
);
|
|
102
|
+
steps.push('agent:prompt');
|
|
103
|
+
logger.log(t('smoke.step_ok', { step: 'agent:prompt' }));
|
|
104
|
+
|
|
105
|
+
const contextResult = await runContextValidate({
|
|
106
|
+
args: [projectDir],
|
|
107
|
+
options: {},
|
|
108
|
+
logger: quietLogger,
|
|
109
|
+
t
|
|
110
|
+
});
|
|
111
|
+
assertStep(contextResult.ok, 'context:validate failed');
|
|
112
|
+
steps.push('context:validate');
|
|
113
|
+
logger.log(t('smoke.step_ok', { step: 'context:validate' }));
|
|
114
|
+
|
|
115
|
+
const doctorResult = await runDoctor(projectDir);
|
|
116
|
+
assertStep(doctorResult.ok, 'doctor check failed');
|
|
117
|
+
steps.push('doctor');
|
|
118
|
+
logger.log(t('smoke.step_ok', { step: 'doctor' }));
|
|
119
|
+
|
|
120
|
+
await runUpdate({
|
|
121
|
+
args: [projectDir],
|
|
122
|
+
options: {},
|
|
123
|
+
logger: quietLogger,
|
|
124
|
+
t
|
|
125
|
+
});
|
|
126
|
+
steps.push('update');
|
|
127
|
+
logger.log(t('smoke.step_ok', { step: 'update' }));
|
|
128
|
+
|
|
129
|
+
logger.log(t('smoke.completed'));
|
|
130
|
+
logger.log(t('smoke.steps_count', { count: steps.length }));
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
ok: true,
|
|
134
|
+
steps,
|
|
135
|
+
workspaceRoot,
|
|
136
|
+
projectDir,
|
|
137
|
+
kept: keep
|
|
138
|
+
};
|
|
139
|
+
} finally {
|
|
140
|
+
if (!keep) {
|
|
141
|
+
await fs.rm(workspaceRoot, { recursive: true, force: true });
|
|
142
|
+
logger.log(t('smoke.workspace_removed', { path: workspaceRoot }));
|
|
143
|
+
} else {
|
|
144
|
+
logger.log(t('smoke.workspace_kept', { path: workspaceRoot }));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = {
|
|
150
|
+
runSmokeTest
|
|
151
|
+
};
|
package/src/constants.js
CHANGED
|
@@ -20,6 +20,20 @@ const MANAGED_FILES = [
|
|
|
20
20
|
'.aios-lite/agents/dev.md',
|
|
21
21
|
'.aios-lite/agents/qa.md',
|
|
22
22
|
'.aios-lite/agents/orchestrator.md',
|
|
23
|
+
'.aios-lite/locales/en/agents/setup.md',
|
|
24
|
+
'.aios-lite/locales/en/agents/analyst.md',
|
|
25
|
+
'.aios-lite/locales/en/agents/architect.md',
|
|
26
|
+
'.aios-lite/locales/en/agents/pm.md',
|
|
27
|
+
'.aios-lite/locales/en/agents/dev.md',
|
|
28
|
+
'.aios-lite/locales/en/agents/qa.md',
|
|
29
|
+
'.aios-lite/locales/en/agents/orchestrator.md',
|
|
30
|
+
'.aios-lite/locales/pt-BR/agents/setup.md',
|
|
31
|
+
'.aios-lite/locales/pt-BR/agents/analyst.md',
|
|
32
|
+
'.aios-lite/locales/pt-BR/agents/architect.md',
|
|
33
|
+
'.aios-lite/locales/pt-BR/agents/pm.md',
|
|
34
|
+
'.aios-lite/locales/pt-BR/agents/dev.md',
|
|
35
|
+
'.aios-lite/locales/pt-BR/agents/qa.md',
|
|
36
|
+
'.aios-lite/locales/pt-BR/agents/orchestrator.md',
|
|
23
37
|
'.aios-lite/skills/static/laravel-conventions.md',
|
|
24
38
|
'.aios-lite/skills/static/tall-stack-patterns.md',
|
|
25
39
|
'.aios-lite/skills/static/jetstream-setup.md',
|
package/src/doctor.js
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('node:path');
|
|
4
4
|
const { REQUIRED_FILES } = require('./constants');
|
|
5
|
+
const { installTemplate } = require('./installer');
|
|
5
6
|
const { exists } = require('./utils');
|
|
6
7
|
const { validateProjectContextFile } = require('./context');
|
|
8
|
+
const { applyAgentLocale, resolveAgentLocale } = require('./locales');
|
|
7
9
|
|
|
8
10
|
function parseMajor(version) {
|
|
9
11
|
const cleaned = String(version || '').replace(/^v/, '');
|
|
@@ -72,7 +74,73 @@ async function runDoctor(targetDir) {
|
|
|
72
74
|
};
|
|
73
75
|
}
|
|
74
76
|
|
|
77
|
+
async function applyDoctorFixes(targetDir, report, options = {}) {
|
|
78
|
+
const dryRun = Boolean(options.dryRun);
|
|
79
|
+
const actions = [];
|
|
80
|
+
let changedCount = 0;
|
|
81
|
+
|
|
82
|
+
const missingRequiredFiles = report.checks
|
|
83
|
+
.filter((check) => !check.ok && check.id.startsWith('file:'))
|
|
84
|
+
.map((check) => check.params.rel);
|
|
85
|
+
|
|
86
|
+
if (missingRequiredFiles.length > 0) {
|
|
87
|
+
const installResult = await installTemplate(targetDir, {
|
|
88
|
+
overwrite: false,
|
|
89
|
+
dryRun,
|
|
90
|
+
mode: 'install'
|
|
91
|
+
});
|
|
92
|
+
const copiedRequired = installResult.copied.filter((rel) => missingRequiredFiles.includes(rel));
|
|
93
|
+
if (copiedRequired.length > 0) changedCount += copiedRequired.length;
|
|
94
|
+
actions.push({
|
|
95
|
+
id: 'required_files',
|
|
96
|
+
applied: copiedRequired.length > 0,
|
|
97
|
+
count: copiedRequired.length,
|
|
98
|
+
missingCount: missingRequiredFiles.length
|
|
99
|
+
});
|
|
100
|
+
} else {
|
|
101
|
+
actions.push({
|
|
102
|
+
id: 'required_files',
|
|
103
|
+
applied: false,
|
|
104
|
+
skipped: true,
|
|
105
|
+
count: 0,
|
|
106
|
+
missingCount: 0
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (
|
|
111
|
+
report.contextValidation &&
|
|
112
|
+
report.contextValidation.parsed &&
|
|
113
|
+
report.contextValidation.valid &&
|
|
114
|
+
report.contextValidation.data &&
|
|
115
|
+
report.contextValidation.data.conversation_language
|
|
116
|
+
) {
|
|
117
|
+
const locale = resolveAgentLocale(report.contextValidation.data.conversation_language);
|
|
118
|
+
const localeResult = await applyAgentLocale(targetDir, locale, { dryRun });
|
|
119
|
+
if (localeResult.copied.length > 0) changedCount += localeResult.copied.length;
|
|
120
|
+
actions.push({
|
|
121
|
+
id: 'locale_sync',
|
|
122
|
+
applied: localeResult.copied.length > 0,
|
|
123
|
+
count: localeResult.copied.length,
|
|
124
|
+
locale: localeResult.locale
|
|
125
|
+
});
|
|
126
|
+
} else {
|
|
127
|
+
actions.push({
|
|
128
|
+
id: 'locale_sync',
|
|
129
|
+
applied: false,
|
|
130
|
+
skipped: true,
|
|
131
|
+
count: 0
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
dryRun,
|
|
137
|
+
actions,
|
|
138
|
+
changedCount
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
75
142
|
module.exports = {
|
|
76
143
|
runDoctor,
|
|
77
|
-
parseMajor
|
|
144
|
+
parseMajor,
|
|
145
|
+
applyDoctorFixes
|
|
78
146
|
};
|
package/src/i18n/messages/en.js
CHANGED
|
@@ -8,12 +8,14 @@ module.exports = {
|
|
|
8
8
|
help_install: 'aios-lite install [path] [--force] [--dry-run] [--locale=en]',
|
|
9
9
|
help_update: 'aios-lite update [path] [--dry-run] [--locale=en]',
|
|
10
10
|
help_info: 'aios-lite info [path] [--locale=en]',
|
|
11
|
-
help_doctor: 'aios-lite doctor [path] [--locale=en]',
|
|
11
|
+
help_doctor: 'aios-lite doctor [path] [--fix] [--dry-run] [--locale=en]',
|
|
12
12
|
help_i18n_add: 'aios-lite i18n:add <locale> [--force] [--dry-run] [--locale=en]',
|
|
13
|
-
help_agents: 'aios-lite agents [--locale=en]',
|
|
14
|
-
help_agent_prompt: 'aios-lite agent:prompt <agent> [--tool=codex|claude|gemini|opencode] [--locale=en]',
|
|
13
|
+
help_agents: 'aios-lite agents [path] [--lang=en|pt-BR] [--locale=en]',
|
|
14
|
+
help_agent_prompt: 'aios-lite agent:prompt <agent> [path] [--tool=codex|claude|gemini|opencode] [--lang=en|pt-BR] [--locale=en]',
|
|
15
15
|
help_context_validate: 'aios-lite context:validate [path] [--locale=en]',
|
|
16
16
|
help_setup_context: 'aios-lite setup:context [path] [--defaults] [--project-name=...] [--language=en] [--locale=en]',
|
|
17
|
+
help_locale_apply: 'aios-lite locale:apply [path] [--lang=en|pt-BR] [--dry-run] [--locale=en]',
|
|
18
|
+
help_test_smoke: 'aios-lite test:smoke [workspace-path] [--lang=en|pt-BR] [--keep] [--locale=en]',
|
|
17
19
|
unknown_command: 'Unknown command: {command}',
|
|
18
20
|
error_prefix: 'Error: {message}'
|
|
19
21
|
},
|
|
@@ -75,7 +77,18 @@ module.exports = {
|
|
|
75
77
|
context_profile_value_hint: 'Use developer, beginner, or team exactly.',
|
|
76
78
|
context_conversation_language_format: '`conversation_language` is not a valid BCP-47 tag',
|
|
77
79
|
context_conversation_language_format_hint: 'Use values like en, en-US, pt-BR.',
|
|
78
|
-
node_version: 'Node.js >= 18 (current: {version})'
|
|
80
|
+
node_version: 'Node.js >= 18 (current: {version})',
|
|
81
|
+
fix_start: 'Safe fix mode enabled.',
|
|
82
|
+
fix_start_dry_run: 'Safe fix mode enabled (dry-run).',
|
|
83
|
+
fix_action_required_files: 'Restore missing managed files from template',
|
|
84
|
+
fix_action_locale_sync: 'Synchronize active agent prompts with context language',
|
|
85
|
+
fix_not_applicable: 'Not applicable for current state.',
|
|
86
|
+
fix_target_count: 'Targets identified: {count}',
|
|
87
|
+
fix_applied_count: 'Changes applied: {count}',
|
|
88
|
+
fix_planned_count: 'Changes planned: {count}',
|
|
89
|
+
fix_locale: 'Resolved locale: {locale}',
|
|
90
|
+
fix_summary: 'Safe fix changes applied: {count}',
|
|
91
|
+
fix_summary_dry_run: '[dry-run] Safe fix changes planned: {count}'
|
|
79
92
|
},
|
|
80
93
|
i18n_add: {
|
|
81
94
|
usage_error: 'Usage: aios-lite i18n:add <locale> [--force] [--dry-run] [--locale=en]',
|
|
@@ -92,14 +105,15 @@ module.exports = {
|
|
|
92
105
|
step_try: '2. Run the CLI with --locale={locale} to validate the new dictionary.'
|
|
93
106
|
},
|
|
94
107
|
agents: {
|
|
95
|
-
list_title: 'Available agents:',
|
|
108
|
+
list_title: 'Available agents (resolved locale: {locale}):',
|
|
96
109
|
path: 'Path',
|
|
110
|
+
active_path: 'Active path',
|
|
97
111
|
depends: 'Depends on',
|
|
98
112
|
output: 'Output',
|
|
99
113
|
none: 'none',
|
|
100
|
-
prompt_usage_error: 'Usage: aios-lite agent:prompt <agent> [--tool=codex|claude|gemini|opencode] [--locale=en]',
|
|
114
|
+
prompt_usage_error: 'Usage: aios-lite agent:prompt <agent> [path] [--tool=codex|claude|gemini|opencode] [--lang=en|pt-BR] [--locale=en]',
|
|
101
115
|
prompt_unknown_agent: 'Unknown agent: {agent}',
|
|
102
|
-
prompt_title: 'Prompt for agent "{agent}" on tool "{tool}":'
|
|
116
|
+
prompt_title: 'Prompt for agent "{agent}" on tool "{tool}" (locale: {locale}):'
|
|
103
117
|
},
|
|
104
118
|
context_validate: {
|
|
105
119
|
missing_file: 'Context file not found: {path}',
|
|
@@ -123,6 +137,21 @@ module.exports = {
|
|
|
123
137
|
q_integrations: 'How many external integrations?',
|
|
124
138
|
q_rules_complexity: 'Rules complexity (none|some|complex)',
|
|
125
139
|
written: 'Context file written: {path}',
|
|
126
|
-
classification_result: 'Classification: {classification} (score={score}/6)'
|
|
140
|
+
classification_result: 'Classification: {classification} (score={score}/6)',
|
|
141
|
+
locale_applied: 'Localized agent pack applied: {locale} ({count} files)'
|
|
142
|
+
},
|
|
143
|
+
locale_apply: {
|
|
144
|
+
applied: 'Locale pack applied: {locale}',
|
|
145
|
+
dry_run_applied: '[dry-run] Locale pack would be applied: {locale}',
|
|
146
|
+
copied_count: 'Files copied: {count}',
|
|
147
|
+
missing_count: 'Missing locale files: {count}'
|
|
148
|
+
},
|
|
149
|
+
smoke: {
|
|
150
|
+
start: 'Running smoke test in: {projectDir}',
|
|
151
|
+
step_ok: 'OK: {step}',
|
|
152
|
+
completed: 'Smoke test completed successfully.',
|
|
153
|
+
steps_count: 'Validated steps: {count}',
|
|
154
|
+
workspace_kept: 'Workspace kept: {path}',
|
|
155
|
+
workspace_removed: 'Workspace removed: {path}'
|
|
127
156
|
}
|
|
128
157
|
};
|
package/src/locales.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs/promises');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const { AGENT_DEFINITIONS } = require('./constants');
|
|
6
|
+
const { exists, ensureDir } = require('./utils');
|
|
7
|
+
|
|
8
|
+
const SUPPORTED_AGENT_LOCALES = ['en', 'pt-BR'];
|
|
9
|
+
|
|
10
|
+
function normalizeLanguageTag(value) {
|
|
11
|
+
return String(value || '').trim();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function localeForPath(value) {
|
|
15
|
+
return String(value || '').replace(/_/g, '-');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function resolveAgentLocale(languageTag) {
|
|
19
|
+
const tag = normalizeLanguageTag(languageTag);
|
|
20
|
+
if (!tag) return 'en';
|
|
21
|
+
|
|
22
|
+
const exact = SUPPORTED_AGENT_LOCALES.find(
|
|
23
|
+
(locale) => locale.toLowerCase() === tag.toLowerCase()
|
|
24
|
+
);
|
|
25
|
+
if (exact) return exact;
|
|
26
|
+
|
|
27
|
+
const base = tag.split('-')[0].toLowerCase();
|
|
28
|
+
if (base === 'pt') return 'pt-BR';
|
|
29
|
+
if (base === 'en') return 'en';
|
|
30
|
+
|
|
31
|
+
return 'en';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function getLocalizedAgentPath(agentId, locale) {
|
|
35
|
+
return `.aios-lite/locales/${localeForPath(locale)}/agents/${agentId}.md`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function getActiveAgentPath(agentId) {
|
|
39
|
+
return `.aios-lite/agents/${agentId}.md`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function applyAgentLocale(targetDir, locale, options = {}) {
|
|
43
|
+
const resolved = resolveAgentLocale(locale);
|
|
44
|
+
const dryRun = Boolean(options.dryRun);
|
|
45
|
+
const copied = [];
|
|
46
|
+
const missing = [];
|
|
47
|
+
|
|
48
|
+
for (const agent of AGENT_DEFINITIONS) {
|
|
49
|
+
const sourceRel = getLocalizedAgentPath(agent.id, resolved);
|
|
50
|
+
const destRel = getActiveAgentPath(agent.id);
|
|
51
|
+
const sourceAbs = path.join(targetDir, sourceRel);
|
|
52
|
+
const destAbs = path.join(targetDir, destRel);
|
|
53
|
+
|
|
54
|
+
if (!(await exists(sourceAbs))) {
|
|
55
|
+
missing.push(sourceRel);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!dryRun) {
|
|
60
|
+
await ensureDir(path.dirname(destAbs));
|
|
61
|
+
await fs.copyFile(sourceAbs, destAbs);
|
|
62
|
+
}
|
|
63
|
+
copied.push({ source: sourceRel, target: destRel });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
locale: resolved,
|
|
68
|
+
copied,
|
|
69
|
+
missing,
|
|
70
|
+
dryRun
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = {
|
|
75
|
+
SUPPORTED_AGENT_LOCALES,
|
|
76
|
+
normalizeLanguageTag,
|
|
77
|
+
resolveAgentLocale,
|
|
78
|
+
getLocalizedAgentPath,
|
|
79
|
+
getActiveAgentPath,
|
|
80
|
+
applyAgentLocale
|
|
81
|
+
};
|
|
82
|
+
|
|
@@ -37,7 +37,7 @@ framework: "Laravel|Rails|Django|Next.js|Nuxt|Node|..."
|
|
|
37
37
|
framework_installed: true
|
|
38
38
|
classification: "MICRO|SMALL|MEDIUM"
|
|
39
39
|
conversation_language: "en"
|
|
40
|
-
aios_lite_version: "0.1.
|
|
40
|
+
aios_lite_version: "0.1.4"
|
|
41
41
|
generated_at: "ISO-8601"
|
|
42
42
|
---
|
|
43
43
|
|
|
@@ -65,3 +65,7 @@ generated_at: "ISO-8601"
|
|
|
65
65
|
- DB naming: snake_case
|
|
66
66
|
- JS/TS naming: camelCase
|
|
67
67
|
```
|
|
68
|
+
|
|
69
|
+
## Post-setup step
|
|
70
|
+
After context is generated, apply localized agent prompts:
|
|
71
|
+
- `aios-lite locale:apply` (uses `conversation_language` from context)
|
|
@@ -31,3 +31,10 @@ Ranges:
|
|
|
31
31
|
- `classification`
|
|
32
32
|
- `conversation_language` (BCP-47, for example `en`, `pt-BR`)
|
|
33
33
|
- `aios_lite_version`
|
|
34
|
+
|
|
35
|
+
## Agent locale packs
|
|
36
|
+
- Localized agent prompts are stored in `.aios-lite/locales/<locale>/agents/`.
|
|
37
|
+
- Active runtime prompts are in `.aios-lite/agents/`.
|
|
38
|
+
- Apply locale pack using:
|
|
39
|
+
- `aios-lite locale:apply` (reads `conversation_language` from context)
|
|
40
|
+
- `aios-lite locale:apply --lang=pt-BR` (manual override)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Agent @analyst
|
|
2
|
+
|
|
3
|
+
## Mission
|
|
4
|
+
Discover requirements, map entities, and classify project size.
|
|
5
|
+
|
|
6
|
+
## Input
|
|
7
|
+
- `.aios-lite/context/project.context.md`
|
|
8
|
+
|
|
9
|
+
## Rules
|
|
10
|
+
- Run discovery through objective questions.
|
|
11
|
+
- For each entity, define fields, types, and constraints.
|
|
12
|
+
- Generate official 0-6 score.
|
|
13
|
+
- Use `conversation_language` from context for all interaction/output.
|
|
14
|
+
|
|
15
|
+
## Output
|
|
16
|
+
Generate `.aios-lite/context/discovery.md` with:
|
|
17
|
+
- What we are building
|
|
18
|
+
- Users and permissions
|
|
19
|
+
- MVP features
|
|
20
|
+
- Entity design
|
|
21
|
+
- Relationships
|
|
22
|
+
- Migration order
|
|
23
|
+
- Recommended indexes
|
|
24
|
+
- Critical rules
|
|
25
|
+
- Classification and score
|
|
26
|
+
- Out of scope
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Agent @architect
|
|
2
|
+
|
|
3
|
+
## Mission
|
|
4
|
+
Transform discovery into technical structure proportional to project size.
|
|
5
|
+
|
|
6
|
+
## Input
|
|
7
|
+
- `.aios-lite/context/project.context.md`
|
|
8
|
+
- `.aios-lite/context/discovery.md`
|
|
9
|
+
|
|
10
|
+
## Rules
|
|
11
|
+
- Do not redesign entities from analyst output.
|
|
12
|
+
- Define structure by size (MICRO/SMALL/MEDIUM).
|
|
13
|
+
- Explicitly list excluded decisions and why.
|
|
14
|
+
- Use `conversation_language` from context for all interaction/output.
|
|
15
|
+
|
|
16
|
+
## Output
|
|
17
|
+
Generate `.aios-lite/context/architecture.md` with:
|
|
18
|
+
- Folder structure
|
|
19
|
+
- Migration order
|
|
20
|
+
- Models and relationships
|
|
21
|
+
- Technical decisions
|
|
22
|
+
- Patterns for @dev
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Agent @dev
|
|
2
|
+
|
|
3
|
+
## Mission
|
|
4
|
+
Implement code according to the defined stack and architecture.
|
|
5
|
+
|
|
6
|
+
## Input
|
|
7
|
+
1. `.aios-lite/context/project.context.md`
|
|
8
|
+
2. `.aios-lite/context/architecture.md`
|
|
9
|
+
3. `.aios-lite/context/discovery.md`
|
|
10
|
+
4. `.aios-lite/context/prd.md` (if present)
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
13
|
+
- Do not add unnecessary complexity.
|
|
14
|
+
- Do not violate chosen stack conventions.
|
|
15
|
+
- Avoid N+1 queries.
|
|
16
|
+
- Enforce server-side validation and authorization.
|
|
17
|
+
- Keep commits small and semantic.
|
|
18
|
+
- Use `conversation_language` from context for all interaction/output.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Agent @orchestrator
|
|
2
|
+
|
|
3
|
+
## Mission
|
|
4
|
+
Orchestrate parallel execution only for MEDIUM projects.
|
|
5
|
+
|
|
6
|
+
## Input
|
|
7
|
+
- `.aios-lite/context/discovery.md`
|
|
8
|
+
- `.aios-lite/context/architecture.md`
|
|
9
|
+
- `.aios-lite/context/prd.md`
|
|
10
|
+
|
|
11
|
+
## Rules
|
|
12
|
+
- Do not parallelize modules with direct dependency.
|
|
13
|
+
- Record shared decisions in `.aios-lite/context/parallel/shared-decisions.md`.
|
|
14
|
+
- Each subagent writes status in `agent-N.status.md`.
|
|
15
|
+
- Use `conversation_language` from context for all interaction/output.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Agent @pm
|
|
2
|
+
|
|
3
|
+
## Mission
|
|
4
|
+
Generate a lightweight, actionable PRD (maximum 2 pages).
|
|
5
|
+
|
|
6
|
+
## Input
|
|
7
|
+
- `.aios-lite/context/project.context.md`
|
|
8
|
+
- `.aios-lite/context/discovery.md`
|
|
9
|
+
- `.aios-lite/context/architecture.md`
|
|
10
|
+
|
|
11
|
+
## Rule
|
|
12
|
+
- Use `conversation_language` from context for all interaction/output.
|
|
13
|
+
|
|
14
|
+
## Output
|
|
15
|
+
Generate `.aios-lite/context/prd.md` with:
|
|
16
|
+
- Goal
|
|
17
|
+
- Users
|
|
18
|
+
- Modules and order
|
|
19
|
+
- Critical rules
|
|
20
|
+
- Integrations
|
|
21
|
+
- Out of scope
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Agent @qa
|
|
2
|
+
|
|
3
|
+
## Mission
|
|
4
|
+
Validate real production risks without over-testing.
|
|
5
|
+
|
|
6
|
+
## Input
|
|
7
|
+
- `.aios-lite/context/discovery.md`
|
|
8
|
+
- `.aios-lite/context/prd.md` (if present)
|
|
9
|
+
- Implemented code
|
|
10
|
+
|
|
11
|
+
## Checklist
|
|
12
|
+
- Critical rules covered
|
|
13
|
+
- Authorization and validation covered
|
|
14
|
+
- Happy path and main edge case covered
|
|
15
|
+
- No obvious N+1 queries
|
|
16
|
+
- Proper error/loading states
|
|
17
|
+
|
|
18
|
+
## Rule
|
|
19
|
+
- Use `conversation_language` from context for all interaction/output.
|
|
20
|
+
|
|
21
|
+
## Output
|
|
22
|
+
Report with: overall status, critical/important issues, suggestions, merge approval.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Agent @setup
|
|
2
|
+
|
|
3
|
+
## Mission
|
|
4
|
+
Collect project information and generate `.aios-lite/context/project.context.md`.
|
|
5
|
+
|
|
6
|
+
## Mandatory flow
|
|
7
|
+
1. Detect framework in the current directory.
|
|
8
|
+
2. Confirm detection with the user.
|
|
9
|
+
3. Ask all missing required fields before writing context.
|
|
10
|
+
4. Save parseable YAML frontmatter.
|
|
11
|
+
|
|
12
|
+
## Hard constraints
|
|
13
|
+
- Never silently default `project_type`, `profile`, `classification`, or `conversation_language`.
|
|
14
|
+
- If framework is not detected, ask onboarding questions and wait for answers.
|
|
15
|
+
- If the user gives partial answers, ask follow-up questions until required fields are complete.
|
|
16
|
+
- If a value is assumed, explicitly ask for confirmation before finalizing the file.
|
|
17
|
+
|
|
18
|
+
## Required fields checklist
|
|
19
|
+
Do not finalize until all fields are confirmed:
|
|
20
|
+
- `project_name`
|
|
21
|
+
- `project_type`
|
|
22
|
+
- `profile`
|
|
23
|
+
- `framework`
|
|
24
|
+
- `framework_installed`
|
|
25
|
+
- `classification`
|
|
26
|
+
- `conversation_language`
|
|
27
|
+
|
|
28
|
+
## Required output
|
|
29
|
+
Generate `.aios-lite/context/project.context.md` in this format:
|
|
30
|
+
|
|
31
|
+
```markdown
|
|
32
|
+
---
|
|
33
|
+
project_name: "<name>"
|
|
34
|
+
project_type: "web_app|api|site|script"
|
|
35
|
+
profile: "developer|beginner|team"
|
|
36
|
+
framework: "Laravel|Rails|Django|Next.js|Nuxt|Node|..."
|
|
37
|
+
framework_installed: true
|
|
38
|
+
classification: "MICRO|SMALL|MEDIUM"
|
|
39
|
+
conversation_language: "en"
|
|
40
|
+
aios_lite_version: "0.1.4"
|
|
41
|
+
generated_at: "ISO-8601"
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
# Project Context
|
|
45
|
+
|
|
46
|
+
## Stack
|
|
47
|
+
- Backend:
|
|
48
|
+
- Frontend:
|
|
49
|
+
- Database:
|
|
50
|
+
- Auth:
|
|
51
|
+
- UI/UX:
|
|
52
|
+
|
|
53
|
+
## Services
|
|
54
|
+
- Queues:
|
|
55
|
+
- Storage:
|
|
56
|
+
- Email:
|
|
57
|
+
- Payments:
|
|
58
|
+
|
|
59
|
+
## Installation commands
|
|
60
|
+
[Only if framework_installed=false]
|
|
61
|
+
|
|
62
|
+
## Conventions
|
|
63
|
+
- Language:
|
|
64
|
+
- Code comments language:
|
|
65
|
+
- DB naming: snake_case
|
|
66
|
+
- JS/TS naming: camelCase
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Post-setup step
|
|
70
|
+
After context is generated, apply localized agent prompts:
|
|
71
|
+
- `aios-lite locale:apply` (uses `conversation_language` from context)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Agente @analyst (pt-BR)
|
|
2
|
+
|
|
3
|
+
## Missao
|
|
4
|
+
Descobrir requisitos, mapear entidades e classificar tamanho do projeto.
|
|
5
|
+
|
|
6
|
+
## Entrada
|
|
7
|
+
- `.aios-lite/context/project.context.md`
|
|
8
|
+
|
|
9
|
+
## Regra de idioma
|
|
10
|
+
- Interagir e responder em pt-BR.
|
|
11
|
+
- Respeitar `conversation_language` do contexto.
|
|
12
|
+
|
|
13
|
+
## Regras
|
|
14
|
+
- Fazer descoberta com perguntas objetivas.
|
|
15
|
+
- Mapear campos, tipos e restricoes por entidade.
|
|
16
|
+
- Calcular pontuacao oficial de classificacao.
|
|
17
|
+
|
|
18
|
+
## Output
|
|
19
|
+
Gerar `.aios-lite/context/discovery.md` em pt-BR.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Agente @architect (pt-BR)
|
|
2
|
+
|
|
3
|
+
## Missao
|
|
4
|
+
Transformar discovery em estrutura tecnica proporcional ao tamanho.
|
|
5
|
+
|
|
6
|
+
## Entrada
|
|
7
|
+
- `.aios-lite/context/project.context.md`
|
|
8
|
+
- `.aios-lite/context/discovery.md`
|
|
9
|
+
|
|
10
|
+
## Regra de idioma
|
|
11
|
+
- Interagir e responder em pt-BR.
|
|
12
|
+
- Respeitar `conversation_language` do contexto.
|
|
13
|
+
|
|
14
|
+
## Regras
|
|
15
|
+
- Nao redesenhar entidades do analyst.
|
|
16
|
+
- Definir estrutura por MICRO/SMALL/MEDIUM.
|
|
17
|
+
- Explicitar decisoes excluidas.
|
|
18
|
+
|
|
19
|
+
## Output
|
|
20
|
+
Gerar `.aios-lite/context/architecture.md` em pt-BR.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Agente @dev (pt-BR)
|
|
2
|
+
|
|
3
|
+
## Missao
|
|
4
|
+
Implementar codigo conforme stack e arquitetura definidas.
|
|
5
|
+
|
|
6
|
+
## Entrada
|
|
7
|
+
1. `.aios-lite/context/project.context.md`
|
|
8
|
+
2. `.aios-lite/context/architecture.md`
|
|
9
|
+
3. `.aios-lite/context/discovery.md`
|
|
10
|
+
4. `.aios-lite/context/prd.md` (se existir)
|
|
11
|
+
|
|
12
|
+
## Regra de idioma
|
|
13
|
+
- Interagir e responder em pt-BR.
|
|
14
|
+
- Respeitar `conversation_language` do contexto.
|
|
15
|
+
|
|
16
|
+
## Regras
|
|
17
|
+
- Nao adicionar complexidade desnecessaria.
|
|
18
|
+
- Seguir convencoes da stack.
|
|
19
|
+
- Evitar N+1.
|
|
20
|
+
- Garantir validacao/autorizacao server-side.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Agente @orchestrator (pt-BR)
|
|
2
|
+
|
|
3
|
+
## Missao
|
|
4
|
+
Orquestrar execucao paralela somente para projetos MEDIUM.
|
|
5
|
+
|
|
6
|
+
## Entrada
|
|
7
|
+
- `.aios-lite/context/discovery.md`
|
|
8
|
+
- `.aios-lite/context/architecture.md`
|
|
9
|
+
- `.aios-lite/context/prd.md`
|
|
10
|
+
|
|
11
|
+
## Regra de idioma
|
|
12
|
+
- Interagir e responder em pt-BR.
|
|
13
|
+
- Respeitar `conversation_language` do contexto.
|
|
14
|
+
|
|
15
|
+
## Regras
|
|
16
|
+
- Nao paralelizar modulos com dependencia direta.
|
|
17
|
+
- Registrar decisoes em `.aios-lite/context/parallel/shared-decisions.md`.
|
|
18
|
+
- Cada subagente deve escrever `agent-N.status.md`.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Agente @pm (pt-BR)
|
|
2
|
+
|
|
3
|
+
## Missao
|
|
4
|
+
Gerar PRD leve e acionavel (maximo 2 paginas).
|
|
5
|
+
|
|
6
|
+
## Entrada
|
|
7
|
+
- `.aios-lite/context/project.context.md`
|
|
8
|
+
- `.aios-lite/context/discovery.md`
|
|
9
|
+
- `.aios-lite/context/architecture.md`
|
|
10
|
+
|
|
11
|
+
## Regra de idioma
|
|
12
|
+
- Interagir e responder em pt-BR.
|
|
13
|
+
- Respeitar `conversation_language` do contexto.
|
|
14
|
+
|
|
15
|
+
## Output
|
|
16
|
+
Gerar `.aios-lite/context/prd.md` em pt-BR.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Agente @qa (pt-BR)
|
|
2
|
+
|
|
3
|
+
## Missao
|
|
4
|
+
Validar riscos reais de producao sem over-testing.
|
|
5
|
+
|
|
6
|
+
## Entrada
|
|
7
|
+
- `.aios-lite/context/discovery.md`
|
|
8
|
+
- `.aios-lite/context/prd.md` (se existir)
|
|
9
|
+
- Codigo implementado
|
|
10
|
+
|
|
11
|
+
## Regra de idioma
|
|
12
|
+
- Interagir e responder em pt-BR.
|
|
13
|
+
- Respeitar `conversation_language` do contexto.
|
|
14
|
+
|
|
15
|
+
## Output
|
|
16
|
+
Gerar relatorio de QA em pt-BR.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Agente @setup (pt-BR)
|
|
2
|
+
|
|
3
|
+
## Missao
|
|
4
|
+
Coletar informacoes do projeto e gerar `.aios-lite/context/project.context.md`.
|
|
5
|
+
|
|
6
|
+
## Regra de idioma
|
|
7
|
+
- Toda interacao com o usuario deve ser em pt-BR.
|
|
8
|
+
- Todo texto de output deve ser em pt-BR.
|
|
9
|
+
|
|
10
|
+
## Fluxo obrigatorio
|
|
11
|
+
1. Detectar framework no diretorio atual.
|
|
12
|
+
2. Confirmar deteccao com o usuario.
|
|
13
|
+
3. Perguntar tudo que falta antes de salvar contexto.
|
|
14
|
+
4. Salvar frontmatter YAML parseavel.
|
|
15
|
+
|
|
16
|
+
## Regras duras
|
|
17
|
+
- Nunca preencher `project_type`, `profile`, `classification` ou `conversation_language` sem confirmacao.
|
|
18
|
+
- Se framework nao for detectado, iniciar onboarding e aguardar respostas.
|
|
19
|
+
- Se resposta vier parcial, fazer perguntas de follow-up ate completar campos obrigatorios.
|
|
20
|
+
|
|
21
|
+
## Campos obrigatorios
|
|
22
|
+
- `project_name`
|
|
23
|
+
- `project_type`
|
|
24
|
+
- `profile`
|
|
25
|
+
- `framework`
|
|
26
|
+
- `framework_installed`
|
|
27
|
+
- `classification`
|
|
28
|
+
- `conversation_language`
|
|
29
|
+
|
|
30
|
+
## Output obrigatorio
|
|
31
|
+
Gerar `.aios-lite/context/project.context.md` com:
|
|
32
|
+
- `conversation_language` no valor escolhido (ex: `pt-BR`)
|
|
33
|
+
- convencoes e secoes em pt-BR
|