foliko 1.1.92 → 2.0.0

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 (212) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/CLAUDE.md +56 -30
  3. package/REFACTORING_PLAN.md +645 -0
  4. package/docs/architecture.md +131 -0
  5. package/docs/migration.md +57 -0
  6. package/docs/public-api.md +138 -0
  7. package/docs/usage.md +385 -0
  8. package/examples/ambient-example.js +20 -137
  9. package/examples/basic.js +21 -48
  10. package/examples/bootstrap.js +16 -74
  11. package/examples/mcp-example.js +6 -29
  12. package/examples/skill-example.js +6 -19
  13. package/examples/workflow.js +8 -56
  14. package/package.json +8 -4
  15. package/plugins/README.md +49 -0
  16. package/plugins/{ambient-agent → ambient}/EventWatcher.js +1 -1
  17. package/plugins/{ambient-agent → ambient}/ExplorerLoop.js +3 -3
  18. package/plugins/{ambient-agent → ambient}/GoalManager.js +2 -2
  19. package/plugins/ambient/README.md +14 -0
  20. package/plugins/{ambient-agent → ambient}/Reflector.js +1 -1
  21. package/plugins/{ambient-agent → ambient}/StateStore.js +1 -1
  22. package/plugins/{ambient-agent → ambient}/index.js +2 -2
  23. package/plugins/{ai-plugin.js → core/ai/index.js} +14 -30
  24. package/plugins/{audit-plugin.js → core/audit/index.js} +3 -30
  25. package/plugins/{coordinator-plugin.js → core/coordinator/index.js} +3 -35
  26. package/plugins/core/default/bootstrap.js +202 -0
  27. package/plugins/core/default/config.js +220 -0
  28. package/plugins/core/default/index.js +58 -0
  29. package/plugins/core/mcp/index.js +1 -0
  30. package/plugins/{python-plugin-loader.js → core/python-loader/index.js} +7 -187
  31. package/plugins/{rules-plugin.js → core/rules/index.js} +121 -64
  32. package/plugins/{scheduler-plugin.js → core/scheduler/index.js} +12 -114
  33. package/plugins/{session-plugin.js → core/session/index.js} +9 -73
  34. package/{src/capabilities/skill-manager.js → plugins/core/skill-manager/index.js} +64 -18
  35. package/plugins/{storage-plugin.js → core/storage/index.js} +5 -29
  36. package/plugins/{subagent-plugin.js → core/sub-agent/index.js} +10 -171
  37. package/plugins/{think-plugin.js → core/think/index.js} +24 -91
  38. package/{src/capabilities/workflow-engine.js → plugins/core/workflow/index.js} +87 -85
  39. package/plugins/default-plugins.js +6 -720
  40. package/plugins/{data-splitter-plugin.js → executors/data-splitter/index.js} +9 -83
  41. package/plugins/{extension-executor-plugin.js → executors/extension/index.js} +13 -97
  42. package/plugins/{python-executor-plugin.js → executors/python/index.js} +6 -31
  43. package/plugins/{shell-executor-plugin.js → executors/shell/index.js} +2 -5
  44. package/plugins/install/README.md +9 -0
  45. package/plugins/{install-plugin.js → install/index.js} +3 -3
  46. package/plugins/{file-system-plugin.js → io/file-system/index.js} +34 -236
  47. package/plugins/{web-plugin.js → io/web/index.js} +11 -113
  48. package/plugins/memory/README.md +13 -0
  49. package/plugins/{memory-plugin.js → memory/index.js} +4 -18
  50. package/plugins/messaging/email/README.md +19 -0
  51. package/plugins/{email → messaging/email}/index.js +2 -2
  52. package/plugins/{feishu-plugin.js → messaging/feishu/index.js} +3 -3
  53. package/plugins/{qq-plugin.js → messaging/qq/index.js} +5 -16
  54. package/plugins/{telegram-plugin.js → messaging/telegram/index.js} +3 -3
  55. package/plugins/{weixin-plugin.js → messaging/weixin/index.js} +15 -15
  56. package/plugins/{plugin-manager-plugin.js → plugin-manager/index.js} +36 -180
  57. package/plugins/{tools-plugin.js → tools/index.js} +68 -116
  58. package/plugins/trading/README.md +15 -0
  59. package/plugins/{gate-trading.js → trading/index.js} +8 -8
  60. package/{examples → sandbox}/test-concurrent-chat.js +2 -2
  61. package/{examples → sandbox}/test-long-chat.js +2 -2
  62. package/{examples → sandbox}/test-session-chat.js +2 -2
  63. package/{examples → sandbox}/test-web-plugin.js +1 -1
  64. package/{examples → sandbox}/test-weixin-feishu.js +2 -2
  65. package/src/agent/base.js +56 -0
  66. package/src/{core/agent-chat.js → agent/chat.js} +11 -11
  67. package/src/{core/coordinator-manager.js → agent/coordinator.js} +3 -3
  68. package/src/agent/index.js +111 -0
  69. package/src/agent/main.js +337 -0
  70. package/src/agent/prompt.js +78 -0
  71. package/src/agent/sub.js +198 -0
  72. package/src/agent/worker.js +104 -0
  73. package/{cli/bin/foliko.js → src/cli/bin.js} +1 -1
  74. package/{cli/src → src/cli}/commands/chat.js +25 -21
  75. package/{cli/src → src/cli}/index.js +1 -0
  76. package/{cli/src → src/cli}/ui/chat-ui-old.js +40 -178
  77. package/{cli/src → src/cli}/ui/chat-ui.js +3 -3
  78. package/{cli/src → src/cli}/ui/components/footer-bar.js +1 -1
  79. package/src/{core → common}/constants.js +3 -0
  80. package/src/common/errors.js +402 -0
  81. package/src/{utils → common}/logger.js +33 -0
  82. package/src/{utils/chat-queue.js → common/queue.js} +2 -2
  83. package/src/config/plugin-config.js +50 -0
  84. package/src/context/agent.js +32 -0
  85. package/src/context/compaction-prompts.js +170 -0
  86. package/src/context/compaction-utils.js +191 -0
  87. package/src/context/compressor.js +413 -0
  88. package/src/context/index.js +9 -0
  89. package/src/{core/context-manager.js → context/manager.js} +1 -1
  90. package/src/context/request.js +50 -0
  91. package/src/context/session.js +33 -0
  92. package/src/context/storage.js +30 -0
  93. package/src/executors/mcp-client.js +153 -0
  94. package/src/executors/mcp-desc.js +236 -0
  95. package/src/executors/mcp-executor.js +91 -956
  96. package/src/{core → framework}/command-registry.js +1 -1
  97. package/src/framework/framework.js +300 -0
  98. package/src/framework/index.js +18 -0
  99. package/src/framework/lifecycle.js +203 -0
  100. package/src/framework/loader.js +78 -0
  101. package/src/framework/registry.js +86 -0
  102. package/src/{core/ui-extension-context.js → framework/ui-extension.js} +1 -1
  103. package/src/index.js +130 -15
  104. package/src/llm/index.js +26 -0
  105. package/src/llm/provider.js +212 -0
  106. package/src/llm/registry.js +11 -0
  107. package/src/{core/token-counter.js → llm/tokens.js} +4 -37
  108. package/src/{core/plugin-base.js → plugin/base.js} +10 -136
  109. package/src/plugin/index.js +14 -0
  110. package/src/plugin/loader.js +101 -0
  111. package/src/plugin/manager.js +261 -0
  112. package/src/{core → session}/branch-summary-auto.js +2 -2
  113. package/src/{core/chat-session.js → session/chat.js} +2 -2
  114. package/src/session/index.js +7 -0
  115. package/src/{core/session-manager.js → session/session.js} +2 -2
  116. package/src/session/ttl.js +92 -0
  117. package/src/{core/jsonl-storage.js → storage/jsonl.js} +1 -1
  118. package/src/tool/executor.js +85 -0
  119. package/src/tool/index.js +15 -0
  120. package/src/tool/registry.js +143 -0
  121. package/src/{core/tool-router.js → tool/router.js} +17 -124
  122. package/src/tool/schema.js +108 -0
  123. package/src/utils/data-splitter.js +1 -1
  124. package/src/utils/download.js +1 -1
  125. package/src/utils/index.js +6 -6
  126. package/src/utils/message-validator.js +1 -1
  127. package/tests/core/context-storage.test.js +46 -0
  128. package/tests/core/llm.test.js +54 -0
  129. package/tests/core/plugin.test.js +42 -0
  130. package/tests/core/tool.test.js +60 -0
  131. package/tests/setup.js +10 -0
  132. package/tests/smoke.test.js +58 -0
  133. package/vitest.config.js +9 -0
  134. package/cli/src/daemon.js +0 -149
  135. package/docs/CONTEXT_DESIGN.md +0 -1596
  136. package/docs/ai-sdk-optimization.md +0 -655
  137. package/docs/features.md +0 -120
  138. package/docs/qq-bot.md +0 -976
  139. package/docs/quick-reference.md +0 -160
  140. package/docs/user-manual.md +0 -1391
  141. package/images/geometric_shapes.jpg +0 -0
  142. package/images/sunset_mountain_lake.jpg +0 -0
  143. package/skills/poster-guide/SKILL.md +0 -792
  144. package/src/capabilities/index.js +0 -11
  145. package/src/core/agent.js +0 -808
  146. package/src/core/context-compressor.js +0 -959
  147. package/src/core/enhanced-context-compressor.js +0 -210
  148. package/src/core/framework.js +0 -1422
  149. package/src/core/index.js +0 -30
  150. package/src/core/plugin-manager.js +0 -961
  151. package/src/core/provider-registry.js +0 -159
  152. package/src/core/provider.js +0 -156
  153. package/src/core/request-context.js +0 -98
  154. package/src/core/subagent.js +0 -442
  155. package/src/core/system-prompt-builder.js +0 -120
  156. package/src/core/tool-executor.js +0 -202
  157. package/src/core/tool-registry.js +0 -517
  158. package/src/core/worker-agent.js +0 -192
  159. package/src/executors/executor-base.js +0 -58
  160. package/src/utils/error-boundary.js +0 -363
  161. package/src/utils/error.js +0 -374
  162. package/system.md +0 -1645
  163. package/website_v2/README.md +0 -57
  164. package/website_v2/SPEC.md +0 -1
  165. package/website_v2/docs/api.html +0 -128
  166. package/website_v2/docs/configuration.html +0 -147
  167. package/website_v2/docs/plugin-development.html +0 -129
  168. package/website_v2/docs/project-structure.html +0 -89
  169. package/website_v2/docs/skill-development.html +0 -85
  170. package/website_v2/index.html +0 -489
  171. package/website_v2/scripts/main.js +0 -93
  172. package/website_v2/styles/animations.css +0 -8
  173. package/website_v2/styles/docs.css +0 -83
  174. package/website_v2/styles/main.css +0 -417
  175. package/xhs_auth.json +0 -268
  176. package//346/265/267/346/212/245/346/217/222/344/273/266.md +0 -621
  177. /package/plugins/{ambient-agent → ambient}/constants.js +0 -0
  178. /package/plugins/{email → messaging/email}/constants.js +0 -0
  179. /package/plugins/{email → messaging/email}/handlers.js +0 -0
  180. /package/plugins/{email → messaging/email}/monitor.js +0 -0
  181. /package/plugins/{email → messaging/email}/parser.js +0 -0
  182. /package/plugins/{email → messaging/email}/reply.js +0 -0
  183. /package/plugins/{email → messaging/email}/utils.js +0 -0
  184. /package/{examples → sandbox}/test-chat.js +0 -0
  185. /package/{examples → sandbox}/test-mcp.js +0 -0
  186. /package/{examples → sandbox}/test-reload.js +0 -0
  187. /package/{examples → sandbox}/test-telegram.js +0 -0
  188. /package/{examples → sandbox}/test-tg-bot.js +0 -0
  189. /package/{examples → sandbox}/test-tg-simple.js +0 -0
  190. /package/{examples → sandbox}/test-tg.js +0 -0
  191. /package/{examples → sandbox}/test-think.js +0 -0
  192. /package/src/{core/sub-agent-config.js → agent/sub-config.js} +0 -0
  193. /package/{cli/src → src/cli}/commands/daemon.js +0 -0
  194. /package/{cli/src → src/cli}/commands/list.js +0 -0
  195. /package/{cli/src → src/cli}/commands/plugin.js +0 -0
  196. /package/{cli/src → src/cli}/ui/components/agent-mention-provider.js +0 -0
  197. /package/{cli/src → src/cli}/ui/components/chained-autocomplete-provider.js +0 -0
  198. /package/{cli/src → src/cli}/ui/components/message-bubble.js +0 -0
  199. /package/{cli/src → src/cli}/ui/components/status-bar.js +0 -0
  200. /package/{cli/src → src/cli}/utils/ansi.js +0 -0
  201. /package/{cli/src → src/cli}/utils/config.js +0 -0
  202. /package/{cli/src → src/cli}/utils/markdown.js +0 -0
  203. /package/{cli/src → src/cli}/utils/plugin-config.js +0 -0
  204. /package/{cli/src → src/cli}/utils/render-diff.js +0 -0
  205. /package/src/{utils/circuit-breaker.js → common/circuit.js} +0 -0
  206. /package/src/{utils/edit-diff.js → common/diff.js} +0 -0
  207. /package/src/{utils/event-emitter.js → common/events.js} +0 -0
  208. /package/src/{utils → common}/id.js +0 -0
  209. /package/src/{utils → common}/retry.js +0 -0
  210. /package/src/{core/notification-manager.js → notification/manager.js} +0 -0
  211. /package/src/{core/session-entry.js → session/entry.js} +0 -0
  212. /package/src/{core/storage-manager.js → storage/manager.js} +0 -0
@@ -1,159 +0,0 @@
1
- /**
2
- * ProviderRegistry - Dynamic LLM Provider Registration
3
- * 允许插件动态注册 LLM Provider
4
- */
5
-
6
- const { createOpenAICompatible } = require('ai');
7
- const { logger } = require('../utils/logger');
8
-
9
- class ProviderRegistry {
10
- constructor() {
11
- this._providers = new Map();
12
- this._models = new Map();
13
- }
14
-
15
- /**
16
- * 注册 Provider
17
- * @param {string} name - Provider 名称 (如 'openai', 'deepseek')
18
- * @param {Object} config - Provider 配置
19
- * @param {string} config.baseURL - API base URL
20
- * @param {string} [config.apiKey] - API key
21
- * @param {string} [config.name] - 显示名称
22
- * @param {string} [config.defaultModel] - 默认模型
23
- * @param {Object} [config.headers] - 自定义 headers
24
- */
25
- registerProvider(name, config) {
26
- this._providers.set(name, {
27
- name: config.name || name,
28
- baseURL: config.baseURL,
29
- apiKey: config.apiKey || '',
30
- defaultModel: config.defaultModel || '',
31
- headers: config.headers || {},
32
- });
33
-
34
- if (config.defaultModel) {
35
- this.registerModel(config.defaultModel, name, {
36
- label: config.defaultModel,
37
- description: `Default model for ${name}`,
38
- });
39
- }
40
-
41
- logger.debug(`[ProviderRegistry] Registered provider: ${name}`);
42
- return this;
43
- }
44
-
45
- /**
46
- * 注册模型
47
- * @param {string} modelId - 模型 ID
48
- * @param {string} provider - Provider 名称
49
- * @param {Object} [options] - 模型选项
50
- */
51
- registerModel(modelId, provider, options = {}) {
52
- this._models.set(modelId, { provider, ...options });
53
- return this;
54
- }
55
-
56
- /**
57
- * 获取 Provider 配置
58
- */
59
- getProvider(name) {
60
- return this._providers.get(name);
61
- }
62
-
63
- /**
64
- * 获取模型配置
65
- */
66
- getModel(modelId) {
67
- return this._models.get(modelId);
68
- }
69
-
70
- /**
71
- * 获取所有已注册的 Provider 名称
72
- */
73
- getProviderNames() {
74
- return Array.from(this._providers.keys());
75
- }
76
-
77
- /**
78
- * 检查 Provider 是否已注册
79
- */
80
- hasProvider(name) {
81
- return this._providers.has(name);
82
- }
83
-
84
- /**
85
- * 创建 AI 客户端
86
- * @param {string} providerName - Provider 名称
87
- * @param {string} model - 模型 ID
88
- * @param {string} [apiKey] - API key (可选,会使用注册时提供的)
89
- * @param {string} [baseURL] - Base URL (可选,会使用注册时提供的)
90
- */
91
- createClient(providerName, model, apiKey, baseURL) {
92
- const provider = this._providers.get(providerName);
93
- if (!provider) {
94
- throw new Error(`Provider '${providerName}' not registered. Use framework.registerProvider() first.`);
95
- }
96
-
97
- const finalApiKey = apiKey || provider.apiKey;
98
- const finalBaseURL = baseURL || provider.baseURL;
99
- const finalModel = model || provider.defaultModel;
100
-
101
- if (!finalApiKey) {
102
- throw new Error(`No API key provided for provider '${providerName}'`);
103
- }
104
-
105
- const client = createOpenAICompatible({
106
- baseURL: finalBaseURL,
107
- apiKey: finalApiKey,
108
- });
109
-
110
- return client(finalModel);
111
- }
112
-
113
- /**
114
- * 移除 Provider
115
- */
116
- unregisterProvider(name) {
117
- this._providers.delete(name);
118
- // 同时移除该 provider 的所有模型
119
- for (const [modelId, modelConfig] of this._models) {
120
- if (modelConfig.provider === name) {
121
- this._models.delete(modelId);
122
- }
123
- }
124
- return this;
125
- }
126
- }
127
-
128
- // 单例
129
- const _registry = new ProviderRegistry();
130
-
131
- /**
132
- * 获取 Provider Registry 实例
133
- */
134
- function getProviderRegistry() {
135
- return _registry;
136
- }
137
-
138
- /**
139
- * 注册默认的 Providers
140
- */
141
- function registerDefaultProviders() {
142
- const { DEFAULT_PROVIDERS } = require('./provider');
143
-
144
- for (const [key, config] of Object.entries(DEFAULT_PROVIDERS)) {
145
- _registry.registerProvider(key, {
146
- name: config.name,
147
- baseURL: config.baseURL,
148
- defaultModel: config.defaultModel,
149
- });
150
- }
151
- }
152
-
153
- // 初始化时注册默认 providers
154
- registerDefaultProviders();
155
-
156
- module.exports = {
157
- ProviderRegistry,
158
- getProviderRegistry,
159
- };
@@ -1,156 +0,0 @@
1
- /**
2
- * AI Provider 工厂
3
- * 支持多种 AI 提供商
4
- */
5
-
6
- const { createOpenAICompatible } = require('@ai-sdk/openai-compatible');
7
- const { createOpenAI } = require('@ai-sdk/openai');
8
- const { createAnthropic } = require('@ai-sdk/anthropic');
9
-
10
- /**
11
- * 默认提供商配置
12
- */
13
- const DEFAULT_PROVIDERS = {
14
- openai: {
15
- name: 'OpenAI',
16
- baseURL: 'https://api.openai.com/v1',
17
- defaultModel: 'gpt-4o',
18
- },
19
- ollama: {
20
- name: 'Ollama',
21
- baseURL: 'http://localhost:11434/v1',
22
- defaultModel: 'llama3',
23
- },
24
- lmstudio: {
25
- name: 'LM Studio',
26
- baseURL: 'http://localhost:1234/v1',
27
- defaultModel: 'local-model',
28
- },
29
- deepseek: {
30
- name: 'DeepSeek',
31
- baseURL: 'https://api.deepseek.com/v1',
32
- defaultModel: 'deepseek-chat',
33
- },
34
- anthropic: {
35
- name: 'Anthropic',
36
- baseURL: 'https://api.anthropic.com/v1',
37
- defaultModel: 'claude-sonnet-4-20250514',
38
- },
39
- minimax: {
40
- name: 'MiniMax',
41
- baseURL: 'https://api.minimaxi.com/v1',
42
- defaultModel: 'MiniMax-M2.7',
43
- },
44
- };
45
-
46
- /**
47
- * 需要禁用 temperature 的模型(thinking mode 模型)
48
- */
49
- const THINKING_MODELS = [
50
- 'deepseek-v4-pro',
51
- 'deepseek-v4-flash',
52
- 'deepseek-reasoner',
53
- ];
54
-
55
- /**
56
- * 检查是否是 thinking mode 模型
57
- * @param {string} model - 模型名称
58
- * @returns {boolean}
59
- */
60
- function isThinkingModel(model) {
61
- if (!model) return false;
62
- const lowerModel = model.toLowerCase();
63
- return THINKING_MODELS.some(
64
- (tm) => lowerModel.includes(tm) || lowerModel === tm
65
- );
66
- }
67
-
68
- /**
69
- * 创建 AI 客户端
70
- * @param {Object} config - 配置
71
- * @param {string} config.provider - 提供商名称
72
- * @param {string} config.model - 模型名称
73
- * @param {string} config.apiKey - API 密钥
74
- * @param {string} [config.baseURL] - 自定义 API 地址
75
- */
76
- function createAI(config) {
77
- const { provider, model, apiKey, baseURL } = config;
78
- const providerName = (provider || 'deepseek').toLowerCase();
79
- const isThinking = isThinkingModel(model);
80
-
81
- // 检查是否是预定义提供商
82
- if (DEFAULT_PROVIDERS[providerName]) {
83
- const providerConfig = DEFAULT_PROVIDERS[providerName];
84
-
85
- // 为 DeepSeek thinking mode 模型添加特殊配置
86
- const streamOptions = {
87
- includeUsage: true,
88
- };
89
-
90
- // DeepSeek 模型添加 reasoning_content 输出
91
- if (providerName === 'deepseek') {
92
- streamOptions.includeReasoningContent = true;
93
- }
94
-
95
- return createOpenAICompatible({
96
- name: providerConfig.name,
97
- baseURL: baseURL || providerConfig.baseURL,
98
- apiKey: apiKey || 'dummy-key',
99
- headers:
100
- provider === 'anthropic'
101
- ? {
102
- 'x-api-key': apiKey,
103
- 'anthropic-version': '2023-06-01',
104
- }
105
- : undefined,
106
- models: {
107
- default: {
108
- id: model || 'deepseek-chat',
109
- streamOptions,
110
- },
111
- },
112
- });
113
- }
114
-
115
- // 自定义提供商
116
- return createOpenAICompatible({
117
- name: providerName || 'Custom',
118
- baseURL: baseURL,
119
- apiKey: apiKey || 'dummy-key',
120
- models: {
121
- default: {
122
- id: model || 'gpt-4',
123
- },
124
- },
125
- });
126
- }
127
-
128
- /**
129
- * 获取可用提供商列表
130
- */
131
- function getAvailableProviders() {
132
- return Object.entries(DEFAULT_PROVIDERS).map(([key, value]) => ({
133
- id: key,
134
- name: value.name,
135
- baseURL: value.baseURL,
136
- }));
137
- }
138
-
139
- /**
140
- * 创建模型实例
141
- * @param {string} model - 模型名称
142
- * @param {Object} provider - Provider 实例
143
- */
144
- function createModel(model, provider) {
145
- return provider(model);
146
- }
147
-
148
- module.exports = {
149
- createAI,
150
- createModel,
151
- getAvailableProviders,
152
- DEFAULT_PROVIDERS,
153
- isThinkingModel,
154
- getProviderRegistry: () => require('./provider-registry').getProviderRegistry(),
155
- registerProvider: (name, config) => require('./provider-registry').getProviderRegistry().registerProvider(name, config),
156
- };
@@ -1,98 +0,0 @@
1
- /**
2
- * RequestContext - Request 级别的上下文封装
3
- *
4
- * 职责:
5
- * 1. 追踪请求链路(requestId, traceId)
6
- * 2. 管理请求级超时
7
- * 3. 传递请求元数据
8
- */
9
-
10
- const { uuid } = require('../utils/id');
11
-
12
- class RequestContext {
13
- /**
14
- * @param {Object} options - 配置选项
15
- * @param {string} [options.requestId] - 请求 ID,默认自动生成
16
- * @param {string} [options.traceId] - 追踪 ID,默认自动生成
17
- * @param {string} [options.parentSpanId] - 父 span ID
18
- * @param {number} [options.timeout] - 超时时间(毫秒),默认 120000
19
- * @param {boolean} [options.isStream] - 是否为流式请求
20
- * @param {string} [options.userId] - 用户标识
21
- */
22
- constructor(options = {}) {
23
- this.requestId = options.requestId || `req_${uuid()}`;
24
- this.traceId = options.traceId || `trace_${uuid()}`;
25
- this.traceId = options.traceId || generateId();
26
- this.parentSpanId = options.parentSpanId || null;
27
-
28
- this.timeout = options.timeout || 120000; // 默认 2 分钟
29
- this.startTime = options.startTime || Date.now();
30
-
31
- this.isStream = options.isStream || false;
32
- this.userId = options.userId || null;
33
-
34
- // 请求级状态
35
- this.cancelled = false;
36
- this.abortController = null;
37
-
38
- // 元数据
39
- this.metadata = options.metadata || {};
40
- }
41
-
42
- /**
43
- * 创建 AbortController(延迟初始化)
44
- * @returns {AbortController}
45
- */
46
- getAbortController() {
47
- if (!this.abortController) {
48
- this.abortController = new AbortController();
49
- }
50
- return this.abortController;
51
- }
52
-
53
- /**
54
- * 检查是否超时
55
- * @returns {boolean}
56
- */
57
- isTimeout() {
58
- return Date.now() - this.startTime > this.timeout;
59
- }
60
-
61
- /**
62
- * 取消请求
63
- */
64
- cancel() {
65
- this.cancelled = true;
66
- if (this.abortController) {
67
- this.abortController.abort();
68
- }
69
- }
70
-
71
- /**
72
- * 获取请求耗时(毫秒)
73
- * @returns {number}
74
- */
75
- getElapsed() {
76
- return Date.now() - this.startTime;
77
- }
78
-
79
- /**
80
- * 获取请求摘要
81
- * @returns {Object}
82
- */
83
- toJSON() {
84
- return {
85
- requestId: this.requestId,
86
- traceId: this.traceId,
87
- parentSpanId: this.parentSpanId,
88
- timeout: this.timeout,
89
- startTime: this.startTime,
90
- elapsed: this.getElapsed(),
91
- isStream: this.isStream,
92
- userId: this.userId,
93
- cancelled: this.cancelled,
94
- };
95
- }
96
- }
97
-
98
- module.exports = { RequestContext };