-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathtool.zod.ts
More file actions
153 lines (132 loc) · 5.67 KB
/
Copy pathtool.zod.ts
File metadata and controls
153 lines (132 loc) · 5.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
import { z } from 'zod';
import { ProtectionSchema } from '../shared/protection.zod';
import { MetadataProtectionFields } from '../kernel/metadata-protection.zod';
// ==========================================
// Tool Category
// ==========================================
/**
* Tool Category
* Classifies the tool by its operational domain.
*/
import { lazySchema } from '../shared/lazy-schema';
export const ToolCategorySchema = lazySchema(() => z.enum([
'data', // CRUD / query operations
'action', // Side-effect actions (send email, create record)
'flow', // Trigger a visual flow
'integration', // External API / webhook calls
'vector_search', // RAG / vector search
'analytics', // Aggregation & reporting
'utility', // Formatters, parsers, helpers
]).describe('Tool operational category'));
export type ToolCategory = z.infer<typeof ToolCategorySchema>;
// ==========================================
// Tool Schema
// ==========================================
/**
* Tool Schema
*
* First-class metadata definition for an AI-callable tool.
* Tools are the atomic units of AI capability — each tool
* represents a single, well-defined operation with strict
* parameter validation via JSON Schema.
*
* Aligned with Salesforce Agentforce, Microsoft Copilot Studio,
* and ServiceNow Now Assist metadata patterns.
*
* @example
* ```ts
* const tool = defineTool({
* name: 'create_case',
* label: 'Create Support Case',
* description: 'Creates a new support case record',
* category: 'action',
* parameters: {
* type: 'object',
* properties: {
* subject: { type: 'string', description: 'Case subject' },
* priority: { type: 'string', enum: ['low', 'medium', 'high'] },
* },
* required: ['subject'],
* },
* objectName: 'support_case',
* requiresConfirmation: true,
* });
* ```
*/
export const ToolSchema = lazySchema(() => z.object({
/** Machine name (snake_case, globally unique) */
name: z.string().regex(/^[a-z_][a-z0-9_]*$/).describe('Tool unique identifier (snake_case)'),
/** Human-readable display name */
label: z.string().describe('Tool display name'),
/** Detailed description for LLM consumption (the model reads this to decide when to call the tool) */
description: z.string().describe('Tool description for LLM function calling'),
/** Operational category */
category: ToolCategorySchema.optional().describe('Tool category for grouping and filtering'),
/**
* JSON Schema describing the tool input parameters.
* Must be a valid JSON Schema object. The AI model generates
* arguments conforming to this schema.
*/
parameters: z.record(z.string(), z.unknown()).describe('JSON Schema for tool parameters'),
/**
* Optional JSON Schema for the tool output.
* Used for structured output validation and downstream tool chaining.
*/
outputSchema: z.record(z.string(), z.unknown()).optional().describe('JSON Schema for tool output'),
/**
* Associated object name (when the tool operates on a specific data object).
* @example 'support_case'
*/
objectName: z.string().regex(/^[a-z_][a-z0-9_]*$/).optional().describe('Target object name (snake_case)'),
/** Whether the tool requires human confirmation before execution */
requiresConfirmation: z.boolean().default(false).describe('Require user confirmation before execution'),
/** Permission-set capabilities required to use this tool */
permissions: z.array(z.string()).optional().describe('Required permission-set capabilities'),
/** Whether the tool is enabled */
active: z.boolean().default(true).describe('Whether the tool is enabled'),
/** Whether this is a platform built-in tool (vs. user-defined) */
builtIn: z.boolean().default(false).describe('Platform built-in tool flag'),
/**
* ADR-0010 §3.7 — Package-level protection envelope. Package
* authors declare lock policy here; the loader translates it
* into the private `_lock` envelope at registration time and
* strips this block before persistence. See
* `shared/protection.zod.ts`.
*/
protection: ProtectionSchema.optional().describe(
'Package author protection block — lock policy for this tool.',
),
// ADR-0010 — runtime protection envelope (internal — set by loader).
...MetadataProtectionFields,
}).describe('AI tool definition. [READ-ONLY PROJECTION — not an execution entry point] Authoring a tool as metadata does NOT make it runnable: this schema has no `implementation`/`handler` field and no framework executor loads a metadata-authored tool. The runtime executes a separately-registered `AIToolDefinition` (cloud `@objectstack/service-ai`); tool metadata is a one-way projection for Studio/discovery. Do not expect a hand-authored tool to run in the open edition (liveness audit #1878/#1892).'));
export type Tool = z.infer<typeof ToolSchema>;
// ==========================================
// Factory
// ==========================================
/**
* Type-safe factory for creating AI tool metadata definitions.
*
* Validates the config at creation time using Zod `.parse()`.
*
* @example
* ```ts
* const tool = defineTool({
* name: 'query_orders',
* label: 'Query Orders',
* description: 'Search and filter customer orders',
* category: 'data',
* parameters: {
* type: 'object',
* properties: {
* customerId: { type: 'string' },
* status: { type: 'string', enum: ['pending', 'shipped', 'delivered'] },
* },
* required: ['customerId'],
* },
* });
* ```
*/
export function defineTool(config: z.input<typeof ToolSchema>): Tool {
return ToolSchema.parse(config);
}