recoder-a2a-sdk 1.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.
Files changed (59) hide show
  1. package/dist/audit-helpers.d.mts +209 -0
  2. package/dist/audit-helpers.d.ts +209 -0
  3. package/dist/audit-helpers.js +905 -0
  4. package/dist/audit-helpers.js.map +1 -0
  5. package/dist/audit-helpers.mjs +34 -0
  6. package/dist/audit-helpers.mjs.map +1 -0
  7. package/dist/chunk-7GY5FFBI.mjs +117 -0
  8. package/dist/chunk-7GY5FFBI.mjs.map +1 -0
  9. package/dist/chunk-AGD6G5N6.mjs +141 -0
  10. package/dist/chunk-AGD6G5N6.mjs.map +1 -0
  11. package/dist/chunk-BWCRJDUB.mjs +357 -0
  12. package/dist/chunk-BWCRJDUB.mjs.map +1 -0
  13. package/dist/chunk-DPFH2JIC.mjs +141 -0
  14. package/dist/chunk-DPFH2JIC.mjs.map +1 -0
  15. package/dist/chunk-EP2GHC3R.mjs +116 -0
  16. package/dist/chunk-EP2GHC3R.mjs.map +1 -0
  17. package/dist/chunk-JOZQDX7A.mjs +359 -0
  18. package/dist/chunk-JOZQDX7A.mjs.map +1 -0
  19. package/dist/chunk-MAA7JZ2Q.mjs +142 -0
  20. package/dist/chunk-MAA7JZ2Q.mjs.map +1 -0
  21. package/dist/chunk-QVOOBAUA.mjs +140 -0
  22. package/dist/chunk-QVOOBAUA.mjs.map +1 -0
  23. package/dist/chunk-T5GUBIFZ.mjs +358 -0
  24. package/dist/chunk-T5GUBIFZ.mjs.map +1 -0
  25. package/dist/chunk-WLNW7Y2H.mjs +636 -0
  26. package/dist/chunk-WLNW7Y2H.mjs.map +1 -0
  27. package/dist/chunk-XSELW6DU.mjs +356 -0
  28. package/dist/chunk-XSELW6DU.mjs.map +1 -0
  29. package/dist/envelope-builders.d.mts +189 -0
  30. package/dist/envelope-builders.d.ts +189 -0
  31. package/dist/envelope-builders.js +652 -0
  32. package/dist/envelope-builders.js.map +1 -0
  33. package/dist/envelope-builders.mjs +20 -0
  34. package/dist/envelope-builders.mjs.map +1 -0
  35. package/dist/error-mapping.d.mts +132 -0
  36. package/dist/error-mapping.d.ts +132 -0
  37. package/dist/error-mapping.js +642 -0
  38. package/dist/error-mapping.js.map +1 -0
  39. package/dist/error-mapping.mjs +16 -0
  40. package/dist/error-mapping.mjs.map +1 -0
  41. package/dist/index.d.mts +7 -0
  42. package/dist/index.d.ts +7 -0
  43. package/dist/index.js +1798 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/index.mjs +153 -0
  46. package/dist/index.mjs.map +1 -0
  47. package/dist/state-mapping.d.mts +139 -0
  48. package/dist/state-mapping.d.ts +139 -0
  49. package/dist/state-mapping.js +641 -0
  50. package/dist/state-mapping.js.map +1 -0
  51. package/dist/state-mapping.mjs +28 -0
  52. package/dist/state-mapping.mjs.map +1 -0
  53. package/dist/validation.d.mts +117 -0
  54. package/dist/validation.d.ts +117 -0
  55. package/dist/validation.js +850 -0
  56. package/dist/validation.js.map +1 -0
  57. package/dist/validation.mjs +22 -0
  58. package/dist/validation.mjs.map +1 -0
  59. package/package.json +18 -0
@@ -0,0 +1,357 @@
1
+ import {
2
+ AUDIT_EVENT_TYPES,
3
+ AUDIT_EVENT_VERSION,
4
+ TASK_ENVELOPE_VERSION,
5
+ TASK_STATES,
6
+ isA2AErrorCode
7
+ } from "./chunk-WLNW7Y2H.mjs";
8
+
9
+ // src/validation.ts
10
+ function isRecord(value) {
11
+ return typeof value === "object" && value !== null && !Array.isArray(value);
12
+ }
13
+ function isNonEmptyString(value) {
14
+ return typeof value === "string" && value.trim().length > 0;
15
+ }
16
+ function isValidISODate(value) {
17
+ return typeof value === "string" && !Number.isNaN(Date.parse(value));
18
+ }
19
+ var VALID_PLATFORMS = /* @__PURE__ */ new Set([
20
+ "codex",
21
+ "claude_code",
22
+ "recoder_web",
23
+ "recoder_pm",
24
+ "recoder_agency",
25
+ "recoder_backend",
26
+ "recoder_desktop",
27
+ "custom"
28
+ ]);
29
+ var VALID_PROTOCOLS = /* @__PURE__ */ new Set(["a2a", "mcp", "jsonrpc", "rest", "file_git"]);
30
+ var VALID_TASK_STATES = new Set(TASK_STATES);
31
+ var VALID_AUDIT_EVENT_TYPES = new Set(AUDIT_EVENT_TYPES);
32
+ var VALID_ACTOR_KINDS = /* @__PURE__ */ new Set(["agent", "user", "system", "connector"]);
33
+ var VALID_TARGET_KINDS = /* @__PURE__ */ new Set([
34
+ "task",
35
+ "agent",
36
+ "connector",
37
+ "channel",
38
+ "thread",
39
+ "message",
40
+ "policy",
41
+ "workspace",
42
+ "system"
43
+ ]);
44
+ var VALID_SEVERITIES = /* @__PURE__ */ new Set(["low", "medium", "high", "critical"]);
45
+ var VALID_AUDIT_SEVERITIES = /* @__PURE__ */ new Set(["info", "warning", "error", "critical"]);
46
+ function validateAgentRef(value, path, issues) {
47
+ if (!isRecord(value)) {
48
+ issues.push({ path, message: "must be an object" });
49
+ return;
50
+ }
51
+ if (!isNonEmptyString(value.agent_id)) {
52
+ issues.push({ path: `${path}.agent_id`, message: "must be a non-empty string" });
53
+ }
54
+ if (!isNonEmptyString(value.platform) || !VALID_PLATFORMS.has(value.platform)) {
55
+ issues.push({
56
+ path: `${path}.platform`,
57
+ message: `must be one of: ${[...VALID_PLATFORMS].join(", ")}`
58
+ });
59
+ }
60
+ }
61
+ function validateConnectorInfo(value, path, issues) {
62
+ if (!isRecord(value)) {
63
+ issues.push({ path, message: "must be an object" });
64
+ return;
65
+ }
66
+ if (!isNonEmptyString(value.platform) || !VALID_PLATFORMS.has(value.platform)) {
67
+ issues.push({
68
+ path: `${path}.platform`,
69
+ message: `must be one of: ${[...VALID_PLATFORMS].join(", ")}`
70
+ });
71
+ }
72
+ if (!isNonEmptyString(value.protocol) || !VALID_PROTOCOLS.has(value.protocol)) {
73
+ issues.push({
74
+ path: `${path}.protocol`,
75
+ message: `must be one of: ${[...VALID_PROTOCOLS].join(", ")}`
76
+ });
77
+ }
78
+ if (!isNonEmptyString(value.connector_id)) {
79
+ issues.push({
80
+ path: `${path}.connector_id`,
81
+ message: "must be a non-empty string"
82
+ });
83
+ }
84
+ }
85
+ function validatePayloadItem(value, path, issues) {
86
+ if (!isRecord(value)) {
87
+ issues.push({ path, message: "must be an object" });
88
+ return;
89
+ }
90
+ const validKinds = /* @__PURE__ */ new Set(["text", "json", "command", "artifact"]);
91
+ if (!isNonEmptyString(value.kind) || !validKinds.has(value.kind)) {
92
+ issues.push({
93
+ path: `${path}.kind`,
94
+ message: `must be one of: ${[...validKinds].join(", ")}`
95
+ });
96
+ return;
97
+ }
98
+ switch (value.kind) {
99
+ case "text":
100
+ if (!isNonEmptyString(value.text)) {
101
+ issues.push({ path: `${path}.text`, message: "must be a non-empty string" });
102
+ }
103
+ break;
104
+ case "json":
105
+ if (!isRecord(value.data)) {
106
+ issues.push({ path: `${path}.data`, message: "must be an object" });
107
+ }
108
+ break;
109
+ case "command":
110
+ if (!isNonEmptyString(value.command)) {
111
+ issues.push({ path: `${path}.command`, message: "must be a non-empty string" });
112
+ }
113
+ break;
114
+ case "artifact":
115
+ if (!isNonEmptyString(value.mimeType) && !isNonEmptyString(value.mime_type)) {
116
+ issues.push({ path: `${path}.mimeType`, message: "must be a non-empty string" });
117
+ }
118
+ if (!isNonEmptyString(value.content)) {
119
+ issues.push({ path: `${path}.content`, message: "must be a non-empty string" });
120
+ }
121
+ break;
122
+ }
123
+ }
124
+ function validateTaskEnvelope(value, options) {
125
+ const issues = [];
126
+ if (!isRecord(value)) {
127
+ return { valid: false, issues: [{ path: "$", message: "must be an object" }] };
128
+ }
129
+ if (!isNonEmptyString(value.envelope_version)) {
130
+ issues.push({ path: "envelope_version", message: "must be a non-empty string" });
131
+ } else if (options?.strictVersion && value.envelope_version !== TASK_ENVELOPE_VERSION) {
132
+ issues.push({
133
+ path: "envelope_version",
134
+ message: `must equal "${TASK_ENVELOPE_VERSION}"`
135
+ });
136
+ }
137
+ if (!isNonEmptyString(value.id)) {
138
+ issues.push({ path: "id", message: "must be a non-empty string" });
139
+ }
140
+ if (!isNonEmptyString(value.workspace_id)) {
141
+ issues.push({ path: "workspace_id", message: "must be a non-empty string" });
142
+ }
143
+ if (!isNonEmptyString(value.thread_id)) {
144
+ issues.push({ path: "thread_id", message: "must be a non-empty string" });
145
+ }
146
+ if (!isNonEmptyString(value.trace_id)) {
147
+ issues.push({ path: "trace_id", message: "must be a non-empty string" });
148
+ }
149
+ if (!isNonEmptyString(value.state) || !VALID_TASK_STATES.has(value.state)) {
150
+ issues.push({
151
+ path: "state",
152
+ message: `must be one of: ${[...VALID_TASK_STATES].join(", ")}`
153
+ });
154
+ }
155
+ validateAgentRef(value.requester, "requester", issues);
156
+ validateAgentRef(value.assignee, "assignee", issues);
157
+ validateConnectorInfo(value.connector, "connector", issues);
158
+ if (value.payload === void 0 || value.payload === null) {
159
+ issues.push({ path: "payload", message: "is required" });
160
+ } else if (Array.isArray(value.payload)) {
161
+ value.payload.forEach(
162
+ (item, i) => validatePayloadItem(item, `payload[${i}]`, issues)
163
+ );
164
+ } else {
165
+ validatePayloadItem(value.payload, "payload", issues);
166
+ }
167
+ if (!isValidISODate(value.created_at)) {
168
+ issues.push({ path: "created_at", message: "must be a valid ISO-8601 timestamp" });
169
+ }
170
+ if (!isValidISODate(value.updated_at)) {
171
+ issues.push({ path: "updated_at", message: "must be a valid ISO-8601 timestamp" });
172
+ }
173
+ if (value.error !== void 0) {
174
+ if (!isRecord(value.error)) {
175
+ issues.push({ path: "error", message: "must be an object when present" });
176
+ } else {
177
+ if (!isNonEmptyString(value.error.code)) {
178
+ issues.push({ path: "error.code", message: "must be a non-empty string" });
179
+ }
180
+ if (!isNonEmptyString(value.error.category)) {
181
+ issues.push({ path: "error.category", message: "must be a non-empty string" });
182
+ }
183
+ if (!isNonEmptyString(value.error.message)) {
184
+ issues.push({ path: "error.message", message: "must be a non-empty string" });
185
+ }
186
+ if (!isNonEmptyString(value.error.severity) || !VALID_SEVERITIES.has(value.error.severity)) {
187
+ issues.push({
188
+ path: "error.severity",
189
+ message: `must be one of: ${[...VALID_SEVERITIES].join(", ")}`
190
+ });
191
+ }
192
+ if (typeof value.error.retryable !== "boolean") {
193
+ issues.push({ path: "error.retryable", message: "must be a boolean" });
194
+ }
195
+ }
196
+ }
197
+ return { valid: issues.length === 0, issues };
198
+ }
199
+ function isValidTaskEnvelope(value) {
200
+ return validateTaskEnvelope(value).valid;
201
+ }
202
+ function assertTaskEnvelope(value) {
203
+ const result = validateTaskEnvelope(value);
204
+ if (!result.valid) {
205
+ const summary = result.issues.map((i) => ` ${i.path}: ${i.message}`).join("\n");
206
+ throw new Error(`Invalid TaskEnvelope:
207
+ ${summary}`);
208
+ }
209
+ }
210
+ function validateAuditActor(value, path, issues) {
211
+ if (!isRecord(value)) {
212
+ issues.push({ path, message: "must be an object" });
213
+ return;
214
+ }
215
+ if (!isNonEmptyString(value.kind) || !VALID_ACTOR_KINDS.has(value.kind)) {
216
+ issues.push({
217
+ path: `${path}.kind`,
218
+ message: `must be one of: ${[...VALID_ACTOR_KINDS].join(", ")}`
219
+ });
220
+ }
221
+ if (!isNonEmptyString(value.id)) {
222
+ issues.push({ path: `${path}.id`, message: "must be a non-empty string" });
223
+ }
224
+ }
225
+ function validateAuditTarget(value, path, issues) {
226
+ if (!isRecord(value)) {
227
+ issues.push({ path, message: "must be an object" });
228
+ return;
229
+ }
230
+ if (!isNonEmptyString(value.kind) || !VALID_TARGET_KINDS.has(value.kind)) {
231
+ issues.push({
232
+ path: `${path}.kind`,
233
+ message: `must be one of: ${[...VALID_TARGET_KINDS].join(", ")}`
234
+ });
235
+ }
236
+ if (!isNonEmptyString(value.id)) {
237
+ issues.push({ path: `${path}.id`, message: "must be a non-empty string" });
238
+ }
239
+ }
240
+ function validateAuditEvent(value, options) {
241
+ const issues = [];
242
+ if (!isRecord(value)) {
243
+ return { valid: false, issues: [{ path: "$", message: "must be an object" }] };
244
+ }
245
+ if (!isNonEmptyString(value.schema_version)) {
246
+ issues.push({ path: "schema_version", message: "must be a non-empty string" });
247
+ } else if (options?.strictVersion && value.schema_version !== AUDIT_EVENT_VERSION) {
248
+ issues.push({
249
+ path: "schema_version",
250
+ message: `must equal "${AUDIT_EVENT_VERSION}"`
251
+ });
252
+ }
253
+ if (!isNonEmptyString(value.id)) {
254
+ issues.push({ path: "id", message: "must be a non-empty string" });
255
+ }
256
+ if (!isNonEmptyString(value.event_type) || !VALID_AUDIT_EVENT_TYPES.has(value.event_type)) {
257
+ issues.push({
258
+ path: "event_type",
259
+ message: `must be one of the canonical audit event types`
260
+ });
261
+ }
262
+ if (value.severity !== void 0 && (!isNonEmptyString(value.severity) || !VALID_AUDIT_SEVERITIES.has(value.severity))) {
263
+ issues.push({
264
+ path: "severity",
265
+ message: `must be one of: ${[...VALID_AUDIT_SEVERITIES].join(", ")}`
266
+ });
267
+ }
268
+ validateAuditActor(value.actor, "actor", issues);
269
+ validateAuditTarget(value.target, "target", issues);
270
+ if (!isNonEmptyString(value.trace_id)) {
271
+ issues.push({ path: "trace_id", message: "must be a non-empty string" });
272
+ }
273
+ if (!isNonEmptyString(value.workspace_id)) {
274
+ issues.push({ path: "workspace_id", message: "must be a non-empty string" });
275
+ }
276
+ if (!isValidISODate(value.timestamp)) {
277
+ issues.push({ path: "timestamp", message: "must be a valid ISO-8601 timestamp" });
278
+ }
279
+ if (value.policy !== void 0) {
280
+ if (!isRecord(value.policy)) {
281
+ issues.push({ path: "policy", message: "must be an object when present" });
282
+ } else {
283
+ if (!isNonEmptyString(value.policy.action)) {
284
+ issues.push({ path: "policy.action", message: "must be a non-empty string" });
285
+ }
286
+ if (!isNonEmptyString(value.policy.rule)) {
287
+ issues.push({ path: "policy.rule", message: "must be a non-empty string" });
288
+ }
289
+ if (typeof value.policy.approved !== "boolean") {
290
+ issues.push({ path: "policy.approved", message: "must be a boolean" });
291
+ }
292
+ if (!isNonEmptyString(value.policy.reason)) {
293
+ issues.push({ path: "policy.reason", message: "must be a non-empty string" });
294
+ }
295
+ if (!isNonEmptyString(value.policy.agent_id)) {
296
+ issues.push({ path: "policy.agent_id", message: "must be a non-empty string" });
297
+ }
298
+ }
299
+ }
300
+ return { valid: issues.length === 0, issues };
301
+ }
302
+ function isValidAuditEvent(value) {
303
+ return validateAuditEvent(value).valid;
304
+ }
305
+ function assertAuditEvent(value) {
306
+ const result = validateAuditEvent(value);
307
+ if (!result.valid) {
308
+ const summary = result.issues.map((i) => ` ${i.path}: ${i.message}`).join("\n");
309
+ throw new Error(`Invalid AuditEvent:
310
+ ${summary}`);
311
+ }
312
+ }
313
+ function validateA2AError(value) {
314
+ const issues = [];
315
+ if (!isRecord(value)) {
316
+ return { valid: false, issues: [{ path: "$", message: "must be an object" }] };
317
+ }
318
+ if (!isNonEmptyString(value.code)) {
319
+ issues.push({ path: "code", message: "must be a non-empty string" });
320
+ } else if (!isA2AErrorCode(value.code)) {
321
+ issues.push({
322
+ path: "code",
323
+ message: "must be a recognized A2A error code"
324
+ });
325
+ }
326
+ if (!isNonEmptyString(value.category)) {
327
+ issues.push({ path: "category", message: "must be a non-empty string" });
328
+ }
329
+ if (!isNonEmptyString(value.message)) {
330
+ issues.push({ path: "message", message: "must be a non-empty string" });
331
+ }
332
+ if (!isNonEmptyString(value.severity) || !VALID_SEVERITIES.has(value.severity)) {
333
+ issues.push({
334
+ path: "severity",
335
+ message: `must be one of: ${[...VALID_SEVERITIES].join(", ")}`
336
+ });
337
+ }
338
+ if (typeof value.retryable !== "boolean") {
339
+ issues.push({ path: "retryable", message: "must be a boolean" });
340
+ }
341
+ return { valid: issues.length === 0, issues };
342
+ }
343
+ function isValidA2AError(value) {
344
+ return validateA2AError(value).valid;
345
+ }
346
+
347
+ export {
348
+ validateTaskEnvelope,
349
+ isValidTaskEnvelope,
350
+ assertTaskEnvelope,
351
+ validateAuditEvent,
352
+ isValidAuditEvent,
353
+ assertAuditEvent,
354
+ validateA2AError,
355
+ isValidA2AError
356
+ };
357
+ //# sourceMappingURL=chunk-BWCRJDUB.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/validation.ts"],"sourcesContent":["/**\n * @module validation\n *\n * Validation utilities for incoming payloads against the canonical A2A schemas.\n *\n * These validators perform structural checks on raw objects to confirm they\n * conform to the `TaskEnvelope`, `AuditEvent`, and related schema shapes.\n * They are designed for use at ingress boundaries -- API routes, message\n * consumers, webhook handlers -- where untyped JSON must be validated before\n * it enters the typed domain.\n *\n * All validators return a `ValidationResult` with a list of issues rather\n * than throwing, so that callers can aggregate errors or return structured\n * 422 responses.\n *\n * @example\n * ```ts\n * import { validateTaskEnvelope, validateAuditEvent } from '@recoder/a2a-sdk/validation';\n *\n * const result = validateTaskEnvelope(rawPayload);\n * if (!result.valid) {\n * console.error('Invalid envelope:', result.issues);\n * }\n * ```\n */\n\nimport {\n type TaskEnvelope,\n type AuditEvent,\n type A2AError,\n TASK_STATES,\n TASK_ENVELOPE_VERSION,\n AUDIT_EVENT_TYPES,\n AUDIT_EVENT_VERSION,\n isA2AErrorCode,\n} from '@recoder/shared/a2a/schemas';\n\n// ---------------------------------------------------------------------------\n// Validation result types\n// ---------------------------------------------------------------------------\n\n/**\n * A single validation issue found during schema validation.\n */\nexport interface ValidationIssue {\n /** Dot-delimited path to the field that failed validation. */\n path: string;\n /** Human-readable description of what is wrong. */\n message: string;\n}\n\n/**\n * The result of a validation operation.\n */\nexport interface ValidationResult {\n /** Whether the payload passed all checks. */\n valid: boolean;\n /** List of issues found. Empty when `valid` is true. */\n issues: ValidationIssue[];\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0;\n}\n\nfunction isValidISODate(value: unknown): boolean {\n return typeof value === 'string' && !Number.isNaN(Date.parse(value));\n}\n\nconst VALID_PLATFORMS = new Set<string>([\n 'codex',\n 'claude_code',\n 'recoder_web',\n 'recoder_pm',\n 'recoder_agency',\n 'recoder_backend',\n 'recoder_desktop',\n 'custom',\n]);\n\nconst VALID_PROTOCOLS = new Set<string>(['a2a', 'mcp', 'jsonrpc', 'rest', 'file_git']);\n\nconst VALID_TASK_STATES = new Set<string>(TASK_STATES);\n\nconst VALID_AUDIT_EVENT_TYPES = new Set<string>(AUDIT_EVENT_TYPES);\n\nconst VALID_ACTOR_KINDS = new Set<string>(['agent', 'user', 'system', 'connector']);\n\nconst VALID_TARGET_KINDS = new Set<string>([\n 'task',\n 'agent',\n 'connector',\n 'channel',\n 'thread',\n 'message',\n 'policy',\n 'workspace',\n 'system',\n]);\n\nconst VALID_SEVERITIES = new Set<string>(['low', 'medium', 'high', 'critical']);\n\nconst VALID_AUDIT_SEVERITIES = new Set<string>(['info', 'warning', 'error', 'critical']);\n\n// ---------------------------------------------------------------------------\n// TaskEnvelope validation\n// ---------------------------------------------------------------------------\n\nfunction validateAgentRef(\n value: unknown,\n path: string,\n issues: ValidationIssue[],\n): void {\n if (!isRecord(value)) {\n issues.push({ path, message: 'must be an object' });\n return;\n }\n if (!isNonEmptyString(value.agent_id)) {\n issues.push({ path: `${path}.agent_id`, message: 'must be a non-empty string' });\n }\n if (!isNonEmptyString(value.platform) || !VALID_PLATFORMS.has(value.platform as string)) {\n issues.push({\n path: `${path}.platform`,\n message: `must be one of: ${[...VALID_PLATFORMS].join(', ')}`,\n });\n }\n}\n\nfunction validateConnectorInfo(\n value: unknown,\n path: string,\n issues: ValidationIssue[],\n): void {\n if (!isRecord(value)) {\n issues.push({ path, message: 'must be an object' });\n return;\n }\n if (!isNonEmptyString(value.platform) || !VALID_PLATFORMS.has(value.platform as string)) {\n issues.push({\n path: `${path}.platform`,\n message: `must be one of: ${[...VALID_PLATFORMS].join(', ')}`,\n });\n }\n if (!isNonEmptyString(value.protocol) || !VALID_PROTOCOLS.has(value.protocol as string)) {\n issues.push({\n path: `${path}.protocol`,\n message: `must be one of: ${[...VALID_PROTOCOLS].join(', ')}`,\n });\n }\n if (!isNonEmptyString(value.connector_id)) {\n issues.push({\n path: `${path}.connector_id`,\n message: 'must be a non-empty string',\n });\n }\n}\n\nfunction validatePayloadItem(\n value: unknown,\n path: string,\n issues: ValidationIssue[],\n): void {\n if (!isRecord(value)) {\n issues.push({ path, message: 'must be an object' });\n return;\n }\n\n const validKinds = new Set(['text', 'json', 'command', 'artifact']);\n if (!isNonEmptyString(value.kind) || !validKinds.has(value.kind as string)) {\n issues.push({\n path: `${path}.kind`,\n message: `must be one of: ${[...validKinds].join(', ')}`,\n });\n return;\n }\n\n switch (value.kind) {\n case 'text':\n if (!isNonEmptyString(value.text)) {\n issues.push({ path: `${path}.text`, message: 'must be a non-empty string' });\n }\n break;\n case 'json':\n if (!isRecord(value.data)) {\n issues.push({ path: `${path}.data`, message: 'must be an object' });\n }\n break;\n case 'command':\n if (!isNonEmptyString(value.command)) {\n issues.push({ path: `${path}.command`, message: 'must be a non-empty string' });\n }\n break;\n case 'artifact':\n if (!isNonEmptyString(value.mimeType) && !isNonEmptyString(value.mime_type)) {\n issues.push({ path: `${path}.mimeType`, message: 'must be a non-empty string' });\n }\n if (!isNonEmptyString(value.content)) {\n issues.push({ path: `${path}.content`, message: 'must be a non-empty string' });\n }\n break;\n }\n}\n\n/**\n * Validate a raw object against the `TaskEnvelope` schema.\n *\n * Checks all required fields, type correctness, enum membership, and\n * nested object structures. Does NOT check whether state transitions in\n * the `history` array are valid -- use `isValidTransition` for that.\n *\n * @param value - The raw object to validate.\n * @param options - Optional strictness flags.\n * @returns A `ValidationResult`.\n */\nexport function validateTaskEnvelope(\n value: unknown,\n options?: {\n /** If true, require `envelope_version` to match `TASK_ENVELOPE_VERSION`. */\n strictVersion?: boolean;\n },\n): ValidationResult {\n const issues: ValidationIssue[] = [];\n\n if (!isRecord(value)) {\n return { valid: false, issues: [{ path: '$', message: 'must be an object' }] };\n }\n\n // Identity\n if (!isNonEmptyString(value.envelope_version)) {\n issues.push({ path: 'envelope_version', message: 'must be a non-empty string' });\n } else if (options?.strictVersion && value.envelope_version !== TASK_ENVELOPE_VERSION) {\n issues.push({\n path: 'envelope_version',\n message: `must equal \"${TASK_ENVELOPE_VERSION}\"`,\n });\n }\n\n if (!isNonEmptyString(value.id)) {\n issues.push({ path: 'id', message: 'must be a non-empty string' });\n }\n\n // Scoping\n if (!isNonEmptyString(value.workspace_id)) {\n issues.push({ path: 'workspace_id', message: 'must be a non-empty string' });\n }\n if (!isNonEmptyString(value.thread_id)) {\n issues.push({ path: 'thread_id', message: 'must be a non-empty string' });\n }\n if (!isNonEmptyString(value.trace_id)) {\n issues.push({ path: 'trace_id', message: 'must be a non-empty string' });\n }\n\n // State\n if (\n !isNonEmptyString(value.state) ||\n !VALID_TASK_STATES.has(value.state as string)\n ) {\n issues.push({\n path: 'state',\n message: `must be one of: ${[...VALID_TASK_STATES].join(', ')}`,\n });\n }\n\n // Participants\n validateAgentRef(value.requester, 'requester', issues);\n validateAgentRef(value.assignee, 'assignee', issues);\n\n // Connector\n validateConnectorInfo(value.connector, 'connector', issues);\n\n // Payload\n if (value.payload === undefined || value.payload === null) {\n issues.push({ path: 'payload', message: 'is required' });\n } else if (Array.isArray(value.payload)) {\n (value.payload as unknown[]).forEach((item, i) =>\n validatePayloadItem(item, `payload[${i}]`, issues),\n );\n } else {\n validatePayloadItem(value.payload, 'payload', issues);\n }\n\n // Timestamps\n if (!isValidISODate(value.created_at)) {\n issues.push({ path: 'created_at', message: 'must be a valid ISO-8601 timestamp' });\n }\n if (!isValidISODate(value.updated_at)) {\n issues.push({ path: 'updated_at', message: 'must be a valid ISO-8601 timestamp' });\n }\n\n // Error info (optional but validated if present)\n if (value.error !== undefined) {\n if (!isRecord(value.error)) {\n issues.push({ path: 'error', message: 'must be an object when present' });\n } else {\n if (!isNonEmptyString(value.error.code)) {\n issues.push({ path: 'error.code', message: 'must be a non-empty string' });\n }\n if (!isNonEmptyString(value.error.category)) {\n issues.push({ path: 'error.category', message: 'must be a non-empty string' });\n }\n if (!isNonEmptyString(value.error.message)) {\n issues.push({ path: 'error.message', message: 'must be a non-empty string' });\n }\n if (\n !isNonEmptyString(value.error.severity) ||\n !VALID_SEVERITIES.has(value.error.severity as string)\n ) {\n issues.push({\n path: 'error.severity',\n message: `must be one of: ${[...VALID_SEVERITIES].join(', ')}`,\n });\n }\n if (typeof value.error.retryable !== 'boolean') {\n issues.push({ path: 'error.retryable', message: 'must be a boolean' });\n }\n }\n }\n\n return { valid: issues.length === 0, issues };\n}\n\n/**\n * Type guard: check whether a value is a valid `TaskEnvelope`.\n *\n * @param value - The value to check.\n * @returns `true` if the value passes structural validation.\n */\nexport function isValidTaskEnvelope(value: unknown): value is TaskEnvelope {\n return validateTaskEnvelope(value).valid;\n}\n\n/**\n * Assert that a value is a valid `TaskEnvelope`, throwing a descriptive\n * error if it is not.\n *\n * @param value - The value to assert.\n * @throws {Error} With a summary of validation issues.\n */\nexport function assertTaskEnvelope(value: unknown): asserts value is TaskEnvelope {\n const result = validateTaskEnvelope(value);\n if (!result.valid) {\n const summary = result.issues.map((i) => ` ${i.path}: ${i.message}`).join('\\n');\n throw new Error(`Invalid TaskEnvelope:\\n${summary}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// AuditEvent validation\n// ---------------------------------------------------------------------------\n\nfunction validateAuditActor(\n value: unknown,\n path: string,\n issues: ValidationIssue[],\n): void {\n if (!isRecord(value)) {\n issues.push({ path, message: 'must be an object' });\n return;\n }\n if (!isNonEmptyString(value.kind) || !VALID_ACTOR_KINDS.has(value.kind as string)) {\n issues.push({\n path: `${path}.kind`,\n message: `must be one of: ${[...VALID_ACTOR_KINDS].join(', ')}`,\n });\n }\n if (!isNonEmptyString(value.id)) {\n issues.push({ path: `${path}.id`, message: 'must be a non-empty string' });\n }\n}\n\nfunction validateAuditTarget(\n value: unknown,\n path: string,\n issues: ValidationIssue[],\n): void {\n if (!isRecord(value)) {\n issues.push({ path, message: 'must be an object' });\n return;\n }\n if (!isNonEmptyString(value.kind) || !VALID_TARGET_KINDS.has(value.kind as string)) {\n issues.push({\n path: `${path}.kind`,\n message: `must be one of: ${[...VALID_TARGET_KINDS].join(', ')}`,\n });\n }\n if (!isNonEmptyString(value.id)) {\n issues.push({ path: `${path}.id`, message: 'must be a non-empty string' });\n }\n}\n\n/**\n * Validate a raw object against the `AuditEvent` schema.\n *\n * @param value - The raw object to validate.\n * @param options - Optional strictness flags.\n * @returns A `ValidationResult`.\n */\nexport function validateAuditEvent(\n value: unknown,\n options?: {\n /** If true, require `schema_version` to match `AUDIT_EVENT_VERSION`. */\n strictVersion?: boolean;\n },\n): ValidationResult {\n const issues: ValidationIssue[] = [];\n\n if (!isRecord(value)) {\n return { valid: false, issues: [{ path: '$', message: 'must be an object' }] };\n }\n\n // Identity\n if (!isNonEmptyString(value.schema_version)) {\n issues.push({ path: 'schema_version', message: 'must be a non-empty string' });\n } else if (options?.strictVersion && value.schema_version !== AUDIT_EVENT_VERSION) {\n issues.push({\n path: 'schema_version',\n message: `must equal \"${AUDIT_EVENT_VERSION}\"`,\n });\n }\n\n if (!isNonEmptyString(value.id)) {\n issues.push({ path: 'id', message: 'must be a non-empty string' });\n }\n\n // Classification\n if (\n !isNonEmptyString(value.event_type) ||\n !VALID_AUDIT_EVENT_TYPES.has(value.event_type as string)\n ) {\n issues.push({\n path: 'event_type',\n message: `must be one of the canonical audit event types`,\n });\n }\n\n if (\n value.severity !== undefined &&\n (!isNonEmptyString(value.severity) ||\n !VALID_AUDIT_SEVERITIES.has(value.severity as string))\n ) {\n issues.push({\n path: 'severity',\n message: `must be one of: ${[...VALID_AUDIT_SEVERITIES].join(', ')}`,\n });\n }\n\n // Actor & target\n validateAuditActor(value.actor, 'actor', issues);\n validateAuditTarget(value.target, 'target', issues);\n\n // Tracing & scoping\n if (!isNonEmptyString(value.trace_id)) {\n issues.push({ path: 'trace_id', message: 'must be a non-empty string' });\n }\n if (!isNonEmptyString(value.workspace_id)) {\n issues.push({ path: 'workspace_id', message: 'must be a non-empty string' });\n }\n\n // Timestamp\n if (!isValidISODate(value.timestamp)) {\n issues.push({ path: 'timestamp', message: 'must be a valid ISO-8601 timestamp' });\n }\n\n // Policy context (optional)\n if (value.policy !== undefined) {\n if (!isRecord(value.policy)) {\n issues.push({ path: 'policy', message: 'must be an object when present' });\n } else {\n if (!isNonEmptyString(value.policy.action)) {\n issues.push({ path: 'policy.action', message: 'must be a non-empty string' });\n }\n if (!isNonEmptyString(value.policy.rule)) {\n issues.push({ path: 'policy.rule', message: 'must be a non-empty string' });\n }\n if (typeof value.policy.approved !== 'boolean') {\n issues.push({ path: 'policy.approved', message: 'must be a boolean' });\n }\n if (!isNonEmptyString(value.policy.reason)) {\n issues.push({ path: 'policy.reason', message: 'must be a non-empty string' });\n }\n if (!isNonEmptyString(value.policy.agent_id)) {\n issues.push({ path: 'policy.agent_id', message: 'must be a non-empty string' });\n }\n }\n }\n\n return { valid: issues.length === 0, issues };\n}\n\n/**\n * Type guard: check whether a value is a valid `AuditEvent`.\n *\n * @param value - The value to check.\n * @returns `true` if the value passes structural validation.\n */\nexport function isValidAuditEvent(value: unknown): value is AuditEvent {\n return validateAuditEvent(value).valid;\n}\n\n/**\n * Assert that a value is a valid `AuditEvent`, throwing a descriptive\n * error if it is not.\n *\n * @param value - The value to assert.\n * @throws {Error} With a summary of validation issues.\n */\nexport function assertAuditEvent(value: unknown): asserts value is AuditEvent {\n const result = validateAuditEvent(value);\n if (!result.valid) {\n const summary = result.issues.map((i) => ` ${i.path}: ${i.message}`).join('\\n');\n throw new Error(`Invalid AuditEvent:\\n${summary}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// A2AError validation\n// ---------------------------------------------------------------------------\n\n/**\n * Validate a raw object against the `A2AError` structure.\n *\n * @param value - The raw object to validate.\n * @returns A `ValidationResult`.\n */\nexport function validateA2AError(value: unknown): ValidationResult {\n const issues: ValidationIssue[] = [];\n\n if (!isRecord(value)) {\n return { valid: false, issues: [{ path: '$', message: 'must be an object' }] };\n }\n\n if (!isNonEmptyString(value.code)) {\n issues.push({ path: 'code', message: 'must be a non-empty string' });\n } else if (!isA2AErrorCode(value.code as string)) {\n issues.push({\n path: 'code',\n message: 'must be a recognized A2A error code',\n });\n }\n\n if (!isNonEmptyString(value.category)) {\n issues.push({ path: 'category', message: 'must be a non-empty string' });\n }\n\n if (!isNonEmptyString(value.message)) {\n issues.push({ path: 'message', message: 'must be a non-empty string' });\n }\n\n if (\n !isNonEmptyString(value.severity) ||\n !VALID_SEVERITIES.has(value.severity as string)\n ) {\n issues.push({\n path: 'severity',\n message: `must be one of: ${[...VALID_SEVERITIES].join(', ')}`,\n });\n }\n\n if (typeof value.retryable !== 'boolean') {\n issues.push({ path: 'retryable', message: 'must be a boolean' });\n }\n\n return { valid: issues.length === 0, issues };\n}\n\n/**\n * Type guard: check whether a value is a valid `A2AError`.\n *\n * @param value - The value to check.\n */\nexport function isValidA2AError(value: unknown): value is A2AError {\n return validateA2AError(value).valid;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,141 @@
1
+ // src/state-mapping.ts
2
+ import {
3
+ TaskStateEnum,
4
+ isValidTransition,
5
+ isTerminalState
6
+ } from "@recoder/shared/a2a/schemas";
7
+ var CODEX_TO_CANONICAL = {
8
+ queued: TaskStateEnum.Submitted,
9
+ running: TaskStateEnum.Working,
10
+ waiting_for_input: TaskStateEnum.InputRequired,
11
+ completed: TaskStateEnum.Completed,
12
+ failed: TaskStateEnum.Failed,
13
+ error: TaskStateEnum.Failed,
14
+ cancelled: TaskStateEnum.Cancelled,
15
+ timeout: TaskStateEnum.Failed
16
+ };
17
+ var CANONICAL_TO_CODEX = {
18
+ [TaskStateEnum.Submitted]: "queued",
19
+ [TaskStateEnum.Working]: "running",
20
+ [TaskStateEnum.InputRequired]: "waiting_for_input",
21
+ [TaskStateEnum.Completed]: "completed",
22
+ [TaskStateEnum.Failed]: "failed",
23
+ [TaskStateEnum.Cancelled]: "cancelled"
24
+ };
25
+ function mapCodexState(nativeState) {
26
+ return CODEX_TO_CANONICAL[nativeState];
27
+ }
28
+ function mapCodexStateStrict(nativeState) {
29
+ const mapped = mapCodexState(nativeState);
30
+ if (mapped === void 0) {
31
+ throw new Error(`Unknown Codex state: "${nativeState}"`);
32
+ }
33
+ return mapped;
34
+ }
35
+ function canonicalToCodexState(canonicalState) {
36
+ return CANONICAL_TO_CODEX[canonicalState];
37
+ }
38
+ var CLAUDE_TO_CANONICAL = {
39
+ pending: TaskStateEnum.Submitted,
40
+ streaming: TaskStateEnum.Working,
41
+ processing: TaskStateEnum.Working,
42
+ waiting_for_approval: TaskStateEnum.InputRequired,
43
+ waiting_for_input: TaskStateEnum.InputRequired,
44
+ done: TaskStateEnum.Completed,
45
+ completed: TaskStateEnum.Completed,
46
+ error: TaskStateEnum.Failed,
47
+ failed: TaskStateEnum.Failed,
48
+ aborted: TaskStateEnum.Cancelled,
49
+ cancelled: TaskStateEnum.Cancelled,
50
+ timeout: TaskStateEnum.Failed
51
+ };
52
+ var CANONICAL_TO_CLAUDE = {
53
+ [TaskStateEnum.Submitted]: "pending",
54
+ [TaskStateEnum.Working]: "streaming",
55
+ [TaskStateEnum.InputRequired]: "waiting_for_input",
56
+ [TaskStateEnum.Completed]: "done",
57
+ [TaskStateEnum.Failed]: "error",
58
+ [TaskStateEnum.Cancelled]: "aborted"
59
+ };
60
+ function mapClaudeState(nativeState) {
61
+ return CLAUDE_TO_CANONICAL[nativeState];
62
+ }
63
+ function mapClaudeStateStrict(nativeState) {
64
+ const mapped = mapClaudeState(nativeState);
65
+ if (mapped === void 0) {
66
+ throw new Error(`Unknown Claude Code state: "${nativeState}"`);
67
+ }
68
+ return mapped;
69
+ }
70
+ function canonicalToClaudeState(canonicalState) {
71
+ return CANONICAL_TO_CLAUDE[canonicalState];
72
+ }
73
+ function mapConnectorState(platform, nativeState) {
74
+ switch (platform) {
75
+ case "codex":
76
+ return mapCodexState(nativeState);
77
+ case "claude_code":
78
+ return mapClaudeState(nativeState);
79
+ default:
80
+ return void 0;
81
+ }
82
+ }
83
+ function mapConnectorStateStrict(platform, nativeState) {
84
+ const mapped = mapConnectorState(platform, nativeState);
85
+ if (mapped === void 0) {
86
+ throw new Error(
87
+ `Cannot map state "${nativeState}" for platform "${platform}"`
88
+ );
89
+ }
90
+ return mapped;
91
+ }
92
+ function canonicalToConnectorState(platform, canonicalState) {
93
+ switch (platform) {
94
+ case "codex":
95
+ return canonicalToCodexState(canonicalState);
96
+ case "claude_code":
97
+ return canonicalToClaudeState(canonicalState);
98
+ default:
99
+ return void 0;
100
+ }
101
+ }
102
+ function checkConnectorTransition(currentCanonical, platform, newNativeState) {
103
+ const mappedState = mapConnectorState(platform, newNativeState);
104
+ if (mappedState === void 0) {
105
+ return {
106
+ valid: false,
107
+ mappedState: void 0,
108
+ error: `Unknown ${platform} state: "${newNativeState}"`
109
+ };
110
+ }
111
+ if (mappedState === currentCanonical) {
112
+ return { valid: true, mappedState };
113
+ }
114
+ if (!isValidTransition(currentCanonical, mappedState)) {
115
+ return {
116
+ valid: false,
117
+ mappedState,
118
+ error: `Invalid transition: ${currentCanonical} -> ${mappedState} (from ${platform} state "${newNativeState}")`
119
+ };
120
+ }
121
+ return { valid: true, mappedState };
122
+ }
123
+ function isConnectorTerminalState(platform, nativeState) {
124
+ const mapped = mapConnectorState(platform, nativeState);
125
+ return mapped !== void 0 && isTerminalState(mapped);
126
+ }
127
+
128
+ export {
129
+ mapCodexState,
130
+ mapCodexStateStrict,
131
+ canonicalToCodexState,
132
+ mapClaudeState,
133
+ mapClaudeStateStrict,
134
+ canonicalToClaudeState,
135
+ mapConnectorState,
136
+ mapConnectorStateStrict,
137
+ canonicalToConnectorState,
138
+ checkConnectorTransition,
139
+ isConnectorTerminalState
140
+ };
141
+ //# sourceMappingURL=chunk-DPFH2JIC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/state-mapping.ts"],"sourcesContent":["/**\n * @module state-mapping\n *\n * Task state mapping helpers for connector adapters.\n *\n * Each external connector (Codex, Claude Code, etc.) has its own native state\n * vocabulary. This module provides bidirectional mapping functions that\n * translate between connector-specific states and the canonical\n * `TaskState` enum defined in `@recoder/shared/a2a/schemas`.\n *\n * Adapter authors should use these mappers at the boundary where connector\n * events enter (or leave) the Recoder A2A control plane, ensuring that all\n * internal logic operates exclusively on canonical states.\n *\n * @example\n * ```ts\n * import { mapCodexState, mapClaudeState } from '@recoder/a2a-sdk/state-mapping';\n *\n * const canonical = mapCodexState('running'); // => 'working'\n * const claude = mapClaudeState('streaming'); // => 'working'\n * ```\n */\n\nimport {\n type TaskState,\n TaskStateEnum,\n isValidTransition,\n isTerminalState,\n} from '@recoder/shared/a2a/schemas';\n\n// ---------------------------------------------------------------------------\n// Connector platform identifier\n// ---------------------------------------------------------------------------\n\n/** Supported connector platforms for state mapping. */\nexport type ConnectorPlatform = 'codex' | 'claude_code';\n\n// ---------------------------------------------------------------------------\n// Codex state mapping\n// ---------------------------------------------------------------------------\n\n/**\n * Native states reported by the OpenAI Codex CLI / API adapter.\n * These are the raw status strings that appear in Codex task events.\n */\nexport type CodexNativeState =\n | 'queued'\n | 'running'\n | 'waiting_for_input'\n | 'completed'\n | 'failed'\n | 'error'\n | 'cancelled'\n | 'timeout';\n\n/**\n * Map from Codex native states to canonical TaskState values.\n * Every known Codex state must appear exactly once as a key.\n */\nconst CODEX_TO_CANONICAL: Readonly<Record<CodexNativeState, TaskState>> = {\n queued: TaskStateEnum.Submitted,\n running: TaskStateEnum.Working,\n waiting_for_input: TaskStateEnum.InputRequired,\n completed: TaskStateEnum.Completed,\n failed: TaskStateEnum.Failed,\n error: TaskStateEnum.Failed,\n cancelled: TaskStateEnum.Cancelled,\n timeout: TaskStateEnum.Failed,\n};\n\n/**\n * Reverse map from canonical TaskState to the \"primary\" Codex native state.\n * When multiple Codex states map to the same canonical state, the most\n * common / expected one is chosen as the primary reverse mapping.\n */\nconst CANONICAL_TO_CODEX: Readonly<Record<TaskState, CodexNativeState>> = {\n [TaskStateEnum.Submitted]: 'queued',\n [TaskStateEnum.Working]: 'running',\n [TaskStateEnum.InputRequired]: 'waiting_for_input',\n [TaskStateEnum.Completed]: 'completed',\n [TaskStateEnum.Failed]: 'failed',\n [TaskStateEnum.Cancelled]: 'cancelled',\n};\n\n/**\n * Map a Codex native state string to the canonical `TaskState`.\n *\n * @param nativeState - The raw state string from a Codex event.\n * @returns The canonical `TaskState`, or `undefined` if the state is unknown.\n */\nexport function mapCodexState(nativeState: string): TaskState | undefined {\n return CODEX_TO_CANONICAL[nativeState as CodexNativeState];\n}\n\n/**\n * Map a Codex native state to canonical, throwing if the state is unknown.\n *\n * @param nativeState - The raw state string from a Codex event.\n * @returns The canonical `TaskState`.\n * @throws {Error} If the state cannot be mapped.\n */\nexport function mapCodexStateStrict(nativeState: string): TaskState {\n const mapped = mapCodexState(nativeState);\n if (mapped === undefined) {\n throw new Error(`Unknown Codex state: \"${nativeState}\"`);\n }\n return mapped;\n}\n\n/**\n * Map a canonical `TaskState` back to the primary Codex native state.\n *\n * @param canonicalState - The canonical task state.\n * @returns The Codex native state string.\n */\nexport function canonicalToCodexState(canonicalState: TaskState): CodexNativeState {\n return CANONICAL_TO_CODEX[canonicalState];\n}\n\n// ---------------------------------------------------------------------------\n// Claude Code state mapping\n// ---------------------------------------------------------------------------\n\n/**\n * Native states reported by the Claude Code CLI / API adapter.\n * These are the raw status strings that appear in Claude Code events.\n */\nexport type ClaudeNativeState =\n | 'pending'\n | 'streaming'\n | 'processing'\n | 'waiting_for_approval'\n | 'waiting_for_input'\n | 'done'\n | 'completed'\n | 'error'\n | 'failed'\n | 'aborted'\n | 'cancelled'\n | 'timeout';\n\n/**\n * Map from Claude Code native states to canonical TaskState values.\n */\nconst CLAUDE_TO_CANONICAL: Readonly<Record<ClaudeNativeState, TaskState>> = {\n pending: TaskStateEnum.Submitted,\n streaming: TaskStateEnum.Working,\n processing: TaskStateEnum.Working,\n waiting_for_approval: TaskStateEnum.InputRequired,\n waiting_for_input: TaskStateEnum.InputRequired,\n done: TaskStateEnum.Completed,\n completed: TaskStateEnum.Completed,\n error: TaskStateEnum.Failed,\n failed: TaskStateEnum.Failed,\n aborted: TaskStateEnum.Cancelled,\n cancelled: TaskStateEnum.Cancelled,\n timeout: TaskStateEnum.Failed,\n};\n\n/**\n * Reverse map from canonical TaskState to the primary Claude Code native state.\n */\nconst CANONICAL_TO_CLAUDE: Readonly<Record<TaskState, ClaudeNativeState>> = {\n [TaskStateEnum.Submitted]: 'pending',\n [TaskStateEnum.Working]: 'streaming',\n [TaskStateEnum.InputRequired]: 'waiting_for_input',\n [TaskStateEnum.Completed]: 'done',\n [TaskStateEnum.Failed]: 'error',\n [TaskStateEnum.Cancelled]: 'aborted',\n};\n\n/**\n * Map a Claude Code native state string to the canonical `TaskState`.\n *\n * @param nativeState - The raw state string from a Claude Code event.\n * @returns The canonical `TaskState`, or `undefined` if the state is unknown.\n */\nexport function mapClaudeState(nativeState: string): TaskState | undefined {\n return CLAUDE_TO_CANONICAL[nativeState as ClaudeNativeState];\n}\n\n/**\n * Map a Claude Code native state to canonical, throwing if the state is unknown.\n *\n * @param nativeState - The raw state string from a Claude Code event.\n * @returns The canonical `TaskState`.\n * @throws {Error} If the state cannot be mapped.\n */\nexport function mapClaudeStateStrict(nativeState: string): TaskState {\n const mapped = mapClaudeState(nativeState);\n if (mapped === undefined) {\n throw new Error(`Unknown Claude Code state: \"${nativeState}\"`);\n }\n return mapped;\n}\n\n/**\n * Map a canonical `TaskState` back to the primary Claude Code native state.\n *\n * @param canonicalState - The canonical task state.\n * @returns The Claude Code native state string.\n */\nexport function canonicalToClaudeState(canonicalState: TaskState): ClaudeNativeState {\n return CANONICAL_TO_CLAUDE[canonicalState];\n}\n\n// ---------------------------------------------------------------------------\n// Generic / platform-agnostic mapping\n// ---------------------------------------------------------------------------\n\n/**\n * Map a native state from any supported connector to canonical `TaskState`.\n *\n * @param platform - The connector platform identifier.\n * @param nativeState - The raw state string from the connector.\n * @returns The canonical `TaskState`, or `undefined` if unmappable.\n */\nexport function mapConnectorState(\n platform: ConnectorPlatform,\n nativeState: string,\n): TaskState | undefined {\n switch (platform) {\n case 'codex':\n return mapCodexState(nativeState);\n case 'claude_code':\n return mapClaudeState(nativeState);\n default:\n return undefined;\n }\n}\n\n/**\n * Map a native state from any supported connector to canonical `TaskState`,\n * throwing if the mapping fails.\n *\n * @param platform - The connector platform identifier.\n * @param nativeState - The raw state string from the connector.\n * @returns The canonical `TaskState`.\n * @throws {Error} If the platform or state is unknown.\n */\nexport function mapConnectorStateStrict(\n platform: ConnectorPlatform,\n nativeState: string,\n): TaskState {\n const mapped = mapConnectorState(platform, nativeState);\n if (mapped === undefined) {\n throw new Error(\n `Cannot map state \"${nativeState}\" for platform \"${platform}\"`,\n );\n }\n return mapped;\n}\n\n/**\n * Map a canonical `TaskState` back to the primary native state for a given\n * connector platform.\n *\n * @param platform - The connector platform identifier.\n * @param canonicalState - The canonical task state.\n * @returns The native state string, or `undefined` if the platform is unknown.\n */\nexport function canonicalToConnectorState(\n platform: ConnectorPlatform,\n canonicalState: TaskState,\n): string | undefined {\n switch (platform) {\n case 'codex':\n return canonicalToCodexState(canonicalState);\n case 'claude_code':\n return canonicalToClaudeState(canonicalState);\n default:\n return undefined;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Transition safety helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Given the current canonical state and a new native state from a connector,\n * determine whether the implied transition is valid according to the\n * canonical lifecycle rules.\n *\n * This is the main \"guard\" function that adapters should call before\n * applying a state update from a connector event.\n *\n * @param currentCanonical - The current canonical task state.\n * @param platform - The connector platform identifier.\n * @param newNativeState - The new native state reported by the connector.\n * @returns An object indicating whether the transition is valid, the mapped\n * canonical state, and an error message if invalid.\n */\nexport function checkConnectorTransition(\n currentCanonical: TaskState,\n platform: ConnectorPlatform,\n newNativeState: string,\n): {\n valid: boolean;\n mappedState: TaskState | undefined;\n error?: string;\n} {\n const mappedState = mapConnectorState(platform, newNativeState);\n\n if (mappedState === undefined) {\n return {\n valid: false,\n mappedState: undefined,\n error: `Unknown ${platform} state: \"${newNativeState}\"`,\n };\n }\n\n // Same state is a no-op, always valid\n if (mappedState === currentCanonical) {\n return { valid: true, mappedState };\n }\n\n if (!isValidTransition(currentCanonical, mappedState)) {\n return {\n valid: false,\n mappedState,\n error: `Invalid transition: ${currentCanonical} -> ${mappedState} (from ${platform} state \"${newNativeState}\")`,\n };\n }\n\n return { valid: true, mappedState };\n}\n\n/**\n * Check whether a connector-reported native state maps to a terminal\n * canonical state.\n *\n * @param platform - The connector platform identifier.\n * @param nativeState - The native state to check.\n * @returns `true` if the mapped canonical state is terminal; `false` if\n * non-terminal or unmappable.\n */\nexport function isConnectorTerminalState(\n platform: ConnectorPlatform,\n nativeState: string,\n): boolean {\n const mapped = mapConnectorState(platform, nativeState);\n return mapped !== undefined && isTerminalState(mapped);\n}\n"],"mappings":"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","names":[]}