@lobu/cli 6.0.0 → 6.1.1

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 (222) hide show
  1. package/README.md +20 -27
  2. package/dist/bundled-skills/lobu/SKILL.md +12 -12
  3. package/dist/commands/_lib/apply/apply-cmd.d.ts +2 -0
  4. package/dist/commands/_lib/apply/apply-cmd.d.ts.map +1 -1
  5. package/dist/commands/_lib/apply/apply-cmd.js +26 -0
  6. package/dist/commands/_lib/apply/apply-cmd.js.map +1 -1
  7. package/dist/commands/_lib/apply/client.d.ts +1 -1
  8. package/dist/commands/_lib/apply/client.d.ts.map +1 -1
  9. package/dist/commands/_lib/apply/desired-state.js +6 -6
  10. package/dist/commands/_lib/apply/desired-state.js.map +1 -1
  11. package/dist/commands/agent.d.ts +7 -0
  12. package/dist/commands/agent.d.ts.map +1 -1
  13. package/dist/commands/agent.js +65 -1
  14. package/dist/commands/agent.js.map +1 -1
  15. package/dist/commands/chat.d.ts +12 -9
  16. package/dist/commands/chat.d.ts.map +1 -1
  17. package/dist/commands/chat.js +117 -56
  18. package/dist/commands/chat.js.map +1 -1
  19. package/dist/commands/dev.d.ts +15 -7
  20. package/dist/commands/dev.d.ts.map +1 -1
  21. package/dist/commands/dev.js +79 -44
  22. package/dist/commands/dev.js.map +1 -1
  23. package/dist/commands/doctor.d.ts +1 -0
  24. package/dist/commands/doctor.d.ts.map +1 -1
  25. package/dist/commands/doctor.js +136 -0
  26. package/dist/commands/doctor.js.map +1 -1
  27. package/dist/commands/eval.d.ts +8 -0
  28. package/dist/commands/eval.d.ts.map +1 -1
  29. package/dist/commands/eval.js +56 -1
  30. package/dist/commands/eval.js.map +1 -1
  31. package/dist/commands/init.d.ts +20 -5
  32. package/dist/commands/init.d.ts.map +1 -1
  33. package/dist/commands/init.js +332 -183
  34. package/dist/commands/init.js.map +1 -1
  35. package/dist/commands/link.d.ts +11 -0
  36. package/dist/commands/link.d.ts.map +1 -0
  37. package/dist/commands/link.js +28 -0
  38. package/dist/commands/link.js.map +1 -0
  39. package/dist/commands/login.d.ts.map +1 -1
  40. package/dist/commands/login.js +14 -2
  41. package/dist/commands/login.js.map +1 -1
  42. package/dist/commands/memory/_lib/browser-auth-cmd.d.ts.map +1 -1
  43. package/dist/commands/memory/_lib/browser-auth-cmd.js +4 -4
  44. package/dist/commands/memory/_lib/browser-auth-cmd.js.map +1 -1
  45. package/dist/commands/memory/_lib/install-targets.d.ts.map +1 -1
  46. package/dist/commands/memory/_lib/install-targets.js +1 -5
  47. package/dist/commands/memory/_lib/install-targets.js.map +1 -1
  48. package/dist/commands/memory/_lib/mcp.d.ts +2 -2
  49. package/dist/commands/memory/_lib/mcp.d.ts.map +1 -1
  50. package/dist/commands/memory/_lib/mcp.js +24 -12
  51. package/dist/commands/memory/_lib/mcp.js.map +1 -1
  52. package/dist/commands/memory/_lib/openclaw-auth.d.ts +1 -0
  53. package/dist/commands/memory/_lib/openclaw-auth.d.ts.map +1 -1
  54. package/dist/commands/memory/_lib/openclaw-auth.js +14 -3
  55. package/dist/commands/memory/_lib/openclaw-auth.js.map +1 -1
  56. package/dist/commands/memory/_lib/openclaw-cmd.js +1 -1
  57. package/dist/commands/memory/_lib/openclaw-cmd.js.map +1 -1
  58. package/dist/commands/memory/_lib/schema.d.ts +2 -2
  59. package/dist/commands/memory/_lib/schema.d.ts.map +1 -1
  60. package/dist/commands/memory/_lib/schema.js +3 -3
  61. package/dist/commands/memory/_lib/schema.js.map +1 -1
  62. package/dist/commands/memory/_lib/seed-cmd.d.ts.map +1 -1
  63. package/dist/commands/memory/_lib/seed-cmd.js +5 -6
  64. package/dist/commands/memory/_lib/seed-cmd.js.map +1 -1
  65. package/dist/commands/memory/run.d.ts.map +1 -1
  66. package/dist/commands/memory/run.js +2 -2
  67. package/dist/commands/memory/run.js.map +1 -1
  68. package/dist/commands/platforms/platform-prompts.d.ts +0 -1
  69. package/dist/commands/platforms/platform-prompts.d.ts.map +1 -1
  70. package/dist/commands/platforms/platform-prompts.js +54 -8
  71. package/dist/commands/platforms/platform-prompts.js.map +1 -1
  72. package/dist/commands/telemetry.d.ts +10 -0
  73. package/dist/commands/telemetry.d.ts.map +1 -0
  74. package/dist/commands/telemetry.js +68 -0
  75. package/dist/commands/telemetry.js.map +1 -0
  76. package/dist/commands/whoami.d.ts.map +1 -1
  77. package/dist/commands/whoami.js +1 -1
  78. package/dist/commands/whoami.js.map +1 -1
  79. package/dist/connectors/README.md +534 -0
  80. package/dist/connectors/__tests__/browser-scraper-utils.test.ts +186 -0
  81. package/dist/connectors/browser-scraper-utils.ts +214 -0
  82. package/dist/connectors/capterra.ts +273 -0
  83. package/dist/connectors/g2.ts +286 -0
  84. package/dist/connectors/github.ts +1553 -0
  85. package/dist/connectors/glassdoor.ts +291 -0
  86. package/dist/connectors/gmaps.ts +197 -0
  87. package/dist/connectors/google_calendar.ts +631 -0
  88. package/dist/connectors/google_gmail.ts +751 -0
  89. package/dist/connectors/google_photos.ts +776 -0
  90. package/dist/connectors/google_play.ts +342 -0
  91. package/dist/connectors/hackernews.ts +471 -0
  92. package/dist/connectors/index.ts +23 -0
  93. package/dist/connectors/ios_appstore.ts +226 -0
  94. package/dist/connectors/linkedin.ts +471 -0
  95. package/dist/connectors/microsoft_outlook.ts +410 -0
  96. package/dist/connectors/producthunt.ts +471 -0
  97. package/dist/connectors/reddit.ts +600 -0
  98. package/dist/connectors/rss.ts +448 -0
  99. package/dist/connectors/spotify.ts +590 -0
  100. package/dist/connectors/trustpilot.ts +199 -0
  101. package/dist/connectors/website.ts +629 -0
  102. package/dist/connectors/whatsapp.ts +1073 -0
  103. package/dist/connectors/x.ts +526 -0
  104. package/dist/connectors/youtube.ts +666 -0
  105. package/dist/db/migrations/00000000000000_baseline.sql +4867 -0
  106. package/dist/db/migrations/20260405193000_add_mcp_sessions.sql +33 -0
  107. package/dist/db/migrations/20260408120000_remove_system_connectors.sql +48 -0
  108. package/dist/db/migrations/20260408120001_optional_compiled_code.sql +6 -0
  109. package/dist/db/migrations/20260409110000_add_active_watcher_run_index.sql +9 -0
  110. package/dist/db/migrations/20260409130000_connector_default_config.sql +5 -0
  111. package/dist/db/migrations/20260410120000_add_agent_secrets.sql +25 -0
  112. package/dist/db/migrations/20260413170000_add_watcher_group_id.sql +67 -0
  113. package/dist/db/migrations/20260416120000_add_entity_wa_jid_index.sql +14 -0
  114. package/dist/db/migrations/20260417100000_add_entity_identities.sql +77 -0
  115. package/dist/db/migrations/20260418100000_add_auth_runs.sql +83 -0
  116. package/dist/db/migrations/20260418110000_add_runs_created_by_user.sql +18 -0
  117. package/dist/db/migrations/20260419120000_add_event_identity_indexes.sql +56 -0
  118. package/dist/db/migrations/20260420120000_extend_reserved_org_slugs.sql +56 -0
  119. package/dist/db/migrations/20260424030000_add_watcher_run_correlation.sql +52 -0
  120. package/dist/db/migrations/20260424130000_relax_events_client_id_fk.sql +47 -0
  121. package/dist/db/migrations/20260425100000_normalize_watcher_feedback.sql +91 -0
  122. package/dist/db/migrations/20260425120000_add_run_diagnostics.sql +20 -0
  123. package/dist/db/migrations/20260425130000_add_repair_agent_plumbing.sql +46 -0
  124. package/dist/db/migrations/20260426120000_entities_entity_type_fk.sql +101 -0
  125. package/dist/db/migrations/20260426130000_db_integrity_cleanup.sql +104 -0
  126. package/dist/db/migrations/20260426130001_db_integrity_cleanup_concurrent.sql +187 -0
  127. package/dist/db/migrations/20260427133000_events_created_by_nullable.sql +74 -0
  128. package/dist/db/migrations/20260427140000_identity_engine_indexes.sql +140 -0
  129. package/dist/db/migrations/20260427150000_drop_events_source_id.sql +177 -0
  130. package/dist/db/migrations/20260427160000_drop_dead_schema.sql +76 -0
  131. package/dist/db/migrations/20260427170000_market_founder_to_member.sql +364 -0
  132. package/dist/db/migrations/20260428040000_cascade_events_watchers_org_fk.sql +66 -0
  133. package/dist/db/migrations/20260428050000_add_runs_approved_input.sql +9 -0
  134. package/dist/db/migrations/20260429010000_auth_profile_tenant_scoped_fk.sql +79 -0
  135. package/dist/db/migrations/20260429060000_extend_runs_for_lobu_queue.sql +108 -0
  136. package/dist/db/migrations/20260429120000_agent_changed_notify.sql +97 -0
  137. package/dist/db/migrations/20260429120100_user_auth_profiles_and_model_prefs.sql +36 -0
  138. package/dist/db/migrations/20260429120200_fix_notify_old_keys.sql +130 -0
  139. package/dist/db/migrations/20260429130000_oauth_states_cli_sessions_rate_limits.sql +83 -0
  140. package/dist/db/migrations/20260429140000_phase8_grants_chat_connections_mcp_sessions.sql +84 -0
  141. package/dist/db/migrations/20260429140100_runs_priority_expires_at_retry_delay.sql +44 -0
  142. package/dist/db/migrations/20260429180000_drop_invalidatable_cache_triggers.sql +25 -0
  143. package/dist/db/migrations/20260430005614_agents_apply_fields.sql +21 -0
  144. package/dist/db/migrations/20260430022231_fix_connection_config_encryption.sql +69 -0
  145. package/dist/db/migrations/20260430151215_add_task_run_type.sql +77 -0
  146. package/dist/db/migrations/20260501000000_drop_cli_sessions.sql +27 -0
  147. package/dist/db/migrations/20260501133000_lobu_memory_mcp_id.sql +117 -0
  148. package/dist/db/migrations/20260502000000_drop_chat_connections.sql +60 -0
  149. package/dist/db/migrations/20260503000000_agent_secrets_org_scope.sql +56 -0
  150. package/dist/db/migrations/20260504000000_flatten_agents_drop_sandbox_model.sql +48 -0
  151. package/dist/index.d.ts.map +1 -1
  152. package/dist/index.js +147 -23
  153. package/dist/index.js.map +1 -1
  154. package/dist/internal/api-client.d.ts +4 -8
  155. package/dist/internal/api-client.d.ts.map +1 -1
  156. package/dist/internal/api-client.js +1 -1
  157. package/dist/internal/api-client.js.map +1 -1
  158. package/dist/internal/context.js +2 -2
  159. package/dist/internal/context.js.map +1 -1
  160. package/dist/internal/credentials.d.ts.map +1 -1
  161. package/dist/internal/credentials.js +6 -1
  162. package/dist/internal/credentials.js.map +1 -1
  163. package/dist/internal/index.d.ts +2 -3
  164. package/dist/internal/index.d.ts.map +1 -1
  165. package/dist/internal/index.js +2 -2
  166. package/dist/internal/index.js.map +1 -1
  167. package/dist/internal/oauth.d.ts +7 -6
  168. package/dist/internal/oauth.d.ts.map +1 -1
  169. package/dist/internal/oauth.js +3 -3
  170. package/dist/internal/project-link.d.ts +10 -0
  171. package/dist/internal/project-link.d.ts.map +1 -0
  172. package/dist/internal/project-link.js +48 -0
  173. package/dist/internal/project-link.js.map +1 -0
  174. package/dist/providers.json +2 -2
  175. package/dist/server.bundle.mjs +3173 -4404
  176. package/dist/start-local.bundle.mjs +71481 -0
  177. package/dist/templates/README.md.tmpl +10 -11
  178. package/package.json +14 -12
  179. package/dist/__tests__/chat.integration.test.d.ts +0 -2
  180. package/dist/__tests__/chat.integration.test.d.ts.map +0 -1
  181. package/dist/__tests__/chat.integration.test.js +0 -337
  182. package/dist/__tests__/chat.integration.test.js.map +0 -1
  183. package/dist/__tests__/dev.test.d.ts +0 -2
  184. package/dist/__tests__/dev.test.d.ts.map +0 -1
  185. package/dist/__tests__/dev.test.js +0 -25
  186. package/dist/__tests__/dev.test.js.map +0 -1
  187. package/dist/__tests__/init-memory.test.d.ts +0 -2
  188. package/dist/__tests__/init-memory.test.d.ts.map +0 -1
  189. package/dist/__tests__/init-memory.test.js +0 -45
  190. package/dist/__tests__/init-memory.test.js.map +0 -1
  191. package/dist/__tests__/token.test.d.ts +0 -2
  192. package/dist/__tests__/token.test.d.ts.map +0 -1
  193. package/dist/__tests__/token.test.js +0 -52
  194. package/dist/__tests__/token.test.js.map +0 -1
  195. package/dist/commands/_lib/apply/__tests__/client.test.d.ts +0 -2
  196. package/dist/commands/_lib/apply/__tests__/client.test.d.ts.map +0 -1
  197. package/dist/commands/_lib/apply/__tests__/client.test.js +0 -23
  198. package/dist/commands/_lib/apply/__tests__/client.test.js.map +0 -1
  199. package/dist/commands/_lib/apply/__tests__/desired-state.test.d.ts +0 -2
  200. package/dist/commands/_lib/apply/__tests__/desired-state.test.d.ts.map +0 -1
  201. package/dist/commands/_lib/apply/__tests__/desired-state.test.js +0 -140
  202. package/dist/commands/_lib/apply/__tests__/desired-state.test.js.map +0 -1
  203. package/dist/commands/_lib/apply/__tests__/diff.test.d.ts +0 -2
  204. package/dist/commands/_lib/apply/__tests__/diff.test.d.ts.map +0 -1
  205. package/dist/commands/_lib/apply/__tests__/diff.test.js +0 -378
  206. package/dist/commands/_lib/apply/__tests__/diff.test.js.map +0 -1
  207. package/dist/commands/apply.d.ts +0 -3
  208. package/dist/commands/apply.d.ts.map +0 -1
  209. package/dist/commands/apply.js +0 -5
  210. package/dist/commands/apply.js.map +0 -1
  211. package/dist/commands/memory/_lib/openclaw-auth.test.d.ts +0 -2
  212. package/dist/commands/memory/_lib/openclaw-auth.test.d.ts.map +0 -1
  213. package/dist/commands/memory/_lib/openclaw-auth.test.js +0 -9
  214. package/dist/commands/memory/_lib/openclaw-auth.test.js.map +0 -1
  215. package/dist/internal/__tests__/api-client.test.d.ts +0 -2
  216. package/dist/internal/__tests__/api-client.test.d.ts.map +0 -1
  217. package/dist/internal/__tests__/api-client.test.js +0 -95
  218. package/dist/internal/__tests__/api-client.test.js.map +0 -1
  219. package/dist/internal/__tests__/context.test.d.ts +0 -2
  220. package/dist/internal/__tests__/context.test.d.ts.map +0 -1
  221. package/dist/internal/__tests__/context.test.js +0 -77
  222. package/dist/internal/__tests__/context.test.js.map +0 -1
@@ -0,0 +1,27 @@
1
+ -- migrate:up
2
+
3
+ -- The bespoke `lobu login` device-code flow that backed `cli_sessions` has
4
+ -- been replaced with standard OAuth 2.0 device-code (issued by the existing
5
+ -- Lobu IdP). The CLI now mints OAuth bearer tokens, so `cli_sessions` is
6
+ -- dead.
7
+ DROP INDEX IF EXISTS public.cli_sessions_user_id_idx;
8
+ DROP INDEX IF EXISTS public.cli_sessions_expires_at_idx;
9
+ DROP TABLE IF EXISTS public.cli_sessions;
10
+
11
+ -- migrate:down
12
+
13
+ CREATE TABLE IF NOT EXISTS public.cli_sessions (
14
+ session_id text PRIMARY KEY,
15
+ user_id text NOT NULL,
16
+ email text,
17
+ name text,
18
+ refresh_token_id text NOT NULL,
19
+ expires_at timestamptz NOT NULL,
20
+ created_at timestamptz NOT NULL DEFAULT now()
21
+ );
22
+
23
+ CREATE INDEX IF NOT EXISTS cli_sessions_user_id_idx
24
+ ON public.cli_sessions (user_id);
25
+
26
+ CREATE INDEX IF NOT EXISTS cli_sessions_expires_at_idx
27
+ ON public.cli_sessions (expires_at);
@@ -0,0 +1,117 @@
1
+ -- migrate:up
2
+
3
+ UPDATE public.agents
4
+ SET mcp_servers = (mcp_servers - 'lobu') || jsonb_build_object('lobu-memory', mcp_servers->'lobu'),
5
+ updated_at = now()
6
+ WHERE mcp_servers ? 'lobu'
7
+ AND NOT (mcp_servers ? 'lobu-memory');
8
+
9
+ UPDATE public.agents
10
+ SET mcp_servers = mcp_servers - 'lobu',
11
+ updated_at = now()
12
+ WHERE mcp_servers ? 'lobu';
13
+
14
+ UPDATE public.agents a
15
+ SET pre_approved_tools = COALESCE((
16
+ SELECT jsonb_agg(DISTINCT mapped.value)
17
+ FROM (
18
+ SELECT CASE
19
+ WHEN tool.value #>> '{}' LIKE '/mcp/lobu/tools/%'
20
+ OR tool.value #>> '{}' LIKE '/mcp/lobu-memory/tools/%'
21
+ THEN to_jsonb('/mcp/lobu-memory/tools/*'::text)
22
+ ELSE tool.value
23
+ END AS value
24
+ FROM jsonb_array_elements(COALESCE(a.pre_approved_tools, '[]'::jsonb)) AS tool(value)
25
+
26
+ UNION ALL
27
+
28
+ SELECT to_jsonb('/mcp/lobu-memory/tools/*'::text) AS value
29
+ WHERE a.mcp_servers ? 'lobu-memory'
30
+ ) AS mapped
31
+ ), '[]'::jsonb),
32
+ updated_at = now()
33
+ WHERE a.mcp_servers ? 'lobu-memory'
34
+ OR EXISTS (
35
+ SELECT 1
36
+ FROM jsonb_array_elements(COALESCE(a.pre_approved_tools, '[]'::jsonb)) AS tool(value)
37
+ WHERE tool.value #>> '{}' LIKE '/mcp/lobu/tools/%'
38
+ OR tool.value #>> '{}' LIKE '/mcp/lobu-memory/tools/%'
39
+ );
40
+
41
+ INSERT INTO public.grants (agent_id, kind, pattern, expires_at, granted_at, denied)
42
+ SELECT g.agent_id,
43
+ g.kind,
44
+ '/mcp/lobu-memory/tools/*',
45
+ CASE
46
+ WHEN bool_or(g.expires_at IS NULL) THEN NULL::timestamptz
47
+ ELSE max(g.expires_at)
48
+ END,
49
+ now(),
50
+ bool_or(g.denied)
51
+ FROM public.grants g
52
+ WHERE g.kind = 'mcp_tool'
53
+ AND (g.pattern LIKE '/mcp/lobu/tools/%' OR g.pattern LIKE '/mcp/lobu-memory/tools/%')
54
+ GROUP BY g.agent_id, g.kind
55
+ ON CONFLICT (agent_id, kind, pattern) DO UPDATE SET
56
+ expires_at = CASE
57
+ WHEN public.grants.expires_at IS NULL THEN EXCLUDED.expires_at
58
+ WHEN EXCLUDED.expires_at IS NULL THEN public.grants.expires_at
59
+ ELSE LEAST(public.grants.expires_at, EXCLUDED.expires_at)
60
+ END,
61
+ granted_at = EXCLUDED.granted_at,
62
+ denied = public.grants.denied OR EXCLUDED.denied;
63
+
64
+ DELETE FROM public.grants
65
+ WHERE kind = 'mcp_tool'
66
+ AND pattern LIKE '/mcp/lobu/tools/%';
67
+
68
+ -- migrate:down
69
+
70
+ UPDATE public.agents
71
+ SET mcp_servers = (mcp_servers - 'lobu-memory') || jsonb_build_object('lobu', mcp_servers->'lobu-memory'),
72
+ updated_at = now()
73
+ WHERE mcp_servers ? 'lobu-memory'
74
+ AND NOT (mcp_servers ? 'lobu');
75
+
76
+ UPDATE public.agents a
77
+ SET pre_approved_tools = COALESCE((
78
+ SELECT jsonb_agg(DISTINCT CASE
79
+ WHEN tool.value #>> '{}' LIKE '/mcp/lobu-memory/tools/%'
80
+ THEN to_jsonb('/mcp/lobu/tools/*'::text)
81
+ ELSE tool.value
82
+ END)
83
+ FROM jsonb_array_elements(COALESCE(a.pre_approved_tools, '[]'::jsonb)) AS tool(value)
84
+ ), '[]'::jsonb),
85
+ updated_at = now()
86
+ WHERE EXISTS (
87
+ SELECT 1
88
+ FROM jsonb_array_elements(COALESCE(a.pre_approved_tools, '[]'::jsonb)) AS tool(value)
89
+ WHERE tool.value #>> '{}' LIKE '/mcp/lobu-memory/tools/%'
90
+ );
91
+
92
+ INSERT INTO public.grants (agent_id, kind, pattern, expires_at, granted_at, denied)
93
+ SELECT g.agent_id,
94
+ g.kind,
95
+ '/mcp/lobu/tools/*',
96
+ CASE
97
+ WHEN bool_or(g.expires_at IS NULL) THEN NULL::timestamptz
98
+ ELSE max(g.expires_at)
99
+ END,
100
+ now(),
101
+ bool_or(g.denied)
102
+ FROM public.grants g
103
+ WHERE g.kind = 'mcp_tool'
104
+ AND g.pattern LIKE '/mcp/lobu-memory/tools/%'
105
+ GROUP BY g.agent_id, g.kind
106
+ ON CONFLICT (agent_id, kind, pattern) DO UPDATE SET
107
+ expires_at = CASE
108
+ WHEN public.grants.expires_at IS NULL THEN EXCLUDED.expires_at
109
+ WHEN EXCLUDED.expires_at IS NULL THEN public.grants.expires_at
110
+ ELSE LEAST(public.grants.expires_at, EXCLUDED.expires_at)
111
+ END,
112
+ granted_at = EXCLUDED.granted_at,
113
+ denied = public.grants.denied OR EXCLUDED.denied;
114
+
115
+ DELETE FROM public.grants
116
+ WHERE kind = 'mcp_tool'
117
+ AND pattern LIKE '/mcp/lobu-memory/tools/%';
@@ -0,0 +1,60 @@
1
+ -- migrate:up
2
+ -- Drop chat_connections table. Connection state is now unified in
3
+ -- agent_connections, which ChatInstanceManager reads/writes directly.
4
+ -- Secret fields (botToken, signingSecret, etc.) live as `secret://`
5
+ -- refs inside the row's `config` JSON and resolve at runtime through
6
+ -- SecretStoreRegistry — backed by Postgres by default, pluggable to
7
+ -- AWS Secrets Manager / Vault / k8s for ops who need it.
8
+
9
+ -- Copy any existing chat_connections rows into agent_connections so a
10
+ -- live deployment with provisioned chat bots doesn't lose them. Configs
11
+ -- carrying the legacy `enc:v1:` ciphertext are handled at read time by
12
+ -- decryptLegacyEncryptedConfig in postgres-stores.ts; refs pass through
13
+ -- unchanged. ON CONFLICT DO NOTHING covers the case where rows have
14
+ -- already been mirrored by an in-flight write through the manager.
15
+ -- agent_connections.agent_id is NOT NULL, but chat_connections.template_agent_id
16
+ -- was nullable. Skip orphaned rows (no parent agent) — they could not start
17
+ -- in the current model anyway.
18
+ -- Guarded by to_regclass: deployments that never had chat_connections
19
+ -- (table created with IF NOT EXISTS in 20260429140000 and never used) skip
20
+ -- the copy entirely instead of erroring on the missing relation.
21
+ DO $$
22
+ BEGIN
23
+ IF to_regclass('public.chat_connections') IS NOT NULL THEN
24
+ INSERT INTO public.agent_connections (
25
+ id, agent_id, platform, config, settings, metadata,
26
+ status, error_message, created_at, updated_at
27
+ )
28
+ SELECT
29
+ id, template_agent_id, platform, config, settings, metadata,
30
+ status, error_message, created_at, updated_at
31
+ FROM public.chat_connections
32
+ WHERE template_agent_id IS NOT NULL
33
+ ON CONFLICT (id) DO NOTHING;
34
+ END IF;
35
+ END $$;
36
+
37
+ DROP TABLE IF EXISTS public.chat_connections;
38
+
39
+ -- migrate:down
40
+ -- Recreate chat_connections for rollback. Data would need to be re-seeded.
41
+
42
+ CREATE TABLE IF NOT EXISTS public.chat_connections (
43
+ id text PRIMARY KEY,
44
+ platform text NOT NULL,
45
+ template_agent_id text REFERENCES public.agents(id) ON DELETE CASCADE,
46
+ config jsonb NOT NULL,
47
+ settings jsonb NOT NULL DEFAULT '{}'::jsonb,
48
+ metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
49
+ status text NOT NULL DEFAULT 'active',
50
+ error_message text,
51
+ created_at timestamptz NOT NULL DEFAULT now(),
52
+ updated_at timestamptz NOT NULL DEFAULT now()
53
+ );
54
+
55
+ CREATE INDEX IF NOT EXISTS chat_connections_template_agent_id_idx
56
+ ON public.chat_connections (template_agent_id)
57
+ WHERE template_agent_id IS NOT NULL;
58
+
59
+ CREATE INDEX IF NOT EXISTS chat_connections_platform_idx
60
+ ON public.chat_connections (platform);
@@ -0,0 +1,56 @@
1
+ -- migrate:up
2
+
3
+ -- agent_secrets used a global `(name)` namespace, so two organizations
4
+ -- storing the same key (e.g. `ANTHROPIC_API_KEY`) would silently overwrite
5
+ -- each other. Scope rows by organization while keeping legacy rows
6
+ -- addressable: empty-string organization_id means "global" (used by
7
+ -- system env-store and any pre-existing rows from the global era).
8
+ --
9
+ -- ROLLOUT NOTE: this migration replaces the primary key on `(name)` with
10
+ -- `(organization_id, name)` non-atomically. Lobu's deployment model is a
11
+ -- single embedded Node process with atomic swap (see "Embedded-only
12
+ -- deployment" in AGENTS.md), so old + new processes never run concurrently
13
+ -- against the same database. If you're running Lobu under a rolling-deploy
14
+ -- supervisor, stop traffic before applying this migration — old pods using
15
+ -- `ON CONFLICT (name)` will fail writes against the new schema.
16
+
17
+ ALTER TABLE public.agent_secrets
18
+ ADD COLUMN IF NOT EXISTS organization_id text NOT NULL DEFAULT '';
19
+
20
+ ALTER TABLE public.agent_secrets
21
+ DROP CONSTRAINT IF EXISTS agent_secrets_pkey;
22
+
23
+ ALTER TABLE public.agent_secrets
24
+ ADD CONSTRAINT agent_secrets_pkey PRIMARY KEY (organization_id, name);
25
+
26
+ CREATE INDEX IF NOT EXISTS agent_secrets_org_id_idx
27
+ ON public.agent_secrets (organization_id);
28
+
29
+ -- migrate:down
30
+
31
+ ALTER TABLE public.agent_secrets
32
+ DROP CONSTRAINT IF EXISTS agent_secrets_pkey;
33
+
34
+ DROP INDEX IF EXISTS public.agent_secrets_org_id_idx;
35
+
36
+ -- Down-step is destructive by design: collapses per-org rows back to the
37
+ -- global namespace. The two DELETEs below pick a survivor non-deterministically
38
+ -- when multiple orgs hold the same name (global wins first; otherwise the
39
+ -- lexicographically-smaller org_id survives). Acceptable because rollback
40
+ -- after multi-org writes is already lossy — there is no "right" winner.
41
+ DELETE FROM public.agent_secrets a
42
+ USING public.agent_secrets b
43
+ WHERE a.name = b.name
44
+ AND a.organization_id <> ''
45
+ AND b.organization_id = '';
46
+
47
+ DELETE FROM public.agent_secrets a
48
+ USING public.agent_secrets b
49
+ WHERE a.name = b.name
50
+ AND a.organization_id > b.organization_id;
51
+
52
+ ALTER TABLE public.agent_secrets
53
+ ADD CONSTRAINT agent_secrets_pkey PRIMARY KEY (name);
54
+
55
+ ALTER TABLE public.agent_secrets
56
+ DROP COLUMN IF EXISTS organization_id;
@@ -0,0 +1,48 @@
1
+ -- migrate:up
2
+
3
+ -- Flatten the agents table: there is no longer a template/sandbox split.
4
+ -- One agents row = one logical agent. Definitions, providers, settings all
5
+ -- live on this row and are agent-only (not per-user).
6
+ --
7
+ -- Per-user state has its own homes:
8
+ -- - user_auth_profiles (per-user-per-agent OAuth tokens) — already canonical
9
+ -- - agent_channel_bindings (where the agent operates)
10
+ -- - agent_users (who has interacted)
11
+ --
12
+ -- ROLLOUT NOTE: this migration deletes every sandbox row. There is no
13
+ -- pre-cutover production data to preserve (per buremba). If that ever
14
+ -- changes, the rollback below restores the columns but NOT the deleted
15
+ -- rows.
16
+
17
+ -- 1. Drop sandbox rows. Anything with template_agent_id or parent_connection_id
18
+ -- set was a per-user / per-connection sandbox.
19
+ DELETE FROM public.agents
20
+ WHERE template_agent_id IS NOT NULL
21
+ OR parent_connection_id IS NOT NULL;
22
+
23
+ -- 2. Drop indexes on the going-away columns.
24
+ DROP INDEX IF EXISTS public.agents_template_agent_id_idx;
25
+ DROP INDEX IF EXISTS public.agents_parent_connection_id_idx;
26
+
27
+ -- 3. Drop the columns themselves.
28
+ ALTER TABLE public.agents DROP COLUMN IF EXISTS template_agent_id;
29
+ ALTER TABLE public.agents DROP COLUMN IF EXISTS parent_connection_id;
30
+
31
+ -- 4. Drop legacy / dead-code columns.
32
+ -- auth_profiles: superseded by user_auth_profiles table (per-user-per-agent).
33
+ -- mcp_install_notified: per-user UI dismissal state, never used at runtime.
34
+ ALTER TABLE public.agents DROP COLUMN IF EXISTS auth_profiles;
35
+ ALTER TABLE public.agents DROP COLUMN IF EXISTS mcp_install_notified;
36
+
37
+ -- migrate:down
38
+
39
+ -- Restore columns (data is gone — the DELETE is irreversible).
40
+ ALTER TABLE public.agents ADD COLUMN IF NOT EXISTS template_agent_id text;
41
+ ALTER TABLE public.agents ADD COLUMN IF NOT EXISTS parent_connection_id text;
42
+ ALTER TABLE public.agents ADD COLUMN IF NOT EXISTS auth_profiles jsonb DEFAULT '[]'::jsonb;
43
+ ALTER TABLE public.agents ADD COLUMN IF NOT EXISTS mcp_install_notified jsonb DEFAULT '{}'::jsonb;
44
+
45
+ CREATE INDEX IF NOT EXISTS agents_template_agent_id_idx
46
+ ON public.agents (template_agent_id);
47
+ CREATE INDEX IF NOT EXISTS agents_parent_connection_id_idx
48
+ ON public.agents (parent_connection_id);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA8BA,wBAAsB,MAAM,CAC1B,IAAI,GAAE,SAAS,MAAM,EAAiB,GACrC,OAAO,CAAC,IAAI,CAAC,CA2qBf"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA8BA,wBAAsB,MAAM,CAC1B,IAAI,GAAE,SAAS,MAAM,EAAiB,GACrC,OAAO,CAAC,IAAI,CAAC,CAs3Bf"}
package/dist/index.js CHANGED
@@ -29,14 +29,74 @@ export async function runCli(argv = process.argv) {
29
29
  .name("lobu")
30
30
  .description("CLI for deploying and managing AI agents on Lobu")
31
31
  .version(version);
32
+ // Group commands in --help output. Commander v14 has no native grouping,
33
+ // so we override the help formatter via addHelpText to print our own
34
+ // categorized list. The flat command list is still available.
35
+ program.addHelpText("after", `
36
+ Local dev:
37
+ init [name] Scaffold a new agent project
38
+ run | dev | start Boot the embedded Lobu stack
39
+ chat <prompt> Send a prompt to an agent and stream the response
40
+ eval [name] Run agent evaluations
41
+ validate Validate lobu.toml
42
+ doctor Health checks (deps, DB, pgvector, ports, keys)
43
+ telemetry Show / toggle anonymous error reporting
44
+
45
+ Cloud:
46
+ login | logout OAuth device-code login (or --token for CI)
47
+ whoami | status Show user / agent state
48
+ context <subcmd> Manage API contexts
49
+ org <subcmd> Manage active org slug
50
+ link | unlink Bind this directory to a (context, org)
51
+ apply | deploy Sync lobu.toml to cloud (idempotent)
52
+ agent <subcmd> CRUD agents via REST
53
+ token [create] Print or mint personal access tokens
54
+
55
+ Memory:
56
+ memory run [tool] Invoke a memory MCP tool
57
+ memory exec <script> Run a ClientSDK script
58
+ memory health Validate login + MCP connectivity
59
+ memory configure Wire OpenClaw config
60
+ memory seed [path] Provision a memory workspace
61
+ memory init Wire agents to a memory MCP endpoint
62
+ `);
32
63
  // ─── init ───────────────────────────────────────────────────────────
33
64
  program
34
65
  .command("init [name]")
35
66
  .description("Scaffold a new agent project (lobu.toml + agent files + .env)")
36
- .action(async (name) => {
67
+ .option("-y, --yes", "Skip prompts; use defaults / flag values")
68
+ .option("--here", "Scaffold into the current directory (alias for `init .`)")
69
+ .option("--port <port>", "Gateway port (default 8787)")
70
+ .option("--public-url <url>", "Public gateway URL (OAuth/webhooks)")
71
+ .option("--network <policy>", "Worker network policy: restricted | open | isolated")
72
+ .option("--provider <id>", "Provider id from `config/providers.json`")
73
+ .option("--provider-key <key>", "Provider API key (else read from env)")
74
+ .option("--platform <type>", "Chat platform: telegram | slack | discord | whatsapp | teams | gchat")
75
+ .option("--memory <choice>", "Memory backend: none | lobu-cloud | lobu-custom")
76
+ .option("--memory-url <url>", "Custom memory MCP URL (with --memory lobu-custom)")
77
+ .option("--otel-endpoint <url>", "OpenTelemetry collector endpoint")
78
+ .option("--sentry", "Enable Sentry error reporting")
79
+ .option("--no-sentry", "Disable Sentry without prompting")
80
+ .action(async (name, options) => {
37
81
  try {
38
82
  const { initCommand } = await import("./commands/init.js");
39
- await initCommand(process.cwd(), name);
83
+ // Commander gives a tristate: true for --sentry, false for
84
+ // --no-sentry, undefined for neither.
85
+ await initCommand(process.cwd(), name, {
86
+ yes: options.yes,
87
+ here: options.here,
88
+ port: options.port,
89
+ publicUrl: options.publicUrl,
90
+ network: options.network,
91
+ provider: options.provider,
92
+ providerKey: options.providerKey,
93
+ platform: options.platform,
94
+ memory: options.memory,
95
+ memoryUrl: options.memoryUrl,
96
+ otelEndpoint: options.otelEndpoint,
97
+ sentry: options.sentry === true,
98
+ noSentry: options.sentry === false,
99
+ });
40
100
  }
41
101
  catch (error) {
42
102
  console.error(chalk.red("\n Error:"), error);
@@ -46,20 +106,23 @@ export async function runCli(argv = process.argv) {
46
106
  // ─── chat ──────────────────────────────────────────────────────────
47
107
  program
48
108
  .command("chat <prompt>")
49
- .description("Send a prompt to an agent and stream the response")
109
+ .description("Send a prompt to an agent and stream the response. With --user, routes through Telegram/Slack.")
50
110
  .option("-a, --agent <id>", "Agent ID (defaults to first in lobu.toml)")
51
111
  .option("-u, --user <id>", "User ID to impersonate (e.g. telegram:12345)")
52
112
  .option("-t, --thread <id>", "Thread/conversation ID for multi-turn")
53
113
  .option("-g, --gateway <url>", `Gateway URL (default: ${GATEWAY_DEFAULT_URL})`)
54
114
  .option("--dry-run", "Process without persisting history")
55
115
  .option("--new", "Force new session (ignore existing)")
116
+ .option("-C, --continue", "Resume the last thread for this (context, agent)")
117
+ .option("--auto-approve", "Auto-approve every tool call (use only in trusted environments)")
118
+ .option("--json", "Emit raw SSE events as JSON lines instead of text")
56
119
  .option("-c, --context <name>", "Use a named context")
57
120
  .action(async (prompt, options) => {
58
121
  const { chatCommand } = await import("./commands/chat.js");
59
122
  await chatCommand(process.cwd(), prompt, options);
60
123
  });
61
124
  // ─── eval ──────────────────────────────────────────────────────────
62
- program
125
+ const evalCmd = program
63
126
  .command("eval [name]")
64
127
  .description("Run agent evaluations")
65
128
  .option("-a, --agent <id>", "Agent ID (defaults to first in lobu.toml)")
@@ -74,6 +137,16 @@ export async function runCli(argv = process.argv) {
74
137
  const { evalCommand } = await import("./commands/eval.js");
75
138
  await evalCommand(process.cwd(), name, options);
76
139
  });
140
+ evalCmd
141
+ .command("new <name>")
142
+ .description("Scaffold a new YAML eval into the agent's evals/ directory")
143
+ .option("-a, --agent <id>", "Agent ID (defaults to first in lobu.toml)")
144
+ .option("--description <text>", "Eval description")
145
+ .option("--trials <n>", "Trial count", parseInt)
146
+ .action(async (name, options) => {
147
+ const { evalNewCommand } = await import("./commands/eval.js");
148
+ await evalNewCommand(name, options);
149
+ });
77
150
  // ─── validate ───────────────────────────────────────────────────────
78
151
  program
79
152
  .command("validate")
@@ -84,18 +157,17 @@ export async function runCli(argv = process.argv) {
84
157
  if (!valid)
85
158
  process.exit(1);
86
159
  });
87
- // ─── apply ──────────────────────────────────────────────────────────
88
- // One-way `lobu.toml` → cloud org converger. GETs current state, renders
89
- // a diff, prompts to confirm, then loops over the existing CRUD endpoints
90
- // in dependency order. Re-running converges on partial failure.
160
+ // ─── apply / deploy ─────────────────────────────────────────────────
91
161
  program
92
162
  .command("apply")
163
+ .alias("deploy")
93
164
  .description("Sync lobu.toml + agent dirs to your Lobu Cloud org (idempotent)")
94
165
  .option("--dry-run", "Show the plan and exit without mutating")
95
166
  .option("--yes", "Skip the confirmation prompt (CI mode)")
96
167
  .option("--only <kind>", "Restrict to one resource family: 'agents' | 'memory'")
97
168
  .option("--org <slug>", "Org slug override (defaults to active session)")
98
169
  .option("--url <url>", "Server URL override")
170
+ .option("--force", "Bypass the project-link guard if context/org don't match")
99
171
  .action(async (options) => {
100
172
  if (options.only !== undefined &&
101
173
  options.only !== "agents" &&
@@ -103,26 +175,28 @@ export async function runCli(argv = process.argv) {
103
175
  console.error(chalk.red("\n Error:"), `--only must be 'agents' or 'memory' (got: ${options.only})`);
104
176
  process.exit(2);
105
177
  }
106
- const { lobuApplyCommand } = await import("./commands/apply.js");
107
- await lobuApplyCommand({
178
+ const { applyCommand } = await import("./commands/_lib/apply/apply-cmd.js");
179
+ await applyCommand({
108
180
  dryRun: options.dryRun,
109
181
  yes: options.yes,
110
182
  only: options.only,
111
183
  org: options.org,
112
184
  url: options.url,
185
+ force: options.force,
113
186
  });
114
187
  });
115
- // ─── run ────────────────────────────────────────────────────────────
116
- // Boots the embedded Lobu stack (gateway + workers + memory backend) as
117
- // a single Node process. Extra args are forwarded to the bundle entry.
188
+ // ─── run / dev / start ──────────────────────────────────────────────
118
189
  program
119
190
  .command("run")
191
+ .aliases(["dev", "start"])
120
192
  .description("Run the embedded Lobu stack (gateway + workers in one Node process)")
121
- .allowUnknownOption(true)
122
- .helpOption(false)
123
- .action(async (_opts, cmd) => {
193
+ .option("--port <port>", "Gateway port (overrides GATEWAY_PORT in .env)")
194
+ .option("--quiet", "Suppress startup banner; raise log level to warn")
195
+ .option("--verbose", "Lower log level to debug")
196
+ .option("--log-level <level>", "Forwarded as LOG_LEVEL to the bundle")
197
+ .action(async (options) => {
124
198
  const { devCommand } = await import("./commands/dev.js");
125
- await devCommand(process.cwd(), cmd.args);
199
+ await devCommand(process.cwd(), options);
126
200
  });
127
201
  // ─── login ──────────────────────────────────────────────────────────
128
202
  program
@@ -253,6 +327,23 @@ export async function runCli(argv = process.argv) {
253
327
  const { orgSetCommand } = await import("./commands/org.js");
254
328
  await orgSetCommand(slug, options);
255
329
  });
330
+ // ─── link / unlink ──────────────────────────────────────────────────
331
+ program
332
+ .command("link")
333
+ .description("Bind the current directory to a (context, org). Stored at .lobu/project.json.")
334
+ .option("-c, --context <name>", "Use a named context")
335
+ .option("--org <slug>", "Org slug to link (defaults to active)")
336
+ .action(async (options) => {
337
+ const { linkCommand } = await import("./commands/link.js");
338
+ await linkCommand(options);
339
+ });
340
+ program
341
+ .command("unlink")
342
+ .description("Remove the project link file")
343
+ .action(async () => {
344
+ const { unlinkCommand } = await import("./commands/link.js");
345
+ await unlinkCommand();
346
+ });
256
347
  // ─── agent ──────────────────────────────────────────────────────────
257
348
  const agent = program
258
349
  .command("agent")
@@ -288,6 +379,15 @@ export async function runCli(argv = process.argv) {
288
379
  const { agentCreateCommand } = await import("./commands/agent.js");
289
380
  await agentCreateCommand(agentId, options);
290
381
  });
382
+ agent
383
+ .command("scaffold <agentId>")
384
+ .description("Add a new local agent (agents/<id>/* + lobu.toml entry) without overwriting existing ones")
385
+ .option("--name <name>", "Display name")
386
+ .option("--description <text>", "Description")
387
+ .action(async (agentId, options) => {
388
+ const { agentScaffoldCommand } = await import("./commands/agent.js");
389
+ await agentScaffoldCommand(agentId, options);
390
+ });
291
391
  agent
292
392
  .command("update <agentId>")
293
393
  .description("Update agent metadata")
@@ -337,15 +437,39 @@ export async function runCli(argv = process.argv) {
337
437
  // ─── doctor ─────────────────────────────────────────────────────────
338
438
  program
339
439
  .command("doctor")
340
- .description("Health checks (system deps, memory MCP)")
440
+ .description("Health checks (deps, DB, pgvector, ports, provider keys)")
341
441
  .option("--memory-only", "Only check memory MCP connectivity + auth")
342
442
  .action(async (options) => {
343
443
  const { doctorCommand } = await import("./commands/doctor.js");
344
444
  await doctorCommand(options);
345
445
  });
446
+ // ─── telemetry ──────────────────────────────────────────────────────
447
+ const telemetry = program
448
+ .command("telemetry")
449
+ .description("Show or toggle anonymous error reporting (Sentry)");
450
+ telemetry
451
+ .command("status", { isDefault: true })
452
+ .description("Show whether telemetry is on or off")
453
+ .action(async () => {
454
+ const { telemetryStatusCommand } = await import("./commands/telemetry.js");
455
+ await telemetryStatusCommand();
456
+ });
457
+ telemetry
458
+ .command("on")
459
+ .description("Enable telemetry (writes SENTRY_DSN to .env)")
460
+ .option("--dsn <dsn>", "Custom Sentry DSN (defaults to Lobu's)")
461
+ .action(async (options) => {
462
+ const { telemetryOnCommand } = await import("./commands/telemetry.js");
463
+ await telemetryOnCommand(options);
464
+ });
465
+ telemetry
466
+ .command("off")
467
+ .description("Disable telemetry (removes SENTRY_DSN from .env)")
468
+ .action(async () => {
469
+ const { telemetryOffCommand } = await import("./commands/telemetry.js");
470
+ await telemetryOffCommand();
471
+ });
346
472
  // ─── memory ─────────────────────────────────────────────────────────
347
- // Memory operations live under the Lobu CLI. Auth is top-level (`lobu login`);
348
- // memory subcommands only configure endpoints and call tools.
349
473
  const memory = program
350
474
  .command("memory")
351
475
  .description("Lobu memory MCP — tools, seeding, and client configuration");
@@ -386,7 +510,7 @@ export async function runCli(argv = process.argv) {
386
510
  .option("-c, --context <name>", "Use a named context")
387
511
  .action(async (script, options) => {
388
512
  const { memoryRunCommand } = await import("./commands/memory/run.js");
389
- await memoryRunCommand("run", JSON.stringify({ script }), options);
513
+ await memoryRunCommand("run_sdk", JSON.stringify({ script }), options);
390
514
  });
391
515
  memory
392
516
  .command("health")
@@ -412,9 +536,9 @@ export async function runCli(argv = process.argv) {
412
536
  });
413
537
  memory
414
538
  .command("seed [path]")
415
- .description("Provision a Lobu memory workspace from [memory.owletto] in lobu.toml + ./models + optional ./data")
539
+ .description("Provision a Lobu memory workspace from [memory] in lobu.toml + ./models + optional ./data")
416
540
  .option("--dry-run", "Log what would be created without mutating")
417
- .option("--org <slug>", "Org slug override (defaults to [memory.owletto].org)")
541
+ .option("--org <slug>", "Org slug override (defaults to [memory].org)")
418
542
  .option("--url <url>", "Server URL override")
419
543
  .option("-c, --context <name>", "Use a named context")
420
544
  .action(async (pathArg, options) => {