@iqai/adk 0.5.0 → 0.5.2

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/dist/index.mjs CHANGED
@@ -3389,6 +3389,11 @@ var EventActions = class {
3389
3389
  * Requested authentication configurations.
3390
3390
  */
3391
3391
  requestedAuthConfigs;
3392
+ /**
3393
+ * Event compaction information. When set, this event represents
3394
+ * a compaction of events within the specified timestamp range.
3395
+ */
3396
+ compaction;
3392
3397
  /**
3393
3398
  * Constructor for EventActions
3394
3399
  */
@@ -3399,6 +3404,7 @@ var EventActions = class {
3399
3404
  this.transferToAgent = options.transferToAgent;
3400
3405
  this.escalate = options.escalate;
3401
3406
  this.requestedAuthConfigs = options.requestedAuthConfigs;
3407
+ this.compaction = options.compaction;
3402
3408
  }
3403
3409
  };
3404
3410
 
@@ -3941,9 +3947,196 @@ init_logger();
3941
3947
  var events_exports = {};
3942
3948
  __export(events_exports, {
3943
3949
  Event: () => Event,
3944
- EventActions: () => EventActions
3950
+ EventActions: () => EventActions,
3951
+ LlmEventSummarizer: () => LlmEventSummarizer,
3952
+ runCompactionForSlidingWindow: () => runCompactionForSlidingWindow
3945
3953
  });
3946
3954
 
3955
+ // src/events/llm-event-summarizer.ts
3956
+ var DEFAULT_SUMMARIZATION_PROMPT = `You are a helpful assistant tasked with summarizing a conversation history.
3957
+ Please provide a concise summary of the following events, capturing the key information and context.
3958
+ Focus on the main topics discussed, important decisions made, and any action items or results.
3959
+
3960
+ Events to summarize:
3961
+ {events}
3962
+
3963
+ Provide your summary in a clear, concise format.`;
3964
+ var LlmEventSummarizer = class {
3965
+ model;
3966
+ prompt;
3967
+ /**
3968
+ * Creates a new LLM event summarizer.
3969
+ * @param model - The LLM model to use for summarization
3970
+ * @param prompt - Optional custom prompt template. Use {events} as placeholder for event content.
3971
+ */
3972
+ constructor(model, prompt) {
3973
+ this.model = model;
3974
+ this.prompt = prompt || DEFAULT_SUMMARIZATION_PROMPT;
3975
+ }
3976
+ /**
3977
+ * Summarizes events using the configured LLM.
3978
+ */
3979
+ async maybeSummarizeEvents(events) {
3980
+ if (!events || events.length === 0) {
3981
+ return void 0;
3982
+ }
3983
+ const eventsText = this.formatEventsForSummarization(events);
3984
+ const promptWithEvents = this.prompt.replace("{events}", eventsText);
3985
+ const llmRequest = new LlmRequest({
3986
+ contents: [
3987
+ {
3988
+ role: "user",
3989
+ parts: [{ text: promptWithEvents }]
3990
+ }
3991
+ ]
3992
+ });
3993
+ let summaryText = "";
3994
+ for await (const response of this.model.generateContentAsync(llmRequest)) {
3995
+ summaryText += response.content?.parts?.map((part) => part.text || "").join("");
3996
+ }
3997
+ summaryText = summaryText.trim();
3998
+ if (!summaryText) {
3999
+ return void 0;
4000
+ }
4001
+ const summaryContent = {
4002
+ role: "model",
4003
+ parts: [{ text: summaryText }]
4004
+ };
4005
+ const compactionEvent = new Event({
4006
+ invocationId: Event.newId(),
4007
+ author: "user",
4008
+ actions: new EventActions({
4009
+ compaction: {
4010
+ startTimestamp: events[0].timestamp,
4011
+ endTimestamp: events[events.length - 1].timestamp,
4012
+ compactedContent: summaryContent
4013
+ }
4014
+ })
4015
+ });
4016
+ return compactionEvent;
4017
+ }
4018
+ /**
4019
+ * Formats events into a readable text format for summarization.
4020
+ */
4021
+ formatEventsForSummarization(events) {
4022
+ const lines = [];
4023
+ for (const event of events) {
4024
+ const timestamp = new Date(event.timestamp * 1e3).toISOString();
4025
+ const author = event.author;
4026
+ if (event.content?.parts) {
4027
+ for (const part of event.content.parts) {
4028
+ if (part.text) {
4029
+ lines.push(`[${timestamp}] ${author}: ${part.text}`);
4030
+ } else if (part.functionCall) {
4031
+ lines.push(
4032
+ `[${timestamp}] ${author}: Called tool '${part.functionCall.name}' with args ${JSON.stringify(part.functionCall.args)}`
4033
+ );
4034
+ } else if (part.functionResponse) {
4035
+ lines.push(
4036
+ `[${timestamp}] ${author}: Tool '${part.functionResponse.name}' returned: ${JSON.stringify(part.functionResponse.response)}`
4037
+ );
4038
+ }
4039
+ }
4040
+ }
4041
+ }
4042
+ return lines.join("\n");
4043
+ }
4044
+ };
4045
+
4046
+ // src/events/compaction.ts
4047
+ init_logger();
4048
+ var logger = new Logger({ name: "EventCompaction" });
4049
+ async function runCompactionForSlidingWindow(config, session, sessionService, summarizer) {
4050
+ if (!session.events || session.events.length === 0) {
4051
+ return;
4052
+ }
4053
+ const lastCompactedEndTimestamp = findLastCompactedEndTimestamp(
4054
+ session.events
4055
+ );
4056
+ const latestTimestampByInvocation = buildLatestTimestampByInvocation(
4057
+ session.events
4058
+ );
4059
+ const uniqueInvocationIds = Array.from(latestTimestampByInvocation.keys());
4060
+ const newInvocationIds = uniqueInvocationIds.filter(
4061
+ (invId) => (latestTimestampByInvocation.get(invId) || 0) > lastCompactedEndTimestamp
4062
+ );
4063
+ if (newInvocationIds.length < config.compactionInterval) {
4064
+ logger.debug(
4065
+ `Not enough new invocations for compaction. Need ${config.compactionInterval}, have ${newInvocationIds.length}`
4066
+ );
4067
+ return;
4068
+ }
4069
+ const endInvId = newInvocationIds[newInvocationIds.length - 1];
4070
+ const firstNewInvId = newInvocationIds[0];
4071
+ const firstNewInvIdx = uniqueInvocationIds.indexOf(firstNewInvId);
4072
+ const startIdx = Math.max(0, firstNewInvIdx - config.overlapSize);
4073
+ const startInvId = uniqueInvocationIds[startIdx];
4074
+ logger.debug(
4075
+ `Compacting invocations from ${startInvId} to ${endInvId} (${newInvocationIds.length} new invocations, overlap: ${config.overlapSize})`
4076
+ );
4077
+ const eventsToCompact = sliceEventsByInvocationRange(
4078
+ session.events,
4079
+ startInvId,
4080
+ endInvId
4081
+ );
4082
+ if (eventsToCompact.length === 0) {
4083
+ logger.debug("No events to compact after filtering");
4084
+ return;
4085
+ }
4086
+ logger.debug(`Summarizing ${eventsToCompact.length} events`);
4087
+ const compactionEvent = await summarizer.maybeSummarizeEvents(eventsToCompact);
4088
+ if (compactionEvent) {
4089
+ logger.debug(
4090
+ `Compaction created covering timestamps ${compactionEvent.actions.compaction?.startTimestamp} to ${compactionEvent.actions.compaction?.endTimestamp}`
4091
+ );
4092
+ await sessionService.appendEvent(session, compactionEvent);
4093
+ }
4094
+ }
4095
+ function findLastCompactedEndTimestamp(events) {
4096
+ for (let i = events.length - 1; i >= 0; i--) {
4097
+ const event = events[i];
4098
+ if (event.actions?.compaction) {
4099
+ return event.actions.compaction.endTimestamp;
4100
+ }
4101
+ }
4102
+ return 0;
4103
+ }
4104
+ function buildLatestTimestampByInvocation(events) {
4105
+ const latestByInvocation = /* @__PURE__ */ new Map();
4106
+ for (const event of events) {
4107
+ if (event.actions?.compaction) {
4108
+ continue;
4109
+ }
4110
+ const invId = event.invocationId;
4111
+ if (!invId) {
4112
+ continue;
4113
+ }
4114
+ const current = latestByInvocation.get(invId) || 0;
4115
+ if (event.timestamp > current) {
4116
+ latestByInvocation.set(invId, event.timestamp);
4117
+ }
4118
+ }
4119
+ return latestByInvocation;
4120
+ }
4121
+ function sliceEventsByInvocationRange(events, startInvId, endInvId) {
4122
+ let firstIndex = -1;
4123
+ let lastIndex = -1;
4124
+ for (let i = 0; i < events.length; i++) {
4125
+ const event = events[i];
4126
+ if (event.invocationId === startInvId && firstIndex === -1) {
4127
+ firstIndex = i;
4128
+ }
4129
+ if (event.invocationId === endInvId) {
4130
+ lastIndex = i;
4131
+ }
4132
+ }
4133
+ if (firstIndex === -1 || lastIndex === -1 || firstIndex > lastIndex) {
4134
+ return [];
4135
+ }
4136
+ const slicedEvents = events.slice(firstIndex, lastIndex + 1);
4137
+ return slicedEvents.filter((event) => !event.actions?.compaction);
4138
+ }
4139
+
3947
4140
  // src/flows/llm-flows/base-llm-flow.ts
3948
4141
  init_logger();
3949
4142
 
@@ -7393,8 +7586,8 @@ var BasicLlmRequestProcessor = class extends BaseLlmRequestProcessor {
7393
7586
  } else {
7394
7587
  (() => {
7395
7588
  try {
7396
- const logger = new Logger({ name: "BasicLlmRequestProcessor" });
7397
- logger.debug(
7589
+ const logger2 = new Logger({ name: "BasicLlmRequestProcessor" });
7590
+ logger2.debug(
7398
7591
  `Skipping request-level output schema for agent ${agent.name} because tools/transfers are present. Schema will be validated during response processing.`
7399
7592
  );
7400
7593
  } catch (e) {
@@ -8296,7 +8489,8 @@ function getContents(currentBranch, events, agentName = "") {
8296
8489
  isOtherAgentReply(agentName, event) ? convertForeignEvent(event) : event
8297
8490
  );
8298
8491
  }
8299
- let resultEvents = rearrangeEventsForLatestFunctionResponse(filteredEvents);
8492
+ const processedEvents = processCompactionEvents(filteredEvents);
8493
+ let resultEvents = rearrangeEventsForLatestFunctionResponse(processedEvents);
8300
8494
  resultEvents = rearrangeEventsForAsyncFunctionResponsesInHistory(resultEvents);
8301
8495
  const contents = [];
8302
8496
  for (const event of resultEvents) {
@@ -8408,6 +8602,31 @@ function isAuthEvent(event) {
8408
8602
  }
8409
8603
  return false;
8410
8604
  }
8605
+ function processCompactionEvents(events) {
8606
+ const result = [];
8607
+ let lastCompactionStartTime = Number.POSITIVE_INFINITY;
8608
+ for (let i = events.length - 1; i >= 0; i--) {
8609
+ const event = events[i];
8610
+ if (event.actions?.compaction) {
8611
+ const compaction = event.actions.compaction;
8612
+ const synthesizedEvent = new Event({
8613
+ timestamp: compaction.endTimestamp,
8614
+ author: "model",
8615
+ content: compaction.compactedContent,
8616
+ branch: event.branch,
8617
+ invocationId: event.invocationId
8618
+ });
8619
+ result.unshift(synthesizedEvent);
8620
+ lastCompactionStartTime = Math.min(
8621
+ lastCompactionStartTime,
8622
+ compaction.startTimestamp
8623
+ );
8624
+ } else if (event.timestamp < lastCompactionStartTime) {
8625
+ result.unshift(event);
8626
+ }
8627
+ }
8628
+ return result;
8629
+ }
8411
8630
 
8412
8631
  // src/flows/llm-flows/identity.ts
8413
8632
  var IdentityLlmRequestProcessor = class extends BaseLlmRequestProcessor {
@@ -8777,14 +8996,7 @@ var NlPlanningRequestProcessor = class extends BaseLlmRequestProcessor {
8777
8996
  llmRequest
8778
8997
  );
8779
8998
  if (planningInstruction) {
8780
- if (llmRequest.appendInstructions) {
8781
- llmRequest.appendInstructions([planningInstruction]);
8782
- } else {
8783
- const existingInstructions = llmRequest.instructions || "";
8784
- llmRequest.instructions = `${existingInstructions}
8785
-
8786
- ${planningInstruction}`;
8787
- }
8999
+ llmRequest.appendInstructions([planningInstruction]);
8788
9000
  }
8789
9001
  removeThoughtFromRequest(llmRequest);
8790
9002
  for await (const _ of []) {
@@ -9876,7 +10088,7 @@ init_logger();
9876
10088
  import { generateId } from "ai";
9877
10089
 
9878
10090
  // src/runners.ts
9879
- import { SpanStatusCode, context as context3, trace as trace3 } from "@opentelemetry/api";
10091
+ import { context as context3, SpanStatusCode, trace as trace3 } from "@opentelemetry/api";
9880
10092
 
9881
10093
  // src/agents/run-config.ts
9882
10094
  var StreamingMode = /* @__PURE__ */ ((StreamingMode2) => {
@@ -10464,6 +10676,10 @@ var Runner = class {
10464
10676
  * The memory service for the runner.
10465
10677
  */
10466
10678
  memoryService;
10679
+ /**
10680
+ * Configuration for event compaction.
10681
+ */
10682
+ eventsCompactionConfig;
10467
10683
  logger = new Logger({ name: "Runner" });
10468
10684
  /**
10469
10685
  * Initializes the Runner.
@@ -10473,13 +10689,15 @@ var Runner = class {
10473
10689
  agent,
10474
10690
  artifactService,
10475
10691
  sessionService,
10476
- memoryService
10692
+ memoryService,
10693
+ eventsCompactionConfig
10477
10694
  }) {
10478
10695
  this.appName = appName;
10479
10696
  this.agent = agent;
10480
10697
  this.artifactService = artifactService;
10481
10698
  this.sessionService = sessionService;
10482
10699
  this.memoryService = memoryService;
10700
+ this.eventsCompactionConfig = eventsCompactionConfig;
10483
10701
  }
10484
10702
  /**
10485
10703
  * Runs the agent synchronously.
@@ -10581,6 +10799,10 @@ var Runner = class {
10581
10799
  }
10582
10800
  yield event;
10583
10801
  }
10802
+ await context3.with(
10803
+ spanContext,
10804
+ () => this._runCompaction(session, invocationContext)
10805
+ );
10584
10806
  } catch (error) {
10585
10807
  this.logger.debug("Error running agent:", error);
10586
10808
  span.recordException(error);
@@ -10693,6 +10915,52 @@ var Runner = class {
10693
10915
  runConfig
10694
10916
  });
10695
10917
  }
10918
+ /**
10919
+ * Runs compaction if configured.
10920
+ */
10921
+ async _runCompaction(session, _invocationContext) {
10922
+ if (!this.eventsCompactionConfig) {
10923
+ return;
10924
+ }
10925
+ const summarizer = this._getOrCreateSummarizer();
10926
+ if (!summarizer) {
10927
+ this.logger.warn(
10928
+ "Event compaction configured but no summarizer available"
10929
+ );
10930
+ return;
10931
+ }
10932
+ try {
10933
+ await runCompactionForSlidingWindow(
10934
+ this.eventsCompactionConfig,
10935
+ session,
10936
+ this.sessionService,
10937
+ summarizer
10938
+ );
10939
+ } catch (error) {
10940
+ this.logger.error("Error running compaction:", error);
10941
+ }
10942
+ }
10943
+ /**
10944
+ * Gets the configured summarizer or creates a default LLM-based one.
10945
+ */
10946
+ _getOrCreateSummarizer() {
10947
+ if (this.eventsCompactionConfig?.summarizer) {
10948
+ return this.eventsCompactionConfig.summarizer;
10949
+ }
10950
+ if (this.agent instanceof LlmAgent) {
10951
+ try {
10952
+ const model = this.agent.canonicalModel;
10953
+ return new LlmEventSummarizer(model);
10954
+ } catch (error) {
10955
+ this.logger.warn(
10956
+ "Could not get canonical model for default summarizer:",
10957
+ error
10958
+ );
10959
+ return void 0;
10960
+ }
10961
+ }
10962
+ return void 0;
10963
+ }
10696
10964
  };
10697
10965
  var InMemoryRunner = class extends Runner {
10698
10966
  /**
@@ -10722,6 +10990,7 @@ var AgentBuilder = class _AgentBuilder {
10722
10990
  sessionOptions;
10723
10991
  memoryService;
10724
10992
  artifactService;
10993
+ eventsCompactionConfig;
10725
10994
  agentType = "llm";
10726
10995
  existingSession;
10727
10996
  existingAgent;
@@ -10935,6 +11204,14 @@ var AgentBuilder = class _AgentBuilder {
10935
11204
  this.config.afterToolCallback = callback;
10936
11205
  return this;
10937
11206
  }
11207
+ /**
11208
+ * Convenience method to start building with an existing agent
11209
+ * @param agent The agent instance to wrap
11210
+ * @returns New AgentBuilder instance with agent set
11211
+ */
11212
+ static withAgent(agent) {
11213
+ return new _AgentBuilder(agent.name || "default_agent").withAgent(agent);
11214
+ }
10938
11215
  /**
10939
11216
  * Provide an already constructed agent instance. Further definition-mutating calls
10940
11217
  * (model/tools/instruction/etc.) will be ignored with a dev warning.
@@ -11116,6 +11393,26 @@ var AgentBuilder = class _AgentBuilder {
11116
11393
  this.runConfig = config instanceof RunConfig ? config : new RunConfig({ ...this.runConfig || {}, ...config });
11117
11394
  return this;
11118
11395
  }
11396
+ /**
11397
+ * Configure event compaction for automatic history management
11398
+ * @param config Event compaction configuration
11399
+ * @returns This builder instance for chaining
11400
+ * @example
11401
+ * ```typescript
11402
+ * const { runner } = await AgentBuilder
11403
+ * .create("assistant")
11404
+ * .withModel("gemini-2.5-flash")
11405
+ * .withEventsCompaction({
11406
+ * compactionInterval: 10, // Compact every 10 invocations
11407
+ * overlapSize: 2, // Include 2 prior invocations
11408
+ * })
11409
+ * .build();
11410
+ * ```
11411
+ */
11412
+ withEventsCompaction(config) {
11413
+ this.eventsCompactionConfig = config;
11414
+ return this;
11415
+ }
11119
11416
  /**
11120
11417
  * Configure with an in-memory session with custom IDs
11121
11418
  * Note: In-memory sessions are created automatically by default, use this only if you need custom appName/userId
@@ -11152,7 +11449,8 @@ var AgentBuilder = class _AgentBuilder {
11152
11449
  agent,
11153
11450
  sessionService: this.sessionService,
11154
11451
  memoryService: this.memoryService,
11155
- artifactService: this.artifactService
11452
+ artifactService: this.artifactService,
11453
+ eventsCompactionConfig: this.eventsCompactionConfig
11156
11454
  };
11157
11455
  const baseRunner = new Runner(runnerConfig);
11158
11456
  runner = this.createEnhancedRunner(baseRunner, session);
@@ -13883,6 +14181,7 @@ export {
13883
14181
  LangGraphAgent,
13884
14182
  LlmAgent,
13885
14183
  LlmCallsLimitExceededError,
14184
+ LlmEventSummarizer,
13886
14185
  LlmRequest,
13887
14186
  LlmResponse,
13888
14187
  LoadArtifactsTool,
@@ -13979,6 +14278,7 @@ export {
13979
14278
  registerProviders,
13980
14279
  removeClientFunctionCallId,
13981
14280
  requestProcessor,
14281
+ runCompactionForSlidingWindow,
13982
14282
  shutdownTelemetry,
13983
14283
  telemetryService,
13984
14284
  traceLlmCall,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iqai/adk",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Agent Development Kit for TypeScript with multi-provider LLM support",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",