@adea-ai/runtime-sdk 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/adapter.d.ts CHANGED
@@ -511,6 +511,7 @@ export declare const RuntimeStartRequestSchema: z.ZodObject<{
511
511
  maximumMicrounits: z.ZodNumber;
512
512
  maximumTokens: z.ZodNumber;
513
513
  }, z.core.$strict>>>;
514
+ traceId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"trace ID">, string>>>;
514
515
  }, z.core.$strict>;
515
516
  export declare const RuntimeInputRequestSchema: z.ZodObject<{
516
517
  interactionId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"interaction ID">, string>>;
@@ -622,8 +623,9 @@ export declare const RuntimeAdapterContract: Readonly<{
622
623
  }>;
623
624
  lifecycle: readonly string[];
624
625
  idempotentOperations: readonly string[];
625
- terminalStates: readonly string[];
626
+ terminalStates: readonly ["completed", "failed", "cancelled", "timed_out"];
626
627
  }>;
628
+ export declare function isTerminalRuntimeState(state: string): boolean;
627
629
  export interface RuntimeProgressOptions {
628
630
  readonly afterSequence?: number;
629
631
  readonly signal?: AbortSignal;
@@ -648,4 +650,5 @@ export declare class RuntimeAdapterError extends Error {
648
650
  constructor(errorInput: RuntimeError);
649
651
  toJSON(): RuntimeError;
650
652
  }
653
+ export declare function failRuntime(code: string, classification: RuntimeError['classification'], retryable?: boolean, details?: Record<string, string>): never;
651
654
  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),
@@ -274,6 +272,7 @@ export const RuntimeStartRequestSchema = z
274
272
  idempotencyKey: IdempotencyKeySchema,
275
273
  executionPlan: RuntimeExecutionPlanSnapshotSchema,
276
274
  attemptBudget: RuntimeAttemptBudgetAuthoritySchema.optional(),
275
+ traceId: IdentifierSchemas.traceId.optional(),
277
276
  })
278
277
  .strict()
279
278
  .superRefine((request, context) => {
@@ -387,6 +386,9 @@ export const RuntimeAdapterContract = Object.freeze({
387
386
  ]),
388
387
  terminalStates: Object.freeze(['completed', 'failed', 'cancelled', 'timed_out']),
389
388
  });
389
+ export function isTerminalRuntimeState(state) {
390
+ return RuntimeAdapterContract.terminalStates.includes(state);
391
+ }
390
392
  export class RuntimeAdapterError extends Error {
391
393
  code;
392
394
  classification;
@@ -412,6 +414,15 @@ export class RuntimeAdapterError extends Error {
412
414
  });
413
415
  }
414
416
  }
417
+ export function failRuntime(code, classification, retryable = false, details) {
418
+ throw new RuntimeAdapterError({
419
+ code,
420
+ classification,
421
+ message: code,
422
+ retryable,
423
+ ...(details ? { details } : {}),
424
+ });
425
+ }
415
426
  export function inspectRuntimeCapabilities(capabilities, requirements) {
416
427
  return evaluateCapabilities(capabilities, CapabilityRequirementSetSchema.parse(requirements));
417
428
  }
@@ -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>;
@@ -253,6 +253,7 @@ export declare const PiDurableSessionEventsRequestSchema: z.ZodObject<{
253
253
  operation: z.ZodLiteral<"pi-durable.lead.session-events">;
254
254
  parameters: z.ZodObject<{
255
255
  runtimeSessionId: typeof PiDurableSessionIdSchema;
256
+ messageId: z.ZodOptional<z.ZodString>;
256
257
  afterSeq: z.ZodNumber;
257
258
  waitMs: z.ZodNumber;
258
259
  limit: z.ZodOptional<z.ZodNumber>;
@@ -271,7 +272,7 @@ export declare const PiDurableLeadChildTargetRequestSchema: z.ZodObject<{
271
272
  correlation: typeof Correlation;
272
273
  operation: z.ZodLiteral<"pi-durable.lead.child-target">;
273
274
  parameters: z.ZodObject<{
274
- dispatchId: typeof DispatchId;
275
+ dispatchId: typeof PiDurableDispatchIdSchema;
275
276
  delegationId: typeof IdentifierSchemas.delegationId;
276
277
  }, z.core.$strict>;
277
278
  }, z.core.$strict>;
@@ -310,7 +311,7 @@ export declare const PiDurableLeadQuestionAnswerRequestSchema: z.ZodObject<{
310
311
  correlation: typeof Correlation;
311
312
  operation: z.ZodLiteral<"pi-durable.lead.question-answer">;
312
313
  payload: z.ZodObject<{
313
- dispatchId: typeof DispatchId;
314
+ dispatchId: typeof PiDurableDispatchIdSchema;
314
315
  requestId: typeof PiDurableQuestionRequestIdSchema;
315
316
  answers: typeof PiDurableQuestionAnswersSchema;
316
317
  }, z.core.$strict>;
@@ -332,6 +333,30 @@ export declare const PiDurableLeadApprovalAnswerRequestSchema: z.ZodObject<{
332
333
  operation: z.ZodLiteral<"pi-durable.lead.approval-answer">;
333
334
  payload: z.ZodObject<typeof PiDurableApprovalAnswerSchema.shape & typeof PiDurableApprovalAttestationSchema.shape, z.core.$strict>;
334
335
  }, z.core.$strict>;
336
+ export declare const PiDurableChildMessageRequestIdSchema: z.ZodString;
337
+ export declare const PI_DURABLE_CHILD_MESSAGE_MAX_CHARS = 8192;
338
+ export declare const PiDurableLeadChildMessageRequestSchema: z.ZodObject<{
339
+ contractVersion: z.ZodObject<{
340
+ major: z.ZodNumber;
341
+ minor: z.ZodNumber;
342
+ }, z.core.$strict>;
343
+ requestId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"request ID">, string>>;
344
+ workspaceId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"workspace ID">, string>>;
345
+ projectId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"project ID">, string>>>;
346
+ commandId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"command ID">, string>>;
347
+ idempotencyKey: z.ZodString;
348
+ payloadHash: z.ZodString;
349
+ issuedAt: z.ZodISODateTime;
350
+ caller: typeof Caller;
351
+ correlation: typeof Correlation;
352
+ operation: z.ZodLiteral<"pi-durable.lead.child-message">;
353
+ payload: z.ZodObject<{
354
+ dispatchId: typeof PiDurableDispatchIdSchema;
355
+ delegationId: typeof IdentifierSchemas.delegationId;
356
+ requestId: typeof PiDurableChildMessageRequestIdSchema;
357
+ text: z.ZodString;
358
+ }, z.core.$strict>;
359
+ }, z.core.$strict>;
335
360
  export declare const PiDurableLeadChildCancelRequestSchema: z.ZodObject<{
336
361
  contractVersion: z.ZodObject<{
337
362
  major: z.ZodNumber;
@@ -348,13 +373,13 @@ export declare const PiDurableLeadChildCancelRequestSchema: z.ZodObject<{
348
373
  correlation: typeof Correlation;
349
374
  operation: z.ZodLiteral<"pi-durable.lead.child-cancel">;
350
375
  payload: z.ZodObject<{
351
- dispatchId: typeof DispatchId;
376
+ dispatchId: typeof PiDurableDispatchIdSchema;
352
377
  delegationId: typeof IdentifierSchemas.delegationId;
353
378
  }, z.core.$strict>;
354
379
  }, z.core.$strict>;
355
380
  export declare const PiDurableLeadReceiptResponseSchema: z.ZodObject<{
356
381
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
357
- dispatchId: typeof DispatchId;
382
+ dispatchId: typeof PiDurableDispatchIdSchema;
358
383
  intentId: typeof IntentId;
359
384
  executionId: typeof IdentifierSchemas.executionId;
360
385
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -362,10 +387,9 @@ export declare const PiDurableLeadReceiptResponseSchema: z.ZodObject<{
362
387
  requestedTarget: z.ZodOptional<typeof PiDurableLeadRequestedTargetSchema>;
363
388
  observedTarget: z.ZodOptional<typeof PiDurableLeadObservedTargetSchema>;
364
389
  }, z.core.$strict>;
365
- declare const PlanDigest: z.ZodString;
366
390
  export declare const PiDurableLeadChildAllowanceSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
367
391
  schemaVersion: z.ZodLiteral<"pi-lead-child-allowance/v1">;
368
- executionPlanDigest: typeof PlanDigest;
392
+ executionPlanDigest: typeof Sha256DigestSchema;
369
393
  profile: z.ZodReadonly<z.ZodObject<{
370
394
  profileId: typeof IdentifierSchemas.profileId;
371
395
  profileVersionId: typeof IdentifierSchemas.profileVersionId;
@@ -378,7 +402,7 @@ export declare const PiDurableLeadChildAllowanceSchema: z.ZodDiscriminatedUnion<
378
402
  maximumTokens: z.ZodNumber;
379
403
  }, z.core.$strict>, z.ZodObject<{
380
404
  schemaVersion: z.ZodLiteral<"pi-lead-child-allowance/v1">;
381
- executionPlanDigest: typeof PlanDigest;
405
+ executionPlanDigest: typeof Sha256DigestSchema;
382
406
  profile: z.ZodReadonly<z.ZodObject<{
383
407
  profileId: typeof IdentifierSchemas.profileId;
384
408
  profileVersionId: typeof IdentifierSchemas.profileVersionId;
@@ -464,7 +488,7 @@ export declare const PiDurableLeadLookupResponseSchema: z.ZodObject<{
464
488
  workspaceId: typeof IdentifierSchemas.workspaceId;
465
489
  intentId: typeof IntentId;
466
490
  receipt: z.ZodNullable<z.ZodObject<{
467
- dispatchId: typeof DispatchId;
491
+ dispatchId: typeof PiDurableDispatchIdSchema;
468
492
  executionId: typeof IdentifierSchemas.executionId;
469
493
  attemptId: typeof IdentifierSchemas.attemptId;
470
494
  state: z.ZodEnum<{
@@ -491,7 +515,7 @@ export declare const PiDurableLeadDispatchResponseSchema: z.ZodObject<{
491
515
  }, z.core.$strict>;
492
516
  data: z.ZodObject<{
493
517
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
494
- dispatchId: typeof DispatchId;
518
+ dispatchId: typeof PiDurableDispatchIdSchema;
495
519
  intentId: typeof IntentId;
496
520
  executionId: typeof IdentifierSchemas.executionId;
497
521
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -515,7 +539,7 @@ export declare const PiDurableLeadStatusResponseSchema: z.ZodObject<{
515
539
  }, z.core.$strict>;
516
540
  data: z.ZodObject<{
517
541
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
518
- dispatchId: typeof DispatchId;
542
+ dispatchId: typeof PiDurableDispatchIdSchema;
519
543
  intentId: typeof IntentId;
520
544
  executionId: typeof IdentifierSchemas.executionId;
521
545
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -539,7 +563,7 @@ export declare const PiDurableLeadProgressResponseSchema: z.ZodObject<{
539
563
  }, z.core.$strict>;
540
564
  data: z.ZodObject<{
541
565
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
542
- dispatchId: typeof DispatchId;
566
+ dispatchId: typeof PiDurableDispatchIdSchema;
543
567
  intentId: typeof IntentId;
544
568
  executionId: typeof IdentifierSchemas.executionId;
545
569
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -563,7 +587,7 @@ export declare const PiDurableLeadCancelResponseSchema: z.ZodObject<{
563
587
  }, z.core.$strict>;
564
588
  data: z.ZodObject<{
565
589
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
566
- dispatchId: typeof DispatchId;
590
+ dispatchId: typeof PiDurableDispatchIdSchema;
567
591
  intentId: typeof IntentId;
568
592
  executionId: typeof IdentifierSchemas.executionId;
569
593
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -587,7 +611,7 @@ export declare const PiDurableLeadQuestionAnswerResponseSchema: z.ZodObject<{
587
611
  }, z.core.$strict>;
588
612
  data: z.ZodObject<{
589
613
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
590
- dispatchId: typeof DispatchId;
614
+ dispatchId: typeof PiDurableDispatchIdSchema;
591
615
  intentId: typeof IntentId;
592
616
  executionId: typeof IdentifierSchemas.executionId;
593
617
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -619,7 +643,7 @@ export declare const PiDurableLeadApprovalAnswerResponseSchema: z.ZodObject<{
619
643
  }, z.core.$strict>;
620
644
  data: z.ZodObject<{
621
645
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
622
- dispatchId: typeof DispatchId;
646
+ dispatchId: typeof PiDurableDispatchIdSchema;
623
647
  intentId: typeof IntentId;
624
648
  executionId: typeof IdentifierSchemas.executionId;
625
649
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -661,7 +685,7 @@ export declare const PiDurableSessionSchema: z.ZodObject<{
661
685
  child: "child";
662
686
  lead: "lead";
663
687
  }>;
664
- dispatchId: typeof DispatchId;
688
+ dispatchId: typeof PiDurableDispatchIdSchema;
665
689
  intentId: typeof IntentId;
666
690
  delegationId: z.ZodOptional<typeof IdentifierSchemas.delegationId>;
667
691
  executionId: typeof IdentifierSchemas.executionId;
@@ -762,7 +786,7 @@ export declare const PiDurableLeadChildrenResponseSchema: z.ZodObject<{
762
786
  }, z.core.$strict>;
763
787
  data: z.ZodObject<{
764
788
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
765
- dispatchId: typeof DispatchId;
789
+ dispatchId: typeof PiDurableDispatchIdSchema;
766
790
  intentId: typeof IntentId;
767
791
  executionId: typeof IdentifierSchemas.executionId;
768
792
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -788,7 +812,7 @@ export declare const PiDurableLeadChildCancelResponseSchema: z.ZodObject<{
788
812
  }, z.core.$strict>;
789
813
  data: z.ZodObject<{
790
814
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
791
- dispatchId: typeof DispatchId;
815
+ dispatchId: typeof PiDurableDispatchIdSchema;
792
816
  intentId: typeof IntentId;
793
817
  executionId: typeof IdentifierSchemas.executionId;
794
818
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -799,6 +823,34 @@ export declare const PiDurableLeadChildCancelResponseSchema: z.ZodObject<{
799
823
  attributed: z.ZodBoolean;
800
824
  }, z.core.$strict>;
801
825
  }, z.core.$strict>;
826
+ export declare const PiDurableLeadChildMessageResponseSchema: z.ZodObject<{
827
+ contractVersion: z.ZodObject<{
828
+ major: z.ZodNumber;
829
+ minor: z.ZodNumber;
830
+ }, z.core.$strict>;
831
+ requestId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"request ID">, string>>;
832
+ correlation: z.ZodObject<{
833
+ traceId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"trace ID">, string>>;
834
+ causationCommandId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"command ID">, string>>>;
835
+ parentEventId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"event ID">, string>>>;
836
+ }, z.core.$strict>;
837
+ data: z.ZodObject<{
838
+ schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
839
+ dispatchId: typeof PiDurableDispatchIdSchema;
840
+ intentId: typeof IntentId;
841
+ executionId: typeof IdentifierSchemas.executionId;
842
+ attemptId: typeof IdentifierSchemas.attemptId;
843
+ runtimeSessionId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"external-session ID">, string>>;
844
+ requestedTarget: z.ZodOptional<typeof PiDurableLeadRequestedTargetSchema>;
845
+ observedTarget: z.ZodOptional<typeof PiDurableLeadObservedTargetSchema>;
846
+ child: typeof PiDurableLeadChildSchema;
847
+ requestId: typeof PiDurableChildMessageRequestIdSchema;
848
+ outcome: z.ZodEnum<{
849
+ already_delivered: "already_delivered";
850
+ delivered: "delivered";
851
+ }>;
852
+ }, z.core.$strict>;
853
+ }, z.core.$strict>;
802
854
  export declare const PiDurableLeadChildTargetSchema: z.ZodObject<{
803
855
  source: z.ZodLiteral<"control_plane_reported">;
804
856
  runtimeConnectionId: typeof IdentifierSchemas.runtimeConnectionId;
@@ -832,7 +884,7 @@ export declare const PiDurableLeadChildTargetResponseSchema: z.ZodObject<{
832
884
  }, z.core.$strict>;
833
885
  data: z.ZodObject<{
834
886
  schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
835
- dispatchId: typeof DispatchId;
887
+ dispatchId: typeof PiDurableDispatchIdSchema;
836
888
  intentId: typeof IntentId;
837
889
  executionId: typeof IdentifierSchemas.executionId;
838
890
  attemptId: typeof IdentifierSchemas.attemptId;
@@ -985,6 +1037,13 @@ export declare const PiDurableLeadHttpContract: Readonly<{
985
1037
  requestSchema: typeof PiDurableLeadChildCancelRequestSchema;
986
1038
  responseSchema: typeof PiDurableLeadChildCancelResponseSchema;
987
1039
  }>;
1040
+ childMessage: Readonly<{
1041
+ route: "child-message";
1042
+ operation: "pi-durable.lead.child-message";
1043
+ scope: "execution:write";
1044
+ requestSchema: typeof PiDurableLeadChildMessageRequestSchema;
1045
+ responseSchema: typeof PiDurableLeadChildMessageResponseSchema;
1046
+ }>;
988
1047
  }>;
989
1048
  export type PiDurableLeadPrepareRequest = z.output<typeof PiDurableLeadPrepareRequestSchema>;
990
1049
  export type PiDurableLeadPrepareResponse = z.output<typeof PiDurableLeadPrepareResponseSchema>;
@@ -1017,6 +1076,8 @@ export type PiDurableLeadApprovalAnswerRequest = z.output<typeof PiDurableLeadAp
1017
1076
  export type PiDurableLeadApprovalAnswerResponse = z.output<typeof PiDurableLeadApprovalAnswerResponseSchema>;
1018
1077
  export type PiDurableLeadChildCancelRequest = z.output<typeof PiDurableLeadChildCancelRequestSchema>;
1019
1078
  export type PiDurableLeadChildCancelResponse = z.output<typeof PiDurableLeadChildCancelResponseSchema>;
1079
+ export type PiDurableLeadChildMessageRequest = z.output<typeof PiDurableLeadChildMessageRequestSchema>;
1080
+ export type PiDurableLeadChildMessageResponse = z.output<typeof PiDurableLeadChildMessageResponseSchema>;
1020
1081
  export type PiDurableLeadChildTargetRequest = z.output<typeof PiDurableLeadChildTargetRequestSchema>;
1021
1082
  export type PiDurableLeadChildTargetResponse = z.output<typeof PiDurableLeadChildTargetResponseSchema>;
1022
1083
  export type PiDurableLeadChildTarget = z.output<typeof PiDurableLeadChildTargetSchema>;
@@ -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
  })
@@ -173,6 +173,12 @@ export const PiDurableSessionEventsRequestSchema = PiDurableLeadReadEnvelopeSche
173
173
  parameters: z
174
174
  .object({
175
175
  runtimeSessionId: PiDurableSessionIdSchema,
176
+ messageId: z
177
+ .string()
178
+ .min(1)
179
+ .max(128)
180
+ .regex(/^[A-Za-z0-9._:-]+$/)
181
+ .optional(),
176
182
  afterSeq: LeadEventSeq,
177
183
  waitMs: z.number().int().min(0).max(PI_DURABLE_LEAD_EVENTS_MAX_WAIT_MS),
178
184
  limit: z.number().int().min(1).max(PI_DURABLE_LEAD_EVENTS_MAX_PAGE).optional(),
@@ -183,20 +189,20 @@ export const PiDurableLeadChildTargetRequestSchema = PiDurableLeadReadEnvelopeSc
183
189
  operation: z.literal('pi-durable.lead.child-target'),
184
190
  parameters: z
185
191
  .object({
186
- dispatchId: DispatchId,
192
+ dispatchId: PiDurableDispatchIdSchema,
187
193
  delegationId: IdentifierSchemas.delegationId,
188
194
  })
189
195
  .strict(),
190
196
  });
191
197
  export const PiDurableLeadCancelRequestSchema = PiDurableLeadCommandEnvelopeSchema.extend({
192
198
  operation: z.literal('pi-durable.lead.cancel'),
193
- payload: z.object({ dispatchId: DispatchId }).strict(),
199
+ payload: z.object({ dispatchId: PiDurableDispatchIdSchema }).strict(),
194
200
  });
195
201
  export const PiDurableLeadQuestionAnswerRequestSchema = PiDurableLeadCommandEnvelopeSchema.extend({
196
202
  operation: z.literal('pi-durable.lead.question-answer'),
197
203
  payload: z
198
204
  .object({
199
- dispatchId: DispatchId,
205
+ dispatchId: PiDurableDispatchIdSchema,
200
206
  requestId: PiDurableQuestionRequestIdSchema,
201
207
  answers: PiDurableQuestionAnswersSchema,
202
208
  })
@@ -206,11 +212,26 @@ export const PiDurableLeadApprovalAnswerRequestSchema = PiDurableLeadCommandEnve
206
212
  operation: z.literal('pi-durable.lead.approval-answer'),
207
213
  payload: PiDurableApprovalAnswerSchema.extend(PiDurableApprovalAttestationSchema.shape),
208
214
  });
215
+ export const PiDurableChildMessageRequestIdSchema = z
216
+ .string()
217
+ .regex(/^pi-child-message:[a-f0-9]{32}$/);
218
+ export const PI_DURABLE_CHILD_MESSAGE_MAX_CHARS = 8192;
219
+ export const PiDurableLeadChildMessageRequestSchema = PiDurableLeadCommandEnvelopeSchema.extend({
220
+ operation: z.literal('pi-durable.lead.child-message'),
221
+ payload: z
222
+ .object({
223
+ dispatchId: PiDurableDispatchIdSchema,
224
+ delegationId: IdentifierSchemas.delegationId,
225
+ requestId: PiDurableChildMessageRequestIdSchema,
226
+ text: z.string().trim().min(1).max(PI_DURABLE_CHILD_MESSAGE_MAX_CHARS),
227
+ })
228
+ .strict(),
229
+ });
209
230
  export const PiDurableLeadChildCancelRequestSchema = PiDurableLeadCommandEnvelopeSchema.extend({
210
231
  operation: z.literal('pi-durable.lead.child-cancel'),
211
232
  payload: z
212
233
  .object({
213
- dispatchId: DispatchId,
234
+ dispatchId: PiDurableDispatchIdSchema,
214
235
  delegationId: IdentifierSchemas.delegationId,
215
236
  })
216
237
  .strict(),
@@ -218,7 +239,7 @@ export const PiDurableLeadChildCancelRequestSchema = PiDurableLeadCommandEnvelop
218
239
  export const PiDurableLeadReceiptResponseSchema = z
219
240
  .object({
220
241
  schemaVersion: z.literal('pi-lead-dispatch/v1'),
221
- dispatchId: DispatchId,
242
+ dispatchId: PiDurableDispatchIdSchema,
222
243
  intentId: IntentId,
223
244
  executionId: IdentifierSchemas.executionId,
224
245
  attemptId: IdentifierSchemas.attemptId,
@@ -231,10 +252,9 @@ export const PiDurableLeadReceiptResponseSchema = z
231
252
  fenceForeignGeneration(receipt, context);
232
253
  });
233
254
  const response = SuccessResponseEnvelopeSchema.extend({ correlation: Correlation }).strict();
234
- const PlanDigest = z.string().regex(/^sha256:[a-f0-9]{64}$/);
235
255
  const ChildAllowanceBinding = {
236
256
  schemaVersion: z.literal('pi-lead-child-allowance/v1'),
237
- executionPlanDigest: PlanDigest,
257
+ executionPlanDigest: Sha256DigestSchema,
238
258
  profile: z
239
259
  .strictObject({
240
260
  profileId: IdentifierSchemas.profileId,
@@ -265,7 +285,7 @@ export const PiDurableLeadPreparationSchema = z
265
285
  selectionRevision: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
266
286
  funding: ModelSelectionFundingViewSchema.options[0],
267
287
  childAllowance: PiDurableLeadChildAllowanceSchema.optional(),
268
- expiresAt: z.iso.datetime(),
288
+ expiresAt: TimestampSchema,
269
289
  replayed: z.boolean(),
270
290
  })
271
291
  .strict()
@@ -296,7 +316,7 @@ export const PiDurableLeadLookupResponseSchema = response.extend({
296
316
  intentId: IntentId,
297
317
  receipt: z
298
318
  .object({
299
- dispatchId: DispatchId,
319
+ dispatchId: PiDurableDispatchIdSchema,
300
320
  executionId: IdentifierSchemas.executionId,
301
321
  attemptId: IdentifierSchemas.attemptId,
302
322
  state: z.enum(['dispatching', 'dispatched', 'reconciliation_required']),
@@ -362,18 +382,18 @@ export const PiDurableSessionSchema = z
362
382
  .object({
363
383
  runtimeSessionId: PiDurableSessionIdSchema,
364
384
  role: z.enum(['lead', 'child']),
365
- dispatchId: DispatchId,
385
+ dispatchId: PiDurableDispatchIdSchema,
366
386
  intentId: IntentId,
367
387
  delegationId: IdentifierSchemas.delegationId.optional(),
368
388
  executionId: IdentifierSchemas.executionId,
369
389
  attemptId: IdentifierSchemas.attemptId,
370
390
  state: RuntimeExecutionStateSchema,
371
- startedAt: z.iso.datetime(),
372
- updatedAt: z.iso.datetime(),
391
+ startedAt: TimestampSchema,
392
+ updatedAt: TimestampSchema,
373
393
  })
374
394
  .strict()
375
395
  .superRefine((value, context) => {
376
- const lead = value.runtimeSessionId === `pi-lead:${value.dispatchId}`;
396
+ const lead = value.runtimeSessionId === piLeadSessionId(value.dispatchId);
377
397
  if ((value.role === 'lead') !== lead ||
378
398
  (value.role === 'lead') !== (value.delegationId === undefined))
379
399
  context.addIssue({
@@ -471,8 +491,8 @@ export const PiDurableLeadChildSchema = z
471
491
  ]),
472
492
  awaitingInput: z.boolean(),
473
493
  stopRequested: z.boolean(),
474
- acceptedAt: z.iso.datetime(),
475
- updatedAt: z.iso.datetime(),
494
+ acceptedAt: TimestampSchema,
495
+ updatedAt: TimestampSchema,
476
496
  revision: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
477
497
  outcome: PiDurableLeadChildOutcomeSchema.optional(),
478
498
  })
@@ -506,13 +526,20 @@ export const PiDurableLeadChildCancelResponseSchema = response.extend({
506
526
  attributed: z.boolean(),
507
527
  }),
508
528
  });
529
+ export const PiDurableLeadChildMessageResponseSchema = response.extend({
530
+ data: PiDurableLeadReceiptResponseSchema.extend({
531
+ child: PiDurableLeadChildSchema,
532
+ requestId: PiDurableChildMessageRequestIdSchema,
533
+ outcome: z.enum(['delivered', 'already_delivered']),
534
+ }),
535
+ });
509
536
  export const PiDurableLeadChildTargetSchema = z.strictObject({
510
537
  source: z.literal('control_plane_reported'),
511
538
  runtimeConnectionId: IdentifierSchemas.runtimeConnectionId,
512
539
  nativeSessionId: IdentifierSchemas.externalSessionId,
513
540
  nativeTaskId: IdentifierSchemas.taskId,
514
541
  nativeState: RuntimeExecutionStateSchema,
515
- observedAt: z.iso.datetime(),
542
+ observedAt: TimestampSchema,
516
543
  observedGeneration: RuntimeObservedGenerationSchema.optional(),
517
544
  });
518
545
  export const PiDurableLeadRemoteSessionReferenceSchema = z
@@ -699,4 +726,11 @@ export const PiDurableLeadHttpContract = Object.freeze({
699
726
  requestSchema: PiDurableLeadChildCancelRequestSchema,
700
727
  responseSchema: PiDurableLeadChildCancelResponseSchema,
701
728
  }),
729
+ childMessage: Object.freeze({
730
+ route: 'child-message',
731
+ operation: 'pi-durable.lead.child-message',
732
+ scope: 'execution:write',
733
+ requestSchema: PiDurableLeadChildMessageRequestSchema,
734
+ responseSchema: PiDurableLeadChildMessageResponseSchema,
735
+ }),
702
736
  });
@@ -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.1.0",
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.3",
46
46
  "zod": "4.6.6"
47
47
  },
48
48
  "engines": {