@dobby.ai/dobby 0.1.0 → 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 +84 -39
- package/dist/src/agent/event-forwarder.js +185 -16
- package/dist/src/cli/commands/cron.js +39 -35
- package/dist/src/cli/commands/doctor.js +81 -2
- package/dist/src/cli/commands/extension.js +3 -1
- package/dist/src/cli/commands/init.js +43 -173
- package/dist/src/cli/commands/topology.js +38 -14
- package/dist/src/cli/program.js +15 -137
- package/dist/src/cli/shared/config-io.js +3 -31
- package/dist/src/cli/shared/config-mutators.js +33 -9
- package/dist/src/cli/shared/configure-sections.js +52 -12
- package/dist/src/cli/shared/init-catalog.js +89 -46
- package/dist/src/cli/shared/local-extension-specs.js +85 -0
- package/dist/src/cli/shared/schema-prompts.js +26 -2
- package/dist/src/core/gateway.js +3 -1
- package/dist/src/core/routing.js +53 -38
- 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/dist/src/main.js +0 -0
- package/dist/src/shared/dobby-repo.js +40 -0
- package/package.json +11 -4
- package/.env.example +0 -9
- package/AGENTS.md +0 -267
- package/ROADMAP.md +0 -34
- package/config/cron.example.json +0 -9
- package/config/gateway.example.json +0 -128
- package/config/models.custom.example.json +0 -27
- package/dist/src/agent/tests/event-forwarder.test.js +0 -113
- package/dist/src/cli/shared/config-path.js +0 -207
- package/dist/src/cli/shared/init-models-file.js +0 -65
- package/dist/src/cli/shared/presets.js +0 -86
- 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/config-path.test.js +0 -21
- package/dist/src/cli/tests/discord-config.test.js +0 -23
- package/dist/src/cli/tests/doctor.test.js +0 -107
- package/dist/src/cli/tests/init-catalog.test.js +0 -87
- package/dist/src/cli/tests/presets.test.js +0 -41
- package/dist/src/cli/tests/program-options.test.js +0 -92
- package/dist/src/cli/tests/routing-config.test.js +0 -199
- package/dist/src/cli/tests/routing-legacy.test.js +0 -191
- package/dist/src/core/tests/control-command.test.js +0 -17
- package/dist/src/core/tests/gateway-update-strategy.test.js +0 -167
- 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 -242
- 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 -350
- package/plugins/connector-discord/src/contribution.ts +0 -21
- package/plugins/connector-discord/src/mapper.ts +0 -102
- 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 -476
- 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 -230
- package/src/cli/commands/extension.ts +0 -205
- package/src/cli/commands/init.ts +0 -396
- package/src/cli/commands/start.ts +0 -223
- package/src/cli/commands/topology.ts +0 -383
- package/src/cli/index.ts +0 -9
- package/src/cli/program.ts +0 -465
- package/src/cli/shared/config-io.ts +0 -277
- package/src/cli/shared/config-mutators.ts +0 -440
- package/src/cli/shared/config-schema.ts +0 -228
- package/src/cli/shared/config-types.ts +0 -121
- package/src/cli/shared/configure-sections.ts +0 -551
- package/src/cli/shared/discord-config.ts +0 -14
- package/src/cli/shared/init-catalog.ts +0 -189
- package/src/cli/shared/init-models-file.ts +0 -77
- package/src/cli/shared/runtime.ts +0 -33
- package/src/cli/shared/schema-prompts.ts +0 -414
- 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/doctor.test.ts +0 -120
- package/src/cli/tests/init-catalog.test.ts +0 -96
- package/src/cli/tests/program-options.test.ts +0 -113
- package/src/cli/tests/routing-config.test.ts +0 -209
- package/src/core/control-command.ts +0 -12
- package/src/core/dedup-store.ts +0 -103
- package/src/core/gateway.ts +0 -607
- package/src/core/routing.ts +0 -379
- 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 -318
- 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/tsconfig.json +0 -18
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { mkdir, mkdtemp, writeFile } from "node:fs/promises";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { tmpdir } from "node:os";
|
|
5
|
-
import { resolve } from "node:path";
|
|
6
|
-
import test from "node:test";
|
|
7
|
-
import { DEFAULT_CONFIG_PATH, resolveConfigPath, resolveDataRootDir } from "../shared/config-io.js";
|
|
8
|
-
test("resolveConfigPath defaults to $HOME/.dobby/gateway.json", () => {
|
|
9
|
-
assert.equal(DEFAULT_CONFIG_PATH, resolve(homedir(), ".dobby", "gateway.json"));
|
|
10
|
-
});
|
|
11
|
-
test("resolveConfigPath falls back to default path outside dobby repository", async () => {
|
|
12
|
-
const cwd = await mkdtemp(resolve(tmpdir(), "dobby-config-path-default-"));
|
|
13
|
-
assert.equal(resolveConfigPath({ cwd, env: {} }), DEFAULT_CONFIG_PATH);
|
|
14
|
-
});
|
|
15
|
-
test("resolveConfigPath detects local dobby repository config path", async () => {
|
|
16
|
-
const repoRoot = await mkdtemp(resolve(tmpdir(), "dobby-config-path-repo-"));
|
|
17
|
-
await mkdir(resolve(repoRoot, "config"), { recursive: true });
|
|
18
|
-
await mkdir(resolve(repoRoot, "scripts"), { recursive: true });
|
|
19
|
-
await mkdir(resolve(repoRoot, "src", "cli"), { recursive: true });
|
|
20
|
-
await writeFile(resolve(repoRoot, "package.json"), JSON.stringify({ name: "dobby" }), "utf-8");
|
|
21
|
-
await writeFile(resolve(repoRoot, "config", "gateway.json"), "{}", "utf-8");
|
|
22
|
-
await writeFile(resolve(repoRoot, "scripts", "local-extensions.mjs"), "#!/usr/bin/env node\n", "utf-8");
|
|
23
|
-
assert.equal(resolveConfigPath({
|
|
24
|
-
cwd: resolve(repoRoot, "src", "cli"),
|
|
25
|
-
env: {},
|
|
26
|
-
}), resolve(repoRoot, "config", "gateway.json"));
|
|
27
|
-
});
|
|
28
|
-
test("resolveConfigPath prioritizes DOBBY_CONFIG_PATH over repository detection", async () => {
|
|
29
|
-
const repoRoot = await mkdtemp(resolve(tmpdir(), "dobby-config-path-env-priority-"));
|
|
30
|
-
await mkdir(resolve(repoRoot, "config"), { recursive: true });
|
|
31
|
-
await mkdir(resolve(repoRoot, "scripts"), { recursive: true });
|
|
32
|
-
await writeFile(resolve(repoRoot, "package.json"), JSON.stringify({ name: "dobby" }), "utf-8");
|
|
33
|
-
await writeFile(resolve(repoRoot, "config", "gateway.json"), "{}", "utf-8");
|
|
34
|
-
await writeFile(resolve(repoRoot, "scripts", "local-extensions.mjs"), "#!/usr/bin/env node\n", "utf-8");
|
|
35
|
-
const customPath = resolve(tmpdir(), "dobby-custom-gateway.json");
|
|
36
|
-
assert.equal(resolveConfigPath({
|
|
37
|
-
cwd: repoRoot,
|
|
38
|
-
env: { DOBBY_CONFIG_PATH: customPath },
|
|
39
|
-
}), customPath);
|
|
40
|
-
});
|
|
41
|
-
test("resolveConfigPath supports relative and home-prefixed DOBBY_CONFIG_PATH", async () => {
|
|
42
|
-
const cwd = await mkdtemp(resolve(tmpdir(), "dobby-config-path-env-expand-"));
|
|
43
|
-
assert.equal(resolveConfigPath({
|
|
44
|
-
cwd,
|
|
45
|
-
env: { DOBBY_CONFIG_PATH: "config/local-gateway.json" },
|
|
46
|
-
}), resolve(cwd, "config/local-gateway.json"));
|
|
47
|
-
assert.equal(resolveConfigPath({
|
|
48
|
-
cwd,
|
|
49
|
-
env: { DOBBY_CONFIG_PATH: "~/custom-gateway.json" },
|
|
50
|
-
}), resolve(homedir(), "custom-gateway.json"));
|
|
51
|
-
});
|
|
52
|
-
test("resolveDataRootDir uses repo root for repo-local config/gateway.json", async () => {
|
|
53
|
-
const repoRoot = await mkdtemp(resolve(tmpdir(), "dobby-data-root-repo-"));
|
|
54
|
-
await mkdir(resolve(repoRoot, "config"), { recursive: true });
|
|
55
|
-
await mkdir(resolve(repoRoot, "scripts"), { recursive: true });
|
|
56
|
-
await writeFile(resolve(repoRoot, "package.json"), JSON.stringify({ name: "dobby" }), "utf-8");
|
|
57
|
-
await writeFile(resolve(repoRoot, "config", "gateway.json"), "{}", "utf-8");
|
|
58
|
-
await writeFile(resolve(repoRoot, "scripts", "local-extensions.mjs"), "#!/usr/bin/env node\n", "utf-8");
|
|
59
|
-
assert.equal(resolveDataRootDir(resolve(repoRoot, "config", "gateway.json"), {
|
|
60
|
-
data: {
|
|
61
|
-
rootDir: "./data",
|
|
62
|
-
},
|
|
63
|
-
}), resolve(repoRoot, "data"));
|
|
64
|
-
});
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { applyContributionTemplates, ensureGatewayConfigShape, setDefaultProviderIfMissingOrInvalid, upsertAllowListPackage, } from "../shared/config-mutators.js";
|
|
4
|
-
test("upsertAllowListPackage is idempotent", () => {
|
|
5
|
-
const config = ensureGatewayConfigShape({});
|
|
6
|
-
upsertAllowListPackage(config, "@dobby.ai/provider-pi", true);
|
|
7
|
-
upsertAllowListPackage(config, "@dobby.ai/provider-pi", true);
|
|
8
|
-
assert.equal(config.extensions?.allowList?.length, 1);
|
|
9
|
-
assert.equal(config.extensions?.allowList?.[0]?.package, "@dobby.ai/provider-pi");
|
|
10
|
-
assert.equal(config.extensions?.allowList?.[0]?.enabled, true);
|
|
11
|
-
});
|
|
12
|
-
test("applyContributionTemplates allocates new instance IDs when needed", () => {
|
|
13
|
-
const config = ensureGatewayConfigShape({
|
|
14
|
-
providers: {
|
|
15
|
-
default: "pi.main",
|
|
16
|
-
items: {
|
|
17
|
-
"pi.main": {
|
|
18
|
-
type: "provider.pi",
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
const added = applyContributionTemplates(config, {
|
|
24
|
-
providers: [
|
|
25
|
-
{ id: "pi.main", type: "provider.another", config: {} },
|
|
26
|
-
{ id: "pi.main", type: "provider.third", config: {} },
|
|
27
|
-
],
|
|
28
|
-
connectors: [],
|
|
29
|
-
sandboxes: [],
|
|
30
|
-
});
|
|
31
|
-
assert.deepEqual(added.providers, ["pi.main-2", "pi.main-3"]);
|
|
32
|
-
assert.equal(config.providers.items["pi.main-2"]?.type, "provider.another");
|
|
33
|
-
assert.equal(config.providers.items["pi.main-3"]?.type, "provider.third");
|
|
34
|
-
});
|
|
35
|
-
test("setDefaultProviderIfMissingOrInvalid picks lexicographically first provider", () => {
|
|
36
|
-
const config = ensureGatewayConfigShape({
|
|
37
|
-
providers: {
|
|
38
|
-
default: "missing",
|
|
39
|
-
items: {
|
|
40
|
-
"z.main": { type: "provider.z" },
|
|
41
|
-
"a.main": { type: "provider.a" },
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
setDefaultProviderIfMissingOrInvalid(config);
|
|
46
|
-
assert.equal(config.providers.default, "a.main");
|
|
47
|
-
});
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { getAtPath, parsePath, setAtPath, unsetAtPath } from "../shared/config-path.js";
|
|
4
|
-
test("parsePath handles dot and bracket notation", () => {
|
|
5
|
-
assert.deepEqual(parsePath("routing.routes.main.projectRoot"), ["routing", "routes", "main", "projectRoot"]);
|
|
6
|
-
assert.deepEqual(parsePath("connectors.instances[discord.main].config.botChannelMap[12345]"), ["connectors", "instances", "discord.main", "config", "botChannelMap", "12345"]);
|
|
7
|
-
});
|
|
8
|
-
test("setAtPath and getAtPath support nested objects", () => {
|
|
9
|
-
const payload = {};
|
|
10
|
-
setAtPath(payload, parsePath("a.b.c"), 42);
|
|
11
|
-
const read = getAtPath(payload, parsePath("a.b.c"));
|
|
12
|
-
assert.equal(read.found, true);
|
|
13
|
-
assert.equal(read.value, 42);
|
|
14
|
-
});
|
|
15
|
-
test("unsetAtPath removes keys", () => {
|
|
16
|
-
const payload = { a: { b: { c: 1 } } };
|
|
17
|
-
const removed = unsetAtPath(payload, parsePath("a.b.c"));
|
|
18
|
-
assert.equal(removed, true);
|
|
19
|
-
const read = getAtPath(payload, parsePath("a.b.c"));
|
|
20
|
-
assert.equal(read.found, false);
|
|
21
|
-
});
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import { normalizeDiscordBotChannelMap } from "../shared/discord-config.js";
|
|
4
|
-
test("normalizeDiscordBotChannelMap keeps valid channel->route entries", () => {
|
|
5
|
-
const normalized = normalizeDiscordBotChannelMap({
|
|
6
|
-
"123": "projectA",
|
|
7
|
-
"456": "projectB",
|
|
8
|
-
});
|
|
9
|
-
assert.deepEqual(normalized, {
|
|
10
|
-
"123": "projectA",
|
|
11
|
-
"456": "projectB",
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
test("normalizeDiscordBotChannelMap drops invalid values", () => {
|
|
15
|
-
const normalized = normalizeDiscordBotChannelMap({
|
|
16
|
-
"123": "projectA",
|
|
17
|
-
"456": "",
|
|
18
|
-
"789": 1,
|
|
19
|
-
});
|
|
20
|
-
assert.deepEqual(normalized, {
|
|
21
|
-
"123": "projectA",
|
|
22
|
-
});
|
|
23
|
-
});
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
3
|
-
import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
|
|
4
|
-
import { tmpdir } from "node:os";
|
|
5
|
-
import { join } from "node:path";
|
|
6
|
-
import test from "node:test";
|
|
7
|
-
/**
|
|
8
|
-
* Writes a temporary default config under HOME/.dobby/gateway.json.
|
|
9
|
-
*/
|
|
10
|
-
async function writeTempHomeConfig(homeDir, payload) {
|
|
11
|
-
const dobbyDir = join(homeDir, ".dobby");
|
|
12
|
-
await mkdir(dobbyDir, { recursive: true });
|
|
13
|
-
const configPath = join(dobbyDir, "gateway.json");
|
|
14
|
-
await writeFile(configPath, `${JSON.stringify(payload, null, 2)}\n`, "utf-8");
|
|
15
|
-
return configPath;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Runs `dobby doctor` in a child process with an isolated HOME directory.
|
|
19
|
-
*/
|
|
20
|
-
async function runDoctorWithHome(homeDir, configPath) {
|
|
21
|
-
return await new Promise((resolve, reject) => {
|
|
22
|
-
const child = spawn(process.execPath, ["--import", "tsx", "src/main.ts", "doctor"], {
|
|
23
|
-
cwd: process.cwd(),
|
|
24
|
-
env: {
|
|
25
|
-
...process.env,
|
|
26
|
-
HOME: homeDir,
|
|
27
|
-
DOBBY_CONFIG_PATH: configPath,
|
|
28
|
-
},
|
|
29
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
30
|
-
});
|
|
31
|
-
let output = "";
|
|
32
|
-
child.stdout.on("data", (chunk) => {
|
|
33
|
-
output += String(chunk);
|
|
34
|
-
});
|
|
35
|
-
child.stderr.on("data", (chunk) => {
|
|
36
|
-
output += String(chunk);
|
|
37
|
-
});
|
|
38
|
-
child.once("error", (error) => reject(error));
|
|
39
|
-
child.once("close", (code) => {
|
|
40
|
-
resolve({ code, output });
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
test("doctor reports invalid binding route references", async () => {
|
|
45
|
-
const homeDir = await mkdtemp(join(tmpdir(), "dobby-doctor-home-"));
|
|
46
|
-
try {
|
|
47
|
-
const configPath = await writeTempHomeConfig(homeDir, {
|
|
48
|
-
extensions: { allowList: [] },
|
|
49
|
-
providers: {
|
|
50
|
-
default: "pi.main",
|
|
51
|
-
items: {
|
|
52
|
-
"pi.main": {
|
|
53
|
-
type: "provider.pi",
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
connectors: {
|
|
58
|
-
items: {
|
|
59
|
-
"discord.main": {
|
|
60
|
-
type: "connector.discord",
|
|
61
|
-
botName: "dobby-main",
|
|
62
|
-
botToken: "token",
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
sandboxes: {
|
|
67
|
-
default: "host.builtin",
|
|
68
|
-
items: {},
|
|
69
|
-
},
|
|
70
|
-
routes: {
|
|
71
|
-
defaults: {
|
|
72
|
-
provider: "pi.main",
|
|
73
|
-
sandbox: "host.builtin",
|
|
74
|
-
tools: "full",
|
|
75
|
-
mentions: "required",
|
|
76
|
-
},
|
|
77
|
-
items: {
|
|
78
|
-
main: {
|
|
79
|
-
projectRoot: process.cwd(),
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
bindings: {
|
|
84
|
-
items: {
|
|
85
|
-
"discord.main.123": {
|
|
86
|
-
connector: "discord.main",
|
|
87
|
-
source: {
|
|
88
|
-
type: "channel",
|
|
89
|
-
id: "123",
|
|
90
|
-
},
|
|
91
|
-
route: "missing-route",
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
data: {
|
|
96
|
-
rootDir: "./data",
|
|
97
|
-
dedupTtlMs: 604800000,
|
|
98
|
-
},
|
|
99
|
-
});
|
|
100
|
-
const result = await runDoctorWithHome(homeDir, configPath);
|
|
101
|
-
assert.equal(result.code, 1);
|
|
102
|
-
assert.equal(result.output.includes("bindings.items['discord.main.123'].route") && result.output.includes("missing-route"), true);
|
|
103
|
-
}
|
|
104
|
-
finally {
|
|
105
|
-
await rm(homeDir, { recursive: true, force: true });
|
|
106
|
-
}
|
|
107
|
-
});
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import { createInitSelectionConfig } from "../shared/init-catalog.js";
|
|
4
|
-
test("createInitSelectionConfig wires explicit Discord bot config for provider.pi", () => {
|
|
5
|
-
const selected = createInitSelectionConfig(["provider.pi"], "connector.discord", {
|
|
6
|
-
routeId: "main",
|
|
7
|
-
projectRoot: "/tmp/project",
|
|
8
|
-
allowAllMessages: false,
|
|
9
|
-
botName: "dobby-main",
|
|
10
|
-
botToken: "token-abc",
|
|
11
|
-
channelId: "123",
|
|
12
|
-
routeProviderChoiceId: "provider.pi",
|
|
13
|
-
});
|
|
14
|
-
assert.deepEqual(selected.connectorConfig, {
|
|
15
|
-
botName: "dobby-main",
|
|
16
|
-
botToken: "token-abc",
|
|
17
|
-
reconnectStaleMs: 60_000,
|
|
18
|
-
reconnectCheckIntervalMs: 10_000,
|
|
19
|
-
});
|
|
20
|
-
assert.deepEqual(selected.providerChoiceIds, ["provider.pi"]);
|
|
21
|
-
assert.equal(selected.providerInstances.length, 1);
|
|
22
|
-
assert.equal(selected.providerInstanceId, "pi.main");
|
|
23
|
-
assert.equal(selected.providerContributionId, "provider.pi");
|
|
24
|
-
assert.equal(selected.routeProfile.provider, "pi.main");
|
|
25
|
-
assert.equal(selected.routeProfile.mentions, "required");
|
|
26
|
-
assert.equal(selected.bindingId, "discord.main.main");
|
|
27
|
-
assert.deepEqual(selected.bindingConfig, {
|
|
28
|
-
connector: "discord.main",
|
|
29
|
-
source: {
|
|
30
|
-
type: "channel",
|
|
31
|
-
id: "123",
|
|
32
|
-
},
|
|
33
|
-
route: "main",
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
test("createInitSelectionConfig wires explicit Discord bot config for provider.claude-cli", () => {
|
|
37
|
-
const selected = createInitSelectionConfig(["provider.claude-cli"], "connector.discord", {
|
|
38
|
-
routeId: "support",
|
|
39
|
-
projectRoot: "/tmp/project",
|
|
40
|
-
allowAllMessages: true,
|
|
41
|
-
botName: "ops-bot",
|
|
42
|
-
botToken: "token-xyz",
|
|
43
|
-
channelId: "999",
|
|
44
|
-
routeProviderChoiceId: "provider.claude-cli",
|
|
45
|
-
});
|
|
46
|
-
assert.deepEqual(selected.connectorConfig, {
|
|
47
|
-
botName: "ops-bot",
|
|
48
|
-
botToken: "token-xyz",
|
|
49
|
-
reconnectStaleMs: 60_000,
|
|
50
|
-
reconnectCheckIntervalMs: 10_000,
|
|
51
|
-
});
|
|
52
|
-
assert.deepEqual(selected.providerChoiceIds, ["provider.claude-cli"]);
|
|
53
|
-
assert.equal(selected.providerInstances.length, 1);
|
|
54
|
-
assert.equal(selected.providerInstanceId, "claude-cli.main");
|
|
55
|
-
assert.equal(selected.providerContributionId, "provider.claude-cli");
|
|
56
|
-
assert.equal(selected.routeProfile.provider, "claude-cli.main");
|
|
57
|
-
assert.equal(selected.routeProfile.mentions, "optional");
|
|
58
|
-
assert.deepEqual(selected.bindingConfig, {
|
|
59
|
-
connector: "discord.main",
|
|
60
|
-
source: {
|
|
61
|
-
type: "channel",
|
|
62
|
-
id: "999",
|
|
63
|
-
},
|
|
64
|
-
route: "support",
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
test("createInitSelectionConfig supports multiple providers and uses explicit route provider", () => {
|
|
68
|
-
const selected = createInitSelectionConfig(["provider.pi", "provider.claude-cli"], "connector.discord", {
|
|
69
|
-
routeId: "ops",
|
|
70
|
-
projectRoot: "/tmp/project",
|
|
71
|
-
allowAllMessages: false,
|
|
72
|
-
botName: "dobby-multi",
|
|
73
|
-
botToken: "token-multi",
|
|
74
|
-
channelId: "777",
|
|
75
|
-
routeProviderChoiceId: "provider.claude-cli",
|
|
76
|
-
});
|
|
77
|
-
assert.deepEqual(selected.providerChoiceIds, ["provider.pi", "provider.claude-cli"]);
|
|
78
|
-
assert.deepEqual(selected.providerInstances.map((item) => item.instanceId), ["pi.main", "claude-cli.main"]);
|
|
79
|
-
assert.deepEqual(selected.extensionPackages, [
|
|
80
|
-
"@dobby.ai/provider-pi",
|
|
81
|
-
"@dobby.ai/provider-claude-cli",
|
|
82
|
-
"@dobby.ai/connector-discord",
|
|
83
|
-
]);
|
|
84
|
-
assert.equal(selected.providerInstanceId, "claude-cli.main");
|
|
85
|
-
assert.equal(selected.routeProfile.provider, "claude-cli.main");
|
|
86
|
-
assert.equal(selected.routeProviderChoiceId, "provider.claude-cli");
|
|
87
|
-
});
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import { createPresetConfig } from "../shared/presets.js";
|
|
4
|
-
test("createPresetConfig wires explicit Discord bot config for discord-pi", () => {
|
|
5
|
-
const preset = createPresetConfig("discord-pi", {
|
|
6
|
-
routeId: "main",
|
|
7
|
-
projectRoot: "/tmp/project",
|
|
8
|
-
allowAllMessages: false,
|
|
9
|
-
botName: "dobby-main",
|
|
10
|
-
botToken: "token-abc",
|
|
11
|
-
channelId: "123",
|
|
12
|
-
});
|
|
13
|
-
assert.deepEqual(preset.connectorConfig, {
|
|
14
|
-
botName: "dobby-main",
|
|
15
|
-
botToken: "token-abc",
|
|
16
|
-
botChannelMap: {
|
|
17
|
-
"123": "main",
|
|
18
|
-
},
|
|
19
|
-
reconnectStaleMs: 60_000,
|
|
20
|
-
reconnectCheckIntervalMs: 10_000,
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
test("createPresetConfig wires explicit Discord bot config for discord-claude-cli", () => {
|
|
24
|
-
const preset = createPresetConfig("discord-claude-cli", {
|
|
25
|
-
routeId: "support",
|
|
26
|
-
projectRoot: "/tmp/project",
|
|
27
|
-
allowAllMessages: true,
|
|
28
|
-
botName: "ops-bot",
|
|
29
|
-
botToken: "token-xyz",
|
|
30
|
-
channelId: "999",
|
|
31
|
-
});
|
|
32
|
-
assert.deepEqual(preset.connectorConfig, {
|
|
33
|
-
botName: "ops-bot",
|
|
34
|
-
botToken: "token-xyz",
|
|
35
|
-
botChannelMap: {
|
|
36
|
-
"999": "support",
|
|
37
|
-
},
|
|
38
|
-
reconnectStaleMs: 60_000,
|
|
39
|
-
reconnectCheckIntervalMs: 10_000,
|
|
40
|
-
});
|
|
41
|
-
});
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import { CommanderError } from "commander";
|
|
4
|
-
import { buildProgram } from "../program.js";
|
|
5
|
-
test("CLI rejects --config option", async () => {
|
|
6
|
-
const program = buildProgram();
|
|
7
|
-
program.configureOutput({
|
|
8
|
-
writeErr: () => { },
|
|
9
|
-
writeOut: () => { },
|
|
10
|
-
});
|
|
11
|
-
program.exitOverride();
|
|
12
|
-
await assert.rejects(program.parseAsync(["node", "dobby", "--config", "./config/gateway.json"]), (error) => {
|
|
13
|
-
assert.equal(error instanceof CommanderError, true);
|
|
14
|
-
assert.equal(error.code, "commander.unknownOption");
|
|
15
|
-
assert.match(String(error.message), /unknown option '--config'/i);
|
|
16
|
-
return true;
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
test("init help has no merge/overwrite flags", () => {
|
|
20
|
-
const program = buildProgram();
|
|
21
|
-
const initCommand = program.commands.find((command) => command.name() === "init");
|
|
22
|
-
assert.ok(initCommand);
|
|
23
|
-
const help = initCommand.helpInformation();
|
|
24
|
-
assert.equal(help.includes("--merge"), false);
|
|
25
|
-
assert.equal(help.includes("--merge-strategy"), false);
|
|
26
|
-
assert.equal(help.includes("--overwrite"), false);
|
|
27
|
-
assert.equal(help.includes("--preset"), false);
|
|
28
|
-
assert.equal(help.includes("--non-interactive"), false);
|
|
29
|
-
assert.equal(help.includes("--yes"), false);
|
|
30
|
-
assert.equal(help.includes("--config"), false);
|
|
31
|
-
});
|
|
32
|
-
test("config help shows show/list/edit and schema", () => {
|
|
33
|
-
const program = buildProgram();
|
|
34
|
-
const configCommand = program.commands.find((command) => command.name() === "config");
|
|
35
|
-
assert.ok(configCommand);
|
|
36
|
-
const help = configCommand.helpInformation();
|
|
37
|
-
assert.match(help, /show \[options\] \[section\]/);
|
|
38
|
-
assert.match(help, /list \[options\] \[section\]/);
|
|
39
|
-
assert.match(help, /edit \[options\]/);
|
|
40
|
-
assert.match(help, /schema/);
|
|
41
|
-
assert.equal(help.includes("get"), false);
|
|
42
|
-
assert.equal(help.includes("set"), false);
|
|
43
|
-
assert.equal(help.includes("unset"), false);
|
|
44
|
-
});
|
|
45
|
-
test("config schema help shows list/show subcommands", () => {
|
|
46
|
-
const program = buildProgram();
|
|
47
|
-
const configCommand = program.commands.find((command) => command.name() === "config");
|
|
48
|
-
assert.ok(configCommand);
|
|
49
|
-
const schemaCommand = configCommand.commands.find((command) => command.name() === "schema");
|
|
50
|
-
assert.ok(schemaCommand);
|
|
51
|
-
const help = schemaCommand.helpInformation();
|
|
52
|
-
assert.match(help, /list \[options\]/);
|
|
53
|
-
assert.match(help, /show \[options\] <contributionId>/);
|
|
54
|
-
});
|
|
55
|
-
test("cron help shows core subcommands", () => {
|
|
56
|
-
const program = buildProgram();
|
|
57
|
-
const cronCommand = program.commands.find((command) => command.name() === "cron");
|
|
58
|
-
assert.ok(cronCommand);
|
|
59
|
-
const help = cronCommand.helpInformation();
|
|
60
|
-
assert.match(help, /add \[options\] <name>/);
|
|
61
|
-
assert.match(help, /list \[options\]/);
|
|
62
|
-
assert.match(help, /run \[options\] <jobId>/);
|
|
63
|
-
assert.match(help, /remove \[options\] <jobId>/);
|
|
64
|
-
});
|
|
65
|
-
test("binding help shows list, set, and remove subcommands", () => {
|
|
66
|
-
const program = buildProgram();
|
|
67
|
-
const bindingCommand = program.commands.find((command) => command.name() === "binding");
|
|
68
|
-
assert.ok(bindingCommand);
|
|
69
|
-
const help = bindingCommand.helpInformation();
|
|
70
|
-
assert.match(help, /list \[options\]/);
|
|
71
|
-
assert.match(help, /set \[options\] <bindingId>/);
|
|
72
|
-
assert.match(help, /remove <bindingId>/);
|
|
73
|
-
});
|
|
74
|
-
test("route help reflects provider, sandbox, mentions, and cascade-bindings options", () => {
|
|
75
|
-
const program = buildProgram();
|
|
76
|
-
const routeCommand = program.commands.find((command) => command.name() === "route");
|
|
77
|
-
assert.ok(routeCommand);
|
|
78
|
-
const setCommand = routeCommand.commands.find((command) => command.name() === "set");
|
|
79
|
-
const removeCommand = routeCommand.commands.find((command) => command.name() === "remove");
|
|
80
|
-
assert.ok(setCommand);
|
|
81
|
-
assert.ok(removeCommand);
|
|
82
|
-
const setHelp = setCommand.helpInformation();
|
|
83
|
-
const removeHelp = removeCommand.helpInformation();
|
|
84
|
-
assert.match(setHelp, /--provider <id>/);
|
|
85
|
-
assert.match(setHelp, /--sandbox <id>/);
|
|
86
|
-
assert.match(setHelp, /--mentions <policy>/);
|
|
87
|
-
assert.equal(setHelp.includes("--provider-id"), false);
|
|
88
|
-
assert.equal(setHelp.includes("--sandbox-id"), false);
|
|
89
|
-
assert.equal(setHelp.includes("--mentions-only"), false);
|
|
90
|
-
assert.equal(setHelp.includes("--default"), false);
|
|
91
|
-
assert.match(removeHelp, /--cascade-bindings/);
|
|
92
|
-
});
|