@framers/agentos 0.10.22 → 0.10.24
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/README.md +1 -1
- package/dist/api/AgentOS.d.ts.map +1 -1
- package/dist/api/AgentOS.js +3 -2
- package/dist/api/AgentOS.js.map +1 -1
- package/dist/api/agent.d.ts.map +1 -1
- package/dist/api/agent.js +25 -10
- package/dist/api/agent.js.map +1 -1
- package/dist/api/embedText.d.ts.map +1 -1
- package/dist/api/embedText.js +53 -17
- package/dist/api/embedText.js.map +1 -1
- package/dist/api/generateImage.d.ts.map +1 -1
- package/dist/api/generateImage.js +51 -7
- package/dist/api/generateImage.js.map +1 -1
- package/dist/api/generateText.d.ts +50 -7
- package/dist/api/generateText.d.ts.map +1 -1
- package/dist/api/generateText.js +265 -35
- package/dist/api/generateText.js.map +1 -1
- package/dist/api/model.d.ts +25 -1
- package/dist/api/model.d.ts.map +1 -1
- package/dist/api/model.js +108 -3
- package/dist/api/model.js.map +1 -1
- package/dist/api/runtime/SelfImprovementSessionManager.d.ts +34 -2
- package/dist/api/runtime/SelfImprovementSessionManager.d.ts.map +1 -1
- package/dist/api/runtime/SelfImprovementSessionManager.js +119 -33
- package/dist/api/runtime/SelfImprovementSessionManager.js.map +1 -1
- package/dist/api/runtime/global-default.d.ts +9 -1
- package/dist/api/runtime/global-default.d.ts.map +1 -1
- package/dist/api/runtime/global-default.js.map +1 -1
- package/dist/api/runtime/provider-defaults.d.ts.map +1 -1
- package/dist/api/runtime/provider-defaults.js +10 -4
- package/dist/api/runtime/provider-defaults.js.map +1 -1
- package/dist/api/runtime/tool-emulation/history.d.ts +16 -0
- package/dist/api/runtime/tool-emulation/history.d.ts.map +1 -0
- package/dist/api/runtime/tool-emulation/history.js +89 -0
- package/dist/api/runtime/tool-emulation/history.js.map +1 -0
- package/dist/api/runtime/tool-emulation/index.d.ts +1 -0
- package/dist/api/runtime/tool-emulation/index.d.ts.map +1 -1
- package/dist/api/runtime/tool-emulation/index.js +1 -0
- package/dist/api/runtime/tool-emulation/index.js.map +1 -1
- package/dist/api/runtime/tool-emulation/loop.d.ts +6 -0
- package/dist/api/runtime/tool-emulation/loop.d.ts.map +1 -1
- package/dist/api/runtime/tool-emulation/loop.js +1 -0
- package/dist/api/runtime/tool-emulation/loop.js.map +1 -1
- package/dist/api/sessionTranscript.d.ts +34 -0
- package/dist/api/sessionTranscript.d.ts.map +1 -1
- package/dist/api/sessionTranscript.js +61 -1
- package/dist/api/sessionTranscript.js.map +1 -1
- package/dist/api/streamText.d.ts.map +1 -1
- package/dist/api/streamText.js +120 -24
- package/dist/api/streamText.js.map +1 -1
- package/dist/api/types/AgentOSInput.d.ts +11 -0
- package/dist/api/types/AgentOSInput.d.ts.map +1 -1
- package/dist/api/types.d.ts +14 -6
- package/dist/api/types.d.ts.map +1 -1
- package/dist/api/types.js.map +1 -1
- package/dist/cognition/emergent/AdaptPersonalityTool.d.ts +13 -4
- package/dist/cognition/emergent/AdaptPersonalityTool.d.ts.map +1 -1
- package/dist/cognition/emergent/AdaptPersonalityTool.js +32 -23
- package/dist/cognition/emergent/AdaptPersonalityTool.js.map +1 -1
- package/dist/cognition/emergent/EmergentCapabilityEngine.d.ts +18 -6
- package/dist/cognition/emergent/EmergentCapabilityEngine.d.ts.map +1 -1
- package/dist/cognition/emergent/EmergentCapabilityEngine.js.map +1 -1
- package/dist/cognition/emergent/SelfEvaluateTool.d.ts +10 -3
- package/dist/cognition/emergent/SelfEvaluateTool.d.ts.map +1 -1
- package/dist/cognition/emergent/SelfEvaluateTool.js +3 -2
- package/dist/cognition/emergent/SelfEvaluateTool.js.map +1 -1
- package/dist/cognition/substrate/CognitiveMemoryBridge.d.ts +51 -2
- package/dist/cognition/substrate/CognitiveMemoryBridge.d.ts.map +1 -1
- package/dist/cognition/substrate/CognitiveMemoryBridge.js +84 -2
- package/dist/cognition/substrate/CognitiveMemoryBridge.js.map +1 -1
- package/dist/cognition/substrate/ConversationHistoryManager.d.ts +8 -4
- package/dist/cognition/substrate/ConversationHistoryManager.d.ts.map +1 -1
- package/dist/cognition/substrate/ConversationHistoryManager.js +17 -5
- package/dist/cognition/substrate/ConversationHistoryManager.js.map +1 -1
- package/dist/cognition/substrate/GMI.d.ts +92 -5
- package/dist/cognition/substrate/GMI.d.ts.map +1 -1
- package/dist/cognition/substrate/GMI.js +291 -65
- package/dist/cognition/substrate/GMI.js.map +1 -1
- package/dist/cognition/substrate/GMIManager.d.ts +12 -0
- package/dist/cognition/substrate/GMIManager.d.ts.map +1 -1
- package/dist/cognition/substrate/GMIManager.js +22 -16
- package/dist/cognition/substrate/GMIManager.js.map +1 -1
- package/dist/cognition/substrate/IGMI.d.ts +23 -0
- package/dist/cognition/substrate/IGMI.d.ts.map +1 -1
- package/dist/cognition/substrate/IGMI.js.map +1 -1
- package/dist/cognition/substrate/MetapromptExecutor.d.ts +183 -28
- package/dist/cognition/substrate/MetapromptExecutor.d.ts.map +1 -1
- package/dist/cognition/substrate/MetapromptExecutor.js +431 -108
- package/dist/cognition/substrate/MetapromptExecutor.js.map +1 -1
- package/dist/cognition/substrate/personas/IPersonaDefinition.d.ts +5 -0
- package/dist/cognition/substrate/personas/IPersonaDefinition.d.ts.map +1 -1
- package/dist/cognition/substrate/personas/PersonaValidation.d.ts.map +1 -1
- package/dist/cognition/substrate/personas/PersonaValidation.js +30 -0
- package/dist/cognition/substrate/personas/PersonaValidation.js.map +1 -1
- package/dist/cognition/substrate/personas/SoulLoader.d.ts +14 -1
- package/dist/cognition/substrate/personas/SoulLoader.d.ts.map +1 -1
- package/dist/cognition/substrate/personas/SoulLoader.js +45 -12
- package/dist/cognition/substrate/personas/SoulLoader.js.map +1 -1
- package/dist/cognition/substrate/personas/definitions/default_assistant_persona.json +3 -35
- package/dist/cognition/substrate/personas/hexaco.d.ts +34 -0
- package/dist/cognition/substrate/personas/hexaco.d.ts.map +1 -0
- package/dist/cognition/substrate/personas/hexaco.js +66 -0
- package/dist/cognition/substrate/personas/hexaco.js.map +1 -0
- package/dist/cognition/substrate/userFeedback.d.ts +69 -0
- package/dist/cognition/substrate/userFeedback.d.ts.map +1 -0
- package/dist/cognition/substrate/userFeedback.js +107 -0
- package/dist/cognition/substrate/userFeedback.js.map +1 -0
- package/dist/core/conversation/ConversationMessage.d.ts +9 -0
- package/dist/core/conversation/ConversationMessage.d.ts.map +1 -1
- package/dist/core/conversation/ConversationMessage.js.map +1 -1
- package/dist/core/llm/IPromptEngine.d.ts +9 -0
- package/dist/core/llm/IPromptEngine.d.ts.map +1 -1
- package/dist/core/llm/IPromptEngine.js.map +1 -1
- package/dist/core/llm/PromptEngine.d.ts +30 -1
- package/dist/core/llm/PromptEngine.d.ts.map +1 -1
- package/dist/core/llm/PromptEngine.js +229 -92
- package/dist/core/llm/PromptEngine.js.map +1 -1
- package/dist/core/llm/providers/AIModelProviderManager.d.ts +20 -0
- package/dist/core/llm/providers/AIModelProviderManager.d.ts.map +1 -1
- package/dist/core/llm/providers/AIModelProviderManager.js +35 -5
- package/dist/core/llm/providers/AIModelProviderManager.js.map +1 -1
- package/dist/core/llm/providers/IProvider.d.ts +28 -8
- package/dist/core/llm/providers/IProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/AnthropicProvider.d.ts +135 -49
- package/dist/core/llm/providers/implementations/AnthropicProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/AnthropicProvider.js +323 -114
- package/dist/core/llm/providers/implementations/AnthropicProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/ClaudeCodeProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/ClaudeCodeProvider.js +15 -1
- package/dist/core/llm/providers/implementations/ClaudeCodeProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/GeminiCLIProvider.d.ts +1 -1
- package/dist/core/llm/providers/implementations/GeminiCLIProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/GeminiCLIProvider.js +51 -24
- package/dist/core/llm/providers/implementations/GeminiCLIProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/GeminiProvider.d.ts +25 -6
- package/dist/core/llm/providers/implementations/GeminiProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/GeminiProvider.js +108 -90
- package/dist/core/llm/providers/implementations/GeminiProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/MistralProvider.d.ts +11 -0
- package/dist/core/llm/providers/implementations/MistralProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/MistralProvider.js +32 -2
- package/dist/core/llm/providers/implementations/MistralProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/OllamaProvider.js +7 -7
- package/dist/core/llm/providers/implementations/OllamaProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/OpenAIProvider.d.ts +53 -2
- package/dist/core/llm/providers/implementations/OpenAIProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/OpenAIProvider.js +84 -17
- package/dist/core/llm/providers/implementations/OpenAIProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/OpenRouterProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/OpenRouterProvider.js +8 -3
- package/dist/core/llm/providers/implementations/OpenRouterProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/TogetherProvider.d.ts +3 -3
- package/dist/core/llm/providers/implementations/TogetherProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/TogetherProvider.js +25 -13
- package/dist/core/llm/providers/implementations/TogetherProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/cacheLeakDetector.d.ts +15 -7
- package/dist/core/llm/providers/implementations/cacheLeakDetector.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/cacheLeakDetector.js +12 -7
- package/dist/core/llm/providers/implementations/cacheLeakDetector.js.map +1 -1
- package/dist/core/llm/providers/model-cache-capabilities.d.ts +24 -9
- package/dist/core/llm/providers/model-cache-capabilities.d.ts.map +1 -1
- package/dist/core/llm/providers/model-cache-capabilities.js +59 -44
- package/dist/core/llm/providers/model-cache-capabilities.js.map +1 -1
- package/dist/core/llm/providers/model-effort.d.ts +14 -0
- package/dist/core/llm/providers/model-effort.d.ts.map +1 -1
- package/dist/core/llm/providers/model-effort.js +22 -0
- package/dist/core/llm/providers/model-effort.js.map +1 -1
- package/dist/core/llm/providers/model-forced-tool-choice.d.ts +13 -6
- package/dist/core/llm/providers/model-forced-tool-choice.d.ts.map +1 -1
- package/dist/core/llm/providers/model-forced-tool-choice.js +14 -7
- package/dist/core/llm/providers/model-forced-tool-choice.js.map +1 -1
- package/dist/core/llm/providers/model-thinking.d.ts +64 -13
- package/dist/core/llm/providers/model-thinking.d.ts.map +1 -1
- package/dist/core/llm/providers/model-thinking.js +52 -12
- package/dist/core/llm/providers/model-thinking.js.map +1 -1
- package/dist/core/llm/providers/openrouter-only-params.d.ts +26 -7
- package/dist/core/llm/providers/openrouter-only-params.d.ts.map +1 -1
- package/dist/core/llm/providers/openrouter-only-params.js +58 -9
- package/dist/core/llm/providers/openrouter-only-params.js.map +1 -1
- package/dist/core/llm/providers/url-secrets.d.ts +42 -0
- package/dist/core/llm/providers/url-secrets.d.ts.map +1 -0
- package/dist/core/llm/providers/url-secrets.js +64 -0
- package/dist/core/llm/providers/url-secrets.js.map +1 -0
- package/dist/core/llm/streaming/StreamingBatcher.d.ts +4 -3
- package/dist/core/llm/streaming/StreamingBatcher.d.ts.map +1 -1
- package/dist/core/llm/streaming/StreamingBatcher.js +8 -3
- package/dist/core/llm/streaming/StreamingBatcher.js.map +1 -1
- package/dist/core/safety/LLMProviderHealthRegistry.d.ts +4 -0
- package/dist/core/safety/LLMProviderHealthRegistry.d.ts.map +1 -1
- package/dist/core/safety/LLMProviderHealthRegistry.js +26 -0
- package/dist/core/safety/LLMProviderHealthRegistry.js.map +1 -1
- package/dist/core/utils/sha256.d.ts +19 -0
- package/dist/core/utils/sha256.d.ts.map +1 -0
- package/dist/core/utils/sha256.js +101 -0
- package/dist/core/utils/sha256.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/orchestration/pipeline/query/types.js +3 -3
- package/dist/orchestration/pipeline/query/types.js.map +1 -1
- package/dist/orchestration/planning/ProviderAssignmentEngine.js +2 -2
- package/dist/orchestration/planning/ProviderAssignmentEngine.js.map +1 -1
- package/package.json +1 -1
|
@@ -21,6 +21,7 @@ import { ConversationHistoryManager } from './ConversationHistoryManager.js';
|
|
|
21
21
|
import { CognitiveMemoryBridge } from './CognitiveMemoryBridge.js';
|
|
22
22
|
import { SentimentTracker } from './SentimentTracker.js';
|
|
23
23
|
import { MetapromptExecutor } from './MetapromptExecutor.js';
|
|
24
|
+
import { feedbackTraceMessage } from './userFeedback.js';
|
|
24
25
|
const DEFAULT_MAX_CONVERSATION_HISTORY_TURNS = 20;
|
|
25
26
|
const DEFAULT_SELF_REFLECTION_INTERVAL_TURNS = 5;
|
|
26
27
|
const MAX_REASONING_TRACE_ENTRIES = 500; // Limit trace size in memory
|
|
@@ -38,6 +39,14 @@ export class GMI {
|
|
|
38
39
|
*/
|
|
39
40
|
constructor(gmiId) {
|
|
40
41
|
this.isInitialized = false; // Maintained as per user-provided GMI.ts
|
|
42
|
+
/**
|
|
43
|
+
* Turn ownership. Each processTurnStream call takes the next number and
|
|
44
|
+
* owns the lifecycle state until a newer turn starts; a turn that no longer
|
|
45
|
+
* owns it (a failed turn whose generator is drained after the next turn
|
|
46
|
+
* began) leaves the state and the trace's turn id to the newer turn.
|
|
47
|
+
*/
|
|
48
|
+
this.turnSequence = 0;
|
|
49
|
+
this.stateOwnerTurn = 0;
|
|
41
50
|
// (Self-reflection state is owned by MetapromptExecutor)
|
|
42
51
|
// Cognitive Memory Bridge
|
|
43
52
|
this.memoryBridge = null;
|
|
@@ -237,6 +246,57 @@ export class GMI {
|
|
|
237
246
|
getCognitiveMemoryManager() {
|
|
238
247
|
return this.cognitiveMemory;
|
|
239
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* Records user feedback on this instance. Adds a reasoning-trace entry
|
|
251
|
+
* (WARNING for negative feedback, DEBUG otherwise) and, when cognitive memory
|
|
252
|
+
* is configured, encodes the feedback as an episodic memory of the user. A
|
|
253
|
+
* correction is also encoded as a semantic memory so later turns can recall
|
|
254
|
+
* it. Memory failures are traced by the bridge and never thrown.
|
|
255
|
+
*
|
|
256
|
+
* @param feedback - Normalized feedback plus the id of the user who sent it.
|
|
257
|
+
*/
|
|
258
|
+
async recordUserFeedback(feedback) {
|
|
259
|
+
const { userId, polarity, score, text, correctedContent, targetMessageId, tags } = feedback;
|
|
260
|
+
this.addTraceEntry(polarity === 'negative' ? ReasoningEntryType.WARNING : ReasoningEntryType.DEBUG, feedbackTraceMessage(polarity), { userId, polarity, score, text, correctedContent, targetMessageId, tags });
|
|
261
|
+
// An empty user id falls back to the bridge's default scope (the current user).
|
|
262
|
+
const scopeId = typeof userId === 'string' && userId.trim() ? userId.trim() : undefined;
|
|
263
|
+
const scoreLabel = score !== undefined ? `, score ${score}` : '';
|
|
264
|
+
await this.memoryBridge?.encode(`User feedback (${polarity}${scoreLabel})${text ? `: ${text}` : ''}`, {
|
|
265
|
+
type: 'episodic',
|
|
266
|
+
sourceType: 'user_statement',
|
|
267
|
+
role: 'user',
|
|
268
|
+
scopeId,
|
|
269
|
+
tags: ['user_feedback', `feedback_${polarity}`, ...(tags ?? [])],
|
|
270
|
+
});
|
|
271
|
+
if (correctedContent) {
|
|
272
|
+
const target = targetMessageId ? ` for message ${targetMessageId}` : '';
|
|
273
|
+
await this.memoryBridge?.encode(`User correction${target}: ${correctedContent}`, {
|
|
274
|
+
type: 'semantic',
|
|
275
|
+
sourceType: 'user_statement',
|
|
276
|
+
role: 'user',
|
|
277
|
+
scopeId,
|
|
278
|
+
tags: ['user_feedback', 'user_correction'],
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Sets one personality trait on this instance only. The persona definition
|
|
284
|
+
* is shared by every GMI of that persona (it is the GMIManager registry
|
|
285
|
+
* object), so the change is made on a copy that replaces this instance's
|
|
286
|
+
* active persona; other sessions and GMIs created later keep the original.
|
|
287
|
+
*
|
|
288
|
+
* @param trait - Trait key, e.g. `openness` or `honesty`.
|
|
289
|
+
* @param value - New trait value.
|
|
290
|
+
* @throws {GMIError} When the GMI has not been initialized.
|
|
291
|
+
*/
|
|
292
|
+
setPersonalityTrait(trait, value) {
|
|
293
|
+
const persona = this.getPersona();
|
|
294
|
+
this.activePersona = {
|
|
295
|
+
...persona,
|
|
296
|
+
personalityTraits: { ...(persona.personalityTraits ?? {}), [trait]: value },
|
|
297
|
+
};
|
|
298
|
+
this.addTraceEntry(ReasoningEntryType.STATE_CHANGE, `Personality trait '${trait}' set to ${value}.`, { trait, value });
|
|
299
|
+
}
|
|
240
300
|
/**
|
|
241
301
|
* Adds an entry to the GMI's reasoning trace.
|
|
242
302
|
* @private
|
|
@@ -282,6 +342,33 @@ export class GMI {
|
|
|
282
342
|
: '';
|
|
283
343
|
return organizationId || undefined;
|
|
284
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Error results for the calls of a tool round that produced none: the call
|
|
347
|
+
* that was running when the round failed and the calls not yet started.
|
|
348
|
+
* Recording them leaves a history in which every tool call the assistant
|
|
349
|
+
* message declared has an answer, which the next request needs (providers
|
|
350
|
+
* reject an unanswered tool call, and a later turn replays this history).
|
|
351
|
+
*
|
|
352
|
+
* @param requests - Every call the round's assistant message declared, in order.
|
|
353
|
+
* @param finishedCount - How many of them already produced a result.
|
|
354
|
+
* @param inFlight - The call that was running when the round failed, if any.
|
|
355
|
+
* @param error - Why the round stopped.
|
|
356
|
+
* @returns One error result per unanswered call.
|
|
357
|
+
*/
|
|
358
|
+
resultsForUnfinishedToolCalls(requests, finishedCount, inFlight, error) {
|
|
359
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
360
|
+
return requests.slice(finishedCount).map((request) => ({
|
|
361
|
+
toolCallId: request.id,
|
|
362
|
+
toolName: request.name,
|
|
363
|
+
output: undefined,
|
|
364
|
+
isError: true,
|
|
365
|
+
errorDetails: {
|
|
366
|
+
message: request === inFlight
|
|
367
|
+
? `Tool '${request.name}' failed: ${reason}`
|
|
368
|
+
: `Tool '${request.name}' was not run because the tool round stopped: ${reason}`,
|
|
369
|
+
},
|
|
370
|
+
}));
|
|
371
|
+
}
|
|
285
372
|
buildToolSessionData(turnInput) {
|
|
286
373
|
const sessionId = typeof turnInput.sessionId === 'string' ? turnInput.sessionId.trim() : '';
|
|
287
374
|
const conversationId = this.getConversationIdForTurn(turnInput);
|
|
@@ -299,15 +386,17 @@ export class GMI {
|
|
|
299
386
|
return Object.keys(sessionData).length > 0 ? sessionData : undefined;
|
|
300
387
|
}
|
|
301
388
|
/**
|
|
302
|
-
* Ensures the GMI is initialized and
|
|
389
|
+
* Ensures the GMI is initialized and idle: READY, or ERRORED after a failed
|
|
390
|
+
* turn. ERRORED only records that the last turn failed; the instance still
|
|
391
|
+
* works, so it does not block the next turn or the memory callbacks.
|
|
303
392
|
* @private
|
|
304
393
|
*/
|
|
305
394
|
ensureReady(additionallyAllowedStates = []) {
|
|
306
395
|
if (!this.isInitialized) {
|
|
307
396
|
throw new GMIError(`GMI (ID: ${this.gmiId}) is not initialized.`, GMIErrorCode.NOT_INITIALIZED);
|
|
308
397
|
}
|
|
309
|
-
|
|
310
|
-
|
|
398
|
+
const isIdle = this.state === GMIPrimeState.READY || this.state === GMIPrimeState.ERRORED;
|
|
399
|
+
if (!isIdle && !additionallyAllowedStates.includes(this.state)) {
|
|
311
400
|
throw new GMIError(`GMI (ID: ${this.gmiId}) is not in READY state. Current state: ${this.state}.`, GMIErrorCode.INVALID_STATE, { currentGMIState: this.state });
|
|
312
401
|
}
|
|
313
402
|
}
|
|
@@ -359,6 +448,58 @@ export class GMI {
|
|
|
359
448
|
};
|
|
360
449
|
return context;
|
|
361
450
|
}
|
|
451
|
+
/**
|
|
452
|
+
* Assembles the conversation history and user input for one model call of
|
|
453
|
+
* a turn.
|
|
454
|
+
*
|
|
455
|
+
* The history is the conversation before this turn, then this turn's own
|
|
456
|
+
* messages. The conversation before the turn is the host's durable history
|
|
457
|
+
* (`metadata.conversationHistoryForPrompt`) when the host passed a non-empty
|
|
458
|
+
* one, which ends before the current user message; otherwise it is this
|
|
459
|
+
* GMI's history as the turn found it, without the user message the turn
|
|
460
|
+
* recorded. The turn's own messages are that user message and the assistant
|
|
461
|
+
* replies and tool results of earlier calls in the turn, so a tool round's
|
|
462
|
+
* calls and results reach the next call on either history.
|
|
463
|
+
*
|
|
464
|
+
* On a turn's first call, plain text input travels as `userInput`, which the
|
|
465
|
+
* chat template places last and attaches retrieved context to; the durable
|
|
466
|
+
* path has always sent it that way. Structured (multimodal) input stays a
|
|
467
|
+
* history message, so its parts reach the provider intact and only once.
|
|
468
|
+
*
|
|
469
|
+
* @param turn - Where the turn's messages come from.
|
|
470
|
+
* @param turn.durableHistory - The host's history before this turn, or
|
|
471
|
+
* `null` to use this GMI's own history.
|
|
472
|
+
* @param turn.historyAtTurnStart - This GMI's history once the turn input
|
|
473
|
+
* was recorded.
|
|
474
|
+
* @param turn.currentUserMessage - The user message the turn input added,
|
|
475
|
+
* when the turn is user-initiated.
|
|
476
|
+
* @param turn.turnMessages - Assistant replies and tool results the turn has
|
|
477
|
+
* added so far.
|
|
478
|
+
* @returns The `conversationHistory` and `userInput` prompt components,
|
|
479
|
+
* and how many history messages belong to this turn (token budgeting
|
|
480
|
+
* leaves those whole).
|
|
481
|
+
*/
|
|
482
|
+
buildPromptConversation(turn) {
|
|
483
|
+
const { durableHistory, historyAtTurnStart, currentUserMessage, turnMessages } = turn;
|
|
484
|
+
const toConversationMessage = (message) => this.conversationHistoryManager.convertToConversationMessage(message);
|
|
485
|
+
const historyBeforeTurn = durableHistory ??
|
|
486
|
+
historyAtTurnStart
|
|
487
|
+
.filter((message) => message !== currentUserMessage)
|
|
488
|
+
.map(toConversationMessage);
|
|
489
|
+
const userContent = currentUserMessage?.content;
|
|
490
|
+
const userText = turnMessages.length === 0 && typeof userContent === 'string' && userContent !== ''
|
|
491
|
+
? userContent
|
|
492
|
+
: null;
|
|
493
|
+
const turnHistory = [
|
|
494
|
+
...(currentUserMessage && userText === null ? [currentUserMessage] : []),
|
|
495
|
+
...turnMessages,
|
|
496
|
+
];
|
|
497
|
+
return {
|
|
498
|
+
conversationHistory: [...historyBeforeTurn, ...turnHistory.map(toConversationMessage)],
|
|
499
|
+
userInput: userText,
|
|
500
|
+
currentTurnMessageCount: turnHistory.length,
|
|
501
|
+
};
|
|
502
|
+
}
|
|
362
503
|
/**
|
|
363
504
|
* Determines if RAG retrieval should be triggered based on the current query and persona configuration.
|
|
364
505
|
* @private
|
|
@@ -385,19 +526,19 @@ export class GMI {
|
|
|
385
526
|
return false;
|
|
386
527
|
}
|
|
387
528
|
/**
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
*
|
|
391
|
-
*
|
|
529
|
+
* Returns the PromptEngine template GMI builds its prompts with.
|
|
530
|
+
*
|
|
531
|
+
* GMI hands the constructed prompt to `IProvider.generateCompletionStream`,
|
|
532
|
+
* whose input is an OpenAI-style `ChatMessage[]` for every provider; each
|
|
533
|
+
* provider converts that array to its own wire format (Anthropic messages
|
|
534
|
+
* with a separate system field, Gemini contents with a systemInstruction).
|
|
535
|
+
* A provider-specific template would hand the provider another shape; the
|
|
536
|
+
* `anthropic_messages` template, for one, returns an object with the
|
|
537
|
+
* system prompt split out, which AnthropicProvider cannot iterate.
|
|
538
|
+
*
|
|
539
|
+
* @returns Always `'openai_chat'`.
|
|
392
540
|
*/
|
|
393
|
-
determinePromptFormat(
|
|
394
|
-
const pid = (modelDetails?.providerId || providerId || '').toLowerCase();
|
|
395
|
-
if (pid.includes('anthropic'))
|
|
396
|
-
return 'anthropic_messages';
|
|
397
|
-
if (pid.includes('google') || pid.includes('gemini'))
|
|
398
|
-
return 'google_gemini';
|
|
399
|
-
if (pid.includes('cohere'))
|
|
400
|
-
return 'cohere_chat';
|
|
541
|
+
determinePromptFormat() {
|
|
401
542
|
return 'openai_chat';
|
|
402
543
|
}
|
|
403
544
|
/**
|
|
@@ -420,7 +561,14 @@ export class GMI {
|
|
|
420
561
|
? [GMIPrimeState.PROCESSING, GMIPrimeState.AWAITING_TOOL_RESULT]
|
|
421
562
|
: [];
|
|
422
563
|
this.ensureReady(continuationAllowedStates);
|
|
564
|
+
if (this.state === GMIPrimeState.ERRORED) {
|
|
565
|
+
this.addTraceEntry(ReasoningEntryType.WARNING, 'Previous turn failed; starting a new turn.');
|
|
566
|
+
}
|
|
423
567
|
this.state = GMIPrimeState.PROCESSING;
|
|
568
|
+
const turnNumber = ++this.turnSequence;
|
|
569
|
+
this.stateOwnerTurn = turnNumber;
|
|
570
|
+
// False once a newer turn has started; lifecycle writes below check it.
|
|
571
|
+
const ownsState = () => this.stateOwnerTurn === turnNumber;
|
|
424
572
|
const turnId = turnInput.interactionId || `turn-${uuidv4()}`;
|
|
425
573
|
// Store turnId on reasoningTrace for current turn
|
|
426
574
|
if (this.reasoningTrace) {
|
|
@@ -463,7 +611,23 @@ export class GMI {
|
|
|
463
611
|
const maxHistoryMessages = this.activePersona.conversationContextConfig?.maxMessages ||
|
|
464
612
|
this.activePersona.memoryConfig?.conversationContext?.maxMessages ||
|
|
465
613
|
DEFAULT_MAX_CONVERSATION_HISTORY_TURNS;
|
|
614
|
+
const messagesBeforeInput = new Set(this.conversationHistoryManager.history);
|
|
466
615
|
this.conversationHistoryManager.update(turnInput, maxHistoryMessages);
|
|
616
|
+
// The turn's prompt sources: this GMI's history once the input is
|
|
617
|
+
// recorded, the user message the input added (user-initiated turns
|
|
618
|
+
// only), the host's durable history when it passed one, and the
|
|
619
|
+
// assistant replies and tool results the loop below adds.
|
|
620
|
+
const historyAtTurnStart = [...this.conversationHistoryManager.history];
|
|
621
|
+
const currentUserMessage = historyAtTurnStart.find((message) => message.role === 'user' && !messagesBeforeInput.has(message));
|
|
622
|
+
const currentTurnText = currentUserMessage?.content
|
|
623
|
+
? (typeof currentUserMessage.content === 'string'
|
|
624
|
+
? currentUserMessage.content
|
|
625
|
+
: JSON.stringify(currentUserMessage.content))
|
|
626
|
+
: '';
|
|
627
|
+
const durableHistoryForPrompt = Array.isArray(turnInput.metadata?.conversationHistoryForPrompt) && turnInput.metadata?.conversationHistoryForPrompt.length > 0
|
|
628
|
+
? turnInput.metadata?.conversationHistoryForPrompt
|
|
629
|
+
: null;
|
|
630
|
+
const turnMessages = [];
|
|
467
631
|
// Analyze sentiment of user input only when sentiment tracking is enabled
|
|
468
632
|
if (this.activePersona.sentimentTracking?.enabled) {
|
|
469
633
|
const lastMsg = this.conversationHistoryManager.history.length > 0
|
|
@@ -511,14 +675,10 @@ export class GMI {
|
|
|
511
675
|
? turnInput.metadata.longTermMemoryContext.trim()
|
|
512
676
|
: "";
|
|
513
677
|
let assembledMemoryContext = null;
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
const
|
|
517
|
-
|
|
518
|
-
? lastMessage.content
|
|
519
|
-
: JSON.stringify(lastMessage.content))
|
|
520
|
-
: '';
|
|
521
|
-
if (this.retrievalAugmentor && this.activePersona.memoryConfig?.ragConfig?.enabled && isUserInitiatedTurn && lastMessage?.content) {
|
|
678
|
+
// Retrieval and memory assembly run for a user turn's first model
|
|
679
|
+
// call only; later calls continue from tool results.
|
|
680
|
+
const isUserInitiatedTurn = currentUserMessage !== undefined && turnMessages.length === 0;
|
|
681
|
+
if (this.retrievalAugmentor && this.activePersona.memoryConfig?.ragConfig?.enabled && isUserInitiatedTurn && currentTurnText) {
|
|
522
682
|
const currentQueryForRag = currentTurnText;
|
|
523
683
|
if (this.shouldTriggerRAGRetrieval(currentQueryForRag)) {
|
|
524
684
|
this.addTraceEntry(ReasoningEntryType.RAG_QUERY_START, "RAG retrieval triggered.", { queryPreview: currentQueryForRag.substring(0, 100) });
|
|
@@ -550,7 +710,12 @@ export class GMI {
|
|
|
550
710
|
}
|
|
551
711
|
}
|
|
552
712
|
if (isUserInitiatedTurn && currentTurnText) {
|
|
553
|
-
|
|
713
|
+
// Recall is limited to this turn's user, session and conversation scopes.
|
|
714
|
+
assembledMemoryContext = await this.memoryBridge?.assembleContext(currentTurnText, {
|
|
715
|
+
sessionId: turnInput.sessionId,
|
|
716
|
+
conversationId: this.getConversationIdForTurn(turnInput),
|
|
717
|
+
organizationId: this.getOrganizationIdForTurn(turnInput),
|
|
718
|
+
}) ?? null;
|
|
554
719
|
}
|
|
555
720
|
const promptExecContext = this.buildPromptExecutionContext();
|
|
556
721
|
const baseSystemPrompts = Array.isArray(this.activePersona.baseSystemPrompt)
|
|
@@ -597,13 +762,17 @@ export class GMI {
|
|
|
597
762
|
priority: 57,
|
|
598
763
|
});
|
|
599
764
|
}
|
|
600
|
-
const
|
|
601
|
-
|
|
602
|
-
|
|
765
|
+
const promptConversation = this.buildPromptConversation({
|
|
766
|
+
durableHistory: durableHistoryForPrompt,
|
|
767
|
+
historyAtTurnStart,
|
|
768
|
+
currentUserMessage,
|
|
769
|
+
turnMessages,
|
|
770
|
+
});
|
|
603
771
|
const promptComponents = {
|
|
604
772
|
systemPrompts,
|
|
605
|
-
conversationHistory:
|
|
606
|
-
|
|
773
|
+
conversationHistory: promptConversation.conversationHistory,
|
|
774
|
+
currentTurnMessageCount: promptConversation.currentTurnMessageCount,
|
|
775
|
+
userInput: promptConversation.userInput,
|
|
607
776
|
retrievedContext: [
|
|
608
777
|
assembledMemoryContext?.contextText,
|
|
609
778
|
augmentedContextFromRAG,
|
|
@@ -624,7 +793,7 @@ export class GMI {
|
|
|
624
793
|
providerId: modelDetails?.providerId || providerIdForModel || this.llmProviderManager.getProviderForModel(modelIdToUse)?.providerId || 'unknown',
|
|
625
794
|
maxContextTokens: modelDetails?.contextWindowSize || 8192, // Default fallback
|
|
626
795
|
capabilities: modelDetails?.capabilities || [],
|
|
627
|
-
promptFormatType: this.determinePromptFormat(
|
|
796
|
+
promptFormatType: this.determinePromptFormat(),
|
|
628
797
|
toolSupport: {
|
|
629
798
|
supported: modelDetails?.capabilities.includes('tool_use') || false,
|
|
630
799
|
format: this.determineToolFormat(modelDetails, providerIdForModel),
|
|
@@ -632,6 +801,16 @@ export class GMI {
|
|
|
632
801
|
};
|
|
633
802
|
const promptEngineResult = await this.promptEngine.constructPrompt(promptComponents, modelTargetInfo, promptExecContext);
|
|
634
803
|
promptEngineResult.issues?.forEach(issue => this.addTraceEntry(ReasoningEntryType.WARNING, `Prompt Engine Issue: ${issue.message}`, issue));
|
|
804
|
+
// A failed template leaves the prompt empty, and every provider takes
|
|
805
|
+
// a non-empty ChatMessage[]; fail the turn rather than send nothing.
|
|
806
|
+
const promptMessages = promptEngineResult.prompt;
|
|
807
|
+
if (!Array.isArray(promptMessages) || promptMessages.length === 0) {
|
|
808
|
+
throw new GMIError(`Prompt construction produced no chat messages for model '${modelTargetInfo.modelId}' (template '${promptEngineResult.metadata?.templateUsed ?? 'unknown'}').`, GMIErrorCode.GMI_PROCESSING_ERROR, {
|
|
809
|
+
turnId,
|
|
810
|
+
templateUsed: promptEngineResult.metadata?.templateUsed,
|
|
811
|
+
issues: promptEngineResult.issues?.filter((issue) => issue.type === 'error'),
|
|
812
|
+
});
|
|
813
|
+
}
|
|
635
814
|
this.addTraceEntry(ReasoningEntryType.PROMPT_CONSTRUCTION_COMPLETE, `Prompt constructed for model ${modelTargetInfo.modelId}.`);
|
|
636
815
|
const provider = this.llmProviderManager.getProvider(modelTargetInfo.providerId);
|
|
637
816
|
if (!provider) {
|
|
@@ -680,7 +859,7 @@ export class GMI {
|
|
|
680
859
|
// turn is unchanged on the normal path.
|
|
681
860
|
let currentIterationThinkingBlocks = [];
|
|
682
861
|
let textDeltaEmitted = false;
|
|
683
|
-
for await (const chunk of provider.generateCompletionStream(modelTargetInfo.modelId,
|
|
862
|
+
for await (const chunk of provider.generateCompletionStream(modelTargetInfo.modelId, promptMessages, llmOptions)) {
|
|
684
863
|
if (chunk.error) {
|
|
685
864
|
throw new GMIError(`LLM stream error: ${chunk.error.message}`, GMIErrorCode.LLM_PROVIDER_ERROR, chunk.error.details);
|
|
686
865
|
}
|
|
@@ -732,7 +911,7 @@ export class GMI {
|
|
|
732
911
|
if (!textDeltaEmitted && aggregatedResponseText) {
|
|
733
912
|
yield this.createOutputChunk(turnInput.interactionId, GMIOutputChunkType.TEXT_DELTA, aggregatedResponseText);
|
|
734
913
|
}
|
|
735
|
-
|
|
914
|
+
const assistantMessage = {
|
|
736
915
|
role: 'assistant',
|
|
737
916
|
content: currentIterationTextResponse || null,
|
|
738
917
|
tool_calls: currentIterationToolCallRequests.length > 0
|
|
@@ -744,42 +923,68 @@ export class GMI {
|
|
|
744
923
|
}))
|
|
745
924
|
: undefined,
|
|
746
925
|
...(currentIterationThinkingBlocks.length > 0 && { thinkingBlocks: currentIterationThinkingBlocks }),
|
|
747
|
-
}
|
|
926
|
+
};
|
|
927
|
+
this.conversationHistoryManager.push(assistantMessage);
|
|
928
|
+
turnMessages.push(assistantMessage);
|
|
748
929
|
if (currentIterationToolCallRequests.length > 0) {
|
|
749
|
-
|
|
930
|
+
if (ownsState())
|
|
931
|
+
this.state = GMIPrimeState.AWAITING_TOOL_RESULT;
|
|
750
932
|
const toolExecutionResults = [];
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
});
|
|
933
|
+
// The call awaiting its result; cleared once processToolCall returns.
|
|
934
|
+
let callInFlight;
|
|
935
|
+
let toolRoundFailure;
|
|
936
|
+
try {
|
|
937
|
+
for (const toolCallReq of currentIterationToolCallRequests) {
|
|
938
|
+
const requestDetails = {
|
|
939
|
+
toolCallRequest: toolCallReq,
|
|
940
|
+
gmiId: this.gmiId, personaId: this.activePersona.id,
|
|
941
|
+
personaCapabilities: this.activePersona.allowedCapabilities || [],
|
|
942
|
+
userContext: this.currentUserContext, correlationId: turnId,
|
|
943
|
+
sessionData: this.buildToolSessionData(turnInput),
|
|
944
|
+
};
|
|
945
|
+
this.addTraceEntry(ReasoningEntryType.TOOL_EXECUTION_START, `Orchestrating tool: ${toolCallReq.name}`, { reqId: toolCallReq.id });
|
|
946
|
+
callInFlight = toolCallReq;
|
|
947
|
+
const result = await this.toolOrchestrator.processToolCall(requestDetails);
|
|
948
|
+
callInFlight = undefined;
|
|
949
|
+
toolExecutionResults.push(result);
|
|
950
|
+
this.addTraceEntry(ReasoningEntryType.TOOL_EXECUTION_RESULT, `Tool '${toolCallReq.name}' result. Success: ${!result.isError}`, { result });
|
|
951
|
+
if (result.isError && plannedToolFailureMode === 'fail_closed') {
|
|
952
|
+
throw new GMIError(`Tool '${toolCallReq.name}' failed and execution policy is fail_closed.`, GMIErrorCode.TOOL_ERROR, {
|
|
953
|
+
toolCallId: toolCallReq.id,
|
|
954
|
+
toolName: toolCallReq.name,
|
|
955
|
+
errorDetails: result.errorDetails,
|
|
956
|
+
});
|
|
957
|
+
}
|
|
769
958
|
}
|
|
770
959
|
}
|
|
771
|
-
|
|
960
|
+
catch (error) {
|
|
961
|
+
toolRoundFailure = { error };
|
|
962
|
+
toolExecutionResults.push(...this.resultsForUnfinishedToolCalls(currentIterationToolCallRequests, toolExecutionResults.length, callInFlight, error));
|
|
963
|
+
}
|
|
964
|
+
// Recorded on success and failure alike, so the history this turn
|
|
965
|
+
// leaves answers every call its assistant message declared.
|
|
966
|
+
for (const tcResult of toolExecutionResults) {
|
|
967
|
+
turnMessages.push(this.conversationHistoryManager.updateWithToolResult(tcResult));
|
|
968
|
+
}
|
|
969
|
+
if (toolRoundFailure)
|
|
970
|
+
throw toolRoundFailure.error;
|
|
772
971
|
currentIterationTextResponse = ""; // Reset for next iteration if any
|
|
773
972
|
currentIterationToolCallRequests = []; // Reset
|
|
774
|
-
|
|
973
|
+
if (ownsState())
|
|
974
|
+
this.state = GMIPrimeState.PROCESSING;
|
|
775
975
|
continue main_processing_loop;
|
|
776
976
|
}
|
|
777
977
|
break main_processing_loop; // Break if no tool calls
|
|
778
978
|
}
|
|
779
979
|
await this.memoryBridge?.syncForTurn(turnInput, aggregatedResponseText);
|
|
780
980
|
await this.performPostTurnIngestion(this.stringifyTurnContent(turnInput.content) ?? '', aggregatedResponseText);
|
|
781
|
-
// Check and trigger all metaprompts (turn_interval, event_based, manual)
|
|
782
|
-
|
|
981
|
+
// Check and trigger all metaprompts (turn_interval, event_based, manual).
|
|
982
|
+
// Only user messages count toward turn_interval triggers: tool
|
|
983
|
+
// continuations, system messages and tool responses do not.
|
|
984
|
+
const isUserTurn = turnInput.metadata?.isToolContinuation !== true &&
|
|
985
|
+
(turnInput.type === GMIInteractionType.TEXT ||
|
|
986
|
+
turnInput.type === GMIInteractionType.MULTIMODAL_CONTENT);
|
|
987
|
+
await this.metapromptExecutor.checkAndTriggerMetaprompts(turnId, { countTurn: isUserTurn });
|
|
783
988
|
// Prepare the final GMIOutput for the generator's return value
|
|
784
989
|
const finalTurnOutput = {
|
|
785
990
|
isFinal: true,
|
|
@@ -794,7 +999,8 @@ export class GMI {
|
|
|
794
999
|
}
|
|
795
1000
|
catch (error) {
|
|
796
1001
|
const gmiError = createGMIErrorFromError(error, GMIErrorCode.GMI_PROCESSING_ERROR, { turnId }, `Error in GMI turn '${turnId}'.`);
|
|
797
|
-
|
|
1002
|
+
if (ownsState())
|
|
1003
|
+
this.state = GMIPrimeState.ERRORED;
|
|
798
1004
|
lastErrorForOutput = { code: gmiError.code, message: gmiError.message, details: gmiError.details };
|
|
799
1005
|
this.addTraceEntry(ReasoningEntryType.ERROR, `GMI processing error: ${gmiError.message}`, gmiError.toPlainObject());
|
|
800
1006
|
console.error(`GMI (ID: ${this.gmiId}) error in turn '${turnId}':`, gmiError);
|
|
@@ -808,13 +1014,19 @@ export class GMI {
|
|
|
808
1014
|
};
|
|
809
1015
|
}
|
|
810
1016
|
finally {
|
|
811
|
-
|
|
1017
|
+
// A newer turn may already own the lifecycle state (this generator was
|
|
1018
|
+
// drained after a failure, once the next turn had started); leave the
|
|
1019
|
+
// state and the trace's turn id to that turn.
|
|
1020
|
+
if (ownsState() &&
|
|
1021
|
+
this.state !== GMIPrimeState.ERRORED &&
|
|
1022
|
+
this.state !== GMIPrimeState.AWAITING_TOOL_RESULT) {
|
|
812
1023
|
this.state = GMIPrimeState.READY;
|
|
813
1024
|
}
|
|
814
1025
|
// This final chunk is part of the stream, not the return value of the generator
|
|
815
1026
|
yield this.createOutputChunk(turnInput.interactionId, GMIOutputChunkType.FINAL_RESPONSE_MARKER, 'Turn processing sequence complete.', { isFinal: true });
|
|
816
1027
|
this.addTraceEntry(ReasoningEntryType.INTERACTION_END, `Turn '${turnId}' finished. GMI State: ${this.state}.`);
|
|
817
|
-
|
|
1028
|
+
// Checked after the yield: a newer turn can start while this one waits there.
|
|
1029
|
+
if (ownsState() && this.reasoningTrace)
|
|
818
1030
|
this.reasoningTrace.turnId = undefined;
|
|
819
1031
|
}
|
|
820
1032
|
}
|
|
@@ -1006,10 +1218,13 @@ export class GMI {
|
|
|
1006
1218
|
}
|
|
1007
1219
|
}
|
|
1008
1220
|
if (!providerId && modelId.includes('/')) {
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1221
|
+
// A namespaced id names its provider only when that provider is
|
|
1222
|
+
// registered here. Otherwise it is a router's model id (OpenRouter
|
|
1223
|
+
// lists `openai/gpt-4o-mini`), and the registry lookup below finds the
|
|
1224
|
+
// provider that serves it.
|
|
1225
|
+
const prefix = modelId.split('/')[0];
|
|
1226
|
+
if (prefix && this.llmProviderManager.getProvider(prefix)) {
|
|
1227
|
+
providerId = prefix;
|
|
1013
1228
|
}
|
|
1014
1229
|
}
|
|
1015
1230
|
if (!providerId) {
|
|
@@ -1021,9 +1236,15 @@ export class GMI {
|
|
|
1021
1236
|
throw new GMIError(`Cannot determine providerId for model '${modelId}'. No explicit providerId, unable to infer from modelId, and no default provider found for it.`, GMIErrorCode.CONFIGURATION_ERROR, { modelId });
|
|
1022
1237
|
}
|
|
1023
1238
|
}
|
|
1024
|
-
//
|
|
1239
|
+
// Drop the provider prefix from the model id. OpenRouter's own ids are
|
|
1240
|
+
// namespaced slugs, and some name OpenRouter itself (`openrouter/auto`),
|
|
1241
|
+
// so there the prefix goes only when it wraps another vendor's slug
|
|
1242
|
+
// (`openrouter/openai/gpt-4o` sends `openai/gpt-4o`).
|
|
1025
1243
|
if (modelId.startsWith(providerId + '/')) {
|
|
1026
|
-
|
|
1244
|
+
const unprefixed = modelId.substring(providerId.length + 1);
|
|
1245
|
+
if (providerId !== 'openrouter' || unprefixed.includes('/')) {
|
|
1246
|
+
modelId = unprefixed;
|
|
1247
|
+
}
|
|
1027
1248
|
}
|
|
1028
1249
|
return { modelId, providerId };
|
|
1029
1250
|
}
|
|
@@ -1119,6 +1340,11 @@ export class GMI {
|
|
|
1119
1340
|
this.state = GMIPrimeState.SHUTTING_DOWN;
|
|
1120
1341
|
this.addTraceEntry(ReasoningEntryType.LIFECYCLE, "GMI shutting down.");
|
|
1121
1342
|
try {
|
|
1343
|
+
// Give metaprompt work still in flight a bounded window to store its
|
|
1344
|
+
// updates before the memories it writes to are closed, then stop the
|
|
1345
|
+
// queue: work not yet started is skipped, and late results are dropped.
|
|
1346
|
+
await this.metapromptExecutor?.drain();
|
|
1347
|
+
this.metapromptExecutor?.close();
|
|
1122
1348
|
await this.cognitiveMemory?.shutdown?.();
|
|
1123
1349
|
await this.workingMemory?.close?.();
|
|
1124
1350
|
// Shared dependencies (tool orchestrator, retrieval augmentor, utility AI, etc.) are owned by
|