@cogitator-ai/server-shared 0.4.1 → 0.5.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.
package/dist/body.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ /** A request body that every adapter refuses the same way, before any run starts */
2
+ export interface BodyRefusal {
3
+ status: 400 | 413 | 415;
4
+ code: 'INVALID_INPUT' | 'PAYLOAD_TOO_LARGE' | 'UNSUPPORTED_MEDIA_TYPE';
5
+ message: string;
6
+ }
7
+ /** The outcome of reading a JSON request body: its value (`undefined` for no body), or a refusal */
8
+ export type JsonBodyResult = {
9
+ ok: true;
10
+ value: unknown;
11
+ } | {
12
+ ok: false;
13
+ refusal: BodyRefusal;
14
+ };
15
+ /** The largest JSON body the adapters read unless configured otherwise: 1 MiB */
16
+ export declare const DEFAULT_JSON_BODY_LIMIT: number;
17
+ /**
18
+ * The refusal of a body that is not JSON.
19
+ *
20
+ * Browsers send `text/plain`, `application/x-www-form-urlencoded` and `multipart/form-data`
21
+ * across origins without a CORS preflight, so a server that read such a body as JSON would
22
+ * let any web page start an agent run on it, with the visitor's cookies or on a server that
23
+ * trusts its network. JSON endpoints read only JSON media types.
24
+ */
25
+ export declare const UNSUPPORTED_MEDIA_TYPE: BodyRefusal;
26
+ export declare const INVALID_JSON: BodyRefusal;
27
+ export declare const PAYLOAD_TOO_LARGE: BodyRefusal;
28
+ /** True for `application/json` and `application/<anything>+json`, with any parameters */
29
+ export declare function isJsonMediaType(contentType: string | null | undefined): boolean;
30
+ /** Reads a header of a Node request or a Fetch `Headers`, as one string */
31
+ type HeaderSource = Headers | Readonly<Record<string, string | string[] | undefined>>;
32
+ /**
33
+ * The refusal a request gets before its body is read, when it carries a body that is not JSON
34
+ * (see {@link UNSUPPORTED_MEDIA_TYPE}). A request without a body passes: routes whose body is
35
+ * optional run without one, and the others refuse the missing fields.
36
+ */
37
+ export declare function refuseNonJsonBody(method: string, headers: HeaderSource): BodyRefusal | undefined;
38
+ /** Parses the text of a request body under the JSON body policy */
39
+ export declare function parseJsonBody(contentType: string | null | undefined, text: string): JsonBodyResult;
40
+ /**
41
+ * Reads the JSON body of a Fetch API `Request`, stopping at `limit` bytes: no body gives
42
+ * `undefined`, a body that is not JSON `415`, one over the limit `413` and broken JSON `400`.
43
+ */
44
+ export declare function readJsonRequestBody(request: Request, limit?: number): Promise<JsonBodyResult>;
45
+ export {};
46
+ //# sourceMappingURL=body.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body.d.ts","sourceRoot":"","sources":["../src/body.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IACxB,IAAI,EAAE,eAAe,GAAG,mBAAmB,GAAG,wBAAwB,CAAC;IACvE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oGAAoG;AACpG,MAAM,MAAM,cAAc,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC;AAEhG,iFAAiF;AACjF,eAAO,MAAM,uBAAuB,QAAc,CAAC;AAEnD;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAIpC,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,WAI1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,WAI/B,CAAC;AAIF,yFAAyF;AACzF,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAI/E;AAED,2EAA2E;AAC3E,KAAK,YAAY,GAAG,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;AAQtF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,WAAW,GAAG,SAAS,CAOhG;AAED,mEAAmE;AACnE,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACtC,IAAI,EAAE,MAAM,GACX,cAAc,CAQhB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,EAChB,KAAK,GAAE,MAAgC,GACtC,OAAO,CAAC,cAAc,CAAC,CAoCzB"}
package/dist/body.js ADDED
@@ -0,0 +1,110 @@
1
+ /** The largest JSON body the adapters read unless configured otherwise: 1 MiB */
2
+ export const DEFAULT_JSON_BODY_LIMIT = 1024 * 1024;
3
+ /**
4
+ * The refusal of a body that is not JSON.
5
+ *
6
+ * Browsers send `text/plain`, `application/x-www-form-urlencoded` and `multipart/form-data`
7
+ * across origins without a CORS preflight, so a server that read such a body as JSON would
8
+ * let any web page start an agent run on it, with the visitor's cookies or on a server that
9
+ * trusts its network. JSON endpoints read only JSON media types.
10
+ */
11
+ export const UNSUPPORTED_MEDIA_TYPE = {
12
+ status: 415,
13
+ code: 'UNSUPPORTED_MEDIA_TYPE',
14
+ message: 'Request body must be JSON (Content-Type: application/json)',
15
+ };
16
+ export const INVALID_JSON = {
17
+ status: 400,
18
+ code: 'INVALID_INPUT',
19
+ message: 'Invalid JSON body',
20
+ };
21
+ export const PAYLOAD_TOO_LARGE = {
22
+ status: 413,
23
+ code: 'PAYLOAD_TOO_LARGE',
24
+ message: 'Payload too large',
25
+ };
26
+ const BODY_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
27
+ /** True for `application/json` and `application/<anything>+json`, with any parameters */
28
+ export function isJsonMediaType(contentType) {
29
+ if (!contentType)
30
+ return false;
31
+ const essence = contentType.split(';', 1)[0]?.trim().toLowerCase() ?? '';
32
+ return essence === 'application/json' || /^application\/[\w.+-]+\+json$/.test(essence);
33
+ }
34
+ function header(headers, name) {
35
+ if (headers instanceof Headers)
36
+ return headers.get(name) ?? undefined;
37
+ const value = headers[name];
38
+ return Array.isArray(value) ? value.join(', ') : value;
39
+ }
40
+ /**
41
+ * The refusal a request gets before its body is read, when it carries a body that is not JSON
42
+ * (see {@link UNSUPPORTED_MEDIA_TYPE}). A request without a body passes: routes whose body is
43
+ * optional run without one, and the others refuse the missing fields.
44
+ */
45
+ export function refuseNonJsonBody(method, headers) {
46
+ if (!BODY_METHODS.has(method.toUpperCase()))
47
+ return undefined;
48
+ const length = header(headers, 'content-length');
49
+ const chunked = header(headers, 'transfer-encoding') !== undefined;
50
+ const hasBody = chunked || (length !== undefined && Number(length) > 0);
51
+ if (!hasBody || isJsonMediaType(header(headers, 'content-type')))
52
+ return undefined;
53
+ return UNSUPPORTED_MEDIA_TYPE;
54
+ }
55
+ /** Parses the text of a request body under the JSON body policy */
56
+ export function parseJsonBody(contentType, text) {
57
+ if (!text.trim())
58
+ return { ok: true, value: undefined };
59
+ if (!isJsonMediaType(contentType))
60
+ return { ok: false, refusal: UNSUPPORTED_MEDIA_TYPE };
61
+ try {
62
+ return { ok: true, value: JSON.parse(text) };
63
+ }
64
+ catch {
65
+ return { ok: false, refusal: INVALID_JSON };
66
+ }
67
+ }
68
+ /**
69
+ * Reads the JSON body of a Fetch API `Request`, stopping at `limit` bytes: no body gives
70
+ * `undefined`, a body that is not JSON `415`, one over the limit `413` and broken JSON `400`.
71
+ */
72
+ export async function readJsonRequestBody(request, limit = DEFAULT_JSON_BODY_LIMIT) {
73
+ const contentType = request.headers.get('content-type');
74
+ const declared = Number(request.headers.get('content-length') ?? Number.NaN);
75
+ if (Number.isFinite(declared) && declared > limit)
76
+ return { ok: false, refusal: PAYLOAD_TOO_LARGE };
77
+ if (!request.body)
78
+ return { ok: true, value: undefined };
79
+ if (Number.isFinite(declared) && declared > 0 && !isJsonMediaType(contentType)) {
80
+ await request.body.cancel().catch(() => undefined);
81
+ return { ok: false, refusal: UNSUPPORTED_MEDIA_TYPE };
82
+ }
83
+ const reader = request.body.getReader();
84
+ const chunks = [];
85
+ let size = 0;
86
+ try {
87
+ for (;;) {
88
+ const { done, value } = await reader.read();
89
+ if (done)
90
+ break;
91
+ size += value.byteLength;
92
+ if (size > limit) {
93
+ await reader.cancel().catch(() => undefined);
94
+ return { ok: false, refusal: PAYLOAD_TOO_LARGE };
95
+ }
96
+ chunks.push(value);
97
+ }
98
+ }
99
+ catch {
100
+ return { ok: false, refusal: { ...INVALID_JSON, message: 'Failed to read request body' } };
101
+ }
102
+ const bytes = new Uint8Array(size);
103
+ let offset = 0;
104
+ for (const chunk of chunks) {
105
+ bytes.set(chunk, offset);
106
+ offset += chunk.byteLength;
107
+ }
108
+ return parseJsonBody(contentType, new TextDecoder().decode(bytes));
109
+ }
110
+ //# sourceMappingURL=body.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body.js","sourceRoot":"","sources":["../src/body.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ import type { ResumeOptions, RunOptions, RunResult } from '@cogitator-ai/types';
2
+ import type { StreamEvent } from './protocol.js';
3
+ import type { ContextPolicy, ThreadMessageRole } from './validation.js';
4
+ /**
5
+ * Conformance cases for Cogitator server adapters.
6
+ *
7
+ * Every adapter runs the same cases against its own app with {@link ConformanceRuntime} in
8
+ * place of a `Cogitator`, so a request body, a refusal or a response field that one adapter
9
+ * handles differently from the others fails that adapter's tests. Adapters of your own can
10
+ * run them too.
11
+ */
12
+ /** The agent, swarm, workflow and thread the cases address */
13
+ export declare const CONFORMANCE_NAMES: {
14
+ readonly agent: "assistant";
15
+ readonly swarm: "team";
16
+ readonly workflow: "flow";
17
+ readonly thread: "thread-1";
18
+ };
19
+ /**
20
+ * The swarm the cases register under {@link CONFORMANCE_NAMES}`.swarm`: a router and pipeline
21
+ * stages, the slots a listing is most likely to miss. The cases never run it.
22
+ */
23
+ export declare const CONFORMANCE_SWARM: {
24
+ readonly name: "team";
25
+ readonly strategy: "pipeline";
26
+ readonly router: {
27
+ readonly name: "router";
28
+ };
29
+ readonly stages: readonly [{
30
+ readonly agent: {
31
+ readonly name: "draft";
32
+ };
33
+ }, {
34
+ readonly agent: {
35
+ readonly name: "review";
36
+ };
37
+ }];
38
+ };
39
+ /** The routes the cases call, relative to where the adapter is mounted */
40
+ export declare const CONFORMANCE_ROUTES: {
41
+ readonly swarmList: "/swarms";
42
+ readonly agentRun: "/agents/assistant/run";
43
+ readonly agentStream: "/agents/assistant/stream";
44
+ readonly agentResume: "/agents/assistant/resume";
45
+ readonly swarmRun: "/swarms/team/run";
46
+ readonly workflowRun: "/workflows/flow/run";
47
+ readonly threadMessages: "/threads/thread-1/messages";
48
+ };
49
+ export type ConformanceRoute = keyof typeof CONFORMANCE_ROUTES;
50
+ /** The server options a case needs; the adapter maps them onto its own option names */
51
+ export interface ConformanceServerOptions {
52
+ acceptContext?: ContextPolicy;
53
+ threadMessageRoles?: readonly ThreadMessageRole[];
54
+ }
55
+ export interface ConformanceCase {
56
+ name: string;
57
+ route: ConformanceRoute;
58
+ /** Default: `POST` */
59
+ method?: 'GET' | 'POST';
60
+ server?: ConformanceServerOptions;
61
+ /** The raw request body; none for a `GET` */
62
+ body?: string;
63
+ /** Default: `application/json` */
64
+ contentType?: string;
65
+ expect: {
66
+ status: number;
67
+ /** The error code of a refusal */
68
+ code?: string;
69
+ /** Runs and resumes the request starts. Default: 1 for a success, 0 for a refusal */
70
+ runs?: number;
71
+ /** Options the run must have been started with */
72
+ runOptions?: Readonly<Record<string, unknown>>;
73
+ /** The JSON answer must be exactly `toAgentRunResponse()` of what the runtime returned */
74
+ runResponse?: true;
75
+ /** The stream must announce the run's thread in `start` and `finish`, this one when set */
76
+ streamThread?: string | true;
77
+ /** Messages the request adds to memory */
78
+ memoryWrites?: number;
79
+ /** The exact JSON answer */
80
+ json?: unknown;
81
+ };
82
+ }
83
+ export declare const CONFORMANCE_CASES: readonly ConformanceCase[];
84
+ /** The method a case sends */
85
+ export declare function conformanceMethod(testCase: ConformanceCase): 'GET' | 'POST';
86
+ /** The content type a case sends */
87
+ export declare function conformanceContentType(testCase: ConformanceCase): string;
88
+ /** The thread id the conformance runtime reports when a run names none, as core would */
89
+ export declare const CONFORMANCE_GENERATED_THREAD = "thread_generated_by_runtime";
90
+ /**
91
+ * A finished run with everything a client must not see: the system prompt in `messages`,
92
+ * trace spans with tool arguments and errors, and provider state on the tool calls.
93
+ */
94
+ export declare function conformanceRunResult(threadId: string): RunResult;
95
+ /** A run paused for an approval, with the checkpoint the server must keep to itself */
96
+ export declare function conformancePausedResult(threadId: string): RunResult;
97
+ /**
98
+ * Stands in for a `Cogitator` in conformance tests: it records every run and resume, streams
99
+ * a reasoning part, text, a tool call and its result when asked to stream, and keeps a
100
+ * memory that records what is added to threads.
101
+ */
102
+ export declare class ConformanceRuntime {
103
+ readonly runs: Array<RunOptions | ResumeOptions>;
104
+ readonly results: RunResult[];
105
+ readonly memoryWrites: unknown[];
106
+ run(_agent: unknown, options: RunOptions): Promise<RunResult>;
107
+ resume(_agent: unknown, threadId: string, options: ResumeOptions): Promise<RunResult>;
108
+ getMemory(): Promise<unknown>;
109
+ private record;
110
+ }
111
+ /** What an adapter answered to a case */
112
+ export interface ConformanceResponse {
113
+ status: number;
114
+ /** The error code of the answer, read the adapter's way */
115
+ code?: string;
116
+ /** The answer's body as text */
117
+ body: string;
118
+ }
119
+ /** How {@link checkConformance} reads an adapter's answers */
120
+ export interface ConformanceCheckOptions {
121
+ /**
122
+ * The adapter's own names for the error codes the cases expect, for an adapter that follows
123
+ * its framework's conventions: Tetsu answers every body that breaks the request schema with
124
+ * `VALIDATION_FAILED`, where the other adapters say `INVALID_INPUT`.
125
+ */
126
+ codes?: Readonly<Record<string, string>>;
127
+ /**
128
+ * The adapter's own statuses for the ones the cases expect: a Tetsu application answers
129
+ * schema refusals with its configured validation status, `422` by default, for `400`.
130
+ */
131
+ statuses?: Readonly<Record<number, number>>;
132
+ }
133
+ /** Reads the `data:` events of an SSE body, skipping comments and `[DONE]` */
134
+ export declare function parseSseEvents(body: string): StreamEvent[];
135
+ /**
136
+ * Compares what an adapter answered to what the case expects, and returns every mismatch;
137
+ * an empty list means the adapter conforms.
138
+ */
139
+ export declare function checkConformance(testCase: ConformanceCase, response: ConformanceResponse, runtime: ConformanceRuntime, check?: ConformanceCheckOptions): string[];
140
+ //# sourceMappingURL=conformance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../src/conformance.ts"],"names":[],"mappings":"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"}