@myagentroam/agent 0.10.68 → 0.11.1
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/agent-core/extensions/tools.js +3 -0
- package/dist/agent-core/model/sse.js +5 -1
- package/dist/agent-core/prompts/workflow.js +1 -1
- package/dist/agent-core/runtime/compaction/generate.d.ts +28 -0
- package/dist/agent-core/runtime/compaction/generate.js +84 -0
- package/dist/agent-core/sdk/agent.js +30 -11
- package/dist/agent-core/sdk/session.d.ts +2 -1
- package/dist/agent-core/sdk/session.js +260 -266
- package/dist/agent-core/session/store/jsonl-store.js +11 -1
- package/dist/agent-core/session/store/records.d.ts +1 -1
- package/dist/agent-core/session/store/records.js +15 -3
- package/dist/agent-core/tools/callers.js +5 -1
- package/dist/agent-core/tools/code-mode/index.js +17 -8
- package/dist/agent-core/tools/contracts.d.ts +2 -0
- package/dist/agent-core/tools/local/apply-patch.js +1 -0
- package/dist/agent-core/tools/mcp/catalog.js +1 -0
- package/dist/agent-core/tools/mcp/tool-search.js +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { isProviderContextOverflow, recoverModelStream } from '../model/recovery.js';
|
|
2
|
-
import { estimatedRequestTokens } from '../runtime/context/request-budget.js';
|
|
3
1
|
import { restoreMessages } from '../runtime/context/restore.js';
|
|
4
2
|
import { createNativeSteer } from './native-steer.js';
|
|
5
|
-
import { lastConfigurationEffort, latestModelUsage, reasoningEffortBaseline
|
|
3
|
+
import { lastConfigurationEffort, latestModelUsage, reasoningEffortBaseline } from '../runtime/context/usage.js';
|
|
6
4
|
import { splitContextualPrompt } from '../runtime/context/contextual-blocks.js';
|
|
7
5
|
import { contextualInstructionInsertIndex, insertContextualWorldState, latestContextualWorldStateGeneration, parsePersistedContextualWorldState, persistContextualWorldState, resetContextualWorldState, updateContextualWorldState, updatePromptWorldState } from '../runtime/context/world-state.js';
|
|
8
6
|
import { eventForPersistence, publicModelUsage } from '../runtime/event-projection.js';
|
|
@@ -35,10 +33,11 @@ import { childSubagentInstruction } from '../prompts/subagent.js';
|
|
|
35
33
|
import { renderSubagentUpdate } from '../subagent/model-update.js';
|
|
36
34
|
import { AsyncQueue } from '../runtime/async-queue.js';
|
|
37
35
|
import { CompactionOperation } from '../runtime/compaction/operation.js';
|
|
36
|
+
import { generateCompactionCandidate } from '../runtime/compaction/generate.js';
|
|
38
37
|
import { CompactCoordinator } from '../runtime/compaction/coordinator.js';
|
|
39
38
|
import { CompactRequests } from '../runtime/compaction/requests.js';
|
|
40
39
|
import { compactSnapshotAnchor } from '../runtime/compaction/retained-context.js';
|
|
41
|
-
import { DEFAULT_COMPACTION_FOCUS, buildCompactedHistory,
|
|
40
|
+
import { DEFAULT_COMPACTION_FOCUS, buildCompactedHistory, buildCompactionMessages, compactedHistoryMessages } from '../runtime/compaction/history.js';
|
|
42
41
|
import { currentLocalTimeContext, environmentContextUpdate, restoreEnvironmentState } from '../runtime/context/environment.js';
|
|
43
42
|
import { ContextGcRuntime } from '../runtime/context/gc-runtime.js';
|
|
44
43
|
import { AGENT_EXECUTION_POLICY } from '../runtime/execution-policy.js';
|
|
@@ -195,7 +194,7 @@ export function createSessionOpener(services) {
|
|
|
195
194
|
}
|
|
196
195
|
};
|
|
197
196
|
const execution = (mode, input, internal = {}) => {
|
|
198
|
-
services.assertCanStart();
|
|
197
|
+
services.assertCanStart(sessionId);
|
|
199
198
|
if ([...active.keys()].some((key) => key.startsWith(`${sessionId}:`)))
|
|
200
199
|
throw new MarAgentError('MAR_AGENT_EXECUTION_ACTIVE', 'Session already has an active execution.');
|
|
201
200
|
const { models: executionModels, defaultModelId: executionDefaultModelId, generation: executionModelGeneration } = services.modelState();
|
|
@@ -280,6 +279,7 @@ export function createSessionOpener(services) {
|
|
|
280
279
|
let sequence = 0;
|
|
281
280
|
let emitTail = Promise.resolve();
|
|
282
281
|
let releaseSession;
|
|
282
|
+
let failedExecution = false;
|
|
283
283
|
let exhaustedModelAttempt;
|
|
284
284
|
// Serialize durable events before either the local stream or Host observes them.
|
|
285
285
|
let persistedTerminal = false;
|
|
@@ -393,31 +393,181 @@ export function createSessionOpener(services) {
|
|
|
393
393
|
const contextualWorldStateGeneration = latestContextualWorldStateGeneration(contextRecords);
|
|
394
394
|
const restoredContextualWorldState = sessionRuntime.contextualWorldState;
|
|
395
395
|
const persistedContextualWorldState = parsePersistedContextualWorldState(await store.readContextualWorldState(sessionId));
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
restoredContextualWorldState
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
resourceSnapshot: undefined,
|
|
411
|
-
entries: []
|
|
412
|
-
};
|
|
413
|
-
sessionRuntime.contextualWorldState = contextualWorldState;
|
|
414
|
-
}
|
|
396
|
+
const initialContextualWorldState = restoredContextualWorldState !== undefined &&
|
|
397
|
+
restoredContextualWorldState.generation === contextualWorldStateGeneration
|
|
398
|
+
? restoredContextualWorldState
|
|
399
|
+
: persistedContextualWorldState !== undefined &&
|
|
400
|
+
persistedContextualWorldState.generation === contextualWorldStateGeneration
|
|
401
|
+
? persistedContextualWorldState
|
|
402
|
+
: {
|
|
403
|
+
generation: contextualWorldStateGeneration,
|
|
404
|
+
initialized: false,
|
|
405
|
+
instructionSnapshot: undefined,
|
|
406
|
+
resourceSnapshot: undefined,
|
|
407
|
+
entries: []
|
|
408
|
+
};
|
|
409
|
+
sessionRuntime.contextualWorldState = initialContextualWorldState;
|
|
415
410
|
const compactMayContainAgentInstructions = contextRecords.some((record) => compactSummaryFromCheckpoint(record) !== undefined);
|
|
416
411
|
const restored = await restoreMessages(store, sessionId, contextRecords, {
|
|
417
412
|
messageSources,
|
|
418
413
|
includeImages: mode !== 'compact'
|
|
419
414
|
});
|
|
420
|
-
|
|
415
|
+
// This execution owns checkpoint adoption, not another copy of the live context.
|
|
416
|
+
const modelContext = (() => {
|
|
417
|
+
const messages = restored.messages;
|
|
418
|
+
let userMessages = [...restored.userMessages];
|
|
419
|
+
let recordedEnvironment = restored.environmentState;
|
|
420
|
+
let instructionInsertIndex = 0;
|
|
421
|
+
let worldState = initialContextualWorldState;
|
|
422
|
+
const commitWorldState = async (next) => {
|
|
423
|
+
await persistContextualWorldState(store, sessionId, next);
|
|
424
|
+
worldState = next;
|
|
425
|
+
sessionRuntime.contextualWorldState = next;
|
|
426
|
+
};
|
|
427
|
+
const resetCompactWorldState = async (generation, committed) => {
|
|
428
|
+
instructionInsertIndex = contextualInstructionInsertIndex(messages);
|
|
429
|
+
const next = resetContextualWorldState(generation, instructionInsertIndex, {
|
|
430
|
+
instructionSnapshot: currentInstructionSnapshot,
|
|
431
|
+
instructionContent: renderAgentInstructions(instructionEntries, true),
|
|
432
|
+
resourceSnapshot: committed
|
|
433
|
+
? committed.resources
|
|
434
|
+
: retainedSessionResourcesSnapshot(await loadRetainedSessionResources())
|
|
435
|
+
});
|
|
436
|
+
if (!committed)
|
|
437
|
+
await commitWorldState(next);
|
|
438
|
+
else {
|
|
439
|
+
// The checkpoint is authoritative; its sidecar is recoverable on restart.
|
|
440
|
+
worldState = next;
|
|
441
|
+
sessionRuntime.contextualWorldState = next;
|
|
442
|
+
try {
|
|
443
|
+
await persistContextualWorldState(store, sessionId, next);
|
|
444
|
+
}
|
|
445
|
+
catch {
|
|
446
|
+
coreExtensions.diagnose({
|
|
447
|
+
code: 'MAR_AGENT_COMPACT_SIDECAR_PERSIST_FAILED',
|
|
448
|
+
sessionId
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
const recordEnvironment = async () => {
|
|
454
|
+
const message = environmentContextUpdate(executionEnvironment, recordedEnvironment);
|
|
455
|
+
if (!message)
|
|
456
|
+
return;
|
|
457
|
+
await store.append(sessionId, {
|
|
458
|
+
type: 'context.environment',
|
|
459
|
+
payload: { version: 1, state: executionEnvironment },
|
|
460
|
+
executionId,
|
|
461
|
+
turnId
|
|
462
|
+
});
|
|
463
|
+
messages.push(message);
|
|
464
|
+
recordedEnvironment = executionEnvironment;
|
|
465
|
+
};
|
|
466
|
+
const syncMcpWorldState = async (index = instructionInsertIndex) => {
|
|
467
|
+
const snapshot = mcpRegistry.navigation();
|
|
468
|
+
if (worldState.mcpSnapshot === snapshot)
|
|
469
|
+
return;
|
|
470
|
+
const next = {
|
|
471
|
+
...worldState,
|
|
472
|
+
mcpSnapshot: snapshot,
|
|
473
|
+
entries: [
|
|
474
|
+
...worldState.entries,
|
|
475
|
+
{
|
|
476
|
+
index,
|
|
477
|
+
kind: 'mcp',
|
|
478
|
+
content: snapshot ?? '<mcp_catalog>No deferred MCP tools remain.</mcp_catalog>'
|
|
479
|
+
}
|
|
480
|
+
]
|
|
481
|
+
};
|
|
482
|
+
await commitWorldState(next);
|
|
483
|
+
};
|
|
484
|
+
return {
|
|
485
|
+
messages,
|
|
486
|
+
get worldState() {
|
|
487
|
+
return worldState;
|
|
488
|
+
},
|
|
489
|
+
commitWorldState,
|
|
490
|
+
recordEnvironment,
|
|
491
|
+
syncMcpWorldState,
|
|
492
|
+
rememberInput(input) {
|
|
493
|
+
userMessages.push(input);
|
|
494
|
+
},
|
|
495
|
+
compactInputs(prefix) {
|
|
496
|
+
return userMessages.filter((entry) => prefix.some((message) => message.role === 'user' &&
|
|
497
|
+
message.contextKind === undefined &&
|
|
498
|
+
(entry.metadata?.recordId
|
|
499
|
+
? message.metadata?.recordId === entry.metadata.recordId
|
|
500
|
+
: message.content === entry.content)));
|
|
501
|
+
},
|
|
502
|
+
async initializeWorldState() {
|
|
503
|
+
instructionInsertIndex =
|
|
504
|
+
mode === 'compact' ? contextualInstructionInsertIndex(messages) : messages.length;
|
|
505
|
+
// Only the latest Compact may rebuild missing sidecar resources, never a GC boundary.
|
|
506
|
+
if (!worldState.initialized &&
|
|
507
|
+
contextRecords.some((record) => record.recordId === contextualWorldStateGeneration &&
|
|
508
|
+
compactSummaryFromCheckpoint(record) !== undefined))
|
|
509
|
+
await resetCompactWorldState(contextualWorldStateGeneration);
|
|
510
|
+
const nextInstructionWorldState = updateContextualWorldState(worldState, instructionInsertIndex, {
|
|
511
|
+
instructionSnapshot: currentInstructionSnapshot,
|
|
512
|
+
instructionContent: renderAgentInstructions(instructionEntries, compactMayContainAgentInstructions ||
|
|
513
|
+
worldState.instructionSnapshot !== undefined)
|
|
514
|
+
});
|
|
515
|
+
if (!isDeepStrictEqual(worldState, nextInstructionWorldState))
|
|
516
|
+
await commitWorldState(nextInstructionWorldState);
|
|
517
|
+
},
|
|
518
|
+
// Must run inside the existing writer/projection commit window.
|
|
519
|
+
replaceCompactMessages(replacementHistory, retainedModelContext) {
|
|
520
|
+
messages.splice(0, messages.length, environmentContextUpdate(executionEnvironment), ...compactedHistoryMessages(replacementHistory), ...retainedModelContext);
|
|
521
|
+
pendingAppends.length = 0;
|
|
522
|
+
selected.resetContinuation?.();
|
|
523
|
+
},
|
|
524
|
+
// Derived state follows the committed splice, never delays it past the writer window.
|
|
525
|
+
async adoptCompactCheckpoint(recordId, replacementHistory, retainedModelContext, resources) {
|
|
526
|
+
contextGc.reset();
|
|
527
|
+
restoreMcpDiscovery();
|
|
528
|
+
recordedEnvironment = executionEnvironment;
|
|
529
|
+
userMessages = replacementHistory
|
|
530
|
+
.filter((message) => message.kind !== 'summary')
|
|
531
|
+
.map((message) => ({
|
|
532
|
+
content: message.content,
|
|
533
|
+
...(message.metadata ? { metadata: { ...message.metadata } } : {})
|
|
534
|
+
}));
|
|
535
|
+
userMessages.push(...retainedModelContext
|
|
536
|
+
.filter((message) => message.role === 'user' && message.contextKind === undefined)
|
|
537
|
+
.map((message) => ({
|
|
538
|
+
content: message.content,
|
|
539
|
+
...(message.metadata ? { metadata: message.metadata } : {})
|
|
540
|
+
})));
|
|
541
|
+
await resetCompactWorldState(recordId, { resources });
|
|
542
|
+
},
|
|
543
|
+
async adoptGcCheckpoint(committed, appendBoundary) {
|
|
544
|
+
smartContextTokens = undefined;
|
|
545
|
+
selected.resetContinuation?.();
|
|
546
|
+
const refreshed = await restoreMessages(store, sessionId, committed.records, {
|
|
547
|
+
includeImages: true,
|
|
548
|
+
currentTurnId: turnId,
|
|
549
|
+
messageSources,
|
|
550
|
+
projection: committed.projection
|
|
551
|
+
});
|
|
552
|
+
const restoredIds = new Set(committed.records.map((record) => record.recordId));
|
|
553
|
+
const lateMessages = pendingAppends
|
|
554
|
+
.slice(appendBoundary)
|
|
555
|
+
.filter((entry) => !restoredIds.has(entry.recordId))
|
|
556
|
+
.map((entry) => entry.message);
|
|
557
|
+
messages.splice(0, messages.length, ...refreshed.messages, ...lateMessages);
|
|
558
|
+
restoreMcpDiscovery();
|
|
559
|
+
recordedEnvironment = refreshed.environmentState;
|
|
560
|
+
userMessages = [...refreshed.userMessages];
|
|
561
|
+
instructionInsertIndex = contextualInstructionInsertIndex(messages);
|
|
562
|
+
const next = resetContextualWorldState(latestContextualWorldStateGeneration(committed.records), instructionInsertIndex, {
|
|
563
|
+
instructionSnapshot: currentInstructionSnapshot,
|
|
564
|
+
instructionContent: renderAgentInstructions(instructionEntries, committed.records.some((record) => compactSummaryFromCheckpoint(record) !== undefined))
|
|
565
|
+
});
|
|
566
|
+
await commitWorldState(next);
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
})();
|
|
570
|
+
const messages = modelContext.messages;
|
|
421
571
|
const pendingInputs = restored.pendingInputs;
|
|
422
572
|
const waitInterrupt = createToolWaitInterrupt(() => pendingInputs.size > 0);
|
|
423
573
|
liveModelMessages = messages;
|
|
@@ -427,7 +577,6 @@ export function createSessionOpener(services) {
|
|
|
427
577
|
messages.push(pending.message);
|
|
428
578
|
pendingAppends.length = 0;
|
|
429
579
|
immediateTarget = messages;
|
|
430
|
-
let recordedEnvironment = restored.environmentState;
|
|
431
580
|
let smartInput;
|
|
432
581
|
let compactContext;
|
|
433
582
|
let startCompact;
|
|
@@ -472,7 +621,7 @@ export function createSessionOpener(services) {
|
|
|
472
621
|
eligible: smartCompaction,
|
|
473
622
|
requested: false
|
|
474
623
|
};
|
|
475
|
-
|
|
624
|
+
modelContext.rememberInput({
|
|
476
625
|
content: content.modelText ?? content.text,
|
|
477
626
|
metadata: inputMetadata
|
|
478
627
|
});
|
|
@@ -545,7 +694,7 @@ export function createSessionOpener(services) {
|
|
|
545
694
|
};
|
|
546
695
|
messages.push(message);
|
|
547
696
|
messageSources.set(message, applied);
|
|
548
|
-
|
|
697
|
+
modelContext.rememberInput({ content, metadata });
|
|
549
698
|
smartInput = { recordId: received.recordId, eligible, requested: false };
|
|
550
699
|
for (const text of (payload.modelContext ?? payload.context ?? []))
|
|
551
700
|
messages.push({ role: 'user', content: text, contextKind: 'contextual' });
|
|
@@ -600,20 +749,6 @@ export function createSessionOpener(services) {
|
|
|
600
749
|
signal: controller.signal,
|
|
601
750
|
...(restoring ? { restoring: true } : {})
|
|
602
751
|
}, inputs.boundarySize);
|
|
603
|
-
const recordEnvironment = async () => {
|
|
604
|
-
const message = environmentContextUpdate(executionEnvironment, recordedEnvironment);
|
|
605
|
-
if (!message)
|
|
606
|
-
return;
|
|
607
|
-
await store.append(sessionId, {
|
|
608
|
-
type: 'context.environment',
|
|
609
|
-
payload: { version: 1, state: executionEnvironment },
|
|
610
|
-
executionId,
|
|
611
|
-
turnId
|
|
612
|
-
});
|
|
613
|
-
messages.push(message);
|
|
614
|
-
recordedEnvironment = executionEnvironment;
|
|
615
|
-
};
|
|
616
|
-
let compactionUserMessages = [...restored.userMessages];
|
|
617
752
|
const hasRestoredUserImages = messages.some((message) => message.role === 'user' && Boolean(message.images?.length));
|
|
618
753
|
let modelInputImages;
|
|
619
754
|
const currentExecutionToolImages = [];
|
|
@@ -854,7 +989,6 @@ export function createSessionOpener(services) {
|
|
|
854
989
|
});
|
|
855
990
|
const instructionEntries = instructionContext?.entries ?? [];
|
|
856
991
|
const currentInstructionSnapshot = renderAgentInstructions(instructionEntries, false);
|
|
857
|
-
let agentInstructionInsertIndex = mode === 'compact' ? contextualInstructionInsertIndex(messages) : messages.length;
|
|
858
992
|
const baseTools = () => [...captureTools().values()]
|
|
859
993
|
.filter((binding) => binding.mcp === undefined)
|
|
860
994
|
.map((binding) => binding.definition)
|
|
@@ -880,49 +1014,7 @@ export function createSessionOpener(services) {
|
|
|
880
1014
|
subagents: subagents?.listSessionResources() ?? []
|
|
881
1015
|
};
|
|
882
1016
|
};
|
|
883
|
-
|
|
884
|
-
await persistContextualWorldState(store, sessionId, next);
|
|
885
|
-
contextualWorldState = next;
|
|
886
|
-
sessionRuntime.contextualWorldState = next;
|
|
887
|
-
};
|
|
888
|
-
const resetCompactWorldState = async (generation, committed) => {
|
|
889
|
-
agentInstructionInsertIndex = contextualInstructionInsertIndex(messages);
|
|
890
|
-
const next = resetContextualWorldState(generation, agentInstructionInsertIndex, {
|
|
891
|
-
instructionSnapshot: currentInstructionSnapshot,
|
|
892
|
-
instructionContent: renderAgentInstructions(instructionEntries, true),
|
|
893
|
-
resourceSnapshot: committed
|
|
894
|
-
? committed.resources
|
|
895
|
-
: retainedSessionResourcesSnapshot(await loadRetainedSessionResources())
|
|
896
|
-
});
|
|
897
|
-
if (!committed)
|
|
898
|
-
await commitWorldState(next);
|
|
899
|
-
else {
|
|
900
|
-
// The checkpoint is authoritative; its sidecar is recoverable on restart.
|
|
901
|
-
contextualWorldState = next;
|
|
902
|
-
sessionRuntime.contextualWorldState = next;
|
|
903
|
-
try {
|
|
904
|
-
await persistContextualWorldState(store, sessionId, next);
|
|
905
|
-
}
|
|
906
|
-
catch {
|
|
907
|
-
coreExtensions.diagnose({
|
|
908
|
-
code: 'MAR_AGENT_COMPACT_SIDECAR_PERSIST_FAILED',
|
|
909
|
-
sessionId
|
|
910
|
-
});
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
};
|
|
914
|
-
// A missing sidecar is rebuilt only for the latest Compact, never for a GC boundary.
|
|
915
|
-
if (!contextualWorldState.initialized &&
|
|
916
|
-
contextRecords.some((record) => record.recordId === contextualWorldStateGeneration &&
|
|
917
|
-
compactSummaryFromCheckpoint(record) !== undefined))
|
|
918
|
-
await resetCompactWorldState(contextualWorldStateGeneration);
|
|
919
|
-
const nextInstructionWorldState = updateContextualWorldState(contextualWorldState, agentInstructionInsertIndex, {
|
|
920
|
-
instructionSnapshot: currentInstructionSnapshot,
|
|
921
|
-
instructionContent: renderAgentInstructions(instructionEntries, compactMayContainAgentInstructions ||
|
|
922
|
-
contextualWorldState.instructionSnapshot !== undefined)
|
|
923
|
-
});
|
|
924
|
-
if (!isDeepStrictEqual(contextualWorldState, nextInstructionWorldState))
|
|
925
|
-
await commitWorldState(nextInstructionWorldState);
|
|
1017
|
+
await modelContext.initializeWorldState();
|
|
926
1018
|
const buildExecutionPromptSections = (availableTools = executionTools, promptMode = mode) => buildSessionPromptSections(availableTools, promptMode, selectedModel, executionSystemInstruction, instructionContext?.skillCatalog);
|
|
927
1019
|
const buildExecutionSystemPrompt = (availableTools = executionTools, promptMode = mode) => renderPromptSections(buildExecutionPromptSections(availableTools, promptMode));
|
|
928
1020
|
const promptComposition = (availableTools, promptMode) => ({
|
|
@@ -933,26 +1025,8 @@ export function createSessionOpener(services) {
|
|
|
933
1025
|
tools: availableTools.map((tool) => tool.name)
|
|
934
1026
|
}
|
|
935
1027
|
});
|
|
936
|
-
const syncMcpWorldState = async (index) => {
|
|
937
|
-
const snapshot = mcpRegistry.navigation();
|
|
938
|
-
if (contextualWorldState.mcpSnapshot === snapshot)
|
|
939
|
-
return;
|
|
940
|
-
const next = {
|
|
941
|
-
...contextualWorldState,
|
|
942
|
-
mcpSnapshot: snapshot,
|
|
943
|
-
entries: [
|
|
944
|
-
...contextualWorldState.entries,
|
|
945
|
-
{
|
|
946
|
-
index,
|
|
947
|
-
kind: 'mcp',
|
|
948
|
-
content: snapshot ?? '<mcp_catalog>No deferred MCP tools remain.</mcp_catalog>'
|
|
949
|
-
}
|
|
950
|
-
]
|
|
951
|
-
};
|
|
952
|
-
await commitWorldState(next);
|
|
953
|
-
};
|
|
954
1028
|
if (mode !== 'compact')
|
|
955
|
-
await syncMcpWorldState(
|
|
1029
|
+
await modelContext.syncMcpWorldState();
|
|
956
1030
|
const writeCompactionRecord = async (summary, _automatic, signal, write) => withRecordProjection(async () => {
|
|
957
1031
|
signal.throwIfAborted();
|
|
958
1032
|
const stored = await write(summary, { signal });
|
|
@@ -1138,7 +1212,7 @@ export function createSessionOpener(services) {
|
|
|
1138
1212
|
? normalizeMessagesForModel([...preparingRequestMessages, ...messages.slice(preparingRequestBaseLength)], { supportsImages: selectedModel.inputCapabilities.includes('IMAGE') })
|
|
1139
1213
|
: projectSessionRequestMessages(messages.map((message, index) => index === currentExecutionUserIndex && modelInputImages?.length
|
|
1140
1214
|
? { ...message, images: modelInputImages }
|
|
1141
|
-
: message), mode === 'compact' ? [] :
|
|
1215
|
+
: message), mode === 'compact' ? [] : modelContext.worldState.entries, mode !== 'compact' && selectedModel.inputCapabilities.includes('IMAGE'), baseTools().some((tool) => tool.name === 'code_exec'), permissionPolicy.mode === 'auto')
|
|
1142
1216
|
};
|
|
1143
1217
|
if (mode !== 'compact') {
|
|
1144
1218
|
if (pendingInputs.size)
|
|
@@ -1153,7 +1227,7 @@ export function createSessionOpener(services) {
|
|
|
1153
1227
|
await sessionRuntime.sessionBackend.enqueue({ kind: 'submit', input: { ...content, delivery: 'idle' } }, call, (request, effective, next) => next(request, effective));
|
|
1154
1228
|
return {};
|
|
1155
1229
|
}
|
|
1156
|
-
await recordEnvironment();
|
|
1230
|
+
await modelContext.recordEnvironment();
|
|
1157
1231
|
call.signal.throwIfAborted();
|
|
1158
1232
|
await writeInputRecord(content, internal.inputSource === 'extension' ? 'extension.input' : 'turn.user', {
|
|
1159
1233
|
...(internal.extensionSource ? { source: internal.extensionSource } : {}),
|
|
@@ -1325,10 +1399,16 @@ export function createSessionOpener(services) {
|
|
|
1325
1399
|
});
|
|
1326
1400
|
let lastServerContextTokens = lastServerUsage?.contextInputTokens;
|
|
1327
1401
|
let compactBoundary = messages.length;
|
|
1402
|
+
const invalidateCompactUsage = () => {
|
|
1403
|
+
lastServerContextTokens = undefined;
|
|
1404
|
+
lastServerUsage = undefined;
|
|
1405
|
+
smartContextTokens = undefined;
|
|
1406
|
+
requestReasoningEffort = reasoningEffort;
|
|
1407
|
+
effectiveReasoningEffort = reasoningEffort;
|
|
1408
|
+
};
|
|
1328
1409
|
const compactLeaf = async (input, signal, prepare, compactionId) => {
|
|
1329
1410
|
if (messages.length < 2)
|
|
1330
1411
|
return false;
|
|
1331
|
-
let compactSummary = '';
|
|
1332
1412
|
const cutoff = Math.min(compactBoundary, messages.length);
|
|
1333
1413
|
const current = messages[cutoff - 1];
|
|
1334
1414
|
const retainCurrent = mode !== 'compact' && current.role === 'user' && current.contextKind === undefined;
|
|
@@ -1338,13 +1418,9 @@ export function createSessionOpener(services) {
|
|
|
1338
1418
|
message.contextKind === 'summary'))
|
|
1339
1419
|
return false;
|
|
1340
1420
|
const compactHistory = structuredClone(prefix);
|
|
1341
|
-
const prefixInputs =
|
|
1342
|
-
message.contextKind === undefined &&
|
|
1343
|
-
(entry.metadata?.recordId
|
|
1344
|
-
? message.metadata?.recordId === entry.metadata.recordId
|
|
1345
|
-
: message.content === entry.content)));
|
|
1421
|
+
const prefixInputs = modelContext.compactInputs(prefix);
|
|
1346
1422
|
const snapshotTools = structuredClone(projectTools(executionTools));
|
|
1347
|
-
const generation =
|
|
1423
|
+
const generation = modelContext.worldState.generation;
|
|
1348
1424
|
const snapshotUsage = lastServerUsage;
|
|
1349
1425
|
const snapshotEffort = requestReasoningEffort ?? reasoningEffort;
|
|
1350
1426
|
const anchorRecordId = prefix
|
|
@@ -1356,29 +1432,6 @@ export function createSessionOpener(services) {
|
|
|
1356
1432
|
...(visibleAnchor ? { anchor: visibleAnchor } : {})
|
|
1357
1433
|
};
|
|
1358
1434
|
const compactComposition = splitContextualPrompt(await operation((call) => coreExtensions.composeModelSystem(promptComposition(snapshotTools, 'run'), call)));
|
|
1359
|
-
const compactSystemPrompt = compactComposition.system;
|
|
1360
|
-
const projectedHistory = normalizeMessagesForModel(compactHistory, {
|
|
1361
|
-
supportsImages: false
|
|
1362
|
-
}).map(projectSmartCompactionMessage);
|
|
1363
|
-
const nativeCompactMessages = buildNativeCompactionMessages(projectedHistory, {
|
|
1364
|
-
...(input.focus === undefined ? {} : { focus: input.focus })
|
|
1365
|
-
});
|
|
1366
|
-
const compactOverheadTokens = estimatedRequestTokens(compactSystemPrompt, buildCompactionMessages(''), snapshotTools);
|
|
1367
|
-
const compactInputTokens = Math.max(0, selectedModel.contextWindowTokens - compactOverheadTokens);
|
|
1368
|
-
let usingNativeMessages = shouldUseNativeCompaction({
|
|
1369
|
-
estimatedRequestTokens: estimatedRequestTokens(compactSystemPrompt, nativeCompactMessages, snapshotTools),
|
|
1370
|
-
contextWindowTokens: selectedModel.contextWindowTokens,
|
|
1371
|
-
latestUsage: snapshotUsage,
|
|
1372
|
-
historyMessages: compactHistory,
|
|
1373
|
-
appendedMessages: nativeCompactMessages.slice(projectedHistory.length)
|
|
1374
|
-
});
|
|
1375
|
-
const fallbackMessages = () => buildCompactionMessages(buildCompactionInput(compactHistory, {
|
|
1376
|
-
...(input.focus === undefined ? {} : { focus: input.focus }),
|
|
1377
|
-
maxTokens: Math.max(1, compactInputTokens)
|
|
1378
|
-
}));
|
|
1379
|
-
let compactMessages = usingNativeMessages
|
|
1380
|
-
? nativeCompactMessages
|
|
1381
|
-
: fallbackMessages();
|
|
1382
1435
|
await emit({
|
|
1383
1436
|
type: 'context.compacting',
|
|
1384
1437
|
compactionId,
|
|
@@ -1387,79 +1440,43 @@ export function createSessionOpener(services) {
|
|
|
1387
1440
|
...anchor
|
|
1388
1441
|
});
|
|
1389
1442
|
let latestUsage;
|
|
1390
|
-
|
|
1443
|
+
let compactSummary;
|
|
1391
1444
|
const compaction = createCompactionOperation(compactionId, signal);
|
|
1392
1445
|
const compactTurn = createModelTurnSession(selectedAdapter);
|
|
1393
1446
|
try {
|
|
1394
|
-
const
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
onAttemptDiagnostic: recordModelAttempt('COMPACTION')
|
|
1423
|
-
}, undefined, selectedModel.id, 'compact');
|
|
1424
|
-
for await (const event of streamModel((signal) => compaction.start({ start: (request) => compactTurn.start(request, signal) }, request), compaction.signal)) {
|
|
1425
|
-
if (event.type === 'text.completed' &&
|
|
1426
|
-
(event.phase ?? 'final_answer') === 'final_answer')
|
|
1427
|
-
compactSummary = event.text.trim();
|
|
1428
|
-
else if (event.type === 'usage') {
|
|
1429
|
-
latestUsage = event.usage;
|
|
1430
|
-
await emit({
|
|
1431
|
-
type: 'usage.updated',
|
|
1432
|
-
purpose: 'compact',
|
|
1433
|
-
...publicModelUsage(event.usage)
|
|
1434
|
-
});
|
|
1435
|
-
}
|
|
1436
|
-
else if (event.type === 'client_tool.call')
|
|
1437
|
-
throw new MarAgentError('MAR_AGENT_MODEL_PROTOCOL_ERROR', 'Compaction returned a tool call while tools were disabled.');
|
|
1438
|
-
}
|
|
1439
|
-
break;
|
|
1440
|
-
}
|
|
1441
|
-
catch (error) {
|
|
1442
|
-
if (await recoverModelStream(error, compactionRetryState, compaction.signal)) {
|
|
1443
|
-
continue;
|
|
1444
|
-
}
|
|
1445
|
-
if (isProviderContextOverflow(error) && usingNativeMessages) {
|
|
1446
|
-
usingNativeMessages = false;
|
|
1447
|
-
compactMessages = fallbackMessages();
|
|
1448
|
-
compactionRetryState.attempts = 0;
|
|
1449
|
-
continue;
|
|
1450
|
-
}
|
|
1451
|
-
if (isProviderContextOverflow(error))
|
|
1452
|
-
throw new MarAgentError('MAR_AGENT_CONTEXT_LIMIT', 'The compaction request exceeds the model context window.', { cause: error });
|
|
1453
|
-
throw error;
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1447
|
+
const candidate = await generateCompactionCandidate({
|
|
1448
|
+
history: compactHistory,
|
|
1449
|
+
system: compactComposition.system,
|
|
1450
|
+
...(compactComposition.systemBlocks === undefined
|
|
1451
|
+
? {}
|
|
1452
|
+
: { systemBlocks: compactComposition.systemBlocks }),
|
|
1453
|
+
tools: snapshotTools,
|
|
1454
|
+
contextWindowTokens: selectedModel.contextWindowTokens,
|
|
1455
|
+
latestUsage: snapshotUsage,
|
|
1456
|
+
reasoningEffort: snapshotEffort,
|
|
1457
|
+
...(input.focus === undefined ? {} : { focus: input.focus }),
|
|
1458
|
+
reason: mode === 'compact' ? 'manual' : 'automatic',
|
|
1459
|
+
promptCacheKey: sessionId
|
|
1460
|
+
}, {
|
|
1461
|
+
operation: compaction,
|
|
1462
|
+
turn: compactTurn,
|
|
1463
|
+
generateExtension: generateCompactExtension,
|
|
1464
|
+
transformRequest: (request) => transformModelRequest(request, undefined, selectedModel.id, 'compact'),
|
|
1465
|
+
stream: streamModel,
|
|
1466
|
+
observeUsage: (usage) => emit({
|
|
1467
|
+
type: 'usage.updated',
|
|
1468
|
+
purpose: 'compact',
|
|
1469
|
+
...publicModelUsage(usage)
|
|
1470
|
+
}),
|
|
1471
|
+
onAttemptDiagnostic: recordModelAttempt('COMPACTION')
|
|
1472
|
+
});
|
|
1473
|
+
compactSummary = candidate.summary;
|
|
1474
|
+
latestUsage = candidate.usage;
|
|
1456
1475
|
}
|
|
1457
1476
|
finally {
|
|
1458
1477
|
await compaction.dispose();
|
|
1459
1478
|
await compactTurn.close();
|
|
1460
1479
|
}
|
|
1461
|
-
if (!compactSummary)
|
|
1462
|
-
throw new MarAgentError('MAR_AGENT_COMPACT_FAILED', 'Automatic compact failed.');
|
|
1463
1480
|
await emit({
|
|
1464
1481
|
type: 'context.compacting',
|
|
1465
1482
|
compactionId,
|
|
@@ -1473,7 +1490,7 @@ export function createSessionOpener(services) {
|
|
|
1473
1490
|
const replacementHistory = buildCompactedHistory(compactSummary, prefixInputs, compactUserTokenLimit);
|
|
1474
1491
|
let retainedModelContext = [];
|
|
1475
1492
|
const compactRecord = await writeCompactionRecord(compactSummary, true, signal, async (actual, options) => {
|
|
1476
|
-
if (
|
|
1493
|
+
if (modelContext.worldState.generation !== generation ||
|
|
1477
1494
|
prefix.some((message, index) => messages[index] !== message))
|
|
1478
1495
|
throw new MarAgentError('MAR_AGENT_COMPACT_STALE', 'The compaction prefix has changed.');
|
|
1479
1496
|
retainedModelContext = messages
|
|
@@ -1508,32 +1525,11 @@ export function createSessionOpener(services) {
|
|
|
1508
1525
|
executionId,
|
|
1509
1526
|
turnId
|
|
1510
1527
|
}, options);
|
|
1511
|
-
|
|
1512
|
-
pendingAppends.length = 0;
|
|
1513
|
-
selected.resetContinuation?.();
|
|
1528
|
+
modelContext.replaceCompactMessages(replacementHistory, retainedModelContext);
|
|
1514
1529
|
return record;
|
|
1515
1530
|
});
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
recordedEnvironment = executionEnvironment;
|
|
1519
|
-
compactionUserMessages = replacementHistory
|
|
1520
|
-
.filter((message) => message.kind !== 'summary')
|
|
1521
|
-
.map((message) => ({
|
|
1522
|
-
content: message.content,
|
|
1523
|
-
...(message.metadata ? { metadata: { ...message.metadata } } : {})
|
|
1524
|
-
}));
|
|
1525
|
-
compactionUserMessages.push(...retainedModelContext
|
|
1526
|
-
.filter((message) => message.role === 'user' && message.contextKind === undefined)
|
|
1527
|
-
.map((message) => ({
|
|
1528
|
-
content: message.content,
|
|
1529
|
-
...(message.metadata ? { metadata: message.metadata } : {})
|
|
1530
|
-
})));
|
|
1531
|
-
await resetCompactWorldState(compactRecord.recordId, { resources: compactResources });
|
|
1532
|
-
lastServerContextTokens = undefined;
|
|
1533
|
-
lastServerUsage = undefined;
|
|
1534
|
-
smartContextTokens = undefined;
|
|
1535
|
-
requestReasoningEffort = reasoningEffort;
|
|
1536
|
-
effectiveReasoningEffort = reasoningEffort;
|
|
1531
|
+
await modelContext.adoptCompactCheckpoint(compactRecord.recordId, replacementHistory, retainedModelContext, compactResources);
|
|
1532
|
+
invalidateCompactUsage();
|
|
1537
1533
|
await emit({
|
|
1538
1534
|
type: 'context.compacted',
|
|
1539
1535
|
compactionId,
|
|
@@ -1679,7 +1675,7 @@ export function createSessionOpener(services) {
|
|
|
1679
1675
|
});
|
|
1680
1676
|
updateMcpRegistry();
|
|
1681
1677
|
executionTools = mcpRegistry.project(baseTools());
|
|
1682
|
-
await syncMcpWorldState(messages.length);
|
|
1678
|
+
await modelContext.syncMcpWorldState(messages.length);
|
|
1683
1679
|
compactBoundary = messages.length;
|
|
1684
1680
|
const blocking = compactRequests.drain((input) => startCompact({
|
|
1685
1681
|
...(input.prompt === undefined ? {} : { focus: input.prompt }),
|
|
@@ -1688,9 +1684,9 @@ export function createSessionOpener(services) {
|
|
|
1688
1684
|
if (blocking)
|
|
1689
1685
|
await compactCoordinator.checkpoint(true);
|
|
1690
1686
|
await ensureContextBudget();
|
|
1691
|
-
await syncMcpWorldState(messages.length);
|
|
1687
|
+
await modelContext.syncMcpWorldState(messages.length);
|
|
1692
1688
|
executionEnvironment = { ...currentEnvironment, ...currentLocalTimeContext() };
|
|
1693
|
-
await recordEnvironment();
|
|
1689
|
+
await modelContext.recordEnvironment();
|
|
1694
1690
|
const { roundTools, roundBindings, toolScope, composeSystemPrompt } = captureRoundToolScope();
|
|
1695
1691
|
const codeModeEnabled = roundTools.some((tool) => tool.name === 'code_exec');
|
|
1696
1692
|
const residentTools = projectTools(mcpRegistry.projectDirect(baseTools()));
|
|
@@ -1706,7 +1702,7 @@ export function createSessionOpener(services) {
|
|
|
1706
1702
|
: [...messages, pendingOutputContinuation];
|
|
1707
1703
|
sources.bind(toolScope);
|
|
1708
1704
|
const composedSystem = splitContextualPrompt(await composeSystemPrompt());
|
|
1709
|
-
const candidateWorld = updatePromptWorldState(
|
|
1705
|
+
const candidateWorld = updatePromptWorldState(modelContext.worldState, messages.length, composedSystem.parts);
|
|
1710
1706
|
const modelMessages = projectSessionRequestMessages(requestContextMessages, candidateWorld.entries, selectedModel.inputCapabilities.includes('IMAGE'), codeModeEnabled, permissionPolicy.mode === 'auto');
|
|
1711
1707
|
const systemPrompt = composedSystem.system;
|
|
1712
1708
|
const candidateRequest = {
|
|
@@ -1732,9 +1728,9 @@ export function createSessionOpener(services) {
|
|
|
1732
1728
|
preparingRequestMessages = undefined;
|
|
1733
1729
|
}
|
|
1734
1730
|
controller.signal.throwIfAborted();
|
|
1735
|
-
if (candidateWorld !==
|
|
1731
|
+
if (candidateWorld !== modelContext.worldState) {
|
|
1736
1732
|
// Commit only after request middleware accepts the entire candidate.
|
|
1737
|
-
await commitWorldState(candidateWorld);
|
|
1733
|
+
await modelContext.commitWorldState(candidateWorld);
|
|
1738
1734
|
}
|
|
1739
1735
|
const lateCoreChange = inputs.hasBoundaryCompactPending && (await appendMailboxMessages());
|
|
1740
1736
|
const lateBlocking = compactRequests.drain((input) => startCompact({
|
|
@@ -1821,28 +1817,7 @@ export function createSessionOpener(services) {
|
|
|
1821
1817
|
}
|
|
1822
1818
|
});
|
|
1823
1819
|
if (committed) {
|
|
1824
|
-
|
|
1825
|
-
selected.resetContinuation?.();
|
|
1826
|
-
const refreshed = await restoreMessages(store, sessionId, committed.records, {
|
|
1827
|
-
includeImages: true,
|
|
1828
|
-
currentTurnId: turnId,
|
|
1829
|
-
projection: committed.projection
|
|
1830
|
-
});
|
|
1831
|
-
const restoredIds = new Set(committed.records.map((record) => record.recordId));
|
|
1832
|
-
const lateMessages = pendingAppends
|
|
1833
|
-
.slice(appendBoundary)
|
|
1834
|
-
.filter((entry) => !restoredIds.has(entry.recordId))
|
|
1835
|
-
.map((entry) => entry.message);
|
|
1836
|
-
messages.splice(0, messages.length, ...refreshed.messages, ...lateMessages);
|
|
1837
|
-
restoreMcpDiscovery();
|
|
1838
|
-
recordedEnvironment = refreshed.environmentState;
|
|
1839
|
-
compactionUserMessages = [...refreshed.userMessages];
|
|
1840
|
-
agentInstructionInsertIndex = contextualInstructionInsertIndex(messages);
|
|
1841
|
-
const next = resetContextualWorldState(latestContextualWorldStateGeneration(committed.records), agentInstructionInsertIndex, {
|
|
1842
|
-
instructionSnapshot: currentInstructionSnapshot,
|
|
1843
|
-
instructionContent: renderAgentInstructions(instructionEntries, committed.records.some((record) => compactSummaryFromCheckpoint(record) !== undefined))
|
|
1844
|
-
});
|
|
1845
|
-
await commitWorldState(next);
|
|
1820
|
+
await modelContext.adoptGcCheckpoint(committed, appendBoundary);
|
|
1846
1821
|
}
|
|
1847
1822
|
}
|
|
1848
1823
|
},
|
|
@@ -1886,6 +1861,7 @@ export function createSessionOpener(services) {
|
|
|
1886
1861
|
};
|
|
1887
1862
|
}
|
|
1888
1863
|
catch (error) {
|
|
1864
|
+
failedExecution = true;
|
|
1889
1865
|
finalAnswer = executionLoop?.finalAnswer ?? finalAnswer;
|
|
1890
1866
|
acceptsMailbox = false;
|
|
1891
1867
|
acceptsSteer = false;
|
|
@@ -1897,7 +1873,8 @@ export function createSessionOpener(services) {
|
|
|
1897
1873
|
delete executionContext.compactRequests;
|
|
1898
1874
|
if (controller.signal.aborted) {
|
|
1899
1875
|
subagents?.endParentExecution(executionId);
|
|
1900
|
-
|
|
1876
|
+
// A faulted Store must not prevent result settlement or lease release.
|
|
1877
|
+
await emit({ type: 'execution.cancelled' }).catch(() => undefined);
|
|
1901
1878
|
return {
|
|
1902
1879
|
executionId,
|
|
1903
1880
|
status: 'cancelled',
|
|
@@ -1906,7 +1883,8 @@ export function createSessionOpener(services) {
|
|
|
1906
1883
|
}
|
|
1907
1884
|
const diagnostic = modelAttemptFailureDiagnostic(describeMarAgentError(error, 'MAR_AGENT_EXECUTION_FAILED'), exhaustedModelAttempt);
|
|
1908
1885
|
subagents?.endParentExecution(executionId);
|
|
1909
|
-
|
|
1886
|
+
// Keep the original diagnostic if persisting the failure terminal also fails.
|
|
1887
|
+
await emit({ type: 'execution.failed', ...diagnostic }).catch(() => undefined);
|
|
1910
1888
|
return {
|
|
1911
1889
|
executionId,
|
|
1912
1890
|
status: 'failed',
|
|
@@ -1940,12 +1918,21 @@ export function createSessionOpener(services) {
|
|
|
1940
1918
|
activeExecutionAdapters.delete(adapter);
|
|
1941
1919
|
}
|
|
1942
1920
|
subagents?.endParentExecution(executionId);
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1921
|
+
try {
|
|
1922
|
+
await releaseSession?.();
|
|
1923
|
+
}
|
|
1924
|
+
catch (error) {
|
|
1925
|
+
// Preserve the first failure/cancellation; successful executions still report release errors.
|
|
1926
|
+
if (!failedExecution)
|
|
1927
|
+
throw error;
|
|
1928
|
+
}
|
|
1929
|
+
finally {
|
|
1930
|
+
if (sessionRuntime.execution === executionContext)
|
|
1931
|
+
delete sessionRuntime.execution;
|
|
1932
|
+
active.delete(`${sessionId}:${executionId}`);
|
|
1933
|
+
sessionRuntime.sessionBackend?.kick();
|
|
1934
|
+
queue.close();
|
|
1935
|
+
}
|
|
1949
1936
|
}
|
|
1950
1937
|
});
|
|
1951
1938
|
const executionKey = `${sessionId}:${executionId}`;
|
|
@@ -2169,6 +2156,7 @@ export function createSessionOpener(services) {
|
|
|
2169
2156
|
sessionRuntime.agentsBackend ??= createExtensionAgentsBackend({
|
|
2170
2157
|
existingController: () => sessionRuntime.subagents,
|
|
2171
2158
|
controller: async () => {
|
|
2159
|
+
// Access to managed children is not a new Execution admission for their parent.
|
|
2172
2160
|
services.assertCanStart();
|
|
2173
2161
|
if (sessionRuntime.subagents === undefined)
|
|
2174
2162
|
await openSession(sessionId);
|
|
@@ -2219,11 +2207,17 @@ export function createSessionOpener(services) {
|
|
|
2219
2207
|
run: (input) => execution('run', input),
|
|
2220
2208
|
plan: (input) => execution('plan', input),
|
|
2221
2209
|
steer: (input) => sessionRuntime.execution?.steer?.(input) ?? Promise.resolve({ status: 'notAccepted' }),
|
|
2222
|
-
compact: (input = {}) =>
|
|
2223
|
-
execution
|
|
2210
|
+
compact: (input = {}) => {
|
|
2211
|
+
const requests = sessionRuntime.execution?.compactRequests;
|
|
2212
|
+
if (requests) {
|
|
2213
|
+
services.assertSessionAdmission(sessionId);
|
|
2214
|
+
return requests.request(input);
|
|
2215
|
+
}
|
|
2216
|
+
return execution('compact', {
|
|
2224
2217
|
prompt: input.prompt ?? DEFAULT_COMPACTION_FOCUS,
|
|
2225
2218
|
...input
|
|
2226
|
-
})
|
|
2219
|
+
});
|
|
2220
|
+
},
|
|
2227
2221
|
cancel: async (executionId) => active.get(`${sessionId}:${executionId}`)?.abort(),
|
|
2228
2222
|
startSubagentTurn: (turn) => execution(turn.role === 'explore' ? 'plan' : 'run', {
|
|
2229
2223
|
prompt: turn.prompt,
|