@agent-wire/terminal 1.7.2 → 1.7.4
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/README.md +11 -0
- package/dist/api.d.ts +2 -1
- package/dist/api.js +2 -2
- package/dist/api.js.map +1 -1
- package/dist/cli.js +49 -8
- package/dist/cli.js.map +1 -1
- package/dist/mcp-server.js +208 -306
- package/dist/mcp-server.js.map +1 -1
- package/dist/tool-projection.d.ts +58 -0
- package/dist/tool-projection.js +144 -0
- package/dist/tool-projection.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool projection — core MCP tools self-populate from graph-published
|
|
3
|
+
* tool_definition contributions (capability published, not released).
|
|
4
|
+
*
|
|
5
|
+
* The package ships this projection runtime, not a tool catalog. Each
|
|
6
|
+
* projected tool's name, description, and full parameter schema come from
|
|
7
|
+
* a `tool_definition` contribution; a capability change is a supersession
|
|
8
|
+
* of that contribution and reaches running agents via wire_refresh_tools —
|
|
9
|
+
* no npm release, no re-pin.
|
|
10
|
+
*
|
|
11
|
+
* Design: playful/159/2964. Bindings:
|
|
12
|
+
* - api_method: invoke a named WireAPI method with the tool params
|
|
13
|
+
* (transport semantics — timeouts, unwrapping — stay in the adapter).
|
|
14
|
+
* - http_api: generic request(method, path, params).
|
|
15
|
+
*/
|
|
16
|
+
import { type ZodTypeAny, type ZodRawShape } from 'zod';
|
|
17
|
+
export interface ToolDefinitionBinding {
|
|
18
|
+
kind: 'api_method' | 'http_api';
|
|
19
|
+
/** api_method: WireAPI method name to call with the tool params. */
|
|
20
|
+
method?: string;
|
|
21
|
+
/** http_api: HTTP verb. */
|
|
22
|
+
http_method?: string;
|
|
23
|
+
/** http_api: request path relative to the API root. */
|
|
24
|
+
path?: string;
|
|
25
|
+
/** http_api: where params go. Defaults to body for non-GET, query for GET. */
|
|
26
|
+
params?: 'body' | 'query';
|
|
27
|
+
}
|
|
28
|
+
export interface ToolDefinition {
|
|
29
|
+
toolName: string;
|
|
30
|
+
description: string;
|
|
31
|
+
parameterSchema: Record<string, unknown>;
|
|
32
|
+
binding: ToolDefinitionBinding;
|
|
33
|
+
/** identity = wire_identify done; confirmed = operator-verified agent. */
|
|
34
|
+
gate: 'identity' | 'confirmed';
|
|
35
|
+
configHandle?: string;
|
|
36
|
+
schemaVersion: number;
|
|
37
|
+
}
|
|
38
|
+
interface ToolDefinitionWireItem {
|
|
39
|
+
type?: string;
|
|
40
|
+
title?: string;
|
|
41
|
+
handle_path?: string;
|
|
42
|
+
structured_data?: Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* JSON Schema → zod raw shape, degrade-open.
|
|
46
|
+
*
|
|
47
|
+
* Converts the subset used by tool_definition parameter schemas. Anything
|
|
48
|
+
* unrecognized degrades to z.unknown() passthrough: a published schema must
|
|
49
|
+
* never client-block a call the server would accept — the server's own
|
|
50
|
+
* validation is the source of truth (a strict client enum lagging the server
|
|
51
|
+
* is the exact defect this module exists to remove).
|
|
52
|
+
*/
|
|
53
|
+
export declare function jsonSchemaToZodType(schema: unknown): ZodTypeAny;
|
|
54
|
+
export declare function jsonSchemaToZodShape(schema: unknown): ZodRawShape;
|
|
55
|
+
export declare function parseToolDefinition(item: ToolDefinitionWireItem): ToolDefinition | null;
|
|
56
|
+
export declare function dedupeToolDefinitions(defs: ToolDefinition[]): ToolDefinition[];
|
|
57
|
+
export declare function fingerprintToolDefinitions(defs: ToolDefinition[]): string;
|
|
58
|
+
export {};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool projection — core MCP tools self-populate from graph-published
|
|
3
|
+
* tool_definition contributions (capability published, not released).
|
|
4
|
+
*
|
|
5
|
+
* The package ships this projection runtime, not a tool catalog. Each
|
|
6
|
+
* projected tool's name, description, and full parameter schema come from
|
|
7
|
+
* a `tool_definition` contribution; a capability change is a supersession
|
|
8
|
+
* of that contribution and reaches running agents via wire_refresh_tools —
|
|
9
|
+
* no npm release, no re-pin.
|
|
10
|
+
*
|
|
11
|
+
* Design: playful/159/2964. Bindings:
|
|
12
|
+
* - api_method: invoke a named WireAPI method with the tool params
|
|
13
|
+
* (transport semantics — timeouts, unwrapping — stay in the adapter).
|
|
14
|
+
* - http_api: generic request(method, path, params).
|
|
15
|
+
*/
|
|
16
|
+
import { createHash } from 'crypto';
|
|
17
|
+
import { z } from 'zod';
|
|
18
|
+
/**
|
|
19
|
+
* JSON Schema → zod raw shape, degrade-open.
|
|
20
|
+
*
|
|
21
|
+
* Converts the subset used by tool_definition parameter schemas. Anything
|
|
22
|
+
* unrecognized degrades to z.unknown() passthrough: a published schema must
|
|
23
|
+
* never client-block a call the server would accept — the server's own
|
|
24
|
+
* validation is the source of truth (a strict client enum lagging the server
|
|
25
|
+
* is the exact defect this module exists to remove).
|
|
26
|
+
*/
|
|
27
|
+
export function jsonSchemaToZodType(schema) {
|
|
28
|
+
if (schema === null || typeof schema !== 'object' || Array.isArray(schema))
|
|
29
|
+
return z.unknown();
|
|
30
|
+
const node = schema;
|
|
31
|
+
if (Array.isArray(node.enum)) {
|
|
32
|
+
const values = node.enum;
|
|
33
|
+
if (values.length > 0 && values.every((v) => typeof v === 'string')) {
|
|
34
|
+
return z.enum(values);
|
|
35
|
+
}
|
|
36
|
+
return z.unknown();
|
|
37
|
+
}
|
|
38
|
+
switch (node.type) {
|
|
39
|
+
case 'string':
|
|
40
|
+
return z.string();
|
|
41
|
+
case 'number':
|
|
42
|
+
return z.number();
|
|
43
|
+
case 'integer':
|
|
44
|
+
return z.number().int();
|
|
45
|
+
case 'boolean':
|
|
46
|
+
return z.boolean();
|
|
47
|
+
case 'array': {
|
|
48
|
+
const items = node.items !== undefined ? jsonSchemaToZodType(node.items) : z.unknown();
|
|
49
|
+
return z.array(items);
|
|
50
|
+
}
|
|
51
|
+
case 'object': {
|
|
52
|
+
if (node.properties && typeof node.properties === 'object') {
|
|
53
|
+
return z.object(jsonSchemaToZodShape(node)).passthrough();
|
|
54
|
+
}
|
|
55
|
+
return z.record(z.unknown());
|
|
56
|
+
}
|
|
57
|
+
default:
|
|
58
|
+
return z.unknown();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export function jsonSchemaToZodShape(schema) {
|
|
62
|
+
const shape = {};
|
|
63
|
+
if (schema === null || typeof schema !== 'object')
|
|
64
|
+
return shape;
|
|
65
|
+
const node = schema;
|
|
66
|
+
const properties = node.properties && typeof node.properties === 'object'
|
|
67
|
+
? node.properties
|
|
68
|
+
: {};
|
|
69
|
+
const required = new Set(Array.isArray(node.required) ? node.required : []);
|
|
70
|
+
for (const [key, propSchema] of Object.entries(properties)) {
|
|
71
|
+
let type = jsonSchemaToZodType(propSchema);
|
|
72
|
+
const description = propSchema && typeof propSchema === 'object' && typeof propSchema.description === 'string'
|
|
73
|
+
? propSchema.description
|
|
74
|
+
: undefined;
|
|
75
|
+
if (description)
|
|
76
|
+
type = type.describe(description);
|
|
77
|
+
shape[key] = required.has(key) ? type : type.optional();
|
|
78
|
+
}
|
|
79
|
+
return shape;
|
|
80
|
+
}
|
|
81
|
+
export function parseToolDefinition(item) {
|
|
82
|
+
const data = item.structured_data ?? {};
|
|
83
|
+
if (data.type !== 'tool_definition' && item.type !== 'tool_definition')
|
|
84
|
+
return null;
|
|
85
|
+
const toolName = typeof data.tool_name === 'string' ? data.tool_name.trim() : '';
|
|
86
|
+
if (!/^[a-z][a-z0-9_]*$/.test(toolName))
|
|
87
|
+
return null;
|
|
88
|
+
const parameterSchema = data.parameter_schema && typeof data.parameter_schema === 'object' && !Array.isArray(data.parameter_schema)
|
|
89
|
+
? data.parameter_schema
|
|
90
|
+
: null;
|
|
91
|
+
if (!parameterSchema)
|
|
92
|
+
return null;
|
|
93
|
+
const rawBinding = data.binding && typeof data.binding === 'object' && !Array.isArray(data.binding)
|
|
94
|
+
? data.binding
|
|
95
|
+
: null;
|
|
96
|
+
if (!rawBinding)
|
|
97
|
+
return null;
|
|
98
|
+
let binding;
|
|
99
|
+
if (rawBinding.kind === 'api_method' && typeof rawBinding.method === 'string' && rawBinding.method.trim()) {
|
|
100
|
+
binding = { kind: 'api_method', method: rawBinding.method.trim() };
|
|
101
|
+
}
|
|
102
|
+
else if (rawBinding.kind === 'http_api' && typeof rawBinding.path === 'string' && rawBinding.path.trim()) {
|
|
103
|
+
binding = {
|
|
104
|
+
kind: 'http_api',
|
|
105
|
+
http_method: typeof rawBinding.method === 'string' ? rawBinding.method.toUpperCase() : 'POST',
|
|
106
|
+
path: rawBinding.path.trim(),
|
|
107
|
+
params: rawBinding.params === 'query' ? 'query' : 'body',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
toolName,
|
|
115
|
+
description: typeof data.description === 'string' ? data.description : (item.title ?? toolName),
|
|
116
|
+
parameterSchema,
|
|
117
|
+
binding,
|
|
118
|
+
gate: data.gate === 'identity' ? 'identity' : 'confirmed',
|
|
119
|
+
configHandle: item.handle_path,
|
|
120
|
+
schemaVersion: typeof data.schema_version === 'number' ? data.schema_version : 1,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
export function dedupeToolDefinitions(defs) {
|
|
124
|
+
// Query results arrive newest-first; the FIRST definition per tool_name is
|
|
125
|
+
// the live head (a supersession must win over its predecessor).
|
|
126
|
+
const byName = new Map();
|
|
127
|
+
for (const def of defs) {
|
|
128
|
+
if (!byName.has(def.toolName))
|
|
129
|
+
byName.set(def.toolName, def);
|
|
130
|
+
}
|
|
131
|
+
return Array.from(byName.values()).sort((a, b) => a.toolName.localeCompare(b.toolName));
|
|
132
|
+
}
|
|
133
|
+
export function fingerprintToolDefinitions(defs) {
|
|
134
|
+
const projected = defs.map((def) => ({
|
|
135
|
+
toolName: def.toolName,
|
|
136
|
+
description: def.description,
|
|
137
|
+
parameterSchema: def.parameterSchema,
|
|
138
|
+
binding: def.binding,
|
|
139
|
+
gate: def.gate,
|
|
140
|
+
configHandle: def.configHandle ?? null,
|
|
141
|
+
}));
|
|
142
|
+
return createHash('sha256').update(JSON.stringify(projected)).digest('hex');
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=tool-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-projection.js","sourceRoot":"","sources":["../src/tool-projection.ts"],"names":[],"mappings":"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"}
|