morpheus-cli 0.9.51 → 0.9.52

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.
@@ -150,6 +150,10 @@ export class Oracle {
150
150
  }
151
151
  return valid;
152
152
  }
153
+ isGeminiToolHistoryError(err) {
154
+ const msg = String(err?.message ?? err ?? '').toLowerCase();
155
+ return msg.includes('function response turn') || msg.includes('function call turn');
156
+ }
153
157
  hasDelegationToolCall(messages) {
154
158
  const delegationTools = SubagentRegistry.getDelegationToolNames();
155
159
  // Also include smith_delegate which may not be in registry if smiths are disabled
@@ -505,7 +509,7 @@ ${SmithRegistry.getInstance().getSystemPromptSection()}
505
509
  // Fail open - do not disrupt main flow
506
510
  this.display.log(`Sati memory retrieval failed: ${e.message}`, { source: 'Sati' });
507
511
  }
508
- const messages = [
512
+ let messages = [
509
513
  systemMessage
510
514
  ];
511
515
  if (memoryMessage) {
@@ -533,12 +537,37 @@ Use it to inform your response and tool selection (if needed), but do not assume
533
537
  const oracleStartMs = Date.now();
534
538
  const display = DisplayManager.getInstance();
535
539
  display.startActivity('oracle', `LLM call (${this.config.llm.model})`);
536
- const response = await TaskRequestContext.run(invokeContext, async () => {
537
- const agentResponse = await this.provider.invoke({ messages }, { recursionLimit: 100 });
538
- contextDelegationAcks = TaskRequestContext.getDelegationAcks();
539
- syncDelegationCount = TaskRequestContext.getSyncDelegationCount();
540
- return agentResponse;
541
- });
540
+ // eslint-disable-next-line prefer-const
541
+ let response;
542
+ try {
543
+ response = await TaskRequestContext.run(invokeContext, async () => {
544
+ const agentResponse = await this.provider.invoke({ messages }, { recursionLimit: 100 });
545
+ contextDelegationAcks = TaskRequestContext.getDelegationAcks();
546
+ syncDelegationCount = TaskRequestContext.getSyncDelegationCount();
547
+ return agentResponse;
548
+ });
549
+ }
550
+ catch (invokeErr) {
551
+ if (this.isGeminiToolHistoryError(invokeErr)) {
552
+ // Gemini rejects histories that contain tool-call/response pairs from previous turns.
553
+ // Strip all AIMessages with tool_calls and ToolMessages, keep only text messages, and retry.
554
+ this.display.log('Gemini rejected tool-call history. Retrying with stripped history.', { source: 'Oracle', level: 'warning' });
555
+ const cleanPrevious = previousMessages.filter((m) => !(m instanceof ToolMessage) &&
556
+ !(m instanceof AIMessage && (m.tool_calls?.length ?? 0) > 0));
557
+ messages = [systemMessage, ...cleanPrevious, userMessage];
558
+ contextDelegationAcks = [];
559
+ syncDelegationCount = 0;
560
+ response = await TaskRequestContext.run(invokeContext, async () => {
561
+ const agentResponse = await this.provider.invoke({ messages }, { recursionLimit: 100 });
562
+ contextDelegationAcks = TaskRequestContext.getDelegationAcks();
563
+ syncDelegationCount = TaskRequestContext.getSyncDelegationCount();
564
+ return agentResponse;
565
+ });
566
+ }
567
+ else {
568
+ throw invokeErr;
569
+ }
570
+ }
542
571
  const oracleDurationMs = Date.now() - oracleStartMs;
543
572
  display.endActivity('oracle', true);
544
573
  // Emit llm_call audit event for Oracle's own invocation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "morpheus-cli",
3
- "version": "0.9.51",
3
+ "version": "0.9.52",
4
4
  "description": "Morpheus is a local AI agent for developers, running as a CLI daemon that connects to LLMs, local tools, and MCPs, enabling interaction via Terminal, Telegram, and Discord. Inspired by the character Morpheus from *The Matrix*, the project acts as an intelligent orchestrator, bridging the gap between the developer and complex systems.",
5
5
  "bin": {
6
6
  "morpheus": "./bin/morpheus.js"