@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
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.
|
package/CONTRIBUTING.md
ADDED
|
@@ -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
|
+
[](https://www.npmjs.com/package/@openlife/cli)
|
|
4
|
+
[](https://github.com/GOOODZ/openlife-core/actions/workflows/test.yml)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
[](https://nodejs.org)
|
|
7
|
+
[](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
|
-
|
|
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
|
-
|
|
190
|
-
|
|
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.
|
|
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
|
-
//
|
|
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
|
-
//
|
|
255
|
+
// 8. Skip doctor?
|
|
223
256
|
const skipDoctor = await this.answers.yesNo('Skip the system doctor run?', false);
|
|
224
|
-
//
|
|
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.
|