@adea-ai/runtime-sdk 3.0.0 → 3.0.1

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/adapter.d.ts CHANGED
@@ -622,8 +622,9 @@ export declare const RuntimeAdapterContract: Readonly<{
622
622
  }>;
623
623
  lifecycle: readonly string[];
624
624
  idempotentOperations: readonly string[];
625
- terminalStates: readonly string[];
625
+ terminalStates: readonly ["completed", "failed", "cancelled", "timed_out"];
626
626
  }>;
627
+ export declare function isTerminalRuntimeState(state: string): boolean;
627
628
  export interface RuntimeProgressOptions {
628
629
  readonly afterSequence?: number;
629
630
  readonly signal?: AbortSignal;
@@ -648,4 +649,5 @@ export declare class RuntimeAdapterError extends Error {
648
649
  constructor(errorInput: RuntimeError);
649
650
  toJSON(): RuntimeError;
650
651
  }
652
+ export declare function failRuntime(code: string, classification: RuntimeError['classification'], retryable?: boolean, details?: Record<string, string>): never;
651
653
  export declare function inspectRuntimeCapabilities(capabilities: RuntimeAdapterInspection['capabilities'], requirements: readonly CapabilityRequirement[]): CapabilityEvaluation;
package/dist/adapter.js CHANGED
@@ -1,12 +1,10 @@
1
- import { ArtifactReferenceSchema, IdentifierSchemas } from '@adea-ai/contracts';
1
+ import { ArtifactReferenceSchema, IdentifierSchemas, Sha256DigestSchema, TimestampSchema, } from '@adea-ai/contracts';
2
2
  import { z } from 'zod';
3
3
  import { CapabilityRequirementSetSchema, RuntimeCapabilitySchema, evaluateCapabilities, } from './capabilities.js';
4
4
  import { AgentPluginsCapabilityReportSchema } from './agent-plugins.js';
5
- const TimestampSchema = z.iso.datetime();
6
5
  const SemanticVersionSchema = z.string().regex(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/);
7
6
  const IdempotencyKeySchema = z.string().min(1).max(256);
8
7
  const HandleIdSchema = z.string().min(1).max(256);
9
- const DigestSchema = z.string().regex(/^sha256:[a-f0-9]{64}$/);
10
8
  export const RuntimeAdapterMetadataSchema = z
11
9
  .object({
12
10
  contractVersion: z.object({ major: z.literal(1), minor: z.number().int().nonnegative() }),
@@ -234,7 +232,7 @@ export const RuntimeExecutionPlanSnapshotSchema = z
234
232
  .object({
235
233
  schemaVersion: z.number().int().positive(),
236
234
  executionPlanId: IdentifierSchemas.executionPlanId,
237
- contentDigest: DigestSchema,
235
+ contentDigest: Sha256DigestSchema,
238
236
  runtimeRequirements: CapabilityRequirementSetSchema,
239
237
  })
240
238
  .catchall(z.unknown());
@@ -245,7 +243,7 @@ export const RuntimeAttemptBudgetAuthoritySchema = z
245
243
  executionId: IdentifierSchemas.executionId,
246
244
  attemptId: IdentifierSchemas.attemptId,
247
245
  executionPlanId: IdentifierSchemas.executionPlanId,
248
- executionPlanDigest: DigestSchema,
246
+ executionPlanDigest: Sha256DigestSchema,
249
247
  reservationKey: z.string().min(1).max(256),
250
248
  currency: z.literal('USD'),
251
249
  maximumMicrounits: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
@@ -387,6 +385,9 @@ export const RuntimeAdapterContract = Object.freeze({
387
385
  ]),
388
386
  terminalStates: Object.freeze(['completed', 'failed', 'cancelled', 'timed_out']),
389
387
  });
388
+ export function isTerminalRuntimeState(state) {
389
+ return RuntimeAdapterContract.terminalStates.includes(state);
390
+ }
390
391
  export class RuntimeAdapterError extends Error {
391
392
  code;
392
393
  classification;
@@ -412,6 +413,15 @@ export class RuntimeAdapterError extends Error {
412
413
  });
413
414
  }
414
415
  }
416
+ export function failRuntime(code, classification, retryable = false, details) {
417
+ throw new RuntimeAdapterError({
418
+ code,
419
+ classification,
420
+ message: code,
421
+ retryable,
422
+ ...(details ? { details } : {}),
423
+ });
424
+ }
415
425
  export function inspectRuntimeCapabilities(capabilities, requirements) {
416
426
  return evaluateCapabilities(capabilities, CapabilityRequirementSetSchema.parse(requirements));
417
427
  }
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { TimestampSchema } from '@adea-ai/contracts';
2
3
  export const RuntimeChannelOwnershipSchema = z
3
4
  .object({
4
5
  nodeId: z.string().regex(/^rnr_[0-9A-HJKMNP-TV-Z]{26}$/),
@@ -9,8 +10,8 @@ export const RuntimeChannelOwnershipSchema = z
9
10
  protocolVersion: z
10
11
  .object({ major: z.number().int().nonnegative(), minor: z.number().int().nonnegative() })
11
12
  .strict(),
12
- connectedAt: z.iso.datetime(),
13
- lastHeartbeatAt: z.iso.datetime(),
13
+ connectedAt: TimestampSchema,
14
+ lastHeartbeatAt: TimestampSchema,
14
15
  })
15
16
  .strict()
16
17
  .refine((record) => Date.parse(record.lastHeartbeatAt) >= Date.parse(record.connectedAt), {
@@ -1,11 +1,10 @@
1
- import { createHash } from 'node:crypto';
2
- import { compareCodePointOrder } from '@adea-ai/contracts';
1
+ import { compareCodePointOrder, Sha256DigestSchema } from '@adea-ai/contracts';
3
2
  import { IdentifierSchemas } from '@adea-ai/contracts';
4
3
  import { z } from 'zod';
5
4
  import { CapabilityRequirementSetSchema, RuntimeCapabilityNameSchema, evaluateCapabilities, } from './capabilities.js';
6
5
  import { RuntimeNodeHealthStatusSchema } from './health.js';
7
6
  import { RuntimeConnectionLocationSchema, RuntimeConnectionSchema, RuntimeTimestampSchema, } from './models.js';
8
- const DigestSchema = z.string().regex(/^sha256:[a-f0-9]{64}$/);
7
+ import { sha256Digest } from '@adea-ai/contracts/digest';
9
8
  const RuntimeFamilySchema = z
10
9
  .string()
11
10
  .min(1)
@@ -24,7 +23,7 @@ export const RuntimeEligibilityInputSchema = z
24
23
  executionPlan: z
25
24
  .object({
26
25
  executionPlanId: IdentifierSchemas.executionPlanId,
27
- contentDigest: DigestSchema,
26
+ contentDigest: Sha256DigestSchema,
28
27
  runtimeRequirements: CapabilityRequirementSetSchema,
29
28
  })
30
29
  .strict(),
@@ -41,7 +40,7 @@ export const RuntimeEligibilityInputSchema = z
41
40
  .object({
42
41
  policyId: z.string().min(1).max(128),
43
42
  version: z.number().int().positive(),
44
- digest: DigestSchema,
43
+ digest: Sha256DigestSchema,
45
44
  })
46
45
  .strict(),
47
46
  allowedFamilies: z.array(RuntimeFamilySchema).min(1).max(64),
@@ -141,11 +140,11 @@ export const RuntimeEligibilityDecisionSchema = z
141
140
  .object({
142
141
  policyId: z.string().min(1).max(128),
143
142
  version: z.number().int().positive(),
144
- digest: DigestSchema,
143
+ digest: Sha256DigestSchema,
145
144
  })
146
145
  .strict(),
147
146
  evaluatedAt: RuntimeTimestampSchema,
148
- inputDigest: DigestSchema,
147
+ inputDigest: Sha256DigestSchema,
149
148
  })
150
149
  .strict(),
151
150
  })
@@ -293,5 +292,5 @@ function digestEligibilityInput(input) {
293
292
  deniedRuntimeConnectionIds: [...input.policy.deniedRuntimeConnectionIds].toSorted(),
294
293
  },
295
294
  };
296
- return `sha256:${createHash('sha256').update(JSON.stringify(normalized)).digest('hex')}`;
295
+ return sha256Digest(JSON.stringify(normalized));
297
296
  }
package/dist/health.js CHANGED
@@ -1,10 +1,10 @@
1
- import { createHash } from 'node:crypto';
2
1
  import { compareCodePointOrder } from '@adea-ai/contracts';
3
2
  import { IdentifierSchemas } from '@adea-ai/contracts';
4
3
  import { z } from 'zod';
5
4
  import { RuntimeCapabilitySchema } from './capabilities.js';
6
5
  import { RuntimeAvailabilityStateSchema, RuntimeCapabilityVerificationSchema, RuntimeDiagnosticCodeSchema, RuntimeSemanticVersionSchema, RuntimeTimestampSchema, } from './models.js';
7
6
  import { RuntimeConnectionRegistry, RuntimeConnectionRegistryError, } from './registry.js';
7
+ import { sha256Digest } from '@adea-ai/contracts/digest';
8
8
  const uniqueCapabilities = (capabilities) => new Set(capabilities.map((capability) => capability.name)).size === capabilities.length;
9
9
  const RuntimeDisplayLimitationSchema = z
10
10
  .string()
@@ -460,7 +460,7 @@ function sameCapabilities(left, right) {
460
460
  return JSON.stringify(left) === JSON.stringify(right);
461
461
  }
462
462
  function digest(value) {
463
- return `sha256:${createHash('sha256').update(JSON.stringify(value)).digest('hex')}`;
463
+ return sha256Digest(JSON.stringify(value));
464
464
  }
465
465
  function addMilliseconds(timestamp, milliseconds) {
466
466
  return new Date(Date.parse(timestamp) + milliseconds).toISOString();
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export * from './adapter.js';
2
2
  export * from './pi-durable-lead.js';
3
3
  export * from './pi-durable-questions.js';
4
4
  export * from './pi-durable-approvals.js';
5
+ export * from './pi-durable-ids.js';
5
6
  export * from './agent-plugins.js';
6
7
  export * from './channel-ownership.js';
7
8
  export * from './capabilities.js';
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@ export * from './adapter.js';
2
2
  export * from './pi-durable-lead.js';
3
3
  export * from './pi-durable-questions.js';
4
4
  export * from './pi-durable-approvals.js';
5
+ export * from './pi-durable-ids.js';
5
6
  export * from './agent-plugins.js';
6
7
  export * from './channel-ownership.js';
7
8
  export * from './capabilities.js';
package/dist/mock.js CHANGED
@@ -1,6 +1,6 @@
1
- import { createHash } from 'node:crypto';
2
- import { RuntimeAdapterInspectionSchema, RuntimeApprovalRequestSchema, RuntimeCancelRequestSchema, RuntimeExecutionHandleSchema, RuntimeExecutionResultSchema, RuntimeExecutionStatusSchema, RuntimeInputRequestSchema, RuntimeSessionOperationSchema, RuntimeSessionResultSchema, RuntimeStartRequestSchema, RuntimeAdapterError, inspectRuntimeCapabilities, } from './adapter.js';
1
+ import { RuntimeAdapterInspectionSchema, RuntimeApprovalRequestSchema, RuntimeCancelRequestSchema, RuntimeExecutionHandleSchema, RuntimeExecutionResultSchema, RuntimeExecutionStatusSchema, RuntimeInputRequestSchema, RuntimeSessionOperationSchema, RuntimeSessionResultSchema, RuntimeStartRequestSchema, inspectRuntimeCapabilities, isTerminalRuntimeState, failRuntime, } from './adapter.js';
3
2
  import { RuntimeCapabilitySchema } from './capabilities.js';
3
+ import { sha256Hex } from '@adea-ai/contracts/digest';
4
4
  export class MockRuntimeAdapter {
5
5
  #now;
6
6
  #capabilities;
@@ -45,8 +45,8 @@ export class MockRuntimeAdapter {
45
45
  const replay = this.#starts.get(request.idempotencyKey);
46
46
  if (replay) {
47
47
  if (replay.fingerprint !== fingerprint)
48
- fail('IDEMPOTENCY_CONFLICT', 'conflict', false);
49
- return clone(replay.handle);
48
+ failRuntime('IDEMPOTENCY_CONFLICT', 'conflict', false);
49
+ return structuredClone(replay.handle);
50
50
  }
51
51
  const startedAt = this.#now();
52
52
  const handle = RuntimeExecutionHandleSchema.parse({
@@ -55,7 +55,7 @@ export class MockRuntimeAdapter {
55
55
  startedAt,
56
56
  });
57
57
  if (this.#executions.has(handle.handleId))
58
- fail('ATTEMPT_ALREADY_STARTED', 'conflict', false);
58
+ failRuntime('ATTEMPT_ALREADY_STARTED', 'conflict', false);
59
59
  const execution = {
60
60
  handle,
61
61
  status: RuntimeExecutionStatusSchema.parse({
@@ -67,7 +67,7 @@ export class MockRuntimeAdapter {
67
67
  nextSequence: 1,
68
68
  };
69
69
  this.#executions.set(handle.handleId, execution);
70
- this.#starts.set(request.idempotencyKey, { fingerprint, handle: clone(handle) });
70
+ this.#starts.set(request.idempotencyKey, { fingerprint, handle: structuredClone(handle) });
71
71
  this.#emit(execution, 'status', { state: 'starting' });
72
72
  execution.status = RuntimeExecutionStatusSchema.parse({
73
73
  handle,
@@ -75,7 +75,7 @@ export class MockRuntimeAdapter {
75
75
  observedAt: this.#now(),
76
76
  });
77
77
  this.#emit(execution, 'status', { state: 'running' });
78
- return clone(handle);
78
+ return structuredClone(handle);
79
79
  }
80
80
  async *progress(handleInput, options = {}) {
81
81
  const execution = this.#execution(handleInput);
@@ -83,7 +83,7 @@ export class MockRuntimeAdapter {
83
83
  if (options.signal?.aborted)
84
84
  return;
85
85
  if (event.sequence > (options.afterSequence ?? 0))
86
- yield clone(event);
86
+ yield structuredClone(event);
87
87
  }
88
88
  }
89
89
  async submitInput(handle, requestInput) {
@@ -113,12 +113,12 @@ export class MockRuntimeAdapter {
113
113
  const replay = this.#actions.get(actionKey);
114
114
  if (replay) {
115
115
  if (replay.fingerprint !== requestFingerprint)
116
- fail('IDEMPOTENCY_CONFLICT', 'conflict', false);
117
- return clone(replay.status);
116
+ failRuntime('IDEMPOTENCY_CONFLICT', 'conflict', false);
117
+ return structuredClone(replay.status);
118
118
  }
119
119
  const execution = this.#execution(handle);
120
- if (terminal(execution.status.state))
121
- fail('EXECUTION_TERMINAL', 'conflict', false);
120
+ if (isTerminalRuntimeState(execution.status.state))
121
+ failRuntime('EXECUTION_TERMINAL', 'conflict', false);
122
122
  execution.status = RuntimeExecutionStatusSchema.parse({
123
123
  handle: execution.handle,
124
124
  state: 'cancelled',
@@ -127,15 +127,15 @@ export class MockRuntimeAdapter {
127
127
  this.#emit(execution, 'status', { state: 'cancelled' });
128
128
  this.#actions.set(actionKey, {
129
129
  fingerprint: requestFingerprint,
130
- status: clone(execution.status),
130
+ status: structuredClone(execution.status),
131
131
  });
132
- return clone(execution.status);
132
+ return structuredClone(execution.status);
133
133
  }
134
134
  async status(handle) {
135
- return clone(this.#execution(handle).status);
135
+ return structuredClone(this.#execution(handle).status);
136
136
  }
137
137
  async reconcile(handle) {
138
- return clone(this.#execution(handle).status);
138
+ return structuredClone(this.#execution(handle).status);
139
139
  }
140
140
  async session(operationInput) {
141
141
  const operation = RuntimeSessionOperationSchema.parse(operationInput);
@@ -143,7 +143,7 @@ export class MockRuntimeAdapter {
143
143
  if (operation.operation === 'create') {
144
144
  const replay = this.#sessionCreates.get(operation.idempotencyKey);
145
145
  if (replay)
146
- return clone(replay);
146
+ return structuredClone(replay);
147
147
  const session = {
148
148
  sessionId: 'ses_01JABCDEF0123456789ABCDEFG',
149
149
  state: 'active',
@@ -152,7 +152,7 @@ export class MockRuntimeAdapter {
152
152
  this.#sessions.set(session.sessionId, session);
153
153
  const result = RuntimeSessionResultSchema.parse({ operation: 'create', session });
154
154
  this.#sessionCreates.set(operation.idempotencyKey, result);
155
- return clone(result);
155
+ return structuredClone(result);
156
156
  }
157
157
  if (operation.operation === 'list') {
158
158
  return RuntimeSessionResultSchema.parse({
@@ -162,7 +162,7 @@ export class MockRuntimeAdapter {
162
162
  }
163
163
  const session = this.#sessions.get(operation.sessionId);
164
164
  if (!session)
165
- fail('SESSION_NOT_FOUND', 'validation', false);
165
+ failRuntime('SESSION_NOT_FOUND', 'validation', false);
166
166
  if (operation.operation === 'history') {
167
167
  return RuntimeSessionResultSchema.parse({
168
168
  operation: 'history',
@@ -175,7 +175,7 @@ export class MockRuntimeAdapter {
175
175
  if (operation.operation === 'close')
176
176
  session.state = 'closed';
177
177
  else if (session.state === 'closed')
178
- fail('SESSION_CLOSED', 'conflict', false);
178
+ failRuntime('SESSION_CLOSED', 'conflict', false);
179
179
  return RuntimeSessionResultSchema.parse({ operation: operation.operation, session });
180
180
  }
181
181
  async cleanup(handleInput) {
@@ -184,8 +184,8 @@ export class MockRuntimeAdapter {
184
184
  }
185
185
  complete(handleInput, resultInput) {
186
186
  const execution = this.#execution(handleInput);
187
- if (terminal(execution.status.state))
188
- return clone(execution.status);
187
+ if (isTerminalRuntimeState(execution.status.state))
188
+ return structuredClone(execution.status);
189
189
  const result = RuntimeExecutionResultSchema.parse({ outcome: 'completed', ...resultInput });
190
190
  execution.status = RuntimeExecutionStatusSchema.parse({
191
191
  handle: execution.handle,
@@ -194,7 +194,7 @@ export class MockRuntimeAdapter {
194
194
  result,
195
195
  });
196
196
  this.#emit(execution, 'status', { state: 'completed' });
197
- return clone(execution.status);
197
+ return structuredClone(execution.status);
198
198
  }
199
199
  #interaction(handleInput, operation, idempotencyKey, request, data) {
200
200
  const handle = RuntimeExecutionHandleSchema.parse(handleInput);
@@ -203,31 +203,31 @@ export class MockRuntimeAdapter {
203
203
  const replay = this.#actions.get(actionKey);
204
204
  if (replay) {
205
205
  if (replay.fingerprint !== requestFingerprint)
206
- fail('IDEMPOTENCY_CONFLICT', 'conflict', false);
207
- return clone(replay.status);
206
+ failRuntime('IDEMPOTENCY_CONFLICT', 'conflict', false);
207
+ return structuredClone(replay.status);
208
208
  }
209
209
  const execution = this.#execution(handle);
210
- if (terminal(execution.status.state))
211
- fail('EXECUTION_TERMINAL', 'conflict', false);
210
+ if (isTerminalRuntimeState(execution.status.state))
211
+ failRuntime('EXECUTION_TERMINAL', 'conflict', false);
212
212
  this.#emit(execution, 'interaction', data);
213
213
  this.#actions.set(actionKey, {
214
214
  fingerprint: requestFingerprint,
215
- status: clone(execution.status),
215
+ status: structuredClone(execution.status),
216
216
  });
217
- return clone(execution.status);
217
+ return structuredClone(execution.status);
218
218
  }
219
219
  #execution(handleInput) {
220
220
  const handle = RuntimeExecutionHandleSchema.parse(handleInput);
221
221
  const execution = this.#executions.get(handle.handleId);
222
222
  if (!execution || stable(execution.handle) !== stable(handle)) {
223
- fail('EXECUTION_HANDLE_NOT_FOUND', 'validation', false);
223
+ failRuntime('EXECUTION_HANDLE_NOT_FOUND', 'validation', false);
224
224
  }
225
225
  return execution;
226
226
  }
227
227
  #requireCapability(name) {
228
228
  const capability = this.#capabilities.find((candidate) => candidate.name === name);
229
229
  if (!capability || capability.support === 'unsupported') {
230
- fail('CAPABILITY_UNSUPPORTED', 'unsupported', false, { capability: name });
230
+ failRuntime('CAPABILITY_UNSUPPORTED', 'unsupported', false, { capability: name });
231
231
  }
232
232
  }
233
233
  #emit(execution, type, data) {
@@ -240,21 +240,6 @@ export class MockRuntimeAdapter {
240
240
  });
241
241
  }
242
242
  }
243
- function terminal(state) {
244
- return ['completed', 'failed', 'cancelled', 'timed_out'].includes(state);
245
- }
246
- function fail(code, classification, retryable, details) {
247
- throw new RuntimeAdapterError({
248
- code,
249
- classification,
250
- message: code,
251
- retryable,
252
- ...(details ? { details } : {}),
253
- });
254
- }
255
243
  function stable(value) {
256
- return createHash('sha256').update(JSON.stringify(value)).digest('hex');
257
- }
258
- function clone(value) {
259
- return structuredClone(value);
244
+ return sha256Hex(JSON.stringify(value));
260
245
  }
package/dist/models.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { z } from 'zod';
2
- import { compareCodePointOrder } from '@adea-ai/contracts';
2
+ import { compareCodePointOrder, Sha256DigestSchema, TimestampSchema, } from '@adea-ai/contracts';
3
3
  import { ContractVersionSchema, IdentifierSchemas } from '@adea-ai/contracts';
4
4
  import { RuntimeCapabilitySchema, evaluateCapabilities, } from './capabilities.js';
5
- export const RuntimeTimestampSchema = z.iso.datetime();
5
+ export const RuntimeTimestampSchema = TimestampSchema;
6
6
  export const RuntimeSemanticVersionSchema = z
7
7
  .string()
8
8
  .regex(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/);
@@ -82,7 +82,7 @@ export const RuntimeCompatibilityStateSchema = z.enum([
82
82
  'unavailable',
83
83
  'capability_missing',
84
84
  ]);
85
- export const RuntimeConnectionIdentityDigestSchema = z.string().regex(/^sha256:[a-f0-9]{64}$/);
85
+ export const RuntimeConnectionIdentityDigestSchema = Sha256DigestSchema;
86
86
  export const RuntimeOpaqueNativeRefSchema = z
87
87
  .string()
88
88
  .length(31)
@@ -1,6 +1,7 @@
1
1
  import { z } from 'zod';
2
- import { canonicalJsonStringify, IdentifierSchemas } from '@adea-ai/contracts';
3
- export const PiDurableApprovalEffectDigestSchema = z.string().regex(/^sha256:[a-f0-9]{64}$/);
2
+ import { canonicalJsonStringify, IdentifierSchemas, Sha256DigestSchema, TimestampSchema, } from '@adea-ai/contracts';
3
+ import { PiDurableDispatchIdSchema } from './pi-durable-ids.js';
4
+ export const PiDurableApprovalEffectDigestSchema = Sha256DigestSchema;
4
5
  export const PiDurableApprovalDecisionIdSchema = z.string().regex(/^pi-decision:[a-f0-9]{32}$/);
5
6
  const Reference = z
6
7
  .string()
@@ -8,7 +9,7 @@ const Reference = z
8
9
  .max(256)
9
10
  .regex(/^[A-Za-z0-9._:-]+$/);
10
11
  export const PiDurableApprovalAnswerSchema = z.strictObject({
11
- dispatchId: z.string().regex(/^dispatch_[a-f0-9]{32}$/),
12
+ dispatchId: PiDurableDispatchIdSchema,
12
13
  approvalId: IdentifierSchemas.interactionId,
13
14
  effectDigest: PiDurableApprovalEffectDigestSchema,
14
15
  decision: z.enum(['approve', 'deny']),
@@ -30,8 +31,8 @@ export const PiDurableApprovalDecisionSchema = z.strictObject({
30
31
  decision: PiDurableApprovalAnswerSchema.shape.decision,
31
32
  decisionId: PiDurableApprovalDecisionIdSchema,
32
33
  ...PiDurableApprovalAttestationSchema.shape,
33
- decidedAt: z.iso.datetime(),
34
- deadlineAt: z.iso.datetime(),
34
+ decidedAt: TimestampSchema,
35
+ deadlineAt: TimestampSchema,
35
36
  });
36
37
  export function samePiDurableApprovalDecision(left, right) {
37
38
  const { decidedAt: _left, ...a } = left;
@@ -0,0 +1,4 @@
1
+ import { z } from 'zod';
2
+ export declare const PiDurableDispatchIdSchema: z.ZodString;
3
+ export declare function piLeadSessionId(dispatchId: string): string;
4
+ export declare const PiLeadSessionIdSchema: z.ZodString;
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ export const PiDurableDispatchIdSchema = z.string().regex(/^dispatch_[a-f0-9]{32}$/);
3
+ export function piLeadSessionId(dispatchId) {
4
+ return `pi-lead:${dispatchId}`;
5
+ }
6
+ export const PiLeadSessionIdSchema = z.string().regex(/^pi-lead:dispatch_[a-f0-9]{32}$/);
@@ -1,10 +1,10 @@
1
1
  import { z } from 'zod';
2
2
  import { PiDurableQuestionAnswersSchema, PiDurableQuestionRequestIdSchema } from './pi-durable-questions.js';
3
3
  import { PiDurableApprovalAnswerSchema, PiDurableApprovalAttestationSchema } from './pi-durable-approvals.js';
4
- import { IdentifierSchemas, ModelSelectionRefSchema } from '@adea-ai/contracts';
4
+ import { IdentifierSchemas, ModelSelectionRefSchema, Sha256DigestSchema } from '@adea-ai/contracts';
5
5
  import { RuntimeExecutionProgressSchema, RuntimeExecutionStatusSchema, RuntimeExecutionStateSchema, RuntimeObservedGenerationSchema } from './adapter.js';
6
+ import { PiDurableDispatchIdSchema } from './pi-durable-ids.js';
6
7
  declare const IntentId: z.ZodUUID;
7
- declare const DispatchId: z.ZodString;
8
8
  export declare const PiDurableLeadPreparationRefSchema: z.ZodString;
9
9
  declare const Caller: z.ZodObject<{
10
10
  servicePrincipalId: z.ZodString;
@@ -142,7 +142,7 @@ export declare const PiDurableLeadProgressRequestSchema: z.ZodObject<{
142
142
  correlation: typeof Correlation;
143
143
  operation: z.ZodLiteral<"pi-durable.lead.progress">;
144
144
  parameters: z.ZodObject<{
145
- dispatchId: typeof DispatchId;
145
+ dispatchId: typeof PiDurableDispatchIdSchema;
146
146
  afterSequence: z.ZodOptional<z.ZodNumber>;
147
147
  }, z.core.$strict>;
148
148
  }, z.core.$strict>;
@@ -163,7 +163,7 @@ export declare const PiDurableLeadEventsRequestSchema: z.ZodObject<{
163
163
  correlation: typeof Correlation;
164
164
  operation: z.ZodLiteral<"pi-durable.lead.events">;
165
165
  parameters: z.ZodObject<{
166
- dispatchId: typeof DispatchId;
166
+ dispatchId: typeof PiDurableDispatchIdSchema;
167
167
  messageId: z.ZodString;
168
168
  afterSeq: z.ZodNumber;
169
169
  waitMs: z.ZodNumber;
@@ -191,7 +191,7 @@ export declare const PiDurableLeadTurnEventSchema: z.ZodObject<{
191
191
  }, z.core.$strict>;
192
192
  export declare const PiDurableLeadEventsDataSchema: z.ZodObject<{
193
193
  contractVersion: z.ZodLiteral<1>;
194
- dispatchId: typeof DispatchId;
194
+ dispatchId: typeof PiDurableDispatchIdSchema;
195
195
  events: z.ZodArray<typeof PiDurableLeadTurnEventSchema>;
196
196
  nextSeq: z.ZodNumber;
197
197
  complete: z.ZodBoolean;
@@ -215,7 +215,7 @@ export declare const PiDurableLeadChildrenRequestSchema: z.ZodObject<{
215
215
  correlation: typeof Correlation;
216
216
  operation: z.ZodLiteral<"pi-durable.lead.children">;
217
217
  parameters: z.ZodObject<{
218
- dispatchId: typeof DispatchId;
218
+ dispatchId: typeof PiDurableDispatchIdSchema;
219
219
  after: z.ZodOptional<typeof PiDurableLeadChildrenCursorSchema>;
220
220
  limit: z.ZodOptional<z.ZodNumber>;
221
221
  }, z.core.$strict>;
@@ -271,7 +271,7 @@ export declare const PiDurableLeadChildTargetRequestSchema: z.ZodObject<{
271
271
  correlation: typeof Correlation;
272
272
  operation: z.ZodLiteral<"pi-durable.lead.child-target">;
273
273
  parameters: z.ZodObject<{
274
- dispatchId: typeof DispatchId;
274
+ dispatchId: typeof PiDurableDispatchIdSchema;
275
275
  delegationId: typeof IdentifierSchemas.delegationId;
276
276
  }, z.core.$strict>;
277
277
  }, z.core.$strict>;
@@ -310,7 +310,7 @@ export declare const PiDurableLeadQuestionAnswerRequestSchema: z.ZodObject<{
310
310
  correlation: typeof Correlation;
311
311
  operation: z.ZodLiteral<"pi-durable.lead.question-answer">;
312
312
  payload: z.ZodObject<{
313
- dispatchId: typeof DispatchId;
313
+ dispatchId: typeof PiDurableDispatchIdSchema;
314
314
  requestId: typeof PiDurableQuestionRequestIdSchema;
315
315
  answers: typeof PiDurableQuestionAnswersSchema;
316
316
  }, z.core.$strict>;
@@ -348,13 +348,13 @@ export declare const PiDurableLeadChildCancelRequestSchema: z.ZodObject<{
348
348
  correlation: typeof Correlation;
349
349
  operation: z.ZodLiteral<"pi-durable.lead.child-cancel">;
350
350
  payload: z.ZodObject<{
351
- dispatchId: typeof DispatchId;
351
+ dispatchId: typeof PiDurableDispatchIdSchema;
352
352
  delegationId: typeof IdentifierSchemas.delegationId;
353
353
  }, z.core.$strict>;
354
354
  }, z.core.$strict>;
355
355
  export declare const PiDurableLeadReceiptResponseSchema: z.ZodObject<{
356
356
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
357
- dispatchId: typeof DispatchId;
357
+ dispatchId: typeof PiDurableDispatchIdSchema;
358
358
  intentId: typeof IntentId;
359
359
  executionId: typeof IdentifierSchemas.executionId;
360
360
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -362,10 +362,9 @@ export declare const PiDurableLeadReceiptResponseSchema: z.ZodObject<{
362
362
  requestedTarget: z.ZodOptional<typeof PiDurableLeadRequestedTargetSchema>;
363
363
  observedTarget: z.ZodOptional<typeof PiDurableLeadObservedTargetSchema>;
364
364
  }, z.core.$strict>;
365
- declare const PlanDigest: z.ZodString;
366
365
  export declare const PiDurableLeadChildAllowanceSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
367
366
  schemaVersion: z.ZodLiteral<"pi-lead-child-allowance/v1">;
368
- executionPlanDigest: typeof PlanDigest;
367
+ executionPlanDigest: typeof Sha256DigestSchema;
369
368
  profile: z.ZodReadonly<z.ZodObject<{
370
369
  profileId: typeof IdentifierSchemas.profileId;
371
370
  profileVersionId: typeof IdentifierSchemas.profileVersionId;
@@ -378,7 +377,7 @@ export declare const PiDurableLeadChildAllowanceSchema: z.ZodDiscriminatedUnion<
378
377
  maximumTokens: z.ZodNumber;
379
378
  }, z.core.$strict>, z.ZodObject<{
380
379
  schemaVersion: z.ZodLiteral<"pi-lead-child-allowance/v1">;
381
- executionPlanDigest: typeof PlanDigest;
380
+ executionPlanDigest: typeof Sha256DigestSchema;
382
381
  profile: z.ZodReadonly<z.ZodObject<{
383
382
  profileId: typeof IdentifierSchemas.profileId;
384
383
  profileVersionId: typeof IdentifierSchemas.profileVersionId;
@@ -464,7 +463,7 @@ export declare const PiDurableLeadLookupResponseSchema: z.ZodObject<{
464
463
  workspaceId: typeof IdentifierSchemas.workspaceId;
465
464
  intentId: typeof IntentId;
466
465
  receipt: z.ZodNullable<z.ZodObject<{
467
- dispatchId: typeof DispatchId;
466
+ dispatchId: typeof PiDurableDispatchIdSchema;
468
467
  executionId: typeof IdentifierSchemas.executionId;
469
468
  attemptId: typeof IdentifierSchemas.attemptId;
470
469
  state: z.ZodEnum<{
@@ -491,7 +490,7 @@ export declare const PiDurableLeadDispatchResponseSchema: z.ZodObject<{
491
490
  }, z.core.$strict>;
492
491
  data: z.ZodObject<{
493
492
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
494
- dispatchId: typeof DispatchId;
493
+ dispatchId: typeof PiDurableDispatchIdSchema;
495
494
  intentId: typeof IntentId;
496
495
  executionId: typeof IdentifierSchemas.executionId;
497
496
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -515,7 +514,7 @@ export declare const PiDurableLeadStatusResponseSchema: z.ZodObject<{
515
514
  }, z.core.$strict>;
516
515
  data: z.ZodObject<{
517
516
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
518
- dispatchId: typeof DispatchId;
517
+ dispatchId: typeof PiDurableDispatchIdSchema;
519
518
  intentId: typeof IntentId;
520
519
  executionId: typeof IdentifierSchemas.executionId;
521
520
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -539,7 +538,7 @@ export declare const PiDurableLeadProgressResponseSchema: z.ZodObject<{
539
538
  }, z.core.$strict>;
540
539
  data: z.ZodObject<{
541
540
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
542
- dispatchId: typeof DispatchId;
541
+ dispatchId: typeof PiDurableDispatchIdSchema;
543
542
  intentId: typeof IntentId;
544
543
  executionId: typeof IdentifierSchemas.executionId;
545
544
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -563,7 +562,7 @@ export declare const PiDurableLeadCancelResponseSchema: z.ZodObject<{
563
562
  }, z.core.$strict>;
564
563
  data: z.ZodObject<{
565
564
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
566
- dispatchId: typeof DispatchId;
565
+ dispatchId: typeof PiDurableDispatchIdSchema;
567
566
  intentId: typeof IntentId;
568
567
  executionId: typeof IdentifierSchemas.executionId;
569
568
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -587,7 +586,7 @@ export declare const PiDurableLeadQuestionAnswerResponseSchema: z.ZodObject<{
587
586
  }, z.core.$strict>;
588
587
  data: z.ZodObject<{
589
588
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
590
- dispatchId: typeof DispatchId;
589
+ dispatchId: typeof PiDurableDispatchIdSchema;
591
590
  intentId: typeof IntentId;
592
591
  executionId: typeof IdentifierSchemas.executionId;
593
592
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -619,7 +618,7 @@ export declare const PiDurableLeadApprovalAnswerResponseSchema: z.ZodObject<{
619
618
  }, z.core.$strict>;
620
619
  data: z.ZodObject<{
621
620
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
622
- dispatchId: typeof DispatchId;
621
+ dispatchId: typeof PiDurableDispatchIdSchema;
623
622
  intentId: typeof IntentId;
624
623
  executionId: typeof IdentifierSchemas.executionId;
625
624
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -661,7 +660,7 @@ export declare const PiDurableSessionSchema: z.ZodObject<{
661
660
  child: "child";
662
661
  lead: "lead";
663
662
  }>;
664
- dispatchId: typeof DispatchId;
663
+ dispatchId: typeof PiDurableDispatchIdSchema;
665
664
  intentId: typeof IntentId;
666
665
  delegationId: z.ZodOptional<typeof IdentifierSchemas.delegationId>;
667
666
  executionId: typeof IdentifierSchemas.executionId;
@@ -762,7 +761,7 @@ export declare const PiDurableLeadChildrenResponseSchema: z.ZodObject<{
762
761
  }, z.core.$strict>;
763
762
  data: z.ZodObject<{
764
763
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
765
- dispatchId: typeof DispatchId;
764
+ dispatchId: typeof PiDurableDispatchIdSchema;
766
765
  intentId: typeof IntentId;
767
766
  executionId: typeof IdentifierSchemas.executionId;
768
767
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -788,7 +787,7 @@ export declare const PiDurableLeadChildCancelResponseSchema: z.ZodObject<{
788
787
  }, z.core.$strict>;
789
788
  data: z.ZodObject<{
790
789
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
791
- dispatchId: typeof DispatchId;
790
+ dispatchId: typeof PiDurableDispatchIdSchema;
792
791
  intentId: typeof IntentId;
793
792
  executionId: typeof IdentifierSchemas.executionId;
794
793
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -832,7 +831,7 @@ export declare const PiDurableLeadChildTargetResponseSchema: z.ZodObject<{
832
831
  }, z.core.$strict>;
833
832
  data: z.ZodObject<{
834
833
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
835
- dispatchId: typeof DispatchId;
834
+ dispatchId: typeof PiDurableDispatchIdSchema;
836
835
  intentId: typeof IntentId;
837
836
  executionId: typeof IdentifierSchemas.executionId;
838
837
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -1,10 +1,10 @@
1
1
  import { z } from 'zod';
2
2
  import { PiDurableQuestionAnswersSchema, PiDurableQuestionRequestIdSchema, } from './pi-durable-questions.js';
3
3
  import { PiDurableApprovalAnswerSchema, PiDurableApprovalAttestationSchema, PiDurableApprovalDecisionIdSchema, } from './pi-durable-approvals.js';
4
- import { IdentifierSchemas, ModelSelectionFundingViewSchema, ModelSelectionRefSchema, ReadRequestEnvelopeSchema, StateChangingCommandEnvelopeSchema, SuccessResponseEnvelopeSchema, } from '@adea-ai/contracts';
4
+ import { IdentifierSchemas, ModelSelectionFundingViewSchema, ModelSelectionRefSchema, ReadRequestEnvelopeSchema, StateChangingCommandEnvelopeSchema, SuccessResponseEnvelopeSchema, Sha256DigestSchema, TimestampSchema, } from '@adea-ai/contracts';
5
5
  import { RuntimeExecutionHandleSchema, RuntimeExecutionProgressSchema, RuntimeExecutionStatusSchema, RuntimeExecutionStateSchema, RuntimeObservedGenerationSchema, } from './adapter.js';
6
+ import { PiDurableDispatchIdSchema, piLeadSessionId } from './pi-durable-ids.js';
6
7
  const IntentId = z.uuid();
7
- const DispatchId = z.string().regex(/^dispatch_[a-f0-9]{32}$/);
8
8
  export const PiDurableLeadPreparationRefSchema = z.string().regex(/^prep_[a-f0-9]{32}$/);
9
9
  const Caller = StateChangingCommandEnvelopeSchema.shape.caller.unwrap().strict();
10
10
  const Correlation = StateChangingCommandEnvelopeSchema.shape.correlation.strict();
@@ -61,7 +61,7 @@ export const PiDurableLeadDispatchRequestSchema = PiDurableLeadCommandEnvelopeSc
61
61
  });
62
62
  export const PiDurableLeadStatusRequestSchema = PiDurableLeadReadEnvelopeSchema.extend({
63
63
  operation: z.literal('pi-durable.lead.status'),
64
- parameters: z.object({ dispatchId: DispatchId }).strict(),
64
+ parameters: z.object({ dispatchId: PiDurableDispatchIdSchema }).strict(),
65
65
  });
66
66
  export const PiDurableLeadLookupRequestSchema = PiDurableLeadReadEnvelopeSchema.extend({
67
67
  operation: z.literal('pi-durable.lead.lookup'),
@@ -71,7 +71,7 @@ export const PiDurableLeadProgressRequestSchema = PiDurableLeadReadEnvelopeSchem
71
71
  operation: z.literal('pi-durable.lead.progress'),
72
72
  parameters: z
73
73
  .object({
74
- dispatchId: DispatchId,
74
+ dispatchId: PiDurableDispatchIdSchema,
75
75
  afterSequence: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional(),
76
76
  })
77
77
  .strict(),
@@ -87,7 +87,7 @@ export const PiDurableLeadEventsRequestSchema = PiDurableLeadReadEnvelopeSchema.
87
87
  operation: z.literal('pi-durable.lead.events'),
88
88
  parameters: z
89
89
  .object({
90
- dispatchId: DispatchId,
90
+ dispatchId: PiDurableDispatchIdSchema,
91
91
  messageId: z
92
92
  .string()
93
93
  .min(1)
@@ -107,8 +107,8 @@ export const PiDurableLeadTurnEventSchema = z
107
107
  harnessRunId: z.string().min(1).max(256),
108
108
  generation: z.literal(1),
109
109
  seq: z.string().regex(/^[1-9]\d*$/),
110
- occurredAt: z.iso.datetime(),
111
- receivedAt: z.iso.datetime(),
110
+ occurredAt: TimestampSchema,
111
+ receivedAt: TimestampSchema,
112
112
  source: z.literal('native'),
113
113
  sourceEventId: z.string().min(1).max(256),
114
114
  confidence: z.literal('authoritative'),
@@ -120,7 +120,7 @@ export const PiDurableLeadTurnEventSchema = z
120
120
  export const PiDurableLeadEventsDataSchema = z
121
121
  .object({
122
122
  contractVersion: z.literal(PI_DURABLE_LEAD_EVENTS_CONTRACT_VERSION),
123
- dispatchId: DispatchId,
123
+ dispatchId: PiDurableDispatchIdSchema,
124
124
  events: z
125
125
  .array(PiDurableLeadTurnEventSchema)
126
126
  .max(PI_DURABLE_LEAD_EVENTS_MAX_PAGE),
@@ -132,7 +132,7 @@ export const PiDurableLeadEventsDataSchema = z
132
132
  const first = value.nextSeq - value.events.length + 1;
133
133
  value.events.forEach((event, index) => {
134
134
  if (event.seq !== String(first + index) ||
135
- event.runtimeSessionId !== `pi-lead:${value.dispatchId}`)
135
+ event.runtimeSessionId !== piLeadSessionId(value.dispatchId))
136
136
  context.addIssue({
137
137
  code: 'custom',
138
138
  path: ['events', index],
@@ -143,7 +143,7 @@ export const PiDurableLeadEventsDataSchema = z
143
143
  context.addIssue({ code: 'custom', path: ['nextSeq'], message: 'nextSeq precedes the page' });
144
144
  });
145
145
  export const PiDurableLeadChildrenCursorSchema = z
146
- .object({ acceptedAt: z.iso.datetime(), delegationId: IdentifierSchemas.delegationId })
146
+ .object({ acceptedAt: TimestampSchema, delegationId: IdentifierSchemas.delegationId })
147
147
  .strict()
148
148
  .readonly();
149
149
  export const PI_DURABLE_LEAD_CHILDREN_MAX_PAGE = 256;
@@ -151,7 +151,7 @@ export const PiDurableLeadChildrenRequestSchema = PiDurableLeadReadEnvelopeSchem
151
151
  operation: z.literal('pi-durable.lead.children'),
152
152
  parameters: z
153
153
  .object({
154
- dispatchId: DispatchId,
154
+ dispatchId: PiDurableDispatchIdSchema,
155
155
  after: PiDurableLeadChildrenCursorSchema.optional(),
156
156
  limit: z.number().int().min(1).max(PI_DURABLE_LEAD_CHILDREN_MAX_PAGE).optional(),
157
157
  })
@@ -183,20 +183,20 @@ export const PiDurableLeadChildTargetRequestSchema = PiDurableLeadReadEnvelopeSc
183
183
  operation: z.literal('pi-durable.lead.child-target'),
184
184
  parameters: z
185
185
  .object({
186
- dispatchId: DispatchId,
186
+ dispatchId: PiDurableDispatchIdSchema,
187
187
  delegationId: IdentifierSchemas.delegationId,
188
188
  })
189
189
  .strict(),
190
190
  });
191
191
  export const PiDurableLeadCancelRequestSchema = PiDurableLeadCommandEnvelopeSchema.extend({
192
192
  operation: z.literal('pi-durable.lead.cancel'),
193
- payload: z.object({ dispatchId: DispatchId }).strict(),
193
+ payload: z.object({ dispatchId: PiDurableDispatchIdSchema }).strict(),
194
194
  });
195
195
  export const PiDurableLeadQuestionAnswerRequestSchema = PiDurableLeadCommandEnvelopeSchema.extend({
196
196
  operation: z.literal('pi-durable.lead.question-answer'),
197
197
  payload: z
198
198
  .object({
199
- dispatchId: DispatchId,
199
+ dispatchId: PiDurableDispatchIdSchema,
200
200
  requestId: PiDurableQuestionRequestIdSchema,
201
201
  answers: PiDurableQuestionAnswersSchema,
202
202
  })
@@ -210,7 +210,7 @@ export const PiDurableLeadChildCancelRequestSchema = PiDurableLeadCommandEnvelop
210
210
  operation: z.literal('pi-durable.lead.child-cancel'),
211
211
  payload: z
212
212
  .object({
213
- dispatchId: DispatchId,
213
+ dispatchId: PiDurableDispatchIdSchema,
214
214
  delegationId: IdentifierSchemas.delegationId,
215
215
  })
216
216
  .strict(),
@@ -218,7 +218,7 @@ export const PiDurableLeadChildCancelRequestSchema = PiDurableLeadCommandEnvelop
218
218
  export const PiDurableLeadReceiptResponseSchema = z
219
219
  .object({
220
220
  schemaVersion: z.literal('pi-lead-dispatch/v1'),
221
- dispatchId: DispatchId,
221
+ dispatchId: PiDurableDispatchIdSchema,
222
222
  intentId: IntentId,
223
223
  executionId: IdentifierSchemas.executionId,
224
224
  attemptId: IdentifierSchemas.attemptId,
@@ -231,10 +231,9 @@ export const PiDurableLeadReceiptResponseSchema = z
231
231
  fenceForeignGeneration(receipt, context);
232
232
  });
233
233
  const response = SuccessResponseEnvelopeSchema.extend({ correlation: Correlation }).strict();
234
- const PlanDigest = z.string().regex(/^sha256:[a-f0-9]{64}$/);
235
234
  const ChildAllowanceBinding = {
236
235
  schemaVersion: z.literal('pi-lead-child-allowance/v1'),
237
- executionPlanDigest: PlanDigest,
236
+ executionPlanDigest: Sha256DigestSchema,
238
237
  profile: z
239
238
  .strictObject({
240
239
  profileId: IdentifierSchemas.profileId,
@@ -265,7 +264,7 @@ export const PiDurableLeadPreparationSchema = z
265
264
  selectionRevision: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
266
265
  funding: ModelSelectionFundingViewSchema.options[0],
267
266
  childAllowance: PiDurableLeadChildAllowanceSchema.optional(),
268
- expiresAt: z.iso.datetime(),
267
+ expiresAt: TimestampSchema,
269
268
  replayed: z.boolean(),
270
269
  })
271
270
  .strict()
@@ -296,7 +295,7 @@ export const PiDurableLeadLookupResponseSchema = response.extend({
296
295
  intentId: IntentId,
297
296
  receipt: z
298
297
  .object({
299
- dispatchId: DispatchId,
298
+ dispatchId: PiDurableDispatchIdSchema,
300
299
  executionId: IdentifierSchemas.executionId,
301
300
  attemptId: IdentifierSchemas.attemptId,
302
301
  state: z.enum(['dispatching', 'dispatched', 'reconciliation_required']),
@@ -362,18 +361,18 @@ export const PiDurableSessionSchema = z
362
361
  .object({
363
362
  runtimeSessionId: PiDurableSessionIdSchema,
364
363
  role: z.enum(['lead', 'child']),
365
- dispatchId: DispatchId,
364
+ dispatchId: PiDurableDispatchIdSchema,
366
365
  intentId: IntentId,
367
366
  delegationId: IdentifierSchemas.delegationId.optional(),
368
367
  executionId: IdentifierSchemas.executionId,
369
368
  attemptId: IdentifierSchemas.attemptId,
370
369
  state: RuntimeExecutionStateSchema,
371
- startedAt: z.iso.datetime(),
372
- updatedAt: z.iso.datetime(),
370
+ startedAt: TimestampSchema,
371
+ updatedAt: TimestampSchema,
373
372
  })
374
373
  .strict()
375
374
  .superRefine((value, context) => {
376
- const lead = value.runtimeSessionId === `pi-lead:${value.dispatchId}`;
375
+ const lead = value.runtimeSessionId === piLeadSessionId(value.dispatchId);
377
376
  if ((value.role === 'lead') !== lead ||
378
377
  (value.role === 'lead') !== (value.delegationId === undefined))
379
378
  context.addIssue({
@@ -471,8 +470,8 @@ export const PiDurableLeadChildSchema = z
471
470
  ]),
472
471
  awaitingInput: z.boolean(),
473
472
  stopRequested: z.boolean(),
474
- acceptedAt: z.iso.datetime(),
475
- updatedAt: z.iso.datetime(),
473
+ acceptedAt: TimestampSchema,
474
+ updatedAt: TimestampSchema,
476
475
  revision: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
477
476
  outcome: PiDurableLeadChildOutcomeSchema.optional(),
478
477
  })
@@ -512,7 +511,7 @@ export const PiDurableLeadChildTargetSchema = z.strictObject({
512
511
  nativeSessionId: IdentifierSchemas.externalSessionId,
513
512
  nativeTaskId: IdentifierSchemas.taskId,
514
513
  nativeState: RuntimeExecutionStateSchema,
515
- observedAt: z.iso.datetime(),
514
+ observedAt: TimestampSchema,
516
515
  observedGeneration: RuntimeObservedGenerationSchema.optional(),
517
516
  });
518
517
  export const PiDurableLeadRemoteSessionReferenceSchema = z
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { TimestampSchema } from '@adea-ai/contracts';
2
3
  export const PI_QUESTION_TIMEOUT_DEFAULT_SECONDS = 60 * 60;
3
4
  export const PI_QUESTION_TIMEOUT_MIN_SECONDS = 60;
4
5
  export const PI_QUESTION_TIMEOUT_MAX_SECONDS = 24 * 60 * 60;
@@ -63,15 +64,15 @@ export const PiDurableQuestionRequestSchema = z.strictObject({
63
64
  requestId: PiDurableQuestionRequestIdSchema,
64
65
  callId: z.string().min(1).max(256),
65
66
  questions: PiDurableQuestionsSchema,
66
- expiresAt: z.iso.datetime(),
67
+ expiresAt: TimestampSchema,
67
68
  });
68
69
  export const PiDurableQuestionOutcomeSchema = z.discriminatedUnion('decision', [
69
70
  z.strictObject({
70
71
  decision: z.literal('answered'),
71
72
  answers: PiDurableQuestionAnswersSchema,
72
- decidedAt: z.iso.datetime(),
73
+ decidedAt: TimestampSchema,
73
74
  }),
74
- z.strictObject({ decision: z.literal('expired'), decidedAt: z.iso.datetime() }),
75
+ z.strictObject({ decision: z.literal('expired'), decidedAt: TimestampSchema }),
75
76
  ]);
76
77
  export function questionAnswersProblem(questions, input) {
77
78
  const parsed = PiDurableQuestionAnswersSchema.safeParse(input);
package/dist/registry.js CHANGED
@@ -101,11 +101,11 @@ export class RuntimeConnectionRegistry {
101
101
  async get(runtimeConnectionId) {
102
102
  const parsedId = IdentifierSchemas.runtimeConnectionId.parse(runtimeConnectionId);
103
103
  const connection = await this.repository.get(parsedId);
104
- return connection ? clone(connection) : undefined;
104
+ return connection ? structuredClone(connection) : undefined;
105
105
  }
106
106
  async listByRuntimeNode(runtimeNodeRefId) {
107
107
  const parsedId = IdentifierSchemas.runtimeNodeRefId.parse(runtimeNodeRefId);
108
- return (await this.repository.listByRuntimeNode(parsedId)).map(clone);
108
+ return (await this.repository.listByRuntimeNode(parsedId)).map((value) => structuredClone(value));
109
109
  }
110
110
  async update(input) {
111
111
  const update = RuntimeConnectionUpdateSchema.parse(input);
@@ -215,7 +215,7 @@ export class InMemoryRuntimeConnectionRepository {
215
215
  this.#identities.has(connection.identityDigest)) {
216
216
  return false;
217
217
  }
218
- this.#connections.set(connection.runtimeConnectionId, clone(connection));
218
+ this.#connections.set(connection.runtimeConnectionId, structuredClone(connection));
219
219
  this.#identities.set(connection.identityDigest, connection.runtimeConnectionId);
220
220
  return true;
221
221
  }
@@ -233,14 +233,14 @@ export class InMemoryRuntimeConnectionRepository {
233
233
  return false;
234
234
  if (!runtimeConnectionsShareStableIdentity(current, connection))
235
235
  return false;
236
- this.#connections.set(connection.runtimeConnectionId, clone(connection));
236
+ this.#connections.set(connection.runtimeConnectionId, structuredClone(connection));
237
237
  return true;
238
238
  }
239
239
  async listByRuntimeNode(runtimeNodeRefId) {
240
240
  return [...this.#connections.values()]
241
241
  .filter((connection) => connection.runtimeNodeRefId === runtimeNodeRefId)
242
242
  .toSorted((left, right) => compareCodePointOrder(left.runtimeConnectionId, right.runtimeConnectionId))
243
- .map(clone);
243
+ .map((value) => structuredClone(value));
244
244
  }
245
245
  async scanByRuntimeNode(input) {
246
246
  const { runtimeNodeRefId, afterConnectionId, limit } = RuntimeConnectionScanSchema.parse(input);
@@ -303,9 +303,6 @@ function latest(...timestamps) {
303
303
  function fail(code) {
304
304
  throw new RuntimeConnectionRegistryError(code);
305
305
  }
306
- function clone(value) {
307
- return structuredClone(value);
308
- }
309
306
  function cloneOptional(value) {
310
- return value === undefined ? undefined : clone(value);
307
+ return value === undefined ? undefined : structuredClone(value);
311
308
  }
package/dist/routing.js CHANGED
@@ -1,10 +1,9 @@
1
- import { createHash } from 'node:crypto';
2
- import { compareCodePointOrder } from '@adea-ai/contracts';
1
+ import { compareCodePointOrder, Sha256DigestSchema } from '@adea-ai/contracts';
3
2
  import { IdentifierSchemas } from '@adea-ai/contracts';
4
3
  import { z } from 'zod';
5
4
  import { RuntimeEligibilityDecisionSchema, RuntimeEligibilityReasonCodeSchema, } from './eligibility.js';
6
5
  import { RuntimeTimestampSchema } from './models.js';
7
- const DigestSchema = z.string().regex(/^sha256:[a-f0-9]{64}$/);
6
+ import { sha256Digest } from '@adea-ai/contracts/digest';
8
7
  const RuntimeFamilySchema = z
9
8
  .string()
10
9
  .min(1)
@@ -15,7 +14,7 @@ export const RuntimeRoutingPolicySchema = z
15
14
  .object({
16
15
  policyId: z.string().min(1).max(128),
17
16
  version: z.number().int().positive(),
18
- digest: DigestSchema,
17
+ digest: Sha256DigestSchema,
19
18
  weights: z
20
19
  .object({
21
20
  explicitConnection: WeightSchema,
@@ -124,12 +123,12 @@ export const RuntimeRoutingDecisionSchema = z
124
123
  .object({
125
124
  policyId: z.string().min(1).max(128),
126
125
  version: z.number().int().positive(),
127
- digest: DigestSchema,
126
+ digest: Sha256DigestSchema,
128
127
  })
129
128
  .strict(),
130
129
  evaluatedAt: RuntimeTimestampSchema,
131
- inputDigest: DigestSchema,
132
- decisionDigest: DigestSchema,
130
+ inputDigest: Sha256DigestSchema,
131
+ decisionDigest: Sha256DigestSchema,
133
132
  })
134
133
  .strict(),
135
134
  })
@@ -310,5 +309,5 @@ function compareCoded(left, right) {
310
309
  return compareCodePointOrder(`${left.code}:${left.capability ?? ''}`, `${right.code}:${right.capability ?? ''}`);
311
310
  }
312
311
  function digest(value) {
313
- return `sha256:${createHash('sha256').update(JSON.stringify(value)).digest('hex')}`;
312
+ return sha256Digest(JSON.stringify(value));
314
313
  }
package/dist/sessions.js CHANGED
@@ -124,7 +124,7 @@ export class InMemoryExternalSessionRepository {
124
124
  candidate.opaqueNativeSessionId === session.opaqueNativeSessionId)) {
125
125
  return false;
126
126
  }
127
- this.#sessions.set(session.externalSessionId, clone(session));
127
+ this.#sessions.set(session.externalSessionId, structuredClone(session));
128
128
  return true;
129
129
  }
130
130
  async get(externalSessionId) {
@@ -141,12 +141,12 @@ export class InMemoryExternalSessionRepository {
141
141
  (scope.runtimeConnectionId === undefined ||
142
142
  session.runtimeConnectionId === scope.runtimeConnectionId))
143
143
  .toSorted((left, right) => compareCodePointOrder(left.externalSessionId, right.externalSessionId))
144
- .map(clone);
144
+ .map((value) => structuredClone(value));
145
145
  }
146
146
  async compareAndSet(expectedVersion, session) {
147
147
  if (this.#sessions.get(session.externalSessionId)?.version !== expectedVersion)
148
148
  return false;
149
- this.#sessions.set(session.externalSessionId, clone(session));
149
+ this.#sessions.set(session.externalSessionId, structuredClone(session));
150
150
  return true;
151
151
  }
152
152
  }
@@ -400,9 +400,6 @@ function sameRegistration(session, input) {
400
400
  function fail(code, currentVersion) {
401
401
  throw new ExternalSessionRegistryError(code, currentVersion);
402
402
  }
403
- function clone(value) {
404
- return structuredClone(value);
405
- }
406
403
  function cloneOptional(value) {
407
- return value === undefined ? undefined : clone(value);
404
+ return value === undefined ? undefined : structuredClone(value);
408
405
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adea-ai/runtime-sdk",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "description": "SDK for building Control Plane runtimes: adapters, capabilities, conformance, discovery, eligibility, health, sessions, transport, and routing.",
5
5
  "keywords": [
6
6
  "adapter",
@@ -42,7 +42,7 @@
42
42
  "test": "bun test src"
43
43
  },
44
44
  "dependencies": {
45
- "@adea-ai/contracts": "^5.0.0",
45
+ "@adea-ai/contracts": "^5.0.2",
46
46
  "zod": "4.6.6"
47
47
  },
48
48
  "engines": {