limbo-ai 1.32.0 → 2026.4.2

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 (116) hide show
  1. package/Dockerfile +123 -0
  2. package/README.md +34 -17
  3. package/RELEASES.md +33 -0
  4. package/cli.js +515 -166
  5. package/evals/cli.js +23 -6
  6. package/lib/cf-tunnel.js +123 -0
  7. package/lib/control-client.js +110 -0
  8. package/lib/control-router.js +174 -0
  9. package/lib/control-server.js +184 -0
  10. package/lib/session-store.js +179 -0
  11. package/lib/supervisor.js +254 -0
  12. package/lib/telegram-notify.js +10 -22
  13. package/lib/wizard-spawner.js +137 -0
  14. package/mcp-server/index.js +159 -1
  15. package/mcp-server/tools/google-calendar.js +277 -0
  16. package/migrations/index.js +199 -0
  17. package/migrations/package.json +3 -0
  18. package/migrations/versions/001-initial-schema.js +47 -0
  19. package/migrations/versions/002-unified-note-types.js +150 -0
  20. package/migrations/versions/003-zeroclaw-migration.js +24 -0
  21. package/migrations/versions/004-assets-directory.js +25 -0
  22. package/migrations/versions/005-fts5-search.js +137 -0
  23. package/migrations/versions/006-fts5-dedupe.js +155 -0
  24. package/openclaw.json.template +56 -0
  25. package/package.json +39 -4
  26. package/scripts/entrypoint.sh +369 -0
  27. package/scripts/patch-openclaw-audio.mjs +158 -0
  28. package/setup-server/public/index.html +124 -4
  29. package/setup-server/server.js +299 -89
  30. package/workspace/skills/google-calendar/SKILL.md +144 -0
  31. package/workspace/skills/retrieve-file/SKILL.md +41 -0
  32. package/workspace/system/AGENTS.md +85 -0
  33. package/workspace/system/IDENTITY.md +61 -0
  34. package/workspace/system/SOUL.md +71 -0
  35. package/workspace/system/TOOLS.md +306 -0
  36. package/workspace/system/limbo-skill.md +152 -0
  37. package/workspace/templates/USER.md.template +19 -0
  38. package/.gitlab-ci.yml +0 -209
  39. package/ARCHITECTURE.md +0 -174
  40. package/CONTRIBUTING.md +0 -34
  41. package/SECURITY.md +0 -108
  42. package/docker-compose.dev.yml +0 -12
  43. package/docker-compose.test.yml +0 -74
  44. package/evals/config.eval.env +0 -9
  45. package/evals/dashboard/public/app.js +0 -975
  46. package/evals/dashboard/public/index.html +0 -89
  47. package/evals/dashboard/public/styles.css +0 -908
  48. package/evals/dashboard/server.js +0 -129
  49. package/evals/docker-compose.eval.yml +0 -57
  50. package/evals/promptfoo/assertions.js +0 -215
  51. package/evals/promptfoo/hooks.js +0 -119
  52. package/evals/promptfoo/promptfooconfig.yaml +0 -106
  53. package/evals/promptfoo/provider.js +0 -206
  54. package/evals/promptfoo/run.sh +0 -25
  55. package/evals/promptfoo/seeds/notes/eval-seed-birthday.md +0 -9
  56. package/evals/results/.gitkeep +0 -0
  57. package/evals/results/history/.gitkeep +0 -0
  58. package/evals/results/history/run-1774559258082.json +0 -662
  59. package/evals/results/history/run-1774559485256.json +0 -662
  60. package/evals/results/history/run-1774559674855.json +0 -662
  61. package/evals/results/history/run-1774561108314.json +0 -662
  62. package/evals/results/history/run-1774561286576.json +0 -662
  63. package/evals/results/history/run-1774561575363.json +0 -575
  64. package/evals/results/history/run-1774563070869.json +0 -662
  65. package/evals/results/history/run-1774563275178.json +0 -662
  66. package/evals/results/history/run-1774622867363.json +0 -934
  67. package/evals/results/history/run-1774623126438.json +0 -934
  68. package/evals/results/history/run-1774624683868.json +0 -934
  69. package/evals/results/history/run-1774625379694.json +0 -934
  70. package/evals/results/history/run-1774629331960.json +0 -746
  71. package/evals/results/history/run-1774632319238.json +0 -39
  72. package/evals/results/history/run-1774633277690.json +0 -94
  73. package/evals/results/history/run-1774636000952.json +0 -934
  74. package/evals/results/history/run-1774636946600.json +0 -151
  75. package/evals/results/history/run-1774637141591.json +0 -374
  76. package/evals/results/history/run-1774639388611.json +0 -1578
  77. package/evals/results/history/run-1774641629961.json +0 -1523
  78. package/evals/results/history/run-1774643063585.json +0 -1653
  79. package/evals/results/history/run-1774644145726.json +0 -73
  80. package/evals/results/history/run-1774644299624.json +0 -1489
  81. package/evals/results/history/run-1774644416754.json +0 -58
  82. package/evals/results/history/run-1774644909594.json +0 -58
  83. package/evals/results/history/run-1774796618679.json +0 -73
  84. package/evals/results/history/run-1774796879800.json +0 -73
  85. package/evals/results/history/run-1774797434760.json +0 -94
  86. package/evals/results/history/run-1774797567080.json +0 -57
  87. package/evals/results/history/run-1774895167606.json +0 -574
  88. package/evals/results/history/run-1774895670045.json +0 -540
  89. package/evals/results/history/run-1774895876781.json +0 -466
  90. package/evals/results/history/run-1774898060232.json +0 -162
  91. package/evals/results/history/run-1774966775381.json +0 -135
  92. package/evals/results/history/run-1774966839076.json +0 -33
  93. package/evals/results/history/run-1774966890459.json +0 -33
  94. package/evals/results/history/run-1774967730887.json +0 -189
  95. package/evals/results/history/run-1774967764419.json +0 -113
  96. package/evals/results/history/run-1775043267611.json +0 -4470
  97. package/evals/results/history/run-1775046132278.json +0 -4420
  98. package/evals/results/history/run-1775068115506.json +0 -5277
  99. package/evals/results/latest.json +0 -5277
  100. package/evals/test/scorer.test.js +0 -218
  101. package/mcp-server/test/benchmark.js +0 -365
  102. package/mcp-server/test/eval-logging.test.js +0 -259
  103. package/mcp-server/test/get-file.test.js +0 -256
  104. package/test/cli-auth.test.js +0 -357
  105. package/test/cli-compose.test.js +0 -471
  106. package/test/cli-filter.test.js +0 -200
  107. package/test/cli-registry.test.js +0 -95
  108. package/test/cli-wizard-parity.test.js +0 -227
  109. package/test/entrypoint.test.js +0 -873
  110. package/test/fts.test.js +0 -141
  111. package/test/mcp-tools.test.js +0 -606
  112. package/test/openclaw-migration.test.js +0 -317
  113. package/test/red-phase.test.js +0 -181
  114. package/test/sanitize-control-chars.test.js +0 -92
  115. package/test/setup-server.test.js +0 -784
  116. package/test/update-system.test.js +0 -210
package/Dockerfile ADDED
@@ -0,0 +1,123 @@
1
+ # syntax=docker/dockerfile:1
2
+
3
+ # OpenClaw version — pin to avoid surprise upgrades in production
4
+ ARG OPENCLAW_VERSION=latest
5
+
6
+ # ──────────────────────────────────────────────
7
+ # Stage 1: deps — build MCP server native addons
8
+ # better-sqlite3 requires python3/make/g++ for node-gyp compilation.
9
+ # This stage is discarded after extracting node_modules.
10
+ # ──────────────────────────────────────────────
11
+ FROM node:22-slim AS deps
12
+
13
+ # Build tools for native addons (better-sqlite3 requires compilation)
14
+ RUN apt-get update && apt-get install -y --no-install-recommends python3 make g++ && rm -rf /var/lib/apt/lists/*
15
+
16
+ WORKDIR /build
17
+
18
+ # Copy MCP server manifest and lockfile (layer cached unless these change)
19
+ COPY mcp-server/package.json mcp-server/package-lock.json* ./mcp-server/
20
+
21
+ # Install deps without running lifecycle scripts, then rebuild better-sqlite3
22
+ # native addon explicitly. Verify with an in-memory open/close smoke test.
23
+ RUN cd mcp-server \
24
+ && npm ci --omit=dev --ignore-scripts \
25
+ && cd node_modules/better-sqlite3 \
26
+ && npx node-gyp rebuild --release \
27
+ && cd /build \
28
+ && node -e "const d=require('/build/mcp-server/node_modules/better-sqlite3');const db=d(':memory:');db.close();console.log('better-sqlite3 OK')"
29
+
30
+ # ──────────────────────────────────────────────
31
+ # Stage 2: runtime — OpenClaw + MCP server + workspace
32
+ # Migrated from ZeroClaw (Rust binary) to OpenClaw (Node.js npm package).
33
+ # OpenClaw is installed globally via npm — no custom binary build needed.
34
+ # ──────────────────────────────────────────────
35
+ FROM node:22-slim AS runtime
36
+
37
+ ARG OPENCLAW_VERSION
38
+
39
+ # Runtime system deps:
40
+ # gettext-base — envsubst for config template rendering
41
+ # tzdata — timezone support
42
+ # tini — minimal init for proper signal handling (PID 1 reaping)
43
+ # libssl3 — OpenSSL 3 shared lib needed by OpenClaw's ACP runtime (codex-acp)
44
+ # python3 — required by OpenClaw's pinned-write-helper for safe atomic file writes
45
+ RUN apt-get update && apt-get install -y --no-install-recommends gettext-base tzdata tini libssl3 python3 ca-certificates && rm -rf /var/lib/apt/lists/* \
46
+ && groupadd -r limbo && useradd --create-home -r -g limbo limbo
47
+
48
+ # Install OpenClaw globally — replaces the ZeroClaw Rust binary.
49
+ # Pinned via OPENCLAW_VERSION build arg (default: latest).
50
+ # @googleworkspace/cli (gws) — Google Calendar integration (optional feature).
51
+ RUN npm install -g "openclaw@${OPENCLAW_VERSION}" "@googleworkspace/cli"
52
+
53
+ # Apply local patch for openclaw#63851 — the guarded fetch drops FormData fields,
54
+ # breaking Groq audio transcription. Remove this once upstream PR #64349 ships in
55
+ # a released openclaw version; the patcher is idempotent and fails loudly if
56
+ # the openclaw code shape has changed.
57
+ COPY scripts/patch-openclaw-audio.mjs /tmp/patch-openclaw-audio.mjs
58
+ RUN node /tmp/patch-openclaw-audio.mjs && rm /tmp/patch-openclaw-audio.mjs
59
+
60
+ # App directories
61
+ WORKDIR /app
62
+
63
+ # MCP server: source code first, then node_modules from deps stage (overrides host binaries)
64
+ COPY --chown=limbo:limbo mcp-server/ ./mcp-server/
65
+ COPY --from=deps /build/mcp-server/node_modules ./mcp-server/node_modules
66
+
67
+ # Setup wizard server (zero dependencies — plain Node.js HTTP server)
68
+ COPY --chown=limbo:limbo setup-server/ /app/setup-server/
69
+
70
+ # System workspace files (product-owned, root-owned for read-only enforcement via symlinks)
71
+ COPY workspace/system/ ./workspace/system/
72
+
73
+ # Skills (product-owned, synced to OpenClaw workspace on boot by entrypoint)
74
+ COPY workspace/skills/ ./workspace/skills/
75
+
76
+ # User workspace templates (limbo-owned, seeded on first run)
77
+ COPY --chown=limbo:limbo workspace/templates/ ./workspace/templates/
78
+
79
+ # Migration runner (no external deps — pure Node.js stdlib)
80
+ COPY --chown=limbo:limbo migrations/ ./migrations/
81
+
82
+ # Shared libs (telegram-notify, wakeup routine)
83
+ COPY --chown=limbo:limbo lib/ ./lib/
84
+
85
+ # Package metadata (version read by wakeup routine)
86
+ COPY --chown=limbo:limbo package.json ./package.json
87
+
88
+ # User-facing release notes (parsed by wakeup routine for update messages)
89
+ COPY --chown=limbo:limbo RELEASES.md ./RELEASES.md
90
+
91
+ # OpenClaw config template (populated by entrypoint from env vars)
92
+ COPY --chown=limbo:limbo openclaw.json.template ./openclaw.json.template
93
+
94
+ # Entrypoint script
95
+ COPY scripts/entrypoint.sh /entrypoint.sh
96
+ RUN chmod +x /entrypoint.sh
97
+
98
+ # Wizard supervisor (container main process after entrypoint bootstrap) +
99
+ # standalone regen helper used by both the entrypoint and the setup-server
100
+ # to rewrite openclaw.json on boot and after wizard completion.
101
+ COPY --chown=limbo:limbo scripts/supervisor.js /app/scripts/supervisor.js
102
+ COPY --chown=limbo:limbo scripts/regen-openclaw-config.sh /app/scripts/regen-openclaw-config.sh
103
+ RUN chmod +x /app/scripts/regen-openclaw-config.sh /app/scripts/supervisor.js
104
+
105
+ # Pre-create dirs with correct ownership for image-layer defaults
106
+ RUN mkdir -p /data && chown limbo:limbo /data
107
+ RUN mkdir -p /flags && chown limbo:limbo /flags
108
+ RUN mkdir -p /home/limbo/.openclaw && chown limbo:limbo /home/limbo/.openclaw
109
+ # Fix npm cache ownership — npm install -g runs as root but limbo user needs write access at runtime
110
+ RUN mkdir -p /home/limbo/.npm && chown -R limbo:limbo /home/limbo/.npm
111
+ RUN chown limbo:limbo /app
112
+
113
+ # Data volume — vault, db, config, memory, backups, logs
114
+ VOLUME ["/data"]
115
+
116
+ # OpenClaw gateway port
117
+ EXPOSE 18789
118
+
119
+ # Run as non-root limbo user
120
+ USER limbo
121
+
122
+ # tini as init process for proper signal forwarding and zombie reaping
123
+ ENTRYPOINT ["/usr/bin/tini", "--", "/entrypoint.sh"]
package/README.md CHANGED
@@ -160,29 +160,46 @@ Limbo uses ~150 MB at rest, peaks ~300 MB during agent runs. CPU usage is neglig
160
160
  ## Architecture
161
161
 
162
162
  ```
163
- ┌─────────────────────────────────────────┐
164
- Docker Container
165
-
166
- ┌─────────────┐ ┌────────────────┐
167
- │ │ OpenClaw │◄──►│ LLM (Claude │ │
168
- │ │ gateway │ │ or OpenAI) │ │
169
- │ :18789└────────┬───────┘
170
- └──────┬──────┘
171
- ┌────────▼───────┐
172
- Telegram Bot MCP Server │ │
173
- │ limbo-vault │
174
- └────────┬───────┘
175
- └────────────────────┤
176
-
177
- /data/vault/
178
- (markdown notes) │
179
- └─────────────────────────────────────────┘
163
+ ┌──────────────────────────────────────────────────┐
164
+ Docker Container
165
+
166
+ ┌──────────────┐
167
+ │ │ Supervisor(PID 2, under tini)
168
+ └──┬────┬──┬───┘
169
+ │ │
170
+ │ │ └── Control plane :LIMBO_PORT+2 ◄── limbo CLI (host)
171
+
172
+ │ └───── Wizard port :LIMBO_PORT+1 ◄── connect-calendar /
173
+ (on-demand, forked by spawner) switch-brain browser
174
+
175
+
176
+ ┌──────────────┐ ┌────────────────────┐
177
+ OpenClaw │◄───►│ LLM provider │ │
178
+ │ gateway │ │ (anthropic/...) │
179
+ │ │ :LIMBO_PORT │ └──────────┬─────────┘ │
180
+ │ └───┬──────────┘ │ │
181
+ │ │ ┌───────────▼──────────┐ │
182
+ │ │ Telegram │ MCP Server │ │
183
+ │ ├── channel │ (limbo-vault) │ │
184
+ │ │ └───────────┬──────────┘ │
185
+ │ │ ▼ │
186
+ │ │ /data/vault/ │
187
+ │ │ (markdown notes) │
188
+ └──────┴───────────────────────────────────────────┘
189
+
190
+
191
+ Telegram
180
192
  ```
181
193
 
194
+ - **Supervisor** — container main process, owns OpenClaw + the wizard control plane
182
195
  - **OpenClaw** — Node.js runtime (~150 MB) handling connections, LLM routing, Telegram, and MCP tools
196
+ - **Control plane** — tiny HTTP API the `limbo` CLI uses to open on-demand wizards (`connect-calendar`, `switch-brain`) without restarting the container
197
+ - **Wizard port** — a setup-server child spawned on demand, used only during an active wizard
183
198
  - **MCP server** — Node.js vault read/write tools, spawned by OpenClaw
184
199
  - **Vault** — plain markdown with YAML frontmatter, persisted in a Docker volume
185
200
 
201
+ All three ports bind to the host loopback only (`127.0.0.1`), never LAN.
202
+
186
203
  ---
187
204
 
188
205
  ## Agent Installation (headless)
package/RELEASES.md CHANGED
@@ -18,6 +18,39 @@
18
18
  > - fix: technical description (#PR)
19
19
  > ```
20
20
 
21
+ ## Next release
22
+
23
+ - **Instant connect-calendar and switch-brain.** Both commands used to tear down the container, rebuild the image, and start a fresh setup wizard — that easily took 5–20 minutes. Now they take a few seconds: Limbo stays running the whole time, the wizard opens in a new window, and your changes apply live.
24
+ - **One single `.env` file.** All tokens (LLM key, Telegram, voice, search, Google) now live in `~/.limbo/config/.env`. Legacy secret files from older installs are migrated automatically on first start after this update — nothing for you to do.
25
+ - **Cloudflare tunnel self-heals.** If a previous `limbo connect-calendar` left a dangling tunnel on your Cloudflare account, `limbo update` cleans it up. Also blocks the case where the tunnel DNS landed in the wrong zone.
26
+
27
+ ### Heads up — **if you already had Google Calendar connected**
28
+
29
+ You need to add one new URL to your Google OAuth client (one-time, ~30 seconds):
30
+
31
+ 1. Open <https://console.cloud.google.com/apis/credentials>
32
+ 2. Click the OAuth 2.0 Client ID you use for Limbo
33
+ 3. Under **Authorized redirect URIs**, add: `http://localhost:18790/auth/google/callback`
34
+ (if you use a custom `LIMBO_PORT`, use `<LIMBO_PORT + 1>` instead of 18790)
35
+ 4. Save
36
+
37
+ Until you do this, `limbo connect-calendar` will fail with `redirect_uri_mismatch`. Existing connections keep working — this is only needed if you re-run connect-calendar.
38
+
39
+ ---
40
+
41
+ ### Technical changelog
42
+
43
+ - feat(supervisor): wizard sidecar — on-demand wizards over a TCP control plane
44
+ - feat(cli): migrate `switch-brain` and `connect-calendar` to the control plane (no more container rebuild)
45
+ - feat(supervisor): control-plane HTTP API bound to 127.0.0.1:LIMBO_PORT+2 with Host-header allowlist
46
+ - fix(supervisor): set `OPENCLAW_NO_RESPAWN=1` on the OpenClaw child so config reloads become in-process restarts (no fork+exec, no port collisions)
47
+ - fix(supervisor): respawn OpenClaw on clean exit with a sliding-window crash-loop guard (5 restarts / 60 s)
48
+ - feat(supervisor): enforce single active wizard session at a time (409 Conflict on concurrent POST /wizard)
49
+ - feat(cli): install SIGINT/SIGTERM cleanup so Ctrl+C during a wizard cancels the session on the supervisor
50
+ - fix(setup-server): honour `SETUP_TOKEN` injected by the supervisor (was generating a mismatched token)
51
+ - fix(secrets): consolidate all tokens into `~/.limbo/config/.env`; drop `/run/secrets` and `~/.limbo/secrets/`
52
+ - fix(cli): cloudflare tunnel self-heal via blocking DNS check + stale-tunnel sweep on start
53
+
21
54
  ## v1.30.0
22
55
 
23
56
  - Limbo now notifies you when a new version is available