@feilunxitong/arkit 0.1.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.
@@ -0,0 +1,508 @@
1
+ "use strict";
2
+ /**
3
+ * SchemaHub — Community Schema Registry
4
+ * v0.4.0: Community-driven schema ecosystem for agent tool validation.
5
+ *
6
+ * Philosophy:
7
+ * 1. Low friction — one TypeScript interface = one schema
8
+ * 2. Offline/online — local cache + remote hub
9
+ * 3. Versioned — semantic versions for every schema
10
+ * 4. Discoverable — search by category, tags, author
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.SchemaHub = exports.BUILTIN_META = exports.BUILTIN_SCHEMAS = exports.CATEGORIES = void 0;
47
+ exports.validateSchema = validateSchema;
48
+ const fs = __importStar(require("node:fs"));
49
+ const path = __importStar(require("node:path"));
50
+ // ─── Categories ───
51
+ exports.CATEGORIES = [
52
+ 'payment',
53
+ 'email',
54
+ 'github',
55
+ 'database',
56
+ 'http',
57
+ 'file',
58
+ 'messaging',
59
+ 'project',
60
+ 'ai',
61
+ 'security',
62
+ 'general',
63
+ ];
64
+ function validateField(field, value, rules) {
65
+ if (rules.required && (value === undefined || value === null)) {
66
+ return { field, message: `${field} is required` };
67
+ }
68
+ if (value === undefined || value === null)
69
+ return null;
70
+ if (typeof rules.type === 'string') {
71
+ const expectedType = rules.type;
72
+ if (expectedType === 'string' && typeof value !== 'string') {
73
+ return { field, message: `${field} must be a string` };
74
+ }
75
+ if (expectedType === 'number' && typeof value !== 'number') {
76
+ return { field, message: `${field} must be a number` };
77
+ }
78
+ if (expectedType === 'boolean' && typeof value !== 'boolean') {
79
+ return { field, message: `${field} must be a boolean` };
80
+ }
81
+ if (expectedType === 'array' && !Array.isArray(value)) {
82
+ return { field, message: `${field} must be an array` };
83
+ }
84
+ if (expectedType === 'object' && (typeof value !== 'object' || value === null || Array.isArray(value))) {
85
+ return { field, message: `${field} must be an object` };
86
+ }
87
+ }
88
+ if (rules.pattern && typeof value === 'string') {
89
+ const regex = new RegExp(rules.pattern);
90
+ if (!regex.test(value)) {
91
+ return { field, message: `${field} must match pattern ${rules.pattern}` };
92
+ }
93
+ }
94
+ if (typeof rules.minLength === 'number' && typeof value === 'string' && value.length < rules.minLength) {
95
+ return { field, message: `${field} must be at least ${rules.minLength} characters` };
96
+ }
97
+ if (typeof rules.maxLength === 'number' && typeof value === 'string' && value.length > rules.maxLength) {
98
+ return { field, message: `${field} must be at most ${rules.maxLength} characters` };
99
+ }
100
+ if (typeof rules.gt === 'number' && typeof value === 'number' && value <= rules.gt) {
101
+ return { field, message: `${field} must be greater than ${rules.gt}` };
102
+ }
103
+ if (typeof rules.minItems === 'number' && Array.isArray(value) && value.length < rules.minItems) {
104
+ return { field, message: `${field} must have at least ${rules.minItems} items` };
105
+ }
106
+ if (typeof rules.minLength === 'number' && Array.isArray(value) && value.length < rules.minLength) {
107
+ return { field, message: `${field} must have at least ${rules.minLength} items` };
108
+ }
109
+ return null;
110
+ }
111
+ function validateSchema(schemaName, data) {
112
+ const schemaDef = exports.BUILTIN_SCHEMAS[schemaName];
113
+ if (!schemaDef) {
114
+ return { valid: false, errors: [{ field: '_schema', message: `Unknown schema: ${schemaName}` }] };
115
+ }
116
+ if (data === null || data === undefined) {
117
+ return { valid: false, errors: [{ field: '_root', message: 'Data is null or undefined' }] };
118
+ }
119
+ if (typeof data !== 'object' || Array.isArray(data)) {
120
+ return { valid: false, errors: [{ field: '_root', message: 'Data must be an object' }] };
121
+ }
122
+ const errors = [];
123
+ const record = data;
124
+ for (const [fieldName, rules] of Object.entries(schemaDef.fields)) {
125
+ const error = validateField(fieldName, record[fieldName], rules);
126
+ if (error)
127
+ errors.push(error);
128
+ }
129
+ return { valid: errors.length === 0, errors };
130
+ }
131
+ exports.BUILTIN_SCHEMAS = {};
132
+ function registerBuiltinSchemas() {
133
+ const schemas = {
134
+ // === Payment ===
135
+ 'stripe.charge': {
136
+ fields: {
137
+ amount: { type: 'number', required: true, gt: 0, description: 'Charge amount in cents' },
138
+ currency: { type: 'string', required: false, pattern: '^[a-z]{3}$', default: 'usd' },
139
+ description: { type: 'string', required: false },
140
+ customer: { type: 'string', required: false },
141
+ },
142
+ },
143
+ 'stripe.refund': {
144
+ fields: {
145
+ charge_id: { type: 'string', required: true, minLength: 5 },
146
+ amount: { type: 'number', required: false, gt: 0 },
147
+ reason: { type: 'string', required: false },
148
+ },
149
+ },
150
+ // === Email ===
151
+ 'email.send': {
152
+ fields: {
153
+ to: { type: 'string', required: true, pattern: '^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$' },
154
+ subject: { type: 'string', required: true, minLength: 1, maxLength: 998 },
155
+ body: { type: 'string', required: true, minLength: 1 },
156
+ cc: { type: 'array', required: false },
157
+ },
158
+ },
159
+ 'email.send_bulk': {
160
+ fields: {
161
+ to: { type: 'array', required: true, minLength: 1 },
162
+ subject: { type: 'string', required: true, minLength: 1 },
163
+ body: { type: 'string', required: true, minLength: 1 },
164
+ },
165
+ },
166
+ // === GitHub ===
167
+ 'github.create_issue': {
168
+ fields: {
169
+ owner: { type: 'string', required: true, minLength: 1 },
170
+ repo: { type: 'string', required: true, minLength: 1 },
171
+ title: { type: 'string', required: true, minLength: 1, maxLength: 256 },
172
+ body: { type: 'string', required: false },
173
+ labels: { type: 'array', required: false },
174
+ },
175
+ },
176
+ 'github.create_pr': {
177
+ fields: {
178
+ owner: { type: 'string', required: true, minLength: 1 },
179
+ repo: { type: 'string', required: true, minLength: 1 },
180
+ title: { type: 'string', required: true, minLength: 1 },
181
+ head: { type: 'string', required: true, minLength: 1 },
182
+ base: { type: 'string', required: false, default: 'main' },
183
+ body: { type: 'string', required: false },
184
+ },
185
+ },
186
+ // === Database ===
187
+ 'db.query': {
188
+ fields: {
189
+ query: { type: 'string', required: true, minLength: 1 },
190
+ params: { type: 'object', required: false },
191
+ },
192
+ },
193
+ 'db.insert': {
194
+ fields: {
195
+ table: {
196
+ type: 'string',
197
+ required: true,
198
+ pattern: '^[a-zA-Z_][a-zA-Z0-9_]*$',
199
+ minLength: 1,
200
+ },
201
+ values: { type: 'object', required: true },
202
+ },
203
+ },
204
+ // === HTTP ===
205
+ 'http.request': {
206
+ fields: {
207
+ url: { type: 'string', required: true, pattern: '^https?://' },
208
+ method: {
209
+ type: 'string',
210
+ required: false,
211
+ pattern: '^(GET|POST|PUT|DELETE|PATCH)$',
212
+ default: 'GET',
213
+ },
214
+ headers: { type: 'object', required: false },
215
+ body: { type: 'object', required: false },
216
+ },
217
+ },
218
+ // === File ===
219
+ 'file.read': {
220
+ fields: {
221
+ path: { type: 'string', required: true, minLength: 1 },
222
+ encoding: { type: 'string', required: false, default: 'utf-8' },
223
+ },
224
+ },
225
+ 'file.write': {
226
+ fields: {
227
+ path: { type: 'string', required: true, minLength: 1 },
228
+ content: { type: 'string', required: true },
229
+ mode: { type: 'string', required: false, pattern: '^(w|a|x)$', default: 'w' },
230
+ },
231
+ },
232
+ // === Slack ===
233
+ 'slack.message': {
234
+ fields: {
235
+ channel: { type: 'string', required: true, minLength: 1 },
236
+ text: { type: 'string', required: true, minLength: 1 },
237
+ thread_ts: { type: 'string', required: false },
238
+ },
239
+ },
240
+ // === Jira ===
241
+ 'jira.create_ticket': {
242
+ fields: {
243
+ project: { type: 'string', required: true, minLength: 1, maxLength: 10 },
244
+ summary: { type: 'string', required: true, minLength: 1 },
245
+ description: { type: 'string', required: false },
246
+ issue_type: {
247
+ type: 'string',
248
+ required: false,
249
+ pattern: '^(Bug|Task|Story|Epic)$',
250
+ default: 'Bug',
251
+ },
252
+ priority: {
253
+ type: 'string',
254
+ required: false,
255
+ pattern: '^(Highest|High|Medium|Low|Lowest)$',
256
+ default: 'Medium',
257
+ },
258
+ },
259
+ },
260
+ };
261
+ Object.assign(exports.BUILTIN_SCHEMAS, schemas);
262
+ }
263
+ registerBuiltinSchemas();
264
+ // ─── Built-in Schema Meta ───
265
+ exports.BUILTIN_META = {
266
+ 'stripe.charge': {
267
+ name: 'stripe.charge', version: '1.0.0', author: 'ark-core',
268
+ category: 'payment', tags: ['stripe', 'charge', 'payment'],
269
+ description: 'Stripe charge request schema', source: 'local', downloads: 0, rating: 0,
270
+ },
271
+ 'stripe.refund': {
272
+ name: 'stripe.refund', version: '1.0.0', author: 'ark-core',
273
+ category: 'payment', tags: ['stripe', 'refund', 'payment'],
274
+ description: 'Stripe refund request schema', source: 'local', downloads: 0, rating: 0,
275
+ },
276
+ 'email.send': {
277
+ name: 'email.send', version: '1.0.0', author: 'ark-core',
278
+ category: 'email', tags: ['email', 'send'],
279
+ description: 'Send single email schema', source: 'local', downloads: 0, rating: 0,
280
+ },
281
+ 'email.send_bulk': {
282
+ name: 'email.send_bulk', version: '1.0.0', author: 'ark-core',
283
+ category: 'email', tags: ['email', 'bulk', 'send'],
284
+ description: 'Send bulk emails schema', source: 'local', downloads: 0, rating: 0,
285
+ },
286
+ 'github.create_issue': {
287
+ name: 'github.create_issue', version: '1.0.0', author: 'ark-core',
288
+ category: 'github', tags: ['github', 'issue'],
289
+ description: 'GitHub create issue schema', source: 'local', downloads: 0, rating: 0,
290
+ },
291
+ 'github.create_pr': {
292
+ name: 'github.create_pr', version: '1.0.0', author: 'ark-core',
293
+ category: 'github', tags: ['github', 'pr', 'pull request'],
294
+ description: 'GitHub create pull request schema', source: 'local', downloads: 0, rating: 0,
295
+ },
296
+ 'db.query': {
297
+ name: 'db.query', version: '1.0.0', author: 'ark-core',
298
+ category: 'database', tags: ['sql', 'query', 'database'],
299
+ description: 'SQL query schema with parameterized params', source: 'local', downloads: 0, rating: 0,
300
+ },
301
+ 'db.insert': {
302
+ name: 'db.insert', version: '1.0.0', author: 'ark-core',
303
+ category: 'database', tags: ['sql', 'insert', 'database'],
304
+ description: 'SQL insert schema with table validation', source: 'local', downloads: 0, rating: 0,
305
+ },
306
+ 'http.request': {
307
+ name: 'http.request', version: '1.0.0', author: 'ark-core',
308
+ category: 'http', tags: ['http', 'api', 'request'],
309
+ description: 'HTTP API request schema', source: 'local', downloads: 0, rating: 0,
310
+ },
311
+ 'file.read': {
312
+ name: 'file.read', version: '1.0.0', author: 'ark-core',
313
+ category: 'file', tags: ['file', 'read'],
314
+ description: 'File read schema', source: 'local', downloads: 0, rating: 0,
315
+ },
316
+ 'file.write': {
317
+ name: 'file.write', version: '1.0.0', author: 'ark-core',
318
+ category: 'file', tags: ['file', 'write'],
319
+ description: 'File write schema', source: 'local', downloads: 0, rating: 0,
320
+ },
321
+ 'slack.message': {
322
+ name: 'slack.message', version: '1.0.0', author: 'ark-core',
323
+ category: 'messaging', tags: ['slack', 'message', 'chat'],
324
+ description: 'Slack message send schema', source: 'local', downloads: 0, rating: 0,
325
+ },
326
+ 'jira.create_ticket': {
327
+ name: 'jira.create_ticket', version: '1.0.0', author: 'ark-core',
328
+ category: 'project', tags: ['jira', 'ticket', 'project'],
329
+ description: 'Jira create ticket schema', source: 'local', downloads: 0, rating: 0,
330
+ },
331
+ };
332
+ // ─── SchemaHub Class ───
333
+ class SchemaHub {
334
+ schemas = new Map();
335
+ metas = new Map();
336
+ constructor(schemasDir) {
337
+ this.registerBuiltins();
338
+ if (schemasDir) {
339
+ this.importDir(schemasDir);
340
+ }
341
+ }
342
+ /** Register a schema definition with optional metadata */
343
+ register(name, schemaDef, meta) {
344
+ this.schemas.set(name, schemaDef);
345
+ this.metas.set(name, {
346
+ name,
347
+ version: '1.0.0',
348
+ author: 'community',
349
+ category: 'general',
350
+ tags: [],
351
+ description: '',
352
+ source: 'local',
353
+ downloads: 0,
354
+ rating: 0,
355
+ ...meta,
356
+ });
357
+ }
358
+ registerBuiltins() {
359
+ for (const [name, schemaDef] of Object.entries(exports.BUILTIN_SCHEMAS)) {
360
+ this.schemas.set(name, schemaDef);
361
+ }
362
+ for (const [name, meta] of Object.entries(exports.BUILTIN_META)) {
363
+ this.metas.set(name, meta);
364
+ }
365
+ }
366
+ // ─── Discovery ───
367
+ get(name) {
368
+ return this.schemas.get(name);
369
+ }
370
+ getMeta(name) {
371
+ return this.metas.get(name);
372
+ }
373
+ get available() {
374
+ return [...this.schemas.keys()].sort();
375
+ }
376
+ get categories() {
377
+ const seen = new Set();
378
+ for (const meta of this.metas.values()) {
379
+ seen.add(meta.category);
380
+ }
381
+ return [...seen].sort();
382
+ }
383
+ search(options) {
384
+ const results = [];
385
+ for (const meta of this.metas.values()) {
386
+ if (options?.query) {
387
+ const q = options.query.toLowerCase();
388
+ if (!meta.name.toLowerCase().includes(q) &&
389
+ !meta.description.toLowerCase().includes(q)) {
390
+ continue;
391
+ }
392
+ }
393
+ if (options?.category && meta.category !== options.category)
394
+ continue;
395
+ if (options?.tags && !options.tags.every((t) => meta.tags.includes(t)))
396
+ continue;
397
+ if (options?.author && meta.author !== options.author)
398
+ continue;
399
+ results.push(meta);
400
+ }
401
+ return results;
402
+ }
403
+ listByCategory() {
404
+ const result = {};
405
+ for (const meta of this.metas.values()) {
406
+ if (!result[meta.category])
407
+ result[meta.category] = [];
408
+ result[meta.category].push(meta);
409
+ }
410
+ return result;
411
+ }
412
+ // ─── Import / Export ───
413
+ importDir(dirPath) {
414
+ const d = path.resolve(dirPath);
415
+ if (!fs.existsSync(d) || !fs.statSync(d).isDirectory())
416
+ return 0;
417
+ let count = 0;
418
+ const files = fs.readdirSync(d).filter((f) => f.endsWith('.json'));
419
+ for (const file of files) {
420
+ try {
421
+ const content = fs.readFileSync(path.join(d, file), 'utf-8');
422
+ const data = JSON.parse(content);
423
+ const fieldsDef = {};
424
+ for (const [fname, finfo] of Object.entries(data.fields ?? {})) {
425
+ const info = finfo;
426
+ const fieldRules = {
427
+ type: info.type ?? 'string',
428
+ required: info.required ?? true,
429
+ description: info.description ?? '',
430
+ };
431
+ fieldsDef[fname] = fieldRules;
432
+ }
433
+ const schemaDef = { fields: fieldsDef };
434
+ this.register(data.name, schemaDef, {
435
+ version: data.version ?? '1.0.0',
436
+ author: data.author ?? 'community',
437
+ category: data.category ?? 'general',
438
+ tags: data.tags ?? [],
439
+ description: data.description ?? '',
440
+ source: 'local',
441
+ });
442
+ count++;
443
+ }
444
+ catch {
445
+ // Skip invalid schema files
446
+ }
447
+ }
448
+ return count;
449
+ }
450
+ exportJSON(filePath) {
451
+ const result = [];
452
+ for (const [name, schemaDef] of this.schemas) {
453
+ const meta = this.metas.get(name);
454
+ result.push({
455
+ name,
456
+ version: meta?.version ?? '1.0.0',
457
+ author: meta?.author ?? 'community',
458
+ category: meta?.category ?? 'general',
459
+ tags: meta?.tags ?? [],
460
+ description: meta?.description ?? '',
461
+ fields: schemaDef.fields,
462
+ });
463
+ }
464
+ fs.writeFileSync(filePath, JSON.stringify(result, null, 2), 'utf-8');
465
+ }
466
+ exportMetaJSON(filePath) {
467
+ const result = [...this.metas.values()].map((m) => ({
468
+ name: m.name,
469
+ version: m.version,
470
+ author: m.author,
471
+ category: m.category,
472
+ tags: m.tags,
473
+ description: m.description,
474
+ source: m.source,
475
+ downloads: m.downloads,
476
+ rating: m.rating,
477
+ }));
478
+ fs.writeFileSync(filePath, JSON.stringify(result, null, 2), 'utf-8');
479
+ }
480
+ // ─── Validation ───
481
+ validate(name, data) {
482
+ return validateSchema(name, data);
483
+ }
484
+ // ─── Stats ───
485
+ get stats() {
486
+ const byCat = this.listByCategory();
487
+ const allTags = new Set();
488
+ for (const meta of this.metas.values()) {
489
+ for (const t of meta.tags)
490
+ allTags.add(t);
491
+ }
492
+ const authors = new Set();
493
+ for (const meta of this.metas.values()) {
494
+ authors.add(meta.author);
495
+ }
496
+ return {
497
+ totalSchemas: this.schemas.size,
498
+ categories: Object.keys(byCat).length,
499
+ byCategory: Object.fromEntries(Object.entries(byCat).map(([k, v]) => [k, v.length])),
500
+ totalTags: allTags.size,
501
+ authors: authors.size,
502
+ };
503
+ }
504
+ toString() {
505
+ return `SchemaHub(schemas=${this.schemas.size}, categories=${this.categories.length})`;
506
+ }
507
+ }
508
+ exports.SchemaHub = SchemaHub;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * SchemaRegistry — 社区驱动的工具Schema库
3
+ * Built-in Zod schemas for common agent tools.
4
+ */
5
+ import { ZodSchema } from 'zod';
6
+ import { OutputValidator } from './validator.js';
7
+ export declare class SchemaRegistry {
8
+ private schemas;
9
+ constructor();
10
+ private registerBuiltins;
11
+ get available(): string[];
12
+ get(name: string): ZodSchema | undefined;
13
+ register(name: string, schema: ZodSchema, description?: string): void;
14
+ validate(name: string, output: unknown, validator?: OutputValidator): import('./validator.js').ValidationResult | null;
15
+ /** Export all schemas as JSON Schema */
16
+ exportAll(): Record<string, unknown>;
17
+ }
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SchemaRegistry = void 0;
4
+ /**
5
+ * SchemaRegistry — 社区驱动的工具Schema库
6
+ * Built-in Zod schemas for common agent tools.
7
+ */
8
+ const zod_1 = require("zod");
9
+ const validator_js_1 = require("./validator.js");
10
+ class SchemaRegistry {
11
+ schemas = new Map();
12
+ constructor() {
13
+ this.registerBuiltins();
14
+ }
15
+ registerBuiltins() {
16
+ const builtins = [
17
+ // Payment
18
+ {
19
+ name: 'stripe.charge',
20
+ description: 'Stripe charge creation',
21
+ schema: zod_1.z.object({
22
+ amount: zod_1.z.number().positive(),
23
+ currency: zod_1.z.string().length(3).default('usd'),
24
+ description: zod_1.z.string().optional(),
25
+ customer: zod_1.z.string().optional(),
26
+ }),
27
+ },
28
+ {
29
+ name: 'stripe.refund',
30
+ description: 'Stripe refund',
31
+ schema: zod_1.z.object({
32
+ chargeId: zod_1.z.string().min(5),
33
+ amount: zod_1.z.number().positive().optional(),
34
+ reason: zod_1.z.string().optional(),
35
+ }),
36
+ },
37
+ // Email
38
+ {
39
+ name: 'email.send',
40
+ description: 'Send an email',
41
+ schema: zod_1.z.object({
42
+ to: zod_1.z.string().email(),
43
+ subject: zod_1.z.string().min(1).max(998),
44
+ body: zod_1.z.string().min(1),
45
+ cc: zod_1.z.array(zod_1.z.string().email()).optional(),
46
+ }),
47
+ },
48
+ // GitHub
49
+ {
50
+ name: 'github.create_issue',
51
+ description: 'Create a GitHub issue',
52
+ schema: zod_1.z.object({
53
+ owner: zod_1.z.string().min(1),
54
+ repo: zod_1.z.string().min(1),
55
+ title: zod_1.z.string().min(1).max(256),
56
+ body: zod_1.z.string().default(''),
57
+ labels: zod_1.z.array(zod_1.z.string()).optional(),
58
+ }),
59
+ },
60
+ // Database
61
+ {
62
+ name: 'db.query',
63
+ description: 'Execute a SQL query',
64
+ schema: zod_1.z.object({
65
+ query: zod_1.z.string().min(1),
66
+ params: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
67
+ }),
68
+ },
69
+ // HTTP
70
+ {
71
+ name: 'http.request',
72
+ description: 'Make an HTTP request',
73
+ schema: zod_1.z.object({
74
+ url: zod_1.z.string().url(),
75
+ method: zod_1.z.string().default('GET'),
76
+ headers: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(),
77
+ body: zod_1.z.unknown().optional(),
78
+ }),
79
+ },
80
+ // Slack
81
+ {
82
+ name: 'slack.message',
83
+ description: 'Send a Slack message',
84
+ schema: zod_1.z.object({
85
+ channel: zod_1.z.string().min(1),
86
+ text: zod_1.z.string().min(1),
87
+ threadTs: zod_1.z.string().optional(),
88
+ }),
89
+ },
90
+ // File
91
+ {
92
+ name: 'file.write',
93
+ description: 'Write to a file',
94
+ schema: zod_1.z.object({
95
+ path: zod_1.z.string().min(1),
96
+ content: zod_1.z.string(),
97
+ mode: zod_1.z.string().default('w'),
98
+ }),
99
+ },
100
+ ];
101
+ for (const entry of builtins) {
102
+ this.schemas.set(entry.name, entry);
103
+ }
104
+ }
105
+ get available() {
106
+ return [...this.schemas.keys()].sort();
107
+ }
108
+ get(name) {
109
+ return this.schemas.get(name)?.schema;
110
+ }
111
+ register(name, schema, description) {
112
+ this.schemas.set(name, { name, schema, description: description || '' });
113
+ }
114
+ validate(name, output, validator) {
115
+ const schema = this.get(name);
116
+ if (!schema)
117
+ return null;
118
+ const v = validator || new validator_js_1.OutputValidator();
119
+ return v.validate(schema, output);
120
+ }
121
+ /** Export all schemas as JSON Schema */
122
+ exportAll() {
123
+ const result = {};
124
+ for (const [name, entry] of this.schemas) {
125
+ result[name] = zodToJsonSchema(entry.schema);
126
+ }
127
+ return result;
128
+ }
129
+ }
130
+ exports.SchemaRegistry = SchemaRegistry;
131
+ /** Minimal Zod → JSON Schema converter */
132
+ function zodToJsonSchema(schema) {
133
+ try {
134
+ // zod v3.23+ has toJsonSchema
135
+ if ('toJsonSchema' in schema && typeof schema.toJsonSchema === 'function') {
136
+ return schema.toJsonSchema();
137
+ }
138
+ }
139
+ catch { }
140
+ // Fallback: return type info
141
+ return { type: 'object', _note: 'Install zod-to-json-schema for full export' };
142
+ }