@adea-ai/runtime-sdk 1.22.0 → 1.23.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/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './adapter.js';
2
2
  export * from './pi-durable-lead.js';
3
+ export * from './pi-durable-questions.js';
3
4
  export * from './agent-plugins.js';
4
5
  export * from './channel-ownership.js';
5
6
  export * from './capabilities.js';
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './adapter.js';
2
2
  export * from './pi-durable-lead.js';
3
+ export * from './pi-durable-questions.js';
3
4
  export * from './agent-plugins.js';
4
5
  export * from './channel-ownership.js';
5
6
  export * from './capabilities.js';
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { PiDurableQuestionAnswersSchema, PiDurableQuestionRequestIdSchema } from './pi-durable-questions.js';
2
3
  import { IdentifierSchemas, ModelSelectionRefSchema } from '@adea-ai/contracts';
3
4
  import { RuntimeExecutionProgressSchema, RuntimeExecutionStatusSchema, RuntimeExecutionStateSchema, RuntimeObservedGenerationSchema } from './adapter.js';
4
5
  declare const IntentId: z.ZodUUID;
@@ -155,6 +156,55 @@ export declare const PiDurableLeadProgressRequestSchema: z.ZodObject<{
155
156
  afterSequence: z.ZodOptional<z.ZodNumber>;
156
157
  }, z.core.$strict>;
157
158
  }, z.core.$strict>;
159
+ export declare const PI_DURABLE_LEAD_EVENTS_CONTRACT_VERSION = 1;
160
+ export declare const PI_DURABLE_LEAD_EVENTS_MAX_PAGE = 256;
161
+ export declare const PI_DURABLE_LEAD_EVENTS_MAX_WAIT_MS = 8000;
162
+ export declare const PiDurableLeadEventsRequestSchema: z.ZodObject<{
163
+ contractVersion: z.ZodObject<{
164
+ major: z.ZodNumber;
165
+ minor: z.ZodNumber;
166
+ }, z.core.$strict>;
167
+ requestId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"request ID">, string>>;
168
+ workspaceId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"workspace ID">, string>>;
169
+ projectId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"project ID">, string>>>;
170
+ requestedAt: z.ZodISODateTime;
171
+ caller: typeof Caller;
172
+ correlation: typeof Correlation;
173
+ operation: z.ZodLiteral<"pi-durable.lead.events">;
174
+ parameters: z.ZodObject<{
175
+ dispatchId: typeof DispatchId;
176
+ messageId: z.ZodString;
177
+ afterSeq: z.ZodNumber;
178
+ waitMs: z.ZodNumber;
179
+ limit: z.ZodOptional<z.ZodNumber>;
180
+ }, z.core.$strict>;
181
+ }, z.core.$strict>;
182
+ export declare const PiDurableLeadTurnEventSchema: z.ZodObject<{
183
+ schemaVersion: z.ZodLiteral<1>;
184
+ eventId: z.ZodString;
185
+ runtimeSessionId: z.ZodString;
186
+ harnessRunId: z.ZodString;
187
+ generation: z.ZodLiteral<1>;
188
+ seq: z.ZodString;
189
+ occurredAt: z.ZodISODateTime;
190
+ receivedAt: z.ZodISODateTime;
191
+ source: z.ZodLiteral<"native">;
192
+ sourceEventId: z.ZodString;
193
+ confidence: z.ZodLiteral<"authoritative">;
194
+ classification: z.ZodEnum<{
195
+ restricted_local: "restricted_local";
196
+ workspace_private: "workspace_private";
197
+ }>;
198
+ kind: z.ZodString;
199
+ payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
200
+ }, z.core.$strict>;
201
+ export declare const PiDurableLeadEventsDataSchema: z.ZodObject<{
202
+ contractVersion: z.ZodLiteral<1>;
203
+ dispatchId: typeof DispatchId;
204
+ events: z.ZodArray<typeof PiDurableLeadTurnEventSchema>;
205
+ nextSeq: z.ZodNumber;
206
+ complete: z.ZodBoolean;
207
+ }, z.core.$strict>;
158
208
  export declare const PiDurableLeadChildrenCursorSchema: z.ZodReadonly<z.ZodObject<{
159
209
  acceptedAt: z.ZodISODateTime;
160
210
  delegationId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"delegation ID">, string>>;
@@ -215,6 +265,27 @@ export declare const PiDurableLeadCancelRequestSchema: z.ZodObject<{
215
265
  dispatchId: z.ZodString;
216
266
  }, z.core.$strict>;
217
267
  }, z.core.$strict>;
268
+ export declare const PiDurableLeadQuestionAnswerRequestSchema: z.ZodObject<{
269
+ contractVersion: z.ZodObject<{
270
+ major: z.ZodNumber;
271
+ minor: z.ZodNumber;
272
+ }, z.core.$strict>;
273
+ requestId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"request ID">, string>>;
274
+ workspaceId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"workspace ID">, string>>;
275
+ projectId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"project ID">, string>>>;
276
+ commandId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"command ID">, string>>;
277
+ idempotencyKey: z.ZodString;
278
+ payloadHash: z.ZodString;
279
+ issuedAt: z.ZodISODateTime;
280
+ caller: typeof Caller;
281
+ correlation: typeof Correlation;
282
+ operation: z.ZodLiteral<"pi-durable.lead.question-answer">;
283
+ payload: z.ZodObject<{
284
+ dispatchId: typeof DispatchId;
285
+ requestId: typeof PiDurableQuestionRequestIdSchema;
286
+ answers: typeof PiDurableQuestionAnswersSchema;
287
+ }, z.core.$strict>;
288
+ }, z.core.$strict>;
218
289
  export declare const PiDurableLeadChildCancelRequestSchema: z.ZodObject<{
219
290
  contractVersion: z.ZodObject<{
220
291
  major: z.ZodNumber;
@@ -457,6 +528,51 @@ export declare const PiDurableLeadCancelResponseSchema: z.ZodObject<{
457
528
  status: typeof RuntimeExecutionStatusSchema;
458
529
  }, z.core.$strict>;
459
530
  }, z.core.$strict>;
531
+ export declare const PiDurableLeadQuestionAnswerResponseSchema: z.ZodObject<{
532
+ contractVersion: z.ZodObject<{
533
+ major: z.ZodNumber;
534
+ minor: z.ZodNumber;
535
+ }, z.core.$strict>;
536
+ requestId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"request ID">, string>>;
537
+ correlation: z.ZodObject<{
538
+ traceId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"trace ID">, string>>;
539
+ causationCommandId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"command ID">, string>>>;
540
+ parentEventId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"event ID">, string>>>;
541
+ }, z.core.$strict>;
542
+ data: z.ZodObject<{
543
+ schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
544
+ dispatchId: typeof DispatchId;
545
+ intentId: typeof IntentId;
546
+ executionId: typeof IdentifierSchemas.executionId;
547
+ attemptId: typeof IdentifierSchemas.attemptId;
548
+ runtimeSessionId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"external-session ID">, string>>;
549
+ requestedTarget: z.ZodOptional<typeof PiDurableLeadRequestedTargetSchema>;
550
+ observedTarget: z.ZodOptional<typeof PiDurableLeadObservedTargetSchema>;
551
+ questionSchemaVersion: z.ZodLiteral<"pi-lead-question-answer/v1">;
552
+ requestId: typeof PiDurableQuestionRequestIdSchema;
553
+ requestEventId: z.ZodString;
554
+ outcome: z.ZodEnum<{
555
+ already_answered: "already_answered";
556
+ answered: "answered";
557
+ expired: "expired";
558
+ }>;
559
+ state: typeof RuntimeExecutionStateSchema;
560
+ status: typeof RuntimeExecutionStatusSchema;
561
+ }, z.core.$strict>;
562
+ }, z.core.$strict>;
563
+ export declare const PiDurableLeadEventsResponseSchema: z.ZodObject<{
564
+ contractVersion: z.ZodObject<{
565
+ major: z.ZodNumber;
566
+ minor: z.ZodNumber;
567
+ }, z.core.$strict>;
568
+ requestId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"request ID">, string>>;
569
+ correlation: z.ZodObject<{
570
+ traceId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"trace ID">, string>>;
571
+ causationCommandId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"command ID">, string>>>;
572
+ parentEventId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"event ID">, string>>>;
573
+ }, z.core.$strict>;
574
+ data: typeof PiDurableLeadEventsDataSchema;
575
+ }, z.core.$strict>;
460
576
  declare const ChildReference: z.ZodString;
461
577
  export declare const PiDurableLeadChildOutcomeSchema: z.ZodObject<{
462
578
  state: z.ZodEnum<{
@@ -673,6 +789,13 @@ export declare const PiDurableLeadHttpContract: Readonly<{
673
789
  requestSchema: typeof PiDurableLeadProgressRequestSchema;
674
790
  responseSchema: typeof PiDurableLeadProgressResponseSchema;
675
791
  }>;
792
+ events: Readonly<{
793
+ route: "events";
794
+ operation: "pi-durable.lead.events";
795
+ scope: "execution:read";
796
+ requestSchema: typeof PiDurableLeadEventsRequestSchema;
797
+ responseSchema: typeof PiDurableLeadEventsResponseSchema;
798
+ }>;
676
799
  children: Readonly<{
677
800
  route: "children";
678
801
  operation: "pi-durable.lead.children";
@@ -694,6 +817,13 @@ export declare const PiDurableLeadHttpContract: Readonly<{
694
817
  requestSchema: typeof PiDurableLeadCancelRequestSchema;
695
818
  responseSchema: typeof PiDurableLeadCancelResponseSchema;
696
819
  }>;
820
+ questionAnswer: Readonly<{
821
+ route: "questions/answer";
822
+ operation: "pi-durable.lead.question-answer";
823
+ scope: "execution:write";
824
+ requestSchema: typeof PiDurableLeadQuestionAnswerRequestSchema;
825
+ responseSchema: typeof PiDurableLeadQuestionAnswerResponseSchema;
826
+ }>;
697
827
  childCancel: Readonly<{
698
828
  route: "child-cancel";
699
829
  operation: "pi-durable.lead.child-cancel";
@@ -714,11 +844,16 @@ export type PiDurableLeadStatusRequest = z.output<typeof PiDurableLeadStatusRequ
714
844
  export type PiDurableLeadStatusResponse = z.output<typeof PiDurableLeadStatusResponseSchema>;
715
845
  export type PiDurableLeadProgressRequest = z.output<typeof PiDurableLeadProgressRequestSchema>;
716
846
  export type PiDurableLeadProgressResponse = z.output<typeof PiDurableLeadProgressResponseSchema>;
847
+ export type PiDurableLeadEventsRequest = z.output<typeof PiDurableLeadEventsRequestSchema>;
848
+ export type PiDurableLeadEventsResponse = z.output<typeof PiDurableLeadEventsResponseSchema>;
849
+ export type PiDurableLeadTurnEvent = z.output<typeof PiDurableLeadTurnEventSchema>;
717
850
  export type PiDurableLeadChildrenRequest = z.output<typeof PiDurableLeadChildrenRequestSchema>;
718
851
  export type PiDurableLeadChildrenResponse = z.output<typeof PiDurableLeadChildrenResponseSchema>;
719
852
  export type PiDurableLeadChild = z.output<typeof PiDurableLeadChildSchema>;
720
853
  export type PiDurableLeadCancelRequest = z.output<typeof PiDurableLeadCancelRequestSchema>;
721
854
  export type PiDurableLeadCancelResponse = z.output<typeof PiDurableLeadCancelResponseSchema>;
855
+ export type PiDurableLeadQuestionAnswerRequest = z.output<typeof PiDurableLeadQuestionAnswerRequestSchema>;
856
+ export type PiDurableLeadQuestionAnswerResponse = z.output<typeof PiDurableLeadQuestionAnswerResponseSchema>;
722
857
  export type PiDurableLeadChildCancelRequest = z.output<typeof PiDurableLeadChildCancelRequestSchema>;
723
858
  export type PiDurableLeadChildCancelResponse = z.output<typeof PiDurableLeadChildCancelResponseSchema>;
724
859
  export type PiDurableLeadChildTargetRequest = z.output<typeof PiDurableLeadChildTargetRequestSchema>;
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { PiDurableQuestionAnswersSchema, PiDurableQuestionRequestIdSchema, } from './pi-durable-questions.js';
2
3
  import { ContractVersionSchema, IdentifierSchemas, ModelSelectionFundingViewSchema, ModelSelectionRefSchema, PublicContractManifest, ReadRequestEnvelopeSchema, StateChangingCommandEnvelopeSchema, SuccessResponseEnvelopeSchema, negotiateContractVersion, } from '@adea-ai/contracts';
3
4
  import { RuntimeExecutionHandleSchema, RuntimeExecutionProgressSchema, RuntimeExecutionStatusSchema, RuntimeExecutionStateSchema, RuntimeObservedGenerationSchema, } from './adapter.js';
4
5
  const IntentId = z.uuid();
@@ -101,6 +102,69 @@ export const PiDurableLeadProgressRequestSchema = PiDurableLeadReadEnvelopeSchem
101
102
  })
102
103
  .strict(),
103
104
  });
105
+ export const PI_DURABLE_LEAD_EVENTS_CONTRACT_VERSION = 1;
106
+ export const PI_DURABLE_LEAD_EVENTS_MAX_PAGE = 256;
107
+ export const PI_DURABLE_LEAD_EVENTS_MAX_WAIT_MS = 8000;
108
+ const LeadEventSeq = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
109
+ export const PiDurableLeadEventsRequestSchema = PiDurableLeadReadEnvelopeSchema.extend({
110
+ operation: z.literal('pi-durable.lead.events'),
111
+ parameters: z
112
+ .object({
113
+ dispatchId: DispatchId,
114
+ messageId: z
115
+ .string()
116
+ .min(1)
117
+ .max(128)
118
+ .regex(/^[A-Za-z0-9._:-]+$/),
119
+ afterSeq: LeadEventSeq,
120
+ waitMs: z.number().int().min(0).max(PI_DURABLE_LEAD_EVENTS_MAX_WAIT_MS),
121
+ limit: z.number().int().min(1).max(PI_DURABLE_LEAD_EVENTS_MAX_PAGE).optional(),
122
+ })
123
+ .strict(),
124
+ });
125
+ export const PiDurableLeadTurnEventSchema = z
126
+ .object({
127
+ schemaVersion: z.literal(1),
128
+ eventId: z.string().min(1).max(256),
129
+ runtimeSessionId: z.string().regex(/^pi-lead:dispatch_[a-f0-9]{32}$/),
130
+ harnessRunId: z.string().min(1).max(256),
131
+ generation: z.literal(1),
132
+ seq: z.string().regex(/^[1-9]\d*$/),
133
+ occurredAt: z.iso.datetime(),
134
+ receivedAt: z.iso.datetime(),
135
+ source: z.literal('native'),
136
+ sourceEventId: z.string().min(1).max(256),
137
+ confidence: z.literal('authoritative'),
138
+ classification: z.enum(['workspace_private', 'restricted_local']),
139
+ kind: z.string().min(1).max(64),
140
+ payload: z.record(z.string(), z.unknown()),
141
+ })
142
+ .strict();
143
+ export const PiDurableLeadEventsDataSchema = z
144
+ .object({
145
+ contractVersion: z.literal(PI_DURABLE_LEAD_EVENTS_CONTRACT_VERSION),
146
+ dispatchId: DispatchId,
147
+ events: z
148
+ .array(PiDurableLeadTurnEventSchema)
149
+ .max(PI_DURABLE_LEAD_EVENTS_MAX_PAGE),
150
+ nextSeq: LeadEventSeq,
151
+ complete: z.boolean(),
152
+ })
153
+ .strict()
154
+ .superRefine((value, context) => {
155
+ const first = value.nextSeq - value.events.length + 1;
156
+ value.events.forEach((event, index) => {
157
+ if (event.seq !== String(first + index) ||
158
+ event.runtimeSessionId !== `pi-lead:${value.dispatchId}`)
159
+ context.addIssue({
160
+ code: 'custom',
161
+ path: ['events', index],
162
+ message: 'Events must be the contiguous seqs of this dispatch ending at nextSeq',
163
+ });
164
+ });
165
+ if (first < 1)
166
+ context.addIssue({ code: 'custom', path: ['nextSeq'], message: 'nextSeq precedes the page' });
167
+ });
104
168
  export const PiDurableLeadChildrenCursorSchema = z
105
169
  .object({ acceptedAt: z.iso.datetime(), delegationId: IdentifierSchemas.delegationId })
106
170
  .strict()
@@ -129,6 +193,16 @@ export const PiDurableLeadCancelRequestSchema = PiDurableLeadCommandEnvelopeSche
129
193
  operation: z.literal('pi-durable.lead.cancel'),
130
194
  payload: z.object({ dispatchId: DispatchId }).strict(),
131
195
  });
196
+ export const PiDurableLeadQuestionAnswerRequestSchema = PiDurableLeadCommandEnvelopeSchema.extend({
197
+ operation: z.literal('pi-durable.lead.question-answer'),
198
+ payload: z
199
+ .object({
200
+ dispatchId: DispatchId,
201
+ requestId: PiDurableQuestionRequestIdSchema,
202
+ answers: PiDurableQuestionAnswersSchema,
203
+ })
204
+ .strict(),
205
+ });
132
206
  export const PiDurableLeadChildCancelRequestSchema = PiDurableLeadCommandEnvelopeSchema.extend({
133
207
  operation: z.literal('pi-durable.lead.child-cancel'),
134
208
  payload: z
@@ -256,6 +330,19 @@ export const PiDurableLeadProgressResponseSchema = response.extend({
256
330
  }),
257
331
  });
258
332
  export const PiDurableLeadCancelResponseSchema = PiDurableLeadStatusResponseSchema;
333
+ export const PiDurableLeadQuestionAnswerResponseSchema = response.extend({
334
+ data: PiDurableLeadReceiptResponseSchema.extend({
335
+ questionSchemaVersion: z.literal('pi-lead-question-answer/v1'),
336
+ requestId: PiDurableQuestionRequestIdSchema,
337
+ requestEventId: z.string().min(1).max(256),
338
+ outcome: z.enum(['answered', 'already_answered', 'expired']),
339
+ state: RuntimeExecutionStateSchema,
340
+ status: RuntimeExecutionStatusSchema,
341
+ }),
342
+ });
343
+ export const PiDurableLeadEventsResponseSchema = response.extend({
344
+ data: PiDurableLeadEventsDataSchema,
345
+ });
259
346
  const ChildReference = z
260
347
  .string()
261
348
  .trim()
@@ -458,6 +545,13 @@ export const PiDurableLeadHttpContract = Object.freeze({
458
545
  requestSchema: PiDurableLeadProgressRequestSchema,
459
546
  responseSchema: PiDurableLeadProgressResponseSchema,
460
547
  }),
548
+ events: Object.freeze({
549
+ route: 'events',
550
+ operation: 'pi-durable.lead.events',
551
+ scope: 'execution:read',
552
+ requestSchema: PiDurableLeadEventsRequestSchema,
553
+ responseSchema: PiDurableLeadEventsResponseSchema,
554
+ }),
461
555
  children: Object.freeze({
462
556
  route: 'children',
463
557
  operation: 'pi-durable.lead.children',
@@ -479,6 +573,13 @@ export const PiDurableLeadHttpContract = Object.freeze({
479
573
  requestSchema: PiDurableLeadCancelRequestSchema,
480
574
  responseSchema: PiDurableLeadCancelResponseSchema,
481
575
  }),
576
+ questionAnswer: Object.freeze({
577
+ route: 'questions/answer',
578
+ operation: 'pi-durable.lead.question-answer',
579
+ scope: 'execution:write',
580
+ requestSchema: PiDurableLeadQuestionAnswerRequestSchema,
581
+ responseSchema: PiDurableLeadQuestionAnswerResponseSchema,
582
+ }),
482
583
  childCancel: Object.freeze({
483
584
  route: 'child-cancel',
484
585
  operation: 'pi-durable.lead.child-cancel',
@@ -0,0 +1,106 @@
1
+ import { z } from 'zod';
2
+ export declare const PI_QUESTION_TIMEOUT_DEFAULT_SECONDS: number;
3
+ export declare const PI_QUESTION_TIMEOUT_MIN_SECONDS = 60;
4
+ export declare const PI_QUESTION_TIMEOUT_MAX_SECONDS: number;
5
+ export declare const PI_QUESTIONS_MAX = 8;
6
+ export declare const PI_QUESTION_OPTIONS_MAX = 16;
7
+ export declare const PI_QUESTION_CONTENT_BYTES_MAX: number;
8
+ export declare const PiDurableQuestionRequestIdSchema: z.ZodString;
9
+ export declare const PiDurableQuestionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
10
+ id: z.ZodString;
11
+ prompt: z.ZodString;
12
+ required: z.ZodBoolean;
13
+ kind: z.ZodLiteral<"text">;
14
+ }, z.core.$strict>, z.ZodObject<{
15
+ id: z.ZodString;
16
+ prompt: z.ZodString;
17
+ required: z.ZodBoolean;
18
+ kind: z.ZodLiteral<"choice">;
19
+ multiple: z.ZodBoolean;
20
+ options: z.ZodArray<z.ZodObject<{
21
+ id: z.ZodString;
22
+ label: z.ZodString;
23
+ description: z.ZodOptional<z.ZodString>;
24
+ }, z.core.$strict>>;
25
+ }, z.core.$strict>], "kind">;
26
+ export type PiDurableQuestion = z.output<typeof PiDurableQuestionSchema>;
27
+ export declare const PiDurableQuestionsSchema: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
28
+ id: z.ZodString;
29
+ prompt: z.ZodString;
30
+ required: z.ZodBoolean;
31
+ kind: z.ZodLiteral<"text">;
32
+ }, z.core.$strict>, z.ZodObject<{
33
+ id: z.ZodString;
34
+ prompt: z.ZodString;
35
+ required: z.ZodBoolean;
36
+ kind: z.ZodLiteral<"choice">;
37
+ multiple: z.ZodBoolean;
38
+ options: z.ZodArray<z.ZodObject<{
39
+ id: z.ZodString;
40
+ label: z.ZodString;
41
+ description: z.ZodOptional<z.ZodString>;
42
+ }, z.core.$strict>>;
43
+ }, z.core.$strict>], "kind">>;
44
+ export declare const PiDurableQuestionAnswerSchema: z.ZodUnion<readonly [z.ZodObject<{
45
+ questionId: z.ZodString;
46
+ text: z.ZodString;
47
+ }, z.core.$strict>, z.ZodObject<{
48
+ questionId: z.ZodString;
49
+ optionIds: z.ZodArray<z.ZodString>;
50
+ }, z.core.$strict>, z.ZodObject<{
51
+ questionId: z.ZodString;
52
+ skipped: z.ZodLiteral<true>;
53
+ }, z.core.$strict>]>;
54
+ export type PiDurableQuestionAnswer = z.output<typeof PiDurableQuestionAnswerSchema>;
55
+ export declare const PiDurableQuestionAnswersSchema: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
56
+ questionId: z.ZodString;
57
+ text: z.ZodString;
58
+ }, z.core.$strict>, z.ZodObject<{
59
+ questionId: z.ZodString;
60
+ optionIds: z.ZodArray<z.ZodString>;
61
+ }, z.core.$strict>, z.ZodObject<{
62
+ questionId: z.ZodString;
63
+ skipped: z.ZodLiteral<true>;
64
+ }, z.core.$strict>]>>;
65
+ export declare const PiDurableQuestionRequestSchema: z.ZodObject<{
66
+ requestId: z.ZodString;
67
+ callId: z.ZodString;
68
+ questions: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
69
+ id: z.ZodString;
70
+ prompt: z.ZodString;
71
+ required: z.ZodBoolean;
72
+ kind: z.ZodLiteral<"text">;
73
+ }, z.core.$strict>, z.ZodObject<{
74
+ id: z.ZodString;
75
+ prompt: z.ZodString;
76
+ required: z.ZodBoolean;
77
+ kind: z.ZodLiteral<"choice">;
78
+ multiple: z.ZodBoolean;
79
+ options: z.ZodArray<z.ZodObject<{
80
+ id: z.ZodString;
81
+ label: z.ZodString;
82
+ description: z.ZodOptional<z.ZodString>;
83
+ }, z.core.$strict>>;
84
+ }, z.core.$strict>], "kind">>;
85
+ expiresAt: z.ZodISODateTime;
86
+ }, z.core.$strict>;
87
+ export type PiDurableQuestionRequest = z.output<typeof PiDurableQuestionRequestSchema>;
88
+ export declare const PiDurableQuestionOutcomeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
89
+ decision: z.ZodLiteral<"answered">;
90
+ answers: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
91
+ questionId: z.ZodString;
92
+ text: z.ZodString;
93
+ }, z.core.$strict>, z.ZodObject<{
94
+ questionId: z.ZodString;
95
+ optionIds: z.ZodArray<z.ZodString>;
96
+ }, z.core.$strict>, z.ZodObject<{
97
+ questionId: z.ZodString;
98
+ skipped: z.ZodLiteral<true>;
99
+ }, z.core.$strict>]>>;
100
+ decidedAt: z.ZodISODateTime;
101
+ }, z.core.$strict>, z.ZodObject<{
102
+ decision: z.ZodLiteral<"expired">;
103
+ decidedAt: z.ZodISODateTime;
104
+ }, z.core.$strict>], "decision">;
105
+ export type PiDurableQuestionOutcome = z.output<typeof PiDurableQuestionOutcomeSchema>;
106
+ export declare function questionAnswersProblem(questions: readonly PiDurableQuestion[], input: unknown): string | undefined;
@@ -0,0 +1,109 @@
1
+ import { z } from 'zod';
2
+ export const PI_QUESTION_TIMEOUT_DEFAULT_SECONDS = 60 * 60;
3
+ export const PI_QUESTION_TIMEOUT_MIN_SECONDS = 60;
4
+ export const PI_QUESTION_TIMEOUT_MAX_SECONDS = 24 * 60 * 60;
5
+ export const PI_QUESTIONS_MAX = 8;
6
+ export const PI_QUESTION_OPTIONS_MAX = 16;
7
+ export const PI_QUESTION_CONTENT_BYTES_MAX = 32 * 1024;
8
+ const Id = z
9
+ .string()
10
+ .min(1)
11
+ .max(64)
12
+ .regex(/^[A-Za-z0-9][A-Za-z0-9._:-]*$/);
13
+ export const PiDurableQuestionRequestIdSchema = z.string().regex(/^pi-question:[a-f0-9]{32}$/);
14
+ const OptionSchema = z.strictObject({
15
+ id: Id,
16
+ label: z.string().trim().min(1).max(512),
17
+ description: z.string().trim().min(1).max(2048).optional(),
18
+ });
19
+ export const PiDurableQuestionSchema = z.discriminatedUnion('kind', [
20
+ z.strictObject({
21
+ id: Id,
22
+ prompt: z.string().trim().min(1).max(4096),
23
+ required: z.boolean(),
24
+ kind: z.literal('text'),
25
+ }),
26
+ z.strictObject({
27
+ id: Id,
28
+ prompt: z.string().trim().min(1).max(4096),
29
+ required: z.boolean(),
30
+ kind: z.literal('choice'),
31
+ multiple: z.boolean(),
32
+ options: z
33
+ .array(OptionSchema)
34
+ .min(1)
35
+ .max(PI_QUESTION_OPTIONS_MAX)
36
+ .refine((options) => unique(options.map((option) => option.id)), 'duplicate option id'),
37
+ }),
38
+ ]);
39
+ export const PiDurableQuestionsSchema = z
40
+ .array(PiDurableQuestionSchema)
41
+ .min(1)
42
+ .max(PI_QUESTIONS_MAX)
43
+ .refine((questions) => unique(questions.map((question) => question.id)), 'duplicate question id')
44
+ .refine((questions) => fits(questions), 'questions too large');
45
+ export const PiDurableQuestionAnswerSchema = z.union([
46
+ z.strictObject({ questionId: Id, text: z.string().min(1).max(16_384) }),
47
+ z.strictObject({
48
+ questionId: Id,
49
+ optionIds: z
50
+ .array(Id)
51
+ .min(1)
52
+ .max(PI_QUESTION_OPTIONS_MAX)
53
+ .refine((ids) => unique(ids), 'duplicate option id'),
54
+ }),
55
+ z.strictObject({ questionId: Id, skipped: z.literal(true) }),
56
+ ]);
57
+ export const PiDurableQuestionAnswersSchema = z
58
+ .array(PiDurableQuestionAnswerSchema)
59
+ .max(PI_QUESTIONS_MAX)
60
+ .refine((answers) => unique(answers.map((answer) => answer.questionId)), 'duplicate question id')
61
+ .refine((answers) => fits(answers), 'answers too large');
62
+ export const PiDurableQuestionRequestSchema = z.strictObject({
63
+ requestId: PiDurableQuestionRequestIdSchema,
64
+ callId: z.string().min(1).max(256),
65
+ questions: PiDurableQuestionsSchema,
66
+ expiresAt: z.iso.datetime(),
67
+ });
68
+ export const PiDurableQuestionOutcomeSchema = z.discriminatedUnion('decision', [
69
+ z.strictObject({
70
+ decision: z.literal('answered'),
71
+ answers: PiDurableQuestionAnswersSchema,
72
+ decidedAt: z.iso.datetime(),
73
+ }),
74
+ z.strictObject({ decision: z.literal('expired'), decidedAt: z.iso.datetime() }),
75
+ ]);
76
+ export function questionAnswersProblem(questions, input) {
77
+ const parsed = PiDurableQuestionAnswersSchema.safeParse(input);
78
+ if (!parsed.success)
79
+ return 'answers are malformed';
80
+ const answers = new Map(parsed.data.map((answer) => [answer.questionId, answer]));
81
+ for (const question of questions) {
82
+ const answer = answers.get(question.id);
83
+ answers.delete(question.id);
84
+ if (!answer || 'skipped' in answer) {
85
+ if (question.required)
86
+ return 'a required question is unanswered';
87
+ }
88
+ else if (question.kind === 'text') {
89
+ if (!('text' in answer))
90
+ return 'a text question needs a text answer';
91
+ }
92
+ else {
93
+ if (!('optionIds' in answer))
94
+ return 'a choice question needs option ids';
95
+ if (!question.multiple && answer.optionIds.length !== 1)
96
+ return 'expected a single choice';
97
+ const known = new Set(question.options.map((option) => option.id));
98
+ if (answer.optionIds.some((id) => !known.has(id)))
99
+ return 'unknown option id';
100
+ }
101
+ }
102
+ return answers.size ? 'unknown question id' : undefined;
103
+ }
104
+ function unique(values) {
105
+ return new Set(values).size === values.length;
106
+ }
107
+ function fits(value) {
108
+ return Buffer.byteLength(JSON.stringify(value), 'utf8') <= PI_QUESTION_CONTENT_BYTES_MAX;
109
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adea-ai/runtime-sdk",
3
- "version": "1.22.0",
3
+ "version": "1.23.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",
@@ -43,7 +43,7 @@
43
43
  "test": "bun test src"
44
44
  },
45
45
  "dependencies": {
46
- "@adea-ai/contracts": "^1.26.1",
46
+ "@adea-ai/contracts": "^3.0.0",
47
47
  "zod": "4.6.6"
48
48
  },
49
49
  "engines": {