@namzu/sdk 0.4.2 → 0.4.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.
Files changed (310) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/advisory/context.test.d.ts +16 -0
  3. package/dist/advisory/context.test.d.ts.map +1 -0
  4. package/dist/advisory/context.test.js +92 -0
  5. package/dist/advisory/context.test.js.map +1 -0
  6. package/dist/advisory/evaluator.test.d.ts +34 -0
  7. package/dist/advisory/evaluator.test.d.ts.map +1 -0
  8. package/dist/advisory/evaluator.test.js +172 -0
  9. package/dist/advisory/evaluator.test.js.map +1 -0
  10. package/dist/advisory/executor.test.d.ts +35 -0
  11. package/dist/advisory/executor.test.d.ts.map +1 -0
  12. package/dist/advisory/executor.test.js +233 -0
  13. package/dist/advisory/executor.test.js.map +1 -0
  14. package/dist/advisory/registry.test.d.ts +16 -0
  15. package/dist/advisory/registry.test.d.ts.map +1 -0
  16. package/dist/advisory/registry.test.js +62 -0
  17. package/dist/advisory/registry.test.js.map +1 -0
  18. package/dist/bridge/a2a/agent-card.test.d.ts +24 -0
  19. package/dist/bridge/a2a/agent-card.test.d.ts.map +1 -0
  20. package/dist/bridge/a2a/agent-card.test.js +118 -0
  21. package/dist/bridge/a2a/agent-card.test.js.map +1 -0
  22. package/dist/bridge/a2a/mapper.test.d.ts +29 -0
  23. package/dist/bridge/a2a/mapper.test.d.ts.map +1 -0
  24. package/dist/bridge/a2a/mapper.test.js +265 -0
  25. package/dist/bridge/a2a/mapper.test.js.map +1 -0
  26. package/dist/bridge/a2a/message.test.d.ts +20 -0
  27. package/dist/bridge/a2a/message.test.d.ts.map +1 -0
  28. package/dist/bridge/a2a/message.test.js +116 -0
  29. package/dist/bridge/a2a/message.test.js.map +1 -0
  30. package/dist/bridge/a2a/task.test.d.ts +29 -0
  31. package/dist/bridge/a2a/task.test.d.ts.map +1 -0
  32. package/dist/bridge/a2a/task.test.js +198 -0
  33. package/dist/bridge/a2a/task.test.js.map +1 -0
  34. package/dist/bridge/mcp/connector/adapter.test.d.ts +27 -0
  35. package/dist/bridge/mcp/connector/adapter.test.d.ts.map +1 -0
  36. package/dist/bridge/mcp/connector/adapter.test.js +203 -0
  37. package/dist/bridge/mcp/connector/adapter.test.js.map +1 -0
  38. package/dist/bridge/sse/mapper.test.d.ts +27 -0
  39. package/dist/bridge/sse/mapper.test.d.ts.map +1 -0
  40. package/dist/bridge/sse/mapper.test.js +271 -0
  41. package/dist/bridge/sse/mapper.test.js.map +1 -0
  42. package/dist/bridge/tools/connector/adapter.d.ts +2 -2
  43. package/dist/bridge/tools/connector/adapter.test.d.ts +28 -0
  44. package/dist/bridge/tools/connector/adapter.test.d.ts.map +1 -0
  45. package/dist/bridge/tools/connector/adapter.test.js +182 -0
  46. package/dist/bridge/tools/connector/adapter.test.js.map +1 -0
  47. package/dist/bridge/tools/connector/definitions.test.d.ts +23 -0
  48. package/dist/bridge/tools/connector/definitions.test.d.ts.map +1 -0
  49. package/dist/bridge/tools/connector/definitions.test.js +158 -0
  50. package/dist/bridge/tools/connector/definitions.test.js.map +1 -0
  51. package/dist/bridge/tools/connector/router.test.d.ts +21 -0
  52. package/dist/bridge/tools/connector/router.test.d.ts.map +1 -0
  53. package/dist/bridge/tools/connector/router.test.js +139 -0
  54. package/dist/bridge/tools/connector/router.test.js.map +1 -0
  55. package/dist/bus/breaker.test.d.ts +41 -0
  56. package/dist/bus/breaker.test.d.ts.map +1 -0
  57. package/dist/bus/breaker.test.js +242 -0
  58. package/dist/bus/breaker.test.js.map +1 -0
  59. package/dist/bus/index.d.ts +3 -1
  60. package/dist/bus/index.d.ts.map +1 -1
  61. package/dist/bus/index.js +18 -11
  62. package/dist/bus/index.js.map +1 -1
  63. package/dist/bus/index.test.d.ts +25 -0
  64. package/dist/bus/index.test.d.ts.map +1 -0
  65. package/dist/bus/index.test.js +151 -0
  66. package/dist/bus/index.test.js.map +1 -0
  67. package/dist/bus/lock.test.d.ts +44 -0
  68. package/dist/bus/lock.test.d.ts.map +1 -0
  69. package/dist/bus/lock.test.js +226 -0
  70. package/dist/bus/lock.test.js.map +1 -0
  71. package/dist/bus/ownership.test.d.ts +26 -0
  72. package/dist/bus/ownership.test.d.ts.map +1 -0
  73. package/dist/bus/ownership.test.js +205 -0
  74. package/dist/bus/ownership.test.js.map +1 -0
  75. package/dist/config/runtime.d.ts +28 -28
  76. package/dist/connector/BaseConnector.test.d.ts +21 -0
  77. package/dist/connector/BaseConnector.test.d.ts.map +1 -0
  78. package/dist/connector/BaseConnector.test.js +108 -0
  79. package/dist/connector/BaseConnector.test.js.map +1 -0
  80. package/dist/connector/builtins/http.test.d.ts +30 -0
  81. package/dist/connector/builtins/http.test.d.ts.map +1 -0
  82. package/dist/connector/builtins/http.test.js +232 -0
  83. package/dist/connector/builtins/http.test.js.map +1 -0
  84. package/dist/connector/builtins/webhook.test.d.ts +20 -0
  85. package/dist/connector/builtins/webhook.test.d.ts.map +1 -0
  86. package/dist/connector/builtins/webhook.test.js +113 -0
  87. package/dist/connector/builtins/webhook.test.js.map +1 -0
  88. package/dist/connector/execution/factory.test.d.ts +16 -0
  89. package/dist/connector/execution/factory.test.d.ts.map +1 -0
  90. package/dist/connector/execution/factory.test.js +64 -0
  91. package/dist/connector/execution/factory.test.js.map +1 -0
  92. package/dist/connector/execution/remote.test.d.ts +16 -0
  93. package/dist/connector/execution/remote.test.d.ts.map +1 -0
  94. package/dist/connector/execution/remote.test.js +53 -0
  95. package/dist/connector/execution/remote.test.js.map +1 -0
  96. package/dist/connector/mcp/adapter.test.d.ts +34 -0
  97. package/dist/connector/mcp/adapter.test.d.ts.map +1 -0
  98. package/dist/connector/mcp/adapter.test.js +199 -0
  99. package/dist/connector/mcp/adapter.test.js.map +1 -0
  100. package/dist/probe/context.d.ts +8 -0
  101. package/dist/probe/context.d.ts.map +1 -0
  102. package/dist/probe/context.js +7 -0
  103. package/dist/probe/context.js.map +1 -0
  104. package/dist/probe/errors.d.ts +12 -0
  105. package/dist/probe/errors.d.ts.map +1 -0
  106. package/dist/probe/errors.js +21 -0
  107. package/dist/probe/errors.js.map +1 -0
  108. package/dist/probe/index.d.ts +5 -0
  109. package/dist/probe/index.d.ts.map +1 -0
  110. package/dist/probe/index.js +4 -0
  111. package/dist/probe/index.js.map +1 -0
  112. package/dist/probe/registry.d.ts +24 -0
  113. package/dist/probe/registry.d.ts.map +1 -0
  114. package/dist/probe/registry.js +228 -0
  115. package/dist/probe/registry.js.map +1 -0
  116. package/dist/probe/registry.test.d.ts +7 -0
  117. package/dist/probe/registry.test.d.ts.map +1 -0
  118. package/dist/probe/registry.test.js +310 -0
  119. package/dist/probe/registry.test.js.map +1 -0
  120. package/dist/provider/instrumentation.d.ts +9 -0
  121. package/dist/provider/instrumentation.d.ts.map +1 -0
  122. package/dist/provider/instrumentation.js +104 -0
  123. package/dist/provider/instrumentation.js.map +1 -0
  124. package/dist/provider/instrumentation.test.d.ts +2 -0
  125. package/dist/provider/instrumentation.test.d.ts.map +1 -0
  126. package/dist/provider/instrumentation.test.js +152 -0
  127. package/dist/provider/instrumentation.test.js.map +1 -0
  128. package/dist/public-runtime.d.ts +5 -0
  129. package/dist/public-runtime.d.ts.map +1 -1
  130. package/dist/public-runtime.js +4 -0
  131. package/dist/public-runtime.js.map +1 -1
  132. package/dist/public-types.d.ts +3 -0
  133. package/dist/public-types.d.ts.map +1 -1
  134. package/dist/rag/chunking.test.d.ts +20 -0
  135. package/dist/rag/chunking.test.d.ts.map +1 -0
  136. package/dist/rag/chunking.test.js +92 -0
  137. package/dist/rag/chunking.test.js.map +1 -0
  138. package/dist/rag/context-assembler.test.d.ts +19 -0
  139. package/dist/rag/context-assembler.test.d.ts.map +1 -0
  140. package/dist/rag/context-assembler.test.js +98 -0
  141. package/dist/rag/context-assembler.test.js.map +1 -0
  142. package/dist/rag/embedding.test.d.ts +19 -0
  143. package/dist/rag/embedding.test.d.ts.map +1 -0
  144. package/dist/rag/embedding.test.js +115 -0
  145. package/dist/rag/embedding.test.js.map +1 -0
  146. package/dist/rag/ingestion.test.d.ts +22 -0
  147. package/dist/rag/ingestion.test.d.ts.map +1 -0
  148. package/dist/rag/ingestion.test.js +99 -0
  149. package/dist/rag/ingestion.test.js.map +1 -0
  150. package/dist/rag/knowledge-base.test.d.ts +17 -0
  151. package/dist/rag/knowledge-base.test.d.ts.map +1 -0
  152. package/dist/rag/knowledge-base.test.js +77 -0
  153. package/dist/rag/knowledge-base.test.js.map +1 -0
  154. package/dist/rag/rag-tool.test.d.ts +21 -0
  155. package/dist/rag/rag-tool.test.d.ts.map +1 -0
  156. package/dist/rag/rag-tool.test.js +149 -0
  157. package/dist/rag/rag-tool.test.js.map +1 -0
  158. package/dist/rag/retriever.test.d.ts +26 -0
  159. package/dist/rag/retriever.test.d.ts.map +1 -0
  160. package/dist/rag/retriever.test.js +180 -0
  161. package/dist/rag/retriever.test.js.map +1 -0
  162. package/dist/rag/vector-store.test.d.ts +38 -0
  163. package/dist/rag/vector-store.test.d.ts.map +1 -0
  164. package/dist/rag/vector-store.test.js +175 -0
  165. package/dist/rag/vector-store.test.js.map +1 -0
  166. package/dist/registry/ManagedRegistry.test.d.ts +21 -0
  167. package/dist/registry/ManagedRegistry.test.d.ts.map +1 -0
  168. package/dist/registry/ManagedRegistry.test.js +98 -0
  169. package/dist/registry/ManagedRegistry.test.js.map +1 -0
  170. package/dist/registry/Registry.test.d.ts +18 -0
  171. package/dist/registry/Registry.test.d.ts.map +1 -0
  172. package/dist/registry/Registry.test.js +79 -0
  173. package/dist/registry/Registry.test.js.map +1 -0
  174. package/dist/registry/agent/definitions.test.d.ts +15 -0
  175. package/dist/registry/agent/definitions.test.d.ts.map +1 -0
  176. package/dist/registry/agent/definitions.test.js +84 -0
  177. package/dist/registry/agent/definitions.test.js.map +1 -0
  178. package/dist/registry/connector/definitions.test.d.ts +13 -0
  179. package/dist/registry/connector/definitions.test.d.ts.map +1 -0
  180. package/dist/registry/connector/definitions.test.js +41 -0
  181. package/dist/registry/connector/definitions.test.js.map +1 -0
  182. package/dist/registry/connector/scoped.test.d.ts +21 -0
  183. package/dist/registry/connector/scoped.test.d.ts.map +1 -0
  184. package/dist/registry/connector/scoped.test.js +115 -0
  185. package/dist/registry/connector/scoped.test.js.map +1 -0
  186. package/dist/registry/plugin/index.test.d.ts +12 -0
  187. package/dist/registry/plugin/index.test.d.ts.map +1 -0
  188. package/dist/registry/plugin/index.test.js +69 -0
  189. package/dist/registry/plugin/index.test.js.map +1 -0
  190. package/dist/registry/tool/execute.test.d.ts +42 -0
  191. package/dist/registry/tool/execute.test.d.ts.map +1 -0
  192. package/dist/registry/tool/execute.test.js +281 -0
  193. package/dist/registry/tool/execute.test.js.map +1 -0
  194. package/dist/runtime/query/events.d.ts +3 -1
  195. package/dist/runtime/query/events.d.ts.map +1 -1
  196. package/dist/runtime/query/events.js +6 -1
  197. package/dist/runtime/query/events.js.map +1 -1
  198. package/dist/runtime/query/executor.d.ts +3 -1
  199. package/dist/runtime/query/executor.d.ts.map +1 -1
  200. package/dist/runtime/query/executor.js +30 -1
  201. package/dist/runtime/query/executor.js.map +1 -1
  202. package/dist/runtime/query/iteration/phases/advisory.test.d.ts +42 -0
  203. package/dist/runtime/query/iteration/phases/advisory.test.d.ts.map +1 -0
  204. package/dist/runtime/query/iteration/phases/advisory.test.js +334 -0
  205. package/dist/runtime/query/iteration/phases/advisory.test.js.map +1 -0
  206. package/dist/test-setup.d.ts +22 -0
  207. package/dist/test-setup.d.ts.map +1 -0
  208. package/dist/test-setup.js +23 -0
  209. package/dist/test-setup.js.map +1 -0
  210. package/dist/types/bus/index.d.ts +46 -2
  211. package/dist/types/bus/index.d.ts.map +1 -1
  212. package/dist/types/doctor/check.d.ts +41 -0
  213. package/dist/types/doctor/check.d.ts.map +1 -0
  214. package/dist/types/doctor/check.js +2 -0
  215. package/dist/types/doctor/check.js.map +1 -0
  216. package/dist/types/doctor/index.d.ts +2 -0
  217. package/dist/types/doctor/index.d.ts.map +1 -0
  218. package/dist/types/doctor/index.js +2 -0
  219. package/dist/types/doctor/index.js.map +1 -0
  220. package/dist/types/probe/event-kind.d.ts +6 -0
  221. package/dist/types/probe/event-kind.d.ts.map +1 -0
  222. package/dist/types/probe/event-kind.js +2 -0
  223. package/dist/types/probe/event-kind.js.map +1 -0
  224. package/dist/types/probe/event-of.d.ts +5 -0
  225. package/dist/types/probe/event-of.d.ts.map +1 -0
  226. package/dist/types/probe/event-of.js +2 -0
  227. package/dist/types/probe/event-of.js.map +1 -0
  228. package/dist/types/probe/index.d.ts +4 -0
  229. package/dist/types/probe/index.d.ts.map +1 -0
  230. package/dist/types/probe/index.js +2 -0
  231. package/dist/types/probe/index.js.map +1 -0
  232. package/dist/types/probe/registry.d.ts +27 -0
  233. package/dist/types/probe/registry.d.ts.map +1 -0
  234. package/dist/types/probe/registry.js +2 -0
  235. package/dist/types/probe/registry.js.map +1 -0
  236. package/dist/utils/logger.d.ts +1 -1
  237. package/dist/utils/logger.d.ts.map +1 -1
  238. package/dist/utils/logger.js +5 -0
  239. package/dist/utils/logger.js.map +1 -1
  240. package/dist/vault/instrumentation.d.ts +11 -0
  241. package/dist/vault/instrumentation.d.ts.map +1 -0
  242. package/dist/vault/instrumentation.js +32 -0
  243. package/dist/vault/instrumentation.js.map +1 -0
  244. package/dist/vault/instrumentation.test.d.ts +2 -0
  245. package/dist/vault/instrumentation.test.d.ts.map +1 -0
  246. package/dist/vault/instrumentation.test.js +80 -0
  247. package/dist/vault/instrumentation.test.js.map +1 -0
  248. package/package.json +4 -1
  249. package/src/advisory/context.test.ts +109 -0
  250. package/src/advisory/evaluator.test.ts +192 -0
  251. package/src/advisory/executor.test.ts +272 -0
  252. package/src/advisory/registry.test.ts +75 -0
  253. package/src/bridge/a2a/agent-card.test.ts +140 -0
  254. package/src/bridge/a2a/mapper.test.ts +293 -0
  255. package/src/bridge/a2a/message.test.ts +138 -0
  256. package/src/bridge/a2a/task.test.ts +235 -0
  257. package/src/bridge/mcp/connector/adapter.test.ts +230 -0
  258. package/src/bridge/sse/mapper.test.ts +422 -0
  259. package/src/bridge/tools/connector/adapter.test.ts +224 -0
  260. package/src/bridge/tools/connector/definitions.test.ts +183 -0
  261. package/src/bridge/tools/connector/router.test.ts +159 -0
  262. package/src/bus/breaker.test.ts +274 -0
  263. package/src/bus/index.test.ts +183 -0
  264. package/src/bus/index.ts +21 -10
  265. package/src/bus/lock.test.ts +265 -0
  266. package/src/bus/ownership.test.ts +243 -0
  267. package/src/connector/BaseConnector.test.ts +130 -0
  268. package/src/connector/builtins/http.test.ts +290 -0
  269. package/src/connector/builtins/webhook.test.ts +138 -0
  270. package/src/connector/execution/factory.test.ts +75 -0
  271. package/src/connector/execution/remote.test.ts +63 -0
  272. package/src/connector/mcp/adapter.test.ts +249 -0
  273. package/src/probe/context.ts +14 -0
  274. package/src/probe/errors.ts +27 -0
  275. package/src/probe/index.ts +4 -0
  276. package/src/probe/registry.test.ts +480 -0
  277. package/src/probe/registry.ts +276 -0
  278. package/src/provider/instrumentation.test.ts +192 -0
  279. package/src/provider/instrumentation.ts +139 -0
  280. package/src/public-runtime.ts +17 -0
  281. package/src/public-types.ts +3 -0
  282. package/src/rag/chunking.test.ts +107 -0
  283. package/src/rag/context-assembler.test.ts +114 -0
  284. package/src/rag/embedding.test.ts +130 -0
  285. package/src/rag/ingestion.test.ts +114 -0
  286. package/src/rag/knowledge-base.test.ts +106 -0
  287. package/src/rag/rag-tool.test.ts +167 -0
  288. package/src/rag/retriever.test.ts +210 -0
  289. package/src/rag/vector-store.test.ts +196 -0
  290. package/src/registry/ManagedRegistry.test.ts +118 -0
  291. package/src/registry/Registry.test.ts +91 -0
  292. package/src/registry/agent/definitions.test.ts +100 -0
  293. package/src/registry/connector/definitions.test.ts +51 -0
  294. package/src/registry/connector/scoped.test.ts +129 -0
  295. package/src/registry/plugin/index.test.ts +85 -0
  296. package/src/registry/tool/execute.test.ts +330 -0
  297. package/src/runtime/query/events.ts +6 -1
  298. package/src/runtime/query/executor.ts +34 -0
  299. package/src/runtime/query/iteration/phases/advisory.test.ts +412 -0
  300. package/src/test-setup.ts +24 -0
  301. package/src/types/bus/index.ts +54 -2
  302. package/src/types/doctor/check.ts +53 -0
  303. package/src/types/doctor/index.ts +9 -0
  304. package/src/types/probe/event-kind.ts +8 -0
  305. package/src/types/probe/event-of.ts +3 -0
  306. package/src/types/probe/index.ts +11 -0
  307. package/src/types/probe/registry.ts +36 -0
  308. package/src/utils/logger.ts +6 -1
  309. package/src/vault/instrumentation.test.ts +98 -0
  310. package/src/vault/instrumentation.ts +56 -0
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Current-code invariants asserted (2026-04-21, ses_006 Phase 5):
3
+ *
4
+ * - `mcpJsonSchemaToZod(schema)`:
5
+ * - Empty / no-properties object → passthrough `z.object({})`.
6
+ * - Maps primitive types (string, number, integer, boolean, array,
7
+ * object) to zod equivalents.
8
+ * - Unknown / null property types → `z.unknown()`.
9
+ * - Fields not in `required[]` are `.optional()`.
10
+ * - `zodToMCPJsonSchema(zodSchema)` wraps `zodToJsonSchema` with
11
+ * `type: 'object'` prefixed.
12
+ * - `mcpToolToToolDefinition(tool, client, serverName)` produces a
13
+ * ToolDefinition:
14
+ * - name = `mcp_<server>_<tool.name>`
15
+ * - description prefixed `[MCP:<server>] <tool.description or name>`
16
+ * - category = 'network', permissions = ['network_access']
17
+ * - readOnly + destructive reflect MCP annotations; concurrency
18
+ * safe defaults to true.
19
+ * - `execute(input, ctx)` calls `client.callTool(tool.name, input)`
20
+ * and adapts the MCPToolResult.
21
+ * - `toolDefinitionToMCPTool(tool)` projects name/description +
22
+ * converts inputSchema + copies annotations.
23
+ * - `mcpToolResultToToolResult`:
24
+ * - success = !isError.
25
+ * - output = text content joined with '\n' (non-text blocks
26
+ * kept in `data` only).
27
+ * - error = same joined text when isError, else undefined.
28
+ * - `toolResultToMCPToolResult`:
29
+ * - success + output → single text block.
30
+ * - failure + error → single text block + isError.
31
+ * - Empty output on success → single empty-text block.
32
+ */
33
+
34
+ import { describe, expect, it, vi } from 'vitest'
35
+ import { z } from 'zod'
36
+
37
+ import type { MCPJsonSchema, MCPToolResult } from '../../types/connector/index.js'
38
+ import type { ToolContext, ToolDefinition, ToolResult } from '../../types/tool/index.js'
39
+
40
+ import {
41
+ mcpJsonSchemaToZod,
42
+ mcpToolResultToToolResult,
43
+ mcpToolToToolDefinition,
44
+ toolDefinitionToMCPTool,
45
+ toolResultToMCPToolResult,
46
+ zodToMCPJsonSchema,
47
+ } from './adapter.js'
48
+ import type { MCPClient } from './client.js'
49
+
50
+ function mockClient(result: MCPToolResult): MCPClient {
51
+ return {
52
+ callTool: vi.fn(async () => result),
53
+ } as unknown as MCPClient
54
+ }
55
+
56
+ describe('mcpJsonSchemaToZod', () => {
57
+ it('empty schema → passthrough empty object', () => {
58
+ const schema = mcpJsonSchemaToZod({ type: 'object' } as MCPJsonSchema)
59
+ expect(() => schema.parse({ extra: 'x' })).not.toThrow()
60
+ })
61
+
62
+ it('maps primitive types', () => {
63
+ const schema = mcpJsonSchemaToZod({
64
+ type: 'object',
65
+ required: ['s', 'n', 'b', 'arr', 'obj'],
66
+ properties: {
67
+ s: { type: 'string' },
68
+ n: { type: 'number' },
69
+ b: { type: 'boolean' },
70
+ arr: { type: 'array' },
71
+ obj: { type: 'object' },
72
+ },
73
+ } as MCPJsonSchema)
74
+ expect(() => schema.parse({ s: 'x', n: 1, b: true, arr: [], obj: {} })).not.toThrow()
75
+ expect(() => schema.parse({ s: 123, n: 1, b: true, arr: [], obj: {} })).toThrow()
76
+ })
77
+
78
+ it('optional fields are not required', () => {
79
+ const schema = mcpJsonSchemaToZod({
80
+ type: 'object',
81
+ required: ['a'],
82
+ properties: {
83
+ a: { type: 'string' },
84
+ b: { type: 'string' },
85
+ },
86
+ } as MCPJsonSchema)
87
+ expect(() => schema.parse({ a: 'x' })).not.toThrow()
88
+ })
89
+
90
+ it('unknown property types map to z.unknown (pass any value)', () => {
91
+ const schema = mcpJsonSchemaToZod({
92
+ type: 'object',
93
+ required: ['x'],
94
+ properties: { x: { type: 'weird' } },
95
+ } as MCPJsonSchema)
96
+ expect(() => schema.parse({ x: { nested: [1, 2] } })).not.toThrow()
97
+ })
98
+ })
99
+
100
+ describe('zodToMCPJsonSchema', () => {
101
+ it('wraps zod schema with type: object', () => {
102
+ const out = zodToMCPJsonSchema(z.object({ a: z.string() }))
103
+ expect(out.type).toBe('object')
104
+ })
105
+ })
106
+
107
+ describe('mcpToolToToolDefinition', () => {
108
+ it('prefixes name + description with the server handle', () => {
109
+ const tool = mcpToolToToolDefinition(
110
+ {
111
+ name: 'search',
112
+ description: 'search docs',
113
+ inputSchema: { type: 'object' } as MCPJsonSchema,
114
+ },
115
+ mockClient({ content: [{ type: 'text', text: 'ok' }], isError: false }),
116
+ 'serverA',
117
+ )
118
+ expect(tool.name).toBe('mcp_serverA_search')
119
+ expect(tool.description).toBe('[MCP:serverA] search docs')
120
+ expect(tool.category).toBe('network')
121
+ })
122
+
123
+ it('uses tool.name as description fallback when no description', () => {
124
+ const tool = mcpToolToToolDefinition(
125
+ { name: 'search', inputSchema: { type: 'object' } as MCPJsonSchema },
126
+ mockClient({ content: [{ type: 'text', text: 'ok' }], isError: false }),
127
+ 'serverA',
128
+ )
129
+ expect(tool.description).toBe('[MCP:serverA] search')
130
+ })
131
+
132
+ it('reflects MCP annotations into tool flags', () => {
133
+ const tool = mcpToolToToolDefinition(
134
+ {
135
+ name: 't',
136
+ inputSchema: { type: 'object' } as MCPJsonSchema,
137
+ annotations: { readOnlyHint: true, destructiveHint: true },
138
+ },
139
+ mockClient({ content: [], isError: false }),
140
+ 's',
141
+ )
142
+ expect(tool.isReadOnly?.({})).toBe(true)
143
+ expect(tool.isDestructive?.({})).toBe(true)
144
+ expect(tool.isConcurrencySafe?.({})).toBe(true)
145
+ })
146
+
147
+ it('default flags when annotations are absent', () => {
148
+ const tool = mcpToolToToolDefinition(
149
+ { name: 't', inputSchema: { type: 'object' } as MCPJsonSchema },
150
+ mockClient({ content: [], isError: false }),
151
+ 's',
152
+ )
153
+ expect(tool.isReadOnly?.({})).toBe(false)
154
+ expect(tool.isDestructive?.({})).toBe(false)
155
+ })
156
+
157
+ it('execute calls client.callTool(tool.name, input) and adapts result', async () => {
158
+ const client = mockClient({
159
+ content: [{ type: 'text', text: 'hello' }],
160
+ isError: false,
161
+ })
162
+ const tool = mcpToolToToolDefinition(
163
+ { name: 'search', inputSchema: { type: 'object' } as MCPJsonSchema },
164
+ client,
165
+ 's',
166
+ )
167
+ const result = await tool.execute({ q: 'hi' }, {} as ToolContext)
168
+ expect(client.callTool).toHaveBeenCalledWith('search', { q: 'hi' })
169
+ expect(result.success).toBe(true)
170
+ expect(result.output).toBe('hello')
171
+ })
172
+ })
173
+
174
+ describe('toolDefinitionToMCPTool', () => {
175
+ it('projects name / description / inputSchema / annotations', () => {
176
+ const tool: ToolDefinition = {
177
+ name: 't',
178
+ description: 'd',
179
+ inputSchema: z.object({ a: z.string() }),
180
+ async execute() {
181
+ return { success: true, output: '' }
182
+ },
183
+ isReadOnly: () => true,
184
+ isDestructive: () => false,
185
+ }
186
+ const out = toolDefinitionToMCPTool(tool)
187
+ expect(out.name).toBe('t')
188
+ expect(out.description).toBe('d')
189
+ expect(out.inputSchema.type).toBe('object')
190
+ expect(out.annotations).toEqual({ readOnlyHint: true, destructiveHint: false })
191
+ })
192
+ })
193
+
194
+ describe('mcpToolResultToToolResult', () => {
195
+ it('joins text blocks with \\n for output', () => {
196
+ const result = mcpToolResultToToolResult({
197
+ content: [
198
+ { type: 'text', text: 'line 1' },
199
+ { type: 'text', text: 'line 2' },
200
+ ],
201
+ isError: false,
202
+ })
203
+ expect(result.output).toBe('line 1\nline 2')
204
+ expect(result.success).toBe(true)
205
+ })
206
+
207
+ it('filters out non-text blocks from output but keeps them in data', () => {
208
+ const result = mcpToolResultToToolResult({
209
+ content: [
210
+ { type: 'text', text: 'text' },
211
+ { type: 'image', data: 'b64', mimeType: 'image/png' },
212
+ ],
213
+ isError: false,
214
+ })
215
+ expect(result.output).toBe('text')
216
+ expect(Array.isArray(result.data)).toBe(true)
217
+ })
218
+
219
+ it('sets error field when isError is true', () => {
220
+ const result = mcpToolResultToToolResult({
221
+ content: [{ type: 'text', text: 'boom' }],
222
+ isError: true,
223
+ })
224
+ expect(result.success).toBe(false)
225
+ expect(result.error).toBe('boom')
226
+ })
227
+ })
228
+
229
+ describe('toolResultToMCPToolResult', () => {
230
+ it('success + output → single text block', () => {
231
+ const result: ToolResult = { success: true, output: 'ok' }
232
+ const out = toolResultToMCPToolResult(result)
233
+ expect(out.content).toEqual([{ type: 'text', text: 'ok' }])
234
+ expect(out.isError).toBe(false)
235
+ })
236
+
237
+ it('failure + error → text block + isError', () => {
238
+ const result: ToolResult = { success: false, output: '', error: 'boom' }
239
+ const out = toolResultToMCPToolResult(result)
240
+ expect(out.content.some((b) => b.type === 'text' && b.text === 'boom')).toBe(true)
241
+ expect(out.isError).toBe(true)
242
+ })
243
+
244
+ it('success with empty output → one empty-text block', () => {
245
+ const result: ToolResult = { success: true, output: '' }
246
+ const out = toolResultToMCPToolResult(result)
247
+ expect(out.content).toEqual([{ type: 'text', text: '' }])
248
+ })
249
+ })
@@ -0,0 +1,14 @@
1
+ import type { RunId } from '../types/ids/index.js'
2
+ import type { ProbeContext } from '../types/probe/index.js'
3
+
4
+ export interface ProbeContextInput {
5
+ readonly runId?: RunId
6
+ readonly isReplay?: boolean
7
+ }
8
+
9
+ export function buildProbeContext(input: ProbeContextInput = {}): ProbeContext {
10
+ return Object.freeze({
11
+ runId: input.runId,
12
+ isReplay: input.isReplay ?? false,
13
+ })
14
+ }
@@ -0,0 +1,27 @@
1
+ import type { VetoableEventKind } from '../types/probe/index.js'
2
+
3
+ export class ProbeNameCollisionError extends Error {
4
+ readonly probeName: string
5
+
6
+ constructor(probeName: string) {
7
+ super(
8
+ `Probe name "${probeName}" is already registered. Pass { override: true } to replace, or pick a different name.`,
9
+ )
10
+ this.name = 'ProbeNameCollisionError'
11
+ this.probeName = probeName
12
+ }
13
+ }
14
+
15
+ export class ProbeVetoError extends Error {
16
+ readonly probeName: string
17
+ readonly reason: string
18
+ readonly eventKind: VetoableEventKind
19
+
20
+ constructor(probeName: string, reason: string, eventKind: VetoableEventKind) {
21
+ super(`Operation denied by probe "${probeName}" on ${eventKind}: ${reason}`)
22
+ this.name = 'ProbeVetoError'
23
+ this.probeName = probeName
24
+ this.reason = reason
25
+ this.eventKind = eventKind
26
+ }
27
+ }
@@ -0,0 +1,4 @@
1
+ export { ProbeNameCollisionError, ProbeVetoError } from './errors.js'
2
+ export { buildProbeContext } from './context.js'
3
+ export type { ProbeContextInput } from './context.js'
4
+ export { ProbeRegistry, createProbeRegistry, probe } from './registry.js'