@researchcomputer/agents-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 (274) hide show
  1. package/README.md +60 -0
  2. package/dist/agents/messages.d.ts +29 -0
  3. package/dist/agents/messages.d.ts.map +1 -0
  4. package/dist/agents/messages.js +56 -0
  5. package/dist/agents/messages.js.map +1 -0
  6. package/dist/agents/messages.test.d.ts +2 -0
  7. package/dist/agents/messages.test.d.ts.map +1 -0
  8. package/dist/agents/messages.test.js +80 -0
  9. package/dist/agents/messages.test.js.map +1 -0
  10. package/dist/agents/subagent.d.ts +16 -0
  11. package/dist/agents/subagent.d.ts.map +1 -0
  12. package/dist/agents/subagent.js +46 -0
  13. package/dist/agents/subagent.js.map +1 -0
  14. package/dist/agents/swarm.d.ts +22 -0
  15. package/dist/agents/swarm.d.ts.map +1 -0
  16. package/dist/agents/swarm.js +140 -0
  17. package/dist/agents/swarm.js.map +1 -0
  18. package/dist/agents/tools.d.ts +6 -0
  19. package/dist/agents/tools.d.ts.map +1 -0
  20. package/dist/agents/tools.js +71 -0
  21. package/dist/agents/tools.js.map +1 -0
  22. package/dist/agents/tools.test.d.ts +2 -0
  23. package/dist/agents/tools.test.d.ts.map +1 -0
  24. package/dist/agents/tools.test.js +70 -0
  25. package/dist/agents/tools.test.js.map +1 -0
  26. package/dist/bridge/config.d.ts +21 -0
  27. package/dist/bridge/config.d.ts.map +1 -0
  28. package/dist/bridge/config.js +35 -0
  29. package/dist/bridge/config.js.map +1 -0
  30. package/dist/bridge/config.test.d.ts +2 -0
  31. package/dist/bridge/config.test.d.ts.map +1 -0
  32. package/dist/bridge/config.test.js +79 -0
  33. package/dist/bridge/config.test.js.map +1 -0
  34. package/dist/bridge/server.d.ts +3 -0
  35. package/dist/bridge/server.d.ts.map +1 -0
  36. package/dist/bridge/server.js +316 -0
  37. package/dist/bridge/server.js.map +1 -0
  38. package/dist/context/compression.d.ts +27 -0
  39. package/dist/context/compression.d.ts.map +1 -0
  40. package/dist/context/compression.js +117 -0
  41. package/dist/context/compression.js.map +1 -0
  42. package/dist/context/compression.test.d.ts +2 -0
  43. package/dist/context/compression.test.d.ts.map +1 -0
  44. package/dist/context/compression.test.js +170 -0
  45. package/dist/context/compression.test.js.map +1 -0
  46. package/dist/context/converter.d.ts +11 -0
  47. package/dist/context/converter.d.ts.map +1 -0
  48. package/dist/context/converter.js +40 -0
  49. package/dist/context/converter.js.map +1 -0
  50. package/dist/context/converter.test.d.ts +2 -0
  51. package/dist/context/converter.test.d.ts.map +1 -0
  52. package/dist/context/converter.test.js +110 -0
  53. package/dist/context/converter.test.js.map +1 -0
  54. package/dist/context/run-context.d.ts +9 -0
  55. package/dist/context/run-context.d.ts.map +1 -0
  56. package/dist/context/run-context.js +14 -0
  57. package/dist/context/run-context.js.map +1 -0
  58. package/dist/context/run-context.test.d.ts +2 -0
  59. package/dist/context/run-context.test.d.ts.map +1 -0
  60. package/dist/context/run-context.test.js +34 -0
  61. package/dist/context/run-context.test.js.map +1 -0
  62. package/dist/context/system-prompt.d.ts +24 -0
  63. package/dist/context/system-prompt.d.ts.map +1 -0
  64. package/dist/context/system-prompt.js +69 -0
  65. package/dist/context/system-prompt.js.map +1 -0
  66. package/dist/context/system-prompt.test.d.ts +2 -0
  67. package/dist/context/system-prompt.test.d.ts.map +1 -0
  68. package/dist/context/system-prompt.test.js +134 -0
  69. package/dist/context/system-prompt.test.js.map +1 -0
  70. package/dist/errors.d.ts +24 -0
  71. package/dist/errors.d.ts.map +1 -0
  72. package/dist/errors.js +47 -0
  73. package/dist/errors.js.map +1 -0
  74. package/dist/errors.test.d.ts +2 -0
  75. package/dist/errors.test.d.ts.map +1 -0
  76. package/dist/errors.test.js +68 -0
  77. package/dist/errors.test.js.map +1 -0
  78. package/dist/factory.d.ts +58 -0
  79. package/dist/factory.d.ts.map +1 -0
  80. package/dist/factory.js +282 -0
  81. package/dist/factory.js.map +1 -0
  82. package/dist/factory.test.d.ts +2 -0
  83. package/dist/factory.test.d.ts.map +1 -0
  84. package/dist/factory.test.js +63 -0
  85. package/dist/factory.test.js.map +1 -0
  86. package/dist/fork.test.d.ts +2 -0
  87. package/dist/fork.test.d.ts.map +1 -0
  88. package/dist/fork.test.js +456 -0
  89. package/dist/fork.test.js.map +1 -0
  90. package/dist/index.d.ts +29 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +32 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/mcp/client.d.ts +3 -0
  95. package/dist/mcp/client.d.ts.map +1 -0
  96. package/dist/mcp/client.js +75 -0
  97. package/dist/mcp/client.js.map +1 -0
  98. package/dist/mcp/schema-convert.d.ts +3 -0
  99. package/dist/mcp/schema-convert.d.ts.map +1 -0
  100. package/dist/mcp/schema-convert.js +73 -0
  101. package/dist/mcp/schema-convert.js.map +1 -0
  102. package/dist/mcp/schema-convert.test.d.ts +2 -0
  103. package/dist/mcp/schema-convert.test.d.ts.map +1 -0
  104. package/dist/mcp/schema-convert.test.js +95 -0
  105. package/dist/mcp/schema-convert.test.js.map +1 -0
  106. package/dist/mcp/tools.d.ts +14 -0
  107. package/dist/mcp/tools.d.ts.map +1 -0
  108. package/dist/mcp/tools.js +23 -0
  109. package/dist/mcp/tools.js.map +1 -0
  110. package/dist/mcp/tools.test.d.ts +2 -0
  111. package/dist/mcp/tools.test.d.ts.map +1 -0
  112. package/dist/mcp/tools.test.js +45 -0
  113. package/dist/mcp/tools.test.js.map +1 -0
  114. package/dist/memory/memory.d.ts +3 -0
  115. package/dist/memory/memory.d.ts.map +1 -0
  116. package/dist/memory/memory.js +130 -0
  117. package/dist/memory/memory.js.map +1 -0
  118. package/dist/memory/memory.test.d.ts +2 -0
  119. package/dist/memory/memory.test.d.ts.map +1 -0
  120. package/dist/memory/memory.test.js +94 -0
  121. package/dist/memory/memory.test.js.map +1 -0
  122. package/dist/middleware/hooks.d.ts +18 -0
  123. package/dist/middleware/hooks.d.ts.map +1 -0
  124. package/dist/middleware/hooks.js +71 -0
  125. package/dist/middleware/hooks.js.map +1 -0
  126. package/dist/middleware/hooks.test.d.ts +2 -0
  127. package/dist/middleware/hooks.test.d.ts.map +1 -0
  128. package/dist/middleware/hooks.test.js +172 -0
  129. package/dist/middleware/hooks.test.js.map +1 -0
  130. package/dist/middleware/index.d.ts +7 -0
  131. package/dist/middleware/index.d.ts.map +1 -0
  132. package/dist/middleware/index.js +5 -0
  133. package/dist/middleware/index.js.map +1 -0
  134. package/dist/middleware/permission-middleware.d.ts +11 -0
  135. package/dist/middleware/permission-middleware.d.ts.map +1 -0
  136. package/dist/middleware/permission-middleware.js +56 -0
  137. package/dist/middleware/permission-middleware.js.map +1 -0
  138. package/dist/middleware/permission-middleware.test.d.ts +2 -0
  139. package/dist/middleware/permission-middleware.test.d.ts.map +1 -0
  140. package/dist/middleware/permission-middleware.test.js +170 -0
  141. package/dist/middleware/permission-middleware.test.js.map +1 -0
  142. package/dist/middleware/permissions.d.ts +14 -0
  143. package/dist/middleware/permissions.d.ts.map +1 -0
  144. package/dist/middleware/permissions.js +118 -0
  145. package/dist/middleware/permissions.js.map +1 -0
  146. package/dist/middleware/permissions.test.d.ts +2 -0
  147. package/dist/middleware/permissions.test.d.ts.map +1 -0
  148. package/dist/middleware/permissions.test.js +187 -0
  149. package/dist/middleware/permissions.test.js.map +1 -0
  150. package/dist/middleware/pipeline.d.ts +13 -0
  151. package/dist/middleware/pipeline.d.ts.map +1 -0
  152. package/dist/middleware/pipeline.js +28 -0
  153. package/dist/middleware/pipeline.js.map +1 -0
  154. package/dist/middleware/pipeline.test.d.ts +2 -0
  155. package/dist/middleware/pipeline.test.d.ts.map +1 -0
  156. package/dist/middleware/pipeline.test.js +189 -0
  157. package/dist/middleware/pipeline.test.js.map +1 -0
  158. package/dist/observability/cost-tracker.d.ts +3 -0
  159. package/dist/observability/cost-tracker.d.ts.map +1 -0
  160. package/dist/observability/cost-tracker.js +26 -0
  161. package/dist/observability/cost-tracker.js.map +1 -0
  162. package/dist/observability/cost-tracker.test.d.ts +2 -0
  163. package/dist/observability/cost-tracker.test.d.ts.map +1 -0
  164. package/dist/observability/cost-tracker.test.js +49 -0
  165. package/dist/observability/cost-tracker.test.js.map +1 -0
  166. package/dist/observability/trace.d.ts +2 -0
  167. package/dist/observability/trace.d.ts.map +1 -0
  168. package/dist/observability/trace.js +5 -0
  169. package/dist/observability/trace.js.map +1 -0
  170. package/dist/session/session.d.ts +3 -0
  171. package/dist/session/session.d.ts.map +1 -0
  172. package/dist/session/session.js +62 -0
  173. package/dist/session/session.js.map +1 -0
  174. package/dist/session/session.test.d.ts +2 -0
  175. package/dist/session/session.test.d.ts.map +1 -0
  176. package/dist/session/session.test.js +84 -0
  177. package/dist/session/session.test.js.map +1 -0
  178. package/dist/skills.d.ts +14 -0
  179. package/dist/skills.d.ts.map +1 -0
  180. package/dist/skills.js +31 -0
  181. package/dist/skills.js.map +1 -0
  182. package/dist/skills.test.d.ts +2 -0
  183. package/dist/skills.test.d.ts.map +1 -0
  184. package/dist/skills.test.js +61 -0
  185. package/dist/skills.test.js.map +1 -0
  186. package/dist/tools/ask-user.d.ts +10 -0
  187. package/dist/tools/ask-user.d.ts.map +1 -0
  188. package/dist/tools/ask-user.js +27 -0
  189. package/dist/tools/ask-user.js.map +1 -0
  190. package/dist/tools/bash.d.ts +11 -0
  191. package/dist/tools/bash.d.ts.map +1 -0
  192. package/dist/tools/bash.js +54 -0
  193. package/dist/tools/bash.js.map +1 -0
  194. package/dist/tools/bash.test.d.ts +2 -0
  195. package/dist/tools/bash.test.d.ts.map +1 -0
  196. package/dist/tools/bash.test.js +63 -0
  197. package/dist/tools/bash.test.js.map +1 -0
  198. package/dist/tools/edit.d.ts +10 -0
  199. package/dist/tools/edit.d.ts.map +1 -0
  200. package/dist/tools/edit.js +65 -0
  201. package/dist/tools/edit.js.map +1 -0
  202. package/dist/tools/edit.test.d.ts +2 -0
  203. package/dist/tools/edit.test.d.ts.map +1 -0
  204. package/dist/tools/edit.test.js +60 -0
  205. package/dist/tools/edit.test.js.map +1 -0
  206. package/dist/tools/glob.d.ts +8 -0
  207. package/dist/tools/glob.d.ts.map +1 -0
  208. package/dist/tools/glob.js +43 -0
  209. package/dist/tools/glob.js.map +1 -0
  210. package/dist/tools/glob.test.d.ts +2 -0
  211. package/dist/tools/glob.test.d.ts.map +1 -0
  212. package/dist/tools/glob.test.js +54 -0
  213. package/dist/tools/glob.test.js.map +1 -0
  214. package/dist/tools/grep.d.ts +9 -0
  215. package/dist/tools/grep.d.ts.map +1 -0
  216. package/dist/tools/grep.js +74 -0
  217. package/dist/tools/grep.js.map +1 -0
  218. package/dist/tools/grep.test.d.ts +2 -0
  219. package/dist/tools/grep.test.d.ts.map +1 -0
  220. package/dist/tools/grep.test.js +48 -0
  221. package/dist/tools/grep.test.js.map +1 -0
  222. package/dist/tools/index.d.ts +25 -0
  223. package/dist/tools/index.d.ts.map +1 -0
  224. package/dist/tools/index.js +40 -0
  225. package/dist/tools/index.js.map +1 -0
  226. package/dist/tools/index.test.d.ts +2 -0
  227. package/dist/tools/index.test.d.ts.map +1 -0
  228. package/dist/tools/index.test.js +102 -0
  229. package/dist/tools/index.test.js.map +1 -0
  230. package/dist/tools/notebook-edit.d.ts +9 -0
  231. package/dist/tools/notebook-edit.d.ts.map +1 -0
  232. package/dist/tools/notebook-edit.js +55 -0
  233. package/dist/tools/notebook-edit.js.map +1 -0
  234. package/dist/tools/read.d.ts +9 -0
  235. package/dist/tools/read.d.ts.map +1 -0
  236. package/dist/tools/read.js +48 -0
  237. package/dist/tools/read.js.map +1 -0
  238. package/dist/tools/read.test.d.ts +2 -0
  239. package/dist/tools/read.test.d.ts.map +1 -0
  240. package/dist/tools/read.test.js +68 -0
  241. package/dist/tools/read.test.js.map +1 -0
  242. package/dist/tools/util.d.ts +19 -0
  243. package/dist/tools/util.d.ts.map +1 -0
  244. package/dist/tools/util.js +44 -0
  245. package/dist/tools/util.js.map +1 -0
  246. package/dist/tools/util.test.d.ts +2 -0
  247. package/dist/tools/util.test.d.ts.map +1 -0
  248. package/dist/tools/util.test.js +75 -0
  249. package/dist/tools/util.test.js.map +1 -0
  250. package/dist/tools/web-fetch.d.ts +7 -0
  251. package/dist/tools/web-fetch.d.ts.map +1 -0
  252. package/dist/tools/web-fetch.js +35 -0
  253. package/dist/tools/web-fetch.js.map +1 -0
  254. package/dist/tools/web-search.d.ts +7 -0
  255. package/dist/tools/web-search.d.ts.map +1 -0
  256. package/dist/tools/web-search.js +20 -0
  257. package/dist/tools/web-search.js.map +1 -0
  258. package/dist/tools/write.d.ts +8 -0
  259. package/dist/tools/write.d.ts.map +1 -0
  260. package/dist/tools/write.js +33 -0
  261. package/dist/tools/write.js.map +1 -0
  262. package/dist/tools/write.test.d.ts +2 -0
  263. package/dist/tools/write.test.d.ts.map +1 -0
  264. package/dist/tools/write.test.js +49 -0
  265. package/dist/tools/write.test.js.map +1 -0
  266. package/dist/types.d.ts +257 -0
  267. package/dist/types.d.ts.map +1 -0
  268. package/dist/types.js +2 -0
  269. package/dist/types.js.map +1 -0
  270. package/dist/types.test.d.ts +2 -0
  271. package/dist/types.test.d.ts.map +1 -0
  272. package/dist/types.test.js +69 -0
  273. package/dist/types.test.js.map +1 -0
  274. package/package.json +51 -0
@@ -0,0 +1,70 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { createSwarmTools } from './tools.js';
3
+ function createMockSwarmManager() {
4
+ return {
5
+ createTeam: vi.fn(),
6
+ spawnTeammate: vi.fn().mockResolvedValue({ name: 'worker', taskId: 'task-1', status: 'running', budget: { maxTurns: 20 } }),
7
+ sendMessage: vi.fn(),
8
+ removeTeammate: vi.fn().mockResolvedValue(undefined),
9
+ destroyTeam: vi.fn().mockResolvedValue(undefined),
10
+ getTeam: vi.fn(),
11
+ };
12
+ }
13
+ describe('createSwarmTools', () => {
14
+ it('returns three tools', () => {
15
+ const swarm = createMockSwarmManager();
16
+ const tools = createSwarmTools('test-team', swarm);
17
+ expect(tools).toHaveLength(3);
18
+ });
19
+ it('has SpawnTeammate tool', () => {
20
+ const swarm = createMockSwarmManager();
21
+ const tools = createSwarmTools('test-team', swarm);
22
+ const spawn = tools.find(t => t.name === 'SpawnTeammate');
23
+ expect(spawn).toBeDefined();
24
+ expect(spawn.description).toContain('Spawn');
25
+ expect(spawn.capabilities).toEqual([]);
26
+ });
27
+ it('has SendMessage tool', () => {
28
+ const swarm = createMockSwarmManager();
29
+ const tools = createSwarmTools('test-team', swarm);
30
+ const send = tools.find(t => t.name === 'SendMessage');
31
+ expect(send).toBeDefined();
32
+ expect(send.description).toContain('message');
33
+ });
34
+ it('has DismissTeammate tool', () => {
35
+ const swarm = createMockSwarmManager();
36
+ const tools = createSwarmTools('test-team', swarm);
37
+ const dismiss = tools.find(t => t.name === 'DismissTeammate');
38
+ expect(dismiss).toBeDefined();
39
+ expect(dismiss.description).toContain('Remove');
40
+ });
41
+ it('SpawnTeammate calls swarm.spawnTeammate', async () => {
42
+ const swarm = createMockSwarmManager();
43
+ const tools = createSwarmTools('test-team', swarm);
44
+ const spawn = tools.find(t => t.name === 'SpawnTeammate');
45
+ const result = await spawn.execute('call-1', { name: 'worker', prompt: 'do stuff' });
46
+ expect(swarm.spawnTeammate).toHaveBeenCalledWith('test-team', expect.objectContaining({
47
+ name: 'worker',
48
+ prompt: 'do stuff',
49
+ }));
50
+ expect(result.content[0]).toHaveProperty('text');
51
+ });
52
+ it('SendMessage calls swarm.sendMessage', async () => {
53
+ const swarm = createMockSwarmManager();
54
+ const tools = createSwarmTools('test-team', swarm);
55
+ const send = tools.find(t => t.name === 'SendMessage');
56
+ await send.execute('call-2', { to: 'worker', message: 'hello' });
57
+ expect(swarm.sendMessage).toHaveBeenCalledWith('test-team', 'worker', expect.objectContaining({
58
+ role: 'user',
59
+ content: 'hello',
60
+ }));
61
+ });
62
+ it('DismissTeammate calls swarm.removeTeammate', async () => {
63
+ const swarm = createMockSwarmManager();
64
+ const tools = createSwarmTools('test-team', swarm);
65
+ const dismiss = tools.find(t => t.name === 'DismissTeammate');
66
+ await dismiss.execute('call-3', { name: 'worker' });
67
+ expect(swarm.removeTeammate).toHaveBeenCalledWith('test-team', 'worker');
68
+ });
69
+ });
70
+ //# sourceMappingURL=tools.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.test.js","sourceRoot":"","sources":["../../src/agents/tools.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { type Model } from '@mariozechner/pi-ai';
2
+ export interface BridgeConfig {
3
+ port: number;
4
+ concurrency: number;
5
+ jobsDir: string;
6
+ apiKey: string;
7
+ idleTimeoutMs: number;
8
+ modelEndpoint: string;
9
+ modelId: string;
10
+ modelProvider: string;
11
+ modelApiStyle: 'chat' | 'responses';
12
+ }
13
+ export interface ModelOverride {
14
+ endpoint?: string;
15
+ modelId?: string;
16
+ apiKey?: string;
17
+ apiStyle?: 'chat' | 'responses';
18
+ }
19
+ export declare function parseBridgeConfig(env: NodeJS.ProcessEnv): BridgeConfig;
20
+ export declare function buildBridgeModel(config: Pick<BridgeConfig, 'modelEndpoint' | 'modelId' | 'modelProvider' | 'modelApiStyle'>, override?: ModelOverride): Model<any>;
21
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/bridge/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,WAAW,CAAC;CACrC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;CACjC;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,YAAY,CAYtE;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,SAAS,GAAG,eAAe,GAAG,eAAe,CAAC,EAC3F,QAAQ,GAAE,aAAkB,GAC3B,KAAK,CAAC,GAAG,CAAC,CAqBZ"}
@@ -0,0 +1,35 @@
1
+ import { getModel } from '@mariozechner/pi-ai';
2
+ export function parseBridgeConfig(env) {
3
+ return {
4
+ port: Number.parseInt(env.PORT ?? '3000', 10),
5
+ concurrency: Number.parseInt(env.CONCURRENCY ?? '5', 10),
6
+ jobsDir: env.JOBS_DIR ?? '/tmp/rc-agent-jobs',
7
+ apiKey: env.API_KEY ?? '',
8
+ idleTimeoutMs: Number.parseInt(env.IDLE_TIMEOUT_MS ?? String(5 * 60 * 1000), 10),
9
+ modelEndpoint: env.MODEL_ENDPOINT ?? '',
10
+ modelId: env.MODEL_ID ?? 'gpt-4o-mini',
11
+ modelProvider: env.MODEL_PROVIDER ?? 'openai',
12
+ modelApiStyle: (env.MODEL_API_STYLE ?? 'chat'),
13
+ };
14
+ }
15
+ export function buildBridgeModel(config, override = {}) {
16
+ const endpoint = override.endpoint ?? config.modelEndpoint;
17
+ const modelId = override.modelId ?? config.modelId;
18
+ const apiStyle = override.apiStyle ?? config.modelApiStyle;
19
+ if (endpoint) {
20
+ return {
21
+ id: modelId,
22
+ name: modelId,
23
+ api: apiStyle === 'responses' ? 'openai-responses' : 'openai-completions',
24
+ provider: 'openai-compatible',
25
+ baseUrl: endpoint,
26
+ reasoning: false,
27
+ input: ['text', 'image'],
28
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
29
+ contextWindow: 128_000,
30
+ maxTokens: 32_768,
31
+ };
32
+ }
33
+ return getModel(config.modelProvider, modelId);
34
+ }
35
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/bridge/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAc,MAAM,qBAAqB,CAAC;AAqB3D,MAAM,UAAU,iBAAiB,CAAC,GAAsB;IACtD,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC;QAC7C,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,EAAE,EAAE,CAAC;QACxD,OAAO,EAAE,GAAG,CAAC,QAAQ,IAAI,oBAAoB;QAC7C,MAAM,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE;QACzB,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,IAAI,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAChF,aAAa,EAAE,GAAG,CAAC,cAAc,IAAI,EAAE;QACvC,OAAO,EAAE,GAAG,CAAC,QAAQ,IAAI,aAAa;QACtC,aAAa,EAAE,GAAG,CAAC,cAAc,IAAI,QAAQ;QAC7C,aAAa,EAAE,CAAC,GAAG,CAAC,eAAe,IAAI,MAAM,CAAyB;KACvE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,MAA2F,EAC3F,WAA0B,EAAE;IAE5B,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC;IAC3D,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC;IACnD,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC;IAE3D,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,OAAO;YACX,IAAI,EAAE,OAAO;YACb,GAAG,EAAE,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,oBAAoB;YACzE,QAAQ,EAAE,mBAAmB;YAC7B,OAAO,EAAE,QAAQ;YACjB,SAAS,EAAE,KAAK;YAChB,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;YACxB,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;YAC1D,aAAa,EAAE,OAAO;YACtB,SAAS,EAAE,MAAM;SAClB,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC,MAAM,CAAC,aAAoB,EAAE,OAAc,CAAC,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../src/bridge/config.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,79 @@
1
+ import { describe, expect, it, vi, beforeEach } from 'vitest';
2
+ import { getModel } from '@mariozechner/pi-ai';
3
+ import { buildBridgeModel, parseBridgeConfig } from './config.js';
4
+ vi.mock('@mariozechner/pi-ai', () => ({
5
+ getModel: vi.fn(),
6
+ }));
7
+ describe('parseBridgeConfig', () => {
8
+ it('uses the documented defaults', () => {
9
+ expect(parseBridgeConfig({})).toEqual({
10
+ port: 3000,
11
+ concurrency: 5,
12
+ jobsDir: '/tmp/rc-agent-jobs',
13
+ apiKey: '',
14
+ idleTimeoutMs: 5 * 60 * 1000,
15
+ modelEndpoint: '',
16
+ modelId: 'gpt-4o-mini',
17
+ modelProvider: 'openai',
18
+ modelApiStyle: 'chat',
19
+ });
20
+ });
21
+ it('reads environment overrides', () => {
22
+ expect(parseBridgeConfig({
23
+ PORT: '4000',
24
+ CONCURRENCY: '9',
25
+ JOBS_DIR: '/work/jobs',
26
+ API_KEY: 'secret',
27
+ IDLE_TIMEOUT_MS: '1234',
28
+ MODEL_ENDPOINT: 'http://localhost:11434/v1',
29
+ MODEL_ID: 'llama3.2',
30
+ MODEL_PROVIDER: 'anthropic',
31
+ MODEL_API_STYLE: 'responses',
32
+ })).toEqual({
33
+ port: 4000,
34
+ concurrency: 9,
35
+ jobsDir: '/work/jobs',
36
+ apiKey: 'secret',
37
+ idleTimeoutMs: 1234,
38
+ modelEndpoint: 'http://localhost:11434/v1',
39
+ modelId: 'llama3.2',
40
+ modelProvider: 'anthropic',
41
+ modelApiStyle: 'responses',
42
+ });
43
+ });
44
+ });
45
+ describe('buildBridgeModel', () => {
46
+ const getModelMock = vi.mocked(getModel);
47
+ beforeEach(() => {
48
+ getModelMock.mockReset();
49
+ });
50
+ it('builds an openai-compatible model when an endpoint is set', () => {
51
+ const model = buildBridgeModel({
52
+ modelEndpoint: 'http://localhost:11434/v1',
53
+ modelId: 'llama3.2',
54
+ modelProvider: 'openai',
55
+ modelApiStyle: 'responses',
56
+ });
57
+ expect(model).toMatchObject({
58
+ id: 'llama3.2',
59
+ name: 'llama3.2',
60
+ api: 'openai-responses',
61
+ provider: 'openai-compatible',
62
+ baseUrl: 'http://localhost:11434/v1',
63
+ });
64
+ expect(getModelMock).not.toHaveBeenCalled();
65
+ });
66
+ it('falls back to the configured provider model when no endpoint is set', () => {
67
+ const providerModel = { id: 'claude-sonnet-4-5' };
68
+ getModelMock.mockReturnValue(providerModel);
69
+ const model = buildBridgeModel({
70
+ modelEndpoint: '',
71
+ modelId: 'claude-sonnet-4-5',
72
+ modelProvider: 'anthropic',
73
+ modelApiStyle: 'chat',
74
+ });
75
+ expect(getModelMock).toHaveBeenCalledWith('anthropic', 'claude-sonnet-4-5');
76
+ expect(model).toBe(providerModel);
77
+ });
78
+ });
79
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/bridge/config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/bridge/server.ts"],"names":[],"mappings":""}
@@ -0,0 +1,316 @@
1
+ #!/usr/bin/env node
2
+ import http from 'node:http';
3
+ import crypto from 'node:crypto';
4
+ import fs from 'node:fs/promises';
5
+ import path from 'node:path';
6
+ import PQueue from 'p-queue';
7
+ import { createCodingAgent } from '../factory.js';
8
+ import { buildBridgeModel, parseBridgeConfig } from './config.js';
9
+ const config = parseBridgeConfig(process.env);
10
+ const PORT = config.port;
11
+ const CONCURRENCY = config.concurrency;
12
+ const JOBS_DIR = config.jobsDir;
13
+ const API_KEY = config.apiKey;
14
+ // Idle timeout: dispose agent and mark job 'done' after this many ms of inactivity
15
+ const IDLE_TIMEOUT = config.idleTimeoutMs;
16
+ const jobs = new Map();
17
+ const queue = new PQueue({ concurrency: CONCURRENCY });
18
+ // ---------------------------------------------------------------------------
19
+ // SSE helpers
20
+ // ---------------------------------------------------------------------------
21
+ function sseWrite(res, event) {
22
+ res.write(`id: ${event.id}\ndata: ${JSON.stringify(event)}\n\n`);
23
+ }
24
+ let globalEventId = 0;
25
+ function broadcast(job, event) {
26
+ const sseEvent = { ...event, id: ++globalEventId };
27
+ job.eventBuffer.push(sseEvent);
28
+ for (const client of job.clients) {
29
+ sseWrite(client, sseEvent);
30
+ }
31
+ }
32
+ function closeClients(job) {
33
+ for (const client of job.clients) {
34
+ client.end();
35
+ }
36
+ job.clients.clear();
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // Idle timeout
40
+ // ---------------------------------------------------------------------------
41
+ function clearIdleTimer(job) {
42
+ if (job.idleTimer) {
43
+ clearTimeout(job.idleTimer);
44
+ job.idleTimer = undefined;
45
+ }
46
+ }
47
+ function setIdleTimer(job) {
48
+ clearIdleTimer(job);
49
+ job.idleTimer = setTimeout(async () => {
50
+ if (job.status !== 'idle')
51
+ return;
52
+ broadcast(job, { type: 'status', data: { status: 'done', reason: 'idle_timeout' } });
53
+ // Unblock the waiting runJob promise so the PQueue slot is freed
54
+ job.replyResolve?.(undefined);
55
+ job.replyResolve = undefined;
56
+ await disposeJob(job, 'done');
57
+ }, IDLE_TIMEOUT);
58
+ }
59
+ async function disposeJob(job, finalStatus) {
60
+ clearIdleTimer(job);
61
+ job.status = finalStatus;
62
+ if (job.agent) {
63
+ try {
64
+ job.agent.agent.abort();
65
+ if (typeof job.agent.agent.waitForIdle === 'function') {
66
+ await job.agent.agent.waitForIdle();
67
+ }
68
+ }
69
+ catch { /* non-critical */ }
70
+ await job.agent.dispose();
71
+ job.agent = undefined;
72
+ }
73
+ closeClients(job);
74
+ }
75
+ // ---------------------------------------------------------------------------
76
+ // Agent runner
77
+ // ---------------------------------------------------------------------------
78
+ async function runJob(job) {
79
+ // Guard: job may have been cancelled while queued
80
+ if (job.status === 'cancelled')
81
+ return;
82
+ const workDir = path.join(JOBS_DIR, job.id);
83
+ await fs.mkdir(workDir, { recursive: true });
84
+ job.status = 'running';
85
+ broadcast(job, { type: 'status', data: { status: 'running' } });
86
+ let codingAgent;
87
+ try {
88
+ const model = buildBridgeModel(config, job.modelOverride);
89
+ codingAgent = await createCodingAgent({
90
+ model,
91
+ cwd: workDir,
92
+ sessionId: job.id,
93
+ sessionDir: workDir,
94
+ memoryDir: workDir,
95
+ permissionMode: 'allowAll',
96
+ toolExecution: 'sequential',
97
+ enableMemory: false,
98
+ getApiKey: async () => job.modelOverride.apiKey ?? API_KEY,
99
+ onQuestion: async (question) => {
100
+ broadcast(job, { type: 'question', data: { question } });
101
+ return '(no interactive input available)';
102
+ },
103
+ });
104
+ }
105
+ catch (err) {
106
+ const message = err instanceof Error ? err.message : String(err);
107
+ job.status = 'error';
108
+ job.error = message;
109
+ broadcast(job, { type: 'status', data: { status: 'error', error: message } });
110
+ closeClients(job);
111
+ return;
112
+ }
113
+ job.agent = codingAgent;
114
+ // Forward all agent events to SSE clients
115
+ codingAgent.agent.subscribe((event) => {
116
+ broadcast(job, { type: 'agent_event', data: serializeEvent(event) });
117
+ });
118
+ // Run turns in a loop until the job is cancelled/errored or no reply arrives
119
+ let nextMessage = job.prompt;
120
+ while (nextMessage !== undefined) {
121
+ const messageToSend = nextMessage;
122
+ nextMessage = undefined;
123
+ job.status = 'running';
124
+ broadcast(job, { type: 'status', data: { status: 'running' } });
125
+ try {
126
+ await codingAgent.prompt(messageToSend);
127
+ }
128
+ catch (err) {
129
+ const message = err instanceof Error ? err.message : String(err);
130
+ const isCancelled = job.status === 'cancelled';
131
+ if (isCancelled) {
132
+ broadcast(job, { type: 'status', data: { status: 'cancelled' } });
133
+ }
134
+ else {
135
+ job.error = message;
136
+ broadcast(job, { type: 'status', data: { status: 'error', error: message } });
137
+ }
138
+ await disposeJob(job, isCancelled ? 'cancelled' : 'error');
139
+ return;
140
+ }
141
+ if (job.status === 'cancelled') {
142
+ broadcast(job, { type: 'status', data: { status: 'cancelled' } });
143
+ await disposeJob(job, 'cancelled');
144
+ return;
145
+ }
146
+ // Turn completed — go idle and wait for a reply or timeout
147
+ job.status = 'idle';
148
+ broadcast(job, { type: 'status', data: { status: 'idle' } });
149
+ setIdleTimer(job);
150
+ // Wait for either a reply message or cancellation
151
+ nextMessage = await new Promise((resolve) => {
152
+ job.replyResolve = resolve;
153
+ });
154
+ job.replyResolve = undefined;
155
+ if (nextMessage === undefined) {
156
+ // Resolved without a reply (timeout or cancel already handled above)
157
+ return;
158
+ }
159
+ clearIdleTimer(job);
160
+ }
161
+ }
162
+ // Strip non-serialisable fields from agent events before sending over the wire
163
+ function serializeEvent(event) {
164
+ return JSON.parse(JSON.stringify(event, (_key, value) => {
165
+ if (typeof value === 'function')
166
+ return undefined;
167
+ if (value instanceof AbortController)
168
+ return undefined;
169
+ return value;
170
+ }));
171
+ }
172
+ // ---------------------------------------------------------------------------
173
+ // HTTP router
174
+ // ---------------------------------------------------------------------------
175
+ function parseBody(req) {
176
+ return new Promise((resolve, reject) => {
177
+ let body = '';
178
+ req.on('data', (chunk) => { body += chunk; });
179
+ req.on('end', () => {
180
+ try {
181
+ resolve(JSON.parse(body || '{}'));
182
+ }
183
+ catch {
184
+ reject(new Error('Invalid JSON'));
185
+ }
186
+ });
187
+ req.on('error', reject);
188
+ });
189
+ }
190
+ function send(res, status, body) {
191
+ const payload = JSON.stringify(body);
192
+ res.writeHead(status, { 'Content-Type': 'application/json' });
193
+ res.end(payload);
194
+ }
195
+ const server = http.createServer(async (req, res) => {
196
+ const url = new URL(req.url ?? '/', `http://localhost:${PORT}`);
197
+ const segments = url.pathname.split('/').filter(Boolean);
198
+ // POST /run — enqueue a new job
199
+ if (req.method === 'POST' && url.pathname === '/run') {
200
+ let body;
201
+ try {
202
+ body = await parseBody(req);
203
+ }
204
+ catch {
205
+ return send(res, 400, { error: 'Invalid JSON' });
206
+ }
207
+ const { prompt, endpoint, modelId, apiKey, apiStyle } = body;
208
+ if (!prompt || typeof prompt !== 'string') {
209
+ return send(res, 400, { error: '"prompt" (string) is required' });
210
+ }
211
+ const jobId = crypto.randomUUID();
212
+ const job = {
213
+ id: jobId,
214
+ status: 'queued',
215
+ prompt,
216
+ modelOverride: { endpoint, modelId, apiKey, apiStyle },
217
+ eventBuffer: [],
218
+ clients: new Set(),
219
+ createdAt: Date.now(),
220
+ };
221
+ jobs.set(jobId, job);
222
+ queue.add(() => runJob(job));
223
+ return send(res, 202, { jobId });
224
+ }
225
+ // POST /jobs/:id/reply — send a follow-up message to an idle job
226
+ if (req.method === 'POST' && segments[0] === 'jobs' && segments[1] && segments[2] === 'reply') {
227
+ const job = jobs.get(segments[1]);
228
+ if (!job)
229
+ return send(res, 404, { error: 'Job not found' });
230
+ if (job.status !== 'idle') {
231
+ return send(res, 409, { error: `Job is ${job.status}, not idle` });
232
+ }
233
+ let body;
234
+ try {
235
+ body = await parseBody(req);
236
+ }
237
+ catch {
238
+ return send(res, 400, { error: 'Invalid JSON' });
239
+ }
240
+ const { message } = body;
241
+ if (!message || typeof message !== 'string') {
242
+ return send(res, 400, { error: '"message" (string) is required' });
243
+ }
244
+ clearIdleTimer(job);
245
+ job.replyResolve?.(message);
246
+ return send(res, 202, { jobId: job.id, status: 'running' });
247
+ }
248
+ // GET /jobs/:id — status
249
+ if (req.method === 'GET' && segments[0] === 'jobs' && segments[1] && !segments[2]) {
250
+ const job = jobs.get(segments[1]);
251
+ if (!job)
252
+ return send(res, 404, { error: 'Job not found' });
253
+ return send(res, 200, {
254
+ jobId: job.id,
255
+ status: job.status,
256
+ error: job.error,
257
+ eventCount: job.eventBuffer.length,
258
+ createdAt: job.createdAt,
259
+ });
260
+ }
261
+ // GET /jobs/:id/events — SSE stream
262
+ if (req.method === 'GET' && segments[0] === 'jobs' && segments[1] && segments[2] === 'events') {
263
+ const job = jobs.get(segments[1]);
264
+ if (!job)
265
+ return send(res, 404, { error: 'Job not found' });
266
+ res.writeHead(200, {
267
+ 'Content-Type': 'text/event-stream',
268
+ 'Cache-Control': 'no-cache',
269
+ 'Connection': 'keep-alive',
270
+ 'X-Accel-Buffering': 'no',
271
+ });
272
+ // Replay buffered events, skipping any the client has already seen
273
+ const lastEventId = parseInt(req.headers['last-event-id'], 10) || 0;
274
+ for (const event of job.eventBuffer) {
275
+ if (event.id > lastEventId) {
276
+ sseWrite(res, event);
277
+ }
278
+ }
279
+ // Already terminal — close immediately
280
+ if (job.status === 'done' || job.status === 'error' || job.status === 'cancelled') {
281
+ return res.end();
282
+ }
283
+ job.clients.add(res);
284
+ req.on('close', () => { job.clients.delete(res); });
285
+ return;
286
+ }
287
+ // DELETE /jobs/:id — cancel
288
+ if (req.method === 'DELETE' && segments[0] === 'jobs' && segments[1]) {
289
+ const job = jobs.get(segments[1]);
290
+ if (!job)
291
+ return send(res, 404, { error: 'Job not found' });
292
+ if (job.status === 'done' || job.status === 'error' || job.status === 'cancelled') {
293
+ return send(res, 409, { error: `Job already ${job.status}` });
294
+ }
295
+ // If idle, unblock the waiting promise before aborting
296
+ job.replyResolve?.(undefined);
297
+ job.status = 'cancelled';
298
+ job.agent?.agent.abort();
299
+ broadcast(job, { type: 'status', data: { status: 'cancelled' } });
300
+ await disposeJob(job, 'cancelled');
301
+ return send(res, 200, { jobId: job.id, status: 'cancelled' });
302
+ }
303
+ send(res, 404, { error: 'Not found' });
304
+ });
305
+ // ---------------------------------------------------------------------------
306
+ // Start
307
+ // ---------------------------------------------------------------------------
308
+ await fs.mkdir(JOBS_DIR, { recursive: true });
309
+ server.listen(PORT, () => {
310
+ console.log(`rc-agents bridge listening on http://localhost:${PORT}`);
311
+ console.log(` concurrency: ${CONCURRENCY}`);
312
+ console.log(` idle timeout: ${IDLE_TIMEOUT / 1000}s`);
313
+ console.log(` model: ${config.modelEndpoint ? `${config.modelEndpoint} / ${config.modelId}` : `${config.modelProvider}/${config.modelId}`}`);
314
+ console.log(` jobs dir: ${JOBS_DIR}`);
315
+ });
316
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/bridge/server.ts"],"names":[],"mappings":";AACA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAsB,MAAM,aAAa,CAAC;AAEtF,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;AACzB,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;AACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC;AAChC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;AAC9B,mFAAmF;AACnF,MAAM,YAAY,GAAG,MAAM,CAAC,aAAa,CAAC;AAkC1C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAe,CAAC;AACpC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;AAEvD,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAC9E,SAAS,QAAQ,CAAC,GAAwB,EAAE,KAAe;IACzD,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,EAAE,WAAW,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACnE,CAAC;AAED,IAAI,aAAa,GAAG,CAAC,CAAC;AAEtB,SAAS,SAAS,CAAC,GAAQ,EAAE,KAA2B;IACtD,MAAM,QAAQ,GAAa,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC;IAC7D,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/B,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QACjC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,GAAQ;IAC5B,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,EAAE,CAAC;IACf,CAAC;IACD,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;AACtB,CAAC;AAED,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAC9E,SAAS,cAAc,CAAC,GAAQ;IAC9B,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;QAClB,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC5B,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,GAAQ;IAC5B,cAAc,CAAC,GAAG,CAAC,CAAC;IACpB,GAAG,CAAC,SAAS,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE;QACpC,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO;QAClC,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC;QACrF,iEAAiE;QACjE,GAAG,CAAC,YAAY,EAAE,CAAC,SAAgB,CAAC,CAAC;QACrC,GAAG,CAAC,YAAY,GAAG,SAAS,CAAC;QAC7B,MAAM,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAChC,CAAC,EAAE,YAAY,CAAC,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,GAAQ,EAAE,WAA2C;IAC7E,cAAc,CAAC,GAAG,CAAC,CAAC;IACpB,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC;IACzB,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QACd,IAAI,CAAC;YACH,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACxB,IAAI,OAAQ,GAAG,CAAC,KAAK,CAAC,KAAa,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;gBAC/D,MAAO,GAAG,CAAC,KAAK,CAAC,KAAa,CAAC,WAAW,EAAE,CAAC;YAC/C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;QAC9B,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC1B,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC;IACxB,CAAC;IACD,YAAY,CAAC,GAAG,CAAC,CAAC;AACpB,CAAC;AAED,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAC9E,KAAK,UAAU,MAAM,CAAC,GAAQ;IAC5B,kDAAkD;IAClD,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO;IAEvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5C,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;IACvB,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;IAEhE,IAAI,WAA0D,CAAC;IAC/D,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;QAC1D,WAAW,GAAG,MAAM,iBAAiB,CAAC;YACpC,KAAK;YACL,GAAG,EAAE,OAAO;YACZ,SAAS,EAAE,GAAG,CAAC,EAAE;YACjB,UAAU,EAAE,OAAO;YACnB,SAAS,EAAE,OAAO;YAClB,cAAc,EAAE,UAAU;YAC1B,aAAa,EAAE,YAAY;YAC3B,YAAY,EAAE,KAAK;YACnB,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,IAAI,OAAO;YAC1D,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;gBAC7B,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACzD,OAAO,kCAAkC,CAAC;YAC5C,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC;QACrB,GAAG,CAAC,KAAK,GAAG,OAAO,CAAC;QACpB,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QAC9E,YAAY,CAAC,GAAG,CAAC,CAAC;QAClB,OAAO;IACT,CAAC;IAED,GAAG,CAAC,KAAK,GAAG,WAAW,CAAC;IAExB,0CAA0C;IAC1C,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAiB,EAAE,EAAE;QAChD,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,6EAA6E;IAC7E,IAAI,WAAW,GAAuB,GAAG,CAAC,MAAM,CAAC;IACjD,OAAO,WAAW,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,WAAW,CAAC;QAClC,WAAW,GAAG,SAAS,CAAC;QAExB,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;QACvB,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAEhE,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,WAAW,GAAI,GAAG,CAAC,MAAiB,KAAK,WAAW,CAAC;YAC3D,IAAI,WAAW,EAAE,CAAC;gBAChB,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;YACpE,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,KAAK,GAAG,OAAO,CAAC;gBACpB,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;YAChF,CAAC;YACD,MAAM,UAAU,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC3D,OAAO;QACT,CAAC;QAED,IAAK,GAAG,CAAC,MAAiB,KAAK,WAAW,EAAE,CAAC;YAC3C,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;YAClE,MAAM,UAAU,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;YACnC,OAAO;QACT,CAAC;QAED,2DAA2D;QAC3D,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;QACpB,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7D,YAAY,CAAC,GAAG,CAAC,CAAC;QAElB,kDAAkD;QAClD,WAAW,GAAG,MAAM,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,EAAE;YAC9D,GAAG,CAAC,YAAY,GAAG,OAAO,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,YAAY,GAAG,SAAS,CAAC;QAE7B,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,qEAAqE;YACrE,OAAO;QACT,CAAC;QAED,cAAc,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,SAAS,cAAc,CAAC,KAAiB;IACvC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACtD,IAAI,OAAO,KAAK,KAAK,UAAU;YAAE,OAAO,SAAS,CAAC;QAClD,IAAI,KAAK,YAAY,eAAe;YAAE,OAAO,SAAS,CAAC;QACvD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC,CAAC;AACN,CAAC;AAED,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAC9E,SAAS,SAAS,CAAC,GAAyB;IAC1C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACjB,IAAI,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC;gBAAC,MAAM,CAAC,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;YAAC,CAAC;QACzF,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,IAAI,CAAC,GAAwB,EAAE,MAAc,EAAE,IAAa;IACnE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACrC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC9D,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IAClD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,oBAAoB,IAAI,EAAE,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEzD,gCAAgC;IAChC,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QACrD,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YAAC,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QAAC,CAAC;QAEhG,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAGvD,CAAC;QACF,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QAClC,MAAM,GAAG,GAAQ;YACf,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,QAAQ;YAChB,MAAM;YACN,aAAa,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE;YACtD,WAAW,EAAE,EAAE;YACf,OAAO,EAAE,IAAI,GAAG,EAAE;YAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACrB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAE7B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,iEAAiE;IACjE,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QAC9F,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAC5D,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,GAAG,CAAC,MAAM,YAAY,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YAAC,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QAAC,CAAC;QAEhG,MAAM,EAAE,OAAO,EAAE,GAAG,IAA4B,CAAC;QACjD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,GAAG,CAAC,YAAY,EAAE,CAAC,OAAO,CAAC,CAAC;QAE5B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,yBAAyB;IACzB,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE;YACpB,KAAK,EAAE,GAAG,CAAC,EAAE;YACb,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,UAAU,EAAE,GAAG,CAAC,WAAW,CAAC,MAAM;YAClC,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC,CAAC;IACL,CAAC;IAED,oCAAoC;IACpC,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC9F,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAE5D,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACjB,cAAc,EAAE,mBAAmB;YACnC,eAAe,EAAE,UAAU;YAC3B,YAAY,EAAE,YAAY;YAC1B,mBAAmB,EAAE,IAAI;SAC1B,CAAC,CAAC;QAEH,mEAAmE;QACnE,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAW,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;QAC9E,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;YACpC,IAAI,KAAK,CAAC,EAAE,GAAG,WAAW,EAAE,CAAC;gBAC3B,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,uCAAuC;QACvC,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,OAAO,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAClF,OAAO,GAAG,CAAC,GAAG,EAAE,CAAC;QACnB,CAAC;QAED,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,OAAO;IACT,CAAC;IAED,4BAA4B;IAC5B,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAC5D,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,OAAO,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAClF,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,eAAe,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,uDAAuD;QACvD,GAAG,CAAC,YAAY,EAAE,CAAC,SAAgB,CAAC,CAAC;QACrC,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC;QACzB,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;QACzB,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,UAAU,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAEnC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;AACzC,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAC9E,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAE9C,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACvB,OAAO,CAAC,GAAG,CAAC,kDAAkD,IAAI,EAAE,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,mBAAmB,WAAW,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,mBAAmB,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,mBAAmB,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,aAAa,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACrJ,OAAO,CAAC,GAAG,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { AgentMessage } from '@mariozechner/pi-agent-core';
2
+ import type { CompressionConfig, TranscriptSegment } from '../types.js';
3
+ /**
4
+ * Estimates token count as ceil(text.length / 4).
5
+ */
6
+ export declare function estimateTokens(text: string): number;
7
+ /**
8
+ * Extracts text content from an AgentMessage.
9
+ * Handles string content, array of TextContent, or falls back to JSON.stringify.
10
+ */
11
+ export declare function messageText(msg: AgentMessage): string;
12
+ /**
13
+ * Groups messages into TranscriptSegments by consecutive role type.
14
+ */
15
+ export declare function segmentMessages(messages: AgentMessage[]): TranscriptSegment[];
16
+ /**
17
+ * Creates a transformContext middleware for context compression.
18
+ *
19
+ * Truncate strategy:
20
+ * - Protects the most recent N turns (protectedRecentTurns * 3 messages)
21
+ * - If total tokens are under 80% of maxTokens, returns unchanged
22
+ * - Otherwise keeps as many older messages as fit in budget, starting from most recent older ones
23
+ *
24
+ * Summarize strategy falls back to truncate for now.
25
+ */
26
+ export declare function createCompressionMiddleware(config: CompressionConfig): (messages: AgentMessage[], signal?: AbortSignal) => Promise<AgentMessage[]>;
27
+ //# sourceMappingURL=compression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../../src/context/compression.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,KAAK,EAAE,iBAAiB,EAAe,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErF;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAkBrD;AAaD;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,iBAAiB,EAAE,CA2B7E;AAED;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,iBAAiB,GACxB,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAkD7E"}