@archon-claw/cli 0.0.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.
Files changed (80) hide show
  1. package/dist/agent.d.ts +2 -0
  2. package/dist/agent.js +152 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +141 -0
  5. package/dist/config.d.ts +2 -0
  6. package/dist/config.js +161 -0
  7. package/dist/eval/assertions.d.ts +9 -0
  8. package/dist/eval/assertions.js +137 -0
  9. package/dist/eval/execute.d.ts +13 -0
  10. package/dist/eval/execute.js +260 -0
  11. package/dist/eval/formatter.d.ts +10 -0
  12. package/dist/eval/formatter.js +62 -0
  13. package/dist/eval/judge.d.ts +7 -0
  14. package/dist/eval/judge.js +116 -0
  15. package/dist/eval/runner.d.ts +9 -0
  16. package/dist/eval/runner.js +156 -0
  17. package/dist/eval/types.d.ts +67 -0
  18. package/dist/eval/types.js +1 -0
  19. package/dist/llm.d.ts +7 -0
  20. package/dist/llm.js +52 -0
  21. package/dist/mcp-manager.d.ts +51 -0
  22. package/dist/mcp-manager.js +268 -0
  23. package/dist/pending-tool-results.d.ts +4 -0
  24. package/dist/pending-tool-results.js +39 -0
  25. package/dist/public/assets/chat-input-BBnVJs9h.js +151 -0
  26. package/dist/public/assets/chat-input-CISJdhF2.css +1 -0
  27. package/dist/public/assets/embed-DhIUBDdf.js +1 -0
  28. package/dist/public/assets/main-Bfvj6DnV.js +16 -0
  29. package/dist/public/embed/widget.js +233 -0
  30. package/dist/public/embed.html +14 -0
  31. package/dist/public/index.html +14 -0
  32. package/dist/scaffold.d.ts +2 -0
  33. package/dist/scaffold.js +82 -0
  34. package/dist/schemas.d.ts +899 -0
  35. package/dist/schemas.js +134 -0
  36. package/dist/server.d.ts +3 -0
  37. package/dist/server.js +258 -0
  38. package/dist/session.d.ts +8 -0
  39. package/dist/session.js +70 -0
  40. package/dist/templates/agent/model.json +6 -0
  41. package/dist/templates/agent/system-prompt.md +9 -0
  42. package/dist/templates/agent/tool-impls/greeting.impl.js +9 -0
  43. package/dist/templates/agent/tools/greeting.json +14 -0
  44. package/dist/templates/workspace/.claude/skills/create-agent/SKILL.md +90 -0
  45. package/dist/templates/workspace/.claude/skills/create-dataset/SKILL.md +57 -0
  46. package/dist/templates/workspace/.claude/skills/create-eval-case/SKILL.md +159 -0
  47. package/dist/templates/workspace/.claude/skills/create-eval-judge/SKILL.md +128 -0
  48. package/dist/templates/workspace/.claude/skills/create-mcp-config/SKILL.md +151 -0
  49. package/dist/templates/workspace/.claude/skills/create-model-config/SKILL.md +45 -0
  50. package/dist/templates/workspace/.claude/skills/create-skill/SKILL.md +63 -0
  51. package/dist/templates/workspace/.claude/skills/create-system-prompt/SKILL.md +168 -0
  52. package/dist/templates/workspace/.claude/skills/create-tool/SKILL.md +56 -0
  53. package/dist/templates/workspace/.claude/skills/create-tool-impl/SKILL.md +83 -0
  54. package/dist/templates/workspace/.claude/skills/create-tool-test/SKILL.md +117 -0
  55. package/dist/templates/workspace/.claude/skills/create-tool-ui/SKILL.md +218 -0
  56. package/dist/test-runner.d.ts +22 -0
  57. package/dist/test-runner.js +166 -0
  58. package/dist/types.d.ts +75 -0
  59. package/dist/types.js +1 -0
  60. package/dist/validator/index.d.ts +16 -0
  61. package/dist/validator/index.js +54 -0
  62. package/dist/validator/plugin.d.ts +21 -0
  63. package/dist/validator/plugin.js +1 -0
  64. package/dist/validator/plugins/agent-dir.d.ts +2 -0
  65. package/dist/validator/plugins/agent-dir.js +171 -0
  66. package/dist/validator/plugins/agent-skill.d.ts +2 -0
  67. package/dist/validator/plugins/agent-skill.js +31 -0
  68. package/dist/validator/plugins/dataset.d.ts +2 -0
  69. package/dist/validator/plugins/dataset.js +20 -0
  70. package/dist/validator/plugins/mcp.d.ts +2 -0
  71. package/dist/validator/plugins/mcp.js +20 -0
  72. package/dist/validator/plugins/model.d.ts +2 -0
  73. package/dist/validator/plugins/model.js +20 -0
  74. package/dist/validator/plugins/system-prompt.d.ts +2 -0
  75. package/dist/validator/plugins/system-prompt.js +25 -0
  76. package/dist/validator/plugins/tool.d.ts +2 -0
  77. package/dist/validator/plugins/tool.js +20 -0
  78. package/dist/validator/zod-utils.d.ts +3 -0
  79. package/dist/validator/zod-utils.js +7 -0
  80. package/package.json +41 -0
@@ -0,0 +1,166 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ async function loadImpl(implPath) {
5
+ const mod = await import(pathToFileURL(implPath).href);
6
+ return mod.default;
7
+ }
8
+ async function loadTestCases(testPath) {
9
+ const mod = await import(pathToFileURL(testPath).href);
10
+ return mod.default;
11
+ }
12
+ function deepEqual(a, b) {
13
+ if (a === b)
14
+ return true;
15
+ if (a == null || b == null)
16
+ return false;
17
+ if (typeof a !== typeof b)
18
+ return false;
19
+ if (typeof a !== "object")
20
+ return false;
21
+ const aObj = a;
22
+ const bObj = b;
23
+ const keys = new Set([...Object.keys(aObj), ...Object.keys(bObj)]);
24
+ for (const key of keys) {
25
+ if (!deepEqual(aObj[key], bObj[key]))
26
+ return false;
27
+ }
28
+ return true;
29
+ }
30
+ async function runTestCase(impl, tc) {
31
+ try {
32
+ const actual = await impl(tc.args);
33
+ // Use validate() if provided
34
+ if (tc.validate) {
35
+ const verdict = tc.validate(actual);
36
+ if (verdict === true) {
37
+ return { name: tc.name, passed: true, actual };
38
+ }
39
+ const msg = typeof verdict === "string" ? verdict : "validate() returned false";
40
+ return { name: tc.name, passed: false, error: msg, actual };
41
+ }
42
+ // Use expected if provided
43
+ if (tc.expected !== undefined) {
44
+ if (deepEqual(actual, tc.expected)) {
45
+ return { name: tc.name, passed: true, actual };
46
+ }
47
+ return {
48
+ name: tc.name,
49
+ passed: false,
50
+ error: `expected ${JSON.stringify(tc.expected)}, got ${JSON.stringify(actual)}`,
51
+ actual,
52
+ };
53
+ }
54
+ // No assertion — just verify it doesn't throw
55
+ return { name: tc.name, passed: true, actual };
56
+ }
57
+ catch (err) {
58
+ return {
59
+ name: tc.name,
60
+ passed: false,
61
+ error: err instanceof Error ? err.message : String(err),
62
+ };
63
+ }
64
+ }
65
+ export async function runToolTests(agentDir) {
66
+ const absDir = path.resolve(agentDir);
67
+ const testsDir = path.join(absDir, "tests");
68
+ const implsDir = path.join(absDir, "tool-impls");
69
+ let files;
70
+ try {
71
+ files = await fs.readdir(testsDir);
72
+ }
73
+ catch {
74
+ return [];
75
+ }
76
+ const testFiles = files.filter((f) => f.endsWith(".test.js"));
77
+ if (testFiles.length === 0) {
78
+ return [];
79
+ }
80
+ const results = [];
81
+ for (const testFile of testFiles) {
82
+ const toolName = testFile.replace(/\.test\.js$/, "");
83
+ const implFile = path.join(implsDir, `${toolName}.impl.js`);
84
+ const testPath = path.join(testsDir, testFile);
85
+ // Check impl exists
86
+ try {
87
+ await fs.access(implFile);
88
+ }
89
+ catch {
90
+ results.push({
91
+ tool: toolName,
92
+ file: testFile,
93
+ results: [
94
+ { name: "(load)", passed: false, error: `Missing implementation: ${toolName}.impl.js` },
95
+ ],
96
+ });
97
+ continue;
98
+ }
99
+ // Load impl and test cases
100
+ let impl;
101
+ let testCases;
102
+ try {
103
+ impl = await loadImpl(implFile);
104
+ }
105
+ catch (err) {
106
+ results.push({
107
+ tool: toolName,
108
+ file: testFile,
109
+ results: [
110
+ {
111
+ name: "(load)",
112
+ passed: false,
113
+ error: `Failed to load ${toolName}.impl.js: ${err instanceof Error ? err.message : err}`,
114
+ },
115
+ ],
116
+ });
117
+ continue;
118
+ }
119
+ try {
120
+ testCases = await loadTestCases(testPath);
121
+ }
122
+ catch (err) {
123
+ results.push({
124
+ tool: toolName,
125
+ file: testFile,
126
+ results: [
127
+ {
128
+ name: "(load)",
129
+ passed: false,
130
+ error: `Failed to load ${testFile}: ${err instanceof Error ? err.message : err}`,
131
+ },
132
+ ],
133
+ });
134
+ continue;
135
+ }
136
+ // Run each case
137
+ const caseResults = [];
138
+ for (const tc of testCases) {
139
+ caseResults.push(await runTestCase(impl, tc));
140
+ }
141
+ results.push({ tool: toolName, file: testFile, results: caseResults });
142
+ }
143
+ return results;
144
+ }
145
+ export function formatResults(results) {
146
+ const lines = [];
147
+ let totalPass = 0;
148
+ let totalFail = 0;
149
+ for (const tool of results) {
150
+ lines.push(`\n ${tool.tool} (${tool.file})`);
151
+ for (const r of tool.results) {
152
+ if (r.passed) {
153
+ totalPass++;
154
+ lines.push(` ✓ ${r.name}`);
155
+ }
156
+ else {
157
+ totalFail++;
158
+ lines.push(` ✗ ${r.name}`);
159
+ lines.push(` ${r.error}`);
160
+ }
161
+ }
162
+ }
163
+ lines.push("");
164
+ lines.push(` ${totalPass + totalFail} tests, ${totalPass} passed, ${totalFail} failed`);
165
+ return lines.join("\n");
166
+ }
@@ -0,0 +1,75 @@
1
+ export type { JSONSchemaProperty, JSONSchema, ToolSchema, ModelConfig, } from "./schemas.js";
2
+ /** Tool implementation function */
3
+ export type ToolImplFn = (args: Record<string, unknown>) => Promise<unknown>;
4
+ /** Loaded agent configuration */
5
+ export interface AgentConfig {
6
+ systemPrompt: string;
7
+ model: import("./schemas.js").ModelConfig;
8
+ tools: import("./schemas.js").ToolSchema[];
9
+ toolImpls: Map<string, ToolImplFn>;
10
+ skills: Record<string, string>;
11
+ mcpManager?: import("./mcp-manager.js").McpManager;
12
+ agentDir: string;
13
+ toolUIs: Set<string>;
14
+ }
15
+ /** OpenAI-compatible chat message */
16
+ export type ChatMessage = {
17
+ role: "system";
18
+ content: string;
19
+ } | {
20
+ role: "user";
21
+ content: string;
22
+ } | {
23
+ role: "assistant";
24
+ content: string | null;
25
+ tool_calls?: ToolCall[];
26
+ } | {
27
+ role: "tool";
28
+ tool_call_id: string;
29
+ content: string;
30
+ };
31
+ /** Tool call from assistant response */
32
+ export interface ToolCall {
33
+ id: string;
34
+ type: "function";
35
+ function: {
36
+ name: string;
37
+ arguments: string;
38
+ };
39
+ }
40
+ /** SSE event pushed to client */
41
+ export type SSEEvent = {
42
+ type: "text";
43
+ content: string;
44
+ } | {
45
+ type: "tool_call";
46
+ name: string;
47
+ args: Record<string, unknown>;
48
+ toolCallId: string;
49
+ executionTarget?: "client" | "host";
50
+ } | {
51
+ type: "tool_result";
52
+ name: string;
53
+ result: unknown;
54
+ toolCallId: string;
55
+ } | {
56
+ type: "tools_config";
57
+ tools: Array<{
58
+ name: string;
59
+ handler?: string;
60
+ executionTarget: string;
61
+ component?: string;
62
+ }>;
63
+ } | {
64
+ type: "done";
65
+ sessionId: string;
66
+ } | {
67
+ type: "error";
68
+ message: string;
69
+ };
70
+ /** Chat session state */
71
+ export interface Session {
72
+ id: string;
73
+ messages: ChatMessage[];
74
+ createdAt: number;
75
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { ValidatorPlugin, DirValidatorPlugin, ValidationResult } from "./plugin.js";
2
+ export type { ValidatorPlugin, DirValidatorPlugin, ValidationResult } from "./plugin.js";
3
+ /** Get a content validator plugin by name */
4
+ export declare function getPlugin(name: string): ValidatorPlugin | undefined;
5
+ /** Get all registered content plugins */
6
+ export declare function getPlugins(): ValidatorPlugin[];
7
+ /** Get a directory validator plugin by name */
8
+ export declare function getDirPlugin(name: string): DirValidatorPlugin | undefined;
9
+ /** Register a custom content plugin */
10
+ export declare function registerPlugin(plugin: ValidatorPlugin): void;
11
+ /** Register a custom directory plugin */
12
+ export declare function registerDirPlugin(plugin: DirValidatorPlugin): void;
13
+ /** Validate content using a specific plugin by name */
14
+ export declare function validate(pluginName: string, content: string, fileName?: string): ValidationResult;
15
+ /** Validate a directory using a specific dir plugin by name */
16
+ export declare function validateDir(pluginName: string, dirPath: string): Promise<ValidationResult>;
@@ -0,0 +1,54 @@
1
+ import { toolPlugin } from "./plugins/tool.js";
2
+ import { modelPlugin } from "./plugins/model.js";
3
+ import { systemPromptPlugin } from "./plugins/system-prompt.js";
4
+ import { agentSkillPlugin } from "./plugins/agent-skill.js";
5
+ import { datasetPlugin } from "./plugins/dataset.js";
6
+ import { mcpPlugin } from "./plugins/mcp.js";
7
+ import { agentDirPlugin } from "./plugins/agent-dir.js";
8
+ const contentPlugins = [
9
+ toolPlugin,
10
+ modelPlugin,
11
+ systemPromptPlugin,
12
+ agentSkillPlugin,
13
+ datasetPlugin,
14
+ mcpPlugin,
15
+ ];
16
+ const dirPlugins = [
17
+ agentDirPlugin,
18
+ ];
19
+ /** Get a content validator plugin by name */
20
+ export function getPlugin(name) {
21
+ return contentPlugins.find((p) => p.name === name);
22
+ }
23
+ /** Get all registered content plugins */
24
+ export function getPlugins() {
25
+ return [...contentPlugins];
26
+ }
27
+ /** Get a directory validator plugin by name */
28
+ export function getDirPlugin(name) {
29
+ return dirPlugins.find((p) => p.name === name);
30
+ }
31
+ /** Register a custom content plugin */
32
+ export function registerPlugin(plugin) {
33
+ contentPlugins.push(plugin);
34
+ }
35
+ /** Register a custom directory plugin */
36
+ export function registerDirPlugin(plugin) {
37
+ dirPlugins.push(plugin);
38
+ }
39
+ /** Validate content using a specific plugin by name */
40
+ export function validate(pluginName, content, fileName) {
41
+ const plugin = getPlugin(pluginName);
42
+ if (!plugin) {
43
+ return { valid: false, errors: [`Unknown validator plugin: ${pluginName}`] };
44
+ }
45
+ return plugin.validate(content, fileName);
46
+ }
47
+ /** Validate a directory using a specific dir plugin by name */
48
+ export async function validateDir(pluginName, dirPath) {
49
+ const plugin = getDirPlugin(pluginName);
50
+ if (!plugin) {
51
+ return { valid: false, errors: [`Unknown dir validator plugin: ${pluginName}`] };
52
+ }
53
+ return plugin.validate(dirPath);
54
+ }
@@ -0,0 +1,21 @@
1
+ /** Validation result */
2
+ export interface ValidationResult {
3
+ valid: boolean;
4
+ errors: string[];
5
+ }
6
+ /** Content validator plugin - validates file content */
7
+ export interface ValidatorPlugin {
8
+ /** Plugin name */
9
+ name: string;
10
+ /** File pattern this plugin handles, e.g. "*.json", "*.md" */
11
+ pattern: string;
12
+ /** Validate raw content, return result */
13
+ validate(content: string, fileName?: string): ValidationResult;
14
+ }
15
+ /** Directory validator plugin - validates directory structure */
16
+ export interface DirValidatorPlugin {
17
+ /** Plugin name */
18
+ name: string;
19
+ /** Validate a directory path, return result */
20
+ validate(dirPath: string): Promise<ValidationResult>;
21
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { DirValidatorPlugin } from "../plugin.js";
2
+ export declare const agentDirPlugin: DirValidatorPlugin;
@@ -0,0 +1,171 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { modelPlugin } from "./model.js";
4
+ import { systemPromptPlugin } from "./system-prompt.js";
5
+ import { toolPlugin } from "./tool.js";
6
+ import { agentSkillPlugin } from "./agent-skill.js";
7
+ import { datasetPlugin } from "./dataset.js";
8
+ import { mcpPlugin } from "./mcp.js";
9
+ export const agentDirPlugin = {
10
+ name: "agent-dir",
11
+ async validate(dirPath) {
12
+ const errors = [];
13
+ // Check directory exists
14
+ try {
15
+ const stat = await fs.stat(dirPath);
16
+ if (!stat.isDirectory()) {
17
+ return { valid: false, errors: [`${dirPath} is not a directory`] };
18
+ }
19
+ }
20
+ catch {
21
+ return { valid: false, errors: [`${dirPath} does not exist`] };
22
+ }
23
+ // Check system-prompt.md
24
+ const promptPath = path.join(dirPath, "system-prompt.md");
25
+ try {
26
+ const content = await fs.readFile(promptPath, "utf-8");
27
+ const result = systemPromptPlugin.validate(content, "system-prompt.md");
28
+ if (!result.valid) {
29
+ errors.push(...result.errors.map((e) => `[system-prompt.md] ${e}`));
30
+ }
31
+ }
32
+ catch {
33
+ errors.push("Missing required file: system-prompt.md");
34
+ }
35
+ // Check model.json
36
+ const modelPath = path.join(dirPath, "model.json");
37
+ try {
38
+ const content = await fs.readFile(modelPath, "utf-8");
39
+ const result = modelPlugin.validate(content, "model.json");
40
+ if (!result.valid) {
41
+ errors.push(...result.errors.map((e) => `[model.json] ${e}`));
42
+ }
43
+ }
44
+ catch {
45
+ errors.push("Missing required file: model.json");
46
+ }
47
+ // Check tools/ directory
48
+ const toolsDir = path.join(dirPath, "tools");
49
+ try {
50
+ const stat = await fs.stat(toolsDir);
51
+ if (!stat.isDirectory()) {
52
+ errors.push("tools is not a directory");
53
+ }
54
+ else {
55
+ const files = await fs.readdir(toolsDir);
56
+ const jsonFiles = files.filter((f) => f.endsWith(".json"));
57
+ if (jsonFiles.length === 0) {
58
+ errors.push("[tools/] No tool definitions found");
59
+ }
60
+ const toolNames = [];
61
+ const nonServerToolNames = new Set();
62
+ for (const file of jsonFiles) {
63
+ const content = await fs.readFile(path.join(toolsDir, file), "utf-8");
64
+ const result = toolPlugin.validate(content, file);
65
+ if (!result.valid) {
66
+ errors.push(...result.errors.map((e) => `[tools/${file}] ${e}`));
67
+ }
68
+ else {
69
+ const name = file.replace(/\.json$/, "");
70
+ toolNames.push(name);
71
+ // Check if tool has execution_target that doesn't need server impl
72
+ try {
73
+ const parsed = JSON.parse(content);
74
+ if (parsed.execution_target === "client" || parsed.execution_target === "host") {
75
+ nonServerToolNames.add(name);
76
+ }
77
+ }
78
+ catch { /* already validated above */ }
79
+ }
80
+ }
81
+ // Server tools that need impl files
82
+ const serverToolNames = toolNames.filter((n) => !nonServerToolNames.has(n));
83
+ // Check tool-impls/ matches server tools
84
+ const implsDir = path.join(dirPath, "tool-impls");
85
+ try {
86
+ const implStat = await fs.stat(implsDir);
87
+ if (implStat.isDirectory()) {
88
+ const implFiles = await fs.readdir(implsDir);
89
+ const implNames = implFiles
90
+ .filter((f) => f.endsWith(".impl.js"))
91
+ .map((f) => f.replace(/\.impl\.js$/, ""));
92
+ // server tools without impl
93
+ for (const name of serverToolNames) {
94
+ if (!implNames.includes(name)) {
95
+ errors.push(`[tool-impls/] Missing implementation for tool: ${name}`);
96
+ }
97
+ }
98
+ // impls without tool
99
+ for (const name of implNames) {
100
+ if (!toolNames.includes(name)) {
101
+ errors.push(`[tool-impls/${name}.impl.js] No matching tool schema in tools/`);
102
+ }
103
+ }
104
+ }
105
+ else {
106
+ errors.push("tool-impls is not a directory");
107
+ }
108
+ }
109
+ catch {
110
+ if (serverToolNames.length > 0) {
111
+ errors.push("Missing required directory: tool-impls/");
112
+ }
113
+ }
114
+ }
115
+ }
116
+ catch {
117
+ errors.push("Missing required directory: tools/");
118
+ }
119
+ // Check datasets/ directory (optional)
120
+ const datasetsDir = path.join(dirPath, "datasets");
121
+ try {
122
+ const stat = await fs.stat(datasetsDir);
123
+ if (stat.isDirectory()) {
124
+ const files = await fs.readdir(datasetsDir);
125
+ const jsonFiles = files.filter((f) => f.endsWith(".json"));
126
+ for (const file of jsonFiles) {
127
+ const content = await fs.readFile(path.join(datasetsDir, file), "utf-8");
128
+ const result = datasetPlugin.validate(content, file);
129
+ if (!result.valid) {
130
+ errors.push(...result.errors.map((e) => `[datasets/${file}] ${e}`));
131
+ }
132
+ }
133
+ }
134
+ }
135
+ catch {
136
+ // datasets/ is optional, skip if not exists
137
+ }
138
+ // Check skills/ directory (optional)
139
+ const skillsDir = path.join(dirPath, "skills");
140
+ try {
141
+ const stat = await fs.stat(skillsDir);
142
+ if (stat.isDirectory()) {
143
+ const files = await fs.readdir(skillsDir);
144
+ const mdFiles = files.filter((f) => f.endsWith(".md"));
145
+ for (const file of mdFiles) {
146
+ const content = await fs.readFile(path.join(skillsDir, file), "utf-8");
147
+ const result = agentSkillPlugin.validate(content, file);
148
+ if (!result.valid) {
149
+ errors.push(...result.errors.map((e) => `[skills/${file}] ${e}`));
150
+ }
151
+ }
152
+ }
153
+ }
154
+ catch {
155
+ // skills/ is optional, skip if not exists
156
+ }
157
+ // Check mcp.json (optional)
158
+ const mcpPath = path.join(dirPath, "mcp.json");
159
+ try {
160
+ const content = await fs.readFile(mcpPath, "utf-8");
161
+ const result = mcpPlugin.validate(content, "mcp.json");
162
+ if (!result.valid) {
163
+ errors.push(...result.errors.map((e) => `[mcp.json] ${e}`));
164
+ }
165
+ }
166
+ catch {
167
+ // mcp.json is optional, skip if not exists
168
+ }
169
+ return { valid: errors.length === 0, errors };
170
+ },
171
+ };
@@ -0,0 +1,2 @@
1
+ import type { ValidatorPlugin } from "../plugin.js";
2
+ export declare const agentSkillPlugin: ValidatorPlugin;
@@ -0,0 +1,31 @@
1
+ import matter from "gray-matter";
2
+ import { agentSkillFrontmatterSchema } from "../../schemas.js";
3
+ import { formatZodErrors } from "../zod-utils.js";
4
+ export const agentSkillPlugin = {
5
+ name: "agent-skill",
6
+ pattern: "skills/*.md",
7
+ validate(content, _fileName) {
8
+ const errors = [];
9
+ let parsed;
10
+ try {
11
+ parsed = matter(content);
12
+ }
13
+ catch {
14
+ return { valid: false, errors: ["Invalid frontmatter syntax"] };
15
+ }
16
+ if (!parsed.data || Object.keys(parsed.data).length === 0) {
17
+ errors.push("Missing frontmatter (---) block");
18
+ }
19
+ else {
20
+ const result = agentSkillFrontmatterSchema.safeParse(parsed.data);
21
+ if (!result.success) {
22
+ const schemaErrors = formatZodErrors(result.error).map((e) => `frontmatter${e}`);
23
+ errors.push(...schemaErrors);
24
+ }
25
+ }
26
+ if (!parsed.content.trim()) {
27
+ errors.push("Skill body content is empty");
28
+ }
29
+ return { valid: errors.length === 0, errors };
30
+ },
31
+ };
@@ -0,0 +1,2 @@
1
+ import type { ValidatorPlugin } from "../plugin.js";
2
+ export declare const datasetPlugin: ValidatorPlugin;
@@ -0,0 +1,20 @@
1
+ import { datasetSchema } from "../../schemas.js";
2
+ import { formatZodErrors } from "../zod-utils.js";
3
+ export const datasetPlugin = {
4
+ name: "dataset",
5
+ pattern: "datasets/*.json",
6
+ validate(content, _fileName) {
7
+ let data;
8
+ try {
9
+ data = JSON.parse(content);
10
+ }
11
+ catch {
12
+ return { valid: false, errors: ["Invalid JSON"] };
13
+ }
14
+ const result = datasetSchema.safeParse(data);
15
+ if (!result.success) {
16
+ return { valid: false, errors: formatZodErrors(result.error) };
17
+ }
18
+ return { valid: true, errors: [] };
19
+ },
20
+ };
@@ -0,0 +1,2 @@
1
+ import type { ValidatorPlugin } from "../plugin.js";
2
+ export declare const mcpPlugin: ValidatorPlugin;
@@ -0,0 +1,20 @@
1
+ import { mcpConfigSchema } from "../../schemas.js";
2
+ import { formatZodErrors } from "../zod-utils.js";
3
+ export const mcpPlugin = {
4
+ name: "mcp",
5
+ pattern: "mcp.json",
6
+ validate(content, _fileName) {
7
+ let data;
8
+ try {
9
+ data = JSON.parse(content);
10
+ }
11
+ catch {
12
+ return { valid: false, errors: ["Invalid JSON"] };
13
+ }
14
+ const result = mcpConfigSchema.safeParse(data);
15
+ if (!result.success) {
16
+ return { valid: false, errors: formatZodErrors(result.error) };
17
+ }
18
+ return { valid: true, errors: [] };
19
+ },
20
+ };
@@ -0,0 +1,2 @@
1
+ import type { ValidatorPlugin } from "../plugin.js";
2
+ export declare const modelPlugin: ValidatorPlugin;
@@ -0,0 +1,20 @@
1
+ import { modelConfigSchema } from "../../schemas.js";
2
+ import { formatZodErrors } from "../zod-utils.js";
3
+ export const modelPlugin = {
4
+ name: "model",
5
+ pattern: "model.json",
6
+ validate(content, _fileName) {
7
+ let data;
8
+ try {
9
+ data = JSON.parse(content);
10
+ }
11
+ catch {
12
+ return { valid: false, errors: ["Invalid JSON"] };
13
+ }
14
+ const result = modelConfigSchema.safeParse(data);
15
+ if (!result.success) {
16
+ return { valid: false, errors: formatZodErrors(result.error) };
17
+ }
18
+ return { valid: true, errors: [] };
19
+ },
20
+ };
@@ -0,0 +1,2 @@
1
+ import type { ValidatorPlugin } from "../plugin.js";
2
+ export declare const systemPromptPlugin: ValidatorPlugin;
@@ -0,0 +1,25 @@
1
+ import { Liquid } from "liquidjs";
2
+ const liquid = new Liquid({ strictVariables: false, strictFilters: true });
3
+ export const systemPromptPlugin = {
4
+ name: "system-prompt",
5
+ pattern: "system-prompt.md",
6
+ validate(content, _fileName) {
7
+ const errors = [];
8
+ if (!content.trim()) {
9
+ errors.push("System prompt content is empty");
10
+ return { valid: false, errors };
11
+ }
12
+ // Validate Liquid template syntax if template tags are present
13
+ const hasLiquid = /\{[%{]/.test(content);
14
+ if (hasLiquid) {
15
+ try {
16
+ liquid.parse(content);
17
+ }
18
+ catch (e) {
19
+ const msg = e instanceof Error ? e.message : String(e);
20
+ errors.push(`Liquid template syntax error: ${msg}`);
21
+ }
22
+ }
23
+ return { valid: errors.length === 0, errors };
24
+ },
25
+ };
@@ -0,0 +1,2 @@
1
+ import type { ValidatorPlugin } from "../plugin.js";
2
+ export declare const toolPlugin: ValidatorPlugin;