@tangle-network/agent-interface 0.45.0 → 0.46.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 +1 -1
- package/dist/agent-candidate-profile-schema.d.ts +2 -2
- package/dist/agent-candidate-promotion-schema.d.ts +22 -22
- package/dist/agent-candidate-schema-common.js +1 -1
- package/dist/agent-candidate-schema.d.ts +2 -2
- package/dist/agent-execution-preparation.d.ts +26 -26
- package/dist/agent-profile.d.ts +10 -3
- package/dist/agent-profile.js +45 -22
- package/dist/backend-message.d.ts +14 -0
- package/dist/backend-message.js +1 -0
- package/dist/contract-limits.d.ts +26 -0
- package/dist/contract-limits.js +175 -0
- package/dist/environment-exact-process.d.ts +161 -0
- package/dist/environment-exact-process.js +1 -0
- package/dist/environment-profile-capabilities.d.ts +26 -0
- package/dist/environment-profile-capabilities.js +34 -0
- package/dist/environment-provider.d.ts +3 -730
- package/dist/environment-provider.js +3 -245
- package/dist/environment-requests.d.ts +70 -0
- package/dist/environment-requests.js +1 -0
- package/dist/environment-runtime.d.ts +834 -0
- package/dist/environment-runtime.js +228 -0
- package/dist/execution-types.d.ts +47 -0
- package/dist/execution-types.js +1 -0
- package/dist/host-services.d.ts +91 -0
- package/dist/host-services.js +1 -0
- package/dist/index.d.ts +10 -617
- package/dist/index.js +10 -125
- package/dist/interaction-answer-validation.d.ts +13 -0
- package/dist/interaction-answer-validation.js +149 -0
- package/dist/interaction-data.d.ts +22 -0
- package/dist/interaction-data.js +46 -0
- package/dist/interaction-envelope.d.ts +258 -0
- package/dist/interaction-envelope.js +245 -0
- package/dist/interaction-fields.d.ts +130 -0
- package/dist/interaction-fields.js +227 -0
- package/dist/interaction-permissions.d.ts +28 -0
- package/dist/interaction-permissions.js +57 -0
- package/dist/interaction-resolution-validation.d.ts +9 -0
- package/dist/interaction-resolution-validation.js +50 -0
- package/dist/interaction-response-validation.d.ts +17 -0
- package/dist/interaction-response-validation.js +102 -0
- package/dist/interaction.d.ts +6 -397
- package/dist/interaction.js +6 -603
- package/dist/mcp.d.ts +38 -0
- package/dist/mcp.js +1 -0
- package/dist/parts.d.ts +104 -0
- package/dist/parts.js +55 -0
- package/dist/portable-context-base.d.ts +82 -0
- package/dist/portable-context-base.js +63 -0
- package/dist/portable-context-continuation.d.ts +168 -0
- package/dist/portable-context-continuation.js +194 -0
- package/dist/portable-context-plan-request.d.ts +86 -0
- package/dist/portable-context-plan-request.js +102 -0
- package/dist/portable-context-plan.d.ts +229 -0
- package/dist/portable-context-plan.js +241 -0
- package/dist/portable-context-shared.d.ts +36 -0
- package/dist/portable-context-shared.js +46 -0
- package/dist/portable-context-transfer.d.ts +319 -0
- package/dist/portable-context-transfer.js +206 -0
- package/dist/portable-context.d.ts +5 -753
- package/dist/portable-context.js +5 -754
- package/dist/profile-diff.js +56 -47
- package/dist/provider-adapter.d.ts +45 -0
- package/dist/provider-adapter.js +1 -0
- package/dist/provider-config.d.ts +58 -0
- package/dist/provider-config.js +42 -0
- package/dist/runtime-control.d.ts +87 -10
- package/dist/runtime-control.js +159 -38
- package/dist/stream-events.d.ts +55 -0
- package/dist/stream-events.js +1 -0
- package/dist/workspace-branching-shared.d.ts +7 -0
- package/dist/workspace-branching-shared.js +20 -0
- package/dist/workspace-branching.d.ts +4 -254
- package/dist/workspace-branching.js +4 -400
- package/dist/workspace-checkpoint.d.ts +99 -0
- package/dist/workspace-checkpoint.js +169 -0
- package/dist/workspace-cleanup.d.ts +85 -0
- package/dist/workspace-cleanup.js +156 -0
- package/dist/workspace-confidentiality.d.ts +59 -0
- package/dist/workspace-confidentiality.js +123 -0
- package/dist/workspace-fork.d.ts +182 -0
- package/dist/workspace-fork.js +267 -0
- package/package.json +1 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Sha256Digest } from "./agent-candidate.js";
|
|
3
|
+
import { type PortableContextDestination, type PortableContextPlan } from "./portable-context-plan.js";
|
|
4
|
+
import { type PortableConversationContext } from "./portable-context-base.js";
|
|
5
|
+
export interface PortableContextPlanRequestMaterial {
|
|
6
|
+
requestId: string;
|
|
7
|
+
source: PortableConversationContext;
|
|
8
|
+
destination: PortableContextDestination;
|
|
9
|
+
maxInputTokens?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function portableContextPlanRequestDigest(request: PortableContextPlanRequestMaterial): Sha256Digest;
|
|
12
|
+
export interface PortableContextPlanRequest extends PortableContextPlanRequestMaterial {
|
|
13
|
+
requestId: string;
|
|
14
|
+
requestDigest: Sha256Digest;
|
|
15
|
+
}
|
|
16
|
+
export declare const PortableContextPlanRequestSchema: z.ZodObject<{
|
|
17
|
+
requestId: z.ZodString;
|
|
18
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
19
|
+
source: z.ZodObject<{
|
|
20
|
+
source: z.ZodObject<{
|
|
21
|
+
runId: z.ZodString;
|
|
22
|
+
messageId: z.ZodString;
|
|
23
|
+
provider: z.ZodString;
|
|
24
|
+
environmentId: z.ZodString;
|
|
25
|
+
sessionId: z.ZodString;
|
|
26
|
+
executionId: z.ZodString;
|
|
27
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
28
|
+
branchId: z.ZodOptional<z.ZodString>;
|
|
29
|
+
}, z.core.$strict>;
|
|
30
|
+
completeness: z.ZodEnum<{
|
|
31
|
+
complete: "complete";
|
|
32
|
+
partial: "partial";
|
|
33
|
+
}>;
|
|
34
|
+
messages: z.ZodArray<z.ZodObject<{
|
|
35
|
+
id: z.ZodString;
|
|
36
|
+
role: z.ZodEnum<{
|
|
37
|
+
user: "user";
|
|
38
|
+
assistant: "assistant";
|
|
39
|
+
system: "system";
|
|
40
|
+
}>;
|
|
41
|
+
parts: z.ZodArray<z.ZodCustom<unknown, unknown>>;
|
|
42
|
+
timestamp: z.ZodISODateTime;
|
|
43
|
+
metadata: z.ZodOptional<z.ZodCustom<Record<string, unknown>, Record<string, unknown>>>;
|
|
44
|
+
}, z.core.$strict>>;
|
|
45
|
+
attachments: z.ZodArray<z.ZodObject<{
|
|
46
|
+
messageId: z.ZodString;
|
|
47
|
+
partIndex: z.ZodNumber;
|
|
48
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
49
|
+
name: z.ZodOptional<z.ZodString>;
|
|
50
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
51
|
+
}, z.core.$strict>>;
|
|
52
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
53
|
+
}, z.core.$strict>;
|
|
54
|
+
destination: z.ZodObject<{
|
|
55
|
+
runner: z.ZodString;
|
|
56
|
+
provider: z.ZodString;
|
|
57
|
+
environmentId: z.ZodString;
|
|
58
|
+
sessionId: z.ZodString;
|
|
59
|
+
runId: z.ZodString;
|
|
60
|
+
executionId: z.ZodString;
|
|
61
|
+
model: z.ZodOptional<z.ZodString>;
|
|
62
|
+
profileDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
63
|
+
}, z.core.$strict>;
|
|
64
|
+
maxInputTokens: z.ZodOptional<z.ZodNumber>;
|
|
65
|
+
}, z.core.$strict>;
|
|
66
|
+
interface PortableContextPlanResultBinding {
|
|
67
|
+
requestId: string;
|
|
68
|
+
requestDigest: Sha256Digest;
|
|
69
|
+
}
|
|
70
|
+
export type PortableContextPlanResult = (PortableContextPlanResultBinding & {
|
|
71
|
+
status: "ready";
|
|
72
|
+
plan: PortableContextPlan;
|
|
73
|
+
}) | (PortableContextPlanResultBinding & {
|
|
74
|
+
status: "over_limit";
|
|
75
|
+
estimatedTokens?: number;
|
|
76
|
+
maxInputTokens: number;
|
|
77
|
+
suggestedBoundaryMessageId?: string;
|
|
78
|
+
message: string;
|
|
79
|
+
}) | (PortableContextPlanResultBinding & {
|
|
80
|
+
status: "unsupported";
|
|
81
|
+
message: string;
|
|
82
|
+
});
|
|
83
|
+
export declare const PortableContextPlanResultSchema: z.ZodType<PortableContextPlanResult>;
|
|
84
|
+
/** Cross-check a planner result against the exact request and token budget. */
|
|
85
|
+
export declare function portableContextPlanResultMatchesRequest(request: PortableContextPlanRequest, result: PortableContextPlanResult): boolean;
|
|
86
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { idSchema, sha256DigestSchema, wireDigest } from "./portable-context-shared.js";
|
|
3
|
+
import { boundedStringSchema } from "./contract-limits.js";
|
|
4
|
+
import { PortableContextDestinationSchema, PortableContextPlanSchema } from "./portable-context-plan.js";
|
|
5
|
+
import { PortableConversationContextSchema } from "./portable-context-base.js";
|
|
6
|
+
const PortableContextPlanRequestMaterialSchema = z.strictObject({
|
|
7
|
+
requestId: idSchema,
|
|
8
|
+
source: PortableConversationContextSchema,
|
|
9
|
+
destination: PortableContextDestinationSchema,
|
|
10
|
+
maxInputTokens: z.number().int().positive().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
11
|
+
});
|
|
12
|
+
export function portableContextPlanRequestDigest(request) {
|
|
13
|
+
const parsed = PortableContextPlanRequestMaterialSchema.parse(request);
|
|
14
|
+
return wireDigest({
|
|
15
|
+
requestId: parsed.requestId,
|
|
16
|
+
source: parsed.source,
|
|
17
|
+
destination: parsed.destination,
|
|
18
|
+
...(parsed.maxInputTokens === undefined
|
|
19
|
+
? {}
|
|
20
|
+
: { maxInputTokens: parsed.maxInputTokens }),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export const PortableContextPlanRequestSchema = z
|
|
24
|
+
.strictObject({
|
|
25
|
+
requestId: idSchema,
|
|
26
|
+
requestDigest: sha256DigestSchema,
|
|
27
|
+
source: PortableConversationContextSchema,
|
|
28
|
+
destination: PortableContextDestinationSchema,
|
|
29
|
+
maxInputTokens: z.number().int().positive().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
30
|
+
})
|
|
31
|
+
.superRefine((request, refinement) => {
|
|
32
|
+
if (request.requestDigest !==
|
|
33
|
+
portableContextPlanRequestDigest({
|
|
34
|
+
source: request.source,
|
|
35
|
+
destination: request.destination,
|
|
36
|
+
maxInputTokens: request.maxInputTokens,
|
|
37
|
+
requestId: request.requestId,
|
|
38
|
+
})) {
|
|
39
|
+
refinement.addIssue({
|
|
40
|
+
code: "custom",
|
|
41
|
+
path: ["requestDigest"],
|
|
42
|
+
message: "portable context plan request digest does not match its content",
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const portableContextPlanResultBinding = {
|
|
47
|
+
requestId: idSchema,
|
|
48
|
+
requestDigest: sha256DigestSchema,
|
|
49
|
+
};
|
|
50
|
+
export const PortableContextPlanResultSchema = z.discriminatedUnion("status", [
|
|
51
|
+
z.strictObject({
|
|
52
|
+
status: z.literal("ready"),
|
|
53
|
+
...portableContextPlanResultBinding,
|
|
54
|
+
plan: PortableContextPlanSchema,
|
|
55
|
+
}),
|
|
56
|
+
z.strictObject({
|
|
57
|
+
status: z.literal("over_limit"),
|
|
58
|
+
...portableContextPlanResultBinding,
|
|
59
|
+
estimatedTokens: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
60
|
+
maxInputTokens: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
61
|
+
suggestedBoundaryMessageId: idSchema.optional(),
|
|
62
|
+
message: boundedStringSchema.min(1),
|
|
63
|
+
}),
|
|
64
|
+
z.strictObject({
|
|
65
|
+
status: z.literal("unsupported"),
|
|
66
|
+
...portableContextPlanResultBinding,
|
|
67
|
+
message: boundedStringSchema.min(1),
|
|
68
|
+
}),
|
|
69
|
+
]);
|
|
70
|
+
/** Cross-check a planner result against the exact request and token budget. */
|
|
71
|
+
export function portableContextPlanResultMatchesRequest(request, result) {
|
|
72
|
+
const parsedRequest = PortableContextPlanRequestSchema.safeParse(request);
|
|
73
|
+
const parsedResult = PortableContextPlanResultSchema.safeParse(result);
|
|
74
|
+
if (!parsedRequest.success || !parsedResult.success)
|
|
75
|
+
return false;
|
|
76
|
+
const exactRequest = parsedRequest.data;
|
|
77
|
+
const exactResult = parsedResult.data;
|
|
78
|
+
if (exactResult.requestId !== exactRequest.requestId ||
|
|
79
|
+
exactResult.requestDigest !== exactRequest.requestDigest) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
if (exactResult.status === "ready") {
|
|
83
|
+
if (wireDigest(exactResult.plan.source) !== wireDigest(exactRequest.source) ||
|
|
84
|
+
wireDigest(exactResult.plan.destination) !==
|
|
85
|
+
wireDigest(exactRequest.destination)) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
if (exactRequest.maxInputTokens === undefined)
|
|
89
|
+
return true;
|
|
90
|
+
return (exactResult.plan.estimatedTokens !== undefined &&
|
|
91
|
+
exactResult.plan.estimatedTokens <= exactRequest.maxInputTokens);
|
|
92
|
+
}
|
|
93
|
+
if (exactResult.status === "over_limit") {
|
|
94
|
+
return (exactRequest.maxInputTokens !== undefined &&
|
|
95
|
+
exactResult.maxInputTokens === exactRequest.maxInputTokens &&
|
|
96
|
+
(exactResult.estimatedTokens === undefined ||
|
|
97
|
+
exactResult.estimatedTokens > exactRequest.maxInputTokens) &&
|
|
98
|
+
(exactResult.suggestedBoundaryMessageId === undefined ||
|
|
99
|
+
exactRequest.source.messages.some((message) => message.id === exactResult.suggestedBoundaryMessageId)));
|
|
100
|
+
}
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Sha256Digest } from "./agent-candidate.js";
|
|
3
|
+
import type { InputPart } from "./parts.js";
|
|
4
|
+
import { type PortableConversationContext } from "./portable-context-base.js";
|
|
5
|
+
export interface PortableContextDestination {
|
|
6
|
+
runner: string;
|
|
7
|
+
provider: string;
|
|
8
|
+
environmentId: string;
|
|
9
|
+
sessionId: string;
|
|
10
|
+
runId: string;
|
|
11
|
+
executionId: string;
|
|
12
|
+
model?: string;
|
|
13
|
+
profileDigest: Sha256Digest;
|
|
14
|
+
}
|
|
15
|
+
export declare const PortableContextDestinationSchema: z.ZodObject<{
|
|
16
|
+
runner: z.ZodString;
|
|
17
|
+
provider: z.ZodString;
|
|
18
|
+
environmentId: z.ZodString;
|
|
19
|
+
sessionId: z.ZodString;
|
|
20
|
+
runId: z.ZodString;
|
|
21
|
+
executionId: z.ZodString;
|
|
22
|
+
model: z.ZodOptional<z.ZodString>;
|
|
23
|
+
profileDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
24
|
+
}, z.core.$strict>;
|
|
25
|
+
export interface PortableContextPartPlan {
|
|
26
|
+
partIndex: number;
|
|
27
|
+
action: "include" | "transform" | "omit";
|
|
28
|
+
output?: InputPart;
|
|
29
|
+
reason?: string;
|
|
30
|
+
}
|
|
31
|
+
export declare const PortableContextPartPlanSchema: z.ZodObject<{
|
|
32
|
+
partIndex: z.ZodNumber;
|
|
33
|
+
action: z.ZodEnum<{
|
|
34
|
+
transform: "transform";
|
|
35
|
+
include: "include";
|
|
36
|
+
omit: "omit";
|
|
37
|
+
}>;
|
|
38
|
+
output: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
39
|
+
type: z.ZodLiteral<"text">;
|
|
40
|
+
text: z.ZodString;
|
|
41
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
42
|
+
type: z.ZodLiteral<"file">;
|
|
43
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
44
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
45
|
+
url: z.ZodOptional<z.ZodString>;
|
|
46
|
+
path: z.ZodOptional<z.ZodString>;
|
|
47
|
+
content: z.ZodOptional<z.ZodString>;
|
|
48
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
49
|
+
type: z.ZodLiteral<"image">;
|
|
50
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
51
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
52
|
+
url: z.ZodOptional<z.ZodString>;
|
|
53
|
+
path: z.ZodOptional<z.ZodString>;
|
|
54
|
+
}, z.core.$strict>], "type">>;
|
|
55
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
56
|
+
}, z.core.$strict>;
|
|
57
|
+
export interface PortableContextMessagePlan {
|
|
58
|
+
messageId: string;
|
|
59
|
+
action: "include" | "omit";
|
|
60
|
+
parts: PortableContextPartPlan[];
|
|
61
|
+
reason?: string;
|
|
62
|
+
}
|
|
63
|
+
export declare const PortableContextMessagePlanSchema: z.ZodObject<{
|
|
64
|
+
messageId: z.ZodString;
|
|
65
|
+
action: z.ZodEnum<{
|
|
66
|
+
include: "include";
|
|
67
|
+
omit: "omit";
|
|
68
|
+
}>;
|
|
69
|
+
parts: z.ZodArray<z.ZodObject<{
|
|
70
|
+
partIndex: z.ZodNumber;
|
|
71
|
+
action: z.ZodEnum<{
|
|
72
|
+
transform: "transform";
|
|
73
|
+
include: "include";
|
|
74
|
+
omit: "omit";
|
|
75
|
+
}>;
|
|
76
|
+
output: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
77
|
+
type: z.ZodLiteral<"text">;
|
|
78
|
+
text: z.ZodString;
|
|
79
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
80
|
+
type: z.ZodLiteral<"file">;
|
|
81
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
82
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
83
|
+
url: z.ZodOptional<z.ZodString>;
|
|
84
|
+
path: z.ZodOptional<z.ZodString>;
|
|
85
|
+
content: z.ZodOptional<z.ZodString>;
|
|
86
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
87
|
+
type: z.ZodLiteral<"image">;
|
|
88
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
89
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
90
|
+
url: z.ZodOptional<z.ZodString>;
|
|
91
|
+
path: z.ZodOptional<z.ZodString>;
|
|
92
|
+
}, z.core.$strict>], "type">>;
|
|
93
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
94
|
+
}, z.core.$strict>>;
|
|
95
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
96
|
+
}, z.core.$strict>;
|
|
97
|
+
export interface PortableContextPlan {
|
|
98
|
+
planId: string;
|
|
99
|
+
/** Full immutable source so an executor can verify every decision itself. */
|
|
100
|
+
source: PortableConversationContext;
|
|
101
|
+
destination: PortableContextDestination;
|
|
102
|
+
messages: PortableContextMessagePlan[];
|
|
103
|
+
context: PortableConversationContext;
|
|
104
|
+
estimatedTokens?: number;
|
|
105
|
+
requiresAcceptance: boolean;
|
|
106
|
+
digest: Sha256Digest;
|
|
107
|
+
}
|
|
108
|
+
export type PortableContextPlanMaterial = Omit<PortableContextPlan, "digest">;
|
|
109
|
+
export declare function portableContextPlanDigest(plan: PortableContextPlanMaterial): Sha256Digest;
|
|
110
|
+
export declare const PortableContextPlanSchema: z.ZodObject<{
|
|
111
|
+
planId: z.ZodString;
|
|
112
|
+
source: z.ZodObject<{
|
|
113
|
+
source: z.ZodObject<{
|
|
114
|
+
runId: z.ZodString;
|
|
115
|
+
messageId: z.ZodString;
|
|
116
|
+
provider: z.ZodString;
|
|
117
|
+
environmentId: z.ZodString;
|
|
118
|
+
sessionId: z.ZodString;
|
|
119
|
+
executionId: z.ZodString;
|
|
120
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
121
|
+
branchId: z.ZodOptional<z.ZodString>;
|
|
122
|
+
}, z.core.$strict>;
|
|
123
|
+
completeness: z.ZodEnum<{
|
|
124
|
+
complete: "complete";
|
|
125
|
+
partial: "partial";
|
|
126
|
+
}>;
|
|
127
|
+
messages: z.ZodArray<z.ZodObject<{
|
|
128
|
+
id: z.ZodString;
|
|
129
|
+
role: z.ZodEnum<{
|
|
130
|
+
user: "user";
|
|
131
|
+
assistant: "assistant";
|
|
132
|
+
system: "system";
|
|
133
|
+
}>;
|
|
134
|
+
parts: z.ZodArray<z.ZodCustom<unknown, unknown>>;
|
|
135
|
+
timestamp: z.ZodISODateTime;
|
|
136
|
+
metadata: z.ZodOptional<z.ZodCustom<Record<string, unknown>, Record<string, unknown>>>;
|
|
137
|
+
}, z.core.$strict>>;
|
|
138
|
+
attachments: z.ZodArray<z.ZodObject<{
|
|
139
|
+
messageId: z.ZodString;
|
|
140
|
+
partIndex: z.ZodNumber;
|
|
141
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
142
|
+
name: z.ZodOptional<z.ZodString>;
|
|
143
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
144
|
+
}, z.core.$strict>>;
|
|
145
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
146
|
+
}, z.core.$strict>;
|
|
147
|
+
destination: z.ZodObject<{
|
|
148
|
+
runner: z.ZodString;
|
|
149
|
+
provider: z.ZodString;
|
|
150
|
+
environmentId: z.ZodString;
|
|
151
|
+
sessionId: z.ZodString;
|
|
152
|
+
runId: z.ZodString;
|
|
153
|
+
executionId: z.ZodString;
|
|
154
|
+
model: z.ZodOptional<z.ZodString>;
|
|
155
|
+
profileDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
156
|
+
}, z.core.$strict>;
|
|
157
|
+
messages: z.ZodArray<z.ZodObject<{
|
|
158
|
+
messageId: z.ZodString;
|
|
159
|
+
action: z.ZodEnum<{
|
|
160
|
+
include: "include";
|
|
161
|
+
omit: "omit";
|
|
162
|
+
}>;
|
|
163
|
+
parts: z.ZodArray<z.ZodObject<{
|
|
164
|
+
partIndex: z.ZodNumber;
|
|
165
|
+
action: z.ZodEnum<{
|
|
166
|
+
transform: "transform";
|
|
167
|
+
include: "include";
|
|
168
|
+
omit: "omit";
|
|
169
|
+
}>;
|
|
170
|
+
output: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
171
|
+
type: z.ZodLiteral<"text">;
|
|
172
|
+
text: z.ZodString;
|
|
173
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
174
|
+
type: z.ZodLiteral<"file">;
|
|
175
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
176
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
177
|
+
url: z.ZodOptional<z.ZodString>;
|
|
178
|
+
path: z.ZodOptional<z.ZodString>;
|
|
179
|
+
content: z.ZodOptional<z.ZodString>;
|
|
180
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
181
|
+
type: z.ZodLiteral<"image">;
|
|
182
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
183
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
184
|
+
url: z.ZodOptional<z.ZodString>;
|
|
185
|
+
path: z.ZodOptional<z.ZodString>;
|
|
186
|
+
}, z.core.$strict>], "type">>;
|
|
187
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
188
|
+
}, z.core.$strict>>;
|
|
189
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
190
|
+
}, z.core.$strict>>;
|
|
191
|
+
context: z.ZodObject<{
|
|
192
|
+
source: z.ZodObject<{
|
|
193
|
+
runId: z.ZodString;
|
|
194
|
+
messageId: z.ZodString;
|
|
195
|
+
provider: z.ZodString;
|
|
196
|
+
environmentId: z.ZodString;
|
|
197
|
+
sessionId: z.ZodString;
|
|
198
|
+
executionId: z.ZodString;
|
|
199
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
200
|
+
branchId: z.ZodOptional<z.ZodString>;
|
|
201
|
+
}, z.core.$strict>;
|
|
202
|
+
completeness: z.ZodEnum<{
|
|
203
|
+
complete: "complete";
|
|
204
|
+
partial: "partial";
|
|
205
|
+
}>;
|
|
206
|
+
messages: z.ZodArray<z.ZodObject<{
|
|
207
|
+
id: z.ZodString;
|
|
208
|
+
role: z.ZodEnum<{
|
|
209
|
+
user: "user";
|
|
210
|
+
assistant: "assistant";
|
|
211
|
+
system: "system";
|
|
212
|
+
}>;
|
|
213
|
+
parts: z.ZodArray<z.ZodCustom<unknown, unknown>>;
|
|
214
|
+
timestamp: z.ZodISODateTime;
|
|
215
|
+
metadata: z.ZodOptional<z.ZodCustom<Record<string, unknown>, Record<string, unknown>>>;
|
|
216
|
+
}, z.core.$strict>>;
|
|
217
|
+
attachments: z.ZodArray<z.ZodObject<{
|
|
218
|
+
messageId: z.ZodString;
|
|
219
|
+
partIndex: z.ZodNumber;
|
|
220
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
221
|
+
name: z.ZodOptional<z.ZodString>;
|
|
222
|
+
mediaType: z.ZodOptional<z.ZodString>;
|
|
223
|
+
}, z.core.$strict>>;
|
|
224
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
225
|
+
}, z.core.$strict>;
|
|
226
|
+
estimatedTokens: z.ZodOptional<z.ZodNumber>;
|
|
227
|
+
requiresAcceptance: z.ZodBoolean;
|
|
228
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
229
|
+
}, z.core.$strict>;
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { idSchema, InputPartSchema, sha256DigestSchema, sameStringSet, wireDigest, } from "./portable-context-shared.js";
|
|
3
|
+
import { boundedStringSchema, CONTRACT_MAX_ARRAY_LENGTH } from "./contract-limits.js";
|
|
4
|
+
import { PortableConversationContextSchema } from "./portable-context-base.js";
|
|
5
|
+
export const PortableContextDestinationSchema = z.strictObject({
|
|
6
|
+
runner: idSchema,
|
|
7
|
+
provider: idSchema,
|
|
8
|
+
environmentId: idSchema,
|
|
9
|
+
sessionId: idSchema,
|
|
10
|
+
runId: idSchema,
|
|
11
|
+
executionId: idSchema,
|
|
12
|
+
model: idSchema.optional(),
|
|
13
|
+
profileDigest: sha256DigestSchema,
|
|
14
|
+
});
|
|
15
|
+
export const PortableContextPartPlanSchema = z
|
|
16
|
+
.strictObject({
|
|
17
|
+
partIndex: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
|
|
18
|
+
action: z.enum(["include", "transform", "omit"]),
|
|
19
|
+
output: InputPartSchema.optional(),
|
|
20
|
+
reason: boundedStringSchema.min(1).optional(),
|
|
21
|
+
})
|
|
22
|
+
.superRefine((part, refinement) => {
|
|
23
|
+
if (part.action === "transform" && part.output === undefined) {
|
|
24
|
+
refinement.addIssue({
|
|
25
|
+
code: "custom",
|
|
26
|
+
path: ["output"],
|
|
27
|
+
message: "a transformed part must include its portable output",
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (part.action !== "transform" && part.output !== undefined) {
|
|
31
|
+
refinement.addIssue({
|
|
32
|
+
code: "custom",
|
|
33
|
+
path: ["output"],
|
|
34
|
+
message: "only a transformed part may include portable output",
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (part.action !== "include" && part.reason === undefined) {
|
|
38
|
+
refinement.addIssue({
|
|
39
|
+
code: "custom",
|
|
40
|
+
path: ["reason"],
|
|
41
|
+
message: "a transformed or omitted part must include a reason",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
export const PortableContextMessagePlanSchema = z
|
|
46
|
+
.strictObject({
|
|
47
|
+
messageId: idSchema,
|
|
48
|
+
action: z.enum(["include", "omit"]),
|
|
49
|
+
parts: z.array(PortableContextPartPlanSchema).max(CONTRACT_MAX_ARRAY_LENGTH),
|
|
50
|
+
reason: boundedStringSchema.min(1).optional(),
|
|
51
|
+
})
|
|
52
|
+
.superRefine((message, refinement) => {
|
|
53
|
+
const indexes = message.parts.map((part) => part.partIndex);
|
|
54
|
+
if (new Set(indexes).size !== indexes.length) {
|
|
55
|
+
refinement.addIssue({
|
|
56
|
+
code: "custom",
|
|
57
|
+
path: ["parts"],
|
|
58
|
+
message: "part indexes must be unique within a message plan",
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (message.action === "omit") {
|
|
62
|
+
if (message.reason === undefined) {
|
|
63
|
+
refinement.addIssue({
|
|
64
|
+
code: "custom",
|
|
65
|
+
path: ["reason"],
|
|
66
|
+
message: "an omitted message must include a reason",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (message.parts.some((part) => part.action !== "omit")) {
|
|
70
|
+
refinement.addIssue({
|
|
71
|
+
code: "custom",
|
|
72
|
+
path: ["parts"],
|
|
73
|
+
message: "every part of an omitted message must be omitted",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
const PortableContextPlanMaterialSchema = z.strictObject({
|
|
79
|
+
planId: idSchema,
|
|
80
|
+
source: PortableConversationContextSchema,
|
|
81
|
+
destination: PortableContextDestinationSchema,
|
|
82
|
+
messages: z.array(PortableContextMessagePlanSchema).max(CONTRACT_MAX_ARRAY_LENGTH),
|
|
83
|
+
context: PortableConversationContextSchema,
|
|
84
|
+
estimatedTokens: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
85
|
+
requiresAcceptance: z.boolean(),
|
|
86
|
+
});
|
|
87
|
+
export function portableContextPlanDigest(plan) {
|
|
88
|
+
const parsed = PortableContextPlanMaterialSchema.parse(plan);
|
|
89
|
+
return wireDigest({
|
|
90
|
+
planId: parsed.planId,
|
|
91
|
+
source: parsed.source,
|
|
92
|
+
destination: parsed.destination,
|
|
93
|
+
messages: parsed.messages,
|
|
94
|
+
context: parsed.context,
|
|
95
|
+
...(parsed.estimatedTokens === undefined
|
|
96
|
+
? {}
|
|
97
|
+
: { estimatedTokens: parsed.estimatedTokens }),
|
|
98
|
+
requiresAcceptance: parsed.requiresAcceptance,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
export const PortableContextPlanSchema = z
|
|
102
|
+
.strictObject({
|
|
103
|
+
planId: idSchema,
|
|
104
|
+
source: PortableConversationContextSchema,
|
|
105
|
+
destination: PortableContextDestinationSchema,
|
|
106
|
+
messages: z.array(PortableContextMessagePlanSchema).max(CONTRACT_MAX_ARRAY_LENGTH),
|
|
107
|
+
context: PortableConversationContextSchema,
|
|
108
|
+
estimatedTokens: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
109
|
+
requiresAcceptance: z.boolean(),
|
|
110
|
+
digest: sha256DigestSchema,
|
|
111
|
+
})
|
|
112
|
+
.superRefine((plan, refinement) => {
|
|
113
|
+
const messageIds = plan.messages.map((message) => message.messageId);
|
|
114
|
+
if (new Set(messageIds).size !== messageIds.length) {
|
|
115
|
+
refinement.addIssue({
|
|
116
|
+
code: "custom",
|
|
117
|
+
path: ["messages"],
|
|
118
|
+
message: "message ids must be unique within a context plan",
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const sourceMessageIds = plan.source.messages.map((message) => message.id);
|
|
122
|
+
if (!sameStringSet(messageIds, sourceMessageIds)) {
|
|
123
|
+
refinement.addIssue({
|
|
124
|
+
code: "custom",
|
|
125
|
+
path: ["messages"],
|
|
126
|
+
message: "a context plan must decide every source message exactly once",
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (wireDigest(plan.context.source) !== wireDigest(plan.source.source)) {
|
|
130
|
+
refinement.addIssue({
|
|
131
|
+
code: "custom",
|
|
132
|
+
path: ["context", "source"],
|
|
133
|
+
message: "output context source must match the immutable source",
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
const expectedMessages = [];
|
|
137
|
+
for (const sourceMessage of plan.source.messages) {
|
|
138
|
+
const messagePlan = plan.messages.find((candidate) => candidate.messageId === sourceMessage.id);
|
|
139
|
+
if (!messagePlan)
|
|
140
|
+
continue;
|
|
141
|
+
const expectedIndexes = sourceMessage.parts.map((_, index) => index);
|
|
142
|
+
const decidedIndexes = messagePlan.parts
|
|
143
|
+
.map((part) => part.partIndex)
|
|
144
|
+
.sort((left, right) => left - right);
|
|
145
|
+
if (JSON.stringify(expectedIndexes) !== JSON.stringify(decidedIndexes)) {
|
|
146
|
+
refinement.addIssue({
|
|
147
|
+
code: "custom",
|
|
148
|
+
path: ["messages"],
|
|
149
|
+
message: `message "${sourceMessage.id}" must decide every source part exactly once`,
|
|
150
|
+
});
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (messagePlan.action === "omit")
|
|
154
|
+
continue;
|
|
155
|
+
const outputParts = [];
|
|
156
|
+
for (const partPlan of [...messagePlan.parts].sort((left, right) => left.partIndex - right.partIndex)) {
|
|
157
|
+
if (partPlan.action === "omit")
|
|
158
|
+
continue;
|
|
159
|
+
if (partPlan.action === "transform") {
|
|
160
|
+
if (partPlan.output)
|
|
161
|
+
outputParts.push(partPlan.output);
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const parsedPart = InputPartSchema.safeParse(sourceMessage.parts[partPlan.partIndex]);
|
|
165
|
+
if (!parsedPart.success) {
|
|
166
|
+
refinement.addIssue({
|
|
167
|
+
code: "custom",
|
|
168
|
+
path: ["messages"],
|
|
169
|
+
message: `message "${sourceMessage.id}" part ${partPlan.partIndex} must be transformed or omitted`,
|
|
170
|
+
});
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
outputParts.push(parsedPart.data);
|
|
174
|
+
}
|
|
175
|
+
if (outputParts.length === 0) {
|
|
176
|
+
refinement.addIssue({
|
|
177
|
+
code: "custom",
|
|
178
|
+
path: ["messages"],
|
|
179
|
+
message: `included message "${sourceMessage.id}" must retain at least one part`,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
expectedMessages.push({ ...sourceMessage, parts: outputParts });
|
|
183
|
+
}
|
|
184
|
+
if (wireDigest(expectedMessages) !== wireDigest(plan.context.messages)) {
|
|
185
|
+
refinement.addIssue({
|
|
186
|
+
code: "custom",
|
|
187
|
+
path: ["context", "messages"],
|
|
188
|
+
message: "output messages do not exactly match the source decisions",
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
const expectedAttachments = plan.source.attachments.filter((attachment) => {
|
|
192
|
+
const message = plan.messages.find((candidate) => candidate.messageId === attachment.messageId);
|
|
193
|
+
const part = message?.parts.find((candidate) => candidate.partIndex === attachment.partIndex);
|
|
194
|
+
return message?.action === "include" && part?.action === "include";
|
|
195
|
+
});
|
|
196
|
+
if (wireDigest(expectedAttachments) !== wireDigest(plan.context.attachments)) {
|
|
197
|
+
refinement.addIssue({
|
|
198
|
+
code: "custom",
|
|
199
|
+
path: ["context", "attachments"],
|
|
200
|
+
message: "output attachments do not exactly match included source parts",
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
const changesContent = plan.messages.some((message) => message.action === "omit" ||
|
|
204
|
+
message.parts.some((part) => part.action !== "include"));
|
|
205
|
+
const requiresAcceptance = changesContent ||
|
|
206
|
+
plan.source.completeness === "partial" ||
|
|
207
|
+
plan.context.completeness === "partial";
|
|
208
|
+
if (plan.requiresAcceptance !== requiresAcceptance) {
|
|
209
|
+
refinement.addIssue({
|
|
210
|
+
code: "custom",
|
|
211
|
+
path: ["requiresAcceptance"],
|
|
212
|
+
message: "requiresAcceptance must be true when content changes or either context is partial",
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const expectedCompleteness = changesContent || plan.source.completeness === "partial"
|
|
216
|
+
? "partial"
|
|
217
|
+
: "complete";
|
|
218
|
+
if (plan.context.completeness !== expectedCompleteness) {
|
|
219
|
+
refinement.addIssue({
|
|
220
|
+
code: "custom",
|
|
221
|
+
path: ["context", "completeness"],
|
|
222
|
+
message: `output context completeness must be ${expectedCompleteness}`,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
if (plan.digest !==
|
|
226
|
+
portableContextPlanDigest({
|
|
227
|
+
planId: plan.planId,
|
|
228
|
+
source: plan.source,
|
|
229
|
+
destination: plan.destination,
|
|
230
|
+
messages: plan.messages,
|
|
231
|
+
context: plan.context,
|
|
232
|
+
estimatedTokens: plan.estimatedTokens,
|
|
233
|
+
requiresAcceptance: plan.requiresAcceptance,
|
|
234
|
+
})) {
|
|
235
|
+
refinement.addIssue({
|
|
236
|
+
code: "custom",
|
|
237
|
+
path: ["digest"],
|
|
238
|
+
message: "portable context plan digest does not match its content",
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
});
|