243 lines
8.6 KiB
TypeScript
243 lines
8.6 KiB
TypeScript
/**
|
|
* Zod input schemas for all 20 ADR-124 MCP tools.
|
|
*
|
|
* §4.1 — 15 sensing tools (presence, vitals, pose, primitives, bfld, node, vector)
|
|
* §4.1a — 5 policy / governance tools (RUVIEW-POLICY)
|
|
*
|
|
* Each exported schema is named `<CamelCase>InputSchema` matching the tool
|
|
* name from the ADR-124 §4.1 catalog table. The parallel `TOOL_NAMES` array
|
|
* is the single source of truth asserted by the schema-coverage test.
|
|
*/
|
|
|
|
import { z } from "zod";
|
|
import {
|
|
NodeIdSchema,
|
|
DurationSSchema,
|
|
WindowSSchema,
|
|
SemanticPrimitiveKindSchema,
|
|
PosePersonResultSchema,
|
|
} from "./common.js";
|
|
|
|
// ── §4.1 Presence ──────────────────────────────────────────────────────────
|
|
|
|
/** ruview.presence.now */
|
|
export const PresenceNowInputSchema = z.object({
|
|
node_id: NodeIdSchema,
|
|
});
|
|
|
|
// ── §4.1 Vitals ───────────────────────────────────────────────────────────
|
|
|
|
/** ruview.vitals.get_breathing */
|
|
export const VitalsGetBreathingInputSchema = z.object({
|
|
node_id: NodeIdSchema,
|
|
window_s: WindowSSchema,
|
|
});
|
|
|
|
/** ruview.vitals.get_heart_rate */
|
|
export const VitalsGetHeartRateInputSchema = z.object({
|
|
node_id: NodeIdSchema,
|
|
window_s: WindowSSchema,
|
|
});
|
|
|
|
/** ruview.vitals.get_all */
|
|
export const VitalsGetAllInputSchema = z.object({
|
|
node_id: NodeIdSchema,
|
|
});
|
|
|
|
// ── §4.1 Pose ─────────────────────────────────────────────────────────────
|
|
|
|
/** ruview.pose.latest */
|
|
export const PoseLatestInputSchema = z.object({
|
|
node_id: NodeIdSchema,
|
|
});
|
|
|
|
/** ruview.pose.subscribe */
|
|
export const PoseSubscribeInputSchema = z.object({
|
|
node_id: NodeIdSchema,
|
|
duration_s: DurationSSchema,
|
|
callback_url: z
|
|
.string()
|
|
.url()
|
|
.optional()
|
|
.describe("Webhook URL to receive PoseDataMessage events (optional)."),
|
|
});
|
|
|
|
// ── §4.1 Primitives ───────────────────────────────────────────────────────
|
|
|
|
/** ruview.primitives.get */
|
|
export const PrimitivesGetInputSchema = z.object({
|
|
node_id: NodeIdSchema,
|
|
primitive: SemanticPrimitiveKindSchema,
|
|
});
|
|
|
|
/** ruview.primitives.list_active */
|
|
export const PrimitivesListActiveInputSchema = z.object({
|
|
node_id: NodeIdSchema,
|
|
});
|
|
|
|
/** ruview.primitives.subscribe */
|
|
export const PrimitivesSubscribeInputSchema = z.object({
|
|
node_id: NodeIdSchema,
|
|
primitive: SemanticPrimitiveKindSchema.optional().describe(
|
|
"Subscribe to a specific primitive. Omit to receive all active primitives."
|
|
),
|
|
duration_s: DurationSSchema,
|
|
});
|
|
|
|
// ── §4.1 BFLD ────────────────────────────────────────────────────────────
|
|
|
|
/** ruview.bfld.last_scan */
|
|
export const BfldLastScanInputSchema = z.object({
|
|
node_id: NodeIdSchema,
|
|
});
|
|
|
|
/** ruview.bfld.subscribe */
|
|
export const BfldSubscribeInputSchema = z.object({
|
|
node_id: NodeIdSchema,
|
|
duration_s: DurationSSchema,
|
|
});
|
|
|
|
// ── §4.1 Node ────────────────────────────────────────────────────────────
|
|
|
|
/** ruview.node.list — empty input per ADR-124 §4.1 table */
|
|
export const NodeListInputSchema = z.object({});
|
|
|
|
/** ruview.node.status */
|
|
export const NodeStatusInputSchema = z.object({
|
|
node_id: z.string().min(1).describe("Node id to query status for."),
|
|
});
|
|
|
|
// ── §4.1 Vector ──────────────────────────────────────────────────────────
|
|
|
|
/** ruview.vector.search_pose */
|
|
export const VectorSearchPoseInputSchema = z.object({
|
|
query_embedding: z
|
|
.array(z.number())
|
|
.min(1)
|
|
.describe("Dense embedding vector to query against the HNSW index."),
|
|
k: z
|
|
.number()
|
|
.int()
|
|
.positive()
|
|
.max(100)
|
|
.optional()
|
|
.default(10)
|
|
.describe("Number of nearest neighbours to return (default 10, max 100)."),
|
|
node_id: NodeIdSchema,
|
|
});
|
|
|
|
/** ruview.vector.store_pose */
|
|
export const VectorStorePoseInputSchema = z.object({
|
|
pose: PosePersonResultSchema,
|
|
node_id: z.string().min(1).describe("Node id that observed this pose."),
|
|
});
|
|
|
|
// ── §4.1a Policy / governance tools ──────────────────────────────────────
|
|
|
|
/** ruview.policy.can_access_vitals */
|
|
export const PolicyCanAccessVitalsInputSchema = z.object({
|
|
agent_id: z.string().min(1).describe("Calling agent identifier."),
|
|
node_id: z.string().min(1).describe("Target sensing node."),
|
|
vital: z
|
|
.enum(["breathing", "heart_rate", "all"])
|
|
.describe("Which vital the agent is requesting."),
|
|
});
|
|
|
|
/** ruview.policy.can_query_presence */
|
|
export const PolicyCanQueryPresenceInputSchema = z.object({
|
|
agent_id: z.string().min(1),
|
|
scope: z
|
|
.enum(["node", "fleet"])
|
|
.describe("node = single node; fleet = all nodes / aggregated count."),
|
|
node_id: NodeIdSchema,
|
|
zone: z
|
|
.string()
|
|
.optional()
|
|
.describe("Named zone within a node (e.g. 'living_room')."),
|
|
});
|
|
|
|
/** ruview.policy.can_subscribe */
|
|
export const PolicyCanSubscribeInputSchema = z.object({
|
|
agent_id: z.string().min(1),
|
|
topic: z
|
|
.string()
|
|
.min(1)
|
|
.describe("MQTT topic or tool name the agent wishes to subscribe to."),
|
|
duration_s: DurationSSchema,
|
|
});
|
|
|
|
/** ruview.policy.redact_identity_fields */
|
|
export const PolicyRedactIdentityFieldsInputSchema = z.object({
|
|
payload: z.record(z.unknown()).describe("Tool return value to redact."),
|
|
agent_id: z.string().min(1),
|
|
});
|
|
|
|
/** ruview.policy.audit_log */
|
|
export const PolicyAuditLogInputSchema = z.object({
|
|
agent_id: z.string().optional().describe("Filter to a specific agent."),
|
|
since_ts: z
|
|
.number()
|
|
.optional()
|
|
.describe("Return events after this Unix timestamp (ms)."),
|
|
});
|
|
|
|
// ── Catalog ───────────────────────────────────────────────────────────────
|
|
|
|
/**
|
|
* Single source of truth: every tool name in the ADR-124 §4.1 + §4.1a catalog.
|
|
* The schema-coverage test asserts this list exactly matches the exported schemas.
|
|
*/
|
|
export const TOOL_NAMES = [
|
|
// §4.1 — 15 sensing tools
|
|
"ruview.presence.now",
|
|
"ruview.vitals.get_breathing",
|
|
"ruview.vitals.get_heart_rate",
|
|
"ruview.vitals.get_all",
|
|
"ruview.pose.latest",
|
|
"ruview.pose.subscribe",
|
|
"ruview.primitives.get",
|
|
"ruview.primitives.list_active",
|
|
"ruview.primitives.subscribe",
|
|
"ruview.bfld.last_scan",
|
|
"ruview.bfld.subscribe",
|
|
"ruview.node.list",
|
|
"ruview.node.status",
|
|
"ruview.vector.search_pose",
|
|
"ruview.vector.store_pose",
|
|
// §4.1a — 5 policy tools
|
|
"ruview.policy.can_access_vitals",
|
|
"ruview.policy.can_query_presence",
|
|
"ruview.policy.can_subscribe",
|
|
"ruview.policy.redact_identity_fields",
|
|
"ruview.policy.audit_log",
|
|
] as const;
|
|
|
|
export type ToolName = (typeof TOOL_NAMES)[number];
|
|
|
|
/**
|
|
* Map from tool name → its Zod input schema. Used by the MCP server's
|
|
* CallTool handler for uniform schema-validation before dispatch.
|
|
*/
|
|
export const TOOL_INPUT_SCHEMAS: Record<ToolName, z.ZodTypeAny> = {
|
|
"ruview.presence.now": PresenceNowInputSchema,
|
|
"ruview.vitals.get_breathing": VitalsGetBreathingInputSchema,
|
|
"ruview.vitals.get_heart_rate": VitalsGetHeartRateInputSchema,
|
|
"ruview.vitals.get_all": VitalsGetAllInputSchema,
|
|
"ruview.pose.latest": PoseLatestInputSchema,
|
|
"ruview.pose.subscribe": PoseSubscribeInputSchema,
|
|
"ruview.primitives.get": PrimitivesGetInputSchema,
|
|
"ruview.primitives.list_active": PrimitivesListActiveInputSchema,
|
|
"ruview.primitives.subscribe": PrimitivesSubscribeInputSchema,
|
|
"ruview.bfld.last_scan": BfldLastScanInputSchema,
|
|
"ruview.bfld.subscribe": BfldSubscribeInputSchema,
|
|
"ruview.node.list": NodeListInputSchema,
|
|
"ruview.node.status": NodeStatusInputSchema,
|
|
"ruview.vector.search_pose": VectorSearchPoseInputSchema,
|
|
"ruview.vector.store_pose": VectorStorePoseInputSchema,
|
|
"ruview.policy.can_access_vitals": PolicyCanAccessVitalsInputSchema,
|
|
"ruview.policy.can_query_presence": PolicyCanQueryPresenceInputSchema,
|
|
"ruview.policy.can_subscribe": PolicyCanSubscribeInputSchema,
|
|
"ruview.policy.redact_identity_fields": PolicyRedactIdentityFieldsInputSchema,
|
|
"ruview.policy.audit_log": PolicyAuditLogInputSchema,
|
|
};
|