bazilion 0.0.0 → 0.1.0

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 (265) hide show
  1. package/README.md +53 -152
  2. package/dist/cli.js +2730 -0
  3. package/dist/cli.js.map +1 -0
  4. package/dist/daemon.js +5888 -0
  5. package/dist/daemon.js.map +1 -0
  6. package/dist/worker.js +1830 -0
  7. package/dist/worker.js.map +1 -0
  8. package/package.json +57 -28
  9. package/.understand-anything/.understandignore +0 -25
  10. package/.understand-anything/fingerprints.json +0 -14267
  11. package/.understand-anything/knowledge-graph.json +0 -18128
  12. package/.understand-anything/meta.json +0 -6
  13. package/CLAUDE.md +0 -164
  14. package/apps/cli/package.json +0 -21
  15. package/apps/cli/src/auth-file.ts +0 -18
  16. package/apps/cli/src/client.ts +0 -37
  17. package/apps/cli/src/columnize.ts +0 -32
  18. package/apps/cli/src/commands/agent.ts +0 -574
  19. package/apps/cli/src/commands/auth.ts +0 -110
  20. package/apps/cli/src/commands/backup.ts +0 -135
  21. package/apps/cli/src/commands/completion.ts +0 -155
  22. package/apps/cli/src/commands/config.ts +0 -95
  23. package/apps/cli/src/commands/doctor.ts +0 -131
  24. package/apps/cli/src/commands/group.ts +0 -132
  25. package/apps/cli/src/commands/inbox.ts +0 -82
  26. package/apps/cli/src/commands/login.ts +0 -73
  27. package/apps/cli/src/commands/memory.ts +0 -106
  28. package/apps/cli/src/commands/profile.ts +0 -259
  29. package/apps/cli/src/commands/provider.ts +0 -170
  30. package/apps/cli/src/commands/send.ts +0 -24
  31. package/apps/cli/src/commands/serve.ts +0 -89
  32. package/apps/cli/src/commands/skill.ts +0 -120
  33. package/apps/cli/src/commands/token.ts +0 -148
  34. package/apps/cli/src/commands/trigger.ts +0 -129
  35. package/apps/cli/src/commands/uninstall.ts +0 -156
  36. package/apps/cli/src/index.ts +0 -196
  37. package/apps/cli/src/paths.ts +0 -12
  38. package/apps/cli/test/agent.test.ts +0 -213
  39. package/apps/cli/test/backup.test.ts +0 -95
  40. package/apps/cli/test/chat.test.ts +0 -539
  41. package/apps/cli/test/columnize.test.ts +0 -29
  42. package/apps/cli/test/completion.test.ts +0 -45
  43. package/apps/cli/test/config-page.test.ts +0 -151
  44. package/apps/cli/test/group.test.ts +0 -74
  45. package/apps/cli/test/helpers.ts +0 -70
  46. package/apps/cli/test/inbox-autodeliver.test.ts +0 -143
  47. package/apps/cli/test/inbox.test.ts +0 -147
  48. package/apps/cli/test/memory.test.ts +0 -69
  49. package/apps/cli/test/profile.test.ts +0 -110
  50. package/apps/cli/test/send.test.ts +0 -30
  51. package/apps/cli/test/server-fixture.ts +0 -212
  52. package/apps/cli/test/session-head.test.ts +0 -45
  53. package/apps/cli/test/skill.test.ts +0 -128
  54. package/apps/cli/test/token.test.ts +0 -109
  55. package/apps/cli/test/trigger.test.ts +0 -245
  56. package/apps/cli/tsconfig.json +0 -4
  57. package/apps/daemon/package.json +0 -31
  58. package/apps/daemon/src/app.ts +0 -41
  59. package/apps/daemon/src/core/agent/archive.ts +0 -8
  60. package/apps/daemon/src/core/agent/delete.ts +0 -30
  61. package/apps/daemon/src/core/agent/resolve.ts +0 -31
  62. package/apps/daemon/src/core/agent/spawn.ts +0 -95
  63. package/apps/daemon/src/core/agent/unarchive.ts +0 -11
  64. package/apps/daemon/src/core/availableModels.ts +0 -58
  65. package/apps/daemon/src/core/db/client.ts +0 -113
  66. package/apps/daemon/src/core/db/migrate.ts +0 -41
  67. package/apps/daemon/src/core/db/migrations/0001_init.sql +0 -179
  68. package/apps/daemon/src/core/group/delete.ts +0 -21
  69. package/apps/daemon/src/core/group/register.ts +0 -68
  70. package/apps/daemon/src/core/index.ts +0 -71
  71. package/apps/daemon/src/core/paths.ts +0 -56
  72. package/apps/daemon/src/core/profile/create.ts +0 -78
  73. package/apps/daemon/src/core/profile/delete.ts +0 -26
  74. package/apps/daemon/src/core/profile/identity.ts +0 -70
  75. package/apps/daemon/src/core/profile/load.ts +0 -45
  76. package/apps/daemon/src/core/profile/seed.ts +0 -74
  77. package/apps/daemon/src/core/profile/templates.ts +0 -60
  78. package/apps/daemon/src/core/profile/update.ts +0 -57
  79. package/apps/daemon/src/core/profile/validate.ts +0 -9
  80. package/apps/daemon/src/core/repos/agents.ts +0 -202
  81. package/apps/daemon/src/core/repos/config.ts +0 -78
  82. package/apps/daemon/src/core/repos/groups.ts +0 -55
  83. package/apps/daemon/src/core/repos/messages.ts +0 -127
  84. package/apps/daemon/src/core/repos/profiles.ts +0 -83
  85. package/apps/daemon/src/core/repos/providerModels.ts +0 -58
  86. package/apps/daemon/src/core/repos/providerState.ts +0 -37
  87. package/apps/daemon/src/core/repos/secrets.ts +0 -145
  88. package/apps/daemon/src/core/repos/skillMeta.ts +0 -49
  89. package/apps/daemon/src/core/repos/triggers.ts +0 -101
  90. package/apps/daemon/src/core/repos/webTokens.ts +0 -87
  91. package/apps/daemon/src/core/secrets.ts +0 -65
  92. package/apps/daemon/src/core/services.ts +0 -264
  93. package/apps/daemon/src/core/skills/discover.ts +0 -28
  94. package/apps/daemon/src/core/skills/import.ts +0 -136
  95. package/apps/daemon/src/core/skills/parse.ts +0 -52
  96. package/apps/daemon/src/core/skills/resolve.ts +0 -50
  97. package/apps/daemon/src/index.ts +0 -45
  98. package/apps/daemon/src/lib/agent-cancel.ts +0 -48
  99. package/apps/daemon/src/lib/agent-id.ts +0 -13
  100. package/apps/daemon/src/lib/agent-turn.ts +0 -56
  101. package/apps/daemon/src/lib/api-key.ts +0 -56
  102. package/apps/daemon/src/lib/auth.ts +0 -41
  103. package/apps/daemon/src/lib/cron.ts +0 -93
  104. package/apps/daemon/src/lib/ctx.ts +0 -80
  105. package/apps/daemon/src/lib/messaging-host.ts +0 -34
  106. package/apps/daemon/src/lib/middleware-auth.ts +0 -52
  107. package/apps/daemon/src/lib/scheduler.ts +0 -294
  108. package/apps/daemon/src/routes/agents.ts +0 -772
  109. package/apps/daemon/src/routes/auth-login.ts +0 -193
  110. package/apps/daemon/src/routes/config.ts +0 -267
  111. package/apps/daemon/src/routes/groups.ts +0 -133
  112. package/apps/daemon/src/routes/messages.ts +0 -29
  113. package/apps/daemon/src/routes/misc.ts +0 -239
  114. package/apps/daemon/src/routes/profiles.ts +0 -197
  115. package/apps/daemon/src/routes/skills.ts +0 -123
  116. package/apps/daemon/src/routes/triggers.ts +0 -29
  117. package/apps/daemon/src/runtime/auth/openai-codex.ts +0 -121
  118. package/apps/daemon/src/runtime/auto-reply/heartbeat.ts +0 -31
  119. package/apps/daemon/src/runtime/index.ts +0 -77
  120. package/apps/daemon/src/runtime/memory/files.ts +0 -103
  121. package/apps/daemon/src/runtime/memory/qmd.ts +0 -152
  122. package/apps/daemon/src/runtime/memory/types.ts +0 -16
  123. package/apps/daemon/src/runtime/pi/events.ts +0 -173
  124. package/apps/daemon/src/runtime/pi/session.ts +0 -536
  125. package/apps/daemon/src/runtime/pi/tools.ts +0 -85
  126. package/apps/daemon/src/runtime/providers/catalog.ts +0 -145
  127. package/apps/daemon/src/runtime/providers/pi-adapter.ts +0 -272
  128. package/apps/daemon/src/runtime/providers/registry.ts +0 -374
  129. package/apps/daemon/src/runtime/providers/retry.ts +0 -176
  130. package/apps/daemon/src/runtime/providers/types.ts +0 -33
  131. package/apps/daemon/src/runtime/session/prompt.ts +0 -83
  132. package/apps/daemon/src/runtime/tools/bootstrap.ts +0 -22
  133. package/apps/daemon/src/runtime/tools/home.ts +0 -114
  134. package/apps/daemon/src/runtime/tools/memory.ts +0 -81
  135. package/apps/daemon/src/runtime/tools/messaging.ts +0 -127
  136. package/apps/daemon/src/runtime/tools/registry.ts +0 -29
  137. package/apps/daemon/src/runtime/tools/types.ts +0 -13
  138. package/apps/daemon/src/runtime/tools/web-extract.ts +0 -110
  139. package/apps/daemon/src/runtime/tools/web-ssrf.ts +0 -245
  140. package/apps/daemon/src/runtime/tools/web.ts +0 -273
  141. package/apps/daemon/src/runtime/worker/entry.ts +0 -221
  142. package/apps/daemon/src/runtime/worker/ipc-protocol.ts +0 -75
  143. package/apps/daemon/src/runtime/worker/spawn.ts +0 -249
  144. package/apps/daemon/test/core/agents.test.ts +0 -319
  145. package/apps/daemon/test/core/available-models.test.ts +0 -63
  146. package/apps/daemon/test/core/config.test.ts +0 -99
  147. package/apps/daemon/test/core/groups.test.ts +0 -63
  148. package/apps/daemon/test/core/helpers.ts +0 -50
  149. package/apps/daemon/test/core/identity.test.ts +0 -85
  150. package/apps/daemon/test/core/migrations.test.ts +0 -83
  151. package/apps/daemon/test/core/profiles.test.ts +0 -182
  152. package/apps/daemon/test/core/provider-models.test.ts +0 -57
  153. package/apps/daemon/test/core/provider-state.test.ts +0 -36
  154. package/apps/daemon/test/core/skill-meta.test.ts +0 -45
  155. package/apps/daemon/test/core/skills.test.ts +0 -271
  156. package/apps/daemon/test/core/triggers.test.ts +0 -182
  157. package/apps/daemon/test/core/web-tokens.test.ts +0 -79
  158. package/apps/daemon/test/cron.test.ts +0 -90
  159. package/apps/daemon/test/runtime/heartbeat.test.ts +0 -34
  160. package/apps/daemon/test/runtime/memory-qmd.test.ts +0 -97
  161. package/apps/daemon/test/runtime/memory.test.ts +0 -78
  162. package/apps/daemon/test/runtime/messaging.test.ts +0 -213
  163. package/apps/daemon/test/runtime/mock-server.ts +0 -65
  164. package/apps/daemon/test/runtime/openai-codex-auth.test.ts +0 -116
  165. package/apps/daemon/test/runtime/providers.test.ts +0 -306
  166. package/apps/daemon/test/runtime/retry.test.ts +0 -191
  167. package/apps/daemon/test/runtime/session-head.test.ts +0 -90
  168. package/apps/daemon/test/runtime/tools-home.test.ts +0 -102
  169. package/apps/daemon/test/runtime/tools-web.test.ts +0 -206
  170. package/apps/daemon/tsconfig.json +0 -4
  171. package/apps/mobile/README.md +0 -60
  172. package/apps/mobile/app/_layout.tsx +0 -58
  173. package/apps/mobile/app/agents/[id]/chat.tsx +0 -486
  174. package/apps/mobile/app/agents/[id]/index.tsx +0 -166
  175. package/apps/mobile/app/agents/index.tsx +0 -212
  176. package/apps/mobile/app/index.tsx +0 -21
  177. package/apps/mobile/app/pair.tsx +0 -226
  178. package/apps/mobile/app/settings.tsx +0 -419
  179. package/apps/mobile/app.json +0 -49
  180. package/apps/mobile/assets/adaptive-icon.png +0 -0
  181. package/apps/mobile/assets/favicon.png +0 -0
  182. package/apps/mobile/assets/icon.png +0 -0
  183. package/apps/mobile/assets/splash-icon.png +0 -0
  184. package/apps/mobile/babel.config.js +0 -6
  185. package/apps/mobile/metro.config.js +0 -28
  186. package/apps/mobile/package.json +0 -44
  187. package/apps/mobile/src/auth.ts +0 -66
  188. package/apps/mobile/src/pair-url.ts +0 -48
  189. package/apps/mobile/src/theme-context.tsx +0 -88
  190. package/apps/mobile/src/theme.ts +0 -135
  191. package/apps/mobile/test/pair-url.test.ts +0 -46
  192. package/apps/mobile/tsconfig.json +0 -23
  193. package/apps/web/components.json +0 -25
  194. package/apps/web/package.json +0 -39
  195. package/apps/web/public/baziu.svg +0 -8
  196. package/apps/web/src/components/AgentTabs.tsx +0 -45
  197. package/apps/web/src/components/BaziuLogo.tsx +0 -21
  198. package/apps/web/src/components/ChatPane.tsx +0 -1033
  199. package/apps/web/src/components/ConfigTabs.tsx +0 -29
  200. package/apps/web/src/components/CopyButton.tsx +0 -68
  201. package/apps/web/src/components/CreateGroupDialog.tsx +0 -127
  202. package/apps/web/src/components/FieldRow.tsx +0 -94
  203. package/apps/web/src/components/Footer.tsx +0 -10
  204. package/apps/web/src/components/PawIcon.tsx +0 -15
  205. package/apps/web/src/components/Sidebar.tsx +0 -287
  206. package/apps/web/src/components/SpawnDialog.tsx +0 -129
  207. package/apps/web/src/components/ThemeToggle.tsx +0 -75
  208. package/apps/web/src/components/TopNav.tsx +0 -34
  209. package/apps/web/src/components/ui/button.tsx +0 -67
  210. package/apps/web/src/components/ui/card.tsx +0 -103
  211. package/apps/web/src/components/ui/checkbox.tsx +0 -31
  212. package/apps/web/src/components/ui/dialog.tsx +0 -168
  213. package/apps/web/src/components/ui/input.tsx +0 -19
  214. package/apps/web/src/components/ui/label.tsx +0 -22
  215. package/apps/web/src/components/ui/radio-group.tsx +0 -44
  216. package/apps/web/src/components/ui/select.tsx +0 -192
  217. package/apps/web/src/components/ui/separator.tsx +0 -26
  218. package/apps/web/src/components/ui/table.tsx +0 -116
  219. package/apps/web/src/components/ui/tabs.tsx +0 -88
  220. package/apps/web/src/components/ui/textarea.tsx +0 -18
  221. package/apps/web/src/lib/auth.ts +0 -50
  222. package/apps/web/src/lib/daemon-client.ts +0 -34
  223. package/apps/web/src/lib/md.ts +0 -45
  224. package/apps/web/src/lib/utils.ts +0 -6
  225. package/apps/web/src/lib/wire-constants.ts +0 -27
  226. package/apps/web/src/routeTree.gen.ts +0 -408
  227. package/apps/web/src/router.tsx +0 -20
  228. package/apps/web/src/routes/__root.tsx +0 -123
  229. package/apps/web/src/routes/agents/$id/inbox.tsx +0 -207
  230. package/apps/web/src/routes/agents/$id/index.tsx +0 -527
  231. package/apps/web/src/routes/agents/$id/triggers.tsx +0 -239
  232. package/apps/web/src/routes/agents/index.tsx +0 -265
  233. package/apps/web/src/routes/api/$.ts +0 -88
  234. package/apps/web/src/routes/config/index.tsx +0 -315
  235. package/apps/web/src/routes/config/services.tsx +0 -49
  236. package/apps/web/src/routes/config/tokens.tsx +0 -192
  237. package/apps/web/src/routes/groups/$id/index.tsx +0 -153
  238. package/apps/web/src/routes/groups/$id/memory.tsx +0 -321
  239. package/apps/web/src/routes/groups/index.tsx +0 -191
  240. package/apps/web/src/routes/index.tsx +0 -133
  241. package/apps/web/src/routes/login.tsx +0 -63
  242. package/apps/web/src/routes/profiles/$id.tsx +0 -549
  243. package/apps/web/src/routes/profiles/index.tsx +0 -458
  244. package/apps/web/src/routes/skills/index.tsx +0 -297
  245. package/apps/web/src/routes/welcome.tsx +0 -61
  246. package/apps/web/src/styles.css +0 -449
  247. package/apps/web/tsconfig.json +0 -25
  248. package/apps/web/vite.config.ts +0 -25
  249. package/biome.json +0 -23
  250. package/docs/agent-engine.md +0 -219
  251. package/docs/architecture.md +0 -627
  252. package/docs/backlog/README.md +0 -42
  253. package/docs/backlog/draft/BAZ-001-a2a-federation-spike.md +0 -125
  254. package/docs/openclaw-reference.md +0 -210
  255. package/packages/api-types/package.json +0 -11
  256. package/packages/api-types/src/entities.ts +0 -146
  257. package/packages/api-types/src/events.ts +0 -55
  258. package/packages/api-types/src/index.ts +0 -488
  259. package/packages/api-types/src/memory.ts +0 -15
  260. package/packages/client/package.json +0 -13
  261. package/packages/client/src/index.ts +0 -117
  262. package/pnpm-workspace.yaml +0 -3
  263. package/tsconfig.base.json +0 -23
  264. package/tsconfig.json +0 -11
  265. package/vitest.config.ts +0 -22
@@ -1,239 +0,0 @@
1
- // Single-route resources: /api/health, /api/backup, /api/tokens.
2
-
3
- import { spawn } from 'node:child_process'
4
- import { existsSync } from 'node:fs'
5
- import { homedir } from 'node:os'
6
- import { join } from 'node:path'
7
- import type {
8
- CreateTokenRequest,
9
- CreateTokenResponse,
10
- HealthReport,
11
- ListTokensResponse,
12
- } from '@bazilion/api-types'
13
- import { Hono } from 'hono'
14
- import {
15
- agentRepo,
16
- discoverSkills,
17
- groupRepo,
18
- mergeSecretsIntoEnv,
19
- parseSkillFile,
20
- profileRepo,
21
- resolvePaths,
22
- webTokenRepo,
23
- } from '../core/index.ts'
24
- import { getCtx } from '../lib/ctx.ts'
25
- import { loadProviderConfigFromEnv } from '../runtime/index.ts'
26
-
27
- export const miscRouter = new Hono()
28
-
29
- // /api/health — install diagnostics. Public (auth middleware whitelists it)
30
- // so the doctor command and external probes can run without a token.
31
- miscRouter.get('/health', (c) => {
32
- const paths = resolvePaths()
33
-
34
- const pathChecks = {
35
- home: existsSync(paths.home),
36
- db: existsSync(paths.db),
37
- auth: existsSync(paths.authFile),
38
- profiles: existsSync(paths.profilesDir),
39
- agents: existsSync(paths.agentsDir),
40
- skills: existsSync(paths.skillsDir),
41
- }
42
-
43
- let database: HealthReport['database'] = null
44
- const triggersSection: HealthReport['triggers'] = { active: 0, disabled: 0 }
45
- let tokensSection: HealthReport['tokens'] = { active: 0 }
46
- if (pathChecks.db) {
47
- try {
48
- const { db } = getCtx()
49
- database = {
50
- ok: true,
51
- profiles: profileRepo.list(db).length,
52
- activeAgents: agentRepo.list(db).length,
53
- totalAgents: agentRepo.list(db, { includeArchived: true }).length,
54
- groups: groupRepo.list(db, paths).length,
55
- }
56
- const triggerRows = db.raw
57
- .query<{ enabled: number; n: number }, []>(
58
- 'SELECT enabled, COUNT(*) AS n FROM agent_triggers GROUP BY enabled',
59
- )
60
- .all()
61
- for (const r of triggerRows) {
62
- if (r.enabled === 1) triggersSection.active = r.n
63
- else triggersSection.disabled = r.n
64
- }
65
- tokensSection = { active: webTokenRepo.list(db).length }
66
- } catch (err) {
67
- database = { ok: false, error: (err as Error).message }
68
- }
69
- }
70
-
71
- const skills = discoverSkills(paths)
72
- let parseErrors = 0
73
- for (const s of skills) {
74
- try {
75
- parseSkillFile(s.skillFile)
76
- } catch {
77
- parseErrors++
78
- }
79
- }
80
-
81
- let effectiveEnv: NodeJS.ProcessEnv = process.env
82
- let oauth: { db: import('../core/index.ts').BazilionDb; authToken: string } | undefined
83
- if (pathChecks.auth && pathChecks.db) {
84
- try {
85
- const { db, authToken } = getCtx()
86
- effectiveEnv = mergeSecretsIntoEnv(db, authToken)
87
- oauth = { db, authToken }
88
- } catch {
89
- // first-run / partially-initialized — fall through with bare env
90
- }
91
- }
92
- const providerConfig = loadProviderConfigFromEnv(effectiveEnv, oauth)
93
- const braveKey = effectiveEnv.BRAVE_API_KEY
94
- const openclawSkillsDir = join(homedir(), '.openclaw', 'skills')
95
-
96
- const CLOUD_KEYS: Array<[string, keyof typeof providerConfig]> = [
97
- ['anthropic', 'anthropic'],
98
- ['openai', 'openai'],
99
- ['google', 'google'],
100
- ['azure-openai', 'azureOpenai'],
101
- ['bedrock', 'bedrock'],
102
- ['google-vertex', 'googleVertex'],
103
- ['mistral', 'mistral'],
104
- ['groq', 'groq'],
105
- ['cerebras', 'cerebras'],
106
- ['xai', 'xai'],
107
- ['zai', 'zai'],
108
- ['huggingface', 'huggingface'],
109
- ['openrouter', 'openrouter'],
110
- ['vercel-ai-gateway', 'vercelAiGateway'],
111
- ]
112
- const providerSection: HealthReport['providers'] = {
113
- configured: CLOUD_KEYS.filter(([, key]) => providerConfig[key]).map(([name]) => name),
114
- lmstudio: {
115
- baseURL: providerConfig.lmstudio?.baseURL ?? 'http://localhost:1234/v1',
116
- hasKey: Boolean(providerConfig.lmstudio?.apiKey),
117
- },
118
- ollama: { baseURL: providerConfig.ollama?.baseURL ?? 'http://localhost:11434/v1' },
119
- }
120
-
121
- const report: HealthReport = {
122
- ok:
123
- pathChecks.home &&
124
- pathChecks.db &&
125
- pathChecks.auth &&
126
- pathChecks.profiles &&
127
- pathChecks.agents &&
128
- pathChecks.skills &&
129
- (database === null || database.ok) &&
130
- parseErrors === 0,
131
- home: paths.home,
132
- paths: pathChecks,
133
- database,
134
- skills: { installed: skills.length, parseErrors },
135
- providers: providerSection,
136
- webSearch: {
137
- bravePreview: braveKey ? `${braveKey.slice(0, 6)}…` : null,
138
- searxngUrl: effectiveEnv.SEARXNG_URL ?? null,
139
- },
140
- openclaw: {
141
- path: openclawSkillsDir,
142
- exists: existsSync(openclawSkillsDir),
143
- },
144
- triggers: triggersSection,
145
- tokens: tokensSection,
146
- scheduler: {
147
- enabled: process.env.BAZILION_SCHEDULER !== 'off',
148
- tickMs: Number(process.env.BAZILION_SCHEDULER_TICK_MS ?? 5_000),
149
- },
150
- }
151
- return c.json(report)
152
- })
153
-
154
- // /api/backup — streams a tar.gz of $BAZILION_HOME
155
- miscRouter.get('/backup', (c) => {
156
- const paths = resolvePaths()
157
- if (!existsSync(paths.home)) {
158
- return c.json({ error: `bazilion home not found at ${paths.home}` }, 404)
159
- }
160
-
161
- const proc = spawn('tar', ['-czf', '-', '-C', paths.home, '.'], {
162
- stdio: ['ignore', 'pipe', 'pipe'],
163
- })
164
-
165
- const stream = new ReadableStream({
166
- start(controller) {
167
- proc.stdout.on('data', (chunk: Buffer) => controller.enqueue(chunk))
168
- proc.stdout.on('end', () => {
169
- try {
170
- controller.close()
171
- } catch {}
172
- })
173
- proc.on('error', (err) => {
174
- try {
175
- controller.error(err)
176
- } catch {}
177
- })
178
- proc.on('exit', (code) => {
179
- if (code !== 0) {
180
- try {
181
- controller.error(new Error(`tar exited with code ${code}`))
182
- } catch {}
183
- }
184
- })
185
- },
186
- cancel() {
187
- proc.kill('SIGTERM')
188
- },
189
- })
190
-
191
- const date = new Date().toISOString().slice(0, 10)
192
- return new Response(stream, {
193
- headers: {
194
- 'content-type': 'application/gzip',
195
- 'content-disposition': `attachment; filename="bazilion-backup-${date}.tar.gz"`,
196
- },
197
- })
198
- })
199
-
200
- // /api/tokens
201
- miscRouter.get('/tokens', (c) => {
202
- const { db } = getCtx()
203
- const includeRevoked = c.req.query('includeRevoked') === '1'
204
- const tokens = webTokenRepo.list(db, { includeRevoked })
205
- return c.json({ tokens } satisfies ListTokensResponse)
206
- })
207
-
208
- miscRouter.post('/tokens', async (c) => {
209
- const body = (await c.req.json().catch(() => null)) as CreateTokenRequest | null
210
- if (!body || typeof body.label !== 'string' || !body.label.trim()) {
211
- return c.json({ error: 'label is required' }, 400)
212
- }
213
- const { db } = getCtx()
214
- const created = webTokenRepo.create(db, body.label.trim())
215
- return c.json({ token: created.token, meta: created.meta } satisfies CreateTokenResponse, 201)
216
- })
217
-
218
- miscRouter.delete('/tokens/:id', (c) => {
219
- const { db, authToken } = getCtx()
220
- const id = c.req.param('id')
221
- const existing = webTokenRepo.get(db, id)
222
- if (!existing) return c.json({ error: `token not found: ${id}` }, 404)
223
- if (existing.revokedAt) return c.json({ error: 'token already revoked' }, 409)
224
- // Refuse to revoke the bootstrap token — that's the plaintext in auth.json
225
- // the local CLI uses for loopback. Revoking it would lock the operator out
226
- // of their own daemon. Match by hash (label is editable, hash isn't).
227
- const bootstrap = webTokenRepo.findActiveByToken(db, authToken)
228
- if (bootstrap && bootstrap.id === id) {
229
- return c.json(
230
- {
231
- error:
232
- 'cannot revoke the bootstrap token — it lives in ~/.bazilion/auth.json and is the local CLI loopback credential',
233
- },
234
- 409,
235
- )
236
- }
237
- webTokenRepo.revoke(db, id)
238
- return c.body(null, 204)
239
- })
@@ -1,197 +0,0 @@
1
- // /api/profiles/* — profile CRUD + per-profile template files.
2
-
3
- import { existsSync, readFileSync, writeFileSync } from 'node:fs'
4
- import { join } from 'node:path'
5
- import type {
6
- CreateProfileRequest,
7
- FileContentResponse,
8
- ProfileFileName,
9
- PutFileRequest,
10
- SkillsMode,
11
- UpdateProfileRequest,
12
- } from '@bazilion/api-types'
13
- import { PROFILE_FILES } from '@bazilion/api-types'
14
- import { Hono } from 'hono'
15
- import {
16
- agentRepo,
17
- createProfile,
18
- DEFAULT_BOOTSTRAP,
19
- DEFAULT_IDENTITY,
20
- DEFAULT_SOUL,
21
- deleteProfile,
22
- loadProfile,
23
- profileRepo,
24
- updateProfile,
25
- } from '../core/index.ts'
26
- import { getCtx } from '../lib/ctx.ts'
27
-
28
- export const profilesRouter = new Hono()
29
-
30
- profilesRouter.get('/', (c) => {
31
- const { db } = getCtx()
32
- const profiles = profileRepo.list(db)
33
- // Hydrate with the per-profile fields the listing UI needs (agent counts,
34
- // default-skill list) so callers don't fan out to extra endpoints per row.
35
- const hydrated = profiles.map((p) => ({
36
- ...p,
37
- agentCount: agentRepo.countByProfile(db, p.id),
38
- defaultSkills: profileRepo.getDefaultSkills(db, p.id),
39
- }))
40
- return c.json(hydrated)
41
- })
42
-
43
- // /api/profiles/_/templates — built-in defaults for the SOUL/IDENTITY/BOOTSTRAP
44
- // markdown templates. Underscore prefix avoids clashing with the `:id` route.
45
- profilesRouter.get('/_/templates', (c) => {
46
- return c.json({
47
- soul: DEFAULT_SOUL,
48
- identity: DEFAULT_IDENTITY,
49
- bootstrap: DEFAULT_BOOTSTRAP,
50
- })
51
- })
52
-
53
- profilesRouter.post('/', async (c) => {
54
- const raw = (await c.req.json().catch(() => null)) as
55
- | (Record<string, unknown> & Partial<CreateProfileRequest>)
56
- | null
57
- if (!raw) return c.json({ error: 'invalid JSON body' }, 400)
58
- const id = typeof raw.id === 'string' ? raw.id : ''
59
- const defaultModel =
60
- typeof raw.defaultModel === 'string'
61
- ? raw.defaultModel
62
- : typeof raw.model === 'string'
63
- ? raw.model
64
- : ''
65
- if (!id || !defaultModel) return c.json({ error: 'id and model are required' }, 400)
66
- const name = typeof raw.name === 'string' ? raw.name : undefined
67
-
68
- const skillsMode = toSkillsMode(raw.skillsMode) ?? 'selected'
69
- const defaultSkills = csvToArray(raw.defaultSkills ?? raw.skills)
70
-
71
- const templates: {
72
- soul?: string
73
- identity?: string
74
- bootstrap?: string | null
75
- agents?: string
76
- tools?: string
77
- heartbeat?: string
78
- } = {}
79
- if (typeof raw.soul === 'string' && raw.soul.length > 0) templates.soul = raw.soul
80
- if (typeof raw.identity === 'string' && raw.identity.length > 0) templates.identity = raw.identity
81
- if (raw.skipBootstrap === true || raw.bootstrap === null) templates.bootstrap = null
82
- else if (typeof raw.bootstrap === 'string' && raw.bootstrap.length > 0)
83
- templates.bootstrap = raw.bootstrap
84
- if (typeof raw.agents === 'string' && raw.agents.length > 0) templates.agents = raw.agents
85
- if (typeof raw.tools === 'string' && raw.tools.length > 0) templates.tools = raw.tools
86
- if (typeof raw.heartbeat === 'string' && raw.heartbeat.length > 0)
87
- templates.heartbeat = raw.heartbeat
88
-
89
- const { db, paths } = getCtx()
90
- try {
91
- const profile = createProfile(db, paths, {
92
- id,
93
- name,
94
- defaultModel,
95
- skillsMode,
96
- defaultSkills,
97
- ...(Object.keys(templates).length > 0 ? { templates } : {}),
98
- })
99
- return c.json(profile, 201)
100
- } catch (err) {
101
- return c.json({ error: (err as Error).message }, 400)
102
- }
103
- })
104
-
105
- profilesRouter.get('/:id', (c) => {
106
- const { db } = getCtx()
107
- try {
108
- return c.json(loadProfile(db, c.req.param('id')))
109
- } catch (err) {
110
- return c.json({ error: (err as Error).message }, 404)
111
- }
112
- })
113
-
114
- profilesRouter.patch('/:id', async (c) => {
115
- const raw = (await c.req.json().catch(() => null)) as
116
- | (UpdateProfileRequest & Record<string, unknown>)
117
- | null
118
- if (!raw) return c.json({ error: 'invalid JSON body' }, 400)
119
-
120
- const input: UpdateProfileRequest = {}
121
- if (typeof raw.name === 'string') input.name = raw.name
122
- if (typeof raw.defaultModel === 'string' && raw.defaultModel.length > 0)
123
- input.defaultModel = raw.defaultModel
124
- if (raw.skillsMode === 'all' || raw.skillsMode === 'selected') {
125
- input.skillsMode = raw.skillsMode
126
- }
127
- const rawSkills: unknown = raw.defaultSkills
128
- if (Array.isArray(rawSkills)) {
129
- input.defaultSkills = rawSkills.filter((s): s is string => typeof s === 'string')
130
- } else if (typeof rawSkills === 'string') {
131
- input.defaultSkills = rawSkills
132
- .split(',')
133
- .map((s) => s.trim())
134
- .filter(Boolean)
135
- }
136
- const { db, paths } = getCtx()
137
- try {
138
- return c.json(updateProfile(db, paths, c.req.param('id'), input))
139
- } catch (err) {
140
- const msg = (err as Error).message
141
- return c.json({ error: msg }, msg.startsWith('profile not found') ? 404 : 400)
142
- }
143
- })
144
-
145
- profilesRouter.delete('/:id', (c) => {
146
- const { db } = getCtx()
147
- try {
148
- deleteProfile(db, c.req.param('id'))
149
- return c.body(null, 204)
150
- } catch (err) {
151
- return c.json({ error: (err as Error).message }, 400)
152
- }
153
- })
154
-
155
- profilesRouter.get('/:id/files/:file', (c) => {
156
- const { db, paths } = getCtx()
157
- if (!profileRepo.get(db, c.req.param('id')))
158
- return c.json({ error: `profile not found: ${c.req.param('id')}` }, 404)
159
- const path = resolveFilePath(paths.profilesDir, c.req.param('id'), c.req.param('file'))
160
- if (!path) return c.json({ error: `unsupported file: ${c.req.param('file')}` }, 400)
161
- if (!existsSync(path)) return c.json({ error: `file not present: ${c.req.param('file')}` }, 404)
162
- const body: FileContentResponse = { content: readFileSync(path, 'utf8') }
163
- return c.json(body)
164
- })
165
-
166
- profilesRouter.put('/:id/files/:file', async (c) => {
167
- const body = (await c.req.json().catch(() => null)) as PutFileRequest | null
168
- if (!body || typeof body.content !== 'string')
169
- return c.json({ error: 'content is required' }, 400)
170
- const { db, paths } = getCtx()
171
- if (!profileRepo.get(db, c.req.param('id')))
172
- return c.json({ error: `profile not found: ${c.req.param('id')}` }, 404)
173
- const path = resolveFilePath(paths.profilesDir, c.req.param('id'), c.req.param('file'))
174
- if (!path) return c.json({ error: `unsupported file: ${c.req.param('file')}` }, 400)
175
- writeFileSync(path, body.content)
176
- return c.body(null, 204)
177
- })
178
-
179
- function resolveFilePath(profilesDir: string, id: string, file: string): string | null {
180
- if (!(PROFILE_FILES as readonly string[]).includes(file)) return null
181
- return join(profilesDir, id, file as ProfileFileName)
182
- }
183
-
184
- function csvToArray(v: unknown): string[] | undefined {
185
- if (Array.isArray(v)) return v.filter((s): s is string => typeof s === 'string')
186
- if (typeof v === 'string' && v.length > 0) {
187
- return v
188
- .split(',')
189
- .map((s) => s.trim())
190
- .filter(Boolean)
191
- }
192
- return undefined
193
- }
194
-
195
- function toSkillsMode(v: unknown): SkillsMode | undefined {
196
- return v === 'all' || v === 'selected' ? v : undefined
197
- }
@@ -1,123 +0,0 @@
1
- // /api/skills/* — skill discovery, removal, and import (file-path or zip upload).
2
-
3
- import { existsSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
4
- import { homedir, tmpdir } from 'node:os'
5
- import { join } from 'node:path'
6
- import type { ImportSkillsRequest, ImportSkillsResponse, SkillInfo } from '@bazilion/api-types'
7
- import { Hono } from 'hono'
8
- import { discoverSkills, importSkills, parseSkillFile, skillMetaRepo } from '../core/index.ts'
9
- import { getCtx } from '../lib/ctx.ts'
10
-
11
- // 50 MiB cap — generous headroom for a bundle of skills, tight enough to
12
- // reject obviously-malicious payloads without needing a streaming upload.
13
- const MAX_ZIP_BYTES = 50 * 1024 * 1024
14
-
15
- export const skillsRouter = new Hono()
16
-
17
- skillsRouter.get('/', (c) => {
18
- const { db, paths } = getCtx()
19
- const out: SkillInfo[] = []
20
- for (const s of discoverSkills(paths)) {
21
- const meta = skillMetaRepo.get(db, s.name)
22
- const entry: SkillInfo = {
23
- name: s.name,
24
- description: '',
25
- source: meta?.source ?? null,
26
- importedAt: meta?.importedAt ?? null,
27
- }
28
- try {
29
- const parsed = parseSkillFile(s.skillFile)
30
- entry.description = parsed.frontmatter.description
31
- } catch (err) {
32
- entry.parseError = (err as Error).message
33
- }
34
- out.push(entry)
35
- }
36
- return c.json(out)
37
- })
38
-
39
- skillsRouter.delete('/:name', (c) => {
40
- const { db, paths } = getCtx()
41
- const name = c.req.param('name')
42
- const dir = paths.skillDir(name)
43
- if (!existsSync(dir)) return c.json({ error: `skill not found: ${name}` }, 404)
44
- rmSync(dir, { recursive: true, force: true })
45
- skillMetaRepo.remove(db, name)
46
- return c.body(null, 204)
47
- })
48
-
49
- skillsRouter.post('/import', async (c) => {
50
- let input: ParsedImportInput
51
- try {
52
- input = await parseImportInput(c.req.raw)
53
- } catch (err) {
54
- return c.json({ error: (err as Error).message }, 400)
55
- }
56
-
57
- const { db, paths } = getCtx()
58
- try {
59
- const result = importSkills(paths, { source: input.source, force: input.force })
60
- const now = Date.now()
61
- for (const name of result.imported) {
62
- skillMetaRepo.upsert(db, { name, source: input.sourceLabel, importedAt: now })
63
- }
64
- const res: ImportSkillsResponse = { imported: result.imported, skipped: result.skipped }
65
- return c.json(res)
66
- } catch (err) {
67
- return c.json({ error: (err as Error).message }, 400)
68
- } finally {
69
- if (input.tempZipPath) rmSync(input.tempZipPath, { recursive: true, force: true })
70
- }
71
- })
72
-
73
- interface ParsedImportInput {
74
- source: string
75
- force: boolean
76
- /** when set, a temp zip was written and should be rm'd after import */
77
- tempZipPath: string | null
78
- /** label stored in skill_meta.source (e.g. "uploaded:foo.zip" for uploads) */
79
- sourceLabel: string
80
- }
81
-
82
- async function parseImportInput(request: Request): Promise<ParsedImportInput> {
83
- const contentType = request.headers.get('content-type') ?? ''
84
- if (contentType.startsWith('multipart/form-data')) {
85
- const form = await request.formData()
86
- const file = form.get('file')
87
- if (!(file instanceof File) || file.size === 0) {
88
- throw new Error('multipart upload missing "file" field')
89
- }
90
- if (file.size > MAX_ZIP_BYTES) {
91
- throw new Error(`zip too large: ${file.size} bytes (max ${MAX_ZIP_BYTES})`)
92
- }
93
- const filename = file.name || 'upload.zip'
94
- if (!filename.toLowerCase().endsWith('.zip')) {
95
- throw new Error('uploaded file must be a .zip archive')
96
- }
97
- const tmpDir = mkdtempSync(join(tmpdir(), 'bazilion-skill-upload-'))
98
- const zipPath = join(tmpDir, filename.replace(/[^\w.-]+/g, '_'))
99
- const buf = Buffer.from(await file.arrayBuffer())
100
- writeFileSync(zipPath, buf)
101
- const forceField = form.get('force')
102
- return {
103
- source: zipPath,
104
- force: forceField === 'true' || forceField === 'on' || forceField === '1',
105
- tempZipPath: tmpDir,
106
- sourceLabel: `uploaded:${filename}`,
107
- }
108
- }
109
-
110
- const body = (await request.json().catch(() => null)) as
111
- | (Partial<ImportSkillsRequest> & { from?: string })
112
- | null
113
- if (!body) throw new Error('invalid JSON body')
114
- const from = body.source ?? body.from
115
- if (typeof from !== 'string' || !from) throw new Error('source is required')
116
- const source = from === 'openclaw' ? join(homedir(), '.openclaw', 'skills') : from
117
- return {
118
- source,
119
- force: Boolean(body.force),
120
- tempZipPath: null,
121
- sourceLabel: from,
122
- }
123
- }
@@ -1,29 +0,0 @@
1
- // /api/triggers/:id — enable/disable + delete. (Listing is per-agent at
2
- // /api/agents/:id/triggers; creation is also per-agent.)
3
-
4
- import type { UpdateTriggerRequest } from '@bazilion/api-types'
5
- import { Hono } from 'hono'
6
- import { triggerRepo } from '../core/index.ts'
7
- import { getCtx } from '../lib/ctx.ts'
8
-
9
- export const triggersRouter = new Hono()
10
-
11
- triggersRouter.delete('/:id', (c) => {
12
- const { db } = getCtx()
13
- const id = c.req.param('id')
14
- if (!triggerRepo.get(db, id)) return c.json({ error: `trigger not found: ${id}` }, 404)
15
- triggerRepo.remove(db, id)
16
- return c.body(null, 204)
17
- })
18
-
19
- triggersRouter.patch('/:id', async (c) => {
20
- const id = c.req.param('id')
21
- const body = (await c.req.json().catch(() => null)) as UpdateTriggerRequest | null
22
- if (!body) return c.json({ error: 'invalid JSON body' }, 400)
23
- const { db } = getCtx()
24
- if (!triggerRepo.get(db, id)) return c.json({ error: `trigger not found: ${id}` }, 404)
25
- if (typeof body.enabled === 'boolean') {
26
- triggerRepo.setEnabled(db, id, body.enabled)
27
- }
28
- return c.json({ trigger: triggerRepo.get(db, id) })
29
- })