@tangle-network/agent-interface 2.20.1 → 3.0.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 -23
- package/dist/agent-candidate-artifact-schema.d.ts +0 -4
- package/dist/agent-candidate-artifact-schema.js +1 -1
- package/dist/agent-candidate-schema-common.d.ts +0 -5
- package/dist/agent-candidate-schema-common.js +0 -27
- package/dist/agent-execution-limits.d.ts +0 -18
- package/dist/agent-execution-limits.js +0 -21
- package/dist/agent-execution-preparation.d.ts +2 -22
- package/dist/agent-execution-preparation.js +1 -25
- package/dist/agent-improvement-measurement-schema.d.ts +0 -17
- package/dist/agent-improvement-measurement-schema.js +3 -3
- package/dist/agent-improvement-source.d.ts +0 -2
- package/dist/agent-workspace-lease.d.ts +0 -23
- package/dist/agent-workspace-lease.js +0 -4
- package/dist/contract-limits.d.ts +0 -3
- package/dist/contract-limits.js +0 -10
- package/dist/environment-interactive-start.d.ts +0 -2
- package/dist/environment-interactive-start.js +1 -1
- package/dist/environment-observation.d.ts +0 -17
- package/dist/environment-observation.js +0 -13
- package/dist/environment-provider.d.ts +2 -1
- package/dist/environment-provider.js +2 -1
- package/dist/environment-runtime.d.ts +2 -16
- package/dist/environment-runtime.js +1 -5
- package/dist/index.d.ts +1 -3
- package/dist/index.js +1 -3
- package/dist/interaction-fields.d.ts +0 -1
- package/dist/interaction-response-validation.d.ts +0 -5
- package/dist/interaction-response-validation.js +0 -12
- package/dist/parts.d.ts +0 -3
- package/dist/parts.js +0 -9
- package/dist/plan.d.ts +0 -8
- package/dist/plan.js +0 -6
- package/dist/profile-diff.d.ts +0 -1
- package/dist/profile-diff.js +0 -31
- package/dist/profile-kb/index.d.ts +1 -22
- package/dist/profile-kb/index.js +1 -23
- package/dist/runtime-control.d.ts +0 -61
- package/dist/runtime-control.js +0 -76
- package/dist/workspace-confidentiality.d.ts +0 -2
- package/dist/workspace-confidentiality.js +1 -1
- package/package.json +1 -11
- package/dist/agent-instance.d.ts +0 -98
- package/dist/agent-instance.js +0 -105
- package/dist/certified-context.d.ts +0 -118
- package/dist/certified-context.js +0 -220
- package/dist/environment-interactive.d.ts +0 -2
- package/dist/environment-interactive.js +0 -2
package/dist/agent-instance.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { isWellFormedUnicode, sha256DigestSchema, } from "./agent-candidate-schema-common.js";
|
|
3
|
-
import { harnessTypeSchema } from "./harness.js";
|
|
4
|
-
import { agentProfileSchema } from "./profile-schema.js";
|
|
5
|
-
/** Lifecycle state of one managed Agent inside an execution environment. */
|
|
6
|
-
export const AGENT_INSTANCE_STATUSES = [
|
|
7
|
-
"starting",
|
|
8
|
-
"ready",
|
|
9
|
-
"busy",
|
|
10
|
-
"failed",
|
|
11
|
-
"stopped",
|
|
12
|
-
];
|
|
13
|
-
/**
|
|
14
|
-
* How one Agent sees the provider-owned workspace.
|
|
15
|
-
*
|
|
16
|
-
* `shared` is ordinary same-computer visibility. `isolated` requests a private
|
|
17
|
-
* writable view with provider-defined inspect or commit behavior. Neither mode
|
|
18
|
-
* is a security boundary between mutually untrusted Agents.
|
|
19
|
-
*/
|
|
20
|
-
export const AGENT_INSTANCE_WORKSPACE_MODES = ["shared", "isolated"];
|
|
21
|
-
const identifierSchema = z
|
|
22
|
-
.string()
|
|
23
|
-
.min(1)
|
|
24
|
-
.max(128)
|
|
25
|
-
.regex(/^[A-Za-z0-9](?:[A-Za-z0-9._:-]*[A-Za-z0-9])?$/, "identifier must use visible alphanumeric, '.', '_', ':', or '-' characters");
|
|
26
|
-
const labelSchema = z
|
|
27
|
-
.string()
|
|
28
|
-
.min(1)
|
|
29
|
-
.max(256)
|
|
30
|
-
.refine((value) => isWellFormedUnicode(value) && !/[\u0000-\u001f\u007f]/u.test(value), "label must be valid Unicode without control characters");
|
|
31
|
-
const failureMessageSchema = z
|
|
32
|
-
.string()
|
|
33
|
-
.min(1)
|
|
34
|
-
.max(16_384)
|
|
35
|
-
.refine((value) => isWellFormedUnicode(value) && !value.includes("\0"), "failure message must be valid Unicode without NUL");
|
|
36
|
-
const timestampSchema = z
|
|
37
|
-
.number()
|
|
38
|
-
.int()
|
|
39
|
-
.nonnegative()
|
|
40
|
-
.max(Number.MAX_SAFE_INTEGER);
|
|
41
|
-
export const agentInstanceStatusSchema = z.enum(AGENT_INSTANCE_STATUSES);
|
|
42
|
-
export const agentInstanceWorkspaceModeSchema = z.enum(AGENT_INSTANCE_WORKSPACE_MODES);
|
|
43
|
-
export const agentInstanceWorkspaceSchema = z.strictObject({
|
|
44
|
-
mode: agentInstanceWorkspaceModeSchema,
|
|
45
|
-
});
|
|
46
|
-
export const agentInstanceSpecSchema = z.strictObject({
|
|
47
|
-
id: identifierSchema.optional(),
|
|
48
|
-
name: labelSchema.optional(),
|
|
49
|
-
profile: agentProfileSchema.optional(),
|
|
50
|
-
harness: harnessTypeSchema.optional(),
|
|
51
|
-
workspace: agentInstanceWorkspaceSchema.optional(),
|
|
52
|
-
});
|
|
53
|
-
export const agentInstanceProfileIdentitySchema = z.strictObject({
|
|
54
|
-
name: labelSchema.optional(),
|
|
55
|
-
digest: sha256DigestSchema,
|
|
56
|
-
});
|
|
57
|
-
export const agentInstanceFailureSchema = z.strictObject({
|
|
58
|
-
code: identifierSchema.optional(),
|
|
59
|
-
message: failureMessageSchema,
|
|
60
|
-
});
|
|
61
|
-
export const agentInstanceRecordSchema = z
|
|
62
|
-
.strictObject({
|
|
63
|
-
kind: z.literal("agent-instance"),
|
|
64
|
-
schemaVersion: z.literal(1),
|
|
65
|
-
id: identifierSchema,
|
|
66
|
-
name: labelSchema.optional(),
|
|
67
|
-
profile: agentInstanceProfileIdentitySchema.optional(),
|
|
68
|
-
harness: harnessTypeSchema.optional(),
|
|
69
|
-
workspace: agentInstanceWorkspaceSchema,
|
|
70
|
-
status: agentInstanceStatusSchema,
|
|
71
|
-
failure: agentInstanceFailureSchema.optional(),
|
|
72
|
-
createdAtMs: timestampSchema,
|
|
73
|
-
updatedAtMs: timestampSchema,
|
|
74
|
-
})
|
|
75
|
-
.superRefine((record, context) => {
|
|
76
|
-
if (record.updatedAtMs < record.createdAtMs) {
|
|
77
|
-
context.addIssue({
|
|
78
|
-
code: "custom",
|
|
79
|
-
path: ["updatedAtMs"],
|
|
80
|
-
message: "agent instance update cannot precede creation",
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
if (record.status === "failed" && record.failure === undefined) {
|
|
84
|
-
context.addIssue({
|
|
85
|
-
code: "custom",
|
|
86
|
-
path: ["failure"],
|
|
87
|
-
message: "failed agent instance requires a failure reason",
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
if (record.status !== "failed" && record.failure !== undefined) {
|
|
91
|
-
context.addIssue({
|
|
92
|
-
code: "custom",
|
|
93
|
-
path: ["failure"],
|
|
94
|
-
message: "failure reason is valid only for failed agent instances",
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
export const agentInstanceStopRequestSchema = z.strictObject({
|
|
99
|
-
agentId: identifierSchema,
|
|
100
|
-
force: z.boolean().optional(),
|
|
101
|
-
});
|
|
102
|
-
export const agentInstanceStopAcknowledgementSchema = z.strictObject({
|
|
103
|
-
agentId: identifierSchema,
|
|
104
|
-
outcome: z.enum(["stopped", "already-stopped", "not-found"]),
|
|
105
|
-
});
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import type { Sha256Digest } from "./agent-candidate.js";
|
|
3
|
-
export type CertifiedContextKind = "prompt" | "skill" | "instructions";
|
|
4
|
-
export type CertifiedContextDelivery = {
|
|
5
|
-
readonly kind: "inline";
|
|
6
|
-
readonly content: string;
|
|
7
|
-
} | {
|
|
8
|
-
readonly kind: "file";
|
|
9
|
-
readonly path: string;
|
|
10
|
-
readonly content: string;
|
|
11
|
-
};
|
|
12
|
-
export interface CertifiedContextProvenance {
|
|
13
|
-
/** SHA-256 of the entry id, kind, name, and delivery. */
|
|
14
|
-
readonly contentHash: Sha256Digest;
|
|
15
|
-
/** Positive release number, or null when the source has no released version. */
|
|
16
|
-
readonly version: number | null;
|
|
17
|
-
readonly promotedAt: string;
|
|
18
|
-
}
|
|
19
|
-
export interface CertifiedContextEntry {
|
|
20
|
-
readonly id: string;
|
|
21
|
-
readonly kind: CertifiedContextKind;
|
|
22
|
-
readonly name: string;
|
|
23
|
-
readonly delivery: CertifiedContextDelivery;
|
|
24
|
-
readonly provenance: CertifiedContextProvenance;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Tenant-bound context delivered by Intelligence.
|
|
28
|
-
*
|
|
29
|
-
* This contract intentionally excludes tools, credentials, executable files,
|
|
30
|
-
* profile patches, MCP servers, and arbitrary network requests.
|
|
31
|
-
*/
|
|
32
|
-
export interface CertifiedContext {
|
|
33
|
-
readonly tenantId: string;
|
|
34
|
-
readonly target: string;
|
|
35
|
-
readonly state: "active" | "revoked";
|
|
36
|
-
/** Monotonic decimal revision for this tenant and target. */
|
|
37
|
-
readonly revision: string;
|
|
38
|
-
readonly generatedAt: string;
|
|
39
|
-
readonly expiresAt: string;
|
|
40
|
-
readonly entries: readonly CertifiedContextEntry[];
|
|
41
|
-
/** SHA-256 of tenantId, target, state, revision, and entries. */
|
|
42
|
-
readonly contentHash: Sha256Digest;
|
|
43
|
-
}
|
|
44
|
-
export declare const certifiedContextDeliverySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
45
|
-
kind: z.ZodLiteral<"inline">;
|
|
46
|
-
content: z.ZodString;
|
|
47
|
-
}, z.core.$strict>, z.ZodObject<{
|
|
48
|
-
kind: z.ZodLiteral<"file">;
|
|
49
|
-
path: z.ZodString;
|
|
50
|
-
content: z.ZodString;
|
|
51
|
-
}, z.core.$strict>], "kind">;
|
|
52
|
-
export declare const certifiedContextProvenanceSchema: z.ZodObject<{
|
|
53
|
-
contentHash: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
54
|
-
version: z.ZodNullable<z.ZodNumber>;
|
|
55
|
-
promotedAt: z.ZodISODateTime;
|
|
56
|
-
}, z.core.$strict>;
|
|
57
|
-
/** Compute the exact digest stored in an entry's provenance. */
|
|
58
|
-
export declare function certifiedContextEntryContentHash(entry: Pick<CertifiedContextEntry, "id" | "kind" | "name" | "delivery">): Sha256Digest;
|
|
59
|
-
export declare const certifiedContextEntrySchema: z.ZodObject<{
|
|
60
|
-
id: z.ZodString;
|
|
61
|
-
kind: z.ZodEnum<{
|
|
62
|
-
instructions: "instructions";
|
|
63
|
-
prompt: "prompt";
|
|
64
|
-
skill: "skill";
|
|
65
|
-
}>;
|
|
66
|
-
name: z.ZodString;
|
|
67
|
-
delivery: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
68
|
-
kind: z.ZodLiteral<"inline">;
|
|
69
|
-
content: z.ZodString;
|
|
70
|
-
}, z.core.$strict>, z.ZodObject<{
|
|
71
|
-
kind: z.ZodLiteral<"file">;
|
|
72
|
-
path: z.ZodString;
|
|
73
|
-
content: z.ZodString;
|
|
74
|
-
}, z.core.$strict>], "kind">;
|
|
75
|
-
provenance: z.ZodObject<{
|
|
76
|
-
contentHash: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
77
|
-
version: z.ZodNullable<z.ZodNumber>;
|
|
78
|
-
promotedAt: z.ZodISODateTime;
|
|
79
|
-
}, z.core.$strict>;
|
|
80
|
-
}, z.core.$strict>;
|
|
81
|
-
/** Compute the stable hash for one context revision. */
|
|
82
|
-
export declare function certifiedContextContentHash(context: Pick<CertifiedContext, "tenantId" | "target" | "state" | "revision" | "entries">): Sha256Digest;
|
|
83
|
-
export declare const certifiedContextSchema: z.ZodObject<{
|
|
84
|
-
tenantId: z.ZodString;
|
|
85
|
-
target: z.ZodString;
|
|
86
|
-
state: z.ZodEnum<{
|
|
87
|
-
active: "active";
|
|
88
|
-
revoked: "revoked";
|
|
89
|
-
}>;
|
|
90
|
-
revision: z.ZodString;
|
|
91
|
-
generatedAt: z.ZodISODateTime;
|
|
92
|
-
expiresAt: z.ZodISODateTime;
|
|
93
|
-
entries: z.ZodArray<z.ZodObject<{
|
|
94
|
-
id: z.ZodString;
|
|
95
|
-
kind: z.ZodEnum<{
|
|
96
|
-
instructions: "instructions";
|
|
97
|
-
prompt: "prompt";
|
|
98
|
-
skill: "skill";
|
|
99
|
-
}>;
|
|
100
|
-
name: z.ZodString;
|
|
101
|
-
delivery: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
102
|
-
kind: z.ZodLiteral<"inline">;
|
|
103
|
-
content: z.ZodString;
|
|
104
|
-
}, z.core.$strict>, z.ZodObject<{
|
|
105
|
-
kind: z.ZodLiteral<"file">;
|
|
106
|
-
path: z.ZodString;
|
|
107
|
-
content: z.ZodString;
|
|
108
|
-
}, z.core.$strict>], "kind">;
|
|
109
|
-
provenance: z.ZodObject<{
|
|
110
|
-
contentHash: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
111
|
-
version: z.ZodNullable<z.ZodNumber>;
|
|
112
|
-
promotedAt: z.ZodISODateTime;
|
|
113
|
-
}, z.core.$strict>;
|
|
114
|
-
}, z.core.$strict>>;
|
|
115
|
-
contentHash: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
116
|
-
}, z.core.$strict>;
|
|
117
|
-
/** Parse, clone, and recursively freeze one untrusted context response. */
|
|
118
|
-
export declare function parseCertifiedContext(value: unknown): CertifiedContext;
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { deepFreeze } from "./deep-freeze.js";
|
|
3
|
-
import { canonicalCandidateDigest, isSafeRelativePath, sha256DigestSchema, } from "./agent-candidate-schema-common.js";
|
|
4
|
-
const MAX_INLINE_CONTEXT_BYTES = 65_536;
|
|
5
|
-
const MAX_TOTAL_INLINE_CONTEXT_BYTES = 131_072;
|
|
6
|
-
const MAX_FILE_CONTEXT_BYTES = 1_048_576;
|
|
7
|
-
const MAX_CERTIFIED_CONTEXT_BYTES = 16_777_216;
|
|
8
|
-
const MAX_CERTIFIED_CONTEXT_LIFETIME_MS = 900_000;
|
|
9
|
-
const revisionPattern = /^(0|[1-9]\d{0,18})$/;
|
|
10
|
-
const nonBlankStringSchema = z
|
|
11
|
-
.string()
|
|
12
|
-
.refine((value) => value.trim().length > 0, "value cannot be blank");
|
|
13
|
-
const identifierSchema = nonBlankStringSchema.max(256);
|
|
14
|
-
const relativePathSchema = nonBlankStringSchema
|
|
15
|
-
.max(1_024)
|
|
16
|
-
.refine((value) => isSafeRelativePath(value, false), "value must be a canonical relative path");
|
|
17
|
-
const inlineContentSchema = z
|
|
18
|
-
.string()
|
|
19
|
-
.max(MAX_INLINE_CONTEXT_BYTES)
|
|
20
|
-
.refine((value) => new TextEncoder().encode(value).byteLength <= MAX_INLINE_CONTEXT_BYTES, `inline content exceeds ${MAX_INLINE_CONTEXT_BYTES} UTF-8 bytes`);
|
|
21
|
-
const fileContentSchema = z
|
|
22
|
-
.string()
|
|
23
|
-
.max(MAX_FILE_CONTEXT_BYTES)
|
|
24
|
-
.refine((value) => new TextEncoder().encode(value).byteLength <= MAX_FILE_CONTEXT_BYTES, `file content exceeds ${MAX_FILE_CONTEXT_BYTES} UTF-8 bytes`);
|
|
25
|
-
export const certifiedContextDeliverySchema = z.discriminatedUnion("kind", [
|
|
26
|
-
z.strictObject({
|
|
27
|
-
kind: z.literal("inline"),
|
|
28
|
-
content: inlineContentSchema,
|
|
29
|
-
}),
|
|
30
|
-
z.strictObject({
|
|
31
|
-
kind: z.literal("file"),
|
|
32
|
-
path: relativePathSchema,
|
|
33
|
-
content: fileContentSchema,
|
|
34
|
-
}),
|
|
35
|
-
]);
|
|
36
|
-
export const certifiedContextProvenanceSchema = z.strictObject({
|
|
37
|
-
contentHash: sha256DigestSchema,
|
|
38
|
-
version: z.number().int().positive().max(Number.MAX_SAFE_INTEGER).nullable(),
|
|
39
|
-
promotedAt: z.iso.datetime(),
|
|
40
|
-
});
|
|
41
|
-
function jsonMaterial(value) {
|
|
42
|
-
const serialized = JSON.stringify(value);
|
|
43
|
-
if (serialized === undefined) {
|
|
44
|
-
throw new Error("certified context material must be JSON serializable");
|
|
45
|
-
}
|
|
46
|
-
return JSON.parse(serialized);
|
|
47
|
-
}
|
|
48
|
-
/** Compute the exact digest stored in an entry's provenance. */
|
|
49
|
-
export function certifiedContextEntryContentHash(entry) {
|
|
50
|
-
return canonicalCandidateDigest(jsonMaterial({
|
|
51
|
-
id: entry.id,
|
|
52
|
-
kind: entry.kind,
|
|
53
|
-
name: entry.name,
|
|
54
|
-
delivery: entry.delivery,
|
|
55
|
-
}));
|
|
56
|
-
}
|
|
57
|
-
export const certifiedContextEntrySchema = z
|
|
58
|
-
.strictObject({
|
|
59
|
-
id: identifierSchema,
|
|
60
|
-
kind: z.enum(["prompt", "skill", "instructions"]),
|
|
61
|
-
name: identifierSchema,
|
|
62
|
-
delivery: certifiedContextDeliverySchema,
|
|
63
|
-
provenance: certifiedContextProvenanceSchema,
|
|
64
|
-
})
|
|
65
|
-
.superRefine((entry, context) => {
|
|
66
|
-
if (entry.kind === "skill" && entry.delivery.kind !== "file") {
|
|
67
|
-
context.addIssue({
|
|
68
|
-
code: "custom",
|
|
69
|
-
path: ["delivery", "kind"],
|
|
70
|
-
message: "skills must be delivered as files",
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
if (entry.kind !== "skill" && entry.delivery.kind !== "inline") {
|
|
74
|
-
context.addIssue({
|
|
75
|
-
code: "custom",
|
|
76
|
-
path: ["delivery", "kind"],
|
|
77
|
-
message: "prompts and instructions must be delivered inline",
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
if (entry.delivery.kind === "inline" &&
|
|
81
|
-
entry.delivery.content.trim().length === 0) {
|
|
82
|
-
context.addIssue({
|
|
83
|
-
code: "custom",
|
|
84
|
-
path: ["delivery", "content"],
|
|
85
|
-
message: "inline context cannot be blank",
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
if (entry.provenance.contentHash !== certifiedContextEntryContentHash(entry)) {
|
|
89
|
-
context.addIssue({
|
|
90
|
-
code: "custom",
|
|
91
|
-
path: ["provenance", "contentHash"],
|
|
92
|
-
message: "entry content hash does not match the delivered context",
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
/** Compute the stable hash for one context revision. */
|
|
97
|
-
export function certifiedContextContentHash(context) {
|
|
98
|
-
return canonicalCandidateDigest(jsonMaterial(context));
|
|
99
|
-
}
|
|
100
|
-
export const certifiedContextSchema = z
|
|
101
|
-
.strictObject({
|
|
102
|
-
tenantId: identifierSchema,
|
|
103
|
-
target: identifierSchema,
|
|
104
|
-
state: z.enum(["active", "revoked"]),
|
|
105
|
-
revision: z
|
|
106
|
-
.string()
|
|
107
|
-
.regex(revisionPattern)
|
|
108
|
-
.refine((value) => !revisionPattern.test(value) ||
|
|
109
|
-
BigInt(value) <= 9223372036854775807n, "revision exceeds signed 64-bit range"),
|
|
110
|
-
generatedAt: z.iso.datetime(),
|
|
111
|
-
expiresAt: z.iso.datetime(),
|
|
112
|
-
entries: z.array(certifiedContextEntrySchema).max(128),
|
|
113
|
-
contentHash: sha256DigestSchema,
|
|
114
|
-
})
|
|
115
|
-
.superRefine((context, refinement) => {
|
|
116
|
-
const generatedAt = Date.parse(context.generatedAt);
|
|
117
|
-
const expiresAt = Date.parse(context.expiresAt);
|
|
118
|
-
if (expiresAt <= generatedAt) {
|
|
119
|
-
refinement.addIssue({
|
|
120
|
-
code: "custom",
|
|
121
|
-
path: ["expiresAt"],
|
|
122
|
-
message: "expiresAt must be after generatedAt",
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
else if (expiresAt - generatedAt >
|
|
126
|
-
MAX_CERTIFIED_CONTEXT_LIFETIME_MS) {
|
|
127
|
-
refinement.addIssue({
|
|
128
|
-
code: "custom",
|
|
129
|
-
path: ["expiresAt"],
|
|
130
|
-
message: "certified context cannot live longer than 15 minutes",
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
const serialized = JSON.stringify(context);
|
|
134
|
-
if (new TextEncoder().encode(serialized).byteLength >
|
|
135
|
-
MAX_CERTIFIED_CONTEXT_BYTES) {
|
|
136
|
-
refinement.addIssue({
|
|
137
|
-
code: "too_big",
|
|
138
|
-
maximum: MAX_CERTIFIED_CONTEXT_BYTES,
|
|
139
|
-
origin: "string",
|
|
140
|
-
inclusive: true,
|
|
141
|
-
message: `serialized context exceeds ${MAX_CERTIFIED_CONTEXT_BYTES} UTF-8 bytes`,
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
const ids = new Set();
|
|
145
|
-
const filePaths = new Set();
|
|
146
|
-
let inlineBytes = 0;
|
|
147
|
-
for (const [index, entry] of context.entries.entries()) {
|
|
148
|
-
if (ids.has(entry.id)) {
|
|
149
|
-
refinement.addIssue({
|
|
150
|
-
code: "custom",
|
|
151
|
-
path: ["entries", index, "id"],
|
|
152
|
-
message: `duplicate context id: ${entry.id}`,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
ids.add(entry.id);
|
|
156
|
-
if (entry.delivery.kind === "file") {
|
|
157
|
-
if (filePaths.has(entry.delivery.path)) {
|
|
158
|
-
refinement.addIssue({
|
|
159
|
-
code: "custom",
|
|
160
|
-
path: ["entries", index, "delivery", "path"],
|
|
161
|
-
message: `duplicate file path: ${entry.delivery.path}`,
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
filePaths.add(entry.delivery.path);
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
inlineBytes += new TextEncoder().encode(entry.delivery.content).byteLength;
|
|
168
|
-
}
|
|
169
|
-
if (Date.parse(entry.provenance.promotedAt) > generatedAt) {
|
|
170
|
-
refinement.addIssue({
|
|
171
|
-
code: "custom",
|
|
172
|
-
path: ["entries", index, "provenance", "promotedAt"],
|
|
173
|
-
message: "context cannot be promoted after bundle generation",
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
if (inlineBytes > MAX_TOTAL_INLINE_CONTEXT_BYTES) {
|
|
178
|
-
refinement.addIssue({
|
|
179
|
-
code: "custom",
|
|
180
|
-
path: ["entries"],
|
|
181
|
-
message: `inline context exceeds ${MAX_TOTAL_INLINE_CONTEXT_BYTES} UTF-8 bytes`,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
if ((context.state === "active" && context.entries.length === 0) ||
|
|
185
|
-
(context.state === "revoked" && context.entries.length !== 0)) {
|
|
186
|
-
refinement.addIssue({
|
|
187
|
-
code: "custom",
|
|
188
|
-
path: ["entries"],
|
|
189
|
-
message: "active context requires entries and revoked context requires none",
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
const material = {
|
|
193
|
-
tenantId: context.tenantId,
|
|
194
|
-
target: context.target,
|
|
195
|
-
state: context.state,
|
|
196
|
-
revision: context.revision,
|
|
197
|
-
entries: context.entries,
|
|
198
|
-
};
|
|
199
|
-
if (context.contentHash !== certifiedContextContentHash(material)) {
|
|
200
|
-
refinement.addIssue({
|
|
201
|
-
code: "custom",
|
|
202
|
-
path: ["contentHash"],
|
|
203
|
-
message: "context content hash does not match the delivered context",
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
const _certifiedContextDeliverySchemaMatches = true;
|
|
208
|
-
const _certifiedContextProvenanceSchemaMatches = true;
|
|
209
|
-
const _certifiedContextEntrySchemaMatches = true;
|
|
210
|
-
const _certifiedContextSchemaMatches = true;
|
|
211
|
-
void [
|
|
212
|
-
_certifiedContextDeliverySchemaMatches,
|
|
213
|
-
_certifiedContextProvenanceSchemaMatches,
|
|
214
|
-
_certifiedContextEntrySchemaMatches,
|
|
215
|
-
_certifiedContextSchemaMatches,
|
|
216
|
-
];
|
|
217
|
-
/** Parse, clone, and recursively freeze one untrusted context response. */
|
|
218
|
-
export function parseCertifiedContext(value) {
|
|
219
|
-
return deepFreeze(certifiedContextSchema.parse(value));
|
|
220
|
-
}
|