@nextclaw/kernel 0.5.1-beta.1 → 0.5.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.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +249 -96
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { APP_NAME, AgentRouteResolver, BUILTIN_MAIN_AGENT_ID, CLEAR_THINKING_TOK
|
|
|
4
4
|
import { NcpEventType, sanitizeAssistantReplyTags } from "@nextclaw/ncp";
|
|
5
5
|
import { LocalAssetStore, buildAssetContentPath, buildNcpUserContent, buildOpenAiFunctionTool, ncpMessageToOpenAiMessages, validateToolArgs } from "@nextclaw/ncp-agent-runtime";
|
|
6
6
|
import { createHash, createHmac, randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
|
|
7
|
-
import { EventBus, Ingress, eventKeys, ingressKeys, isRuntimeDefaultModelValue, normalizeRuntimeModelSelectionMode } from "@nextclaw/shared";
|
|
7
|
+
import { CHAT_SESSION_MATERIALIZATION_METADATA_KEY, EventBus, Ingress, eventKeys, ingressKeys, isRuntimeDefaultModelValue, normalizeRuntimeModelSelectionMode } from "@nextclaw/shared";
|
|
8
8
|
import { catchError, from, lastValueFrom, tap } from "rxjs";
|
|
9
9
|
import { appendFileSync, chmodSync, constants, existsSync, mkdirSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
10
10
|
import { basename, delimiter, dirname, extname, isAbsolute, join, normalize, relative, resolve } from "node:path";
|
|
@@ -584,6 +584,20 @@ function readOptionalString$10(value) {
|
|
|
584
584
|
if (typeof value !== "string") return;
|
|
585
585
|
return value.trim() || void 0;
|
|
586
586
|
}
|
|
587
|
+
function readSessionMaterialization(metadata) {
|
|
588
|
+
const value = metadata[CHAT_SESSION_MATERIALIZATION_METADATA_KEY];
|
|
589
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
590
|
+
const materialization = value;
|
|
591
|
+
if (materialization.kind !== "child") throw new Error("session_materialization.kind must be \"child\".");
|
|
592
|
+
const parentSessionId = readOptionalString$10(materialization.parentSessionId);
|
|
593
|
+
if (!parentSessionId) throw new Error("session_materialization.parentSessionId is required.");
|
|
594
|
+
if (materialization.inheritContext !== true) throw new Error("session_materialization.inheritContext must be true.");
|
|
595
|
+
return {
|
|
596
|
+
kind: "child",
|
|
597
|
+
parentSessionId,
|
|
598
|
+
inheritContext: true
|
|
599
|
+
};
|
|
600
|
+
}
|
|
587
601
|
function toRunHandle(accepted) {
|
|
588
602
|
return {
|
|
589
603
|
sessionId: accepted.sessionId,
|
|
@@ -642,18 +656,7 @@ var AgentRunRequestManager = class {
|
|
|
642
656
|
}));
|
|
643
657
|
};
|
|
644
658
|
send = async (request) => {
|
|
645
|
-
const session = await this.
|
|
646
|
-
sessionId: request.sessionId,
|
|
647
|
-
peerId: request.peerId,
|
|
648
|
-
agentId: request.agentId,
|
|
649
|
-
agentRuntimeId: request.agentRuntimeId,
|
|
650
|
-
channel: request.channel,
|
|
651
|
-
metadata: request.metadata,
|
|
652
|
-
model: request.model,
|
|
653
|
-
projectRoot: request.projectRoot,
|
|
654
|
-
task: readMessageTask(request.message),
|
|
655
|
-
thinkingEffort: request.thinkingEffort
|
|
656
|
-
});
|
|
659
|
+
const session = await this.getOrCreateSessionForRequest(request);
|
|
657
660
|
const sessionRun = this.sessionRunManager.getSessionRun(session.sessionId) ?? await this.sessionRunManager.createSessionRun(session.sessionId);
|
|
658
661
|
const message = {
|
|
659
662
|
...request.message,
|
|
@@ -763,6 +766,25 @@ var AgentRunRequestManager = class {
|
|
|
763
766
|
correlationId: request.correlationId
|
|
764
767
|
};
|
|
765
768
|
};
|
|
769
|
+
getOrCreateSessionForRequest = async (request) => {
|
|
770
|
+
const sessionMaterialization = readSessionMaterialization(request.metadata ?? {});
|
|
771
|
+
if (sessionMaterialization && (request.sessionId || request.peerId)) throw new Error("session_materialization requires a new session request.");
|
|
772
|
+
return await this.sessionManager.getOrCreateAgentRunSession({
|
|
773
|
+
sessionId: request.sessionId,
|
|
774
|
+
peerId: request.peerId,
|
|
775
|
+
agentId: request.agentId,
|
|
776
|
+
agentRuntimeId: request.agentRuntimeId,
|
|
777
|
+
channel: request.channel,
|
|
778
|
+
contextInheritance: sessionMaterialization ? {} : void 0,
|
|
779
|
+
metadata: request.metadata,
|
|
780
|
+
model: request.model,
|
|
781
|
+
parentSessionId: sessionMaterialization?.parentSessionId,
|
|
782
|
+
projectRoot: request.projectRoot,
|
|
783
|
+
sourceSessionId: sessionMaterialization?.parentSessionId,
|
|
784
|
+
task: readMessageTask(request.message),
|
|
785
|
+
thinkingEffort: request.thinkingEffort
|
|
786
|
+
});
|
|
787
|
+
};
|
|
766
788
|
abort = async (request) => {
|
|
767
789
|
this.sessionRunManager.getSessionRun(request.sessionId)?.abortRun(request.runId);
|
|
768
790
|
};
|
|
@@ -3433,29 +3455,53 @@ function upsertNcpAgentSessionSummaryEvent(params) {
|
|
|
3433
3455
|
async function replayNcpAgentSessionEvents(events) {
|
|
3434
3456
|
const stateManager = new DefaultNcpAgentConversationStateManager();
|
|
3435
3457
|
const knownMessageIds = /* @__PURE__ */ new Set();
|
|
3458
|
+
const toolResultsByCallId = /* @__PURE__ */ new Map();
|
|
3436
3459
|
for (const event of events) {
|
|
3437
3460
|
if (isJournalOnlyEvent(event)) continue;
|
|
3438
|
-
const replayEvent = createReplayEvent(event);
|
|
3461
|
+
const replayEvent = createReplayEvent(event, toolResultsByCallId);
|
|
3439
3462
|
const bootstrapEvent = createReplayStreamingBootstrapEvent(replayEvent, knownMessageIds);
|
|
3440
3463
|
if (bootstrapEvent) await stateManager.dispatch(bootstrapEvent);
|
|
3441
3464
|
rememberReplayMessageId(replayEvent, knownMessageIds);
|
|
3442
3465
|
await stateManager.dispatch(replayEvent);
|
|
3466
|
+
if (replayEvent.type === NcpEventType.MessageToolCallResult) toolResultsByCallId.set(replayEvent.payload.toolCallId, replayEvent.payload);
|
|
3443
3467
|
}
|
|
3444
3468
|
const snapshot = stateManager.getSnapshot();
|
|
3445
3469
|
return [...snapshot.messages.map((message) => structuredClone(message)), ...snapshot.streamingMessage ? [structuredClone(snapshot.streamingMessage)] : []];
|
|
3446
3470
|
}
|
|
3447
|
-
function createReplayEvent(event) {
|
|
3471
|
+
function createReplayEvent(event, toolResultsByCallId) {
|
|
3448
3472
|
const replayEvent = structuredClone(event);
|
|
3449
3473
|
const replayMessage = readMessageFromSummaryEvent(replayEvent);
|
|
3450
3474
|
const legacyCompactionMessageId = readLegacyContextCompactionMessageId(replayMessage);
|
|
3451
3475
|
if (replayMessage && legacyCompactionMessageId) replayMessage.id = legacyCompactionMessageId;
|
|
3452
3476
|
if (replayMessage?.role === "assistant" && (replayMessage.status === "pending" || replayMessage.status === "streaming")) replayMessage.status = "final";
|
|
3453
|
-
if (replayEvent.type === "session.snapshot.message" || replayEvent.type === NcpEventType.MessageCompleted)
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3477
|
+
if (replayEvent.type === "session.snapshot.message" || replayEvent.type === NcpEventType.MessageCompleted) {
|
|
3478
|
+
replayEvent.payload.message = mergeReplayCompletedToolResults(replayEvent.payload.message, toolResultsByCallId);
|
|
3479
|
+
return {
|
|
3480
|
+
type: NcpEventType.MessageSent,
|
|
3481
|
+
payload: replayEvent.payload
|
|
3482
|
+
};
|
|
3483
|
+
}
|
|
3457
3484
|
return replayEvent;
|
|
3458
3485
|
}
|
|
3486
|
+
function mergeReplayCompletedToolResults(message, toolResultsByCallId) {
|
|
3487
|
+
let changed = false;
|
|
3488
|
+
const parts = message.parts.map((part) => {
|
|
3489
|
+
if (part.type !== "tool-invocation" || part.state === "result" || !part.toolCallId) return part;
|
|
3490
|
+
const result = toolResultsByCallId.get(part.toolCallId);
|
|
3491
|
+
if (!result) return part;
|
|
3492
|
+
changed = true;
|
|
3493
|
+
return {
|
|
3494
|
+
...part,
|
|
3495
|
+
state: "result",
|
|
3496
|
+
result: result.content,
|
|
3497
|
+
resultContentItems: result.contentItems
|
|
3498
|
+
};
|
|
3499
|
+
});
|
|
3500
|
+
return changed ? {
|
|
3501
|
+
...message,
|
|
3502
|
+
parts
|
|
3503
|
+
} : message;
|
|
3504
|
+
}
|
|
3459
3505
|
function readLegacyContextCompactionMessageId(message) {
|
|
3460
3506
|
const checkpoint = isRecord$11(message?.metadata?.checkpoint) ? message.metadata.checkpoint : null;
|
|
3461
3507
|
const checkpointId = typeof checkpoint?.id === "string" ? checkpoint.id : "";
|
|
@@ -3557,6 +3603,144 @@ function readOptionalMetadataString(value) {
|
|
|
3557
3603
|
function readEventSessionId$1(event) {
|
|
3558
3604
|
return "payload" in event && "sessionId" in event.payload ? readOptionalMetadataString(event.payload.sessionId) : void 0;
|
|
3559
3605
|
}
|
|
3606
|
+
const DEFAULT_SESSION_LIFECYCLE = "persistent";
|
|
3607
|
+
const SESSION_METADATA_LABEL_KEY = "label";
|
|
3608
|
+
const CHILD_SESSION_PARENT_METADATA_KEY = "parent_session_id";
|
|
3609
|
+
const CHILD_SESSION_REQUEST_METADATA_KEY = "spawned_by_request_id";
|
|
3610
|
+
const CHILD_SESSION_LIFECYCLE_METADATA_KEY = "session_lifecycle";
|
|
3611
|
+
function readThinkingEffort(metadata) {
|
|
3612
|
+
return readOptionalMetadataString(metadata?.thinkingEffort) ?? readOptionalMetadataString(metadata?.preferred_thinking) ?? readOptionalMetadataString(metadata?.thinking) ?? null;
|
|
3613
|
+
}
|
|
3614
|
+
function readProjectRoot(metadata) {
|
|
3615
|
+
return readOptionalMetadataString(metadata?.project_root) ?? readOptionalMetadataString(metadata?.projectRoot);
|
|
3616
|
+
}
|
|
3617
|
+
function readAgentRuntimeId(metadata) {
|
|
3618
|
+
return readOptionalMetadataString(metadata?.agentRuntimeId) ?? readOptionalMetadataString(metadata?.runtime) ?? readOptionalMetadataString(metadata?.session_type);
|
|
3619
|
+
}
|
|
3620
|
+
function summarizeTask(task) {
|
|
3621
|
+
const normalized = task.trim().replace(/\s+/g, " ");
|
|
3622
|
+
if (!normalized) return "Session";
|
|
3623
|
+
return normalized.length <= 72 ? normalized : `${normalized.slice(0, 69)}...`;
|
|
3624
|
+
}
|
|
3625
|
+
function cloneInheritedMetadata(sourceMetadata) {
|
|
3626
|
+
const nextMetadata = {};
|
|
3627
|
+
for (const key of [
|
|
3628
|
+
"runtime",
|
|
3629
|
+
"session_type",
|
|
3630
|
+
"preferred_model",
|
|
3631
|
+
"preferred_thinking",
|
|
3632
|
+
"project_root",
|
|
3633
|
+
"requested_skill_refs",
|
|
3634
|
+
"codex_runtime_backend",
|
|
3635
|
+
"reasoningNormalizationMode",
|
|
3636
|
+
"reasoning_normalization_mode"
|
|
3637
|
+
]) if (Object.prototype.hasOwnProperty.call(sourceMetadata, key)) nextMetadata[key] = structuredClone(sourceMetadata[key]);
|
|
3638
|
+
return nextMetadata;
|
|
3639
|
+
}
|
|
3640
|
+
function mergeMetadataOverrides(metadata, overrides) {
|
|
3641
|
+
return overrides && Object.keys(overrides).length > 0 ? {
|
|
3642
|
+
...metadata,
|
|
3643
|
+
...structuredClone(overrides)
|
|
3644
|
+
} : metadata;
|
|
3645
|
+
}
|
|
3646
|
+
function resolveSessionType(params) {
|
|
3647
|
+
const { metadata, runtime, sessionType } = params;
|
|
3648
|
+
return readOptionalString$8(runtime) ?? readOptionalString$8(metadata.runtime) ?? readOptionalString$8(sessionType) ?? readOptionalString$8(metadata.session_type) ?? "native";
|
|
3649
|
+
}
|
|
3650
|
+
function applySessionOverrides(params) {
|
|
3651
|
+
const { lifecycle, metadata, model, parentSessionId, projectRoot, requestId, sessionType, thinkingLevel, title } = params;
|
|
3652
|
+
metadata.session_type = sessionType;
|
|
3653
|
+
metadata.runtime = sessionType;
|
|
3654
|
+
metadata[SESSION_METADATA_LABEL_KEY] = title;
|
|
3655
|
+
metadata[CHILD_SESSION_LIFECYCLE_METADATA_KEY] = lifecycle;
|
|
3656
|
+
if (parentSessionId) metadata[CHILD_SESSION_PARENT_METADATA_KEY] = parentSessionId;
|
|
3657
|
+
if (requestId) metadata[CHILD_SESSION_REQUEST_METADATA_KEY] = requestId;
|
|
3658
|
+
if (readOptionalString$8(model)) {
|
|
3659
|
+
metadata.model = model?.trim();
|
|
3660
|
+
metadata.preferred_model = model?.trim();
|
|
3661
|
+
}
|
|
3662
|
+
if (readOptionalString$8(thinkingLevel)) {
|
|
3663
|
+
metadata.thinking = thinkingLevel?.trim();
|
|
3664
|
+
metadata.preferred_thinking = thinkingLevel?.trim();
|
|
3665
|
+
}
|
|
3666
|
+
if (readOptionalString$8(projectRoot)) metadata.project_root = projectRoot?.trim();
|
|
3667
|
+
}
|
|
3668
|
+
//#endregion
|
|
3669
|
+
//#region src/utils/session-context-inheritance.utils.ts
|
|
3670
|
+
const CONTEXT_INHERITANCE_METADATA_KEY = "context_inheritance";
|
|
3671
|
+
const INHERITED_FROM_SESSION_METADATA_KEY = "inherited_from_session_id";
|
|
3672
|
+
const INHERITED_FROM_MESSAGE_METADATA_KEY = "inherited_from_message_id";
|
|
3673
|
+
function hasToolCall(message, toolCallId) {
|
|
3674
|
+
return message.parts.some((part) => part.type === "tool-invocation" && part.toolCallId === toolCallId);
|
|
3675
|
+
}
|
|
3676
|
+
function findContextInheritanceAnchor(params) {
|
|
3677
|
+
const anchorToolCallId = readOptionalString$8(params.anchorToolCallId);
|
|
3678
|
+
if (!anchorToolCallId) return null;
|
|
3679
|
+
const index = params.messages.findIndex((message) => hasToolCall(message, anchorToolCallId));
|
|
3680
|
+
const message = index >= 0 ? params.messages[index] : void 0;
|
|
3681
|
+
return message ? {
|
|
3682
|
+
index,
|
|
3683
|
+
message
|
|
3684
|
+
} : null;
|
|
3685
|
+
}
|
|
3686
|
+
function createInheritedContextMessage(params) {
|
|
3687
|
+
const { childSessionId, index, sourceMessage, sourceSessionId } = params;
|
|
3688
|
+
const message = structuredClone(sourceMessage);
|
|
3689
|
+
const metadata = structuredClone(message.metadata ?? {});
|
|
3690
|
+
metadata[INHERITED_FROM_SESSION_METADATA_KEY] = sourceSessionId;
|
|
3691
|
+
metadata[INHERITED_FROM_MESSAGE_METADATA_KEY] = sourceMessage.id;
|
|
3692
|
+
return {
|
|
3693
|
+
...message,
|
|
3694
|
+
id: `${childSessionId}:inherited:${index + 1}`,
|
|
3695
|
+
sessionId: childSessionId,
|
|
3696
|
+
metadata
|
|
3697
|
+
};
|
|
3698
|
+
}
|
|
3699
|
+
function createInheritedContextSnapshot(params) {
|
|
3700
|
+
const { anchorToolCallId, childSessionId, sourceRecord } = params;
|
|
3701
|
+
const anchor = findContextInheritanceAnchor({
|
|
3702
|
+
anchorToolCallId,
|
|
3703
|
+
messages: sourceRecord.messages
|
|
3704
|
+
});
|
|
3705
|
+
const messages = (anchor ? sourceRecord.messages.slice(0, anchor.index) : sourceRecord.messages).filter((message) => message.status === "final").map((sourceMessage, index) => createInheritedContextMessage({
|
|
3706
|
+
childSessionId,
|
|
3707
|
+
index,
|
|
3708
|
+
sourceMessage,
|
|
3709
|
+
sourceSessionId: sourceRecord.sessionId
|
|
3710
|
+
}));
|
|
3711
|
+
return {
|
|
3712
|
+
messages,
|
|
3713
|
+
metadata: {
|
|
3714
|
+
enabled: true,
|
|
3715
|
+
sourceSessionId: sourceRecord.sessionId,
|
|
3716
|
+
anchorKind: anchor ? "tool_call" : "latest_persisted",
|
|
3717
|
+
anchorToolCallId: readOptionalString$8(anchorToolCallId),
|
|
3718
|
+
anchorMessageId: anchor?.message.id,
|
|
3719
|
+
inheritedMessageCount: messages.length
|
|
3720
|
+
}
|
|
3721
|
+
};
|
|
3722
|
+
}
|
|
3723
|
+
function createSessionContextInheritance(params) {
|
|
3724
|
+
const { childSessionId, contextInheritance, metadata, parentSessionId, sourceRecord } = params;
|
|
3725
|
+
if (!contextInheritance) return {
|
|
3726
|
+
messages: [],
|
|
3727
|
+
metadata
|
|
3728
|
+
};
|
|
3729
|
+
if (!parentSessionId) throw new Error("contextInheritance requires a child session parentSessionId.");
|
|
3730
|
+
if (!sourceRecord) throw new Error("Cannot inherit context because the source session was not found.");
|
|
3731
|
+
const snapshot = createInheritedContextSnapshot({
|
|
3732
|
+
anchorToolCallId: contextInheritance.anchorToolCallId,
|
|
3733
|
+
childSessionId,
|
|
3734
|
+
sourceRecord
|
|
3735
|
+
});
|
|
3736
|
+
return {
|
|
3737
|
+
messages: snapshot.messages,
|
|
3738
|
+
metadata: {
|
|
3739
|
+
...metadata,
|
|
3740
|
+
[CONTEXT_INHERITANCE_METADATA_KEY]: snapshot.metadata
|
|
3741
|
+
}
|
|
3742
|
+
};
|
|
3743
|
+
}
|
|
3560
3744
|
//#endregion
|
|
3561
3745
|
//#region src/contributions/session-activity-preview/utils/session-activity-preview-ncp-event.utils.ts
|
|
3562
3746
|
const PREVIEW_TEXT_MAX_LENGTH = 160;
|
|
@@ -3836,69 +4020,9 @@ var SessionWorkingDirResolver = class {
|
|
|
3836
4020
|
};
|
|
3837
4021
|
//#endregion
|
|
3838
4022
|
//#region src/managers/session.manager.ts
|
|
3839
|
-
const DEFAULT_SESSION_TYPE = "native";
|
|
3840
|
-
const DEFAULT_LIFECYCLE = "persistent";
|
|
3841
|
-
const SESSION_METADATA_LABEL_KEY = "label";
|
|
3842
|
-
const CHILD_SESSION_PARENT_METADATA_KEY = "parent_session_id";
|
|
3843
|
-
const CHILD_SESSION_REQUEST_METADATA_KEY = "spawned_by_request_id";
|
|
3844
|
-
const CHILD_SESSION_LIFECYCLE_METADATA_KEY = "session_lifecycle";
|
|
3845
|
-
function readThinkingEffort(metadata) {
|
|
3846
|
-
return readOptionalMetadataString(metadata?.thinkingEffort) ?? null;
|
|
3847
|
-
}
|
|
3848
|
-
function readProjectRoot(metadata) {
|
|
3849
|
-
return readOptionalMetadataString(metadata?.project_root) ?? readOptionalMetadataString(metadata?.projectRoot);
|
|
3850
|
-
}
|
|
3851
|
-
function summarizeTask(task) {
|
|
3852
|
-
const normalized = task.trim().replace(/\s+/g, " ");
|
|
3853
|
-
if (!normalized) return "Session";
|
|
3854
|
-
return normalized.length <= 72 ? normalized : `${normalized.slice(0, 69)}...`;
|
|
3855
|
-
}
|
|
3856
4023
|
function buildSessionId() {
|
|
3857
4024
|
return `ncp-${Date.now().toString(36)}-${randomUUID().replace(/-/g, "").slice(0, 8)}`;
|
|
3858
4025
|
}
|
|
3859
|
-
function cloneInheritedMetadata(sourceMetadata) {
|
|
3860
|
-
const nextMetadata = {};
|
|
3861
|
-
for (const key of [
|
|
3862
|
-
"runtime",
|
|
3863
|
-
"session_type",
|
|
3864
|
-
"preferred_model",
|
|
3865
|
-
"preferred_thinking",
|
|
3866
|
-
"project_root",
|
|
3867
|
-
"requested_skill_refs",
|
|
3868
|
-
"codex_runtime_backend",
|
|
3869
|
-
"reasoningNormalizationMode",
|
|
3870
|
-
"reasoning_normalization_mode"
|
|
3871
|
-
]) if (Object.prototype.hasOwnProperty.call(sourceMetadata, key)) nextMetadata[key] = structuredClone(sourceMetadata[key]);
|
|
3872
|
-
return nextMetadata;
|
|
3873
|
-
}
|
|
3874
|
-
function mergeMetadataOverrides(metadata, overrides) {
|
|
3875
|
-
return overrides && Object.keys(overrides).length > 0 ? {
|
|
3876
|
-
...metadata,
|
|
3877
|
-
...structuredClone(overrides)
|
|
3878
|
-
} : metadata;
|
|
3879
|
-
}
|
|
3880
|
-
function resolveSessionType(params) {
|
|
3881
|
-
const { metadata, runtime, sessionType } = params;
|
|
3882
|
-
return readOptionalString$8(runtime) ?? readOptionalString$8(metadata.runtime) ?? readOptionalString$8(sessionType) ?? readOptionalString$8(metadata.session_type) ?? DEFAULT_SESSION_TYPE;
|
|
3883
|
-
}
|
|
3884
|
-
function applySessionOverrides(params) {
|
|
3885
|
-
const { lifecycle, metadata, model, parentSessionId, projectRoot, requestId, sessionType, thinkingLevel, title } = params;
|
|
3886
|
-
metadata.session_type = sessionType;
|
|
3887
|
-
metadata.runtime = sessionType;
|
|
3888
|
-
metadata[SESSION_METADATA_LABEL_KEY] = title;
|
|
3889
|
-
metadata[CHILD_SESSION_LIFECYCLE_METADATA_KEY] = lifecycle;
|
|
3890
|
-
if (parentSessionId) metadata[CHILD_SESSION_PARENT_METADATA_KEY] = parentSessionId;
|
|
3891
|
-
if (requestId) metadata[CHILD_SESSION_REQUEST_METADATA_KEY] = requestId;
|
|
3892
|
-
if (readOptionalString$8(model)) {
|
|
3893
|
-
metadata.model = model?.trim();
|
|
3894
|
-
metadata.preferred_model = model?.trim();
|
|
3895
|
-
}
|
|
3896
|
-
if (readOptionalString$8(thinkingLevel)) {
|
|
3897
|
-
metadata.thinking = thinkingLevel?.trim();
|
|
3898
|
-
metadata.preferred_thinking = thinkingLevel?.trim();
|
|
3899
|
-
}
|
|
3900
|
-
if (readOptionalString$8(projectRoot)) metadata.project_root = projectRoot?.trim();
|
|
3901
|
-
}
|
|
3902
4026
|
function isSessionSummaryRefreshEvent(event) {
|
|
3903
4027
|
switch (event.type) {
|
|
3904
4028
|
case NcpEventType.MessageSent:
|
|
@@ -3940,7 +4064,7 @@ var SessionManager = class {
|
|
|
3940
4064
|
this.started = false;
|
|
3941
4065
|
};
|
|
3942
4066
|
createSession = async (params) => {
|
|
3943
|
-
const { agentId: requestedAgentId, metadataOverrides, model, parentSessionId: rawParentSessionId, projectRoot, requestId: rawRequestId, runtime, sessionId: requestedSessionId, sessionType: requestedSessionType, sourceSessionId, sourceSessionMetadata, task, thinkingLevel, title: requestedTitle } = params;
|
|
4067
|
+
const { agentId: requestedAgentId, contextInheritance, metadataOverrides, model, parentSessionId: rawParentSessionId, projectRoot, requestId: rawRequestId, runtime, sessionId: requestedSessionId, sessionType: requestedSessionType, sourceSessionId, sourceSessionMetadata, task, thinkingLevel, title: requestedTitle } = params;
|
|
3944
4068
|
const sourceRecord = sourceSessionId ? await this.getSessionRecord(sourceSessionId) : null;
|
|
3945
4069
|
const metadata = cloneInheritedMetadata(sourceSessionMetadata);
|
|
3946
4070
|
const title = readOptionalString$8(requestedTitle) ?? summarizeTask(task);
|
|
@@ -3952,7 +4076,7 @@ var SessionManager = class {
|
|
|
3952
4076
|
metadata
|
|
3953
4077
|
});
|
|
3954
4078
|
applySessionOverrides({
|
|
3955
|
-
lifecycle:
|
|
4079
|
+
lifecycle: DEFAULT_SESSION_LIFECYCLE,
|
|
3956
4080
|
metadata,
|
|
3957
4081
|
model,
|
|
3958
4082
|
parentSessionId: parentSessionId ?? void 0,
|
|
@@ -3966,13 +4090,20 @@ var SessionManager = class {
|
|
|
3966
4090
|
const nextMetadata = mergeMetadataOverrides(metadata, metadataOverrides);
|
|
3967
4091
|
const agentId = readOptionalString$8(requestedAgentId) ?? readOptionalString$8(sourceRecord?.agentId) ?? BUILTIN_MAIN_AGENT_ID;
|
|
3968
4092
|
const sessionId = readOptionalString$8(requestedSessionId) ?? buildSessionId();
|
|
4093
|
+
const inheritedContext = createSessionContextInheritance({
|
|
4094
|
+
childSessionId: sessionId,
|
|
4095
|
+
contextInheritance,
|
|
4096
|
+
metadata: nextMetadata,
|
|
4097
|
+
parentSessionId,
|
|
4098
|
+
sourceRecord
|
|
4099
|
+
});
|
|
3969
4100
|
const record = {
|
|
3970
4101
|
sessionId,
|
|
3971
4102
|
...agentId ? { agentId } : {},
|
|
3972
|
-
messages:
|
|
4103
|
+
messages: inheritedContext.messages,
|
|
3973
4104
|
createdAt: now,
|
|
3974
4105
|
updatedAt: now,
|
|
3975
|
-
metadata:
|
|
4106
|
+
metadata: inheritedContext.metadata
|
|
3976
4107
|
};
|
|
3977
4108
|
await this.options.journalStore.importSessionSnapshot(record);
|
|
3978
4109
|
await this.publishSessionChange(sessionId);
|
|
@@ -3980,12 +4111,12 @@ var SessionManager = class {
|
|
|
3980
4111
|
sessionId,
|
|
3981
4112
|
agentId,
|
|
3982
4113
|
sessionType,
|
|
3983
|
-
runtimeFamily: sessionType ===
|
|
4114
|
+
runtimeFamily: sessionType === "native" ? "native" : "external",
|
|
3984
4115
|
...parentSessionId ? { parentSessionId } : {},
|
|
3985
4116
|
...requestId ? { spawnedByRequestId: requestId } : {},
|
|
3986
|
-
lifecycle:
|
|
4117
|
+
lifecycle: DEFAULT_SESSION_LIFECYCLE,
|
|
3987
4118
|
title,
|
|
3988
|
-
metadata:
|
|
4119
|
+
metadata: inheritedContext.metadata,
|
|
3989
4120
|
createdAt: now,
|
|
3990
4121
|
updatedAt: now
|
|
3991
4122
|
};
|
|
@@ -4073,9 +4204,13 @@ var SessionManager = class {
|
|
|
4073
4204
|
};
|
|
4074
4205
|
};
|
|
4075
4206
|
createAgentRunSession = async (params) => {
|
|
4076
|
-
const { agentId, agentRuntimeId: requestedAgentRuntimeId, channel, metadata, model, peerId: rawPeerId, projectRoot, sessionId, task, thinkingEffort } = params;
|
|
4077
|
-
const agentRuntimeId = requestedAgentRuntimeId ?? "native";
|
|
4207
|
+
const { agentId, agentRuntimeId: requestedAgentRuntimeId, channel, contextInheritance, metadata, model, parentSessionId: rawParentSessionId, peerId: rawPeerId, projectRoot, sessionId, sourceSessionId: rawSourceSessionId, sourceSessionMetadata: requestedSourceSessionMetadata, task, thinkingEffort } = params;
|
|
4078
4208
|
const peerId = readOptionalString$8(rawPeerId);
|
|
4209
|
+
const parentSessionId = readOptionalString$8(rawParentSessionId);
|
|
4210
|
+
const sourceSessionId = readOptionalString$8(rawSourceSessionId);
|
|
4211
|
+
const sourceRecord = sourceSessionId ? await this.getSessionRecord(sourceSessionId) : null;
|
|
4212
|
+
const sourceSessionMetadata = requestedSourceSessionMetadata ?? sourceRecord?.metadata ?? {};
|
|
4213
|
+
const agentRuntimeId = requestedAgentRuntimeId ?? readAgentRuntimeId(sourceSessionMetadata) ?? "native";
|
|
4079
4214
|
const peerIdentity = peerId ? createAgentPeerSessionIdentity({
|
|
4080
4215
|
agentId,
|
|
4081
4216
|
channel,
|
|
@@ -4084,7 +4219,10 @@ var SessionManager = class {
|
|
|
4084
4219
|
}) : void 0;
|
|
4085
4220
|
const requestedSessionId = readOptionalString$8(sessionId);
|
|
4086
4221
|
const created = await this.createSession({
|
|
4087
|
-
|
|
4222
|
+
contextInheritance,
|
|
4223
|
+
parentSessionId: parentSessionId ?? void 0,
|
|
4224
|
+
sourceSessionId: sourceSessionId ?? void 0,
|
|
4225
|
+
sourceSessionMetadata,
|
|
4088
4226
|
sessionId: requestedSessionId ?? peerIdentity?.sessionId,
|
|
4089
4227
|
task: task ?? "Session",
|
|
4090
4228
|
agentId,
|
|
@@ -4100,16 +4238,16 @@ var SessionManager = class {
|
|
|
4100
4238
|
});
|
|
4101
4239
|
return {
|
|
4102
4240
|
sessionId: created.sessionId,
|
|
4103
|
-
agentId,
|
|
4241
|
+
agentId: created.agentId,
|
|
4104
4242
|
agentRuntimeId,
|
|
4105
4243
|
metadata: structuredClone(created.metadata ?? {}),
|
|
4106
|
-
model,
|
|
4107
|
-
projectRoot,
|
|
4244
|
+
model: model ?? readOptionalMetadataString(created.metadata?.model) ?? readOptionalMetadataString(created.metadata?.preferred_model),
|
|
4245
|
+
projectRoot: projectRoot ?? readProjectRoot(created.metadata),
|
|
4108
4246
|
workingDir: this.workingDirResolver.resolve({
|
|
4109
|
-
agentId,
|
|
4247
|
+
agentId: created.agentId,
|
|
4110
4248
|
metadata: created.metadata
|
|
4111
4249
|
}),
|
|
4112
|
-
thinkingEffort: thinkingEffort ??
|
|
4250
|
+
thinkingEffort: thinkingEffort ?? readThinkingEffort(created.metadata)
|
|
4113
4251
|
};
|
|
4114
4252
|
};
|
|
4115
4253
|
getOrCreateAgentRunSession = async (params) => {
|
|
@@ -7127,7 +7265,7 @@ var SessionRequestManager = class {
|
|
|
7127
7265
|
this.options = options;
|
|
7128
7266
|
}
|
|
7129
7267
|
spawnSessionAndRequest = async (params) => {
|
|
7130
|
-
const { sourceSessionId, sourceToolCallId, updateToolCallResult, sourceSessionMetadata, metadataOverrides, task, title, model, runtime, handoffDepth, sessionType, thinkingLevel, projectRoot, agentId, parentSessionId, notify } = params;
|
|
7268
|
+
const { sourceSessionId, sourceToolCallId, updateToolCallResult, sourceSessionMetadata, metadataOverrides, contextInheritance, task, title, model, runtime, handoffDepth, sessionType, thinkingLevel, projectRoot, agentId, parentSessionId, notify } = params;
|
|
7131
7269
|
const requestId = randomUUID();
|
|
7132
7270
|
const createdSession = await this.options.sessionManager.createSession({
|
|
7133
7271
|
sourceSessionId,
|
|
@@ -7136,6 +7274,7 @@ var SessionRequestManager = class {
|
|
|
7136
7274
|
title,
|
|
7137
7275
|
sourceSessionMetadata,
|
|
7138
7276
|
...metadataOverrides ? { metadataOverrides } : {},
|
|
7277
|
+
contextInheritance,
|
|
7139
7278
|
agentId,
|
|
7140
7279
|
model,
|
|
7141
7280
|
runtime,
|
|
@@ -9510,6 +9649,11 @@ function readSpawnNotify(value) {
|
|
|
9510
9649
|
if (notifyMode === "none" || notifyMode === "final_reply") return notifyMode;
|
|
9511
9650
|
throw new Error("notify must be \"none\" or \"final_reply\".");
|
|
9512
9651
|
}
|
|
9652
|
+
function readInheritContext(value) {
|
|
9653
|
+
if (typeof value === "undefined") return false;
|
|
9654
|
+
if (typeof value === "boolean") return value;
|
|
9655
|
+
throw new Error("inheritContext must be a boolean.");
|
|
9656
|
+
}
|
|
9513
9657
|
var SessionSpawnTool = class {
|
|
9514
9658
|
name = "sessions_spawn";
|
|
9515
9659
|
description = "Create a new session. Use scope=\"child\" to create a child session of the current flow, and add notify when the new session should start immediately.";
|
|
@@ -9545,6 +9689,10 @@ var SessionSpawnTool = class {
|
|
|
9545
9689
|
type: "string",
|
|
9546
9690
|
enum: ["none", "final_reply"],
|
|
9547
9691
|
description: "Optional. Starts the new session immediately. Use \"final_reply\" to continue this session after the new session reaches its final reply, or \"none\" to let it run independently."
|
|
9692
|
+
},
|
|
9693
|
+
inheritContext: {
|
|
9694
|
+
type: "boolean",
|
|
9695
|
+
description: "Child sessions only. When true, the child starts with parent context inherited up to this tool call."
|
|
9548
9696
|
}
|
|
9549
9697
|
},
|
|
9550
9698
|
required: ["task"],
|
|
@@ -9563,11 +9711,14 @@ var SessionSpawnTool = class {
|
|
|
9563
9711
|
this.handoffDepth = params.handoffDepth ?? 0;
|
|
9564
9712
|
};
|
|
9565
9713
|
execute = async (args, context) => {
|
|
9566
|
-
const { agentId: rawAgentId, model: rawModel, notify: rawNotify, runtime: rawRuntime, scope: rawScope, task: rawTask, title: rawTitle } = normalizeToolParams(args);
|
|
9714
|
+
const { agentId: rawAgentId, model: rawModel, notify: rawNotify, runtime: rawRuntime, scope: rawScope, task: rawTask, title: rawTitle, inheritContext: rawInheritContext } = normalizeToolParams(args);
|
|
9567
9715
|
const task = readRequiredString$1(rawTask, "task");
|
|
9568
9716
|
const scope = readSpawnScope(rawScope);
|
|
9569
9717
|
const notify = readSpawnNotify(rawNotify);
|
|
9718
|
+
const inheritContext = readInheritContext(rawInheritContext);
|
|
9719
|
+
if (inheritContext && scope !== "child") throw new Error("inheritContext=true requires scope=\"child\".");
|
|
9570
9720
|
const parentSessionId = scope === "child" ? this.readParentSessionIdOrThrow() : void 0;
|
|
9721
|
+
const contextInheritance = inheritContext ? { anchorToolCallId: context?.toolCallId } : void 0;
|
|
9571
9722
|
if (notify) return this.sessionRequestManager.spawnSessionAndRequest({
|
|
9572
9723
|
sourceSessionId: this.sourceSessionId,
|
|
9573
9724
|
sourceToolCallId: context?.toolCallId,
|
|
@@ -9578,6 +9729,7 @@ var SessionSpawnTool = class {
|
|
|
9578
9729
|
agentId: readOptionalString$2(rawAgentId),
|
|
9579
9730
|
model: readOptionalString$2(rawModel),
|
|
9580
9731
|
runtime: readOptionalString$2(rawRuntime),
|
|
9732
|
+
contextInheritance,
|
|
9581
9733
|
handoffDepth: this.handoffDepth,
|
|
9582
9734
|
parentSessionId,
|
|
9583
9735
|
notify
|
|
@@ -9590,6 +9742,7 @@ var SessionSpawnTool = class {
|
|
|
9590
9742
|
agentId: readOptionalString$2(rawAgentId),
|
|
9591
9743
|
model: readOptionalString$2(rawModel),
|
|
9592
9744
|
runtime: readOptionalString$2(rawRuntime),
|
|
9745
|
+
contextInheritance,
|
|
9593
9746
|
parentSessionId
|
|
9594
9747
|
});
|
|
9595
9748
|
return {
|