@agentproto/tool 0.1.1
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/LICENSE +21 -0
- package/README.md +52 -0
- package/dist/chunk-ZFIMSZXN.mjs +245 -0
- package/dist/chunk-ZFIMSZXN.mjs.map +1 -0
- package/dist/index.d.ts +127 -0
- package/dist/index.mjs +55 -0
- package/dist/index.mjs.map +1 -0
- package/dist/manifest/index.d.ts +82 -0
- package/dist/manifest/index.mjs +3 -0
- package/dist/manifest/index.mjs.map +1 -0
- package/dist/types-Ce8BEvMm.d.ts +161 -0
- package/package.json +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jeremy (agentik.net)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# @agentproto/tool
|
|
2
|
+
|
|
3
|
+
Reference implementation of
|
|
4
|
+
[**AIP-14 TOOL.md**](https://agentik.net/docs/aip-14) `defineTool` contract.
|
|
5
|
+
|
|
6
|
+
A vendor-neutral tool registration primitive: an author writes a single
|
|
7
|
+
`defineTool({...})` module + an optional sidecar `TOOL.md` manifest, and any
|
|
8
|
+
framework-specific adapter (`@agentproto/adapter-mastra`, `@agencies/tool-langchain`,
|
|
9
|
+
`@agencies/tool-a2a`, …) can wrap the resulting `ToolHandle` into its native
|
|
10
|
+
tool API.
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { defineTool, ToolError } from "@agentproto/tool"
|
|
14
|
+
import { z } from "zod"
|
|
15
|
+
|
|
16
|
+
export default defineTool({
|
|
17
|
+
id: "echo",
|
|
18
|
+
description: "Returns its input verbatim.",
|
|
19
|
+
inputSchema: z.object({ message: z.string() }),
|
|
20
|
+
outputSchema: z.object({ echo: z.string() }),
|
|
21
|
+
mutates: [],
|
|
22
|
+
approval: "auto",
|
|
23
|
+
execute: async ({ input }) => {
|
|
24
|
+
if (input.message.length > 10_000) {
|
|
25
|
+
throw new ToolError({
|
|
26
|
+
code: "input_invalid",
|
|
27
|
+
message: "message too long",
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
return { echo: input.message }
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The host calls `handle.execute({ input, context })`. The runtime validates
|
|
36
|
+
`input` against `inputSchema` (rejects with
|
|
37
|
+
`ToolError({ code: "input_invalid" })` on shape mismatch) before invoking the
|
|
38
|
+
body, then validates the body's return against `outputSchema`. Errors travel
|
|
39
|
+
out-of-band: success returns the value; failures throw a `ToolError` that
|
|
40
|
+
adapters MUST wrap into the standard `ToolResult<T>` envelope.
|
|
41
|
+
|
|
42
|
+
## Spec
|
|
43
|
+
|
|
44
|
+
See [AIP-14](https://agentik.net/docs/aip-14) for the canonical `defineTool`
|
|
45
|
+
contract and conformance rules. This package is the TypeScript reference
|
|
46
|
+
implementation.
|
|
47
|
+
|
|
48
|
+
## Adapter packages
|
|
49
|
+
|
|
50
|
+
- `@agentproto/adapter-mastra` — `toMastraTool(handle, ctx)` (planned)
|
|
51
|
+
- `@agencies/tool-langchain` — (planned)
|
|
52
|
+
- `@agencies/tool-a2a` — (planned)
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import matter from 'gray-matter';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { createDoctype } from '@agentproto/define-doctype';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @agentproto/tool v0.1.0-alpha
|
|
7
|
+
* AIP-14 TOOL.md `defineTool` reference implementation.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
// src/errors.ts
|
|
12
|
+
var ToolError = class extends Error {
|
|
13
|
+
code;
|
|
14
|
+
retryable;
|
|
15
|
+
cause;
|
|
16
|
+
constructor(payload) {
|
|
17
|
+
super(payload.message);
|
|
18
|
+
this.name = "ToolError";
|
|
19
|
+
this.code = payload.code;
|
|
20
|
+
this.retryable = payload.retryable ?? false;
|
|
21
|
+
this.cause = payload.cause;
|
|
22
|
+
}
|
|
23
|
+
toJSON() {
|
|
24
|
+
return {
|
|
25
|
+
code: this.code,
|
|
26
|
+
message: this.message,
|
|
27
|
+
retryable: this.retryable,
|
|
28
|
+
...this.cause !== void 0 ? { cause: this.cause } : {}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
function toToolError(thrown) {
|
|
33
|
+
if (thrown instanceof ToolError) return thrown;
|
|
34
|
+
if (thrown instanceof Error) {
|
|
35
|
+
return new ToolError({
|
|
36
|
+
code: "internal",
|
|
37
|
+
message: thrown.message,
|
|
38
|
+
cause: thrown
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return new ToolError({
|
|
42
|
+
code: "internal",
|
|
43
|
+
message: String(thrown),
|
|
44
|
+
cause: thrown
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function toToolResult(value, thrown) {
|
|
48
|
+
if (thrown !== void 0) {
|
|
49
|
+
const err = toToolError(thrown);
|
|
50
|
+
return { ok: false, error: err.toJSON() };
|
|
51
|
+
}
|
|
52
|
+
return { ok: true, value };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/define-tool.ts
|
|
56
|
+
var PROVIDER_KINDS = [
|
|
57
|
+
"cli",
|
|
58
|
+
"http",
|
|
59
|
+
"mcp",
|
|
60
|
+
"sdk",
|
|
61
|
+
"builtin"
|
|
62
|
+
];
|
|
63
|
+
var constructTool = createDoctype({
|
|
64
|
+
aip: 14,
|
|
65
|
+
name: "tool",
|
|
66
|
+
validate(def) {
|
|
67
|
+
if ("execute" in def) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`defineTool: id='${def.id}' carries an 'execute' property. Bodies live on AIP-30 PROVIDER manifests, not on the TOOL contract. See https://agentproto.sh/docs/aip-30 for migration.`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
build(def) {
|
|
74
|
+
return {
|
|
75
|
+
id: def.id,
|
|
76
|
+
name: def.name ?? def.id,
|
|
77
|
+
description: def.description,
|
|
78
|
+
version: def.version,
|
|
79
|
+
inputSchema: def.inputSchema,
|
|
80
|
+
outputSchema: def.outputSchema,
|
|
81
|
+
contextSchema: def.contextSchema,
|
|
82
|
+
mutates: Object.freeze([...def.mutates ?? []]),
|
|
83
|
+
requires: freezeCapabilities(def.requires),
|
|
84
|
+
approval: defaultApproval(def.approval, def.mutates),
|
|
85
|
+
riskLevel: def.riskLevel ?? 0,
|
|
86
|
+
costClass: def.costClass ?? "trivial",
|
|
87
|
+
timeoutMs: def.timeoutMs ?? 3e4,
|
|
88
|
+
retry: def.retry,
|
|
89
|
+
tags: Object.freeze([...def.tags ?? []]),
|
|
90
|
+
metadata: Object.freeze({ ...def.metadata ?? {} }),
|
|
91
|
+
idempotent: def.idempotent ?? false,
|
|
92
|
+
defaultImplementation: def.defaultImplementation,
|
|
93
|
+
driverConstraints: freezeProviderConstraints(def.driverConstraints)
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
function defineTool(definition) {
|
|
98
|
+
return constructTool(
|
|
99
|
+
definition
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
function validateInput(handle, input) {
|
|
103
|
+
const result = handle.inputSchema.safeParse(input);
|
|
104
|
+
if (!result.success) {
|
|
105
|
+
return {
|
|
106
|
+
ok: false,
|
|
107
|
+
error: {
|
|
108
|
+
code: "input_invalid",
|
|
109
|
+
message: `id='${handle.id}': ${formatZodIssues(result.error.issues)}`,
|
|
110
|
+
cause: result.error.issues
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return { ok: true, value: result.data };
|
|
115
|
+
}
|
|
116
|
+
function validateContext(handle, context) {
|
|
117
|
+
if (!handle.contextSchema) {
|
|
118
|
+
return { ok: true, value: context };
|
|
119
|
+
}
|
|
120
|
+
const result = handle.contextSchema.safeParse(context);
|
|
121
|
+
if (!result.success) {
|
|
122
|
+
return {
|
|
123
|
+
ok: false,
|
|
124
|
+
error: {
|
|
125
|
+
code: "input_invalid",
|
|
126
|
+
message: `id='${handle.id}': context does not match contextSchema \u2014 ${formatZodIssues(result.error.issues)}`,
|
|
127
|
+
field: "context",
|
|
128
|
+
cause: result.error.issues
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return { ok: true, value: result.data };
|
|
133
|
+
}
|
|
134
|
+
function validateOutput(handle, output) {
|
|
135
|
+
const result = handle.outputSchema.safeParse(output);
|
|
136
|
+
if (!result.success) {
|
|
137
|
+
throw new ToolError({
|
|
138
|
+
code: "output_invalid",
|
|
139
|
+
message: `id='${handle.id}': provider produced output that does not match outputSchema \u2014 ${formatZodIssues(result.error.issues)}`,
|
|
140
|
+
cause: result.error.issues
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return result.data;
|
|
144
|
+
}
|
|
145
|
+
function defaultApproval(declared, mutates) {
|
|
146
|
+
if (declared) return declared;
|
|
147
|
+
return mutates && mutates.length > 0 ? "on-mutate" : "auto";
|
|
148
|
+
}
|
|
149
|
+
function freezeCapabilities(caps) {
|
|
150
|
+
return Object.freeze({
|
|
151
|
+
network: Object.freeze([...caps?.network ?? []]),
|
|
152
|
+
secrets: Object.freeze([...caps?.secrets ?? []]),
|
|
153
|
+
tools: Object.freeze([...caps?.tools ?? []])
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function freezeProviderConstraints(c) {
|
|
157
|
+
const forbid = (c?.forbid ?? []).filter(
|
|
158
|
+
(k) => PROVIDER_KINDS.includes(k)
|
|
159
|
+
);
|
|
160
|
+
const requireKind = (c?.requireKind ?? []).filter(
|
|
161
|
+
(k) => PROVIDER_KINDS.includes(k)
|
|
162
|
+
);
|
|
163
|
+
return Object.freeze({
|
|
164
|
+
forbid: Object.freeze(forbid),
|
|
165
|
+
requireKind: Object.freeze(requireKind)
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function formatZodIssues(issues) {
|
|
169
|
+
return issues.map((i) => `${i.path.length > 0 ? i.path.join(".") + ": " : ""}${i.message}`).join("; ");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/manifest/index.ts
|
|
173
|
+
var toolManifestFrontmatterSchema = z.object({
|
|
174
|
+
schema: z.literal("agentproto/tool/v1").optional(),
|
|
175
|
+
name: z.string().min(1).max(80),
|
|
176
|
+
id: z.string().regex(/^[a-z][a-z0-9._-]{1,63}$/),
|
|
177
|
+
description: z.string().min(1).max(2e3),
|
|
178
|
+
version: z.string().regex(/^\d+\.\d+\.\d+/),
|
|
179
|
+
// Optional metadata
|
|
180
|
+
mutates: z.array(z.string()).optional(),
|
|
181
|
+
requires: z.object({
|
|
182
|
+
network: z.array(z.string()).optional(),
|
|
183
|
+
secrets: z.array(z.string()).optional(),
|
|
184
|
+
tools: z.array(z.string()).optional()
|
|
185
|
+
}).optional(),
|
|
186
|
+
// `ApprovalClass` is `"auto" | "always" | "on-mutate" | \`policy:${string}\``.
|
|
187
|
+
// z.union widens the regex branch to plain `string` (zod can't express
|
|
188
|
+
// template literal types), so we use `z.custom` to keep the inferred
|
|
189
|
+
// type exact — matters because `defineTool` accepts `ApprovalClass`.
|
|
190
|
+
approval: z.custom(
|
|
191
|
+
(v) => typeof v === "string" && (v === "auto" || v === "always" || v === "on-mutate" || /^policy:/.test(v)),
|
|
192
|
+
{ message: "expected 'auto' | 'always' | 'on-mutate' | 'policy:<name>'" }
|
|
193
|
+
).optional(),
|
|
194
|
+
risk_level: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]).optional(),
|
|
195
|
+
cost_class: z.enum(["trivial", "metered", "expensive"]).optional(),
|
|
196
|
+
timeout_ms: z.number().int().positive().optional(),
|
|
197
|
+
idempotent: z.boolean().optional(),
|
|
198
|
+
tags: z.array(z.string()).optional(),
|
|
199
|
+
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
200
|
+
// AIP-26 / AIP-17 / AIP-19 references — kept loose; validated by their
|
|
201
|
+
// respective AIPs' adapters when consumed.
|
|
202
|
+
code: z.unknown().optional(),
|
|
203
|
+
run: z.unknown().optional(),
|
|
204
|
+
runner: z.unknown().optional(),
|
|
205
|
+
secrets: z.unknown().optional(),
|
|
206
|
+
network: z.unknown().optional()
|
|
207
|
+
});
|
|
208
|
+
function parseToolManifest(source) {
|
|
209
|
+
const parsed = matter(source);
|
|
210
|
+
if (Object.keys(parsed.data).length === 0) {
|
|
211
|
+
throw new Error("parseToolManifest: missing or empty frontmatter");
|
|
212
|
+
}
|
|
213
|
+
const result = toolManifestFrontmatterSchema.safeParse(parsed.data);
|
|
214
|
+
if (!result.success) {
|
|
215
|
+
throw new Error(
|
|
216
|
+
`parseToolManifest: invalid frontmatter \u2014 ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
return { frontmatter: result.data, body: parsed.content };
|
|
220
|
+
}
|
|
221
|
+
function toolFromManifest(args) {
|
|
222
|
+
const fm = args.manifest.frontmatter;
|
|
223
|
+
return defineTool({
|
|
224
|
+
id: fm.id,
|
|
225
|
+
name: fm.name,
|
|
226
|
+
description: fm.description,
|
|
227
|
+
version: fm.version,
|
|
228
|
+
inputSchema: args.inputSchema,
|
|
229
|
+
outputSchema: args.outputSchema,
|
|
230
|
+
contextSchema: args.contextSchema,
|
|
231
|
+
mutates: fm.mutates,
|
|
232
|
+
requires: fm.requires,
|
|
233
|
+
approval: fm.approval,
|
|
234
|
+
riskLevel: fm.risk_level,
|
|
235
|
+
costClass: fm.cost_class,
|
|
236
|
+
timeoutMs: fm.timeout_ms,
|
|
237
|
+
idempotent: fm.idempotent,
|
|
238
|
+
tags: fm.tags,
|
|
239
|
+
metadata: fm.metadata
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export { ToolError, defineTool, parseToolManifest, toToolError, toToolResult, toolFromManifest, toolManifestFrontmatterSchema, validateContext, validateInput, validateOutput };
|
|
244
|
+
//# sourceMappingURL=chunk-ZFIMSZXN.mjs.map
|
|
245
|
+
//# sourceMappingURL=chunk-ZFIMSZXN.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/define-tool.ts","../src/manifest/index.ts"],"names":[],"mappings":"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","file":"chunk-ZFIMSZXN.mjs","sourcesContent":["import type { ToolResult } from \"./types.js\"\n\n/**\n * AIP-14 conventional error codes. Tool-specific codes MAY use a domain\n * prefix (`\"stripe:card_declined\"`).\n */\nexport type ToolErrorCode =\n | \"input_invalid\"\n | \"output_invalid\"\n | \"unauthorised\"\n | \"not_found\"\n | \"rate_limited\"\n | \"timeout\"\n | \"upstream_error\"\n | \"internal\"\n | (string & {})\n\nexport interface ToolErrorPayload {\n code: ToolErrorCode\n message: string\n retryable?: boolean\n cause?: unknown\n}\n\n/**\n * Structured error thrown by tool bodies. Adapters wrap this into the\n * standard {@link ToolResult} envelope; bodies MUST throw it (never\n * return error objects).\n */\nexport class ToolError extends Error {\n readonly code: ToolErrorCode\n readonly retryable: boolean\n readonly cause: unknown\n\n constructor(payload: ToolErrorPayload) {\n super(payload.message)\n this.name = \"ToolError\"\n this.code = payload.code\n this.retryable = payload.retryable ?? false\n this.cause = payload.cause\n }\n\n toJSON(): ToolErrorPayload {\n return {\n code: this.code,\n message: this.message,\n retryable: this.retryable,\n ...(this.cause !== undefined ? { cause: this.cause } : {}),\n }\n }\n}\n\n/**\n * Wrap an unknown thrown value into a {@link ToolError}. Used by adapters\n * to normalise non-ToolError throws into the standard envelope.\n */\nexport function toToolError(thrown: unknown): ToolError {\n if (thrown instanceof ToolError) return thrown\n if (thrown instanceof Error) {\n return new ToolError({\n code: \"internal\",\n message: thrown.message,\n cause: thrown,\n })\n }\n return new ToolError({\n code: \"internal\",\n message: String(thrown),\n cause: thrown,\n })\n}\n\n/**\n * Adapter helper: project a thrown ToolError (or any throw) into the\n * standard {@link ToolResult} envelope. Adapters MUST do this; bodies MUST NOT.\n */\nexport function toToolResult<T>(\n value: T | undefined,\n thrown: unknown\n): ToolResult<T> {\n if (thrown !== undefined) {\n const err = toToolError(thrown)\n return { ok: false, error: err.toJSON() }\n }\n return { ok: true, value: value as T }\n}\n","import { createDoctype } from \"@agentproto/define-doctype\"\nimport type { ZodType } from \"zod\"\nimport { ToolError } from \"./errors.js\"\nimport type {\n ApprovalClass,\n DriverConstraints,\n DriverKind,\n ToolCapabilities,\n ToolContext,\n ToolDefinition,\n ToolHandle,\n ValidationResult,\n} from \"./types.js\"\n\nconst PROVIDER_KINDS: readonly DriverKind[] = [\n \"cli\",\n \"http\",\n \"mcp\",\n \"sdk\",\n \"builtin\",\n]\n\n/**\n * AIP-14 reference implementation of `defineTool`.\n *\n * Returns a {@link ToolHandle} with defaults applied. The handle is a\n * pure contract — schemas, governance metadata, provider routing\n * hints. Bodies live on AIP-30 PROVIDER manifests; invocation goes\n * through provider-runtime's resolver.\n *\n * Built on `createDoctype` from `@agentproto/define-doctype`: the\n * id-pattern + description-length validation and the top-level\n * `Object.freeze` are shared with every other AIP defineX. The\n * spec-14-specific parts (migration guard for `execute`, defaulting\n * `approval` from `mutates`, freezing nested arrays/objects) live in\n * `validate` and `build` below.\n *\n * Conformance highlights ([§ Conformance rules](https://agentproto.sh/docs/aip-14)):\n * - No `execute` field on the contract — bodies are providers' job.\n * - `defineTool` MUST refuse a definition carrying `execute` (migration error).\n * - No I/O at module load — `defineTool(...)` is pure construction.\n */\nconst constructTool = createDoctype<\n ToolDefinition<unknown, unknown, ToolContext>,\n ToolHandle<unknown, unknown, ToolContext>\n>({\n aip: 14,\n name: \"tool\",\n validate(def) {\n // Migration guard: catch authors trying to ship a body on the contract.\n // The body lives on a PROVIDER (per AIP-30); reject at construction.\n if (\"execute\" in (def as unknown as Record<string, unknown>)) {\n throw new Error(\n `defineTool: id='${def.id}' carries an 'execute' property. ` +\n `Bodies live on AIP-30 PROVIDER manifests, not on the TOOL contract. ` +\n `See https://agentproto.sh/docs/aip-30 for migration.`,\n )\n }\n },\n build(def) {\n return {\n id: def.id,\n name: def.name ?? def.id,\n description: def.description,\n version: def.version,\n inputSchema: def.inputSchema,\n outputSchema: def.outputSchema,\n contextSchema: def.contextSchema,\n mutates: Object.freeze([...(def.mutates ?? [])]),\n requires: freezeCapabilities(def.requires),\n approval: defaultApproval(def.approval, def.mutates),\n riskLevel: def.riskLevel ?? 0,\n costClass: def.costClass ?? \"trivial\",\n timeoutMs: def.timeoutMs ?? 30_000,\n retry: def.retry,\n tags: Object.freeze([...(def.tags ?? [])]),\n metadata: Object.freeze({ ...(def.metadata ?? {}) }),\n idempotent: def.idempotent ?? false,\n defaultImplementation: def.defaultImplementation,\n driverConstraints: freezeProviderConstraints(def.driverConstraints),\n }\n },\n})\n\n/**\n * Public-facing `defineTool` — typed wrapper around `constructTool`\n * that preserves the per-call `<TInput, TOutput, TContext>` inference\n * so callers don't write any generics. The wrapper exists purely for\n * generic propagation; the runtime body is the meta-factory above.\n */\nexport function defineTool<\n TInput,\n TOutput,\n TContext extends ToolContext = ToolContext,\n>(\n definition: ToolDefinition<TInput, TOutput, TContext>,\n): ToolHandle<TInput, TOutput, TContext> {\n return constructTool(\n definition as ToolDefinition<unknown, unknown, ToolContext>,\n ) as unknown as ToolHandle<TInput, TOutput, TContext>\n}\n\n/**\n * Validate input against a tool's `inputSchema`. Returns a typed\n * {@link ValidationResult}; provider runtimes MUST call this BEFORE\n * dispatching to the provider's body.\n */\nexport function validateInput<TInput>(\n handle: Pick<ToolHandle<TInput>, \"id\" | \"inputSchema\">,\n input: unknown,\n): ValidationResult<TInput> {\n const result = handle.inputSchema.safeParse(input)\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"input_invalid\",\n message: `id='${handle.id}': ${formatZodIssues(result.error.issues)}`,\n cause: result.error.issues,\n },\n }\n }\n return { ok: true, value: result.data as TInput }\n}\n\n/**\n * Validate context against a tool's `contextSchema` (when declared).\n * Returns a typed {@link ValidationResult}; provider runtimes MUST\n * call this BEFORE dispatching when the contract has a contextSchema.\n *\n * Tools without a contextSchema accept any context shape; this helper\n * returns the input verbatim in that case.\n */\nexport function validateContext<TContext extends ToolContext = ToolContext>(\n handle: Pick<ToolHandle<unknown, unknown, TContext>, \"id\" | \"contextSchema\">,\n context: unknown,\n): ValidationResult<TContext> {\n if (!handle.contextSchema) {\n return { ok: true, value: context as TContext }\n }\n const result = handle.contextSchema.safeParse(context)\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"input_invalid\",\n message: `id='${handle.id}': context does not match contextSchema — ${formatZodIssues(result.error.issues)}`,\n field: \"context\",\n cause: result.error.issues,\n },\n }\n }\n return { ok: true, value: result.data as TContext }\n}\n\n/**\n * Validate output against a tool's `outputSchema`. Returns the typed\n * {@link ValidationResult}; provider runtimes MUST call this AFTER\n * the body returns and BEFORE handing the value to the caller.\n *\n * On failure, hosts SHOULD throw {@link ToolError} with code\n * `\"output_invalid\"` — the tool produced a contract violation.\n */\nexport function validateOutput<TOutput>(\n handle: Pick<ToolHandle<unknown, TOutput>, \"id\" | \"outputSchema\">,\n output: unknown,\n): TOutput {\n const result = handle.outputSchema.safeParse(output)\n if (!result.success) {\n throw new ToolError({\n code: \"output_invalid\",\n message: `id='${handle.id}': provider produced output that does not match outputSchema — ${formatZodIssues(result.error.issues)}`,\n cause: result.error.issues,\n })\n }\n return result.data as TOutput\n}\n\nfunction defaultApproval(\n declared: ApprovalClass | undefined,\n mutates: readonly string[] | undefined,\n): ApprovalClass {\n if (declared) return declared\n return mutates && mutates.length > 0 ? \"on-mutate\" : \"auto\"\n}\n\nfunction freezeCapabilities(\n caps: ToolCapabilities | undefined,\n): Readonly<ToolCapabilities> {\n return Object.freeze({\n network: Object.freeze([...(caps?.network ?? [])]),\n secrets: Object.freeze([...(caps?.secrets ?? [])]),\n tools: Object.freeze([...(caps?.tools ?? [])]),\n })\n}\n\nfunction freezeProviderConstraints(\n c: DriverConstraints | undefined,\n): Required<DriverConstraints> {\n const forbid = (c?.forbid ?? []).filter((k): k is DriverKind =>\n PROVIDER_KINDS.includes(k as DriverKind),\n )\n const requireKind = (c?.requireKind ?? []).filter((k): k is DriverKind =>\n PROVIDER_KINDS.includes(k as DriverKind),\n )\n return Object.freeze({\n forbid: Object.freeze(forbid) as readonly DriverKind[],\n requireKind: Object.freeze(requireKind) as readonly DriverKind[],\n })\n}\n\nfunction formatZodIssues(\n issues: ReadonlyArray<{ path: ReadonlyArray<PropertyKey>; message: string }>,\n): string {\n return issues\n .map((i) => `${i.path.length > 0 ? i.path.join(\".\") + \": \" : \"\"}${i.message}`)\n .join(\"; \")\n}\n\nexport type { ZodType }\n","import matter from \"gray-matter\"\nimport { z, type ZodType } from \"zod\"\nimport { defineTool } from \"../define-tool.js\"\nimport type { ApprovalClass, ToolContext, ToolHandle } from \"../types.js\"\n\n/**\n * AIP-14 TOOL.md sidecar parser.\n *\n * Reads frontmatter (host-relevant metadata) + body (long-form\n * description / examples / errors). The TS module's `defineTool(...)`\n * supplies the schemas and execute body; this manifest supplies the\n * runtime metadata that overrides or augments the in-code defaults.\n *\n * Field set covers AIP-14 §\"Frontmatter\" — required and optional fields\n * normalised to snake_case → camelCase.\n */\n\nexport const toolManifestFrontmatterSchema = z.object({\n schema: z.literal(\"agentproto/tool/v1\").optional(),\n name: z.string().min(1).max(80),\n id: z.string().regex(/^[a-z][a-z0-9._-]{1,63}$/),\n description: z.string().min(1).max(2000),\n version: z.string().regex(/^\\d+\\.\\d+\\.\\d+/),\n\n // Optional metadata\n mutates: z.array(z.string()).optional(),\n requires: z\n .object({\n network: z.array(z.string()).optional(),\n secrets: z.array(z.string()).optional(),\n tools: z.array(z.string()).optional(),\n })\n .optional(),\n // `ApprovalClass` is `\"auto\" | \"always\" | \"on-mutate\" | \\`policy:${string}\\``.\n // z.union widens the regex branch to plain `string` (zod can't express\n // template literal types), so we use `z.custom` to keep the inferred\n // type exact — matters because `defineTool` accepts `ApprovalClass`.\n approval: z\n .custom<ApprovalClass>(\n (v): v is ApprovalClass =>\n typeof v === \"string\" &&\n (v === \"auto\" ||\n v === \"always\" ||\n v === \"on-mutate\" ||\n /^policy:/.test(v)),\n { message: \"expected 'auto' | 'always' | 'on-mutate' | 'policy:<name>'\" },\n )\n .optional(),\n risk_level: z\n .union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)])\n .optional(),\n cost_class: z.enum([\"trivial\", \"metered\", \"expensive\"]).optional(),\n timeout_ms: z.number().int().positive().optional(),\n idempotent: z.boolean().optional(),\n tags: z.array(z.string()).optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n\n // AIP-26 / AIP-17 / AIP-19 references — kept loose; validated by their\n // respective AIPs' adapters when consumed.\n code: z.unknown().optional(),\n run: z.unknown().optional(),\n runner: z.unknown().optional(),\n secrets: z.unknown().optional(),\n network: z.unknown().optional(),\n})\n\nexport type ToolManifestFrontmatter = z.infer<\n typeof toolManifestFrontmatterSchema\n>\n\nexport interface ToolManifest {\n frontmatter: ToolManifestFrontmatter\n body: string\n}\n\n/**\n * Parse a TOOL.md source string into structured frontmatter + body.\n * Throws on missing frontmatter or schema-invalid frontmatter.\n */\nexport function parseToolManifest(source: string): ToolManifest {\n const parsed = matter(source)\n if (Object.keys(parsed.data).length === 0) {\n throw new Error(\"parseToolManifest: missing or empty frontmatter\")\n }\n const result = toolManifestFrontmatterSchema.safeParse(parsed.data)\n if (!result.success) {\n throw new Error(\n `parseToolManifest: invalid frontmatter — ${result.error.issues\n .map(i => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`\n )\n }\n return { frontmatter: result.data, body: parsed.content }\n}\n\n/**\n * Build a fully-typed {@link ToolHandle} from a parsed `TOOL.md` manifest\n * + caller-supplied schemas. The .md is the single source of truth for\n * metadata (id, name, description, version, mutates, approval, …); the\n * schemas live in the TS module that ships alongside the .md.\n *\n * Both inputs are revalidated by `defineTool`'s shared invariants\n * (id pattern, description length, top-level freeze) — `parseToolManifest`\n * already enforces a stricter id pattern + version semver, so a\n * well-formed manifest passes through cleanly. Mismatches between the\n * manifest's id-shape and `defineTool`'s pattern surface a\n * descriptive error from the same validation pipeline as the TS path.\n *\n * @example\n * const manifest = parseToolManifest(readFileSync(\"./echo/TOOL.md\", \"utf8\"))\n * const echo = toolFromManifest({\n * manifest,\n * inputSchema: z.object({ msg: z.string() }),\n * outputSchema: z.object({ msg: z.string() }),\n * })\n */\nexport function toolFromManifest<\n TInput,\n TOutput,\n TContext extends ToolContext = ToolContext,\n>(args: {\n manifest: ToolManifest\n inputSchema: ZodType<TInput>\n outputSchema: ZodType<TOutput>\n contextSchema?: ZodType<TContext>\n}): ToolHandle<TInput, TOutput, TContext> {\n const fm = args.manifest.frontmatter\n return defineTool<TInput, TOutput, TContext>({\n id: fm.id,\n name: fm.name,\n description: fm.description,\n version: fm.version,\n inputSchema: args.inputSchema,\n outputSchema: args.outputSchema,\n contextSchema: args.contextSchema,\n mutates: fm.mutates,\n requires: fm.requires,\n approval: fm.approval,\n riskLevel: fm.risk_level,\n costClass: fm.cost_class,\n timeoutMs: fm.timeout_ms,\n idempotent: fm.idempotent,\n tags: fm.tags,\n metadata: fm.metadata,\n })\n}\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { T as ToolContext, a as ToolDefinition, b as ToolHandle, V as ValidationResult, c as ToolResult } from './types-Ce8BEvMm.js';
|
|
2
|
+
export { A as ApprovalClass, D as DriverConstraints, d as DriverKind, R as RetryPolicy, e as ToolCapabilities, f as ValidationFailure, g as ValidationSuccess } from './types-Ce8BEvMm.js';
|
|
3
|
+
import * as _agentproto_manifest from '@agentproto/manifest';
|
|
4
|
+
import { DoctypeSpec } from '@agentproto/manifest';
|
|
5
|
+
import 'zod';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Public-facing `defineTool` — typed wrapper around `constructTool`
|
|
9
|
+
* that preserves the per-call `<TInput, TOutput, TContext>` inference
|
|
10
|
+
* so callers don't write any generics. The wrapper exists purely for
|
|
11
|
+
* generic propagation; the runtime body is the meta-factory above.
|
|
12
|
+
*/
|
|
13
|
+
declare function defineTool<TInput, TOutput, TContext extends ToolContext = ToolContext>(definition: ToolDefinition<TInput, TOutput, TContext>): ToolHandle<TInput, TOutput, TContext>;
|
|
14
|
+
/**
|
|
15
|
+
* Validate input against a tool's `inputSchema`. Returns a typed
|
|
16
|
+
* {@link ValidationResult}; provider runtimes MUST call this BEFORE
|
|
17
|
+
* dispatching to the provider's body.
|
|
18
|
+
*/
|
|
19
|
+
declare function validateInput<TInput>(handle: Pick<ToolHandle<TInput>, "id" | "inputSchema">, input: unknown): ValidationResult<TInput>;
|
|
20
|
+
/**
|
|
21
|
+
* Validate context against a tool's `contextSchema` (when declared).
|
|
22
|
+
* Returns a typed {@link ValidationResult}; provider runtimes MUST
|
|
23
|
+
* call this BEFORE dispatching when the contract has a contextSchema.
|
|
24
|
+
*
|
|
25
|
+
* Tools without a contextSchema accept any context shape; this helper
|
|
26
|
+
* returns the input verbatim in that case.
|
|
27
|
+
*/
|
|
28
|
+
declare function validateContext<TContext extends ToolContext = ToolContext>(handle: Pick<ToolHandle<unknown, unknown, TContext>, "id" | "contextSchema">, context: unknown): ValidationResult<TContext>;
|
|
29
|
+
/**
|
|
30
|
+
* Validate output against a tool's `outputSchema`. Returns the typed
|
|
31
|
+
* {@link ValidationResult}; provider runtimes MUST call this AFTER
|
|
32
|
+
* the body returns and BEFORE handing the value to the caller.
|
|
33
|
+
*
|
|
34
|
+
* On failure, hosts SHOULD throw {@link ToolError} with code
|
|
35
|
+
* `"output_invalid"` — the tool produced a contract violation.
|
|
36
|
+
*/
|
|
37
|
+
declare function validateOutput<TOutput>(handle: Pick<ToolHandle<unknown, TOutput>, "id" | "outputSchema">, output: unknown): TOutput;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* `createTool(params, opts)` — write a TOOL.md to disk.
|
|
41
|
+
*
|
|
42
|
+
* Symmetric to `parseToolManifest` (.md → handle) and `defineTool`
|
|
43
|
+
* (params → handle): this takes params, validates via defineTool
|
|
44
|
+
* (single source of truth — same zod schema, same cross-AIP
|
|
45
|
+
* invariants), then serialises the validated frontmatter to YAML
|
|
46
|
+
* and writes it under `<dir>/<id>/TOOL.md`.
|
|
47
|
+
*
|
|
48
|
+
* The author's body markdown is preserved verbatim in `opts.body`.
|
|
49
|
+
* Pass `dryRun: true` to get the rendered string without touching
|
|
50
|
+
* disk — useful for tests, the MCP server's preview, and CI lints.
|
|
51
|
+
*
|
|
52
|
+
* Non-frontmatter values that can't appear in YAML (zod schemas,
|
|
53
|
+
* function bodies) are filtered out by `filterSerializable` from
|
|
54
|
+
* `@agentproto/define-doctype`; the resulting frontmatter matches
|
|
55
|
+
* what `parseToolManifest` would consume on the way back in.
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
interface CreateToolOptions {
|
|
59
|
+
/** Workspace-relative or absolute directory under which to write `<id>/TOOL.md`. */
|
|
60
|
+
dir: string;
|
|
61
|
+
/** Body markdown after the frontmatter. Defaults to a one-line stub. */
|
|
62
|
+
body?: string;
|
|
63
|
+
/** Render only — don't write. Returns the rendered string. */
|
|
64
|
+
dryRun?: boolean;
|
|
65
|
+
}
|
|
66
|
+
interface CreateToolResult<TInput, TOutput, TContext extends ToolContext> {
|
|
67
|
+
/** The path where the file was (or would be) written. */
|
|
68
|
+
path: string;
|
|
69
|
+
/** The validated handle returned by defineTool. */
|
|
70
|
+
handle: ToolHandle<TInput, TOutput, TContext>;
|
|
71
|
+
/** The full rendered file contents (frontmatter + body). */
|
|
72
|
+
rendered: string;
|
|
73
|
+
}
|
|
74
|
+
declare function createTool<TInput, TOutput, TContext extends ToolContext = ToolContext>(params: ToolDefinition<TInput, TOutput, TContext>, opts: CreateToolOptions): Promise<CreateToolResult<TInput, TOutput, TContext>>;
|
|
75
|
+
|
|
76
|
+
declare const toolSpec: DoctypeSpec<ToolDefinition<unknown, unknown>, ToolHandle<unknown, unknown>>;
|
|
77
|
+
declare const toolVerbs: _agentproto_manifest.Verbs<ToolDefinition<unknown, unknown, ToolContext>, ToolHandle<unknown, unknown, ToolContext>>;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* AIP-14 conventional error codes. Tool-specific codes MAY use a domain
|
|
81
|
+
* prefix (`"stripe:card_declined"`).
|
|
82
|
+
*/
|
|
83
|
+
type ToolErrorCode = "input_invalid" | "output_invalid" | "unauthorised" | "not_found" | "rate_limited" | "timeout" | "upstream_error" | "internal" | (string & {});
|
|
84
|
+
interface ToolErrorPayload {
|
|
85
|
+
code: ToolErrorCode;
|
|
86
|
+
message: string;
|
|
87
|
+
retryable?: boolean;
|
|
88
|
+
cause?: unknown;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Structured error thrown by tool bodies. Adapters wrap this into the
|
|
92
|
+
* standard {@link ToolResult} envelope; bodies MUST throw it (never
|
|
93
|
+
* return error objects).
|
|
94
|
+
*/
|
|
95
|
+
declare class ToolError extends Error {
|
|
96
|
+
readonly code: ToolErrorCode;
|
|
97
|
+
readonly retryable: boolean;
|
|
98
|
+
readonly cause: unknown;
|
|
99
|
+
constructor(payload: ToolErrorPayload);
|
|
100
|
+
toJSON(): ToolErrorPayload;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Wrap an unknown thrown value into a {@link ToolError}. Used by adapters
|
|
104
|
+
* to normalise non-ToolError throws into the standard envelope.
|
|
105
|
+
*/
|
|
106
|
+
declare function toToolError(thrown: unknown): ToolError;
|
|
107
|
+
/**
|
|
108
|
+
* Adapter helper: project a thrown ToolError (or any throw) into the
|
|
109
|
+
* standard {@link ToolResult} envelope. Adapters MUST do this; bodies MUST NOT.
|
|
110
|
+
*/
|
|
111
|
+
declare function toToolResult<T>(value: T | undefined, thrown: unknown): ToolResult<T>;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @agentproto/tool — AIP-14 TOOL.md `defineTool` reference impl.
|
|
115
|
+
*
|
|
116
|
+
* Vendor-neutral tool **contract** registration: an author writes
|
|
117
|
+
* `defineTool({...})` and the runtime returns a `ToolHandle` carrying
|
|
118
|
+
* identity, schemas, side-effect profile, approval class, and
|
|
119
|
+
* provider routing hints. Bodies live on AIP-30 PROVIDER manifests;
|
|
120
|
+
* invocation goes through `@agentproto/driver`.
|
|
121
|
+
*
|
|
122
|
+
* Spec: https://agentproto.sh/docs/aip-14
|
|
123
|
+
*/
|
|
124
|
+
declare const SPEC_NAME: "agenttool/v1";
|
|
125
|
+
declare const SPEC_VERSION: "1.0.0-alpha";
|
|
126
|
+
|
|
127
|
+
export { type CreateToolOptions, type CreateToolResult, SPEC_NAME, SPEC_VERSION, ToolContext, ToolDefinition, ToolError, type ToolErrorCode, type ToolErrorPayload, ToolHandle, ToolResult, ValidationResult, createTool, defineTool, toToolError, toToolResult, toolSpec, toolVerbs, validateContext, validateInput, validateOutput };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { parseToolManifest, defineTool } from './chunk-ZFIMSZXN.mjs';
|
|
2
|
+
export { ToolError, defineTool, toToolError, toToolResult, validateContext, validateInput, validateOutput } from './chunk-ZFIMSZXN.mjs';
|
|
3
|
+
import { filterSerializable } from '@agentproto/define-doctype';
|
|
4
|
+
import matter from 'gray-matter';
|
|
5
|
+
import { mkdir, writeFile } from 'fs/promises';
|
|
6
|
+
import { join, dirname } from 'path';
|
|
7
|
+
import { createVerbs } from '@agentproto/manifest';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @agentproto/tool v0.1.0-alpha
|
|
11
|
+
* AIP-14 TOOL.md `defineTool` reference implementation.
|
|
12
|
+
*/
|
|
13
|
+
async function createTool(params, opts) {
|
|
14
|
+
const handle = defineTool(params);
|
|
15
|
+
const path = join(opts.dir, handle.id, "TOOL.md");
|
|
16
|
+
const frontmatter = filterSerializable({
|
|
17
|
+
schema: "agentproto/tool/v1",
|
|
18
|
+
...params
|
|
19
|
+
});
|
|
20
|
+
const rendered = matter.stringify(
|
|
21
|
+
opts.body ?? `# ${handle.name}
|
|
22
|
+
|
|
23
|
+
${handle.description}
|
|
24
|
+
`,
|
|
25
|
+
frontmatter
|
|
26
|
+
);
|
|
27
|
+
if (!opts.dryRun) {
|
|
28
|
+
await mkdir(dirname(path), { recursive: true });
|
|
29
|
+
await writeFile(path, rendered, "utf8");
|
|
30
|
+
}
|
|
31
|
+
return { path, handle, rendered };
|
|
32
|
+
}
|
|
33
|
+
var toolSpec = {
|
|
34
|
+
name: "tool",
|
|
35
|
+
aip: 14,
|
|
36
|
+
schemaLiteral: "agentproto/tool/v1",
|
|
37
|
+
pathOf: (h) => `${h.id}/TOOL.md`,
|
|
38
|
+
define: (params) => defineTool(params),
|
|
39
|
+
parse: (source) => {
|
|
40
|
+
const m = parseToolManifest(source);
|
|
41
|
+
return {
|
|
42
|
+
frontmatter: m.frontmatter,
|
|
43
|
+
body: m.body
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
var toolVerbs = createVerbs(toolSpec);
|
|
48
|
+
|
|
49
|
+
// src/index.ts
|
|
50
|
+
var SPEC_NAME = "agenttool/v1";
|
|
51
|
+
var SPEC_VERSION = "1.0.0-alpha";
|
|
52
|
+
|
|
53
|
+
export { SPEC_NAME, SPEC_VERSION, createTool, toolSpec, toolVerbs };
|
|
54
|
+
//# sourceMappingURL=index.mjs.map
|
|
55
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/create-tool.ts","../src/spec.ts","../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAgDA,eAAsB,UAAA,CAKpB,QACA,IAAA,EACsD;AACtD,EAAA,MAAM,MAAA,GAAS,WAAsC,MAAM,CAAA;AAC3D,EAAA,MAAM,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,MAAA,CAAO,IAAI,SAAS,CAAA;AAChD,EAAA,MAAM,cAAc,kBAAA,CAAmB;AAAA,IACrC,MAAA,EAAQ,oBAAA;AAAA,IACR,GAAG;AAAA,GACJ,CAAA;AACD,EAAA,MAAM,WAAW,MAAA,CAAO,SAAA;AAAA,IACtB,IAAA,CAAK,IAAA,IAAQ,CAAA,EAAA,EAAK,MAAA,CAAO,IAAI;;AAAA,EAAO,OAAO,WAAW;AAAA,CAAA;AAAA,IACtD;AAAA,GACF;AACA,EAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAChB,IAAA,MAAM,MAAM,OAAA,CAAQ,IAAI,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAC9C,IAAA,MAAM,SAAA,CAAU,IAAA,EAAM,QAAA,EAAU,MAAM,CAAA;AAAA,EACxC;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,QAAA,EAAS;AAClC;AC1DO,IAAM,QAAA,GAGT;AAAA,EACF,IAAA,EAAM,MAAA;AAAA,EACN,GAAA,EAAK,EAAA;AAAA,EACL,aAAA,EAAe,oBAAA;AAAA,EACf,MAAA,EAAQ,CAAC,CAAA,KAAM,CAAA,EAAG,EAAE,EAAE,CAAA,QAAA,CAAA;AAAA,EACtB,MAAA,EAAQ,CAAC,MAAA,KACP,UAAA,CAAW,MAAM,CAAA;AAAA,EACnB,KAAA,EAAO,CAAC,MAAA,KAAW;AACjB,IAAA,MAAM,CAAA,GAAI,kBAAkB,MAAM,CAAA;AAClC,IAAA,OAAO;AAAA,MACL,aAAa,CAAA,CAAE,WAAA;AAAA,MACf,MAAM,CAAA,CAAE;AAAA,KACV;AAAA,EACF;AACF;AAEO,IAAM,SAAA,GAAY,YAAY,QAAQ;;;ACpBtC,IAAM,SAAA,GAAY;AAClB,IAAM,YAAA,GAAe","file":"index.mjs","sourcesContent":["/**\n * `createTool(params, opts)` — write a TOOL.md to disk.\n *\n * Symmetric to `parseToolManifest` (.md → handle) and `defineTool`\n * (params → handle): this takes params, validates via defineTool\n * (single source of truth — same zod schema, same cross-AIP\n * invariants), then serialises the validated frontmatter to YAML\n * and writes it under `<dir>/<id>/TOOL.md`.\n *\n * The author's body markdown is preserved verbatim in `opts.body`.\n * Pass `dryRun: true` to get the rendered string without touching\n * disk — useful for tests, the MCP server's preview, and CI lints.\n *\n * Non-frontmatter values that can't appear in YAML (zod schemas,\n * function bodies) are filtered out by `filterSerializable` from\n * `@agentproto/define-doctype`; the resulting frontmatter matches\n * what `parseToolManifest` would consume on the way back in.\n */\n\nimport { filterSerializable } from \"@agentproto/define-doctype\"\nimport matter from \"gray-matter\"\nimport { mkdir, writeFile } from \"node:fs/promises\"\nimport { dirname, join } from \"node:path\"\nimport { defineTool } from \"./define-tool.js\"\nimport type { ToolContext, ToolDefinition, ToolHandle } from \"./types.js\"\n\nexport interface CreateToolOptions {\n /** Workspace-relative or absolute directory under which to write `<id>/TOOL.md`. */\n dir: string\n /** Body markdown after the frontmatter. Defaults to a one-line stub. */\n body?: string\n /** Render only — don't write. Returns the rendered string. */\n dryRun?: boolean\n}\n\nexport interface CreateToolResult<\n TInput,\n TOutput,\n TContext extends ToolContext,\n> {\n /** The path where the file was (or would be) written. */\n path: string\n /** The validated handle returned by defineTool. */\n handle: ToolHandle<TInput, TOutput, TContext>\n /** The full rendered file contents (frontmatter + body). */\n rendered: string\n}\n\nexport async function createTool<\n TInput,\n TOutput,\n TContext extends ToolContext = ToolContext,\n>(\n params: ToolDefinition<TInput, TOutput, TContext>,\n opts: CreateToolOptions,\n): Promise<CreateToolResult<TInput, TOutput, TContext>> {\n const handle = defineTool<TInput, TOutput, TContext>(params)\n const path = join(opts.dir, handle.id, \"TOOL.md\")\n const frontmatter = filterSerializable({\n schema: \"agentproto/tool/v1\",\n ...params,\n }) as Record<string, unknown>\n const rendered = matter.stringify(\n opts.body ?? `# ${handle.name}\\n\\n${handle.description}\\n`,\n frontmatter,\n )\n if (!opts.dryRun) {\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, rendered, \"utf8\")\n }\n return { path, handle, rendered }\n}\n","/**\n * AIP-14 doctype spec — fed to `@agentproto/manifest.createVerbs`\n * to derive create / load / list / update / resolve / delete in one\n * place. Keeping the spec separate from `define-tool.ts` lets the\n * manifest layer (and the future MCP server) iterate over a uniform\n * descriptor without each package re-implementing the wiring.\n */\n\nimport { createVerbs, type DoctypeSpec } from \"@agentproto/manifest\"\nimport { defineTool } from \"./define-tool.js\"\nimport { parseToolManifest } from \"./manifest/index.js\"\nimport type { ToolDefinition, ToolHandle } from \"./types.js\"\n\nexport const toolSpec: DoctypeSpec<\n ToolDefinition<unknown, unknown>,\n ToolHandle<unknown, unknown>\n> = {\n name: \"tool\",\n aip: 14,\n schemaLiteral: \"agentproto/tool/v1\",\n pathOf: (h) => `${h.id}/TOOL.md`,\n define: (params) =>\n defineTool(params) as ToolHandle<unknown, unknown>,\n parse: (source) => {\n const m = parseToolManifest(source)\n return {\n frontmatter: m.frontmatter as unknown as Record<string, unknown>,\n body: m.body,\n }\n },\n}\n\nexport const toolVerbs = createVerbs(toolSpec)\n","/**\n * @agentproto/tool — AIP-14 TOOL.md `defineTool` reference impl.\n *\n * Vendor-neutral tool **contract** registration: an author writes\n * `defineTool({...})` and the runtime returns a `ToolHandle` carrying\n * identity, schemas, side-effect profile, approval class, and\n * provider routing hints. Bodies live on AIP-30 PROVIDER manifests;\n * invocation goes through `@agentproto/driver`.\n *\n * Spec: https://agentproto.sh/docs/aip-14\n */\n\nexport const SPEC_NAME = \"agenttool/v1\" as const\nexport const SPEC_VERSION = \"1.0.0-alpha\" as const\n\nexport {\n defineTool,\n validateInput,\n validateContext,\n validateOutput,\n} from \"./define-tool.js\"\n// Standalone create-tool kept for back-compat; new code should import\n// the unified verb surface (`toolVerbs.create`, `.load`, `.list`,\n// `.update`, `.resolve`, `.delete`) from `./spec.js`.\nexport {\n createTool,\n type CreateToolOptions,\n type CreateToolResult,\n} from \"./create-tool.js\"\nexport { toolSpec, toolVerbs } from \"./spec.js\"\nexport {\n ToolError,\n toToolError,\n toToolResult,\n type ToolErrorCode,\n type ToolErrorPayload,\n} from \"./errors.js\"\nexport type {\n ToolDefinition,\n ToolHandle,\n ToolContext,\n ToolCapabilities,\n ApprovalClass,\n DriverConstraints,\n DriverKind,\n RetryPolicy,\n ToolResult,\n ValidationResult,\n ValidationFailure,\n ValidationSuccess,\n} from \"./types.js\"\n"]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { z, ZodType } from 'zod';
|
|
2
|
+
import { A as ApprovalClass, T as ToolContext, b as ToolHandle } from '../types-Ce8BEvMm.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* AIP-14 TOOL.md sidecar parser.
|
|
6
|
+
*
|
|
7
|
+
* Reads frontmatter (host-relevant metadata) + body (long-form
|
|
8
|
+
* description / examples / errors). The TS module's `defineTool(...)`
|
|
9
|
+
* supplies the schemas and execute body; this manifest supplies the
|
|
10
|
+
* runtime metadata that overrides or augments the in-code defaults.
|
|
11
|
+
*
|
|
12
|
+
* Field set covers AIP-14 §"Frontmatter" — required and optional fields
|
|
13
|
+
* normalised to snake_case → camelCase.
|
|
14
|
+
*/
|
|
15
|
+
declare const toolManifestFrontmatterSchema: z.ZodObject<{
|
|
16
|
+
schema: z.ZodOptional<z.ZodLiteral<"agentproto/tool/v1">>;
|
|
17
|
+
name: z.ZodString;
|
|
18
|
+
id: z.ZodString;
|
|
19
|
+
description: z.ZodString;
|
|
20
|
+
version: z.ZodString;
|
|
21
|
+
mutates: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
22
|
+
requires: z.ZodOptional<z.ZodObject<{
|
|
23
|
+
network: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
24
|
+
secrets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
25
|
+
tools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
26
|
+
}, z.core.$strip>>;
|
|
27
|
+
approval: z.ZodOptional<z.ZodCustom<ApprovalClass, ApprovalClass>>;
|
|
28
|
+
risk_level: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<0>, z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>>;
|
|
29
|
+
cost_class: z.ZodOptional<z.ZodEnum<{
|
|
30
|
+
trivial: "trivial";
|
|
31
|
+
metered: "metered";
|
|
32
|
+
expensive: "expensive";
|
|
33
|
+
}>>;
|
|
34
|
+
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
35
|
+
idempotent: z.ZodOptional<z.ZodBoolean>;
|
|
36
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
37
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
38
|
+
code: z.ZodOptional<z.ZodUnknown>;
|
|
39
|
+
run: z.ZodOptional<z.ZodUnknown>;
|
|
40
|
+
runner: z.ZodOptional<z.ZodUnknown>;
|
|
41
|
+
secrets: z.ZodOptional<z.ZodUnknown>;
|
|
42
|
+
network: z.ZodOptional<z.ZodUnknown>;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
type ToolManifestFrontmatter = z.infer<typeof toolManifestFrontmatterSchema>;
|
|
45
|
+
interface ToolManifest {
|
|
46
|
+
frontmatter: ToolManifestFrontmatter;
|
|
47
|
+
body: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Parse a TOOL.md source string into structured frontmatter + body.
|
|
51
|
+
* Throws on missing frontmatter or schema-invalid frontmatter.
|
|
52
|
+
*/
|
|
53
|
+
declare function parseToolManifest(source: string): ToolManifest;
|
|
54
|
+
/**
|
|
55
|
+
* Build a fully-typed {@link ToolHandle} from a parsed `TOOL.md` manifest
|
|
56
|
+
* + caller-supplied schemas. The .md is the single source of truth for
|
|
57
|
+
* metadata (id, name, description, version, mutates, approval, …); the
|
|
58
|
+
* schemas live in the TS module that ships alongside the .md.
|
|
59
|
+
*
|
|
60
|
+
* Both inputs are revalidated by `defineTool`'s shared invariants
|
|
61
|
+
* (id pattern, description length, top-level freeze) — `parseToolManifest`
|
|
62
|
+
* already enforces a stricter id pattern + version semver, so a
|
|
63
|
+
* well-formed manifest passes through cleanly. Mismatches between the
|
|
64
|
+
* manifest's id-shape and `defineTool`'s pattern surface a
|
|
65
|
+
* descriptive error from the same validation pipeline as the TS path.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* const manifest = parseToolManifest(readFileSync("./echo/TOOL.md", "utf8"))
|
|
69
|
+
* const echo = toolFromManifest({
|
|
70
|
+
* manifest,
|
|
71
|
+
* inputSchema: z.object({ msg: z.string() }),
|
|
72
|
+
* outputSchema: z.object({ msg: z.string() }),
|
|
73
|
+
* })
|
|
74
|
+
*/
|
|
75
|
+
declare function toolFromManifest<TInput, TOutput, TContext extends ToolContext = ToolContext>(args: {
|
|
76
|
+
manifest: ToolManifest;
|
|
77
|
+
inputSchema: ZodType<TInput>;
|
|
78
|
+
outputSchema: ZodType<TOutput>;
|
|
79
|
+
contextSchema?: ZodType<TContext>;
|
|
80
|
+
}): ToolHandle<TInput, TOutput, TContext>;
|
|
81
|
+
|
|
82
|
+
export { type ToolManifest, type ToolManifestFrontmatter, parseToolManifest, toolFromManifest, toolManifestFrontmatterSchema };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.mjs"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { ZodType } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AIP-14 ToolDefinition — the abstract agent contract.
|
|
5
|
+
*
|
|
6
|
+
* Field set mirrors `TOOL.md` frontmatter so a manifest and a TS
|
|
7
|
+
* module are interchangeable inputs to the runtime. The contract
|
|
8
|
+
* carries identity, schemas, side-effect profile, approval class,
|
|
9
|
+
* and resource budget — but **not** the body. Bodies live on
|
|
10
|
+
* AIP-30 PROVIDER manifests + their `execute[<toolId>]` entries.
|
|
11
|
+
*
|
|
12
|
+
* Generic over context: tools that depend on host-injected state
|
|
13
|
+
* (database connections, governance config, …) declare a
|
|
14
|
+
* `contextSchema` — analogous to `inputSchema` but for the per-call
|
|
15
|
+
* context object — and the host validates context against it before
|
|
16
|
+
* dispatching to the resolved provider's body.
|
|
17
|
+
*/
|
|
18
|
+
interface ToolDefinition<TInput = unknown, TOutput = unknown, TContext extends ToolContext = ToolContext> {
|
|
19
|
+
/** Machine identifier. Lowercase, digits, dashes, dots. 2–80 chars. */
|
|
20
|
+
id: string;
|
|
21
|
+
/** Human-readable display name. Optional; falls back to `id`. */
|
|
22
|
+
name?: string;
|
|
23
|
+
/** One-paragraph purpose, written for the LLM caller. */
|
|
24
|
+
description: string;
|
|
25
|
+
/** Spec version of THIS tool (semver). */
|
|
26
|
+
version?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Input shape — zod schema in v0.1. Hosts validate args.input against
|
|
29
|
+
* it before dispatching to the resolved provider; bodies MUST NOT
|
|
30
|
+
* re-validate.
|
|
31
|
+
*
|
|
32
|
+
* v0.2 will also accept JSON Schema directly.
|
|
33
|
+
*/
|
|
34
|
+
inputSchema: ZodType<TInput>;
|
|
35
|
+
outputSchema: ZodType<TOutput>;
|
|
36
|
+
/**
|
|
37
|
+
* Optional context schema. When provided, the host validates
|
|
38
|
+
* `args.context` against it before dispatching to the provider,
|
|
39
|
+
* rejecting with `input_invalid` (field=`context`) on mismatch.
|
|
40
|
+
* Providers receive the narrowed, typed context.
|
|
41
|
+
*/
|
|
42
|
+
contextSchema?: ZodType<TContext>;
|
|
43
|
+
/** Resources the tool may modify. Format: `<class>:<scope>`. */
|
|
44
|
+
mutates?: readonly string[];
|
|
45
|
+
/** Capability requirements (governance/gating per AIP-7). */
|
|
46
|
+
requires?: ToolCapabilities;
|
|
47
|
+
approval?: ApprovalClass;
|
|
48
|
+
riskLevel?: 0 | 1 | 2 | 3;
|
|
49
|
+
costClass?: "trivial" | "metered" | "expensive";
|
|
50
|
+
/** Hard wall-clock contract ceiling. Providers MAY narrow; never widen. */
|
|
51
|
+
timeoutMs?: number;
|
|
52
|
+
retry?: RetryPolicy;
|
|
53
|
+
/** Free-form discovery tags. */
|
|
54
|
+
tags?: readonly string[];
|
|
55
|
+
/** Free-form metadata under namespaced keys (`mastra.…`, `langchain.…`). */
|
|
56
|
+
metadata?: Record<string, unknown>;
|
|
57
|
+
/** Whether retries are observably free of extra effect. Defaults to `false`. */
|
|
58
|
+
idempotent?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Optional pin for the canonical provider. The AIP-30 resolver uses
|
|
61
|
+
* this in Phase 5 (cost ranking) when no other signal differentiates
|
|
62
|
+
* candidates. Null/undefined = pick by resolver policy.
|
|
63
|
+
*/
|
|
64
|
+
defaultImplementation?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Author-side allowlist/denylist on which provider kinds the contract
|
|
67
|
+
* permits. Use to express "this tool MUST NOT be served via untrusted
|
|
68
|
+
* HTTP" (`forbid: ["http"]`) for self-hosted-only contracts.
|
|
69
|
+
*/
|
|
70
|
+
driverConstraints?: DriverConstraints;
|
|
71
|
+
}
|
|
72
|
+
type DriverKind = "cli" | "http" | "mcp" | "sdk" | "builtin";
|
|
73
|
+
interface DriverConstraints {
|
|
74
|
+
/** Provider kinds the contract refuses. */
|
|
75
|
+
forbid?: readonly DriverKind[];
|
|
76
|
+
/** Whitelist of allowed provider kinds. Empty/missing = all permitted. */
|
|
77
|
+
requireKind?: readonly DriverKind[];
|
|
78
|
+
}
|
|
79
|
+
type ToolContext = Record<string, unknown> & {
|
|
80
|
+
signal?: AbortSignal;
|
|
81
|
+
};
|
|
82
|
+
type ApprovalClass = "auto" | "always" | "on-mutate" | `policy:${string}`;
|
|
83
|
+
interface ToolCapabilities {
|
|
84
|
+
network?: readonly string[];
|
|
85
|
+
secrets?: readonly string[];
|
|
86
|
+
tools?: readonly string[];
|
|
87
|
+
}
|
|
88
|
+
interface RetryPolicy {
|
|
89
|
+
maxAttempts: number;
|
|
90
|
+
backoff: "fixed" | "exponential";
|
|
91
|
+
initialMs: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The host-registrable contract handle returned by `defineTool`.
|
|
95
|
+
*
|
|
96
|
+
* Adapters (`toMastraTool`, …) AND provider runtimes (`http-runtime`,
|
|
97
|
+
* `cli-runtime`, …) consume this shape. The handle does **not** carry
|
|
98
|
+
* an invoke method — invocation goes through provider-runtime, which
|
|
99
|
+
* resolves a provider per call and dispatches to its `execute[id]`.
|
|
100
|
+
*/
|
|
101
|
+
interface ToolHandle<TInput = unknown, TOutput = unknown, TContext extends ToolContext = ToolContext> {
|
|
102
|
+
readonly id: string;
|
|
103
|
+
readonly name: string;
|
|
104
|
+
readonly description: string;
|
|
105
|
+
readonly version?: string;
|
|
106
|
+
readonly inputSchema: ZodType<TInput>;
|
|
107
|
+
readonly outputSchema: ZodType<TOutput>;
|
|
108
|
+
readonly contextSchema?: ZodType<TContext>;
|
|
109
|
+
readonly mutates: readonly string[];
|
|
110
|
+
readonly requires: ToolCapabilities;
|
|
111
|
+
readonly approval: ApprovalClass;
|
|
112
|
+
readonly riskLevel: 0 | 1 | 2 | 3;
|
|
113
|
+
readonly costClass: "trivial" | "metered" | "expensive";
|
|
114
|
+
readonly timeoutMs: number;
|
|
115
|
+
readonly retry?: RetryPolicy;
|
|
116
|
+
readonly tags: readonly string[];
|
|
117
|
+
readonly metadata: Record<string, unknown>;
|
|
118
|
+
readonly idempotent: boolean;
|
|
119
|
+
readonly defaultImplementation?: string;
|
|
120
|
+
readonly driverConstraints: Required<DriverConstraints>;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Standard out-of-band result envelope. Provider runtimes wrap thrown
|
|
124
|
+
* errors into this shape; consumers consume `ToolResult<T>` rather than
|
|
125
|
+
* `Promise<T>`.
|
|
126
|
+
*/
|
|
127
|
+
type ToolResult<T> = {
|
|
128
|
+
ok: true;
|
|
129
|
+
value: T;
|
|
130
|
+
} | {
|
|
131
|
+
ok: false;
|
|
132
|
+
error: {
|
|
133
|
+
code: string;
|
|
134
|
+
message: string;
|
|
135
|
+
retryable?: boolean;
|
|
136
|
+
cause?: unknown;
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Validation helpers exposed for provider-runtime to reuse the same
|
|
141
|
+
* input/output/context validation logic AIP-14 prescribes. Provider
|
|
142
|
+
* runtimes MUST validate args.input against `tool.inputSchema` and
|
|
143
|
+
* (when declared) args.context against `tool.contextSchema` BEFORE
|
|
144
|
+
* dispatching to a provider's body.
|
|
145
|
+
*/
|
|
146
|
+
interface ValidationFailure {
|
|
147
|
+
ok: false;
|
|
148
|
+
error: {
|
|
149
|
+
code: "input_invalid";
|
|
150
|
+
message: string;
|
|
151
|
+
field?: string;
|
|
152
|
+
cause?: unknown;
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
interface ValidationSuccess<T> {
|
|
156
|
+
ok: true;
|
|
157
|
+
value: T;
|
|
158
|
+
}
|
|
159
|
+
type ValidationResult<T> = ValidationSuccess<T> | ValidationFailure;
|
|
160
|
+
|
|
161
|
+
export type { ApprovalClass as A, DriverConstraints as D, RetryPolicy as R, ToolContext as T, ValidationResult as V, ToolDefinition as a, ToolHandle as b, ToolResult as c, DriverKind as d, ToolCapabilities as e, ValidationFailure as f, ValidationSuccess as g };
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentproto/tool",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "agentproto/tool-runtime — reference implementation of AIP-14 TOOL.md `defineTool` contract. Vendor-neutral tool registration with validated input/output schemas, structured error envelopes, and side-effect declarations. Per-framework adapters (Mastra, LangChain, A2A) consume the produced ToolHandle.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agentproto",
|
|
7
|
+
"aip-14",
|
|
8
|
+
"tool",
|
|
9
|
+
"tool-runtime",
|
|
10
|
+
"defineTool",
|
|
11
|
+
"open-standard",
|
|
12
|
+
"agentic"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://agentik.net/docs/aip-14",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/agentproto/ts"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/agentproto/ts/issues"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "dist/index.mjs",
|
|
25
|
+
"module": "dist/index.mjs",
|
|
26
|
+
"types": "dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.mjs",
|
|
31
|
+
"default": "./dist/index.mjs"
|
|
32
|
+
},
|
|
33
|
+
"./manifest": {
|
|
34
|
+
"types": "./dist/manifest/index.d.ts",
|
|
35
|
+
"import": "./dist/manifest/index.mjs",
|
|
36
|
+
"default": "./dist/manifest/index.mjs"
|
|
37
|
+
},
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"README.md",
|
|
43
|
+
"LICENSE"
|
|
44
|
+
],
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"ajv": "^8.20.0",
|
|
50
|
+
"gray-matter": "^4.0.3",
|
|
51
|
+
"zod": "^4.4.3",
|
|
52
|
+
"@agentproto/define-doctype": "0.1.0",
|
|
53
|
+
"@agentproto/manifest": "0.2.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/node": "^25.6.2",
|
|
57
|
+
"tsup": "^8.5.1",
|
|
58
|
+
"typescript": "^5.9.3",
|
|
59
|
+
"vitest": "^3.2.4",
|
|
60
|
+
"@agentproto/tooling": "0.1.0-alpha.0"
|
|
61
|
+
},
|
|
62
|
+
"scripts": {
|
|
63
|
+
"dev": "tsup --watch",
|
|
64
|
+
"build": "tsup",
|
|
65
|
+
"clean": "rm -rf dist",
|
|
66
|
+
"check-types": "tsc --noEmit",
|
|
67
|
+
"test": "vitest run",
|
|
68
|
+
"test:watch": "vitest"
|
|
69
|
+
}
|
|
70
|
+
}
|