@downcity/agent 1.1.79 → 1.1.82

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.
Files changed (173) hide show
  1. package/README.md +1 -1
  2. package/bin/agent/local/Agent.d.ts +8 -121
  3. package/bin/agent/local/Agent.d.ts.map +1 -1
  4. package/bin/agent/local/Agent.js +63 -381
  5. package/bin/agent/local/Agent.js.map +1 -1
  6. package/bin/agent/local/AgentRuntimeFactory.d.ts +2 -2
  7. package/bin/agent/local/AgentRuntimeFactory.d.ts.map +1 -1
  8. package/bin/agent/local/AgentRuntimeFactory.js +2 -23
  9. package/bin/agent/local/AgentRuntimeFactory.js.map +1 -1
  10. package/bin/agent/local/services/AgentAssemblyService.d.ts +112 -0
  11. package/bin/agent/local/services/AgentAssemblyService.d.ts.map +1 -0
  12. package/bin/agent/local/services/AgentAssemblyService.js +135 -0
  13. package/bin/agent/local/services/AgentAssemblyService.js.map +1 -0
  14. package/bin/agent/local/services/AgentLifecycleService.d.ts +59 -0
  15. package/bin/agent/local/services/AgentLifecycleService.d.ts.map +1 -0
  16. package/bin/agent/local/services/AgentLifecycleService.js +136 -0
  17. package/bin/agent/local/services/AgentLifecycleService.js.map +1 -0
  18. package/bin/agent/local/services/AgentSessionManager.d.ts +106 -0
  19. package/bin/agent/local/services/AgentSessionManager.d.ts.map +1 -0
  20. package/bin/agent/local/services/AgentSessionManager.js +182 -0
  21. package/bin/agent/local/services/AgentSessionManager.js.map +1 -0
  22. package/bin/executor/Executor.d.ts +7 -24
  23. package/bin/executor/Executor.d.ts.map +1 -1
  24. package/bin/executor/Executor.js +73 -361
  25. package/bin/executor/Executor.js.map +1 -1
  26. package/bin/executor/SessionRunScope.d.ts +18 -34
  27. package/bin/executor/SessionRunScope.d.ts.map +1 -1
  28. package/bin/executor/SessionRunScope.js +42 -28
  29. package/bin/executor/SessionRunScope.js.map +1 -1
  30. package/bin/executor/composer/context/LocalSessionContextComposer.d.ts +5 -3
  31. package/bin/executor/composer/context/LocalSessionContextComposer.d.ts.map +1 -1
  32. package/bin/executor/composer/context/LocalSessionContextComposer.js +11 -18
  33. package/bin/executor/composer/context/LocalSessionContextComposer.js.map +1 -1
  34. package/bin/executor/composer/context/SessionContextComposer.d.ts +8 -3
  35. package/bin/executor/composer/context/SessionContextComposer.d.ts.map +1 -1
  36. package/bin/executor/composer/system/SessionSystemComposer.d.ts +2 -1
  37. package/bin/executor/composer/system/SessionSystemComposer.d.ts.map +1 -1
  38. package/bin/executor/composer/system/default/DefaultSessionSystemComposer.d.ts +2 -1
  39. package/bin/executor/composer/system/default/DefaultSessionSystemComposer.d.ts.map +1 -1
  40. package/bin/executor/composer/system/default/DefaultSessionSystemComposer.js +2 -4
  41. package/bin/executor/composer/system/default/DefaultSessionSystemComposer.js.map +1 -1
  42. package/bin/executor/core-engine/CoreEngineRunner.d.ts +62 -0
  43. package/bin/executor/core-engine/CoreEngineRunner.d.ts.map +1 -0
  44. package/bin/executor/core-engine/CoreEngineRunner.js +309 -0
  45. package/bin/executor/core-engine/CoreEngineRunner.js.map +1 -0
  46. package/bin/executor/core-engine/CoreEngineUiStreamCollector.d.ts +5 -0
  47. package/bin/executor/core-engine/CoreEngineUiStreamCollector.d.ts.map +1 -1
  48. package/bin/executor/core-engine/CoreEngineUiStreamCollector.js +2 -4
  49. package/bin/executor/core-engine/CoreEngineUiStreamCollector.js.map +1 -1
  50. package/bin/executor/services/ExecutorInflightService.d.ts +39 -0
  51. package/bin/executor/services/ExecutorInflightService.d.ts.map +1 -0
  52. package/bin/executor/services/ExecutorInflightService.js +75 -0
  53. package/bin/executor/services/ExecutorInflightService.js.map +1 -0
  54. package/bin/executor/services/ExecutorRecoveryPolicy.d.ts +103 -0
  55. package/bin/executor/services/ExecutorRecoveryPolicy.d.ts.map +1 -0
  56. package/bin/executor/services/ExecutorRecoveryPolicy.js +87 -0
  57. package/bin/executor/services/ExecutorRecoveryPolicy.js.map +1 -0
  58. package/bin/executor/tools/plugin/PluginToolBridge.d.ts +19 -0
  59. package/bin/executor/tools/plugin/PluginToolBridge.d.ts.map +1 -0
  60. package/bin/executor/tools/plugin/PluginToolBridge.js +143 -0
  61. package/bin/executor/tools/plugin/PluginToolBridge.js.map +1 -0
  62. package/bin/executor/tools/plugin/PluginToolDefinition.d.ts +32 -0
  63. package/bin/executor/tools/plugin/PluginToolDefinition.d.ts.map +1 -0
  64. package/bin/executor/tools/plugin/PluginToolDefinition.js +27 -0
  65. package/bin/executor/tools/plugin/PluginToolDefinition.js.map +1 -0
  66. package/bin/executor/tools/plugin/PluginToolSchemas.d.ts +14 -0
  67. package/bin/executor/tools/plugin/PluginToolSchemas.d.ts.map +1 -0
  68. package/bin/executor/tools/plugin/PluginToolSchemas.js +19 -0
  69. package/bin/executor/tools/plugin/PluginToolSchemas.js.map +1 -0
  70. package/bin/executor/tools/plugin/types/PluginTool.d.ts +39 -0
  71. package/bin/executor/tools/plugin/types/PluginTool.d.ts.map +1 -0
  72. package/bin/executor/tools/plugin/types/PluginTool.js +9 -0
  73. package/bin/executor/tools/plugin/types/PluginTool.js.map +1 -0
  74. package/bin/executor/tools/shell/ShellToolBridge.js +3 -3
  75. package/bin/executor/tools/shell/ShellToolBridge.js.map +1 -1
  76. package/bin/executor/types/SessionRun.d.ts +18 -0
  77. package/bin/executor/types/SessionRun.d.ts.map +1 -1
  78. package/bin/index.d.ts +10 -1
  79. package/bin/index.d.ts.map +1 -1
  80. package/bin/index.js +3 -0
  81. package/bin/index.js.map +1 -1
  82. package/bin/plugin/core/BasePlugin.d.ts +2 -2
  83. package/bin/plugin/core/BasePlugin.d.ts.map +1 -1
  84. package/bin/plugin/core/BasePlugin.js.map +1 -1
  85. package/bin/plugin/core/ImagePlugin.d.ts +56 -0
  86. package/bin/plugin/core/ImagePlugin.d.ts.map +1 -0
  87. package/bin/plugin/core/ImagePlugin.js +109 -0
  88. package/bin/plugin/core/ImagePlugin.js.map +1 -0
  89. package/bin/session/Session.d.ts +25 -84
  90. package/bin/session/Session.d.ts.map +1 -1
  91. package/bin/session/Session.js +162 -367
  92. package/bin/session/Session.js.map +1 -1
  93. package/bin/session/SessionSystemBuilder.d.ts +2 -1
  94. package/bin/session/SessionSystemBuilder.d.ts.map +1 -1
  95. package/bin/session/SessionSystemBuilder.js +2 -3
  96. package/bin/session/SessionSystemBuilder.js.map +1 -1
  97. package/bin/session/services/SessionStateService.d.ts +132 -0
  98. package/bin/session/services/SessionStateService.d.ts.map +1 -0
  99. package/bin/session/services/SessionStateService.js +242 -0
  100. package/bin/session/services/SessionStateService.js.map +1 -0
  101. package/bin/session/services/SessionTurnService.d.ts +66 -0
  102. package/bin/session/services/SessionTurnService.d.ts.map +1 -0
  103. package/bin/session/services/SessionTurnService.js +137 -0
  104. package/bin/session/services/SessionTurnService.js.map +1 -0
  105. package/bin/session/services/SessionViewService.d.ts +106 -0
  106. package/bin/session/services/SessionViewService.d.ts.map +1 -0
  107. package/bin/session/services/SessionViewService.js +198 -0
  108. package/bin/session/services/SessionViewService.js.map +1 -0
  109. package/bin/types/agent/AgentOptions.d.ts +18 -0
  110. package/bin/types/agent/AgentOptions.d.ts.map +1 -1
  111. package/bin/types/agent/AgentTypes.d.ts +3 -1
  112. package/bin/types/agent/AgentTypes.d.ts.map +1 -1
  113. package/bin/types/agent/SessionTypes.d.ts.map +1 -1
  114. package/bin/types/executor/SessionRunContext.d.ts +66 -0
  115. package/bin/types/executor/SessionRunContext.d.ts.map +1 -0
  116. package/bin/types/executor/SessionRunContext.js +10 -0
  117. package/bin/types/executor/SessionRunContext.js.map +1 -0
  118. package/bin/types/plugin/ImagePlugin.d.ts +94 -0
  119. package/bin/types/plugin/ImagePlugin.d.ts.map +1 -0
  120. package/bin/types/plugin/ImagePlugin.js +10 -0
  121. package/bin/types/plugin/ImagePlugin.js.map +1 -0
  122. package/bin/types/session/SessionComposerOptions.d.ts +90 -0
  123. package/bin/types/session/SessionComposerOptions.d.ts.map +1 -0
  124. package/bin/types/session/SessionComposerOptions.js +10 -0
  125. package/bin/types/session/SessionComposerOptions.js.map +1 -0
  126. package/bin/types/session/SessionLocalState.d.ts +35 -0
  127. package/bin/types/session/SessionLocalState.d.ts.map +1 -0
  128. package/bin/types/session/SessionLocalState.js +10 -0
  129. package/bin/types/session/SessionLocalState.js.map +1 -0
  130. package/bin/types/session/SessionOptions.d.ts +85 -0
  131. package/bin/types/session/SessionOptions.d.ts.map +1 -0
  132. package/bin/types/session/SessionOptions.js +10 -0
  133. package/bin/types/session/SessionOptions.js.map +1 -0
  134. package/package.json +1 -1
  135. package/src/agent/local/Agent.ts +74 -433
  136. package/src/agent/local/AgentRuntimeFactory.ts +4 -25
  137. package/src/agent/local/services/AgentAssemblyService.ts +268 -0
  138. package/src/agent/local/services/AgentLifecycleService.ts +187 -0
  139. package/src/agent/local/services/AgentSessionManager.ts +290 -0
  140. package/src/executor/Executor.ts +103 -441
  141. package/src/executor/README.md +4 -4
  142. package/src/executor/SessionRunScope.ts +47 -71
  143. package/src/executor/composer/context/LocalSessionContextComposer.ts +24 -20
  144. package/src/executor/composer/context/SessionContextComposer.ts +13 -3
  145. package/src/executor/composer/system/SessionSystemComposer.ts +2 -1
  146. package/src/executor/composer/system/default/DefaultSessionSystemComposer.ts +3 -4
  147. package/src/executor/core-engine/CoreEngineRunner.ts +433 -0
  148. package/src/executor/core-engine/CoreEngineUiStreamCollector.ts +7 -5
  149. package/src/executor/services/ExecutorInflightService.ts +101 -0
  150. package/src/executor/services/ExecutorRecoveryPolicy.ts +213 -0
  151. package/src/executor/tools/plugin/PluginToolBridge.ts +161 -0
  152. package/src/executor/tools/plugin/PluginToolDefinition.ts +32 -0
  153. package/src/executor/tools/plugin/PluginToolSchemas.ts +20 -0
  154. package/src/executor/tools/plugin/types/PluginTool.ts +41 -0
  155. package/src/executor/tools/shell/ShellToolBridge.ts +3 -3
  156. package/src/executor/types/SessionRun.ts +20 -0
  157. package/src/index.ts +33 -0
  158. package/src/plugin/core/BasePlugin.ts +2 -2
  159. package/src/plugin/core/ImagePlugin.ts +128 -0
  160. package/src/session/Session.ts +216 -500
  161. package/src/session/SessionSystemBuilder.ts +3 -3
  162. package/src/session/services/SessionStateService.ts +341 -0
  163. package/src/session/services/SessionTurnService.ts +202 -0
  164. package/src/session/services/SessionViewService.ts +323 -0
  165. package/src/types/agent/AgentOptions.ts +25 -0
  166. package/src/types/agent/AgentTypes.ts +10 -0
  167. package/src/types/agent/SessionTypes.ts +1 -0
  168. package/src/types/executor/SessionRunContext.ts +76 -0
  169. package/src/types/plugin/ImagePlugin.ts +103 -0
  170. package/src/types/session/SessionComposerOptions.ts +107 -0
  171. package/src/types/session/SessionLocalState.ts +40 -0
  172. package/src/types/session/SessionOptions.ts +99 -0
  173. package/tsconfig.tsbuildinfo +1 -1
@@ -3,25 +3,18 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - 面向 `new Agent(...)` 的本地会话使用场景。
6
- * - 统一收口消息落盘、session 级模型配置、prompt/subscribe/fork 等高层 API
6
+ * - 对外保留稳定 Session facade,把状态、turn、view 逻辑下沉到独立 service
7
7
  * - 内部继续复用 `Executor` / `JsonlSessionHistoryStore` / Composer 体系。
8
8
  */
9
- import { nanoid } from "nanoid";
10
9
  import { Executor } from "../executor/Executor.js";
11
10
  import { JsonlSessionHistoryComposer } from "../executor/composer/history/jsonl/JsonlSessionHistoryComposer.js";
12
11
  import { JsonlSessionHistoryStore } from "../executor/store/history/jsonl/JsonlSessionHistoryStore.js";
13
- import { extractTextFromUiMessage } from "../executor/messages/UIMessageTransformer.js";
14
- import { buildSessionSystemBlocks, SessionSystemBuilder, } from "../session/SessionSystemBuilder.js";
15
- import { buildSessionHistoryPage, buildSessionInfo, patchSessionModelLabel, readSessionMetadata, resolveSystemTimezone, writeSessionMetadata, } from "../session/index.js";
16
- import { getSdkAgentSessionArchiveDirPath, getSdkAgentSessionDirPath, getSdkAgentSessionInflightPath, } from "../session/index.js";
17
- import { mapAgentEventToSessionEvent, mapUiMessageChunkToAgentEvent, } from "../session/SessionEventMapper.js";
18
- import { persistSdkAssistantResult, touchSessionMetadata, } from "../session/index.js";
19
- import { createRuntimeSessionPort } from "../session/index.js";
20
- import { drainDeferredPersistedUserMessages } from "../executor/SessionRunScope.js";
12
+ import { getSdkAgentSessionArchiveDirPath, getSdkAgentSessionDirPath, getSdkAgentSessionInflightPath, resolveSystemTimezone, createRuntimeSessionPort, } from "../session/index.js";
13
+ import { SessionSystemBuilder } from "../session/SessionSystemBuilder.js";
21
14
  import { SessionEventHub } from "../session/runtime/SessionEventHub.js";
22
- import { SessionPromptRuntime } from "../session/runtime/SessionPromptRuntime.js";
23
- import { inferAgentModelLabel, normalizeAgentModel, } from "../model/CityModelAdapter.js";
24
- import { ensureSessionTitle } from "../session/SessionTitle.js";
15
+ import { SessionStateService } from "../session/services/SessionStateService.js";
16
+ import { SessionTurnService } from "../session/services/SessionTurnService.js";
17
+ import { SessionViewService } from "../session/services/SessionViewService.js";
25
18
  /**
26
19
  * SDK 本地 Session。
27
20
  */
@@ -35,16 +28,15 @@ export class Session {
35
28
  getManagedPluginSystemBlocks;
36
29
  getPluginSystemBlocks;
37
30
  ensureConfiguredHook;
31
+ composers;
38
32
  historyStore;
39
33
  historyComposer;
40
34
  executor;
41
35
  eventHub = new SessionEventHub();
42
- promptRuntime;
43
- sessionConfig = {};
44
- createdAt = Date.now();
45
- timezone = resolveSystemTimezone();
46
- initializePromise = null;
47
- ensureConfiguredPromise = null;
36
+ localState;
37
+ stateService;
38
+ turnService;
39
+ viewService;
48
40
  runtimePort = null;
49
41
  constructor(options) {
50
42
  this.id = String(options.sessionId || "").trim();
@@ -56,6 +48,7 @@ export class Session {
56
48
  this.getManagedPluginSystemBlocks = options.getManagedPluginSystemBlocks;
57
49
  this.getPluginSystemBlocks = options.getPluginSystemBlocks;
58
50
  this.ensureConfiguredHook = options.ensureConfigured;
51
+ this.composers = options.composers;
59
52
  if (!this.id) {
60
53
  throw new Error("Session requires a non-empty sessionId");
61
54
  }
@@ -65,246 +58,152 @@ export class Session {
65
58
  if (!this.projectRoot) {
66
59
  throw new Error("Session requires a non-empty projectRoot");
67
60
  }
68
- const sessionDirPath = getSdkAgentSessionDirPath(this.projectRoot, this.agentId, this.id);
69
- const messagesDirPath = `${sessionDirPath}/messages`;
70
- this.historyStore = new JsonlSessionHistoryStore({
71
- rootPath: this.projectRoot,
72
- agentId: this.agentId,
73
- sessionId: this.id,
74
- paths: {
75
- sessionDirPath,
76
- messagesDirPath,
77
- messagesFilePath: `${messagesDirPath}/messages.jsonl`,
78
- metaFilePath: `${messagesDirPath}/meta.json`,
79
- archiveDirPath: getSdkAgentSessionArchiveDirPath(this.projectRoot, this.agentId, this.id),
80
- inflightFilePath: getSdkAgentSessionInflightPath(this.projectRoot, this.agentId, this.id),
81
- },
82
- });
83
- this.historyComposer = new JsonlSessionHistoryComposer({
61
+ this.historyStore = this.create_history_store();
62
+ this.localState = this.create_local_state();
63
+ const composer_context = this.create_composer_context();
64
+ this.historyComposer = this.resolve_composer(this.composers?.historyComposer, composer_context, () => new JsonlSessionHistoryComposer({
84
65
  store: this.historyStore,
85
- });
66
+ }));
67
+ const system_composer = this.resolve_composer(this.composers?.systemComposer, composer_context, () => new SessionSystemBuilder({
68
+ agentId: this.agentId,
69
+ projectRoot: this.projectRoot,
70
+ getSessionCreatedAt: () => this.localState.createdAt,
71
+ getSessionTimezone: () => this.localState.timezone,
72
+ getInstructionSystemBlocks: this.getInstructionSystemBlocks,
73
+ getManagedPluginSystemBlocks: this.getManagedPluginSystemBlocks,
74
+ getPluginSystemBlocks: this.getPluginSystemBlocks,
75
+ }));
76
+ const context_composer = this.resolve_optional_composer(this.composers?.contextComposer, composer_context);
77
+ const compaction_composer = this.resolve_optional_composer(this.composers?.compactionComposer, composer_context);
86
78
  this.executor = new Executor({
87
79
  sessionId: this.id,
88
80
  historyStore: this.historyStore,
89
81
  historyComposer: this.historyComposer,
90
- getModel: () => this.sessionConfig.model,
82
+ getModel: () => this.localState.sessionConfig.model,
91
83
  logger: this.logger,
92
- systemComposer: new SessionSystemBuilder({
93
- agentId: this.agentId,
94
- projectRoot: this.projectRoot,
95
- getSessionCreatedAt: () => this.createdAt,
96
- getSessionTimezone: () => this.timezone,
97
- getInstructionSystemBlocks: this.getInstructionSystemBlocks,
98
- getManagedPluginSystemBlocks: this.getManagedPluginSystemBlocks,
99
- getPluginSystemBlocks: this.getPluginSystemBlocks,
100
- }),
84
+ systemComposer: system_composer,
101
85
  getTools: () => this.tools,
86
+ ...(context_composer ? { contextComposer: context_composer } : {}),
87
+ ...(compaction_composer
88
+ ? { compactionComposer: compaction_composer }
89
+ : {}),
102
90
  });
103
- this.promptRuntime = new SessionPromptRuntime({
104
- sessionId: this.id,
105
- publish: (event) => {
91
+ this.stateService = new SessionStateService({
92
+ agent_id: this.agentId,
93
+ project_root: this.projectRoot,
94
+ session_id: this.id,
95
+ history_store: this.historyStore,
96
+ executor: this.executor,
97
+ state: this.localState,
98
+ ensure_configured_hook: this.ensureConfiguredHook
99
+ ? async () => {
100
+ await this.ensureConfiguredHook?.(this);
101
+ }
102
+ : undefined,
103
+ publish_event: (event) => {
106
104
  this.eventHub.publish(event);
107
105
  },
108
- createAndPersistUserMessage: async (input) => {
109
- return await this.createAndPersistUserPromptMessage(input);
110
- },
111
- executeTurn: async ({ turnId, promptInput, onStepMerge }) => {
112
- return await this.executePromptTurn({
113
- turnId,
114
- promptInput,
115
- onStepMerge,
116
- });
106
+ });
107
+ this.turnService = new SessionTurnService({
108
+ session_id: this.id,
109
+ executor: this.executor,
110
+ state_service: this.stateService,
111
+ event_hub: this.eventHub,
112
+ });
113
+ this.viewService = new SessionViewService({
114
+ agent_id: this.agentId,
115
+ project_root: this.projectRoot,
116
+ session_id: this.id,
117
+ history_store: this.historyStore,
118
+ state_service: this.stateService,
119
+ is_executing: () => this.isExecuting(),
120
+ get_instruction_system_blocks: this.getInstructionSystemBlocks,
121
+ get_managed_plugin_system_blocks: this.getManagedPluginSystemBlocks,
122
+ get_plugin_system_blocks: this.getPluginSystemBlocks,
123
+ ...(this.composers?.systemComposer
124
+ ? { custom_system_composer: system_composer }
125
+ : {}),
126
+ create_fork_session: async (session_id) => {
127
+ const session = this.create_fork_session(session_id);
128
+ await session.initialize();
129
+ return {
130
+ session,
131
+ history_store: session.historyStore,
132
+ state_service: session.stateService,
133
+ };
117
134
  },
118
135
  });
119
136
  }
120
137
  /**
121
- * 初始化当前 session 的 meta 信息与内存配置。
138
+ * 初始化当前 session
122
139
  */
123
140
  async initialize() {
124
- if (this.initializePromise) {
125
- return await this.initializePromise;
126
- }
127
- this.initializePromise = (async () => {
128
- const metadata = await readSessionMetadata({
129
- projectRoot: this.projectRoot,
130
- agentId: this.agentId,
131
- sessionId: this.id,
132
- });
133
- const createdAt = typeof metadata.createdAt === "number" ? metadata.createdAt : Date.now();
134
- const timezone = typeof metadata.timezone === "string" && metadata.timezone.trim()
135
- ? metadata.timezone.trim()
136
- : resolveSystemTimezone();
137
- await writeSessionMetadata({
138
- projectRoot: this.projectRoot,
139
- agentId: this.agentId,
140
- sessionId: this.id,
141
- meta: {
142
- ...metadata,
143
- agentId: this.agentId,
144
- createdAt,
145
- timezone,
146
- },
147
- });
148
- this.createdAt = createdAt;
149
- this.timezone = timezone;
150
- this.sessionConfig = {
151
- ...(metadata.modelLabel
152
- ? { modelLabel: metadata.modelLabel }
153
- : {}),
154
- };
155
- return this;
156
- })();
157
- return await this.initializePromise;
141
+ await this.stateService.initialize();
142
+ return this;
158
143
  }
159
144
  /**
160
145
  * 读取当前 session 配置快照。
161
146
  */
162
147
  get config() {
163
- return {
164
- ...this.sessionConfig,
165
- };
148
+ return this.stateService.get_config();
166
149
  }
167
150
  /**
168
151
  * 写入当前 session 默认配置。
169
152
  */
170
153
  async set(input) {
171
- if (input.model) {
172
- this.sessionConfig.model = normalizeAgentModel(input.model);
173
- this.sessionConfig.modelLabel = inferAgentModelLabel(input.model);
174
- this.executor.clearExecutor();
175
- }
176
- await patchSessionModelLabel({
177
- projectRoot: this.projectRoot,
178
- agentId: this.agentId,
179
- sessionId: this.id,
180
- model: this.sessionConfig.model,
181
- });
154
+ await this.stateService.set(input);
182
155
  }
183
156
  /**
184
157
  * 追加一条新的 Session prompt。
185
- *
186
- * 关键点(中文)
187
- * - 这是 Session actor 模型下唯一的输入入口。
188
- * - 首条输入、运行中补充输入、排到下一轮的输入,调用方式完全一致。
189
158
  */
190
159
  async prompt(input) {
191
- const query = String(input.query || "").trim();
192
- if (!query) {
193
- throw new Error("session.prompt requires a non-empty query");
194
- }
195
- await this.ensureRunnable();
196
- return await this.promptRuntime.prompt({
197
- query,
198
- });
160
+ return await this.turnService.prompt(input);
199
161
  }
200
162
  /**
201
163
  * 订阅当前 Session 的未来事件。
202
- *
203
- * 关键点(中文)
204
- * - 只广播订阅之后产生的事件。
205
- * - 不做历史回放;历史仍通过 `history()` 读取。
206
164
  */
207
165
  subscribe(subscriber) {
208
- return this.eventHub.subscribe(subscriber);
166
+ return this.turnService.subscribe(subscriber);
209
167
  }
210
168
  /**
211
169
  * 追加一条 user 文本消息。
212
170
  */
213
171
  async appendUserMessage(input) {
214
- await this.executor.appendUserMessage({
172
+ await this.stateService.append_user_message({
215
173
  text: String(input.text || "").trim(),
216
174
  });
217
- await this.ensureTitleFromHistory({ generate: true });
218
- await this.touchMetadata();
219
175
  }
220
176
  /**
221
177
  * 追加一条 assistant 文本消息。
222
178
  */
223
179
  async appendAssistantMessage(input) {
224
- await this.executor.appendAssistantMessage({
180
+ await this.stateService.append_assistant_message({
225
181
  fallbackText: String(input.text || "").trim(),
226
182
  });
227
- await this.touchMetadata();
228
183
  }
229
184
  /**
230
185
  * 读取当前 session 详情。
231
186
  */
232
187
  async getInfo() {
233
- const [metadata, messages] = await Promise.all([
234
- readSessionMetadata({
235
- projectRoot: this.projectRoot,
236
- agentId: this.agentId,
237
- sessionId: this.id,
238
- }),
239
- this.historyStore.list(),
240
- ]);
241
- const metadataWithTitle = metadata.title
242
- ? metadata
243
- : await ensureSessionTitle({
244
- projectRoot: this.projectRoot,
245
- agentId: this.agentId,
246
- sessionId: this.id,
247
- messages,
248
- });
249
- return buildSessionInfo({
250
- projectRoot: this.projectRoot,
251
- agentId: this.agentId,
252
- sessionId: this.id,
253
- metadata: metadataWithTitle,
254
- messages,
255
- executing: this.isExecuting(),
256
- });
188
+ return await this.viewService.get_info();
257
189
  }
258
190
  /**
259
191
  * 读取当前 session 历史分页。
260
192
  */
261
193
  async history(input) {
262
- const [session, messages] = await Promise.all([
263
- this.getInfo(),
264
- this.historyStore.list(),
265
- ]);
266
- return buildSessionHistoryPage({
267
- session,
268
- messages,
269
- input,
270
- });
194
+ return await this.viewService.history(input);
271
195
  }
272
196
  /**
273
- * 读取当前 session 生效的 system prompt 文本集合。
274
- *
275
- * 关键点(中文)
276
- * - 返回内容与实际 run 时使用的 SDK system composer 同源。
277
- * - 包含 instruction/core、受托管 plugin system、显式注册 plugin system 与 session 上下文。
278
- * - 返回结构化快照,不把 system prompt 写入会话历史。
197
+ * 读取当前 session 生效的 system 快照。
279
198
  */
280
199
  async system() {
281
- const blocks = await buildSessionSystemBlocks({
282
- agentId: this.agentId,
283
- projectRoot: this.projectRoot,
284
- sessionId: this.id,
285
- createdAt: this.createdAt,
286
- timezone: this.timezone,
287
- getInstructionSystemBlocks: this.getInstructionSystemBlocks,
288
- getManagedPluginSystemBlocks: this.getManagedPluginSystemBlocks,
289
- getPluginSystemBlocks: this.getPluginSystemBlocks,
290
- });
291
- return {
292
- sessionId: this.id,
293
- session: {
294
- agentId: this.agentId,
295
- sessionId: this.id,
296
- projectRoot: this.projectRoot,
297
- createdAt: new Date(this.createdAt).toISOString(),
298
- timezone: this.timezone,
299
- },
300
- blocks,
301
- };
200
+ return await this.viewService.system();
302
201
  }
303
202
  /**
304
203
  * 返回当前 session 是否正在执行。
305
204
  */
306
205
  isExecuting() {
307
- return this.promptRuntime.isActive() || this.executor.isExecuting();
206
+ return this.turnService.is_prompt_runtime_active() || this.executor.isExecuting();
308
207
  }
309
208
  /**
310
209
  * 清理当前 session 的执行器缓存。
@@ -316,41 +215,7 @@ export class Session {
316
215
  * 从当前 session 创建一个分叉会话。
317
216
  */
318
217
  async fork(input) {
319
- const messageId = typeof input === "string"
320
- ? String(input || "").trim() || undefined
321
- : String(input?.messageId || "").trim() || undefined;
322
- const messages = await this.historyStore.list();
323
- const forkMessages = !messageId
324
- ? messages
325
- : (() => {
326
- const targetIndex = messages.findIndex((message) => String(message.id || "").trim() === messageId);
327
- if (targetIndex < 0) {
328
- throw new Error(`Cannot fork session "${this.id}": messageId "${messageId}" not found.`);
329
- }
330
- return messages.slice(0, targetIndex + 1);
331
- })();
332
- const forked = new Session({
333
- agentId: this.agentId,
334
- projectRoot: this.projectRoot,
335
- sessionId: `fork-${Date.now()}-${nanoid(8)}`,
336
- tools: this.tools,
337
- logger: this.logger,
338
- getInstructionSystemBlocks: this.getInstructionSystemBlocks,
339
- getManagedPluginSystemBlocks: this.getManagedPluginSystemBlocks,
340
- getPluginSystemBlocks: this.getPluginSystemBlocks,
341
- });
342
- await forked.initialize();
343
- if (this.sessionConfig.model) {
344
- await forked.set({
345
- model: this.sessionConfig.model,
346
- });
347
- }
348
- for (const message of forkMessages) {
349
- await forked.historyStore.append(message);
350
- }
351
- await forked.ensureTitleFromHistory({ generate: true });
352
- await forked.touchMetadata();
353
- return forked;
218
+ return await this.viewService.fork(input);
354
219
  }
355
220
  /**
356
221
  * 返回供受托管 plugin 使用的 session 端口。
@@ -361,25 +226,19 @@ export class Session {
361
226
  this.runtimePort = createRuntimeSessionPort({
362
227
  sessionId: this.id,
363
228
  getExecutor: () => this.executor.getExecutor(),
364
- prompt: async (input) => {
365
- return await this.prompt(input);
366
- },
367
- subscribe: (subscriber) => {
368
- return this.subscribe(subscriber);
369
- },
229
+ prompt: async (input) => await this.prompt(input),
230
+ subscribe: (subscriber) => this.subscribe(subscriber),
370
231
  clearExecutor: () => {
371
232
  this.executor.clearExecutor();
372
233
  },
373
234
  afterSessionUpdatedAsync: async () => {
374
235
  await this.executor.afterSessionUpdatedAsync();
375
236
  },
376
- appendUserMessage: async (messageParams) => {
377
- await this.executor.appendUserMessage(messageParams);
378
- await this.ensureTitleFromHistory({ generate: true });
379
- await this.touchMetadata();
237
+ appendUserMessage: async (message_params) => {
238
+ await this.stateService.append_user_message(message_params);
380
239
  },
381
- appendAssistantMessage: async (messageParams) => {
382
- await this.executor.appendAssistantMessage(messageParams);
240
+ appendAssistantMessage: async (message_params) => {
241
+ await this.stateService.append_assistant_message(message_params);
383
242
  },
384
243
  isExecuting: () => this.isExecuting(),
385
244
  historyStore: this.historyStore,
@@ -387,7 +246,7 @@ export class Session {
387
246
  await this.ensureReadyForExecution();
388
247
  },
389
248
  touchMetadata: async () => {
390
- await this.touchMetadata();
249
+ await this.stateService.touch_metadata();
391
250
  },
392
251
  });
393
252
  return this.runtimePort;
@@ -396,149 +255,85 @@ export class Session {
396
255
  * 在执行前确保 session 已完成初始化与宿主装配。
397
256
  */
398
257
  async ensureReadyForExecution() {
399
- await this.initialize();
400
- if (this.ensureConfiguredPromise) {
401
- await this.ensureConfiguredPromise;
402
- return;
403
- }
404
- this.ensureConfiguredPromise = (async () => {
405
- if (!this.ensureConfiguredHook)
406
- return;
407
- await this.ensureConfiguredHook(this);
408
- })();
409
- try {
410
- await this.ensureConfiguredPromise;
411
- }
412
- catch (error) {
413
- this.ensureConfiguredPromise = null;
414
- throw error;
415
- }
416
- }
417
- async ensureRunnable() {
418
- await this.ensureReadyForExecution();
419
- if (!this.sessionConfig.model) {
420
- throw new Error(`Session "${this.id}" requires a configured model. Pass model to new Agent({ model }) or call session.set({ model }) first.`);
421
- }
422
- }
423
- async touchMetadata() {
424
- await touchSessionMetadata({
425
- projectRoot: this.projectRoot,
426
- agentId: this.agentId,
427
- sessionId: this.id,
428
- sessionConfig: this.sessionConfig,
429
- });
258
+ await this.stateService.ensure_ready_for_execution();
430
259
  }
431
- async ensureTitleFromHistory(input) {
432
- const messages = await this.historyStore.list();
433
- const beforeMetadata = await readSessionMetadata({
434
- projectRoot: this.projectRoot,
260
+ create_fork_session(session_id) {
261
+ return this.create_child_session({
435
262
  agentId: this.agentId,
436
- sessionId: this.id,
437
- });
438
- const beforeTitle = String(beforeMetadata.title || "").trim();
439
- const nextMetadata = await ensureSessionTitle({
440
263
  projectRoot: this.projectRoot,
441
- agentId: this.agentId,
442
- sessionId: this.id,
443
- messages,
444
- ...(input?.generate ? { model: this.sessionConfig.model } : {}),
445
- generate: input?.generate === true,
446
- });
447
- const nextTitle = String(nextMetadata.title || "").trim();
448
- if (!nextTitle || nextTitle === beforeTitle)
449
- return;
450
- this.eventHub.publish({
451
- type: "session-title",
452
- sessionId: this.id,
453
- title: nextTitle,
264
+ sessionId: session_id,
265
+ tools: this.tools,
266
+ logger: this.logger,
267
+ getInstructionSystemBlocks: this.getInstructionSystemBlocks,
268
+ getManagedPluginSystemBlocks: this.getManagedPluginSystemBlocks,
269
+ getPluginSystemBlocks: this.getPluginSystemBlocks,
270
+ ensureConfigured: this.ensureConfiguredHook,
271
+ composers: this.composers,
454
272
  });
455
273
  }
456
- async persistAssistantResult(assistantMessage) {
457
- await persistSdkAssistantResult({
458
- projectRoot: this.projectRoot,
274
+ /**
275
+ * 创建当前 Session 的同类子会话。
276
+ *
277
+ * 关键点(中文)
278
+ * - 默认沿用当前实例的 class,避免自定义 Session 在 fork 后退回默认实现。
279
+ * - 子类仍可覆盖该方法,接管更特殊的子会话创建逻辑。
280
+ */
281
+ create_child_session(options) {
282
+ const SessionClass = this.constructor;
283
+ return new SessionClass(options);
284
+ }
285
+ create_history_store() {
286
+ const session_dir_path = getSdkAgentSessionDirPath(this.projectRoot, this.agentId, this.id);
287
+ const messages_dir_path = `${session_dir_path}/messages`;
288
+ return new JsonlSessionHistoryStore({
289
+ rootPath: this.projectRoot,
459
290
  agentId: this.agentId,
460
291
  sessionId: this.id,
461
- sessionConfig: this.sessionConfig,
462
- executor: this.executor,
463
- assistantMessage,
464
- });
465
- }
466
- async createAndPersistUserPromptMessage(input) {
467
- const message = this.historyStore.userText({
468
- text: String(input.query || "").trim(),
469
- metadata: {
470
- sessionId: this.id,
292
+ paths: {
293
+ sessionDirPath: session_dir_path,
294
+ messagesDirPath: messages_dir_path,
295
+ messagesFilePath: `${messages_dir_path}/messages.jsonl`,
296
+ metaFilePath: `${messages_dir_path}/meta.json`,
297
+ archiveDirPath: getSdkAgentSessionArchiveDirPath(this.projectRoot, this.agentId, this.id),
298
+ inflightFilePath: getSdkAgentSessionInflightPath(this.projectRoot, this.agentId, this.id),
471
299
  },
472
300
  });
473
- await this.executor.appendUserMessage({
474
- message,
475
- });
476
- await this.ensureTitleFromHistory({ generate: true });
477
- await this.touchMetadata();
478
- return message;
479
301
  }
480
- async executePromptTurn(input) {
481
- const toolNameByCallId = new Map();
482
- const result = await this.executor.run({
483
- query: input.promptInput.query,
484
- onStepCallback: input.onStepMerge,
485
- onAssistantStepCallback: async (step) => {
486
- this.eventHub.publish({
487
- type: "assistant-step",
488
- turnId: input.turnId,
489
- text: step.text,
490
- stepIndex: step.stepIndex,
491
- ...(step.visibility ? { visibility: step.visibility } : {}),
492
- });
493
- },
494
- onUiMessageChunkCallback: async (chunk) => {
495
- if (chunk.type === "tool-input-start") {
496
- toolNameByCallId.set(chunk.toolCallId, chunk.toolName);
497
- return;
498
- }
499
- const event = mapUiMessageChunkToAgentEvent(chunk);
500
- if (!event)
501
- return;
502
- const resolvedEvent = (event.type === "tool-result" ||
503
- event.type === "tool-error") &&
504
- event.toolName === "unknown"
505
- ? {
506
- ...event,
507
- toolName: toolNameByCallId.get(event.toolCallId) || event.toolName,
508
- }
509
- : event;
510
- if (resolvedEvent.type === "tool-call" ||
511
- resolvedEvent.type === "tool-error") {
512
- toolNameByCallId.set(resolvedEvent.toolCallId, resolvedEvent.toolName);
513
- }
514
- const sessionEvent = mapAgentEventToSessionEvent({
515
- event: resolvedEvent,
516
- turnId: input.turnId,
517
- });
518
- if (sessionEvent) {
519
- this.eventHub.publish(sessionEvent);
520
- }
521
- },
522
- });
523
- await this.persistAssistantResult(result.assistantMessage);
524
- await this.persistDeferredUserMessages();
302
+ create_local_state() {
525
303
  return {
526
- text: extractTextFromUiMessage(result.assistantMessage),
527
- success: result.success,
528
- assistantMessage: result.assistantMessage,
529
- ...(result.error ? { error: result.error } : {}),
304
+ sessionConfig: {},
305
+ createdAt: Date.now(),
306
+ timezone: resolveSystemTimezone(),
307
+ initializePromise: null,
308
+ ensureConfiguredPromise: null,
530
309
  };
531
310
  }
532
- async persistDeferredUserMessages() {
533
- const deferredMessages = drainDeferredPersistedUserMessages(this.id);
534
- for (const message of deferredMessages) {
535
- await this.executor.appendUserMessage({
536
- message,
537
- });
538
- }
539
- if (deferredMessages.length > 0) {
540
- await this.touchMetadata();
311
+ create_composer_context() {
312
+ return {
313
+ agentId: this.agentId,
314
+ projectRoot: this.projectRoot,
315
+ sessionId: this.id,
316
+ historyStore: this.historyStore,
317
+ getTools: () => this.tools,
318
+ getInstructionSystemBlocks: this.getInstructionSystemBlocks,
319
+ getManagedPluginSystemBlocks: this.getManagedPluginSystemBlocks,
320
+ getPluginSystemBlocks: this.getPluginSystemBlocks,
321
+ getSessionCreatedAt: () => this.localState.createdAt,
322
+ getSessionTimezone: () => this.localState.timezone,
323
+ };
324
+ }
325
+ resolve_composer(input, context, create_default) {
326
+ const composer = this.resolve_optional_composer(input, context);
327
+ return composer || create_default();
328
+ }
329
+ resolve_optional_composer(input, context) {
330
+ if (!input)
331
+ return undefined;
332
+ if (typeof input === "function") {
333
+ const create_composer = input;
334
+ return create_composer(context);
541
335
  }
336
+ return input;
542
337
  }
543
338
  }
544
339
  //# sourceMappingURL=Session.js.map