@gajae-code/ai 0.11.2 → 0.11.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.11.4] - 2026-07-20
6
+
7
+ ### Added
8
+
9
+ - Added the native Kimi Code `k3` catalog entry with its 1M-token context window, multimodal input, and reasoning support.
10
+
5
11
  ## [0.11.2] - 2026-07-19
6
12
 
7
13
  ### Fixed
@@ -519,10 +519,20 @@ export type TSchema = ZodType | TJsonSchema;
519
519
  export type Static<S> = S extends ZodType ? z.infer<S> : S extends {
520
520
  static: infer T;
521
521
  } ? T : unknown;
522
+ export type RawArgumentValidationResult = {
523
+ outcome: "passthrough";
524
+ } | {
525
+ outcome: "accept";
526
+ arguments: ToolCall["arguments"];
527
+ } | {
528
+ outcome: "reject";
529
+ };
522
530
  export interface Tool<TParameters extends TSchema = TSchema> {
523
531
  name: string;
524
532
  description: string;
525
533
  parameters: TParameters;
534
+ /** Optional pre-coercion adapter for narrowly scoped raw argument recovery or rejection. */
535
+ rawArgumentValidation?: (arguments_: ToolCall["arguments"]) => RawArgumentValidationResult;
526
536
  /** If true, tool is strictly typed and validated against the parameters schema before execution */
527
537
  strict?: boolean;
528
538
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/ai",
4
- "version": "0.11.2",
4
+ "version": "0.11.4",
5
5
  "description": "Unified LLM API with automatic model discovery and provider configuration",
6
6
  "homepage": "https://gajae-code.com",
7
7
  "author": "Yeachan-Heo and Gajae Code Contributors",
@@ -40,7 +40,7 @@
40
40
  "dependencies": {
41
41
  "@anthropic-ai/sdk": "^0.94.0",
42
42
  "@bufbuild/protobuf": "^2.12.0",
43
- "@gajae-code/utils": "0.11.2",
43
+ "@gajae-code/utils": "0.11.4",
44
44
  "openai": "^6.36.0",
45
45
  "partial-json": "^0.1.7",
46
46
  "zod": "4.4.3"
@@ -50,6 +50,7 @@ const GEMINI_3_FLASH_EFFORTS: readonly Effort[] = [Effort.Minimal, Effort.Low, E
50
50
  const GPT_5_2_PLUS_EFFORTS: readonly Effort[] = [Effort.Low, Effort.Medium, Effort.High, Effort.XHigh];
51
51
  const GPT_5_6_PLUS_EFFORTS: readonly Effort[] = [Effort.Low, Effort.Medium, Effort.High, Effort.XHigh, Effort.Max];
52
52
  const GPT_5_5_DEFAULT_EFFORT = Effort.XHigh;
53
+ const KIMI_K3_EFFORTS: readonly Effort[] = [Effort.Low, Effort.High, Effort.Max];
53
54
 
54
55
  const GPT_5_1_CODEX_MINI_EFFORTS: readonly Effort[] = [Effort.Medium, Effort.High];
55
56
  const CLOUDFLARE_AI_GATEWAY_BASE_URL = "https://gateway.ai.cloudflare.com/v1/<account>/<gateway>/anthropic";
@@ -516,6 +517,9 @@ function applyOpenAICatalogPolicy(model: ApiModel<Api>, parsedModel: OpenAIModel
516
517
  }
517
518
 
518
519
  function inferDefaultEffort<TApi extends Api>(model: ApiModel<TApi>, parsedModel: ParsedModel): Effort | undefined {
520
+ if (model.provider === "kimi-code" && model.id === "k3") {
521
+ return Effort.High;
522
+ }
519
523
  if (
520
524
  parsedModel.family === "openai" &&
521
525
  model.provider === "openai-codex" &&
@@ -591,6 +595,9 @@ function expandEffortRange(thinking: ThinkingConfig): readonly Effort[] {
591
595
  }
592
596
 
593
597
  function inferSupportedEfforts<TApi extends Api>(parsedModel: ParsedModel, model: ApiModel<TApi>): readonly Effort[] {
598
+ if (model.provider === "kimi-code" && model.id === "k3") {
599
+ return KIMI_K3_EFFORTS;
600
+ }
594
601
  switch (parsedModel.family) {
595
602
  case "openai":
596
603
  return inferOpenAISupportedEfforts(parsedModel);
package/src/models.json CHANGED
@@ -21259,6 +21259,42 @@
21259
21259
  }
21260
21260
  },
21261
21261
  "kimi-code": {
21262
+ "k3": {
21263
+ "id": "k3",
21264
+ "name": "K3",
21265
+ "api": "openai-completions",
21266
+ "provider": "kimi-code",
21267
+ "baseUrl": "https://api.kimi.com/coding/v1",
21268
+ "reasoning": true,
21269
+ "input": [
21270
+ "text",
21271
+ "image"
21272
+ ],
21273
+ "cost": {
21274
+ "input": 0,
21275
+ "output": 0,
21276
+ "cacheRead": 0,
21277
+ "cacheWrite": 0
21278
+ },
21279
+ "contextWindow": 1048576,
21280
+ "maxTokens": 32000,
21281
+ "compat": {
21282
+ "thinkingFormat": "zai",
21283
+ "reasoningContentField": "reasoning_content",
21284
+ "supportsDeveloperRole": false
21285
+ },
21286
+ "thinking": {
21287
+ "mode": "effort",
21288
+ "minLevel": "low",
21289
+ "maxLevel": "max",
21290
+ "defaultLevel": "high",
21291
+ "levels": [
21292
+ "low",
21293
+ "high",
21294
+ "max"
21295
+ ]
21296
+ }
21297
+ },
21262
21298
  "kimi-for-coding": {
21263
21299
  "id": "kimi-for-coding",
21264
21300
  "name": "Kimi For Coding",
package/src/types.ts CHANGED
@@ -709,10 +709,17 @@ export type TSchema = ZodType | TJsonSchema;
709
709
  /** Resolve parameter types for tool execution / handlers. */
710
710
  export type Static<S> = S extends ZodType ? z.infer<S> : S extends { static: infer T } ? T : unknown;
711
711
 
712
+ export type RawArgumentValidationResult =
713
+ | { outcome: "passthrough" }
714
+ | { outcome: "accept"; arguments: ToolCall["arguments"] }
715
+ | { outcome: "reject" };
716
+
712
717
  export interface Tool<TParameters extends TSchema = TSchema> {
713
718
  name: string;
714
719
  description: string;
715
720
  parameters: TParameters;
721
+ /** Optional pre-coercion adapter for narrowly scoped raw argument recovery or rejection. */
722
+ rawArgumentValidation?: (arguments_: ToolCall["arguments"]) => RawArgumentValidationResult;
716
723
  /** If true, tool is strictly typed and validated against the parameters schema before execution */
717
724
  strict?: boolean;
718
725
  /**
@@ -967,13 +967,18 @@ export function validateToolCall(tools: Tool[], toolCall: ToolCall): ToolCall["a
967
967
  */
968
968
  export function validateToolArguments(tool: Tool, toolCall: ToolCall): ToolCall["arguments"] {
969
969
  const originalArgs = toolCall.arguments;
970
+ const rawValidation = tool.rawArgumentValidation?.(originalArgs);
971
+ if (rawValidation?.outcome === "reject") {
972
+ throw new Error(`Validation failed for tool "${toolCall.name}": raw arguments rejected before coercion`);
973
+ }
974
+ const rawArgs = rawValidation?.outcome === "accept" ? rawValidation.arguments : originalArgs;
970
975
  const ctx = getValidationContext(tool);
971
976
  const { json } = ctx;
972
977
 
973
978
  // Always normalize first — strip null and string "null" from optional
974
979
  // fields and substitute defaults. Handles LLM outputting string "null"
975
980
  // to mean "no value" even when validation would otherwise pass.
976
- let normalizedArgs: unknown = originalArgs;
981
+ let normalizedArgs: unknown = rawArgs;
977
982
  let changed = false;
978
983
  const initialNormalization = normalizeOptionalNullsForSchema(json, normalizedArgs);
979
984
  if (initialNormalization.changed) {