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.
- package/README.md +53 -152
- package/dist/cli.js +2730 -0
- package/dist/cli.js.map +1 -0
- package/dist/daemon.js +5888 -0
- package/dist/daemon.js.map +1 -0
- package/dist/worker.js +1830 -0
- package/dist/worker.js.map +1 -0
- package/package.json +57 -28
- package/.understand-anything/.understandignore +0 -25
- package/.understand-anything/fingerprints.json +0 -14267
- package/.understand-anything/knowledge-graph.json +0 -18128
- package/.understand-anything/meta.json +0 -6
- package/CLAUDE.md +0 -164
- package/apps/cli/package.json +0 -21
- package/apps/cli/src/auth-file.ts +0 -18
- package/apps/cli/src/client.ts +0 -37
- package/apps/cli/src/columnize.ts +0 -32
- package/apps/cli/src/commands/agent.ts +0 -574
- package/apps/cli/src/commands/auth.ts +0 -110
- package/apps/cli/src/commands/backup.ts +0 -135
- package/apps/cli/src/commands/completion.ts +0 -155
- package/apps/cli/src/commands/config.ts +0 -95
- package/apps/cli/src/commands/doctor.ts +0 -131
- package/apps/cli/src/commands/group.ts +0 -132
- package/apps/cli/src/commands/inbox.ts +0 -82
- package/apps/cli/src/commands/login.ts +0 -73
- package/apps/cli/src/commands/memory.ts +0 -106
- package/apps/cli/src/commands/profile.ts +0 -259
- package/apps/cli/src/commands/provider.ts +0 -170
- package/apps/cli/src/commands/send.ts +0 -24
- package/apps/cli/src/commands/serve.ts +0 -89
- package/apps/cli/src/commands/skill.ts +0 -120
- package/apps/cli/src/commands/token.ts +0 -148
- package/apps/cli/src/commands/trigger.ts +0 -129
- package/apps/cli/src/commands/uninstall.ts +0 -156
- package/apps/cli/src/index.ts +0 -196
- package/apps/cli/src/paths.ts +0 -12
- package/apps/cli/test/agent.test.ts +0 -213
- package/apps/cli/test/backup.test.ts +0 -95
- package/apps/cli/test/chat.test.ts +0 -539
- package/apps/cli/test/columnize.test.ts +0 -29
- package/apps/cli/test/completion.test.ts +0 -45
- package/apps/cli/test/config-page.test.ts +0 -151
- package/apps/cli/test/group.test.ts +0 -74
- package/apps/cli/test/helpers.ts +0 -70
- package/apps/cli/test/inbox-autodeliver.test.ts +0 -143
- package/apps/cli/test/inbox.test.ts +0 -147
- package/apps/cli/test/memory.test.ts +0 -69
- package/apps/cli/test/profile.test.ts +0 -110
- package/apps/cli/test/send.test.ts +0 -30
- package/apps/cli/test/server-fixture.ts +0 -212
- package/apps/cli/test/session-head.test.ts +0 -45
- package/apps/cli/test/skill.test.ts +0 -128
- package/apps/cli/test/token.test.ts +0 -109
- package/apps/cli/test/trigger.test.ts +0 -245
- package/apps/cli/tsconfig.json +0 -4
- package/apps/daemon/package.json +0 -31
- package/apps/daemon/src/app.ts +0 -41
- package/apps/daemon/src/core/agent/archive.ts +0 -8
- package/apps/daemon/src/core/agent/delete.ts +0 -30
- package/apps/daemon/src/core/agent/resolve.ts +0 -31
- package/apps/daemon/src/core/agent/spawn.ts +0 -95
- package/apps/daemon/src/core/agent/unarchive.ts +0 -11
- package/apps/daemon/src/core/availableModels.ts +0 -58
- package/apps/daemon/src/core/db/client.ts +0 -113
- package/apps/daemon/src/core/db/migrate.ts +0 -41
- package/apps/daemon/src/core/db/migrations/0001_init.sql +0 -179
- package/apps/daemon/src/core/group/delete.ts +0 -21
- package/apps/daemon/src/core/group/register.ts +0 -68
- package/apps/daemon/src/core/index.ts +0 -71
- package/apps/daemon/src/core/paths.ts +0 -56
- package/apps/daemon/src/core/profile/create.ts +0 -78
- package/apps/daemon/src/core/profile/delete.ts +0 -26
- package/apps/daemon/src/core/profile/identity.ts +0 -70
- package/apps/daemon/src/core/profile/load.ts +0 -45
- package/apps/daemon/src/core/profile/seed.ts +0 -74
- package/apps/daemon/src/core/profile/templates.ts +0 -60
- package/apps/daemon/src/core/profile/update.ts +0 -57
- package/apps/daemon/src/core/profile/validate.ts +0 -9
- package/apps/daemon/src/core/repos/agents.ts +0 -202
- package/apps/daemon/src/core/repos/config.ts +0 -78
- package/apps/daemon/src/core/repos/groups.ts +0 -55
- package/apps/daemon/src/core/repos/messages.ts +0 -127
- package/apps/daemon/src/core/repos/profiles.ts +0 -83
- package/apps/daemon/src/core/repos/providerModels.ts +0 -58
- package/apps/daemon/src/core/repos/providerState.ts +0 -37
- package/apps/daemon/src/core/repos/secrets.ts +0 -145
- package/apps/daemon/src/core/repos/skillMeta.ts +0 -49
- package/apps/daemon/src/core/repos/triggers.ts +0 -101
- package/apps/daemon/src/core/repos/webTokens.ts +0 -87
- package/apps/daemon/src/core/secrets.ts +0 -65
- package/apps/daemon/src/core/services.ts +0 -264
- package/apps/daemon/src/core/skills/discover.ts +0 -28
- package/apps/daemon/src/core/skills/import.ts +0 -136
- package/apps/daemon/src/core/skills/parse.ts +0 -52
- package/apps/daemon/src/core/skills/resolve.ts +0 -50
- package/apps/daemon/src/index.ts +0 -45
- package/apps/daemon/src/lib/agent-cancel.ts +0 -48
- package/apps/daemon/src/lib/agent-id.ts +0 -13
- package/apps/daemon/src/lib/agent-turn.ts +0 -56
- package/apps/daemon/src/lib/api-key.ts +0 -56
- package/apps/daemon/src/lib/auth.ts +0 -41
- package/apps/daemon/src/lib/cron.ts +0 -93
- package/apps/daemon/src/lib/ctx.ts +0 -80
- package/apps/daemon/src/lib/messaging-host.ts +0 -34
- package/apps/daemon/src/lib/middleware-auth.ts +0 -52
- package/apps/daemon/src/lib/scheduler.ts +0 -294
- package/apps/daemon/src/routes/agents.ts +0 -772
- package/apps/daemon/src/routes/auth-login.ts +0 -193
- package/apps/daemon/src/routes/config.ts +0 -267
- package/apps/daemon/src/routes/groups.ts +0 -133
- package/apps/daemon/src/routes/messages.ts +0 -29
- package/apps/daemon/src/routes/misc.ts +0 -239
- package/apps/daemon/src/routes/profiles.ts +0 -197
- package/apps/daemon/src/routes/skills.ts +0 -123
- package/apps/daemon/src/routes/triggers.ts +0 -29
- package/apps/daemon/src/runtime/auth/openai-codex.ts +0 -121
- package/apps/daemon/src/runtime/auto-reply/heartbeat.ts +0 -31
- package/apps/daemon/src/runtime/index.ts +0 -77
- package/apps/daemon/src/runtime/memory/files.ts +0 -103
- package/apps/daemon/src/runtime/memory/qmd.ts +0 -152
- package/apps/daemon/src/runtime/memory/types.ts +0 -16
- package/apps/daemon/src/runtime/pi/events.ts +0 -173
- package/apps/daemon/src/runtime/pi/session.ts +0 -536
- package/apps/daemon/src/runtime/pi/tools.ts +0 -85
- package/apps/daemon/src/runtime/providers/catalog.ts +0 -145
- package/apps/daemon/src/runtime/providers/pi-adapter.ts +0 -272
- package/apps/daemon/src/runtime/providers/registry.ts +0 -374
- package/apps/daemon/src/runtime/providers/retry.ts +0 -176
- package/apps/daemon/src/runtime/providers/types.ts +0 -33
- package/apps/daemon/src/runtime/session/prompt.ts +0 -83
- package/apps/daemon/src/runtime/tools/bootstrap.ts +0 -22
- package/apps/daemon/src/runtime/tools/home.ts +0 -114
- package/apps/daemon/src/runtime/tools/memory.ts +0 -81
- package/apps/daemon/src/runtime/tools/messaging.ts +0 -127
- package/apps/daemon/src/runtime/tools/registry.ts +0 -29
- package/apps/daemon/src/runtime/tools/types.ts +0 -13
- package/apps/daemon/src/runtime/tools/web-extract.ts +0 -110
- package/apps/daemon/src/runtime/tools/web-ssrf.ts +0 -245
- package/apps/daemon/src/runtime/tools/web.ts +0 -273
- package/apps/daemon/src/runtime/worker/entry.ts +0 -221
- package/apps/daemon/src/runtime/worker/ipc-protocol.ts +0 -75
- package/apps/daemon/src/runtime/worker/spawn.ts +0 -249
- package/apps/daemon/test/core/agents.test.ts +0 -319
- package/apps/daemon/test/core/available-models.test.ts +0 -63
- package/apps/daemon/test/core/config.test.ts +0 -99
- package/apps/daemon/test/core/groups.test.ts +0 -63
- package/apps/daemon/test/core/helpers.ts +0 -50
- package/apps/daemon/test/core/identity.test.ts +0 -85
- package/apps/daemon/test/core/migrations.test.ts +0 -83
- package/apps/daemon/test/core/profiles.test.ts +0 -182
- package/apps/daemon/test/core/provider-models.test.ts +0 -57
- package/apps/daemon/test/core/provider-state.test.ts +0 -36
- package/apps/daemon/test/core/skill-meta.test.ts +0 -45
- package/apps/daemon/test/core/skills.test.ts +0 -271
- package/apps/daemon/test/core/triggers.test.ts +0 -182
- package/apps/daemon/test/core/web-tokens.test.ts +0 -79
- package/apps/daemon/test/cron.test.ts +0 -90
- package/apps/daemon/test/runtime/heartbeat.test.ts +0 -34
- package/apps/daemon/test/runtime/memory-qmd.test.ts +0 -97
- package/apps/daemon/test/runtime/memory.test.ts +0 -78
- package/apps/daemon/test/runtime/messaging.test.ts +0 -213
- package/apps/daemon/test/runtime/mock-server.ts +0 -65
- package/apps/daemon/test/runtime/openai-codex-auth.test.ts +0 -116
- package/apps/daemon/test/runtime/providers.test.ts +0 -306
- package/apps/daemon/test/runtime/retry.test.ts +0 -191
- package/apps/daemon/test/runtime/session-head.test.ts +0 -90
- package/apps/daemon/test/runtime/tools-home.test.ts +0 -102
- package/apps/daemon/test/runtime/tools-web.test.ts +0 -206
- package/apps/daemon/tsconfig.json +0 -4
- package/apps/mobile/README.md +0 -60
- package/apps/mobile/app/_layout.tsx +0 -58
- package/apps/mobile/app/agents/[id]/chat.tsx +0 -486
- package/apps/mobile/app/agents/[id]/index.tsx +0 -166
- package/apps/mobile/app/agents/index.tsx +0 -212
- package/apps/mobile/app/index.tsx +0 -21
- package/apps/mobile/app/pair.tsx +0 -226
- package/apps/mobile/app/settings.tsx +0 -419
- package/apps/mobile/app.json +0 -49
- package/apps/mobile/assets/adaptive-icon.png +0 -0
- package/apps/mobile/assets/favicon.png +0 -0
- package/apps/mobile/assets/icon.png +0 -0
- package/apps/mobile/assets/splash-icon.png +0 -0
- package/apps/mobile/babel.config.js +0 -6
- package/apps/mobile/metro.config.js +0 -28
- package/apps/mobile/package.json +0 -44
- package/apps/mobile/src/auth.ts +0 -66
- package/apps/mobile/src/pair-url.ts +0 -48
- package/apps/mobile/src/theme-context.tsx +0 -88
- package/apps/mobile/src/theme.ts +0 -135
- package/apps/mobile/test/pair-url.test.ts +0 -46
- package/apps/mobile/tsconfig.json +0 -23
- package/apps/web/components.json +0 -25
- package/apps/web/package.json +0 -39
- package/apps/web/public/baziu.svg +0 -8
- package/apps/web/src/components/AgentTabs.tsx +0 -45
- package/apps/web/src/components/BaziuLogo.tsx +0 -21
- package/apps/web/src/components/ChatPane.tsx +0 -1033
- package/apps/web/src/components/ConfigTabs.tsx +0 -29
- package/apps/web/src/components/CopyButton.tsx +0 -68
- package/apps/web/src/components/CreateGroupDialog.tsx +0 -127
- package/apps/web/src/components/FieldRow.tsx +0 -94
- package/apps/web/src/components/Footer.tsx +0 -10
- package/apps/web/src/components/PawIcon.tsx +0 -15
- package/apps/web/src/components/Sidebar.tsx +0 -287
- package/apps/web/src/components/SpawnDialog.tsx +0 -129
- package/apps/web/src/components/ThemeToggle.tsx +0 -75
- package/apps/web/src/components/TopNav.tsx +0 -34
- package/apps/web/src/components/ui/button.tsx +0 -67
- package/apps/web/src/components/ui/card.tsx +0 -103
- package/apps/web/src/components/ui/checkbox.tsx +0 -31
- package/apps/web/src/components/ui/dialog.tsx +0 -168
- package/apps/web/src/components/ui/input.tsx +0 -19
- package/apps/web/src/components/ui/label.tsx +0 -22
- package/apps/web/src/components/ui/radio-group.tsx +0 -44
- package/apps/web/src/components/ui/select.tsx +0 -192
- package/apps/web/src/components/ui/separator.tsx +0 -26
- package/apps/web/src/components/ui/table.tsx +0 -116
- package/apps/web/src/components/ui/tabs.tsx +0 -88
- package/apps/web/src/components/ui/textarea.tsx +0 -18
- package/apps/web/src/lib/auth.ts +0 -50
- package/apps/web/src/lib/daemon-client.ts +0 -34
- package/apps/web/src/lib/md.ts +0 -45
- package/apps/web/src/lib/utils.ts +0 -6
- package/apps/web/src/lib/wire-constants.ts +0 -27
- package/apps/web/src/routeTree.gen.ts +0 -408
- package/apps/web/src/router.tsx +0 -20
- package/apps/web/src/routes/__root.tsx +0 -123
- package/apps/web/src/routes/agents/$id/inbox.tsx +0 -207
- package/apps/web/src/routes/agents/$id/index.tsx +0 -527
- package/apps/web/src/routes/agents/$id/triggers.tsx +0 -239
- package/apps/web/src/routes/agents/index.tsx +0 -265
- package/apps/web/src/routes/api/$.ts +0 -88
- package/apps/web/src/routes/config/index.tsx +0 -315
- package/apps/web/src/routes/config/services.tsx +0 -49
- package/apps/web/src/routes/config/tokens.tsx +0 -192
- package/apps/web/src/routes/groups/$id/index.tsx +0 -153
- package/apps/web/src/routes/groups/$id/memory.tsx +0 -321
- package/apps/web/src/routes/groups/index.tsx +0 -191
- package/apps/web/src/routes/index.tsx +0 -133
- package/apps/web/src/routes/login.tsx +0 -63
- package/apps/web/src/routes/profiles/$id.tsx +0 -549
- package/apps/web/src/routes/profiles/index.tsx +0 -458
- package/apps/web/src/routes/skills/index.tsx +0 -297
- package/apps/web/src/routes/welcome.tsx +0 -61
- package/apps/web/src/styles.css +0 -449
- package/apps/web/tsconfig.json +0 -25
- package/apps/web/vite.config.ts +0 -25
- package/biome.json +0 -23
- package/docs/agent-engine.md +0 -219
- package/docs/architecture.md +0 -627
- package/docs/backlog/README.md +0 -42
- package/docs/backlog/draft/BAZ-001-a2a-federation-spike.md +0 -125
- package/docs/openclaw-reference.md +0 -210
- package/packages/api-types/package.json +0 -11
- package/packages/api-types/src/entities.ts +0 -146
- package/packages/api-types/src/events.ts +0 -55
- package/packages/api-types/src/index.ts +0 -488
- package/packages/api-types/src/memory.ts +0 -15
- package/packages/client/package.json +0 -13
- package/packages/client/src/index.ts +0 -117
- package/pnpm-workspace.yaml +0 -3
- package/tsconfig.base.json +0 -23
- package/tsconfig.json +0 -11
- package/vitest.config.ts +0 -22
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
// Per-service field registry — the shape of the /config page.
|
|
2
|
-
//
|
|
3
|
-
// Each entry describes one "thing" the user might configure: an LLM provider
|
|
4
|
-
// (Anthropic, LM Studio, …) or an ancillary service (Brave Search, SearXNG).
|
|
5
|
-
// Fields know which storage backend they live in: `secret` → the encrypted
|
|
6
|
-
// `secrets` table, `config` → the plaintext `config` table. The registry is
|
|
7
|
-
// the single source of truth for the UI layout and for the generic
|
|
8
|
-
// field-write endpoint's dispatch.
|
|
9
|
-
//
|
|
10
|
-
// When adding a new provider or service, append an entry here and the
|
|
11
|
-
// config page + CLI pick it up automatically.
|
|
12
|
-
|
|
13
|
-
export type FieldKind = 'secret' | 'config'
|
|
14
|
-
|
|
15
|
-
export interface ServiceField {
|
|
16
|
-
/** Env var name — canonical key in both stores. */
|
|
17
|
-
envVar: string
|
|
18
|
-
kind: FieldKind
|
|
19
|
-
label: string
|
|
20
|
-
placeholder?: string
|
|
21
|
-
description?: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export type ServiceCategory = 'provider' | 'service'
|
|
25
|
-
|
|
26
|
-
export interface ServiceDef {
|
|
27
|
-
/** Matches the provider-registry key for providers (e.g. 'anthropic'). */
|
|
28
|
-
id: string
|
|
29
|
-
displayName: string
|
|
30
|
-
category: ServiceCategory
|
|
31
|
-
/** Sign-up link, docs, or 1-line description shown on the card. */
|
|
32
|
-
hint?: string
|
|
33
|
-
fields: ServiceField[]
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* One-liner: what's shown on each service card.
|
|
38
|
-
* Order here is the display order on the config page.
|
|
39
|
-
*/
|
|
40
|
-
export const SERVICES: ServiceDef[] = [
|
|
41
|
-
// --- LLM providers (configured via API keys / URLs) ---
|
|
42
|
-
{
|
|
43
|
-
id: 'anthropic',
|
|
44
|
-
displayName: 'Anthropic',
|
|
45
|
-
category: 'provider',
|
|
46
|
-
hint: 'Claude models · console.anthropic.com',
|
|
47
|
-
fields: [
|
|
48
|
-
{ envVar: 'ANTHROPIC_API_KEY', kind: 'secret', label: 'API key', placeholder: 'sk-ant-...' },
|
|
49
|
-
{
|
|
50
|
-
envVar: 'ANTHROPIC_OAUTH_TOKEN',
|
|
51
|
-
kind: 'secret',
|
|
52
|
-
label: 'OAuth token (alternative to API key)',
|
|
53
|
-
description: 'Takes precedence over ANTHROPIC_API_KEY when set',
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
id: 'openai',
|
|
59
|
-
displayName: 'OpenAI',
|
|
60
|
-
category: 'provider',
|
|
61
|
-
hint: 'GPT models · platform.openai.com',
|
|
62
|
-
fields: [{ envVar: 'OPENAI_API_KEY', kind: 'secret', label: 'API key', placeholder: 'sk-...' }],
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
id: 'openai-codex',
|
|
66
|
-
displayName: 'OpenAI ChatGPT (OAuth)',
|
|
67
|
-
category: 'provider',
|
|
68
|
-
hint: 'Use your ChatGPT Plus/Pro/Team account (same login as Codex CLI)',
|
|
69
|
-
// No form fields — credentials come from an OAuth flow. The /config page
|
|
70
|
-
// renders a Connect/Disconnect card using /api/auth/openai instead of the
|
|
71
|
-
// standard field inputs.
|
|
72
|
-
fields: [],
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
id: 'google',
|
|
76
|
-
displayName: 'Google (Gemini)',
|
|
77
|
-
category: 'provider',
|
|
78
|
-
hint: 'Gemini models · ai.google.dev (free tier available)',
|
|
79
|
-
fields: [
|
|
80
|
-
{ envVar: 'GEMINI_API_KEY', kind: 'secret', label: 'API key', placeholder: 'AIza...' },
|
|
81
|
-
],
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
id: 'google-vertex',
|
|
85
|
-
displayName: 'Google Vertex AI',
|
|
86
|
-
category: 'provider',
|
|
87
|
-
hint: 'Authenticates via `gcloud auth application-default login`',
|
|
88
|
-
fields: [
|
|
89
|
-
{
|
|
90
|
-
envVar: 'GOOGLE_CLOUD_PROJECT',
|
|
91
|
-
kind: 'config',
|
|
92
|
-
label: 'GCP project ID',
|
|
93
|
-
placeholder: 'my-project-123456',
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
envVar: 'GOOGLE_CLOUD_LOCATION',
|
|
97
|
-
kind: 'config',
|
|
98
|
-
label: 'GCP region',
|
|
99
|
-
placeholder: 'us-central1',
|
|
100
|
-
},
|
|
101
|
-
],
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
id: 'azure-openai',
|
|
105
|
-
displayName: 'Azure OpenAI',
|
|
106
|
-
category: 'provider',
|
|
107
|
-
fields: [{ envVar: 'AZURE_OPENAI_API_KEY', kind: 'secret', label: 'API key' }],
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
id: 'bedrock',
|
|
111
|
-
displayName: 'Amazon Bedrock',
|
|
112
|
-
category: 'provider',
|
|
113
|
-
hint: 'Authenticates via AWS SDK env (AWS_PROFILE or AWS_ACCESS_KEY_ID/SECRET)',
|
|
114
|
-
fields: [],
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
id: 'mistral',
|
|
118
|
-
displayName: 'Mistral',
|
|
119
|
-
category: 'provider',
|
|
120
|
-
hint: 'mistral.ai',
|
|
121
|
-
fields: [{ envVar: 'MISTRAL_API_KEY', kind: 'secret', label: 'API key' }],
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
id: 'groq',
|
|
125
|
-
displayName: 'Groq',
|
|
126
|
-
category: 'provider',
|
|
127
|
-
hint: 'Fast inference · groq.com',
|
|
128
|
-
fields: [{ envVar: 'GROQ_API_KEY', kind: 'secret', label: 'API key' }],
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
id: 'cerebras',
|
|
132
|
-
displayName: 'Cerebras',
|
|
133
|
-
category: 'provider',
|
|
134
|
-
fields: [{ envVar: 'CEREBRAS_API_KEY', kind: 'secret', label: 'API key' }],
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
id: 'xai',
|
|
138
|
-
displayName: 'xAI',
|
|
139
|
-
category: 'provider',
|
|
140
|
-
hint: 'Grok · x.ai',
|
|
141
|
-
fields: [{ envVar: 'XAI_API_KEY', kind: 'secret', label: 'API key' }],
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
id: 'zai',
|
|
145
|
-
displayName: 'zAI',
|
|
146
|
-
category: 'provider',
|
|
147
|
-
fields: [{ envVar: 'ZAI_API_KEY', kind: 'secret', label: 'API key' }],
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
id: 'huggingface',
|
|
151
|
-
displayName: 'Hugging Face',
|
|
152
|
-
category: 'provider',
|
|
153
|
-
hint: 'Inference endpoints · huggingface.co',
|
|
154
|
-
fields: [{ envVar: 'HF_TOKEN', kind: 'secret', label: 'Access token', placeholder: 'hf_...' }],
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
id: 'openrouter',
|
|
158
|
-
displayName: 'OpenRouter',
|
|
159
|
-
category: 'provider',
|
|
160
|
-
hint: 'Proxy for 200+ models · openrouter.ai',
|
|
161
|
-
fields: [
|
|
162
|
-
{ envVar: 'OPENROUTER_API_KEY', kind: 'secret', label: 'API key', placeholder: 'sk-or-...' },
|
|
163
|
-
],
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
id: 'vercel-ai-gateway',
|
|
167
|
-
displayName: 'Vercel AI Gateway',
|
|
168
|
-
category: 'provider',
|
|
169
|
-
fields: [
|
|
170
|
-
{ envVar: 'AI_GATEWAY_API_KEY', kind: 'secret', label: 'API key' },
|
|
171
|
-
{
|
|
172
|
-
envVar: 'AI_GATEWAY_BASE_URL',
|
|
173
|
-
kind: 'config',
|
|
174
|
-
label: 'Base URL (optional)',
|
|
175
|
-
placeholder: 'https://ai-gateway.vercel.sh/v1',
|
|
176
|
-
},
|
|
177
|
-
],
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
id: 'lmstudio',
|
|
181
|
-
displayName: 'LM Studio',
|
|
182
|
-
category: 'provider',
|
|
183
|
-
hint: 'Local inference · lmstudio.ai',
|
|
184
|
-
fields: [
|
|
185
|
-
{
|
|
186
|
-
envVar: 'LMSTUDIO_URL',
|
|
187
|
-
kind: 'config',
|
|
188
|
-
label: 'Endpoint URL',
|
|
189
|
-
placeholder: 'http://127.0.0.1:1234/v1',
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
envVar: 'LMSTUDIO_API_KEY',
|
|
193
|
-
kind: 'secret',
|
|
194
|
-
label: 'API key (rarely needed)',
|
|
195
|
-
},
|
|
196
|
-
],
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
id: 'ollama',
|
|
200
|
-
displayName: 'Ollama',
|
|
201
|
-
category: 'provider',
|
|
202
|
-
hint: 'Local inference · ollama.com',
|
|
203
|
-
fields: [
|
|
204
|
-
{
|
|
205
|
-
envVar: 'OLLAMA_URL',
|
|
206
|
-
kind: 'config',
|
|
207
|
-
label: 'Endpoint URL',
|
|
208
|
-
placeholder: 'http://127.0.0.1:11434/v1',
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
envVar: 'OLLAMA_API_KEY',
|
|
212
|
-
kind: 'secret',
|
|
213
|
-
label: 'API key (rarely needed)',
|
|
214
|
-
},
|
|
215
|
-
],
|
|
216
|
-
},
|
|
217
|
-
|
|
218
|
-
// --- Ancillary services (web search, etc) ---
|
|
219
|
-
{
|
|
220
|
-
id: 'brave-search',
|
|
221
|
-
displayName: 'Brave Search',
|
|
222
|
-
category: 'service',
|
|
223
|
-
hint: 'Web search tool · free tier at brave.com/search/api/',
|
|
224
|
-
fields: [{ envVar: 'BRAVE_API_KEY', kind: 'secret', label: 'API key', placeholder: 'BSA...' }],
|
|
225
|
-
},
|
|
226
|
-
{
|
|
227
|
-
id: 'searxng',
|
|
228
|
-
displayName: 'SearXNG',
|
|
229
|
-
category: 'service',
|
|
230
|
-
hint: 'Self-hosted meta-search engine · searxng.org',
|
|
231
|
-
fields: [
|
|
232
|
-
{
|
|
233
|
-
envVar: 'SEARXNG_URL',
|
|
234
|
-
kind: 'config',
|
|
235
|
-
label: 'Instance URL',
|
|
236
|
-
placeholder: 'https://searxng.example.com',
|
|
237
|
-
},
|
|
238
|
-
],
|
|
239
|
-
},
|
|
240
|
-
]
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Fast lookup: envVar → the field definition + owning service.
|
|
244
|
-
* Rebuilt once at module init — the list is static.
|
|
245
|
-
*/
|
|
246
|
-
const FIELD_INDEX: Map<string, { service: ServiceDef; field: ServiceField }> = (() => {
|
|
247
|
-
const m = new Map<string, { service: ServiceDef; field: ServiceField }>()
|
|
248
|
-
for (const service of SERVICES) {
|
|
249
|
-
for (const field of service.fields) {
|
|
250
|
-
m.set(field.envVar, { service, field })
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
return m
|
|
254
|
-
})()
|
|
255
|
-
|
|
256
|
-
export function findFieldByEnvVar(
|
|
257
|
-
envVar: string,
|
|
258
|
-
): { service: ServiceDef; field: ServiceField } | undefined {
|
|
259
|
-
return FIELD_INDEX.get(envVar)
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
export function servicesByCategory(category: ServiceCategory): ServiceDef[] {
|
|
263
|
-
return SERVICES.filter((s) => s.category === category)
|
|
264
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { existsSync, readdirSync } from 'node:fs'
|
|
2
|
-
import { join } from 'node:path'
|
|
3
|
-
import type { Paths } from '../paths.ts'
|
|
4
|
-
|
|
5
|
-
export interface DiscoveredSkill {
|
|
6
|
-
name: string
|
|
7
|
-
dir: string
|
|
8
|
-
skillFile: string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Walk the bazilion skill library and return every directory that contains a
|
|
13
|
-
* SKILL.md file. Pure filesystem read — does not parse the markdown.
|
|
14
|
-
*/
|
|
15
|
-
export function discoverSkills(paths: Paths): DiscoveredSkill[] {
|
|
16
|
-
if (!existsSync(paths.skillsDir)) return []
|
|
17
|
-
|
|
18
|
-
const entries = readdirSync(paths.skillsDir, { withFileTypes: true })
|
|
19
|
-
const skills: DiscoveredSkill[] = []
|
|
20
|
-
for (const entry of entries) {
|
|
21
|
-
if (!entry.isDirectory()) continue
|
|
22
|
-
const dir = join(paths.skillsDir, entry.name)
|
|
23
|
-
const skillFile = join(dir, 'SKILL.md')
|
|
24
|
-
if (!existsSync(skillFile)) continue
|
|
25
|
-
skills.push({ name: entry.name, dir, skillFile })
|
|
26
|
-
}
|
|
27
|
-
return skills.sort((a, b) => a.name.localeCompare(b.name))
|
|
28
|
-
}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import { cpSync, existsSync, mkdtempSync, readdirSync, rmSync, statSync } from 'node:fs'
|
|
2
|
-
import { tmpdir } from 'node:os'
|
|
3
|
-
import { basename, join, resolve, sep } from 'node:path'
|
|
4
|
-
import AdmZip from 'adm-zip'
|
|
5
|
-
import type { Paths } from '../paths.ts'
|
|
6
|
-
import { parseSkillFile } from './parse.ts'
|
|
7
|
-
|
|
8
|
-
export interface ImportSkillsInput {
|
|
9
|
-
/**
|
|
10
|
-
* Absolute path to either:
|
|
11
|
-
* - a single skill folder (contains SKILL.md),
|
|
12
|
-
* - a parent directory containing multiple skill folders,
|
|
13
|
-
* - a `.zip` file whose top level holds one-folder-per-skill (or a single
|
|
14
|
-
* wrapping folder that holds them).
|
|
15
|
-
*/
|
|
16
|
-
source: string
|
|
17
|
-
/** overwrite existing target skills */
|
|
18
|
-
force?: boolean
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface ImportResult {
|
|
22
|
-
imported: string[]
|
|
23
|
-
skipped: { name: string; reason: string }[]
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Extract a zip archive into a fresh temp dir with a zip-slip guard — every
|
|
28
|
-
* entry's resolved path must stay under the extraction root. Returns both the
|
|
29
|
-
* mkdtemp root (for cleanup) and the effective source path to hand to the
|
|
30
|
-
* importer. When the archive is wrapped in a single top-level directory
|
|
31
|
-
* (common with GitHub-style archives), we descend into it so `source` lines
|
|
32
|
-
* up with the "parent-of-skill-dirs" shape the importer already understands.
|
|
33
|
-
*/
|
|
34
|
-
function extractZipSafely(zipPath: string): { root: string; effectiveSource: string } {
|
|
35
|
-
const root = mkdtempSync(join(tmpdir(), 'bazilion-skill-zip-'))
|
|
36
|
-
try {
|
|
37
|
-
const zip = new AdmZip(zipPath)
|
|
38
|
-
for (const entry of zip.getEntries()) {
|
|
39
|
-
const rawName = entry.entryName
|
|
40
|
-
if (rawName.startsWith('/') || rawName.startsWith('\\')) {
|
|
41
|
-
throw new Error(`zip entry has absolute path: ${rawName}`)
|
|
42
|
-
}
|
|
43
|
-
const resolved = resolve(root, rawName)
|
|
44
|
-
if (resolved !== root && !resolved.startsWith(root + sep)) {
|
|
45
|
-
throw new Error(`zip entry escapes extraction root: ${rawName}`)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
zip.extractAllTo(root, true)
|
|
49
|
-
} catch (err) {
|
|
50
|
-
rmSync(root, { recursive: true, force: true })
|
|
51
|
-
throw err
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Unwrap a single top-level folder if present — the importer's
|
|
55
|
-
// "source-is-a-directory" cases (single-skill dir vs. parent-of-skills dir)
|
|
56
|
-
// both apply equally well to the unwrapped path.
|
|
57
|
-
let effectiveSource = root
|
|
58
|
-
const topEntries = readdirSync(root, { withFileTypes: true })
|
|
59
|
-
if (topEntries.length === 1 && topEntries[0]?.isDirectory()) {
|
|
60
|
-
effectiveSource = join(root, topEntries[0].name)
|
|
61
|
-
}
|
|
62
|
-
return { root, effectiveSource }
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function importSkills(paths: Paths, input: ImportSkillsInput): ImportResult {
|
|
66
|
-
const rawSource = resolve(input.source)
|
|
67
|
-
if (!existsSync(rawSource)) {
|
|
68
|
-
throw new Error(`source does not exist: ${rawSource}`)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
let source = rawSource
|
|
72
|
-
let tempRoot: string | null = null
|
|
73
|
-
const sourceStat = statSync(rawSource)
|
|
74
|
-
if (sourceStat.isFile()) {
|
|
75
|
-
if (!rawSource.toLowerCase().endsWith('.zip')) {
|
|
76
|
-
throw new Error(`source file must be a .zip archive: ${rawSource}`)
|
|
77
|
-
}
|
|
78
|
-
const { root, effectiveSource } = extractZipSafely(rawSource)
|
|
79
|
-
tempRoot = root
|
|
80
|
-
source = effectiveSource
|
|
81
|
-
} else if (!sourceStat.isDirectory()) {
|
|
82
|
-
throw new Error(`source is not a directory: ${rawSource}`)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
return importSkillsFromDir(paths, source, input)
|
|
87
|
-
} finally {
|
|
88
|
-
if (tempRoot) rmSync(tempRoot, { recursive: true, force: true })
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function importSkillsFromDir(paths: Paths, source: string, input: ImportSkillsInput): ImportResult {
|
|
93
|
-
const candidates: { name: string; dir: string }[] = []
|
|
94
|
-
|
|
95
|
-
// Two shapes are accepted:
|
|
96
|
-
// 1. source is itself a single skill dir (contains SKILL.md)
|
|
97
|
-
// 2. source is a parent containing multiple skill dirs
|
|
98
|
-
if (existsSync(join(source, 'SKILL.md'))) {
|
|
99
|
-
candidates.push({ name: basename(source), dir: source })
|
|
100
|
-
} else {
|
|
101
|
-
const entries = readdirSync(source, { withFileTypes: true })
|
|
102
|
-
for (const e of entries) {
|
|
103
|
-
if (!e.isDirectory()) continue
|
|
104
|
-
const skillDir = join(source, e.name)
|
|
105
|
-
if (!existsSync(join(skillDir, 'SKILL.md'))) continue
|
|
106
|
-
candidates.push({ name: e.name, dir: skillDir })
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (candidates.length === 0) {
|
|
111
|
-
throw new Error(`no skills found in ${source}`)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Validate every SKILL.md before touching the target dir.
|
|
115
|
-
for (const c of candidates) {
|
|
116
|
-
parseSkillFile(join(c.dir, 'SKILL.md'))
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const imported: string[] = []
|
|
120
|
-
const skipped: { name: string; reason: string }[] = []
|
|
121
|
-
|
|
122
|
-
for (const c of candidates) {
|
|
123
|
-
const target = join(paths.skillsDir, c.name)
|
|
124
|
-
if (existsSync(target) && !input.force) {
|
|
125
|
-
skipped.push({
|
|
126
|
-
name: c.name,
|
|
127
|
-
reason: 'already exists (use --force to overwrite)',
|
|
128
|
-
})
|
|
129
|
-
continue
|
|
130
|
-
}
|
|
131
|
-
cpSync(c.dir, target, { recursive: true, force: !!input.force })
|
|
132
|
-
imported.push(c.name)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return { imported, skipped }
|
|
136
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs'
|
|
2
|
-
import { parse as parseYaml } from 'yaml'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Standard agent-skill frontmatter. Required fields are typed; the rest is open
|
|
6
|
-
* (skill formats may add fields like `allowed-tools`, `homepage`, etc.).
|
|
7
|
-
*/
|
|
8
|
-
export interface SkillFrontmatter {
|
|
9
|
-
name: string
|
|
10
|
-
description: string
|
|
11
|
-
[key: string]: unknown
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface ParsedSkill {
|
|
15
|
-
frontmatter: SkillFrontmatter
|
|
16
|
-
body: string
|
|
17
|
-
raw: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/
|
|
21
|
-
|
|
22
|
-
export function parseSkillContent(raw: string): ParsedSkill {
|
|
23
|
-
const m = raw.match(FRONTMATTER_RE)
|
|
24
|
-
if (!m) {
|
|
25
|
-
throw new Error('SKILL.md missing YAML frontmatter (expected leading "---")')
|
|
26
|
-
}
|
|
27
|
-
const yamlBlock = m[1] ?? ''
|
|
28
|
-
const body = m[2] ?? ''
|
|
29
|
-
|
|
30
|
-
let fm: unknown
|
|
31
|
-
try {
|
|
32
|
-
fm = parseYaml(yamlBlock)
|
|
33
|
-
} catch (err) {
|
|
34
|
-
throw new Error(`SKILL.md frontmatter is not valid YAML: ${(err as Error).message}`)
|
|
35
|
-
}
|
|
36
|
-
if (!fm || typeof fm !== 'object' || Array.isArray(fm)) {
|
|
37
|
-
throw new Error('SKILL.md frontmatter must be a YAML object')
|
|
38
|
-
}
|
|
39
|
-
const fmObj = fm as Record<string, unknown>
|
|
40
|
-
if (typeof fmObj.name !== 'string' || fmObj.name.length === 0) {
|
|
41
|
-
throw new Error('SKILL.md frontmatter missing required "name"')
|
|
42
|
-
}
|
|
43
|
-
if (typeof fmObj.description !== 'string' || fmObj.description.length === 0) {
|
|
44
|
-
throw new Error('SKILL.md frontmatter missing required "description"')
|
|
45
|
-
}
|
|
46
|
-
return { frontmatter: fmObj as SkillFrontmatter, body, raw }
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function parseSkillFile(path: string): ParsedSkill {
|
|
50
|
-
const raw = readFileSync(path, 'utf8')
|
|
51
|
-
return parseSkillContent(raw)
|
|
52
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import type { BazilionDb } from '../db/client.ts'
|
|
2
|
-
import type { Paths } from '../paths.ts'
|
|
3
|
-
import * as agentRepo from '../repos/agents.ts'
|
|
4
|
-
import { discoverSkills } from './discover.ts'
|
|
5
|
-
import { type ParsedSkill, parseSkillFile } from './parse.ts'
|
|
6
|
-
|
|
7
|
-
export interface ResolvedSkill {
|
|
8
|
-
name: string
|
|
9
|
-
dir: string
|
|
10
|
-
parsed: ParsedSkill
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface ResolvedSkillSet {
|
|
14
|
-
/** skills attached to the agent that exist and parse correctly */
|
|
15
|
-
resolved: ResolvedSkill[]
|
|
16
|
-
/** attached skill names that are missing from the library or fail to parse */
|
|
17
|
-
missing: { name: string; reason: string }[]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Given an agent, return the parsed skills currently attached to it. Skill
|
|
22
|
-
* attachments live in `agent_skills`; the source of truth for content is
|
|
23
|
-
* `~/.bazilion/skills/<name>/SKILL.md`.
|
|
24
|
-
*/
|
|
25
|
-
export function resolveAgentSkills(
|
|
26
|
-
db: BazilionDb,
|
|
27
|
-
paths: Paths,
|
|
28
|
-
agentId: string,
|
|
29
|
-
): ResolvedSkillSet {
|
|
30
|
-
const attached = agentRepo.listAttachedSkills(db, agentId)
|
|
31
|
-
const discovered = new Map(discoverSkills(paths).map((s) => [s.name, s]))
|
|
32
|
-
|
|
33
|
-
const resolved: ResolvedSkill[] = []
|
|
34
|
-
const missing: { name: string; reason: string }[] = []
|
|
35
|
-
|
|
36
|
-
for (const name of attached) {
|
|
37
|
-
const ds = discovered.get(name)
|
|
38
|
-
if (!ds) {
|
|
39
|
-
missing.push({ name, reason: 'not in library' })
|
|
40
|
-
continue
|
|
41
|
-
}
|
|
42
|
-
try {
|
|
43
|
-
const parsed = parseSkillFile(ds.skillFile)
|
|
44
|
-
resolved.push({ name, dir: ds.dir, parsed })
|
|
45
|
-
} catch (err) {
|
|
46
|
-
missing.push({ name, reason: (err as Error).message })
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return { resolved, missing }
|
|
50
|
-
}
|
package/apps/daemon/src/index.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
// Daemon entry point. Reads HOST/PORT env, boots the Hono app, and waits on
|
|
2
|
-
// SIGINT/SIGTERM for shutdown.
|
|
3
|
-
//
|
|
4
|
-
// This process is the single owner of `~/.bazilion`. The web app, CLI, and
|
|
5
|
-
// mobile clients all talk to it over HTTP via @bazilion/client.
|
|
6
|
-
|
|
7
|
-
import { serve } from '@hono/node-server'
|
|
8
|
-
import { createApp } from './app.ts'
|
|
9
|
-
import { getCtx } from './lib/ctx.ts'
|
|
10
|
-
|
|
11
|
-
const host = process.env.HOST ?? '127.0.0.1'
|
|
12
|
-
const port = Number.parseInt(process.env.PORT ?? '4321', 10)
|
|
13
|
-
|
|
14
|
-
// Eagerly bootstrap ~/.bazilion (mkdir, openDb, runMigrations, mint token,
|
|
15
|
-
// write auth.json) before binding the port. Otherwise the first request
|
|
16
|
-
// would race with bootstrap and the operator wouldn't see the bootstrap
|
|
17
|
-
// message until something actually hits the daemon.
|
|
18
|
-
getCtx()
|
|
19
|
-
|
|
20
|
-
const app = createApp()
|
|
21
|
-
|
|
22
|
-
const server = serve({ fetch: app.fetch, hostname: host, port }, (info) => {
|
|
23
|
-
console.log(`bazilion daemon listening at http://${info.address}:${info.port}`)
|
|
24
|
-
if (host !== '127.0.0.1' && host !== 'localhost' && host !== '::1') {
|
|
25
|
-
console.error('')
|
|
26
|
-
console.error(`⚠ binding to ${host} — the daemon is now reachable beyond loopback.`)
|
|
27
|
-
console.error(' anyone on this network who has a valid token can reach every API.')
|
|
28
|
-
console.error(' put a TLS proxy in front for untrusted networks.')
|
|
29
|
-
console.error('')
|
|
30
|
-
}
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
const shutdown = (signal: NodeJS.Signals): void => {
|
|
34
|
-
console.log(`\nbazilion daemon caught ${signal}, shutting down…`)
|
|
35
|
-
server.close((err) => {
|
|
36
|
-
if (err) {
|
|
37
|
-
console.error('shutdown error:', err)
|
|
38
|
-
process.exit(1)
|
|
39
|
-
}
|
|
40
|
-
process.exit(0)
|
|
41
|
-
})
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
process.on('SIGINT', () => shutdown('SIGINT'))
|
|
45
|
-
process.on('SIGTERM', () => shutdown('SIGTERM'))
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
// In-memory registry of agents currently running a turn and their
|
|
2
|
-
// AbortControllers. The chat / scheduler / inbox-wake paths register before
|
|
3
|
-
// they spawn a worker; the cancel route looks the agent up and calls
|
|
4
|
-
// `abort()`. Doubles as the "is this agent busy?" probe the scheduler uses
|
|
5
|
-
// to skip overlapping inbox-wakes and triggers.
|
|
6
|
-
//
|
|
7
|
-
// Pinned to `globalThis` via a well-known Symbol so there is exactly one
|
|
8
|
-
// instance per process even if a bundler ever splits this module across
|
|
9
|
-
// chunks. Two different Map instances would make registrations invisible to
|
|
10
|
-
// the cancel side.
|
|
11
|
-
|
|
12
|
-
const REGISTRY_KEY = Symbol.for('bazilion.agent-cancel.registry')
|
|
13
|
-
|
|
14
|
-
interface Registry {
|
|
15
|
-
active: Map<string, AbortController>
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function registry(): Registry {
|
|
19
|
-
const g = globalThis as unknown as Record<symbol, Registry | undefined>
|
|
20
|
-
let r = g[REGISTRY_KEY]
|
|
21
|
-
if (!r) {
|
|
22
|
-
r = { active: new Map() }
|
|
23
|
-
g[REGISTRY_KEY] = r
|
|
24
|
-
}
|
|
25
|
-
return r
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function registerAgent(agentId: string, controller: AbortController): void {
|
|
29
|
-
registry().active.set(agentId, controller)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function unregisterAgent(agentId: string): void {
|
|
33
|
-
registry().active.delete(agentId)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Returns true if the agent had an active turn that was aborted, false otherwise. */
|
|
37
|
-
export function cancelAgent(agentId: string): boolean {
|
|
38
|
-
const { active } = registry()
|
|
39
|
-
const c = active.get(agentId)
|
|
40
|
-
if (!c) return false
|
|
41
|
-
c.abort()
|
|
42
|
-
active.delete(agentId)
|
|
43
|
-
return true
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function isActiveAgent(agentId: string): boolean {
|
|
47
|
-
return registry().active.has(agentId)
|
|
48
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { agentRepo, type BazilionDb } from '../core/index.ts'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Expand an agent ID prefix (from URL params) to the full UUID.
|
|
5
|
-
*
|
|
6
|
-
* Returns the resolved full ID when the prefix is exact or uniquely resolves;
|
|
7
|
-
* returns the raw input otherwise so the caller's existing "not found" branch
|
|
8
|
-
* fires with the original value in the error message.
|
|
9
|
-
*/
|
|
10
|
-
export function resolveAgentIdParam(db: BazilionDb, raw: string | undefined): string {
|
|
11
|
-
if (!raw) return ''
|
|
12
|
-
return agentRepo.resolveId(db, raw) ?? raw
|
|
13
|
-
}
|