@nextclaw/kernel 0.5.1 → 0.5.3

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.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { n as getUnsignedUpdateManifest, r as serializeUnsignedUpdateManifest, t as UpdateManifestReader } from "./update-manifest.types-C0qPrjGQ.js";
2
2
  import { createRequire } from "node:module";
3
- import { APP_NAME, AgentRouteResolver, BUILTIN_MAIN_AGENT_ID, CLEAR_THINKING_TOKENS, CONTEXT_COMPACTION_METADATA_KEY, ConfigSchema, ContextCompactionService, ContextWindowBudgetService, CronService, CronTool, DEFAULT_PANELS_DIR, DEFAULT_SERVICE_APPS_DIR, DEFAULT_SESSION_SEARCH_LIMIT, DEFAULT_WORKSPACE_REPOSITORY_IDENTITY_RESOLVER, EditFileTool, ExecTool, ExtensionChannelAdapter, GatewayTool, InputBudgetPruner, LLMProvider, ListDirTool, LiteLLMProvider, MAX_SESSION_SEARCH_LIMIT, MemoryGetTool, MemorySearchTool, MemoryStore, MessageBus, MessageTool, ProviderRegistry, ReadFileTool, RequestedSkillsMetadataReader, SILENT_REPLY_TOKEN, SessionProjectContextResolver, SessionSearchService, SkillsLoader, THINKING_LEVELS, WebFetchTool, WebSearchTool, WriteFileTool, buildCompressingCompactionCheckpoint, buildConfigSchema, buildContextWindowSnapshot, buildReloadPlan, buildSessionRequestToolResult, buildToolCatalogEntries, createAgentProfile, createAssistantStreamDeltaControlMessage, createAssistantStreamResetControlMessage, createCompletedSessionRequest, createFailedSessionRequest, createRunningSessionRequest, createRuntimeChildEnv, createTypingStopControlMessage, diffConfigPaths, ensureDir, evaluateSilentReply, expandHome, findEffectiveAgentProfile, getConfigPath, getDataDir, getDataPath, getSessionsPath, getWorkspacePath, getWorkspacePathFromConfig, isNextclawControlMessage, loadConfig, mergeExtensionConfigView, modelSupportsVision, normalizeAgentProfileId, normalizeInlineSecretRefs, normalizeModelThinkingCapability, normalizeProviderModelConfig, normalizeToolParams, parseAgentScopedSessionKey, parseThinkingLevel, readCompressedContextCompactionCheckpoint, readOptionalString, readParentSessionId, readSessionProjectRoot, redactConfigObject, removeAgentProfile, resolveConfigSecrets, resolveDefaultAgentProfileId, resolveEffectiveAgentProfiles, resolveNextclawSelfManageGuidePaths, resolveProviderRuntime, resolveSessionWorkspacePath, resolveThinkingLevel, sanitizeOutboundAssistantContent, saveConfig, summarizeSessionRequestTask, toExtensionConfigView, updateAgentProfile } from "@nextclaw/core";
3
+ import { APP_NAME, AgentRouteResolver, BUILTIN_MAIN_AGENT_ID, CLEAR_THINKING_TOKENS, CONTEXT_COMPACTION_METADATA_KEY, ConfigSchema, ContextCompactionService, ContextWindowBudgetService, CronService, CronTool, DEFAULT_PANELS_DIR, DEFAULT_SERVICE_APPS_DIR, DEFAULT_SESSION_SEARCH_LIMIT, DEFAULT_WORKSPACE_REPOSITORY_IDENTITY_RESOLVER, EditFileTool, ExecTool, ExtensionChannelAdapter, GatewayTool, InputBudgetPruner, LLMProvider, ListDirTool, LiteLLMProvider, MAX_SESSION_SEARCH_LIMIT, MemoryGetTool, MemorySearchTool, MemoryStore, MessageBus, MessageTool, ProviderRegistry, ReadFileTool, RequestedSkillsMetadataReader, SILENT_REPLY_TOKEN, SessionProjectContextResolver, SessionSearchService, SkillsLoader, THINKING_LEVELS, WebFetchTool, WebSearchTool, WriteFileTool, buildCompressingCompactionCheckpoint, buildConfigSchema, buildContextWindowSnapshot, buildReloadPlan, buildSessionRequestToolResult, buildToolCatalogEntries, createAgentProfile, createAssistantStreamDeltaControlMessage, createAssistantStreamResetControlMessage, createCompletedSessionRequest, createFailedSessionRequest, createRunningSessionRequest, createRuntimeChildEnv, createTypingStopControlMessage, diffConfigPaths, ensureDir, evaluateSilentReply, expandHome, findEffectiveAgentProfile, getConfigPath, getDataDir, getDataPath, getSessionsPath, getWorkspacePath, getWorkspacePathFromConfig, isNextclawControlMessage, loadConfig, mergeExtensionConfigView, modelSupportsVision, normalizeAgentProfileId, normalizeInlineSecretRefs, normalizeModelThinkingCapability, normalizeProviderModelConfig, normalizeToolParams, parseAgentScopedSessionKey, parseThinkingLevel, readCompressedContextCompactionCheckpoint, readOptionalString, readParentSessionId, readSessionProjectRoot, redactConfigObject, removeAgentProfile, resolveConfigSecrets, resolveDefaultAgentProfileId, resolveEffectiveAgentProfiles, resolveNextclawSelfManageGuidePaths, resolveProviderRuntime, resolveSessionProjectContext, resolveSessionWorkspacePath, resolveThinkingLevel, sanitizeOutboundAssistantContent, saveConfig, summarizeSessionRequestTask, toExtensionConfigView, updateAgentProfile } from "@nextclaw/core";
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.sessionManager.getOrCreateAgentRunSession({
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
  };
@@ -3581,6 +3603,144 @@ function readOptionalMetadataString(value) {
3581
3603
  function readEventSessionId$1(event) {
3582
3604
  return "payload" in event && "sessionId" in event.payload ? readOptionalMetadataString(event.payload.sessionId) : void 0;
3583
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
+ }
3584
3744
  //#endregion
3585
3745
  //#region src/contributions/session-activity-preview/utils/session-activity-preview-ncp-event.utils.ts
3586
3746
  const PREVIEW_TEXT_MAX_LENGTH = 160;
@@ -3839,20 +3999,32 @@ var SessionEventIngestionService = class {
3839
3999
  };
3840
4000
  //#endregion
3841
4001
  //#region src/services/session-working-dir-resolver.service.ts
4002
+ function stripProjectRootMetadata(metadata) {
4003
+ if (!metadata) return;
4004
+ const { project_root: _projectRootLegacy, projectRoot: _projectRoot, ...rest } = metadata;
4005
+ return rest;
4006
+ }
3842
4007
  var SessionWorkingDirResolver = class {
3843
4008
  constructor(agentManager) {
3844
4009
  this.agentManager = agentManager;
3845
4010
  }
3846
- withWorkingDir = (summary) => ({
3847
- ...summary,
3848
- workingDir: this.resolve({
4011
+ withWorkingDir = (summary) => {
4012
+ const context = this.resolveContext({
3849
4013
  agentId: summary.agentId,
3850
4014
  metadata: summary.metadata
3851
- })
3852
- });
4015
+ });
4016
+ return {
4017
+ ...summary,
4018
+ metadata: context.projectRoot ? summary.metadata : stripProjectRootMetadata(summary.metadata),
4019
+ workingDir: context.effectiveWorkspace
4020
+ };
4021
+ };
3853
4022
  resolve = (params) => {
4023
+ return this.resolveContext(params).effectiveWorkspace;
4024
+ };
4025
+ resolveContext = (params) => {
3854
4026
  const profile = this.agentManager.resolveAgentProfile(readOptionalString$8(params.agentId));
3855
- return resolveSessionWorkspacePath({
4027
+ return resolveSessionProjectContext({
3856
4028
  sessionMetadata: params.metadata,
3857
4029
  workspace: profile.workspace
3858
4030
  });
@@ -3860,69 +4032,9 @@ var SessionWorkingDirResolver = class {
3860
4032
  };
3861
4033
  //#endregion
3862
4034
  //#region src/managers/session.manager.ts
3863
- const DEFAULT_SESSION_TYPE = "native";
3864
- const DEFAULT_LIFECYCLE = "persistent";
3865
- const SESSION_METADATA_LABEL_KEY = "label";
3866
- const CHILD_SESSION_PARENT_METADATA_KEY = "parent_session_id";
3867
- const CHILD_SESSION_REQUEST_METADATA_KEY = "spawned_by_request_id";
3868
- const CHILD_SESSION_LIFECYCLE_METADATA_KEY = "session_lifecycle";
3869
- function readThinkingEffort(metadata) {
3870
- return readOptionalMetadataString(metadata?.thinkingEffort) ?? null;
3871
- }
3872
- function readProjectRoot(metadata) {
3873
- return readOptionalMetadataString(metadata?.project_root) ?? readOptionalMetadataString(metadata?.projectRoot);
3874
- }
3875
- function summarizeTask(task) {
3876
- const normalized = task.trim().replace(/\s+/g, " ");
3877
- if (!normalized) return "Session";
3878
- return normalized.length <= 72 ? normalized : `${normalized.slice(0, 69)}...`;
3879
- }
3880
4035
  function buildSessionId() {
3881
4036
  return `ncp-${Date.now().toString(36)}-${randomUUID().replace(/-/g, "").slice(0, 8)}`;
3882
4037
  }
3883
- function cloneInheritedMetadata(sourceMetadata) {
3884
- const nextMetadata = {};
3885
- for (const key of [
3886
- "runtime",
3887
- "session_type",
3888
- "preferred_model",
3889
- "preferred_thinking",
3890
- "project_root",
3891
- "requested_skill_refs",
3892
- "codex_runtime_backend",
3893
- "reasoningNormalizationMode",
3894
- "reasoning_normalization_mode"
3895
- ]) if (Object.prototype.hasOwnProperty.call(sourceMetadata, key)) nextMetadata[key] = structuredClone(sourceMetadata[key]);
3896
- return nextMetadata;
3897
- }
3898
- function mergeMetadataOverrides(metadata, overrides) {
3899
- return overrides && Object.keys(overrides).length > 0 ? {
3900
- ...metadata,
3901
- ...structuredClone(overrides)
3902
- } : metadata;
3903
- }
3904
- function resolveSessionType(params) {
3905
- const { metadata, runtime, sessionType } = params;
3906
- return readOptionalString$8(runtime) ?? readOptionalString$8(metadata.runtime) ?? readOptionalString$8(sessionType) ?? readOptionalString$8(metadata.session_type) ?? DEFAULT_SESSION_TYPE;
3907
- }
3908
- function applySessionOverrides(params) {
3909
- const { lifecycle, metadata, model, parentSessionId, projectRoot, requestId, sessionType, thinkingLevel, title } = params;
3910
- metadata.session_type = sessionType;
3911
- metadata.runtime = sessionType;
3912
- metadata[SESSION_METADATA_LABEL_KEY] = title;
3913
- metadata[CHILD_SESSION_LIFECYCLE_METADATA_KEY] = lifecycle;
3914
- if (parentSessionId) metadata[CHILD_SESSION_PARENT_METADATA_KEY] = parentSessionId;
3915
- if (requestId) metadata[CHILD_SESSION_REQUEST_METADATA_KEY] = requestId;
3916
- if (readOptionalString$8(model)) {
3917
- metadata.model = model?.trim();
3918
- metadata.preferred_model = model?.trim();
3919
- }
3920
- if (readOptionalString$8(thinkingLevel)) {
3921
- metadata.thinking = thinkingLevel?.trim();
3922
- metadata.preferred_thinking = thinkingLevel?.trim();
3923
- }
3924
- if (readOptionalString$8(projectRoot)) metadata.project_root = projectRoot?.trim();
3925
- }
3926
4038
  function isSessionSummaryRefreshEvent(event) {
3927
4039
  switch (event.type) {
3928
4040
  case NcpEventType.MessageSent:
@@ -3964,7 +4076,7 @@ var SessionManager = class {
3964
4076
  this.started = false;
3965
4077
  };
3966
4078
  createSession = async (params) => {
3967
- const { agentId: requestedAgentId, metadataOverrides, model, parentSessionId: rawParentSessionId, projectRoot, requestId: rawRequestId, runtime, sessionId: requestedSessionId, sessionType: requestedSessionType, sourceSessionId, sourceSessionMetadata, task, thinkingLevel, title: requestedTitle } = params;
4079
+ const { agentId: requestedAgentId, contextInheritance, metadataOverrides, model, parentSessionId: rawParentSessionId, projectRoot, requestId: rawRequestId, runtime, sessionId: requestedSessionId, sessionType: requestedSessionType, sourceSessionId, sourceSessionMetadata, task, thinkingLevel, title: requestedTitle } = params;
3968
4080
  const sourceRecord = sourceSessionId ? await this.getSessionRecord(sourceSessionId) : null;
3969
4081
  const metadata = cloneInheritedMetadata(sourceSessionMetadata);
3970
4082
  const title = readOptionalString$8(requestedTitle) ?? summarizeTask(task);
@@ -3976,7 +4088,7 @@ var SessionManager = class {
3976
4088
  metadata
3977
4089
  });
3978
4090
  applySessionOverrides({
3979
- lifecycle: DEFAULT_LIFECYCLE,
4091
+ lifecycle: DEFAULT_SESSION_LIFECYCLE,
3980
4092
  metadata,
3981
4093
  model,
3982
4094
  parentSessionId: parentSessionId ?? void 0,
@@ -3990,13 +4102,20 @@ var SessionManager = class {
3990
4102
  const nextMetadata = mergeMetadataOverrides(metadata, metadataOverrides);
3991
4103
  const agentId = readOptionalString$8(requestedAgentId) ?? readOptionalString$8(sourceRecord?.agentId) ?? BUILTIN_MAIN_AGENT_ID;
3992
4104
  const sessionId = readOptionalString$8(requestedSessionId) ?? buildSessionId();
4105
+ const inheritedContext = createSessionContextInheritance({
4106
+ childSessionId: sessionId,
4107
+ contextInheritance,
4108
+ metadata: nextMetadata,
4109
+ parentSessionId,
4110
+ sourceRecord
4111
+ });
3993
4112
  const record = {
3994
4113
  sessionId,
3995
4114
  ...agentId ? { agentId } : {},
3996
- messages: [],
4115
+ messages: inheritedContext.messages,
3997
4116
  createdAt: now,
3998
4117
  updatedAt: now,
3999
- metadata: nextMetadata
4118
+ metadata: inheritedContext.metadata
4000
4119
  };
4001
4120
  await this.options.journalStore.importSessionSnapshot(record);
4002
4121
  await this.publishSessionChange(sessionId);
@@ -4004,12 +4123,12 @@ var SessionManager = class {
4004
4123
  sessionId,
4005
4124
  agentId,
4006
4125
  sessionType,
4007
- runtimeFamily: sessionType === DEFAULT_SESSION_TYPE ? "native" : "external",
4126
+ runtimeFamily: sessionType === "native" ? "native" : "external",
4008
4127
  ...parentSessionId ? { parentSessionId } : {},
4009
4128
  ...requestId ? { spawnedByRequestId: requestId } : {},
4010
- lifecycle: DEFAULT_LIFECYCLE,
4129
+ lifecycle: DEFAULT_SESSION_LIFECYCLE,
4011
4130
  title,
4012
- metadata: nextMetadata,
4131
+ metadata: inheritedContext.metadata,
4013
4132
  createdAt: now,
4014
4133
  updatedAt: now
4015
4134
  };
@@ -4097,9 +4216,13 @@ var SessionManager = class {
4097
4216
  };
4098
4217
  };
4099
4218
  createAgentRunSession = async (params) => {
4100
- const { agentId, agentRuntimeId: requestedAgentRuntimeId, channel, metadata, model, peerId: rawPeerId, projectRoot, sessionId, task, thinkingEffort } = params;
4101
- const agentRuntimeId = requestedAgentRuntimeId ?? "native";
4219
+ const { agentId, agentRuntimeId: requestedAgentRuntimeId, channel, contextInheritance, metadata, model, parentSessionId: rawParentSessionId, peerId: rawPeerId, projectRoot, sessionId, sourceSessionId: rawSourceSessionId, sourceSessionMetadata: requestedSourceSessionMetadata, task, thinkingEffort } = params;
4102
4220
  const peerId = readOptionalString$8(rawPeerId);
4221
+ const parentSessionId = readOptionalString$8(rawParentSessionId);
4222
+ const sourceSessionId = readOptionalString$8(rawSourceSessionId);
4223
+ const sourceRecord = sourceSessionId ? await this.getSessionRecord(sourceSessionId) : null;
4224
+ const sourceSessionMetadata = requestedSourceSessionMetadata ?? sourceRecord?.metadata ?? {};
4225
+ const agentRuntimeId = requestedAgentRuntimeId ?? readAgentRuntimeId(sourceSessionMetadata) ?? "native";
4103
4226
  const peerIdentity = peerId ? createAgentPeerSessionIdentity({
4104
4227
  agentId,
4105
4228
  channel,
@@ -4108,7 +4231,10 @@ var SessionManager = class {
4108
4231
  }) : void 0;
4109
4232
  const requestedSessionId = readOptionalString$8(sessionId);
4110
4233
  const created = await this.createSession({
4111
- sourceSessionMetadata: {},
4234
+ contextInheritance,
4235
+ parentSessionId: parentSessionId ?? void 0,
4236
+ sourceSessionId: sourceSessionId ?? void 0,
4237
+ sourceSessionMetadata,
4112
4238
  sessionId: requestedSessionId ?? peerIdentity?.sessionId,
4113
4239
  task: task ?? "Session",
4114
4240
  agentId,
@@ -4124,16 +4250,16 @@ var SessionManager = class {
4124
4250
  });
4125
4251
  return {
4126
4252
  sessionId: created.sessionId,
4127
- agentId,
4253
+ agentId: created.agentId,
4128
4254
  agentRuntimeId,
4129
4255
  metadata: structuredClone(created.metadata ?? {}),
4130
- model,
4131
- projectRoot,
4256
+ model: model ?? readOptionalMetadataString(created.metadata?.model) ?? readOptionalMetadataString(created.metadata?.preferred_model),
4257
+ projectRoot: projectRoot ?? readProjectRoot(created.metadata),
4132
4258
  workingDir: this.workingDirResolver.resolve({
4133
- agentId,
4259
+ agentId: created.agentId,
4134
4260
  metadata: created.metadata
4135
4261
  }),
4136
- thinkingEffort: thinkingEffort ?? null
4262
+ thinkingEffort: thinkingEffort ?? readThinkingEffort(created.metadata)
4137
4263
  };
4138
4264
  };
4139
4265
  getOrCreateAgentRunSession = async (params) => {
@@ -7151,7 +7277,7 @@ var SessionRequestManager = class {
7151
7277
  this.options = options;
7152
7278
  }
7153
7279
  spawnSessionAndRequest = async (params) => {
7154
- const { sourceSessionId, sourceToolCallId, updateToolCallResult, sourceSessionMetadata, metadataOverrides, task, title, model, runtime, handoffDepth, sessionType, thinkingLevel, projectRoot, agentId, parentSessionId, notify } = params;
7280
+ const { sourceSessionId, sourceToolCallId, updateToolCallResult, sourceSessionMetadata, metadataOverrides, contextInheritance, task, title, model, runtime, handoffDepth, sessionType, thinkingLevel, projectRoot, agentId, parentSessionId, notify } = params;
7155
7281
  const requestId = randomUUID();
7156
7282
  const createdSession = await this.options.sessionManager.createSession({
7157
7283
  sourceSessionId,
@@ -7160,6 +7286,7 @@ var SessionRequestManager = class {
7160
7286
  title,
7161
7287
  sourceSessionMetadata,
7162
7288
  ...metadataOverrides ? { metadataOverrides } : {},
7289
+ contextInheritance,
7163
7290
  agentId,
7164
7291
  model,
7165
7292
  runtime,
@@ -9534,6 +9661,11 @@ function readSpawnNotify(value) {
9534
9661
  if (notifyMode === "none" || notifyMode === "final_reply") return notifyMode;
9535
9662
  throw new Error("notify must be \"none\" or \"final_reply\".");
9536
9663
  }
9664
+ function readInheritContext(value) {
9665
+ if (typeof value === "undefined") return false;
9666
+ if (typeof value === "boolean") return value;
9667
+ throw new Error("inheritContext must be a boolean.");
9668
+ }
9537
9669
  var SessionSpawnTool = class {
9538
9670
  name = "sessions_spawn";
9539
9671
  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.";
@@ -9569,6 +9701,10 @@ var SessionSpawnTool = class {
9569
9701
  type: "string",
9570
9702
  enum: ["none", "final_reply"],
9571
9703
  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."
9704
+ },
9705
+ inheritContext: {
9706
+ type: "boolean",
9707
+ description: "Child sessions only. When true, the child starts with parent context inherited up to this tool call."
9572
9708
  }
9573
9709
  },
9574
9710
  required: ["task"],
@@ -9587,11 +9723,14 @@ var SessionSpawnTool = class {
9587
9723
  this.handoffDepth = params.handoffDepth ?? 0;
9588
9724
  };
9589
9725
  execute = async (args, context) => {
9590
- const { agentId: rawAgentId, model: rawModel, notify: rawNotify, runtime: rawRuntime, scope: rawScope, task: rawTask, title: rawTitle } = normalizeToolParams(args);
9726
+ const { agentId: rawAgentId, model: rawModel, notify: rawNotify, runtime: rawRuntime, scope: rawScope, task: rawTask, title: rawTitle, inheritContext: rawInheritContext } = normalizeToolParams(args);
9591
9727
  const task = readRequiredString$1(rawTask, "task");
9592
9728
  const scope = readSpawnScope(rawScope);
9593
9729
  const notify = readSpawnNotify(rawNotify);
9730
+ const inheritContext = readInheritContext(rawInheritContext);
9731
+ if (inheritContext && scope !== "child") throw new Error("inheritContext=true requires scope=\"child\".");
9594
9732
  const parentSessionId = scope === "child" ? this.readParentSessionIdOrThrow() : void 0;
9733
+ const contextInheritance = inheritContext ? { anchorToolCallId: context?.toolCallId } : void 0;
9595
9734
  if (notify) return this.sessionRequestManager.spawnSessionAndRequest({
9596
9735
  sourceSessionId: this.sourceSessionId,
9597
9736
  sourceToolCallId: context?.toolCallId,
@@ -9602,6 +9741,7 @@ var SessionSpawnTool = class {
9602
9741
  agentId: readOptionalString$2(rawAgentId),
9603
9742
  model: readOptionalString$2(rawModel),
9604
9743
  runtime: readOptionalString$2(rawRuntime),
9744
+ contextInheritance,
9605
9745
  handoffDepth: this.handoffDepth,
9606
9746
  parentSessionId,
9607
9747
  notify
@@ -9614,6 +9754,7 @@ var SessionSpawnTool = class {
9614
9754
  agentId: readOptionalString$2(rawAgentId),
9615
9755
  model: readOptionalString$2(rawModel),
9616
9756
  runtime: readOptionalString$2(rawRuntime),
9757
+ contextInheritance,
9617
9758
  parentSessionId
9618
9759
  });
9619
9760
  return {