wave-agent-sdk 1.1.2 → 1.1.3

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.
@@ -3,7 +3,7 @@ import { convertMessagesForAPI } from "../utils/convertMessagesForAPI.js";
3
3
  import { supportsVision } from "../utils/modelCapabilities.js";
4
4
  import { persistToolImages } from "../utils/toolImagePersistence.js";
5
5
  import { parseTaskNotificationXml, taskNotificationToXml, } from "../utils/notificationXml.js";
6
- import { calculateComprehensiveTotalTokens, estimateContextTokens, } from "../utils/tokenCalculation.js";
6
+ import { estimateContextTokens } from "../utils/tokenCalculation.js";
7
7
  import { estimateTokens } from "../utils/tokenEstimate.js";
8
8
  import { getTaskReminderTurnCounts, maybeInjectTaskReminder, TASK_REMINDER_CONFIG, } from "../utils/taskReminder.js";
9
9
  import { createWriteStream, existsSync } from "node:fs";
@@ -370,16 +370,16 @@ export class AIManager {
370
370
  return "";
371
371
  }
372
372
  // Private method to update the displayed token statistics from a response.
373
- // The comprehensive value (including cache tokens) is intentionally kept:
374
- // it drives cost/usage display. Auto-compaction is NOT decided here it
375
- // happens pre-request via maybeAutoCompactBeforeRequest so that over-limit
376
- // requests never go out (aligned with Claude Code's proactive autocompact).
373
+ // Uses only total_tokens OpenAI-compatible usage already includes cache
374
+ // hits there, so adding cache fields would double-count and show an
375
+ // inflated context percentage. Same semantics as the auto-compaction
376
+ // threshold (maybeAutoCompactBeforeRequest), keeping display and
377
+ // compaction judgment consistent.
377
378
  updateLatestTotalTokens(usage) {
378
379
  if (!usage)
379
380
  return;
380
- // Update token statistics - display comprehensive token usage including cache tokens
381
- const comprehensiveTotalTokens = calculateComprehensiveTotalTokens(usage);
382
- this.messageManager.setlatestTotalTokens(comprehensiveTotalTokens);
381
+ // Update token statistics - display total_tokens (cache fields excluded)
382
+ this.messageManager.setlatestTotalTokens(usage.total_tokens);
383
383
  }
384
384
  /**
385
385
  * Pre-request auto-compaction check (aligned with Claude Code's
@@ -10,7 +10,7 @@ import { Container } from "../utils/container.js";
10
10
  import type { WaveConfiguration } from "../types/configuration.js";
11
11
  export interface LiveConfigManagerOptions {
12
12
  workdir: string;
13
- onReload?: (config: WaveConfiguration) => void;
13
+ onReload?: (config: WaveConfiguration) => void | Promise<void>;
14
14
  }
15
15
  export declare class LiveConfigManager {
16
16
  private container;
@@ -177,8 +177,11 @@ export class LiveConfigManager {
177
177
  this.permissionManager.updateDeniedRules(this.currentConfiguration.permissions?.deny || []);
178
178
  this.permissionManager.updateAdditionalDirectories(this.currentConfiguration.permissions?.additionalDirectories || []);
179
179
  }
180
- // Trigger reload callback
181
- this.options.onReload?.(this.currentConfiguration);
180
+ // Trigger reload callback. Awaited so fire-and-forget work spawned by the
181
+ // callback (e.g. skill rediscovery) completes before the reload resolves —
182
+ // otherwise Agent.create() can return with a cleared skill map (see race
183
+ // where refreshSkills() clears skillMetadata before async discoverSkills).
184
+ await this.options.onReload?.(this.currentConfiguration);
182
185
  return this.currentConfiguration;
183
186
  }
184
187
  catch (error) {
@@ -221,15 +221,19 @@ export function setupAgentContainer(setupOptions) {
221
221
  container.register("CanUseToolCallback", canUseToolWithPermissionRequest);
222
222
  const liveConfigManager = new LiveConfigManager(container, {
223
223
  workdir,
224
- onReload: () => {
224
+ onReload: async () => {
225
225
  const models = configurationService.getConfiguredModels();
226
226
  callbacks.onConfiguredModelsChange?.(models);
227
227
  // Re-evaluate feature-gated tools (e.g. Artifact behind
228
228
  // enableArtifact) so toggling the flag applies without a restart.
229
229
  toolManager.reloadFeatureGatedTools();
230
230
  // Same gate for the builtin /artifact skill: refresh emits "refreshed"
231
- // so slash-command registration follows enableArtifact.
232
- void skillManager.reloadFeatureGatedSkills().catch((error) => {
231
+ // so slash-command registration follows enableArtifact. Awaited (via the
232
+ // awaited onReload) so skills are re-populated before Agent.create()
233
+ // returns — reloadFeatureGatedSkills() clears the skill map before
234
+ // rediscovering asynchronously, which would otherwise expose an empty
235
+ // skill list to callers right after create().
236
+ await skillManager.reloadFeatureGatedSkills().catch((error) => {
233
237
  logger.error("Failed to reload feature-gated skills:", error);
234
238
  });
235
239
  },
@@ -299,7 +299,7 @@ export function convertMessagesForAPI(messages, options) {
299
299
  if (block.type === "task_notification") {
300
300
  contentParts.push({
301
301
  type: "text",
302
- text: taskNotificationToXml(block),
302
+ text: `A background agent completed a task:\n${taskNotificationToXml(block)}`,
303
303
  });
304
304
  }
305
305
  });
@@ -482,6 +482,7 @@ export const addNotificationMessageToMessages = ({ messages, taskId, taskType, s
482
482
  id: generateMessageId(),
483
483
  role: "user",
484
484
  blocks: [block],
485
+ isMeta: true,
485
486
  timestamp: new Date().toISOString(),
486
487
  };
487
488
  return [...messages, notificationMessage];
@@ -1,24 +1,12 @@
1
1
  import type { Message, Usage } from "../types/index.js";
2
2
  /**
3
- * Calculate comprehensive total tokens including cache-related tokens
4
- *
5
- * This function computes the true total token cost by including:
6
- * - Base total_tokens (prompt + completion)
7
- * - Cache read tokens (cost savings indicator)
8
- * - Cache creation tokens (cache investment)
9
- *
10
- * For accurate cost tracking with Claude models that support cache control.
11
- *
12
- * @param usage - Usage statistics from AI operation
13
- * @returns Comprehensive total including all cache-related tokens
14
- */
15
- export declare function calculateComprehensiveTotalTokens(usage: Usage): number;
16
- /**
17
- * Extract the latest total tokens from the last message with usage data
18
- * Uses comprehensive calculation that includes cache tokens for accurate tracking
3
+ * Extract the latest total tokens from the last message with usage data.
4
+ * Uses only `total_tokens` — OpenAI-compatible usage already includes cache
5
+ * hits there, so adding cache fields would double-count (same semantics as
6
+ * the auto-compaction threshold; keeps UI usage display aligned with it).
19
7
  *
20
8
  * @param messages - Array of messages to search
21
- * @returns Comprehensive total tokens from the most recent usage data, or 0 if none found
9
+ * @returns Total tokens from the most recent usage data, or 0 if none found
22
10
  */
23
11
  export declare function extractLatestTotalTokens(messages: Array<{
24
12
  usage?: Usage;
@@ -1,36 +1,19 @@
1
1
  import { estimateTokens } from "./tokenEstimate.js";
2
2
  /**
3
- * Calculate comprehensive total tokens including cache-related tokens
4
- *
5
- * This function computes the true total token cost by including:
6
- * - Base total_tokens (prompt + completion)
7
- * - Cache read tokens (cost savings indicator)
8
- * - Cache creation tokens (cache investment)
9
- *
10
- * For accurate cost tracking with Claude models that support cache control.
11
- *
12
- * @param usage - Usage statistics from AI operation
13
- * @returns Comprehensive total including all cache-related tokens
14
- */
15
- export function calculateComprehensiveTotalTokens(usage) {
16
- const baseTokens = usage.total_tokens;
17
- const cacheReadTokens = usage.cache_read_input_tokens || 0;
18
- const cacheCreateTokens = usage.cache_creation_input_tokens || 0;
19
- return baseTokens + cacheReadTokens + cacheCreateTokens;
20
- }
21
- /**
22
- * Extract the latest total tokens from the last message with usage data
23
- * Uses comprehensive calculation that includes cache tokens for accurate tracking
3
+ * Extract the latest total tokens from the last message with usage data.
4
+ * Uses only `total_tokens` — OpenAI-compatible usage already includes cache
5
+ * hits there, so adding cache fields would double-count (same semantics as
6
+ * the auto-compaction threshold; keeps UI usage display aligned with it).
24
7
  *
25
8
  * @param messages - Array of messages to search
26
- * @returns Comprehensive total tokens from the most recent usage data, or 0 if none found
9
+ * @returns Total tokens from the most recent usage data, or 0 if none found
27
10
  */
28
11
  export function extractLatestTotalTokens(messages) {
29
12
  // Find the last message with usage data (iterate backwards for efficiency)
30
13
  for (let i = messages.length - 1; i >= 0; i--) {
31
14
  const message = messages[i];
32
15
  if (message.usage) {
33
- return calculateComprehensiveTotalTokens(message.usage);
16
+ return message.usage.total_tokens;
34
17
  }
35
18
  }
36
19
  return 0; // No usage data found
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",