@lobu/gateway 3.0.9 → 3.0.12
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/dist/api/platform.d.ts.map +1 -1
- package/dist/api/platform.js +7 -26
- package/dist/api/platform.js.map +1 -1
- package/dist/auth/mcp/proxy.d.ts +14 -0
- package/dist/auth/mcp/proxy.d.ts.map +1 -1
- package/dist/auth/mcp/proxy.js +149 -13
- package/dist/auth/mcp/proxy.js.map +1 -1
- package/dist/cli/gateway.d.ts.map +1 -1
- package/dist/cli/gateway.js +29 -0
- package/dist/cli/gateway.js.map +1 -1
- package/dist/connections/chat-instance-manager.d.ts.map +1 -1
- package/dist/connections/chat-instance-manager.js +2 -1
- package/dist/connections/chat-instance-manager.js.map +1 -1
- package/dist/connections/interaction-bridge.d.ts +9 -2
- package/dist/connections/interaction-bridge.d.ts.map +1 -1
- package/dist/connections/interaction-bridge.js +121 -261
- package/dist/connections/interaction-bridge.js.map +1 -1
- package/dist/interactions.d.ts +9 -43
- package/dist/interactions.d.ts.map +1 -1
- package/dist/interactions.js +10 -52
- package/dist/interactions.js.map +1 -1
- package/dist/routes/public/agent.d.ts +4 -0
- package/dist/routes/public/agent.d.ts.map +1 -1
- package/dist/routes/public/agent.js +21 -0
- package/dist/routes/public/agent.js.map +1 -1
- package/dist/services/core-services.d.ts.map +1 -1
- package/dist/services/core-services.js +4 -0
- package/dist/services/core-services.js.map +1 -1
- package/package.json +9 -9
- package/src/__tests__/agent-config-routes.test.ts +0 -254
- package/src/__tests__/agent-history-routes.test.ts +0 -72
- package/src/__tests__/agent-routes.test.ts +0 -68
- package/src/__tests__/agent-schedules-routes.test.ts +0 -59
- package/src/__tests__/agent-settings-store.test.ts +0 -323
- package/src/__tests__/bedrock-model-catalog.test.ts +0 -40
- package/src/__tests__/bedrock-openai-service.test.ts +0 -157
- package/src/__tests__/bedrock-provider-module.test.ts +0 -56
- package/src/__tests__/chat-instance-manager-slack.test.ts +0 -204
- package/src/__tests__/chat-response-bridge.test.ts +0 -131
- package/src/__tests__/config-memory-plugins.test.ts +0 -92
- package/src/__tests__/config-request-store.test.ts +0 -127
- package/src/__tests__/connection-routes.test.ts +0 -144
- package/src/__tests__/core-services-store-selection.test.ts +0 -92
- package/src/__tests__/docker-deployment.test.ts +0 -1211
- package/src/__tests__/embedded-deployment.test.ts +0 -342
- package/src/__tests__/grant-store.test.ts +0 -148
- package/src/__tests__/http-proxy.test.ts +0 -281
- package/src/__tests__/instruction-service.test.ts +0 -37
- package/src/__tests__/link-buttons.test.ts +0 -112
- package/src/__tests__/lobu.test.ts +0 -32
- package/src/__tests__/mcp-config-service.test.ts +0 -347
- package/src/__tests__/mcp-proxy.test.ts +0 -694
- package/src/__tests__/message-handler-bridge.test.ts +0 -17
- package/src/__tests__/model-selection.test.ts +0 -172
- package/src/__tests__/oauth-templates.test.ts +0 -39
- package/src/__tests__/platform-adapter-slack-send.test.ts +0 -114
- package/src/__tests__/platform-helpers-model-resolution.test.ts +0 -253
- package/src/__tests__/provider-inheritance.test.ts +0 -212
- package/src/__tests__/routes/cli-auth.test.ts +0 -337
- package/src/__tests__/routes/interactions.test.ts +0 -121
- package/src/__tests__/secret-proxy.test.ts +0 -85
- package/src/__tests__/session-manager.test.ts +0 -572
- package/src/__tests__/setup.ts +0 -133
- package/src/__tests__/skill-and-mcp-registry.test.ts +0 -203
- package/src/__tests__/slack-routes.test.ts +0 -161
- package/src/__tests__/system-config-resolver.test.ts +0 -75
- package/src/__tests__/system-message-limiter.test.ts +0 -89
- package/src/__tests__/system-skills-service.test.ts +0 -362
- package/src/__tests__/transcription-service.test.ts +0 -222
- package/src/__tests__/utils/rate-limiter.test.ts +0 -102
- package/src/__tests__/worker-connection-manager.test.ts +0 -497
- package/src/__tests__/worker-job-router.test.ts +0 -722
- package/src/api/index.ts +0 -1
- package/src/api/platform.ts +0 -292
- package/src/api/response-renderer.ts +0 -157
- package/src/auth/agent-metadata-store.ts +0 -168
- package/src/auth/api-auth-middleware.ts +0 -69
- package/src/auth/api-key-provider-module.ts +0 -213
- package/src/auth/base-provider-module.ts +0 -201
- package/src/auth/bedrock/provider-module.ts +0 -110
- package/src/auth/chatgpt/chatgpt-oauth-module.ts +0 -185
- package/src/auth/chatgpt/device-code-client.ts +0 -218
- package/src/auth/chatgpt/index.ts +0 -1
- package/src/auth/claude/oauth-module.ts +0 -280
- package/src/auth/cli/token-service.ts +0 -249
- package/src/auth/external/client.ts +0 -560
- package/src/auth/external/device-code-client.ts +0 -235
- package/src/auth/mcp/config-service.ts +0 -420
- package/src/auth/mcp/proxy.ts +0 -1086
- package/src/auth/mcp/string-substitution.ts +0 -17
- package/src/auth/mcp/tool-cache.ts +0 -90
- package/src/auth/oauth/base-client.ts +0 -267
- package/src/auth/oauth/client.ts +0 -153
- package/src/auth/oauth/credentials.ts +0 -7
- package/src/auth/oauth/providers.ts +0 -69
- package/src/auth/oauth/state-store.ts +0 -150
- package/src/auth/oauth-templates.ts +0 -179
- package/src/auth/provider-catalog.ts +0 -220
- package/src/auth/provider-model-options.ts +0 -41
- package/src/auth/settings/agent-settings-store.ts +0 -565
- package/src/auth/settings/auth-profiles-manager.ts +0 -216
- package/src/auth/settings/index.ts +0 -12
- package/src/auth/settings/model-preference-store.ts +0 -52
- package/src/auth/settings/model-selection.ts +0 -135
- package/src/auth/settings/resolved-settings-view.ts +0 -298
- package/src/auth/settings/template-utils.ts +0 -44
- package/src/auth/settings/token-service.ts +0 -88
- package/src/auth/system-env-store.ts +0 -98
- package/src/auth/user-agents-store.ts +0 -68
- package/src/channels/binding-service.ts +0 -214
- package/src/channels/index.ts +0 -4
- package/src/cli/gateway.ts +0 -1312
- package/src/cli/index.ts +0 -74
- package/src/commands/built-in-commands.ts +0 -80
- package/src/commands/command-dispatcher.ts +0 -94
- package/src/commands/command-reply-adapters.ts +0 -27
- package/src/config/file-loader.ts +0 -618
- package/src/config/index.ts +0 -588
- package/src/config/network-allowlist.ts +0 -71
- package/src/connections/chat-instance-manager.ts +0 -1284
- package/src/connections/chat-response-bridge.ts +0 -618
- package/src/connections/index.ts +0 -7
- package/src/connections/interaction-bridge.ts +0 -831
- package/src/connections/message-handler-bridge.ts +0 -440
- package/src/connections/platform-auth-methods.ts +0 -15
- package/src/connections/types.ts +0 -84
- package/src/gateway/connection-manager.ts +0 -291
- package/src/gateway/index.ts +0 -698
- package/src/gateway/job-router.ts +0 -201
- package/src/gateway-main.ts +0 -200
- package/src/index.ts +0 -41
- package/src/infrastructure/queue/index.ts +0 -12
- package/src/infrastructure/queue/queue-producer.ts +0 -148
- package/src/infrastructure/queue/redis-queue.ts +0 -361
- package/src/infrastructure/queue/types.ts +0 -133
- package/src/infrastructure/redis/system-message-limiter.ts +0 -94
- package/src/interactions/config-request-store.ts +0 -198
- package/src/interactions.ts +0 -363
- package/src/lobu.ts +0 -311
- package/src/metrics/prometheus.ts +0 -159
- package/src/modules/module-system.ts +0 -179
- package/src/orchestration/base-deployment-manager.ts +0 -900
- package/src/orchestration/deployment-utils.ts +0 -98
- package/src/orchestration/impl/docker-deployment.ts +0 -620
- package/src/orchestration/impl/embedded-deployment.ts +0 -268
- package/src/orchestration/impl/index.ts +0 -8
- package/src/orchestration/impl/k8s/deployment.ts +0 -1061
- package/src/orchestration/impl/k8s/helpers.ts +0 -610
- package/src/orchestration/impl/k8s/index.ts +0 -1
- package/src/orchestration/index.ts +0 -333
- package/src/orchestration/message-consumer.ts +0 -584
- package/src/orchestration/scheduled-wakeup.ts +0 -704
- package/src/permissions/approval-policy.ts +0 -36
- package/src/permissions/grant-store.ts +0 -219
- package/src/platform/file-handler.ts +0 -66
- package/src/platform/link-buttons.ts +0 -57
- package/src/platform/renderer-utils.ts +0 -44
- package/src/platform/response-renderer.ts +0 -84
- package/src/platform/unified-thread-consumer.ts +0 -194
- package/src/platform.ts +0 -318
- package/src/proxy/http-proxy.ts +0 -752
- package/src/proxy/proxy-manager.ts +0 -81
- package/src/proxy/secret-proxy.ts +0 -402
- package/src/proxy/token-refresh-job.ts +0 -143
- package/src/routes/internal/audio.ts +0 -141
- package/src/routes/internal/device-auth.ts +0 -652
- package/src/routes/internal/files.ts +0 -226
- package/src/routes/internal/history.ts +0 -69
- package/src/routes/internal/images.ts +0 -127
- package/src/routes/internal/interactions.ts +0 -84
- package/src/routes/internal/middleware.ts +0 -23
- package/src/routes/internal/schedule.ts +0 -226
- package/src/routes/internal/types.ts +0 -22
- package/src/routes/openapi-auto.ts +0 -239
- package/src/routes/public/agent-access.ts +0 -23
- package/src/routes/public/agent-config.ts +0 -675
- package/src/routes/public/agent-history.ts +0 -422
- package/src/routes/public/agent-schedules.ts +0 -296
- package/src/routes/public/agent.ts +0 -1086
- package/src/routes/public/agents.ts +0 -373
- package/src/routes/public/channels.ts +0 -191
- package/src/routes/public/cli-auth.ts +0 -896
- package/src/routes/public/connections.ts +0 -574
- package/src/routes/public/landing.ts +0 -16
- package/src/routes/public/oauth.ts +0 -147
- package/src/routes/public/settings-auth.ts +0 -104
- package/src/routes/public/slack.ts +0 -173
- package/src/routes/shared/agent-ownership.ts +0 -101
- package/src/routes/shared/token-verifier.ts +0 -34
- package/src/services/bedrock-model-catalog.ts +0 -217
- package/src/services/bedrock-openai-service.ts +0 -658
- package/src/services/core-services.ts +0 -1072
- package/src/services/image-generation-service.ts +0 -257
- package/src/services/instruction-service.ts +0 -318
- package/src/services/mcp-registry.ts +0 -94
- package/src/services/platform-helpers.ts +0 -287
- package/src/services/session-manager.ts +0 -262
- package/src/services/settings-resolver.ts +0 -74
- package/src/services/system-config-resolver.ts +0 -89
- package/src/services/system-skills-service.ts +0 -229
- package/src/services/transcription-service.ts +0 -684
- package/src/session.ts +0 -110
- package/src/spaces/index.ts +0 -1
- package/src/spaces/space-resolver.ts +0 -17
- package/src/stores/in-memory-agent-store.ts +0 -403
- package/src/stores/redis-agent-store.ts +0 -279
- package/src/utils/public-url.ts +0 -44
- package/src/utils/rate-limiter.ts +0 -94
- package/tsconfig.json +0 -33
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -1,1072 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
type AgentAccessStore,
|
|
5
|
-
type AgentConfigStore,
|
|
6
|
-
type AgentConnectionStore,
|
|
7
|
-
CommandRegistry,
|
|
8
|
-
createLogger,
|
|
9
|
-
moduleRegistry,
|
|
10
|
-
type SystemSkillEntry,
|
|
11
|
-
} from "@lobu/core";
|
|
12
|
-
import { AgentMetadataStore } from "../auth/agent-metadata-store";
|
|
13
|
-
import { ApiKeyProviderModule } from "../auth/api-key-provider-module";
|
|
14
|
-
import { BedrockProviderModule } from "../auth/bedrock/provider-module";
|
|
15
|
-
import { ChatGPTOAuthModule } from "../auth/chatgpt";
|
|
16
|
-
import { ClaudeOAuthModule } from "../auth/claude/oauth-module";
|
|
17
|
-
import { ExternalAuthClient } from "../auth/external/client";
|
|
18
|
-
import { McpConfigService } from "../auth/mcp/config-service";
|
|
19
|
-
import { McpProxy } from "../auth/mcp/proxy";
|
|
20
|
-
import { McpToolCache } from "../auth/mcp/tool-cache";
|
|
21
|
-
import { OAuthClient } from "../auth/oauth/client";
|
|
22
|
-
import { CLAUDE_PROVIDER } from "../auth/oauth/providers";
|
|
23
|
-
import {
|
|
24
|
-
createOAuthStateStore,
|
|
25
|
-
type ProviderOAuthStateStore,
|
|
26
|
-
} from "../auth/oauth/state-store";
|
|
27
|
-
import { ProviderCatalogService } from "../auth/provider-catalog";
|
|
28
|
-
import { AgentSettingsStore, AuthProfilesManager } from "../auth/settings";
|
|
29
|
-
import { ModelPreferenceStore } from "../auth/settings/model-preference-store";
|
|
30
|
-
import { UserAgentsStore } from "../auth/user-agents-store";
|
|
31
|
-
import { ChannelBindingService } from "../channels";
|
|
32
|
-
import { registerBuiltInCommands } from "../commands/built-in-commands";
|
|
33
|
-
import type { AgentConfig, GatewayConfig } from "../config";
|
|
34
|
-
import {
|
|
35
|
-
type FileLoadedAgent,
|
|
36
|
-
loadAgentConfigFromFiles,
|
|
37
|
-
} from "../config/file-loader";
|
|
38
|
-
import { WorkerGateway } from "../gateway";
|
|
39
|
-
import type { IMessageQueue } from "../infrastructure/queue";
|
|
40
|
-
import {
|
|
41
|
-
QueueProducer,
|
|
42
|
-
RedisQueue,
|
|
43
|
-
type RedisQueueConfig,
|
|
44
|
-
} from "../infrastructure/queue";
|
|
45
|
-
import { InteractionService } from "../interactions";
|
|
46
|
-
import { getModelProviderModules } from "../modules/module-system";
|
|
47
|
-
import {
|
|
48
|
-
ScheduledWakeupService,
|
|
49
|
-
setScheduledWakeupService,
|
|
50
|
-
} from "../orchestration/scheduled-wakeup";
|
|
51
|
-
import { GrantStore } from "../permissions/grant-store";
|
|
52
|
-
import { SecretProxy } from "../proxy/secret-proxy";
|
|
53
|
-
import { TokenRefreshJob } from "../proxy/token-refresh-job";
|
|
54
|
-
import { InMemoryAgentStore } from "../stores/in-memory-agent-store";
|
|
55
|
-
import {
|
|
56
|
-
RedisAgentAccessStore,
|
|
57
|
-
RedisAgentConfigStore,
|
|
58
|
-
RedisAgentConnectionStore,
|
|
59
|
-
} from "../stores/redis-agent-store";
|
|
60
|
-
import { ImageGenerationService } from "./image-generation-service";
|
|
61
|
-
import { BedrockModelCatalog } from "./bedrock-model-catalog";
|
|
62
|
-
import { BedrockOpenAIService } from "./bedrock-openai-service";
|
|
63
|
-
import { InstructionService } from "./instruction-service";
|
|
64
|
-
import { RedisSessionStore, SessionManager } from "./session-manager";
|
|
65
|
-
import { SettingsResolver } from "./settings-resolver";
|
|
66
|
-
import { SystemConfigResolver } from "./system-config-resolver";
|
|
67
|
-
import { SystemSkillsService } from "./system-skills-service";
|
|
68
|
-
import { TranscriptionService } from "./transcription-service";
|
|
69
|
-
|
|
70
|
-
const logger = createLogger("core-services");
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Core Services - Centralized service initialization and lifecycle management
|
|
74
|
-
*/
|
|
75
|
-
export class CoreServices {
|
|
76
|
-
// ============================================================================
|
|
77
|
-
// Queue Services
|
|
78
|
-
// ============================================================================
|
|
79
|
-
private queue?: IMessageQueue;
|
|
80
|
-
private queueProducer?: QueueProducer;
|
|
81
|
-
|
|
82
|
-
// ============================================================================
|
|
83
|
-
// Session Services
|
|
84
|
-
// ============================================================================
|
|
85
|
-
private sessionManager?: SessionManager;
|
|
86
|
-
private instructionService?: InstructionService;
|
|
87
|
-
private interactionService?: InteractionService;
|
|
88
|
-
|
|
89
|
-
// ============================================================================
|
|
90
|
-
// Auth & Provider Services
|
|
91
|
-
// ============================================================================
|
|
92
|
-
private authProfilesManager?: AuthProfilesManager;
|
|
93
|
-
private modelPreferenceStore?: ModelPreferenceStore;
|
|
94
|
-
private oauthStateStore?: ProviderOAuthStateStore;
|
|
95
|
-
private secretProxy?: SecretProxy;
|
|
96
|
-
private tokenRefreshJob?: TokenRefreshJob;
|
|
97
|
-
|
|
98
|
-
// ============================================================================
|
|
99
|
-
// MCP Services
|
|
100
|
-
// ============================================================================
|
|
101
|
-
private mcpConfigService?: McpConfigService;
|
|
102
|
-
private mcpProxy?: McpProxy;
|
|
103
|
-
|
|
104
|
-
// ============================================================================
|
|
105
|
-
// Permissions
|
|
106
|
-
// ============================================================================
|
|
107
|
-
private grantStore?: GrantStore;
|
|
108
|
-
|
|
109
|
-
// ============================================================================
|
|
110
|
-
// System Skills Service
|
|
111
|
-
// ============================================================================
|
|
112
|
-
private systemSkillsService?: SystemSkillsService;
|
|
113
|
-
private systemConfigResolver?: SystemConfigResolver;
|
|
114
|
-
|
|
115
|
-
// ============================================================================
|
|
116
|
-
// Worker Gateway
|
|
117
|
-
// ============================================================================
|
|
118
|
-
private workerGateway?: WorkerGateway;
|
|
119
|
-
|
|
120
|
-
// ============================================================================
|
|
121
|
-
// Agent Configuration Services
|
|
122
|
-
// ============================================================================
|
|
123
|
-
private agentSettingsStore?: AgentSettingsStore;
|
|
124
|
-
private channelBindingService?: ChannelBindingService;
|
|
125
|
-
private transcriptionService?: TranscriptionService;
|
|
126
|
-
private imageGenerationService?: ImageGenerationService;
|
|
127
|
-
private bedrockOpenAIService?: BedrockOpenAIService;
|
|
128
|
-
private userAgentsStore?: UserAgentsStore;
|
|
129
|
-
private agentMetadataStore?: AgentMetadataStore;
|
|
130
|
-
|
|
131
|
-
// ============================================================================
|
|
132
|
-
// External OAuth
|
|
133
|
-
// ============================================================================
|
|
134
|
-
private externalAuthClient?: ExternalAuthClient;
|
|
135
|
-
|
|
136
|
-
// ============================================================================
|
|
137
|
-
// Provider Catalog
|
|
138
|
-
// ============================================================================
|
|
139
|
-
private providerCatalogService?: ProviderCatalogService;
|
|
140
|
-
|
|
141
|
-
// ============================================================================
|
|
142
|
-
// Command Registry
|
|
143
|
-
// ============================================================================
|
|
144
|
-
private commandRegistry?: CommandRegistry;
|
|
145
|
-
|
|
146
|
-
// ============================================================================
|
|
147
|
-
// Scheduled Wakeup Service
|
|
148
|
-
// ============================================================================
|
|
149
|
-
private scheduledWakeupService?: ScheduledWakeupService;
|
|
150
|
-
|
|
151
|
-
// ============================================================================
|
|
152
|
-
// Agent Sub-Stores (injectable — host can provide its own implementations)
|
|
153
|
-
// ============================================================================
|
|
154
|
-
private configStore?: AgentConfigStore;
|
|
155
|
-
private connectionStore?: AgentConnectionStore;
|
|
156
|
-
private accessStore?: AgentAccessStore;
|
|
157
|
-
private settingsResolver?: SettingsResolver;
|
|
158
|
-
|
|
159
|
-
// File-first architecture state
|
|
160
|
-
private fileLoadedAgents: FileLoadedAgent[] = [];
|
|
161
|
-
private projectPath: string | null = null;
|
|
162
|
-
private configAgents: AgentConfig[] = [];
|
|
163
|
-
|
|
164
|
-
// Options stored for deferred initialization
|
|
165
|
-
private options?: {
|
|
166
|
-
configStore?: AgentConfigStore;
|
|
167
|
-
connectionStore?: AgentConnectionStore;
|
|
168
|
-
accessStore?: AgentAccessStore;
|
|
169
|
-
systemSkills?: SystemSkillEntry[];
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
constructor(
|
|
173
|
-
private readonly config: GatewayConfig,
|
|
174
|
-
options?: {
|
|
175
|
-
configStore?: AgentConfigStore;
|
|
176
|
-
connectionStore?: AgentConnectionStore;
|
|
177
|
-
accessStore?: AgentAccessStore;
|
|
178
|
-
systemSkills?: SystemSkillEntry[];
|
|
179
|
-
}
|
|
180
|
-
) {
|
|
181
|
-
this.options = options;
|
|
182
|
-
if (options?.configStore) this.configStore = options.configStore;
|
|
183
|
-
if (options?.connectionStore)
|
|
184
|
-
this.connectionStore = options.connectionStore;
|
|
185
|
-
if (options?.accessStore) this.accessStore = options.accessStore;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
getConfigStore(): AgentConfigStore | undefined {
|
|
189
|
-
return this.configStore;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
getConnectionStore(): AgentConnectionStore | undefined {
|
|
193
|
-
return this.connectionStore;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
getAccessStore(): AgentAccessStore | undefined {
|
|
197
|
-
return this.accessStore;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
getSettingsResolver(): SettingsResolver | undefined {
|
|
201
|
-
return this.settingsResolver;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Initialize all core services in dependency order
|
|
206
|
-
*/
|
|
207
|
-
async initialize(): Promise<void> {
|
|
208
|
-
logger.debug("Initializing core services...");
|
|
209
|
-
|
|
210
|
-
// 1. Queue (foundation for everything else)
|
|
211
|
-
await this.initializeQueue();
|
|
212
|
-
logger.debug("Queue initialized");
|
|
213
|
-
|
|
214
|
-
// 2. Session management
|
|
215
|
-
await this.initializeSessionServices();
|
|
216
|
-
logger.debug("Session services initialized");
|
|
217
|
-
|
|
218
|
-
// 3. Auth & provider services
|
|
219
|
-
await this.initializeClaudeServices();
|
|
220
|
-
logger.debug("Auth & provider services initialized");
|
|
221
|
-
|
|
222
|
-
// 4. MCP ecosystem (depends on queue and Claude services)
|
|
223
|
-
await this.initializeMcpServices();
|
|
224
|
-
logger.debug("MCP services initialized");
|
|
225
|
-
|
|
226
|
-
// 5. Queue producer (depends on queue being ready)
|
|
227
|
-
await this.initializeQueueProducer();
|
|
228
|
-
logger.debug("Queue producer initialized");
|
|
229
|
-
|
|
230
|
-
// 6. Scheduled wakeup service (depends on queue)
|
|
231
|
-
await this.initializeScheduledWakeupService();
|
|
232
|
-
logger.debug("Scheduled wakeup service initialized");
|
|
233
|
-
|
|
234
|
-
// 7. Command registry (depends on agent settings store)
|
|
235
|
-
this.initializeCommandRegistry();
|
|
236
|
-
logger.debug("Command registry initialized");
|
|
237
|
-
|
|
238
|
-
logger.info("Core services initialized successfully");
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// ============================================================================
|
|
242
|
-
// 1. Queue Services Initialization
|
|
243
|
-
// ============================================================================
|
|
244
|
-
|
|
245
|
-
private async initializeQueue(): Promise<void> {
|
|
246
|
-
if (!this.config.queues?.connectionString) {
|
|
247
|
-
throw new Error("Queue connection string is required");
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const url = new URL(this.config.queues.connectionString);
|
|
251
|
-
if (url.protocol !== "redis:") {
|
|
252
|
-
throw new Error(
|
|
253
|
-
`Unsupported queue protocol: ${url.protocol}. Only redis:// is supported.`
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const config: RedisQueueConfig = {
|
|
258
|
-
host: url.hostname,
|
|
259
|
-
port: Number.parseInt(url.port, 10) || 6379,
|
|
260
|
-
password: url.password || undefined,
|
|
261
|
-
db: url.pathname ? Number.parseInt(url.pathname.slice(1), 10) : 0,
|
|
262
|
-
maxRetriesPerRequest: 3,
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
this.queue = new RedisQueue(config);
|
|
266
|
-
await this.queue.start();
|
|
267
|
-
logger.debug("Queue connection established");
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
private async initializeQueueProducer(): Promise<void> {
|
|
271
|
-
if (!this.queue) {
|
|
272
|
-
throw new Error("Queue must be initialized before queue producer");
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
this.queueProducer = new QueueProducer(this.queue);
|
|
276
|
-
await this.queueProducer.start();
|
|
277
|
-
logger.debug("Queue producer initialized");
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// ============================================================================
|
|
281
|
-
// Scheduled Wakeup Service Initialization
|
|
282
|
-
// ============================================================================
|
|
283
|
-
|
|
284
|
-
private async initializeScheduledWakeupService(): Promise<void> {
|
|
285
|
-
if (!this.queue) {
|
|
286
|
-
throw new Error(
|
|
287
|
-
"Queue must be initialized before scheduled wakeup service"
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
this.scheduledWakeupService = new ScheduledWakeupService(this.queue);
|
|
292
|
-
await this.scheduledWakeupService.start();
|
|
293
|
-
// Set global reference for BaseDeploymentManager cleanup
|
|
294
|
-
setScheduledWakeupService(this.scheduledWakeupService);
|
|
295
|
-
logger.debug("Scheduled wakeup service initialized");
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// ============================================================================
|
|
299
|
-
// 2. Session Services Initialization
|
|
300
|
-
// ============================================================================
|
|
301
|
-
|
|
302
|
-
private async initializeSessionServices(): Promise<void> {
|
|
303
|
-
if (!this.queue) {
|
|
304
|
-
throw new Error("Queue must be initialized before session services");
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
const redisClient = this.queue.getRedisClient();
|
|
308
|
-
|
|
309
|
-
const sessionStore = new RedisSessionStore(this.queue);
|
|
310
|
-
this.sessionManager = new SessionManager(sessionStore);
|
|
311
|
-
logger.debug("Session manager initialized");
|
|
312
|
-
|
|
313
|
-
this.interactionService = new InteractionService();
|
|
314
|
-
logger.debug("Interaction service initialized");
|
|
315
|
-
|
|
316
|
-
// Initialize grant store for unified permissions
|
|
317
|
-
this.grantStore = new GrantStore(redisClient);
|
|
318
|
-
logger.debug("Grant store initialized");
|
|
319
|
-
|
|
320
|
-
// Initialize agent configuration stores
|
|
321
|
-
this.agentSettingsStore = new AgentSettingsStore(redisClient);
|
|
322
|
-
this.channelBindingService = new ChannelBindingService(redisClient);
|
|
323
|
-
this.userAgentsStore = new UserAgentsStore(redisClient);
|
|
324
|
-
this.agentMetadataStore = new AgentMetadataStore(redisClient);
|
|
325
|
-
logger.debug(
|
|
326
|
-
"Agent settings, channel binding, user agents & metadata stores initialized"
|
|
327
|
-
);
|
|
328
|
-
|
|
329
|
-
// Initialize agent sub-stores
|
|
330
|
-
if (!this.configStore || !this.connectionStore || !this.accessStore) {
|
|
331
|
-
if (this.config.agents?.length) {
|
|
332
|
-
const inMemoryStore = new InMemoryAgentStore();
|
|
333
|
-
if (!this.configStore) this.configStore = inMemoryStore;
|
|
334
|
-
if (!this.connectionStore) this.connectionStore = inMemoryStore;
|
|
335
|
-
if (!this.accessStore) this.accessStore = inMemoryStore;
|
|
336
|
-
|
|
337
|
-
await this.populateStoreFromAgentConfigs(
|
|
338
|
-
inMemoryStore,
|
|
339
|
-
this.config.agents
|
|
340
|
-
);
|
|
341
|
-
logger.debug(
|
|
342
|
-
`Agent sub-stores initialized (in-memory, ${this.config.agents.length} agent(s) from config)`
|
|
343
|
-
);
|
|
344
|
-
} else {
|
|
345
|
-
// Check if lobu.toml exists (file-first dev mode)
|
|
346
|
-
const { existsSync } = await import("node:fs");
|
|
347
|
-
const { resolve } = await import("node:path");
|
|
348
|
-
const workspaceRoot = process.env.LOBU_WORKSPACE_ROOT?.trim();
|
|
349
|
-
const candidatePaths = [
|
|
350
|
-
...(workspaceRoot ? [resolve(workspaceRoot, "lobu.toml")] : []),
|
|
351
|
-
resolve(process.cwd(), "lobu.toml"),
|
|
352
|
-
resolve("/app/lobu.toml"),
|
|
353
|
-
];
|
|
354
|
-
const tomlPath = candidatePaths.find((p) => existsSync(p));
|
|
355
|
-
|
|
356
|
-
if (tomlPath) {
|
|
357
|
-
const inMemoryStore = new InMemoryAgentStore();
|
|
358
|
-
if (!this.configStore) this.configStore = inMemoryStore;
|
|
359
|
-
if (!this.connectionStore) this.connectionStore = inMemoryStore;
|
|
360
|
-
if (!this.accessStore) this.accessStore = inMemoryStore;
|
|
361
|
-
|
|
362
|
-
// File-first dev mode: use InMemoryAgentStore populated from files
|
|
363
|
-
this.projectPath = resolve(tomlPath, "..");
|
|
364
|
-
|
|
365
|
-
// Load agents from files and populate store
|
|
366
|
-
this.fileLoadedAgents = await loadAgentConfigFromFiles(
|
|
367
|
-
this.projectPath
|
|
368
|
-
);
|
|
369
|
-
await this.populateStoreFromFiles(
|
|
370
|
-
inMemoryStore,
|
|
371
|
-
this.fileLoadedAgents
|
|
372
|
-
);
|
|
373
|
-
logger.debug(
|
|
374
|
-
`Agent sub-stores initialized (in-memory, ${this.fileLoadedAgents.length} agent(s) from files)`
|
|
375
|
-
);
|
|
376
|
-
} else {
|
|
377
|
-
if (!this.configStore) {
|
|
378
|
-
this.configStore = new RedisAgentConfigStore(
|
|
379
|
-
this.agentSettingsStore,
|
|
380
|
-
this.agentMetadataStore
|
|
381
|
-
);
|
|
382
|
-
}
|
|
383
|
-
if (!this.connectionStore) {
|
|
384
|
-
this.connectionStore = new RedisAgentConnectionStore(
|
|
385
|
-
redisClient,
|
|
386
|
-
this.channelBindingService
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
|
-
if (!this.accessStore) {
|
|
390
|
-
this.accessStore = new RedisAgentAccessStore(
|
|
391
|
-
this.grantStore,
|
|
392
|
-
this.userAgentsStore
|
|
393
|
-
);
|
|
394
|
-
}
|
|
395
|
-
logger.debug("Agent sub-stores initialized (Redis-backed defaults)");
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
} else {
|
|
399
|
-
logger.debug("Using host-provided agent sub-stores (embedded mode)");
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// Create settings resolver (template fallback logic)
|
|
403
|
-
this.settingsResolver = new SettingsResolver(
|
|
404
|
-
this.configStore,
|
|
405
|
-
this.connectionStore
|
|
406
|
-
);
|
|
407
|
-
|
|
408
|
-
// Initialize external OAuth client if configured
|
|
409
|
-
this.externalAuthClient =
|
|
410
|
-
ExternalAuthClient.fromEnv(this.config.mcp.publicGatewayUrl, {
|
|
411
|
-
get: (key) => redisClient.get(key),
|
|
412
|
-
set: (key, value, ttlSeconds) =>
|
|
413
|
-
redisClient.setex(key, ttlSeconds, value),
|
|
414
|
-
}) ?? undefined;
|
|
415
|
-
if (this.externalAuthClient) {
|
|
416
|
-
logger.debug("External OAuth client initialized");
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
// ============================================================================
|
|
421
|
-
// 3. Auth & Provider Services Initialization
|
|
422
|
-
// ============================================================================
|
|
423
|
-
|
|
424
|
-
private async initializeClaudeServices(): Promise<void> {
|
|
425
|
-
if (!this.queue) {
|
|
426
|
-
throw new Error("Queue must be initialized before auth services");
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
const redisClient = this.queue.getRedisClient();
|
|
430
|
-
|
|
431
|
-
if (!this.agentSettingsStore) {
|
|
432
|
-
throw new Error(
|
|
433
|
-
"Agent settings store must be initialized before auth services"
|
|
434
|
-
);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
if (this.fileLoadedAgents.length > 0) {
|
|
438
|
-
for (const agent of this.fileLoadedAgents) {
|
|
439
|
-
await this.syncAgentSettingsToRuntimeStore(
|
|
440
|
-
agent.agentId,
|
|
441
|
-
agent.settings
|
|
442
|
-
);
|
|
443
|
-
}
|
|
444
|
-
logger.debug(
|
|
445
|
-
`Synced settings for ${this.fileLoadedAgents.length} file-loaded agent(s)`
|
|
446
|
-
);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
if (this.configAgents.length > 0) {
|
|
450
|
-
for (const agent of this.configAgents) {
|
|
451
|
-
await this.syncAgentSettingsToRuntimeStore(
|
|
452
|
-
agent.id,
|
|
453
|
-
this.buildSettingsFromAgentConfig(agent)
|
|
454
|
-
);
|
|
455
|
-
}
|
|
456
|
-
logger.debug(
|
|
457
|
-
`Synced settings for ${this.configAgents.length} config agent(s)`
|
|
458
|
-
);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
// Initialize auth profile and preference stores
|
|
462
|
-
this.authProfilesManager = new AuthProfilesManager(this.agentSettingsStore);
|
|
463
|
-
this.transcriptionService = new TranscriptionService(
|
|
464
|
-
this.authProfilesManager
|
|
465
|
-
);
|
|
466
|
-
this.imageGenerationService = new ImageGenerationService(
|
|
467
|
-
this.authProfilesManager
|
|
468
|
-
);
|
|
469
|
-
this.modelPreferenceStore = new ModelPreferenceStore(redisClient, "claude");
|
|
470
|
-
|
|
471
|
-
// Seed provider credentials from file-loaded agents
|
|
472
|
-
if (this.authProfilesManager && this.fileLoadedAgents.length > 0) {
|
|
473
|
-
for (const agent of this.fileLoadedAgents) {
|
|
474
|
-
for (const cred of agent.credentials) {
|
|
475
|
-
await this.authProfilesManager.upsertProfile({
|
|
476
|
-
agentId: agent.agentId,
|
|
477
|
-
provider: cred.provider,
|
|
478
|
-
credential: cred.key,
|
|
479
|
-
authType: "api-key",
|
|
480
|
-
label: `${cred.provider} (from lobu.toml)`,
|
|
481
|
-
makePrimary: true,
|
|
482
|
-
});
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
logger.debug(
|
|
486
|
-
`Seeded credentials for ${this.fileLoadedAgents.length} file-loaded agent(s)`
|
|
487
|
-
);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
// Seed provider credentials from config agents (embedded mode)
|
|
491
|
-
if (this.authProfilesManager && this.configAgents.length > 0) {
|
|
492
|
-
for (const agent of this.configAgents) {
|
|
493
|
-
for (const provider of agent.providers || []) {
|
|
494
|
-
if (!provider.key) continue;
|
|
495
|
-
await this.authProfilesManager.upsertProfile({
|
|
496
|
-
agentId: agent.id,
|
|
497
|
-
provider: provider.id,
|
|
498
|
-
credential: provider.key,
|
|
499
|
-
authType: "api-key",
|
|
500
|
-
label: `${provider.id} (from config)`,
|
|
501
|
-
makePrimary: true,
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
logger.debug(
|
|
506
|
-
`Seeded credentials for ${this.configAgents.length} config agent(s)`
|
|
507
|
-
);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
logger.debug(
|
|
511
|
-
"Auth profile, model preference, transcription, and image generation services initialized"
|
|
512
|
-
);
|
|
513
|
-
|
|
514
|
-
// Initialize secret injection proxy (will be finalized after provider modules are registered)
|
|
515
|
-
this.secretProxy = new SecretProxy({
|
|
516
|
-
defaultUpstreamUrl:
|
|
517
|
-
this.config.anthropicProxy.anthropicBaseUrl ||
|
|
518
|
-
"https://api.anthropic.com",
|
|
519
|
-
});
|
|
520
|
-
this.secretProxy.initialize(redisClient);
|
|
521
|
-
logger.debug(
|
|
522
|
-
`Secret proxy initialized (upstream: ${this.config.anthropicProxy.anthropicBaseUrl || "https://api.anthropic.com"})`
|
|
523
|
-
);
|
|
524
|
-
|
|
525
|
-
// Start background token refresh job
|
|
526
|
-
if (!this.authProfilesManager) {
|
|
527
|
-
throw new Error(
|
|
528
|
-
"Auth profiles manager must be initialized before token refresh job"
|
|
529
|
-
);
|
|
530
|
-
}
|
|
531
|
-
this.tokenRefreshJob = new TokenRefreshJob(
|
|
532
|
-
this.authProfilesManager,
|
|
533
|
-
redisClient,
|
|
534
|
-
[{ providerId: "claude", oauthClient: new OAuthClient(CLAUDE_PROVIDER) }]
|
|
535
|
-
);
|
|
536
|
-
this.tokenRefreshJob.start();
|
|
537
|
-
logger.debug("Token refresh job started");
|
|
538
|
-
|
|
539
|
-
// Register Claude OAuth module
|
|
540
|
-
this.oauthStateStore = createOAuthStateStore("claude", redisClient);
|
|
541
|
-
const claudeOAuthModule = new ClaudeOAuthModule(
|
|
542
|
-
this.authProfilesManager,
|
|
543
|
-
this.modelPreferenceStore
|
|
544
|
-
);
|
|
545
|
-
moduleRegistry.register(claudeOAuthModule);
|
|
546
|
-
logger.debug(
|
|
547
|
-
`Claude OAuth module registered (system token: ${claudeOAuthModule.hasSystemKey() ? "available" : "not available"})`
|
|
548
|
-
);
|
|
549
|
-
|
|
550
|
-
// Register ChatGPT OAuth module
|
|
551
|
-
const chatgptOAuthModule = new ChatGPTOAuthModule(this.agentSettingsStore);
|
|
552
|
-
moduleRegistry.register(chatgptOAuthModule);
|
|
553
|
-
logger.debug(
|
|
554
|
-
`ChatGPT OAuth module registered (system token: ${chatgptOAuthModule.hasSystemKey() ? "available" : "not available"})`
|
|
555
|
-
);
|
|
556
|
-
|
|
557
|
-
const bedrockModelCatalog = new BedrockModelCatalog();
|
|
558
|
-
const bedrockProviderModule = new BedrockProviderModule(
|
|
559
|
-
this.authProfilesManager,
|
|
560
|
-
bedrockModelCatalog
|
|
561
|
-
);
|
|
562
|
-
moduleRegistry.register(bedrockProviderModule);
|
|
563
|
-
this.bedrockOpenAIService = new BedrockOpenAIService({
|
|
564
|
-
modelCatalog: bedrockModelCatalog,
|
|
565
|
-
});
|
|
566
|
-
logger.debug("Bedrock provider module registered");
|
|
567
|
-
|
|
568
|
-
// Initialize system skills — use injected skills if provided, else load from file
|
|
569
|
-
if (this.options?.systemSkills) {
|
|
570
|
-
this.systemSkillsService = new SystemSkillsService(
|
|
571
|
-
undefined,
|
|
572
|
-
this.options.systemSkills
|
|
573
|
-
);
|
|
574
|
-
} else {
|
|
575
|
-
this.systemSkillsService = new SystemSkillsService(
|
|
576
|
-
"config/system-skills.json"
|
|
577
|
-
);
|
|
578
|
-
}
|
|
579
|
-
this.systemConfigResolver = new SystemConfigResolver(
|
|
580
|
-
this.systemSkillsService
|
|
581
|
-
);
|
|
582
|
-
logger.debug("System skills service initialized");
|
|
583
|
-
|
|
584
|
-
this.transcriptionService?.setProviderConfigSource(() =>
|
|
585
|
-
this.systemConfigResolver
|
|
586
|
-
? this.systemConfigResolver.getProviderConfigs()
|
|
587
|
-
: Promise.resolve({})
|
|
588
|
-
);
|
|
589
|
-
|
|
590
|
-
// Register config-driven providers from system skills
|
|
591
|
-
const configProviders =
|
|
592
|
-
await this.systemConfigResolver.getProviderConfigs();
|
|
593
|
-
const registeredIds = new Set(
|
|
594
|
-
getModelProviderModules().map((m) => m.providerId)
|
|
595
|
-
);
|
|
596
|
-
for (const [id, entry] of Object.entries(configProviders)) {
|
|
597
|
-
if (registeredIds.has(id)) {
|
|
598
|
-
logger.info(
|
|
599
|
-
`Skipping config-driven provider "${id}" — already registered`
|
|
600
|
-
);
|
|
601
|
-
continue;
|
|
602
|
-
}
|
|
603
|
-
const module = new ApiKeyProviderModule({
|
|
604
|
-
providerId: id,
|
|
605
|
-
providerDisplayName: entry.displayName,
|
|
606
|
-
providerIconUrl: entry.iconUrl,
|
|
607
|
-
envVarName: entry.envVarName,
|
|
608
|
-
slug: id,
|
|
609
|
-
upstreamBaseUrl: entry.upstreamBaseUrl,
|
|
610
|
-
modelsEndpoint: entry.modelsEndpoint,
|
|
611
|
-
sdkCompat: entry.sdkCompat,
|
|
612
|
-
defaultModel: entry.defaultModel,
|
|
613
|
-
registryAlias: entry.registryAlias,
|
|
614
|
-
apiKeyInstructions: entry.apiKeyInstructions,
|
|
615
|
-
apiKeyPlaceholder: entry.apiKeyPlaceholder,
|
|
616
|
-
agentSettingsStore: this.agentSettingsStore,
|
|
617
|
-
});
|
|
618
|
-
moduleRegistry.register(module);
|
|
619
|
-
registeredIds.add(id);
|
|
620
|
-
logger.debug(
|
|
621
|
-
`Registered config-driven provider: ${id} (system key: ${module.hasSystemKey() ? "available" : "not available"})`
|
|
622
|
-
);
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
// Initialize provider catalog service
|
|
626
|
-
this.providerCatalogService = new ProviderCatalogService(
|
|
627
|
-
this.agentSettingsStore,
|
|
628
|
-
this.authProfilesManager
|
|
629
|
-
);
|
|
630
|
-
logger.debug("Provider catalog service initialized");
|
|
631
|
-
|
|
632
|
-
// Register provider upstream configs with the secret proxy for path-based routing
|
|
633
|
-
if (this.secretProxy) {
|
|
634
|
-
this.secretProxy.setAuthProfilesManager(this.authProfilesManager);
|
|
635
|
-
for (const provider of getModelProviderModules()) {
|
|
636
|
-
const upstream = provider.getUpstreamConfig?.();
|
|
637
|
-
if (upstream) {
|
|
638
|
-
this.secretProxy.registerUpstream(upstream, provider.providerId);
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
// Register system key resolver for fallback when no per-agent auth profile exists
|
|
642
|
-
const modules = getModelProviderModules();
|
|
643
|
-
this.secretProxy.setSystemKeyResolver((providerId: string) => {
|
|
644
|
-
const mod = modules.find((m) => m.providerId === providerId);
|
|
645
|
-
if (!mod) return undefined;
|
|
646
|
-
// Use the module's injectSystemKeyFallback to resolve the system key.
|
|
647
|
-
// The fallback may inject into a different env var than credentialEnvVarName
|
|
648
|
-
// (e.g., Claude injects ANTHROPIC_API_KEY, not CLAUDE_CODE_OAUTH_TOKEN),
|
|
649
|
-
// so check all secret env var names.
|
|
650
|
-
const testEnv: Record<string, string> = {};
|
|
651
|
-
mod.injectSystemKeyFallback(testEnv);
|
|
652
|
-
for (const varName of mod.getSecretEnvVarNames()) {
|
|
653
|
-
if (testEnv[varName]) return testEnv[varName];
|
|
654
|
-
}
|
|
655
|
-
return testEnv[mod.getCredentialEnvVarName()] || undefined;
|
|
656
|
-
});
|
|
657
|
-
logger.debug("Provider upstreams registered with secret proxy");
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
// ============================================================================
|
|
662
|
-
// 4. MCP Services Initialization
|
|
663
|
-
// ============================================================================
|
|
664
|
-
|
|
665
|
-
private async initializeMcpServices(): Promise<void> {
|
|
666
|
-
if (!this.queue) {
|
|
667
|
-
throw new Error("Queue must be initialized before MCP services");
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
const redisClient = this.queue.getRedisClient();
|
|
671
|
-
|
|
672
|
-
// Initialize simplified MCP config service (no OAuth discovery)
|
|
673
|
-
this.mcpConfigService = new McpConfigService({
|
|
674
|
-
agentSettingsStore: this.agentSettingsStore,
|
|
675
|
-
configResolver: this.systemConfigResolver,
|
|
676
|
-
});
|
|
677
|
-
|
|
678
|
-
// Initialize instruction service (needed by WorkerGateway)
|
|
679
|
-
this.instructionService = new InstructionService(
|
|
680
|
-
this.mcpConfigService,
|
|
681
|
-
this.agentSettingsStore
|
|
682
|
-
);
|
|
683
|
-
logger.debug("Instruction service initialized");
|
|
684
|
-
|
|
685
|
-
// Initialize MCP tool cache and proxy
|
|
686
|
-
const mcpToolCache = new McpToolCache(redisClient);
|
|
687
|
-
this.mcpProxy = new McpProxy(
|
|
688
|
-
this.mcpConfigService,
|
|
689
|
-
this.queue,
|
|
690
|
-
mcpToolCache,
|
|
691
|
-
this.grantStore
|
|
692
|
-
);
|
|
693
|
-
logger.debug("MCP proxy initialized");
|
|
694
|
-
|
|
695
|
-
// Initialize worker gateway
|
|
696
|
-
if (!this.sessionManager) {
|
|
697
|
-
throw new Error(
|
|
698
|
-
"Session manager must be initialized before worker gateway"
|
|
699
|
-
);
|
|
700
|
-
}
|
|
701
|
-
this.workerGateway = new WorkerGateway(
|
|
702
|
-
this.queue,
|
|
703
|
-
this.config.mcp.publicGatewayUrl,
|
|
704
|
-
this.sessionManager,
|
|
705
|
-
this.mcpConfigService,
|
|
706
|
-
this.instructionService,
|
|
707
|
-
this.mcpProxy,
|
|
708
|
-
this.providerCatalogService,
|
|
709
|
-
this.settingsResolver,
|
|
710
|
-
this.systemSkillsService
|
|
711
|
-
);
|
|
712
|
-
logger.debug("Worker gateway initialized");
|
|
713
|
-
|
|
714
|
-
// Discover and initialize all available modules
|
|
715
|
-
await moduleRegistry.registerAvailableModules();
|
|
716
|
-
await moduleRegistry.initAll();
|
|
717
|
-
logger.debug("Modules initialized");
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
// ============================================================================
|
|
721
|
-
// 7. Command Registry Initialization
|
|
722
|
-
// ============================================================================
|
|
723
|
-
|
|
724
|
-
private initializeCommandRegistry(): void {
|
|
725
|
-
if (!this.agentSettingsStore) {
|
|
726
|
-
throw new Error(
|
|
727
|
-
"Agent settings store must be initialized before command registry"
|
|
728
|
-
);
|
|
729
|
-
}
|
|
730
|
-
this.commandRegistry = new CommandRegistry();
|
|
731
|
-
registerBuiltInCommands(this.commandRegistry, {
|
|
732
|
-
agentSettingsStore: this.agentSettingsStore,
|
|
733
|
-
});
|
|
734
|
-
logger.debug("Command registry initialized with built-in commands");
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
// ============================================================================
|
|
738
|
-
// File-First Helpers
|
|
739
|
-
// ============================================================================
|
|
740
|
-
|
|
741
|
-
private async populateStoreFromFiles(
|
|
742
|
-
store: InMemoryAgentStore,
|
|
743
|
-
agents: FileLoadedAgent[]
|
|
744
|
-
): Promise<void> {
|
|
745
|
-
for (const agent of agents) {
|
|
746
|
-
await store.saveMetadata(agent.agentId, {
|
|
747
|
-
agentId: agent.agentId,
|
|
748
|
-
name: agent.name,
|
|
749
|
-
description: agent.description,
|
|
750
|
-
owner: { platform: "system", userId: "manifest" },
|
|
751
|
-
createdAt: Date.now(),
|
|
752
|
-
});
|
|
753
|
-
await store.saveSettings(agent.agentId, {
|
|
754
|
-
...agent.settings,
|
|
755
|
-
updatedAt: Date.now(),
|
|
756
|
-
} as any);
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
private buildSettingsFromAgentConfig(
|
|
761
|
-
agent: AgentConfig
|
|
762
|
-
): Record<string, any> {
|
|
763
|
-
const settings: Record<string, any> = {};
|
|
764
|
-
if (agent.identityMd) settings.identityMd = agent.identityMd;
|
|
765
|
-
if (agent.soulMd) settings.soulMd = agent.soulMd;
|
|
766
|
-
if (agent.userMd) settings.userMd = agent.userMd;
|
|
767
|
-
|
|
768
|
-
if (agent.providers?.length) {
|
|
769
|
-
settings.installedProviders = agent.providers.map((p) => ({
|
|
770
|
-
providerId: p.id,
|
|
771
|
-
installedAt: Date.now(),
|
|
772
|
-
}));
|
|
773
|
-
settings.modelSelection = { mode: "auto" };
|
|
774
|
-
const providerModelPreferences = Object.fromEntries(
|
|
775
|
-
agent.providers
|
|
776
|
-
.filter((p) => !!p.model?.trim())
|
|
777
|
-
.map((p) => [p.id, p.model!.trim()])
|
|
778
|
-
);
|
|
779
|
-
if (Object.keys(providerModelPreferences).length > 0) {
|
|
780
|
-
settings.providerModelPreferences = providerModelPreferences;
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
if (agent.skills?.mcp) {
|
|
785
|
-
settings.mcpServers = agent.skills.mcp;
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
if (agent.network) {
|
|
789
|
-
settings.networkConfig = {
|
|
790
|
-
allowedDomains: agent.network.allowed,
|
|
791
|
-
deniedDomains: agent.network.denied,
|
|
792
|
-
};
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
if (agent.nixPackages?.length) {
|
|
796
|
-
settings.nixConfig = { packages: agent.nixPackages };
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
return settings;
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
private async syncAgentSettingsToRuntimeStore(
|
|
803
|
-
agentId: string,
|
|
804
|
-
settings: Record<string, any>
|
|
805
|
-
): Promise<void> {
|
|
806
|
-
if (!this.agentSettingsStore) {
|
|
807
|
-
throw new Error("Agent settings store must be initialized");
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
const existing = await this.agentSettingsStore.getSettings(agentId);
|
|
811
|
-
await this.agentSettingsStore.saveSettings(agentId, {
|
|
812
|
-
...settings,
|
|
813
|
-
authProfiles: existing?.authProfiles,
|
|
814
|
-
mcpInstallNotified: existing?.mcpInstallNotified,
|
|
815
|
-
});
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
private async populateStoreFromAgentConfigs(
|
|
819
|
-
store: InMemoryAgentStore,
|
|
820
|
-
agents: AgentConfig[]
|
|
821
|
-
): Promise<void> {
|
|
822
|
-
for (const agent of agents) {
|
|
823
|
-
await store.saveMetadata(agent.id, {
|
|
824
|
-
agentId: agent.id,
|
|
825
|
-
name: agent.name,
|
|
826
|
-
description: agent.description,
|
|
827
|
-
owner: { platform: "system", userId: "config" },
|
|
828
|
-
createdAt: Date.now(),
|
|
829
|
-
});
|
|
830
|
-
await store.saveSettings(agent.id, {
|
|
831
|
-
...this.buildSettingsFromAgentConfig(agent),
|
|
832
|
-
updatedAt: Date.now(),
|
|
833
|
-
} as any);
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
// Store agent configs for credential seeding and connection seeding later
|
|
837
|
-
this.configAgents = agents;
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
/**
|
|
841
|
-
* Reload agent config from files (dev mode only).
|
|
842
|
-
* Re-reads lobu.toml + markdown, clears and re-populates the in-memory store.
|
|
843
|
-
*/
|
|
844
|
-
async reloadFromFiles(): Promise<{ reloaded: boolean; agents: string[] }> {
|
|
845
|
-
if (!this.projectPath) {
|
|
846
|
-
return { reloaded: false, agents: [] };
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
// Re-load from disk
|
|
850
|
-
this.fileLoadedAgents = await loadAgentConfigFromFiles(this.projectPath);
|
|
851
|
-
|
|
852
|
-
// Re-populate the in-memory store (clear existing data first)
|
|
853
|
-
if (this.configStore instanceof InMemoryAgentStore) {
|
|
854
|
-
const store = this.configStore as InMemoryAgentStore;
|
|
855
|
-
// Clear existing agents by loading fresh
|
|
856
|
-
const existing = await store.listAgents();
|
|
857
|
-
for (const meta of existing) {
|
|
858
|
-
// Only clear file-managed agents (owner: system/manifest)
|
|
859
|
-
if (
|
|
860
|
-
meta.owner?.platform === "system" &&
|
|
861
|
-
meta.owner?.userId === "manifest"
|
|
862
|
-
) {
|
|
863
|
-
await store.deleteSettings(meta.agentId);
|
|
864
|
-
await store.deleteMetadata(meta.agentId);
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
await this.populateStoreFromFiles(store, this.fileLoadedAgents);
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
if (this.agentSettingsStore) {
|
|
871
|
-
for (const agent of this.fileLoadedAgents) {
|
|
872
|
-
await this.syncAgentSettingsToRuntimeStore(
|
|
873
|
-
agent.agentId,
|
|
874
|
-
agent.settings
|
|
875
|
-
);
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
// Re-seed credentials
|
|
880
|
-
if (this.authProfilesManager) {
|
|
881
|
-
for (const agent of this.fileLoadedAgents) {
|
|
882
|
-
for (const cred of agent.credentials) {
|
|
883
|
-
await this.authProfilesManager.upsertProfile({
|
|
884
|
-
agentId: agent.agentId,
|
|
885
|
-
provider: cred.provider,
|
|
886
|
-
credential: cred.key,
|
|
887
|
-
authType: "api-key",
|
|
888
|
-
label: `${cred.provider} (from lobu.toml)`,
|
|
889
|
-
makePrimary: true,
|
|
890
|
-
});
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
const agentIds = this.fileLoadedAgents.map((a) => a.agentId);
|
|
896
|
-
logger.info(`Reloaded ${agentIds.length} agent(s) from files`);
|
|
897
|
-
return { reloaded: true, agents: agentIds };
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
getFileLoadedAgents(): FileLoadedAgent[] {
|
|
901
|
-
return this.fileLoadedAgents;
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
getConfigAgents(): AgentConfig[] {
|
|
905
|
-
return this.configAgents;
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
getProjectPath(): string | null {
|
|
909
|
-
return this.projectPath;
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
isFileFirstMode(): boolean {
|
|
913
|
-
return this.projectPath !== null;
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
// ============================================================================
|
|
917
|
-
// Shutdown
|
|
918
|
-
// ============================================================================
|
|
919
|
-
|
|
920
|
-
async shutdown(): Promise<void> {
|
|
921
|
-
logger.info("Shutting down core services...");
|
|
922
|
-
|
|
923
|
-
if (this.tokenRefreshJob) {
|
|
924
|
-
this.tokenRefreshJob.stop();
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
if (this.queueProducer) {
|
|
928
|
-
await this.queueProducer.stop();
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
if (this.workerGateway) {
|
|
932
|
-
this.workerGateway.shutdown();
|
|
933
|
-
logger.info("Worker gateway shutdown complete");
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
if (this.queue) {
|
|
937
|
-
await this.queue.stop();
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
logger.info("Core services shutdown complete");
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
// ============================================================================
|
|
944
|
-
// Service Accessors (implements ICoreServices interface)
|
|
945
|
-
// ============================================================================
|
|
946
|
-
|
|
947
|
-
getQueue(): IMessageQueue {
|
|
948
|
-
if (!this.queue) throw new Error("Queue not initialized");
|
|
949
|
-
return this.queue;
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
getQueueProducer(): QueueProducer {
|
|
953
|
-
if (!this.queueProducer) throw new Error("Queue producer not initialized");
|
|
954
|
-
return this.queueProducer;
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
getSecretProxy(): SecretProxy | undefined {
|
|
958
|
-
return this.secretProxy;
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
getWorkerGateway(): WorkerGateway | undefined {
|
|
962
|
-
return this.workerGateway;
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
getMcpProxy(): McpProxy | undefined {
|
|
966
|
-
return this.mcpProxy;
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
getMcpConfigService(): McpConfigService | undefined {
|
|
970
|
-
return this.mcpConfigService;
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
getModelPreferenceStore(): ModelPreferenceStore | undefined {
|
|
974
|
-
return this.modelPreferenceStore;
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
getOAuthStateStore(): ProviderOAuthStateStore | undefined {
|
|
978
|
-
return this.oauthStateStore;
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
getPublicGatewayUrl(): string {
|
|
982
|
-
return this.config.mcp.publicGatewayUrl;
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
getSessionManager(): SessionManager {
|
|
986
|
-
if (!this.sessionManager)
|
|
987
|
-
throw new Error("Session manager not initialized");
|
|
988
|
-
return this.sessionManager;
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
getInstructionService(): InstructionService | undefined {
|
|
992
|
-
return this.instructionService;
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
getInteractionService(): InteractionService {
|
|
996
|
-
if (!this.interactionService)
|
|
997
|
-
throw new Error("Interaction service not initialized");
|
|
998
|
-
return this.interactionService;
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
getAgentSettingsStore(): AgentSettingsStore {
|
|
1002
|
-
if (!this.agentSettingsStore)
|
|
1003
|
-
throw new Error("Agent settings store not initialized");
|
|
1004
|
-
return this.agentSettingsStore;
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
getChannelBindingService(): ChannelBindingService {
|
|
1008
|
-
if (!this.channelBindingService)
|
|
1009
|
-
throw new Error("Channel binding service not initialized");
|
|
1010
|
-
return this.channelBindingService;
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
getScheduledWakeupService(): ScheduledWakeupService | undefined {
|
|
1014
|
-
return this.scheduledWakeupService;
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
getTranscriptionService(): TranscriptionService | undefined {
|
|
1018
|
-
return this.transcriptionService;
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
getImageGenerationService(): ImageGenerationService | undefined {
|
|
1022
|
-
return this.imageGenerationService;
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
getBedrockOpenAIService(): BedrockOpenAIService | undefined {
|
|
1026
|
-
return this.bedrockOpenAIService;
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
getUserAgentsStore(): UserAgentsStore {
|
|
1030
|
-
if (!this.userAgentsStore)
|
|
1031
|
-
throw new Error("User agents store not initialized");
|
|
1032
|
-
return this.userAgentsStore;
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
getAgentMetadataStore(): AgentMetadataStore {
|
|
1036
|
-
if (!this.agentMetadataStore)
|
|
1037
|
-
throw new Error("Agent metadata store not initialized");
|
|
1038
|
-
return this.agentMetadataStore;
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
getCommandRegistry(): CommandRegistry {
|
|
1042
|
-
if (!this.commandRegistry)
|
|
1043
|
-
throw new Error("Command registry not initialized");
|
|
1044
|
-
return this.commandRegistry;
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
getProviderCatalogService(): ProviderCatalogService {
|
|
1048
|
-
if (!this.providerCatalogService)
|
|
1049
|
-
throw new Error("Provider catalog service not initialized");
|
|
1050
|
-
return this.providerCatalogService;
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
getAuthProfilesManager(): AuthProfilesManager | undefined {
|
|
1054
|
-
return this.authProfilesManager;
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
getGrantStore(): GrantStore | undefined {
|
|
1058
|
-
return this.grantStore;
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
|
-
getSystemSkillsService(): SystemSkillsService | undefined {
|
|
1062
|
-
return this.systemSkillsService;
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
getSystemConfigResolver(): SystemConfigResolver | undefined {
|
|
1066
|
-
return this.systemConfigResolver;
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
getExternalAuthClient(): ExternalAuthClient | undefined {
|
|
1070
|
-
return this.externalAuthClient;
|
|
1071
|
-
}
|
|
1072
|
-
}
|