@roll-agent/protocol 0.6.1 → 0.8.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/README.md CHANGED
@@ -94,7 +94,7 @@ function handleEvent(event: RuntimeEventEnvelopeV13): void {
94
94
 
95
95
  协议版本与 npm 包版本相互独立。`RUNTIME_PROTOCOL_VERSION` 表示这个包提供的最新 wire
96
96
  schema,并不代表调用方已实现对应 Client 能力。当前支持顺序为
97
- `["1.4", "1.3", "1.2", "1.1", "1.0"]`。`initialize` 请求保持旧 strict 形状;协商到 `"1.2"`、
97
+ `["1.5", "1.4", "1.3", "1.2", "1.1", "1.0"]`。`initialize` 请求保持旧 strict 形状;协商到 `"1.2"`、
98
98
  `"1.3"` 或 `"1.4"` 后,
99
99
  Client 必须用 `client.capabilities.set` 提交单调 `revision` 与当前 Handler methods,Runtime
100
100
  返回 registry 交集后才进入 interaction-ready。ACK 可以为空或为请求集的任意子集,顺序按
@@ -0,0 +1,86 @@
1
+ import { z } from "zod/v4";
2
+ /** Independent of a renderer and of the lossy model/display projections. */
3
+ export declare const APP_OUTPUT_META_KEY = "roll/appOutput";
4
+ export declare const APP_OUTPUT_STATUS_META_KEY = "roll/appOutputStatus";
5
+ export declare const APP_OUTPUT_LIMITS: {
6
+ readonly resultBytes: number;
7
+ readonly schemaBytes: number;
8
+ readonly threadBytes: number;
9
+ readonly threadRecords: 2000;
10
+ readonly maxAgeMs: number;
11
+ };
12
+ export declare const appOutputDeclarationSchema: z.ZodReadonly<z.ZodObject<{
13
+ schemaId: z.ZodString;
14
+ schemaVersion: z.ZodNumber;
15
+ remoteReadable: z.ZodDefault<z.ZodBoolean>;
16
+ }, z.core.$strict>>;
17
+ export type AppOutputDeclaration = z.infer<typeof appOutputDeclarationSchema>;
18
+ export declare const appOutputContractSchema: z.ZodReadonly<z.ZodObject<{
19
+ outputSchema: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
20
+ schemaId: z.ZodString;
21
+ schemaVersion: z.ZodNumber;
22
+ remoteReadable: z.ZodDefault<z.ZodBoolean>;
23
+ }, z.core.$strict>>;
24
+ export type AppOutputContract = z.infer<typeof appOutputContractSchema>;
25
+ export declare const APP_OUTPUT_UNAVAILABLE_STATUSES: readonly ["not_provided", "invalid", "too_large", "expired", "denied"];
26
+ export declare const appOutputRejectionSchema: z.ZodReadonly<z.ZodObject<{
27
+ status: z.ZodLiteral<"rejected">;
28
+ reason: z.ZodEnum<{
29
+ credential_field: "credential_field";
30
+ credential_value: "credential_value";
31
+ }>;
32
+ field: z.ZodOptional<z.ZodString>;
33
+ }, z.core.$strict>>;
34
+ export type AppOutputRejection = z.infer<typeof appOutputRejectionSchema>;
35
+ export declare const appOutputResultSchema: z.ZodReadonly<z.ZodDiscriminatedUnion<[z.ZodReadonly<z.ZodObject<{
36
+ status: z.ZodLiteral<"rejected">;
37
+ reason: z.ZodEnum<{
38
+ credential_field: "credential_field";
39
+ credential_value: "credential_value";
40
+ }>;
41
+ field: z.ZodOptional<z.ZodString>;
42
+ }, z.core.$strict>>, z.ZodObject<{
43
+ status: z.ZodLiteral<"available">;
44
+ schemaId: z.ZodString;
45
+ schemaVersion: z.ZodNumber;
46
+ remoteReadable: z.ZodBoolean;
47
+ data: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
48
+ fallbackText: z.ZodString;
49
+ }, z.core.$strict>, z.ZodObject<{
50
+ status: z.ZodEnum<{
51
+ not_provided: "not_provided";
52
+ invalid: "invalid";
53
+ too_large: "too_large";
54
+ expired: "expired";
55
+ denied: "denied";
56
+ }>;
57
+ }, z.core.$strict>]>>;
58
+ export type AppOutputResult = z.infer<typeof appOutputResultSchema>;
59
+ export declare const appOutputDescriptorSchema: z.ZodReadonly<z.ZodDiscriminatedUnion<[z.ZodReadonly<z.ZodObject<{
60
+ status: z.ZodLiteral<"rejected">;
61
+ reason: z.ZodEnum<{
62
+ credential_field: "credential_field";
63
+ credential_value: "credential_value";
64
+ }>;
65
+ field: z.ZodOptional<z.ZodString>;
66
+ }, z.core.$strict>>, z.ZodObject<{
67
+ status: z.ZodLiteral<"available">;
68
+ schemaId: z.ZodString;
69
+ schemaVersion: z.ZodNumber;
70
+ }, z.core.$strict>, z.ZodObject<{
71
+ status: z.ZodEnum<{
72
+ not_provided: "not_provided";
73
+ invalid: "invalid";
74
+ too_large: "too_large";
75
+ expired: "expired";
76
+ denied: "denied";
77
+ }>;
78
+ }, z.core.$strict>]>>;
79
+ export type AppOutputDescriptor = z.infer<typeof appOutputDescriptorSchema>;
80
+ export declare function describeAppOutput(result: AppOutputResult): AppOutputDescriptor;
81
+ /** Validate portable, self-contained contracts without dereferencing network resources. */
82
+ export declare function validateAppOutputContract(value: unknown): AppOutputContract;
83
+ /** MCP uses isError for invalid output even when execution has completed. */
84
+ export declare const COMPLETED_APP_OUTPUT_STATUSES: readonly ["invalid", "too_large"];
85
+ export type CompletedAppOutputStatus = (typeof COMPLETED_APP_OUTPUT_STATUSES)[number];
86
+ export declare function getCompletedAppOutputStatus(value: unknown): CompletedAppOutputStatus | undefined;
@@ -0,0 +1,178 @@
1
+ import { z } from "zod/v4";
2
+ /** Independent of a renderer and of the lossy model/display projections. */
3
+ export const APP_OUTPUT_META_KEY = "roll/appOutput";
4
+ export const APP_OUTPUT_STATUS_META_KEY = "roll/appOutputStatus";
5
+ export const APP_OUTPUT_LIMITS = {
6
+ resultBytes: 256 * 1024,
7
+ schemaBytes: 32 * 1024,
8
+ threadBytes: 16 * 1024 * 1024,
9
+ threadRecords: 2000,
10
+ maxAgeMs: 30 * 24 * 60 * 60 * 1000,
11
+ };
12
+ const appOutputDeclarationObjectSchema = z
13
+ .object({
14
+ schemaId: z.string().min(1).max(256),
15
+ schemaVersion: z.number().int().positive(),
16
+ remoteReadable: z.boolean().default(false),
17
+ })
18
+ .strict();
19
+ export const appOutputDeclarationSchema = appOutputDeclarationObjectSchema.readonly();
20
+ export const appOutputContractSchema = z
21
+ .object({
22
+ ...appOutputDeclarationObjectSchema.shape,
23
+ outputSchema: z.record(z.string(), z.json()),
24
+ })
25
+ .strict()
26
+ .readonly();
27
+ export const APP_OUTPUT_UNAVAILABLE_STATUSES = [
28
+ "not_provided",
29
+ "invalid",
30
+ "too_large",
31
+ "expired",
32
+ "denied",
33
+ ];
34
+ export const appOutputRejectionSchema = z
35
+ .object({
36
+ status: z.literal("rejected"),
37
+ reason: z.enum(["credential_field", "credential_value"]),
38
+ field: z.string().max(64).optional(),
39
+ })
40
+ .strict()
41
+ .readonly();
42
+ export const appOutputResultSchema = z
43
+ .discriminatedUnion("status", [
44
+ appOutputRejectionSchema,
45
+ z
46
+ .object({
47
+ status: z.literal("available"),
48
+ schemaId: z.string().min(1).max(256),
49
+ schemaVersion: z.number().int().positive(),
50
+ remoteReadable: z.boolean(),
51
+ data: z.record(z.string(), z.json()),
52
+ fallbackText: z.string().max(4096),
53
+ })
54
+ .strict(),
55
+ z.object({ status: z.enum(APP_OUTPUT_UNAVAILABLE_STATUSES) }).strict(),
56
+ ])
57
+ .readonly();
58
+ export const appOutputDescriptorSchema = z
59
+ .discriminatedUnion("status", [
60
+ appOutputRejectionSchema,
61
+ z
62
+ .object({
63
+ status: z.literal("available"),
64
+ schemaId: z.string().min(1).max(256),
65
+ schemaVersion: z.number().int().positive(),
66
+ })
67
+ .strict(),
68
+ z.object({ status: z.enum(APP_OUTPUT_UNAVAILABLE_STATUSES) }).strict(),
69
+ ])
70
+ .readonly();
71
+ export function describeAppOutput(result) {
72
+ if (result.status === "rejected")
73
+ return result;
74
+ return result.status === "available"
75
+ ? { status: result.status, schemaId: result.schemaId, schemaVersion: result.schemaVersion }
76
+ : { status: result.status };
77
+ }
78
+ /** Validate portable, self-contained contracts without dereferencing network resources. */
79
+ export function validateAppOutputContract(value) {
80
+ const contract = appOutputContractSchema.parse(value);
81
+ const schema = contract.outputSchema;
82
+ if (schema.type !== "object")
83
+ throw new Error("appOutput outputSchema must be an object schema");
84
+ if (new TextEncoder().encode(JSON.stringify(schema)).byteLength > APP_OUTPUT_LIMITS.schemaBytes) {
85
+ throw new Error("appOutput outputSchema exceeds 32 KiB");
86
+ }
87
+ const visit = (node) => {
88
+ if (typeof node !== "object" || node === null || Array.isArray(node))
89
+ return;
90
+ const record = { ...node };
91
+ if ("$dynamicRef" in record || "$recursiveRef" in record) {
92
+ throw new Error("appOutput supports only static local references");
93
+ }
94
+ if ("$ref" in record) {
95
+ const ref = record["$ref"];
96
+ if (typeof ref !== "string" || (ref !== "#" && !ref.startsWith("#/"))) {
97
+ throw new Error("appOutput outputSchema only supports local JSON Pointer references");
98
+ }
99
+ let target = schema;
100
+ for (const part of ref === "#" ? [] : ref.slice(2).split("/")) {
101
+ const key = decodeURIComponent(part).replace(/~1/g, "/").replace(/~0/g, "~");
102
+ if (typeof target !== "object" || target === null || !Object.hasOwn(target, key)) {
103
+ throw new Error("appOutput outputSchema has an unresolved local reference");
104
+ }
105
+ target = Reflect.get(target, key);
106
+ }
107
+ if (typeof target !== "boolean" &&
108
+ (typeof target !== "object" || target === null || Array.isArray(target))) {
109
+ throw new Error("appOutput local reference must target a schema");
110
+ }
111
+ }
112
+ for (const key of [
113
+ "properties",
114
+ "patternProperties",
115
+ "$defs",
116
+ "definitions",
117
+ "dependentSchemas",
118
+ "dependencies",
119
+ ]) {
120
+ const children = record[key];
121
+ if (typeof children === "object" && children !== null && !Array.isArray(children)) {
122
+ for (const child of Object.values(children))
123
+ visit(child);
124
+ }
125
+ }
126
+ for (const key of ["allOf", "anyOf", "oneOf", "prefixItems"]) {
127
+ const children = record[key];
128
+ if (Array.isArray(children))
129
+ children.forEach(visit);
130
+ }
131
+ for (const key of [
132
+ "additionalProperties",
133
+ "additionalItems",
134
+ "contains",
135
+ "not",
136
+ "if",
137
+ "then",
138
+ "else",
139
+ "propertyNames",
140
+ "unevaluatedProperties",
141
+ "unevaluatedItems",
142
+ ]) {
143
+ visit(record[key]);
144
+ }
145
+ const items = record["items"];
146
+ if (Array.isArray(items))
147
+ items.forEach(visit);
148
+ else
149
+ visit(items);
150
+ // A nested identifier can change the meaning of otherwise local references.
151
+ if (node !== schema && ("$id" in record || "id" in record)) {
152
+ throw new Error("appOutput does not support nested schema identifiers");
153
+ }
154
+ };
155
+ visit(schema);
156
+ return contract;
157
+ }
158
+ /** MCP uses isError for invalid output even when execution has completed. */
159
+ export const COMPLETED_APP_OUTPUT_STATUSES = ["invalid", "too_large"];
160
+ export function getCompletedAppOutputStatus(value) {
161
+ if (typeof value !== "object" ||
162
+ value === null ||
163
+ !("isError" in value) ||
164
+ value.isError !== true ||
165
+ !("_meta" in value)) {
166
+ return undefined;
167
+ }
168
+ const meta = value._meta;
169
+ if (typeof meta !== "object" ||
170
+ meta === null ||
171
+ !("roll/executionStatus" in meta) ||
172
+ meta["roll/executionStatus"] !== "completed" ||
173
+ !(APP_OUTPUT_STATUS_META_KEY in meta)) {
174
+ return undefined;
175
+ }
176
+ const status = meta[APP_OUTPUT_STATUS_META_KEY];
177
+ return status === "invalid" || status === "too_large" ? status : undefined;
178
+ }