@lobu/gateway 2.8.0 → 3.0.6
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/package.json +2 -2
- package/src/__tests__/agent-config-routes.test.ts +254 -0
- package/src/__tests__/agent-history-routes.test.ts +72 -0
- package/src/__tests__/agent-routes.test.ts +68 -0
- package/src/__tests__/agent-schedules-routes.test.ts +59 -0
- package/src/__tests__/agent-settings-store.test.ts +323 -0
- package/src/__tests__/chat-instance-manager-slack.test.ts +204 -0
- package/src/__tests__/chat-response-bridge.test.ts +131 -0
- package/src/__tests__/config-memory-plugins.test.ts +92 -0
- package/src/__tests__/config-request-store.test.ts +127 -0
- package/src/__tests__/connection-routes.test.ts +144 -0
- package/src/__tests__/core-services-store-selection.test.ts +92 -0
- package/src/__tests__/docker-deployment.test.ts +1211 -0
- package/src/__tests__/embedded-deployment.test.ts +342 -0
- package/src/__tests__/grant-store.test.ts +148 -0
- package/src/__tests__/http-proxy.test.ts +281 -0
- package/src/__tests__/instruction-service.test.ts +37 -0
- package/src/__tests__/link-buttons.test.ts +112 -0
- package/src/__tests__/lobu.test.ts +32 -0
- package/src/__tests__/mcp-config-service.test.ts +347 -0
- package/src/__tests__/mcp-proxy.test.ts +696 -0
- package/src/__tests__/message-handler-bridge.test.ts +17 -0
- package/src/__tests__/model-selection.test.ts +172 -0
- package/src/__tests__/oauth-templates.test.ts +39 -0
- package/src/__tests__/platform-adapter-slack-send.test.ts +114 -0
- package/src/__tests__/platform-helpers-model-resolution.test.ts +253 -0
- package/src/__tests__/provider-inheritance.test.ts +212 -0
- package/src/__tests__/routes/cli-auth.test.ts +337 -0
- package/src/__tests__/routes/interactions.test.ts +121 -0
- package/src/__tests__/secret-proxy.test.ts +85 -0
- package/src/__tests__/session-manager.test.ts +572 -0
- package/src/__tests__/setup.ts +133 -0
- package/src/__tests__/skill-and-mcp-registry.test.ts +203 -0
- package/src/__tests__/slack-routes.test.ts +161 -0
- package/src/__tests__/system-config-resolver.test.ts +75 -0
- package/src/__tests__/system-message-limiter.test.ts +89 -0
- package/src/__tests__/system-skills-service.test.ts +362 -0
- package/src/__tests__/transcription-service.test.ts +222 -0
- package/src/__tests__/utils/rate-limiter.test.ts +102 -0
- package/src/__tests__/worker-connection-manager.test.ts +497 -0
- package/src/__tests__/worker-job-router.test.ts +722 -0
- package/src/api/index.ts +1 -0
- package/src/api/platform.ts +292 -0
- package/src/api/response-renderer.ts +157 -0
- package/src/auth/agent-metadata-store.ts +168 -0
- package/src/auth/api-auth-middleware.ts +69 -0
- package/src/auth/api-key-provider-module.ts +213 -0
- package/src/auth/base-provider-module.ts +201 -0
- package/src/auth/chatgpt/chatgpt-oauth-module.ts +185 -0
- package/src/auth/chatgpt/device-code-client.ts +218 -0
- package/src/auth/chatgpt/index.ts +1 -0
- package/src/auth/claude/oauth-module.ts +280 -0
- package/src/auth/cli/token-service.ts +249 -0
- package/src/auth/external/client.ts +560 -0
- package/src/auth/external/device-code-client.ts +225 -0
- package/src/auth/mcp/config-service.ts +392 -0
- package/src/auth/mcp/proxy.ts +1088 -0
- package/src/auth/mcp/string-substitution.ts +17 -0
- package/src/auth/mcp/tool-cache.ts +90 -0
- package/src/auth/oauth/base-client.ts +267 -0
- package/src/auth/oauth/client.ts +153 -0
- package/src/auth/oauth/credentials.ts +7 -0
- package/src/auth/oauth/providers.ts +69 -0
- package/src/auth/oauth/state-store.ts +150 -0
- package/src/auth/oauth-templates.ts +179 -0
- package/src/auth/provider-catalog.ts +220 -0
- package/src/auth/provider-model-options.ts +41 -0
- package/src/auth/settings/agent-settings-store.ts +565 -0
- package/src/auth/settings/auth-profiles-manager.ts +216 -0
- package/src/auth/settings/index.ts +12 -0
- package/src/auth/settings/model-preference-store.ts +52 -0
- package/src/auth/settings/model-selection.ts +135 -0
- package/src/auth/settings/resolved-settings-view.ts +298 -0
- package/src/auth/settings/template-utils.ts +44 -0
- package/src/auth/settings/token-service.ts +88 -0
- package/src/auth/system-env-store.ts +98 -0
- package/src/auth/user-agents-store.ts +68 -0
- package/src/channels/binding-service.ts +214 -0
- package/src/channels/index.ts +4 -0
- package/src/cli/gateway.ts +1304 -0
- package/src/cli/index.ts +74 -0
- package/src/commands/built-in-commands.ts +80 -0
- package/src/commands/command-dispatcher.ts +94 -0
- package/src/commands/command-reply-adapters.ts +27 -0
- package/src/config/file-loader.ts +618 -0
- package/src/config/index.ts +588 -0
- package/src/config/network-allowlist.ts +71 -0
- package/src/connections/chat-instance-manager.ts +1284 -0
- package/src/connections/chat-response-bridge.ts +618 -0
- package/src/connections/index.ts +7 -0
- package/src/connections/interaction-bridge.ts +831 -0
- package/src/connections/message-handler-bridge.ts +415 -0
- package/src/connections/platform-auth-methods.ts +15 -0
- package/src/connections/types.ts +84 -0
- package/src/gateway/connection-manager.ts +291 -0
- package/src/gateway/index.ts +700 -0
- package/src/gateway/job-router.ts +201 -0
- package/src/gateway-main.ts +200 -0
- package/src/index.ts +41 -0
- package/src/infrastructure/queue/index.ts +12 -0
- package/src/infrastructure/queue/queue-producer.ts +148 -0
- package/src/infrastructure/queue/redis-queue.ts +361 -0
- package/src/infrastructure/queue/types.ts +133 -0
- package/src/infrastructure/redis/system-message-limiter.ts +94 -0
- package/src/interactions/config-request-store.ts +198 -0
- package/src/interactions.ts +363 -0
- package/src/lobu.ts +311 -0
- package/src/metrics/prometheus.ts +159 -0
- package/src/modules/module-system.ts +179 -0
- package/src/orchestration/base-deployment-manager.ts +900 -0
- package/src/orchestration/deployment-utils.ts +98 -0
- package/src/orchestration/impl/docker-deployment.ts +620 -0
- package/src/orchestration/impl/embedded-deployment.ts +268 -0
- package/src/orchestration/impl/index.ts +8 -0
- package/src/orchestration/impl/k8s/deployment.ts +1061 -0
- package/src/orchestration/impl/k8s/helpers.ts +610 -0
- package/src/orchestration/impl/k8s/index.ts +1 -0
- package/src/orchestration/index.ts +333 -0
- package/src/orchestration/message-consumer.ts +584 -0
- package/src/orchestration/scheduled-wakeup.ts +704 -0
- package/src/permissions/approval-policy.ts +36 -0
- package/src/permissions/grant-store.ts +219 -0
- package/src/platform/file-handler.ts +66 -0
- package/src/platform/link-buttons.ts +57 -0
- package/src/platform/renderer-utils.ts +44 -0
- package/src/platform/response-renderer.ts +84 -0
- package/src/platform/unified-thread-consumer.ts +187 -0
- package/src/platform.ts +318 -0
- package/src/proxy/http-proxy.ts +752 -0
- package/src/proxy/proxy-manager.ts +81 -0
- package/src/proxy/secret-proxy.ts +402 -0
- package/src/proxy/token-refresh-job.ts +143 -0
- package/src/routes/internal/audio.ts +141 -0
- package/src/routes/internal/device-auth.ts +566 -0
- package/src/routes/internal/files.ts +226 -0
- package/src/routes/internal/history.ts +69 -0
- package/src/routes/internal/images.ts +127 -0
- package/src/routes/internal/interactions.ts +84 -0
- package/src/routes/internal/middleware.ts +23 -0
- package/src/routes/internal/schedule.ts +226 -0
- package/src/routes/internal/types.ts +22 -0
- package/src/routes/openapi-auto.ts +239 -0
- package/src/routes/public/agent-access.ts +23 -0
- package/src/routes/public/agent-config.ts +675 -0
- package/src/routes/public/agent-history.ts +422 -0
- package/src/routes/public/agent-schedules.ts +296 -0
- package/src/routes/public/agent.ts +1086 -0
- package/src/routes/public/agents.ts +373 -0
- package/src/routes/public/channels.ts +191 -0
- package/src/routes/public/cli-auth.ts +883 -0
- package/src/routes/public/connections.ts +574 -0
- package/src/routes/public/landing.ts +16 -0
- package/src/routes/public/oauth.ts +147 -0
- package/src/routes/public/settings-auth.ts +104 -0
- package/src/routes/public/slack.ts +173 -0
- package/src/routes/shared/agent-ownership.ts +101 -0
- package/src/routes/shared/token-verifier.ts +34 -0
- package/src/services/core-services.ts +1053 -0
- package/src/services/image-generation-service.ts +257 -0
- package/src/services/instruction-service.ts +318 -0
- package/src/services/mcp-registry.ts +94 -0
- package/src/services/platform-helpers.ts +287 -0
- package/src/services/session-manager.ts +262 -0
- package/src/services/settings-resolver.ts +74 -0
- package/src/services/system-config-resolver.ts +90 -0
- package/src/services/system-skills-service.ts +229 -0
- package/src/services/transcription-service.ts +684 -0
- package/src/session.ts +110 -0
- package/src/spaces/index.ts +1 -0
- package/src/spaces/space-resolver.ts +17 -0
- package/src/stores/in-memory-agent-store.ts +403 -0
- package/src/stores/redis-agent-store.ts +279 -0
- package/src/utils/public-url.ts +44 -0
- package/src/utils/rate-limiter.ts +94 -0
- package/tsconfig.json +33 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { type ChildProcess, spawn } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { createLogger, ErrorCode, OrchestratorError } from "@lobu/core";
|
|
5
|
+
import type { ModelProviderModule } from "../../modules/module-system";
|
|
6
|
+
import {
|
|
7
|
+
BaseDeploymentManager,
|
|
8
|
+
type DeploymentInfo,
|
|
9
|
+
type MessagePayload,
|
|
10
|
+
type ModuleEnvVarsBuilder,
|
|
11
|
+
type OrchestratorConfig,
|
|
12
|
+
} from "../base-deployment-manager";
|
|
13
|
+
import {
|
|
14
|
+
buildDeploymentInfoSummary,
|
|
15
|
+
getVeryOldThresholdDays,
|
|
16
|
+
} from "../deployment-utils";
|
|
17
|
+
|
|
18
|
+
const logger = createLogger("orchestrator");
|
|
19
|
+
|
|
20
|
+
/** Timeout (ms) to wait for graceful shutdown before SIGKILL. */
|
|
21
|
+
const KILL_TIMEOUT_MS = 5_000;
|
|
22
|
+
const WORKER_BIN_DIR_CANDIDATES = [
|
|
23
|
+
path.resolve("node_modules/.bin"),
|
|
24
|
+
path.resolve("packages/worker/node_modules/.bin"),
|
|
25
|
+
"/app/node_modules/.bin",
|
|
26
|
+
"/app/packages/worker/node_modules/.bin",
|
|
27
|
+
] as const;
|
|
28
|
+
|
|
29
|
+
interface EmbeddedWorkerEntry {
|
|
30
|
+
process: ChildProcess;
|
|
31
|
+
env: Record<string, string>;
|
|
32
|
+
lastActivity: Date;
|
|
33
|
+
workspaceDir: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function buildEmbeddedWorkerPath(existingPath?: string): string | undefined {
|
|
37
|
+
const segments = (existingPath || "").split(":").filter(Boolean);
|
|
38
|
+
|
|
39
|
+
for (const candidate of [...WORKER_BIN_DIR_CANDIDATES].reverse()) {
|
|
40
|
+
if (!fs.existsSync(candidate)) continue;
|
|
41
|
+
if (segments.includes(candidate)) continue;
|
|
42
|
+
segments.unshift(candidate);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return segments.length > 0 ? segments.join(":") : existingPath;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getBunExecutable(): string {
|
|
49
|
+
return path.basename(process.execPath).startsWith("bun")
|
|
50
|
+
? process.execPath
|
|
51
|
+
: "bun";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export class EmbeddedDeploymentManager extends BaseDeploymentManager {
|
|
55
|
+
private workers: Map<string, EmbeddedWorkerEntry> = new Map();
|
|
56
|
+
|
|
57
|
+
constructor(
|
|
58
|
+
config: OrchestratorConfig,
|
|
59
|
+
moduleEnvVarsBuilder?: ModuleEnvVarsBuilder,
|
|
60
|
+
providerModules: ModelProviderModule[] = []
|
|
61
|
+
) {
|
|
62
|
+
super(config, moduleEnvVarsBuilder, providerModules);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
protected getDispatcherHost(): string {
|
|
66
|
+
return "localhost";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async validateWorkerImage(): Promise<void> {
|
|
70
|
+
const entryPoint = path.resolve("packages/worker/src/index.ts");
|
|
71
|
+
if (!fs.existsSync(entryPoint)) {
|
|
72
|
+
throw new OrchestratorError(
|
|
73
|
+
ErrorCode.DEPLOYMENT_CREATE_FAILED,
|
|
74
|
+
`Worker entry point not found: ${entryPoint}. Run from the project root.`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
logger.debug(`Worker entry point verified: ${entryPoint}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async createDeployment(
|
|
81
|
+
...args: Parameters<BaseDeploymentManager["createDeployment"]>
|
|
82
|
+
): Promise<void> {
|
|
83
|
+
const [deploymentName, username, userId, messageDataRaw] = args;
|
|
84
|
+
const messageData = messageDataRaw as MessagePayload | undefined;
|
|
85
|
+
|
|
86
|
+
const agentId = messageData?.agentId;
|
|
87
|
+
if (!agentId) {
|
|
88
|
+
throw new OrchestratorError(
|
|
89
|
+
ErrorCode.DEPLOYMENT_CREATE_FAILED,
|
|
90
|
+
"Missing agentId in message payload"
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
const workspaceDir = path.resolve(`workspaces/${agentId}`);
|
|
94
|
+
fs.mkdirSync(workspaceDir, { recursive: true });
|
|
95
|
+
|
|
96
|
+
const commonEnvVars = await this.generateEnvironmentVariables(
|
|
97
|
+
username,
|
|
98
|
+
userId,
|
|
99
|
+
deploymentName,
|
|
100
|
+
messageData,
|
|
101
|
+
true
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
commonEnvVars.WORKSPACE_DIR = workspaceDir;
|
|
105
|
+
commonEnvVars.DEPLOYMENT_MODE = "embedded";
|
|
106
|
+
const embeddedPath = buildEmbeddedWorkerPath(
|
|
107
|
+
commonEnvVars.PATH || process.env.PATH
|
|
108
|
+
);
|
|
109
|
+
if (embeddedPath) {
|
|
110
|
+
commonEnvVars.PATH = embeddedPath;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Serialize allowed domains for worker-side just-bash bootstrap
|
|
114
|
+
const allowedDomains = messageData?.networkConfig?.allowedDomains ?? [];
|
|
115
|
+
if (allowedDomains.length > 0) {
|
|
116
|
+
commonEnvVars.JUST_BASH_ALLOWED_DOMAINS = JSON.stringify(allowedDomains);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Determine spawn command based on nix packages
|
|
120
|
+
const nixPackages = messageData?.nixConfig?.packages ?? [];
|
|
121
|
+
const workerEntryPoint = path.resolve("packages/worker/src/index.ts");
|
|
122
|
+
const bunExecutable = getBunExecutable();
|
|
123
|
+
|
|
124
|
+
let command: string;
|
|
125
|
+
let spawnArgs: string[];
|
|
126
|
+
|
|
127
|
+
if (nixPackages.length > 0) {
|
|
128
|
+
// Wrap in nix-shell so nix binaries are on PATH
|
|
129
|
+
command = "nix-shell";
|
|
130
|
+
spawnArgs = [
|
|
131
|
+
"-p",
|
|
132
|
+
...nixPackages,
|
|
133
|
+
"--run",
|
|
134
|
+
`${bunExecutable} run ${workerEntryPoint}`,
|
|
135
|
+
];
|
|
136
|
+
logger.info(
|
|
137
|
+
`Spawning embedded worker ${deploymentName} with nix packages: ${nixPackages.join(", ")}`
|
|
138
|
+
);
|
|
139
|
+
} else {
|
|
140
|
+
command = bunExecutable;
|
|
141
|
+
spawnArgs = ["run", workerEntryPoint];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const child = spawn(command, spawnArgs, {
|
|
145
|
+
env: { ...process.env, ...commonEnvVars },
|
|
146
|
+
cwd: workspaceDir,
|
|
147
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Pipe child stdout/stderr to gateway logger
|
|
151
|
+
child.stdout?.on("data", (data: Buffer) => {
|
|
152
|
+
for (const line of data.toString().trimEnd().split("\n")) {
|
|
153
|
+
logger.info({ worker: deploymentName }, line);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
child.stderr?.on("data", (data: Buffer) => {
|
|
157
|
+
for (const line of data.toString().trimEnd().split("\n")) {
|
|
158
|
+
logger.warn({ worker: deploymentName }, line);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Handle child exit (use once to prevent duplicate handler invocations)
|
|
163
|
+
child.once("exit", (code, signal) => {
|
|
164
|
+
const entry = this.workers.get(deploymentName);
|
|
165
|
+
if (entry) {
|
|
166
|
+
this.workers.delete(deploymentName);
|
|
167
|
+
if (signal) {
|
|
168
|
+
logger.info(
|
|
169
|
+
`Embedded worker ${deploymentName} exited with signal ${signal}`
|
|
170
|
+
);
|
|
171
|
+
} else if (code !== 0) {
|
|
172
|
+
logger.error(
|
|
173
|
+
`Embedded worker ${deploymentName} exited with code ${code}`
|
|
174
|
+
);
|
|
175
|
+
} else {
|
|
176
|
+
logger.info(`Embedded worker ${deploymentName} exited cleanly`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
this.workers.set(deploymentName, {
|
|
182
|
+
process: child,
|
|
183
|
+
env: commonEnvVars,
|
|
184
|
+
lastActivity: new Date(),
|
|
185
|
+
workspaceDir,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
logger.info(
|
|
189
|
+
`Started embedded worker subprocess for ${deploymentName} (pid=${child.pid})`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async scaleDeployment(
|
|
194
|
+
deploymentName: string,
|
|
195
|
+
replicas: number
|
|
196
|
+
): Promise<void> {
|
|
197
|
+
const entry = this.workers.get(deploymentName);
|
|
198
|
+
|
|
199
|
+
if (replicas === 0 && entry) {
|
|
200
|
+
this.killWorker(entry, deploymentName);
|
|
201
|
+
logger.info(`Stopped embedded worker ${deploymentName}`);
|
|
202
|
+
} else if (replicas === 1 && !entry) {
|
|
203
|
+
logger.warn(
|
|
204
|
+
`Cannot scale up ${deploymentName} — use createDeployment to re-spawn`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async deleteDeployment(deploymentName: string): Promise<void> {
|
|
210
|
+
const entry = this.workers.get(deploymentName);
|
|
211
|
+
if (entry) {
|
|
212
|
+
this.killWorker(entry, deploymentName);
|
|
213
|
+
logger.info(`Stopped embedded worker: ${deploymentName}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async listDeployments(): Promise<DeploymentInfo[]> {
|
|
218
|
+
const now = Date.now();
|
|
219
|
+
const idleThresholdMinutes = this.config.worker.idleCleanupMinutes;
|
|
220
|
+
const veryOldDays = getVeryOldThresholdDays(this.config);
|
|
221
|
+
|
|
222
|
+
const results: DeploymentInfo[] = [];
|
|
223
|
+
for (const [deploymentName, entry] of this.workers) {
|
|
224
|
+
results.push(
|
|
225
|
+
buildDeploymentInfoSummary({
|
|
226
|
+
deploymentName,
|
|
227
|
+
lastActivity: entry.lastActivity,
|
|
228
|
+
now,
|
|
229
|
+
idleThresholdMinutes,
|
|
230
|
+
veryOldDays,
|
|
231
|
+
replicas: 1,
|
|
232
|
+
})
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
return results;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async updateDeploymentActivity(deploymentName: string): Promise<void> {
|
|
239
|
+
const entry = this.workers.get(deploymentName);
|
|
240
|
+
if (entry) {
|
|
241
|
+
entry.lastActivity = new Date();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** Send SIGTERM, then SIGKILL after timeout. */
|
|
246
|
+
private killWorker(entry: EmbeddedWorkerEntry, deploymentName: string): void {
|
|
247
|
+
const child = entry.process;
|
|
248
|
+
|
|
249
|
+
// Delete from map first to prevent race with exit handler
|
|
250
|
+
this.workers.delete(deploymentName);
|
|
251
|
+
|
|
252
|
+
// Check if already exited after map deletion
|
|
253
|
+
if (child.exitCode !== null || child.killed) return;
|
|
254
|
+
|
|
255
|
+
child.kill("SIGTERM");
|
|
256
|
+
|
|
257
|
+
const killTimer = setTimeout(() => {
|
|
258
|
+
if (child.exitCode === null && !child.killed) {
|
|
259
|
+
logger.warn(
|
|
260
|
+
`Embedded worker ${deploymentName} did not exit after SIGTERM, sending SIGKILL`
|
|
261
|
+
);
|
|
262
|
+
child.kill("SIGKILL");
|
|
263
|
+
}
|
|
264
|
+
}, KILL_TIMEOUT_MS);
|
|
265
|
+
|
|
266
|
+
child.once("exit", () => clearTimeout(killTimer));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment manager implementations
|
|
3
|
+
* Add new deployment targets here (e.g., CloudflareDeploymentManager, LambdaDeploymentManager)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { DockerDeploymentManager } from "./docker-deployment";
|
|
7
|
+
export { EmbeddedDeploymentManager } from "./embedded-deployment";
|
|
8
|
+
export { K8sDeploymentManager } from "./k8s";
|