@dobby.ai/dobby 0.1.1 → 0.1.2
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 +20 -7
- package/dist/src/agent/event-forwarder.js +185 -16
- package/dist/src/cli/commands/cron.js +39 -35
- package/dist/src/cli/program.js +0 -6
- package/dist/src/core/types.js +2 -0
- package/dist/src/cron/config.js +2 -2
- package/dist/src/cron/service.js +87 -23
- package/dist/src/cron/store.js +1 -1
- package/package.json +9 -3
- package/.env.example +0 -8
- package/AGENTS.md +0 -267
- package/ROADMAP.md +0 -34
- package/config/cron.example.json +0 -9
- package/config/gateway.example.json +0 -132
- package/dist/plugins/connector-discord/src/mapper.js +0 -75
- package/dist/src/cli/tests/config-command.test.js +0 -42
- package/dist/src/cli/tests/config-io.test.js +0 -64
- package/dist/src/cli/tests/config-mutators.test.js +0 -47
- package/dist/src/cli/tests/discord-mapper.test.js +0 -90
- package/dist/src/cli/tests/doctor.test.js +0 -252
- package/dist/src/cli/tests/init-catalog.test.js +0 -134
- package/dist/src/cli/tests/program-options.test.js +0 -78
- package/dist/src/cli/tests/routing-config.test.js +0 -254
- package/dist/src/core/tests/control-command.test.js +0 -17
- package/dist/src/core/tests/runtime-registry.test.js +0 -116
- package/dist/src/core/tests/typing-controller.test.js +0 -103
- package/docs/BOXLITE_SANDBOX_FEASIBILITY.md +0 -175
- package/docs/CRON_SCHEDULER_DESIGN.md +0 -374
- package/docs/DOCKER_SANDBOX_vs_BOXLITE.md +0 -77
- package/docs/EXTENSION_SYSTEM_ARCHITECTURE.md +0 -119
- package/docs/MVP.md +0 -135
- package/docs/RUNBOOK.md +0 -243
- package/docs/TEAMWORK_HANDOFF_DESIGN.md +0 -440
- package/plugins/connector-discord/dobby.manifest.json +0 -18
- package/plugins/connector-discord/index.js +0 -1
- package/plugins/connector-discord/package-lock.json +0 -360
- package/plugins/connector-discord/package.json +0 -38
- package/plugins/connector-discord/src/connector.ts +0 -345
- package/plugins/connector-discord/src/contribution.ts +0 -21
- package/plugins/connector-discord/src/mapper.ts +0 -101
- package/plugins/connector-discord/tsconfig.json +0 -19
- package/plugins/connector-feishu/dobby.manifest.json +0 -18
- package/plugins/connector-feishu/index.js +0 -1
- package/plugins/connector-feishu/package-lock.json +0 -618
- package/plugins/connector-feishu/package.json +0 -38
- package/plugins/connector-feishu/src/connector.ts +0 -343
- package/plugins/connector-feishu/src/contribution.ts +0 -26
- package/plugins/connector-feishu/src/mapper.ts +0 -401
- package/plugins/connector-feishu/tsconfig.json +0 -19
- package/plugins/plugin-sdk/index.d.ts +0 -261
- package/plugins/plugin-sdk/index.js +0 -1
- package/plugins/plugin-sdk/package-lock.json +0 -12
- package/plugins/plugin-sdk/package.json +0 -22
- package/plugins/provider-claude/dobby.manifest.json +0 -17
- package/plugins/provider-claude/index.js +0 -1
- package/plugins/provider-claude/package-lock.json +0 -3398
- package/plugins/provider-claude/package.json +0 -39
- package/plugins/provider-claude/src/contribution.ts +0 -1018
- package/plugins/provider-claude/tsconfig.json +0 -19
- package/plugins/provider-claude-cli/dobby.manifest.json +0 -17
- package/plugins/provider-claude-cli/index.js +0 -1
- package/plugins/provider-claude-cli/package-lock.json +0 -2898
- package/plugins/provider-claude-cli/package.json +0 -38
- package/plugins/provider-claude-cli/src/contribution.ts +0 -1673
- package/plugins/provider-claude-cli/tsconfig.json +0 -19
- package/plugins/provider-pi/dobby.manifest.json +0 -17
- package/plugins/provider-pi/index.js +0 -1
- package/plugins/provider-pi/package-lock.json +0 -3877
- package/plugins/provider-pi/package.json +0 -40
- package/plugins/provider-pi/src/contribution.ts +0 -606
- package/plugins/provider-pi/tsconfig.json +0 -19
- package/plugins/sandbox-core/boxlite.js +0 -1
- package/plugins/sandbox-core/dobby.manifest.json +0 -17
- package/plugins/sandbox-core/docker.js +0 -1
- package/plugins/sandbox-core/package-lock.json +0 -136
- package/plugins/sandbox-core/package.json +0 -39
- package/plugins/sandbox-core/src/boxlite-context.ts +0 -2
- package/plugins/sandbox-core/src/boxlite-contribution.ts +0 -53
- package/plugins/sandbox-core/src/boxlite-executor.ts +0 -911
- package/plugins/sandbox-core/src/docker-contribution.ts +0 -43
- package/plugins/sandbox-core/src/docker-executor.ts +0 -217
- package/plugins/sandbox-core/tsconfig.json +0 -19
- package/scripts/local-extensions.mjs +0 -168
- package/src/agent/event-forwarder.ts +0 -414
- package/src/cli/commands/config.ts +0 -328
- package/src/cli/commands/configure.ts +0 -92
- package/src/cli/commands/cron.ts +0 -410
- package/src/cli/commands/doctor.ts +0 -331
- package/src/cli/commands/extension.ts +0 -207
- package/src/cli/commands/init.ts +0 -211
- package/src/cli/commands/start.ts +0 -223
- package/src/cli/commands/topology.ts +0 -415
- package/src/cli/index.ts +0 -9
- package/src/cli/program.ts +0 -314
- package/src/cli/shared/config-io.ts +0 -245
- package/src/cli/shared/config-mutators.ts +0 -470
- package/src/cli/shared/config-schema.ts +0 -228
- package/src/cli/shared/config-types.ts +0 -129
- package/src/cli/shared/configure-sections.ts +0 -595
- package/src/cli/shared/discord-config.ts +0 -14
- package/src/cli/shared/init-catalog.ts +0 -249
- package/src/cli/shared/local-extension-specs.ts +0 -108
- package/src/cli/shared/runtime.ts +0 -33
- package/src/cli/shared/schema-prompts.ts +0 -443
- package/src/cli/tests/config-command.test.ts +0 -56
- package/src/cli/tests/config-io.test.ts +0 -92
- package/src/cli/tests/config-mutators.test.ts +0 -59
- package/src/cli/tests/discord-mapper.test.ts +0 -128
- package/src/cli/tests/doctor.test.ts +0 -269
- package/src/cli/tests/init-catalog.test.ts +0 -144
- package/src/cli/tests/program-options.test.ts +0 -95
- package/src/cli/tests/routing-config.test.ts +0 -281
- package/src/core/control-command.ts +0 -12
- package/src/core/dedup-store.ts +0 -103
- package/src/core/gateway.ts +0 -609
- package/src/core/routing.ts +0 -404
- package/src/core/runtime-registry.ts +0 -141
- package/src/core/tests/control-command.test.ts +0 -20
- package/src/core/tests/runtime-registry.test.ts +0 -140
- package/src/core/tests/typing-controller.test.ts +0 -129
- package/src/core/types.ts +0 -324
- package/src/core/typing-controller.ts +0 -119
- package/src/cron/config.ts +0 -154
- package/src/cron/schedule.ts +0 -61
- package/src/cron/service.ts +0 -249
- package/src/cron/store.ts +0 -155
- package/src/cron/types.ts +0 -60
- package/src/extension/loader.ts +0 -145
- package/src/extension/manager.ts +0 -355
- package/src/extension/manifest.ts +0 -26
- package/src/extension/registry.ts +0 -229
- package/src/main.ts +0 -8
- package/src/sandbox/executor.ts +0 -44
- package/src/sandbox/host-executor.ts +0 -118
- package/src/shared/dobby-repo.ts +0 -48
- package/tsconfig.json +0 -18
package/src/cli/commands/init.ts
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
cancel,
|
|
3
|
-
intro,
|
|
4
|
-
isCancel,
|
|
5
|
-
multiselect,
|
|
6
|
-
outro,
|
|
7
|
-
select,
|
|
8
|
-
spinner,
|
|
9
|
-
} from "@clack/prompts";
|
|
10
|
-
import { ExtensionStoreManager } from "../../extension/manager.js";
|
|
11
|
-
import {
|
|
12
|
-
ensureGatewayConfigShape,
|
|
13
|
-
upsertAllowListPackage,
|
|
14
|
-
upsertBinding,
|
|
15
|
-
upsertConnectorInstance,
|
|
16
|
-
upsertProviderInstance,
|
|
17
|
-
upsertRoute,
|
|
18
|
-
} from "../shared/config-mutators.js";
|
|
19
|
-
import { applyAndValidateContributionSchemas } from "../shared/config-schema.js";
|
|
20
|
-
import {
|
|
21
|
-
readRawConfig,
|
|
22
|
-
resolveConfigPath,
|
|
23
|
-
resolveDataRootDir,
|
|
24
|
-
writeConfigWithValidation,
|
|
25
|
-
} from "../shared/config-io.js";
|
|
26
|
-
import {
|
|
27
|
-
createInitSelectionConfig,
|
|
28
|
-
isInitConnectorChoiceId,
|
|
29
|
-
isInitProviderChoiceId,
|
|
30
|
-
listInitConnectorChoices,
|
|
31
|
-
listInitProviderChoices,
|
|
32
|
-
type InitConnectorChoiceId,
|
|
33
|
-
type InitProviderChoiceId,
|
|
34
|
-
} from "../shared/init-catalog.js";
|
|
35
|
-
import { resolveExtensionInstallSpecs } from "../shared/local-extension-specs.js";
|
|
36
|
-
import { createLogger } from "../shared/runtime.js";
|
|
37
|
-
|
|
38
|
-
interface InitInput {
|
|
39
|
-
providerChoiceIds: InitProviderChoiceId[];
|
|
40
|
-
routeProviderChoiceId: InitProviderChoiceId;
|
|
41
|
-
connectorChoiceIds: InitConnectorChoiceId[];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Collects high-level starter choices only; config values are written as templates.
|
|
46
|
-
*/
|
|
47
|
-
async function collectInitInput(): Promise<InitInput> {
|
|
48
|
-
intro("dobby init");
|
|
49
|
-
|
|
50
|
-
const providerChoices = listInitProviderChoices();
|
|
51
|
-
const providerChoiceResult = await multiselect({
|
|
52
|
-
message: "Choose provider(s) (space to select multiple)",
|
|
53
|
-
options: providerChoices.map((item) => ({
|
|
54
|
-
value: item.id,
|
|
55
|
-
label: item.label,
|
|
56
|
-
})),
|
|
57
|
-
initialValues: ["provider.pi"],
|
|
58
|
-
required: true,
|
|
59
|
-
});
|
|
60
|
-
if (isCancel(providerChoiceResult)) {
|
|
61
|
-
cancel("Initialization cancelled.");
|
|
62
|
-
throw new Error("Initialization cancelled.");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const providerChoiceIds = (providerChoiceResult as unknown[]).map((value) => String(value));
|
|
66
|
-
if (providerChoiceIds.length === 0) {
|
|
67
|
-
throw new Error("At least one provider must be selected");
|
|
68
|
-
}
|
|
69
|
-
if (!providerChoiceIds.every((providerChoiceId) => isInitProviderChoiceId(providerChoiceId))) {
|
|
70
|
-
const invalidChoice = providerChoiceIds.find((providerChoiceId) => !isInitProviderChoiceId(providerChoiceId));
|
|
71
|
-
throw new Error(`Unsupported provider choice '${invalidChoice}'`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const providerChoicesById = new Map(providerChoices.map((choice) => [choice.id, choice]));
|
|
75
|
-
let routeProviderChoiceId = providerChoiceIds[0] as InitProviderChoiceId;
|
|
76
|
-
if (providerChoiceIds.length > 1) {
|
|
77
|
-
const routeProviderChoiceResult = await select({
|
|
78
|
-
message: "Choose default provider",
|
|
79
|
-
options: providerChoiceIds.map((providerChoiceId) => ({
|
|
80
|
-
value: providerChoiceId,
|
|
81
|
-
label: providerChoicesById.get(providerChoiceId as InitProviderChoiceId)?.label ?? providerChoiceId,
|
|
82
|
-
})),
|
|
83
|
-
initialValue: providerChoiceIds[0],
|
|
84
|
-
});
|
|
85
|
-
if (isCancel(routeProviderChoiceResult)) {
|
|
86
|
-
cancel("Initialization cancelled.");
|
|
87
|
-
throw new Error("Initialization cancelled.");
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const routeProviderCandidate = String(routeProviderChoiceResult);
|
|
91
|
-
if (!isInitProviderChoiceId(routeProviderCandidate) || !providerChoiceIds.includes(routeProviderCandidate)) {
|
|
92
|
-
throw new Error(`Unsupported route provider choice '${routeProviderCandidate}'`);
|
|
93
|
-
}
|
|
94
|
-
routeProviderChoiceId = routeProviderCandidate;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const connectorChoices = listInitConnectorChoices();
|
|
98
|
-
const connectorChoiceResult = await multiselect({
|
|
99
|
-
message: "Choose connector(s) (space to select multiple)",
|
|
100
|
-
options: connectorChoices.map((item) => ({
|
|
101
|
-
value: item.id,
|
|
102
|
-
label: item.label,
|
|
103
|
-
})),
|
|
104
|
-
initialValues: ["connector.discord"],
|
|
105
|
-
required: true,
|
|
106
|
-
});
|
|
107
|
-
if (isCancel(connectorChoiceResult)) {
|
|
108
|
-
cancel("Initialization cancelled.");
|
|
109
|
-
throw new Error("Initialization cancelled.");
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const connectorChoiceIds = (connectorChoiceResult as unknown[]).map((value) => String(value));
|
|
113
|
-
if (connectorChoiceIds.length === 0) {
|
|
114
|
-
throw new Error("At least one connector must be selected");
|
|
115
|
-
}
|
|
116
|
-
if (!connectorChoiceIds.every((connectorChoiceId) => isInitConnectorChoiceId(connectorChoiceId))) {
|
|
117
|
-
const invalidChoice = connectorChoiceIds.find((connectorChoiceId) => !isInitConnectorChoiceId(connectorChoiceId));
|
|
118
|
-
throw new Error(`Unsupported connector choice '${invalidChoice}'`);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
providerChoiceIds: providerChoiceIds as InitProviderChoiceId[],
|
|
123
|
-
routeProviderChoiceId,
|
|
124
|
-
connectorChoiceIds: connectorChoiceIds as InitConnectorChoiceId[],
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Executes first-time initialization by installing starter extensions and writing template config.
|
|
130
|
-
*/
|
|
131
|
-
export async function runInitCommand(): Promise<void> {
|
|
132
|
-
const configPath = resolveConfigPath();
|
|
133
|
-
const existingConfig = await readRawConfig(configPath);
|
|
134
|
-
if (existingConfig) {
|
|
135
|
-
throw new Error(
|
|
136
|
-
`Config '${configPath}' already exists. Edit the file directly to update existing values.`,
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const input = await collectInitInput();
|
|
141
|
-
const selected = createInitSelectionConfig(input.providerChoiceIds, input.connectorChoiceIds, {
|
|
142
|
-
routeProviderChoiceId: input.routeProviderChoiceId,
|
|
143
|
-
defaultProjectRoot: process.cwd(),
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
const next = ensureGatewayConfigShape({});
|
|
147
|
-
const rootDir = resolveDataRootDir(configPath, next);
|
|
148
|
-
const manager = new ExtensionStoreManager(createLogger(), `${rootDir}/extensions`);
|
|
149
|
-
const extensionInstallSpecs = await resolveExtensionInstallSpecs(selected.extensionPackages);
|
|
150
|
-
|
|
151
|
-
const installSpinner = spinner();
|
|
152
|
-
installSpinner.start(`Installing required extensions (${selected.extensionPackages.length} packages)`);
|
|
153
|
-
try {
|
|
154
|
-
const installedPackages = await manager.installMany(extensionInstallSpecs);
|
|
155
|
-
for (const installed of installedPackages) {
|
|
156
|
-
upsertAllowListPackage(next, installed.packageName, true);
|
|
157
|
-
}
|
|
158
|
-
installSpinner.stop("Extensions installed");
|
|
159
|
-
} catch (error) {
|
|
160
|
-
installSpinner.stop("Extension installation failed");
|
|
161
|
-
throw error;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
for (const provider of selected.providerInstances) {
|
|
165
|
-
upsertProviderInstance(next, provider.instanceId, provider.contributionId, provider.config);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
for (const connector of selected.connectorInstances) {
|
|
169
|
-
upsertConnectorInstance(next, connector.instanceId, connector.contributionId, connector.config);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
next.providers = {
|
|
173
|
-
...next.providers,
|
|
174
|
-
default: selected.providerInstanceId,
|
|
175
|
-
items: next.providers.items,
|
|
176
|
-
};
|
|
177
|
-
next.routes = {
|
|
178
|
-
...next.routes,
|
|
179
|
-
default: {
|
|
180
|
-
...next.routes.default,
|
|
181
|
-
...selected.routeDefaults,
|
|
182
|
-
},
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
upsertRoute(next, selected.routeId, selected.routeProfile);
|
|
186
|
-
if (selected.defaultBinding) {
|
|
187
|
-
next.bindings = {
|
|
188
|
-
...next.bindings,
|
|
189
|
-
default: selected.defaultBinding,
|
|
190
|
-
items: next.bindings.items,
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
for (const binding of selected.bindings) {
|
|
194
|
-
upsertBinding(next, binding.id, binding.config);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const validatedConfig = await applyAndValidateContributionSchemas(configPath, next);
|
|
198
|
-
|
|
199
|
-
await writeConfigWithValidation(configPath, validatedConfig, {
|
|
200
|
-
validate: true,
|
|
201
|
-
createBackup: false,
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
outro("Initialization completed.");
|
|
205
|
-
|
|
206
|
-
console.log(`Config written: ${configPath}`);
|
|
207
|
-
console.log("Next steps:");
|
|
208
|
-
console.log("1. Edit gateway.json and replace all REPLACE_WITH_* / YOUR_* placeholders");
|
|
209
|
-
console.log("2. Run 'dobby doctor' to validate the edited config");
|
|
210
|
-
console.log("3. Run 'dobby start' when the placeholders are replaced");
|
|
211
|
-
}
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { dirname, join } from "node:path";
|
|
2
|
-
import { loadCronConfig } from "../../cron/config.js";
|
|
3
|
-
import { CronService } from "../../cron/service.js";
|
|
4
|
-
import { CronStore } from "../../cron/store.js";
|
|
5
|
-
import { DedupStore } from "../../core/dedup-store.js";
|
|
6
|
-
import { Gateway } from "../../core/gateway.js";
|
|
7
|
-
import { BindingResolver, loadGatewayConfig, RouteResolver } from "../../core/routing.js";
|
|
8
|
-
import { RuntimeRegistry } from "../../core/runtime-registry.js";
|
|
9
|
-
import { BUILTIN_HOST_SANDBOX_ID } from "../../core/types.js";
|
|
10
|
-
import type {
|
|
11
|
-
GatewayLogger,
|
|
12
|
-
ProviderInstance,
|
|
13
|
-
ProvidersConfig,
|
|
14
|
-
SandboxInstance,
|
|
15
|
-
SandboxesConfig,
|
|
16
|
-
} from "../../core/types.js";
|
|
17
|
-
import { ExtensionLoader } from "../../extension/loader.js";
|
|
18
|
-
import { ExtensionRegistry } from "../../extension/registry.js";
|
|
19
|
-
import type { Executor } from "../../sandbox/executor.js";
|
|
20
|
-
import { HostExecutor } from "../../sandbox/host-executor.js";
|
|
21
|
-
import { resolveConfigPath } from "../shared/config-io.js";
|
|
22
|
-
import { createLogger, ensureDataDirs, extensionStoreDir } from "../shared/runtime.js";
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Closes provider instances best-effort so shutdown does not stop on one failed provider.
|
|
26
|
-
*/
|
|
27
|
-
async function closeProviderInstances(providers: Map<string, ProviderInstance>, logger: GatewayLogger): Promise<void> {
|
|
28
|
-
for (const [providerId, provider] of providers.entries()) {
|
|
29
|
-
if (!provider.close) {
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
await provider.close();
|
|
35
|
-
} catch (error) {
|
|
36
|
-
logger.warn({ err: error, providerId }, "Failed to close provider instance");
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Closes sandbox executors and optional sandbox lifecycle hooks during shutdown.
|
|
43
|
-
*/
|
|
44
|
-
async function closeSandboxInstances(sandboxes: Map<string, SandboxInstance>, logger: GatewayLogger): Promise<void> {
|
|
45
|
-
for (const [sandboxId, sandbox] of sandboxes.entries()) {
|
|
46
|
-
try {
|
|
47
|
-
await sandbox.executor.close();
|
|
48
|
-
} catch (error) {
|
|
49
|
-
logger.warn({ err: error, sandboxId }, "Failed to close sandbox executor");
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (!sandbox.close) {
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
try {
|
|
57
|
-
await sandbox.close();
|
|
58
|
-
} catch (error) {
|
|
59
|
-
logger.warn({ err: error, sandboxId }, "Failed to close sandbox instance");
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Narrows provider instances to only those referenced by default provider or any route override.
|
|
66
|
-
*/
|
|
67
|
-
function selectProviderInstances(config: Awaited<ReturnType<typeof loadGatewayConfig>>): ProvidersConfig {
|
|
68
|
-
const requiredProviderIds = new Set<string>([config.providers.default]);
|
|
69
|
-
for (const route of Object.values(config.routes.items)) {
|
|
70
|
-
requiredProviderIds.add(route.provider);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const instances = Object.fromEntries(
|
|
74
|
-
Object.entries(config.providers.items).filter(([instanceId]) => requiredProviderIds.has(instanceId)),
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
default: config.providers.default,
|
|
79
|
-
items: instances,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Narrows sandbox instances to only those referenced by default/route sandbox settings.
|
|
85
|
-
*/
|
|
86
|
-
function selectSandboxInstances(config: Awaited<ReturnType<typeof loadGatewayConfig>>): SandboxesConfig {
|
|
87
|
-
const defaultSandboxId = config.sandboxes.default ?? BUILTIN_HOST_SANDBOX_ID;
|
|
88
|
-
const requiredSandboxIds = new Set<string>();
|
|
89
|
-
|
|
90
|
-
if (defaultSandboxId !== BUILTIN_HOST_SANDBOX_ID) {
|
|
91
|
-
requiredSandboxIds.add(defaultSandboxId);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
for (const route of Object.values(config.routes.items)) {
|
|
95
|
-
if (route.sandbox !== BUILTIN_HOST_SANDBOX_ID) {
|
|
96
|
-
requiredSandboxIds.add(route.sandbox);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const instances = Object.fromEntries(
|
|
101
|
-
Object.entries(config.sandboxes.items).filter(([instanceId]) => requiredSandboxIds.has(instanceId)),
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
...(config.sandboxes.default ? { default: config.sandboxes.default } : {}),
|
|
106
|
-
items: instances,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Starts the gateway runtime from config and wires graceful shutdown handlers.
|
|
112
|
-
*/
|
|
113
|
-
export async function runStartCommand(): Promise<void> {
|
|
114
|
-
const configPath = resolveConfigPath();
|
|
115
|
-
const config = await loadGatewayConfig(configPath);
|
|
116
|
-
|
|
117
|
-
await ensureDataDirs(config.data.rootDir);
|
|
118
|
-
|
|
119
|
-
const logger = createLogger();
|
|
120
|
-
const loader = new ExtensionLoader(logger, {
|
|
121
|
-
extensionsDir: extensionStoreDir(config),
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
const loadedPackages = await loader.loadAllowList(config.extensions.allowList);
|
|
125
|
-
const registry = new ExtensionRegistry();
|
|
126
|
-
registry.registerPackages(loadedPackages);
|
|
127
|
-
|
|
128
|
-
logger.info(
|
|
129
|
-
{
|
|
130
|
-
extensionStoreDir: extensionStoreDir(config),
|
|
131
|
-
packages: loadedPackages.map((item) => ({
|
|
132
|
-
package: item.packageName,
|
|
133
|
-
manifestName: item.manifest.name,
|
|
134
|
-
version: item.manifest.version,
|
|
135
|
-
contributions: item.manifest.contributions.map((contribution) => `${contribution.kind}:${contribution.id}`),
|
|
136
|
-
})),
|
|
137
|
-
},
|
|
138
|
-
"Extension packages loaded",
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
const extensionHostContext = {
|
|
142
|
-
logger,
|
|
143
|
-
configBaseDir: dirname(configPath),
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
const activeProvidersConfig = selectProviderInstances(config);
|
|
147
|
-
const activeSandboxesConfig = selectSandboxInstances(config);
|
|
148
|
-
|
|
149
|
-
const providers = await registry.createProviderInstances(activeProvidersConfig, extensionHostContext, config.data);
|
|
150
|
-
const connectors = await registry.createConnectorInstances(config.connectors, extensionHostContext, config.data.attachmentsDir);
|
|
151
|
-
const sandboxes = await registry.createSandboxInstances(activeSandboxesConfig, extensionHostContext);
|
|
152
|
-
|
|
153
|
-
const hostExecutor = new HostExecutor(logger);
|
|
154
|
-
const executors = new Map<string, Executor>();
|
|
155
|
-
executors.set(BUILTIN_HOST_SANDBOX_ID, hostExecutor);
|
|
156
|
-
|
|
157
|
-
for (const [sandboxId, sandbox] of sandboxes.entries()) {
|
|
158
|
-
executors.set(sandboxId, sandbox.executor);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (connectors.length === 0) {
|
|
162
|
-
throw new Error("No connectors are configured. Add connector instances in your dobby config.");
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const dedupStore = new DedupStore(join(config.data.stateDir, "dedup.json"), config.data.dedupTtlMs, logger);
|
|
166
|
-
const routeResolver = new RouteResolver(config.routes);
|
|
167
|
-
const bindingResolver = new BindingResolver(config.bindings);
|
|
168
|
-
const runtimeRegistry = new RuntimeRegistry(logger);
|
|
169
|
-
|
|
170
|
-
const gateway = new Gateway({
|
|
171
|
-
config,
|
|
172
|
-
connectors,
|
|
173
|
-
providers,
|
|
174
|
-
executors,
|
|
175
|
-
routeResolver,
|
|
176
|
-
bindingResolver,
|
|
177
|
-
dedupStore,
|
|
178
|
-
runtimeRegistry,
|
|
179
|
-
logger,
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
const loadedCronConfig = await loadCronConfig({
|
|
183
|
-
gatewayConfigPath: configPath,
|
|
184
|
-
gatewayConfig: config,
|
|
185
|
-
});
|
|
186
|
-
const cronStore = new CronStore(loadedCronConfig.config.storeFile, loadedCronConfig.config.runLogFile, logger);
|
|
187
|
-
const cronService = new CronService({
|
|
188
|
-
config: loadedCronConfig.config,
|
|
189
|
-
store: cronStore,
|
|
190
|
-
gateway,
|
|
191
|
-
logger,
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
await gateway.start();
|
|
195
|
-
await cronService.start();
|
|
196
|
-
logger.info(
|
|
197
|
-
{
|
|
198
|
-
configPath,
|
|
199
|
-
cronConfigPath: loadedCronConfig.configPath,
|
|
200
|
-
cronConfigSource: loadedCronConfig.source,
|
|
201
|
-
cronEnabled: loadedCronConfig.config.enabled,
|
|
202
|
-
},
|
|
203
|
-
"Gateway started",
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
const shutdown = async (signal: string) => {
|
|
207
|
-
logger.info({ signal }, "Shutting down gateway");
|
|
208
|
-
await cronService.stop();
|
|
209
|
-
await gateway.stop();
|
|
210
|
-
await hostExecutor.close();
|
|
211
|
-
await closeProviderInstances(providers, logger);
|
|
212
|
-
await closeSandboxInstances(sandboxes, logger);
|
|
213
|
-
process.exit(0);
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
process.on("SIGINT", () => {
|
|
217
|
-
void shutdown("SIGINT");
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
process.on("SIGTERM", () => {
|
|
221
|
-
void shutdown("SIGTERM");
|
|
222
|
-
});
|
|
223
|
-
}
|