@adea-ai/runtime-sdk 1.23.0 → 2.0.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/README.md CHANGED
@@ -1,13 +1,11 @@
1
1
  # @control-plane/runtime-sdk
2
2
 
3
3
  SDK for building runtimes that plug into the Control Plane: implement the
4
- adapter interface, declare capabilities, pass conformance, and speak the
5
- gateway protocol — without touching Control Plane internals.
4
+ adapter interface, declare capabilities, and pass conformance — without
5
+ touching Control Plane internals.
6
6
 
7
7
  Depends only on [`@adea-ai/contracts`](https://www.npmjs.com/package/@adea-ai/contracts)
8
- and Zod. Pair it with
9
- [`@adea-ai/runtime-gateway-protocol`](https://www.npmjs.com/package/@adea-ai/runtime-gateway-protocol)
10
- for the wire protocol and [`@adea-ai/contracts`](https://www.npmjs.com/package/@adea-ai/contracts)
8
+ and Zod. Pair it with [`@adea-ai/contracts`](https://www.npmjs.com/package/@adea-ai/contracts)
11
9
  for the service boundary.
12
10
 
13
11
  ## What's inside
@@ -20,8 +18,8 @@ for the service boundary.
20
18
  - **Conformance & compatibility** — versioned conformance suites and
21
19
  compatibility checks for runtime implementations.
22
20
  - **Sessions & routing** — external session types and routing decisions.
23
- - **Transport** — transport ports with deterministic in-memory doubles
24
- (`mock.ts`, `fixtures.ts`) for testing adapters without a live gateway.
21
+ - **Transport** — the co-located transport port with deterministic in-memory
22
+ doubles (`mock.ts`, `fixtures.ts`) for testing adapters.
25
23
 
26
24
  Runtime usage accounting distinguishes HQ-funded API usage (`hq_managed`),
27
25
  user-funded API usage (`byo_api`), and external subscriptions
package/dist/adapter.d.ts CHANGED
@@ -12,7 +12,6 @@ export declare const RuntimeAdapterMetadataSchema: z.ZodObject<{
12
12
  harnessVersion: z.ZodString;
13
13
  transportKind: z.ZodOptional<z.ZodEnum<{
14
14
  "direct-local": "direct-local";
15
- "remote-gateway": "remote-gateway";
16
15
  }>>;
17
16
  }, z.core.$strict>;
18
17
  export declare const RuntimeAdapterInspectionSchema: z.ZodObject<{
@@ -28,7 +27,6 @@ export declare const RuntimeAdapterInspectionSchema: z.ZodObject<{
28
27
  harnessVersion: z.ZodString;
29
28
  transportKind: z.ZodOptional<z.ZodEnum<{
30
29
  "direct-local": "direct-local";
31
- "remote-gateway": "remote-gateway";
32
30
  }>>;
33
31
  }, z.core.$strict>;
34
32
  health: z.ZodEnum<{
package/dist/adapter.js CHANGED
@@ -23,7 +23,7 @@ export const RuntimeAdapterMetadataSchema = z
23
23
  .regex(/^[a-z][a-z0-9-]*$/),
24
24
  driverVersion: SemanticVersionSchema,
25
25
  harnessVersion: SemanticVersionSchema,
26
- transportKind: z.enum(['direct-local', 'remote-gateway']).optional(),
26
+ transportKind: z.enum(['direct-local']).optional(),
27
27
  })
28
28
  .strict();
29
29
  const CapabilityEvaluationSchema = z
@@ -13,10 +13,6 @@ export declare const RuntimeChannelOwnershipSchema: z.ZodObject<{
13
13
  lastHeartbeatAt: z.ZodISODateTime;
14
14
  }, z.core.$strict>;
15
15
  export type RuntimeChannelOwnership = z.output<typeof RuntimeChannelOwnershipSchema>;
16
- export interface RuntimeChannelOwnershipCredentialFence {
17
- readonly credentialId: string;
18
- readonly revocationVersion: number;
19
- }
20
16
  export declare const RuntimeChannelSequenceRequestSchema: z.ZodObject<{
21
17
  channel: z.ZodObject<{
22
18
  nodeId: z.ZodString;
@@ -38,12 +34,3 @@ export type RuntimeChannelSequenceRequest = z.output<typeof RuntimeChannelSequen
38
34
  export interface RuntimeChannelSequenceRepository {
39
35
  reserve(request: RuntimeChannelSequenceRequest): Promise<number>;
40
36
  }
41
- export interface RuntimeChannelOwnershipRepository {
42
- claim(record: RuntimeChannelOwnership, credentialFence?: RuntimeChannelOwnershipCredentialFence): Promise<{
43
- accepted: boolean;
44
- previous?: RuntimeChannelOwnership;
45
- }>;
46
- lookup(nodeId: string): Promise<RuntimeChannelOwnership | undefined>;
47
- heartbeat(record: RuntimeChannelOwnership, credentialFence?: RuntimeChannelOwnershipCredentialFence): Promise<boolean>;
48
- release(record: RuntimeChannelOwnership): Promise<boolean>;
49
- }
@@ -13,7 +13,6 @@ export declare const RuntimeCertificationSchema: z.ZodObject<{
13
13
  runtimeFamily: z.ZodString;
14
14
  connectionType: z.ZodEnum<{
15
15
  external_local: "external_local";
16
- managed_cloud: "managed_cloud";
17
16
  managed_local: "managed_local";
18
17
  }>;
19
18
  classification: z.ZodEnum<{
@@ -67,7 +66,6 @@ export declare const RuntimeCertificationSchema: z.ZodObject<{
67
66
  x64: "x64";
68
67
  }>;
69
68
  location: z.ZodEnum<{
70
- agent_hq_cloud: "agent_hq_cloud";
71
69
  local_device: "local_device";
72
70
  }>;
73
71
  environment: z.ZodString;
@@ -78,7 +76,6 @@ export declare const RuntimeCertificationSchema: z.ZodObject<{
78
76
  "direct-local-transport-integration": "direct-local-transport-integration";
79
77
  "hosted-runtime-integration": "hosted-runtime-integration";
80
78
  "runtime-adapter-conformance": "runtime-adapter-conformance";
81
- "runtime-gateway-integration": "runtime-gateway-integration";
82
79
  }>;
83
80
  source: z.ZodString;
84
81
  command: z.ZodString;
@@ -101,7 +98,6 @@ export declare const RuntimeCompatibilityMatrixSchema: z.ZodObject<{
101
98
  runtimeFamily: z.ZodString;
102
99
  connectionType: z.ZodEnum<{
103
100
  external_local: "external_local";
104
- managed_cloud: "managed_cloud";
105
101
  managed_local: "managed_local";
106
102
  }>;
107
103
  classification: z.ZodEnum<{
@@ -155,7 +151,6 @@ export declare const RuntimeCompatibilityMatrixSchema: z.ZodObject<{
155
151
  x64: "x64";
156
152
  }>;
157
153
  location: z.ZodEnum<{
158
- agent_hq_cloud: "agent_hq_cloud";
159
154
  local_device: "local_device";
160
155
  }>;
161
156
  environment: z.ZodString;
@@ -166,7 +161,6 @@ export declare const RuntimeCompatibilityMatrixSchema: z.ZodObject<{
166
161
  "direct-local-transport-integration": "direct-local-transport-integration";
167
162
  "hosted-runtime-integration": "hosted-runtime-integration";
168
163
  "runtime-adapter-conformance": "runtime-adapter-conformance";
169
- "runtime-gateway-integration": "runtime-gateway-integration";
170
164
  }>;
171
165
  source: z.ZodString;
172
166
  command: z.ZodString;
@@ -54,7 +54,6 @@ export const RuntimeCertificationSchema = z
54
54
  suite: z.enum([
55
55
  'runtime-adapter-conformance',
56
56
  'direct-local-transport-integration',
57
- 'runtime-gateway-integration',
58
57
  'hosted-runtime-integration',
59
58
  ]),
60
59
  source: z
@@ -73,7 +72,8 @@ export const RuntimeCertificationSchema = z
73
72
  .superRefine((certification, context) => {
74
73
  if (certification.classification === 'supported' &&
75
74
  (!certification.evidence.some((entry) => entry.suite === 'runtime-adapter-conformance') ||
76
- !certification.evidence.some((entry) => ['direct-local-transport-integration', 'runtime-gateway-integration'].includes(entry.suite) || entry.suite === 'hosted-runtime-integration'))) {
75
+ !certification.evidence.some((entry) => entry.suite === 'direct-local-transport-integration' ||
76
+ entry.suite === 'hosted-runtime-integration'))) {
77
77
  context.addIssue({
78
78
  code: 'custom',
79
79
  path: ['evidence'],
@@ -6,7 +6,7 @@ export interface RuntimeConnectionDiscoveryProjectionInput {
6
6
  readonly connection: RuntimeConnection;
7
7
  readonly family: string;
8
8
  readonly node?: unknown;
9
- readonly nodeHealth: 'online' | 'offline' | 'unknown' | 'revoked' | 'not_applicable';
9
+ readonly nodeHealth: 'online' | 'offline' | 'unknown' | 'revoked';
10
10
  readonly evaluatedAt: string;
11
11
  readonly localProjectGrant: {
12
12
  readonly required: boolean;
package/dist/discovery.js CHANGED
@@ -7,15 +7,12 @@ import { ExternalSessionAssessmentSchema, ExternalSessionSchema, } from './sessi
7
7
  export function projectRuntimeConnectionDiscovery(inputValue) {
8
8
  const connection = RuntimeConnectionSchema.parse(inputValue.connection);
9
9
  const evaluatedAt = RuntimeTimestampSchema.parse(inputValue.evaluatedAt);
10
- const nodeHealth = inputValue.nodeHealth === 'not_applicable'
11
- ? 'not_applicable'
12
- : RuntimeNodeHealthStatusSchema.parse(inputValue.nodeHealth);
10
+ const nodeHealth = RuntimeNodeHealthStatusSchema.parse(inputValue.nodeHealth);
13
11
  const node = inputValue.node === undefined ? undefined : RuntimeNodeRefSchema.parse(inputValue.node);
14
- const local = connection.connectionType !== 'managed_cloud';
15
- if (local !== (node !== undefined) || local !== (nodeHealth !== 'not_applicable')) {
12
+ if (node === undefined) {
16
13
  throw new Error('RUNTIME_DISCOVERY_NODE_SCOPE_MISMATCH');
17
14
  }
18
- if (node && node.runtimeNodeRefId !== connection.runtimeNodeRefId) {
15
+ if (node.runtimeNodeRefId !== connection.runtimeNodeRefId) {
19
16
  throw new Error('RUNTIME_DISCOVERY_NODE_ID_MISMATCH');
20
17
  }
21
18
  const requiredCapabilities = (inputValue.requiredCapabilities ?? []).map((capability) => RuntimeCapabilityNameSchema.parse(capability));
@@ -1,10 +1,10 @@
1
1
  import { z } from 'zod';
2
- export declare const RuntimeEligibilityNodeStatusSchema: z.ZodUnion<readonly [z.ZodEnum<{
2
+ export declare const RuntimeEligibilityNodeStatusSchema: z.ZodEnum<{
3
3
  offline: "offline";
4
4
  online: "online";
5
5
  revoked: "revoked";
6
6
  unknown: "unknown";
7
- }>, z.ZodLiteral<"not_applicable">]>;
7
+ }>;
8
8
  export declare const RuntimeEligibilityInputSchema: z.ZodObject<{
9
9
  eligibilityVersion: z.ZodLiteral<1>;
10
10
  evaluatedAt: z.ZodISODateTime;
@@ -47,24 +47,22 @@ export declare const RuntimeEligibilityInputSchema: z.ZodObject<{
47
47
  }, z.core.$strict>;
48
48
  candidate: z.ZodObject<{
49
49
  family: z.ZodString;
50
- nodeStatus: z.ZodUnion<readonly [z.ZodEnum<{
50
+ nodeStatus: z.ZodEnum<{
51
51
  offline: "offline";
52
52
  online: "online";
53
53
  revoked: "revoked";
54
54
  unknown: "unknown";
55
- }>, z.ZodLiteral<"not_applicable">]>;
55
+ }>;
56
56
  connection: z.ZodObject<{
57
57
  runtimeConnectionId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"runtime-connection ID">, string>>;
58
58
  identityDigest: z.ZodString;
59
59
  connectionType: z.ZodEnum<{
60
60
  external_local: "external_local";
61
- managed_cloud: "managed_cloud";
62
61
  managed_local: "managed_local";
63
62
  }>;
64
63
  runtimeNodeRefId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"runtime-node reference ID">, string>>>;
65
64
  runtimeDefinitionId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"runtime-definition ID">, string>>;
66
65
  location: z.ZodEnum<{
67
- agent_hq_cloud: "agent_hq_cloud";
68
66
  local_device: "local_device";
69
67
  }>;
70
68
  opaqueNativeRef: z.ZodOptional<z.ZodString>;
@@ -164,7 +162,6 @@ export declare const RuntimeEligibilityInputSchema: z.ZodObject<{
164
162
  }, z.core.$strict>;
165
163
  allowedFamilies: z.ZodArray<z.ZodString>;
166
164
  allowedLocations: z.ZodArray<z.ZodEnum<{
167
- agent_hq_cloud: "agent_hq_cloud";
168
165
  local_device: "local_device";
169
166
  }>>;
170
167
  deniedRuntimeConnectionIds: z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"runtime-connection ID">, string>>>;
@@ -16,10 +16,7 @@ const PolicyReasonCodeSchema = z
16
16
  .min(1)
17
17
  .max(128)
18
18
  .regex(/^[A-Z][A-Z0-9_]*$/);
19
- export const RuntimeEligibilityNodeStatusSchema = z.union([
20
- RuntimeNodeHealthStatusSchema,
21
- z.literal('not_applicable'),
22
- ]);
19
+ export const RuntimeEligibilityNodeStatusSchema = RuntimeNodeHealthStatusSchema;
23
20
  export const RuntimeEligibilityInputSchema = z
24
21
  .object({
25
22
  eligibilityVersion: z.literal(1),
@@ -85,17 +82,7 @@ export const RuntimeEligibilityInputSchema = z
85
82
  .strict()
86
83
  .optional(),
87
84
  })
88
- .strict()
89
- .superRefine((input, context) => {
90
- const managedCloud = input.candidate.connection.connectionType === 'managed_cloud';
91
- if (managedCloud !== (input.candidate.nodeStatus === 'not_applicable')) {
92
- context.addIssue({
93
- code: 'custom',
94
- path: ['candidate', 'nodeStatus'],
95
- message: 'Managed-cloud candidates must not invent RuntimeNode health',
96
- });
97
- }
98
- });
85
+ .strict();
99
86
  export const RuntimeEligibilityReasonCodeSchema = z.enum([
100
87
  'CAPABILITY_SNAPSHOT_MISSING',
101
88
  'CAPABILITY_SNAPSHOT_STALE',
@@ -5,7 +5,7 @@ export declare const RuntimeFixtures: Readonly<{
5
5
  adapterVersion: string;
6
6
  driverVersion: string;
7
7
  harnessVersion: string;
8
- location: "agent_hq_cloud" | "local_device" | "remote_host";
8
+ location: "local_device";
9
9
  health: "degraded" | "healthy" | "unavailable";
10
10
  lifecycle: "active" | "deprecated" | "revoked";
11
11
  capabilities: {
@@ -34,7 +34,7 @@ export declare const RuntimeFixtures: Readonly<{
34
34
  adapterVersion: string;
35
35
  driverVersion: string;
36
36
  harnessVersion: string;
37
- location: "agent_hq_cloud" | "local_device" | "remote_host";
37
+ location: "local_device";
38
38
  health: "degraded" | "healthy" | "unavailable";
39
39
  lifecycle: "active" | "deprecated" | "revoked";
40
40
  capabilities: {
@@ -63,7 +63,7 @@ export declare const RuntimeFixtures: Readonly<{
63
63
  adapterVersion: string;
64
64
  driverVersion: string;
65
65
  harnessVersion: string;
66
- location: "agent_hq_cloud" | "local_device" | "remote_host";
66
+ location: "local_device";
67
67
  health: "degraded" | "healthy" | "unavailable";
68
68
  lifecycle: "active" | "deprecated" | "revoked";
69
69
  capabilities: {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './adapter.js';
2
2
  export * from './pi-durable-lead.js';
3
3
  export * from './pi-durable-questions.js';
4
+ export * from './pi-durable-approvals.js';
4
5
  export * from './agent-plugins.js';
5
6
  export * from './channel-ownership.js';
6
7
  export * from './capabilities.js';
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './adapter.js';
2
2
  export * from './pi-durable-lead.js';
3
3
  export * from './pi-durable-questions.js';
4
+ export * from './pi-durable-approvals.js';
4
5
  export * from './agent-plugins.js';
5
6
  export * from './channel-ownership.js';
6
7
  export * from './capabilities.js';
package/dist/models.d.ts CHANGED
@@ -3,9 +3,7 @@ import { type CapabilityRequirement } from './capabilities.js';
3
3
  export declare const RuntimeTimestampSchema: z.ZodISODateTime;
4
4
  export declare const RuntimeSemanticVersionSchema: z.ZodString;
5
5
  export declare const RuntimeLocationSchema: z.ZodEnum<{
6
- agent_hq_cloud: "agent_hq_cloud";
7
6
  local_device: "local_device";
8
- remote_host: "remote_host";
9
7
  }>;
10
8
  export declare const RuntimeHealthSchema: z.ZodEnum<{
11
9
  degraded: "degraded";
@@ -42,9 +40,7 @@ export declare const RuntimeDefinitionSchema: z.ZodObject<{
42
40
  driverVersion: z.ZodString;
43
41
  harnessVersion: z.ZodString;
44
42
  location: z.ZodEnum<{
45
- agent_hq_cloud: "agent_hq_cloud";
46
43
  local_device: "local_device";
47
- remote_host: "remote_host";
48
44
  }>;
49
45
  health: z.ZodEnum<{
50
46
  degraded: "degraded";
@@ -112,9 +108,7 @@ export declare const RuntimeNodeRefSchema: z.ZodObject<{
112
108
  authority: z.ZodLiteral<"agent_hq">;
113
109
  displayName: z.ZodString;
114
110
  location: z.ZodEnum<{
115
- agent_hq_cloud: "agent_hq_cloud";
116
111
  local_device: "local_device";
117
- remote_host: "remote_host";
118
112
  }>;
119
113
  status: z.ZodEnum<{
120
114
  offline: "offline";
@@ -124,12 +118,10 @@ export declare const RuntimeNodeRefSchema: z.ZodObject<{
124
118
  observedAt: z.ZodISODateTime;
125
119
  }, z.core.$strip>;
126
120
  export declare const RuntimeConnectionLocationSchema: z.ZodEnum<{
127
- agent_hq_cloud: "agent_hq_cloud";
128
121
  local_device: "local_device";
129
122
  }>;
130
123
  export declare const RuntimeConnectionTypeSchema: z.ZodEnum<{
131
124
  external_local: "external_local";
132
- managed_cloud: "managed_cloud";
133
125
  managed_local: "managed_local";
134
126
  }>;
135
127
  export declare const RuntimeConnectionStatusSchema: z.ZodEnum<{
@@ -172,13 +164,11 @@ export declare const RuntimeConnectionSchema: z.ZodObject<{
172
164
  identityDigest: z.ZodString;
173
165
  connectionType: z.ZodEnum<{
174
166
  external_local: "external_local";
175
- managed_cloud: "managed_cloud";
176
167
  managed_local: "managed_local";
177
168
  }>;
178
169
  runtimeNodeRefId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"runtime-node reference ID">, string>>>;
179
170
  runtimeDefinitionId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"runtime-definition ID">, string>>;
180
171
  location: z.ZodEnum<{
181
- agent_hq_cloud: "agent_hq_cloud";
182
172
  local_device: "local_device";
183
173
  }>;
184
174
  opaqueNativeRef: z.ZodOptional<z.ZodString>;
package/dist/models.js CHANGED
@@ -12,7 +12,7 @@ const RuntimeFamilySchema = z
12
12
  .max(64)
13
13
  .regex(/^[a-z][a-z0-9-]*$/);
14
14
  const uniqueCapabilities = (capabilities) => new Set(capabilities.map((capability) => capability.name)).size === capabilities.length;
15
- export const RuntimeLocationSchema = z.enum(['local_device', 'remote_host', 'agent_hq_cloud']);
15
+ export const RuntimeLocationSchema = z.enum(['local_device']);
16
16
  export const RuntimeHealthSchema = z.enum(['healthy', 'degraded', 'unavailable']);
17
17
  export const RuntimeLifecycleSchema = z.enum(['active', 'deprecated', 'revoked']);
18
18
  export const RuntimeCompatibilityMetadataSchema = z.object({
@@ -46,12 +46,8 @@ export const RuntimeNodeRefSchema = z.object({
46
46
  status: z.enum(['online', 'offline', 'revoked']),
47
47
  observedAt: RuntimeTimestampSchema,
48
48
  });
49
- export const RuntimeConnectionLocationSchema = z.enum(['local_device', 'agent_hq_cloud']);
50
- export const RuntimeConnectionTypeSchema = z.enum([
51
- 'managed_cloud',
52
- 'managed_local',
53
- 'external_local',
54
- ]);
49
+ export const RuntimeConnectionLocationSchema = z.enum(['local_device']);
50
+ export const RuntimeConnectionTypeSchema = z.enum(['managed_local', 'external_local']);
55
51
  export const RuntimeConnectionStatusSchema = z.enum([
56
52
  'connected',
57
53
  'degraded',
@@ -127,13 +123,8 @@ export const RuntimeConnectionSchema = z
127
123
  })
128
124
  .strict()
129
125
  .superRefine((connection, context) => {
130
- const local = connection.connectionType !== 'managed_cloud';
131
- if (local !== (connection.runtimeNodeRefId !== undefined)) {
132
- context.addIssue({ code: 'custom', message: 'Only local connections require a RuntimeNode' });
133
- }
134
- const expectedLocation = local ? 'local_device' : 'agent_hq_cloud';
135
- if (connection.location !== expectedLocation) {
136
- context.addIssue({ code: 'custom', message: 'Connection type and location must agree' });
126
+ if (connection.runtimeNodeRefId === undefined) {
127
+ context.addIssue({ code: 'custom', message: 'A connection requires a RuntimeNode' });
137
128
  }
138
129
  const unavailable = ['unavailable', 'disconnected', 'expired', 'revoked'].includes(connection.status);
139
130
  if (unavailable !== (connection.health === 'unavailable')) {
@@ -0,0 +1,47 @@
1
+ import { z } from 'zod';
2
+ import { IdentifierSchemas } from '@adea-ai/contracts';
3
+ export declare const PiDurableApprovalEffectDigestSchema: z.ZodString;
4
+ export declare const PiDurableApprovalDecisionIdSchema: z.ZodString;
5
+ export declare const PiDurableApprovalAnswerSchema: z.ZodObject<{
6
+ dispatchId: z.ZodString;
7
+ approvalId: typeof IdentifierSchemas.interactionId;
8
+ effectDigest: z.ZodString;
9
+ decision: z.ZodEnum<{
10
+ approve: "approve";
11
+ deny: "deny";
12
+ }>;
13
+ decisionId: z.ZodString;
14
+ }, z.core.$strict>;
15
+ export declare const PiDurableApprovalAttestationSchema: z.ZodObject<{
16
+ decidedBy: z.ZodString;
17
+ senderKeyId: z.ZodString;
18
+ keyringRevision: z.ZodNumber;
19
+ }, z.core.$strict>;
20
+ export declare const PiDurableApprovalDecisionSchema: z.ZodObject<{
21
+ decidedBy: z.ZodString;
22
+ senderKeyId: z.ZodString;
23
+ keyringRevision: z.ZodNumber;
24
+ schemaVersion: z.ZodLiteral<"pi-lead-approval-decision/v1">;
25
+ workspaceId: typeof IdentifierSchemas.workspaceId;
26
+ dispatchId: z.ZodString;
27
+ executionId: typeof IdentifierSchemas.executionId;
28
+ attemptId: typeof IdentifierSchemas.attemptId;
29
+ approvalId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"interaction ID">, string>>;
30
+ effectDigest: z.ZodString;
31
+ decision: z.ZodEnum<{
32
+ approve: "approve";
33
+ deny: "deny";
34
+ }>;
35
+ decisionId: z.ZodString;
36
+ decidedAt: z.ZodISODateTime;
37
+ deadlineAt: z.ZodISODateTime;
38
+ }, z.core.$strict>;
39
+ export type PiDurableApprovalAnswer = z.output<typeof PiDurableApprovalAnswerSchema>;
40
+ export type PiDurableApprovalAttestation = z.output<typeof PiDurableApprovalAttestationSchema>;
41
+ export type PiDurableApprovalDecision = z.output<typeof PiDurableApprovalDecisionSchema>;
42
+ export interface PiDurableApprovalDecisionAuthority {
43
+ readonly principalId: string;
44
+ authorize(decision: PiDurableApprovalDecision): Promise<boolean>;
45
+ publish?(decision: PiDurableApprovalDecision): Promise<void>;
46
+ }
47
+ export declare function samePiDurableApprovalDecision(left: PiDurableApprovalDecision, right: PiDurableApprovalDecision): boolean;
@@ -0,0 +1,40 @@
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}$/);
4
+ export const PiDurableApprovalDecisionIdSchema = z.string().regex(/^pi-decision:[a-f0-9]{32}$/);
5
+ const Reference = z
6
+ .string()
7
+ .min(1)
8
+ .max(256)
9
+ .regex(/^[A-Za-z0-9._:-]+$/);
10
+ export const PiDurableApprovalAnswerSchema = z.strictObject({
11
+ dispatchId: z.string().regex(/^dispatch_[a-f0-9]{32}$/),
12
+ approvalId: IdentifierSchemas.interactionId,
13
+ effectDigest: PiDurableApprovalEffectDigestSchema,
14
+ decision: z.enum(['approve', 'deny']),
15
+ decisionId: PiDurableApprovalDecisionIdSchema,
16
+ });
17
+ export const PiDurableApprovalAttestationSchema = z.strictObject({
18
+ decidedBy: Reference,
19
+ senderKeyId: Reference,
20
+ keyringRevision: z.number().int().min(1),
21
+ });
22
+ export const PiDurableApprovalDecisionSchema = z.strictObject({
23
+ schemaVersion: z.literal('pi-lead-approval-decision/v1'),
24
+ workspaceId: IdentifierSchemas.workspaceId,
25
+ dispatchId: PiDurableApprovalAnswerSchema.shape.dispatchId,
26
+ executionId: IdentifierSchemas.executionId,
27
+ attemptId: IdentifierSchemas.attemptId,
28
+ approvalId: PiDurableApprovalAnswerSchema.shape.approvalId,
29
+ effectDigest: PiDurableApprovalEffectDigestSchema,
30
+ decision: PiDurableApprovalAnswerSchema.shape.decision,
31
+ decisionId: PiDurableApprovalDecisionIdSchema,
32
+ ...PiDurableApprovalAttestationSchema.shape,
33
+ decidedAt: z.iso.datetime(),
34
+ deadlineAt: z.iso.datetime(),
35
+ });
36
+ export function samePiDurableApprovalDecision(left, right) {
37
+ const { decidedAt: _left, ...a } = left;
38
+ const { decidedAt: _right, ...b } = right;
39
+ return canonicalJsonStringify(a) === canonicalJsonStringify(b);
40
+ }
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { PiDurableQuestionAnswersSchema, PiDurableQuestionRequestIdSchema } from './pi-durable-questions.js';
3
+ import { PiDurableApprovalAnswerSchema, PiDurableApprovalAttestationSchema } from './pi-durable-approvals.js';
3
4
  import { IdentifierSchemas, ModelSelectionRefSchema } from '@adea-ai/contracts';
4
5
  import { RuntimeExecutionProgressSchema, RuntimeExecutionStatusSchema, RuntimeExecutionStateSchema, RuntimeObservedGenerationSchema } from './adapter.js';
5
6
  declare const IntentId: z.ZodUUID;
@@ -159,6 +160,7 @@ export declare const PiDurableLeadProgressRequestSchema: z.ZodObject<{
159
160
  export declare const PI_DURABLE_LEAD_EVENTS_CONTRACT_VERSION = 1;
160
161
  export declare const PI_DURABLE_LEAD_EVENTS_MAX_PAGE = 256;
161
162
  export declare const PI_DURABLE_LEAD_EVENTS_MAX_WAIT_MS = 8000;
163
+ export declare const PiDurableSessionIdSchema: z.ZodString;
162
164
  export declare const PiDurableLeadEventsRequestSchema: z.ZodObject<{
163
165
  contractVersion: z.ZodObject<{
164
166
  major: z.ZodNumber;
@@ -182,7 +184,7 @@ export declare const PiDurableLeadEventsRequestSchema: z.ZodObject<{
182
184
  export declare const PiDurableLeadTurnEventSchema: z.ZodObject<{
183
185
  schemaVersion: z.ZodLiteral<1>;
184
186
  eventId: z.ZodString;
185
- runtimeSessionId: z.ZodString;
187
+ runtimeSessionId: typeof PiDurableSessionIdSchema;
186
188
  harnessRunId: z.ZodString;
187
189
  generation: z.ZodLiteral<1>;
188
190
  seq: z.ZodString;
@@ -229,6 +231,44 @@ export declare const PiDurableLeadChildrenRequestSchema: z.ZodObject<{
229
231
  limit: z.ZodOptional<z.ZodNumber>;
230
232
  }, z.core.$strict>;
231
233
  }, z.core.$strict>;
234
+ export declare const PI_DURABLE_SESSIONS_MAX_PAGE = 256;
235
+ export declare const PiDurableSessionsRequestSchema: z.ZodObject<{
236
+ contractVersion: z.ZodObject<{
237
+ major: z.ZodNumber;
238
+ minor: z.ZodNumber;
239
+ }, z.core.$strict>;
240
+ requestId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"request ID">, string>>;
241
+ workspaceId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"workspace ID">, string>>;
242
+ projectId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"project ID">, string>>>;
243
+ requestedAt: z.ZodISODateTime;
244
+ caller: typeof Caller;
245
+ correlation: typeof Correlation;
246
+ operation: z.ZodLiteral<"pi-durable.lead.sessions">;
247
+ parameters: z.ZodObject<{
248
+ runtimeSessionId: z.ZodOptional<typeof PiDurableSessionIdSchema>;
249
+ after: z.ZodOptional<typeof PiDurableSessionIdSchema>;
250
+ limit: z.ZodOptional<z.ZodNumber>;
251
+ }, z.core.$strict>;
252
+ }, z.core.$strict>;
253
+ export declare const PiDurableSessionEventsRequestSchema: z.ZodObject<{
254
+ contractVersion: z.ZodObject<{
255
+ major: z.ZodNumber;
256
+ minor: z.ZodNumber;
257
+ }, z.core.$strict>;
258
+ requestId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"request ID">, string>>;
259
+ workspaceId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"workspace ID">, string>>;
260
+ projectId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"project ID">, string>>>;
261
+ requestedAt: z.ZodISODateTime;
262
+ caller: typeof Caller;
263
+ correlation: typeof Correlation;
264
+ operation: z.ZodLiteral<"pi-durable.lead.session-events">;
265
+ parameters: z.ZodObject<{
266
+ runtimeSessionId: typeof PiDurableSessionIdSchema;
267
+ afterSeq: z.ZodNumber;
268
+ waitMs: z.ZodNumber;
269
+ limit: z.ZodOptional<z.ZodNumber>;
270
+ }, z.core.$strict>;
271
+ }, z.core.$strict>;
232
272
  export declare const PiDurableLeadChildTargetRequestSchema: z.ZodObject<{
233
273
  contractVersion: z.ZodObject<{
234
274
  major: z.ZodNumber;
@@ -286,6 +326,23 @@ export declare const PiDurableLeadQuestionAnswerRequestSchema: z.ZodObject<{
286
326
  answers: typeof PiDurableQuestionAnswersSchema;
287
327
  }, z.core.$strict>;
288
328
  }, z.core.$strict>;
329
+ export declare const PiDurableLeadApprovalAnswerRequestSchema: z.ZodObject<{
330
+ contractVersion: z.ZodObject<{
331
+ major: z.ZodNumber;
332
+ minor: z.ZodNumber;
333
+ }, z.core.$strict>;
334
+ requestId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"request ID">, string>>;
335
+ workspaceId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"workspace ID">, string>>;
336
+ projectId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"project ID">, string>>>;
337
+ commandId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"command ID">, string>>;
338
+ idempotencyKey: z.ZodString;
339
+ payloadHash: z.ZodString;
340
+ issuedAt: z.ZodISODateTime;
341
+ caller: typeof Caller;
342
+ correlation: typeof Correlation;
343
+ operation: z.ZodLiteral<"pi-durable.lead.approval-answer">;
344
+ payload: z.ZodObject<typeof PiDurableApprovalAnswerSchema.shape & typeof PiDurableApprovalAttestationSchema.shape, z.core.$strict>;
345
+ }, z.core.$strict>;
289
346
  export declare const PiDurableLeadChildCancelRequestSchema: z.ZodObject<{
290
347
  contractVersion: z.ZodObject<{
291
348
  major: z.ZodNumber;
@@ -560,6 +617,42 @@ export declare const PiDurableLeadQuestionAnswerResponseSchema: z.ZodObject<{
560
617
  status: typeof RuntimeExecutionStatusSchema;
561
618
  }, z.core.$strict>;
562
619
  }, z.core.$strict>;
620
+ export declare const PiDurableLeadApprovalAnswerResponseSchema: z.ZodObject<{
621
+ contractVersion: z.ZodObject<{
622
+ major: z.ZodNumber;
623
+ minor: z.ZodNumber;
624
+ }, z.core.$strict>;
625
+ requestId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"request ID">, string>>;
626
+ correlation: z.ZodObject<{
627
+ traceId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"trace ID">, string>>;
628
+ causationCommandId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"command ID">, string>>>;
629
+ parentEventId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"event ID">, string>>>;
630
+ }, z.core.$strict>;
631
+ data: z.ZodObject<{
632
+ schemaVersion: z.ZodLiteral<"pi-lead-dispatch/v1">;
633
+ dispatchId: typeof DispatchId;
634
+ intentId: typeof IntentId;
635
+ executionId: typeof IdentifierSchemas.executionId;
636
+ attemptId: typeof IdentifierSchemas.attemptId;
637
+ runtimeSessionId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"external-session ID">, string>>;
638
+ requestedTarget: z.ZodOptional<typeof PiDurableLeadRequestedTargetSchema>;
639
+ observedTarget: z.ZodOptional<typeof PiDurableLeadObservedTargetSchema>;
640
+ approvalSchemaVersion: z.ZodLiteral<"pi-lead-approval-answer/v1">;
641
+ approvalId: typeof IdentifierSchemas.interactionId;
642
+ decisionId: z.ZodString;
643
+ requestEventId: z.ZodString;
644
+ decision: z.ZodEnum<{
645
+ approve: "approve";
646
+ deny: "deny";
647
+ }>;
648
+ outcome: z.ZodEnum<{
649
+ already_decided: "already_decided";
650
+ decided: "decided";
651
+ }>;
652
+ state: typeof RuntimeExecutionStateSchema;
653
+ status: typeof RuntimeExecutionStatusSchema;
654
+ }, z.core.$strict>;
655
+ }, z.core.$strict>;
563
656
  export declare const PiDurableLeadEventsResponseSchema: z.ZodObject<{
564
657
  contractVersion: z.ZodObject<{
565
658
  major: z.ZodNumber;
@@ -573,6 +666,56 @@ export declare const PiDurableLeadEventsResponseSchema: z.ZodObject<{
573
666
  }, z.core.$strict>;
574
667
  data: typeof PiDurableLeadEventsDataSchema;
575
668
  }, z.core.$strict>;
669
+ export declare const PiDurableSessionSchema: z.ZodObject<{
670
+ runtimeSessionId: typeof PiDurableSessionIdSchema;
671
+ role: z.ZodEnum<{
672
+ child: "child";
673
+ lead: "lead";
674
+ }>;
675
+ dispatchId: typeof DispatchId;
676
+ intentId: typeof IntentId;
677
+ delegationId: z.ZodOptional<typeof IdentifierSchemas.delegationId>;
678
+ executionId: typeof IdentifierSchemas.executionId;
679
+ attemptId: typeof IdentifierSchemas.attemptId;
680
+ state: typeof RuntimeExecutionStateSchema;
681
+ startedAt: z.ZodISODateTime;
682
+ updatedAt: z.ZodISODateTime;
683
+ }, z.core.$strict>;
684
+ export declare const PiDurableSessionsResponseSchema: z.ZodObject<{
685
+ contractVersion: z.ZodObject<{
686
+ major: z.ZodNumber;
687
+ minor: z.ZodNumber;
688
+ }, z.core.$strict>;
689
+ requestId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"request ID">, string>>;
690
+ correlation: z.ZodObject<{
691
+ traceId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"trace ID">, string>>;
692
+ causationCommandId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"command ID">, string>>>;
693
+ parentEventId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"event ID">, string>>>;
694
+ }, z.core.$strict>;
695
+ data: z.ZodObject<{
696
+ sessions: z.ZodArray<typeof PiDurableSessionSchema>;
697
+ next: z.ZodOptional<typeof PiDurableSessionIdSchema>;
698
+ }, z.core.$strict>;
699
+ }, z.core.$strict>;
700
+ export declare const PiDurableSessionEventsResponseSchema: z.ZodObject<{
701
+ contractVersion: z.ZodObject<{
702
+ major: z.ZodNumber;
703
+ minor: z.ZodNumber;
704
+ }, z.core.$strict>;
705
+ requestId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"request ID">, string>>;
706
+ correlation: z.ZodObject<{
707
+ traceId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"trace ID">, string>>;
708
+ causationCommandId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"command ID">, string>>>;
709
+ parentEventId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"event ID">, string>>>;
710
+ }, z.core.$strict>;
711
+ data: z.ZodObject<{
712
+ contractVersion: z.ZodLiteral<1>;
713
+ runtimeSessionId: typeof PiDurableSessionIdSchema;
714
+ events: z.ZodArray<typeof PiDurableLeadTurnEventSchema>;
715
+ nextSeq: z.ZodNumber;
716
+ complete: z.ZodBoolean;
717
+ }, z.core.$strict>;
718
+ }, z.core.$strict>;
576
719
  declare const ChildReference: z.ZodString;
577
720
  export declare const PiDurableLeadChildOutcomeSchema: z.ZodObject<{
578
721
  state: z.ZodEnum<{
@@ -598,6 +741,7 @@ export declare const PiDurableLeadChildSchema: z.ZodObject<{
598
741
  delegationId: typeof IdentifierSchemas.delegationId;
599
742
  childExecutionId: typeof IdentifierSchemas.executionId;
600
743
  childAttemptId: z.ZodOptional<typeof IdentifierSchemas.attemptId>;
744
+ runtimeSessionId: z.ZodOptional<typeof IdentifierSchemas.externalSessionId>;
601
745
  role: typeof ChildReference;
602
746
  state: z.ZodEnum<{
603
747
  awaiting_input: "awaiting_input";
@@ -810,6 +954,20 @@ export declare const PiDurableLeadHttpContract: Readonly<{
810
954
  requestSchema: typeof PiDurableLeadChildTargetRequestSchema;
811
955
  responseSchema: typeof PiDurableLeadChildTargetResponseSchema;
812
956
  }>;
957
+ sessions: Readonly<{
958
+ route: "sessions";
959
+ operation: "pi-durable.lead.sessions";
960
+ scope: "execution:read";
961
+ requestSchema: typeof PiDurableSessionsRequestSchema;
962
+ responseSchema: typeof PiDurableSessionsResponseSchema;
963
+ }>;
964
+ sessionEvents: Readonly<{
965
+ route: "session-events";
966
+ operation: "pi-durable.lead.session-events";
967
+ scope: "execution:read";
968
+ requestSchema: typeof PiDurableSessionEventsRequestSchema;
969
+ responseSchema: typeof PiDurableSessionEventsResponseSchema;
970
+ }>;
813
971
  cancel: Readonly<{
814
972
  route: "cancel";
815
973
  operation: "pi-durable.lead.cancel";
@@ -824,6 +982,13 @@ export declare const PiDurableLeadHttpContract: Readonly<{
824
982
  requestSchema: typeof PiDurableLeadQuestionAnswerRequestSchema;
825
983
  responseSchema: typeof PiDurableLeadQuestionAnswerResponseSchema;
826
984
  }>;
985
+ approvalAnswer: Readonly<{
986
+ route: "approvals/answer";
987
+ operation: "pi-durable.lead.approval-answer";
988
+ scope: "execution:write";
989
+ requestSchema: typeof PiDurableLeadApprovalAnswerRequestSchema;
990
+ responseSchema: typeof PiDurableLeadApprovalAnswerResponseSchema;
991
+ }>;
827
992
  childCancel: Readonly<{
828
993
  route: "child-cancel";
829
994
  operation: "pi-durable.lead.child-cancel";
@@ -848,12 +1013,19 @@ export type PiDurableLeadEventsRequest = z.output<typeof PiDurableLeadEventsRequ
848
1013
  export type PiDurableLeadEventsResponse = z.output<typeof PiDurableLeadEventsResponseSchema>;
849
1014
  export type PiDurableLeadTurnEvent = z.output<typeof PiDurableLeadTurnEventSchema>;
850
1015
  export type PiDurableLeadChildrenRequest = z.output<typeof PiDurableLeadChildrenRequestSchema>;
1016
+ export type PiDurableSession = z.output<typeof PiDurableSessionSchema>;
1017
+ export type PiDurableSessionsRequest = z.output<typeof PiDurableSessionsRequestSchema>;
1018
+ export type PiDurableSessionsResponse = z.output<typeof PiDurableSessionsResponseSchema>;
1019
+ export type PiDurableSessionEventsRequest = z.output<typeof PiDurableSessionEventsRequestSchema>;
1020
+ export type PiDurableSessionEventsResponse = z.output<typeof PiDurableSessionEventsResponseSchema>;
851
1021
  export type PiDurableLeadChildrenResponse = z.output<typeof PiDurableLeadChildrenResponseSchema>;
852
1022
  export type PiDurableLeadChild = z.output<typeof PiDurableLeadChildSchema>;
853
1023
  export type PiDurableLeadCancelRequest = z.output<typeof PiDurableLeadCancelRequestSchema>;
854
1024
  export type PiDurableLeadCancelResponse = z.output<typeof PiDurableLeadCancelResponseSchema>;
855
1025
  export type PiDurableLeadQuestionAnswerRequest = z.output<typeof PiDurableLeadQuestionAnswerRequestSchema>;
856
1026
  export type PiDurableLeadQuestionAnswerResponse = z.output<typeof PiDurableLeadQuestionAnswerResponseSchema>;
1027
+ export type PiDurableLeadApprovalAnswerRequest = z.output<typeof PiDurableLeadApprovalAnswerRequestSchema>;
1028
+ export type PiDurableLeadApprovalAnswerResponse = z.output<typeof PiDurableLeadApprovalAnswerResponseSchema>;
857
1029
  export type PiDurableLeadChildCancelRequest = z.output<typeof PiDurableLeadChildCancelRequestSchema>;
858
1030
  export type PiDurableLeadChildCancelResponse = z.output<typeof PiDurableLeadChildCancelResponseSchema>;
859
1031
  export type PiDurableLeadChildTargetRequest = z.output<typeof PiDurableLeadChildTargetRequestSchema>;
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { PiDurableQuestionAnswersSchema, PiDurableQuestionRequestIdSchema, } from './pi-durable-questions.js';
3
+ import { PiDurableApprovalAnswerSchema, PiDurableApprovalAttestationSchema, PiDurableApprovalDecisionIdSchema, } from './pi-durable-approvals.js';
3
4
  import { ContractVersionSchema, IdentifierSchemas, ModelSelectionFundingViewSchema, ModelSelectionRefSchema, PublicContractManifest, ReadRequestEnvelopeSchema, StateChangingCommandEnvelopeSchema, SuccessResponseEnvelopeSchema, negotiateContractVersion, } from '@adea-ai/contracts';
4
5
  import { RuntimeExecutionHandleSchema, RuntimeExecutionProgressSchema, RuntimeExecutionStatusSchema, RuntimeExecutionStateSchema, RuntimeObservedGenerationSchema, } from './adapter.js';
5
6
  const IntentId = z.uuid();
@@ -29,32 +30,34 @@ export const PiDurableLeadObservedTargetSchema = z
29
30
  generation: RuntimeObservedGenerationSchema.optional(),
30
31
  })
31
32
  .readonly();
33
+ function contractIncludes(negotiated, introduced) {
34
+ return (negotiated.major > introduced.major ||
35
+ (negotiated.major === introduced.major && negotiated.minor >= introduced.minor));
36
+ }
32
37
  export const PI_DURABLE_OBSERVED_GENERATION_CONTRACT_VERSION = { major: 3, minor: 1 };
33
38
  export function supportsPiDurableObservedGeneration(consumerVersion) {
34
39
  const consumer = ContractVersionSchema.safeParse(consumerVersion);
35
40
  if (!consumer.success)
36
41
  return false;
37
- const negotiated = negotiateContractVersion([PublicContractManifest.current], [consumer.data]);
38
- if (negotiated === undefined)
39
- return false;
40
- return (negotiated.major === PI_DURABLE_OBSERVED_GENERATION_CONTRACT_VERSION.major &&
41
- negotiated.minor >= PI_DURABLE_OBSERVED_GENERATION_CONTRACT_VERSION.minor);
42
+ const negotiated = negotiateContractVersion(PublicContractManifest.supported, [consumer.data]);
43
+ return (negotiated !== undefined &&
44
+ contractIncludes(negotiated, PI_DURABLE_OBSERVED_GENERATION_CONTRACT_VERSION));
42
45
  }
43
46
  export const PI_DURABLE_REMOTE_SESSION_REFERENCE_CONTRACT_VERSION = { major: 3, minor: 2 };
44
47
  export function supportsPiDurableRemoteSessionReference(consumerVersion) {
45
48
  const consumer = ContractVersionSchema.safeParse(consumerVersion);
46
49
  if (!consumer.success)
47
50
  return false;
48
- const negotiated = negotiateContractVersion([PublicContractManifest.current], [consumer.data]);
49
- return (negotiated?.major === PI_DURABLE_REMOTE_SESSION_REFERENCE_CONTRACT_VERSION.major &&
50
- negotiated.minor >= PI_DURABLE_REMOTE_SESSION_REFERENCE_CONTRACT_VERSION.minor);
51
+ const negotiated = negotiateContractVersion(PublicContractManifest.supported, [consumer.data]);
52
+ return (negotiated !== undefined &&
53
+ contractIncludes(negotiated, PI_DURABLE_REMOTE_SESSION_REFERENCE_CONTRACT_VERSION));
51
54
  }
52
55
  export function supportsPiDurableRemoteOwnerObservation(consumerVersion) {
53
56
  const consumer = ContractVersionSchema.safeParse(consumerVersion);
54
57
  if (!consumer.success)
55
58
  return false;
56
- const negotiated = negotiateContractVersion([PublicContractManifest.current], [consumer.data]);
57
- return negotiated?.major === 3 && negotiated.minor >= 3;
59
+ const negotiated = negotiateContractVersion(PublicContractManifest.supported, [consumer.data]);
60
+ return negotiated !== undefined && contractIncludes(negotiated, { major: 3, minor: 3 });
58
61
  }
59
62
  function fenceForeignGeneration(receipt, context) {
60
63
  const foreign = (generation) => generation !== undefined && generation.attemptId !== receipt.attemptId;
@@ -106,6 +109,9 @@ export const PI_DURABLE_LEAD_EVENTS_CONTRACT_VERSION = 1;
106
109
  export const PI_DURABLE_LEAD_EVENTS_MAX_PAGE = 256;
107
110
  export const PI_DURABLE_LEAD_EVENTS_MAX_WAIT_MS = 8000;
108
111
  const LeadEventSeq = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
112
+ export const PiDurableSessionIdSchema = z
113
+ .string()
114
+ .regex(/^(?:pi-lead:dispatch_[a-f0-9]{32}|ses_[0-9A-HJKMNP-TV-Z]{26})$/);
109
115
  export const PiDurableLeadEventsRequestSchema = PiDurableLeadReadEnvelopeSchema.extend({
110
116
  operation: z.literal('pi-durable.lead.events'),
111
117
  parameters: z
@@ -126,7 +132,7 @@ export const PiDurableLeadTurnEventSchema = z
126
132
  .object({
127
133
  schemaVersion: z.literal(1),
128
134
  eventId: z.string().min(1).max(256),
129
- runtimeSessionId: z.string().regex(/^pi-lead:dispatch_[a-f0-9]{32}$/),
135
+ runtimeSessionId: PiDurableSessionIdSchema,
130
136
  harnessRunId: z.string().min(1).max(256),
131
137
  generation: z.literal(1),
132
138
  seq: z.string().regex(/^[1-9]\d*$/),
@@ -180,6 +186,28 @@ export const PiDurableLeadChildrenRequestSchema = PiDurableLeadReadEnvelopeSchem
180
186
  })
181
187
  .strict(),
182
188
  });
189
+ export const PI_DURABLE_SESSIONS_MAX_PAGE = 256;
190
+ export const PiDurableSessionsRequestSchema = PiDurableLeadReadEnvelopeSchema.extend({
191
+ operation: z.literal('pi-durable.lead.sessions'),
192
+ parameters: z
193
+ .object({
194
+ runtimeSessionId: PiDurableSessionIdSchema.optional(),
195
+ after: PiDurableSessionIdSchema.optional(),
196
+ limit: z.number().int().min(1).max(PI_DURABLE_SESSIONS_MAX_PAGE).optional(),
197
+ })
198
+ .strict(),
199
+ });
200
+ export const PiDurableSessionEventsRequestSchema = PiDurableLeadReadEnvelopeSchema.extend({
201
+ operation: z.literal('pi-durable.lead.session-events'),
202
+ parameters: z
203
+ .object({
204
+ runtimeSessionId: PiDurableSessionIdSchema,
205
+ afterSeq: LeadEventSeq,
206
+ waitMs: z.number().int().min(0).max(PI_DURABLE_LEAD_EVENTS_MAX_WAIT_MS),
207
+ limit: z.number().int().min(1).max(PI_DURABLE_LEAD_EVENTS_MAX_PAGE).optional(),
208
+ })
209
+ .strict(),
210
+ });
183
211
  export const PiDurableLeadChildTargetRequestSchema = PiDurableLeadReadEnvelopeSchema.extend({
184
212
  operation: z.literal('pi-durable.lead.child-target'),
185
213
  parameters: z
@@ -203,6 +231,10 @@ export const PiDurableLeadQuestionAnswerRequestSchema = PiDurableLeadCommandEnve
203
231
  })
204
232
  .strict(),
205
233
  });
234
+ export const PiDurableLeadApprovalAnswerRequestSchema = PiDurableLeadCommandEnvelopeSchema.extend({
235
+ operation: z.literal('pi-durable.lead.approval-answer'),
236
+ payload: PiDurableApprovalAnswerSchema.extend(PiDurableApprovalAttestationSchema.shape),
237
+ });
206
238
  export const PiDurableLeadChildCancelRequestSchema = PiDurableLeadCommandEnvelopeSchema.extend({
207
239
  operation: z.literal('pi-durable.lead.child-cancel'),
208
240
  payload: z
@@ -340,9 +372,96 @@ export const PiDurableLeadQuestionAnswerResponseSchema = response.extend({
340
372
  status: RuntimeExecutionStatusSchema,
341
373
  }),
342
374
  });
375
+ export const PiDurableLeadApprovalAnswerResponseSchema = response.extend({
376
+ data: PiDurableLeadReceiptResponseSchema.extend({
377
+ approvalSchemaVersion: z.literal('pi-lead-approval-answer/v1'),
378
+ approvalId: IdentifierSchemas.interactionId,
379
+ decisionId: PiDurableApprovalDecisionIdSchema,
380
+ requestEventId: z.string().min(1).max(256),
381
+ decision: z.enum(['approve', 'deny']),
382
+ outcome: z.enum(['decided', 'already_decided']),
383
+ state: RuntimeExecutionStateSchema,
384
+ status: RuntimeExecutionStatusSchema,
385
+ }),
386
+ });
343
387
  export const PiDurableLeadEventsResponseSchema = response.extend({
344
388
  data: PiDurableLeadEventsDataSchema,
345
389
  });
390
+ export const PiDurableSessionSchema = z
391
+ .object({
392
+ runtimeSessionId: PiDurableSessionIdSchema,
393
+ role: z.enum(['lead', 'child']),
394
+ dispatchId: DispatchId,
395
+ intentId: IntentId,
396
+ delegationId: IdentifierSchemas.delegationId.optional(),
397
+ executionId: IdentifierSchemas.executionId,
398
+ attemptId: IdentifierSchemas.attemptId,
399
+ state: RuntimeExecutionStateSchema,
400
+ startedAt: z.iso.datetime(),
401
+ updatedAt: z.iso.datetime(),
402
+ })
403
+ .strict()
404
+ .superRefine((value, context) => {
405
+ const lead = value.runtimeSessionId === `pi-lead:${value.dispatchId}`;
406
+ if ((value.role === 'lead') !== lead ||
407
+ (value.role === 'lead') !== (value.delegationId === undefined))
408
+ context.addIssue({
409
+ code: 'custom',
410
+ message: 'A lead session is its dispatch; a child session names its delegation',
411
+ });
412
+ });
413
+ export const PiDurableSessionsResponseSchema = response.extend({
414
+ data: z
415
+ .object({
416
+ sessions: z.array(PiDurableSessionSchema).max(PI_DURABLE_SESSIONS_MAX_PAGE),
417
+ next: PiDurableSessionIdSchema.optional(),
418
+ })
419
+ .strict()
420
+ .superRefine((value, context) => {
421
+ value.sessions.forEach((session, index) => {
422
+ const previous = value.sessions[index - 1];
423
+ if (previous && previous.runtimeSessionId >= session.runtimeSessionId)
424
+ context.addIssue({
425
+ code: 'custom',
426
+ path: ['sessions', index],
427
+ message: 'Sessions are unique and sorted by runtimeSessionId',
428
+ });
429
+ });
430
+ if (value.next !== undefined && value.next !== value.sessions.at(-1)?.runtimeSessionId)
431
+ context.addIssue({ code: 'custom', path: ['next'], message: 'next is the last session' });
432
+ }),
433
+ });
434
+ export const PiDurableSessionEventsResponseSchema = response.extend({
435
+ data: z
436
+ .object({
437
+ contractVersion: z.literal(PI_DURABLE_LEAD_EVENTS_CONTRACT_VERSION),
438
+ runtimeSessionId: PiDurableSessionIdSchema,
439
+ events: z
440
+ .array(PiDurableLeadTurnEventSchema)
441
+ .max(PI_DURABLE_LEAD_EVENTS_MAX_PAGE),
442
+ nextSeq: LeadEventSeq,
443
+ complete: z.boolean(),
444
+ })
445
+ .strict()
446
+ .superRefine((value, context) => {
447
+ const first = value.nextSeq - value.events.length + 1;
448
+ value.events.forEach((event, index) => {
449
+ if (event.seq !== String(first + index) ||
450
+ event.runtimeSessionId !== value.runtimeSessionId)
451
+ context.addIssue({
452
+ code: 'custom',
453
+ path: ['events', index],
454
+ message: 'Events must be the contiguous seqs of this session ending at nextSeq',
455
+ });
456
+ });
457
+ if (first < 1)
458
+ context.addIssue({
459
+ code: 'custom',
460
+ path: ['nextSeq'],
461
+ message: 'nextSeq precedes the page',
462
+ });
463
+ }),
464
+ });
346
465
  const ChildReference = z
347
466
  .string()
348
467
  .trim()
@@ -367,6 +486,7 @@ export const PiDurableLeadChildSchema = z
367
486
  delegationId: IdentifierSchemas.delegationId,
368
487
  childExecutionId: IdentifierSchemas.executionId,
369
488
  childAttemptId: IdentifierSchemas.attemptId.optional(),
489
+ runtimeSessionId: IdentifierSchemas.externalSessionId.optional(),
370
490
  role: ChildReference,
371
491
  state: z.enum([
372
492
  'requested',
@@ -566,6 +686,20 @@ export const PiDurableLeadHttpContract = Object.freeze({
566
686
  requestSchema: PiDurableLeadChildTargetRequestSchema,
567
687
  responseSchema: PiDurableLeadChildTargetResponseSchema,
568
688
  }),
689
+ sessions: Object.freeze({
690
+ route: 'sessions',
691
+ operation: 'pi-durable.lead.sessions',
692
+ scope: 'execution:read',
693
+ requestSchema: PiDurableSessionsRequestSchema,
694
+ responseSchema: PiDurableSessionsResponseSchema,
695
+ }),
696
+ sessionEvents: Object.freeze({
697
+ route: 'session-events',
698
+ operation: 'pi-durable.lead.session-events',
699
+ scope: 'execution:read',
700
+ requestSchema: PiDurableSessionEventsRequestSchema,
701
+ responseSchema: PiDurableSessionEventsResponseSchema,
702
+ }),
569
703
  cancel: Object.freeze({
570
704
  route: 'cancel',
571
705
  operation: 'pi-durable.lead.cancel',
@@ -580,6 +714,13 @@ export const PiDurableLeadHttpContract = Object.freeze({
580
714
  requestSchema: PiDurableLeadQuestionAnswerRequestSchema,
581
715
  responseSchema: PiDurableLeadQuestionAnswerResponseSchema,
582
716
  }),
717
+ approvalAnswer: Object.freeze({
718
+ route: 'approvals/answer',
719
+ operation: 'pi-durable.lead.approval-answer',
720
+ scope: 'execution:write',
721
+ requestSchema: PiDurableLeadApprovalAnswerRequestSchema,
722
+ responseSchema: PiDurableLeadApprovalAnswerResponseSchema,
723
+ }),
583
724
  childCancel: Object.freeze({
584
725
  route: 'child-cancel',
585
726
  operation: 'pi-durable.lead.child-cancel',
@@ -5,13 +5,11 @@ export declare const RuntimeConnectionRegistrationSchema: z.ZodObject<{
5
5
  identityDigest: z.ZodString;
6
6
  connectionType: z.ZodEnum<{
7
7
  external_local: "external_local";
8
- managed_cloud: "managed_cloud";
9
8
  managed_local: "managed_local";
10
9
  }>;
11
10
  runtimeNodeRefId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"runtime-node reference ID">, string>>>;
12
11
  runtimeDefinitionId: z.ZodPipe<z.ZodString, z.ZodTransform<import("@adea-ai/contracts").OpaqueIdentifier<"runtime-definition ID">, string>>;
13
12
  location: z.ZodEnum<{
14
- agent_hq_cloud: "agent_hq_cloud";
15
13
  local_device: "local_device";
16
14
  }>;
17
15
  opaqueNativeRef: z.ZodOptional<z.ZodString>;
package/dist/sessions.js CHANGED
@@ -292,10 +292,7 @@ const ExternalSessionAssessmentContextSchema = z
292
292
  nodeStatus: RuntimeEligibilityNodeStatusSchema,
293
293
  evaluatedAt: RuntimeTimestampSchema,
294
294
  })
295
- .strict()
296
- .refine((context) => context.connection === undefined ||
297
- (context.connection.connectionType === 'managed_cloud') ===
298
- (context.nodeStatus === 'not_applicable'), 'Managed-cloud sessions must not invent RuntimeNode health');
295
+ .strict();
299
296
  export function assessExternalSession(sessionValue, contextValue) {
300
297
  const session = ExternalSessionSchema.parse(sessionValue);
301
298
  const context = ExternalSessionAssessmentContextSchema.parse(contextValue);
@@ -1,5 +1,5 @@
1
1
  import type { RuntimeAdapter, RuntimeAdapterInspection, RuntimeApprovalRequest, RuntimeCancelRequest, RuntimeExecutionHandle, RuntimeExecutionProgress, RuntimeExecutionStatus, RuntimeInputRequest, RuntimeProgressOptions, RuntimeSessionOperation, RuntimeSessionResult, RuntimeStartRequest } from './adapter.js';
2
- export type RuntimeTransportKind = 'direct-local' | 'remote-gateway';
2
+ export type RuntimeTransportKind = 'direct-local';
3
3
  export type RuntimeDriver = RuntimeAdapter;
4
4
  export interface RuntimeTransport extends RuntimeAdapter {
5
5
  readonly kind: RuntimeTransportKind;
@@ -34,7 +34,4 @@ export declare class TransportedRuntimeAdapter extends DelegatingRuntimeAdapter
34
34
  export declare class DirectLocalRuntimeTransport extends DelegatingRuntimeTransport {
35
35
  readonly kind: 'direct-local';
36
36
  }
37
- export declare class RemoteRuntimeGatewayTransport extends DelegatingRuntimeTransport {
38
- readonly kind: 'remote-gateway';
39
- }
40
37
  export {};
package/dist/transport.js CHANGED
@@ -61,6 +61,3 @@ export class TransportedRuntimeAdapter extends DelegatingRuntimeAdapter {
61
61
  export class DirectLocalRuntimeTransport extends DelegatingRuntimeTransport {
62
62
  kind = 'direct-local';
63
63
  }
64
- export class RemoteRuntimeGatewayTransport extends DelegatingRuntimeTransport {
65
- kind = 'remote-gateway';
66
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adea-ai/runtime-sdk",
3
- "version": "1.23.0",
3
+ "version": "2.0.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": "^3.0.0",
46
+ "@adea-ai/contracts": "^4.0.0",
47
47
  "zod": "4.6.6"
48
48
  },
49
49
  "engines": {