micro-models-agent 0.2.44 → 0.2.46

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 (256) hide show
  1. package/dist/agent/context.d.ts +39 -0
  2. package/dist/agent/context.d.ts.map +1 -1
  3. package/dist/agent/context.js +52 -10
  4. package/dist/agent/context.js.map +1 -1
  5. package/dist/agent/loop.d.ts +27 -0
  6. package/dist/agent/loop.d.ts.map +1 -1
  7. package/dist/agent/loop.js +79 -16
  8. package/dist/agent/loop.js.map +1 -1
  9. package/dist/agent/memory.d.ts +46 -0
  10. package/dist/agent/memory.d.ts.map +1 -1
  11. package/dist/agent/memory.js +67 -3
  12. package/dist/agent/memory.js.map +1 -1
  13. package/dist/agent/system-prompt.d.ts +20 -0
  14. package/dist/agent/system-prompt.d.ts.map +1 -1
  15. package/dist/agent/system-prompt.js +50 -0
  16. package/dist/agent/system-prompt.js.map +1 -1
  17. package/dist/agent/user-profile.d.ts +21 -0
  18. package/dist/agent/user-profile.d.ts.map +1 -1
  19. package/dist/agent/user-profile.js +43 -1
  20. package/dist/agent/user-profile.js.map +1 -1
  21. package/dist/cli/config.d.ts +10 -0
  22. package/dist/cli/config.d.ts.map +1 -1
  23. package/dist/cli/config.js +10 -0
  24. package/dist/cli/config.js.map +1 -1
  25. package/dist/cli/model.d.ts +10 -0
  26. package/dist/cli/model.d.ts.map +1 -1
  27. package/dist/cli/model.js +10 -0
  28. package/dist/cli/model.js.map +1 -1
  29. package/dist/cli/provider.d.ts +9 -0
  30. package/dist/cli/provider.d.ts.map +1 -1
  31. package/dist/cli/provider.js +9 -0
  32. package/dist/cli/provider.js.map +1 -1
  33. package/dist/cli/update.d.ts +9 -0
  34. package/dist/cli/update.d.ts.map +1 -1
  35. package/dist/cli/update.js +9 -0
  36. package/dist/cli/update.js.map +1 -1
  37. package/dist/cli.d.ts.map +1 -1
  38. package/dist/cli.js +14 -0
  39. package/dist/cli.js.map +1 -1
  40. package/dist/config/config.d.ts +6 -0
  41. package/dist/config/config.d.ts.map +1 -1
  42. package/dist/config/config.js +22 -0
  43. package/dist/config/config.js.map +1 -1
  44. package/dist/config/types.d.ts +18 -0
  45. package/dist/config/types.d.ts.map +1 -1
  46. package/dist/config/types.js +11 -0
  47. package/dist/config/types.js.map +1 -1
  48. package/dist/file-loader.d.ts +8 -0
  49. package/dist/file-loader.d.ts.map +1 -1
  50. package/dist/file-loader.js.map +1 -1
  51. package/dist/index.d.ts +6 -0
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +6 -0
  54. package/dist/index.js.map +1 -1
  55. package/dist/indexer/cache.d.ts.map +1 -1
  56. package/dist/indexer/cache.js +12 -0
  57. package/dist/indexer/cache.js.map +1 -1
  58. package/dist/indexer/code-index.d.ts.map +1 -1
  59. package/dist/indexer/code-index.js +17 -0
  60. package/dist/indexer/code-index.js.map +1 -1
  61. package/dist/indexer/project-map.d.ts.map +1 -1
  62. package/dist/indexer/project-map.js +17 -0
  63. package/dist/indexer/project-map.js.map +1 -1
  64. package/dist/llm/openai-compat.d.ts.map +1 -1
  65. package/dist/llm/openai-compat.js.map +1 -1
  66. package/dist/llm/provider.d.ts +15 -0
  67. package/dist/llm/provider.d.ts.map +1 -1
  68. package/dist/llm/provider.js +11 -0
  69. package/dist/llm/provider.js.map +1 -1
  70. package/dist/llm/token-counter.d.ts +8 -0
  71. package/dist/llm/token-counter.d.ts.map +1 -1
  72. package/dist/llm/token-counter.js +8 -0
  73. package/dist/llm/token-counter.js.map +1 -1
  74. package/dist/logger.d.ts.map +1 -1
  75. package/dist/logger.js +12 -0
  76. package/dist/logger.js.map +1 -1
  77. package/dist/repl/commands.d.ts +18 -0
  78. package/dist/repl/commands.d.ts.map +1 -1
  79. package/dist/repl/commands.js +2 -0
  80. package/dist/repl/commands.js.map +1 -1
  81. package/dist/repl/history.d.ts +9 -0
  82. package/dist/repl/history.d.ts.map +1 -1
  83. package/dist/repl/history.js +9 -0
  84. package/dist/repl/history.js.map +1 -1
  85. package/dist/repl/index.d.ts +4 -0
  86. package/dist/repl/index.d.ts.map +1 -1
  87. package/dist/repl/index.js +17 -0
  88. package/dist/repl/index.js.map +1 -1
  89. package/dist/session/store.d.ts +12 -0
  90. package/dist/session/store.d.ts.map +1 -1
  91. package/dist/session/store.js +30 -0
  92. package/dist/session/store.js.map +1 -1
  93. package/dist/skills/loader.d.ts.map +1 -1
  94. package/dist/skills/loader.js +13 -0
  95. package/dist/skills/loader.js.map +1 -1
  96. package/dist/styling/engine.d.ts +1 -0
  97. package/dist/styling/engine.d.ts.map +1 -1
  98. package/dist/styling/engine.js +10 -0
  99. package/dist/styling/engine.js.map +1 -1
  100. package/dist/styling/index.d.ts +5 -0
  101. package/dist/styling/index.d.ts.map +1 -1
  102. package/dist/styling/index.js +16 -0
  103. package/dist/styling/index.js.map +1 -1
  104. package/dist/styling/loader.d.ts.map +1 -1
  105. package/dist/styling/loader.js +11 -0
  106. package/dist/styling/loader.js.map +1 -1
  107. package/dist/styling/types.d.ts +14 -0
  108. package/dist/styling/types.d.ts.map +1 -1
  109. package/dist/styling/types.js +10 -0
  110. package/dist/styling/types.js.map +1 -1
  111. package/dist/tools/approve.d.ts +14 -0
  112. package/dist/tools/approve.d.ts.map +1 -1
  113. package/dist/tools/approve.js +13 -0
  114. package/dist/tools/approve.js.map +1 -1
  115. package/dist/tools/bash.d.ts +13 -0
  116. package/dist/tools/bash.d.ts.map +1 -1
  117. package/dist/tools/bash.js +3 -1
  118. package/dist/tools/bash.js.map +1 -1
  119. package/dist/tools/fs/copy-file.d.ts +6 -0
  120. package/dist/tools/fs/copy-file.d.ts.map +1 -1
  121. package/dist/tools/fs/copy-file.js +6 -0
  122. package/dist/tools/fs/copy-file.js.map +1 -1
  123. package/dist/tools/fs/create-dir.d.ts +6 -0
  124. package/dist/tools/fs/create-dir.d.ts.map +1 -1
  125. package/dist/tools/fs/create-dir.js +6 -0
  126. package/dist/tools/fs/create-dir.js.map +1 -1
  127. package/dist/tools/fs/delete-file.d.ts +6 -0
  128. package/dist/tools/fs/delete-file.d.ts.map +1 -1
  129. package/dist/tools/fs/delete-file.js +6 -0
  130. package/dist/tools/fs/delete-file.js.map +1 -1
  131. package/dist/tools/fs/edit-file.d.ts +8 -0
  132. package/dist/tools/fs/edit-file.d.ts.map +1 -1
  133. package/dist/tools/fs/edit-file.js +8 -0
  134. package/dist/tools/fs/edit-file.js.map +1 -1
  135. package/dist/tools/fs/file-info.d.ts +6 -0
  136. package/dist/tools/fs/file-info.d.ts.map +1 -1
  137. package/dist/tools/fs/file-info.js +6 -0
  138. package/dist/tools/fs/file-info.js.map +1 -1
  139. package/dist/tools/fs/glob-search.d.ts +6 -0
  140. package/dist/tools/fs/glob-search.d.ts.map +1 -1
  141. package/dist/tools/fs/glob-search.js +7 -0
  142. package/dist/tools/fs/glob-search.js.map +1 -1
  143. package/dist/tools/fs/grep-search.d.ts +7 -0
  144. package/dist/tools/fs/grep-search.d.ts.map +1 -1
  145. package/dist/tools/fs/grep-search.js +8 -0
  146. package/dist/tools/fs/grep-search.js.map +1 -1
  147. package/dist/tools/fs/list-dir.d.ts +6 -0
  148. package/dist/tools/fs/list-dir.d.ts.map +1 -1
  149. package/dist/tools/fs/list-dir.js +6 -0
  150. package/dist/tools/fs/list-dir.js.map +1 -1
  151. package/dist/tools/fs/move-file.d.ts +6 -0
  152. package/dist/tools/fs/move-file.d.ts.map +1 -1
  153. package/dist/tools/fs/move-file.js +6 -0
  154. package/dist/tools/fs/move-file.js.map +1 -1
  155. package/dist/tools/fs/path-utils.d.ts +21 -0
  156. package/dist/tools/fs/path-utils.d.ts.map +1 -1
  157. package/dist/tools/fs/path-utils.js +22 -0
  158. package/dist/tools/fs/path-utils.js.map +1 -1
  159. package/dist/tools/fs/read-file.d.ts +6 -0
  160. package/dist/tools/fs/read-file.d.ts.map +1 -1
  161. package/dist/tools/fs/read-file.js +6 -0
  162. package/dist/tools/fs/read-file.js.map +1 -1
  163. package/dist/tools/fs/tree.d.ts +6 -0
  164. package/dist/tools/fs/tree.d.ts.map +1 -1
  165. package/dist/tools/fs/tree.js +7 -0
  166. package/dist/tools/fs/tree.js.map +1 -1
  167. package/dist/tools/fs/types.d.ts +7 -0
  168. package/dist/tools/fs/types.d.ts.map +1 -1
  169. package/dist/tools/fs/types.js +4 -2
  170. package/dist/tools/fs/types.js.map +1 -1
  171. package/dist/tools/fs/write-file.d.ts +7 -0
  172. package/dist/tools/fs/write-file.d.ts.map +1 -1
  173. package/dist/tools/fs/write-file.js +7 -0
  174. package/dist/tools/fs/write-file.js.map +1 -1
  175. package/dist/tools/hooks.d.ts +27 -0
  176. package/dist/tools/hooks.d.ts.map +1 -1
  177. package/dist/tools/hooks.js +6 -0
  178. package/dist/tools/hooks.js.map +1 -1
  179. package/dist/tools/mcp.d.ts +14 -0
  180. package/dist/tools/mcp.d.ts.map +1 -1
  181. package/dist/tools/mcp.js +3 -0
  182. package/dist/tools/mcp.js.map +1 -1
  183. package/dist/tools/plan.d.ts +7 -0
  184. package/dist/tools/plan.d.ts.map +1 -1
  185. package/dist/tools/plan.js +19 -0
  186. package/dist/tools/plan.js.map +1 -1
  187. package/dist/tools/question.d.ts +16 -0
  188. package/dist/tools/question.d.ts.map +1 -1
  189. package/dist/tools/question.js +8 -1
  190. package/dist/tools/question.js.map +1 -1
  191. package/dist/tools/registry.d.ts +9 -0
  192. package/dist/tools/registry.d.ts.map +1 -1
  193. package/dist/tools/registry.js +26 -0
  194. package/dist/tools/registry.js.map +1 -1
  195. package/dist/tools/sanitizer.d.ts +23 -0
  196. package/dist/tools/sanitizer.d.ts.map +1 -1
  197. package/dist/tools/sanitizer.js +27 -0
  198. package/dist/tools/sanitizer.js.map +1 -1
  199. package/dist/tools/subagent.d.ts +59 -0
  200. package/dist/tools/subagent.d.ts.map +1 -1
  201. package/dist/tools/subagent.js +46 -2
  202. package/dist/tools/subagent.js.map +1 -1
  203. package/dist/tools/syntax-check.d.ts +16 -0
  204. package/dist/tools/syntax-check.d.ts.map +1 -1
  205. package/dist/tools/syntax-check.js.map +1 -1
  206. package/dist/tools/todo.d.ts +7 -0
  207. package/dist/tools/todo.d.ts.map +1 -1
  208. package/dist/tools/todo.js +17 -0
  209. package/dist/tools/todo.js.map +1 -1
  210. package/dist/tools/web-fetch.d.ts +8 -0
  211. package/dist/tools/web-fetch.d.ts.map +1 -1
  212. package/dist/tools/web-fetch.js +8 -0
  213. package/dist/tools/web-fetch.js.map +1 -1
  214. package/dist/tools/web-search.d.ts +8 -0
  215. package/dist/tools/web-search.d.ts.map +1 -1
  216. package/dist/tools/web-search.js +8 -0
  217. package/dist/tools/web-search.js.map +1 -1
  218. package/dist/ui/components/status-bar.d.ts +8 -0
  219. package/dist/ui/components/status-bar.d.ts.map +1 -1
  220. package/dist/ui/components/status-bar.js +8 -0
  221. package/dist/ui/components/status-bar.js.map +1 -1
  222. package/dist/ui/index.d.ts +12 -0
  223. package/dist/ui/index.d.ts.map +1 -1
  224. package/dist/ui/index.js +1 -0
  225. package/dist/ui/index.js.map +1 -1
  226. package/dist/ui/ink/components/App.d.ts +12 -0
  227. package/dist/ui/ink/components/App.d.ts.map +1 -1
  228. package/dist/ui/ink/components/App.js.map +1 -1
  229. package/dist/ui/ink/components/MessageBlock.d.ts +12 -0
  230. package/dist/ui/ink/components/MessageBlock.d.ts.map +1 -1
  231. package/dist/ui/ink/components/MessageBlock.js.map +1 -1
  232. package/dist/ui/ink/components/PromptInput.d.ts +11 -0
  233. package/dist/ui/ink/components/PromptInput.d.ts.map +1 -1
  234. package/dist/ui/ink/components/PromptInput.js +1 -0
  235. package/dist/ui/ink/components/PromptInput.js.map +1 -1
  236. package/dist/ui/ink/components/ToolCallBlock.d.ts +12 -0
  237. package/dist/ui/ink/components/ToolCallBlock.d.ts.map +1 -1
  238. package/dist/ui/ink/components/ToolCallBlock.js.map +1 -1
  239. package/dist/ui/ink/renderer.d.ts +12 -0
  240. package/dist/ui/ink/renderer.d.ts.map +1 -1
  241. package/dist/ui/ink/renderer.js +1 -0
  242. package/dist/ui/ink/renderer.js.map +1 -1
  243. package/dist/ui/ink/theme.d.ts +8 -0
  244. package/dist/ui/ink/theme.d.ts.map +1 -1
  245. package/dist/ui/ink/theme.js.map +1 -1
  246. package/dist/ui/readline-renderer.d.ts.map +1 -1
  247. package/dist/ui/readline-renderer.js +11 -0
  248. package/dist/ui/readline-renderer.js.map +1 -1
  249. package/dist/ui/renderer.d.ts +16 -0
  250. package/dist/ui/renderer.d.ts.map +1 -1
  251. package/dist/ui/renderer.js +14 -0
  252. package/dist/ui/renderer.js.map +1 -1
  253. package/dist/updater.d.ts.map +1 -1
  254. package/dist/updater.js +9 -1
  255. package/dist/updater.js.map +1 -1
  256. package/package.json +1 -1
@@ -1,4 +1,8 @@
1
1
  import type { ChatMessage } from '../llm/provider.js';
2
+ /**
3
+ * Менеджер контекста — управляет историей сообщений и компактификацией.
4
+ * Создаётся один раз на сессию агента.
5
+ */
2
6
  export declare class ContextManager {
3
7
  private contextWindow;
4
8
  private compactThreshold;
@@ -6,13 +10,48 @@ export declare class ContextManager {
6
10
  private compacted;
7
11
  private _totalTokens;
8
12
  private _history;
13
+ /**
14
+ * @param contextWindow - размер контекстного окна модели (в токенах)
15
+ * @param compactThreshold - порог компактификации (по умолчанию 85%)
16
+ */
9
17
  constructor(contextWindow: number, compactThreshold?: number);
10
18
  get totalTokens(): number;
11
19
  get usagePercent(): number;
12
20
  get needsCompact(): boolean;
21
+ /**
22
+ * Оценивает важность сообщения для компактификации.
23
+ *
24
+ * Алгоритм:
25
+ * - System: 100 (всегда сохраняется отдельно)
26
+ * - Tool с ошибкой: 90 (важно для диагностики)
27
+ * - User с "важно"/"critical": 85
28
+ * - Tool с успехом: 70
29
+ * - Assistant с ошибкой/решением: 70-75
30
+ * - User-вопрос: 65
31
+ * - Обычный user/assistant: 40-60
32
+ * + Recency bonus: (index/total) * 20
33
+ */
13
34
  private scoreMessage;
35
+ /**
36
+ * Обновляет подсчёт токенов для всех сообщений.
37
+ * Использует WeakMap для кэширования — повторный подсчёт не выполняется.
38
+ */
14
39
  updateTokens(messages: ChatMessage[]): Promise<void>;
40
+ /**
41
+ * Компактификация истории сообщений.
42
+ *
43
+ * Стратегия:
44
+ * 1. Сохраняем system prompt (всегда первый)
45
+ * 2. Сохраняем первое user-сообщение (контекст задачи)
46
+ * 3. Остальные сообщения оцениваем по score
47
+ * 4. Сохраняем топ-6 по score + последние 6 по позиции
48
+ * 5. Остальные суммируем в "[Ранее в разговоре (сжато):]"
49
+ *
50
+ * @param messages - полная история сообщений
51
+ * @returns Сжатая история
52
+ */
15
53
  compact(messages: ChatMessage[]): ChatMessage[];
54
+ /** Форматирует строку использования контекста для отображения в UI */
16
55
  formatUsage(): string;
17
56
  }
18
57
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/agent/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAWtD,qBAAa,cAAc;IAOvB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,gBAAgB;IAP1B,OAAO,CAAC,UAAU,CAAsC;IACxD,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAA0C;gBAGhD,aAAa,EAAE,MAAM,EACrB,gBAAgB,GAAE,MAAa;IAGzC,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,OAAO,CAAC,YAAY;IA+Bd,YAAY,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB1D,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE;IA8E/C,WAAW,IAAI,MAAM;CAiBtB"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/agent/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA6BtD;;;GAGG;AACH,qBAAa,cAAc;IAWvB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,gBAAgB;IAX1B,OAAO,CAAC,UAAU,CAAsC;IACxD,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAA0C;IAE1D;;;OAGG;gBAEO,aAAa,EAAE,MAAM,EACrB,gBAAgB,GAAE,MAAa;IAGzC,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,YAAY;IA+BpB;;;OAGG;IACG,YAAY,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB1D;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE;IAiF/C,sEAAsE;IACtE,WAAW,IAAI,MAAM;CAiBtB"}
@@ -1,13 +1,21 @@
1
1
  import { countTokens } from '../llm/token-counter.js';
2
2
  import { getTheme } from '../styling/index.js';
3
3
  import { logInfo, logDebug } from '../logger.js';
4
+ /**
5
+ * Менеджер контекста — управляет историей сообщений и компактификацией.
6
+ * Создаётся один раз на сессию агента.
7
+ */
4
8
  export class ContextManager {
5
9
  contextWindow;
6
10
  compactThreshold;
7
- tokenCache = new WeakMap();
8
- compacted = 0;
9
- _totalTokens = 0;
10
- _history = [];
11
+ tokenCache = new WeakMap(); // кэш подсчёта токенов
12
+ compacted = 0; // количество компактификаций за сессию
13
+ _totalTokens = 0; // общее количество токенов в истории
14
+ _history = []; // история по ролям
15
+ /**
16
+ * @param contextWindow - размер контекстного окна модели (в токенах)
17
+ * @param compactThreshold - порог компактификации (по умолчанию 85%)
18
+ */
11
19
  constructor(contextWindow, compactThreshold = 0.85) {
12
20
  this.contextWindow = contextWindow;
13
21
  this.compactThreshold = compactThreshold;
@@ -21,9 +29,22 @@ export class ContextManager {
21
29
  get needsCompact() {
22
30
  return this.usagePercent >= this.compactThreshold * 100;
23
31
  }
32
+ /**
33
+ * Оценивает важность сообщения для компактификации.
34
+ *
35
+ * Алгоритм:
36
+ * - System: 100 (всегда сохраняется отдельно)
37
+ * - Tool с ошибкой: 90 (важно для диагностики)
38
+ * - User с "важно"/"critical": 85
39
+ * - Tool с успехом: 70
40
+ * - Assistant с ошибкой/решением: 70-75
41
+ * - User-вопрос: 65
42
+ * - Обычный user/assistant: 40-60
43
+ * + Recency bonus: (index/total) * 20
44
+ */
24
45
  scoreMessage(msg, index, total) {
25
- let score = 50; // base
26
- // Role-based scoring
46
+ let score = 50; // базовая оценка
47
+ // Оценка по роли сообщения
27
48
  if (msg.role === 'system')
28
49
  score = 100;
29
50
  else if (msg.role === 'tool') {
@@ -53,11 +74,15 @@ export class ContextManager {
53
74
  else
54
75
  score = 40;
55
76
  }
56
- // Recency bonus (more recent = higher)
77
+ // Бонус за свежесть: чем позже сообщение, тем выше бонус
57
78
  const recencyBonus = (index / total) * 20;
58
79
  score += recencyBonus;
59
80
  return score;
60
81
  }
82
+ /**
83
+ * Обновляет подсчёт токенов для всех сообщений.
84
+ * Использует WeakMap для кэширования — повторный подсчёт не выполняется.
85
+ */
61
86
  async updateTokens(messages) {
62
87
  const start = performance.now();
63
88
  let total = 0;
@@ -75,11 +100,25 @@ export class ContextManager {
75
100
  const elapsed = (performance.now() - start).toFixed(1);
76
101
  logDebug('CONTEXT', `updateTokens: ${messages.length} msgs, ${total} tokens, ${elapsed}ms`);
77
102
  }
103
+ /**
104
+ * Компактификация истории сообщений.
105
+ *
106
+ * Стратегия:
107
+ * 1. Сохраняем system prompt (всегда первый)
108
+ * 2. Сохраняем первое user-сообщение (контекст задачи)
109
+ * 3. Остальные сообщения оцениваем по score
110
+ * 4. Сохраняем топ-6 по score + последние 6 по позиции
111
+ * 5. Остальные суммируем в "[Ранее в разговоре (сжато):]"
112
+ *
113
+ * @param messages - полная история сообщений
114
+ * @returns Сжатая история
115
+ */
78
116
  compact(messages) {
79
117
  const start = performance.now();
80
118
  logInfo('CONTEXT', `compact: ${messages.length} messages before`);
81
119
  if (messages.length <= 4)
82
120
  return messages;
121
+ // Извлекаем system prompt и первое user-сообщение
83
122
  const systemIdx = messages.findIndex(m => m.role === 'system');
84
123
  const system = systemIdx >= 0 ? [messages[systemIdx]] : [];
85
124
  const keepFirstUser = [];
@@ -94,24 +133,26 @@ export class ContextManager {
94
133
  remaining.push(messages[i]);
95
134
  }
96
135
  }
97
- // Score all messages
136
+ // Оцениваем все оставшиеся сообщения
98
137
  const scored = remaining.map((msg, i) => ({
99
138
  msg,
100
139
  score: this.scoreMessage(msg, i, remaining.length),
101
140
  tokens: this.tokenCache.get(msg) || 0,
102
141
  }));
103
- // Sort by score descending
142
+ // Сортируем по убыванию score
104
143
  scored.sort((a, b) => b.score - a.score);
105
- // Keep top 6 by score + last 6 by position
144
+ // Сохраняем топ-6 по score + последние 6 по позиции
106
145
  const recentMsgs = remaining.slice(-6);
107
146
  const recentIds = new Set(recentMsgs.map(m => m));
108
147
  const importantByScore = scored
109
148
  .filter(s => !recentIds.has(s.msg))
110
149
  .slice(0, 6)
111
150
  .map(s => s.msg);
151
+ // Сообщения, которые будут сжаты в summary
112
152
  const toCompact = remaining.filter(m => !recentMsgs.includes(m) && !importantByScore.includes(m));
113
153
  if (toCompact.length === 0)
114
154
  return messages;
155
+ // Формируем краткую сводку из сжатых сообщений
115
156
  const compactedPairs = [];
116
157
  let i = 0;
117
158
  while (i < toCompact.length) {
@@ -144,6 +185,7 @@ export class ContextManager {
144
185
  logInfo('CONTEXT', `compact: ${messages.length} → ${result.length} msgs in ${elapsed}ms`);
145
186
  return result;
146
187
  }
188
+ /** Форматирует строку использования контекста для отображения в UI */
147
189
  formatUsage() {
148
190
  const theme = getTheme();
149
191
  const pct = this.usagePercent;
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/agent/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/agent/context.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,11 @@ import { ToolRegistry } from '../tools/registry.js';
3
3
  import { ContextManager } from './context.js';
4
4
  import type { OutputRenderer } from '../ui/renderer.js';
5
5
  import type { AgentMode } from '../config/types.js';
6
+ /**
7
+ * Результат выполнения цикла агента.
8
+ * Содержит всю историю сообщений и опциональный pending-вопрос
9
+ * (если агент вызвал инструмент question и ждёт ответа пользователя).
10
+ */
6
11
  export interface AgentLoopResult {
7
12
  messages: ChatMessage[];
8
13
  questionPending?: {
@@ -10,6 +15,28 @@ export interface AgentLoopResult {
10
15
  choices?: string[];
11
16
  };
12
17
  }
18
+ /**
19
+ * Запускает основной цикл ReAct-агента.
20
+ *
21
+ * Цикл работает до тех пор, пока:
22
+ * - Агент не перестанет вызывать инструменты (финальный текстовый ответ)
23
+ * - Не будет достигнут лимит ходов (maxSteps из конфига)
24
+ * - Пользователь не прервёт выполнение (abort signal)
25
+ *
26
+ * Стратегия обработки ошибок:
27
+ * - Пустые ответы: retry до 3 раз с подсказкой "Continue."
28
+ * - Невалидные tool calls: отправка обратной связи модели
29
+ * - Пустые ответы подряд >3: остановка цикла
30
+ *
31
+ * @param provider - провайдер LLM (OpenAI-совместимый)
32
+ * @param registry - реестр доступных инструментов
33
+ * @param prompt - начальный промпт пользователя
34
+ * @param contextManager - менеджер контекста (опциональный, создаётся новый если не передан)
35
+ * @param previousMessages - предыдущие сообщения для восстановления сессии
36
+ * @param renderer - рендерер вывода (Ink или readline)
37
+ * @param providerName - имя провайдера для отображения
38
+ * @param options - дополнительные опции (quiet, showThinking, mode)
39
+ */
13
40
  export declare function runAgentLoop(provider: LLMProvider, registry: ToolRegistry, prompt: string, contextManager?: ContextManager, previousMessages?: ChatMessage[], renderer?: OutputRenderer, providerName?: string, options?: {
14
41
  quiet?: boolean;
15
42
  showThinking?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAc9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AA2BpD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,eAAe,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC5D;AAED,wBAAsB,YAAY,CAChC,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,cAAc,EAC/B,gBAAgB,CAAC,EAAE,WAAW,EAAE,EAChC,QAAQ,CAAC,EAAE,cAAc,EACzB,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAAE,GACtE,OAAO,CAAC,eAAe,CAAC,CAm0B1B"}
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAc9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AA+CpD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,eAAe,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC5D;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,cAAc,EAC/B,gBAAgB,CAAC,EAAE,WAAW,EAAE,EAChC,QAAQ,CAAC,EAAE,cAAc,EACzB,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAAE,GACtE,OAAO,CAAC,eAAe,CAAC,CAq1B1B"}
@@ -19,7 +19,31 @@ import { loadConfig, saveConfig } from '../config/config.js';
19
19
  import { buildSystemPrompt } from './system-prompt.js';
20
20
  import { logInfo, logWarn, logError, logDebug, logToolCall, setStatusWriter, writeStatus } from '../logger.js';
21
21
  import { buildSubagentContext, runIsolatedLoop, extractAllToolCalls, validateToolCall, doChat } from '../tools/subagent.js';
22
- // extractAllToolCalls moved to src/tools/subagent.ts
22
+ /**
23
+ * Основной цикл ReAct-агента.
24
+ *
25
+ * Архитектура цикла:
26
+ * 1. Сборка system prompt (кэшируется на время сессии)
27
+ * 2. Отправка запроса к LLM с историей сообщений
28
+ * 3. Парсинг tool calls из ответа модели (формат <tool_call>)
29
+ * 4. Валидация и исполнение каждого tool call
30
+ * 5. Добавление результата в историю
31
+ * 6. Повтор до завершения (нет tool calls) или лимита ходов
32
+ *
33
+ * Особенности:
34
+ * - Fallback-парсинг при невалидном JSON от маленьких моделей
35
+ * - Автоматическое компактирование контекста при приближении к лимиту
36
+ * - Retry с увеличением temperature при пустых ответах
37
+ * - Автодобавление скилов при обнаружении релевантных паттернов
38
+ *
39
+ * @module agent/loop
40
+ */
41
+ /**
42
+ * Fallback-извлечение bash-команды из ответа модели.
43
+ * Используется когда основной парсинг tool calls не сработал
44
+ * (маленькие модели часто генерируют невалидный JSON).
45
+ * Применяет три regex-паттерна для поиска команды bash.
46
+ */
23
47
  function extractToolCallFallback(response) {
24
48
  const patterns = [
25
49
  /"name"\s*:\s*"bash"\s*,\s*"arguments"\s*:\s*\{\s*"cmd"\s*:\s*"((?:[^"\\]|\\.)*)"/,
@@ -36,12 +60,36 @@ function extractToolCallFallback(response) {
36
60
  }
37
61
  return null;
38
62
  }
63
+ /**
64
+ * Запускает основной цикл ReAct-агента.
65
+ *
66
+ * Цикл работает до тех пор, пока:
67
+ * - Агент не перестанет вызывать инструменты (финальный текстовый ответ)
68
+ * - Не будет достигнут лимит ходов (maxSteps из конфига)
69
+ * - Пользователь не прервёт выполнение (abort signal)
70
+ *
71
+ * Стратегия обработки ошибок:
72
+ * - Пустые ответы: retry до 3 раз с подсказкой "Continue."
73
+ * - Невалидные tool calls: отправка обратной связи модели
74
+ * - Пустые ответы подряд >3: остановка цикла
75
+ *
76
+ * @param provider - провайдер LLM (OpenAI-совместимый)
77
+ * @param registry - реестр доступных инструментов
78
+ * @param prompt - начальный промпт пользователя
79
+ * @param contextManager - менеджер контекста (опциональный, создаётся новый если не передан)
80
+ * @param previousMessages - предыдущие сообщения для восстановления сессии
81
+ * @param renderer - рендерер вывода (Ink или readline)
82
+ * @param providerName - имя провайдера для отображения
83
+ * @param options - дополнительные опции (quiet, showThinking, mode)
84
+ */
39
85
  export async function runAgentLoop(provider, registry, prompt, contextManager, previousMessages, renderer, providerName, options) {
40
86
  logInfo('LOOP', `runAgentLoop started: "${prompt.slice(0, 50)}"`);
41
87
  renderer?.resetAbort?.();
88
+ // Парсинг ссылок на файлы в промпте (формат @path/to/file)
42
89
  const { prompt: enrichedPrompt, files } = await parseFileRefs(prompt);
43
90
  logDebug('LOOP', `parseFileRefs: ${files.length} files, prompt len: ${enrichedPrompt.length}`);
44
91
  const quiet = options?.quiet ?? false;
92
+ // Автозагрузка скилов из промпта (если пользователь указал @skill-name)
45
93
  const loadedSkills = loadSkillsFromRefs(prompt, process.cwd());
46
94
  const loadedSkillNames = new Set(loadedSkills.map(s => s.name));
47
95
  if (loadedSkills.length > 0) {
@@ -70,11 +118,13 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
70
118
  }
71
119
  setStatusWriter(renderer ? (msg) => renderer.writeDim(` ${msg}`) : null);
72
120
  writeStatus('Initializing...');
121
+ // Сборка system prompt (включает инструкции, информацию о проекте, скилы, память)
73
122
  const sysStart = performance.now();
74
123
  const systemPrompt = buildSystemPrompt(loadedSkills.length > 0 ? loadedSkills : undefined, options?.mode);
75
124
  const sysElapsed = ((performance.now() - sysStart) / 1000).toFixed(1);
76
125
  writeStatus(`Done (${sysElapsed}s)`);
77
126
  setStatusWriter(null);
127
+ // Начальное состояние истории: system prompt + предыдущие сообщения + текущий промпт
78
128
  const messages = [
79
129
  { role: 'system', content: systemPrompt },
80
130
  ...(previousMessages || []),
@@ -83,11 +133,11 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
83
133
  const ctx = contextManager ?? new ContextManager(provider.contextWindow);
84
134
  const config = loadConfig();
85
135
  const maxSteps = config.agent.maxSteps ?? 100;
86
- let consecutiveEmpty = 0;
136
+ let consecutiveEmpty = 0; // счётчик пустых ответов подряд
87
137
  let pendingSyntaxError = '';
88
138
  let aborted = false;
89
- let continuationNudges = 0;
90
- let directWriteStreak = 0; // consecutive write_file calls without subagent (across steps)
139
+ let continuationNudges = 0; // счётчик подсказок "продолжай работать"
140
+ let directWriteStreak = 0; // количество прямых write_file без subagent
91
141
  // Reset abort signal for this run
92
142
  if (renderer?.abortSignal === undefined) {
93
143
  // Renderer doesn't support abort — fine
@@ -99,14 +149,14 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
99
149
  step: 0,
100
150
  maxSteps,
101
151
  });
152
+ // ─── Основной цикл ReAct ────────────────────────────────
102
153
  for (let step = 0; step < maxSteps; step++) {
103
154
  if (renderer?.abortSignal?.aborted) {
104
155
  aborted = true;
105
156
  break;
106
157
  }
107
158
  let skillsAutoLoaded = false;
108
- // Track files created/modified in this session for completion reporting
109
- const createdFiles = [];
159
+ const createdFiles = []; // отслеживание созданных/изменённых файлов
110
160
  logDebug('LOOP', `step ${step + 1}/${maxSteps} starting, ${messages.length} messages`);
111
161
  await ctx.updateTokens(messages);
112
162
  const skillNames = loadedSkills.map(s => s.name).join(', ');
@@ -120,6 +170,8 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
120
170
  step: step + 1,
121
171
  maxSteps,
122
172
  });
173
+ // ─── Compaction контекста ─────────────────────────────
174
+ // Если использование контекста превышает порог (85%), компактируем историю
123
175
  if (ctx.needsCompact && messages.length > 6) {
124
176
  const before = messages.length;
125
177
  messages.splice(0, messages.length, ...ctx.compact(messages));
@@ -128,15 +180,16 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
128
180
  }
129
181
  await ctx.updateTokens(messages);
130
182
  }
183
+ // ─── Запрос к LLM ────────────────────────────────────
131
184
  logInfo('LOOP', `calling doChat, messages: ${messages.length}, options.showThinking: ${options?.showThinking}`);
132
185
  const { response } = await doChat(provider, messages, renderer, renderer?.abortSignal, 1, options?.showThinking);
133
- // Check if aborted during generation
186
+ // Проверка прерывания во время генерации
134
187
  if (renderer?.abortSignal?.aborted) {
135
188
  aborted = true;
136
189
  break;
137
190
  }
138
- // Auto-load skills if the response contains @skill mentions
139
- // Works with or without tool calls — agent can mention skills while working
191
+ // ─── Автозагрузка скилов по @упоминаниям ─────────────
192
+ // Если ответ содержит @skill-name, загружаем скил и пересобираем system prompt
140
193
  if (options?.mode !== 'fast' && !skillsAutoLoaded) {
141
194
  const suggestedSkillRefs = response.matchAll(/@(\w[\w-]*)/g);
142
195
  const newSkillNames = [];
@@ -161,6 +214,8 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
161
214
  continue;
162
215
  }
163
216
  } // end fast-mode skill block
217
+ // ─── Обработка пустых ответов ────────────────────────
218
+ // Маленькие модели иногда возвращают пустой ответ — повторяем с подсказкой
164
219
  if (!response.trim()) {
165
220
  logWarn('LOOP', `empty response #${consecutiveEmpty + 1}`);
166
221
  consecutiveEmpty++;
@@ -179,6 +234,8 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
179
234
  }
180
235
  consecutiveEmpty = 0;
181
236
  messages.push({ role: 'assistant', content: response });
237
+ // ─── Парсинг tool calls ─────────────────────────────
238
+ // Извлекаем JSON из тегов <tool_call>...</tool_call> и валидируем
182
239
  const allJsonRaw = extractAllToolCalls(response);
183
240
  const validCalls = [];
184
241
  const invalidCalls = [];
@@ -203,6 +260,7 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
203
260
  }
204
261
  }
205
262
  }
263
+ // ─── Fallback: regex-извлечение при невалидном JSON ───
206
264
  if (validCalls.length === 0) {
207
265
  const fallback = extractToolCallFallback(response);
208
266
  if (fallback) {
@@ -261,9 +319,10 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
261
319
  }
262
320
  continue;
263
321
  }
264
- // Track consecutive read_file calls to the same file for consolidation
322
+ // ─── Enforce: лимиты на запись файлов ────────────────
323
+ // Отслеживание повторных чтений одного файла для консолидации
265
324
  let lastReadFile = null;
266
- // ENFORCEMENT: if plan has 3+ steps, block write_file and force subagent
325
+ // Блокировка прямых write_file когда есть план с 3+ шагами —.force subagent
267
326
  const planSteps = showPlan();
268
327
  const hasMultiStepPlan = !planSteps.startsWith('No active plan') && (planSteps.match(/\n/g) || []).length >= 3;
269
328
  if (hasMultiStepPlan) {
@@ -323,7 +382,7 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
323
382
  }
324
383
  }
325
384
  }
326
- // ENFORCEMENT: one file write at a time — block extra write_file/edit_file calls
385
+ // Блокировка нескольких записей файлов за один ответ — максимум одна
327
386
  const writeCalls = validCalls.filter(c => c.parsed.name === 'write_file' || c.parsed.name === 'edit_file');
328
387
  if (writeCalls.length > 1) {
329
388
  // Keep only the first write call, block the rest
@@ -341,6 +400,7 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
341
400
  renderer?.writeWarning(` [blocked ${blocked.length} extra file writes — one at a time]`);
342
401
  }
343
402
  }
403
+ // ─── Исполнение tool calls ──────────────────────────
344
404
  for (const call of validCalls) {
345
405
  const { parsed, cmd } = call;
346
406
  const isBash = parsed.name === 'bash';
@@ -380,7 +440,7 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
380
440
  let toolOutput = '';
381
441
  let toolExitCode = 0;
382
442
  const toolStart = performance.now();
383
- // Native tool calls: plan/todo/question/approve
443
+ // ─── Нативные инструменты (plan/todo/question/approve) ──
384
444
  if (parsed.name === 'plan') {
385
445
  const planName = String(parsed.arguments.TaskName || parsed.arguments.name || parsed.arguments.plan || 'Untitled');
386
446
  const stepsRaw = parsed.arguments.Steps || parsed.arguments.steps || [];
@@ -566,7 +626,7 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
566
626
  }
567
627
  }
568
628
  else if (parsed.name === 'subagent') {
569
- // Subagent: isolated context for a single task
629
+ // ─── Субагент: изолированный контекст для задачи ──
570
630
  const task = String(parsed.arguments.task || '');
571
631
  if (!task) {
572
632
  toolOutput = 'Error: task is required';
@@ -681,6 +741,7 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
681
741
  messages,
682
742
  questionPending: { question: `Approve: ${action}?`, choices: ['Yes', 'No'] },
683
743
  };
744
+ // ─── MCP-инструменты ────────────────────────────────
684
745
  }
685
746
  else if (isBash && isMCPCommand(cmd)) {
686
747
  const mcpCmd = parseMCPCommand(cmd);
@@ -694,11 +755,13 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
694
755
  toolOutput = 'Invalid MCP command. Format: mcp <server> <tool> [args_json]';
695
756
  toolExitCode = 1;
696
757
  }
758
+ // ─── Файловые инструменты (не bash) ─────────────────
697
759
  }
698
760
  else if (!isBash) {
699
761
  const result = await registry.execute({ id: toolId, name: parsed.name, arguments: parsed.arguments });
700
762
  toolOutput = result.stdout || result.stderr || '(no output)';
701
763
  toolExitCode = result.exitCode;
764
+ // ─── Bash: выполнение shell-команд ──────────────────
702
765
  }
703
766
  else {
704
767
  const result = await registry.execute({ id: toolId, name: 'bash', arguments: { cmd, timeout: parsed.arguments?.timeout ?? 120 } });
@@ -751,7 +814,7 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
751
814
  else if (!isBash && parsed.name !== 'read_file') {
752
815
  lastReadFile = null;
753
816
  }
754
- // Syntax check after file write operations
817
+ // ─── Проверка синтаксиса после записи файлов ────────
755
818
  let hasSyntaxError = false;
756
819
  if (toolExitCode === 0) {
757
820
  const isWriteOp = isBash
@@ -814,7 +877,7 @@ export async function runAgentLoop(provider, registry, prompt, contextManager, p
814
877
  pendingSyntaxError = '';
815
878
  }
816
879
  }
817
- // Auto-detect coding style from file content
880
+ // Автодетекция стиля кодирования из содержимого файла
818
881
  if (toolExitCode === 0 && filePath) {
819
882
  try {
820
883
  const fullContent = readFileSync(join(process.cwd(), filePath), 'utf-8');