@gajae-code/ai 0.15.6 → 0.16.1

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 (51) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/types/adapter-internals/aws-region.d.ts +7 -0
  3. package/dist/types/core.d.ts +1 -0
  4. package/dist/types/index.d.ts +1 -0
  5. package/dist/types/provider-models/openai-compat.d.ts +1 -0
  6. package/dist/types/providers/anthropic.d.ts +1 -1
  7. package/dist/types/providers/cursor.d.ts +27 -1
  8. package/dist/types/providers/google-gemini-headers.d.ts +1 -1
  9. package/dist/types/providers/openai-codex-responses.d.ts +6 -0
  10. package/dist/types/utils/discovery/openai-compatible.d.ts +21 -0
  11. package/dist/types/utils/h2-fetch.d.ts +7 -0
  12. package/dist/types/utils/schema/normalize.d.ts +0 -5
  13. package/dist/types/utils/sqlite-errors.d.ts +4 -0
  14. package/package.json +3 -3
  15. package/src/adapter-internals/aws-region.d.ts +7 -0
  16. package/src/adapter-internals/aws-region.ts +14 -0
  17. package/src/auth-broker/server.ts +10 -1
  18. package/src/auth-storage.ts +14 -14
  19. package/src/core.ts +1 -0
  20. package/src/index.ts +1 -0
  21. package/src/model-thinking.ts +8 -0
  22. package/src/models.json +201 -3
  23. package/src/provider-models/openai-compat.ts +93 -8
  24. package/src/providers/amazon-bedrock.ts +5 -1
  25. package/src/providers/anthropic.d.ts +1 -1
  26. package/src/providers/anthropic.ts +1 -1
  27. package/src/providers/aws-credentials.ts +6 -0
  28. package/src/providers/cursor.d.ts +27 -1
  29. package/src/providers/cursor.ts +234 -17
  30. package/src/providers/google-gemini-headers.d.ts +1 -1
  31. package/src/providers/google-gemini-headers.ts +1 -1
  32. package/src/providers/kiro-api-key.ts +33 -8
  33. package/src/providers/kiro-codewhisperer.ts +4 -1
  34. package/src/providers/openai-codex-responses.d.ts +6 -0
  35. package/src/providers/openai-codex-responses.ts +17 -2
  36. package/src/providers/pi-native-client.ts +24 -1
  37. package/src/utils/discovery/antigravity.ts +10 -1
  38. package/src/utils/discovery/openai-compatible.ts +38 -0
  39. package/src/utils/h2-fetch.ts +10 -0
  40. package/src/utils/oauth/callback-server.ts +8 -1
  41. package/src/utils/oauth/glm-zcode.ts +1 -1
  42. package/src/utils/oauth/kiro.ts +91 -22
  43. package/src/utils/schema/dereference.ts +169 -49
  44. package/src/utils/schema/draft.ts +46 -23
  45. package/src/utils/schema/normalize.d.ts +0 -5
  46. package/src/utils/schema/normalize.ts +396 -119
  47. package/src/utils/schema/types.ts +3 -1
  48. package/src/utils/schema/zod-decontaminate.ts +83 -29
  49. package/src/utils/sqlite-errors.d.ts +4 -0
  50. package/src/utils/sqlite-errors.ts +13 -0
  51. package/src/utils/tool-choice-capability.ts +2 -3
@@ -6,6 +6,8 @@ export function isJsonObject(value: unknown): value is JsonObject {
6
6
 
7
7
  /** True when `value` is a plain JSON object with no own enumerable keys. */
8
8
  export function isJsonObjectEmpty(value: JsonObject): boolean {
9
- for (const _ in value) return false;
9
+ for (const key in value) {
10
+ if (Object.hasOwn(value, key)) return false;
11
+ }
10
12
  return true;
11
13
  }
@@ -114,17 +114,40 @@ const KEYS_THAT_ACCEPT_NULL: Record<string, true> = {
114
114
  const: true,
115
115
  examples: true,
116
116
  };
117
+ const JSON_SCHEMA_LITERAL_PAYLOAD_KEYS = new Set(["default", "const", "enum", "examples"]);
118
+ const JSON_SCHEMA_MAP_KEYS = new Set([
119
+ "properties",
120
+ "patternProperties",
121
+ "dependencies",
122
+ "dependentSchemas",
123
+ "$defs",
124
+ "definitions",
125
+ ]);
126
+
127
+ function setOwnKey(target: JsonObject, key: string, value: unknown): void {
128
+ if (key === "__proto__") {
129
+ Object.defineProperty(target, key, { value, writable: true, enumerable: true, configurable: true });
130
+ return;
131
+ }
132
+ target[key] = value;
133
+ }
117
134
 
118
135
  function isZodLeak(node: JsonObject): boolean {
136
+ if (!Object.hasOwn(node, "def") || !Object.hasOwn(node, "type")) return false;
119
137
  const def = node.def;
120
138
  if (!isJsonObject(def)) return false;
139
+ if (!Object.hasOwn(def, "type")) return false;
121
140
  const defType = def.type;
122
- if (typeof defType !== "string" || !ZOD_KINDS[defType]) return false;
141
+ if (typeof defType !== "string" || !Object.hasOwn(ZOD_KINDS, defType)) return false;
123
142
  // Both surface and inner `.type` must agree — Zod always mirrors `_def.type`
124
143
  // onto the instance, so this is a near-zero false-positive guard.
125
144
  return node.type === defType;
126
145
  }
127
146
 
147
+ function ownValue(object: JsonObject, key: string): unknown {
148
+ return Object.hasOwn(object, key) ? object[key] : undefined;
149
+ }
150
+
128
151
  function inferTypeFromValues(values: readonly unknown[]): string {
129
152
  if (values.length === 0) return "string";
130
153
  const first = values[0];
@@ -139,16 +162,20 @@ function unwrapInnerSchema(def: JsonObject): unknown {
139
162
  // optional/nullable/readonly/brand/default → `innerType`
140
163
  // pipe → `in` (or `out`)
141
164
  // lazy → `getter` (a function — gone after JSON.stringify); fall back to {}
142
- return def.innerType ?? def.in ?? def.out ?? def.schema ?? def.element ?? {};
165
+ for (const key of ["innerType", "in", "out", "schema", "element"]) {
166
+ if (Object.hasOwn(def, key) && def[key] !== undefined) return def[key];
167
+ }
168
+ return {};
143
169
  }
144
170
 
145
171
  function copyWithoutNoise(node: JsonObject): JsonObject {
146
172
  const out: JsonObject = {};
147
173
  for (const key in node) {
148
- if (ZOD_NOISE_KEYS[key]) continue;
174
+ if (!Object.hasOwn(node, key)) continue;
175
+ if (Object.hasOwn(ZOD_NOISE_KEYS, key)) continue;
149
176
  const value = node[key];
150
- if (value === null && !KEYS_THAT_ACCEPT_NULL[key]) continue;
151
- out[key] = value;
177
+ if (value === null && !Object.hasOwn(KEYS_THAT_ACCEPT_NULL, key)) continue;
178
+ setOwnKey(out, key, value);
152
179
  }
153
180
  return out;
154
181
  }
@@ -161,15 +188,19 @@ function rewriteZodNode(node: JsonObject, seen: WeakSet<object>): unknown {
161
188
  case "enum": {
162
189
  // Prefer node.options (array form Zod exposes) → def.entries values →
163
190
  // object-shaped node.enum values. All three carry the same data.
164
- const optionsArray = Array.isArray(node.options) ? (node.options as unknown[]) : null;
165
- const entries = isJsonObject(def.entries) ? Object.values(def.entries) : null;
166
- const enumObj = isJsonObject(node.enum) ? Object.values(node.enum) : null;
191
+ const optionsValue = Object.hasOwn(node, "options") ? node.options : undefined;
192
+ const entriesValue = Object.hasOwn(def, "entries") ? def.entries : undefined;
193
+ const enumValue = Object.hasOwn(node, "enum") ? node.enum : undefined;
194
+ const optionsArray = Array.isArray(optionsValue) ? optionsValue : null;
195
+ const entries = isJsonObject(entriesValue) ? Object.values(entriesValue) : null;
196
+ const enumObj = isJsonObject(enumValue) ? Object.values(enumValue) : null;
167
197
  const values = optionsArray ?? entries ?? enumObj ?? [];
168
198
  return { type: inferTypeFromValues(values), enum: values };
169
199
  }
170
200
 
171
201
  case "literal": {
172
- const values = Array.isArray(def.values) ? (def.values as unknown[]) : [];
202
+ const valuesValue = ownValue(def, "values");
203
+ const values = Array.isArray(valuesValue) ? valuesValue : [];
173
204
  if (values.length === 1) {
174
205
  return { const: values[0] };
175
206
  }
@@ -181,49 +212,50 @@ function rewriteZodNode(node: JsonObject, seen: WeakSet<object>): unknown {
181
212
 
182
213
  case "union":
183
214
  case "discriminatedUnion": {
184
- const arms = Array.isArray(def.options)
185
- ? (def.options as unknown[])
186
- : Array.isArray(node.options)
187
- ? (node.options as unknown[])
188
- : [];
215
+ const defOptions = Object.hasOwn(def, "options") ? def.options : undefined;
216
+ const nodeOptions = Object.hasOwn(node, "options") ? node.options : undefined;
217
+ const arms = Array.isArray(defOptions) ? defOptions : Array.isArray(nodeOptions) ? nodeOptions : [];
189
218
  return { anyOf: arms.map(x => walk(x, seen)) };
190
219
  }
191
220
 
192
221
  case "intersection": {
193
222
  return {
194
- allOf: [walk(def.left, seen), walk(def.right, seen)],
223
+ allOf: [walk(ownValue(def, "left"), seen), walk(ownValue(def, "right"), seen)],
195
224
  };
196
225
  }
197
226
 
198
227
  case "array": {
199
- return { type: "array", items: walk(def.element, seen) };
228
+ return { type: "array", items: walk(ownValue(def, "element"), seen) };
200
229
  }
201
230
 
202
231
  case "set": {
203
- const element = def.valueType ?? def.element;
232
+ const element = ownValue(def, "valueType") ?? ownValue(def, "element");
204
233
  return { type: "array", uniqueItems: true, items: walk(element, seen) };
205
234
  }
206
235
 
207
236
  case "tuple": {
208
- const items = Array.isArray(def.items) ? (def.items as unknown[]) : [];
237
+ const itemsValue = ownValue(def, "items");
238
+ const items = Array.isArray(itemsValue) ? itemsValue : [];
209
239
  const out: JsonObject = { type: "array", prefixItems: items.map(x => walk(x, seen)) };
210
- const rest = def.rest;
240
+ const rest = ownValue(def, "rest");
211
241
  if (rest != null) out.items = walk(rest, seen);
212
242
  return out;
213
243
  }
214
244
 
215
245
  case "record":
216
246
  case "map": {
217
- return { type: "object", additionalProperties: walk(def.valueType, seen) };
247
+ return { type: "object", additionalProperties: walk(ownValue(def, "valueType"), seen) };
218
248
  }
219
249
 
220
250
  case "object": {
221
- const shape = isJsonObject(def.shape) ? def.shape : ({} as JsonObject);
251
+ const shapeValue = ownValue(def, "shape");
252
+ const shape = isJsonObject(shapeValue) ? shapeValue : ({} as JsonObject);
222
253
  const properties: JsonObject = {};
223
254
  const required: string[] = [];
224
255
  for (const key in shape) {
256
+ if (!Object.hasOwn(shape, key)) continue;
225
257
  const inner = walk(shape[key], seen);
226
- properties[key] = inner;
258
+ setOwnKey(properties, key, inner);
227
259
  if (!isOptionalEntry(shape[key])) required.push(key);
228
260
  }
229
261
  const out: JsonObject = { type: "object", properties };
@@ -244,10 +276,10 @@ function rewriteZodNode(node: JsonObject, seen: WeakSet<object>): unknown {
244
276
  case "transform": {
245
277
  const inner = walk(unwrapInnerSchema(def), seen);
246
278
  if (kind === "nullable" && isJsonObject(inner)) {
247
- if (typeof inner.type === "string") {
279
+ if (Object.hasOwn(inner, "type") && typeof inner.type === "string") {
248
280
  return { ...inner, type: [inner.type, "null"] };
249
281
  }
250
- if (Array.isArray(inner.type)) {
282
+ if (Object.hasOwn(inner, "type") && Array.isArray(inner.type)) {
251
283
  return (inner.type as string[]).includes("null")
252
284
  ? inner
253
285
  : { ...inner, type: [...(inner.type as string[]), "null"] };
@@ -266,7 +298,7 @@ function rewriteZodNode(node: JsonObject, seen: WeakSet<object>): unknown {
266
298
  const mapped = ZOD_SCALAR_TO_JSON_TYPE[kind];
267
299
  if (mapped) {
268
300
  cleaned.type = mapped;
269
- } else if (typeof cleaned.type === "string" && !VALID_JSON_SCHEMA_TYPES[cleaned.type]) {
301
+ } else if (typeof cleaned.type === "string" && !Object.hasOwn(VALID_JSON_SCHEMA_TYPES, cleaned.type)) {
270
302
  delete cleaned.type;
271
303
  }
272
304
  // Object-shaped `enum` survives as a noise field — remove if present.
@@ -281,7 +313,8 @@ function rewriteZodNode(node: JsonObject, seen: WeakSet<object>): unknown {
281
313
  function isOptionalEntry(value: unknown): boolean {
282
314
  if (!isJsonObject(value)) return false;
283
315
  if (!isZodLeak(value)) return false;
284
- const kind = (value.def as JsonObject).type;
316
+ const def = value.def as JsonObject;
317
+ const kind = Object.hasOwn(def, "type") ? def.type : undefined;
285
318
  return kind === "optional" || kind === "default" || kind === "prefault";
286
319
  }
287
320
 
@@ -294,7 +327,20 @@ export function decontaminateZodInstance(value: unknown): unknown {
294
327
  return walk(value, new WeakSet());
295
328
  }
296
329
 
297
- function walk(value: unknown, seen: WeakSet<object>): unknown {
330
+ function walkSchemaMap(value: JsonObject, seen: WeakSet<object>): JsonObject {
331
+ let changed = false;
332
+ const out: JsonObject = {};
333
+ for (const key in value) {
334
+ if (!Object.hasOwn(value, key)) continue;
335
+ const child = value[key];
336
+ const rewritten = walk(child, seen);
337
+ if (rewritten !== child) changed = true;
338
+ setOwnKey(out, key, rewritten);
339
+ }
340
+ return changed ? out : value;
341
+ }
342
+
343
+ function walk(value: unknown, seen: WeakSet<object>, inSchemaMap = false): unknown {
298
344
  if (Array.isArray(value)) {
299
345
  if (seen.has(value)) return value;
300
346
  seen.add(value);
@@ -322,10 +368,18 @@ function walk(value: unknown, seen: WeakSet<object>): unknown {
322
368
  let changed = false;
323
369
  const out: JsonObject = {};
324
370
  for (const key in value) {
371
+ if (!Object.hasOwn(value, key)) continue;
325
372
  const child = value[key];
326
- const rewritten = walk(child, seen);
373
+ if (!inSchemaMap && JSON_SCHEMA_LITERAL_PAYLOAD_KEYS.has(key)) {
374
+ setOwnKey(out, key, child);
375
+ continue;
376
+ }
377
+ const rewritten =
378
+ !inSchemaMap && JSON_SCHEMA_MAP_KEYS.has(key) && isJsonObject(child)
379
+ ? walkSchemaMap(child, seen)
380
+ : walk(child, seen);
327
381
  if (rewritten !== child) changed = true;
328
- out[key] = rewritten;
382
+ setOwnKey(out, key, rewritten);
329
383
  }
330
384
  return changed ? out : value;
331
385
  }
@@ -0,0 +1,4 @@
1
+ /** Return whether an error carries a SQLite result code. */
2
+ export declare function isSqliteError(error: unknown): boolean;
3
+ /** Return whether an error is one of SQLite's explicit database-corruption classes. */
4
+ export declare function isSqliteCorruptionError(error: unknown): boolean;
@@ -0,0 +1,13 @@
1
+ /** Return whether an error carries a SQLite result code. */
2
+ export function isSqliteError(error: unknown): boolean {
3
+ if (!error || typeof error !== "object") return false;
4
+ const code = (error as { code?: unknown }).code;
5
+ return typeof code === "string" && code.startsWith("SQLITE_");
6
+ }
7
+
8
+ /** Return whether an error is one of SQLite's explicit database-corruption classes. */
9
+ export function isSqliteCorruptionError(error: unknown): boolean {
10
+ if (!isSqliteError(error)) return false;
11
+ const code = (error as { code?: unknown }).code;
12
+ return code === "SQLITE_CORRUPT" || code === "SQLITE_NOTADB";
13
+ }
@@ -6,6 +6,7 @@ import { getToolChoiceCapabilityCachePath } from "@gajae-code/utils/dirs";
6
6
  import { extractHttpStatusFromError } from "@gajae-code/utils/fetch-retry";
7
7
  import * as logger from "@gajae-code/utils/logger";
8
8
  import type { Api, Model, ToolChoice, ToolChoiceCompat, ToolChoiceSupport, ToolChoiceSupportSource } from "../types";
9
+ import { isSqliteCorruptionError } from "./sqlite-errors";
9
10
 
10
11
  const supportRank: Record<ToolChoiceSupport, number> = {
11
12
  none: 0,
@@ -575,9 +576,7 @@ class CapabilityCacheCorruptionError extends Error {}
575
576
 
576
577
  function isCorruptCapabilityCacheError(error: unknown): boolean {
577
578
  if (error instanceof CapabilityCacheCorruptionError) return true;
578
- if (!error || typeof error !== "object") return false;
579
- const code = (error as { code?: unknown }).code;
580
- return code === "SQLITE_CORRUPT" || code === "SQLITE_NOTADB";
579
+ return isSqliteCorruptionError(error);
581
580
  }
582
581
 
583
582
  /**