@sequenceholdings/managed-functions 0.4.0 → 0.4.2

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 (92) hide show
  1. package/README.md +444 -2
  2. package/dist/abrigo-contract.d.ts +92 -0
  3. package/dist/abrigo-contract.js +55 -0
  4. package/dist/abrigo-response.d.ts +6 -0
  5. package/dist/abrigo-response.js +27 -0
  6. package/dist/abrigo.d.ts +14 -0
  7. package/dist/abrigo.js +150 -0
  8. package/dist/agent-evidence.d.ts +9 -0
  9. package/dist/agent-evidence.js +84 -0
  10. package/dist/agent-source-evidence-contract.d.ts +1197 -0
  11. package/dist/agent-source-evidence-contract.js +96 -0
  12. package/dist/agents-contract.d.ts +99 -0
  13. package/dist/agents-contract.js +69 -0
  14. package/dist/agents.d.ts +15 -0
  15. package/dist/agents.js +121 -0
  16. package/dist/capabilities.d.ts +165 -0
  17. package/dist/capabilities.js +61 -1
  18. package/dist/config.d.ts +18 -2
  19. package/dist/config.js +62 -1
  20. package/dist/deployed-policy.js +102 -0
  21. package/dist/directory-config.d.ts +23 -0
  22. package/dist/directory-config.js +22 -0
  23. package/dist/directory-contract.d.ts +68 -0
  24. package/dist/directory-contract.js +57 -0
  25. package/dist/directory-manifest.d.ts +5 -0
  26. package/dist/directory-manifest.js +10 -0
  27. package/dist/directory.d.ts +15 -0
  28. package/dist/directory.js +65 -0
  29. package/dist/http-tracing.js +3 -0
  30. package/dist/immutable-release-contract.d.ts +3 -0
  31. package/dist/immutable-release-contract.js +12 -0
  32. package/dist/index.d.ts +40 -1
  33. package/dist/index.js +75 -1
  34. package/dist/invocation-client.d.ts +45 -0
  35. package/dist/invocation-client.js +90 -0
  36. package/dist/invocation-contract.d.ts +36 -0
  37. package/dist/invocation-contract.js +48 -0
  38. package/dist/invocation.d.ts +8 -0
  39. package/dist/invocation.js +134 -0
  40. package/dist/lattice-capability.d.ts +5 -0
  41. package/dist/lattice-capability.js +16 -0
  42. package/dist/lattice-provenance-contract.d.ts +519 -0
  43. package/dist/lattice-provenance-contract.js +148 -0
  44. package/dist/lattice-provenance.d.ts +16 -0
  45. package/dist/lattice-provenance.js +167 -0
  46. package/dist/monitoring-annotations.d.ts +53 -0
  47. package/dist/monitoring-annotations.js +54 -0
  48. package/dist/monitoring-contract.d.ts +463 -0
  49. package/dist/monitoring-contract.js +89 -0
  50. package/dist/monitoring-events.d.ts +257 -0
  51. package/dist/monitoring-events.js +136 -0
  52. package/dist/monitoring.d.ts +14 -0
  53. package/dist/monitoring.js +78 -0
  54. package/dist/orm-contract.d.ts +1 -0
  55. package/dist/orm-contract.js +4 -0
  56. package/dist/orm.d.ts +19 -3
  57. package/dist/orm.js +93 -13
  58. package/dist/preflight-abrigo.d.ts +10 -0
  59. package/dist/preflight-abrigo.js +26 -0
  60. package/dist/preflight-agents.d.ts +10 -0
  61. package/dist/preflight-agents.js +51 -0
  62. package/dist/preflight-directory.d.ts +10 -0
  63. package/dist/preflight-directory.js +36 -0
  64. package/dist/preflight-immutable-release.d.ts +10 -0
  65. package/dist/preflight-immutable-release.js +34 -0
  66. package/dist/preflight-invocation.d.ts +10 -0
  67. package/dist/preflight-invocation.js +40 -0
  68. package/dist/preflight-lattice.d.ts +10 -0
  69. package/dist/preflight-lattice.js +40 -0
  70. package/dist/preflight-monitoring.d.ts +10 -0
  71. package/dist/preflight-monitoring.js +46 -0
  72. package/dist/preflight-service-directory.d.ts +10 -0
  73. package/dist/preflight-service-directory.js +26 -0
  74. package/dist/preflight-workflows.d.ts +10 -0
  75. package/dist/preflight-workflows.js +38 -0
  76. package/dist/preflight.js +50 -2
  77. package/dist/processes-contract.d.ts +20 -0
  78. package/dist/processes-contract.js +8 -1
  79. package/dist/processes.d.ts +4 -8
  80. package/dist/processes.js +52 -83
  81. package/dist/runtime.cjs +3387 -259
  82. package/dist/sdk-range.d.ts +1 -0
  83. package/dist/sdk-range.js +25 -0
  84. package/dist/service-directory.d.ts +12 -0
  85. package/dist/service-directory.js +72 -0
  86. package/dist/workflow-scopes-contract.d.ts +8 -0
  87. package/dist/workflow-scopes-contract.js +29 -0
  88. package/dist/workflow-source-contract.d.ts +524 -0
  89. package/dist/workflow-source-contract.js +59 -0
  90. package/dist/workflow-source.d.ts +12 -0
  91. package/dist/workflow-source.js +93 -0
  92. package/package.json +2 -2
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateAbrigoReviewResponse = validateAbrigoReviewResponse;
4
+ const zod_1 = require("zod");
5
+ const abrigo_contract_1 = require("./abrigo-contract");
6
+ const positiveId = zod_1.z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
7
+ const reviewWorkflowSchema = zod_1.z.strictObject({ id: positiveId, customerId: positiveId });
8
+ const reviewDocumentsSchema = zod_1.z.object({ items: zod_1.z.array(zod_1.z.unknown()).max(500) }).passthrough();
9
+ const reviewCustomerDocumentsSchema = reviewDocumentsSchema.extend({ workflowId: positiveId, customerId: positiveId });
10
+ function validateAbrigoReviewResponse({ query, body }) {
11
+ const invalid = () => new abrigo_contract_1.FunctionAbrigoReadError(502, 'malformed_response', 'Atlas returned an invalid workflow document review response');
12
+ if (query.operation === 'reviewWorkflow') {
13
+ const parsed = reviewWorkflowSchema.safeParse(body);
14
+ if (!parsed.success || parsed.data.id !== query.workflowId)
15
+ throw invalid();
16
+ }
17
+ else if (query.operation === 'reviewWorkflowDocuments') {
18
+ const parsed = reviewDocumentsSchema.safeParse(body);
19
+ if (!parsed.success || parsed.data.items.length > query.perPage)
20
+ throw invalid();
21
+ }
22
+ else if (query.operation === 'reviewWorkflowCustomerDocuments') {
23
+ const parsed = reviewCustomerDocumentsSchema.safeParse(body);
24
+ if (!parsed.success || parsed.data.workflowId !== query.workflowId || parsed.data.items.length > query.perPage)
25
+ throw invalid();
26
+ }
27
+ }
@@ -0,0 +1,14 @@
1
+ import type { JsonValue } from './cache';
2
+ import { type FunctionAbrigoReadRequest } from './abrigo-contract';
3
+ export * from './abrigo-contract';
4
+ export interface FunctionCallerAbrigoOptions {
5
+ request: {
6
+ headers: Pick<Headers, 'get'> | Readonly<Record<string, string | readonly string[] | undefined>>;
7
+ };
8
+ baseUrl: string;
9
+ fetchImpl?: typeof globalThis.fetch;
10
+ }
11
+ export interface FunctionCallerAbrigoClient {
12
+ read(query: FunctionAbrigoReadRequest): Promise<JsonValue>;
13
+ }
14
+ export declare function createFunctionCallerAbrigoClient({ request, baseUrl, fetchImpl }: FunctionCallerAbrigoOptions): FunctionCallerAbrigoClient;
package/dist/abrigo.js ADDED
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.createFunctionCallerAbrigoClient = createFunctionCallerAbrigoClient;
18
+ const zod_1 = require("zod");
19
+ const abrigo_response_1 = require("./abrigo-response");
20
+ const abrigo_contract_1 = require("./abrigo-contract");
21
+ __exportStar(require("./abrigo-contract"), exports);
22
+ const claimsSchema = zod_1.z.object({
23
+ audience: zod_1.z.literal(abrigo_contract_1.FUNCTION_ABRIGO_READ_AUDIENCE), environment: zod_1.z.string().min(1).max(4096),
24
+ functionId: zod_1.z.uuid(), versionId: zod_1.z.uuid(), invocationId: zod_1.z.uuid(), serviceAccountId: zod_1.z.uuid(),
25
+ org: zod_1.z.string().min(1).max(255), callerKind: zod_1.z.literal('human'),
26
+ callerSub: zod_1.z.string().min(1).max(512).regex(/^[^\s:#|]+\|[^\s:#]+$/).refine((sub) => !sub.startsWith('service-account|') && !sub.startsWith('managed-function|') &&
27
+ !sub.startsWith('system|') && !sub.endsWith('@clients') && sub !== 'google-apps|sequence.agent@seqholdings.com', 'Only actual human callers may read Abrigo'),
28
+ callerAuthenticationMethod: zod_1.z.string().min(1).max(64),
29
+ exp: zod_1.z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
30
+ });
31
+ function credential({ request }) {
32
+ const invalid = () => new abrigo_contract_1.FunctionAbrigoReadError(401, 'invalid_context', 'This invocation has no valid caller Abrigo read credential');
33
+ const headers = request.headers;
34
+ const matches = typeof headers.get === 'function' ? [headers.get(abrigo_contract_1.FUNCTION_ABRIGO_READ_TOKEN_HEADER)]
35
+ : Object.entries(headers).filter(([name]) => name.toLowerCase() === abrigo_contract_1.FUNCTION_ABRIGO_READ_TOKEN_HEADER).map(([, value]) => value);
36
+ const token = matches[0];
37
+ if (matches.length !== 1 || typeof token !== 'string' || token.length > 16_384)
38
+ throw invalid();
39
+ const envelope = /^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]{43})$/.exec(token);
40
+ if (!envelope?.[1])
41
+ throw invalid();
42
+ let value;
43
+ try {
44
+ const decoded = Buffer.from(envelope[1], 'base64url');
45
+ if (decoded.toString('base64url') !== envelope[1])
46
+ throw invalid();
47
+ value = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(decoded));
48
+ }
49
+ catch {
50
+ throw invalid();
51
+ }
52
+ const parsed = claimsSchema.safeParse(value);
53
+ if (!parsed.success)
54
+ throw invalid();
55
+ return { token, expiresAt: parsed.data.exp };
56
+ }
57
+ function origin(baseUrl) {
58
+ const invalid = () => new abrigo_contract_1.FunctionAbrigoReadError(400, 'invalid_configuration', 'Configure a trusted HTTPS Atlas origin without credentials, path, query or fragment');
59
+ let url;
60
+ try {
61
+ url = new URL(baseUrl);
62
+ }
63
+ catch {
64
+ throw invalid();
65
+ }
66
+ const loopback = url.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname);
67
+ if ((!loopback && url.protocol !== 'https:') || url.username || url.password || url.pathname !== '/' || url.search || url.hash)
68
+ throw invalid();
69
+ return url.origin;
70
+ }
71
+ function validJson(value, depth = 0) {
72
+ if (depth > 64)
73
+ return false;
74
+ if (value === null || typeof value === 'string' || typeof value === 'boolean')
75
+ return true;
76
+ if (typeof value === 'number')
77
+ return Number.isFinite(value) && (!Number.isInteger(value) || Number.isSafeInteger(value));
78
+ if (Array.isArray(value))
79
+ return value.every((item) => validJson(item, depth + 1));
80
+ return typeof value === 'object' && Object.values(value).every((item) => validJson(item, depth + 1));
81
+ }
82
+ async function boundedBody(response) {
83
+ const oversized = () => new abrigo_contract_1.FunctionAbrigoReadError(502, 'response_too_large', 'Abrigo read exceeded the bounded response size; reduce perPage');
84
+ const length = response.headers.get('content-length');
85
+ if (length && /^\d+$/.test(length) && Number(length) > abrigo_contract_1.ABRIGO_READ_MAX_RESPONSE_BYTES) {
86
+ await response.body?.cancel().catch(() => { });
87
+ throw oversized();
88
+ }
89
+ if (!response.body)
90
+ throw new abrigo_contract_1.FunctionAbrigoReadError(502, 'malformed_response', 'Atlas returned invalid Abrigo JSON');
91
+ const reader = response.body.getReader();
92
+ const chunks = [];
93
+ let bytes = 0;
94
+ try {
95
+ for (;;) {
96
+ const chunk = await reader.read();
97
+ if (chunk.done)
98
+ break;
99
+ bytes += chunk.value.byteLength;
100
+ if (bytes > abrigo_contract_1.ABRIGO_READ_MAX_RESPONSE_BYTES) {
101
+ await reader.cancel().catch(() => { });
102
+ throw oversized();
103
+ }
104
+ chunks.push(chunk.value);
105
+ }
106
+ }
107
+ finally {
108
+ reader.releaseLock();
109
+ }
110
+ try {
111
+ return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(Buffer.concat(chunks, bytes)));
112
+ }
113
+ catch {
114
+ throw new abrigo_contract_1.FunctionAbrigoReadError(502, 'malformed_response', 'Atlas returned invalid Abrigo JSON');
115
+ }
116
+ }
117
+ function createFunctionCallerAbrigoClient({ request, baseUrl, fetchImpl = globalThis.fetch }) {
118
+ const url = `${origin(baseUrl)}${abrigo_contract_1.FUNCTION_ABRIGO_READ_PATH}`;
119
+ const { token, expiresAt } = credential({ request });
120
+ return {
121
+ async read(input) {
122
+ if (expiresAt <= Date.now() / 1000)
123
+ throw new abrigo_contract_1.FunctionAbrigoReadError(401, 'expired_context', 'The Abrigo read credential expired; start a new invocation');
124
+ const query = abrigo_contract_1.functionAbrigoReadRequestSchema.safeParse(input);
125
+ if (!query.success)
126
+ throw new abrigo_contract_1.FunctionAbrigoReadError(400, 'invalid_request', 'Invalid bounded Abrigo read request');
127
+ try {
128
+ const response = await fetchImpl(url, { method: 'POST', headers: { 'content-type': 'application/json', [abrigo_contract_1.FUNCTION_ABRIGO_READ_TOKEN_HEADER]: token }, body: JSON.stringify(query.data), redirect: 'error', signal: AbortSignal.timeout(abrigo_contract_1.ABRIGO_READ_TIMEOUT_MS) });
129
+ const body = await boundedBody(response).catch((error) => {
130
+ if (!response.ok && error instanceof abrigo_contract_1.FunctionAbrigoReadError && error.code === 'malformed_response')
131
+ return null;
132
+ throw error;
133
+ });
134
+ if (!response.ok) {
135
+ const error = zod_1.z.object({ code: zod_1.z.string().max(128).regex(/^[a-z][a-z0-9_]*$/).optional() }).safeParse(body);
136
+ throw new abrigo_contract_1.FunctionAbrigoReadError(response.status, error.success ? error.data.code ?? 'abrigo_read_failed' : 'abrigo_read_failed', 'The authorized Abrigo read failed');
137
+ }
138
+ if (!validJson(body))
139
+ throw new abrigo_contract_1.FunctionAbrigoReadError(502, 'malformed_response', 'Atlas returned invalid Abrigo JSON');
140
+ (0, abrigo_response_1.validateAbrigoReviewResponse)({ query: query.data, body });
141
+ return body;
142
+ }
143
+ catch (error) {
144
+ if (error instanceof abrigo_contract_1.FunctionAbrigoReadError)
145
+ throw error;
146
+ throw new abrigo_contract_1.FunctionAbrigoReadError(503, 'abrigo_read_unavailable', 'The authorized Abrigo read could not be completed');
147
+ }
148
+ },
149
+ };
150
+ }
@@ -0,0 +1,9 @@
1
+ import { type FunctionServiceAgentsOptions } from './agents';
2
+ import { type FunctionAgentSourceEvidenceRequest, type FunctionAgentConversationEvidenceRequest, type FunctionAgentSourceEvidenceVerification } from './agent-source-evidence-contract';
3
+ export type FunctionAgentSourceEvidenceInput = Omit<FunctionAgentSourceEvidenceRequest, 'operation'>;
4
+ export type FunctionAgentConversationEvidenceInput = Omit<FunctionAgentConversationEvidenceRequest, 'operation'>;
5
+ export interface FunctionAgentEvidenceClient {
6
+ verifySourceEvidence(input: FunctionAgentSourceEvidenceInput): Promise<FunctionAgentSourceEvidenceVerification>;
7
+ verifyConversationEvidence(input: FunctionAgentConversationEvidenceInput): Promise<FunctionAgentSourceEvidenceVerification>;
8
+ }
9
+ export declare function createFunctionAgentEvidenceClient({ request, baseUrl, fetchImpl }: FunctionServiceAgentsOptions): FunctionAgentEvidenceClient;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createFunctionAgentEvidenceClient = createFunctionAgentEvidenceClient;
4
+ const zod_1 = require("zod");
5
+ const agents_1 = require("./agents");
6
+ const agent_source_evidence_contract_1 = require("./agent-source-evidence-contract");
7
+ function header(request, name) {
8
+ const { headers } = request;
9
+ const values = typeof headers.get === 'function' ? [headers.get(name)] : Object.entries(headers).filter(([key]) => key.toLowerCase() === name).map(([, value]) => value);
10
+ return values.length === 1 && typeof values[0] === 'string' ? values[0] : null;
11
+ }
12
+ const bindingSchema = zod_1.z.object({ audience: zod_1.z.literal('atlas-managed-function-agent-evidence'), sub: zod_1.z.string().startsWith('service-account|'), functionId: zod_1.z.uuid(), versionId: zod_1.z.uuid(), invocationId: zod_1.z.uuid(), serviceAccountId: zod_1.z.uuid(), org: zod_1.z.string().min(1), exp: zod_1.z.number().int() });
13
+ function invocation(request) {
14
+ const denied = () => new agents_1.FunctionAgentReadError(401, 'invalid_context', 'This invocation has no valid agent-evidence credential');
15
+ const token = header(request, agent_source_evidence_contract_1.FUNCTION_AGENT_EVIDENCE_TOKEN_HEADER);
16
+ const body = token && token.length <= 16_384 ? /^([A-Za-z0-9_-]+)\.[A-Za-z0-9_-]{43}$/.exec(token)?.[1] : null;
17
+ if (!body || !token)
18
+ throw denied();
19
+ let value;
20
+ try {
21
+ value = JSON.parse(Buffer.from(body, 'base64url').toString('utf8'));
22
+ }
23
+ catch {
24
+ throw denied();
25
+ }
26
+ const binding = bindingSchema.safeParse(value);
27
+ if (!binding.success || binding.data.sub !== `service-account|${binding.data.serviceAccountId}`)
28
+ throw denied();
29
+ return { token, binding: binding.data };
30
+ }
31
+ function origin(baseUrl) {
32
+ let url;
33
+ try {
34
+ url = new URL(baseUrl);
35
+ }
36
+ catch {
37
+ throw new agents_1.FunctionAgentReadError(400, 'invalid_configuration', 'Configure a trusted Atlas origin');
38
+ }
39
+ const loopback = url.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname);
40
+ if ((!loopback && url.protocol !== 'https:') || url.username || url.password || url.pathname !== '/' || url.search || url.hash)
41
+ throw new agents_1.FunctionAgentReadError(400, 'invalid_configuration', 'Configure an HTTPS Atlas origin without credentials, path, query or fragment');
42
+ return url.origin;
43
+ }
44
+ function createFunctionAgentEvidenceClient({ request, baseUrl, fetchImpl = globalThis.fetch }) {
45
+ const url = `${origin(baseUrl)}${agent_source_evidence_contract_1.FUNCTION_AGENT_EVIDENCE_PATH}`;
46
+ const { token, binding } = invocation(request);
47
+ const lattice = header(request, 'x-sequence-lattice-execution-token');
48
+ async function verify(input) {
49
+ if (binding.exp <= Date.now() / 1000)
50
+ throw new agents_1.FunctionAgentReadError(401, 'expired_context', 'The agent-evidence credential expired; start a new invocation');
51
+ const body = JSON.stringify(input);
52
+ if (Buffer.byteLength(body, 'utf8') > agent_source_evidence_contract_1.AGENT_SOURCE_VERIFY_MAX_BYTES)
53
+ throw new agents_1.FunctionAgentReadError(413, 'source_evidence_too_large', 'Source verification exceeds 768 KiB; capture a smaller source before writing');
54
+ const response = await fetchImpl(url, { method: 'POST', headers: { 'content-type': 'application/json', [agent_source_evidence_contract_1.FUNCTION_AGENT_EVIDENCE_TOKEN_HEADER]: token, ...(lattice ? { 'x-sequence-lattice-execution-token': lattice } : {}) }, body, redirect: 'error', signal: AbortSignal.timeout(30_000) });
55
+ const result = await response.json().catch(() => null);
56
+ if (!response.ok) {
57
+ const error = zod_1.z.object({ detail: zod_1.z.string().max(2000).optional(), code: zod_1.z.string().max(128).optional() }).safeParse(result);
58
+ throw new agents_1.FunctionAgentReadError(response.status, error.success ? (error.data.code ?? 'agent_evidence_failed') : 'agent_evidence_failed', error.success ? (error.data.detail ?? 'Source verification failed') : 'Source verification failed');
59
+ }
60
+ const verified = agent_source_evidence_contract_1.functionAgentSourceEvidenceVerificationSchema.safeParse(result);
61
+ if (!verified.success)
62
+ throw new agents_1.FunctionAgentReadError(502, 'malformed_response', 'Atlas returned invalid source verification');
63
+ const { source, receiver } = verified.data;
64
+ const execution = verified.data.lattice;
65
+ if (source.agentId !== input.agent || source.threadId !== input.response.threadId || source.responseHash !== input.responseHash || receiver.functionId !== binding.functionId || receiver.versionId !== binding.versionId || receiver.invocationId !== binding.invocationId || receiver.serviceAccountId !== binding.serviceAccountId || receiver.org !== binding.org ||
66
+ (execution !== null && (execution.receiverFunctionOrgId !== receiver.org || execution.receiver.functionId !== receiver.functionId || execution.receiver.versionId !== receiver.versionId || execution.receiver.invocationId !== receiver.invocationId)))
67
+ throw new agents_1.FunctionAgentReadError(502, 'malformed_response', 'Atlas returned source verification for another request or invocation');
68
+ return verified.data;
69
+ }
70
+ return {
71
+ async verifySourceEvidence(input) {
72
+ const result = await verify(agent_source_evidence_contract_1.functionAgentSourceEvidenceRequestSchema.parse({ ...input, operation: 'verifySourceEvidence' }));
73
+ if (result.source.projection === 'thread-conversation-v1' || result.source.runId !== input.runId)
74
+ throw new agents_1.FunctionAgentReadError(502, 'malformed_response', 'Atlas returned evidence for a different completed source');
75
+ return result;
76
+ },
77
+ async verifyConversationEvidence(input) {
78
+ const result = await verify(agent_source_evidence_contract_1.functionAgentConversationEvidenceRequestSchema.parse({ ...input, operation: 'verifyConversationEvidence' }));
79
+ if (result.source.projection !== 'thread-conversation-v1' || result.source.threadId !== input.threadId || result.source.revision !== input.response.revision || result.source.cutoffAt !== input.response.cutoffAt)
80
+ throw new agents_1.FunctionAgentReadError(502, 'malformed_response', 'Atlas returned evidence for a different settled conversation');
81
+ return result;
82
+ },
83
+ };
84
+ }