@omnidev-ai/core 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +889 -0
- package/dist/index.js +2173 -0
- package/dist/test-utils/index.d.ts +142 -0
- package/dist/test-utils/index.js +261 -0
- package/package.json +16 -6
- package/src/capability/AGENTS.md +0 -58
- package/src/capability/commands.test.ts +0 -410
- package/src/capability/commands.ts +0 -72
- package/src/capability/docs.test.ts +0 -192
- package/src/capability/docs.ts +0 -48
- package/src/capability/index.ts +0 -20
- package/src/capability/loader.test.ts +0 -668
- package/src/capability/loader.ts +0 -431
- package/src/capability/registry.test.ts +0 -455
- package/src/capability/registry.ts +0 -55
- package/src/capability/rules.test.ts +0 -135
- package/src/capability/rules.ts +0 -135
- package/src/capability/skills.test.ts +0 -312
- package/src/capability/skills.ts +0 -58
- package/src/capability/sources.test.ts +0 -439
- package/src/capability/sources.ts +0 -998
- package/src/capability/subagents.test.ts +0 -474
- package/src/capability/subagents.ts +0 -105
- package/src/capability/wrapping-integration.test.ts +0 -412
- package/src/capability/yaml-parser.ts +0 -81
- package/src/config/AGENTS.md +0 -46
- package/src/config/capabilities.ts +0 -54
- package/src/config/env.test.ts +0 -270
- package/src/config/env.ts +0 -96
- package/src/config/index.ts +0 -6
- package/src/config/loader.test.ts +0 -198
- package/src/config/loader.ts +0 -207
- package/src/config/parser.test.ts +0 -256
- package/src/config/parser.ts +0 -55
- package/src/config/profiles.test.ts +0 -222
- package/src/config/profiles.ts +0 -75
- package/src/config/provider.test.ts +0 -66
- package/src/config/provider.ts +0 -55
- package/src/debug.ts +0 -20
- package/src/index.test.ts +0 -26
- package/src/index.ts +0 -37
- package/src/mcp-json/index.ts +0 -1
- package/src/mcp-json/manager.test.ts +0 -310
- package/src/mcp-json/manager.ts +0 -106
- package/src/state/active-profile.test.ts +0 -117
- package/src/state/active-profile.ts +0 -41
- package/src/state/index.ts +0 -3
- package/src/state/manifest.test.ts +0 -411
- package/src/state/manifest.ts +0 -137
- package/src/state/providers.test.ts +0 -125
- package/src/state/providers.ts +0 -69
- package/src/sync.ts +0 -288
- package/src/templates/agents.test.ts +0 -23
- package/src/templates/agents.ts +0 -14
- package/src/templates/claude.test.ts +0 -48
- package/src/templates/claude.ts +0 -57
- package/src/test-utils/helpers.test.ts +0 -214
- package/src/test-utils/helpers.ts +0 -284
- package/src/test-utils/index.ts +0 -34
- package/src/test-utils/mocks.test.ts +0 -83
- package/src/test-utils/mocks.ts +0 -101
- package/src/types/capability-export.ts +0 -157
- package/src/types/index.test.ts +0 -28
- package/src/types/index.ts +0 -314
package/src/config/loader.ts
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import type { OmniConfig } from "../types";
|
|
3
|
-
import { parseOmniConfig } from "./parser";
|
|
4
|
-
|
|
5
|
-
const CONFIG_PATH = "omni.toml";
|
|
6
|
-
const LOCAL_CONFIG = "omni.local.toml";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Deep merge two config objects, with override taking precedence
|
|
10
|
-
* @param base - The base config object
|
|
11
|
-
* @param override - The override config object
|
|
12
|
-
* @returns Merged config with override values taking precedence
|
|
13
|
-
*/
|
|
14
|
-
function mergeConfigs(base: OmniConfig, override: OmniConfig): OmniConfig {
|
|
15
|
-
const merged: OmniConfig = { ...base, ...override };
|
|
16
|
-
|
|
17
|
-
// Deep merge env
|
|
18
|
-
merged.env = { ...base.env, ...override.env };
|
|
19
|
-
|
|
20
|
-
// Deep merge profiles
|
|
21
|
-
merged.profiles = { ...base.profiles };
|
|
22
|
-
for (const [name, profile] of Object.entries(override.profiles || {})) {
|
|
23
|
-
merged.profiles[name] = {
|
|
24
|
-
...(base.profiles?.[name] || {}),
|
|
25
|
-
...profile,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Deep merge mcps (only if at least one config has it)
|
|
30
|
-
if (base.mcps || override.mcps) {
|
|
31
|
-
merged.mcps = { ...base.mcps, ...override.mcps };
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return merged;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Load and merge config and local configuration files
|
|
39
|
-
* @returns Merged OmniConfig object
|
|
40
|
-
*
|
|
41
|
-
* Reads omni.toml (main config) and omni.local.toml (local overrides).
|
|
42
|
-
* Local config takes precedence over main config. Missing files are treated as empty configs.
|
|
43
|
-
*/
|
|
44
|
-
export async function loadConfig(): Promise<OmniConfig> {
|
|
45
|
-
let baseConfig: OmniConfig = {};
|
|
46
|
-
let localConfig: OmniConfig = {};
|
|
47
|
-
|
|
48
|
-
if (existsSync(CONFIG_PATH)) {
|
|
49
|
-
const content = await Bun.file(CONFIG_PATH).text();
|
|
50
|
-
baseConfig = parseOmniConfig(content);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (existsSync(LOCAL_CONFIG)) {
|
|
54
|
-
const content = await Bun.file(LOCAL_CONFIG).text();
|
|
55
|
-
localConfig = parseOmniConfig(content);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return mergeConfigs(baseConfig, localConfig);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Write config to omni.toml at project root
|
|
63
|
-
* @param config - The config object to write
|
|
64
|
-
*/
|
|
65
|
-
export async function writeConfig(config: OmniConfig): Promise<void> {
|
|
66
|
-
const content = generateConfigToml(config);
|
|
67
|
-
await Bun.write(CONFIG_PATH, content);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Generate TOML content for OmniConfig
|
|
72
|
-
* @param config - The config object
|
|
73
|
-
* @returns TOML string
|
|
74
|
-
*/
|
|
75
|
-
function generateConfigToml(config: OmniConfig): string {
|
|
76
|
-
const lines: string[] = [];
|
|
77
|
-
|
|
78
|
-
lines.push("# =============================================================================");
|
|
79
|
-
lines.push("# OmniDev Configuration");
|
|
80
|
-
lines.push("# =============================================================================");
|
|
81
|
-
lines.push("# This file defines your project's capabilities, profiles, and settings.");
|
|
82
|
-
lines.push("#");
|
|
83
|
-
lines.push("# Files:");
|
|
84
|
-
lines.push("# • omni.toml - Main config (commit to share with team)");
|
|
85
|
-
lines.push("# • omni.local.toml - Local overrides (add to .gitignore)");
|
|
86
|
-
lines.push("# • omni.lock.toml - Version lock file (commit for reproducibility)");
|
|
87
|
-
lines.push("#");
|
|
88
|
-
lines.push("# Quick start:");
|
|
89
|
-
lines.push("# 1. Add capability sources to [capabilities.sources]");
|
|
90
|
-
lines.push("# 2. Reference them in your profiles");
|
|
91
|
-
lines.push("# 3. Run: omnidev sync");
|
|
92
|
-
lines.push("# 4. Switch profiles: omnidev profile use <name>");
|
|
93
|
-
lines.push("");
|
|
94
|
-
|
|
95
|
-
// Project name
|
|
96
|
-
if (config.project) {
|
|
97
|
-
lines.push(`project = "${config.project}"`);
|
|
98
|
-
lines.push("");
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Note: active_profile is stored in .omni/state/active-profile, not in config.toml
|
|
102
|
-
// We still read it from config.toml for backwards compatibility, but don't write it here
|
|
103
|
-
|
|
104
|
-
// Providers
|
|
105
|
-
if (config.providers?.enabled && config.providers.enabled.length > 0) {
|
|
106
|
-
lines.push("# AI providers to enable (claude, codex, or both)");
|
|
107
|
-
lines.push("[providers]");
|
|
108
|
-
lines.push(`enabled = [${config.providers.enabled.map((p) => `"${p}"`).join(", ")}]`);
|
|
109
|
-
lines.push("");
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Environment variables
|
|
113
|
-
lines.push("# =============================================================================");
|
|
114
|
-
lines.push("# Environment Variables");
|
|
115
|
-
lines.push("# =============================================================================");
|
|
116
|
-
lines.push("# Global environment variables available to all capabilities.");
|
|
117
|
-
// biome-ignore lint/suspicious/noTemplateCurlyInString: Example of env var syntax
|
|
118
|
-
lines.push("# Use ${VAR_NAME} syntax to reference shell environment variables.");
|
|
119
|
-
lines.push("#");
|
|
120
|
-
if (config.env && Object.keys(config.env).length > 0) {
|
|
121
|
-
lines.push("[env]");
|
|
122
|
-
for (const [key, value] of Object.entries(config.env)) {
|
|
123
|
-
lines.push(`${key} = "${value}"`);
|
|
124
|
-
}
|
|
125
|
-
} else {
|
|
126
|
-
lines.push("# [env]");
|
|
127
|
-
// biome-ignore lint/suspicious/noTemplateCurlyInString: Example of env var syntax
|
|
128
|
-
lines.push('# DATABASE_URL = "${DATABASE_URL}"');
|
|
129
|
-
// biome-ignore lint/suspicious/noTemplateCurlyInString: Example of env var syntax
|
|
130
|
-
lines.push('# API_KEY = "${MY_API_KEY}"');
|
|
131
|
-
}
|
|
132
|
-
lines.push("");
|
|
133
|
-
|
|
134
|
-
// Capability sources (commented examples)
|
|
135
|
-
lines.push("# =============================================================================");
|
|
136
|
-
lines.push("# Capability Sources");
|
|
137
|
-
lines.push("# =============================================================================");
|
|
138
|
-
lines.push("# Fetch capabilities from Git repositories. On sync, these are");
|
|
139
|
-
lines.push("# cloned/updated and made available to your profiles.");
|
|
140
|
-
lines.push("#");
|
|
141
|
-
lines.push("# [capabilities.sources]");
|
|
142
|
-
lines.push("# # GitHub shorthand (uses latest commit)");
|
|
143
|
-
lines.push('# tasks = "github:example-org/tasks-capability"');
|
|
144
|
-
lines.push("#");
|
|
145
|
-
lines.push("# # Version pinning (recommended for production)");
|
|
146
|
-
lines.push('# ralph = { source = "github:example-org/ralph", ref = "v1.2.0" }');
|
|
147
|
-
lines.push("#");
|
|
148
|
-
lines.push("# # Other Git sources");
|
|
149
|
-
lines.push('# private = "git@github.com:company/private-cap.git"');
|
|
150
|
-
lines.push('# gitlab = "https://gitlab.com/user/capability.git"');
|
|
151
|
-
lines.push("");
|
|
152
|
-
|
|
153
|
-
// MCP servers (commented examples)
|
|
154
|
-
lines.push("# =============================================================================");
|
|
155
|
-
lines.push("# MCP Servers");
|
|
156
|
-
lines.push("# =============================================================================");
|
|
157
|
-
lines.push("# Define MCP servers that automatically become capabilities.");
|
|
158
|
-
lines.push(
|
|
159
|
-
'# Reference in profiles using the MCP name directly, e.g. capabilities = ["filesystem"]',
|
|
160
|
-
);
|
|
161
|
-
lines.push("#");
|
|
162
|
-
lines.push("# [mcps.filesystem]");
|
|
163
|
-
lines.push('# command = "npx"');
|
|
164
|
-
lines.push('# args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]');
|
|
165
|
-
lines.push('# transport = "stdio" # stdio (default), sse, or http');
|
|
166
|
-
lines.push("#");
|
|
167
|
-
lines.push("# [mcps.database]");
|
|
168
|
-
lines.push('# command = "node"');
|
|
169
|
-
lines.push('# args = ["./servers/database.js"]');
|
|
170
|
-
lines.push('# cwd = "./mcp-servers"');
|
|
171
|
-
lines.push("# [mcps.database.env]");
|
|
172
|
-
// biome-ignore lint/suspicious/noTemplateCurlyInString: Example of env var syntax
|
|
173
|
-
lines.push('# DB_URL = "${DATABASE_URL}"');
|
|
174
|
-
lines.push("");
|
|
175
|
-
|
|
176
|
-
// Always enabled capabilities
|
|
177
|
-
lines.push("# =============================================================================");
|
|
178
|
-
lines.push("# Always Enabled Capabilities");
|
|
179
|
-
lines.push("# =============================================================================");
|
|
180
|
-
lines.push("# Capabilities that load in ALL profiles, regardless of profile config.");
|
|
181
|
-
lines.push("# Useful for essential tools needed everywhere.");
|
|
182
|
-
lines.push("#");
|
|
183
|
-
lines.push('# always_enabled_capabilities = ["git-tools", "linting"]');
|
|
184
|
-
lines.push("");
|
|
185
|
-
|
|
186
|
-
// Profiles
|
|
187
|
-
lines.push("# =============================================================================");
|
|
188
|
-
lines.push("# Profiles");
|
|
189
|
-
lines.push("# =============================================================================");
|
|
190
|
-
lines.push("# Define different capability sets for different workflows.");
|
|
191
|
-
lines.push("# Switch profiles with: omnidev profile use <name>");
|
|
192
|
-
lines.push("");
|
|
193
|
-
if (config.profiles && Object.keys(config.profiles).length > 0) {
|
|
194
|
-
for (const [name, profile] of Object.entries(config.profiles)) {
|
|
195
|
-
lines.push(`[profiles.${name}]`);
|
|
196
|
-
const capabilities = profile.capabilities ?? [];
|
|
197
|
-
if (capabilities.length > 0) {
|
|
198
|
-
lines.push(`capabilities = [${capabilities.map((id) => `"${id}"`).join(", ")}]`);
|
|
199
|
-
} else {
|
|
200
|
-
lines.push("capabilities = []");
|
|
201
|
-
}
|
|
202
|
-
lines.push("");
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return lines.join("\n");
|
|
207
|
-
}
|
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import { parseCapabilityConfig, parseOmniConfig } from "./parser";
|
|
3
|
-
|
|
4
|
-
describe("parseOmniConfig", () => {
|
|
5
|
-
test("parses valid TOML with all fields", () => {
|
|
6
|
-
const toml = `
|
|
7
|
-
project = "my-project"
|
|
8
|
-
default_profile = "dev"
|
|
9
|
-
|
|
10
|
-
[capabilities]
|
|
11
|
-
enable = ["tasks", "git"]
|
|
12
|
-
disable = ["docker"]
|
|
13
|
-
|
|
14
|
-
[env]
|
|
15
|
-
API_URL = "https://api.example.com"
|
|
16
|
-
|
|
17
|
-
[profiles.dev]
|
|
18
|
-
enable = ["debug"]
|
|
19
|
-
disable = []
|
|
20
|
-
|
|
21
|
-
[profiles.prod]
|
|
22
|
-
enable = []
|
|
23
|
-
disable = ["debug"]
|
|
24
|
-
`;
|
|
25
|
-
|
|
26
|
-
const config = parseOmniConfig(toml);
|
|
27
|
-
|
|
28
|
-
expect(config.project).toBe("my-project");
|
|
29
|
-
expect(config.default_profile).toBe("dev");
|
|
30
|
-
expect(config.capabilities?.enable).toEqual(["tasks", "git"]);
|
|
31
|
-
expect(config.capabilities?.disable).toEqual(["docker"]);
|
|
32
|
-
expect(config.env?.API_URL).toBe("https://api.example.com");
|
|
33
|
-
expect(config.profiles?.dev?.enable).toEqual(["debug"]);
|
|
34
|
-
expect(config.profiles?.prod?.disable).toEqual(["debug"]);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test("parses minimal TOML", () => {
|
|
38
|
-
const toml = `
|
|
39
|
-
project = "minimal"
|
|
40
|
-
`;
|
|
41
|
-
|
|
42
|
-
const config = parseOmniConfig(toml);
|
|
43
|
-
|
|
44
|
-
expect(config.project).toBe("minimal");
|
|
45
|
-
expect(config.capabilities).toBeUndefined();
|
|
46
|
-
expect(config.profiles).toBeUndefined();
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test("parses empty TOML", () => {
|
|
50
|
-
const config = parseOmniConfig("");
|
|
51
|
-
|
|
52
|
-
expect(config).toEqual({});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test("parses TOML with arrays", () => {
|
|
56
|
-
const toml = `
|
|
57
|
-
[capabilities]
|
|
58
|
-
enable = ["cap1", "cap2", "cap3"]
|
|
59
|
-
`;
|
|
60
|
-
|
|
61
|
-
const config = parseOmniConfig(toml);
|
|
62
|
-
|
|
63
|
-
expect(config.capabilities?.enable).toEqual(["cap1", "cap2", "cap3"]);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test("parses TOML with nested tables", () => {
|
|
67
|
-
const toml = `
|
|
68
|
-
[profiles.dev]
|
|
69
|
-
enable = ["debug"]
|
|
70
|
-
|
|
71
|
-
[profiles.prod]
|
|
72
|
-
disable = ["debug"]
|
|
73
|
-
`;
|
|
74
|
-
|
|
75
|
-
const config = parseOmniConfig(toml);
|
|
76
|
-
|
|
77
|
-
expect(config.profiles?.dev?.enable).toEqual(["debug"]);
|
|
78
|
-
expect(config.profiles?.prod?.disable).toEqual(["debug"]);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test("throws error for invalid TOML syntax", () => {
|
|
82
|
-
const toml = `
|
|
83
|
-
project = "test
|
|
84
|
-
[invalid
|
|
85
|
-
`;
|
|
86
|
-
|
|
87
|
-
expect(() => parseOmniConfig(toml)).toThrow(/Invalid TOML in config:/);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test("throws error for duplicate keys", () => {
|
|
91
|
-
const toml = `
|
|
92
|
-
project = "test"
|
|
93
|
-
project = "duplicate"
|
|
94
|
-
`;
|
|
95
|
-
|
|
96
|
-
expect(() => parseOmniConfig(toml)).toThrow(/Invalid TOML in config:/);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test("handles boolean values", () => {
|
|
100
|
-
const toml = `
|
|
101
|
-
[capabilities]
|
|
102
|
-
debug = true
|
|
103
|
-
production = false
|
|
104
|
-
`;
|
|
105
|
-
|
|
106
|
-
const config = parseOmniConfig(toml);
|
|
107
|
-
|
|
108
|
-
expect((config.capabilities as Record<string, unknown>)?.debug).toBe(true);
|
|
109
|
-
expect((config.capabilities as Record<string, unknown>)?.production).toBe(false);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
test("handles numeric values", () => {
|
|
113
|
-
const toml = `
|
|
114
|
-
timeout = 30
|
|
115
|
-
max_retries = 5
|
|
116
|
-
`;
|
|
117
|
-
|
|
118
|
-
const config = parseOmniConfig(toml);
|
|
119
|
-
|
|
120
|
-
expect((config as Record<string, unknown>).timeout).toBe(30);
|
|
121
|
-
expect((config as Record<string, unknown>).max_retries).toBe(5);
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
describe("parseCapabilityConfig", () => {
|
|
126
|
-
test("parses valid capability.toml with all required fields", () => {
|
|
127
|
-
const toml = `
|
|
128
|
-
[capability]
|
|
129
|
-
id = "tasks"
|
|
130
|
-
name = "Task Management"
|
|
131
|
-
version = "1.0.0"
|
|
132
|
-
description = "Manage tasks and workflows"
|
|
133
|
-
`;
|
|
134
|
-
|
|
135
|
-
const config = parseCapabilityConfig(toml);
|
|
136
|
-
|
|
137
|
-
expect(config.capability.id).toBe("tasks");
|
|
138
|
-
expect(config.capability.name).toBe("Task Management");
|
|
139
|
-
expect(config.capability.version).toBe("1.0.0");
|
|
140
|
-
expect(config.capability.description).toBe("Manage tasks and workflows");
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
test("parses capability with exports", () => {
|
|
144
|
-
const toml = `
|
|
145
|
-
[capability]
|
|
146
|
-
id = "tasks"
|
|
147
|
-
name = "Task Management"
|
|
148
|
-
version = "1.0.0"
|
|
149
|
-
description = "Manage tasks"
|
|
150
|
-
|
|
151
|
-
[exports]
|
|
152
|
-
module = "index.ts"
|
|
153
|
-
`;
|
|
154
|
-
|
|
155
|
-
const config = parseCapabilityConfig(toml);
|
|
156
|
-
|
|
157
|
-
expect(config.exports?.module).toBe("index.ts");
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
test("parses capability with env declarations", () => {
|
|
161
|
-
const toml = `
|
|
162
|
-
[capability]
|
|
163
|
-
id = "api"
|
|
164
|
-
name = "API Client"
|
|
165
|
-
version = "1.0.0"
|
|
166
|
-
description = "API access"
|
|
167
|
-
|
|
168
|
-
[env.API_KEY]
|
|
169
|
-
required = true
|
|
170
|
-
secret = true
|
|
171
|
-
|
|
172
|
-
[env.API_URL]
|
|
173
|
-
required = false
|
|
174
|
-
default = "https://api.example.com"
|
|
175
|
-
`;
|
|
176
|
-
|
|
177
|
-
const config = parseCapabilityConfig(toml);
|
|
178
|
-
|
|
179
|
-
expect(config.env?.API_KEY).toEqual({ required: true, secret: true });
|
|
180
|
-
expect(config.env?.API_URL).toEqual({
|
|
181
|
-
required: false,
|
|
182
|
-
default: "https://api.example.com",
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
test("throws error when capability.id is missing", () => {
|
|
187
|
-
const toml = `
|
|
188
|
-
[capability]
|
|
189
|
-
name = "Test"
|
|
190
|
-
version = "1.0.0"
|
|
191
|
-
`;
|
|
192
|
-
|
|
193
|
-
expect(() => parseCapabilityConfig(toml)).toThrow(
|
|
194
|
-
/capability.id is required in capability.toml/,
|
|
195
|
-
);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
test("throws error when capability.name is missing", () => {
|
|
199
|
-
const toml = `
|
|
200
|
-
[capability]
|
|
201
|
-
id = "test"
|
|
202
|
-
version = "1.0.0"
|
|
203
|
-
`;
|
|
204
|
-
|
|
205
|
-
expect(() => parseCapabilityConfig(toml)).toThrow(
|
|
206
|
-
/capability.name is required in capability.toml/,
|
|
207
|
-
);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
test("throws error when capability.version is missing", () => {
|
|
211
|
-
const toml = `
|
|
212
|
-
[capability]
|
|
213
|
-
id = "test"
|
|
214
|
-
name = "Test"
|
|
215
|
-
`;
|
|
216
|
-
|
|
217
|
-
expect(() => parseCapabilityConfig(toml)).toThrow(
|
|
218
|
-
/capability.version is required in capability.toml/,
|
|
219
|
-
);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
test("throws error when capability table is missing", () => {
|
|
223
|
-
const toml = `
|
|
224
|
-
project = "test"
|
|
225
|
-
`;
|
|
226
|
-
|
|
227
|
-
expect(() => parseCapabilityConfig(toml)).toThrow(
|
|
228
|
-
/capability.id is required in capability.toml/,
|
|
229
|
-
);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
test("throws error for invalid TOML syntax", () => {
|
|
233
|
-
const toml = `
|
|
234
|
-
[capability
|
|
235
|
-
id = "test"
|
|
236
|
-
`;
|
|
237
|
-
|
|
238
|
-
expect(() => parseCapabilityConfig(toml)).toThrow(/Invalid capability.toml:/);
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
test("handles empty env declarations", () => {
|
|
242
|
-
const toml = `
|
|
243
|
-
[capability]
|
|
244
|
-
id = "test"
|
|
245
|
-
name = "Test"
|
|
246
|
-
version = "1.0.0"
|
|
247
|
-
description = "Test"
|
|
248
|
-
|
|
249
|
-
[env.SIMPLE_VAR]
|
|
250
|
-
`;
|
|
251
|
-
|
|
252
|
-
const config = parseCapabilityConfig(toml);
|
|
253
|
-
|
|
254
|
-
expect(config.env?.SIMPLE_VAR).toEqual({});
|
|
255
|
-
});
|
|
256
|
-
});
|
package/src/config/parser.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { parse } from "smol-toml";
|
|
2
|
-
import type { CapabilityConfig, OmniConfig } from "../types";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Parse a TOML string into an OmniConfig object
|
|
6
|
-
* @param tomlContent - The TOML content to parse
|
|
7
|
-
* @returns Parsed OmniConfig object
|
|
8
|
-
* @throws Error if TOML is invalid
|
|
9
|
-
*/
|
|
10
|
-
export function parseOmniConfig(tomlContent: string): OmniConfig {
|
|
11
|
-
try {
|
|
12
|
-
return parse(tomlContent) as OmniConfig;
|
|
13
|
-
} catch (error) {
|
|
14
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
15
|
-
throw new Error(`Invalid TOML in config: ${message}`);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Validate that parsed TOML has required capability fields
|
|
21
|
-
*/
|
|
22
|
-
function validateCapabilityConfig(parsed: Record<string, unknown>): void {
|
|
23
|
-
const cap = parsed["capability"];
|
|
24
|
-
if (typeof cap !== "object" || cap === null) {
|
|
25
|
-
throw new Error("capability.id is required in capability.toml");
|
|
26
|
-
}
|
|
27
|
-
const capability = cap as Record<string, unknown>;
|
|
28
|
-
if (typeof capability["id"] !== "string") {
|
|
29
|
-
throw new Error("capability.id is required in capability.toml");
|
|
30
|
-
}
|
|
31
|
-
if (typeof capability["name"] !== "string") {
|
|
32
|
-
throw new Error("capability.name is required in capability.toml");
|
|
33
|
-
}
|
|
34
|
-
if (typeof capability["version"] !== "string") {
|
|
35
|
-
throw new Error("capability.version is required in capability.toml");
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Parse a TOML string into a CapabilityConfig object
|
|
41
|
-
* @param tomlContent - The TOML content to parse
|
|
42
|
-
* @returns Parsed CapabilityConfig object
|
|
43
|
-
* @throws Error if TOML is invalid or required fields are missing
|
|
44
|
-
*/
|
|
45
|
-
export function parseCapabilityConfig(tomlContent: string): CapabilityConfig {
|
|
46
|
-
try {
|
|
47
|
-
const parsed = parse(tomlContent) as Record<string, unknown>;
|
|
48
|
-
validateCapabilityConfig(parsed);
|
|
49
|
-
// After validation, we know the structure matches CapabilityConfig
|
|
50
|
-
return parsed as unknown as CapabilityConfig;
|
|
51
|
-
} catch (error) {
|
|
52
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
53
|
-
throw new Error(`Invalid capability.toml: ${message}`);
|
|
54
|
-
}
|
|
55
|
-
}
|