foliko 1.0.73 → 1.0.75

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 (237) hide show
  1. package/.agent/.shared/ui-ux-pro-max/data/charts.csv +26 -0
  2. package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
  3. package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
  4. package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
  5. package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
  6. package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
  7. package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
  8. package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  9. package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  10. package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  11. package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  12. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  13. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  14. package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  15. package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
  16. package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  17. package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  18. package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  19. package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  20. package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
  21. package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
  22. package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  23. package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  24. package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
  25. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  26. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  27. package/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
  28. package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +1067 -0
  29. package/.agent/.shared/ui-ux-pro-max/scripts/search.py +106 -0
  30. package/.agent/ARCHITECTURE.md +288 -0
  31. package/.agent/agents/ambient-agent.md +57 -0
  32. package/.agent/agents/debugger.md +55 -0
  33. package/.agent/agents/email-assistant.md +49 -0
  34. package/.agent/agents/file-manager.md +42 -0
  35. package/.agent/agents/python-developer.md +60 -0
  36. package/.agent/agents/scheduler.md +59 -0
  37. package/.agent/agents/web-developer.md +45 -0
  38. package/.agent/data/default.json +29 -0
  39. package/.agent/data/plugins-state.json +255 -0
  40. package/.agent/mcp_config.json +4 -0
  41. package/.agent/mcp_config_updated.json +12 -0
  42. package/.agent/plugins.json +5 -0
  43. package/.agent/rules/GEMINI.md +273 -0
  44. package/.agent/rules/allow-rule.md +77 -0
  45. package/.agent/rules/log-rule.md +83 -0
  46. package/.agent/rules/security-rule.md +93 -0
  47. package/.agent/scripts/auto_preview.py +148 -0
  48. package/.agent/scripts/checklist.py +217 -0
  49. package/.agent/scripts/session_manager.py +120 -0
  50. package/.agent/scripts/verify_all.py +327 -0
  51. package/.agent/skills/api-patterns/SKILL.md +81 -0
  52. package/.agent/skills/api-patterns/api-style.md +42 -0
  53. package/.agent/skills/api-patterns/auth.md +24 -0
  54. package/.agent/skills/api-patterns/documentation.md +26 -0
  55. package/.agent/skills/api-patterns/graphql.md +41 -0
  56. package/.agent/skills/api-patterns/rate-limiting.md +31 -0
  57. package/.agent/skills/api-patterns/response.md +37 -0
  58. package/.agent/skills/api-patterns/rest.md +40 -0
  59. package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  60. package/.agent/skills/api-patterns/security-testing.md +122 -0
  61. package/.agent/skills/api-patterns/trpc.md +41 -0
  62. package/.agent/skills/api-patterns/versioning.md +22 -0
  63. package/.agent/skills/app-builder/SKILL.md +75 -0
  64. package/.agent/skills/app-builder/agent-coordination.md +71 -0
  65. package/.agent/skills/app-builder/feature-building.md +53 -0
  66. package/.agent/skills/app-builder/project-detection.md +34 -0
  67. package/.agent/skills/app-builder/scaffolding.md +118 -0
  68. package/.agent/skills/app-builder/tech-stack.md +40 -0
  69. package/.agent/skills/app-builder/templates/SKILL.md +39 -0
  70. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  71. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  72. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  73. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  74. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  75. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  76. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  77. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  78. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  79. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  80. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  81. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  82. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  83. package/.agent/skills/architecture/SKILL.md +55 -0
  84. package/.agent/skills/architecture/context-discovery.md +43 -0
  85. package/.agent/skills/architecture/examples.md +94 -0
  86. package/.agent/skills/architecture/pattern-selection.md +68 -0
  87. package/.agent/skills/architecture/patterns-reference.md +50 -0
  88. package/.agent/skills/architecture/trade-off-analysis.md +77 -0
  89. package/.agent/skills/clean-code/SKILL.md +201 -0
  90. package/.agent/skills/doc.md +177 -0
  91. package/.agent/skills/frontend-design/SKILL.md +418 -0
  92. package/.agent/skills/frontend-design/animation-guide.md +331 -0
  93. package/.agent/skills/frontend-design/color-system.md +311 -0
  94. package/.agent/skills/frontend-design/decision-trees.md +418 -0
  95. package/.agent/skills/frontend-design/motion-graphics.md +306 -0
  96. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  97. package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  98. package/.agent/skills/frontend-design/typography-system.md +345 -0
  99. package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
  100. package/.agent/skills/frontend-design/visual-effects.md +383 -0
  101. package/.agent/skills/i18n-localization/SKILL.md +154 -0
  102. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  103. package/.agent/skills/mcp-builder/SKILL.md +176 -0
  104. package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
  105. package/.agent/workflows/brainstorm.md +113 -0
  106. package/.agent/workflows/create.md +59 -0
  107. package/.agent/workflows/debug.md +103 -0
  108. package/.agent/workflows/deploy.md +176 -0
  109. package/.agent/workflows/enhance.md +63 -0
  110. package/.agent/workflows/orchestrate.md +237 -0
  111. package/.agent/workflows/plan.md +89 -0
  112. package/.agent/workflows/preview.md +81 -0
  113. package/.agent/workflows/simple-test.md +42 -0
  114. package/.agent/workflows/status.md +86 -0
  115. package/.agent/workflows/structured-orchestrate.md +180 -0
  116. package/.agent/workflows/test.md +144 -0
  117. package/.agent/workflows/ui-ux-pro-max.md +296 -0
  118. package/.claude/settings.local.json +157 -149
  119. package/.editorconfig +56 -0
  120. package/.husky/pre-commit +4 -0
  121. package/.lintstagedrc +7 -0
  122. package/.prettierignore +29 -0
  123. package/.prettierrc +11 -0
  124. package/CLAUDE.md +2 -0
  125. package/README.md +64 -55
  126. package/SPEC.md +102 -61
  127. package/cli/bin/foliko.js +4 -4
  128. package/cli/src/commands/chat.js +53 -51
  129. package/cli/src/commands/list.js +40 -37
  130. package/cli/src/index.js +18 -18
  131. package/cli/src/ui/chat-ui.js +78 -76
  132. package/cli/src/utils/ansi.js +15 -15
  133. package/cli/src/utils/markdown.js +112 -116
  134. package/docker-compose.yml +1 -1
  135. package/docs/ai-sdk-optimization.md +655 -636
  136. package/docs/features.md +80 -80
  137. package/docs/quick-reference.md +49 -46
  138. package/docs/user-manual.md +411 -380
  139. package/examples/ambient-example.js +95 -97
  140. package/examples/basic.js +115 -110
  141. package/examples/bootstrap.js +52 -43
  142. package/examples/mcp-example.js +56 -53
  143. package/examples/skill-example.js +49 -49
  144. package/examples/test-chat.js +60 -58
  145. package/examples/test-mcp.js +49 -43
  146. package/examples/test-reload.js +38 -40
  147. package/examples/test-telegram.js +3 -3
  148. package/examples/test-tg-bot.js +7 -4
  149. package/examples/test-tg-simple.js +4 -3
  150. package/examples/test-tg.js +3 -3
  151. package/examples/test-think.js +13 -7
  152. package/examples/test-web-plugin.js +61 -56
  153. package/examples/test-weixin-feishu.js +40 -37
  154. package/examples/workflow.js +49 -49
  155. package/foliko-1.0.75.tgz +0 -0
  156. package/package.json +37 -3
  157. package/plugins/ai-plugin.js +7 -5
  158. package/plugins/ambient-agent/EventWatcher.js +113 -0
  159. package/plugins/ambient-agent/ExplorerLoop.js +640 -0
  160. package/plugins/ambient-agent/GoalManager.js +197 -0
  161. package/plugins/ambient-agent/Reflector.js +95 -0
  162. package/plugins/ambient-agent/StateStore.js +90 -0
  163. package/plugins/ambient-agent/constants.js +101 -0
  164. package/plugins/ambient-agent/index.js +579 -0
  165. package/plugins/default-plugins.js +62 -49
  166. package/plugins/email/constants.js +64 -0
  167. package/plugins/email/handlers.js +461 -0
  168. package/plugins/email/index.js +278 -0
  169. package/plugins/email/monitor.js +269 -0
  170. package/plugins/email/parser.js +138 -0
  171. package/plugins/email/reply.js +151 -0
  172. package/plugins/email/utils.js +124 -0
  173. package/plugins/feishu-plugin.js +23 -19
  174. package/plugins/file-system-plugin.js +469 -120
  175. package/plugins/install-plugin.js +6 -4
  176. package/plugins/python-executor-plugin.js +3 -1
  177. package/plugins/python-plugin-loader.js +10 -8
  178. package/plugins/rules-plugin.js +5 -3
  179. package/plugins/scheduler-plugin.js +18 -16
  180. package/plugins/session-plugin.js +3 -1
  181. package/plugins/storage-plugin.js +5 -3
  182. package/plugins/subagent-plugin.js +152 -92
  183. package/plugins/telegram-plugin.js +26 -19
  184. package/plugins/think-plugin.js +4 -2
  185. package/plugins/tools-plugin.js +3 -1
  186. package/plugins/web-plugin.js +15 -13
  187. package/plugins/weixin-plugin.js +43 -36
  188. package/reports/system-health-report-20260401.md +79 -0
  189. package/skills/ambient-agent/SKILL.md +49 -39
  190. package/skills/foliko-dev/AGENTS.md +64 -61
  191. package/skills/foliko-dev/SKILL.md +125 -119
  192. package/skills/mcp-usage/SKILL.md +19 -17
  193. package/skills/python-plugin-dev/SKILL.md +16 -15
  194. package/skills/skill-guide/SKILL.md +12 -12
  195. package/skills/subagent-guide/SKILL.md +237 -0
  196. package/skills/workflow-guide/SKILL.md +90 -45
  197. package/skills/workflow-troubleshooting/DEBUGGING.md +36 -21
  198. package/skills/workflow-troubleshooting/SKILL.md +156 -79
  199. package/src/capabilities/index.js +4 -4
  200. package/src/capabilities/skill-manager.js +211 -197
  201. package/src/capabilities/workflow-engine.js +461 -547
  202. package/src/core/agent-chat.js +426 -279
  203. package/src/core/agent.js +453 -248
  204. package/src/core/framework.js +183 -149
  205. package/src/core/index.js +8 -8
  206. package/src/core/plugin-base.js +52 -52
  207. package/src/core/plugin-manager.js +377 -281
  208. package/src/core/provider.js +35 -32
  209. package/src/core/sub-agent-config.js +264 -0
  210. package/src/core/system-prompt-builder.js +120 -0
  211. package/src/core/tool-registry.js +416 -33
  212. package/src/core/tool-router.js +149 -68
  213. package/src/executors/executor-base.js +58 -58
  214. package/src/executors/mcp-executor.js +269 -257
  215. package/src/index.js +5 -17
  216. package/src/utils/circuit-breaker.js +301 -0
  217. package/src/utils/error-boundary.js +363 -0
  218. package/src/utils/error.js +374 -0
  219. package/src/utils/event-emitter.js +20 -20
  220. package/src/utils/id.js +133 -0
  221. package/src/utils/index.js +217 -3
  222. package/src/utils/logger.js +181 -0
  223. package/src/utils/plugin-helpers.js +90 -0
  224. package/src/utils/retry.js +122 -0
  225. package/src/utils/sandbox.js +292 -0
  226. package/test/tool-registry-validation.test.js +218 -0
  227. package/test_report.md +70 -0
  228. package/website/docs/api.html +169 -107
  229. package/website/docs/configuration.html +296 -144
  230. package/website/docs/plugin-development.html +154 -85
  231. package/website/docs/project-structure.html +110 -109
  232. package/website/docs/skill-development.html +117 -61
  233. package/website/index.html +209 -205
  234. package/website/script.js +20 -17
  235. package/website/styles.css +1 -1
  236. package/plugins/ambient-agent-plugin.js +0 -1565
  237. package/plugins/email.js +0 -1142
@@ -3,98 +3,95 @@
3
3
  * 支持: **粗体**, *斜体*, `代码`, ```代码块```, # 标题, 列表, 引用, <think>思考
4
4
  */
5
5
 
6
- const {
7
- BOLD, DIM, CLEAR, RED, GREEN, YELLOW, CYAN, BLUE, MAGENTA, WHITE
8
- } = require('./ansi')
6
+ const { BOLD, DIM, CLEAR, RED, GREEN, YELLOW, CYAN, BLUE, MAGENTA, WHITE } = require('./ansi');
9
7
 
10
8
  // Markdown 标记对应的 ANSI 样式
11
9
  const STYLES = {
12
10
  bold: { prefix: BOLD, suffix: CLEAR },
13
11
  italic: { prefix: DIM, suffix: CLEAR },
14
- code: { prefix: CYAN, suffix: CLEAR }, // dim = 暗色
15
- codeBlock: { prefix: YELLOW, suffix: CLEAR }, // yellow = 黄色
16
- h1: { prefix: BOLD, suffix: CLEAR }, // bold white
17
- h2: { prefix: BOLD, suffix: CLEAR }, // bold white
12
+ code: { prefix: CYAN, suffix: CLEAR }, // dim = 暗色
13
+ codeBlock: { prefix: YELLOW, suffix: CLEAR }, // yellow = 黄色
14
+ h1: { prefix: BOLD, suffix: CLEAR }, // bold white
15
+ h2: { prefix: BOLD, suffix: CLEAR }, // bold white
18
16
  h3: { prefix: BOLD, suffix: CLEAR },
19
- link: { prefix: '\x1B[34m\x1B[4m', suffix: CLEAR }, // blue underline
20
- list: { prefix: DIM, suffix: CLEAR }, // dim = 暗色
21
- blockquote: { prefix: DIM, suffix: CLEAR }, // dim = 暗色
22
- think: { prefix: `\x1B[38;5;240m`, suffix: CLEAR }, // yellow = 黄色
23
- }
17
+ link: { prefix: '\x1B[34m\x1B[4m', suffix: CLEAR }, // blue underline
18
+ list: { prefix: DIM, suffix: CLEAR }, // dim = 暗色
19
+ blockquote: { prefix: DIM, suffix: CLEAR }, // dim = 暗色
20
+ think: { prefix: `\x1B[38;5;240m`, suffix: CLEAR }, // yellow = 黄色
21
+ };
24
22
 
25
23
  /**
26
24
  * 验证并修复UTF-16代理对
27
25
  */
28
26
  function fixSurrogates(text) {
29
- if (!text) return ''
30
- const result = []
31
- let i = 0
27
+ if (!text) return '';
28
+ const result = [];
29
+ let i = 0;
32
30
  while (i < text.length) {
33
- const char = text[i]
34
- const code = text.charCodeAt(i)
31
+ const char = text[i];
32
+ const code = text.charCodeAt(i);
35
33
  // 高代理
36
- if (code >= 0xD800 && code <= 0xDBFF) {
37
- const nextCode = text.charCodeAt(i + 1)
34
+ if (code >= 0xd800 && code <= 0xdbff) {
35
+ const nextCode = text.charCodeAt(i + 1);
38
36
  // 如果有低代理,配对
39
- if (nextCode >= 0xDC00 && nextCode <= 0xDFFF) {
40
- result.push(char + text[i + 1])
41
- i += 2
42
- continue
37
+ if (nextCode >= 0xdc00 && nextCode <= 0xdfff) {
38
+ result.push(char + text[i + 1]);
39
+ i += 2;
40
+ continue;
43
41
  }
44
42
  // 孤立的高代理,替换为方框
45
- result.push('\uFFFD')
46
- i += 1
47
- continue
43
+ result.push('\uFFFD');
44
+ i += 1;
45
+ continue;
48
46
  }
49
47
  // 低代理(不应该单独出现)
50
- if (code >= 0xDC00 && code <= 0xDFFF) {
51
- result.push('\uFFFD')
52
- i += 1
53
- continue
48
+ if (code >= 0xdc00 && code <= 0xdfff) {
49
+ result.push('\uFFFD');
50
+ i += 1;
51
+ continue;
54
52
  }
55
- result.push(char)
56
- i++
53
+ result.push(char);
54
+ i++;
57
55
  }
58
- return result.join('')
56
+ return result.join('');
59
57
  }
60
58
 
61
59
  /**
62
60
  * 渲染单行 markdown(流式友好,简单处理)
63
61
  */
64
62
  function renderInline(text) {
65
- if (!text) return ''
63
+ if (!text) return '';
66
64
 
67
65
  // 修复不完整的代理对
68
- const fixed = fixSurrogates(text)
69
- let result = fixed
70
-
66
+ const fixed = fixSurrogates(text);
67
+ let result = fixed;
71
68
 
72
69
  // 处理行内代码 `code`
73
70
  result = result.replace(/`([^`]+)`/g, (match, code) => {
74
- return `${STYLES.code.prefix}${code}${STYLES.code.suffix}`
75
- })
71
+ return `${STYLES.code.prefix}${code}${STYLES.code.suffix}`;
72
+ });
76
73
 
77
74
  // 处理 **粗体**
78
75
  result = result.replace(/\*\*([^*]+)\*\*/g, (match, bold) => {
79
- return `${STYLES.bold.prefix}${bold}${STYLES.bold.suffix}`
80
- })
76
+ return `${STYLES.bold.prefix}${bold}${STYLES.bold.suffix}`;
77
+ });
81
78
 
82
79
  // 处理 *斜体*(不匹配已处理的粗体内部)
83
80
  result = result.replace(/(?<!\*)\*([^*\n]+)\*(?!\*)/g, (match, italic) => {
84
- return `${STYLES.italic.prefix}${italic}${STYLES.italic.suffix}`
85
- })
81
+ return `${STYLES.italic.prefix}${italic}${STYLES.italic.suffix}`;
82
+ });
86
83
 
87
84
  // 处理 ~~删除线~~ (简单处理)
88
85
  result = result.replace(/~~([^~]+)~~/g, (match, strikethrough) => {
89
- return `${DIM}${strikethrough}${CLEAR}`
90
- })
86
+ return `${DIM}${strikethrough}${CLEAR}`;
87
+ });
91
88
 
92
89
  // 处理行内链接 [text](url) -> text
93
90
  result = result.replace(/\[([^\]]+)\]\([^)]+\)/g, (match, text) => {
94
- return `${STYLES.link.prefix}${text}${STYLES.link.suffix}`
95
- })
91
+ return `${STYLES.link.prefix}${text}${STYLES.link.suffix}`;
92
+ });
96
93
 
97
- return result
94
+ return result;
98
95
  }
99
96
 
100
97
  /**
@@ -102,55 +99,55 @@ function renderInline(text) {
102
99
  */
103
100
  function renderThink(line, state = { inThink: false }) {
104
101
  // <think>思考内容</think> -> 思考内容用暗色显示
105
- let result = ''
102
+ let result = '';
106
103
 
107
- let i = 0
108
- let lastEnd = 0
104
+ let i = 0;
105
+ let lastEnd = 0;
109
106
 
110
107
  // 如果在思考块中但这行没有开始标签,在行首添加黄色前缀
111
108
  if (state.inThink && !line.includes('<think>')) {
112
- result += STYLES.think.prefix
109
+ result += STYLES.think.prefix;
113
110
  }
114
111
 
115
112
  while (i < line.length) {
116
113
  // 检查 <think> (7个字符)
117
114
  if (line.substring(i, i + 7) === '<think>') {
118
115
  if (i > lastEnd) {
119
- result += renderInline(line.substring(lastEnd, i))
116
+ result += renderInline(line.substring(lastEnd, i));
120
117
  }
121
- result += STYLES.think.prefix + '<think>'
122
- i += 7
123
- lastEnd = i
124
- state.inThink = true
118
+ result += STYLES.think.prefix + '<think>';
119
+ i += 7;
120
+ lastEnd = i;
121
+ state.inThink = true;
125
122
  // 如果这行只有<think>标签,不要在这里添加CLEAR
126
123
  // 后续行会继续使用黄色
127
124
  if (i >= line.length) {
128
125
  // 没有更多内容,return时不添加CLEAR,保持黄色状态
129
- return result
126
+ return result;
130
127
  }
131
- continue
128
+ continue;
132
129
  }
133
130
 
134
131
  // 检查</think> (8个字符)
135
132
  if (line.substring(i, i + 8) === '</think>') {
136
133
  if (i > lastEnd) {
137
- result += line.substring(lastEnd, i) + STYLES.think.suffix
134
+ result += line.substring(lastEnd, i) + STYLES.think.suffix;
138
135
  }
139
- result += '</think>' + CLEAR
140
- i += 8
141
- lastEnd = i
142
- state.inThink = false
143
- continue
136
+ result += '</think>' + CLEAR;
137
+ i += 8;
138
+ lastEnd = i;
139
+ state.inThink = false;
140
+ continue;
144
141
  }
145
142
 
146
- i++
143
+ i++;
147
144
  }
148
145
 
149
146
  if (lastEnd < line.length) {
150
- result += renderInline(line.substring(lastEnd))
147
+ result += renderInline(line.substring(lastEnd));
151
148
  }
152
149
 
153
- return result
150
+ return result;
154
151
  }
155
152
 
156
153
  /**
@@ -159,103 +156,103 @@ function renderThink(line, state = { inThink: false }) {
159
156
  */
160
157
  function renderLine(line, state = { inThink: false, inCodeBlock: false }) {
161
158
  // 思考标签 - 保留首尾换行符
162
- const leadingNL = line.match(/^\n*/)[0]
163
- const trailingNL = line.match(/\n*$/)[0]
164
- const trimmed = line.trim()
159
+ const leadingNL = line.match(/^\n*/)[0];
160
+ const trailingNL = line.match(/\n*$/)[0];
161
+ const trimmed = line.trim();
165
162
 
166
163
  // 代码块处理
167
164
  if (trimmed.startsWith('```')) {
168
165
  if (state.inCodeBlock) {
169
166
  // 结束代码块
170
- state.inCodeBlock = false
171
- return `\`\`\`${trimmed.slice(3) ? ' ' + trimmed.slice(3) : ''}${STYLES.codeBlock.suffix}`
167
+ state.inCodeBlock = false;
168
+ return `\`\`\`${trimmed.slice(3) ? ' ' + trimmed.slice(3) : ''}${STYLES.codeBlock.suffix}`;
172
169
  } else {
173
170
  // 开始代码块
174
- state.inCodeBlock = true
175
- const lang = trimmed.slice(3).trim()
176
- return `${STYLES.codeBlock.prefix}\`\`\`${lang ? ' ' + lang : ''}`
171
+ state.inCodeBlock = true;
172
+ const lang = trimmed.slice(3).trim();
173
+ return `${STYLES.codeBlock.prefix}\`\`\`${lang ? ' ' + lang : ''}`;
177
174
  }
178
175
  }
179
176
 
180
177
  // 如果在代码块中,整行用代码样式
181
178
  if (state.inCodeBlock) {
182
- return `${STYLES.codeBlock.prefix}${line}${STYLES.codeBlock.suffix}`
179
+ return `${STYLES.codeBlock.prefix}${line}${STYLES.codeBlock.suffix}`;
183
180
  }
184
181
 
185
182
  // 如果在思考块中或者有思考标签
186
183
  if (state.inThink || trimmed.includes('<think>') || trimmed.includes('</think>')) {
187
- const result = leadingNL + renderThink(trimmed, state) + trailingNL
188
- return result
184
+ const result = leadingNL + renderThink(trimmed, state) + trailingNL;
185
+ return result;
189
186
  }
190
187
 
191
188
  // 标题
192
189
  if (line.startsWith('### ')) {
193
- return `${STYLES.h3.prefix}${renderInline(line.substring(4))}${STYLES.h3.suffix}`
190
+ return `${STYLES.h3.prefix}${renderInline(line.substring(4))}${STYLES.h3.suffix}`;
194
191
  }
195
192
  if (line.startsWith('## ')) {
196
- return `${STYLES.h2.prefix}${renderInline(line.substring(3))}${STYLES.h2.suffix}`
193
+ return `${STYLES.h2.prefix}${renderInline(line.substring(3))}${STYLES.h2.suffix}`;
197
194
  }
198
195
  if (line.startsWith('# ')) {
199
- return `${STYLES.h1.prefix}${renderInline(line.substring(2))}${STYLES.h1.suffix}`
196
+ return `${STYLES.h1.prefix}${renderInline(line.substring(2))}${STYLES.h1.suffix}`;
200
197
  }
201
198
 
202
199
  // 无序列表
203
200
  if (line.match(/^[-*+] /)) {
204
201
  return line.replace(/^([-*+] )(.*)/, (match, bullet, content) => {
205
- return `${STYLES.list.prefix}${bullet}${CLEAR}${renderInline(content)}`
206
- })
202
+ return `${STYLES.list.prefix}${bullet}${CLEAR}${renderInline(content)}`;
203
+ });
207
204
  }
208
205
 
209
206
  // 有序列表
210
207
  if (line.match(/^\d+\. /)) {
211
208
  return line.replace(/^(\d+\. )(.*)/, (match, bullet, content) => {
212
- return `${STYLES.list.prefix}${bullet}${CLEAR}${renderInline(content)}`
213
- })
209
+ return `${STYLES.list.prefix}${bullet}${CLEAR}${renderInline(content)}`;
210
+ });
214
211
  }
215
212
 
216
213
  // 引用
217
214
  if (line.startsWith('> ')) {
218
215
  return line.replace(/^> (.*)/, (match, content) => {
219
- return `${STYLES.blockquote.prefix}| ${renderInline(content)}${STYLES.blockquote.suffix}`
220
- })
216
+ return `${STYLES.blockquote.prefix}| ${renderInline(content)}${STYLES.blockquote.suffix}`;
217
+ });
221
218
  }
222
219
 
223
- return renderInline(line)
220
+ return renderInline(line);
224
221
  }
225
222
 
226
223
  /**
227
224
  * 渲染完整的 markdown 文本
228
225
  */
229
226
  function render(text) {
230
- if (!text) return ''
227
+ if (!text) return '';
231
228
 
232
- const lines = text.split('\n')
233
- const rendered = []
229
+ const lines = text.split('\n');
230
+ const rendered = [];
234
231
 
235
- let inCodeBlock = false
232
+ let inCodeBlock = false;
236
233
 
237
234
  for (const line of lines) {
238
235
  // 代码块
239
236
  if (line.startsWith('```')) {
240
237
  if (inCodeBlock) {
241
- rendered.push(`\`\`\`${STYLES.codeBlock.suffix}`)
242
- inCodeBlock = false
238
+ rendered.push(`\`\`\`${STYLES.codeBlock.suffix}`);
239
+ inCodeBlock = false;
243
240
  } else {
244
- const lang = line.substring(3).trim() || ''
245
- rendered.push(`${STYLES.codeBlock.prefix}\`\`\`${lang ? ' ' + lang : ''}`)
246
- inCodeBlock = true
241
+ const lang = line.substring(3).trim() || '';
242
+ rendered.push(`${STYLES.codeBlock.prefix}\`\`\`${lang ? ' ' + lang : ''}`);
243
+ inCodeBlock = true;
247
244
  }
248
- continue
245
+ continue;
249
246
  }
250
247
 
251
248
  if (inCodeBlock) {
252
- rendered.push(`${STYLES.codeBlock.prefix}${line}${STYLES.codeBlock.suffix}`)
249
+ rendered.push(`${STYLES.codeBlock.prefix}${line}${STYLES.codeBlock.suffix}`);
253
250
  } else {
254
- rendered.push(renderLine(line))
251
+ rendered.push(renderLine(line));
255
252
  }
256
253
  }
257
254
 
258
- return rendered.join('\n')
255
+ return rendered.join('\n');
259
256
  }
260
257
 
261
258
  /**
@@ -263,34 +260,33 @@ function render(text) {
263
260
  * 返回 { done: boolean, line: string }
264
261
  */
265
262
  function* streamRender(text) {
266
- if (!text) return
263
+ if (!text) return;
267
264
 
268
- const lines = text.split('\n')
269
- let inCodeBlock = false
265
+ const lines = text.split('\n');
266
+ let inCodeBlock = false;
270
267
 
271
268
  for (const line of lines) {
272
269
  // 代码块
273
270
  if (line.startsWith('```')) {
274
271
  if (inCodeBlock) {
275
- yield { done: false, line: `${STYLES.codeBlock.suffix}` }
276
- inCodeBlock = false
272
+ yield { done: false, line: `${STYLES.codeBlock.suffix}` };
273
+ inCodeBlock = false;
277
274
  } else {
278
- const lang = line.substring(3).trim() || ''
279
- yield { done: false, line: `${STYLES.codeBlock.prefix}\`\`\`${lang ? ' ' + lang : ''}` }
280
- inCodeBlock = true
275
+ const lang = line.substring(3).trim() || '';
276
+ yield { done: false, line: `${STYLES.codeBlock.prefix}\`\`\`${lang ? ' ' + lang : ''}` };
277
+ inCodeBlock = true;
281
278
  }
282
- continue
279
+ continue;
283
280
  }
284
-
285
281
 
286
282
  if (inCodeBlock) {
287
- yield { done: false, line: `${STYLES.codeBlock.prefix}${line}${STYLES.codeBlock.suffix}` }
283
+ yield { done: false, line: `${STYLES.codeBlock.prefix}${line}${STYLES.codeBlock.suffix}` };
288
284
  } else {
289
- yield { done: false, line: renderLine(line) }
285
+ yield { done: false, line: renderLine(line) };
290
286
  }
291
287
  }
292
288
 
293
- yield { done: true }
289
+ yield { done: true };
294
290
  }
295
291
 
296
- module.exports = { render, renderInline, renderLine, streamRender, STYLES }
292
+ module.exports = { render, renderInline, renderLine, streamRender, STYLES };
@@ -7,7 +7,7 @@ services:
7
7
  container_name: foliko-agent
8
8
  restart: unless-stopped
9
9
  ports:
10
- - "3000:3000"
10
+ - '3000:3000'
11
11
  environment:
12
12
  # AI 配置
13
13
  - FOLIKO_PROVIDER=${FOLIKO_PROVIDER:-minimax}