@xandout/libra-harness 0.1.8

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 (289) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +486 -0
  3. package/dist/agent.d.ts +174 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +575 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/ai-sdk-model.d.ts +26 -0
  8. package/dist/ai-sdk-model.d.ts.map +1 -0
  9. package/dist/ai-sdk-model.js +260 -0
  10. package/dist/ai-sdk-model.js.map +1 -0
  11. package/dist/context.d.ts +75 -0
  12. package/dist/context.d.ts.map +1 -0
  13. package/dist/context.js +2 -0
  14. package/dist/context.js.map +1 -0
  15. package/dist/errors.d.ts +33 -0
  16. package/dist/errors.d.ts.map +1 -0
  17. package/dist/errors.js +59 -0
  18. package/dist/errors.js.map +1 -0
  19. package/dist/extension.d.ts +63 -0
  20. package/dist/extension.d.ts.map +1 -0
  21. package/dist/extension.js +2 -0
  22. package/dist/extension.js.map +1 -0
  23. package/dist/extras/extension-loader.d.ts +205 -0
  24. package/dist/extras/extension-loader.d.ts.map +1 -0
  25. package/dist/extras/extension-loader.js +315 -0
  26. package/dist/extras/extension-loader.js.map +1 -0
  27. package/dist/extras/extensions/auto-steer/extension.d.ts +46 -0
  28. package/dist/extras/extensions/auto-steer/extension.d.ts.map +1 -0
  29. package/dist/extras/extensions/auto-steer/extension.js +52 -0
  30. package/dist/extras/extensions/auto-steer/extension.js.map +1 -0
  31. package/dist/extras/extensions/auto-steer/extension.json +7 -0
  32. package/dist/extras/extensions/auto-steer/index.d.ts +3 -0
  33. package/dist/extras/extensions/auto-steer/index.d.ts.map +1 -0
  34. package/dist/extras/extensions/auto-steer/index.js +2 -0
  35. package/dist/extras/extensions/auto-steer/index.js.map +1 -0
  36. package/dist/extras/extensions/disk-session/extension.d.ts +167 -0
  37. package/dist/extras/extensions/disk-session/extension.d.ts.map +1 -0
  38. package/dist/extras/extensions/disk-session/extension.js +492 -0
  39. package/dist/extras/extensions/disk-session/extension.js.map +1 -0
  40. package/dist/extras/extensions/disk-session/extension.json +6 -0
  41. package/dist/extras/extensions/disk-session/extension.test.d.ts +2 -0
  42. package/dist/extras/extensions/disk-session/extension.test.d.ts.map +1 -0
  43. package/dist/extras/extensions/disk-session/extension.test.js +672 -0
  44. package/dist/extras/extensions/disk-session/extension.test.js.map +1 -0
  45. package/dist/extras/extensions/disk-session/index.d.ts +3 -0
  46. package/dist/extras/extensions/disk-session/index.d.ts.map +1 -0
  47. package/dist/extras/extensions/disk-session/index.js +2 -0
  48. package/dist/extras/extensions/disk-session/index.js.map +1 -0
  49. package/dist/extras/extensions/emoji/extension.d.ts +20 -0
  50. package/dist/extras/extensions/emoji/extension.d.ts.map +1 -0
  51. package/dist/extras/extensions/emoji/extension.js +22 -0
  52. package/dist/extras/extensions/emoji/extension.js.map +1 -0
  53. package/dist/extras/extensions/emoji/extension.json +7 -0
  54. package/dist/extras/extensions/emoji/index.d.ts +3 -0
  55. package/dist/extras/extensions/emoji/index.d.ts.map +1 -0
  56. package/dist/extras/extensions/emoji/index.js +2 -0
  57. package/dist/extras/extensions/emoji/index.js.map +1 -0
  58. package/dist/extras/extensions/filesystem/extension.d.ts +53 -0
  59. package/dist/extras/extensions/filesystem/extension.d.ts.map +1 -0
  60. package/dist/extras/extensions/filesystem/extension.js +350 -0
  61. package/dist/extras/extensions/filesystem/extension.js.map +1 -0
  62. package/dist/extras/extensions/filesystem/extension.json +6 -0
  63. package/dist/extras/extensions/filesystem/extension.test.d.ts +2 -0
  64. package/dist/extras/extensions/filesystem/extension.test.d.ts.map +1 -0
  65. package/dist/extras/extensions/filesystem/extension.test.js +387 -0
  66. package/dist/extras/extensions/filesystem/extension.test.js.map +1 -0
  67. package/dist/extras/extensions/filesystem/index.d.ts +2 -0
  68. package/dist/extras/extensions/filesystem/index.d.ts.map +1 -0
  69. package/dist/extras/extensions/filesystem/index.js +2 -0
  70. package/dist/extras/extensions/filesystem/index.js.map +1 -0
  71. package/dist/extras/extensions/keyword-extractor/extension.d.ts +53 -0
  72. package/dist/extras/extensions/keyword-extractor/extension.d.ts.map +1 -0
  73. package/dist/extras/extensions/keyword-extractor/extension.js +61 -0
  74. package/dist/extras/extensions/keyword-extractor/extension.js.map +1 -0
  75. package/dist/extras/extensions/keyword-extractor/extension.json +6 -0
  76. package/dist/extras/extensions/keyword-extractor/extension.test.d.ts +2 -0
  77. package/dist/extras/extensions/keyword-extractor/extension.test.d.ts.map +1 -0
  78. package/dist/extras/extensions/keyword-extractor/extension.test.js +105 -0
  79. package/dist/extras/extensions/keyword-extractor/extension.test.js.map +1 -0
  80. package/dist/extras/extensions/keyword-extractor/index.d.ts +5 -0
  81. package/dist/extras/extensions/keyword-extractor/index.d.ts.map +1 -0
  82. package/dist/extras/extensions/keyword-extractor/index.js +3 -0
  83. package/dist/extras/extensions/keyword-extractor/index.js.map +1 -0
  84. package/dist/extras/extensions/keyword-extractor/nlp.d.ts +68 -0
  85. package/dist/extras/extensions/keyword-extractor/nlp.d.ts.map +1 -0
  86. package/dist/extras/extensions/keyword-extractor/nlp.js +156 -0
  87. package/dist/extras/extensions/keyword-extractor/nlp.js.map +1 -0
  88. package/dist/extras/extensions/keyword-extractor/nlp.test.d.ts +2 -0
  89. package/dist/extras/extensions/keyword-extractor/nlp.test.d.ts.map +1 -0
  90. package/dist/extras/extensions/keyword-extractor/nlp.test.js +176 -0
  91. package/dist/extras/extensions/keyword-extractor/nlp.test.js.map +1 -0
  92. package/dist/extras/extensions/logger/extension.d.ts +52 -0
  93. package/dist/extras/extensions/logger/extension.d.ts.map +1 -0
  94. package/dist/extras/extensions/logger/extension.js +68 -0
  95. package/dist/extras/extensions/logger/extension.js.map +1 -0
  96. package/dist/extras/extensions/logger/extension.json +7 -0
  97. package/dist/extras/extensions/logger/index.d.ts +3 -0
  98. package/dist/extras/extensions/logger/index.d.ts.map +1 -0
  99. package/dist/extras/extensions/logger/index.js +2 -0
  100. package/dist/extras/extensions/logger/index.js.map +1 -0
  101. package/dist/extras/extensions/mcp/extension.d.ts +63 -0
  102. package/dist/extras/extensions/mcp/extension.d.ts.map +1 -0
  103. package/dist/extras/extensions/mcp/extension.js +437 -0
  104. package/dist/extras/extensions/mcp/extension.js.map +1 -0
  105. package/dist/extras/extensions/mcp/extension.json +7 -0
  106. package/dist/extras/extensions/mcp/extension.test.d.ts +2 -0
  107. package/dist/extras/extensions/mcp/extension.test.d.ts.map +1 -0
  108. package/dist/extras/extensions/mcp/extension.test.js +286 -0
  109. package/dist/extras/extensions/mcp/extension.test.js.map +1 -0
  110. package/dist/extras/extensions/mcp/index.d.ts +3 -0
  111. package/dist/extras/extensions/mcp/index.d.ts.map +1 -0
  112. package/dist/extras/extensions/mcp/index.js +2 -0
  113. package/dist/extras/extensions/mcp/index.js.map +1 -0
  114. package/dist/extras/extensions/mem-session/extension.d.ts +24 -0
  115. package/dist/extras/extensions/mem-session/extension.d.ts.map +1 -0
  116. package/dist/extras/extensions/mem-session/extension.js +49 -0
  117. package/dist/extras/extensions/mem-session/extension.js.map +1 -0
  118. package/dist/extras/extensions/mem-session/extension.json +6 -0
  119. package/dist/extras/extensions/mem-session/index.d.ts +2 -0
  120. package/dist/extras/extensions/mem-session/index.d.ts.map +1 -0
  121. package/dist/extras/extensions/mem-session/index.js +2 -0
  122. package/dist/extras/extensions/mem-session/index.js.map +1 -0
  123. package/dist/extras/extensions/memory/extension.d.ts +54 -0
  124. package/dist/extras/extensions/memory/extension.d.ts.map +1 -0
  125. package/dist/extras/extensions/memory/extension.js +143 -0
  126. package/dist/extras/extensions/memory/extension.js.map +1 -0
  127. package/dist/extras/extensions/memory/extension.json +7 -0
  128. package/dist/extras/extensions/memory/index.d.ts +5 -0
  129. package/dist/extras/extensions/memory/index.d.ts.map +1 -0
  130. package/dist/extras/extensions/memory/index.js +3 -0
  131. package/dist/extras/extensions/memory/index.js.map +1 -0
  132. package/dist/extras/extensions/memory/llm-extractor.d.ts +42 -0
  133. package/dist/extras/extensions/memory/llm-extractor.d.ts.map +1 -0
  134. package/dist/extras/extensions/memory/llm-extractor.js +89 -0
  135. package/dist/extras/extensions/memory/llm-extractor.js.map +1 -0
  136. package/dist/extras/extensions/memory/types.d.ts +142 -0
  137. package/dist/extras/extensions/memory/types.d.ts.map +1 -0
  138. package/dist/extras/extensions/memory/types.js +2 -0
  139. package/dist/extras/extensions/memory/types.js.map +1 -0
  140. package/dist/extras/extensions/otel/extension.d.ts +57 -0
  141. package/dist/extras/extensions/otel/extension.d.ts.map +1 -0
  142. package/dist/extras/extensions/otel/extension.js +253 -0
  143. package/dist/extras/extensions/otel/extension.js.map +1 -0
  144. package/dist/extras/extensions/otel/extension.json +7 -0
  145. package/dist/extras/extensions/otel/extension.test.d.ts +2 -0
  146. package/dist/extras/extensions/otel/extension.test.d.ts.map +1 -0
  147. package/dist/extras/extensions/otel/extension.test.js +399 -0
  148. package/dist/extras/extensions/otel/extension.test.js.map +1 -0
  149. package/dist/extras/extensions/otel/index.d.ts +4 -0
  150. package/dist/extras/extensions/otel/index.d.ts.map +1 -0
  151. package/dist/extras/extensions/otel/index.js +3 -0
  152. package/dist/extras/extensions/otel/index.js.map +1 -0
  153. package/dist/extras/extensions/otel/jsonl-span-exporter.d.ts +60 -0
  154. package/dist/extras/extensions/otel/jsonl-span-exporter.d.ts.map +1 -0
  155. package/dist/extras/extensions/otel/jsonl-span-exporter.js +134 -0
  156. package/dist/extras/extensions/otel/jsonl-span-exporter.js.map +1 -0
  157. package/dist/extras/extensions/scripts/extension.d.ts +180 -0
  158. package/dist/extras/extensions/scripts/extension.d.ts.map +1 -0
  159. package/dist/extras/extensions/scripts/extension.js +618 -0
  160. package/dist/extras/extensions/scripts/extension.js.map +1 -0
  161. package/dist/extras/extensions/scripts/extension.json +7 -0
  162. package/dist/extras/extensions/scripts/extension.test.d.ts +2 -0
  163. package/dist/extras/extensions/scripts/extension.test.d.ts.map +1 -0
  164. package/dist/extras/extensions/scripts/extension.test.js +552 -0
  165. package/dist/extras/extensions/scripts/extension.test.js.map +1 -0
  166. package/dist/extras/extensions/scripts/index.d.ts +3 -0
  167. package/dist/extras/extensions/scripts/index.d.ts.map +1 -0
  168. package/dist/extras/extensions/scripts/index.js +2 -0
  169. package/dist/extras/extensions/scripts/index.js.map +1 -0
  170. package/dist/extras/extensions/skills/extension.d.ts +105 -0
  171. package/dist/extras/extensions/skills/extension.d.ts.map +1 -0
  172. package/dist/extras/extensions/skills/extension.js +419 -0
  173. package/dist/extras/extensions/skills/extension.js.map +1 -0
  174. package/dist/extras/extensions/skills/extension.json +7 -0
  175. package/dist/extras/extensions/skills/extension.test.d.ts +2 -0
  176. package/dist/extras/extensions/skills/extension.test.d.ts.map +1 -0
  177. package/dist/extras/extensions/skills/extension.test.js +184 -0
  178. package/dist/extras/extensions/skills/extension.test.js.map +1 -0
  179. package/dist/extras/extensions/skills/index.d.ts +4 -0
  180. package/dist/extras/extensions/skills/index.d.ts.map +1 -0
  181. package/dist/extras/extensions/skills/index.js +3 -0
  182. package/dist/extras/extensions/skills/index.js.map +1 -0
  183. package/dist/extras/extensions/streaming/extension.d.ts +15 -0
  184. package/dist/extras/extensions/streaming/extension.d.ts.map +1 -0
  185. package/dist/extras/extensions/streaming/extension.js +41 -0
  186. package/dist/extras/extensions/streaming/extension.js.map +1 -0
  187. package/dist/extras/extensions/streaming/extension.json +6 -0
  188. package/dist/extras/extensions/streaming/index.d.ts +2 -0
  189. package/dist/extras/extensions/streaming/index.d.ts.map +1 -0
  190. package/dist/extras/extensions/streaming/index.js +2 -0
  191. package/dist/extras/extensions/streaming/index.js.map +1 -0
  192. package/dist/extras/extensions/structured-output/extension.d.ts +11 -0
  193. package/dist/extras/extensions/structured-output/extension.d.ts.map +1 -0
  194. package/dist/extras/extensions/structured-output/extension.js +102 -0
  195. package/dist/extras/extensions/structured-output/extension.js.map +1 -0
  196. package/dist/extras/extensions/structured-output/extension.json +7 -0
  197. package/dist/extras/extensions/structured-output/index.d.ts +3 -0
  198. package/dist/extras/extensions/structured-output/index.d.ts.map +1 -0
  199. package/dist/extras/extensions/structured-output/index.js +2 -0
  200. package/dist/extras/extensions/structured-output/index.js.map +1 -0
  201. package/dist/extras/extensions/timestamp/extension.d.ts +11 -0
  202. package/dist/extras/extensions/timestamp/extension.d.ts.map +1 -0
  203. package/dist/extras/extensions/timestamp/extension.js +21 -0
  204. package/dist/extras/extensions/timestamp/extension.js.map +1 -0
  205. package/dist/extras/extensions/timestamp/extension.json +6 -0
  206. package/dist/extras/extensions/timestamp/index.d.ts +2 -0
  207. package/dist/extras/extensions/timestamp/index.d.ts.map +1 -0
  208. package/dist/extras/extensions/timestamp/index.js +2 -0
  209. package/dist/extras/extensions/timestamp/index.js.map +1 -0
  210. package/dist/extras/extensions/token-stats/extension.d.ts +50 -0
  211. package/dist/extras/extensions/token-stats/extension.d.ts.map +1 -0
  212. package/dist/extras/extensions/token-stats/extension.js +99 -0
  213. package/dist/extras/extensions/token-stats/extension.js.map +1 -0
  214. package/dist/extras/extensions/token-stats/extension.json +7 -0
  215. package/dist/extras/extensions/token-stats/extension.test.d.ts +2 -0
  216. package/dist/extras/extensions/token-stats/extension.test.d.ts.map +1 -0
  217. package/dist/extras/extensions/token-stats/extension.test.js +197 -0
  218. package/dist/extras/extensions/token-stats/extension.test.js.map +1 -0
  219. package/dist/extras/extensions/token-stats/index.d.ts +3 -0
  220. package/dist/extras/extensions/token-stats/index.d.ts.map +1 -0
  221. package/dist/extras/extensions/token-stats/index.js +2 -0
  222. package/dist/extras/extensions/token-stats/index.js.map +1 -0
  223. package/dist/extras/extensions/tool-buffer/extension.d.ts +89 -0
  224. package/dist/extras/extensions/tool-buffer/extension.d.ts.map +1 -0
  225. package/dist/extras/extensions/tool-buffer/extension.js +182 -0
  226. package/dist/extras/extensions/tool-buffer/extension.js.map +1 -0
  227. package/dist/extras/extensions/tool-buffer/extension.json +7 -0
  228. package/dist/extras/extensions/tool-buffer/extension.test.d.ts +2 -0
  229. package/dist/extras/extensions/tool-buffer/extension.test.d.ts.map +1 -0
  230. package/dist/extras/extensions/tool-buffer/extension.test.js +549 -0
  231. package/dist/extras/extensions/tool-buffer/extension.test.js.map +1 -0
  232. package/dist/extras/extensions/tool-buffer/index.d.ts +3 -0
  233. package/dist/extras/extensions/tool-buffer/index.d.ts.map +1 -0
  234. package/dist/extras/extensions/tool-buffer/index.js +2 -0
  235. package/dist/extras/extensions/tool-buffer/index.js.map +1 -0
  236. package/dist/extras/extensions/weather-tool/extension.d.ts +22 -0
  237. package/dist/extras/extensions/weather-tool/extension.d.ts.map +1 -0
  238. package/dist/extras/extensions/weather-tool/extension.js +33 -0
  239. package/dist/extras/extensions/weather-tool/extension.js.map +1 -0
  240. package/dist/extras/extensions/weather-tool/extension.json +7 -0
  241. package/dist/extras/extensions/weather-tool/index.d.ts +3 -0
  242. package/dist/extras/extensions/weather-tool/index.d.ts.map +1 -0
  243. package/dist/extras/extensions/weather-tool/index.js +2 -0
  244. package/dist/extras/extensions/weather-tool/index.js.map +1 -0
  245. package/dist/extras/models/ai-sdk-resolver.d.ts +15 -0
  246. package/dist/extras/models/ai-sdk-resolver.d.ts.map +1 -0
  247. package/dist/extras/models/ai-sdk-resolver.js +57 -0
  248. package/dist/extras/models/ai-sdk-resolver.js.map +1 -0
  249. package/dist/extras/models/index.d.ts +5 -0
  250. package/dist/extras/models/index.d.ts.map +1 -0
  251. package/dist/extras/models/index.js +3 -0
  252. package/dist/extras/models/index.js.map +1 -0
  253. package/dist/extras/models/routing-model.d.ts +18 -0
  254. package/dist/extras/models/routing-model.d.ts.map +1 -0
  255. package/dist/extras/models/routing-model.js +24 -0
  256. package/dist/extras/models/routing-model.js.map +1 -0
  257. package/dist/extras/openai-provider/index.d.ts +3 -0
  258. package/dist/extras/openai-provider/index.d.ts.map +1 -0
  259. package/dist/extras/openai-provider/index.js +2 -0
  260. package/dist/extras/openai-provider/index.js.map +1 -0
  261. package/dist/extras/openai-provider/server.d.ts +34 -0
  262. package/dist/extras/openai-provider/server.d.ts.map +1 -0
  263. package/dist/extras/openai-provider/server.js +335 -0
  264. package/dist/extras/openai-provider/server.js.map +1 -0
  265. package/dist/handle.d.ts +56 -0
  266. package/dist/handle.d.ts.map +1 -0
  267. package/dist/handle.js +2 -0
  268. package/dist/handle.js.map +1 -0
  269. package/dist/hooks.d.ts +98 -0
  270. package/dist/hooks.d.ts.map +1 -0
  271. package/dist/hooks.js +53 -0
  272. package/dist/hooks.js.map +1 -0
  273. package/dist/index.d.ts +16 -0
  274. package/dist/index.d.ts.map +1 -0
  275. package/dist/index.js +9 -0
  276. package/dist/index.js.map +1 -0
  277. package/dist/model.d.ts +75 -0
  278. package/dist/model.d.ts.map +1 -0
  279. package/dist/model.js +2 -0
  280. package/dist/model.js.map +1 -0
  281. package/dist/tool.d.ts +78 -0
  282. package/dist/tool.d.ts.map +1 -0
  283. package/dist/tool.js +78 -0
  284. package/dist/tool.js.map +1 -0
  285. package/dist/types.d.ts +83 -0
  286. package/dist/types.d.ts.map +1 -0
  287. package/dist/types.js +21 -0
  288. package/dist/types.js.map +1 -0
  289. package/package.json +178 -0
@@ -0,0 +1,184 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { mkdtempSync, rmSync, mkdirSync, writeFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { Agent } from '../../../agent.js';
6
+ import { createSkillExtension } from './index.js';
7
+ // โ”€โ”€ Mock model โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
8
+ // Returns a fixed assistant message.
9
+ function mockModel() {
10
+ return {
11
+ async generate() {
12
+ return {
13
+ message: { role: 'assistant', content: 'ok' },
14
+ finishReason: 'stop',
15
+ };
16
+ },
17
+ };
18
+ }
19
+ // โ”€โ”€ Helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
20
+ function makeSkill(dir, name, frontmatter = {}, body = 'Skill body') {
21
+ const skillDir = join(dir, name);
22
+ mkdirSync(skillDir, { recursive: true });
23
+ const fmLines = Object.entries(frontmatter).map(([k, v]) => `${k}: ${v}`);
24
+ const content = `---\nname: ${name}\n${fmLines.join('\n')}\n---\n${body}`;
25
+ writeFileSync(join(skillDir, 'SKILL.md'), content);
26
+ return skillDir;
27
+ }
28
+ // โ”€โ”€ Test setup โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
29
+ let tmpDir;
30
+ beforeEach(() => {
31
+ tmpDir = mkdtempSync(join(tmpdir(), 'skills-test-'));
32
+ });
33
+ afterEach(() => {
34
+ rmSync(tmpDir, { recursive: true, force: true });
35
+ });
36
+ // โ”€โ”€ Tests โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
37
+ describe('skills extension', () => {
38
+ it('loads skills from a directory at startup', () => {
39
+ makeSkill(tmpDir, 'code-review', { description: 'Review code' });
40
+ makeSkill(tmpDir, 'summarize', { description: 'Summarize text' });
41
+ const ext = createSkillExtension({ skillsDirs: tmpDir });
42
+ expect(ext).toBeDefined();
43
+ const agent = new Agent({ model: mockModel() });
44
+ agent.use(ext);
45
+ // list_skills should be registered as a tool
46
+ expect(agent.getTools()).toContain('list_skills');
47
+ expect(agent.getTools()).toContain('use_skill');
48
+ });
49
+ it('returns undefined when no skillsDirs provided', () => {
50
+ const ext = createSkillExtension({});
51
+ expect(ext).toBeUndefined();
52
+ });
53
+ it('list_skills returns skills present at startup', async () => {
54
+ makeSkill(tmpDir, 'alpha', { description: 'Alpha skill' });
55
+ makeSkill(tmpDir, 'beta', { description: 'Beta skill' });
56
+ const ext = createSkillExtension({ skillsDirs: tmpDir });
57
+ const agent = new Agent({ model: mockModel() });
58
+ agent.use(ext);
59
+ // Find the list_skills tool and call it directly.
60
+ const tools = agent.getTools();
61
+ expect(tools).toContain('list_skills');
62
+ });
63
+ it('list_skills discovers new skills added at runtime', async () => {
64
+ // Start with one skill.
65
+ makeSkill(tmpDir, 'existing', { description: 'Existing skill' });
66
+ const ext = createSkillExtension({ skillsDirs: tmpDir });
67
+ const agent = new Agent({ model: mockModel() });
68
+ agent.use(ext);
69
+ // Add a new skill directory after the extension is installed.
70
+ makeSkill(tmpDir, 'runtime-added', { description: 'Added at runtime' });
71
+ // Model that calls list_skills on first turn, then returns the
72
+ // tool result as the final message so we can inspect it.
73
+ let callCount = 0;
74
+ let capturedToolResult = '';
75
+ const callModel = {
76
+ async generate(req) {
77
+ callCount++;
78
+ if (callCount === 1) {
79
+ return {
80
+ message: {
81
+ role: 'assistant',
82
+ content: '',
83
+ toolCalls: [{
84
+ id: 'call_1',
85
+ name: 'list_skills',
86
+ arguments: '{}',
87
+ }],
88
+ },
89
+ finishReason: 'tool_calls',
90
+ };
91
+ }
92
+ // Second call: capture the tool result and return it.
93
+ const toolMsg = req.messages.find((m) => m.role === 'tool');
94
+ capturedToolResult = toolMsg?.content ?? '';
95
+ return {
96
+ message: { role: 'assistant', content: capturedToolResult },
97
+ finishReason: 'stop',
98
+ };
99
+ },
100
+ };
101
+ const agent2 = new Agent({ model: callModel });
102
+ agent2.use(ext);
103
+ const result = await agent2.run({ message: 'list skills' });
104
+ expect(result.finishReason).toBe('stop');
105
+ expect(result.toolCalls?.some((tc) => tc.name === 'list_skills')).toBe(true);
106
+ // The tool result should include both the existing and runtime-added skills.
107
+ expect(capturedToolResult).toContain('existing');
108
+ expect(capturedToolResult).toContain('runtime-added');
109
+ });
110
+ it('use_skill can load a skill added at runtime', async () => {
111
+ // Start with no skills.
112
+ const ext = createSkillExtension({ skillsDirs: tmpDir });
113
+ const agent = new Agent({ model: mockModel() });
114
+ agent.use(ext);
115
+ // Add a skill after install.
116
+ makeSkill(tmpDir, 'late-skill', { description: 'Added late' }, 'Late skill content');
117
+ // Model that calls use_skill, then returns the result.
118
+ let sawSkillContent = false;
119
+ const callModel = {
120
+ async generate(req) {
121
+ const hasUseSkill = req.tools?.some((t) => t.function.name === 'use_skill');
122
+ if (hasUseSkill && !req.messages.some((m) => m.role === 'tool')) {
123
+ return {
124
+ message: {
125
+ role: 'assistant',
126
+ content: '',
127
+ toolCalls: [{
128
+ id: 'call_1',
129
+ name: 'use_skill',
130
+ arguments: JSON.stringify({ skill: 'late-skill' }),
131
+ }],
132
+ },
133
+ finishReason: 'tool_calls',
134
+ };
135
+ }
136
+ // Check if the tool result contains the late skill content
137
+ const toolMsg = req.messages.find((m) => m.role === 'tool');
138
+ if (toolMsg && toolMsg.content.includes('Late skill content')) {
139
+ sawSkillContent = true;
140
+ }
141
+ return {
142
+ message: { role: 'assistant', content: 'done' },
143
+ finishReason: 'stop',
144
+ };
145
+ },
146
+ };
147
+ const agent2 = new Agent({ model: callModel });
148
+ agent2.use(ext);
149
+ await agent2.run({ message: 'use the late skill' });
150
+ expect(sawSkillContent).toBe(true);
151
+ });
152
+ it('autoLoad skills are appended to system prompt at install time', () => {
153
+ makeSkill(tmpDir, 'always-on', { autoLoad: 'true', description: 'Always active' }, 'Always-on content');
154
+ let seenSystemPrompt = '';
155
+ const model = {
156
+ async generate(req) {
157
+ seenSystemPrompt = req.systemPrompt ?? '';
158
+ return {
159
+ message: { role: 'assistant', content: 'ok' },
160
+ finishReason: 'stop',
161
+ };
162
+ },
163
+ };
164
+ const ext = createSkillExtension({ skillsDirs: tmpDir });
165
+ const agent = new Agent({ model: model, systemPrompt: 'Base prompt.' });
166
+ agent.use(ext);
167
+ return agent.run({ message: 'hi' }).then(() => {
168
+ expect(seenSystemPrompt).toContain('Base prompt.');
169
+ expect(seenSystemPrompt).toContain('Always-on content');
170
+ });
171
+ });
172
+ it('supports multiple skills directories', () => {
173
+ const dir2 = mkdtempSync(join(tmpdir(), 'skills-test-2-'));
174
+ makeSkill(tmpDir, 'from-dir1', { description: 'First dir' });
175
+ makeSkill(dir2, 'from-dir2', { description: 'Second dir' });
176
+ const ext = createSkillExtension({ skillsDirs: [tmpDir, dir2] });
177
+ const agent = new Agent({ model: mockModel() });
178
+ agent.use(ext);
179
+ expect(agent.getTools()).toContain('list_skills');
180
+ // Clean up second dir
181
+ rmSync(dir2, { recursive: true, force: true });
182
+ });
183
+ });
184
+ //# sourceMappingURL=extension.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.test.js","sourceRoot":"","sources":["../../../../src/extras/extensions/skills/extension.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { default as createSkillExtension } from './extension.js';
2
+ export type { SkillsExtensionConfig, SkillMeta, Skill } from './extension.js';
3
+ export { loadSkills } from './extension.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/extras/extensions/skills/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACjE,YAAY,EAAE,qBAAqB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { default as createSkillExtension } from './extension.js';
2
+ export { loadSkills } from './extension.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/extras/extensions/skills/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { Extension } from '../../../extension.js';
2
+ /**
3
+ * Streaming extension โ€” sets `onDelta` on the model request in
4
+ * `beforeLLM` so the AISdkModel uses its streaming path.
5
+ *
6
+ * The caller passes callbacks via `metadata.streamCallbacks`:
7
+ * - `onText(delta)` โ€” text token deltas
8
+ * - `onReasoning(delta)` โ€” reasoning/thinking token deltas
9
+ * - `onToolInput(delta, toolName)` โ€” tool argument token deltas
10
+ *
11
+ * When no `streamCallbacks` are in metadata, the extension is a no-op
12
+ * and the model uses `doGenerate` (no streaming overhead).
13
+ */
14
+ export default function createStreamingExtension(): Extension;
15
+ //# sourceMappingURL=extension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../../../../src/extras/extensions/streaming/extension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGvD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,UAAU,wBAAwB,IAAI,SAAS,CAgC5D"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Streaming extension โ€” sets `onDelta` on the model request in
3
+ * `beforeLLM` so the AISdkModel uses its streaming path.
4
+ *
5
+ * The caller passes callbacks via `metadata.streamCallbacks`:
6
+ * - `onText(delta)` โ€” text token deltas
7
+ * - `onReasoning(delta)` โ€” reasoning/thinking token deltas
8
+ * - `onToolInput(delta, toolName)` โ€” tool argument token deltas
9
+ *
10
+ * When no `streamCallbacks` are in metadata, the extension is a no-op
11
+ * and the model uses `doGenerate` (no streaming overhead).
12
+ */
13
+ export default function createStreamingExtension() {
14
+ return {
15
+ name: 'streaming',
16
+ priority: 100,
17
+ install(agent) {
18
+ agent.hook('beforeLLM', 'streaming', async (ctx) => {
19
+ if (!ctx.modelRequest)
20
+ return;
21
+ const callbacks = ctx.turn.metadata.streamCallbacks;
22
+ if (!callbacks)
23
+ return;
24
+ ctx.modelRequest.onDelta = (delta) => {
25
+ switch (delta.type) {
26
+ case 'text':
27
+ callbacks.onText?.(delta.content);
28
+ break;
29
+ case 'reasoning':
30
+ callbacks.onReasoning?.(delta.content);
31
+ break;
32
+ case 'tool-input':
33
+ callbacks.onToolInput?.(delta.content, delta.toolName ?? '');
34
+ break;
35
+ }
36
+ };
37
+ });
38
+ },
39
+ };
40
+ }
41
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../../../../src/extras/extensions/streaming/extension.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,UAAU,wBAAwB;IAC9C,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,GAAG;QACb,OAAO,CAAC,KAAK;YACX,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;gBACjD,IAAI,CAAC,GAAG,CAAC,YAAY;oBAAE,OAAO;gBAE9B,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,eAIvB,CAAC;gBAEd,IAAI,CAAC,SAAS;oBAAE,OAAO;gBAEvB,GAAG,CAAC,YAAY,CAAC,OAAO,GAAG,CAAC,KAAiB,EAAE,EAAE;oBAC/C,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;wBACnB,KAAK,MAAM;4BACT,SAAS,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;4BAClC,MAAM;wBACR,KAAK,WAAW;4BACd,SAAS,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;4BACvC,MAAM;wBACR,KAAK,YAAY;4BACf,SAAS,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;4BAC7D,MAAM;oBACV,CAAC;gBACH,CAAC,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "streaming",
3
+ "description": "Sets onDelta on modelRequest via beforeLLM hook to enable streaming. Caller passes callbacks via metadata.streamCallbacks.",
4
+ "enabled": true,
5
+ "priority": 100
6
+ }
@@ -0,0 +1,2 @@
1
+ export { default as createStreamingExtension } from './extension.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/extras/extensions/streaming/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { default as createStreamingExtension } from './extension.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/extras/extensions/streaming/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Extension } from '../../../extension.js';
2
+ export interface StructuredOutputConfig {
3
+ /** JSON schema to validate against. Required. */
4
+ schema: Record<string, unknown>;
5
+ /** Field name in metadata to store the parsed JSON. Default: "structured". */
6
+ metadataKey?: string;
7
+ /** Whether to strip markdown code fences from the response. Default: true. */
8
+ stripCodeFences?: boolean;
9
+ }
10
+ export default function createStructuredOutputExtension(config: StructuredOutputConfig): Extension | undefined;
11
+ //# sourceMappingURL=extension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../../../../src/extras/extensions/structured-output/extension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,WAAW,sBAAsB;IACrC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,CAAC,OAAO,UAAU,+BAA+B,CACrD,MAAM,EAAE,sBAAsB,GAC7B,SAAS,GAAG,SAAS,CA8GvB"}
@@ -0,0 +1,102 @@
1
+ export default function createStructuredOutputExtension(config) {
2
+ if (!config?.schema) {
3
+ console.log('[structured-output] no schema in config โ€” skipping');
4
+ return undefined;
5
+ }
6
+ const { schema } = config;
7
+ const metadataKey = config.metadataKey ?? 'structured';
8
+ const stripCodeFences = config.stripCodeFences ?? true;
9
+ return {
10
+ name: 'structured-output',
11
+ priority: 50,
12
+ install(agent) {
13
+ agent.hook('beforeResponse', 'structured-output', async (ctx) => {
14
+ if (!ctx.turn.response)
15
+ return;
16
+ let raw = ctx.turn.response.message;
17
+ // Strip markdown code fences if present (LLMs often wrap JSON in ```json ... ```).
18
+ if (stripCodeFences) {
19
+ const fenceMatch = raw.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
20
+ if (fenceMatch) {
21
+ raw = fenceMatch[1].trim();
22
+ }
23
+ }
24
+ let parsed;
25
+ try {
26
+ parsed = JSON.parse(raw);
27
+ }
28
+ catch {
29
+ // Not valid JSON โ€” replace the response with an error that includes the schema.
30
+ ctx.turn.response = {
31
+ ...ctx.turn.response,
32
+ message: JSON.stringify({
33
+ error: 'Response is not valid JSON',
34
+ expectedSchema: schema,
35
+ rawResponse: ctx.turn.response.message.slice(0, 500),
36
+ }),
37
+ };
38
+ return;
39
+ }
40
+ // Validate against the schema's required fields.
41
+ const required = schema.required ?? [];
42
+ const missing = required.filter((field) => {
43
+ const value = parsed[field];
44
+ return value === undefined || value === null;
45
+ });
46
+ if (missing.length > 0) {
47
+ ctx.turn.response = {
48
+ ...ctx.turn.response,
49
+ message: JSON.stringify({
50
+ error: `Missing required fields: ${missing.join(', ')}`,
51
+ expectedSchema: schema,
52
+ received: Object.keys(parsed),
53
+ }),
54
+ };
55
+ return;
56
+ }
57
+ // Type-check each field against the schema.
58
+ const properties = schema.properties ?? {};
59
+ const typeErrors = [];
60
+ for (const [field, spec] of Object.entries(properties)) {
61
+ const value = parsed[field];
62
+ if (value === undefined)
63
+ continue;
64
+ const expectedType = spec.type;
65
+ let actualType;
66
+ if (Array.isArray(value)) {
67
+ actualType = 'array';
68
+ }
69
+ else if (typeof value === 'number' && Number.isInteger(value)) {
70
+ actualType = 'number';
71
+ }
72
+ else {
73
+ actualType = typeof value;
74
+ }
75
+ if (actualType !== expectedType) {
76
+ typeErrors.push(`Field "${field}" expected ${expectedType}, got ${actualType}`);
77
+ }
78
+ }
79
+ if (typeErrors.length > 0) {
80
+ ctx.turn.response = {
81
+ ...ctx.turn.response,
82
+ message: JSON.stringify({
83
+ error: 'Type validation failed',
84
+ errors: typeErrors,
85
+ expectedSchema: schema,
86
+ }),
87
+ };
88
+ return;
89
+ }
90
+ // Valid โ€” store the parsed object in metadata and clean up the response.
91
+ ctx.turn.metadata[metadataKey] = parsed;
92
+ // Keep the response as the raw JSON string so callers can parse it.
93
+ // Or optionally replace with a formatted version.
94
+ ctx.turn.response = {
95
+ ...ctx.turn.response,
96
+ message: JSON.stringify(parsed, null, 2),
97
+ };
98
+ });
99
+ },
100
+ };
101
+ }
102
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../../../../src/extras/extensions/structured-output/extension.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "structured-output",
3
+ "description": "Validates LLM output against a JSON schema via beforeResponse hook. Accepts a schema, optional metadataKey, and stripCodeFences via config.",
4
+ "enabled": true,
5
+ "priority": 50,
6
+ "configKeys": ["schema", "metadataKey", "stripCodeFences"]
7
+ }
@@ -0,0 +1,3 @@
1
+ export { default as createStructuredOutputExtension } from './extension.js';
2
+ export type { StructuredOutputConfig } from './extension.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/extras/extensions/structured-output/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,+BAA+B,EAAE,MAAM,gBAAgB,CAAC;AAC5E,YAAY,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { default as createStructuredOutputExtension } from './extension.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/extras/extensions/structured-output/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,+BAA+B,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Extension } from '../../../extension.js';
2
+ /**
3
+ * timestamp extension โ€” records start/finish ISO timestamps in turn
4
+ * metadata for observability.
5
+ *
6
+ * Sets `metadata.startedAt` in `beforeTurn` and `metadata.finishedAt`
7
+ * in `afterTurn`. No config needed โ€” self-contained.
8
+ */
9
+ declare const timestampExtension: Extension;
10
+ export default timestampExtension;
11
+ //# sourceMappingURL=extension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../../../../src/extras/extensions/timestamp/extension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;;;;;GAMG;AACH,QAAA,MAAM,kBAAkB,EAAE,SAWzB,CAAC;eAEa,kBAAkB"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * timestamp extension โ€” records start/finish ISO timestamps in turn
3
+ * metadata for observability.
4
+ *
5
+ * Sets `metadata.startedAt` in `beforeTurn` and `metadata.finishedAt`
6
+ * in `afterTurn`. No config needed โ€” self-contained.
7
+ */
8
+ const timestampExtension = {
9
+ name: 'timestamp',
10
+ priority: 0,
11
+ install(agent) {
12
+ agent.hook('beforeTurn', 'timestamp', async (ctx) => {
13
+ ctx.turn.metadata.startedAt = new Date().toISOString();
14
+ });
15
+ agent.hook('afterTurn', 'timestamp', async (ctx) => {
16
+ ctx.turn.metadata.finishedAt = new Date().toISOString();
17
+ });
18
+ },
19
+ };
20
+ export default timestampExtension;
21
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../../../../src/extras/extensions/timestamp/extension.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,kBAAkB,GAAc;IACpC,IAAI,EAAE,WAAW;IACjB,QAAQ,EAAE,CAAC;IACX,OAAO,CAAC,KAAK;QACX,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAClD,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACzD,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YACjD,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "timestamp",
3
+ "description": "Records start/finish ISO timestamps in turn metadata for observability.",
4
+ "enabled": true,
5
+ "priority": 0
6
+ }
@@ -0,0 +1,2 @@
1
+ export { default as timestampExtension } from './extension.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/extras/extensions/timestamp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { default as timestampExtension } from './extension.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/extras/extensions/timestamp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,50 @@
1
+ import type { Extension } from '../../../extension.js';
2
+ /**
3
+ * Config for the token-stats extension.
4
+ */
5
+ export interface TokenStatsConfig {
6
+ /**
7
+ * The model's maximum context window in tokens. Used to compute the
8
+ * context window usage percentage. If omitted, the percentage is
9
+ * not shown. Default: not set.
10
+ *
11
+ * For DeepSeek v4: 131072 (128K). Check your provider's docs.
12
+ */
13
+ contextWindow?: number;
14
+ /**
15
+ * Whether to use Slack italic formatting (`_text_`) for the stats
16
+ * line. Default: `true`.
17
+ */
18
+ slackItalics?: boolean;
19
+ /**
20
+ * Label for the stats line. Default: `๐Ÿ“Š`.
21
+ */
22
+ label?: string;
23
+ }
24
+ /**
25
+ * Token-stats extension โ€” appends a stats line to the agent's final
26
+ * response message.
27
+ *
28
+ * Accumulates token usage across all LLM calls in a turn (via
29
+ * `afterLLM`), then appends a summary to `turn.response.message` in
30
+ * `beforeResponse`. The stats include:
31
+ *
32
+ * - Total prompt + completion tokens
33
+ * - Cached and reasoning tokens (if reported)
34
+ * - Number of LLM calls / iterations
35
+ * - Context window usage percentage (if `contextWindow` is configured)
36
+ *
37
+ * ## Example output (Slack italics)
38
+ *
39
+ * ```
40
+ * _๐Ÿ“Š 105,445 prompt + 2,324 completion ยท 1,503 reasoning ยท 3 LLM calls ยท 82% of 128K context_
41
+ * ```
42
+ *
43
+ * ## Priority
44
+ *
45
+ * Uses priority -100 (runs late, after most extensions) so it sees
46
+ * the final response after other extensions have potentially modified
47
+ * it. The `afterLLM` accumulator runs at the same priority.
48
+ */
49
+ export default function createTokenStatsExtension(config?: TokenStatsConfig): Extension;
50
+ //# sourceMappingURL=extension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../../../../src/extras/extensions/token-stats/extension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAcD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAC/C,MAAM,CAAC,EAAE,gBAAgB,GACxB,SAAS,CAsEX"}