@openlife/cli 1.7.4 → 1.7.6
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 +186 -0
- package/CODE_OF_CONDUCT.md +31 -0
- package/CONTRIBUTING.md +133 -0
- package/README.md +25 -9
- package/dist/cli/InstallModules.js +37 -0
- package/dist/cli/InstallWizard.js +46 -8
- package/dist/index.js +11 -0
- package/dist/test_install_wizard.js +86 -21
- package/docs/getting-started.md +137 -0
- package/package.json +11 -2
- package/docs/CHANGELOG_FEATURE_ROLLOUT_DESIGNMD.md +0 -43
- package/docs/EXTERNAL_SOURCES_AND_SECURITY_GUARD.md +0 -33
- package/docs/OPENLIFE_AUDIT_2026-05-06.md +0 -170
- package/docs/OPENLIFE_CONSOLIDATED_PLAN_2026-05-06.md +0 -299
- package/docs/OPENLIFE_DUAL_MODE_IMPLEMENTATION_PLAN.md +0 -205
- package/docs/OPENLIFE_EVOLUTION_SURFACE_2026-05-07.md +0 -53
- package/docs/OPENLIFE_SKILLS_IMPORT_2026-05-07.json +0 -223
- package/docs/OPENLIFE_SQUADS_IMPORT_2026-05-07.json +0 -184
- package/docs/PAPERCLIP_OPENLIFE_INVESTIGATION.md +0 -85
- package/docs/RELEASE_ORGANIZATION_PLAN.md +0 -164
- package/docs/audit/CLI-EXECUTION-RESULTS.md +0 -113
- package/docs/audit/CLI-MATRIX.md +0 -556
- package/docs/audit/DOC-PARITY-GAPS.md +0 -351
- package/docs/audit/ORCHESTRATOR-MATRIX.md +0 -136
- package/docs/audit/TEST-COVERAGE-GAPS.md +0 -334
- package/docs/audit/integrations/SKIPPED.md +0 -101
- package/docs/autonomous-install.md +0 -79
- package/docs/capability-genesis.md +0 -137
- package/docs/capability-pack-schema.md +0 -157
- package/docs/commands.md +0 -82
- package/docs/deep-research-capability.md +0 -114
- package/docs/development/typescript-conventions.md +0 -95
- package/docs/host-installers.md +0 -68
- package/docs/install/aiobuilder.md +0 -70
- package/docs/install/claude-code.md +0 -83
- package/docs/install/codex.md +0 -64
- package/docs/install/gemini-cli.md +0 -64
- package/docs/install/runtime-profiles.md +0 -83
- package/docs/openlife-agent-os-blueprint.md +0 -114
- package/docs/openlife-install-backlog.md +0 -115
- package/docs/openlife-install-spec.md +0 -306
- package/docs/operations/CLOUD_CUTOVER_AUDIT.md +0 -37
- package/docs/operations/PHASE_PROGRESS_CONTINUATION.md +0 -24
- package/docs/performance-benchmarks.md +0 -83
- package/docs/planning/v1.3-capability-genesis.md +0 -157
- package/docs/plans/2026-05-05-admin-interface-professional-dark-premium-plan.md +0 -84
- package/docs/plans/2026-05-05-openlife-autonomous-domain-marketplace-masterplan.md +0 -122
- package/docs/roadmap/OPENLIFE_MASTER_PLAN_CLOUD_V3.md +0 -97
- package/docs/sandboxing-research.md +0 -117
- package/docs/stories/epic-feature-audit/1.1.story.md +0 -84
- package/docs/stories/epic-feature-audit/1.2.story.md +0 -102
- package/docs/stories/epic-feature-audit/1.3.story.md +0 -93
- package/docs/stories/epic-feature-audit/1.5.story.md +0 -121
- package/docs/stories/epic-feature-audit/1.6.story.md +0 -80
- package/docs/stories/epic-feature-completeness/2.1.story.md +0 -70
- package/docs/stories/epic-feature-completeness/2.2.story.md +0 -49
- package/docs/stories/epic-feature-completeness/2.3.story.md +0 -74
- package/docs/stories/epic-feature-completeness/2.4.story.md +0 -71
- package/docs/stories/epic-feature-completeness/3.1.story.md +0 -56
- package/docs/stories/epic-feature-completeness/3.2.story.md +0 -80
- package/docs/stories/epic-feature-completeness/3.3.story.md +0 -68
- package/docs/stories/epic-feature-completeness/3.4.story.md +0 -71
- package/docs/stories/epic-feature-completeness/3.5.story.md +0 -72
- package/docs/stories/epic-feature-completeness/3.6.story.md +0 -69
- package/docs/stories/epic-feature-completeness/3.7.story.md +0 -68
- package/docs/stories/epic-feature-completeness/3.8.story.md +0 -57
- package/docs/v1.4-changelog.md +0 -159
- package/docs/v1.5-changelog.md +0 -106
- package/docs/v1.5-roadmap.md +0 -121
- package/docs/v1.6-changelog.md +0 -67
- package/docs/v1.6-roadmap.md +0 -89
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
// Uses CannedAnswerProvider so no real stdin/tty is required.
|
|
4
4
|
//
|
|
5
5
|
// Question order in wizard.run() (when no pre-existing install):
|
|
6
|
-
// 1) profile (choice: 0=framework, 1=autonomous)
|
|
6
|
+
// 1) profile (choice: 0=framework, 1=autonomous, 2=both)
|
|
7
7
|
// 2) host (choice: 0=claude-code, 1=gemini-cli, 2=codex)
|
|
8
|
-
// 3)
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
8
|
+
// 3) wantsApiKeys (yesNo)
|
|
9
|
+
// 3a-d) [if Y] OPENAI / ANTHROPIC / GEMINI / OPENROUTER pastes (text)
|
|
10
|
+
// 4) wantsOAuth (yesNo)
|
|
11
|
+
// 5) model order (text: blank or comma list)
|
|
12
|
+
// 6) telegram? (yesNo, autonomous only)
|
|
13
|
+
// 7) skip doctor? (yesNo)
|
|
14
|
+
// 8) confirm preview (yesNo)
|
|
12
15
|
//
|
|
13
16
|
// When pre-existing install detected, an extra choice prompt fires FIRST:
|
|
14
17
|
// 0) abort 1) reinstall 2) repair
|
|
@@ -76,8 +79,8 @@ function writeExistingInstall(root) {
|
|
|
76
79
|
async function scenario1HappyPathFrameworkClaudeCode() {
|
|
77
80
|
const root = tempRoot();
|
|
78
81
|
try {
|
|
79
|
-
// profile=framework(0), host=claude-code(0), models='', skipDoctor=false, confirm=true
|
|
80
|
-
const provider = new InstallWizard_1.CannedAnswerProvider([0, 0, '', false, true]);
|
|
82
|
+
// profile=framework(0), host=claude-code(0), apiKeys=N, oauth=N, models='', skipDoctor=false, confirm=true
|
|
83
|
+
const provider = new InstallWizard_1.CannedAnswerProvider([0, 0, false, false, '', false, true]);
|
|
81
84
|
const wizard = new InstallWizard_1.InstallWizard(root, provider);
|
|
82
85
|
const result = await wizard.run();
|
|
83
86
|
assert(result.ok === true, 'scenario1: expected ok=true');
|
|
@@ -88,7 +91,8 @@ async function scenario1HappyPathFrameworkClaudeCode() {
|
|
|
88
91
|
assert(result.options.skipDoctor === false, 'scenario1: skipDoctor should be false');
|
|
89
92
|
assert(result.options.modelOrder === undefined, 'scenario1: modelOrder should be undefined when blank');
|
|
90
93
|
assert(result.preExistingAction === undefined, 'scenario1: no pre-existing action expected');
|
|
91
|
-
|
|
94
|
+
// SKIPPED_API_KEYS warning is expected when wantsApiKeys=false
|
|
95
|
+
assert(Array.isArray(result.warnings) && result.warnings.some((w) => w.includes('SKIPPED_API_KEYS')), 'scenario1: should warn SKIPPED_API_KEYS when api-key prompt skipped');
|
|
92
96
|
console.log('✅ scenario 1: happy path framework + claude-code');
|
|
93
97
|
}
|
|
94
98
|
finally {
|
|
@@ -98,8 +102,8 @@ async function scenario1HappyPathFrameworkClaudeCode() {
|
|
|
98
102
|
async function scenario2HappyPathAutonomousClaudeCode() {
|
|
99
103
|
const root = tempRoot();
|
|
100
104
|
try {
|
|
101
|
-
// profile=autonomous(1), host=claude-code(0), models='', telegram=true, skipDoctor=false, confirm=true
|
|
102
|
-
const provider = new InstallWizard_1.CannedAnswerProvider([1, 0, '', true, false, true]);
|
|
105
|
+
// profile=autonomous(1), host=claude-code(0), apiKeys=N, oauth=N, models='', telegram=true, skipDoctor=false, confirm=true
|
|
106
|
+
const provider = new InstallWizard_1.CannedAnswerProvider([1, 0, false, false, '', true, false, true]);
|
|
103
107
|
const wizard = new InstallWizard_1.InstallWizard(root, provider);
|
|
104
108
|
const result = await wizard.run();
|
|
105
109
|
assert(result.ok === true, 'scenario2: expected ok=true');
|
|
@@ -107,7 +111,8 @@ async function scenario2HappyPathAutonomousClaudeCode() {
|
|
|
107
111
|
return;
|
|
108
112
|
assert(result.options.profile === 'autonomous', 'scenario2: profile should be autonomous');
|
|
109
113
|
assert(result.options.host === 'claude-code', 'scenario2: host should be claude-code');
|
|
110
|
-
|
|
114
|
+
// SKIPPED_API_KEYS warning is expected when wantsApiKeys=false
|
|
115
|
+
assert(Array.isArray(result.warnings) && result.warnings.some((w) => w.includes('SKIPPED_API_KEYS')), 'scenario2: should warn SKIPPED_API_KEYS when api-key prompt skipped');
|
|
111
116
|
console.log('✅ scenario 2: happy path autonomous + claude-code');
|
|
112
117
|
}
|
|
113
118
|
finally {
|
|
@@ -117,8 +122,8 @@ async function scenario2HappyPathAutonomousClaudeCode() {
|
|
|
117
122
|
async function scenario3UserAbortsOnConfirm() {
|
|
118
123
|
const root = tempRoot();
|
|
119
124
|
try {
|
|
120
|
-
// framework, claude-code, blank models, skipDoctor=false, confirm=false (abort)
|
|
121
|
-
const provider = new InstallWizard_1.CannedAnswerProvider([0, 0, '', false, false]);
|
|
125
|
+
// framework, claude-code, apiKeys=N, oauth=N, blank models, skipDoctor=false, confirm=false (abort)
|
|
126
|
+
const provider = new InstallWizard_1.CannedAnswerProvider([0, 0, false, false, '', false, false]);
|
|
122
127
|
const wizard = new InstallWizard_1.InstallWizard(root, provider);
|
|
123
128
|
const result = await wizard.run();
|
|
124
129
|
assert(result.ok === false, 'scenario3: expected ok=false');
|
|
@@ -156,8 +161,8 @@ async function scenario5PreExistingRepair() {
|
|
|
156
161
|
const root = tempRoot();
|
|
157
162
|
try {
|
|
158
163
|
writeExistingInstall(root);
|
|
159
|
-
// 2=repair, then full flow: framework, claude-code, '', skipDoctor=false, confirm=true
|
|
160
|
-
const provider = new InstallWizard_1.CannedAnswerProvider([2, 0, 0, '', false, true]);
|
|
164
|
+
// 2=repair, then full flow: framework, claude-code, apiKeys=N, oauth=N, '', skipDoctor=false, confirm=true
|
|
165
|
+
const provider = new InstallWizard_1.CannedAnswerProvider([2, 0, 0, false, false, '', false, true]);
|
|
161
166
|
const wizard = new InstallWizard_1.InstallWizard(root, provider);
|
|
162
167
|
const result = await wizard.run();
|
|
163
168
|
assert(result.ok === true, 'scenario5: expected ok=true');
|
|
@@ -175,8 +180,8 @@ async function scenario6PreExistingReinstall() {
|
|
|
175
180
|
const root = tempRoot();
|
|
176
181
|
try {
|
|
177
182
|
writeExistingInstall(root);
|
|
178
|
-
// 1=reinstall, framework, claude-code, '', skipDoctor=false, confirm=true
|
|
179
|
-
const provider = new InstallWizard_1.CannedAnswerProvider([1, 0, 0, '', false, true]);
|
|
183
|
+
// 1=reinstall, framework, claude-code, apiKeys=N, oauth=N, '', skipDoctor=false, confirm=true
|
|
184
|
+
const provider = new InstallWizard_1.CannedAnswerProvider([1, 0, 0, false, false, '', false, true]);
|
|
180
185
|
const wizard = new InstallWizard_1.InstallWizard(root, provider);
|
|
181
186
|
const result = await wizard.run();
|
|
182
187
|
assert(result.ok === true, 'scenario6: expected ok=true');
|
|
@@ -192,8 +197,8 @@ async function scenario6PreExistingReinstall() {
|
|
|
192
197
|
async function scenario7UnsupportedHostGeminiCli() {
|
|
193
198
|
const root = tempRoot();
|
|
194
199
|
try {
|
|
195
|
-
// framework, host=1 (gemini-cli, not yet supported), blank models, skipDoctor=false, confirm=true
|
|
196
|
-
const provider = new InstallWizard_1.CannedAnswerProvider([0, 1, '', false, true]);
|
|
200
|
+
// framework, host=1 (gemini-cli, not yet supported), apiKeys=N, oauth=N, blank models, skipDoctor=false, confirm=true
|
|
201
|
+
const provider = new InstallWizard_1.CannedAnswerProvider([0, 1, false, false, '', false, true]);
|
|
197
202
|
const wizard = new InstallWizard_1.InstallWizard(root, provider);
|
|
198
203
|
const result = await wizard.run();
|
|
199
204
|
assert(result.ok === true, 'scenario7: expected ok=true even with unsupported host');
|
|
@@ -212,8 +217,8 @@ async function scenario8CustomModelChain() {
|
|
|
212
217
|
const root = tempRoot();
|
|
213
218
|
try {
|
|
214
219
|
const models = 'gemini-api/gemini-3.1-pro-preview,openai-api/gpt-5.4-mini';
|
|
215
|
-
// framework, claude-code, models=custom, skipDoctor=false, confirm=true
|
|
216
|
-
const provider = new InstallWizard_1.CannedAnswerProvider([0, 0, models, false, true]);
|
|
220
|
+
// framework, claude-code, apiKeys=N, oauth=N, models=custom, skipDoctor=false, confirm=true
|
|
221
|
+
const provider = new InstallWizard_1.CannedAnswerProvider([0, 0, false, false, models, false, true]);
|
|
217
222
|
const wizard = new InstallWizard_1.InstallWizard(root, provider);
|
|
218
223
|
const result = await wizard.run();
|
|
219
224
|
assert(result.ok === true, 'scenario8: expected ok=true');
|
|
@@ -252,6 +257,64 @@ async function scenario9OutOfAnswersThrows() {
|
|
|
252
257
|
cleanup(root);
|
|
253
258
|
}
|
|
254
259
|
}
|
|
260
|
+
async function scenario10WithApiKeysPersists() {
|
|
261
|
+
const root = tempRoot();
|
|
262
|
+
try {
|
|
263
|
+
// framework, claude-code, apiKeys=Y, paste 4 keys (openai+anthropic, skip gemini+openrouter),
|
|
264
|
+
// oauth=N, blank models, skipDoctor=false, confirm=true
|
|
265
|
+
const provider = new InstallWizard_1.CannedAnswerProvider([
|
|
266
|
+
0, 0,
|
|
267
|
+
true, // wantsApiKeys
|
|
268
|
+
'openai-test-key', // openai paste (non-secret test fixture)
|
|
269
|
+
'anthropic-test-key', // anthropic paste (non-secret test fixture)
|
|
270
|
+
'', // gemini skip
|
|
271
|
+
'', // openrouter skip
|
|
272
|
+
false, // wantsOAuth
|
|
273
|
+
'', // models
|
|
274
|
+
false, // skipDoctor
|
|
275
|
+
true, // confirm
|
|
276
|
+
]);
|
|
277
|
+
const wizard = new InstallWizard_1.InstallWizard(root, provider);
|
|
278
|
+
const result = await wizard.run();
|
|
279
|
+
assert(result.ok === true, 'scenario10: expected ok=true');
|
|
280
|
+
if (!result.ok)
|
|
281
|
+
return;
|
|
282
|
+
// .env should contain the pasted keys
|
|
283
|
+
const envPath = path.join(root, '.env');
|
|
284
|
+
assert(fs.existsSync(envPath), 'scenario10: .env should exist after wizard');
|
|
285
|
+
const envContent = fs.readFileSync(envPath, 'utf-8');
|
|
286
|
+
assert(envContent.includes('OPENAI_API_KEY=openai-test-key'), 'scenario10: .env should have OPENAI_API_KEY');
|
|
287
|
+
assert(envContent.includes('ANTHROPIC_API_KEY=anthropic-test-key'), 'scenario10: .env should have ANTHROPIC_API_KEY');
|
|
288
|
+
assert(!envContent.includes('GEMINI_API_KEY='), 'scenario10: .env should NOT have GEMINI_API_KEY (skipped)');
|
|
289
|
+
// SKIPPED_API_KEYS warning should NOT fire when at least one key was provided
|
|
290
|
+
if (result.warnings) {
|
|
291
|
+
assert(!result.warnings.some((w) => w.includes('SKIPPED_API_KEYS')), 'scenario10: should NOT warn SKIPPED_API_KEYS when keys were provided');
|
|
292
|
+
}
|
|
293
|
+
console.log('✅ scenario 10: API keys collected and persisted to .env');
|
|
294
|
+
}
|
|
295
|
+
finally {
|
|
296
|
+
cleanup(root);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
async function scenario11ProfileBothMapsToAutonomous() {
|
|
300
|
+
const root = tempRoot();
|
|
301
|
+
try {
|
|
302
|
+
// profile=both(2), claude-code, apiKeys=N, oauth=N, models='', telegram=true (autonomous path),
|
|
303
|
+
// skipDoctor=false, confirm=true
|
|
304
|
+
const provider = new InstallWizard_1.CannedAnswerProvider([2, 0, false, false, '', true, false, true]);
|
|
305
|
+
const wizard = new InstallWizard_1.InstallWizard(root, provider);
|
|
306
|
+
const result = await wizard.run();
|
|
307
|
+
assert(result.ok === true, 'scenario11: expected ok=true');
|
|
308
|
+
if (!result.ok)
|
|
309
|
+
return;
|
|
310
|
+
assert(result.options.profile === 'autonomous', 'scenario11: profile=both should map internally to autonomous');
|
|
311
|
+
assert(Array.isArray(result.warnings) && result.warnings.some((w) => w.includes('INSTALLING_BOTH')), 'scenario11: should emit INSTALLING_BOTH warning so caller knows both layers were intended');
|
|
312
|
+
console.log('✅ scenario 11: profile=both maps to autonomous with INSTALLING_BOTH warning');
|
|
313
|
+
}
|
|
314
|
+
finally {
|
|
315
|
+
cleanup(root);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
255
318
|
async function main() {
|
|
256
319
|
console.log('🧪 test_install_wizard — Story 3.5 regression suite');
|
|
257
320
|
await scenario1HappyPathFrameworkClaudeCode();
|
|
@@ -263,6 +326,8 @@ async function main() {
|
|
|
263
326
|
await scenario7UnsupportedHostGeminiCli();
|
|
264
327
|
await scenario8CustomModelChain();
|
|
265
328
|
await scenario9OutOfAnswersThrows();
|
|
329
|
+
await scenario10WithApiKeysPersists();
|
|
330
|
+
await scenario11ProfileBothMapsToAutonomous();
|
|
266
331
|
console.log('');
|
|
267
332
|
console.log('TEST_INSTALL_WIZARD_OK');
|
|
268
333
|
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
A 5-minute walkthrough to get OpenLife CLI running on your machine.
|
|
4
|
+
|
|
5
|
+
## 1. Install globally
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @openlife/cli
|
|
9
|
+
openlife --version
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
You should see the current version (matching the npm tag).
|
|
13
|
+
|
|
14
|
+
## 2. Run the wizard
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
openlife init
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The wizard prints the OpenLife banner, then walks you through:
|
|
21
|
+
|
|
22
|
+
1. **Profile** — choose `framework` (CLI only), `autonomous` (daemon),
|
|
23
|
+
or `both`. `both` installs the autonomous profile, which includes
|
|
24
|
+
the framework layer.
|
|
25
|
+
2. **Host** — `claude-code`, `gemini-cli`, or `codex`. Auto-detected
|
|
26
|
+
when you launch `openlife init` from inside one of these CLIs.
|
|
27
|
+
3. **API keys** — paste your `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`,
|
|
28
|
+
`GEMINI_API_KEY`, and/or `OPENROUTER_API_KEY`. Press Enter to skip
|
|
29
|
+
any one. Keys are saved to `.env` in the project directory.
|
|
30
|
+
4. **OAuth pointer** — answer `y` if you plan to use `openlife auth
|
|
31
|
+
gemini` or `openlife auth openai` later. The wizard does not start
|
|
32
|
+
the OAuth flow itself; it just reminds you to run those commands
|
|
33
|
+
after init completes.
|
|
34
|
+
5. **Model chain** — comma-separated `provider/model` list, e.g.
|
|
35
|
+
`openai-api/gpt-5.4-mini,anthropic-api/claude-sonnet-4-6`. Leave
|
|
36
|
+
blank to accept the defaults from `models.json`.
|
|
37
|
+
6. **Telegram** (autonomous only) — confirm whether `TELEGRAM_BOT_TOKEN`
|
|
38
|
+
and `OPENLIFE_TELEGRAM_ALLOWED_USER_ID` are already in `.env`.
|
|
39
|
+
7. **Doctor** — answer `n` to run system diagnostics after install.
|
|
40
|
+
8. **Confirm** — review the summary and answer `Y` to proceed.
|
|
41
|
+
|
|
42
|
+
When the wizard finishes you should see:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
✅ OpenLife ready.
|
|
46
|
+
|
|
47
|
+
Try:
|
|
48
|
+
openlife ask "hello, what can you do?"
|
|
49
|
+
openlife status
|
|
50
|
+
openlife --help
|
|
51
|
+
|
|
52
|
+
Docs: https://github.com/GOOODZ/openlife-core
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 3. Try your first command
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
openlife ask "summarize this README in one sentence"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
OpenLife will route the request to the highest-priority model in your
|
|
62
|
+
chain that has a working key. If no API key is configured, it falls
|
|
63
|
+
back to local Ollama (if available) or returns an error.
|
|
64
|
+
|
|
65
|
+
## 4. Common follow-ups
|
|
66
|
+
|
|
67
|
+
- **Set up OAuth (no API key needed):**
|
|
68
|
+
```bash
|
|
69
|
+
openlife auth gemini # browser-based Google login
|
|
70
|
+
openlife auth openai # browser-based OpenAI login
|
|
71
|
+
```
|
|
72
|
+
- **Start the autonomous daemon (autonomous profile):**
|
|
73
|
+
```bash
|
|
74
|
+
openlife start --daemon
|
|
75
|
+
```
|
|
76
|
+
- **Inspect runtime state:**
|
|
77
|
+
```bash
|
|
78
|
+
ls .openlife/
|
|
79
|
+
cat .openlife/heartbeat.json
|
|
80
|
+
cat .openlife/install-manifest.json
|
|
81
|
+
```
|
|
82
|
+
- **Update to latest version:**
|
|
83
|
+
```bash
|
|
84
|
+
npm install -g @openlife/cli@latest
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Troubleshooting
|
|
88
|
+
|
|
89
|
+
### `openlife: command not found` after install
|
|
90
|
+
|
|
91
|
+
The global npm bin directory is probably not on your `PATH`. Run:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npm bin -g
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Add that path to your shell profile (`~/.bashrc`, `~/.zshrc`).
|
|
98
|
+
|
|
99
|
+
### `npm install -g` says EEXIST
|
|
100
|
+
|
|
101
|
+
You have a leftover symlink from a previous `npm link`. Run:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm unlink -g @openlife/cli
|
|
105
|
+
rm -f $(which openlife)
|
|
106
|
+
npm install -g @openlife/cli
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### `openlife ask` fails with `MODEL_TIMEOUT` or `no provider available`
|
|
110
|
+
|
|
111
|
+
No API key is configured and no fallback (Ollama, OAuth) is wired up.
|
|
112
|
+
Either:
|
|
113
|
+
|
|
114
|
+
- Edit `.env` to add `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or
|
|
115
|
+
`GEMINI_API_KEY`, then retry, or
|
|
116
|
+
- Run `openlife auth gemini` / `openlife auth openai` to use OAuth, or
|
|
117
|
+
- Start a local Ollama server (`ollama serve`) and set
|
|
118
|
+
`OPENLIFE_ENABLE_OLLAMA=true` in `.env`.
|
|
119
|
+
|
|
120
|
+
### Telegram autonomous mode reports `TELEGRAM_NOT_CONFIGURED`
|
|
121
|
+
|
|
122
|
+
Set both in `.env`:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
TELEGRAM_BOT_TOKEN=<from BotFather>
|
|
126
|
+
OPENLIFE_TELEGRAM_ALLOWED_USER_ID=<your Telegram user id>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Then restart with `openlife start --daemon`.
|
|
130
|
+
|
|
131
|
+
## Where to go next
|
|
132
|
+
|
|
133
|
+
- [INSTALL.md](../INSTALL.md) — full install options including
|
|
134
|
+
non-interactive (`openlife system setup`) for CI use.
|
|
135
|
+
- [README.md](../README.md) — feature overview and architecture.
|
|
136
|
+
- [CHANGELOG.md](../CHANGELOG.md) — what changed across versions.
|
|
137
|
+
- [CONTRIBUTING.md](../CONTRIBUTING.md) — dev setup and conventions.
|
package/package.json
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openlife/cli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.6",
|
|
4
4
|
"description": "OPEN-LIFE Córtex Orquestrador Dual-Core",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
8
8
|
"bin",
|
|
9
9
|
"scripts",
|
|
10
|
-
"docs",
|
|
11
10
|
"dist-templates",
|
|
11
|
+
"docs/README.md",
|
|
12
|
+
"docs/quickstart.md",
|
|
13
|
+
"docs/getting-started.md",
|
|
14
|
+
"docs/workflow-schema.md",
|
|
15
|
+
"docs/toolset-enforcement.md",
|
|
16
|
+
"docs/release-process.md",
|
|
17
|
+
"docs/v1.7-changelog.md",
|
|
18
|
+
"CHANGELOG.md",
|
|
12
19
|
"LICENSE",
|
|
13
20
|
"README.md",
|
|
14
21
|
"INSTALL.md",
|
|
22
|
+
"CONTRIBUTING.md",
|
|
23
|
+
"CODE_OF_CONDUCT.md",
|
|
15
24
|
"package.json"
|
|
16
25
|
],
|
|
17
26
|
"repository": {
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# OpenLife Feature Rollout Changelog (Dual Mode + Reversa + DesignMD)
|
|
2
|
-
|
|
3
|
-
## Completed in this cycle
|
|
4
|
-
|
|
5
|
-
### Core execution
|
|
6
|
-
- Dual mode persisted in mission lifecycle (`task` default, `service` explicit)
|
|
7
|
-
- Formal job lifecycle with events (`enqueued/claimed/started/completed/failed/blocked`)
|
|
8
|
-
- Destructive guardrails enforced (delete/remove/erase requires explicit consent)
|
|
9
|
-
|
|
10
|
-
### Service operations
|
|
11
|
-
- CLI operations: `service status/pause/resume/events`
|
|
12
|
-
- Task introspection: `task status`
|
|
13
|
-
- Budget hard-stop -> service paused + event log
|
|
14
|
-
|
|
15
|
-
### Workspace foundations
|
|
16
|
-
- Workspace-aware artifacts path under `.artifacts/workspaces/<workspaceId>/...`
|
|
17
|
-
- Service state/events now namespaced by workspace
|
|
18
|
-
|
|
19
|
-
### Runtime and orchestration
|
|
20
|
-
- Runtime registry probe/list baseline
|
|
21
|
-
- Teammate board baseline (owner/status/blockers/comments)
|
|
22
|
-
- Learning loop baseline (governed skill candidates)
|
|
23
|
-
|
|
24
|
-
### Reversa and DesignMD
|
|
25
|
-
- Reversa state now supports mode metadata (`default` | `designmd`)
|
|
26
|
-
- New mode setter in Reversa (`setMode`)
|
|
27
|
-
- New `DesignMdMode` manager to apply/design profile and write root `DESIGN.md`
|
|
28
|
-
- CLI surface:
|
|
29
|
-
- `reversa mode --set <default|designmd> --profile <id>`
|
|
30
|
-
- `designmd status`
|
|
31
|
-
- `designmd apply <profileId> <source> <title> <designPath>`
|
|
32
|
-
- `aiobuilder mode --set <default|designmd> --profile <id>`
|
|
33
|
-
|
|
34
|
-
## Validation status
|
|
35
|
-
- TypeScript build: passing
|
|
36
|
-
- Automated tests passing for dual mode, guardrails, lifecycle, runtime, reversa-lite, service CLI, teammate/learning
|
|
37
|
-
|
|
38
|
-
## Next integration step (pending your references/models)
|
|
39
|
-
1. Add importer for Awesome DESIGN.md catalog profile manifests
|
|
40
|
-
2. Add profile templates bundle under `design/profiles/`
|
|
41
|
-
3. Wire Reversa generation phase to enforce active DesignMD profile tokens
|
|
42
|
-
4. Wire AIOBUILDER scaffolding prompts to DesignMD profile context
|
|
43
|
-
5. Add regression tests for DesignMD profile switching and output consistency
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# OpenLife External Sources & Security Guard
|
|
2
|
-
|
|
3
|
-
## New source catalog commands
|
|
4
|
-
- `openlife sources list`
|
|
5
|
-
- `openlife sources guard-check <url>`
|
|
6
|
-
- `openlife sources scaffold <type> <id> --notes "..."`
|
|
7
|
-
|
|
8
|
-
## Autonomous creation baselines (local)
|
|
9
|
-
- `openlife agents create <id> --role <role> --notes "..."`
|
|
10
|
-
- `openlife squads create <id> --domain <domain> --notes "..."`
|
|
11
|
-
- `openlife skills create <id> --notes "..."`
|
|
12
|
-
- `openlife mcp create <id> --transport <stdio|http> --entry "..."`
|
|
13
|
-
|
|
14
|
-
Created artifacts:
|
|
15
|
-
- `.catalog/agents/<id>/AGENT.md`
|
|
16
|
-
- `.catalog/squads/<id>/SQUAD.md`
|
|
17
|
-
- `.catalog/skills/<id>/SKILL.md`
|
|
18
|
-
- `.catalog/mcps/<id>/mcp.json`
|
|
19
|
-
|
|
20
|
-
## Default reference sources configured
|
|
21
|
-
- https://skills.sh/
|
|
22
|
-
- https://clawhub.ai/
|
|
23
|
-
- https://mcpmarket.com/
|
|
24
|
-
- https://mcpservers.org/
|
|
25
|
-
- https://github.com/ (import-allowed with guard)
|
|
26
|
-
|
|
27
|
-
## Cybersecurity guard (mandatory pre-download)
|
|
28
|
-
1. Validate source URL trust.
|
|
29
|
-
2. Scan file list / extracted directory for blocked patterns.
|
|
30
|
-
3. Reject package when blocked files are present.
|
|
31
|
-
|
|
32
|
-
Active enforcement:
|
|
33
|
-
- `designmd import` runs guard before import and blocks when malicious patterns exist.
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
# OpenLife — Auditoria Geral (2026-05-06)
|
|
2
|
-
|
|
3
|
-
## Escopo
|
|
4
|
-
|
|
5
|
-
Auditoria executada em `D:\\VSCODDE-DEV\\openlife-core-main` (`/mnt/d/VSCODDE-DEV/openlife-core-main`).
|
|
6
|
-
|
|
7
|
-
Sem ações destrutivas, sem commit/push/deploy.
|
|
8
|
-
|
|
9
|
-
## Estado geral
|
|
10
|
-
|
|
11
|
-
- Repo correto: `https://github.com/GOOODZ/openlife-core.git`
|
|
12
|
-
- Branch: `main`
|
|
13
|
-
- Build TypeScript: OK
|
|
14
|
-
- CLI principal: operacional via `node bin/openlife.js`
|
|
15
|
-
- Testes oficiais de package:
|
|
16
|
-
- `npm run test:distribution`: OK
|
|
17
|
-
- `npm run test:orchestration`: OK
|
|
18
|
-
- Skill `design-extractor`: instalada e reconhecida pelo OpenLife runtime.
|
|
19
|
-
|
|
20
|
-
## Correções aplicadas após a auditoria
|
|
21
|
-
|
|
22
|
-
- Runtime-source truth corrigido: `agents list` e `squads list` agora usam `.catalog/agents` e `.catalog/squads` por padrão.
|
|
23
|
-
- `FileAgentProvider` e `FileSquadProvider` aceitam estrutura recursiva `.catalog/<tipo>/<id>/AGENT.md|SQUAD.md`.
|
|
24
|
-
- `phase1-check` não falha mais falsamente quando a fixture de imagem não existe; o check multimodal vira skip explícito.
|
|
25
|
-
- README atualizado para comandos reais (`install`, `system setup`, `up`, `start --daemon`, `chat`).
|
|
26
|
-
- `npm audit fix` aplicado para `axios`/`follow-redirects`; resta apenas advisory moderado de `@anthropic-ai/sdk` com fix breaking.
|
|
27
|
-
- `postinstall-check.sh` atualizado para npm moderno (`npm prefix -g`).
|
|
28
|
-
- Adicionados `test:runtime-source` e `test:all`.
|
|
29
|
-
- Material extra de referência encontrado em `LARA/OPEN-LIFE`; continua tratado como estratégia/documentação, não runtime.
|
|
30
|
-
|
|
31
|
-
## Achados críticos remanescentes
|
|
32
|
-
|
|
33
|
-
### 1. Railway último deploy falhou
|
|
34
|
-
|
|
35
|
-
`railway status` aponta:
|
|
36
|
-
|
|
37
|
-
- Project: `openlife-01`
|
|
38
|
-
- Environment: `production`
|
|
39
|
-
- Service: `openlife-01`
|
|
40
|
-
|
|
41
|
-
Último deploy listado: `FAILED` (`efaa3b3f-97b4-4012-a4a2-d6f2f826dec6`).
|
|
42
|
-
|
|
43
|
-
Logs via CLI não retornaram conteúdo útil nesta auditoria.
|
|
44
|
-
|
|
45
|
-
Recomendação: investigar pelo Railway UI ou redeploy controlado somente com aprovação explícita.
|
|
46
|
-
|
|
47
|
-
### 3. `phase1-check` falha em gateway-image
|
|
48
|
-
|
|
49
|
-
Resultado:
|
|
50
|
-
|
|
51
|
-
- `gateway-image`: falha por imagem de teste ausente em `.temp_images`.
|
|
52
|
-
|
|
53
|
-
Recomendação: criar fixture estável de imagem de teste ou tornar o check opcional/skip explícito quando fixture não existir.
|
|
54
|
-
|
|
55
|
-
### 4. Vulnerabilidades npm
|
|
56
|
-
|
|
57
|
-
`npm audit --omit=dev` reportou:
|
|
58
|
-
|
|
59
|
-
- `axios`: high
|
|
60
|
-
- `follow-redirects`: moderate
|
|
61
|
-
- `@anthropic-ai/sdk`: moderate, fix com breaking change
|
|
62
|
-
|
|
63
|
-
Recomendação: aplicar `npm audit fix` para axios/follow-redirects e avaliar upgrade controlado do Anthropic SDK.
|
|
64
|
-
|
|
65
|
-
## Achados importantes
|
|
66
|
-
|
|
67
|
-
### 5. README tem drift de comandos
|
|
68
|
-
|
|
69
|
-
README documenta:
|
|
70
|
-
|
|
71
|
-
- `openlife agent start`
|
|
72
|
-
|
|
73
|
-
Mas o CLI atual não lista comando `agent`; o caminho real é:
|
|
74
|
-
|
|
75
|
-
- `openlife start --daemon`
|
|
76
|
-
- `openlife up`
|
|
77
|
-
|
|
78
|
-
Recomendação: atualizar README/INSTALL/docs/commands para superfície real.
|
|
79
|
-
|
|
80
|
-
### 6. Doctor textual `system doctor` mostra Anthropic ausente como ❌
|
|
81
|
-
|
|
82
|
-
Mesmo com `OPENLIFE_RUNTIME_PROFILE=oauth-only`, o comando textual `system doctor` ainda imprime `❌ env:ANTHROPIC_API_KEY`.
|
|
83
|
-
|
|
84
|
-
O doctor universal (`openlife doctor`) classifica corretamente como `severity: info`.
|
|
85
|
-
|
|
86
|
-
Recomendação: alinhar `system doctor` com severidade do doctor universal para não assustar operador.
|
|
87
|
-
|
|
88
|
-
### 7. Railway variables parecem incompletas vs local
|
|
89
|
-
|
|
90
|
-
Railway mostrou `GEMINI_API_KEY`, `TELEGRAM_BOT_TOKEN`, Nixpacks commands e Railway vars. Não apareceram no recorte:
|
|
91
|
-
|
|
92
|
-
- `OPENLIFE_TELEGRAM_ALLOWED_USER_ID`
|
|
93
|
-
- `OPENLIFE_RUNTIME_PROFILE`
|
|
94
|
-
- `OPENLIFE_ALLOWED_LLM_EXECUTORS`
|
|
95
|
-
- `OPENAI_API_KEY`
|
|
96
|
-
|
|
97
|
-
Recomendação: validar vars de produção antes de redeploy/start.
|
|
98
|
-
|
|
99
|
-
### 8. Não há daemon OpenLife local rodando
|
|
100
|
-
|
|
101
|
-
Processos locais não mostram `openlife.js start --daemon`; só `telegram-proxy.js`.
|
|
102
|
-
|
|
103
|
-
Recomendação: se a operação local for desejada, iniciar com `openlife up` após confirmar single-poller e token correto.
|
|
104
|
-
|
|
105
|
-
## Pontos positivos
|
|
106
|
-
|
|
107
|
-
- `npm run build`: OK
|
|
108
|
-
- `node bin/openlife.js --help`: OK
|
|
109
|
-
- `node bin/openlife.js status`: OK
|
|
110
|
-
- `node bin/openlife.js doctor`: JSON com severidade e sem blocker de Anthropic no perfil oauth-only
|
|
111
|
-
- Telegram token local valida com `getMe` para `@openlife_master_bot`
|
|
112
|
-
- MCP real detecta `mcporter`, `claude`, `codex`
|
|
113
|
-
- Inventário determinístico existe:
|
|
114
|
-
- 323 agentes
|
|
115
|
-
- 47 squads
|
|
116
|
-
- 71 skills
|
|
117
|
-
- `design-extractor` aparece em `skills list` via `/home/rafaleao/skills/design-extractor/SKILL.md`
|
|
118
|
-
- Segurança de delete tem testes dedicados.
|
|
119
|
-
- `Procfile` e `NIXPACKS_START_CMD` usam `node dist/index.js start --daemon`.
|
|
120
|
-
|
|
121
|
-
## Plano de ação recomendado
|
|
122
|
-
|
|
123
|
-
### P0 — Estabilização operacional
|
|
124
|
-
|
|
125
|
-
1. Remover dependência runtime de Obsidian/LARA para agents/squads.
|
|
126
|
-
2. Corrigir Railway vars e investigar último deploy falho.
|
|
127
|
-
3. Atualizar README/INSTALL para comandos reais (`install`, `up`, `start --daemon`).
|
|
128
|
-
4. Corrigir `phase1-check gateway-image` com fixture ou skip controlado.
|
|
129
|
-
|
|
130
|
-
### P1 — Segurança e governança
|
|
131
|
-
|
|
132
|
-
1. Rodar upgrade controlado de `axios`/`follow-redirects`.
|
|
133
|
-
2. Avaliar upgrade do `@anthropic-ai/sdk` sem reintroduzir Anthropic obrigatório.
|
|
134
|
-
3. Trocar `execSync(curl ... token ...)` por `fetch`/axios sem interpolar token em shell em `InstallModules.ts`.
|
|
135
|
-
4. Garantir que Railway usa `OPENLIFE_TELEGRAM_ALLOWED_USER_ID`.
|
|
136
|
-
|
|
137
|
-
### P2 — Produto/UX
|
|
138
|
-
|
|
139
|
-
1. Consolidar doctor único com severidade clara.
|
|
140
|
-
2. Criar comando `openlife audit` ou `system audit`.
|
|
141
|
-
3. Criar `media route-status` como alias de status, pois `media status` falha.
|
|
142
|
-
4. Documentar separação Hermes vs OpenLife no README principal.
|
|
143
|
-
|
|
144
|
-
### P3 — Qualidade contínua
|
|
145
|
-
|
|
146
|
-
1. Criar script `test:all` para os 44 testes `src/test_*.ts`.
|
|
147
|
-
2. Separar testes mutantes dos testes puros.
|
|
148
|
-
3. Criar CI com build + audit + testes essenciais.
|
|
149
|
-
4. Adicionar smoke Railway pós-deploy.
|
|
150
|
-
|
|
151
|
-
## Comandos usados
|
|
152
|
-
|
|
153
|
-
```bash
|
|
154
|
-
npm run build
|
|
155
|
-
node bin/openlife.js --help
|
|
156
|
-
node bin/openlife.js system status
|
|
157
|
-
OPENLIFE_RUNTIME_PROFILE=oauth-only node bin/openlife.js system doctor
|
|
158
|
-
node bin/openlife.js doctor
|
|
159
|
-
node bin/openlife.js status
|
|
160
|
-
node bin/openlife.js agents list
|
|
161
|
-
node bin/openlife.js squads list
|
|
162
|
-
node bin/openlife.js skills list
|
|
163
|
-
node bin/openlife.js mcp status --real
|
|
164
|
-
node bin/openlife.js phase1-check
|
|
165
|
-
npm run test:distribution
|
|
166
|
-
npm run test:orchestration
|
|
167
|
-
npm audit --omit=dev
|
|
168
|
-
railway status
|
|
169
|
-
railway deployment list
|
|
170
|
-
```
|