@aigne/core 1.72.0-beta.2 → 1.72.0-beta.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.
Files changed (105) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/lib/cjs/agents/agent.d.ts +31 -1
  3. package/lib/cjs/agents/agent.js +13 -0
  4. package/lib/cjs/agents/ai-agent.d.ts +7 -0
  5. package/lib/cjs/agents/ai-agent.js +85 -3
  6. package/lib/cjs/agents/chat-model.d.ts +153 -0
  7. package/lib/cjs/agents/chat-model.js +35 -1
  8. package/lib/cjs/agents/image-agent.d.ts +17 -1
  9. package/lib/cjs/agents/image-agent.js +16 -0
  10. package/lib/cjs/agents/image-model.d.ts +14 -4
  11. package/lib/cjs/agents/mcp-agent.d.ts +17 -0
  12. package/lib/cjs/agents/mcp-agent.js +18 -0
  13. package/lib/cjs/agents/team-agent.d.ts +55 -0
  14. package/lib/cjs/agents/team-agent.js +31 -0
  15. package/lib/cjs/agents/transform-agent.d.ts +12 -0
  16. package/lib/cjs/agents/transform-agent.js +13 -0
  17. package/lib/cjs/agents/video-model.d.ts +14 -4
  18. package/lib/cjs/aigne/usage.d.ts +4 -0
  19. package/lib/cjs/aigne/usage.js +6 -0
  20. package/lib/cjs/loader/agent-yaml.d.ts +5 -63
  21. package/lib/cjs/loader/agent-yaml.js +4 -129
  22. package/lib/cjs/loader/agents.d.ts +4 -0
  23. package/lib/cjs/loader/agents.js +17 -0
  24. package/lib/cjs/loader/index.d.ts +18 -14
  25. package/lib/cjs/loader/index.js +20 -81
  26. package/lib/cjs/loader/schema.d.ts +21 -6
  27. package/lib/cjs/loader/schema.js +60 -1
  28. package/lib/cjs/prompt/prompt-builder.js +0 -1
  29. package/lib/cjs/prompt/skills/afs/agent-skill/agent-skill.d.ts +17 -0
  30. package/lib/cjs/prompt/skills/afs/agent-skill/agent-skill.js +63 -0
  31. package/lib/cjs/prompt/skills/afs/agent-skill/skill-loader.d.ts +13 -0
  32. package/lib/cjs/prompt/skills/afs/agent-skill/skill-loader.js +61 -0
  33. package/lib/cjs/prompt/skills/afs/delete.js +15 -3
  34. package/lib/cjs/prompt/skills/afs/edit.js +30 -7
  35. package/lib/cjs/prompt/skills/afs/exec.js +17 -6
  36. package/lib/cjs/prompt/skills/afs/index.js +4 -1
  37. package/lib/cjs/prompt/skills/afs/list.js +26 -10
  38. package/lib/cjs/prompt/skills/afs/read.js +14 -3
  39. package/lib/cjs/prompt/skills/afs/rename.js +18 -4
  40. package/lib/cjs/prompt/skills/afs/search.js +21 -5
  41. package/lib/cjs/prompt/skills/afs/write.js +18 -4
  42. package/lib/cjs/prompt/template.d.ts +92 -17
  43. package/lib/cjs/prompt/template.js +46 -17
  44. package/lib/dts/agents/agent.d.ts +31 -1
  45. package/lib/dts/agents/ai-agent.d.ts +7 -0
  46. package/lib/dts/agents/chat-model.d.ts +153 -0
  47. package/lib/dts/agents/image-agent.d.ts +17 -1
  48. package/lib/dts/agents/image-model.d.ts +14 -4
  49. package/lib/dts/agents/mcp-agent.d.ts +17 -0
  50. package/lib/dts/agents/team-agent.d.ts +55 -0
  51. package/lib/dts/agents/transform-agent.d.ts +12 -0
  52. package/lib/dts/agents/video-model.d.ts +14 -4
  53. package/lib/dts/aigne/context.d.ts +2 -2
  54. package/lib/dts/aigne/usage.d.ts +4 -0
  55. package/lib/dts/loader/agent-yaml.d.ts +5 -63
  56. package/lib/dts/loader/agents.d.ts +4 -0
  57. package/lib/dts/loader/index.d.ts +18 -14
  58. package/lib/dts/loader/schema.d.ts +21 -6
  59. package/lib/dts/prompt/skills/afs/agent-skill/agent-skill.d.ts +17 -0
  60. package/lib/dts/prompt/skills/afs/agent-skill/skill-loader.d.ts +13 -0
  61. package/lib/dts/prompt/template.d.ts +92 -17
  62. package/lib/esm/agents/agent.d.ts +31 -1
  63. package/lib/esm/agents/agent.js +13 -0
  64. package/lib/esm/agents/ai-agent.d.ts +7 -0
  65. package/lib/esm/agents/ai-agent.js +85 -3
  66. package/lib/esm/agents/chat-model.d.ts +153 -0
  67. package/lib/esm/agents/chat-model.js +34 -0
  68. package/lib/esm/agents/image-agent.d.ts +17 -1
  69. package/lib/esm/agents/image-agent.js +16 -0
  70. package/lib/esm/agents/image-model.d.ts +14 -4
  71. package/lib/esm/agents/mcp-agent.d.ts +17 -0
  72. package/lib/esm/agents/mcp-agent.js +18 -0
  73. package/lib/esm/agents/team-agent.d.ts +55 -0
  74. package/lib/esm/agents/team-agent.js +31 -0
  75. package/lib/esm/agents/transform-agent.d.ts +12 -0
  76. package/lib/esm/agents/transform-agent.js +13 -0
  77. package/lib/esm/agents/video-model.d.ts +14 -4
  78. package/lib/esm/aigne/context.d.ts +2 -2
  79. package/lib/esm/aigne/usage.d.ts +4 -0
  80. package/lib/esm/aigne/usage.js +6 -0
  81. package/lib/esm/loader/agent-yaml.d.ts +5 -63
  82. package/lib/esm/loader/agent-yaml.js +4 -128
  83. package/lib/esm/loader/agents.d.ts +4 -0
  84. package/lib/esm/loader/agents.js +14 -0
  85. package/lib/esm/loader/index.d.ts +18 -14
  86. package/lib/esm/loader/index.js +21 -81
  87. package/lib/esm/loader/schema.d.ts +21 -6
  88. package/lib/esm/loader/schema.js +57 -0
  89. package/lib/esm/prompt/prompt-builder.js +1 -2
  90. package/lib/esm/prompt/skills/afs/agent-skill/agent-skill.d.ts +17 -0
  91. package/lib/esm/prompt/skills/afs/agent-skill/agent-skill.js +59 -0
  92. package/lib/esm/prompt/skills/afs/agent-skill/skill-loader.d.ts +13 -0
  93. package/lib/esm/prompt/skills/afs/agent-skill/skill-loader.js +53 -0
  94. package/lib/esm/prompt/skills/afs/delete.js +15 -3
  95. package/lib/esm/prompt/skills/afs/edit.js +30 -7
  96. package/lib/esm/prompt/skills/afs/exec.js +17 -6
  97. package/lib/esm/prompt/skills/afs/index.js +4 -1
  98. package/lib/esm/prompt/skills/afs/list.js +26 -10
  99. package/lib/esm/prompt/skills/afs/read.js +14 -3
  100. package/lib/esm/prompt/skills/afs/rename.js +18 -4
  101. package/lib/esm/prompt/skills/afs/search.js +21 -5
  102. package/lib/esm/prompt/skills/afs/write.js +18 -4
  103. package/lib/esm/prompt/template.d.ts +92 -17
  104. package/lib/esm/prompt/template.js +46 -17
  105. package/package.json +5 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.72.0-beta.4](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.72.0-beta.3...core-v1.72.0-beta.4) (2025-12-24)
4
+
5
+
6
+ ### Features
7
+
8
+ * add Agent Skill support ([#787](https://github.com/AIGNE-io/aigne-framework/issues/787)) ([f04fbe7](https://github.com/AIGNE-io/aigne-framework/commit/f04fbe76ec24cf3c59c74adf92d87b0c3784a8f7))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **cli:** improve terminal outputs ([#847](https://github.com/AIGNE-io/aigne-framework/issues/847)) ([329e91b](https://github.com/AIGNE-io/aigne-framework/commit/329e91bc3323f72fc8a2d278ff5e6bba9adbd6e0))
14
+
15
+
16
+ ### Dependencies
17
+
18
+ * The following workspace dependencies were updated
19
+ * dependencies
20
+ * @aigne/afs bumped to 1.4.0-beta.3
21
+ * @aigne/afs-history bumped to 1.2.0-beta.3
22
+
23
+ ## [1.72.0-beta.3](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.72.0-beta.2...core-v1.72.0-beta.3) (2025-12-19)
24
+
25
+
26
+ ### Features
27
+
28
+ * add prompt caching for OpenAI/Gemini/Anthropic and cache token display ([#838](https://github.com/AIGNE-io/aigne-framework/issues/838)) ([46c628f](https://github.com/AIGNE-io/aigne-framework/commit/46c628f180572ea1b955d1a9888aad6145204842))
29
+
30
+
31
+ ### Dependencies
32
+
33
+ * The following workspace dependencies were updated
34
+ * dependencies
35
+ * @aigne/observability-api bumped to 0.11.14-beta.1
36
+
3
37
  ## [1.72.0-beta.2](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.72.0-beta.1...core-v1.72.0-beta.2) (2025-12-19)
4
38
 
5
39
 
@@ -1,7 +1,7 @@
1
1
  import { AFS, type AFSExecOptions, type AFSExecResult, type AFSListOptions, type AFSListResult, type AFSModule, type AFSOptions, type AFSReadResult, type AFSSearchOptions } from "@aigne/afs";
2
2
  import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
3
3
  import type * as prompts from "@inquirer/prompts";
4
- import { type ZodObject, type ZodType } from "zod";
4
+ import { type ZodObject, type ZodType, z } from "zod";
5
5
  import type { AgentEvent, Context, UserContext } from "../aigne/context.js";
6
6
  import type { MessagePayload } from "../aigne/message-queue.js";
7
7
  import type { ContextUsage } from "../aigne/usage.js";
@@ -783,6 +783,25 @@ export interface AgentResponseProgress {
783
783
  } | {
784
784
  event: "agentFailed";
785
785
  error: Error;
786
+ } | {
787
+ event: "message";
788
+ role: "user" | "agent";
789
+ message: ({
790
+ type: "text";
791
+ content: string;
792
+ } | {
793
+ type: "thinking";
794
+ thoughts: string;
795
+ } | {
796
+ type: "tool_use";
797
+ toolUseId: string;
798
+ name: string;
799
+ input: unknown;
800
+ } | {
801
+ type: "tool_result";
802
+ toolUseId: string;
803
+ content: unknown;
804
+ })[];
786
805
  }) & Omit<AgentEvent, "agent"> & {
787
806
  agent: {
788
807
  name: string;
@@ -870,6 +889,17 @@ export interface FunctionAgentOptions<I extends Message = Message, O extends Mes
870
889
  */
871
890
  export declare class FunctionAgent<I extends Message = Message, O extends Message = Message> extends Agent<I, O> {
872
891
  tag: string;
892
+ static schema(): ZodObject<{
893
+ process: ZodType<FunctionAgentFn>;
894
+ }, "strip", z.ZodTypeAny, {
895
+ process: FunctionAgentFn<any, any, FunctionAgent<any, any>>;
896
+ }, {
897
+ process: FunctionAgentFn<any, any, FunctionAgent<any, any>>;
898
+ }>;
899
+ static load<I extends Message = any, O extends Message = any>(options: {
900
+ filepath: string;
901
+ parsed: object;
902
+ }): Promise<Agent<I, O>>;
873
903
  /**
874
904
  * Create a function agent from a function or options
875
905
  *
@@ -53,6 +53,7 @@ const nunjucks_1 = __importDefault(require("nunjucks"));
53
53
  const ufo_1 = require("ufo");
54
54
  const zod_1 = require("zod");
55
55
  const zod_to_json_schema_1 = require("zod-to-json-schema");
56
+ const function_agent_js_1 = require("../loader/function-agent.js");
56
57
  const agent_utils_js_1 = require("../utils/agent-utils.js");
57
58
  const json_schema_js_1 = require("../utils/json-schema.js");
58
59
  const logger_js_1 = require("../utils/logger.js");
@@ -873,6 +874,18 @@ function checkAgentInputOutputSchema(schema) {
873
874
  */
874
875
  class FunctionAgent extends Agent {
875
876
  tag = "FunctionAgent";
877
+ static schema() {
878
+ return zod_1.z.object({
879
+ process: zod_1.z.preprocess((v) => (typeof v === "string" ? (0, function_agent_js_1.codeToFunctionAgentFn)(v) : v), zod_1.z.custom()),
880
+ });
881
+ }
882
+ static async load(options) {
883
+ const valid = await FunctionAgent.schema().parseAsync(options.parsed);
884
+ return new FunctionAgent({
885
+ ...options.parsed,
886
+ process: valid.process,
887
+ });
888
+ }
876
889
  /**
877
890
  * Create a function agent from a function or options
878
891
  *
@@ -188,6 +188,13 @@ export declare const aiAgentOptionsSchema: ZodObject<{
188
188
  */
189
189
  export declare class AIAgent<I extends Message = any, O extends Message = any> extends Agent<I, O> {
190
190
  tag: string;
191
+ static schema<T>({ filepath }: {
192
+ filepath: string;
193
+ }): ZodType<T>;
194
+ static load<I extends Message = any, O extends Message = any>(options: {
195
+ filepath: string;
196
+ parsed: object;
197
+ }): Promise<Agent<I, O>>;
191
198
  /**
192
199
  * Create an AIAgent with the specified options
193
200
  *
@@ -35,10 +35,12 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.AIAgent = exports.aiAgentOptionsSchema = exports.aiAgentToolChoiceSchema = exports.AIAgentToolChoice = exports.DEFAULT_OUTPUT_FILE_KEY = exports.DEFAULT_OUTPUT_KEY = void 0;
37
37
  const zod_1 = require("zod");
38
+ const schema_js_1 = require("../loader/schema.js");
38
39
  const prompt_builder_js_1 = require("../prompt/prompt-builder.js");
39
40
  const structured_stream_instructions_js_1 = require("../prompt/prompts/structured-stream-instructions.js");
40
41
  const template_js_1 = require("../prompt/template.js");
41
42
  const fastq = __importStar(require("../utils/queue.js"));
43
+ const stream_utils_js_1 = require("../utils/stream-utils.js");
42
44
  const structured_stream_extractor_js_1 = require("../utils/structured-stream-extractor.js");
43
45
  const type_utils_js_1 = require("../utils/type-utils.js");
44
46
  const agent_js_1 = require("./agent.js");
@@ -120,6 +122,32 @@ exports.aiAgentOptionsSchema = agent_js_1.agentOptionsSchema.extend({
120
122
  */
121
123
  class AIAgent extends agent_js_1.Agent {
122
124
  tag = "AIAgent";
125
+ static schema({ filepath }) {
126
+ const instructionsSchema = (0, schema_js_1.getInstructionsSchema)({ filepath });
127
+ return (0, schema_js_1.camelizeSchema)(zod_1.z.object({
128
+ instructions: (0, schema_js_1.optionalize)(instructionsSchema),
129
+ autoReorderSystemMessages: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
130
+ autoMergeSystemMessages: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
131
+ inputKey: (0, schema_js_1.optionalize)(zod_1.z.string()),
132
+ outputKey: (0, schema_js_1.optionalize)(zod_1.z.string()),
133
+ inputFileKey: (0, schema_js_1.optionalize)(zod_1.z.string()),
134
+ outputFileKey: (0, schema_js_1.optionalize)(zod_1.z.string()),
135
+ toolChoice: (0, schema_js_1.optionalize)(zod_1.z.nativeEnum(AIAgentToolChoice)),
136
+ toolCallsConcurrency: (0, schema_js_1.optionalize)(zod_1.z.number().int().min(0)),
137
+ keepTextInToolUses: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
138
+ catchToolsError: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
139
+ structuredStreamMode: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
140
+ }));
141
+ }
142
+ static async load(options) {
143
+ const schema = AIAgent.schema(options);
144
+ const valid = await schema.parseAsync(options.parsed);
145
+ return new AIAgent({
146
+ ...options.parsed,
147
+ ...valid,
148
+ instructions: valid.instructions && (0, schema_js_1.instructionsToPromptBuilder)(valid.instructions),
149
+ });
150
+ }
123
151
  /**
124
152
  * Create an AIAgent with the specified options
125
153
  *
@@ -316,6 +344,16 @@ class AIAgent extends agent_js_1.Agent {
316
344
  }
317
345
  const toolCallMessages = [];
318
346
  const outputKey = this.outputKey;
347
+ const inputMessage = this.inputKey ? input[this.inputKey] : undefined;
348
+ if (inputMessage) {
349
+ yield {
350
+ progress: {
351
+ event: "message",
352
+ role: "user",
353
+ message: [{ type: "text", content: inputMessage }],
354
+ },
355
+ };
356
+ }
319
357
  for (;;) {
320
358
  const modelOutput = {};
321
359
  let stream = await this.invokeChildAgent(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { ...options, streaming: true });
@@ -325,12 +363,12 @@ class AIAgent extends agent_js_1.Agent {
325
363
  }
326
364
  let isTextIgnored = false;
327
365
  for await (const value of stream) {
366
+ (0, stream_utils_js_1.mergeAgentResponseChunk)(modelOutput, value);
328
367
  if ((0, agent_js_1.isAgentResponseDelta)(value)) {
329
368
  if (!isTextIgnored && value.delta.text?.text) {
330
369
  yield { delta: { text: { [outputKey]: value.delta.text.text } } };
331
370
  }
332
371
  if (value.delta.json) {
333
- Object.assign(modelOutput, value.delta.json);
334
372
  if (this.structuredStreamMode) {
335
373
  yield { delta: { json: value.delta.json.json } };
336
374
  if (!isTextIgnored && modelOutput.json && this.ignoreTextOfStructuredStreamMode) {
@@ -340,13 +378,23 @@ class AIAgent extends agent_js_1.Agent {
340
378
  }
341
379
  }
342
380
  }
343
- const { toolCalls, json, text, files } = modelOutput;
381
+ const { toolCalls, json, text, thoughts, files } = modelOutput;
382
+ if (text) {
383
+ yield {
384
+ progress: { event: "message", role: "agent", message: [{ type: "text", content: text }] },
385
+ };
386
+ }
387
+ if (thoughts) {
388
+ yield {
389
+ progress: { event: "message", role: "agent", message: [{ type: "thinking", thoughts }] },
390
+ };
391
+ }
344
392
  if (toolCalls?.length) {
345
393
  if (this.keepTextInToolUses !== true) {
346
394
  yield { delta: { json: { [outputKey]: "" } } };
347
395
  }
348
396
  else {
349
- yield { delta: { text: { [outputKey]: "\n" } } };
397
+ yield { delta: { text: { [outputKey]: "\n\n" } } };
350
398
  }
351
399
  const executedToolCalls = [];
352
400
  let error;
@@ -376,6 +424,20 @@ class AIAgent extends agent_js_1.Agent {
376
424
  const tool = toolsMap.get(call.function.name);
377
425
  if (!tool)
378
426
  throw new Error(`Tool not found: ${call.function.name}`);
427
+ yield {
428
+ progress: {
429
+ event: "message",
430
+ role: "agent",
431
+ message: [
432
+ {
433
+ type: "tool_use",
434
+ name: call.function.name,
435
+ input: call.function.arguments,
436
+ toolUseId: call.id,
437
+ },
438
+ ],
439
+ },
440
+ };
379
441
  queue.push({ tool, call });
380
442
  }
381
443
  await queue.drained();
@@ -383,6 +445,21 @@ class AIAgent extends agent_js_1.Agent {
383
445
  throw error;
384
446
  // Continue LLM function calling loop if any tools were executed
385
447
  if (executedToolCalls.length) {
448
+ for (const { call, output } of executedToolCalls) {
449
+ yield {
450
+ progress: {
451
+ event: "message",
452
+ role: "agent",
453
+ message: [
454
+ {
455
+ type: "tool_result",
456
+ toolUseId: call.id,
457
+ content: output,
458
+ },
459
+ ],
460
+ },
461
+ };
462
+ }
386
463
  const transferOutput = executedToolCalls.find((i) => (0, types_js_1.isTransferAgentOutput)(i.output))?.output;
387
464
  if (transferOutput)
388
465
  return transferOutput;
@@ -403,6 +480,11 @@ class AIAgent extends agent_js_1.Agent {
403
480
  if (!(0, type_utils_js_1.isEmpty)(result)) {
404
481
  yield { delta: { json: result } };
405
482
  }
483
+ if (text) {
484
+ yield {
485
+ progress: { event: "message", role: "agent", message: [{ type: "text", content: text }] },
486
+ };
487
+ }
406
488
  return;
407
489
  }
408
490
  }
@@ -203,6 +203,13 @@ export interface ChatModelInputMessage {
203
203
  * Name of the message sender (for multi-agent scenarios)
204
204
  */
205
205
  name?: string;
206
+ /**
207
+ * Cache control marker for the entire message (only supported by Claude)
208
+ *
209
+ * This is syntactic sugar that applies cacheControl to the last content block
210
+ * of the message. See {@link CacheControl} for details.
211
+ */
212
+ cacheControl?: CacheControl;
206
213
  }
207
214
  /**
208
215
  * Type of input message content
@@ -218,27 +225,64 @@ export type ChatModelInputMessageContent = string | UnionContent[];
218
225
  export type TextContent = {
219
226
  type: "text";
220
227
  text: string;
228
+ /**
229
+ * Cache control marker (only supported by Claude)
230
+ *
231
+ * When set, this content block will be marked as a cache breakpoint.
232
+ * See {@link CacheControl} for details.
233
+ */
234
+ cacheControl?: CacheControl;
221
235
  };
222
236
  export declare const textContentSchema: z.ZodObject<{
223
237
  type: z.ZodLiteral<"text">;
224
238
  text: z.ZodString;
239
+ cacheControl: ZodType<{
240
+ type: "ephemeral";
241
+ ttl?: "5m" | "1h" | undefined;
242
+ } | undefined, z.ZodTypeDef, {
243
+ type: "ephemeral";
244
+ ttl?: "5m" | "1h" | undefined;
245
+ } | undefined>;
225
246
  }, "strip", z.ZodTypeAny, {
226
247
  type: "text";
227
248
  text: string;
249
+ cacheControl?: {
250
+ type: "ephemeral";
251
+ ttl?: "5m" | "1h" | undefined;
252
+ } | undefined;
228
253
  }, {
229
254
  type: "text";
230
255
  text: string;
256
+ cacheControl?: {
257
+ type: "ephemeral";
258
+ ttl?: "5m" | "1h" | undefined;
259
+ } | undefined;
231
260
  }>;
232
261
  export type UnionContent = TextContent | FileUnionContent;
233
262
  export declare const unionContentSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
234
263
  type: z.ZodLiteral<"text">;
235
264
  text: z.ZodString;
265
+ cacheControl: ZodType<{
266
+ type: "ephemeral";
267
+ ttl?: "5m" | "1h" | undefined;
268
+ } | undefined, z.ZodTypeDef, {
269
+ type: "ephemeral";
270
+ ttl?: "5m" | "1h" | undefined;
271
+ } | undefined>;
236
272
  }, "strip", z.ZodTypeAny, {
237
273
  type: "text";
238
274
  text: string;
275
+ cacheControl?: {
276
+ type: "ephemeral";
277
+ ttl?: "5m" | "1h" | undefined;
278
+ } | undefined;
239
279
  }, {
240
280
  type: "text";
241
281
  text: string;
282
+ cacheControl?: {
283
+ type: "ephemeral";
284
+ ttl?: "5m" | "1h" | undefined;
285
+ } | undefined;
242
286
  }>, z.ZodObject<{
243
287
  filename: ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
244
288
  mimeType: ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
@@ -340,6 +384,14 @@ export interface ChatModelInputTool {
340
384
  * For example, Gemini's thought_signature
341
385
  */
342
386
  metadata?: Record<string, any>;
387
+ /**
388
+ * Cache control marker (only supported by Claude)
389
+ *
390
+ * When set, this tool definition will be marked as a cache breakpoint.
391
+ * Typically applied to the last tool in the tools array.
392
+ * See {@link CacheControl} for details.
393
+ */
394
+ cacheControl?: CacheControl;
343
395
  }
344
396
  /**
345
397
  * Tool selection strategy
@@ -362,6 +414,82 @@ export type ChatModelInputToolChoice = "auto" | "none" | "required" | {
362
414
  };
363
415
  };
364
416
  export type Modality = "text" | "image" | "audio";
417
+ /**
418
+ * Cache control marker for prompt caching
419
+ *
420
+ * Used to mark content blocks, messages, or tools for caching.
421
+ * Currently only supported by Anthropic (Claude) models.
422
+ */
423
+ export interface CacheControl {
424
+ /**
425
+ * Cache type (currently only "ephemeral" is supported)
426
+ */
427
+ type: "ephemeral";
428
+ /**
429
+ * Cache TTL (Time To Live)
430
+ * - "5m": 5 minutes (default)
431
+ * - "1h": 1 hour
432
+ */
433
+ ttl?: "5m" | "1h";
434
+ }
435
+ /**
436
+ * Cache configuration options
437
+ *
438
+ * Controls how prompt caching is used for supported providers.
439
+ * Prompt caching can significantly reduce costs and latency by reusing
440
+ * previously processed prompts (system messages, tool definitions, etc.).
441
+ */
442
+ export interface CacheConfig {
443
+ /**
444
+ * Whether to enable prompt caching
445
+ *
446
+ * - OpenAI: Ignored (always enabled automatically)
447
+ * - Gemini: Controls explicit caching
448
+ * - Claude: Controls whether to add cache_control markers
449
+ *
450
+ * @default true
451
+ */
452
+ enabled?: boolean;
453
+ /**
454
+ * Cache TTL (Time To Live)
455
+ *
456
+ * - OpenAI: Ignored (automatic)
457
+ * - Gemini: Supports custom seconds
458
+ * - Claude: Only supports "5m" or "1h"
459
+ *
460
+ * @default "5m"
461
+ */
462
+ ttl?: "5m" | "1h" | number;
463
+ /**
464
+ * Caching strategy
465
+ *
466
+ * - "auto": Automatically add cache breakpoints at optimal locations
467
+ * - "manual": Require explicit cacheControl markers on messages/tools
468
+ *
469
+ * @default "auto"
470
+ */
471
+ strategy?: "auto" | "manual";
472
+ /**
473
+ * Auto cache breakpoint locations (only effective when strategy="auto")
474
+ *
475
+ * @default { tools: true, system: true, lastMessage: false }
476
+ */
477
+ autoBreakpoints?: {
478
+ /** Cache tool definitions */
479
+ tools?: boolean;
480
+ /** Cache system messages */
481
+ system?: boolean;
482
+ /** Cache last message in conversation history */
483
+ lastMessage?: boolean;
484
+ };
485
+ }
486
+ /**
487
+ * Default cache configuration
488
+ *
489
+ * Enables automatic caching for system messages and tool definitions,
490
+ * which typically provides the best cost/performance tradeoff.
491
+ */
492
+ export declare const DEFAULT_CACHE_CONFIG: CacheConfig;
365
493
  /**
366
494
  * Model-specific configuration options
367
495
  *
@@ -395,6 +523,15 @@ export interface ChatModelInputOptions extends Record<string, unknown> {
395
523
  modalities?: Modality[];
396
524
  preferInputFileType?: "file" | "url";
397
525
  reasoningEffort?: number | "minimal" | "low" | "medium" | "high";
526
+ /**
527
+ * Cache configuration for prompt caching
528
+ *
529
+ * Enables caching of system messages, tool definitions, and conversation history
530
+ * to reduce costs and latency. See {@link CacheConfig} for details.
531
+ *
532
+ * @default DEFAULT_CACHE_CONFIG (enabled with auto strategy)
533
+ */
534
+ cacheConfig?: CacheConfig;
398
535
  }
399
536
  export type ChatModelInputOptionsWithGetter = GetterSchema<ChatModelInputOptions>;
400
537
  /**
@@ -492,6 +629,16 @@ export interface ChatModelOutputUsage {
492
629
  * AIGNE Hub credit usage
493
630
  */
494
631
  aigneHubCredits?: number;
632
+ /**
633
+ * Number of tokens written to cache (first time caching)
634
+ * Only applicable for providers that support explicit cache creation (e.g., Anthropic)
635
+ */
636
+ cacheCreationInputTokens?: number;
637
+ /**
638
+ * Number of tokens read from cache (cache hit)
639
+ * Supported by OpenAI, Anthropic, and Gemini
640
+ */
641
+ cacheReadInputTokens?: number;
495
642
  /**
496
643
  * Credit prefix
497
644
  */
@@ -501,15 +648,21 @@ export declare const chatModelOutputUsageSchema: z.ZodObject<{
501
648
  inputTokens: z.ZodNumber;
502
649
  outputTokens: z.ZodNumber;
503
650
  aigneHubCredits: ZodType<number | undefined, z.ZodTypeDef, number | undefined>;
651
+ cacheCreationInputTokens: ZodType<number | undefined, z.ZodTypeDef, number | undefined>;
652
+ cacheReadInputTokens: ZodType<number | undefined, z.ZodTypeDef, number | undefined>;
504
653
  creditPrefix: ZodType<"$" | "€" | "¥" | undefined, z.ZodTypeDef, "$" | "€" | "¥" | undefined>;
505
654
  }, "strip", z.ZodTypeAny, {
506
655
  inputTokens: number;
507
656
  outputTokens: number;
508
657
  aigneHubCredits?: number | undefined;
658
+ cacheCreationInputTokens?: number | undefined;
659
+ cacheReadInputTokens?: number | undefined;
509
660
  creditPrefix?: "$" | "€" | "¥" | undefined;
510
661
  }, {
511
662
  inputTokens: number;
512
663
  outputTokens: number;
513
664
  aigneHubCredits?: number | undefined;
665
+ cacheCreationInputTokens?: number | undefined;
666
+ cacheReadInputTokens?: number | undefined;
514
667
  creditPrefix?: "$" | "€" | "¥" | undefined;
515
668
  }>;
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.chatModelOutputUsageSchema = exports.unionContentSchema = exports.textContentSchema = exports.roleSchema = exports.ChatModel = exports.StructuredOutputError = void 0;
36
+ exports.chatModelOutputUsageSchema = exports.DEFAULT_CACHE_CONFIG = exports.unionContentSchema = exports.textContentSchema = exports.roleSchema = exports.ChatModel = exports.StructuredOutputError = void 0;
37
37
  const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
38
38
  const zod_1 = require("zod");
39
39
  const zod_from_json_schema_1 = require("zod-from-json-schema");
@@ -225,6 +225,10 @@ class ChatModel extends model_js_1.Model {
225
225
  options.context.usage.inputTokens += usage.inputTokens;
226
226
  if (usage.aigneHubCredits)
227
227
  options.context.usage.aigneHubCredits += usage.aigneHubCredits;
228
+ if (usage.cacheCreationInputTokens)
229
+ options.context.usage.cacheCreationInputTokens += usage.cacheCreationInputTokens;
230
+ if (usage.cacheReadInputTokens)
231
+ options.context.usage.cacheReadInputTokens += usage.cacheReadInputTokens;
228
232
  if (usage.creditPrefix)
229
233
  options.context.usage.creditPrefix = usage.creditPrefix;
230
234
  }
@@ -282,6 +286,10 @@ exports.roleSchema = zod_1.z.union([
282
286
  exports.textContentSchema = zod_1.z.object({
283
287
  type: zod_1.z.literal("text"),
284
288
  text: zod_1.z.string(),
289
+ cacheControl: (0, schema_js_1.optionalize)(zod_1.z.object({
290
+ type: zod_1.z.literal("ephemeral"),
291
+ ttl: (0, schema_js_1.optionalize)(zod_1.z.union([zod_1.z.literal("5m"), zod_1.z.literal("1h")])),
292
+ })),
285
293
  });
286
294
  exports.unionContentSchema = zod_1.z.discriminatedUnion("type", [
287
295
  exports.textContentSchema,
@@ -303,6 +311,10 @@ const chatModelInputMessageSchema = zod_1.z.object({
303
311
  }))),
304
312
  toolCallId: (0, schema_js_1.optionalize)(zod_1.z.string()),
305
313
  name: (0, schema_js_1.optionalize)(zod_1.z.string()),
314
+ cacheControl: (0, schema_js_1.optionalize)(zod_1.z.object({
315
+ type: zod_1.z.literal("ephemeral"),
316
+ ttl: (0, schema_js_1.optionalize)(zod_1.z.union([zod_1.z.literal("5m"), zod_1.z.literal("1h")])),
317
+ })),
306
318
  });
307
319
  const chatModelInputResponseFormatSchema = zod_1.z.discriminatedUnion("type", [
308
320
  zod_1.z.object({ type: zod_1.z.literal("text") }),
@@ -324,6 +336,10 @@ const chatModelInputToolSchema = zod_1.z.object({
324
336
  parameters: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()),
325
337
  }),
326
338
  metadata: (0, schema_js_1.optionalize)(zod_1.z.record(zod_1.z.string(), zod_1.z.unknown())),
339
+ cacheControl: (0, schema_js_1.optionalize)(zod_1.z.object({
340
+ type: zod_1.z.literal("ephemeral"),
341
+ ttl: (0, schema_js_1.optionalize)(zod_1.z.union([zod_1.z.literal("5m"), zod_1.z.literal("1h")])),
342
+ })),
327
343
  });
328
344
  const chatModelInputToolChoiceSchema = zod_1.z.union([
329
345
  zod_1.z.literal("auto"),
@@ -331,6 +347,22 @@ const chatModelInputToolChoiceSchema = zod_1.z.union([
331
347
  zod_1.z.literal("required"),
332
348
  chatModelInputToolSchema,
333
349
  ]);
350
+ /**
351
+ * Default cache configuration
352
+ *
353
+ * Enables automatic caching for system messages and tool definitions,
354
+ * which typically provides the best cost/performance tradeoff.
355
+ */
356
+ exports.DEFAULT_CACHE_CONFIG = {
357
+ enabled: true,
358
+ ttl: "5m",
359
+ strategy: "auto",
360
+ autoBreakpoints: {
361
+ tools: true,
362
+ system: true,
363
+ lastMessage: false,
364
+ },
365
+ };
334
366
  const modelOptionsSchemaProperties = {
335
367
  model: zod_1.z.string(),
336
368
  temperature: zod_1.z.number(),
@@ -379,6 +411,8 @@ exports.chatModelOutputUsageSchema = zod_1.z.object({
379
411
  inputTokens: zod_1.z.number(),
380
412
  outputTokens: zod_1.z.number(),
381
413
  aigneHubCredits: (0, schema_js_1.optionalize)(zod_1.z.number()),
414
+ cacheCreationInputTokens: (0, schema_js_1.optionalize)(zod_1.z.number()),
415
+ cacheReadInputTokens: (0, schema_js_1.optionalize)(zod_1.z.number()),
382
416
  creditPrefix: (0, schema_js_1.optionalize)(zod_1.z.union([zod_1.z.literal("$"), zod_1.z.literal("€"), zod_1.z.literal("¥")])),
383
417
  });
384
418
  const chatModelOutputSchema = zod_1.z.object({
@@ -1,4 +1,4 @@
1
- import { type ZodObject, type ZodType } from "zod";
1
+ import z, { type ZodObject, type ZodType } from "zod";
2
2
  import { PromptBuilder } from "../prompt/prompt-builder.js";
3
3
  import { Agent, type AgentInvokeOptions, type AgentOptions, type Message } from "./agent.js";
4
4
  import { type ImageModelOutput } from "./image-model.js";
@@ -13,6 +13,22 @@ export declare const imageAgentOptionsSchema: ZodObject<{
13
13
  }>;
14
14
  export declare class ImageAgent<I extends Message = any, O extends ImageModelOutput = any> extends Agent<I, O> {
15
15
  tag: string;
16
+ static schema({ filepath }: {
17
+ filepath: string;
18
+ }): z.ZodObject<{
19
+ instructions: z.ZodType<import("../loader/schema.js").Instructions, z.ZodTypeDef, import("../loader/schema.js").Instructions>;
20
+ inputFileKey: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
21
+ }, "strip", z.ZodTypeAny, {
22
+ instructions: import("../loader/schema.js").Instructions;
23
+ inputFileKey?: string | undefined;
24
+ }, {
25
+ instructions: import("../loader/schema.js").Instructions;
26
+ inputFileKey?: string | undefined;
27
+ }>;
28
+ static load<I extends Message = any, O extends Message = any>(options: {
29
+ filepath: string;
30
+ parsed: object;
31
+ }): Promise<Agent<I, O>>;
16
32
  static from<I extends Message = any, O extends ImageModelOutput = any>(options: ImageAgentOptions<I, O>): ImageAgent<I, O>;
17
33
  constructor(options: ImageAgentOptions<I, O>);
18
34
  instructions: PromptBuilder;
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ImageAgent = exports.imageAgentOptionsSchema = void 0;
7
7
  const zod_1 = __importDefault(require("zod"));
8
+ const schema_js_1 = require("../loader/schema.js");
8
9
  const prompt_builder_js_1 = require("../prompt/prompt-builder.js");
9
10
  const type_utils_js_1 = require("../utils/type-utils.js");
10
11
  const agent_js_1 = require("./agent.js");
@@ -16,6 +17,21 @@ exports.imageAgentOptionsSchema = agent_js_1.agentOptionsSchema.extend({
16
17
  });
17
18
  class ImageAgent extends agent_js_1.Agent {
18
19
  tag = "ImageAgent";
20
+ static schema({ filepath }) {
21
+ const instructionsSchema = (0, schema_js_1.getInstructionsSchema)({ filepath });
22
+ return (0, schema_js_1.camelizeSchema)(zod_1.default.object({
23
+ instructions: instructionsSchema,
24
+ inputFileKey: (0, schema_js_1.optionalize)(zod_1.default.string()),
25
+ }));
26
+ }
27
+ static async load(options) {
28
+ const valid = await ImageAgent.schema({ filepath: options.filepath }).parseAsync(options.parsed);
29
+ return new ImageAgent({
30
+ ...options.parsed,
31
+ ...valid,
32
+ instructions: (0, schema_js_1.instructionsToPromptBuilder)(valid.instructions),
33
+ });
34
+ }
19
35
  static from(options) {
20
36
  return new ImageAgent(options);
21
37
  }