@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.
Files changed (71) hide show
  1. package/CHANGELOG.md +186 -0
  2. package/CODE_OF_CONDUCT.md +31 -0
  3. package/CONTRIBUTING.md +133 -0
  4. package/README.md +25 -9
  5. package/dist/cli/InstallModules.js +37 -0
  6. package/dist/cli/InstallWizard.js +46 -8
  7. package/dist/index.js +11 -0
  8. package/dist/test_install_wizard.js +86 -21
  9. package/docs/getting-started.md +137 -0
  10. package/package.json +11 -2
  11. package/docs/CHANGELOG_FEATURE_ROLLOUT_DESIGNMD.md +0 -43
  12. package/docs/EXTERNAL_SOURCES_AND_SECURITY_GUARD.md +0 -33
  13. package/docs/OPENLIFE_AUDIT_2026-05-06.md +0 -170
  14. package/docs/OPENLIFE_CONSOLIDATED_PLAN_2026-05-06.md +0 -299
  15. package/docs/OPENLIFE_DUAL_MODE_IMPLEMENTATION_PLAN.md +0 -205
  16. package/docs/OPENLIFE_EVOLUTION_SURFACE_2026-05-07.md +0 -53
  17. package/docs/OPENLIFE_SKILLS_IMPORT_2026-05-07.json +0 -223
  18. package/docs/OPENLIFE_SQUADS_IMPORT_2026-05-07.json +0 -184
  19. package/docs/PAPERCLIP_OPENLIFE_INVESTIGATION.md +0 -85
  20. package/docs/RELEASE_ORGANIZATION_PLAN.md +0 -164
  21. package/docs/audit/CLI-EXECUTION-RESULTS.md +0 -113
  22. package/docs/audit/CLI-MATRIX.md +0 -556
  23. package/docs/audit/DOC-PARITY-GAPS.md +0 -351
  24. package/docs/audit/ORCHESTRATOR-MATRIX.md +0 -136
  25. package/docs/audit/TEST-COVERAGE-GAPS.md +0 -334
  26. package/docs/audit/integrations/SKIPPED.md +0 -101
  27. package/docs/autonomous-install.md +0 -79
  28. package/docs/capability-genesis.md +0 -137
  29. package/docs/capability-pack-schema.md +0 -157
  30. package/docs/commands.md +0 -82
  31. package/docs/deep-research-capability.md +0 -114
  32. package/docs/development/typescript-conventions.md +0 -95
  33. package/docs/host-installers.md +0 -68
  34. package/docs/install/aiobuilder.md +0 -70
  35. package/docs/install/claude-code.md +0 -83
  36. package/docs/install/codex.md +0 -64
  37. package/docs/install/gemini-cli.md +0 -64
  38. package/docs/install/runtime-profiles.md +0 -83
  39. package/docs/openlife-agent-os-blueprint.md +0 -114
  40. package/docs/openlife-install-backlog.md +0 -115
  41. package/docs/openlife-install-spec.md +0 -306
  42. package/docs/operations/CLOUD_CUTOVER_AUDIT.md +0 -37
  43. package/docs/operations/PHASE_PROGRESS_CONTINUATION.md +0 -24
  44. package/docs/performance-benchmarks.md +0 -83
  45. package/docs/planning/v1.3-capability-genesis.md +0 -157
  46. package/docs/plans/2026-05-05-admin-interface-professional-dark-premium-plan.md +0 -84
  47. package/docs/plans/2026-05-05-openlife-autonomous-domain-marketplace-masterplan.md +0 -122
  48. package/docs/roadmap/OPENLIFE_MASTER_PLAN_CLOUD_V3.md +0 -97
  49. package/docs/sandboxing-research.md +0 -117
  50. package/docs/stories/epic-feature-audit/1.1.story.md +0 -84
  51. package/docs/stories/epic-feature-audit/1.2.story.md +0 -102
  52. package/docs/stories/epic-feature-audit/1.3.story.md +0 -93
  53. package/docs/stories/epic-feature-audit/1.5.story.md +0 -121
  54. package/docs/stories/epic-feature-audit/1.6.story.md +0 -80
  55. package/docs/stories/epic-feature-completeness/2.1.story.md +0 -70
  56. package/docs/stories/epic-feature-completeness/2.2.story.md +0 -49
  57. package/docs/stories/epic-feature-completeness/2.3.story.md +0 -74
  58. package/docs/stories/epic-feature-completeness/2.4.story.md +0 -71
  59. package/docs/stories/epic-feature-completeness/3.1.story.md +0 -56
  60. package/docs/stories/epic-feature-completeness/3.2.story.md +0 -80
  61. package/docs/stories/epic-feature-completeness/3.3.story.md +0 -68
  62. package/docs/stories/epic-feature-completeness/3.4.story.md +0 -71
  63. package/docs/stories/epic-feature-completeness/3.5.story.md +0 -72
  64. package/docs/stories/epic-feature-completeness/3.6.story.md +0 -69
  65. package/docs/stories/epic-feature-completeness/3.7.story.md +0 -68
  66. package/docs/stories/epic-feature-completeness/3.8.story.md +0 -57
  67. package/docs/v1.4-changelog.md +0 -159
  68. package/docs/v1.5-changelog.md +0 -106
  69. package/docs/v1.5-roadmap.md +0 -121
  70. package/docs/v1.6-changelog.md +0 -67
  71. package/docs/v1.6-roadmap.md +0 -89
package/CHANGELOG.md ADDED
@@ -0,0 +1,186 @@
1
+ # Changelog
2
+
3
+ All notable changes to OpenLife CLI (`@openlife/cli`) are documented here.
4
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
+ Project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ Detailed per-milestone notes (story-level breakdown, commit map, scorecard
8
+ deltas) live in `docs/v<N>-changelog.md`.
9
+
10
+ ## [Unreleased]
11
+
12
+ Hit-10 sprint in progress — see plan for M2→M6 (docs hygiene, first-run
13
+ wizard, observability, aiobuilder depth, self-update).
14
+
15
+ ---
16
+
17
+ ## [1.7.4] — 2026-05-14
18
+
19
+ ### Fixed
20
+ - `openlife --version` now reads dynamically from `package.json` instead
21
+ of a hardcoded `1.0.0`. After install, the reported version matches
22
+ the npm tag.
23
+
24
+ ## [1.7.3] — 2026-05-14
25
+
26
+ ### Added
27
+ - `LICENSE` (MIT) at repository root and registered in `package.json`
28
+ `files[]` so the tarball ships it.
29
+ - `.npmignore` to enforce exclusions over `files[]` whitelist when
30
+ needed.
31
+
32
+ ### Changed
33
+ - Cleaned external dev-kit branding (AIOX, GSD, AIOS) from every
34
+ user-facing surface: 33 catalog files scrubbed, 8 unused legacy
35
+ catalog entries removed, source comments and test function names
36
+ generalized, `dist-templates/workflows/AIOX_PORT_NOTES.md` renamed
37
+ to `PORTED_WORKFLOWS.md`.
38
+ - `.planning/` and `CLAUDE.md` untracked and `.gitignore`'d — they
39
+ remain on disk for the maintainer but never ship publicly.
40
+ - Compact, OpenLife-only `CLAUDE.md` content (local-only).
41
+
42
+ ### Removed
43
+ - 7 unused `aios-*` agents + 1 squad from `.catalog/` (imported mirrors
44
+ with zero runtime consumers).
45
+ - Internal strategy/study docs moved out of public `docs/`.
46
+
47
+ ## [1.7.2] — 2026-05-14
48
+
49
+ ### Changed
50
+ - Package renamed from `@open-life/cli` → `@openlife/cli` to match
51
+ the existing npm organization (`openlife`). No code/behavior change.
52
+
53
+ ## [1.7.1] — 2026-05-13
54
+
55
+ ### Fixed
56
+ - `SystemDoctor` graceful downgrade when running on Node 20+ builds
57
+ that lack `--permission` flag support (e.g. CI runners). Sandbox
58
+ enforcement check no longer false-fails on unsupported runtimes.
59
+
60
+ ## [1.7.0] — 2026-05-13 — "Enforcement at scale"
61
+
62
+ See `docs/v1.7-changelog.md` for full per-story breakdown.
63
+
64
+ ### Added
65
+ - Toolset enforcement coverage expanded from 2 to **13 categories**
66
+ (memory, tts, cron, mcp, skills, workflows, squads, web, file,
67
+ vision, gateway, plus terminal and delegation from v1.4). Behind
68
+ `OPENLIFE_TOOLSET_ENFORCEMENT=on` (default still off, calendar-gated
69
+ flip in 20.1).
70
+ - `OrchestrationLoop` now branches on `OPENLIFE_BRAIN_FORECAST=on` to
71
+ reach `ConsequenceForecaster.forecastWithBrain()` (shipped v1.5,
72
+ unwired until now). Brain verdict / risk amplifiers / opportunity
73
+ factors surfaced into the attempt trace.
74
+ - `test_forecast_brain_wiring.ts` regression guard catches the
75
+ "shipped but unwired" class of bug.
76
+ - Consolidated `docs/release-process.md` runbook.
77
+
78
+ ### Fixed
79
+ - CI lint `any`-budget grep filter (`-h` flag was stripping filenames,
80
+ causing test-file matches to count as production). Production `any`
81
+ count driven to **0** against a filename-aware grep.
82
+
83
+ ### Note on prior measurement
84
+ The v1.4–v1.6 `any` counts (172, 109, 83) reflected the broken filter
85
+ and were inflated. Real production counts were ~30, ~20, 12–14.
86
+ Historical changelogs are not retroactively edited; the correction is
87
+ documented in `docs/v1.7-changelog.md`.
88
+
89
+ ## [1.6.0] — 2026-05-13 — "Sandbox rollout"
90
+
91
+ See `docs/v1.6-changelog.md`.
92
+
93
+ ### Added
94
+ - `ProcessSandbox` (Story 18.1): Node 20+ `--permission` flag-based
95
+ process sandboxing. First production wire-in via `openlife doctor`
96
+ with graceful downgrade when unsupported.
97
+ - `TaskExecutor` opt-in sandbox (Story 18.2) via
98
+ `OPENLIFE_SANDBOX_TASK_EXEC=on`.
99
+ - Distributed lock primitive for multi-process queue coordination.
100
+
101
+ ### Changed
102
+ - `RuntimeHealthMonitor` exponential backoff (10s base → 1h cap) with
103
+ 10-failure budget per 1h window.
104
+
105
+ ## [1.5.0] — 2026-05-13 — "Evaluation + remote publishing"
106
+
107
+ See `docs/v1.5-changelog.md` and `docs/v1.5-roadmap.md`.
108
+
109
+ ### Added
110
+ - Brain-driven post-mission evaluation (Story 13.1) — automatic
111
+ `quality / governance / actionability` scoring via `eval judge`
112
+ command, results in `.openlife/evaluations/`.
113
+ - SHA-chained governance scope ledger (Story 14.2):
114
+ `.openlife/governance-ledger.jsonl` with tamper detection via chain
115
+ walk. PII protection by hashing goals before persistence.
116
+ - Remote asset publishing over HTTPS (Story 14.1) —
117
+ `RemotePublisher` + signed manifests for catalog distribution.
118
+ - `ConsequenceForecaster.forecastWithBrain()` API (wiring in v1.7).
119
+ - Type safety improvements: structured Telegram API parsing, event
120
+ iteration typing.
121
+
122
+ ## [1.4.0] / [1.4.1] — 2026-05-12/13 — "Path to 10/10"
123
+
124
+ See `docs/v1.4-changelog.md`.
125
+
126
+ ### Added (consolidation milestone — no new pillars)
127
+ - Intelligence wiring: `Brain.isAnyProviderAvailable()` opt-in,
128
+ `SquadCreator/SkillCreator.designWithBrain()`, post-mission memory
129
+ consolidation hook.
130
+ - Real I/O: `SecurityDownloadGuard.downloadAndScan()` with size cap +
131
+ filename-pattern scanning; `HostInstaller` real implementations for
132
+ Gemini CLI and Codex (no longer stubs); seeded
133
+ `dist-templates/{gemini-cli,codex}/`.
134
+ - Toolset enforcement kernel: `assertToolsetAllowed()` at
135
+ `TaskExecutor` and `Brain` CLI sites (terminal + delegation
136
+ categories).
137
+ - Workflow condition parser: tokenize → recursive-descent → evaluate
138
+ pipeline supporting `AND/OR/NOT/==/!=` + parens + dotted identifiers.
139
+ - CI + perf telemetry: `npm run test:performance-latency`,
140
+ `.github/workflows/{test,build,lint}.yml`.
141
+
142
+ ### v1.4.1 — Maintenance cut
143
+ - Backport-eligible bug fixes for v1.4 line.
144
+
145
+ ## [1.3.0] — 2026-05-12 — "Agent OS Integration"
146
+
147
+ ### Added
148
+ - 5 blueprint docs covering Agent OS integration architecture.
149
+ - Service Mode contract caller fixes (required `actor` parameter).
150
+ - v1.3 placeholder commands now have real implementations.
151
+ - Capability Pack schema + Capability Genesis Engine — turns free-text
152
+ briefs into draft capability packs (Stories 1.1, 2.1–2.4, 3.1–3.3).
153
+
154
+ ## [1.2.0] — 2026-05-12 — "Royal Stack"
155
+
156
+ ### Added
157
+ - Workflow engine: `WorkflowSchema` + `WorkflowParser` +
158
+ `WorkflowEngine` with atomic state persistence and phase-step
159
+ execution model (Story 4.1).
160
+ - 4 ported workflows shipped in `dist-templates/workflows/`:
161
+ `story-development-cycle`, `greenfield-fullstack`,
162
+ `brownfield-discovery`, `qa-loop` (Story 4.4).
163
+ - Squad + Skill creators with interactive UX and Brain-driven design
164
+ modes (Stories 5.1–5.5).
165
+ - Atomic writer + mission checkpoint API (Stories 6.1–6.2).
166
+ - Runtime reliability: heartbeat, watchdog, distributed lock,
167
+ exponential backoff health monitor.
168
+ - `aiobuilder` CLI surface with 16 sub-commands (`mode`, `create-agent`,
169
+ `create-squad`, `build-skill`, `generate-ui`, `discover`, `plan`,
170
+ `build`, `test`, `preview`, `release`, `infra`, `score`, `evolve`,
171
+ `ship`, `chat`, `canonize`, `create-capability`).
172
+
173
+ ---
174
+
175
+ [Unreleased]: https://github.com/GOOODZ/openlife-core/compare/v1.7.4...HEAD
176
+ [1.7.4]: https://github.com/GOOODZ/openlife-core/releases/tag/v1.7.4
177
+ [1.7.3]: https://github.com/GOOODZ/openlife-core/releases/tag/v1.7.3
178
+ [1.7.2]: https://github.com/GOOODZ/openlife-core/releases/tag/v1.7.2
179
+ [1.7.1]: https://github.com/GOOODZ/openlife-core/releases/tag/v1.7.1
180
+ [1.7.0]: https://github.com/GOOODZ/openlife-core/releases/tag/v1.7.0
181
+ [1.6.0]: https://github.com/GOOODZ/openlife-core/releases/tag/v1.6.0
182
+ [1.5.0]: https://github.com/GOOODZ/openlife-core/releases/tag/v1.5.0
183
+ [1.4.1]: https://github.com/GOOODZ/openlife-core/releases/tag/v1.4.1
184
+ [1.4.0]: https://github.com/GOOODZ/openlife-core/releases/tag/v1.4.0
185
+ [1.3.0]: https://github.com/GOOODZ/openlife-core/releases/tag/v1.3.0
186
+ [1.2.0]: https://github.com/GOOODZ/openlife-core/releases/tag/v1.2.0
@@ -0,0 +1,31 @@
1
+ # Code of Conduct
2
+
3
+ This project welcomes contributions from anyone willing to engage
4
+ constructively. To keep collaboration productive and respectful, all
5
+ participants are expected to:
6
+
7
+ - Communicate professionally and assume good faith.
8
+ - Focus discussion on ideas, code, and project goals.
9
+ - Accept constructive feedback gracefully and offer it the same way.
10
+ - Respect differing viewpoints and experience levels.
11
+ - Help maintain a focused, useful technical environment.
12
+
13
+ ## Scope
14
+
15
+ This Code of Conduct applies to all project spaces — issues, pull
16
+ requests, discussions, and any public communication associated with
17
+ OpenLife CLI.
18
+
19
+ ## Reporting
20
+
21
+ If a concern arises, please contact the maintainer privately by opening
22
+ a confidential issue or via email at the address listed in
23
+ `package.json`. Reports will be reviewed and addressed by the
24
+ maintainer.
25
+
26
+ ## Enforcement
27
+
28
+ The maintainer is responsible for clarifying acceptable behavior and
29
+ may take appropriate corrective action for participation that disrupts
30
+ the project, including edits to or removal of contributions and, where
31
+ necessary, blocking continued participation.
@@ -0,0 +1,133 @@
1
+ # Contributing to OpenLife CLI
2
+
3
+ Thanks for your interest in improving OpenLife. This document covers the
4
+ dev setup, test discipline, commit conventions, and PR process used in
5
+ this project.
6
+
7
+ ## Quick start (dev setup)
8
+
9
+ ```bash
10
+ git clone https://github.com/GOOODZ/openlife-core.git
11
+ cd openlife-core
12
+ npm install # postinstall runs scripts/postinstall-check.sh
13
+ npm run build # tsc → dist/
14
+ node bin/openlife.js --help # verify the CLI loads
15
+ ```
16
+
17
+ For interactive development without rebuilding each time:
18
+
19
+ ```bash
20
+ npm run dev # ts-node src/index.ts
21
+ ```
22
+
23
+ ## Test discipline
24
+
25
+ OpenLife does **not** use Jest. Each test is a standalone executable in
26
+ `src/test_*.ts` that the `test:*` script in `package.json` compiles and
27
+ runs directly. Tests `throw` or `process.exit(1)` on failure; success
28
+ prints a summary line ending with `TEST_<NAME>_OK`.
29
+
30
+ Run the full canonical suite before committing:
31
+
32
+ ```bash
33
+ npm run test:all
34
+ ```
35
+
36
+ Run an individual test:
37
+
38
+ ```bash
39
+ npm run test:workflow-parser
40
+ # or ad-hoc without script:
41
+ npm run build && node dist/test_<name>.js
42
+ ```
43
+
44
+ `prepublishOnly` runs `test:all` automatically — publish will block on
45
+ the suite. Add new tests by:
46
+
47
+ 1. Create `src/test_<feature>.ts` following the existing pattern (use a
48
+ neighboring test file as template).
49
+ 2. Add a matching `test:<feature>` script in `package.json`.
50
+ 3. If the test is canonical, append it to the `test:all` chain.
51
+
52
+ ## Commit conventions
53
+
54
+ - Use [Conventional Commits](https://www.conventionalcommits.org/):
55
+ `feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `test:`, `ci:`,
56
+ `style:`, `perf:`, `build:`.
57
+ - Reference the story or issue: `feat(workflow): add idempotent flag (Story 4.2, v1.2)`.
58
+ - Keep commits atomic — one logical change per commit. Pre-commit
59
+ validation runs `npm run test:all` indirectly via prepublish gate.
60
+
61
+ ## TypeScript conventions
62
+
63
+ - **Strict mode** is enforced (`tsconfig.json` has `"strict": true`).
64
+ Production code must not use `any` — `unknown` + type narrowing is the
65
+ idiomatic alternative. Test files may use `(x as any)` as a test seam.
66
+ - **Lazy imports** for heavy classes inside `src/index.ts` Commander
67
+ handlers — never move `Gateway`, `Brain`, `TestHarness`,
68
+ `OrchestrationLoop`, etc. to module scope. They are inside
69
+ `.action(...)` via `require(...)` so that deterministic commands
70
+ (`--help`, `plugin`, tests) stay fast.
71
+ - **Error contract for CLI handlers**: return JSON via
72
+ `JSON.stringify(...)` with `{ ok: false, error: '<snake_case_code>',
73
+ ... }`. Use `process.exitCode = 1` (not `process.exit(1)`) for
74
+ failures in handlers.
75
+ - **Provider pattern**: new asset sources follow `Composite{X}Provider`
76
+ → `File{X}Provider` / `Cloud{X}Provider` in
77
+ `src/orchestrator/providers/`.
78
+ - **No external dev-kit paths at runtime** — runtime must not import
79
+ from `~/.hermes`, Obsidian vaults, or local-only dev-kit dirs.
80
+
81
+ ## Pull request process
82
+
83
+ 1. Fork the repository or create a feature branch (`feat/<short-name>`
84
+ or `fix/<short-name>`).
85
+ 2. Make atomic commits with conventional commit messages.
86
+ 3. Ensure `npm run test:all` passes locally.
87
+ 4. Run `npm run build` to confirm clean TypeScript compilation.
88
+ 5. Open a PR against `main`. Include in the description:
89
+ - **Summary** of the change (1-3 bullets).
90
+ - **Tests added/changed** with file paths.
91
+ - **Risk assessment** for any runtime-behavior change.
92
+ 6. CI (`.github/workflows/test.yml`, `build.yml`, `lint.yml`) must pass.
93
+ 7. A maintainer will review and merge. **Push to `main` and
94
+ `gh pr merge` are restricted to the maintainer** to keep the release
95
+ pipeline deterministic.
96
+
97
+ ## Filing issues
98
+
99
+ Use the templates in `.github/ISSUE_TEMPLATE/`:
100
+
101
+ - **Bug report** — for unexpected behavior, crashes, or regressions.
102
+ - **Feature request** — for new capabilities or enhancements.
103
+ - **Question** — for usage questions that don't fit the above.
104
+
105
+ Include OS, Node version, OpenLife version (`openlife --version`),
106
+ reproduction steps, and expected vs actual behavior.
107
+
108
+ ## Where to put new code
109
+
110
+ | Adding... | Lives in... |
111
+ |---|---|
112
+ | Commander command | `src/index.ts` (near related commands, reuse banner sections) |
113
+ | Orchestrator class | `src/orchestrator/<ClassName>.ts` |
114
+ | CLI installer/wizard | `src/cli/<ClassName>.ts` |
115
+ | Memory provider | `src/memory/<Name>Provider.ts` + register in `MemoryProviderRegistry.ts` |
116
+ | Asset provider | `src/orchestrator/providers/{File,Cloud,Composite}<X>Provider.ts` |
117
+ | Reversa contract/executor | `src/reversa/Reversa<Name>.ts` |
118
+ | Test | `src/test_<feature>.ts` + matching `test:<feature>` script |
119
+
120
+ ## Code of Conduct
121
+
122
+ This project adheres to a Contributor Covenant. See
123
+ [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md). By participating, you agree
124
+ to abide by its terms.
125
+
126
+ ## License
127
+
128
+ By contributing, you agree that your contributions will be licensed
129
+ under the [MIT License](./LICENSE).
130
+
131
+ ## Questions
132
+
133
+ Open a question issue or check `docs/getting-started.md` (coming soon).
package/README.md CHANGED
@@ -1,19 +1,18 @@
1
1
  # OpenLife CLI
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@openlife/cli.svg)](https://www.npmjs.com/package/@openlife/cli)
4
+ [![Build](https://github.com/GOOODZ/openlife-core/actions/workflows/test.yml/badge.svg)](https://github.com/GOOODZ/openlife-core/actions/workflows/test.yml)
5
+ [![License: MIT](https://img.shields.io/npm/l/@openlife/cli.svg)](./LICENSE)
6
+ [![Node](https://img.shields.io/node/v/@openlife/cli.svg)](https://nodejs.org)
7
+ [![npm downloads](https://img.shields.io/npm/dm/@openlife/cli.svg)](https://www.npmjs.com/package/@openlife/cli)
8
+
3
9
  OpenLife é um CLI/framework de orquestração com dois modos principais:
4
10
 
5
11
  - **CLI framework**: uso local por terminal, automações e comandos de operador.
6
12
  - **Agente autônomo**: runtime contínuo com daemon, Telegram e governança.
7
13
 
8
- > OpenLife é separado do Hermes. Hermes pode ajudar a operar/desenvolver OpenLife, mas o runtime do OpenLife não deve depender de `~/.hermes` nem de pastas do Obsidian.
9
-
10
- ## Fonte executável canônica
11
-
12
- - Código/dev: `D:\VSCODDE-DEV\openlife-core-main`
13
- - WSL: `/mnt/d/VSCODDE-DEV/openlife-core-main`
14
- - GitHub: `https://github.com/GOOODZ/openlife-core`
15
-
16
- Obsidian (`OPENLIFE_PRODUCTION` e `LARA/OPEN-LIFE`) é camada estratégica/documental. Catálogos runtime devem viver no repo/cloud, por exemplo:
14
+ OpenLife é um produto standalone. Catálogos runtime vivem no repositório
15
+ e não dependem de dev-kits externos ou pastas de terceiros.
17
16
 
18
17
  ```txt
19
18
  .catalog/agents/
@@ -22,6 +21,23 @@ Obsidian (`OPENLIFE_PRODUCTION` e `LARA/OPEN-LIFE`) é camada estratégica/docum
22
21
  .catalog/mcps/
23
22
  ```
24
23
 
24
+ ## Quickstart
25
+
26
+ ```bash
27
+ npm install -g @openlife/cli
28
+ openlife init # wizard interativo com banner, chaves, OAuth, Telegram
29
+ openlife ask "hello, what can you do?"
30
+ ```
31
+
32
+ Mais detalhes em [INSTALL.md](INSTALL.md) e [docs/getting-started.md](docs/getting-started.md).
33
+
34
+ ## Repositório
35
+
36
+ - GitHub: <https://github.com/GOOODZ/openlife-core>
37
+ - npm: <https://www.npmjs.com/package/@openlife/cli>
38
+ - Issues: <https://github.com/GOOODZ/openlife-core/issues>
39
+ - Changelog: [CHANGELOG.md](CHANGELOG.md)
40
+
25
41
  ## Quick Start
26
42
 
27
43
  ### Caminho recomendado — wizard interativo
@@ -35,6 +35,8 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.runPrecheck = runPrecheck;
37
37
  exports.maskToken = maskToken;
38
+ exports.providedApiKeyEnvNames = providedApiKeyEnvNames;
39
+ exports.saveApiKeysToEnv = saveApiKeysToEnv;
38
40
  exports.saveTelegramConfig = saveTelegramConfig;
39
41
  exports.validateTelegramToken = validateTelegramToken;
40
42
  exports.checkTelegram409Conflict = checkTelegram409Conflict;
@@ -71,6 +73,41 @@ function maskToken(token) {
71
73
  return '***';
72
74
  return `${token.slice(0, 6)}...${token.slice(-4)}`;
73
75
  }
76
+ const API_KEY_ENV_MAP = {
77
+ openai: 'OPENAI_API_KEY',
78
+ anthropic: 'ANTHROPIC_API_KEY',
79
+ gemini: 'GEMINI_API_KEY',
80
+ openrouter: 'OPENROUTER_API_KEY',
81
+ elevenlabs: 'ELEVENLABS_API_KEY',
82
+ };
83
+ function providedApiKeyEnvNames(keys) {
84
+ return Object.keys(keys)
85
+ .filter((k) => typeof keys[k] === 'string' && keys[k].trim().length > 0)
86
+ .map((k) => API_KEY_ENV_MAP[k]);
87
+ }
88
+ function saveApiKeysToEnv(root, keys) {
89
+ const envPath = path.join(root, '.env');
90
+ const current = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf-8') : '';
91
+ const provided = Object.keys(keys)
92
+ .filter((k) => typeof keys[k] === 'string' && keys[k].trim().length > 0);
93
+ if (provided.length === 0)
94
+ return { saved: [], path: envPath };
95
+ const envVars = new Set(provided.map((k) => API_KEY_ENV_MAP[k]));
96
+ const lines = current
97
+ .split('\n')
98
+ .filter(Boolean)
99
+ .filter((l) => {
100
+ const eq = l.indexOf('=');
101
+ if (eq < 0)
102
+ return true;
103
+ return !envVars.has(l.slice(0, eq));
104
+ });
105
+ for (const k of provided) {
106
+ lines.push(`${API_KEY_ENV_MAP[k]}=${keys[k].trim()}`);
107
+ }
108
+ fs.writeFileSync(envPath, lines.join('\n') + '\n', 'utf-8');
109
+ return { saved: provided.map((k) => API_KEY_ENV_MAP[k]), path: envPath };
110
+ }
74
111
  function saveTelegramConfig(root, token, chatId) {
75
112
  const envPath = path.join(root, '.env');
76
113
  const current = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf-8') : '';
@@ -185,9 +185,15 @@ class InstallWizard {
185
185
  }
186
186
  preExistingAction = idx === 1 ? 'reinstall' : 'repair';
187
187
  }
188
- // 2. Profile selection
189
- const profileIdx = await this.answers.choice('Which profile do you want to install?\n framework — local interactive CLI (default)\n autonomous long-running daemon with Telegram gateway and governance', ['framework', 'autonomous'], 0);
190
- const profile = profileIdx === 1 ? 'autonomous' : 'framework';
188
+ // 2. Profile selection — 3 user-visible options. `both` is an alias for
189
+ // `autonomous` since autonomous already includes the framework layer
190
+ // (systemInstaller.install() runs unconditionally in InstallFlow.run()).
191
+ const profileIdx = await this.answers.choice('Which profile do you want to install?\n framework — local interactive CLI only\n autonomous — long-running daemon with Telegram gateway and governance\n both — autonomous daemon plus framework CLI (recommended for full setup)', ['framework', 'autonomous', 'both'], 0);
192
+ const profile = profileIdx === 0 ? 'framework' : 'autonomous';
193
+ const installBoth = profileIdx === 2;
194
+ if (installBoth) {
195
+ warnings.push('INSTALLING_BOTH: autonomous profile selected (includes framework layer)');
196
+ }
191
197
  // 3. Host selection — auto-detect, but always ask to confirm.
192
198
  const detected = (0, InstallFlow_1.detectHostFromEnv)();
193
199
  const hostOptions = [...InstallFlow_1.VALID_HOSTS];
@@ -207,25 +213,53 @@ class InstallWizard {
207
213
  if (validatedHost !== 'claude-code') {
208
214
  warnings.push(`HOST_NOT_YET_SUPPORTED: ${validatedHost} host-specific install is a no-op for now; .openlife state will still be created`);
209
215
  }
210
- // 4. Model chain (optional)
216
+ // 4. API keys (optional) — each prompt accepts paste or blank to skip.
217
+ // IMPORTANT: collect first, but only persist after final confirmation.
218
+ // An aborted wizard must not mutate .env or write pasted secrets.
219
+ let savedApiKeyNames = [];
220
+ const collectedApiKeys = {};
221
+ const wantsApiKeys = await this.answers.yesNo('Configure LLM API keys now? (You can also set them later in .env)', true);
222
+ if (wantsApiKeys) {
223
+ collectedApiKeys.openai = await this.answers.text('OPENAI_API_KEY (paste or Enter to skip)', '');
224
+ collectedApiKeys.anthropic = await this.answers.text('ANTHROPIC_API_KEY (paste or Enter to skip)', '');
225
+ collectedApiKeys.gemini = await this.answers.text('GEMINI_API_KEY (paste or Enter to skip)', '');
226
+ collectedApiKeys.openrouter = await this.answers.text('OPENROUTER_API_KEY (paste or Enter to skip)', '');
227
+ savedApiKeyNames = (0, InstallModules_1.providedApiKeyEnvNames)(collectedApiKeys);
228
+ if (savedApiKeyNames.length === 0) {
229
+ warnings.push('NO_API_KEYS_PROVIDED: model providers will only work via OAuth CLIs or Ollama until keys are added to .env');
230
+ }
231
+ }
232
+ else {
233
+ warnings.push('SKIPPED_API_KEYS: configure providers later via .env or `openlife auth <provider>`');
234
+ }
235
+ // 5. OAuth pointer — informational only. The actual `openlife auth gemini`
236
+ // / `auth openai` flows are interactive subprocesses; running them inside
237
+ // the wizard would break the canned-answer test seam. We just signal the
238
+ // operator that the flag exists so they can opt-in after init completes.
239
+ const wantsOAuth = await this.answers.yesNo('Plan to configure OAuth for Gemini or OpenAI CLI later?', false);
240
+ if (wantsOAuth) {
241
+ warnings.push('OAUTH_PENDING: after init completes, run `openlife auth gemini` and/or `openlife auth openai` to log in');
242
+ }
243
+ // 6. Model chain (optional)
211
244
  const modelsRaw = await this.answers.text('LLM model order (comma-separated provider/model chain, blank = defaults)', '');
212
245
  const modelOrder = modelsRaw
213
246
  ? modelsRaw.split(',').map((m) => m.trim()).filter(Boolean)
214
247
  : undefined;
215
- // 5. Telegram (autonomous only)
248
+ // 7. Telegram (autonomous only)
216
249
  if (profile === 'autonomous') {
217
250
  const hasTelegram = await this.answers.yesNo('Do you already have TELEGRAM_BOT_TOKEN and OPENLIFE_TELEGRAM_ALLOWED_USER_ID set in your .env?', false);
218
251
  if (!hasTelegram) {
219
252
  warnings.push('TELEGRAM_NOT_CONFIGURED: autonomous profile needs TELEGRAM_BOT_TOKEN and OPENLIFE_TELEGRAM_ALLOWED_USER_ID — set them in .env before running `openlife agent start`');
220
253
  }
221
254
  }
222
- // 6. Skip doctor?
255
+ // 8. Skip doctor?
223
256
  const skipDoctor = await this.answers.yesNo('Skip the system doctor run?', false);
224
- // 7. Confirm preview
257
+ // 9. Confirm preview
225
258
  const previewLines = [
226
259
  'Review your choices:',
227
- ` profile : ${profile}`,
260
+ ` profile : ${profile}${installBoth ? ' (both — framework + autonomous)' : ''}`,
228
261
  ` host : ${validatedHost}`,
262
+ ` apiKeys : ${savedApiKeyNames.length ? savedApiKeyNames.join(', ') : '(none saved)'}`,
229
263
  ` modelOrder : ${modelOrder ? modelOrder.join(', ') : '(defaults)'}`,
230
264
  ` skipDoctor : ${skipDoctor}`,
231
265
  preExistingAction ? ` preExisting : ${preExistingAction}` : ''
@@ -239,6 +273,10 @@ class InstallWizard {
239
273
  if (!confirmed) {
240
274
  return { ok: false, reason: 'user_aborted', detail: 'preview_not_confirmed' };
241
275
  }
276
+ if (savedApiKeyNames.length > 0) {
277
+ const saved = (0, InstallModules_1.saveApiKeysToEnv)(this.root, collectedApiKeys);
278
+ savedApiKeyNames = saved.saved;
279
+ }
242
280
  const options = {
243
281
  profile,
244
282
  host: validatedHost,
package/dist/index.js CHANGED
@@ -298,6 +298,8 @@ program
298
298
  program.command('init')
299
299
  .description('Interactive install wizard — guided setup for OpenLife into the chosen host CLI')
300
300
  .action(async () => {
301
+ console.log((0, InstallBanner_1.installationBanner)());
302
+ console.log('');
301
303
  // Lazy require preserves the lazy-import contract (`src/index.ts:11-13`).
302
304
  const { InstallWizard, ReadlineAnswerProvider } = require('./cli/InstallWizard');
303
305
  const { InstallFlow } = require('./cli/InstallFlow');
@@ -320,6 +322,15 @@ program.command('init')
320
322
  for (const w of result.warnings)
321
323
  console.log(` - ${w}`);
322
324
  }
325
+ console.log('');
326
+ console.log('✅ OpenLife ready.');
327
+ console.log('');
328
+ console.log('Try:');
329
+ console.log(' openlife ask "hello, what can you do?"');
330
+ console.log(' openlife status');
331
+ console.log(' openlife --help');
332
+ console.log('');
333
+ console.log('Docs: https://github.com/GOOODZ/openlife-core');
323
334
  }
324
335
  finally {
325
336
  // Release the readline interface so the CLI exits cleanly.