@irogane/kaji 0.2.0-beta.11

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 (136) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +598 -0
  3. package/contracts/README.md +14 -0
  4. package/contracts/beta-core-v1.json +52 -0
  5. package/contracts/cli/init-cases-v1.json +27 -0
  6. package/contracts/errors/error-codes.json +48 -0
  7. package/contracts/errors/integration-recovery-v1.json +127 -0
  8. package/contracts/errors/provider-normalization.json +111 -0
  9. package/contracts/events/conformance-invalid.json +20 -0
  10. package/contracts/events/conformance.json +511 -0
  11. package/contracts/events/new-kaji-event-v1.schema.json +1021 -0
  12. package/contracts/events/stored-kaji-event-v1.schema.json +1025 -0
  13. package/contracts/feature-tiers-v1.json +488 -0
  14. package/contracts/integrations/abi-index-v1.json +8 -0
  15. package/contracts/integrations/conformance-invalid.json +443 -0
  16. package/contracts/integrations/conformance-valid.json +121 -0
  17. package/contracts/integrations/copy-provenance-v1.schema.json +61 -0
  18. package/contracts/integrations/echo-tool-abi-v1.json +37 -0
  19. package/contracts/integrations/github-api-conformance-v1.json +644 -0
  20. package/contracts/integrations/github-tool-abi-typescript-v1.json +369 -0
  21. package/contracts/integrations/github-tool-abi-v1.json +146 -0
  22. package/contracts/integrations/gmail-api-conformance-v1.json +750 -0
  23. package/contracts/integrations/gmail-tool-abi-v1.json +62 -0
  24. package/contracts/integrations/index.schema.json +37 -0
  25. package/contracts/integrations/manifest.schema.json +119 -0
  26. package/contracts/parity/expected-normalized.json +4906 -0
  27. package/contracts/parity/scenarios.json +100 -0
  28. package/contracts/parity/scenarios.schema.json +214 -0
  29. package/contracts/providers/cost-conformance.json +112 -0
  30. package/contracts/release/github-proof-v1.schema.json +138 -0
  31. package/contracts/release/gmail-proof-v1.schema.json +138 -0
  32. package/contracts/release/kaji-ts-consumer-handoff-v1.schema.json +1289 -0
  33. package/contracts/release/publisher-identity-receipt-v1.schema.json +319 -0
  34. package/contracts/release/typescript-onboarding-evidence-v1.schema.json +740 -0
  35. package/contracts/tools/conformance-invalid.json +271 -0
  36. package/contracts/tools/conformance-valid.json +78 -0
  37. package/contracts/tools/tool-schema-v1.schema.json +18 -0
  38. package/dist/anthropic.cjs +1231 -0
  39. package/dist/anthropic.cjs.map +1 -0
  40. package/dist/anthropic.d.cts +26 -0
  41. package/dist/anthropic.d.ts +26 -0
  42. package/dist/anthropic.js +270 -0
  43. package/dist/anthropic.js.map +1 -0
  44. package/dist/auth.cjs +1507 -0
  45. package/dist/auth.cjs.map +1 -0
  46. package/dist/auth.d.cts +129 -0
  47. package/dist/auth.d.ts +129 -0
  48. package/dist/auth.js +1039 -0
  49. package/dist/auth.js.map +1 -0
  50. package/dist/base-B9FRMcP8.d.cts +140 -0
  51. package/dist/base-nHQd1VtS.d.ts +140 -0
  52. package/dist/chunk-AAM33KAO.js +4367 -0
  53. package/dist/chunk-AAM33KAO.js.map +1 -0
  54. package/dist/chunk-KAJ6BM64.js +153 -0
  55. package/dist/chunk-KAJ6BM64.js.map +1 -0
  56. package/dist/chunk-KCAXIOZS.js +308 -0
  57. package/dist/chunk-KCAXIOZS.js.map +1 -0
  58. package/dist/chunk-LSJ4AVO2.js +243 -0
  59. package/dist/chunk-LSJ4AVO2.js.map +1 -0
  60. package/dist/chunk-TM7ZGOJX.js +716 -0
  61. package/dist/chunk-TM7ZGOJX.js.map +1 -0
  62. package/dist/cli/bin.d.ts +2 -0
  63. package/dist/cli/bin.js +13 -0
  64. package/dist/cli/bin.js.map +1 -0
  65. package/dist/cli/chunk-2RCWPRVY.js +6277 -0
  66. package/dist/cli/chunk-2RCWPRVY.js.map +1 -0
  67. package/dist/cli/chunk-SEBX54TR.js +681 -0
  68. package/dist/cli/chunk-SEBX54TR.js.map +1 -0
  69. package/dist/cli/index.d.ts +232 -0
  70. package/dist/cli/index.js +11 -0
  71. package/dist/cli/index.js.map +1 -0
  72. package/dist/cli/init-worker.d.ts +2 -0
  73. package/dist/cli/init-worker.js +18 -0
  74. package/dist/cli/init-worker.js.map +1 -0
  75. package/dist/cli/integration-copy-worker.js +48 -0
  76. package/dist/cli/integration-copy-worker.js.map +1 -0
  77. package/dist/cli/package-entry-cjs.cjs +21 -0
  78. package/dist/cli/package-entry-cjs.cjs.map +1 -0
  79. package/dist/cli/package-entry-cjs.d.cts +2 -0
  80. package/dist/cli/package-entry.d.ts +2 -0
  81. package/dist/cli/package-entry.js +13 -0
  82. package/dist/cli/package-entry.js.map +1 -0
  83. package/dist/context-BaFHrQHv.d.cts +21 -0
  84. package/dist/context-BaFHrQHv.d.ts +21 -0
  85. package/dist/context-C-YPY-GS.d.cts +1538 -0
  86. package/dist/context-C-YPY-GS.d.ts +1538 -0
  87. package/dist/index.cjs +12346 -0
  88. package/dist/index.cjs.map +1 -0
  89. package/dist/index.d.cts +1560 -0
  90. package/dist/index.d.ts +1560 -0
  91. package/dist/index.js +7852 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/integrations/github.cjs +2092 -0
  94. package/dist/integrations/github.cjs.map +1 -0
  95. package/dist/integrations/github.d.cts +21 -0
  96. package/dist/integrations/github.d.ts +21 -0
  97. package/dist/integrations/github.js +2088 -0
  98. package/dist/integrations/github.js.map +1 -0
  99. package/dist/integrations.cjs +3370 -0
  100. package/dist/integrations.cjs.map +1 -0
  101. package/dist/integrations.d.cts +202 -0
  102. package/dist/integrations.d.ts +202 -0
  103. package/dist/integrations.js +2650 -0
  104. package/dist/integrations.js.map +1 -0
  105. package/dist/observability-Cj--OkME.d.cts +96 -0
  106. package/dist/observability-Cj--OkME.d.ts +96 -0
  107. package/dist/openai.cjs +1235 -0
  108. package/dist/openai.cjs.map +1 -0
  109. package/dist/openai.d.cts +32 -0
  110. package/dist/openai.d.ts +32 -0
  111. package/dist/openai.js +272 -0
  112. package/dist/openai.js.map +1 -0
  113. package/dist/testing.cjs +554 -0
  114. package/dist/testing.cjs.map +1 -0
  115. package/dist/testing.d.cts +43 -0
  116. package/dist/testing.d.ts +43 -0
  117. package/dist/testing.js +118 -0
  118. package/dist/testing.js.map +1 -0
  119. package/package.json +188 -0
  120. package/registry/echo/index.ts +53 -0
  121. package/registry/echo/manifest.json +53 -0
  122. package/registry/github/LICENSE +105 -0
  123. package/registry/github/client.ts +1727 -0
  124. package/registry/github/index.ts +263 -0
  125. package/registry/github/manifest.json +227 -0
  126. package/registry/github/owner-fixtures.json +10 -0
  127. package/registry/github/tests/github.test.ts +32 -0
  128. package/registry/gmail/LICENSE +105 -0
  129. package/registry/gmail/client.ts +548 -0
  130. package/registry/gmail/index.ts +165 -0
  131. package/registry/gmail/manifest.json +102 -0
  132. package/registry/gmail/owner-fixtures.json +10 -0
  133. package/registry/gmail/tests/gmail.test.ts +32 -0
  134. package/registry/index.json +21 -0
  135. package/registry/index.schema.json +37 -0
  136. package/registry/schema.json +119 -0
@@ -0,0 +1,3370 @@
1
+ 'use strict';
2
+
3
+ var z = require('zod');
4
+ var Ajv2020 = require('ajv/dist/2020.js');
5
+ var https = require('https');
6
+
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ function _interopNamespace(e) {
10
+ if (e && e.__esModule) return e;
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var z__namespace = /*#__PURE__*/_interopNamespace(z);
28
+ var Ajv2020__default = /*#__PURE__*/_interopDefault(Ajv2020);
29
+
30
+ // src/events/errors.ts
31
+ var DURABLE_JSON_SUBJECTS = /* @__PURE__ */ new Set([
32
+ "tool_result",
33
+ "workflow_result",
34
+ "event_metadata",
35
+ "memory_document",
36
+ "pending_tool_call",
37
+ "event"
38
+ ]);
39
+ var InvalidDurableValueError = class extends Error {
40
+ constructor(subject) {
41
+ super(`Invalid durable JSON value for ${subject}`);
42
+ this.subject = subject;
43
+ this.name = "InvalidDurableValueError";
44
+ }
45
+ subject;
46
+ code = "INVALID_DURABLE_VALUE";
47
+ };
48
+ var DurableJsonLimitError = class extends Error {
49
+ constructor(subject, maxBytes) {
50
+ super(`Durable JSON value for ${subject} exceeds ${maxBytes} UTF-8 bytes`);
51
+ this.subject = subject;
52
+ this.maxBytes = maxBytes;
53
+ this.name = "DurableJsonLimitError";
54
+ }
55
+ subject;
56
+ maxBytes;
57
+ code = "EVENT_PAYLOAD_TOO_LARGE";
58
+ };
59
+ function cloneAndFreezeJson(value) {
60
+ return cloneJsonValue(value, /* @__PURE__ */ new WeakSet());
61
+ }
62
+ function canonicalJsonValue(value, subject = "JSON value") {
63
+ const ancestors = /* @__PURE__ */ new WeakSet();
64
+ const assertUnicodeScalarString = (text) => {
65
+ for (let index = 0; index < text.length; index += 1) {
66
+ const unit = text.charCodeAt(index);
67
+ if (unit >= 55296 && unit <= 56319) {
68
+ const next = text.charCodeAt(index + 1);
69
+ if (!(next >= 56320 && next <= 57343)) {
70
+ throw new TypeError(`${subject} contains an unpaired Unicode surrogate`);
71
+ }
72
+ index += 1;
73
+ } else if (unit >= 56320 && unit <= 57343) {
74
+ throw new TypeError(`${subject} contains an unpaired Unicode surrogate`);
75
+ }
76
+ }
77
+ };
78
+ const encode = (item) => {
79
+ if (item === null) return "null";
80
+ switch (typeof item) {
81
+ case "boolean":
82
+ return item ? "true" : "false";
83
+ case "string":
84
+ assertUnicodeScalarString(item);
85
+ return JSON.stringify(item);
86
+ case "number":
87
+ if (!Number.isFinite(item)) throw new TypeError(`${subject} contains a non-finite number`);
88
+ if (Number.isInteger(item) && !Number.isSafeInteger(item)) {
89
+ throw new TypeError(`${subject} contains an integer outside the I-JSON safe range`);
90
+ }
91
+ return Object.is(item, -0) ? "0" : item.toString();
92
+ case "object": {
93
+ if (ancestors.has(item)) throw new TypeError(`${subject} must be acyclic`);
94
+ if (Object.getOwnPropertySymbols(item).length > 0) {
95
+ throw new TypeError(`${subject} JSON object keys must be strings`);
96
+ }
97
+ ancestors.add(item);
98
+ try {
99
+ if (Array.isArray(item)) {
100
+ const descriptors = Object.getOwnPropertyDescriptors(item);
101
+ const values = [];
102
+ for (let index = 0; index < item.length; index += 1) {
103
+ const descriptor = descriptors[String(index)];
104
+ if (descriptor === void 0 || !descriptor.enumerable || !("value" in descriptor)) {
105
+ throw new TypeError(`${subject} array values must be enumerable data values`);
106
+ }
107
+ values.push(encode(descriptor.value));
108
+ }
109
+ for (const key of Object.keys(descriptors)) {
110
+ if (key === "length") continue;
111
+ const index = Number(key);
112
+ if (Number.isInteger(index) && index >= 0 && index < item.length && String(index) === key) {
113
+ continue;
114
+ }
115
+ throw new TypeError(`${subject} arrays cannot carry named properties`);
116
+ }
117
+ return `[${values.join(",")}]`;
118
+ }
119
+ const prototype = Object.getPrototypeOf(item);
120
+ if (prototype !== Object.prototype && prototype !== null) {
121
+ throw new TypeError(`${subject} contains a non-plain object`);
122
+ }
123
+ const keys = Object.getOwnPropertyNames(item);
124
+ for (const key of keys) {
125
+ assertUnicodeScalarString(key);
126
+ const descriptor = Object.getOwnPropertyDescriptor(item, key);
127
+ if (descriptor === void 0 || !descriptor.enumerable || !("value" in descriptor)) {
128
+ throw new TypeError(
129
+ `${subject} JSON object properties must be enumerable data values`
130
+ );
131
+ }
132
+ }
133
+ return `{${keys.sort().map((key) => {
134
+ const descriptor = Object.getOwnPropertyDescriptor(item, key);
135
+ return `${JSON.stringify(key)}:${encode(descriptor.value)}`;
136
+ }).join(",")}}`;
137
+ } finally {
138
+ ancestors.delete(item);
139
+ }
140
+ }
141
+ default:
142
+ throw new TypeError(`${subject} contains non-JSON value ${typeof item}`);
143
+ }
144
+ };
145
+ return encode(value);
146
+ }
147
+ function durableJsonSnapshot(value, subject, maxBytes) {
148
+ if (!DURABLE_JSON_SUBJECTS.has(subject)) {
149
+ throw new RangeError("Durable JSON subject must use the closed vocabulary");
150
+ }
151
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < 0) {
152
+ throw new RangeError("maxBytes must be a non-negative safe integer");
153
+ }
154
+ let encoded;
155
+ try {
156
+ encoded = canonicalJsonValue(value, subject);
157
+ } catch {
158
+ throw new InvalidDurableValueError(subject);
159
+ }
160
+ if (new TextEncoder().encode(encoded).byteLength > maxBytes) {
161
+ throw new DurableJsonLimitError(subject, maxBytes);
162
+ }
163
+ return cloneAndFreezeJson(JSON.parse(encoded));
164
+ }
165
+ function cloneJsonValue(value, ancestors) {
166
+ if (value === null || typeof value === "string" || typeof value === "boolean") return value;
167
+ if (typeof value === "number") {
168
+ if (!Number.isFinite(value) || Number.isInteger(value) && !Number.isSafeInteger(value)) {
169
+ throw new TypeError("Event values must be JSON-safe");
170
+ }
171
+ return value;
172
+ }
173
+ if (Array.isArray(value)) {
174
+ enter(value, ancestors);
175
+ const clone = value.map((item) => cloneJsonValue(item, ancestors));
176
+ ancestors.delete(value);
177
+ return Object.freeze(clone);
178
+ }
179
+ if (typeof value === "object") {
180
+ assertJsonObject(value);
181
+ enter(value, ancestors);
182
+ const clone = {};
183
+ for (const [key, child] of Object.entries(value)) {
184
+ Object.defineProperty(clone, key, {
185
+ value: cloneJsonValue(child, ancestors),
186
+ enumerable: true,
187
+ writable: true,
188
+ configurable: true
189
+ });
190
+ }
191
+ ancestors.delete(value);
192
+ return Object.freeze(clone);
193
+ }
194
+ throw new TypeError("Event values must be JSON-safe");
195
+ }
196
+ function assertJsonObject(value) {
197
+ const prototype = Object.getPrototypeOf(value);
198
+ if (prototype !== Object.prototype && prototype !== null || Object.getOwnPropertySymbols(value).length > 0) {
199
+ throw new TypeError("Event values must be JSON-safe");
200
+ }
201
+ }
202
+ function enter(value, ancestors) {
203
+ if (ancestors.has(value)) throw new TypeError("Event values must be JSON-safe and acyclic");
204
+ ancestors.add(value);
205
+ }
206
+
207
+ // src/internal/uuid.ts
208
+ function defaultUuid() {
209
+ const c = globalThis.crypto;
210
+ if (c?.randomUUID) return c.randomUUID();
211
+ const hex = (bytes) => Math.floor(Math.random() * 16 ** (bytes * 2)).toString(16).padStart(bytes * 2, "0");
212
+ return `${hex(4)}-${hex(2)}-${hex(2)}-${hex(2)}-${hex(6)}`;
213
+ }
214
+
215
+ // src/events/types.ts
216
+ var EventType = {
217
+ SESSION_CREATED: "session.created",
218
+ SESSION_CLOSED: "session.closed",
219
+ USER_MESSAGE: "user.message",
220
+ USER_AUDIO_CHUNK: "user.audio.chunk",
221
+ TRANSCRIPT_PARTIAL: "transcript.partial",
222
+ TRANSCRIPT_FINAL: "transcript.final",
223
+ MEMORY_RETRIEVAL_STARTED: "memory.retrieval.started",
224
+ MEMORY_RETRIEVAL_COMPLETED: "memory.retrieval.completed",
225
+ AGENT_REASONING_STARTED: "agent.reasoning.started",
226
+ AGENT_MESSAGE_DELTA: "agent.message.delta",
227
+ AGENT_MESSAGE_COMPLETED: "agent.message.completed",
228
+ AGENT_TURN_EXHAUSTED: "agent.turn.exhausted",
229
+ AGENT_TURN_FAILED: "agent.turn.failed",
230
+ TOOL_CALL_REQUESTED: "tool.call.requested",
231
+ TOOL_CALL_STARTED: "tool.call.started",
232
+ TOOL_CALL_COMPLETED: "tool.call.completed",
233
+ TOOL_CALL_FAILED: "tool.call.failed",
234
+ TOOL_APPROVAL_REQUESTED: "tool.approval.requested",
235
+ TOOL_APPROVAL_APPROVED: "tool.approval.approved",
236
+ TOOL_APPROVAL_REJECTED: "tool.approval.rejected",
237
+ WORKFLOW_STARTED: "workflow.started",
238
+ WORKFLOW_COMPLETED: "workflow.completed",
239
+ WORKFLOW_FAILED: "workflow.failed",
240
+ CANCELLATION_REQUESTED: "cancellation.requested",
241
+ CANCELLATION_COMPLETED: "cancellation.completed"
242
+ };
243
+
244
+ // src/contracts/integration-recovery.ts
245
+ var DOCS = "https://kaji.dev/docs/integrations/recovery-v1";
246
+ function recovery(errorCode, recoveryCode, anchor, problem, cause, fix) {
247
+ return Object.freeze({
248
+ errorCode,
249
+ recoveryCode,
250
+ docUrl: `${DOCS}#${anchor}`,
251
+ problem,
252
+ cause,
253
+ fix
254
+ });
255
+ }
256
+ var INTEGRATION_RECOVERY = Object.freeze({
257
+ github_token_missing: recovery(
258
+ "INTEGRATION_AUTH_REQUIRED",
259
+ "CONFIGURE_GITHUB_TOKEN",
260
+ "github-token",
261
+ "GitHub authentication is required.",
262
+ "The configured GitHub token is unavailable.",
263
+ "Set the manifest-declared GitHub token environment variable and retry."
264
+ ),
265
+ gmail_grant_missing: recovery(
266
+ "INTEGRATION_AUTH_REQUIRED",
267
+ "CONNECT_GMAIL",
268
+ "gmail-grant",
269
+ "Gmail authorization is required.",
270
+ "No Gmail grant exists for this principal.",
271
+ "Use the package-qualified connect command for this runtime and principal, then retry."
272
+ ),
273
+ keychain_missing: recovery(
274
+ "INTEGRATION_AUTH_ERROR",
275
+ "RESTORE_KEYCHAIN",
276
+ "keychain-missing",
277
+ "The macOS Keychain is unavailable.",
278
+ "The Keychain command could not be found.",
279
+ "Restore `/usr/bin/security` on a supported macOS host and retry."
280
+ ),
281
+ keychain_locked: recovery(
282
+ "INTEGRATION_AUTH_ERROR",
283
+ "UNLOCK_KEYCHAIN",
284
+ "keychain-locked",
285
+ "The macOS Keychain is locked.",
286
+ "The stored integration grant cannot be read while Keychain is locked.",
287
+ "Unlock the login Keychain and retry."
288
+ ),
289
+ keychain_corrupt: recovery(
290
+ "INTEGRATION_AUTH_ERROR",
291
+ "RESET_GMAIL_GRANT",
292
+ "keychain-corrupt",
293
+ "The stored Gmail grant is invalid.",
294
+ "The Keychain entry is corrupt or incomplete.",
295
+ "Disconnect Gmail locally, then reconnect with the same principal."
296
+ ),
297
+ keychain_unsupported: recovery(
298
+ "INTEGRATION_AUTH_ERROR",
299
+ "USE_SUPPORTED_KEYCHAIN",
300
+ "keychain-unsupported",
301
+ "Secure Gmail grant storage is unsupported.",
302
+ "This host cannot provide the required macOS Keychain boundary.",
303
+ "Use a supported macOS host; do not fall back to plaintext storage."
304
+ ),
305
+ gmail_scope_drift: recovery(
306
+ "INTEGRATION_AUTH_REQUIRED",
307
+ "RECONNECT_GMAIL",
308
+ "gmail-scope-drift",
309
+ "The Gmail grant no longer has the required scopes.",
310
+ "Stored and required OAuth scopes differ.",
311
+ "Use the package-qualified connect command for this runtime and principal, then consent again."
312
+ ),
313
+ policy_rejected: recovery(
314
+ "INTEGRATION_POLICY_REJECTED",
315
+ "REVIEW_INTEGRATION_POLICY",
316
+ "policy-rejected",
317
+ "The integration request was rejected before dispatch.",
318
+ "A fixed-origin, repository, recipient, or schema policy did not match.",
319
+ "Review the integration allowlist and request shape before retrying."
320
+ ),
321
+ api_rejected: recovery(
322
+ "INTEGRATION_API_ERROR",
323
+ "REVIEW_PROVIDER_REJECTION",
324
+ "api-rejected",
325
+ "The provider rejected the integration request.",
326
+ "The provider returned a confirmed non-retryable API rejection.",
327
+ "Review the request against the provider response guidance before retrying manually."
328
+ ),
329
+ transient_read_failed: recovery(
330
+ "INTEGRATION_API_ERROR",
331
+ "RETRY_INTEGRATION_READ",
332
+ "transient-read",
333
+ "The integration read did not complete.",
334
+ "The provider returned a transient failure before any external effect.",
335
+ "Retry the idempotent read with bounded backoff."
336
+ ),
337
+ rate_limited: recovery(
338
+ "INTEGRATION_RATE_LIMITED",
339
+ "RETRY_AFTER_RATE_LIMIT",
340
+ "rate-limited",
341
+ "The provider rate limit was reached.",
342
+ "The provider confirmed that this request was rate limited.",
343
+ "Reduce parallelism and retry only after the bounded provider delay."
344
+ ),
345
+ redirect_rejected: recovery(
346
+ "INTEGRATION_REDIRECT_REJECTED",
347
+ "REJECT_PROVIDER_REDIRECT",
348
+ "redirect-rejected",
349
+ "The provider returned a redirect that Kaji will not follow.",
350
+ "Fixed-origin integration requests reject every redirect.",
351
+ "Verify the provider endpoint; do not retry an ambiguous mutation blindly."
352
+ ),
353
+ response_limit_exceeded: recovery(
354
+ "INTEGRATION_RESPONSE_LIMIT",
355
+ "REDUCE_INTEGRATION_RESPONSE",
356
+ "response-limit",
357
+ "The integration response exceeded a safety bound.",
358
+ "Provider headers or body were malformed or too large.",
359
+ "Narrow the read request; reconcile a mutation before any retry."
360
+ ),
361
+ github_mutation_unknown: recovery(
362
+ "TOOL_EXECUTION_FAILED",
363
+ "RECONCILE_GITHUB_MUTATION",
364
+ "github-mutation-unknown",
365
+ "The GitHub mutation outcome is unknown.",
366
+ "The connection failed after dispatch without a confirmed provider result.",
367
+ "Reconcile the GitHub issue or comment marker before any manual retry."
368
+ ),
369
+ gmail_mutation_unknown: recovery(
370
+ "TOOL_EXECUTION_FAILED",
371
+ "RECONCILE_GMAIL_MUTATION",
372
+ "gmail-mutation-unknown",
373
+ "The Gmail mutation outcome is unknown.",
374
+ "The connection failed after dispatch without a confirmed provider result.",
375
+ "Reconcile the Gmail draft key or sent message before any manual retry."
376
+ )
377
+ });
378
+ function recoveryForReason(reasonCode) {
379
+ const value = INTEGRATION_RECOVERY[reasonCode];
380
+ if (value === void 0) throw new TypeError("unknown integration recovery reason");
381
+ return value;
382
+ }
383
+ function closedRecoveryFields(value) {
384
+ if (typeof value !== "object" || value === null) return void 0;
385
+ const candidate = value;
386
+ if (typeof candidate.reason_code !== "string" || typeof candidate.recovery_code !== "string" || typeof candidate.doc_url !== "string") {
387
+ return void 0;
388
+ }
389
+ const recovery2 = INTEGRATION_RECOVERY[candidate.reason_code];
390
+ if (recovery2 === void 0 || recovery2.recoveryCode !== candidate.recovery_code || recovery2.docUrl !== candidate.doc_url || "error_code" in candidate && recovery2.errorCode !== candidate.error_code) {
391
+ return void 0;
392
+ }
393
+ return Object.freeze({
394
+ reason_code: candidate.reason_code,
395
+ recovery_code: candidate.recovery_code,
396
+ doc_url: candidate.doc_url
397
+ });
398
+ }
399
+ function isClosedRecoveryTuple(reasonCode, recoveryCode, docUrl, errorCode) {
400
+ if (reasonCode === void 0 && recoveryCode === void 0 && docUrl === void 0) return true;
401
+ return closedRecoveryFields({
402
+ error_code: errorCode,
403
+ reason_code: reasonCode,
404
+ recovery_code: recoveryCode,
405
+ doc_url: docUrl
406
+ }) !== void 0;
407
+ }
408
+
409
+ // contracts/events/new-kaji-event-v1.schema.json
410
+ var new_kaji_event_v1_schema_default = {
411
+ $schema: "https://json-schema.org/draft/2020-12/schema",
412
+ $id: "https://kaji.dev/contracts/events/new-kaji-event-v1.schema.json",
413
+ title: "New Kaji event",
414
+ "x-maxSerializedBytes": 1048576,
415
+ $defs: {
416
+ nonEmptyId: {
417
+ type: "string",
418
+ minLength: 1
419
+ },
420
+ integrationRecoveryFields: {
421
+ oneOf: [
422
+ { properties: { error_code: { const: "INTEGRATION_AUTH_REQUIRED" }, reason_code: { const: "github_token_missing" }, recovery_code: { const: "CONFIGURE_GITHUB_TOKEN" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#github-token" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
423
+ { properties: { error_code: { const: "INTEGRATION_AUTH_REQUIRED" }, reason_code: { const: "gmail_grant_missing" }, recovery_code: { const: "CONNECT_GMAIL" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#gmail-grant" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
424
+ { properties: { error_code: { const: "INTEGRATION_AUTH_ERROR" }, reason_code: { const: "keychain_missing" }, recovery_code: { const: "RESTORE_KEYCHAIN" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#keychain-missing" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
425
+ { properties: { error_code: { const: "INTEGRATION_AUTH_ERROR" }, reason_code: { const: "keychain_locked" }, recovery_code: { const: "UNLOCK_KEYCHAIN" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#keychain-locked" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
426
+ { properties: { error_code: { const: "INTEGRATION_AUTH_ERROR" }, reason_code: { const: "keychain_corrupt" }, recovery_code: { const: "RESET_GMAIL_GRANT" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#keychain-corrupt" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
427
+ { properties: { error_code: { const: "INTEGRATION_AUTH_ERROR" }, reason_code: { const: "keychain_unsupported" }, recovery_code: { const: "USE_SUPPORTED_KEYCHAIN" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#keychain-unsupported" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
428
+ { properties: { error_code: { const: "INTEGRATION_AUTH_REQUIRED" }, reason_code: { const: "gmail_scope_drift" }, recovery_code: { const: "RECONNECT_GMAIL" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#gmail-scope-drift" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
429
+ { properties: { error_code: { const: "INTEGRATION_POLICY_REJECTED" }, reason_code: { const: "policy_rejected" }, recovery_code: { const: "REVIEW_INTEGRATION_POLICY" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#policy-rejected" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
430
+ { properties: { error_code: { const: "INTEGRATION_API_ERROR" }, reason_code: { const: "api_rejected" }, recovery_code: { const: "REVIEW_PROVIDER_REJECTION" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#api-rejected" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
431
+ { properties: { error_code: { const: "INTEGRATION_API_ERROR" }, reason_code: { const: "transient_read_failed" }, recovery_code: { const: "RETRY_INTEGRATION_READ" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#transient-read" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
432
+ { properties: { error_code: { const: "INTEGRATION_RATE_LIMITED" }, reason_code: { const: "rate_limited" }, recovery_code: { const: "RETRY_AFTER_RATE_LIMIT" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#rate-limited" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
433
+ { properties: { error_code: { const: "INTEGRATION_REDIRECT_REJECTED" }, reason_code: { const: "redirect_rejected" }, recovery_code: { const: "REJECT_PROVIDER_REDIRECT" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#redirect-rejected" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
434
+ { properties: { error_code: { const: "INTEGRATION_RESPONSE_LIMIT" }, reason_code: { const: "response_limit_exceeded" }, recovery_code: { const: "REDUCE_INTEGRATION_RESPONSE" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#response-limit" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
435
+ { properties: { error_code: { const: "TOOL_EXECUTION_FAILED" }, reason_code: { const: "github_mutation_unknown" }, recovery_code: { const: "RECONCILE_GITHUB_MUTATION" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#github-mutation-unknown" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
436
+ { properties: { error_code: { const: "TOOL_EXECUTION_FAILED" }, reason_code: { const: "gmail_mutation_unknown" }, recovery_code: { const: "RECONCILE_GMAIL_MUTATION" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#gmail-mutation-unknown" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] }
437
+ ]
438
+ },
439
+ safeInteger: {
440
+ type: "integer",
441
+ minimum: -9007199254740991,
442
+ maximum: 9007199254740991
443
+ },
444
+ positiveInteger: {
445
+ allOf: [
446
+ {
447
+ $ref: "#/$defs/safeInteger"
448
+ },
449
+ {
450
+ minimum: 1
451
+ }
452
+ ]
453
+ },
454
+ nonNegativeInteger: {
455
+ allOf: [
456
+ {
457
+ $ref: "#/$defs/safeInteger"
458
+ },
459
+ {
460
+ minimum: 0
461
+ }
462
+ ]
463
+ },
464
+ jsonNumber: {
465
+ oneOf: [
466
+ {
467
+ $ref: "#/$defs/safeInteger"
468
+ },
469
+ {
470
+ type: "number",
471
+ not: {
472
+ type: "integer"
473
+ }
474
+ }
475
+ ]
476
+ },
477
+ nonNegativeNumber: {
478
+ allOf: [
479
+ {
480
+ $ref: "#/$defs/jsonNumber"
481
+ },
482
+ {
483
+ minimum: 0
484
+ }
485
+ ]
486
+ },
487
+ jsonValue: {
488
+ oneOf: [
489
+ {
490
+ type: "null"
491
+ },
492
+ {
493
+ type: "boolean"
494
+ },
495
+ {
496
+ $ref: "#/$defs/jsonNumber"
497
+ },
498
+ {
499
+ type: "string"
500
+ },
501
+ {
502
+ type: "array",
503
+ items: {
504
+ $ref: "#/$defs/jsonValue"
505
+ }
506
+ },
507
+ {
508
+ type: "object",
509
+ additionalProperties: {
510
+ $ref: "#/$defs/jsonValue"
511
+ }
512
+ }
513
+ ]
514
+ },
515
+ jsonObject: {
516
+ type: "object",
517
+ additionalProperties: {
518
+ $ref: "#/$defs/jsonValue"
519
+ }
520
+ },
521
+ tokenUsage: {
522
+ type: "object",
523
+ properties: {
524
+ input: {
525
+ $ref: "#/$defs/nonNegativeInteger"
526
+ },
527
+ output: {
528
+ $ref: "#/$defs/nonNegativeInteger"
529
+ }
530
+ },
531
+ required: [
532
+ "input",
533
+ "output"
534
+ ],
535
+ additionalProperties: false
536
+ },
537
+ base: {
538
+ type: "object",
539
+ properties: {
540
+ id: {
541
+ $ref: "#/$defs/nonEmptyId"
542
+ },
543
+ version: {
544
+ const: "1.0"
545
+ },
546
+ timestamp: {
547
+ $ref: "#/$defs/jsonNumber"
548
+ },
549
+ session_id: {
550
+ $ref: "#/$defs/nonEmptyId"
551
+ },
552
+ turn_id: {
553
+ $ref: "#/$defs/nonEmptyId"
554
+ },
555
+ metadata: {
556
+ $ref: "#/$defs/jsonObject"
557
+ }
558
+ },
559
+ required: [
560
+ "id",
561
+ "version",
562
+ "timestamp",
563
+ "session_id"
564
+ ]
565
+ },
566
+ sessionCreated: {
567
+ allOf: [
568
+ {
569
+ $ref: "#/$defs/base"
570
+ },
571
+ {
572
+ type: "object",
573
+ properties: {
574
+ type: {
575
+ const: "session.created"
576
+ }
577
+ },
578
+ required: [
579
+ "type"
580
+ ]
581
+ }
582
+ ],
583
+ unevaluatedProperties: false
584
+ },
585
+ sessionClosed: {
586
+ allOf: [
587
+ {
588
+ $ref: "#/$defs/base"
589
+ },
590
+ {
591
+ type: "object",
592
+ properties: {
593
+ type: {
594
+ const: "session.closed"
595
+ },
596
+ reason: {
597
+ type: [
598
+ "string",
599
+ "null"
600
+ ]
601
+ }
602
+ },
603
+ required: [
604
+ "type"
605
+ ]
606
+ }
607
+ ],
608
+ unevaluatedProperties: false
609
+ },
610
+ userMessage: {
611
+ allOf: [
612
+ {
613
+ $ref: "#/$defs/base"
614
+ },
615
+ {
616
+ type: "object",
617
+ properties: {
618
+ type: {
619
+ const: "user.message"
620
+ },
621
+ content: {
622
+ type: "string"
623
+ }
624
+ },
625
+ required: [
626
+ "type",
627
+ "content"
628
+ ]
629
+ }
630
+ ],
631
+ unevaluatedProperties: false
632
+ },
633
+ userAudioChunk: {
634
+ allOf: [
635
+ {
636
+ $ref: "#/$defs/base"
637
+ },
638
+ {
639
+ type: "object",
640
+ properties: {
641
+ type: {
642
+ const: "user.audio.chunk"
643
+ },
644
+ chunk_size_bytes: {
645
+ $ref: "#/$defs/safeInteger"
646
+ }
647
+ },
648
+ required: [
649
+ "type",
650
+ "chunk_size_bytes"
651
+ ]
652
+ }
653
+ ],
654
+ unevaluatedProperties: false
655
+ },
656
+ transcriptPartial: {
657
+ allOf: [
658
+ {
659
+ $ref: "#/$defs/base"
660
+ },
661
+ {
662
+ type: "object",
663
+ properties: {
664
+ type: {
665
+ const: "transcript.partial"
666
+ },
667
+ text: {
668
+ type: "string"
669
+ }
670
+ },
671
+ required: [
672
+ "type",
673
+ "text"
674
+ ]
675
+ }
676
+ ],
677
+ unevaluatedProperties: false
678
+ },
679
+ transcriptFinal: {
680
+ allOf: [
681
+ {
682
+ $ref: "#/$defs/base"
683
+ },
684
+ {
685
+ type: "object",
686
+ properties: {
687
+ type: {
688
+ const: "transcript.final"
689
+ },
690
+ text: {
691
+ type: "string"
692
+ }
693
+ },
694
+ required: [
695
+ "type",
696
+ "text"
697
+ ]
698
+ }
699
+ ],
700
+ unevaluatedProperties: false
701
+ },
702
+ memoryRetrievalStarted: {
703
+ allOf: [
704
+ {
705
+ $ref: "#/$defs/base"
706
+ },
707
+ {
708
+ type: "object",
709
+ properties: {
710
+ type: {
711
+ const: "memory.retrieval.started"
712
+ },
713
+ query: {
714
+ type: "string"
715
+ }
716
+ },
717
+ required: [
718
+ "type",
719
+ "query"
720
+ ]
721
+ }
722
+ ],
723
+ unevaluatedProperties: false
724
+ },
725
+ memoryRetrievalCompleted: {
726
+ allOf: [
727
+ {
728
+ $ref: "#/$defs/base"
729
+ },
730
+ {
731
+ type: "object",
732
+ properties: {
733
+ type: {
734
+ const: "memory.retrieval.completed"
735
+ },
736
+ query: {
737
+ type: "string"
738
+ },
739
+ documents: {
740
+ type: "array",
741
+ items: {
742
+ $ref: "#/$defs/jsonObject"
743
+ }
744
+ }
745
+ },
746
+ required: [
747
+ "type",
748
+ "query",
749
+ "documents"
750
+ ]
751
+ }
752
+ ],
753
+ unevaluatedProperties: false
754
+ },
755
+ agentReasoningStarted: {
756
+ allOf: [
757
+ {
758
+ $ref: "#/$defs/base"
759
+ },
760
+ {
761
+ type: "object",
762
+ properties: {
763
+ type: {
764
+ const: "agent.reasoning.started"
765
+ }
766
+ },
767
+ required: [
768
+ "type"
769
+ ]
770
+ }
771
+ ],
772
+ unevaluatedProperties: false
773
+ },
774
+ agentMessageDelta: {
775
+ allOf: [
776
+ {
777
+ $ref: "#/$defs/base"
778
+ },
779
+ {
780
+ type: "object",
781
+ properties: {
782
+ type: {
783
+ const: "agent.message.delta"
784
+ },
785
+ delta: {
786
+ type: "string"
787
+ }
788
+ },
789
+ required: [
790
+ "type",
791
+ "delta"
792
+ ]
793
+ }
794
+ ],
795
+ unevaluatedProperties: false
796
+ },
797
+ agentMessageCompleted: {
798
+ allOf: [
799
+ {
800
+ $ref: "#/$defs/base"
801
+ },
802
+ {
803
+ type: "object",
804
+ properties: {
805
+ type: {
806
+ const: "agent.message.completed"
807
+ },
808
+ content: {
809
+ type: "string"
810
+ },
811
+ tokens: {
812
+ oneOf: [
813
+ { $ref: "#/$defs/tokenUsage" },
814
+ { type: "null" }
815
+ ]
816
+ },
817
+ cost_usd: {
818
+ oneOf: [
819
+ { $ref: "#/$defs/nonNegativeNumber" },
820
+ { type: "null" }
821
+ ]
822
+ }
823
+ },
824
+ required: [
825
+ "type",
826
+ "content"
827
+ ]
828
+ }
829
+ ],
830
+ unevaluatedProperties: false
831
+ },
832
+ agentTurnExhausted: {
833
+ allOf: [
834
+ {
835
+ $ref: "#/$defs/base"
836
+ },
837
+ {
838
+ type: "object",
839
+ properties: {
840
+ type: {
841
+ const: "agent.turn.exhausted"
842
+ },
843
+ max_iterations: {
844
+ $ref: "#/$defs/nonNegativeInteger"
845
+ },
846
+ pending_tool_calls: {
847
+ type: "array",
848
+ items: {
849
+ $ref: "#/$defs/jsonObject"
850
+ }
851
+ },
852
+ reason: {
853
+ type: [
854
+ "string",
855
+ "null"
856
+ ]
857
+ }
858
+ },
859
+ required: [
860
+ "type",
861
+ "max_iterations",
862
+ "pending_tool_calls"
863
+ ]
864
+ }
865
+ ],
866
+ unevaluatedProperties: false
867
+ },
868
+ agentTurnFailed: {
869
+ allOf: [
870
+ {
871
+ $ref: "#/$defs/base"
872
+ },
873
+ {
874
+ type: "object",
875
+ properties: {
876
+ type: {
877
+ const: "agent.turn.failed"
878
+ },
879
+ turn_id: {
880
+ $ref: "#/$defs/nonEmptyId"
881
+ },
882
+ error: {
883
+ type: "string",
884
+ minLength: 1,
885
+ maxLength: 200
886
+ },
887
+ error_code: {
888
+ type: "string"
889
+ },
890
+ phase: {
891
+ enum: [
892
+ "queue",
893
+ "provider_open",
894
+ "provider_stream",
895
+ "approval",
896
+ "tool"
897
+ ]
898
+ },
899
+ retryable: {
900
+ type: "boolean"
901
+ },
902
+ outcome: {
903
+ enum: [
904
+ "not_started",
905
+ "failed",
906
+ "unknown"
907
+ ]
908
+ }
909
+ },
910
+ required: [
911
+ "type",
912
+ "turn_id",
913
+ "error"
914
+ ]
915
+ }
916
+ ],
917
+ unevaluatedProperties: false
918
+ },
919
+ toolCallRequested: {
920
+ allOf: [
921
+ {
922
+ $ref: "#/$defs/base"
923
+ },
924
+ {
925
+ type: "object",
926
+ properties: {
927
+ type: {
928
+ const: "tool.call.requested"
929
+ },
930
+ turn_id: {
931
+ $ref: "#/$defs/nonEmptyId"
932
+ },
933
+ tool_name: {
934
+ $ref: "#/$defs/nonEmptyId"
935
+ },
936
+ tool_args: {
937
+ $ref: "#/$defs/jsonObject",
938
+ "x-maxSerializedBytes": 65536
939
+ },
940
+ tool_call_id: {
941
+ $ref: "#/$defs/nonEmptyId"
942
+ }
943
+ },
944
+ required: [
945
+ "type",
946
+ "turn_id",
947
+ "tool_name",
948
+ "tool_args",
949
+ "tool_call_id"
950
+ ]
951
+ }
952
+ ],
953
+ unevaluatedProperties: false
954
+ },
955
+ toolCallStarted: {
956
+ allOf: [
957
+ {
958
+ $ref: "#/$defs/base"
959
+ },
960
+ {
961
+ type: "object",
962
+ properties: {
963
+ type: {
964
+ const: "tool.call.started"
965
+ },
966
+ turn_id: {
967
+ $ref: "#/$defs/nonEmptyId"
968
+ },
969
+ tool_name: {
970
+ $ref: "#/$defs/nonEmptyId"
971
+ },
972
+ tool_call_id: {
973
+ $ref: "#/$defs/nonEmptyId"
974
+ }
975
+ },
976
+ required: [
977
+ "type",
978
+ "turn_id",
979
+ "tool_name",
980
+ "tool_call_id"
981
+ ]
982
+ }
983
+ ],
984
+ unevaluatedProperties: false
985
+ },
986
+ toolCallCompleted: {
987
+ allOf: [
988
+ {
989
+ $ref: "#/$defs/base"
990
+ },
991
+ {
992
+ type: "object",
993
+ properties: {
994
+ type: {
995
+ const: "tool.call.completed"
996
+ },
997
+ turn_id: {
998
+ $ref: "#/$defs/nonEmptyId"
999
+ },
1000
+ tool_name: {
1001
+ $ref: "#/$defs/nonEmptyId"
1002
+ },
1003
+ tool_call_id: {
1004
+ $ref: "#/$defs/nonEmptyId"
1005
+ },
1006
+ result: {
1007
+ $ref: "#/$defs/jsonValue",
1008
+ "x-maxSerializedBytes": 65536
1009
+ },
1010
+ tokens: {
1011
+ oneOf: [
1012
+ { $ref: "#/$defs/tokenUsage" },
1013
+ { type: "null" }
1014
+ ]
1015
+ },
1016
+ cost_usd: {
1017
+ oneOf: [
1018
+ { $ref: "#/$defs/nonNegativeNumber" },
1019
+ { type: "null" }
1020
+ ]
1021
+ }
1022
+ },
1023
+ required: [
1024
+ "type",
1025
+ "turn_id",
1026
+ "tool_name",
1027
+ "tool_call_id",
1028
+ "result"
1029
+ ]
1030
+ }
1031
+ ],
1032
+ unevaluatedProperties: false
1033
+ },
1034
+ toolCallFailed: {
1035
+ allOf: [
1036
+ {
1037
+ $ref: "#/$defs/base"
1038
+ },
1039
+ {
1040
+ type: "object",
1041
+ properties: {
1042
+ type: {
1043
+ const: "tool.call.failed"
1044
+ },
1045
+ turn_id: {
1046
+ $ref: "#/$defs/nonEmptyId"
1047
+ },
1048
+ tool_name: {
1049
+ $ref: "#/$defs/nonEmptyId"
1050
+ },
1051
+ tool_call_id: {
1052
+ $ref: "#/$defs/nonEmptyId"
1053
+ },
1054
+ error: {
1055
+ type: "string",
1056
+ minLength: 1,
1057
+ maxLength: 200
1058
+ },
1059
+ error_code: {
1060
+ type: "string"
1061
+ },
1062
+ error_path: {
1063
+ type: "string"
1064
+ },
1065
+ retryable: {
1066
+ type: "boolean"
1067
+ },
1068
+ outcome: {
1069
+ enum: [
1070
+ "not_started",
1071
+ "failed",
1072
+ "unknown"
1073
+ ]
1074
+ },
1075
+ reason_code: {
1076
+ type: "string"
1077
+ },
1078
+ recovery_code: {
1079
+ type: "string"
1080
+ },
1081
+ doc_url: {
1082
+ type: "string"
1083
+ }
1084
+ },
1085
+ required: [
1086
+ "type",
1087
+ "turn_id",
1088
+ "tool_name",
1089
+ "tool_call_id",
1090
+ "error"
1091
+ ]
1092
+ },
1093
+ {
1094
+ if: {
1095
+ anyOf: [
1096
+ { required: ["reason_code"] },
1097
+ { required: ["recovery_code"] },
1098
+ { required: ["doc_url"] }
1099
+ ]
1100
+ },
1101
+ then: {
1102
+ $ref: "#/$defs/integrationRecoveryFields"
1103
+ }
1104
+ }
1105
+ ],
1106
+ unevaluatedProperties: false
1107
+ },
1108
+ toolApprovalRequested: {
1109
+ allOf: [
1110
+ {
1111
+ $ref: "#/$defs/base"
1112
+ },
1113
+ {
1114
+ type: "object",
1115
+ properties: {
1116
+ type: {
1117
+ const: "tool.approval.requested"
1118
+ },
1119
+ turn_id: {
1120
+ $ref: "#/$defs/nonEmptyId"
1121
+ },
1122
+ tool_name: {
1123
+ $ref: "#/$defs/nonEmptyId"
1124
+ },
1125
+ tool_call_id: {
1126
+ $ref: "#/$defs/nonEmptyId"
1127
+ },
1128
+ tool_args: {
1129
+ $ref: "#/$defs/jsonObject",
1130
+ "x-maxSerializedBytes": 65536
1131
+ },
1132
+ risk: {
1133
+ enum: [
1134
+ "read",
1135
+ "write",
1136
+ "external_effect",
1137
+ "destructive",
1138
+ "admin"
1139
+ ]
1140
+ }
1141
+ },
1142
+ required: [
1143
+ "type",
1144
+ "turn_id",
1145
+ "tool_name",
1146
+ "tool_call_id",
1147
+ "tool_args",
1148
+ "risk"
1149
+ ]
1150
+ }
1151
+ ],
1152
+ unevaluatedProperties: false
1153
+ },
1154
+ toolApprovalApproved: {
1155
+ allOf: [
1156
+ {
1157
+ $ref: "#/$defs/base"
1158
+ },
1159
+ {
1160
+ type: "object",
1161
+ properties: {
1162
+ type: {
1163
+ const: "tool.approval.approved"
1164
+ },
1165
+ turn_id: {
1166
+ $ref: "#/$defs/nonEmptyId"
1167
+ },
1168
+ tool_name: {
1169
+ $ref: "#/$defs/nonEmptyId"
1170
+ },
1171
+ tool_call_id: {
1172
+ $ref: "#/$defs/nonEmptyId"
1173
+ }
1174
+ },
1175
+ required: [
1176
+ "type",
1177
+ "turn_id",
1178
+ "tool_name",
1179
+ "tool_call_id"
1180
+ ]
1181
+ }
1182
+ ],
1183
+ unevaluatedProperties: false
1184
+ },
1185
+ toolApprovalRejected: {
1186
+ allOf: [
1187
+ {
1188
+ $ref: "#/$defs/base"
1189
+ },
1190
+ {
1191
+ type: "object",
1192
+ properties: {
1193
+ type: {
1194
+ const: "tool.approval.rejected"
1195
+ },
1196
+ turn_id: {
1197
+ $ref: "#/$defs/nonEmptyId"
1198
+ },
1199
+ tool_name: {
1200
+ $ref: "#/$defs/nonEmptyId"
1201
+ },
1202
+ tool_call_id: {
1203
+ $ref: "#/$defs/nonEmptyId"
1204
+ },
1205
+ error_code: {
1206
+ enum: [
1207
+ "APPROVAL_REJECTED",
1208
+ "APPROVAL_TIMEOUT",
1209
+ "TURN_TIMEOUT",
1210
+ "TOOL_CANCELLED",
1211
+ "APPROVAL_UNAVAILABLE"
1212
+ ]
1213
+ },
1214
+ reason: {
1215
+ type: "string",
1216
+ minLength: 1,
1217
+ maxLength: 200,
1218
+ pattern: "\\S"
1219
+ }
1220
+ },
1221
+ required: [
1222
+ "type",
1223
+ "turn_id",
1224
+ "tool_name",
1225
+ "tool_call_id",
1226
+ "error_code",
1227
+ "reason"
1228
+ ]
1229
+ }
1230
+ ],
1231
+ unevaluatedProperties: false
1232
+ },
1233
+ workflowStarted: {
1234
+ allOf: [
1235
+ {
1236
+ $ref: "#/$defs/base"
1237
+ },
1238
+ {
1239
+ type: "object",
1240
+ properties: {
1241
+ type: {
1242
+ const: "workflow.started"
1243
+ },
1244
+ workflow_name: {
1245
+ type: "string"
1246
+ }
1247
+ },
1248
+ required: [
1249
+ "type",
1250
+ "workflow_name"
1251
+ ]
1252
+ }
1253
+ ],
1254
+ unevaluatedProperties: false
1255
+ },
1256
+ workflowCompleted: {
1257
+ allOf: [
1258
+ {
1259
+ $ref: "#/$defs/base"
1260
+ },
1261
+ {
1262
+ type: "object",
1263
+ properties: {
1264
+ type: {
1265
+ const: "workflow.completed"
1266
+ },
1267
+ workflow_name: {
1268
+ type: "string"
1269
+ },
1270
+ result: {
1271
+ $ref: "#/$defs/jsonValue"
1272
+ }
1273
+ },
1274
+ required: [
1275
+ "type",
1276
+ "workflow_name",
1277
+ "result"
1278
+ ]
1279
+ }
1280
+ ],
1281
+ unevaluatedProperties: false
1282
+ },
1283
+ workflowFailed: {
1284
+ allOf: [
1285
+ {
1286
+ $ref: "#/$defs/base"
1287
+ },
1288
+ {
1289
+ type: "object",
1290
+ properties: {
1291
+ type: {
1292
+ const: "workflow.failed"
1293
+ },
1294
+ workflow_name: {
1295
+ type: "string"
1296
+ },
1297
+ error: {
1298
+ type: "string"
1299
+ }
1300
+ },
1301
+ required: [
1302
+ "type",
1303
+ "workflow_name",
1304
+ "error"
1305
+ ]
1306
+ }
1307
+ ],
1308
+ unevaluatedProperties: false
1309
+ },
1310
+ cancellationRequested: {
1311
+ allOf: [
1312
+ {
1313
+ $ref: "#/$defs/base"
1314
+ },
1315
+ {
1316
+ type: "object",
1317
+ properties: {
1318
+ type: {
1319
+ const: "cancellation.requested"
1320
+ },
1321
+ reason: {
1322
+ type: "string"
1323
+ }
1324
+ },
1325
+ required: [
1326
+ "type",
1327
+ "reason"
1328
+ ]
1329
+ }
1330
+ ],
1331
+ unevaluatedProperties: false
1332
+ },
1333
+ cancellationCompleted: {
1334
+ allOf: [
1335
+ {
1336
+ $ref: "#/$defs/base"
1337
+ },
1338
+ {
1339
+ type: "object",
1340
+ properties: {
1341
+ type: {
1342
+ const: "cancellation.completed"
1343
+ }
1344
+ },
1345
+ required: [
1346
+ "type"
1347
+ ]
1348
+ }
1349
+ ],
1350
+ unevaluatedProperties: false
1351
+ }
1352
+ },
1353
+ oneOf: [
1354
+ {
1355
+ $ref: "#/$defs/sessionCreated"
1356
+ },
1357
+ {
1358
+ $ref: "#/$defs/sessionClosed"
1359
+ },
1360
+ {
1361
+ $ref: "#/$defs/userMessage"
1362
+ },
1363
+ {
1364
+ $ref: "#/$defs/userAudioChunk"
1365
+ },
1366
+ {
1367
+ $ref: "#/$defs/transcriptPartial"
1368
+ },
1369
+ {
1370
+ $ref: "#/$defs/transcriptFinal"
1371
+ },
1372
+ {
1373
+ $ref: "#/$defs/memoryRetrievalStarted"
1374
+ },
1375
+ {
1376
+ $ref: "#/$defs/memoryRetrievalCompleted"
1377
+ },
1378
+ {
1379
+ $ref: "#/$defs/agentReasoningStarted"
1380
+ },
1381
+ {
1382
+ $ref: "#/$defs/agentMessageDelta"
1383
+ },
1384
+ {
1385
+ $ref: "#/$defs/agentMessageCompleted"
1386
+ },
1387
+ {
1388
+ $ref: "#/$defs/agentTurnExhausted"
1389
+ },
1390
+ {
1391
+ $ref: "#/$defs/agentTurnFailed"
1392
+ },
1393
+ {
1394
+ $ref: "#/$defs/toolCallRequested"
1395
+ },
1396
+ {
1397
+ $ref: "#/$defs/toolCallStarted"
1398
+ },
1399
+ {
1400
+ $ref: "#/$defs/toolCallCompleted"
1401
+ },
1402
+ {
1403
+ $ref: "#/$defs/toolCallFailed"
1404
+ },
1405
+ {
1406
+ $ref: "#/$defs/toolApprovalRequested"
1407
+ },
1408
+ {
1409
+ $ref: "#/$defs/toolApprovalApproved"
1410
+ },
1411
+ {
1412
+ $ref: "#/$defs/toolApprovalRejected"
1413
+ },
1414
+ {
1415
+ $ref: "#/$defs/workflowStarted"
1416
+ },
1417
+ {
1418
+ $ref: "#/$defs/workflowCompleted"
1419
+ },
1420
+ {
1421
+ $ref: "#/$defs/workflowFailed"
1422
+ },
1423
+ {
1424
+ $ref: "#/$defs/cancellationRequested"
1425
+ },
1426
+ {
1427
+ $ref: "#/$defs/cancellationCompleted"
1428
+ }
1429
+ ]
1430
+ };
1431
+
1432
+ // contracts/events/stored-kaji-event-v1.schema.json
1433
+ var stored_kaji_event_v1_schema_default = {
1434
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1435
+ $id: "https://kaji.dev/contracts/events/stored-kaji-event-v1.schema.json",
1436
+ title: "Stored Kaji event",
1437
+ "x-maxSerializedBytes": 1048576,
1438
+ $defs: {
1439
+ nonEmptyId: {
1440
+ type: "string",
1441
+ minLength: 1
1442
+ },
1443
+ integrationRecoveryFields: {
1444
+ oneOf: [
1445
+ { properties: { error_code: { const: "INTEGRATION_AUTH_REQUIRED" }, reason_code: { const: "github_token_missing" }, recovery_code: { const: "CONFIGURE_GITHUB_TOKEN" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#github-token" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1446
+ { properties: { error_code: { const: "INTEGRATION_AUTH_REQUIRED" }, reason_code: { const: "gmail_grant_missing" }, recovery_code: { const: "CONNECT_GMAIL" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#gmail-grant" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1447
+ { properties: { error_code: { const: "INTEGRATION_AUTH_ERROR" }, reason_code: { const: "keychain_missing" }, recovery_code: { const: "RESTORE_KEYCHAIN" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#keychain-missing" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1448
+ { properties: { error_code: { const: "INTEGRATION_AUTH_ERROR" }, reason_code: { const: "keychain_locked" }, recovery_code: { const: "UNLOCK_KEYCHAIN" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#keychain-locked" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1449
+ { properties: { error_code: { const: "INTEGRATION_AUTH_ERROR" }, reason_code: { const: "keychain_corrupt" }, recovery_code: { const: "RESET_GMAIL_GRANT" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#keychain-corrupt" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1450
+ { properties: { error_code: { const: "INTEGRATION_AUTH_ERROR" }, reason_code: { const: "keychain_unsupported" }, recovery_code: { const: "USE_SUPPORTED_KEYCHAIN" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#keychain-unsupported" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1451
+ { properties: { error_code: { const: "INTEGRATION_AUTH_REQUIRED" }, reason_code: { const: "gmail_scope_drift" }, recovery_code: { const: "RECONNECT_GMAIL" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#gmail-scope-drift" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1452
+ { properties: { error_code: { const: "INTEGRATION_POLICY_REJECTED" }, reason_code: { const: "policy_rejected" }, recovery_code: { const: "REVIEW_INTEGRATION_POLICY" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#policy-rejected" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1453
+ { properties: { error_code: { const: "INTEGRATION_API_ERROR" }, reason_code: { const: "api_rejected" }, recovery_code: { const: "REVIEW_PROVIDER_REJECTION" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#api-rejected" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1454
+ { properties: { error_code: { const: "INTEGRATION_API_ERROR" }, reason_code: { const: "transient_read_failed" }, recovery_code: { const: "RETRY_INTEGRATION_READ" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#transient-read" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1455
+ { properties: { error_code: { const: "INTEGRATION_RATE_LIMITED" }, reason_code: { const: "rate_limited" }, recovery_code: { const: "RETRY_AFTER_RATE_LIMIT" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#rate-limited" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1456
+ { properties: { error_code: { const: "INTEGRATION_REDIRECT_REJECTED" }, reason_code: { const: "redirect_rejected" }, recovery_code: { const: "REJECT_PROVIDER_REDIRECT" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#redirect-rejected" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1457
+ { properties: { error_code: { const: "INTEGRATION_RESPONSE_LIMIT" }, reason_code: { const: "response_limit_exceeded" }, recovery_code: { const: "REDUCE_INTEGRATION_RESPONSE" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#response-limit" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1458
+ { properties: { error_code: { const: "TOOL_EXECUTION_FAILED" }, reason_code: { const: "github_mutation_unknown" }, recovery_code: { const: "RECONCILE_GITHUB_MUTATION" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#github-mutation-unknown" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] },
1459
+ { properties: { error_code: { const: "TOOL_EXECUTION_FAILED" }, reason_code: { const: "gmail_mutation_unknown" }, recovery_code: { const: "RECONCILE_GMAIL_MUTATION" }, doc_url: { const: "https://kaji.dev/docs/integrations/recovery-v1#gmail-mutation-unknown" } }, required: ["error_code", "reason_code", "recovery_code", "doc_url"] }
1460
+ ]
1461
+ },
1462
+ safeInteger: {
1463
+ type: "integer",
1464
+ minimum: -9007199254740991,
1465
+ maximum: 9007199254740991
1466
+ },
1467
+ positiveInteger: {
1468
+ allOf: [
1469
+ {
1470
+ $ref: "#/$defs/safeInteger"
1471
+ },
1472
+ {
1473
+ minimum: 1
1474
+ }
1475
+ ]
1476
+ },
1477
+ nonNegativeInteger: {
1478
+ allOf: [
1479
+ {
1480
+ $ref: "#/$defs/safeInteger"
1481
+ },
1482
+ {
1483
+ minimum: 0
1484
+ }
1485
+ ]
1486
+ },
1487
+ jsonNumber: {
1488
+ oneOf: [
1489
+ {
1490
+ $ref: "#/$defs/safeInteger"
1491
+ },
1492
+ {
1493
+ type: "number",
1494
+ not: {
1495
+ type: "integer"
1496
+ }
1497
+ }
1498
+ ]
1499
+ },
1500
+ nonNegativeNumber: {
1501
+ allOf: [
1502
+ {
1503
+ $ref: "#/$defs/jsonNumber"
1504
+ },
1505
+ {
1506
+ minimum: 0
1507
+ }
1508
+ ]
1509
+ },
1510
+ jsonValue: {
1511
+ oneOf: [
1512
+ {
1513
+ type: "null"
1514
+ },
1515
+ {
1516
+ type: "boolean"
1517
+ },
1518
+ {
1519
+ $ref: "#/$defs/jsonNumber"
1520
+ },
1521
+ {
1522
+ type: "string"
1523
+ },
1524
+ {
1525
+ type: "array",
1526
+ items: {
1527
+ $ref: "#/$defs/jsonValue"
1528
+ }
1529
+ },
1530
+ {
1531
+ type: "object",
1532
+ additionalProperties: {
1533
+ $ref: "#/$defs/jsonValue"
1534
+ }
1535
+ }
1536
+ ]
1537
+ },
1538
+ jsonObject: {
1539
+ type: "object",
1540
+ additionalProperties: {
1541
+ $ref: "#/$defs/jsonValue"
1542
+ }
1543
+ },
1544
+ tokenUsage: {
1545
+ type: "object",
1546
+ properties: {
1547
+ input: {
1548
+ $ref: "#/$defs/nonNegativeInteger"
1549
+ },
1550
+ output: {
1551
+ $ref: "#/$defs/nonNegativeInteger"
1552
+ }
1553
+ },
1554
+ required: [
1555
+ "input",
1556
+ "output"
1557
+ ],
1558
+ additionalProperties: false
1559
+ },
1560
+ base: {
1561
+ type: "object",
1562
+ properties: {
1563
+ id: {
1564
+ $ref: "#/$defs/nonEmptyId"
1565
+ },
1566
+ version: {
1567
+ const: "1.0"
1568
+ },
1569
+ timestamp: {
1570
+ $ref: "#/$defs/jsonNumber"
1571
+ },
1572
+ session_id: {
1573
+ $ref: "#/$defs/nonEmptyId"
1574
+ },
1575
+ turn_id: {
1576
+ $ref: "#/$defs/nonEmptyId"
1577
+ },
1578
+ metadata: {
1579
+ $ref: "#/$defs/jsonObject"
1580
+ },
1581
+ sequence: {
1582
+ $ref: "#/$defs/positiveInteger"
1583
+ }
1584
+ },
1585
+ required: [
1586
+ "id",
1587
+ "version",
1588
+ "timestamp",
1589
+ "session_id",
1590
+ "sequence"
1591
+ ]
1592
+ },
1593
+ sessionCreated: {
1594
+ allOf: [
1595
+ {
1596
+ $ref: "#/$defs/base"
1597
+ },
1598
+ {
1599
+ type: "object",
1600
+ properties: {
1601
+ type: {
1602
+ const: "session.created"
1603
+ }
1604
+ },
1605
+ required: [
1606
+ "type"
1607
+ ]
1608
+ }
1609
+ ],
1610
+ unevaluatedProperties: false
1611
+ },
1612
+ sessionClosed: {
1613
+ allOf: [
1614
+ {
1615
+ $ref: "#/$defs/base"
1616
+ },
1617
+ {
1618
+ type: "object",
1619
+ properties: {
1620
+ type: {
1621
+ const: "session.closed"
1622
+ },
1623
+ reason: {
1624
+ type: [
1625
+ "string",
1626
+ "null"
1627
+ ]
1628
+ }
1629
+ },
1630
+ required: [
1631
+ "type"
1632
+ ]
1633
+ }
1634
+ ],
1635
+ unevaluatedProperties: false
1636
+ },
1637
+ userMessage: {
1638
+ allOf: [
1639
+ {
1640
+ $ref: "#/$defs/base"
1641
+ },
1642
+ {
1643
+ type: "object",
1644
+ properties: {
1645
+ type: {
1646
+ const: "user.message"
1647
+ },
1648
+ content: {
1649
+ type: "string"
1650
+ }
1651
+ },
1652
+ required: [
1653
+ "type",
1654
+ "content"
1655
+ ]
1656
+ }
1657
+ ],
1658
+ unevaluatedProperties: false
1659
+ },
1660
+ userAudioChunk: {
1661
+ allOf: [
1662
+ {
1663
+ $ref: "#/$defs/base"
1664
+ },
1665
+ {
1666
+ type: "object",
1667
+ properties: {
1668
+ type: {
1669
+ const: "user.audio.chunk"
1670
+ },
1671
+ chunk_size_bytes: {
1672
+ $ref: "#/$defs/safeInteger"
1673
+ }
1674
+ },
1675
+ required: [
1676
+ "type",
1677
+ "chunk_size_bytes"
1678
+ ]
1679
+ }
1680
+ ],
1681
+ unevaluatedProperties: false
1682
+ },
1683
+ transcriptPartial: {
1684
+ allOf: [
1685
+ {
1686
+ $ref: "#/$defs/base"
1687
+ },
1688
+ {
1689
+ type: "object",
1690
+ properties: {
1691
+ type: {
1692
+ const: "transcript.partial"
1693
+ },
1694
+ text: {
1695
+ type: "string"
1696
+ }
1697
+ },
1698
+ required: [
1699
+ "type",
1700
+ "text"
1701
+ ]
1702
+ }
1703
+ ],
1704
+ unevaluatedProperties: false
1705
+ },
1706
+ transcriptFinal: {
1707
+ allOf: [
1708
+ {
1709
+ $ref: "#/$defs/base"
1710
+ },
1711
+ {
1712
+ type: "object",
1713
+ properties: {
1714
+ type: {
1715
+ const: "transcript.final"
1716
+ },
1717
+ text: {
1718
+ type: "string"
1719
+ }
1720
+ },
1721
+ required: [
1722
+ "type",
1723
+ "text"
1724
+ ]
1725
+ }
1726
+ ],
1727
+ unevaluatedProperties: false
1728
+ },
1729
+ memoryRetrievalStarted: {
1730
+ allOf: [
1731
+ {
1732
+ $ref: "#/$defs/base"
1733
+ },
1734
+ {
1735
+ type: "object",
1736
+ properties: {
1737
+ type: {
1738
+ const: "memory.retrieval.started"
1739
+ },
1740
+ query: {
1741
+ type: "string"
1742
+ }
1743
+ },
1744
+ required: [
1745
+ "type",
1746
+ "query"
1747
+ ]
1748
+ }
1749
+ ],
1750
+ unevaluatedProperties: false
1751
+ },
1752
+ memoryRetrievalCompleted: {
1753
+ allOf: [
1754
+ {
1755
+ $ref: "#/$defs/base"
1756
+ },
1757
+ {
1758
+ type: "object",
1759
+ properties: {
1760
+ type: {
1761
+ const: "memory.retrieval.completed"
1762
+ },
1763
+ query: {
1764
+ type: "string"
1765
+ },
1766
+ documents: {
1767
+ type: "array",
1768
+ items: {
1769
+ $ref: "#/$defs/jsonObject"
1770
+ }
1771
+ }
1772
+ },
1773
+ required: [
1774
+ "type",
1775
+ "query",
1776
+ "documents"
1777
+ ]
1778
+ }
1779
+ ],
1780
+ unevaluatedProperties: false
1781
+ },
1782
+ agentReasoningStarted: {
1783
+ allOf: [
1784
+ {
1785
+ $ref: "#/$defs/base"
1786
+ },
1787
+ {
1788
+ type: "object",
1789
+ properties: {
1790
+ type: {
1791
+ const: "agent.reasoning.started"
1792
+ }
1793
+ },
1794
+ required: [
1795
+ "type"
1796
+ ]
1797
+ }
1798
+ ],
1799
+ unevaluatedProperties: false
1800
+ },
1801
+ agentMessageDelta: {
1802
+ allOf: [
1803
+ {
1804
+ $ref: "#/$defs/base"
1805
+ },
1806
+ {
1807
+ type: "object",
1808
+ properties: {
1809
+ type: {
1810
+ const: "agent.message.delta"
1811
+ },
1812
+ delta: {
1813
+ type: "string"
1814
+ }
1815
+ },
1816
+ required: [
1817
+ "type",
1818
+ "delta"
1819
+ ]
1820
+ }
1821
+ ],
1822
+ unevaluatedProperties: false
1823
+ },
1824
+ agentMessageCompleted: {
1825
+ allOf: [
1826
+ {
1827
+ $ref: "#/$defs/base"
1828
+ },
1829
+ {
1830
+ type: "object",
1831
+ properties: {
1832
+ type: {
1833
+ const: "agent.message.completed"
1834
+ },
1835
+ content: {
1836
+ type: "string"
1837
+ },
1838
+ tokens: {
1839
+ oneOf: [
1840
+ { $ref: "#/$defs/tokenUsage" },
1841
+ { type: "null" }
1842
+ ]
1843
+ },
1844
+ cost_usd: {
1845
+ oneOf: [
1846
+ { $ref: "#/$defs/nonNegativeNumber" },
1847
+ { type: "null" }
1848
+ ]
1849
+ }
1850
+ },
1851
+ required: [
1852
+ "type",
1853
+ "content"
1854
+ ]
1855
+ }
1856
+ ],
1857
+ unevaluatedProperties: false
1858
+ },
1859
+ agentTurnExhausted: {
1860
+ allOf: [
1861
+ {
1862
+ $ref: "#/$defs/base"
1863
+ },
1864
+ {
1865
+ type: "object",
1866
+ properties: {
1867
+ type: {
1868
+ const: "agent.turn.exhausted"
1869
+ },
1870
+ max_iterations: {
1871
+ $ref: "#/$defs/nonNegativeInteger"
1872
+ },
1873
+ pending_tool_calls: {
1874
+ type: "array",
1875
+ items: {
1876
+ $ref: "#/$defs/jsonObject"
1877
+ }
1878
+ },
1879
+ reason: {
1880
+ type: [
1881
+ "string",
1882
+ "null"
1883
+ ]
1884
+ }
1885
+ },
1886
+ required: [
1887
+ "type",
1888
+ "max_iterations",
1889
+ "pending_tool_calls"
1890
+ ]
1891
+ }
1892
+ ],
1893
+ unevaluatedProperties: false
1894
+ },
1895
+ agentTurnFailed: {
1896
+ allOf: [
1897
+ {
1898
+ $ref: "#/$defs/base"
1899
+ },
1900
+ {
1901
+ type: "object",
1902
+ properties: {
1903
+ type: {
1904
+ const: "agent.turn.failed"
1905
+ },
1906
+ turn_id: {
1907
+ $ref: "#/$defs/nonEmptyId"
1908
+ },
1909
+ error: {
1910
+ type: "string",
1911
+ minLength: 1,
1912
+ maxLength: 200
1913
+ },
1914
+ error_code: {
1915
+ type: "string"
1916
+ },
1917
+ phase: {
1918
+ enum: [
1919
+ "queue",
1920
+ "provider_open",
1921
+ "provider_stream",
1922
+ "approval",
1923
+ "tool"
1924
+ ]
1925
+ },
1926
+ retryable: {
1927
+ type: "boolean"
1928
+ },
1929
+ outcome: {
1930
+ enum: [
1931
+ "not_started",
1932
+ "failed",
1933
+ "unknown"
1934
+ ]
1935
+ }
1936
+ },
1937
+ required: [
1938
+ "type",
1939
+ "turn_id",
1940
+ "error"
1941
+ ]
1942
+ }
1943
+ ],
1944
+ unevaluatedProperties: false
1945
+ },
1946
+ toolCallRequested: {
1947
+ allOf: [
1948
+ {
1949
+ $ref: "#/$defs/base"
1950
+ },
1951
+ {
1952
+ type: "object",
1953
+ properties: {
1954
+ type: {
1955
+ const: "tool.call.requested"
1956
+ },
1957
+ turn_id: {
1958
+ $ref: "#/$defs/nonEmptyId"
1959
+ },
1960
+ tool_name: {
1961
+ $ref: "#/$defs/nonEmptyId"
1962
+ },
1963
+ tool_args: {
1964
+ $ref: "#/$defs/jsonObject",
1965
+ "x-maxSerializedBytes": 65536
1966
+ },
1967
+ tool_call_id: {
1968
+ $ref: "#/$defs/nonEmptyId"
1969
+ }
1970
+ },
1971
+ required: [
1972
+ "type",
1973
+ "turn_id",
1974
+ "tool_name",
1975
+ "tool_args",
1976
+ "tool_call_id"
1977
+ ]
1978
+ }
1979
+ ],
1980
+ unevaluatedProperties: false
1981
+ },
1982
+ toolCallStarted: {
1983
+ allOf: [
1984
+ {
1985
+ $ref: "#/$defs/base"
1986
+ },
1987
+ {
1988
+ type: "object",
1989
+ properties: {
1990
+ type: {
1991
+ const: "tool.call.started"
1992
+ },
1993
+ turn_id: {
1994
+ $ref: "#/$defs/nonEmptyId"
1995
+ },
1996
+ tool_name: {
1997
+ $ref: "#/$defs/nonEmptyId"
1998
+ },
1999
+ tool_call_id: {
2000
+ $ref: "#/$defs/nonEmptyId"
2001
+ }
2002
+ },
2003
+ required: [
2004
+ "type",
2005
+ "turn_id",
2006
+ "tool_name",
2007
+ "tool_call_id"
2008
+ ]
2009
+ }
2010
+ ],
2011
+ unevaluatedProperties: false
2012
+ },
2013
+ toolCallCompleted: {
2014
+ allOf: [
2015
+ {
2016
+ $ref: "#/$defs/base"
2017
+ },
2018
+ {
2019
+ type: "object",
2020
+ properties: {
2021
+ type: {
2022
+ const: "tool.call.completed"
2023
+ },
2024
+ turn_id: {
2025
+ $ref: "#/$defs/nonEmptyId"
2026
+ },
2027
+ tool_name: {
2028
+ $ref: "#/$defs/nonEmptyId"
2029
+ },
2030
+ tool_call_id: {
2031
+ $ref: "#/$defs/nonEmptyId"
2032
+ },
2033
+ result: {
2034
+ $ref: "#/$defs/jsonValue",
2035
+ "x-maxSerializedBytes": 65536
2036
+ },
2037
+ tokens: {
2038
+ oneOf: [
2039
+ { $ref: "#/$defs/tokenUsage" },
2040
+ { type: "null" }
2041
+ ]
2042
+ },
2043
+ cost_usd: {
2044
+ oneOf: [
2045
+ { $ref: "#/$defs/nonNegativeNumber" },
2046
+ { type: "null" }
2047
+ ]
2048
+ }
2049
+ },
2050
+ required: [
2051
+ "type",
2052
+ "turn_id",
2053
+ "tool_name",
2054
+ "tool_call_id",
2055
+ "result"
2056
+ ]
2057
+ }
2058
+ ],
2059
+ unevaluatedProperties: false
2060
+ },
2061
+ toolCallFailed: {
2062
+ allOf: [
2063
+ {
2064
+ $ref: "#/$defs/base"
2065
+ },
2066
+ {
2067
+ type: "object",
2068
+ properties: {
2069
+ type: {
2070
+ const: "tool.call.failed"
2071
+ },
2072
+ turn_id: {
2073
+ $ref: "#/$defs/nonEmptyId"
2074
+ },
2075
+ tool_name: {
2076
+ $ref: "#/$defs/nonEmptyId"
2077
+ },
2078
+ tool_call_id: {
2079
+ $ref: "#/$defs/nonEmptyId"
2080
+ },
2081
+ error: {
2082
+ type: "string",
2083
+ minLength: 1,
2084
+ maxLength: 200
2085
+ },
2086
+ error_code: {
2087
+ type: "string"
2088
+ },
2089
+ error_path: {
2090
+ type: "string"
2091
+ },
2092
+ retryable: {
2093
+ type: "boolean"
2094
+ },
2095
+ outcome: {
2096
+ enum: [
2097
+ "not_started",
2098
+ "failed",
2099
+ "unknown"
2100
+ ]
2101
+ },
2102
+ reason_code: {
2103
+ type: "string"
2104
+ },
2105
+ recovery_code: {
2106
+ type: "string"
2107
+ },
2108
+ doc_url: {
2109
+ type: "string"
2110
+ }
2111
+ },
2112
+ required: [
2113
+ "type",
2114
+ "turn_id",
2115
+ "tool_name",
2116
+ "tool_call_id",
2117
+ "error"
2118
+ ]
2119
+ },
2120
+ {
2121
+ if: {
2122
+ anyOf: [
2123
+ { required: ["reason_code"] },
2124
+ { required: ["recovery_code"] },
2125
+ { required: ["doc_url"] }
2126
+ ]
2127
+ },
2128
+ then: {
2129
+ $ref: "#/$defs/integrationRecoveryFields"
2130
+ }
2131
+ }
2132
+ ],
2133
+ unevaluatedProperties: false
2134
+ },
2135
+ toolApprovalRequested: {
2136
+ allOf: [
2137
+ {
2138
+ $ref: "#/$defs/base"
2139
+ },
2140
+ {
2141
+ type: "object",
2142
+ properties: {
2143
+ type: {
2144
+ const: "tool.approval.requested"
2145
+ },
2146
+ turn_id: {
2147
+ $ref: "#/$defs/nonEmptyId"
2148
+ },
2149
+ tool_name: {
2150
+ $ref: "#/$defs/nonEmptyId"
2151
+ },
2152
+ tool_call_id: {
2153
+ $ref: "#/$defs/nonEmptyId"
2154
+ },
2155
+ tool_args: {
2156
+ $ref: "#/$defs/jsonObject",
2157
+ "x-maxSerializedBytes": 65536
2158
+ },
2159
+ risk: {
2160
+ enum: [
2161
+ "read",
2162
+ "write",
2163
+ "external_effect",
2164
+ "destructive",
2165
+ "admin"
2166
+ ]
2167
+ }
2168
+ },
2169
+ required: [
2170
+ "type",
2171
+ "turn_id",
2172
+ "tool_name",
2173
+ "tool_call_id",
2174
+ "tool_args",
2175
+ "risk"
2176
+ ]
2177
+ }
2178
+ ],
2179
+ unevaluatedProperties: false
2180
+ },
2181
+ toolApprovalApproved: {
2182
+ allOf: [
2183
+ {
2184
+ $ref: "#/$defs/base"
2185
+ },
2186
+ {
2187
+ type: "object",
2188
+ properties: {
2189
+ type: {
2190
+ const: "tool.approval.approved"
2191
+ },
2192
+ turn_id: {
2193
+ $ref: "#/$defs/nonEmptyId"
2194
+ },
2195
+ tool_name: {
2196
+ $ref: "#/$defs/nonEmptyId"
2197
+ },
2198
+ tool_call_id: {
2199
+ $ref: "#/$defs/nonEmptyId"
2200
+ }
2201
+ },
2202
+ required: [
2203
+ "type",
2204
+ "turn_id",
2205
+ "tool_name",
2206
+ "tool_call_id"
2207
+ ]
2208
+ }
2209
+ ],
2210
+ unevaluatedProperties: false
2211
+ },
2212
+ toolApprovalRejected: {
2213
+ allOf: [
2214
+ {
2215
+ $ref: "#/$defs/base"
2216
+ },
2217
+ {
2218
+ type: "object",
2219
+ properties: {
2220
+ type: {
2221
+ const: "tool.approval.rejected"
2222
+ },
2223
+ turn_id: {
2224
+ $ref: "#/$defs/nonEmptyId"
2225
+ },
2226
+ tool_name: {
2227
+ $ref: "#/$defs/nonEmptyId"
2228
+ },
2229
+ tool_call_id: {
2230
+ $ref: "#/$defs/nonEmptyId"
2231
+ },
2232
+ error_code: {
2233
+ enum: [
2234
+ "APPROVAL_REJECTED",
2235
+ "APPROVAL_TIMEOUT",
2236
+ "TURN_TIMEOUT",
2237
+ "TOOL_CANCELLED",
2238
+ "APPROVAL_UNAVAILABLE"
2239
+ ]
2240
+ },
2241
+ reason: {
2242
+ type: "string",
2243
+ minLength: 1,
2244
+ maxLength: 200,
2245
+ pattern: "\\S"
2246
+ }
2247
+ },
2248
+ required: [
2249
+ "type",
2250
+ "turn_id",
2251
+ "tool_name",
2252
+ "tool_call_id",
2253
+ "error_code",
2254
+ "reason"
2255
+ ]
2256
+ }
2257
+ ],
2258
+ unevaluatedProperties: false
2259
+ },
2260
+ workflowStarted: {
2261
+ allOf: [
2262
+ {
2263
+ $ref: "#/$defs/base"
2264
+ },
2265
+ {
2266
+ type: "object",
2267
+ properties: {
2268
+ type: {
2269
+ const: "workflow.started"
2270
+ },
2271
+ workflow_name: {
2272
+ type: "string"
2273
+ }
2274
+ },
2275
+ required: [
2276
+ "type",
2277
+ "workflow_name"
2278
+ ]
2279
+ }
2280
+ ],
2281
+ unevaluatedProperties: false
2282
+ },
2283
+ workflowCompleted: {
2284
+ allOf: [
2285
+ {
2286
+ $ref: "#/$defs/base"
2287
+ },
2288
+ {
2289
+ type: "object",
2290
+ properties: {
2291
+ type: {
2292
+ const: "workflow.completed"
2293
+ },
2294
+ workflow_name: {
2295
+ type: "string"
2296
+ },
2297
+ result: {
2298
+ $ref: "#/$defs/jsonValue"
2299
+ }
2300
+ },
2301
+ required: [
2302
+ "type",
2303
+ "workflow_name",
2304
+ "result"
2305
+ ]
2306
+ }
2307
+ ],
2308
+ unevaluatedProperties: false
2309
+ },
2310
+ workflowFailed: {
2311
+ allOf: [
2312
+ {
2313
+ $ref: "#/$defs/base"
2314
+ },
2315
+ {
2316
+ type: "object",
2317
+ properties: {
2318
+ type: {
2319
+ const: "workflow.failed"
2320
+ },
2321
+ workflow_name: {
2322
+ type: "string"
2323
+ },
2324
+ error: {
2325
+ type: "string"
2326
+ }
2327
+ },
2328
+ required: [
2329
+ "type",
2330
+ "workflow_name",
2331
+ "error"
2332
+ ]
2333
+ }
2334
+ ],
2335
+ unevaluatedProperties: false
2336
+ },
2337
+ cancellationRequested: {
2338
+ allOf: [
2339
+ {
2340
+ $ref: "#/$defs/base"
2341
+ },
2342
+ {
2343
+ type: "object",
2344
+ properties: {
2345
+ type: {
2346
+ const: "cancellation.requested"
2347
+ },
2348
+ reason: {
2349
+ type: "string"
2350
+ }
2351
+ },
2352
+ required: [
2353
+ "type",
2354
+ "reason"
2355
+ ]
2356
+ }
2357
+ ],
2358
+ unevaluatedProperties: false
2359
+ },
2360
+ cancellationCompleted: {
2361
+ allOf: [
2362
+ {
2363
+ $ref: "#/$defs/base"
2364
+ },
2365
+ {
2366
+ type: "object",
2367
+ properties: {
2368
+ type: {
2369
+ const: "cancellation.completed"
2370
+ }
2371
+ },
2372
+ required: [
2373
+ "type"
2374
+ ]
2375
+ }
2376
+ ],
2377
+ unevaluatedProperties: false
2378
+ }
2379
+ },
2380
+ oneOf: [
2381
+ {
2382
+ $ref: "#/$defs/sessionCreated"
2383
+ },
2384
+ {
2385
+ $ref: "#/$defs/sessionClosed"
2386
+ },
2387
+ {
2388
+ $ref: "#/$defs/userMessage"
2389
+ },
2390
+ {
2391
+ $ref: "#/$defs/userAudioChunk"
2392
+ },
2393
+ {
2394
+ $ref: "#/$defs/transcriptPartial"
2395
+ },
2396
+ {
2397
+ $ref: "#/$defs/transcriptFinal"
2398
+ },
2399
+ {
2400
+ $ref: "#/$defs/memoryRetrievalStarted"
2401
+ },
2402
+ {
2403
+ $ref: "#/$defs/memoryRetrievalCompleted"
2404
+ },
2405
+ {
2406
+ $ref: "#/$defs/agentReasoningStarted"
2407
+ },
2408
+ {
2409
+ $ref: "#/$defs/agentMessageDelta"
2410
+ },
2411
+ {
2412
+ $ref: "#/$defs/agentMessageCompleted"
2413
+ },
2414
+ {
2415
+ $ref: "#/$defs/agentTurnExhausted"
2416
+ },
2417
+ {
2418
+ $ref: "#/$defs/agentTurnFailed"
2419
+ },
2420
+ {
2421
+ $ref: "#/$defs/toolCallRequested"
2422
+ },
2423
+ {
2424
+ $ref: "#/$defs/toolCallStarted"
2425
+ },
2426
+ {
2427
+ $ref: "#/$defs/toolCallCompleted"
2428
+ },
2429
+ {
2430
+ $ref: "#/$defs/toolCallFailed"
2431
+ },
2432
+ {
2433
+ $ref: "#/$defs/toolApprovalRequested"
2434
+ },
2435
+ {
2436
+ $ref: "#/$defs/toolApprovalApproved"
2437
+ },
2438
+ {
2439
+ $ref: "#/$defs/toolApprovalRejected"
2440
+ },
2441
+ {
2442
+ $ref: "#/$defs/workflowStarted"
2443
+ },
2444
+ {
2445
+ $ref: "#/$defs/workflowCompleted"
2446
+ },
2447
+ {
2448
+ $ref: "#/$defs/workflowFailed"
2449
+ },
2450
+ {
2451
+ $ref: "#/$defs/cancellationRequested"
2452
+ },
2453
+ {
2454
+ $ref: "#/$defs/cancellationCompleted"
2455
+ }
2456
+ ]
2457
+ };
2458
+
2459
+ // src/events/schemas.ts
2460
+ var MAX_DURABLE_TOOL_ARGUMENT_BYTES = 64 * 1024;
2461
+ var MAX_DURABLE_TOOL_RESULT_BYTES = 64 * 1024;
2462
+ var MAX_DURABLE_EVENT_BYTES = 1024 * 1024;
2463
+ function durableToolArgumentsSize(value) {
2464
+ return new TextEncoder().encode(canonicalJsonValue(value, "tool arguments")).byteLength;
2465
+ }
2466
+ var durableJsonValue = z__namespace.unknown().superRefine((value, ctx) => {
2467
+ try {
2468
+ canonicalJsonValue(value, "event value");
2469
+ } catch {
2470
+ ctx.addIssue({ code: "custom", message: "event value must contain only JSON values" });
2471
+ }
2472
+ });
2473
+ var durableJsonObject = z__namespace.record(z__namespace.string(), durableJsonValue).superRefine((value, ctx) => {
2474
+ try {
2475
+ canonicalJsonValue(value, "event value");
2476
+ } catch {
2477
+ ctx.addIssue({ code: "custom", message: "event value must contain only JSON values" });
2478
+ }
2479
+ });
2480
+ function durableSubjectValue(subject, maxBytes) {
2481
+ return z__namespace.unknown().superRefine((value, ctx) => {
2482
+ try {
2483
+ durableJsonSnapshot(value, subject, maxBytes);
2484
+ } catch {
2485
+ ctx.addIssue({ code: "custom", message: `${subject} must be bounded durable JSON` });
2486
+ }
2487
+ });
2488
+ }
2489
+ function durableSubjectObject(subject) {
2490
+ return z__namespace.record(z__namespace.string(), z__namespace.unknown()).superRefine((value, ctx) => {
2491
+ try {
2492
+ durableJsonSnapshot(value, subject, MAX_DURABLE_EVENT_BYTES);
2493
+ } catch {
2494
+ ctx.addIssue({ code: "custom", message: `${subject} must be bounded durable JSON` });
2495
+ }
2496
+ });
2497
+ }
2498
+ var durableToolArguments = durableJsonObject.superRefine((value, ctx) => {
2499
+ let size;
2500
+ try {
2501
+ size = durableToolArgumentsSize(value);
2502
+ } catch {
2503
+ ctx.addIssue({ code: "custom", message: "tool_args must contain only JSON values" });
2504
+ return;
2505
+ }
2506
+ if (size > MAX_DURABLE_TOOL_ARGUMENT_BYTES) {
2507
+ ctx.addIssue({
2508
+ code: "custom",
2509
+ message: "tool_args cannot exceed 65536 serialized bytes; payload redacted"
2510
+ });
2511
+ }
2512
+ });
2513
+ var nonEmptyId = z__namespace.string().min(1);
2514
+ var baseShape = {
2515
+ id: nonEmptyId.default(() => defaultUuid()),
2516
+ version: z__namespace.literal("1.0").default("1.0"),
2517
+ timestamp: z__namespace.number().default(() => Date.now() / 1e3),
2518
+ session_id: nonEmptyId,
2519
+ turn_id: nonEmptyId.optional(),
2520
+ metadata: durableSubjectObject("event_metadata").default(() => ({}))
2521
+ };
2522
+ function maxUnicodeCodePoints(field) {
2523
+ return (value, ctx) => {
2524
+ if (Array.from(value).length > 200) {
2525
+ ctx.addIssue({ code: "custom", message: `${field} must contain at most 200 characters` });
2526
+ }
2527
+ };
2528
+ }
2529
+ function event(shape) {
2530
+ return z__namespace.object(baseShape).extend(shape).strict();
2531
+ }
2532
+ var SessionCreated = event({
2533
+ type: z__namespace.literal(EventType.SESSION_CREATED)
2534
+ });
2535
+ var SessionClosed = event({
2536
+ type: z__namespace.literal(EventType.SESSION_CLOSED),
2537
+ reason: z__namespace.string().nullish()
2538
+ });
2539
+ var UserMessage = event({
2540
+ type: z__namespace.literal(EventType.USER_MESSAGE),
2541
+ content: z__namespace.string()
2542
+ });
2543
+ var UserAudioChunk = event({
2544
+ type: z__namespace.literal(EventType.USER_AUDIO_CHUNK),
2545
+ chunk_size_bytes: z__namespace.number().int()
2546
+ });
2547
+ var TranscriptPartial = event({
2548
+ type: z__namespace.literal(EventType.TRANSCRIPT_PARTIAL),
2549
+ text: z__namespace.string()
2550
+ });
2551
+ var TranscriptFinal = event({
2552
+ type: z__namespace.literal(EventType.TRANSCRIPT_FINAL),
2553
+ text: z__namespace.string()
2554
+ });
2555
+ var MemoryRetrievalStarted = event({
2556
+ type: z__namespace.literal(EventType.MEMORY_RETRIEVAL_STARTED),
2557
+ query: z__namespace.string()
2558
+ });
2559
+ var MemoryRetrievalCompleted = event({
2560
+ type: z__namespace.literal(EventType.MEMORY_RETRIEVAL_COMPLETED),
2561
+ query: z__namespace.string(),
2562
+ documents: z__namespace.array(durableSubjectObject("memory_document"))
2563
+ });
2564
+ var AgentReasoningStarted = event({
2565
+ type: z__namespace.literal(EventType.AGENT_REASONING_STARTED)
2566
+ });
2567
+ var AgentMessageDelta = event({
2568
+ type: z__namespace.literal(EventType.AGENT_MESSAGE_DELTA),
2569
+ delta: z__namespace.string()
2570
+ });
2571
+ var AgentMessageCompleted = event({
2572
+ type: z__namespace.literal(EventType.AGENT_MESSAGE_COMPLETED),
2573
+ content: z__namespace.string(),
2574
+ tokens: z__namespace.object({ input: z__namespace.number().int().nonnegative(), output: z__namespace.number().int().nonnegative() }).strict().nullish(),
2575
+ cost_usd: z__namespace.number().nonnegative().nullish()
2576
+ });
2577
+ var AgentTurnExhausted = event({
2578
+ type: z__namespace.literal(EventType.AGENT_TURN_EXHAUSTED),
2579
+ max_iterations: z__namespace.number().int().nonnegative(),
2580
+ pending_tool_calls: z__namespace.array(durableSubjectObject("pending_tool_call")),
2581
+ reason: z__namespace.string().nullish()
2582
+ });
2583
+ var AgentTurnFailed = event({
2584
+ type: z__namespace.literal(EventType.AGENT_TURN_FAILED),
2585
+ turn_id: z__namespace.string().min(1),
2586
+ error: z__namespace.string().min(1).superRefine(maxUnicodeCodePoints("error")),
2587
+ error_code: z__namespace.string().optional(),
2588
+ phase: z__namespace.enum(["queue", "provider_open", "provider_stream", "approval", "tool"]).optional(),
2589
+ retryable: z__namespace.boolean().optional(),
2590
+ outcome: z__namespace.enum(["not_started", "failed", "unknown"]).optional()
2591
+ });
2592
+ var ToolCallRequested = event({
2593
+ type: z__namespace.literal(EventType.TOOL_CALL_REQUESTED),
2594
+ turn_id: z__namespace.string().min(1),
2595
+ tool_name: z__namespace.string().min(1),
2596
+ tool_args: durableToolArguments,
2597
+ tool_call_id: z__namespace.string().min(1)
2598
+ });
2599
+ var ToolCallStarted = event({
2600
+ type: z__namespace.literal(EventType.TOOL_CALL_STARTED),
2601
+ turn_id: z__namespace.string().min(1),
2602
+ tool_name: z__namespace.string().min(1),
2603
+ tool_call_id: z__namespace.string().min(1)
2604
+ });
2605
+ var ToolCallCompleted = event({
2606
+ type: z__namespace.literal(EventType.TOOL_CALL_COMPLETED),
2607
+ turn_id: z__namespace.string().min(1),
2608
+ tool_name: z__namespace.string().min(1),
2609
+ tool_call_id: z__namespace.string().min(1),
2610
+ result: durableSubjectValue("tool_result", MAX_DURABLE_TOOL_RESULT_BYTES),
2611
+ tokens: z__namespace.object({ input: z__namespace.number().int().nonnegative(), output: z__namespace.number().int().nonnegative() }).strict().nullish(),
2612
+ cost_usd: z__namespace.number().nonnegative().nullish()
2613
+ });
2614
+ var ToolCallFailed = event({
2615
+ type: z__namespace.literal(EventType.TOOL_CALL_FAILED),
2616
+ turn_id: z__namespace.string().min(1),
2617
+ tool_name: z__namespace.string().min(1),
2618
+ tool_call_id: z__namespace.string().min(1),
2619
+ error: z__namespace.string().min(1).superRefine(maxUnicodeCodePoints("error")),
2620
+ error_code: z__namespace.string().optional(),
2621
+ error_path: z__namespace.string().optional(),
2622
+ retryable: z__namespace.boolean().optional(),
2623
+ outcome: z__namespace.enum(["not_started", "failed", "unknown"]).optional(),
2624
+ reason_code: z__namespace.string().optional(),
2625
+ recovery_code: z__namespace.string().optional(),
2626
+ doc_url: z__namespace.string().optional()
2627
+ }).superRefine((value, ctx) => {
2628
+ if (!isClosedRecoveryTuple(value.reason_code, value.recovery_code, value.doc_url, value.error_code)) {
2629
+ ctx.addIssue({
2630
+ code: "custom",
2631
+ path: ["reason_code"],
2632
+ message: "integration recovery metadata must be a closed tuple"
2633
+ });
2634
+ }
2635
+ });
2636
+ var ToolApprovalRequested = event({
2637
+ type: z__namespace.literal(EventType.TOOL_APPROVAL_REQUESTED),
2638
+ turn_id: z__namespace.string().min(1),
2639
+ tool_name: z__namespace.string().min(1),
2640
+ tool_call_id: z__namespace.string().min(1),
2641
+ tool_args: durableToolArguments,
2642
+ risk: z__namespace.enum(["read", "write", "external_effect", "destructive", "admin"])
2643
+ });
2644
+ var ToolApprovalApproved = event({
2645
+ type: z__namespace.literal(EventType.TOOL_APPROVAL_APPROVED),
2646
+ turn_id: z__namespace.string().min(1),
2647
+ tool_name: z__namespace.string().min(1),
2648
+ tool_call_id: z__namespace.string().min(1)
2649
+ });
2650
+ var ToolApprovalRejected = event({
2651
+ type: z__namespace.literal(EventType.TOOL_APPROVAL_REJECTED),
2652
+ turn_id: z__namespace.string().min(1),
2653
+ tool_name: z__namespace.string().min(1),
2654
+ tool_call_id: z__namespace.string().min(1),
2655
+ error_code: z__namespace.enum([
2656
+ "APPROVAL_REJECTED",
2657
+ "APPROVAL_TIMEOUT",
2658
+ "TURN_TIMEOUT",
2659
+ "TOOL_CANCELLED",
2660
+ "APPROVAL_UNAVAILABLE"
2661
+ ]),
2662
+ reason: z__namespace.string().min(1).refine((value) => value.trim().length > 0, "reason must not be blank").superRefine(maxUnicodeCodePoints("reason"))
2663
+ });
2664
+ var WorkflowStarted = event({
2665
+ type: z__namespace.literal(EventType.WORKFLOW_STARTED),
2666
+ workflow_name: z__namespace.string()
2667
+ });
2668
+ var WorkflowCompleted = event({
2669
+ type: z__namespace.literal(EventType.WORKFLOW_COMPLETED),
2670
+ workflow_name: z__namespace.string(),
2671
+ result: durableSubjectValue("workflow_result", MAX_DURABLE_EVENT_BYTES)
2672
+ });
2673
+ var WorkflowFailed = event({
2674
+ type: z__namespace.literal(EventType.WORKFLOW_FAILED),
2675
+ workflow_name: z__namespace.string(),
2676
+ error: z__namespace.string()
2677
+ });
2678
+ var CancellationRequested = event({
2679
+ type: z__namespace.literal(EventType.CANCELLATION_REQUESTED),
2680
+ reason: z__namespace.string()
2681
+ });
2682
+ var CancellationCompleted = event({
2683
+ type: z__namespace.literal(EventType.CANCELLATION_COMPLETED)
2684
+ });
2685
+ var KajiEvent = z__namespace.discriminatedUnion("type", [
2686
+ SessionCreated,
2687
+ SessionClosed,
2688
+ UserMessage,
2689
+ UserAudioChunk,
2690
+ TranscriptPartial,
2691
+ TranscriptFinal,
2692
+ MemoryRetrievalStarted,
2693
+ MemoryRetrievalCompleted,
2694
+ AgentReasoningStarted,
2695
+ AgentMessageDelta,
2696
+ AgentMessageCompleted,
2697
+ AgentTurnExhausted,
2698
+ AgentTurnFailed,
2699
+ ToolCallRequested,
2700
+ ToolCallStarted,
2701
+ ToolCallCompleted,
2702
+ ToolCallFailed,
2703
+ ToolApprovalRequested,
2704
+ ToolApprovalApproved,
2705
+ ToolApprovalRejected,
2706
+ WorkflowStarted,
2707
+ WorkflowCompleted,
2708
+ WorkflowFailed,
2709
+ CancellationRequested,
2710
+ CancellationCompleted
2711
+ ]);
2712
+ z__namespace.object({ sequence: z__namespace.number().int().positive() }).loose().transform((value, ctx) => {
2713
+ const { sequence, ...candidate } = value;
2714
+ const parsed = KajiEvent.safeParse(candidate);
2715
+ if (!parsed.success) {
2716
+ for (const issue of parsed.error.issues) ctx.addIssue({ ...issue });
2717
+ return z__namespace.NEVER;
2718
+ }
2719
+ return cloneAndFreezeJson({ ...parsed.data, sequence });
2720
+ });
2721
+ new Set(Object.values(EventType));
2722
+ var wireAjv = new Ajv2020__default.default({ allErrors: true, strict: false });
2723
+ wireAjv.compile(new_kaji_event_v1_schema_default);
2724
+ wireAjv.compile(stored_kaji_event_v1_schema_default);
2725
+
2726
+ // src/tools/execution-errors.ts
2727
+ var TOOL_EXECUTION_ERROR_BRAND = /* @__PURE__ */ Symbol.for("@kaji/sdk.ToolExecutionError.v1");
2728
+ function nativeInstanceOf(constructor, value) {
2729
+ return Function.prototype[Symbol.hasInstance].call(constructor, value);
2730
+ }
2731
+ var ToolExecutionError = class _ToolExecutionError extends Error {
2732
+ constructor(message, error_code, retryable, outcome, recovery2) {
2733
+ super(message);
2734
+ this.error_code = error_code;
2735
+ this.retryable = retryable;
2736
+ this.outcome = outcome;
2737
+ this.name = "ToolExecutionError";
2738
+ Object.defineProperty(this, TOOL_EXECUTION_ERROR_BRAND, { value: true });
2739
+ if (recovery2 !== void 0) {
2740
+ this.reason_code = recovery2.reason_code;
2741
+ this.recovery_code = recovery2.recovery_code;
2742
+ this.doc_url = recovery2.doc_url;
2743
+ }
2744
+ }
2745
+ error_code;
2746
+ retryable;
2747
+ outcome;
2748
+ static [Symbol.hasInstance](value) {
2749
+ if (this !== _ToolExecutionError) return nativeInstanceOf(this, value);
2750
+ return nativeInstanceOf(this, value) || value instanceof Error && Reflect.get(value, TOOL_EXECUTION_ERROR_BRAND) === true;
2751
+ }
2752
+ reason_code;
2753
+ recovery_code;
2754
+ doc_url;
2755
+ };
2756
+
2757
+ // src/integrations/errors.ts
2758
+ function certified(kind, reasonCode, retryable) {
2759
+ return Object.freeze({ kind, recovery: recoveryForReason(reasonCode), retryable });
2760
+ }
2761
+ var CERTIFIED_FAILURES = Object.freeze({
2762
+ api_rejected: certified("api", "api_rejected", false),
2763
+ github_token_missing: certified("auth_required", "github_token_missing", false),
2764
+ gmail_grant_missing: certified("auth_required", "gmail_grant_missing", false),
2765
+ gmail_scope_drift: certified("auth_required", "gmail_scope_drift", false),
2766
+ keychain_missing: certified("auth", "keychain_missing", false),
2767
+ keychain_locked: certified("auth", "keychain_locked", false),
2768
+ keychain_corrupt: certified("auth", "keychain_corrupt", false),
2769
+ keychain_unsupported: certified("auth", "keychain_unsupported", false),
2770
+ rate_limited: certified("rate_limited", "rate_limited", true),
2771
+ transient_read_failed: certified("transient_read", "transient_read_failed", true),
2772
+ policy_rejected: certified("policy", "policy_rejected", false)
2773
+ });
2774
+ function certifiedFailure(reasonCode) {
2775
+ const failure = CERTIFIED_FAILURES[reasonCode];
2776
+ if (failure === void 0) throw new TypeError("uncertified integration failure reason");
2777
+ return failure;
2778
+ }
2779
+ function constructorKind(constructor) {
2780
+ if (constructor === IntegrationExecutionError) return "api";
2781
+ if (constructor === IntegrationAuthRequiredError) return "auth_required";
2782
+ if (constructor === IntegrationAuthError) return "auth";
2783
+ if (constructor === IntegrationRateLimitedError) return "rate_limited";
2784
+ if (constructor === IntegrationTransientReadError) return "transient_read";
2785
+ if (constructor === IntegrationPolicyError) return "policy";
2786
+ return void 0;
2787
+ }
2788
+ var IntegrationExecutionError = class extends ToolExecutionError {
2789
+ constructor(reasonCode) {
2790
+ const failure = certifiedFailure(reasonCode);
2791
+ if (failure.kind !== constructorKind(new.target)) {
2792
+ throw new TypeError("integration failure reason is not certified for this error class");
2793
+ }
2794
+ const { recovery: recovery2 } = failure;
2795
+ super("Tool execution failed", recovery2.errorCode, failure.retryable, "failed", {
2796
+ reason_code: reasonCode,
2797
+ recovery_code: recovery2.recoveryCode,
2798
+ doc_url: recovery2.docUrl
2799
+ });
2800
+ this.name = "IntegrationExecutionError";
2801
+ }
2802
+ };
2803
+ var IntegrationAuthRequiredError = class extends IntegrationExecutionError {
2804
+ constructor(reasonCode) {
2805
+ super(reasonCode);
2806
+ this.name = "IntegrationAuthRequiredError";
2807
+ }
2808
+ };
2809
+ var IntegrationAuthError = class extends IntegrationExecutionError {
2810
+ constructor(reasonCode) {
2811
+ super(reasonCode);
2812
+ this.name = "IntegrationAuthError";
2813
+ }
2814
+ };
2815
+ var IntegrationRateLimitedError = class extends IntegrationExecutionError {
2816
+ constructor() {
2817
+ super("rate_limited");
2818
+ this.name = "IntegrationRateLimitedError";
2819
+ }
2820
+ };
2821
+ var IntegrationTransientReadError = class extends IntegrationExecutionError {
2822
+ constructor() {
2823
+ super("transient_read_failed");
2824
+ this.name = "IntegrationTransientReadError";
2825
+ }
2826
+ };
2827
+ var IntegrationPolicyError = class extends IntegrationExecutionError {
2828
+ constructor() {
2829
+ super("policy_rejected");
2830
+ this.name = "IntegrationPolicyError";
2831
+ }
2832
+ };
2833
+ var IntegrationTransportError = class extends Error {
2834
+ constructor(error_code, reasonCode) {
2835
+ super("Integration transport failed");
2836
+ this.error_code = error_code;
2837
+ this.name = "IntegrationTransportError";
2838
+ if (reasonCode !== void 0) {
2839
+ const recovery2 = recoveryForReason(reasonCode);
2840
+ if (recovery2.errorCode !== error_code) {
2841
+ throw new TypeError("integration recovery reason does not match error code");
2842
+ }
2843
+ this.reason_code = reasonCode;
2844
+ this.recovery_code = recovery2.recoveryCode;
2845
+ this.doc_url = recovery2.docUrl;
2846
+ }
2847
+ }
2848
+ error_code;
2849
+ reason_code;
2850
+ recovery_code;
2851
+ doc_url;
2852
+ };
2853
+
2854
+ // src/observability.ts
2855
+ var SPAN_NAMES = /* @__PURE__ */ new Set([
2856
+ "kaji.turn",
2857
+ "kaji.provider",
2858
+ "kaji.tool",
2859
+ "kaji.integration.auth",
2860
+ "kaji.integration.request"
2861
+ ]);
2862
+ var TRACE_ATTRIBUTES = /* @__PURE__ */ new Set([
2863
+ "session.id",
2864
+ "turn.id",
2865
+ "request.id",
2866
+ "trace.id",
2867
+ "tool.call_id",
2868
+ "provider.family",
2869
+ "integration.name",
2870
+ "integration.operation",
2871
+ "http.status_family"
2872
+ ]);
2873
+ var METRIC_UNITS = Object.freeze({
2874
+ "kaji.turn.queue_wait_ms": "ms",
2875
+ "kaji.turn.duration_ms": "ms",
2876
+ "kaji.turn.iterations": "count",
2877
+ "kaji.provider.duration_ms": "ms",
2878
+ "kaji.provider.retries": "count",
2879
+ "kaji.replay.input_events": "count",
2880
+ "kaji.context.messages": "count",
2881
+ "kaji.context.characters": "count",
2882
+ "kaji.tool.queue_wait_ms": "ms",
2883
+ "kaji.tool.active": "gauge",
2884
+ "kaji.tool.duration_ms": "ms",
2885
+ "kaji.journal.failures": "count",
2886
+ "kaji.subscriber.lag_events": "count",
2887
+ "kaji.subscriber.overflow": "count",
2888
+ "kaji.integration.auth_ms": "ms",
2889
+ "kaji.integration.request_ms": "ms"
2890
+ });
2891
+ Object.freeze(
2892
+ Object.keys(METRIC_UNITS)
2893
+ );
2894
+ var ALLOWED_LABELS = Object.freeze({
2895
+ "kaji.turn.queue_wait_ms": [],
2896
+ "kaji.turn.duration_ms": ["outcome"],
2897
+ "kaji.turn.iterations": ["outcome"],
2898
+ "kaji.provider.duration_ms": ["provider_family", "status"],
2899
+ "kaji.provider.retries": ["provider_family"],
2900
+ "kaji.replay.input_events": [],
2901
+ "kaji.context.messages": [],
2902
+ "kaji.context.characters": [],
2903
+ "kaji.tool.queue_wait_ms": ["outcome"],
2904
+ "kaji.tool.active": [],
2905
+ "kaji.tool.duration_ms": ["outcome", "error_code"],
2906
+ "kaji.journal.failures": ["stage"],
2907
+ "kaji.subscriber.lag_events": [],
2908
+ "kaji.subscriber.overflow": ["stage"],
2909
+ "kaji.integration.auth_ms": ["integration", "operation", "outcome"],
2910
+ "kaji.integration.request_ms": ["integration", "operation", "outcome"]
2911
+ });
2912
+ var STABLE_ERROR_CODES = /* @__PURE__ */ new Set([
2913
+ "NONE",
2914
+ "OTHER",
2915
+ "INVALID_TOOL_SCHEMA",
2916
+ "INVALID_TOOL_ARGUMENTS",
2917
+ "UNCLASSIFIED_TOOL_RISK",
2918
+ "MISSING_TOOL_IDENTITY",
2919
+ "TOOL_NOT_ALLOWED",
2920
+ "APPROVAL_UNAVAILABLE",
2921
+ "APPROVAL_REJECTED",
2922
+ "APPROVAL_TIMEOUT",
2923
+ "TOOL_CANCELLED",
2924
+ "TOOL_TIMEOUT",
2925
+ "TURN_TIMEOUT",
2926
+ "TOOL_EXECUTION_FAILED",
2927
+ "TOOL_START_RECORD_FAILED",
2928
+ "IDEMPOTENCY_CAPACITY_EXCEEDED",
2929
+ "IDEMPOTENCY_CONFLICT",
2930
+ "INTEGRATION_AUTH_ERROR",
2931
+ "INTEGRATION_AUTH_REQUIRED",
2932
+ "INTEGRATION_API_ERROR",
2933
+ "INTEGRATION_POLICY_REJECTED",
2934
+ "INTEGRATION_RATE_LIMITED",
2935
+ "INTEGRATION_REDIRECT_REJECTED",
2936
+ "INTEGRATION_RESPONSE_LIMIT"
2937
+ ]);
2938
+ function validLabel(key, value) {
2939
+ if (typeof value !== "string") return false;
2940
+ const text = value;
2941
+ if (key === "provider_family") {
2942
+ return text === "openai" || text === "anthropic" || text === "custom";
2943
+ }
2944
+ if (key === "status") {
2945
+ return text === "success" || text === "cancelled" || text === "error";
2946
+ }
2947
+ if (key === "stage") {
2948
+ return ["append", "publish", "lag", "overflow"].includes(text);
2949
+ }
2950
+ if (key === "error_code") return STABLE_ERROR_CODES.has(text);
2951
+ if (key === "outcome") {
2952
+ return [
2953
+ "acquired",
2954
+ "completed",
2955
+ "failed",
2956
+ "cancelled",
2957
+ "timeout",
2958
+ "not_started",
2959
+ "unknown",
2960
+ "success",
2961
+ "error"
2962
+ ].includes(text);
2963
+ }
2964
+ if (key === "integration") return text === "github" || text === "gmail";
2965
+ if (key === "operation") return ["read", "mutation", "token"].includes(text);
2966
+ return false;
2967
+ }
2968
+ function recordMetric(sink, name, value, labels) {
2969
+ if (!Number.isFinite(value)) return;
2970
+ if (sink === NOOP_METRICS) return;
2971
+ if (!Object.hasOwn(METRIC_UNITS, name)) return;
2972
+ const sanitized = {};
2973
+ const allowed = ALLOWED_LABELS[name];
2974
+ const supplied = Object.keys(labels);
2975
+ if (supplied.length !== allowed.length || supplied.some((key) => !allowed.includes(key))) return;
2976
+ for (const key of allowed) {
2977
+ const raw = labels[key];
2978
+ if (!validLabel(key, raw)) return;
2979
+ sanitized[key] = raw;
2980
+ }
2981
+ const measurement = Object.freeze({
2982
+ name,
2983
+ value,
2984
+ unit: METRIC_UNITS[name],
2985
+ labels: Object.freeze(sanitized)
2986
+ });
2987
+ try {
2988
+ const pending = sink.record(measurement);
2989
+ if (pending !== void 0) void Promise.resolve(pending).catch(() => void 0);
2990
+ } catch {
2991
+ }
2992
+ }
2993
+ var NOOP_SPAN = Object.freeze({
2994
+ setAttribute: () => {
2995
+ },
2996
+ recordError: () => {
2997
+ },
2998
+ end: () => {
2999
+ }
3000
+ });
3001
+ var NOOP_METRICS = Object.freeze({ record: () => {
3002
+ } });
3003
+ var NOOP_TRACE = Object.freeze({ startSpan: () => NOOP_SPAN });
3004
+ function validTraceAttribute(name, value) {
3005
+ if (typeof value !== "string") return false;
3006
+ if (name === "integration.name") return value === "github" || value === "gmail";
3007
+ if (name === "integration.operation") {
3008
+ return value === "read" || value === "mutation" || value === "token";
3009
+ }
3010
+ if (name === "http.status_family") return /^(?:[1-5]xx|none)$/.test(value);
3011
+ return true;
3012
+ }
3013
+ function startSpan(sink, name, attributes = {}) {
3014
+ if (sink === NOOP_TRACE) return NOOP_SPAN;
3015
+ if (!SPAN_NAMES.has(name)) return NOOP_SPAN;
3016
+ let safeAttributes;
3017
+ try {
3018
+ const entries = Object.entries(attributes);
3019
+ if (entries.some(
3020
+ ([key, value]) => !TRACE_ATTRIBUTES.has(key) || !validTraceAttribute(key, value)
3021
+ )) {
3022
+ return NOOP_SPAN;
3023
+ }
3024
+ safeAttributes = Object.freeze(Object.fromEntries(entries));
3025
+ } catch {
3026
+ return NOOP_SPAN;
3027
+ }
3028
+ let inner;
3029
+ try {
3030
+ inner = sink.startSpan(name, safeAttributes);
3031
+ } catch {
3032
+ return NOOP_SPAN;
3033
+ }
3034
+ let ended = false;
3035
+ return {
3036
+ setAttribute(attributeName, value) {
3037
+ if (ended) return;
3038
+ if (!TRACE_ATTRIBUTES.has(attributeName) || !validTraceAttribute(attributeName, value))
3039
+ return;
3040
+ try {
3041
+ inner.setAttribute(attributeName, value);
3042
+ } catch {
3043
+ }
3044
+ },
3045
+ recordError(error) {
3046
+ if (ended) return;
3047
+ try {
3048
+ const kind = error instanceof Error ? error.name : typeof error;
3049
+ inner.recordError(new Error(`${kind}: details redacted`));
3050
+ } catch {
3051
+ }
3052
+ },
3053
+ end() {
3054
+ if (ended) return;
3055
+ ended = true;
3056
+ try {
3057
+ inner.end();
3058
+ } catch {
3059
+ }
3060
+ }
3061
+ };
3062
+ }
3063
+
3064
+ // src/integrations/fixed-origin.ts
3065
+ var DEFAULT_TIMEOUT_MS = 1e4;
3066
+ var DEFAULT_MAX_RESPONSE_BYTES = 1048576;
3067
+ var MAX_RESPONSE_HEADER_FIELDS = 64;
3068
+ var MAX_RESPONSE_HEADER_BYTES = 64 * 1024;
3069
+ var FORBIDDEN_REQUEST_HEADERS = /* @__PURE__ */ new Set([
3070
+ "connection",
3071
+ "content-length",
3072
+ "host",
3073
+ "keep-alive",
3074
+ "proxy-authenticate",
3075
+ "proxy-authorization",
3076
+ "proxy-connection",
3077
+ "te",
3078
+ "trailer",
3079
+ "transfer-encoding",
3080
+ "upgrade"
3081
+ ]);
3082
+ function policyError() {
3083
+ return new IntegrationPolicyError();
3084
+ }
3085
+ function responseLimit() {
3086
+ return new IntegrationTransportError("INTEGRATION_RESPONSE_LIMIT", "response_limit_exceeded");
3087
+ }
3088
+ function positiveInteger(value, fallback) {
3089
+ const resolved = value ?? fallback;
3090
+ if (!Number.isSafeInteger(resolved) || resolved < 1) throw policyError();
3091
+ return resolved;
3092
+ }
3093
+ function validatedOrigin(input) {
3094
+ const origin = new URL(input.href);
3095
+ if (origin.protocol !== "https:" || origin.username !== "" || origin.password !== "" || origin.pathname !== "/" || origin.search !== "" || origin.hash !== "") {
3096
+ throw policyError();
3097
+ }
3098
+ return origin;
3099
+ }
3100
+ function validatedPath(origin, pathAndQuery) {
3101
+ if (typeof pathAndQuery !== "string" || !pathAndQuery.startsWith("/") || pathAndQuery.startsWith("//") || pathAndQuery.includes("\\") || pathAndQuery.includes("#")) {
3102
+ throw policyError();
3103
+ }
3104
+ const rawPath = pathAndQuery.split("?", 1)[0];
3105
+ let decodedPath;
3106
+ try {
3107
+ decodedPath = decodeURIComponent(rawPath);
3108
+ } catch {
3109
+ throw policyError();
3110
+ }
3111
+ if (decodedPath.startsWith("//") || decodedPath.includes("\\")) throw policyError();
3112
+ const target = new URL(pathAndQuery, origin);
3113
+ if (target.origin !== origin.origin) throw policyError();
3114
+ return target;
3115
+ }
3116
+ function validatedRequestHeaders(input) {
3117
+ let headers;
3118
+ try {
3119
+ headers = new Headers(input);
3120
+ } catch {
3121
+ throw policyError();
3122
+ }
3123
+ const result = {};
3124
+ for (const [name, value] of headers) {
3125
+ const normalized = name.toLowerCase();
3126
+ if (FORBIDDEN_REQUEST_HEADERS.has(normalized) || normalized.startsWith("proxy-")) {
3127
+ throw policyError();
3128
+ }
3129
+ result[normalized] = value;
3130
+ }
3131
+ return Object.freeze(result);
3132
+ }
3133
+ function boundedResponseHeaders(input) {
3134
+ if (input.length > MAX_RESPONSE_HEADER_FIELDS) throw responseLimit();
3135
+ const encoder = new TextEncoder();
3136
+ let size = 0;
3137
+ const result = {};
3138
+ const contentLengths = [];
3139
+ for (const [name, value] of input) {
3140
+ size += encoder.encode(name).byteLength + encoder.encode(value).byteLength;
3141
+ if (size > MAX_RESPONSE_HEADER_BYTES) throw responseLimit();
3142
+ const normalized = name.toLowerCase();
3143
+ if (normalized === "content-length") contentLengths.push(value);
3144
+ result[normalized] = value;
3145
+ }
3146
+ if (contentLengths.length > 1 || contentLengths.length === 1 && !/^\d+$/.test(contentLengths[0])) {
3147
+ throw responseLimit();
3148
+ }
3149
+ return Object.freeze(result);
3150
+ }
3151
+ function safeAbort(name) {
3152
+ return new DOMException(
3153
+ name === "AbortError" ? "Integration request cancelled" : "Integration request timed out",
3154
+ name
3155
+ );
3156
+ }
3157
+ function requestSignal(context, timeoutMs) {
3158
+ if (context.signal.aborted) throw safeAbort("AbortError");
3159
+ const remaining = context.deadlineMonotonicMs === void 0 ? timeoutMs : Math.min(timeoutMs, context.deadlineMonotonicMs - performance.now());
3160
+ if (remaining <= 0) throw safeAbort("TimeoutError");
3161
+ const controller = new AbortController();
3162
+ const onAbort = () => controller.abort(safeAbort("AbortError"));
3163
+ context.signal.addEventListener("abort", onAbort, { once: true });
3164
+ const timer = setTimeout(() => controller.abort(safeAbort("TimeoutError")), remaining);
3165
+ return {
3166
+ signal: controller.signal,
3167
+ dispose() {
3168
+ clearTimeout(timer);
3169
+ context.signal.removeEventListener("abort", onAbort);
3170
+ }
3171
+ };
3172
+ }
3173
+ async function withAbort(operation, signal) {
3174
+ if (signal.aborted) throw signal.reason;
3175
+ return new Promise((resolve, reject) => {
3176
+ const onAbort = () => {
3177
+ cleanup();
3178
+ reject(signal.reason);
3179
+ };
3180
+ const cleanup = () => signal.removeEventListener("abort", onAbort);
3181
+ signal.addEventListener("abort", onAbort, { once: true });
3182
+ void operation.then(
3183
+ (value) => {
3184
+ cleanup();
3185
+ resolve(value);
3186
+ },
3187
+ (error) => {
3188
+ cleanup();
3189
+ reject(error);
3190
+ }
3191
+ );
3192
+ });
3193
+ }
3194
+ var NodeHttpsTransport = class {
3195
+ agent = new https.Agent({ keepAlive: true });
3196
+ request(url, init) {
3197
+ return new Promise((resolve, reject) => {
3198
+ const request = https.request(
3199
+ url,
3200
+ { method: init.method, headers: init.headers, agent: this.agent },
3201
+ (response) => {
3202
+ const headers = [];
3203
+ for (let index = 0; index < response.rawHeaders.length; index += 2) {
3204
+ headers.push([response.rawHeaders[index], response.rawHeaders[index + 1] ?? ""]);
3205
+ }
3206
+ resolve({
3207
+ status: response.statusCode ?? 0,
3208
+ headers,
3209
+ body: response,
3210
+ close: () => response.destroy()
3211
+ });
3212
+ }
3213
+ );
3214
+ const onAbort = () => request.destroy(init.signal.reason);
3215
+ init.signal.addEventListener("abort", onAbort, { once: true });
3216
+ request.once("error", reject);
3217
+ request.once("close", () => init.signal.removeEventListener("abort", onAbort));
3218
+ request.end(init.body);
3219
+ });
3220
+ }
3221
+ close() {
3222
+ this.agent.destroy();
3223
+ }
3224
+ };
3225
+ var FixedOriginRequesterImpl = class {
3226
+ constructor(policy, transport, observability = {}) {
3227
+ this.transport = transport;
3228
+ this.origin = validatedOrigin(policy.origin);
3229
+ this.integration = policy.integration;
3230
+ this.timeoutMs = positiveInteger(policy.timeoutMs, DEFAULT_TIMEOUT_MS);
3231
+ this.maxResponseBytes = positiveInteger(policy.maxResponseBytes, DEFAULT_MAX_RESPONSE_BYTES);
3232
+ const allowedMethods = policy.allowedMethods ?? ["GET", "POST"];
3233
+ if (allowedMethods.length === 0 || allowedMethods.some((method) => method !== "GET" && method !== "POST")) {
3234
+ throw policyError();
3235
+ }
3236
+ this.allowedMethods = new Set(allowedMethods);
3237
+ this.metrics = observability.metricsSink ?? NOOP_METRICS;
3238
+ this.trace = observability.traceSink ?? NOOP_TRACE;
3239
+ this.monotonicNow = observability.monotonicNow ?? (() => performance.now());
3240
+ }
3241
+ transport;
3242
+ origin;
3243
+ timeoutMs;
3244
+ maxResponseBytes;
3245
+ allowedMethods;
3246
+ integration;
3247
+ metrics;
3248
+ trace;
3249
+ monotonicNow;
3250
+ closed = false;
3251
+ async request(pathAndQuery, init, context) {
3252
+ const started = this.monotonicNow();
3253
+ const operation = init.method === "GET" ? "read" : "mutation";
3254
+ const span = startSpan(this.trace, "kaji.integration.request", {
3255
+ "session.id": context.sessionId,
3256
+ "turn.id": context.turnId,
3257
+ "request.id": context.requestId,
3258
+ "trace.id": context.traceId,
3259
+ "tool.call_id": context.toolCallId,
3260
+ "integration.name": this.integration,
3261
+ "integration.operation": operation,
3262
+ "http.status_family": "none"
3263
+ });
3264
+ let outcome = "error";
3265
+ let scope;
3266
+ let response;
3267
+ try {
3268
+ if (this.closed) throw policyError();
3269
+ if (!this.allowedMethods.has(init.method)) throw policyError();
3270
+ if (init.body !== void 0 && !(init.body instanceof Uint8Array)) throw policyError();
3271
+ const url = validatedPath(this.origin, pathAndQuery);
3272
+ const headers = validatedRequestHeaders(init.headers);
3273
+ scope = requestSignal(context, this.timeoutMs);
3274
+ const signal = scope.signal;
3275
+ const pendingResponse = this.transport.request(url, {
3276
+ method: init.method,
3277
+ headers,
3278
+ ...init.body === void 0 ? {} : { body: init.body },
3279
+ signal
3280
+ });
3281
+ void pendingResponse.then((lateResponse) => {
3282
+ if (signal.aborted && response === void 0) lateResponse.close();
3283
+ }).catch(() => void 0);
3284
+ response = await withAbort(pendingResponse, signal);
3285
+ const boundedHeaders = boundedResponseHeaders(response.headers);
3286
+ if (response.status >= 300 && response.status < 400) {
3287
+ throw new IntegrationTransportError("INTEGRATION_REDIRECT_REJECTED", "redirect_rejected");
3288
+ }
3289
+ const contentLength = boundedHeaders["content-length"];
3290
+ if (contentLength !== void 0 && Number(contentLength) > this.maxResponseBytes) {
3291
+ throw responseLimit();
3292
+ }
3293
+ const iterator = response.body[Symbol.asyncIterator]();
3294
+ const chunks = [];
3295
+ let size = 0;
3296
+ while (true) {
3297
+ const next = await withAbort(iterator.next(), scope.signal);
3298
+ if (next.done) break;
3299
+ if (!(next.value instanceof Uint8Array)) throw responseLimit();
3300
+ size += next.value.byteLength;
3301
+ if (size > this.maxResponseBytes) {
3302
+ throw responseLimit();
3303
+ }
3304
+ chunks.push(next.value);
3305
+ }
3306
+ const bytes = new Uint8Array(size);
3307
+ let offset = 0;
3308
+ for (const chunk of chunks) {
3309
+ bytes.set(chunk, offset);
3310
+ offset += chunk.byteLength;
3311
+ }
3312
+ const family = Math.floor(response.status / 100);
3313
+ span.setAttribute("http.status_family", family >= 1 && family <= 5 ? `${family}xx` : "none");
3314
+ outcome = response.status >= 200 && response.status < 300 ? "success" : "error";
3315
+ return { status: response.status, headers: boundedHeaders, bytes };
3316
+ } catch (error) {
3317
+ response?.close();
3318
+ if (error instanceof DOMException && error.name === "AbortError") outcome = "cancelled";
3319
+ span.recordError(error);
3320
+ throw error;
3321
+ } finally {
3322
+ scope?.dispose();
3323
+ recordMetric(
3324
+ this.metrics,
3325
+ "kaji.integration.request_ms",
3326
+ Math.max(0, this.monotonicNow() - started),
3327
+ { integration: this.integration, operation, outcome }
3328
+ );
3329
+ span.end();
3330
+ }
3331
+ }
3332
+ close() {
3333
+ if (this.closed) return;
3334
+ this.transport.close?.();
3335
+ this.closed = true;
3336
+ }
3337
+ };
3338
+ var productionTransport = () => new NodeHttpsTransport();
3339
+ function createGitHubRequester(observability = {}) {
3340
+ return new FixedOriginRequesterImpl(
3341
+ { origin: new URL("https://api.github.com/"), integration: "github" },
3342
+ productionTransport(),
3343
+ observability
3344
+ );
3345
+ }
3346
+ function createGmailRequester(observability = {}) {
3347
+ return new FixedOriginRequesterImpl(
3348
+ { origin: new URL("https://gmail.googleapis.com/"), integration: "gmail" },
3349
+ productionTransport(),
3350
+ observability
3351
+ );
3352
+ }
3353
+
3354
+ // src/integrations/public.ts
3355
+ function snapshotIntegrationResult(value) {
3356
+ return durableJsonSnapshot(value, "tool_result", MAX_DURABLE_TOOL_RESULT_BYTES);
3357
+ }
3358
+
3359
+ exports.INTEGRATION_RECOVERY = INTEGRATION_RECOVERY;
3360
+ exports.IntegrationAuthRequiredError = IntegrationAuthRequiredError;
3361
+ exports.IntegrationExecutionError = IntegrationExecutionError;
3362
+ exports.IntegrationPolicyError = IntegrationPolicyError;
3363
+ exports.IntegrationRateLimitedError = IntegrationRateLimitedError;
3364
+ exports.IntegrationTransientReadError = IntegrationTransientReadError;
3365
+ exports.closedRecoveryFields = closedRecoveryFields;
3366
+ exports.createGitHubRequester = createGitHubRequester;
3367
+ exports.createGmailRequester = createGmailRequester;
3368
+ exports.snapshotIntegrationResult = snapshotIntegrationResult;
3369
+ //# sourceMappingURL=integrations.cjs.map
3370
+ //# sourceMappingURL=integrations.cjs.map