@procedures/client 0.37.0 → 0.39.0

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 (78) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/adapters/http/server/handler.js +3 -2
  4. package/dist/adapters/http/server/handler.js.map +1 -1
  5. package/dist/adapters/websocket/client/transport.d.ts +1 -1
  6. package/dist/adapters/websocket/client/transport.d.ts.map +1 -1
  7. package/dist/adapters/websocket/client/transport.js +18 -6
  8. package/dist/adapters/websocket/client/transport.js.map +1 -1
  9. package/dist/browser.d.ts +2 -1
  10. package/dist/browser.d.ts.map +1 -1
  11. package/dist/browser.js +2 -1
  12. package/dist/browser.js.map +1 -1
  13. package/dist/client/validation/types.d.ts.map +1 -1
  14. package/dist/client/validation/types.js +1 -0
  15. package/dist/client/validation/types.js.map +1 -1
  16. package/dist/procedures/collection/schemas.d.ts.map +1 -1
  17. package/dist/procedures/collection/schemas.js +1 -0
  18. package/dist/procedures/collection/schemas.js.map +1 -1
  19. package/dist/procedures/envelope.d.ts.map +1 -1
  20. package/dist/procedures/envelope.js +2 -0
  21. package/dist/procedures/envelope.js.map +1 -1
  22. package/dist/procedures/policy.js +2 -2
  23. package/dist/procedures/policy.js.map +1 -1
  24. package/dist/procedures/program.d.ts.map +1 -1
  25. package/dist/procedures/program.js +3 -0
  26. package/dist/procedures/program.js.map +1 -1
  27. package/dist/procedures/ref.d.ts.map +1 -1
  28. package/dist/procedures/ref.js +1 -0
  29. package/dist/procedures/ref.js.map +1 -1
  30. package/dist/procedures/types.d.ts +1 -1
  31. package/dist/procedures/types.d.ts.map +1 -1
  32. package/dist/procedures/types.js.map +1 -1
  33. package/dist/server/index.d.ts +2 -1
  34. package/dist/server/index.d.ts.map +1 -1
  35. package/dist/server/index.js +2 -1
  36. package/dist/server/index.js.map +1 -1
  37. package/dist/server/procedure-server.d.ts +0 -9
  38. package/dist/server/procedure-server.d.ts.map +1 -1
  39. package/dist/server/procedure-server.js +2 -9
  40. package/dist/server/procedure-server.js.map +1 -1
  41. package/dist/server/stream-metadata.d.ts +15 -0
  42. package/dist/server/stream-metadata.d.ts.map +1 -0
  43. package/dist/server/stream-metadata.js +15 -0
  44. package/dist/server/stream-metadata.js.map +1 -0
  45. package/dist/testing/index.d.ts +13 -0
  46. package/dist/testing/index.d.ts.map +1 -0
  47. package/dist/testing/index.js +11 -0
  48. package/dist/testing/index.js.map +1 -0
  49. package/dist/testing/log-storage.d.ts +28 -0
  50. package/dist/testing/log-storage.d.ts.map +1 -0
  51. package/dist/testing/log-storage.js +75 -0
  52. package/dist/testing/log-storage.js.map +1 -0
  53. package/dist/testing/mcp-caller.d.ts +33 -0
  54. package/dist/testing/mcp-caller.d.ts.map +1 -0
  55. package/dist/testing/mcp-caller.js +97 -0
  56. package/dist/testing/mcp-caller.js.map +1 -0
  57. package/dist/testing/transport-contract.d.ts +167 -0
  58. package/dist/testing/transport-contract.d.ts.map +1 -0
  59. package/dist/testing/transport-contract.js +387 -0
  60. package/dist/testing/transport-contract.js.map +1 -0
  61. package/package.json +5 -1
  62. package/src/adapters/http/server/handler.ts +3 -2
  63. package/src/adapters/websocket/client/transport.ts +20 -7
  64. package/src/browser.ts +2 -1
  65. package/src/client/validation/types.ts +1 -0
  66. package/src/procedures/collection/schemas.ts +1 -0
  67. package/src/procedures/envelope.ts +2 -0
  68. package/src/procedures/policy.ts +2 -2
  69. package/src/procedures/program.ts +3 -0
  70. package/src/procedures/ref.ts +1 -0
  71. package/src/procedures/types.ts +1 -1
  72. package/src/server/index.ts +2 -1
  73. package/src/server/procedure-server.ts +2 -11
  74. package/src/server/stream-metadata.ts +16 -0
  75. package/src/testing/index.ts +31 -0
  76. package/src/testing/log-storage.ts +72 -0
  77. package/src/testing/mcp-caller.ts +100 -0
  78. package/src/testing/transport-contract.ts +560 -0
@@ -0,0 +1,33 @@
1
+ /**
2
+ * A caller of the transport contract over an MCP client (CLI-85). The MCP faces of `client-mcp`
3
+ * and of a host in `client-server` use it. It has no import of the MCP SDK: the face gives the
4
+ * client, so the caller works with the copy of the SDK of each package.
5
+ *
6
+ * An MCP tool call is one result. A stream comes back as one result with a text block for each
7
+ * item. An error result has `isError`, its code and its flag in `_meta`, and its message in the
8
+ * last text block.
9
+ */
10
+ import { type ContractCaller } from "./transport-contract.js";
11
+ /** The parts of an MCP client of the SDK that the caller uses. */
12
+ export interface McpClientLike {
13
+ listTools(): Promise<{
14
+ tools: Array<{
15
+ name: string;
16
+ description?: string | undefined;
17
+ }>;
18
+ }>;
19
+ callTool(params: {
20
+ name: string;
21
+ arguments?: Record<string, unknown>;
22
+ }, resultSchema?: undefined, options?: {
23
+ signal?: AbortSignal;
24
+ }): Promise<unknown>;
25
+ close(): Promise<void>;
26
+ }
27
+ /**
28
+ * A caller of an MCP client. It finds the tool of a path by the description of the procedure, so
29
+ * it does not depend on the form of a tool name. The client connects at its first call, so a
30
+ * refusal of the connection is the error of that call.
31
+ */
32
+ export declare function mcpCaller(open: () => Promise<McpClientLike>): ContractCaller;
33
+ //# sourceMappingURL=mcp-caller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-caller.d.ts","sourceRoot":"","sources":["../../src/testing/mcp-caller.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEnF,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC5B,SAAS,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IAC3F,QAAQ,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,EAAE,YAAY,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxJ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAyCD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,GAAG,cAAc,CAmC5E"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * A caller of the transport contract over an MCP client (CLI-85). The MCP faces of `client-mcp`
3
+ * and of a host in `client-server` use it. It has no import of the MCP SDK: the face gives the
4
+ * client, so the caller works with the copy of the SDK of each package.
5
+ *
6
+ * An MCP tool call is one result. A stream comes back as one result with a text block for each
7
+ * item. An error result has `isError`, its code and its flag in `_meta`, and its message in the
8
+ * last text block.
9
+ */
10
+ import { pathToKey } from "../index.js";
11
+ import { contractDescription } from "./transport-contract.js";
12
+ /** The value of a text block: JSON, or the text itself. */
13
+ function valueOf(text) {
14
+ if (text === undefined)
15
+ return undefined;
16
+ try {
17
+ return JSON.parse(text);
18
+ }
19
+ catch {
20
+ return text;
21
+ }
22
+ }
23
+ /**
24
+ * The error of an error result: the code and the flag of `_meta`, and the message of the last text
25
+ * block. The blocks of a stream that fails are its items, then the message of the error.
26
+ */
27
+ function errorOf(result) {
28
+ const meta = result._meta ?? {};
29
+ return Object.assign(new Error(result.content?.at(-1)?.text ?? ""), { code: meta["code"], retryable: meta["retryable"] === true, metadata: meta });
30
+ }
31
+ /**
32
+ * The error of a refusal of the HTTP endpoint, before the tool call: the SDK puts the JSON-RPC
33
+ * body of the refusal in its message. Its `data.code` is the code of the refusal.
34
+ */
35
+ function refusalOf(error) {
36
+ const message = error instanceof Error ? error.message : String(error);
37
+ const start = message.indexOf("{");
38
+ if (start < 0)
39
+ return error;
40
+ try {
41
+ const body = JSON.parse(message.slice(start));
42
+ const code = body.error?.data?.code;
43
+ if (code === undefined)
44
+ return error;
45
+ return Object.assign(new Error(body.error?.message ?? message), { code, retryable: body.error?.data?.retryable === true });
46
+ }
47
+ catch {
48
+ return error;
49
+ }
50
+ }
51
+ /**
52
+ * A caller of an MCP client. It finds the tool of a path by the description of the procedure, so
53
+ * it does not depend on the form of a tool name. The client connects at its first call, so a
54
+ * refusal of the connection is the error of that call.
55
+ */
56
+ export function mcpCaller(open) {
57
+ let client;
58
+ const connect = () => (client ??= (async () => {
59
+ const mcp = await open();
60
+ const { tools } = await mcp.listTools();
61
+ return { mcp, names: new Map(tools.map((tool) => [tool.description ?? "", tool.name])) };
62
+ })());
63
+ const call = async (path, input, signal) => {
64
+ try {
65
+ const { mcp, names } = await connect();
66
+ const name = names.get(contractDescription(path)) ?? pathToKey(path);
67
+ return (await mcp.callTool({ name, arguments: input }, undefined, signal ? { signal } : {}));
68
+ }
69
+ catch (error) {
70
+ throw refusalOf(error);
71
+ }
72
+ };
73
+ return {
74
+ async call(path, input, options) {
75
+ const result = await call(path, input, options?.signal);
76
+ if (result.isError)
77
+ throw errorOf(result);
78
+ return valueOf(result.content?.[0]?.text);
79
+ },
80
+ async *stream(path, input, options) {
81
+ const result = await call(path, input, options?.signal);
82
+ if (result.isError)
83
+ throw errorOf(result);
84
+ // A stream without items gives one block "(no items)" for the reader of the result
85
+ const blocks = result.content ?? [];
86
+ if (blocks.length === 1 && blocks[0].text === "(no items)")
87
+ return;
88
+ for (const block of blocks)
89
+ yield valueOf(block.text);
90
+ },
91
+ async close() {
92
+ if (client)
93
+ await (await client.catch(() => undefined))?.mcp.close();
94
+ },
95
+ };
96
+ }
97
+ //# sourceMappingURL=mcp-caller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-caller.js","sourceRoot":"","sources":["../../src/testing/mcp-caller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * The transport contract (roadmap CLI-85, invariant I4 of ARCHITECTURE.md): one suite of wire
3
+ * cases that each face of the procedures server runs. `WIRE-PROTOCOL.md` is the contract.
4
+ *
5
+ * A face gives a factory (`ContractFace`): it starts a server of the face with the procedures of
6
+ * the suite, and it connects callers. The suite then runs the same cases over each face:
7
+ *
8
+ * - a call and its value, on paths of 1, 2 and 4 segments, and segments with "." and "%" (D36, CLI-75)
9
+ * - `NOT_FOUND` for an unknown path and for an empty segment, and `VALIDATION_ERROR`
10
+ * - the code, the message and the retryable flag of a handler error, for a value and for a stream (CLI-58, CLI-68)
11
+ * - the error policy `expose: "coded"` of the server (CLI-80)
12
+ * - `VERSION_CONFLICT` and its conflicts (CLI-16)
13
+ * - the items of a stream and its end, the abort of a call and the cancel of a stream
14
+ * - the deadline of the caller
15
+ * - the token, and the principal of the request hook in the handler (CLI-1, R18)
16
+ * - a subscription to the change topic of a collection: the hint arrives (CLI-15, CLI-75)
17
+ * - the refusal of a request above the size limit of the face
18
+ *
19
+ * A face that does not have a feature by design declares it in its capabilities, and the suite
20
+ * skips the cases of that feature. Each skip thus is data in the test file of the face.
21
+ *
22
+ * The suite is the entry point `@procedures/client/testing`, so a face in another package (and
23
+ * a server of an app, for example Graph) runs the same cases with the client that it uses. The
24
+ * suite imports no test runner: the caller gives `describe`, `it`, `afterEach` and `expect`
25
+ * (`ContractRunner`). Those of Vitest fit.
26
+ */
27
+ import type { CollectionStorage } from "../procedures/collection/storage.js";
28
+ import type { ProcedureRegistry } from "../procedures/registry.js";
29
+ import type { PrincipalOf } from "../server/types.js";
30
+ import type { ServerErrorPolicy } from "../server/error-policy.js";
31
+ import type { EventPublisherOptions } from "../events/publisher.js";
32
+ import type { EventTransport } from "../events/remote.js";
33
+ import type { Transport } from "../client/types.js";
34
+ /** The assertions of the suite on one value. The `expect` of Vitest gives them. */
35
+ export interface ContractExpectation {
36
+ toBe(expected: unknown): void;
37
+ toEqual(expected: unknown): void;
38
+ toMatchObject(expected: object): void;
39
+ toContain(expected: unknown): void;
40
+ toBeGreaterThan(expected: number): void;
41
+ toBeGreaterThanOrEqual(expected: number): void;
42
+ toBeLessThanOrEqual(expected: number): void;
43
+ readonly not: ContractExpectation;
44
+ }
45
+ /** A case of the suite. */
46
+ export type ContractCase = (name: string, body: () => Promise<void>) => void;
47
+ /** The parts of a test runner that the suite uses. Give those of Vitest: `{ describe, it, afterEach, expect }`. */
48
+ export interface ContractRunner {
49
+ describe(name: string, body: () => void): void;
50
+ readonly it: ContractCase & {
51
+ skipIf(condition: boolean): ContractCase;
52
+ };
53
+ afterEach(body: () => Promise<void>): void;
54
+ expect(actual: unknown, message?: string): ContractExpectation;
55
+ }
56
+ /**
57
+ * The features of a face. A feature that a face does not have by design is false (or undefined),
58
+ * and the suite skips its cases.
59
+ */
60
+ export interface ContractCapabilities {
61
+ /**
62
+ * The face goes through `Server.handle()`, so the options of the server apply: the error policy
63
+ * (`errors`), the token and the request hook. `LocalTransport` calls the registry directly.
64
+ */
65
+ readonly server: boolean;
66
+ /** The face carries network credentials (a bearer token) to the token check and the request hook. */
67
+ readonly auth: boolean;
68
+ /**
69
+ * Where the face refuses a caller without the token. `call` (the default): each call gets
70
+ * `UNAUTHORIZED`. `connect`: the face refuses the connection, and the caller gets an error
71
+ * without a code. The WebSocket face of a host refuses the upgrade with 401, and a WebSocket
72
+ * client cannot read the status of a refused upgrade.
73
+ */
74
+ readonly authRefusal?: "call" | "connect" | undefined;
75
+ /** The face carries a subscription (`events.subscribe`) to the event bus of the server. */
76
+ readonly subscriptions: boolean;
77
+ /**
78
+ * `items`: the caller reads each item of a stream when it arrives, and it can cancel the stream.
79
+ * `collected`: one result holds the items (MCP).
80
+ */
81
+ readonly streams: "items" | "collected";
82
+ /** The face carries the deadline of the caller (`procedure-timeout`) to the handler. */
83
+ readonly deadline: boolean;
84
+ /** The caller gets the metadata of an error, for example the conflicts of `VERSION_CONFLICT`. */
85
+ readonly errorMetadata: boolean;
86
+ /**
87
+ * The face carries the retryable flag of an error from the handler. `LocalTransport` gives
88
+ * `retryable: false` to each error by design: a local call does not get a retry.
89
+ */
90
+ readonly retryable: boolean;
91
+ /**
92
+ * The size limit of a request of the face. The face sets `ContractSpec.sizeLimit` as its limit,
93
+ * and `code` is the code of the refusal. Undefined: the face has no size limit.
94
+ */
95
+ readonly sizeLimit?: {
96
+ readonly code: string;
97
+ } | undefined;
98
+ }
99
+ /** What the server of a face serves. The face makes its server from these options. */
100
+ export interface ContractSpec {
101
+ /** The procedures of the suite, and the procedures of the collection. */
102
+ readonly registry: ProcedureRegistry;
103
+ /** The storages of the collections (`ProcedureServerOptions.collections`). */
104
+ readonly collections: Readonly<Record<string, CollectionStorage<unknown>>>;
105
+ /** The remote events of the server, with the topic rule of the collection. */
106
+ readonly events: EventPublisherOptions;
107
+ /** The token of the server. Only a face with `auth` gets it. */
108
+ readonly token?: string | undefined;
109
+ /** The request hook of the server. Only a face with `auth` gets it. */
110
+ readonly principalOf?: PrincipalOf | undefined;
111
+ /** The error policy of the server (CLI-80), and its logger. */
112
+ readonly errors?: ServerErrorPolicy | undefined;
113
+ readonly onError?: ((error: Error) => void) | undefined;
114
+ /** The size limit of a request, in bytes, for a face with `sizeLimit`. */
115
+ readonly sizeLimit?: number | undefined;
116
+ }
117
+ /** The options of one call of a caller. */
118
+ export interface ContractCallOptions {
119
+ readonly signal?: AbortSignal | undefined;
120
+ /** The deadline of the call, in milliseconds from now. */
121
+ readonly deadlineMs?: number | undefined;
122
+ }
123
+ /**
124
+ * A caller of a face. An error has the fields of a `ClientError`: `code`, `message`, `retryable`
125
+ * and `metadata`.
126
+ */
127
+ export interface ContractCaller {
128
+ call(path: readonly string[], input: unknown, options?: ContractCallOptions): Promise<unknown>;
129
+ stream(path: readonly string[], input: unknown, options?: ContractCallOptions): AsyncIterable<unknown>;
130
+ /** The transport of the remote events, for a face with `subscriptions`. */
131
+ readonly events?: EventTransport | undefined;
132
+ close?(): Promise<void>;
133
+ }
134
+ /** A started server of a face. */
135
+ export interface ContractServer {
136
+ /** A caller that presents the bearer token, or no credentials. */
137
+ connect(bearer?: string | undefined): Promise<ContractCaller>;
138
+ stop(): Promise<void>;
139
+ }
140
+ /** A face of the procedures server for the suite. */
141
+ export interface ContractFace {
142
+ readonly name: string;
143
+ readonly capabilities: ContractCapabilities;
144
+ start(spec: ContractSpec): Promise<ContractServer>;
145
+ }
146
+ /** The token of the server of a face with `auth`. */
147
+ export declare const CONTRACT_TOKEN = "contract-token-0123456789";
148
+ /** The principal that the request hook gives for the token. */
149
+ export declare const CONTRACT_PRINCIPAL = "contract-user";
150
+ /** The collection of the suite. Its name has a dot and a `%`, so the codec must keep it one segment (D36). */
151
+ export declare const CONTRACT_COLLECTION = "contract.tabs%";
152
+ /** The paths of the path case: 1, 2 and 4 segments, and segments with "." and "%" (CLI-28, CLI-75). */
153
+ export declare const CONTRACT_PATHS: readonly (readonly string[])[];
154
+ /** The description of a procedure of the suite: a face can find its tool by it. */
155
+ export declare function contractDescription(path: readonly string[]): string;
156
+ /**
157
+ * A caller of a `Client` over a transport of the client: HTTP, WebSocket, a message port or the
158
+ * local transport. Each face of the client uses it.
159
+ */
160
+ export declare function clientCaller(transport: Transport, close?: () => Promise<void>): ContractCaller;
161
+ /**
162
+ * This function declares the cases of the transport contract for one face. Call it at the top
163
+ * level of the test file of the face, with the functions of the test runner:
164
+ * `describeTransportContract(face, { describe, it, afterEach, expect })`.
165
+ */
166
+ export declare function describeTransportContract(face: ContractFace, runner: ContractRunner): void;
167
+ //# sourceMappingURL=transport-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-contract.d.ts","sourceRoot":"","sources":["../../src/testing/transport-contract.ts"],"names":[],"mappings":"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"}