agentx-sdk 0.1.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 (318) hide show
  1. package/README.md +561 -0
  2. package/dist/agent.d.ts +105 -0
  3. package/dist/agent.d.ts.map +1 -0
  4. package/dist/agent.js +690 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/config/config.d.ts +346 -0
  7. package/dist/config/config.d.ts.map +1 -0
  8. package/dist/config/config.js +93 -0
  9. package/dist/config/config.js.map +1 -0
  10. package/dist/contracts/entities/agent-event.d.ts +97 -0
  11. package/dist/contracts/entities/agent-event.d.ts.map +1 -0
  12. package/dist/contracts/entities/agent-event.js +2 -0
  13. package/dist/contracts/entities/agent-event.js.map +1 -0
  14. package/dist/contracts/entities/agent-skill.d.ts +59 -0
  15. package/dist/contracts/entities/agent-skill.d.ts.map +1 -0
  16. package/dist/contracts/entities/agent-skill.js +2 -0
  17. package/dist/contracts/entities/agent-skill.js.map +1 -0
  18. package/dist/contracts/entities/agent-tool.d.ts +42 -0
  19. package/dist/contracts/entities/agent-tool.d.ts.map +1 -0
  20. package/dist/contracts/entities/agent-tool.js +2 -0
  21. package/dist/contracts/entities/agent-tool.js.map +1 -0
  22. package/dist/contracts/entities/chat-message.d.ts +13 -0
  23. package/dist/contracts/entities/chat-message.d.ts.map +1 -0
  24. package/dist/contracts/entities/chat-message.js +2 -0
  25. package/dist/contracts/entities/chat-message.js.map +1 -0
  26. package/dist/contracts/entities/content-part.d.ts +16 -0
  27. package/dist/contracts/entities/content-part.d.ts.map +1 -0
  28. package/dist/contracts/entities/content-part.js +2 -0
  29. package/dist/contracts/entities/content-part.js.map +1 -0
  30. package/dist/contracts/entities/execution-context.d.ts +9 -0
  31. package/dist/contracts/entities/execution-context.d.ts.map +1 -0
  32. package/dist/contracts/entities/execution-context.js +2 -0
  33. package/dist/contracts/entities/execution-context.js.map +1 -0
  34. package/dist/contracts/entities/index.d.ts +11 -0
  35. package/dist/contracts/entities/index.d.ts.map +1 -0
  36. package/dist/contracts/entities/index.js +2 -0
  37. package/dist/contracts/entities/index.js.map +1 -0
  38. package/dist/contracts/entities/knowledge.d.ts +21 -0
  39. package/dist/contracts/entities/knowledge.d.ts.map +1 -0
  40. package/dist/contracts/entities/knowledge.js +2 -0
  41. package/dist/contracts/entities/knowledge.js.map +1 -0
  42. package/dist/contracts/entities/stores.d.ts +18 -0
  43. package/dist/contracts/entities/stores.d.ts.map +1 -0
  44. package/dist/contracts/entities/stores.js +2 -0
  45. package/dist/contracts/entities/stores.js.map +1 -0
  46. package/dist/contracts/entities/token-usage.d.ts +7 -0
  47. package/dist/contracts/entities/token-usage.d.ts.map +1 -0
  48. package/dist/contracts/entities/token-usage.js +2 -0
  49. package/dist/contracts/entities/token-usage.js.map +1 -0
  50. package/dist/contracts/entities/tool-call.d.ts +16 -0
  51. package/dist/contracts/entities/tool-call.d.ts.map +1 -0
  52. package/dist/contracts/entities/tool-call.js +2 -0
  53. package/dist/contracts/entities/tool-call.js.map +1 -0
  54. package/dist/contracts/enums/index.d.ts +21 -0
  55. package/dist/contracts/enums/index.d.ts.map +1 -0
  56. package/dist/contracts/enums/index.js +8 -0
  57. package/dist/contracts/enums/index.js.map +1 -0
  58. package/dist/contracts/index.d.ts +3 -0
  59. package/dist/contracts/index.d.ts.map +1 -0
  60. package/dist/contracts/index.js +3 -0
  61. package/dist/contracts/index.js.map +1 -0
  62. package/dist/core/compaction/autocompact.d.ts +18 -0
  63. package/dist/core/compaction/autocompact.d.ts.map +1 -0
  64. package/dist/core/compaction/autocompact.js +68 -0
  65. package/dist/core/compaction/autocompact.js.map +1 -0
  66. package/dist/core/compaction/microcompact.d.ts +20 -0
  67. package/dist/core/compaction/microcompact.d.ts.map +1 -0
  68. package/dist/core/compaction/microcompact.js +38 -0
  69. package/dist/core/compaction/microcompact.js.map +1 -0
  70. package/dist/core/compaction/snip-compact.d.ts +22 -0
  71. package/dist/core/compaction/snip-compact.d.ts.map +1 -0
  72. package/dist/core/compaction/snip-compact.js +61 -0
  73. package/dist/core/compaction/snip-compact.js.map +1 -0
  74. package/dist/core/compaction/tool-result-budget.d.ts +24 -0
  75. package/dist/core/compaction/tool-result-budget.d.ts.map +1 -0
  76. package/dist/core/compaction/tool-result-budget.js +67 -0
  77. package/dist/core/compaction/tool-result-budget.js.map +1 -0
  78. package/dist/core/context-analysis.d.ts +24 -0
  79. package/dist/core/context-analysis.d.ts.map +1 -0
  80. package/dist/core/context-analysis.js +37 -0
  81. package/dist/core/context-analysis.js.map +1 -0
  82. package/dist/core/context-builder.d.ts +25 -0
  83. package/dist/core/context-builder.d.ts.map +1 -0
  84. package/dist/core/context-builder.js +108 -0
  85. package/dist/core/context-builder.js.map +1 -0
  86. package/dist/core/conversation-manager.d.ts +19 -0
  87. package/dist/core/conversation-manager.d.ts.map +1 -0
  88. package/dist/core/conversation-manager.js +62 -0
  89. package/dist/core/conversation-manager.js.map +1 -0
  90. package/dist/core/execution-context.d.ts +6 -0
  91. package/dist/core/execution-context.d.ts.map +1 -0
  92. package/dist/core/execution-context.js +14 -0
  93. package/dist/core/execution-context.js.map +1 -0
  94. package/dist/core/loop-deps.d.ts +15 -0
  95. package/dist/core/loop-deps.d.ts.map +1 -0
  96. package/dist/core/loop-deps.js +8 -0
  97. package/dist/core/loop-deps.js.map +1 -0
  98. package/dist/core/loop-types.d.ts +34 -0
  99. package/dist/core/loop-types.d.ts.map +1 -0
  100. package/dist/core/loop-types.js +15 -0
  101. package/dist/core/loop-types.js.map +1 -0
  102. package/dist/core/message-normalize.d.ts +18 -0
  103. package/dist/core/message-normalize.d.ts.map +1 -0
  104. package/dist/core/message-normalize.js +69 -0
  105. package/dist/core/message-normalize.js.map +1 -0
  106. package/dist/core/prompt-builders.d.ts +36 -0
  107. package/dist/core/prompt-builders.d.ts.map +1 -0
  108. package/dist/core/prompt-builders.js +89 -0
  109. package/dist/core/prompt-builders.js.map +1 -0
  110. package/dist/core/prompt-cache.d.ts +25 -0
  111. package/dist/core/prompt-cache.d.ts.map +1 -0
  112. package/dist/core/prompt-cache.js +34 -0
  113. package/dist/core/prompt-cache.js.map +1 -0
  114. package/dist/core/react-loop.d.ts +43 -0
  115. package/dist/core/react-loop.d.ts.map +1 -0
  116. package/dist/core/react-loop.js +403 -0
  117. package/dist/core/react-loop.js.map +1 -0
  118. package/dist/core/stop-hooks.d.ts +18 -0
  119. package/dist/core/stop-hooks.d.ts.map +1 -0
  120. package/dist/core/stop-hooks.js +18 -0
  121. package/dist/core/stop-hooks.js.map +1 -0
  122. package/dist/core/stream-emitter.d.ts +24 -0
  123. package/dist/core/stream-emitter.d.ts.map +1 -0
  124. package/dist/core/stream-emitter.js +65 -0
  125. package/dist/core/stream-emitter.js.map +1 -0
  126. package/dist/core/streaming-tool-executor.d.ts +54 -0
  127. package/dist/core/streaming-tool-executor.d.ts.map +1 -0
  128. package/dist/core/streaming-tool-executor.js +164 -0
  129. package/dist/core/streaming-tool-executor.js.map +1 -0
  130. package/dist/core/turn-end-hooks.d.ts +39 -0
  131. package/dist/core/turn-end-hooks.d.ts.map +1 -0
  132. package/dist/core/turn-end-hooks.js +36 -0
  133. package/dist/core/turn-end-hooks.js.map +1 -0
  134. package/dist/index.d.ts +39 -0
  135. package/dist/index.d.ts.map +1 -0
  136. package/dist/index.js +45 -0
  137. package/dist/index.js.map +1 -0
  138. package/dist/knowledge/chunking.d.ts +9 -0
  139. package/dist/knowledge/chunking.d.ts.map +1 -0
  140. package/dist/knowledge/chunking.js +49 -0
  141. package/dist/knowledge/chunking.js.map +1 -0
  142. package/dist/knowledge/embedding-service.d.ts +16 -0
  143. package/dist/knowledge/embedding-service.d.ts.map +1 -0
  144. package/dist/knowledge/embedding-service.js +43 -0
  145. package/dist/knowledge/embedding-service.js.map +1 -0
  146. package/dist/knowledge/knowledge-manager.d.ts +33 -0
  147. package/dist/knowledge/knowledge-manager.d.ts.map +1 -0
  148. package/dist/knowledge/knowledge-manager.js +62 -0
  149. package/dist/knowledge/knowledge-manager.js.map +1 -0
  150. package/dist/knowledge/sqlite-vector-store.d.ts +16 -0
  151. package/dist/knowledge/sqlite-vector-store.d.ts.map +1 -0
  152. package/dist/knowledge/sqlite-vector-store.js +56 -0
  153. package/dist/knowledge/sqlite-vector-store.js.map +1 -0
  154. package/dist/knowledge/vector-store.d.ts +2 -0
  155. package/dist/knowledge/vector-store.d.ts.map +1 -0
  156. package/dist/knowledge/vector-store.js +2 -0
  157. package/dist/knowledge/vector-store.js.map +1 -0
  158. package/dist/llm/errors.d.ts +15 -0
  159. package/dist/llm/errors.d.ts.map +1 -0
  160. package/dist/llm/errors.js +39 -0
  161. package/dist/llm/errors.js.map +1 -0
  162. package/dist/llm/message-types.d.ts +80 -0
  163. package/dist/llm/message-types.d.ts.map +1 -0
  164. package/dist/llm/message-types.js +2 -0
  165. package/dist/llm/message-types.js.map +1 -0
  166. package/dist/llm/openrouter-client.d.ts +18 -0
  167. package/dist/llm/openrouter-client.d.ts.map +1 -0
  168. package/dist/llm/openrouter-client.js +215 -0
  169. package/dist/llm/openrouter-client.js.map +1 -0
  170. package/dist/llm/reasoning.d.ts +10 -0
  171. package/dist/llm/reasoning.d.ts.map +1 -0
  172. package/dist/llm/reasoning.js +18 -0
  173. package/dist/llm/reasoning.js.map +1 -0
  174. package/dist/memory/file-memory-system.d.ts +98 -0
  175. package/dist/memory/file-memory-system.d.ts.map +1 -0
  176. package/dist/memory/file-memory-system.js +310 -0
  177. package/dist/memory/file-memory-system.js.map +1 -0
  178. package/dist/memory/memory-age.d.ts +22 -0
  179. package/dist/memory/memory-age.d.ts.map +1 -0
  180. package/dist/memory/memory-age.js +44 -0
  181. package/dist/memory/memory-age.js.map +1 -0
  182. package/dist/memory/memory-extractor.d.ts +56 -0
  183. package/dist/memory/memory-extractor.d.ts.map +1 -0
  184. package/dist/memory/memory-extractor.js +91 -0
  185. package/dist/memory/memory-extractor.js.map +1 -0
  186. package/dist/memory/memory-paths.d.ts +45 -0
  187. package/dist/memory/memory-paths.d.ts.map +1 -0
  188. package/dist/memory/memory-paths.js +121 -0
  189. package/dist/memory/memory-paths.js.map +1 -0
  190. package/dist/memory/memory-prompts.d.ts +41 -0
  191. package/dist/memory/memory-prompts.d.ts.map +1 -0
  192. package/dist/memory/memory-prompts.js +279 -0
  193. package/dist/memory/memory-prompts.js.map +1 -0
  194. package/dist/memory/memory-relevance.d.ts +16 -0
  195. package/dist/memory/memory-relevance.d.ts.map +1 -0
  196. package/dist/memory/memory-relevance.js +46 -0
  197. package/dist/memory/memory-relevance.js.map +1 -0
  198. package/dist/memory/memory-scanner.d.ts +22 -0
  199. package/dist/memory/memory-scanner.d.ts.map +1 -0
  200. package/dist/memory/memory-scanner.js +99 -0
  201. package/dist/memory/memory-scanner.js.map +1 -0
  202. package/dist/memory/memory-tools.d.ts +16 -0
  203. package/dist/memory/memory-tools.d.ts.map +1 -0
  204. package/dist/memory/memory-tools.js +196 -0
  205. package/dist/memory/memory-tools.js.map +1 -0
  206. package/dist/memory/memory-types.d.ts +47 -0
  207. package/dist/memory/memory-types.d.ts.map +1 -0
  208. package/dist/memory/memory-types.js +24 -0
  209. package/dist/memory/memory-types.js.map +1 -0
  210. package/dist/skills/skill-args.d.ts +23 -0
  211. package/dist/skills/skill-args.d.ts.map +1 -0
  212. package/dist/skills/skill-args.js +77 -0
  213. package/dist/skills/skill-args.js.map +1 -0
  214. package/dist/skills/skill-glob.d.ts +24 -0
  215. package/dist/skills/skill-glob.d.ts.map +1 -0
  216. package/dist/skills/skill-glob.js +60 -0
  217. package/dist/skills/skill-glob.js.map +1 -0
  218. package/dist/skills/skill-loader.d.ts +49 -0
  219. package/dist/skills/skill-loader.d.ts.map +1 -0
  220. package/dist/skills/skill-loader.js +197 -0
  221. package/dist/skills/skill-loader.js.map +1 -0
  222. package/dist/skills/skill-manager.d.ts +83 -0
  223. package/dist/skills/skill-manager.d.ts.map +1 -0
  224. package/dist/skills/skill-manager.js +338 -0
  225. package/dist/skills/skill-manager.js.map +1 -0
  226. package/dist/storage/sqlite-conversation-store.d.ts +15 -0
  227. package/dist/storage/sqlite-conversation-store.d.ts.map +1 -0
  228. package/dist/storage/sqlite-conversation-store.js +45 -0
  229. package/dist/storage/sqlite-conversation-store.js.map +1 -0
  230. package/dist/storage/sqlite-database.d.ts +14 -0
  231. package/dist/storage/sqlite-database.d.ts.map +1 -0
  232. package/dist/storage/sqlite-database.js +95 -0
  233. package/dist/storage/sqlite-database.js.map +1 -0
  234. package/dist/tools/builtin/ask-user.d.ts +7 -0
  235. package/dist/tools/builtin/ask-user.d.ts.map +1 -0
  236. package/dist/tools/builtin/ask-user.js +23 -0
  237. package/dist/tools/builtin/ask-user.js.map +1 -0
  238. package/dist/tools/builtin/bash.d.ts +3 -0
  239. package/dist/tools/builtin/bash.d.ts.map +1 -0
  240. package/dist/tools/builtin/bash.js +54 -0
  241. package/dist/tools/builtin/bash.js.map +1 -0
  242. package/dist/tools/builtin/file-edit.d.ts +3 -0
  243. package/dist/tools/builtin/file-edit.d.ts.map +1 -0
  244. package/dist/tools/builtin/file-edit.js +50 -0
  245. package/dist/tools/builtin/file-edit.js.map +1 -0
  246. package/dist/tools/builtin/file-read.d.ts +3 -0
  247. package/dist/tools/builtin/file-read.d.ts.map +1 -0
  248. package/dist/tools/builtin/file-read.js +47 -0
  249. package/dist/tools/builtin/file-read.js.map +1 -0
  250. package/dist/tools/builtin/file-write.d.ts +3 -0
  251. package/dist/tools/builtin/file-write.d.ts.map +1 -0
  252. package/dist/tools/builtin/file-write.js +29 -0
  253. package/dist/tools/builtin/file-write.js.map +1 -0
  254. package/dist/tools/builtin/glob.d.ts +3 -0
  255. package/dist/tools/builtin/glob.d.ts.map +1 -0
  256. package/dist/tools/builtin/glob.js +67 -0
  257. package/dist/tools/builtin/glob.js.map +1 -0
  258. package/dist/tools/builtin/grep.d.ts +3 -0
  259. package/dist/tools/builtin/grep.d.ts.map +1 -0
  260. package/dist/tools/builtin/grep.js +94 -0
  261. package/dist/tools/builtin/grep.js.map +1 -0
  262. package/dist/tools/builtin/index.d.ts +49 -0
  263. package/dist/tools/builtin/index.d.ts.map +1 -0
  264. package/dist/tools/builtin/index.js +65 -0
  265. package/dist/tools/builtin/index.js.map +1 -0
  266. package/dist/tools/builtin/web-fetch.d.ts +3 -0
  267. package/dist/tools/builtin/web-fetch.d.ts.map +1 -0
  268. package/dist/tools/builtin/web-fetch.js +56 -0
  269. package/dist/tools/builtin/web-fetch.js.map +1 -0
  270. package/dist/tools/json-schema-to-zod.d.ts +30 -0
  271. package/dist/tools/json-schema-to-zod.d.ts.map +1 -0
  272. package/dist/tools/json-schema-to-zod.js +123 -0
  273. package/dist/tools/json-schema-to-zod.js.map +1 -0
  274. package/dist/tools/mcp-adapter.d.ts +80 -0
  275. package/dist/tools/mcp-adapter.d.ts.map +1 -0
  276. package/dist/tools/mcp-adapter.js +326 -0
  277. package/dist/tools/mcp-adapter.js.map +1 -0
  278. package/dist/tools/skill-tool.d.ts +41 -0
  279. package/dist/tools/skill-tool.d.ts.map +1 -0
  280. package/dist/tools/skill-tool.js +149 -0
  281. package/dist/tools/skill-tool.js.map +1 -0
  282. package/dist/tools/sql/index.d.ts +4 -0
  283. package/dist/tools/sql/index.d.ts.map +1 -0
  284. package/dist/tools/sql/index.js +2 -0
  285. package/dist/tools/sql/index.js.map +1 -0
  286. package/dist/tools/sql/sql-query-def.d.ts +22 -0
  287. package/dist/tools/sql/sql-query-def.d.ts.map +1 -0
  288. package/dist/tools/sql/sql-query-def.js +2 -0
  289. package/dist/tools/sql/sql-query-def.js.map +1 -0
  290. package/dist/tools/sql/sql-tool-factory.d.ts +28 -0
  291. package/dist/tools/sql/sql-tool-factory.d.ts.map +1 -0
  292. package/dist/tools/sql/sql-tool-factory.js +136 -0
  293. package/dist/tools/sql/sql-tool-factory.js.map +1 -0
  294. package/dist/tools/tool-executor.d.ts +67 -0
  295. package/dist/tools/tool-executor.d.ts.map +1 -0
  296. package/dist/tools/tool-executor.js +232 -0
  297. package/dist/tools/tool-executor.js.map +1 -0
  298. package/dist/utils/cache.d.ts +22 -0
  299. package/dist/utils/cache.d.ts.map +1 -0
  300. package/dist/utils/cache.js +61 -0
  301. package/dist/utils/cache.js.map +1 -0
  302. package/dist/utils/logger.d.ts +15 -0
  303. package/dist/utils/logger.d.ts.map +1 -0
  304. package/dist/utils/logger.js +46 -0
  305. package/dist/utils/logger.js.map +1 -0
  306. package/dist/utils/model-context.d.ts +14 -0
  307. package/dist/utils/model-context.d.ts.map +1 -0
  308. package/dist/utils/model-context.js +52 -0
  309. package/dist/utils/model-context.js.map +1 -0
  310. package/dist/utils/retry.d.ts +13 -0
  311. package/dist/utils/retry.d.ts.map +1 -0
  312. package/dist/utils/retry.js +41 -0
  313. package/dist/utils/retry.js.map +1 -0
  314. package/dist/utils/token-counter.d.ts +6 -0
  315. package/dist/utils/token-counter.d.ts.map +1 -0
  316. package/dist/utils/token-counter.js +19 -0
  317. package/dist/utils/token-counter.js.map +1 -0
  318. package/package.json +43 -0
@@ -0,0 +1,338 @@
1
+ import { scanSkillFiles } from './skill-loader.js';
2
+ import { substituteArgs } from './skill-args.js';
3
+ import { matchAnyGlob } from './skill-glob.js';
4
+ const MAX_LISTING_DESC_CHARS = 250;
5
+ /**
6
+ * Registers skills, matches them against user input, manages conditional
7
+ * activation, and provides budget-aware skill listings for model discovery.
8
+ *
9
+ * Matching hierarchy: prefix > alias > custom match() > semantic similarity.
10
+ */
11
+ export class SkillManager {
12
+ /** All registered skills (unconditional — always eligible for matching) */
13
+ skills = new Map();
14
+ /** Skills with `paths` — waiting for file touch to activate */
15
+ conditionalSkills = new Map();
16
+ /** Skills activated via path matching (moved from conditionalSkills) */
17
+ activatedSkills = new Map();
18
+ /** Tracks which skills have been invoked in this session */
19
+ invokedSkills = new Set();
20
+ /** Sticky skill sessions per thread — outer key: threadId, inner key: skillName */
21
+ stickySessions = new Map();
22
+ embeddingService;
23
+ maxActiveSkills;
24
+ constructor(options) {
25
+ this.embeddingService = options?.embeddingService;
26
+ this.maxActiveSkills = options?.maxActiveSkills ?? 3;
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // Registration
30
+ // ---------------------------------------------------------------------------
31
+ register(skill) {
32
+ if (skill.paths && skill.paths.length > 0) {
33
+ this.conditionalSkills.set(skill.name, skill);
34
+ }
35
+ else {
36
+ this.skills.set(skill.name, skill);
37
+ }
38
+ }
39
+ unregister(name) {
40
+ return this.skills.delete(name)
41
+ || this.conditionalSkills.delete(name)
42
+ || this.activatedSkills.delete(name);
43
+ }
44
+ /** All skills (unconditional + activated conditional) */
45
+ listSkills() {
46
+ return [...this.skills.values(), ...this.activatedSkills.values()];
47
+ }
48
+ /** All skills including pending conditional ones */
49
+ listAllSkills() {
50
+ return [
51
+ ...this.skills.values(),
52
+ ...this.activatedSkills.values(),
53
+ ...this.conditionalSkills.values(),
54
+ ];
55
+ }
56
+ // ---------------------------------------------------------------------------
57
+ // File-based loading
58
+ // ---------------------------------------------------------------------------
59
+ /**
60
+ * Load skills from a directory containing SKILL.md files.
61
+ * Returns the number of skills loaded.
62
+ */
63
+ async loadFromDirectory(dir) {
64
+ const skills = await scanSkillFiles(dir);
65
+ for (const skill of skills) {
66
+ this.register(skill);
67
+ }
68
+ return skills.length;
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Conditional path activation
72
+ // ---------------------------------------------------------------------------
73
+ /**
74
+ * Activate conditional skills whose `paths` match any of the given file paths.
75
+ * Returns the names of newly activated skills.
76
+ */
77
+ activateForPaths(filePaths) {
78
+ const activated = [];
79
+ for (const [name, skill] of this.conditionalSkills) {
80
+ if (!skill.paths)
81
+ continue;
82
+ const matched = filePaths.some(fp => matchAnyGlob(skill.paths, fp));
83
+ if (matched) {
84
+ this.activatedSkills.set(name, skill);
85
+ this.conditionalSkills.delete(name);
86
+ activated.push(name);
87
+ }
88
+ }
89
+ return activated;
90
+ }
91
+ // ---------------------------------------------------------------------------
92
+ // Matching
93
+ // ---------------------------------------------------------------------------
94
+ /**
95
+ * Matches skills against input. Returns top skills sorted by priority.
96
+ */
97
+ async match(input, context) {
98
+ const matches = [];
99
+ const matchedNames = new Set();
100
+ const eligible = this.getEligibleSkills();
101
+ // 0. Sticky sessions — re-inject skills that are active for this thread
102
+ const threadSessions = this.stickySessions.get(context.threadId);
103
+ if (threadSessions) {
104
+ for (const [skillName, session] of threadSessions) {
105
+ if (session.turnsRemaining <= 0) {
106
+ threadSessions.delete(skillName);
107
+ continue;
108
+ }
109
+ const skill = this.skills.get(skillName) ?? this.activatedSkills.get(skillName);
110
+ if (skill) {
111
+ matches.push({ skill, matchType: 'sticky', score: 0.9 });
112
+ matchedNames.add(skillName);
113
+ }
114
+ }
115
+ // Clean up empty thread entry
116
+ if (threadSessions.size === 0) {
117
+ this.stickySessions.delete(context.threadId);
118
+ }
119
+ }
120
+ for (const skill of eligible) {
121
+ if (matchedNames.has(skill.name))
122
+ continue;
123
+ // 1. Prefix match (highest priority)
124
+ if (skill.triggerPrefix && input.startsWith(skill.triggerPrefix)) {
125
+ matches.push({ skill, matchType: 'prefix', score: 1.0 });
126
+ matchedNames.add(skill.name);
127
+ continue;
128
+ }
129
+ // 2. Alias match
130
+ if (skill.aliases) {
131
+ const matched = skill.aliases.some(alias => {
132
+ const prefix = alias.startsWith('/') ? alias : `/${alias}`;
133
+ return input.startsWith(prefix);
134
+ });
135
+ if (matched) {
136
+ matches.push({ skill, matchType: 'alias', score: 0.95 });
137
+ matchedNames.add(skill.name);
138
+ continue;
139
+ }
140
+ }
141
+ // 3. Custom match function
142
+ if (skill.match && skill.match(input, { threadId: context.threadId, recentMessages: 0 })) {
143
+ matches.push({ skill, matchType: 'custom', score: 0.8 });
144
+ matchedNames.add(skill.name);
145
+ continue;
146
+ }
147
+ }
148
+ // 4. Semantic match — only if no prefix/alias/custom/sticky matches found
149
+ // and there are skills that lack explicit matchers
150
+ if (this.embeddingService && matches.length === 0 && this.hasSkillsNeedingSemantic(eligible)) {
151
+ const semanticMatches = await this.semanticMatch(input, eligible);
152
+ matches.push(...semanticMatches);
153
+ }
154
+ // Sort: exclusive first, then by match type priority, then by skill.priority
155
+ const sorted = matches.sort((a, b) => {
156
+ if (a.skill.exclusive && !b.skill.exclusive)
157
+ return -1;
158
+ if (!a.skill.exclusive && b.skill.exclusive)
159
+ return 1;
160
+ const typeOrder = { prefix: 4, sticky: 3.5, alias: 3, custom: 2, semantic: 1 };
161
+ const typeDiff = (typeOrder[b.matchType] ?? 0) - (typeOrder[a.matchType] ?? 0);
162
+ if (typeDiff !== 0)
163
+ return typeDiff;
164
+ return (b.skill.priority ?? 0) - (a.skill.priority ?? 0);
165
+ });
166
+ // Activate sticky sessions for newly matched skills and decrement turn counters
167
+ for (const match of sorted) {
168
+ if (match.skill.sticky) {
169
+ this.activateStickySession(context.threadId, match.skill);
170
+ }
171
+ }
172
+ this.decrementStickySessions(context.threadId);
173
+ // If exclusive skill matched, return only it
174
+ if (sorted[0]?.skill.exclusive) {
175
+ return [sorted[0].skill];
176
+ }
177
+ return sorted.slice(0, this.maxActiveSkills).map(m => m.skill);
178
+ }
179
+ // ---------------------------------------------------------------------------
180
+ // Dynamic prompt resolution
181
+ // ---------------------------------------------------------------------------
182
+ /**
183
+ * Resolve the final instructions for a matched skill.
184
+ * If `getPrompt` exists, calls it with args and context.
185
+ * Otherwise uses static `instructions` with argument substitution.
186
+ */
187
+ async resolveInstructions(skill, args, context) {
188
+ if (skill.getPrompt) {
189
+ return skill.getPrompt(args, context);
190
+ }
191
+ // Static instructions with optional substitution
192
+ if (skill.argNames && skill.argNames.length > 0) {
193
+ return substituteArgs(skill.instructions, args, skill.argNames, {
194
+ SKILL_DIR: context.skillDir ?? skill.skillDir ?? '',
195
+ THREAD_ID: context.threadId,
196
+ TRACE_ID: context.traceId,
197
+ });
198
+ }
199
+ return skill.instructions;
200
+ }
201
+ // ---------------------------------------------------------------------------
202
+ // Budget-aware listing for model discovery
203
+ // ---------------------------------------------------------------------------
204
+ /**
205
+ * Build a formatted listing of available skills for model context.
206
+ * Truncates to fit within the given character budget.
207
+ */
208
+ buildSkillListing(budgetChars) {
209
+ const eligible = this.getEligibleSkills()
210
+ .filter(s => s.modelInvocable !== false);
211
+ if (eligible.length === 0)
212
+ return '';
213
+ const lines = [];
214
+ let usedChars = 0;
215
+ for (const skill of eligible) {
216
+ const prefix = skill.triggerPrefix
217
+ ? skill.triggerPrefix
218
+ : `/${skill.name}`;
219
+ let line = `- ${prefix}: ${skill.description}`;
220
+ if (skill.whenToUse) {
221
+ line += ` — ${skill.whenToUse}`;
222
+ }
223
+ // Truncate individual entry
224
+ if (line.length > MAX_LISTING_DESC_CHARS) {
225
+ line = line.slice(0, MAX_LISTING_DESC_CHARS - 3) + '...';
226
+ }
227
+ if (usedChars + line.length > budgetChars)
228
+ break;
229
+ lines.push(line);
230
+ usedChars += line.length + 1; // +1 for newline
231
+ }
232
+ return lines.join('\n');
233
+ }
234
+ // ---------------------------------------------------------------------------
235
+ // Invocation tracking
236
+ // ---------------------------------------------------------------------------
237
+ markInvoked(name) {
238
+ this.invokedSkills.add(name);
239
+ }
240
+ getInvokedSkills() {
241
+ return [...this.invokedSkills];
242
+ }
243
+ // ---------------------------------------------------------------------------
244
+ // Sticky session management
245
+ // ---------------------------------------------------------------------------
246
+ /** Remove a single sticky skill from a thread */
247
+ clearStickySkill(threadId, skillName) {
248
+ this.stickySessions.get(threadId)?.delete(skillName);
249
+ }
250
+ /** Remove all sticky skills for a thread (e.g. on clearHistory) */
251
+ clearStickySkills(threadId) {
252
+ this.stickySessions.delete(threadId);
253
+ }
254
+ /** Remove all sticky sessions across all threads (e.g. on destroy) */
255
+ clearAllStickySessions() {
256
+ this.stickySessions.clear();
257
+ }
258
+ // ---------------------------------------------------------------------------
259
+ // Private helpers
260
+ // ---------------------------------------------------------------------------
261
+ activateStickySession(threadId, skill) {
262
+ if (!this.stickySessions.has(threadId)) {
263
+ this.stickySessions.set(threadId, new Map());
264
+ }
265
+ const sessions = this.stickySessions.get(threadId);
266
+ // Don't reset an existing session (first activation wins)
267
+ if (!sessions.has(skill.name)) {
268
+ sessions.set(skill.name, {
269
+ skillName: skill.name,
270
+ activatedAt: Date.now(),
271
+ turnsRemaining: skill.sticky === true ? Infinity : skill.sticky,
272
+ });
273
+ }
274
+ }
275
+ decrementStickySessions(threadId) {
276
+ const sessions = this.stickySessions.get(threadId);
277
+ if (!sessions)
278
+ return;
279
+ for (const session of sessions.values()) {
280
+ if (session.turnsRemaining !== Infinity) {
281
+ session.turnsRemaining--;
282
+ }
283
+ }
284
+ }
285
+ /** Get all skills eligible for matching (unconditional + activated) */
286
+ getEligibleSkills() {
287
+ const eligible = [];
288
+ for (const skill of this.skills.values()) {
289
+ if (skill.isEnabled && !skill.isEnabled())
290
+ continue;
291
+ eligible.push(skill);
292
+ }
293
+ for (const skill of this.activatedSkills.values()) {
294
+ if (skill.isEnabled && !skill.isEnabled())
295
+ continue;
296
+ eligible.push(skill);
297
+ }
298
+ return eligible;
299
+ }
300
+ /**
301
+ * Returns true if any eligible skill lacks both triggerPrefix, aliases, and match(),
302
+ * meaning it can only be activated via semantic matching.
303
+ */
304
+ hasSkillsNeedingSemantic(eligible) {
305
+ return eligible.some(s => !s.triggerPrefix && !s.aliases?.length && !s.match);
306
+ }
307
+ async semanticMatch(input, eligible) {
308
+ if (!this.embeddingService)
309
+ return [];
310
+ const inputEmbedding = await this.embeddingService.embedSingle(input);
311
+ const results = [];
312
+ for (const skill of eligible) {
313
+ // Only semantic-match skills that lack explicit matchers
314
+ if (skill.triggerPrefix || skill.aliases?.length || skill.match)
315
+ continue;
316
+ const text = skill.whenToUse
317
+ ? `${skill.description}. ${skill.whenToUse}`
318
+ : skill.description;
319
+ const skillEmbedding = await this.embeddingService.embedSingle(text);
320
+ const score = cosineSimilarity(inputEmbedding, skillEmbedding);
321
+ if (score > 0.7) {
322
+ results.push({ skill, matchType: 'semantic', score });
323
+ }
324
+ }
325
+ return results;
326
+ }
327
+ }
328
+ function cosineSimilarity(a, b) {
329
+ let dot = 0, normA = 0, normB = 0;
330
+ for (let i = 0; i < a.length; i++) {
331
+ dot += a[i] * b[i];
332
+ normA += a[i] * a[i];
333
+ normB += b[i] * b[i];
334
+ }
335
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
336
+ return denom === 0 ? 0 : dot / denom;
337
+ }
338
+ //# sourceMappingURL=skill-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-manager.js","sourceRoot":"","sources":["../../src/skills/skill-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { ConversationStore } from '../contracts/entities/stores.js';
2
+ import type { ChatMessage } from '../contracts/entities/chat-message.js';
3
+ import type { SQLiteDatabase } from './sqlite-database.js';
4
+ /**
5
+ * SQLite implementation of ConversationStore.
6
+ */
7
+ export declare class SQLiteConversationStore implements ConversationStore {
8
+ private readonly database;
9
+ constructor(database: SQLiteDatabase);
10
+ appendMessage(message: ChatMessage, threadId: string): void;
11
+ listThread(threadId: string): ChatMessage[];
12
+ listPinned(threadId: string): ChatMessage[];
13
+ clearThread(threadId: string): void;
14
+ }
15
+ //# sourceMappingURL=sqlite-conversation-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-conversation-store.d.ts","sourceRoot":"","sources":["../../src/storage/sqlite-conversation-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;GAEG;AACH,qBAAa,uBAAwB,YAAW,iBAAiB;IAC/D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;gBAE9B,QAAQ,EAAE,cAAc;IAIpC,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAe3D,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE;IAO3C,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE;IAO3C,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;CAGpC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * SQLite implementation of ConversationStore.
3
+ */
4
+ export class SQLiteConversationStore {
5
+ database;
6
+ constructor(database) {
7
+ this.database = database;
8
+ }
9
+ appendMessage(message, threadId) {
10
+ this.database.db.prepare(`
11
+ INSERT INTO conversations (thread_id, role, content, tool_calls, tool_call_id, pinned, created_at)
12
+ VALUES (?, ?, ?, ?, ?, ?, ?)
13
+ `).run(threadId, message.role, typeof message.content === 'string' ? message.content : JSON.stringify(message.content), message.toolCalls ? JSON.stringify(message.toolCalls) : null, message.toolCallId ?? null, message.pinned ? 1 : 0, message.createdAt);
14
+ }
15
+ listThread(threadId) {
16
+ const rows = this.database.db.prepare('SELECT * FROM conversations WHERE thread_id = ? ORDER BY created_at ASC').all(threadId);
17
+ return rows.map(rowToMessage);
18
+ }
19
+ listPinned(threadId) {
20
+ const rows = this.database.db.prepare('SELECT * FROM conversations WHERE thread_id = ? AND pinned = 1 ORDER BY created_at ASC').all(threadId);
21
+ return rows.map(rowToMessage);
22
+ }
23
+ clearThread(threadId) {
24
+ this.database.db.prepare('DELETE FROM conversations WHERE thread_id = ?').run(threadId);
25
+ }
26
+ }
27
+ function rowToMessage(row) {
28
+ let content;
29
+ try {
30
+ const parsed = JSON.parse(row.content);
31
+ content = Array.isArray(parsed) ? parsed : row.content;
32
+ }
33
+ catch {
34
+ content = row.content;
35
+ }
36
+ return {
37
+ role: row.role,
38
+ content: content,
39
+ toolCalls: row.tool_calls ? JSON.parse(row.tool_calls) : undefined,
40
+ toolCallId: row.tool_call_id ?? undefined,
41
+ pinned: row.pinned === 1,
42
+ createdAt: row.created_at,
43
+ };
44
+ }
45
+ //# sourceMappingURL=sqlite-conversation-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-conversation-store.js","sourceRoot":"","sources":["../../src/storage/sqlite-conversation-store.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,OAAO,uBAAuB;IACjB,QAAQ,CAAiB;IAE1C,YAAY,QAAwB;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,aAAa,CAAC,OAAoB,EAAE,QAAgB;QAClD,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAGxB,CAAC,CAAC,GAAG,CACJ,QAAQ,EACR,OAAO,CAAC,IAAI,EACZ,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EACvF,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAC5D,OAAO,CAAC,UAAU,IAAI,IAAI,EAC1B,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACtB,OAAO,CAAC,SAAS,CAClB,CAAC;IACJ,CAAC;IAED,UAAU,CAAC,QAAgB;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CACnC,yEAAyE,CAC1E,CAAC,GAAG,CAAC,QAAQ,CAAsB,CAAC;QACrC,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAChC,CAAC;IAED,UAAU,CAAC,QAAgB;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CACnC,wFAAwF,CACzF,CAAC,GAAG,CAAC,QAAQ,CAAsB,CAAC;QACrC,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAChC,CAAC;IAED,WAAW,CAAC,QAAgB;QAC1B,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1F,CAAC;CACF;AAED,SAAS,YAAY,CAAC,GAAoB;IACxC,IAAI,OAAqF,CAAC;IAC1F,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAA2B;QACrC,OAAO,EAAE,OAAiC;QAC1C,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS;QAClE,UAAU,EAAE,GAAG,CAAC,YAAY,IAAI,SAAS;QACzC,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,CAAC;QACxB,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type BetterSqlite3 from 'better-sqlite3';
2
+ /**
3
+ * Centralized SQLite wrapper with auto-create tables, migrations, and WAL mode.
4
+ */
5
+ export declare class SQLiteDatabase {
6
+ private _db;
7
+ private readonly path;
8
+ constructor(path: string);
9
+ get db(): BetterSqlite3.Database;
10
+ initialize(): void;
11
+ close(): void;
12
+ private migrateV1;
13
+ }
14
+ //# sourceMappingURL=sqlite-database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-database.d.ts","sourceRoot":"","sources":["../../src/storage/sqlite-database.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAEhD;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAAuC;IAClD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,IAAI,EAAE,MAAM;IAIxB,IAAI,EAAE,IAAI,aAAa,CAAC,QAAQ,CAG/B;IAED,UAAU,IAAI,IAAI;IAiBlB,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,SAAS;CA+DlB"}
@@ -0,0 +1,95 @@
1
+ import { mkdirSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ import Database from 'better-sqlite3';
4
+ /**
5
+ * Centralized SQLite wrapper with auto-create tables, migrations, and WAL mode.
6
+ */
7
+ export class SQLiteDatabase {
8
+ _db = null;
9
+ path;
10
+ constructor(path) {
11
+ this.path = path;
12
+ }
13
+ get db() {
14
+ if (!this._db)
15
+ throw new Error('Database not initialized. Call initialize() first.');
16
+ return this._db;
17
+ }
18
+ initialize() {
19
+ if (this._db)
20
+ return;
21
+ // Auto-create parent directory for file-based databases
22
+ if (this.path !== ':memory:') {
23
+ mkdirSync(dirname(this.path), { recursive: true });
24
+ }
25
+ this._db = new Database(this.path);
26
+ // Enable WAL mode for concurrent reads
27
+ this._db.pragma('journal_mode = WAL');
28
+ this._db.pragma('synchronous = NORMAL');
29
+ this.migrateV1();
30
+ }
31
+ close() {
32
+ if (this._db) {
33
+ this._db.close();
34
+ this._db = null;
35
+ }
36
+ }
37
+ migrateV1() {
38
+ const db = this.db;
39
+ db.exec(`
40
+ CREATE TABLE IF NOT EXISTS memories (
41
+ id TEXT PRIMARY KEY,
42
+ content TEXT NOT NULL,
43
+ scope TEXT NOT NULL,
44
+ category TEXT NOT NULL,
45
+ confidence REAL NOT NULL DEFAULT 0.8,
46
+ access_count INTEGER NOT NULL DEFAULT 0,
47
+ source TEXT NOT NULL DEFAULT 'extracted',
48
+ thread_id TEXT,
49
+ embedding BLOB,
50
+ created_at INTEGER NOT NULL,
51
+ last_accessed_at INTEGER NOT NULL
52
+ );
53
+
54
+ CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope);
55
+ CREATE INDEX IF NOT EXISTS idx_memories_thread ON memories(thread_id);
56
+ CREATE INDEX IF NOT EXISTS idx_memories_confidence ON memories(confidence);
57
+ `);
58
+ // FTS5 virtual table for full-text search
59
+ // Check if already exists (FTS5 tables don't support IF NOT EXISTS in all versions)
60
+ const ftsExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='memories_fts'").get();
61
+ if (!ftsExists) {
62
+ db.exec(`
63
+ CREATE VIRTUAL TABLE memories_fts USING fts5(
64
+ content,
65
+ content=memories,
66
+ content_rowid=rowid
67
+ );
68
+ `);
69
+ }
70
+ db.exec(`
71
+ CREATE TABLE IF NOT EXISTS vectors (
72
+ id TEXT PRIMARY KEY,
73
+ content TEXT NOT NULL,
74
+ embedding BLOB NOT NULL,
75
+ metadata TEXT,
76
+ created_at INTEGER NOT NULL
77
+ );
78
+
79
+ CREATE TABLE IF NOT EXISTS conversations (
80
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
81
+ thread_id TEXT NOT NULL,
82
+ role TEXT NOT NULL,
83
+ content TEXT NOT NULL,
84
+ tool_calls TEXT,
85
+ tool_call_id TEXT,
86
+ pinned INTEGER NOT NULL DEFAULT 0,
87
+ created_at INTEGER NOT NULL
88
+ );
89
+
90
+ CREATE INDEX IF NOT EXISTS idx_conversations_thread ON conversations(thread_id, created_at);
91
+ CREATE INDEX IF NOT EXISTS idx_conversations_pinned ON conversations(thread_id, pinned);
92
+ `);
93
+ }
94
+ }
95
+ //# sourceMappingURL=sqlite-database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-database.js","sourceRoot":"","sources":["../../src/storage/sqlite-database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAGtC;;GAEG;AACH,MAAM,OAAO,cAAc;IACjB,GAAG,GAAkC,IAAI,CAAC;IACjC,IAAI,CAAS;IAE9B,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,IAAI,EAAE;QACJ,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACrF,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;IAED,UAAU;QACR,IAAI,IAAI,CAAC,GAAG;YAAE,OAAO;QAErB,wDAAwD;QACxD,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC7B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEnC,uCAAuC;QACvC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACtC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAExC,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;QAClB,CAAC;IACH,CAAC;IAEO,SAAS;QACf,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QAEnB,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;KAkBP,CAAC,CAAC;QAEH,0CAA0C;QAC1C,oFAAoF;QACpF,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAC1B,2EAA2E,CAC5E,CAAC,GAAG,EAAE,CAAC;QAER,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,EAAE,CAAC,IAAI,CAAC;;;;;;OAMP,CAAC,CAAC;QACL,CAAC;QAED,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;KAsBP,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ import type { AgentTool } from '../../contracts/entities/agent-tool.js';
2
+ export interface AskUserOptions {
3
+ /** Callback invoked when the model asks a question. Consumer implements this. */
4
+ onAsk: (question: string, options?: string[]) => Promise<string>;
5
+ }
6
+ export declare function createAskUserTool(opts: AskUserOptions): AgentTool;
7
+ //# sourceMappingURL=ask-user.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask-user.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/ask-user.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AAOxE,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAClE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,CAiBjE"}
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod';
2
+ const AskUserParams = z.object({
3
+ question: z.string().describe('Question to ask the user'),
4
+ options: z.array(z.string()).optional().describe('Optional multiple-choice options'),
5
+ });
6
+ export function createAskUserTool(opts) {
7
+ return {
8
+ name: 'AskUser',
9
+ description: 'Ask the user a question and wait for their response. Use when you need clarification or confirmation.',
10
+ parameters: AskUserParams,
11
+ async execute(rawArgs) {
12
+ const { question, options } = rawArgs;
13
+ try {
14
+ const answer = await opts.onAsk(question, options);
15
+ return `User responded: ${answer}`;
16
+ }
17
+ catch (error) {
18
+ return { content: `Failed to get user response: ${error.message}`, isError: true };
19
+ }
20
+ },
21
+ };
22
+ }
23
+ //# sourceMappingURL=ask-user.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask-user.js","sourceRoot":"","sources":["../../../src/tools/builtin/ask-user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IACzD,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;CACrF,CAAC,CAAC;AAOH,MAAM,UAAU,iBAAiB,CAAC,IAAoB;IACpD,OAAO;QACL,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,uGAAuG;QACpH,UAAU,EAAE,aAAa;QAEzB,KAAK,CAAC,OAAO,CAAC,OAAgB;YAC5B,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAwC,CAAC;YAEvE,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACnD,OAAO,mBAAmB,MAAM,EAAE,CAAC;YACrC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,EAAE,OAAO,EAAE,gCAAiC,KAAe,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAChG,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AgentTool } from '../../contracts/entities/agent-tool.js';
2
+ export declare function createBashTool(): AgentTool;
3
+ //# sourceMappingURL=bash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/bash.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AAUxE,wBAAgB,cAAc,IAAI,SAAS,CA4C1C"}
@@ -0,0 +1,54 @@
1
+ import { exec } from 'node:child_process';
2
+ import { z } from 'zod';
3
+ const DEFAULT_TIMEOUT = 120_000;
4
+ const MAX_OUTPUT = 500_000; // 500KB
5
+ const BashParams = z.object({
6
+ command: z.string().describe('Shell command to execute'),
7
+ timeout: z.number().optional().describe('Timeout in milliseconds. Default: 120000 (2 minutes).'),
8
+ });
9
+ export function createBashTool() {
10
+ return {
11
+ name: 'Bash',
12
+ description: 'Execute a shell command and return stdout/stderr.',
13
+ parameters: BashParams,
14
+ isDestructive: true, // conservative — commands can have side effects
15
+ timeoutMs: DEFAULT_TIMEOUT,
16
+ async execute(rawArgs, signal) {
17
+ const { command, timeout } = rawArgs;
18
+ const effectiveTimeout = timeout ?? DEFAULT_TIMEOUT;
19
+ return new Promise((resolve) => {
20
+ exec(command, {
21
+ timeout: effectiveTimeout,
22
+ maxBuffer: MAX_OUTPUT,
23
+ shell: process.env.SHELL || '/bin/sh',
24
+ signal,
25
+ }, (error, stdout, stderr) => {
26
+ const out = stdout?.slice(0, MAX_OUTPUT) ?? '';
27
+ const err = stderr?.slice(0, MAX_OUTPUT) ?? '';
28
+ if (error) {
29
+ const exitCode = error.code ?? 'unknown';
30
+ const parts = [];
31
+ if (out)
32
+ parts.push(out);
33
+ if (err)
34
+ parts.push(err);
35
+ if (!out && !err)
36
+ parts.push(error.message);
37
+ parts.push(`\nExit code: ${exitCode}`);
38
+ resolve({ content: parts.join('\n'), isError: true });
39
+ return;
40
+ }
41
+ const parts = [];
42
+ if (out)
43
+ parts.push(out);
44
+ if (err)
45
+ parts.push(`[stderr]\n${err}`);
46
+ if (!out && !err)
47
+ parts.push('(no output)');
48
+ resolve(parts.join('\n'));
49
+ });
50
+ });
51
+ },
52
+ };
53
+ }
54
+ //# sourceMappingURL=bash.js.map