@everworker/oneringai 0.4.0 → 0.4.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.cjs CHANGED
@@ -11943,6 +11943,9 @@ var ToolManager = class extends eventemitter3.EventEmitter {
11943
11943
  }
11944
11944
  };
11945
11945
 
11946
+ // src/core/context-nextgen/AgentContextNextGen.ts
11947
+ init_Logger();
11948
+
11946
11949
  // src/core/Vendor.ts
11947
11950
  var Vendor = {
11948
11951
  OpenAI: "openai",
@@ -13316,6 +13319,7 @@ var ContentType = /* @__PURE__ */ ((ContentType2) => {
13316
13319
  ContentType2["OUTPUT_TEXT"] = "output_text";
13317
13320
  ContentType2["TOOL_USE"] = "tool_use";
13318
13321
  ContentType2["TOOL_RESULT"] = "tool_result";
13322
+ ContentType2["THINKING"] = "thinking";
13319
13323
  return ContentType2;
13320
13324
  })(ContentType || {});
13321
13325
 
@@ -13578,6 +13582,11 @@ var BasePluginNextGen = class {
13578
13582
  }
13579
13583
  };
13580
13584
 
13585
+ // src/core/context-nextgen/snapshot.ts
13586
+ function formatPluginDisplayName(name) {
13587
+ return name.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
13588
+ }
13589
+
13581
13590
  // src/core/context-nextgen/AgentContextNextGen.ts
13582
13591
  init_Connector();
13583
13592
 
@@ -14505,7 +14514,7 @@ var PRIORITY_VALUES = {
14505
14514
  };
14506
14515
  var DEFAULT_CONFIG = {
14507
14516
  maxEntries: 20,
14508
- maxTotalTokens: 4e3,
14517
+ maxTotalTokens: 4e4,
14509
14518
  defaultPriority: "normal",
14510
14519
  showTimestamps: false
14511
14520
  };
@@ -16256,8 +16265,11 @@ var AlgorithmicCompactionStrategy = class {
16256
16265
  * Emergency compaction when context exceeds threshold.
16257
16266
  *
16258
16267
  * Strategy:
16259
- * 1. Run consolidate() first to move tool results to memory
16268
+ * 1. Run consolidate() first to move tool results to memory (if working memory available)
16260
16269
  * 2. If still need space, apply rolling window (remove oldest messages)
16270
+ *
16271
+ * Gracefully degrades: if working memory plugin is not registered,
16272
+ * skips step 1 and only uses rolling window compaction.
16261
16273
  */
16262
16274
  async compact(context, targetToFree) {
16263
16275
  const log = [];
@@ -16270,7 +16282,7 @@ var AlgorithmicCompactionStrategy = class {
16270
16282
  tokensFreed += Math.abs(consolidateResult.tokensChanged);
16271
16283
  log.push(...consolidateResult.actions);
16272
16284
  }
16273
- let remaining = targetToFree - tokensFreed;
16285
+ const remaining = targetToFree - tokensFreed;
16274
16286
  if (remaining > 0 && context.conversation.length > 0) {
16275
16287
  log.push(`Rolling window: need to free ~${remaining} more tokens`);
16276
16288
  const result = await this.applyRollingWindow(context, remaining, log);
@@ -16284,8 +16296,11 @@ var AlgorithmicCompactionStrategy = class {
16284
16296
  * Post-cycle consolidation.
16285
16297
  *
16286
16298
  * 1. Find all tool pairs in conversation
16287
- * 2. Move large tool results (> threshold) to Working Memory
16299
+ * 2. Move large tool results (> threshold) to Working Memory (if available)
16288
16300
  * 3. Limit remaining tool pairs to maxToolPairs
16301
+ *
16302
+ * Gracefully degrades: if working memory is not available, skips step 2
16303
+ * and only limits tool pairs + removes excess via rolling window.
16289
16304
  */
16290
16305
  async consolidate(context) {
16291
16306
  const log = [];
@@ -16296,23 +16311,25 @@ var AlgorithmicCompactionStrategy = class {
16296
16311
  return { performed: false, tokensChanged: 0, actions: [] };
16297
16312
  }
16298
16313
  const indicesToRemove = [];
16299
- for (const pair of toolPairs) {
16300
- if (pair.resultSizeBytes > this.toolResultSizeThreshold) {
16301
- const key = this.generateKey(pair.toolName, pair.toolUseId);
16302
- const desc = this.generateDescription(pair.toolName, pair.toolArgs);
16303
- await memory.store(key, desc, pair.resultContent, {
16304
- tier: "raw",
16305
- priority: "normal"
16306
- });
16307
- if (!indicesToRemove.includes(pair.toolUseIndex)) {
16308
- indicesToRemove.push(pair.toolUseIndex);
16309
- }
16310
- if (!indicesToRemove.includes(pair.toolResultIndex)) {
16311
- indicesToRemove.push(pair.toolResultIndex);
16314
+ if (memory) {
16315
+ for (const pair of toolPairs) {
16316
+ if (pair.resultSizeBytes > this.toolResultSizeThreshold) {
16317
+ const key = this.generateKey(pair.toolName, pair.toolUseId);
16318
+ const desc = this.generateDescription(pair.toolName, pair.toolArgs);
16319
+ await memory.store(key, desc, pair.resultContent, {
16320
+ tier: "raw",
16321
+ priority: "normal"
16322
+ });
16323
+ if (!indicesToRemove.includes(pair.toolUseIndex)) {
16324
+ indicesToRemove.push(pair.toolUseIndex);
16325
+ }
16326
+ if (!indicesToRemove.includes(pair.toolResultIndex)) {
16327
+ indicesToRemove.push(pair.toolResultIndex);
16328
+ }
16329
+ log.push(
16330
+ `Moved ${pair.toolName} result (${this.formatBytes(pair.resultSizeBytes)}) to memory: ${key}`
16331
+ );
16312
16332
  }
16313
- log.push(
16314
- `Moved ${pair.toolName} result (${this.formatBytes(pair.resultSizeBytes)}) to memory: ${key}`
16315
- );
16316
16333
  }
16317
16334
  }
16318
16335
  const remainingPairs = toolPairs.filter(
@@ -16341,15 +16358,12 @@ var AlgorithmicCompactionStrategy = class {
16341
16358
  };
16342
16359
  }
16343
16360
  /**
16344
- * Get the Working Memory plugin from context.
16345
- * @throws Error if plugin is not available
16361
+ * Get the Working Memory plugin from context, or null if not available.
16362
+ * When null, the strategy degrades gracefully (skips memory operations).
16346
16363
  */
16347
16364
  getWorkingMemory(context) {
16348
16365
  const plugin = context.plugins.find((p) => p.name === "working_memory");
16349
- if (!plugin) {
16350
- throw new Error("AlgorithmicCompactionStrategy requires working_memory plugin");
16351
- }
16352
- return plugin;
16366
+ return plugin ? plugin : null;
16353
16367
  }
16354
16368
  /**
16355
16369
  * Find all tool_use/tool_result pairs in conversation.
@@ -16690,7 +16704,7 @@ var StrategyRegistry = class {
16690
16704
  // src/core/context-nextgen/types.ts
16691
16705
  var DEFAULT_FEATURES = {
16692
16706
  workingMemory: true,
16693
- inContextMemory: false,
16707
+ inContextMemory: true,
16694
16708
  persistentInstructions: false,
16695
16709
  userInfo: false
16696
16710
  };
@@ -16734,6 +16748,8 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
16734
16748
  _storage;
16735
16749
  /** Destroyed flag */
16736
16750
  _destroyed = false;
16751
+ /** Last thinking/reasoning content from the most recent assistant response */
16752
+ _lastThinking = null;
16737
16753
  /** Cached budget from last prepare() call */
16738
16754
  _cachedBudget = null;
16739
16755
  /** Callback for beforeCompaction hook (set by Agent) */
@@ -16821,15 +16837,16 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
16821
16837
  }
16822
16838
  /**
16823
16839
  * Validate that a strategy's required plugins are registered.
16824
- * @throws Error if any required plugin is missing
16840
+ * Logs a warning if required plugins are missing — the strategy should degrade gracefully.
16825
16841
  */
16826
16842
  validateStrategyDependencies(strategy) {
16827
16843
  if (!strategy.requiredPlugins?.length) return;
16828
16844
  const availablePlugins = new Set(this._plugins.keys());
16829
16845
  const missing = strategy.requiredPlugins.filter((name) => !availablePlugins.has(name));
16830
16846
  if (missing.length > 0) {
16831
- throw new Error(
16832
- `Strategy '${strategy.name}' requires plugins that are not registered: ${missing.join(", ")}. Available plugins: ${Array.from(availablePlugins).join(", ") || "none"}`
16847
+ exports.logger.warn(
16848
+ { strategy: strategy.name, missing, available: Array.from(availablePlugins) },
16849
+ `Strategy '${strategy.name}' recommends plugins that are not registered: ${missing.join(", ")}. Strategy will degrade gracefully.`
16833
16850
  );
16834
16851
  }
16835
16852
  }
@@ -16945,6 +16962,13 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
16945
16962
  get storage() {
16946
16963
  return this._storage ?? null;
16947
16964
  }
16965
+ /**
16966
+ * Get the last thinking/reasoning content from the most recent assistant response.
16967
+ * Updated on every assistant response, always available regardless of persistence setting.
16968
+ */
16969
+ get lastThinking() {
16970
+ return this._lastThinking;
16971
+ }
16948
16972
  /** Get max context tokens */
16949
16973
  get maxContextTokens() {
16950
16974
  return this._maxContextTokens;
@@ -17126,6 +17150,7 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
17126
17150
  }
17127
17151
  const id = this.generateId();
17128
17152
  const contentArray = [];
17153
+ let thinkingText = null;
17129
17154
  for (const item of output) {
17130
17155
  if (item.type === "message" && "content" in item) {
17131
17156
  const msg = item;
@@ -17137,12 +17162,19 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
17137
17162
  });
17138
17163
  } else if (c.type === "tool_use" /* TOOL_USE */) {
17139
17164
  contentArray.push(c);
17165
+ } else if (c.type === "thinking" /* THINKING */) {
17166
+ const thinking = c;
17167
+ thinkingText = thinking.thinking;
17168
+ if (thinking.persistInHistory) {
17169
+ contentArray.push(c);
17170
+ }
17140
17171
  }
17141
17172
  }
17142
17173
  } else if (item.type === "compaction" || item.type === "reasoning") {
17143
17174
  continue;
17144
17175
  }
17145
17176
  }
17177
+ this._lastThinking = thinkingText;
17146
17178
  if (contentArray.length > 0) {
17147
17179
  const message = {
17148
17180
  type: "message",
@@ -17241,6 +17273,7 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
17241
17273
  */
17242
17274
  async prepare() {
17243
17275
  this.assertNotDestroyed();
17276
+ this._lastThinking = null;
17244
17277
  const compactionLog = [];
17245
17278
  const toolsTokens = this.calculateToolsTokens();
17246
17279
  const availableForContent = this._maxContextTokens - this._config.responseReserve - toolsTokens;
@@ -17453,6 +17486,8 @@ ${content}`);
17453
17486
  total += this._estimateImageTokens();
17454
17487
  }
17455
17488
  }
17489
+ } else if (c.type === "thinking" /* THINKING */) {
17490
+ total += this._estimator.estimateTokens(c.thinking || "");
17456
17491
  } else if (c.type === "input_image_url" /* INPUT_IMAGE_URL */) {
17457
17492
  const imgContent = c;
17458
17493
  const detail = imgContent.image_url?.detail;
@@ -17950,6 +17985,188 @@ ${content}`);
17950
17985
  get strategy() {
17951
17986
  return this._compactionStrategy.name;
17952
17987
  }
17988
+ /**
17989
+ * Get a complete, serializable snapshot of the context state.
17990
+ *
17991
+ * Returns all data needed by UI "Look Inside" panels without reaching
17992
+ * into plugin internals. Plugin data is auto-discovered from the plugin
17993
+ * registry — new/custom plugins appear automatically.
17994
+ *
17995
+ * @param toolStats - Optional tool usage stats (from ToolManager.getStats())
17996
+ * @returns Serializable context snapshot
17997
+ */
17998
+ async getSnapshot(toolStats) {
17999
+ const resolveContents = async (raw) => {
18000
+ const resolved = raw instanceof Promise ? await raw : raw;
18001
+ if (resolved instanceof Map) return Array.from(resolved.values());
18002
+ return resolved;
18003
+ };
18004
+ if (this._destroyed) {
18005
+ const emptyBudget = this._cachedBudget ?? {
18006
+ maxTokens: this._maxContextTokens,
18007
+ responseReserve: this._config.responseReserve,
18008
+ systemMessageTokens: 0,
18009
+ toolsTokens: 0,
18010
+ conversationTokens: 0,
18011
+ currentInputTokens: 0,
18012
+ totalUsed: 0,
18013
+ available: this._maxContextTokens - this._config.responseReserve,
18014
+ utilizationPercent: 0,
18015
+ breakdown: {
18016
+ systemPrompt: 0,
18017
+ persistentInstructions: 0,
18018
+ pluginInstructions: 0,
18019
+ pluginContents: {},
18020
+ tools: 0,
18021
+ conversation: 0,
18022
+ currentInput: 0
18023
+ }
18024
+ };
18025
+ return {
18026
+ available: false,
18027
+ agentId: this._agentId,
18028
+ model: this._config.model,
18029
+ features: this._config.features,
18030
+ budget: emptyBudget,
18031
+ strategy: this._compactionStrategy.name,
18032
+ messagesCount: 0,
18033
+ toolCallsCount: 0,
18034
+ systemPrompt: null,
18035
+ plugins: [],
18036
+ tools: []
18037
+ };
18038
+ }
18039
+ const budget = await this.calculateBudget();
18040
+ const plugins = [];
18041
+ for (const plugin of this._plugins.values()) {
18042
+ let formattedContent = null;
18043
+ try {
18044
+ formattedContent = await plugin.getContent();
18045
+ } catch {
18046
+ }
18047
+ plugins.push({
18048
+ name: plugin.name,
18049
+ displayName: formatPluginDisplayName(plugin.name),
18050
+ enabled: true,
18051
+ tokenSize: plugin.getTokenSize(),
18052
+ instructionsTokenSize: plugin.getInstructionsTokenSize(),
18053
+ compactable: plugin.isCompactable(),
18054
+ contents: await resolveContents(plugin.getContents()),
18055
+ formattedContent
18056
+ });
18057
+ }
18058
+ const usageCounts = /* @__PURE__ */ new Map();
18059
+ if (toolStats?.mostUsed) {
18060
+ for (const { name, count } of toolStats.mostUsed) {
18061
+ usageCounts.set(name, count);
18062
+ }
18063
+ }
18064
+ const tools = [];
18065
+ for (const toolName of this._tools.list()) {
18066
+ const reg = this._tools.getRegistration(toolName);
18067
+ if (!reg) continue;
18068
+ tools.push({
18069
+ name: toolName,
18070
+ description: reg.tool.definition.function.description || "",
18071
+ enabled: reg.enabled,
18072
+ callCount: reg.metadata.usageCount ?? usageCounts.get(toolName) ?? 0,
18073
+ namespace: reg.namespace || void 0
18074
+ });
18075
+ }
18076
+ let toolCallsCount = 0;
18077
+ for (const item of this._conversation) {
18078
+ if (item.type === "message" && item.role === "assistant" /* ASSISTANT */) {
18079
+ for (const c of item.content) {
18080
+ if (c.type === "tool_use" /* TOOL_USE */) toolCallsCount++;
18081
+ }
18082
+ }
18083
+ }
18084
+ return {
18085
+ available: true,
18086
+ agentId: this._agentId,
18087
+ model: this._config.model,
18088
+ features: this._config.features,
18089
+ budget,
18090
+ strategy: this._compactionStrategy.name,
18091
+ messagesCount: this._conversation.length,
18092
+ toolCallsCount,
18093
+ systemPrompt: this._systemPrompt ?? null,
18094
+ plugins,
18095
+ tools
18096
+ };
18097
+ }
18098
+ /**
18099
+ * Get a human-readable breakdown of the prepared context.
18100
+ *
18101
+ * Calls `prepare()` internally, then maps each InputItem to a named
18102
+ * component with content text and token estimate. Used by "View Full Context" UIs.
18103
+ *
18104
+ * @returns View context data with components and raw text for "Copy All"
18105
+ */
18106
+ async getViewContext() {
18107
+ if (this._destroyed) {
18108
+ return { available: false, components: [], totalTokens: 0, rawContext: "" };
18109
+ }
18110
+ const { input, budget } = await this.prepare();
18111
+ const components = [];
18112
+ let rawParts = [];
18113
+ for (const item of input) {
18114
+ if (item.type === "compaction") {
18115
+ components.push({
18116
+ name: "Compaction Block",
18117
+ content: "[Compacted content]",
18118
+ tokenEstimate: 0
18119
+ });
18120
+ continue;
18121
+ }
18122
+ const msg = item;
18123
+ const roleName = msg.role === "developer" /* DEVELOPER */ ? "System Message" : msg.role === "user" /* USER */ ? "User Message" : "Assistant Message";
18124
+ for (const block of msg.content) {
18125
+ let name = roleName;
18126
+ let text = "";
18127
+ switch (block.type) {
18128
+ case "input_text" /* INPUT_TEXT */:
18129
+ text = block.text;
18130
+ break;
18131
+ case "output_text" /* OUTPUT_TEXT */:
18132
+ text = block.text;
18133
+ break;
18134
+ case "tool_use" /* TOOL_USE */:
18135
+ name = `Tool Call: ${block.name}`;
18136
+ text = `${block.name}(${block.arguments})`;
18137
+ break;
18138
+ case "tool_result" /* TOOL_RESULT */:
18139
+ name = `Tool Result: ${block.tool_use_id}`;
18140
+ text = typeof block.content === "string" ? block.content : JSON.stringify(block.content, null, 2);
18141
+ if (block.error) text = `[Error] ${block.error}
18142
+ ${text}`;
18143
+ break;
18144
+ case "input_image_url" /* INPUT_IMAGE_URL */:
18145
+ name = "Image Input";
18146
+ text = `[Image: ${block.image_url.url.substring(0, 100)}...]`;
18147
+ break;
18148
+ case "input_file" /* INPUT_FILE */:
18149
+ name = "File Input";
18150
+ text = `[File: ${block.file_id}]`;
18151
+ break;
18152
+ case "thinking" /* THINKING */:
18153
+ name = "Thinking";
18154
+ text = block.thinking || "";
18155
+ break;
18156
+ }
18157
+ const tokenEstimate = this._estimator.estimateTokens(text);
18158
+ components.push({ name, content: text, tokenEstimate });
18159
+ rawParts.push(`--- ${name} ---
18160
+ ${text}`);
18161
+ }
18162
+ }
18163
+ return {
18164
+ available: true,
18165
+ components,
18166
+ totalTokens: budget.totalUsed,
18167
+ rawContext: rawParts.join("\n\n")
18168
+ };
18169
+ }
17953
18170
  // ============================================================================
17954
18171
  // Utilities
17955
18172
  // ============================================================================
@@ -18208,6 +18425,13 @@ var BaseTextProvider = class extends BaseProvider {
18208
18425
  }
18209
18426
  return textParts.join("\n");
18210
18427
  }
18428
+ /**
18429
+ * List available models from the provider's API.
18430
+ * Default returns empty array; providers override when they have SDK support.
18431
+ */
18432
+ async listModels() {
18433
+ return [];
18434
+ }
18211
18435
  /**
18212
18436
  * Clean up provider resources (circuit breaker listeners, etc.)
18213
18437
  * Should be called when the provider is no longer needed.
@@ -18360,12 +18584,21 @@ var OpenAIResponsesConverter = class {
18360
18584
  } else if (item.type === "reasoning") {
18361
18585
  const reasoning = item;
18362
18586
  if (reasoning.summary) {
18363
- content.push({
18364
- type: "reasoning",
18365
- summary: reasoning.summary,
18366
- // effort field may not exist in all versions
18367
- ..."effort" in reasoning && { effort: reasoning.effort }
18368
- });
18587
+ let summaryText;
18588
+ if (typeof reasoning.summary === "string") {
18589
+ summaryText = reasoning.summary;
18590
+ } else if (Array.isArray(reasoning.summary)) {
18591
+ summaryText = reasoning.summary.map((s) => s.text || "").filter(Boolean).join("\n");
18592
+ } else {
18593
+ summaryText = "";
18594
+ }
18595
+ if (summaryText) {
18596
+ content.push({
18597
+ type: "thinking" /* THINKING */,
18598
+ thinking: summaryText,
18599
+ persistInHistory: false
18600
+ });
18601
+ }
18369
18602
  }
18370
18603
  }
18371
18604
  }
@@ -18388,10 +18621,20 @@ var OpenAIResponsesConverter = class {
18388
18621
  }
18389
18622
  ],
18390
18623
  output_text: outputText,
18624
+ // Extract thinking text from content for convenience field
18625
+ ...(() => {
18626
+ const thinkingTexts = content.filter((c) => c.type === "thinking" /* THINKING */).map((c) => c.thinking).filter(Boolean);
18627
+ return thinkingTexts.length > 0 ? { thinking: thinkingTexts.join("\n") } : {};
18628
+ })(),
18391
18629
  usage: {
18392
18630
  input_tokens: response.usage?.input_tokens || 0,
18393
18631
  output_tokens: response.usage?.output_tokens || 0,
18394
- total_tokens: response.usage?.total_tokens || 0
18632
+ total_tokens: response.usage?.total_tokens || 0,
18633
+ ...response.usage?.output_tokens_details?.reasoning_tokens != null && {
18634
+ output_tokens_details: {
18635
+ reasoning_tokens: response.usage.output_tokens_details.reasoning_tokens
18636
+ }
18637
+ }
18395
18638
  }
18396
18639
  };
18397
18640
  }
@@ -18496,6 +18739,8 @@ var StreamEventType = /* @__PURE__ */ ((StreamEventType2) => {
18496
18739
  StreamEventType2["TOOL_EXECUTION_START"] = "response.tool_execution.start";
18497
18740
  StreamEventType2["TOOL_EXECUTION_DONE"] = "response.tool_execution.done";
18498
18741
  StreamEventType2["ITERATION_COMPLETE"] = "response.iteration.complete";
18742
+ StreamEventType2["REASONING_DELTA"] = "response.reasoning.delta";
18743
+ StreamEventType2["REASONING_DONE"] = "response.reasoning.done";
18499
18744
  StreamEventType2["RESPONSE_COMPLETE"] = "response.complete";
18500
18745
  StreamEventType2["ERROR"] = "response.error";
18501
18746
  return StreamEventType2;
@@ -18515,6 +18760,12 @@ function isToolCallArgumentsDelta(event) {
18515
18760
  function isToolCallArgumentsDone(event) {
18516
18761
  return event.type === "response.tool_call_arguments.done" /* TOOL_CALL_ARGUMENTS_DONE */;
18517
18762
  }
18763
+ function isReasoningDelta(event) {
18764
+ return event.type === "response.reasoning.delta" /* REASONING_DELTA */;
18765
+ }
18766
+ function isReasoningDone(event) {
18767
+ return event.type === "response.reasoning.done" /* REASONING_DONE */;
18768
+ }
18518
18769
  function isResponseComplete(event) {
18519
18770
  return event.type === "response.complete" /* RESPONSE_COMPLETE */;
18520
18771
  }
@@ -18532,6 +18783,8 @@ var OpenAIResponsesStreamConverter = class {
18532
18783
  let sequenceNumber = 0;
18533
18784
  const activeItems = /* @__PURE__ */ new Map();
18534
18785
  const toolCallBuffers = /* @__PURE__ */ new Map();
18786
+ const reasoningBuffers = /* @__PURE__ */ new Map();
18787
+ const reasoningDoneEmitted = /* @__PURE__ */ new Set();
18535
18788
  for await (const event of stream) {
18536
18789
  if (process.env.DEBUG_OPENAI) {
18537
18790
  console.error("[DEBUG] Responses API event:", event.type);
@@ -18553,6 +18806,12 @@ var OpenAIResponsesStreamConverter = class {
18553
18806
  activeItems.set(addedEvent.output_index.toString(), {
18554
18807
  type: item.type
18555
18808
  });
18809
+ if (item.type === "reasoning") {
18810
+ activeItems.set(addedEvent.output_index.toString(), {
18811
+ type: "reasoning"
18812
+ });
18813
+ reasoningBuffers.set(addedEvent.output_index.toString(), []);
18814
+ }
18556
18815
  if (item.type === "function_call") {
18557
18816
  const functionCall = item;
18558
18817
  const toolCallId = functionCall.call_id;
@@ -18610,9 +18869,53 @@ var OpenAIResponsesStreamConverter = class {
18610
18869
  }
18611
18870
  break;
18612
18871
  }
18872
+ case "response.reasoning_summary_text.delta":
18873
+ case "response.reasoning_text.delta": {
18874
+ const reasoningEvent = event;
18875
+ const outputIdx = reasoningEvent.output_index?.toString();
18876
+ const buffer = outputIdx ? reasoningBuffers.get(outputIdx) : void 0;
18877
+ if (buffer) {
18878
+ buffer.push(reasoningEvent.delta || "");
18879
+ }
18880
+ yield {
18881
+ type: "response.reasoning.delta" /* REASONING_DELTA */,
18882
+ response_id: responseId,
18883
+ item_id: reasoningEvent.item_id || `reasoning_${responseId}`,
18884
+ delta: reasoningEvent.delta || "",
18885
+ sequence_number: sequenceNumber++
18886
+ };
18887
+ break;
18888
+ }
18889
+ case "response.reasoning_text.done": {
18890
+ const doneEvent = event;
18891
+ const outputIdx = doneEvent.output_index.toString();
18892
+ const rBuf = reasoningBuffers.get(outputIdx);
18893
+ const thinkingText = rBuf ? rBuf.join("") : doneEvent.text || "";
18894
+ reasoningDoneEmitted.add(outputIdx);
18895
+ yield {
18896
+ type: "response.reasoning.done" /* REASONING_DONE */,
18897
+ response_id: responseId,
18898
+ item_id: doneEvent.item_id || `reasoning_${responseId}`,
18899
+ thinking: thinkingText
18900
+ };
18901
+ break;
18902
+ }
18613
18903
  case "response.output_item.done": {
18614
18904
  const doneEvent = event;
18615
18905
  const item = doneEvent.item;
18906
+ if (item.type === "reasoning") {
18907
+ const outputIdx = doneEvent.output_index.toString();
18908
+ if (!reasoningDoneEmitted.has(outputIdx)) {
18909
+ const rBuf = reasoningBuffers.get(outputIdx);
18910
+ const thinkingText = rBuf ? rBuf.join("") : "";
18911
+ yield {
18912
+ type: "response.reasoning.done" /* REASONING_DONE */,
18913
+ response_id: responseId,
18914
+ item_id: item.id || `reasoning_${responseId}`,
18915
+ thinking: thinkingText
18916
+ };
18917
+ }
18918
+ }
18616
18919
  if (item.type === "function_call") {
18617
18920
  const functionCall = item;
18618
18921
  const buffer = toolCallBuffers.get(functionCall.call_id);
@@ -18644,7 +18947,12 @@ var OpenAIResponsesStreamConverter = class {
18644
18947
  usage: {
18645
18948
  input_tokens: response.usage?.input_tokens || 0,
18646
18949
  output_tokens: response.usage?.output_tokens || 0,
18647
- total_tokens: response.usage?.total_tokens || 0
18950
+ total_tokens: response.usage?.total_tokens || 0,
18951
+ ...response.usage?.output_tokens_details?.reasoning_tokens != null && {
18952
+ output_tokens_details: {
18953
+ reasoning_tokens: response.usage.output_tokens_details.reasoning_tokens
18954
+ }
18955
+ }
18648
18956
  },
18649
18957
  iterations: 1
18650
18958
  };
@@ -18685,6 +18993,26 @@ function resolveMaxContextTokens(model, fallback) {
18685
18993
  return info ? info.features.input.tokens : fallback;
18686
18994
  }
18687
18995
 
18996
+ // src/infrastructure/providers/shared/validateThinkingConfig.ts
18997
+ function validateThinkingConfig(thinking) {
18998
+ if (!thinking.enabled) return;
18999
+ if (thinking.budgetTokens !== void 0) {
19000
+ if (typeof thinking.budgetTokens !== "number" || thinking.budgetTokens < 1) {
19001
+ throw new Error(
19002
+ `Invalid thinking budgetTokens: ${thinking.budgetTokens}. Must be a positive number.`
19003
+ );
19004
+ }
19005
+ }
19006
+ if (thinking.effort !== void 0) {
19007
+ const validEfforts = ["low", "medium", "high"];
19008
+ if (!validEfforts.includes(thinking.effort)) {
19009
+ throw new Error(
19010
+ `Invalid thinking effort: '${thinking.effort}'. Must be one of: ${validEfforts.join(", ")}`
19011
+ );
19012
+ }
19013
+ }
19014
+ }
19015
+
18688
19016
  // src/infrastructure/providers/openai/OpenAITextProvider.ts
18689
19017
  var OpenAITextProvider = class extends BaseTextProvider {
18690
19018
  name = "openai";
@@ -18752,6 +19080,7 @@ var OpenAITextProvider = class extends BaseTextProvider {
18752
19080
  },
18753
19081
  ...options.metadata && { metadata: options.metadata }
18754
19082
  };
19083
+ this.applyReasoningConfig(params, options);
18755
19084
  const response = await this.client.responses.create(params);
18756
19085
  return this.converter.convertResponse(response);
18757
19086
  } catch (error) {
@@ -18793,6 +19122,7 @@ var OpenAITextProvider = class extends BaseTextProvider {
18793
19122
  ...options.metadata && { metadata: options.metadata },
18794
19123
  stream: true
18795
19124
  };
19125
+ this.applyReasoningConfig(params, options);
18796
19126
  const stream = await this.client.responses.create(params);
18797
19127
  yield* this.streamConverter.convertStream(stream);
18798
19128
  } catch (error) {
@@ -18814,6 +19144,27 @@ var OpenAITextProvider = class extends BaseTextProvider {
18814
19144
  maxOutputTokens: 16384
18815
19145
  });
18816
19146
  }
19147
+ /**
19148
+ * List available models from the OpenAI API
19149
+ */
19150
+ async listModels() {
19151
+ const models = [];
19152
+ for await (const model of this.client.models.list()) {
19153
+ models.push(model.id);
19154
+ }
19155
+ return models.sort();
19156
+ }
19157
+ /**
19158
+ * Apply reasoning config from unified thinking option to request params
19159
+ */
19160
+ applyReasoningConfig(params, options) {
19161
+ if (options.thinking?.enabled) {
19162
+ validateThinkingConfig(options.thinking);
19163
+ params.reasoning = {
19164
+ effort: options.thinking.effort || "medium"
19165
+ };
19166
+ }
19167
+ }
18817
19168
  /**
18818
19169
  * Handle OpenAI-specific errors
18819
19170
  */
@@ -18856,6 +19207,7 @@ function buildLLMResponse(options) {
18856
19207
  }
18857
19208
  ];
18858
19209
  const outputText = extractTextFromContent(content);
19210
+ const thinking = extractThinkingFromContent(content);
18859
19211
  return {
18860
19212
  id: responseId,
18861
19213
  object: "response",
@@ -18864,6 +19216,7 @@ function buildLLMResponse(options) {
18864
19216
  model,
18865
19217
  output,
18866
19218
  output_text: outputText,
19219
+ ...thinking && { thinking },
18867
19220
  usage: {
18868
19221
  input_tokens: usage.inputTokens,
18869
19222
  output_tokens: usage.outputTokens,
@@ -18876,6 +19229,10 @@ function extractTextFromContent(content) {
18876
19229
  (c) => c.type === "output_text" /* OUTPUT_TEXT */
18877
19230
  ).map((c) => c.text).join("\n");
18878
19231
  }
19232
+ function extractThinkingFromContent(content) {
19233
+ const thinkingTexts = content.filter((c) => c.type === "thinking" /* THINKING */).map((c) => c.thinking).filter(Boolean);
19234
+ return thinkingTexts.length > 0 ? thinkingTexts.join("\n") : void 0;
19235
+ }
18879
19236
  function createTextContent(text) {
18880
19237
  return {
18881
19238
  type: "output_text" /* OUTPUT_TEXT */,
@@ -19125,7 +19482,15 @@ var AnthropicConverter = class extends BaseConverter {
19125
19482
  if (tools && tools.length > 0) {
19126
19483
  params.tools = tools;
19127
19484
  }
19128
- if (options.temperature !== void 0) {
19485
+ if (options.thinking?.enabled) {
19486
+ validateThinkingConfig(options.thinking);
19487
+ const budgetTokens = options.thinking.budgetTokens || 1e4;
19488
+ params.thinking = {
19489
+ type: "enabled",
19490
+ budget_tokens: budgetTokens
19491
+ };
19492
+ params.temperature = 1;
19493
+ } else if (options.temperature !== void 0) {
19129
19494
  params.temperature = options.temperature;
19130
19495
  }
19131
19496
  return params;
@@ -19171,6 +19536,14 @@ var AnthropicConverter = class extends BaseConverter {
19171
19536
  content.push(this.createText(block.text));
19172
19537
  } else if (block.type === "tool_use") {
19173
19538
  content.push(this.createToolUse(block.id, block.name, block.input));
19539
+ } else if (block.type === "thinking") {
19540
+ const thinkingBlock = block;
19541
+ content.push({
19542
+ type: "thinking" /* THINKING */,
19543
+ thinking: thinkingBlock.thinking || "",
19544
+ signature: thinkingBlock.signature,
19545
+ persistInHistory: true
19546
+ });
19174
19547
  }
19175
19548
  }
19176
19549
  return content;
@@ -19249,6 +19622,17 @@ var AnthropicConverter = class extends BaseConverter {
19249
19622
  });
19250
19623
  break;
19251
19624
  }
19625
+ case "thinking" /* THINKING */: {
19626
+ const thinkingContent = c;
19627
+ if (thinkingContent.signature) {
19628
+ blocks.push({
19629
+ type: "thinking",
19630
+ thinking: thinkingContent.thinking,
19631
+ signature: thinkingContent.signature
19632
+ });
19633
+ }
19634
+ break;
19635
+ }
19252
19636
  }
19253
19637
  }
19254
19638
  if (blocks.length === 1 && blocks[0]?.type === "text") {
@@ -19381,6 +19765,8 @@ var BaseStreamConverter = class {
19381
19765
  usage = { inputTokens: 0, outputTokens: 0 };
19382
19766
  /** Buffers for accumulating tool call arguments */
19383
19767
  toolCallBuffers = /* @__PURE__ */ new Map();
19768
+ /** Buffer for accumulating reasoning/thinking content */
19769
+ reasoningBuffer = "";
19384
19770
  // ==========================================================================
19385
19771
  // Public API
19386
19772
  // ==========================================================================
@@ -19415,6 +19801,7 @@ var BaseStreamConverter = class {
19415
19801
  this.sequenceNumber = 0;
19416
19802
  this.usage = { inputTokens: 0, outputTokens: 0 };
19417
19803
  this.toolCallBuffers.clear();
19804
+ this.reasoningBuffer = "";
19418
19805
  }
19419
19806
  /**
19420
19807
  * Reset converter state for a new stream
@@ -19469,6 +19856,33 @@ var BaseStreamConverter = class {
19469
19856
  sequence_number: this.nextSequence()
19470
19857
  };
19471
19858
  }
19859
+ /**
19860
+ * Create REASONING_DELTA event and accumulate reasoning buffer
19861
+ */
19862
+ emitReasoningDelta(delta, itemId) {
19863
+ this.reasoningBuffer += delta;
19864
+ return {
19865
+ type: "response.reasoning.delta" /* REASONING_DELTA */,
19866
+ response_id: this.responseId,
19867
+ item_id: itemId || `reasoning_${this.responseId}`,
19868
+ delta,
19869
+ sequence_number: this.nextSequence()
19870
+ };
19871
+ }
19872
+ /**
19873
+ * Create REASONING_DONE event with accumulated reasoning
19874
+ */
19875
+ emitReasoningDone(itemId) {
19876
+ const id = itemId || `reasoning_${this.responseId}`;
19877
+ const thinking = this.reasoningBuffer;
19878
+ this.reasoningBuffer = "";
19879
+ return {
19880
+ type: "response.reasoning.done" /* REASONING_DONE */,
19881
+ response_id: this.responseId,
19882
+ item_id: id,
19883
+ thinking
19884
+ };
19885
+ }
19472
19886
  /**
19473
19887
  * Create TOOL_CALL_START event
19474
19888
  */
@@ -19613,7 +20027,10 @@ var AnthropicStreamConverter = class extends BaseStreamConverter {
19613
20027
  handleContentBlockStart(event) {
19614
20028
  const index = event.index;
19615
20029
  const block = event.content_block;
19616
- if (block.type === "text") {
20030
+ if (block.type === "thinking") {
20031
+ this.contentBlockIndex.set(index, { type: "thinking" });
20032
+ return [];
20033
+ } else if (block.type === "text") {
19617
20034
  this.contentBlockIndex.set(index, { type: "text" });
19618
20035
  return [];
19619
20036
  } else if (block.type === "tool_use") {
@@ -19634,7 +20051,12 @@ var AnthropicStreamConverter = class extends BaseStreamConverter {
19634
20051
  const delta = event.delta;
19635
20052
  const blockInfo = this.contentBlockIndex.get(index);
19636
20053
  if (!blockInfo) return [];
19637
- if (delta.type === "text_delta") {
20054
+ if (delta.type === "thinking_delta") {
20055
+ const thinkingDelta = delta;
20056
+ return [
20057
+ this.emitReasoningDelta(thinkingDelta.thinking || "", `thinking_${this.responseId}`)
20058
+ ];
20059
+ } else if (delta.type === "text_delta") {
19638
20060
  return [
19639
20061
  this.emitTextDelta(delta.text, {
19640
20062
  itemId: `msg_${this.responseId}`,
@@ -19654,6 +20076,9 @@ var AnthropicStreamConverter = class extends BaseStreamConverter {
19654
20076
  const index = event.index;
19655
20077
  const blockInfo = this.contentBlockIndex.get(index);
19656
20078
  if (!blockInfo) return [];
20079
+ if (blockInfo.type === "thinking") {
20080
+ return [this.emitReasoningDone(`thinking_${this.responseId}`)];
20081
+ }
19657
20082
  if (blockInfo.type === "tool_use") {
19658
20083
  return [this.emitToolCallArgsDone(blockInfo.id || "", blockInfo.name)];
19659
20084
  }
@@ -19752,6 +20177,16 @@ var AnthropicTextProvider = class extends BaseTextProvider {
19752
20177
  caps.supportsJSONSchema = false;
19753
20178
  return caps;
19754
20179
  }
20180
+ /**
20181
+ * List available models from the Anthropic API
20182
+ */
20183
+ async listModels() {
20184
+ const models = [];
20185
+ for await (const model of this.client.models.list()) {
20186
+ models.push(model.id);
20187
+ }
20188
+ return models.sort();
20189
+ }
19755
20190
  /**
19756
20191
  * Handle Anthropic-specific errors
19757
20192
  */
@@ -19930,6 +20365,11 @@ var GoogleConverter = class {
19930
20365
  request.generationConfig.thinkingConfig = {
19931
20366
  thinkingLevel: options.vendorOptions.thinkingLevel
19932
20367
  };
20368
+ } else if (options.thinking?.enabled) {
20369
+ validateThinkingConfig(options.thinking);
20370
+ request.generationConfig.thinkingConfig = {
20371
+ thinkingBudget: options.thinking.budgetTokens || 8192
20372
+ };
19933
20373
  }
19934
20374
  if (tools && tools.length > 0) {
19935
20375
  request.generationConfig.allowCodeExecution = false;
@@ -20145,7 +20585,13 @@ var GoogleConverter = class {
20145
20585
  convertGeminiPartsToContent(parts) {
20146
20586
  const content = [];
20147
20587
  for (const part of parts) {
20148
- if ("text" in part && part.text) {
20588
+ if ("thought" in part && part.thought === true && "text" in part && part.text) {
20589
+ content.push({
20590
+ type: "thinking" /* THINKING */,
20591
+ thinking: part.text,
20592
+ persistInHistory: false
20593
+ });
20594
+ } else if ("text" in part && part.text) {
20149
20595
  content.push(createTextContent(part.text));
20150
20596
  } else if ("functionCall" in part && part.functionCall) {
20151
20597
  const toolId = generateToolCallId("google");
@@ -20223,6 +20669,8 @@ var GoogleStreamConverter = class {
20223
20669
  isFirst = true;
20224
20670
  toolCallBuffers = /* @__PURE__ */ new Map();
20225
20671
  hadToolCalls = false;
20672
+ reasoningBuffer = "";
20673
+ wasThinking = false;
20226
20674
  // External storage for thought signatures (shared with GoogleConverter)
20227
20675
  thoughtSignatureStorage = null;
20228
20676
  // External storage for tool call ID → name mapping (shared with GoogleConverter)
@@ -20250,6 +20698,8 @@ var GoogleStreamConverter = class {
20250
20698
  this.isFirst = true;
20251
20699
  this.toolCallBuffers.clear();
20252
20700
  this.hadToolCalls = false;
20701
+ this.reasoningBuffer = "";
20702
+ this.wasThinking = false;
20253
20703
  let lastUsage = {
20254
20704
  input_tokens: 0,
20255
20705
  output_tokens: 0,
@@ -20275,6 +20725,16 @@ var GoogleStreamConverter = class {
20275
20725
  yield event;
20276
20726
  }
20277
20727
  }
20728
+ if (this.wasThinking && this.reasoningBuffer) {
20729
+ yield {
20730
+ type: "response.reasoning.done" /* REASONING_DONE */,
20731
+ response_id: this.responseId,
20732
+ item_id: `thinking_${this.responseId}`,
20733
+ thinking: this.reasoningBuffer
20734
+ };
20735
+ this.reasoningBuffer = "";
20736
+ this.wasThinking = false;
20737
+ }
20278
20738
  if (this.toolCallBuffers.size > 0) {
20279
20739
  for (const [toolCallId, buffer] of this.toolCallBuffers) {
20280
20740
  yield {
@@ -20314,7 +20774,28 @@ var GoogleStreamConverter = class {
20314
20774
  const candidate = chunk.candidates?.[0];
20315
20775
  if (!candidate?.content?.parts) return events;
20316
20776
  for (const part of candidate.content.parts) {
20317
- if (part.text) {
20777
+ const isThought = "thought" in part && part.thought === true;
20778
+ if (isThought && part.text) {
20779
+ this.wasThinking = true;
20780
+ this.reasoningBuffer += part.text;
20781
+ events.push({
20782
+ type: "response.reasoning.delta" /* REASONING_DELTA */,
20783
+ response_id: this.responseId,
20784
+ item_id: `thinking_${this.responseId}`,
20785
+ delta: part.text,
20786
+ sequence_number: this.sequenceNumber++
20787
+ });
20788
+ } else if (part.text) {
20789
+ if (this.wasThinking) {
20790
+ this.wasThinking = false;
20791
+ events.push({
20792
+ type: "response.reasoning.done" /* REASONING_DONE */,
20793
+ response_id: this.responseId,
20794
+ item_id: `thinking_${this.responseId}`,
20795
+ thinking: this.reasoningBuffer
20796
+ });
20797
+ this.reasoningBuffer = "";
20798
+ }
20318
20799
  events.push({
20319
20800
  type: "response.output_text.delta" /* OUTPUT_TEXT_DELTA */,
20320
20801
  response_id: this.responseId,
@@ -20413,6 +20894,8 @@ var GoogleStreamConverter = class {
20413
20894
  this.isFirst = true;
20414
20895
  this.toolCallBuffers.clear();
20415
20896
  this.hadToolCalls = false;
20897
+ this.reasoningBuffer = "";
20898
+ this.wasThinking = false;
20416
20899
  }
20417
20900
  /**
20418
20901
  * Reset converter state for a new stream
@@ -20542,6 +21025,18 @@ var GoogleTextProvider = class extends BaseTextProvider {
20542
21025
  maxOutputTokens: 65536
20543
21026
  });
20544
21027
  }
21028
+ /**
21029
+ * List available models from the Google Gemini API
21030
+ */
21031
+ async listModels() {
21032
+ const models = [];
21033
+ const pager = await this.client.models.list();
21034
+ for await (const model of pager) {
21035
+ const name = model.name?.replace(/^models\//, "") ?? "";
21036
+ if (name) models.push(name);
21037
+ }
21038
+ return models.sort();
21039
+ }
20545
21040
  /**
20546
21041
  * Handle Google-specific errors
20547
21042
  */
@@ -20649,6 +21144,18 @@ var VertexAITextProvider = class extends BaseTextProvider {
20649
21144
  maxOutputTokens: 65536
20650
21145
  });
20651
21146
  }
21147
+ /**
21148
+ * List available models from the Vertex AI API
21149
+ */
21150
+ async listModels() {
21151
+ const models = [];
21152
+ const pager = await this.client.models.list();
21153
+ for await (const model of pager) {
21154
+ const name = model.name?.replace(/^models\//, "") ?? "";
21155
+ if (name) models.push(name);
21156
+ }
21157
+ return models.sort();
21158
+ }
20652
21159
  /**
20653
21160
  * Handle Vertex AI-specific errors
20654
21161
  */
@@ -20694,6 +21201,23 @@ var GenericOpenAIProvider = class extends OpenAITextProvider {
20694
21201
  };
20695
21202
  }
20696
21203
  }
21204
+ /**
21205
+ * Override API key validation for generic providers.
21206
+ * Services like Ollama don't require authentication, so accept any key including mock/placeholder keys.
21207
+ */
21208
+ validateApiKey() {
21209
+ return { isValid: true };
21210
+ }
21211
+ /**
21212
+ * Override listModels for error safety — some OpenAI-compatible APIs may not support /v1/models
21213
+ */
21214
+ async listModels() {
21215
+ try {
21216
+ return await super.listModels();
21217
+ } catch {
21218
+ return [];
21219
+ }
21220
+ }
20697
21221
  /**
20698
21222
  * Override model capabilities for generic providers (registry-driven with conservative defaults)
20699
21223
  */
@@ -21138,6 +21662,34 @@ var BaseAgent = class extends eventemitter3.EventEmitter {
21138
21662
  return tool.definition;
21139
21663
  });
21140
21664
  }
21665
+ // ===== Model Discovery =====
21666
+ /**
21667
+ * List available models from the provider's API.
21668
+ * Useful for discovering models dynamically (e.g., Ollama local models).
21669
+ */
21670
+ async listModels() {
21671
+ return this._provider.listModels();
21672
+ }
21673
+ // ===== Snapshot / Inspection =====
21674
+ /**
21675
+ * Get a complete, serializable snapshot of the agent's context state.
21676
+ *
21677
+ * Convenience method that auto-wires tool usage stats from ToolManager.
21678
+ * Used by UI "Look Inside" panels.
21679
+ */
21680
+ async getSnapshot() {
21681
+ const stats = this._agentContext.tools.getStats();
21682
+ return this._agentContext.getSnapshot({ mostUsed: stats.mostUsed });
21683
+ }
21684
+ /**
21685
+ * Get a human-readable breakdown of the prepared context.
21686
+ *
21687
+ * Convenience method that delegates to AgentContextNextGen.
21688
+ * Used by "View Full Context" UI panels.
21689
+ */
21690
+ async getViewContext() {
21691
+ return this._agentContext.getViewContext();
21692
+ }
21141
21693
  // ===== Direct LLM Access (Bypasses AgentContext) =====
21142
21694
  /**
21143
21695
  * Get the provider for LLM calls.
@@ -21901,6 +22453,8 @@ var StreamState = class {
21901
22453
  createdAt;
21902
22454
  // Text accumulation: item_id -> text chunks
21903
22455
  textBuffers;
22456
+ // Reasoning accumulation: item_id -> reasoning chunks
22457
+ reasoningBuffers;
21904
22458
  // Tool call accumulation: tool_call_id -> buffer
21905
22459
  toolCallBuffers;
21906
22460
  // Completed tool calls
@@ -21922,6 +22476,7 @@ var StreamState = class {
21922
22476
  this.model = model;
21923
22477
  this.createdAt = createdAt || Date.now();
21924
22478
  this.textBuffers = /* @__PURE__ */ new Map();
22479
+ this.reasoningBuffers = /* @__PURE__ */ new Map();
21925
22480
  this.toolCallBuffers = /* @__PURE__ */ new Map();
21926
22481
  this.completedToolCalls = [];
21927
22482
  this.toolResults = /* @__PURE__ */ new Map();
@@ -21965,6 +22520,39 @@ var StreamState = class {
21965
22520
  }
21966
22521
  return allText.join("");
21967
22522
  }
22523
+ /**
22524
+ * Accumulate reasoning delta for a specific item
22525
+ */
22526
+ accumulateReasoningDelta(itemId, delta) {
22527
+ if (!this.reasoningBuffers.has(itemId)) {
22528
+ this.reasoningBuffers.set(itemId, []);
22529
+ }
22530
+ this.reasoningBuffers.get(itemId).push(delta);
22531
+ this.totalChunks++;
22532
+ }
22533
+ /**
22534
+ * Get complete accumulated reasoning for an item
22535
+ */
22536
+ getCompleteReasoning(itemId) {
22537
+ const chunks = this.reasoningBuffers.get(itemId);
22538
+ return chunks ? chunks.join("") : "";
22539
+ }
22540
+ /**
22541
+ * Get all accumulated reasoning (all items concatenated)
22542
+ */
22543
+ getAllReasoning() {
22544
+ const allReasoning = [];
22545
+ for (const chunks of this.reasoningBuffers.values()) {
22546
+ allReasoning.push(chunks.join(""));
22547
+ }
22548
+ return allReasoning.join("");
22549
+ }
22550
+ /**
22551
+ * Check if stream has any accumulated reasoning
22552
+ */
22553
+ hasReasoning() {
22554
+ return this.reasoningBuffers.size > 0;
22555
+ }
21968
22556
  /**
21969
22557
  * Start accumulating tool call arguments
21970
22558
  */
@@ -22133,6 +22721,7 @@ var StreamState = class {
22133
22721
  */
22134
22722
  clear() {
22135
22723
  this.textBuffers.clear();
22724
+ this.reasoningBuffers.clear();
22136
22725
  this.toolCallBuffers.clear();
22137
22726
  this.completedToolCalls = [];
22138
22727
  this.toolResults.clear();
@@ -22146,6 +22735,7 @@ var StreamState = class {
22146
22735
  model: this.model,
22147
22736
  createdAt: this.createdAt,
22148
22737
  textBuffers: new Map(this.textBuffers),
22738
+ reasoningBuffers: new Map(this.reasoningBuffers),
22149
22739
  toolCallBuffers: new Map(this.toolCallBuffers),
22150
22740
  completedToolCalls: [...this.completedToolCalls],
22151
22741
  toolResults: new Map(this.toolResults),
@@ -22575,6 +23165,20 @@ var Agent = class _Agent extends BaseAgent {
22575
23165
  _addStreamingAssistantMessage(streamState, toolCalls) {
22576
23166
  const assistantText = streamState.getAllText();
22577
23167
  const assistantContent = [];
23168
+ if (streamState.hasReasoning()) {
23169
+ const reasoning = streamState.getAllReasoning();
23170
+ if (reasoning) {
23171
+ const isAnthropic = this.connector.vendor === Vendor.Anthropic;
23172
+ assistantContent.push({
23173
+ type: "thinking" /* THINKING */,
23174
+ thinking: reasoning,
23175
+ // Streaming doesn't carry Anthropic signatures, so signature is undefined here.
23176
+ // Non-streaming responses (via convertResponse) capture signatures correctly.
23177
+ signature: void 0,
23178
+ persistInHistory: isAnthropic
23179
+ });
23180
+ }
23181
+ }
22578
23182
  if (assistantText && assistantText.trim()) {
22579
23183
  assistantContent.push({
22580
23184
  type: "output_text" /* OUTPUT_TEXT */,
@@ -22813,6 +23417,7 @@ var Agent = class _Agent extends BaseAgent {
22813
23417
  tools: this.getEnabledToolDefinitions(),
22814
23418
  tool_choice: "auto",
22815
23419
  temperature: this._config.temperature,
23420
+ thinking: this._config.thinking,
22816
23421
  vendorOptions: this._config.vendorOptions
22817
23422
  };
22818
23423
  const beforeLLM = await this.hookManager.executeHooks("before:llm", {
@@ -22878,6 +23483,7 @@ var Agent = class _Agent extends BaseAgent {
22878
23483
  tools: this.getEnabledToolDefinitions(),
22879
23484
  tool_choice: "auto",
22880
23485
  temperature: this._config.temperature,
23486
+ thinking: this._config.thinking,
22881
23487
  vendorOptions: this._config.vendorOptions
22882
23488
  };
22883
23489
  await this.hookManager.executeHooks("before:llm", {
@@ -22895,7 +23501,9 @@ var Agent = class _Agent extends BaseAgent {
22895
23501
  });
22896
23502
  try {
22897
23503
  for await (const event of this._provider.streamGenerate(generateOptions)) {
22898
- if (event.type === "response.output_text.delta" /* OUTPUT_TEXT_DELTA */) {
23504
+ if (isReasoningDelta(event)) {
23505
+ streamState.accumulateReasoningDelta(event.item_id, event.delta);
23506
+ } else if (event.type === "response.output_text.delta" /* OUTPUT_TEXT_DELTA */) {
22899
23507
  streamState.accumulateTextDelta(event.item_id, event.delta);
22900
23508
  } else if (event.type === "response.tool_call.start" /* TOOL_CALL_START */) {
22901
23509
  streamState.startToolCall(event.tool_call_id, event.tool_name);
@@ -23931,6 +24539,12 @@ function defaultTaskPrompt(task) {
23931
24539
  }
23932
24540
  parts.push("");
23933
24541
  }
24542
+ if (task.dependsOn.length > 0) {
24543
+ parts.push("Note: Results from prerequisite tasks are available in your live context.");
24544
+ parts.push("Small results appear directly; larger results are in working memory \u2014 use memory_retrieve to access them.");
24545
+ parts.push("Review the plan overview and dependency results before starting.");
24546
+ parts.push("");
24547
+ }
23934
24548
  parts.push("After completing the work, store key results in memory once, then respond with a text summary (no more tool calls).");
23935
24549
  return parts.join("\n");
23936
24550
  }
@@ -24014,6 +24628,127 @@ async function collectValidationContext(agent, responseText) {
24014
24628
  toolCallLog
24015
24629
  };
24016
24630
  }
24631
+ function estimateTokens(text) {
24632
+ return Math.ceil(text.length / 4);
24633
+ }
24634
+ function buildPlanOverview(execution, definition, currentTaskId) {
24635
+ const parts = [];
24636
+ const progress = execution.progress ?? 0;
24637
+ parts.push(`Routine: ${definition.name}`);
24638
+ if (definition.description) {
24639
+ parts.push(`Goal: ${definition.description}`);
24640
+ }
24641
+ parts.push(`Progress: ${Math.round(progress * 100)}%`);
24642
+ parts.push("");
24643
+ parts.push("Tasks:");
24644
+ for (const task of execution.plan.tasks) {
24645
+ let statusIcon;
24646
+ switch (task.status) {
24647
+ case "completed":
24648
+ statusIcon = "[x]";
24649
+ break;
24650
+ case "in_progress":
24651
+ statusIcon = "[>]";
24652
+ break;
24653
+ case "failed":
24654
+ statusIcon = "[!]";
24655
+ break;
24656
+ case "skipped":
24657
+ statusIcon = "[-]";
24658
+ break;
24659
+ default:
24660
+ statusIcon = "[ ]";
24661
+ }
24662
+ let line = `${statusIcon} ${task.name}`;
24663
+ if (task.dependsOn.length > 0) {
24664
+ const depNames = task.dependsOn.map((depId) => execution.plan.tasks.find((t) => t.id === depId)?.name ?? depId).join(", ");
24665
+ line += ` (after: ${depNames})`;
24666
+ }
24667
+ if (task.id === currentTaskId) {
24668
+ line += " \u2190 CURRENT";
24669
+ }
24670
+ parts.push(line);
24671
+ }
24672
+ return parts.join("\n");
24673
+ }
24674
+ async function injectRoutineContext(agent, execution, definition, currentTask) {
24675
+ const icmPlugin = agent.context.getPlugin("in_context_memory");
24676
+ const wmPlugin = agent.context.memory;
24677
+ if (!icmPlugin && !wmPlugin) {
24678
+ exports.logger.warn("injectRoutineContext: No ICM or WM plugin available \u2014 skipping context injection");
24679
+ return;
24680
+ }
24681
+ const planOverview = buildPlanOverview(execution, definition, currentTask.id);
24682
+ if (icmPlugin) {
24683
+ icmPlugin.set("__routine_plan", "Routine plan overview with task statuses", planOverview, "high");
24684
+ }
24685
+ if (icmPlugin) {
24686
+ for (const entry of icmPlugin.list()) {
24687
+ if (entry.key.startsWith("__dep_result_") || entry.key === "__routine_deps") {
24688
+ icmPlugin.delete(entry.key);
24689
+ }
24690
+ }
24691
+ }
24692
+ if (wmPlugin) {
24693
+ const { entries: wmEntries } = await wmPlugin.query();
24694
+ for (const entry of wmEntries) {
24695
+ if (entry.key.startsWith("__dep_result_") || entry.key.startsWith("findings/__dep_result_")) {
24696
+ await wmPlugin.delete(entry.key);
24697
+ }
24698
+ }
24699
+ }
24700
+ if (currentTask.dependsOn.length === 0) return;
24701
+ const inContextDeps = [];
24702
+ const workingMemoryDeps = [];
24703
+ for (const depId of currentTask.dependsOn) {
24704
+ const depTask = execution.plan.tasks.find((t) => t.id === depId);
24705
+ if (!depTask?.result?.output) continue;
24706
+ const output = typeof depTask.result.output === "string" ? depTask.result.output : JSON.stringify(depTask.result.output);
24707
+ const tokens = estimateTokens(output);
24708
+ const depKey = `__dep_result_${depId}`;
24709
+ const depLabel = `Result from task "${depTask.name}"`;
24710
+ if (tokens < 5e3 && icmPlugin) {
24711
+ icmPlugin.set(depKey, depLabel, output, "high");
24712
+ inContextDeps.push(depTask.name);
24713
+ } else if (wmPlugin) {
24714
+ await wmPlugin.store(depKey, depLabel, output, { tier: "findings" });
24715
+ workingMemoryDeps.push(depTask.name);
24716
+ } else if (icmPlugin) {
24717
+ const truncated = output.slice(0, 2e4) + "\n... (truncated, full result not available)";
24718
+ icmPlugin.set(depKey, depLabel, truncated, "high");
24719
+ inContextDeps.push(depTask.name + " (truncated)");
24720
+ }
24721
+ }
24722
+ if (icmPlugin && (inContextDeps.length > 0 || workingMemoryDeps.length > 0)) {
24723
+ const summaryParts = ["Dependency results available:"];
24724
+ if (inContextDeps.length > 0) {
24725
+ summaryParts.push(`In context (visible now): ${inContextDeps.join(", ")}`);
24726
+ }
24727
+ if (workingMemoryDeps.length > 0) {
24728
+ summaryParts.push(`In working memory (use memory_retrieve): ${workingMemoryDeps.join(", ")}`);
24729
+ }
24730
+ icmPlugin.set("__routine_deps", "Dependency results location guide", summaryParts.join("\n"), "high");
24731
+ }
24732
+ }
24733
+ async function cleanupRoutineContext(agent) {
24734
+ const icmPlugin = agent.context.getPlugin("in_context_memory");
24735
+ const wmPlugin = agent.context.memory;
24736
+ if (icmPlugin) {
24737
+ for (const entry of icmPlugin.list()) {
24738
+ if (entry.key.startsWith("__routine_") || entry.key.startsWith("__dep_result_")) {
24739
+ icmPlugin.delete(entry.key);
24740
+ }
24741
+ }
24742
+ }
24743
+ if (wmPlugin) {
24744
+ const { entries: wmEntries } = await wmPlugin.query();
24745
+ for (const entry of wmEntries) {
24746
+ if (entry.key.startsWith("__dep_result_") || entry.key.startsWith("findings/__dep_result_")) {
24747
+ await wmPlugin.delete(entry.key);
24748
+ }
24749
+ }
24750
+ }
24751
+ }
24017
24752
  async function validateTaskCompletion(agent, task, responseText, validationPromptBuilder) {
24018
24753
  const hasExplicitValidation = task.validation?.skipReflection === false && task.validation?.completionCriteria && task.validation.completionCriteria.length > 0;
24019
24754
  if (!hasExplicitValidation) {
@@ -24150,7 +24885,7 @@ async function executeRoutine(options) {
24150
24885
  execution.lastUpdatedAt = Date.now();
24151
24886
  onTaskStarted?.(execution.plan.tasks[taskIndex], execution);
24152
24887
  let taskCompleted = false;
24153
- const maxTaskIterations = task.execution?.maxIterations ?? 15;
24888
+ const maxTaskIterations = task.execution?.maxIterations ?? 50;
24154
24889
  const iterationLimiter = async (ctx) => {
24155
24890
  if (ctx.iteration >= maxTaskIterations) {
24156
24891
  agent.cancel(`Task "${task.name}" exceeded max iterations (${maxTaskIterations})`);
@@ -24159,6 +24894,7 @@ async function executeRoutine(options) {
24159
24894
  };
24160
24895
  agent.registerHook("pause:check", iterationLimiter);
24161
24896
  const getTask = () => execution.plan.tasks[taskIndex];
24897
+ await injectRoutineContext(agent, execution, definition, getTask());
24162
24898
  while (!taskCompleted) {
24163
24899
  try {
24164
24900
  const taskPrompt = buildTaskPrompt(getTask());
@@ -24261,6 +24997,10 @@ async function executeRoutine(options) {
24261
24997
  );
24262
24998
  return execution;
24263
24999
  } finally {
25000
+ try {
25001
+ await cleanupRoutineContext(agent);
25002
+ } catch {
25003
+ }
24264
25004
  for (const { name, hook } of registeredHooks) {
24265
25005
  try {
24266
25006
  agent.unregisterHook(name, hook);
@@ -38788,6 +39528,42 @@ var StreamHelpers = class {
38788
39528
  }
38789
39529
  return chunks.join("");
38790
39530
  }
39531
+ /**
39532
+ * Get only reasoning/thinking deltas from stream
39533
+ * Filters out all other event types
39534
+ */
39535
+ static async *thinkingOnly(stream) {
39536
+ for await (const event of stream) {
39537
+ if (isReasoningDelta(event)) {
39538
+ yield event.delta;
39539
+ }
39540
+ }
39541
+ }
39542
+ /**
39543
+ * Get both text and thinking deltas from stream
39544
+ * Yields tagged objects so consumers can distinguish them
39545
+ */
39546
+ static async *textAndThinking(stream) {
39547
+ for await (const event of stream) {
39548
+ if (isOutputTextDelta(event)) {
39549
+ yield { type: "text", delta: event.delta };
39550
+ } else if (isReasoningDelta(event)) {
39551
+ yield { type: "thinking", delta: event.delta };
39552
+ }
39553
+ }
39554
+ }
39555
+ /**
39556
+ * Accumulate all thinking/reasoning content from stream into a single string
39557
+ */
39558
+ static async accumulateThinking(stream) {
39559
+ const chunks = [];
39560
+ for await (const event of stream) {
39561
+ if (isReasoningDelta(event)) {
39562
+ chunks.push(event.delta);
39563
+ }
39564
+ }
39565
+ return chunks.join("");
39566
+ }
38791
39567
  /**
38792
39568
  * Buffer stream events into batches
38793
39569
  */
@@ -38847,6 +39623,11 @@ var StreamHelpers = class {
38847
39623
  case "response.output_text.delta" /* OUTPUT_TEXT_DELTA */:
38848
39624
  state.accumulateTextDelta(event.item_id, event.delta);
38849
39625
  break;
39626
+ case "response.reasoning.delta" /* REASONING_DELTA */:
39627
+ state.accumulateReasoningDelta(event.item_id, event.delta);
39628
+ break;
39629
+ case "response.reasoning.done" /* REASONING_DONE */:
39630
+ break;
38850
39631
  case "response.tool_call.start" /* TOOL_CALL_START */:
38851
39632
  state.startToolCall(event.tool_call_id, event.tool_name);
38852
39633
  break;
@@ -38877,21 +39658,36 @@ var StreamHelpers = class {
38877
39658
  */
38878
39659
  static reconstructLLMResponse(state) {
38879
39660
  const output = [];
39661
+ const contentParts = [];
39662
+ let thinkingText;
39663
+ if (state.hasReasoning()) {
39664
+ const reasoning = state.getAllReasoning();
39665
+ if (reasoning) {
39666
+ thinkingText = reasoning;
39667
+ contentParts.push({
39668
+ type: "thinking" /* THINKING */,
39669
+ thinking: reasoning,
39670
+ persistInHistory: false
39671
+ // Vendor-agnostic default; caller can adjust
39672
+ });
39673
+ }
39674
+ }
38880
39675
  if (state.hasText()) {
38881
39676
  const textContent = state.getAllText();
38882
39677
  if (textContent) {
38883
- output.push({
38884
- type: "message",
38885
- role: "assistant" /* ASSISTANT */,
38886
- content: [
38887
- {
38888
- type: "output_text" /* OUTPUT_TEXT */,
38889
- text: textContent
38890
- }
38891
- ]
39678
+ contentParts.push({
39679
+ type: "output_text" /* OUTPUT_TEXT */,
39680
+ text: textContent
38892
39681
  });
38893
39682
  }
38894
39683
  }
39684
+ if (contentParts.length > 0) {
39685
+ output.push({
39686
+ type: "message",
39687
+ role: "assistant" /* ASSISTANT */,
39688
+ content: contentParts
39689
+ });
39690
+ }
38895
39691
  const toolCalls = state.getCompletedToolCalls();
38896
39692
  if (toolCalls.length > 0) {
38897
39693
  const toolUseContent = toolCalls.map((tc) => ({
@@ -38920,6 +39716,7 @@ var StreamHelpers = class {
38920
39716
  model: state.model,
38921
39717
  output,
38922
39718
  output_text: outputText,
39719
+ thinking: thinkingText,
38923
39720
  usage: state.usage
38924
39721
  };
38925
39722
  }
@@ -50368,6 +51165,7 @@ exports.findConnectorByServiceTypes = findConnectorByServiceTypes;
50368
51165
  exports.forPlan = forPlan;
50369
51166
  exports.forTasks = forTasks;
50370
51167
  exports.formatAttendees = formatAttendees;
51168
+ exports.formatPluginDisplayName = formatPluginDisplayName;
50371
51169
  exports.formatRecipients = formatRecipients;
50372
51170
  exports.generateEncryptionKey = generateEncryptionKey;
50373
51171
  exports.generateSimplePlan = generateSimplePlan;
@@ -50436,6 +51234,8 @@ exports.isErrorEvent = isErrorEvent;
50436
51234
  exports.isExcludedExtension = isExcludedExtension;
50437
51235
  exports.isKnownService = isKnownService;
50438
51236
  exports.isOutputTextDelta = isOutputTextDelta;
51237
+ exports.isReasoningDelta = isReasoningDelta;
51238
+ exports.isReasoningDone = isReasoningDone;
50439
51239
  exports.isResponseComplete = isResponseComplete;
50440
51240
  exports.isSimpleScope = isSimpleScope;
50441
51241
  exports.isStreamEvent = isStreamEvent;