@adea-ai/runtime-sdk 2.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;
@@ -57,17 +57,6 @@ export declare const PiDurableLeadObservedTargetSchema: z.ZodReadonly<z.ZodObjec
57
57
  generation: z.ZodOptional<typeof RuntimeObservedGenerationSchema>;
58
58
  }, z.core.$strict>>;
59
59
  export type PiDurableLeadObservedTarget = z.output<typeof PiDurableLeadObservedTargetSchema>;
60
- export declare const PI_DURABLE_OBSERVED_GENERATION_CONTRACT_VERSION: {
61
- readonly major: 3;
62
- readonly minor: 1;
63
- };
64
- export declare function supportsPiDurableObservedGeneration(consumerVersion: unknown): boolean;
65
- export declare const PI_DURABLE_REMOTE_SESSION_REFERENCE_CONTRACT_VERSION: {
66
- readonly major: 3;
67
- readonly minor: 2;
68
- };
69
- export declare function supportsPiDurableRemoteSessionReference(consumerVersion: unknown): boolean;
70
- export declare function supportsPiDurableRemoteOwnerObservation(consumerVersion: unknown): boolean;
71
60
  export declare const PiDurableLeadPrepareRequestSchema: z.ZodObject<{
72
61
  contractVersion: z.ZodObject<{
73
62
  major: z.ZodNumber;
@@ -153,7 +142,7 @@ export declare const PiDurableLeadProgressRequestSchema: z.ZodObject<{
153
142
  correlation: typeof Correlation;
154
143
  operation: z.ZodLiteral<"pi-durable.lead.progress">;
155
144
  parameters: z.ZodObject<{
156
- dispatchId: typeof DispatchId;
145
+ dispatchId: typeof PiDurableDispatchIdSchema;
157
146
  afterSequence: z.ZodOptional<z.ZodNumber>;
158
147
  }, z.core.$strict>;
159
148
  }, z.core.$strict>;
@@ -174,7 +163,7 @@ export declare const PiDurableLeadEventsRequestSchema: z.ZodObject<{
174
163
  correlation: typeof Correlation;
175
164
  operation: z.ZodLiteral<"pi-durable.lead.events">;
176
165
  parameters: z.ZodObject<{
177
- dispatchId: typeof DispatchId;
166
+ dispatchId: typeof PiDurableDispatchIdSchema;
178
167
  messageId: z.ZodString;
179
168
  afterSeq: z.ZodNumber;
180
169
  waitMs: z.ZodNumber;
@@ -202,7 +191,7 @@ export declare const PiDurableLeadTurnEventSchema: z.ZodObject<{
202
191
  }, z.core.$strict>;
203
192
  export declare const PiDurableLeadEventsDataSchema: z.ZodObject<{
204
193
  contractVersion: z.ZodLiteral<1>;
205
- dispatchId: typeof DispatchId;
194
+ dispatchId: typeof PiDurableDispatchIdSchema;
206
195
  events: z.ZodArray<typeof PiDurableLeadTurnEventSchema>;
207
196
  nextSeq: z.ZodNumber;
208
197
  complete: z.ZodBoolean;
@@ -226,7 +215,7 @@ export declare const PiDurableLeadChildrenRequestSchema: z.ZodObject<{
226
215
  correlation: typeof Correlation;
227
216
  operation: z.ZodLiteral<"pi-durable.lead.children">;
228
217
  parameters: z.ZodObject<{
229
- dispatchId: typeof DispatchId;
218
+ dispatchId: typeof PiDurableDispatchIdSchema;
230
219
  after: z.ZodOptional<typeof PiDurableLeadChildrenCursorSchema>;
231
220
  limit: z.ZodOptional<z.ZodNumber>;
232
221
  }, z.core.$strict>;
@@ -282,7 +271,7 @@ export declare const PiDurableLeadChildTargetRequestSchema: z.ZodObject<{
282
271
  correlation: typeof Correlation;
283
272
  operation: z.ZodLiteral<"pi-durable.lead.child-target">;
284
273
  parameters: z.ZodObject<{
285
- dispatchId: typeof DispatchId;
274
+ dispatchId: typeof PiDurableDispatchIdSchema;
286
275
  delegationId: typeof IdentifierSchemas.delegationId;
287
276
  }, z.core.$strict>;
288
277
  }, z.core.$strict>;
@@ -321,7 +310,7 @@ export declare const PiDurableLeadQuestionAnswerRequestSchema: z.ZodObject<{
321
310
  correlation: typeof Correlation;
322
311
  operation: z.ZodLiteral<"pi-durable.lead.question-answer">;
323
312
  payload: z.ZodObject<{
324
- dispatchId: typeof DispatchId;
313
+ dispatchId: typeof PiDurableDispatchIdSchema;
325
314
  requestId: typeof PiDurableQuestionRequestIdSchema;
326
315
  answers: typeof PiDurableQuestionAnswersSchema;
327
316
  }, z.core.$strict>;
@@ -359,13 +348,13 @@ export declare const PiDurableLeadChildCancelRequestSchema: z.ZodObject<{
359
348
  correlation: typeof Correlation;
360
349
  operation: z.ZodLiteral<"pi-durable.lead.child-cancel">;
361
350
  payload: z.ZodObject<{
362
- dispatchId: typeof DispatchId;
351
+ dispatchId: typeof PiDurableDispatchIdSchema;
363
352
  delegationId: typeof IdentifierSchemas.delegationId;
364
353
  }, z.core.$strict>;
365
354
  }, z.core.$strict>;
366
355
  export declare const PiDurableLeadReceiptResponseSchema: z.ZodObject<{
367
356
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
368
- dispatchId: typeof DispatchId;
357
+ dispatchId: typeof PiDurableDispatchIdSchema;
369
358
  intentId: typeof IntentId;
370
359
  executionId: typeof IdentifierSchemas.executionId;
371
360
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -373,10 +362,9 @@ export declare const PiDurableLeadReceiptResponseSchema: z.ZodObject<{
373
362
  requestedTarget: z.ZodOptional<typeof PiDurableLeadRequestedTargetSchema>;
374
363
  observedTarget: z.ZodOptional<typeof PiDurableLeadObservedTargetSchema>;
375
364
  }, z.core.$strict>;
376
- declare const PlanDigest: z.ZodString;
377
365
  export declare const PiDurableLeadChildAllowanceSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
378
366
  schemaVersion: z.ZodLiteral<"pi-lead-child-allowance/v1">;
379
- executionPlanDigest: typeof PlanDigest;
367
+ executionPlanDigest: typeof Sha256DigestSchema;
380
368
  profile: z.ZodReadonly<z.ZodObject<{
381
369
  profileId: typeof IdentifierSchemas.profileId;
382
370
  profileVersionId: typeof IdentifierSchemas.profileVersionId;
@@ -389,7 +377,7 @@ export declare const PiDurableLeadChildAllowanceSchema: z.ZodDiscriminatedUnion<
389
377
  maximumTokens: z.ZodNumber;
390
378
  }, z.core.$strict>, z.ZodObject<{
391
379
  schemaVersion: z.ZodLiteral<"pi-lead-child-allowance/v1">;
392
- executionPlanDigest: typeof PlanDigest;
380
+ executionPlanDigest: typeof Sha256DigestSchema;
393
381
  profile: z.ZodReadonly<z.ZodObject<{
394
382
  profileId: typeof IdentifierSchemas.profileId;
395
383
  profileVersionId: typeof IdentifierSchemas.profileVersionId;
@@ -475,7 +463,7 @@ export declare const PiDurableLeadLookupResponseSchema: z.ZodObject<{
475
463
  workspaceId: typeof IdentifierSchemas.workspaceId;
476
464
  intentId: typeof IntentId;
477
465
  receipt: z.ZodNullable<z.ZodObject<{
478
- dispatchId: typeof DispatchId;
466
+ dispatchId: typeof PiDurableDispatchIdSchema;
479
467
  executionId: typeof IdentifierSchemas.executionId;
480
468
  attemptId: typeof IdentifierSchemas.attemptId;
481
469
  state: z.ZodEnum<{
@@ -502,7 +490,7 @@ export declare const PiDurableLeadDispatchResponseSchema: z.ZodObject<{
502
490
  }, z.core.$strict>;
503
491
  data: z.ZodObject<{
504
492
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
505
- dispatchId: typeof DispatchId;
493
+ dispatchId: typeof PiDurableDispatchIdSchema;
506
494
  intentId: typeof IntentId;
507
495
  executionId: typeof IdentifierSchemas.executionId;
508
496
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -526,7 +514,7 @@ export declare const PiDurableLeadStatusResponseSchema: z.ZodObject<{
526
514
  }, z.core.$strict>;
527
515
  data: z.ZodObject<{
528
516
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
529
- dispatchId: typeof DispatchId;
517
+ dispatchId: typeof PiDurableDispatchIdSchema;
530
518
  intentId: typeof IntentId;
531
519
  executionId: typeof IdentifierSchemas.executionId;
532
520
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -550,7 +538,7 @@ export declare const PiDurableLeadProgressResponseSchema: z.ZodObject<{
550
538
  }, z.core.$strict>;
551
539
  data: z.ZodObject<{
552
540
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
553
- dispatchId: typeof DispatchId;
541
+ dispatchId: typeof PiDurableDispatchIdSchema;
554
542
  intentId: typeof IntentId;
555
543
  executionId: typeof IdentifierSchemas.executionId;
556
544
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -574,7 +562,7 @@ export declare const PiDurableLeadCancelResponseSchema: z.ZodObject<{
574
562
  }, z.core.$strict>;
575
563
  data: z.ZodObject<{
576
564
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
577
- dispatchId: typeof DispatchId;
565
+ dispatchId: typeof PiDurableDispatchIdSchema;
578
566
  intentId: typeof IntentId;
579
567
  executionId: typeof IdentifierSchemas.executionId;
580
568
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -598,7 +586,7 @@ export declare const PiDurableLeadQuestionAnswerResponseSchema: z.ZodObject<{
598
586
  }, z.core.$strict>;
599
587
  data: z.ZodObject<{
600
588
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
601
- dispatchId: typeof DispatchId;
589
+ dispatchId: typeof PiDurableDispatchIdSchema;
602
590
  intentId: typeof IntentId;
603
591
  executionId: typeof IdentifierSchemas.executionId;
604
592
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -630,7 +618,7 @@ export declare const PiDurableLeadApprovalAnswerResponseSchema: z.ZodObject<{
630
618
  }, z.core.$strict>;
631
619
  data: z.ZodObject<{
632
620
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
633
- dispatchId: typeof DispatchId;
621
+ dispatchId: typeof PiDurableDispatchIdSchema;
634
622
  intentId: typeof IntentId;
635
623
  executionId: typeof IdentifierSchemas.executionId;
636
624
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -672,7 +660,7 @@ export declare const PiDurableSessionSchema: z.ZodObject<{
672
660
  child: "child";
673
661
  lead: "lead";
674
662
  }>;
675
- dispatchId: typeof DispatchId;
663
+ dispatchId: typeof PiDurableDispatchIdSchema;
676
664
  intentId: typeof IntentId;
677
665
  delegationId: z.ZodOptional<typeof IdentifierSchemas.delegationId>;
678
666
  executionId: typeof IdentifierSchemas.executionId;
@@ -773,7 +761,7 @@ export declare const PiDurableLeadChildrenResponseSchema: z.ZodObject<{
773
761
  }, z.core.$strict>;
774
762
  data: z.ZodObject<{
775
763
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
776
- dispatchId: typeof DispatchId;
764
+ dispatchId: typeof PiDurableDispatchIdSchema;
777
765
  intentId: typeof IntentId;
778
766
  executionId: typeof IdentifierSchemas.executionId;
779
767
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -799,7 +787,7 @@ export declare const PiDurableLeadChildCancelResponseSchema: z.ZodObject<{
799
787
  }, z.core.$strict>;
800
788
  data: z.ZodObject<{
801
789
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
802
- dispatchId: typeof DispatchId;
790
+ dispatchId: typeof PiDurableDispatchIdSchema;
803
791
  intentId: typeof IntentId;
804
792
  executionId: typeof IdentifierSchemas.executionId;
805
793
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -843,7 +831,7 @@ export declare const PiDurableLeadChildTargetResponseSchema: z.ZodObject<{
843
831
  }, z.core.$strict>;
844
832
  data: z.ZodObject<{
845
833
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
846
- dispatchId: typeof DispatchId;
834
+ dispatchId: typeof PiDurableDispatchIdSchema;
847
835
  intentId: typeof IntentId;
848
836
  executionId: typeof IdentifierSchemas.executionId;
849
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 { ContractVersionSchema, IdentifierSchemas, ModelSelectionFundingViewSchema, ModelSelectionRefSchema, PublicContractManifest, ReadRequestEnvelopeSchema, StateChangingCommandEnvelopeSchema, SuccessResponseEnvelopeSchema, negotiateContractVersion, } 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();
@@ -30,35 +30,6 @@ export const PiDurableLeadObservedTargetSchema = z
30
30
  generation: RuntimeObservedGenerationSchema.optional(),
31
31
  })
32
32
  .readonly();
33
- function contractIncludes(negotiated, introduced) {
34
- return (negotiated.major > introduced.major ||
35
- (negotiated.major === introduced.major && negotiated.minor >= introduced.minor));
36
- }
37
- export const PI_DURABLE_OBSERVED_GENERATION_CONTRACT_VERSION = { major: 3, minor: 1 };
38
- export function supportsPiDurableObservedGeneration(consumerVersion) {
39
- const consumer = ContractVersionSchema.safeParse(consumerVersion);
40
- if (!consumer.success)
41
- return false;
42
- const negotiated = negotiateContractVersion(PublicContractManifest.supported, [consumer.data]);
43
- return (negotiated !== undefined &&
44
- contractIncludes(negotiated, PI_DURABLE_OBSERVED_GENERATION_CONTRACT_VERSION));
45
- }
46
- export const PI_DURABLE_REMOTE_SESSION_REFERENCE_CONTRACT_VERSION = { major: 3, minor: 2 };
47
- export function supportsPiDurableRemoteSessionReference(consumerVersion) {
48
- const consumer = ContractVersionSchema.safeParse(consumerVersion);
49
- if (!consumer.success)
50
- return false;
51
- const negotiated = negotiateContractVersion(PublicContractManifest.supported, [consumer.data]);
52
- return (negotiated !== undefined &&
53
- contractIncludes(negotiated, PI_DURABLE_REMOTE_SESSION_REFERENCE_CONTRACT_VERSION));
54
- }
55
- export function supportsPiDurableRemoteOwnerObservation(consumerVersion) {
56
- const consumer = ContractVersionSchema.safeParse(consumerVersion);
57
- if (!consumer.success)
58
- return false;
59
- const negotiated = negotiateContractVersion(PublicContractManifest.supported, [consumer.data]);
60
- return negotiated !== undefined && contractIncludes(negotiated, { major: 3, minor: 3 });
61
- }
62
33
  function fenceForeignGeneration(receipt, context) {
63
34
  const foreign = (generation) => generation !== undefined && generation.attemptId !== receipt.attemptId;
64
35
  if (foreign(receipt.observedTarget?.generation))
@@ -90,7 +61,7 @@ export const PiDurableLeadDispatchRequestSchema = PiDurableLeadCommandEnvelopeSc
90
61
  });
91
62
  export const PiDurableLeadStatusRequestSchema = PiDurableLeadReadEnvelopeSchema.extend({
92
63
  operation: z.literal('pi-durable.lead.status'),
93
- parameters: z.object({ dispatchId: DispatchId }).strict(),
64
+ parameters: z.object({ dispatchId: PiDurableDispatchIdSchema }).strict(),
94
65
  });
95
66
  export const PiDurableLeadLookupRequestSchema = PiDurableLeadReadEnvelopeSchema.extend({
96
67
  operation: z.literal('pi-durable.lead.lookup'),
@@ -100,7 +71,7 @@ export const PiDurableLeadProgressRequestSchema = PiDurableLeadReadEnvelopeSchem
100
71
  operation: z.literal('pi-durable.lead.progress'),
101
72
  parameters: z
102
73
  .object({
103
- dispatchId: DispatchId,
74
+ dispatchId: PiDurableDispatchIdSchema,
104
75
  afterSequence: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional(),
105
76
  })
106
77
  .strict(),
@@ -116,7 +87,7 @@ export const PiDurableLeadEventsRequestSchema = PiDurableLeadReadEnvelopeSchema.
116
87
  operation: z.literal('pi-durable.lead.events'),
117
88
  parameters: z
118
89
  .object({
119
- dispatchId: DispatchId,
90
+ dispatchId: PiDurableDispatchIdSchema,
120
91
  messageId: z
121
92
  .string()
122
93
  .min(1)
@@ -136,8 +107,8 @@ export const PiDurableLeadTurnEventSchema = z
136
107
  harnessRunId: z.string().min(1).max(256),
137
108
  generation: z.literal(1),
138
109
  seq: z.string().regex(/^[1-9]\d*$/),
139
- occurredAt: z.iso.datetime(),
140
- receivedAt: z.iso.datetime(),
110
+ occurredAt: TimestampSchema,
111
+ receivedAt: TimestampSchema,
141
112
  source: z.literal('native'),
142
113
  sourceEventId: z.string().min(1).max(256),
143
114
  confidence: z.literal('authoritative'),
@@ -149,7 +120,7 @@ export const PiDurableLeadTurnEventSchema = z
149
120
  export const PiDurableLeadEventsDataSchema = z
150
121
  .object({
151
122
  contractVersion: z.literal(PI_DURABLE_LEAD_EVENTS_CONTRACT_VERSION),
152
- dispatchId: DispatchId,
123
+ dispatchId: PiDurableDispatchIdSchema,
153
124
  events: z
154
125
  .array(PiDurableLeadTurnEventSchema)
155
126
  .max(PI_DURABLE_LEAD_EVENTS_MAX_PAGE),
@@ -161,7 +132,7 @@ export const PiDurableLeadEventsDataSchema = z
161
132
  const first = value.nextSeq - value.events.length + 1;
162
133
  value.events.forEach((event, index) => {
163
134
  if (event.seq !== String(first + index) ||
164
- event.runtimeSessionId !== `pi-lead:${value.dispatchId}`)
135
+ event.runtimeSessionId !== piLeadSessionId(value.dispatchId))
165
136
  context.addIssue({
166
137
  code: 'custom',
167
138
  path: ['events', index],
@@ -172,7 +143,7 @@ export const PiDurableLeadEventsDataSchema = z
172
143
  context.addIssue({ code: 'custom', path: ['nextSeq'], message: 'nextSeq precedes the page' });
173
144
  });
174
145
  export const PiDurableLeadChildrenCursorSchema = z
175
- .object({ acceptedAt: z.iso.datetime(), delegationId: IdentifierSchemas.delegationId })
146
+ .object({ acceptedAt: TimestampSchema, delegationId: IdentifierSchemas.delegationId })
176
147
  .strict()
177
148
  .readonly();
178
149
  export const PI_DURABLE_LEAD_CHILDREN_MAX_PAGE = 256;
@@ -180,7 +151,7 @@ export const PiDurableLeadChildrenRequestSchema = PiDurableLeadReadEnvelopeSchem
180
151
  operation: z.literal('pi-durable.lead.children'),
181
152
  parameters: z
182
153
  .object({
183
- dispatchId: DispatchId,
154
+ dispatchId: PiDurableDispatchIdSchema,
184
155
  after: PiDurableLeadChildrenCursorSchema.optional(),
185
156
  limit: z.number().int().min(1).max(PI_DURABLE_LEAD_CHILDREN_MAX_PAGE).optional(),
186
157
  })
@@ -212,20 +183,20 @@ export const PiDurableLeadChildTargetRequestSchema = PiDurableLeadReadEnvelopeSc
212
183
  operation: z.literal('pi-durable.lead.child-target'),
213
184
  parameters: z
214
185
  .object({
215
- dispatchId: DispatchId,
186
+ dispatchId: PiDurableDispatchIdSchema,
216
187
  delegationId: IdentifierSchemas.delegationId,
217
188
  })
218
189
  .strict(),
219
190
  });
220
191
  export const PiDurableLeadCancelRequestSchema = PiDurableLeadCommandEnvelopeSchema.extend({
221
192
  operation: z.literal('pi-durable.lead.cancel'),
222
- payload: z.object({ dispatchId: DispatchId }).strict(),
193
+ payload: z.object({ dispatchId: PiDurableDispatchIdSchema }).strict(),
223
194
  });
224
195
  export const PiDurableLeadQuestionAnswerRequestSchema = PiDurableLeadCommandEnvelopeSchema.extend({
225
196
  operation: z.literal('pi-durable.lead.question-answer'),
226
197
  payload: z
227
198
  .object({
228
- dispatchId: DispatchId,
199
+ dispatchId: PiDurableDispatchIdSchema,
229
200
  requestId: PiDurableQuestionRequestIdSchema,
230
201
  answers: PiDurableQuestionAnswersSchema,
231
202
  })
@@ -239,7 +210,7 @@ export const PiDurableLeadChildCancelRequestSchema = PiDurableLeadCommandEnvelop
239
210
  operation: z.literal('pi-durable.lead.child-cancel'),
240
211
  payload: z
241
212
  .object({
242
- dispatchId: DispatchId,
213
+ dispatchId: PiDurableDispatchIdSchema,
243
214
  delegationId: IdentifierSchemas.delegationId,
244
215
  })
245
216
  .strict(),
@@ -247,7 +218,7 @@ export const PiDurableLeadChildCancelRequestSchema = PiDurableLeadCommandEnvelop
247
218
  export const PiDurableLeadReceiptResponseSchema = z
248
219
  .object({
249
220
  schemaVersion: z.literal('pi-lead-dispatch/v1'),
250
- dispatchId: DispatchId,
221
+ dispatchId: PiDurableDispatchIdSchema,
251
222
  intentId: IntentId,
252
223
  executionId: IdentifierSchemas.executionId,
253
224
  attemptId: IdentifierSchemas.attemptId,
@@ -260,10 +231,9 @@ export const PiDurableLeadReceiptResponseSchema = z
260
231
  fenceForeignGeneration(receipt, context);
261
232
  });
262
233
  const response = SuccessResponseEnvelopeSchema.extend({ correlation: Correlation }).strict();
263
- const PlanDigest = z.string().regex(/^sha256:[a-f0-9]{64}$/);
264
234
  const ChildAllowanceBinding = {
265
235
  schemaVersion: z.literal('pi-lead-child-allowance/v1'),
266
- executionPlanDigest: PlanDigest,
236
+ executionPlanDigest: Sha256DigestSchema,
267
237
  profile: z
268
238
  .strictObject({
269
239
  profileId: IdentifierSchemas.profileId,
@@ -294,7 +264,7 @@ export const PiDurableLeadPreparationSchema = z
294
264
  selectionRevision: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
295
265
  funding: ModelSelectionFundingViewSchema.options[0],
296
266
  childAllowance: PiDurableLeadChildAllowanceSchema.optional(),
297
- expiresAt: z.iso.datetime(),
267
+ expiresAt: TimestampSchema,
298
268
  replayed: z.boolean(),
299
269
  })
300
270
  .strict()
@@ -325,7 +295,7 @@ export const PiDurableLeadLookupResponseSchema = response.extend({
325
295
  intentId: IntentId,
326
296
  receipt: z
327
297
  .object({
328
- dispatchId: DispatchId,
298
+ dispatchId: PiDurableDispatchIdSchema,
329
299
  executionId: IdentifierSchemas.executionId,
330
300
  attemptId: IdentifierSchemas.attemptId,
331
301
  state: z.enum(['dispatching', 'dispatched', 'reconciliation_required']),
@@ -391,18 +361,18 @@ export const PiDurableSessionSchema = z
391
361
  .object({
392
362
  runtimeSessionId: PiDurableSessionIdSchema,
393
363
  role: z.enum(['lead', 'child']),
394
- dispatchId: DispatchId,
364
+ dispatchId: PiDurableDispatchIdSchema,
395
365
  intentId: IntentId,
396
366
  delegationId: IdentifierSchemas.delegationId.optional(),
397
367
  executionId: IdentifierSchemas.executionId,
398
368
  attemptId: IdentifierSchemas.attemptId,
399
369
  state: RuntimeExecutionStateSchema,
400
- startedAt: z.iso.datetime(),
401
- updatedAt: z.iso.datetime(),
370
+ startedAt: TimestampSchema,
371
+ updatedAt: TimestampSchema,
402
372
  })
403
373
  .strict()
404
374
  .superRefine((value, context) => {
405
- const lead = value.runtimeSessionId === `pi-lead:${value.dispatchId}`;
375
+ const lead = value.runtimeSessionId === piLeadSessionId(value.dispatchId);
406
376
  if ((value.role === 'lead') !== lead ||
407
377
  (value.role === 'lead') !== (value.delegationId === undefined))
408
378
  context.addIssue({
@@ -500,8 +470,8 @@ export const PiDurableLeadChildSchema = z
500
470
  ]),
501
471
  awaitingInput: z.boolean(),
502
472
  stopRequested: z.boolean(),
503
- acceptedAt: z.iso.datetime(),
504
- updatedAt: z.iso.datetime(),
473
+ acceptedAt: TimestampSchema,
474
+ updatedAt: TimestampSchema,
505
475
  revision: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
506
476
  outcome: PiDurableLeadChildOutcomeSchema.optional(),
507
477
  })
@@ -541,7 +511,7 @@ export const PiDurableLeadChildTargetSchema = z.strictObject({
541
511
  nativeSessionId: IdentifierSchemas.externalSessionId,
542
512
  nativeTaskId: IdentifierSchemas.taskId,
543
513
  nativeState: RuntimeExecutionStateSchema,
544
- observedAt: z.iso.datetime(),
514
+ observedAt: TimestampSchema,
545
515
  observedGeneration: RuntimeObservedGenerationSchema.optional(),
546
516
  });
547
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": "2.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",
@@ -31,19 +31,18 @@
31
31
  }
32
32
  },
33
33
  "publishConfig": {
34
- "access": "public",
35
- "provenance": true
34
+ "access": "public"
36
35
  },
37
36
  "scripts": {
38
37
  "build": "tsc -p tsconfig.json",
39
- "typecheck": "bun check -p tsconfig.json && bun check -p tsconfig.scripts.json",
38
+ "typecheck": "bun check -p tsconfig.json && bun check -p tsconfig.test.json && bun check -p tsconfig.scripts.json",
40
39
  "compatibility:check": "bun scripts/compatibility.ts --check",
41
40
  "compatibility:generate": "bun scripts/compatibility.ts",
42
41
  "lint": "oxlint src",
43
42
  "test": "bun test src"
44
43
  },
45
44
  "dependencies": {
46
- "@adea-ai/contracts": "^4.0.0",
45
+ "@adea-ai/contracts": "^5.0.2",
47
46
  "zod": "4.6.6"
48
47
  },
49
48
  "engines": {