@renseiai/agentfactory 0.8.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 (246) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +125 -0
  3. package/dist/src/config/index.d.ts +3 -0
  4. package/dist/src/config/index.d.ts.map +1 -0
  5. package/dist/src/config/index.js +1 -0
  6. package/dist/src/config/repository-config.d.ts +44 -0
  7. package/dist/src/config/repository-config.d.ts.map +1 -0
  8. package/dist/src/config/repository-config.js +88 -0
  9. package/dist/src/config/repository-config.test.d.ts +2 -0
  10. package/dist/src/config/repository-config.test.d.ts.map +1 -0
  11. package/dist/src/config/repository-config.test.js +249 -0
  12. package/dist/src/deployment/deployment-checker.d.ts +110 -0
  13. package/dist/src/deployment/deployment-checker.d.ts.map +1 -0
  14. package/dist/src/deployment/deployment-checker.js +242 -0
  15. package/dist/src/deployment/index.d.ts +3 -0
  16. package/dist/src/deployment/index.d.ts.map +1 -0
  17. package/dist/src/deployment/index.js +2 -0
  18. package/dist/src/frontend/index.d.ts +2 -0
  19. package/dist/src/frontend/index.d.ts.map +1 -0
  20. package/dist/src/frontend/index.js +1 -0
  21. package/dist/src/frontend/types.d.ts +106 -0
  22. package/dist/src/frontend/types.d.ts.map +1 -0
  23. package/dist/src/frontend/types.js +11 -0
  24. package/dist/src/governor/decision-engine.d.ts +52 -0
  25. package/dist/src/governor/decision-engine.d.ts.map +1 -0
  26. package/dist/src/governor/decision-engine.js +220 -0
  27. package/dist/src/governor/decision-engine.test.d.ts +2 -0
  28. package/dist/src/governor/decision-engine.test.d.ts.map +1 -0
  29. package/dist/src/governor/decision-engine.test.js +629 -0
  30. package/dist/src/governor/event-bus.d.ts +43 -0
  31. package/dist/src/governor/event-bus.d.ts.map +1 -0
  32. package/dist/src/governor/event-bus.js +8 -0
  33. package/dist/src/governor/event-deduplicator.d.ts +43 -0
  34. package/dist/src/governor/event-deduplicator.d.ts.map +1 -0
  35. package/dist/src/governor/event-deduplicator.js +53 -0
  36. package/dist/src/governor/event-driven-governor.d.ts +131 -0
  37. package/dist/src/governor/event-driven-governor.d.ts.map +1 -0
  38. package/dist/src/governor/event-driven-governor.js +379 -0
  39. package/dist/src/governor/event-driven-governor.test.d.ts +2 -0
  40. package/dist/src/governor/event-driven-governor.test.d.ts.map +1 -0
  41. package/dist/src/governor/event-driven-governor.test.js +673 -0
  42. package/dist/src/governor/event-types.d.ts +78 -0
  43. package/dist/src/governor/event-types.d.ts.map +1 -0
  44. package/dist/src/governor/event-types.js +32 -0
  45. package/dist/src/governor/governor-types.d.ts +82 -0
  46. package/dist/src/governor/governor-types.d.ts.map +1 -0
  47. package/dist/src/governor/governor-types.js +21 -0
  48. package/dist/src/governor/governor.d.ts +100 -0
  49. package/dist/src/governor/governor.d.ts.map +1 -0
  50. package/dist/src/governor/governor.js +262 -0
  51. package/dist/src/governor/governor.test.d.ts +2 -0
  52. package/dist/src/governor/governor.test.d.ts.map +1 -0
  53. package/dist/src/governor/governor.test.js +514 -0
  54. package/dist/src/governor/human-touchpoints.d.ts +131 -0
  55. package/dist/src/governor/human-touchpoints.d.ts.map +1 -0
  56. package/dist/src/governor/human-touchpoints.js +251 -0
  57. package/dist/src/governor/human-touchpoints.test.d.ts +2 -0
  58. package/dist/src/governor/human-touchpoints.test.d.ts.map +1 -0
  59. package/dist/src/governor/human-touchpoints.test.js +366 -0
  60. package/dist/src/governor/in-memory-event-bus.d.ts +29 -0
  61. package/dist/src/governor/in-memory-event-bus.d.ts.map +1 -0
  62. package/dist/src/governor/in-memory-event-bus.js +79 -0
  63. package/dist/src/governor/index.d.ts +14 -0
  64. package/dist/src/governor/index.d.ts.map +1 -0
  65. package/dist/src/governor/index.js +13 -0
  66. package/dist/src/governor/override-parser.d.ts +60 -0
  67. package/dist/src/governor/override-parser.d.ts.map +1 -0
  68. package/dist/src/governor/override-parser.js +98 -0
  69. package/dist/src/governor/override-parser.test.d.ts +2 -0
  70. package/dist/src/governor/override-parser.test.d.ts.map +1 -0
  71. package/dist/src/governor/override-parser.test.js +312 -0
  72. package/dist/src/governor/platform-adapter.d.ts +69 -0
  73. package/dist/src/governor/platform-adapter.d.ts.map +1 -0
  74. package/dist/src/governor/platform-adapter.js +11 -0
  75. package/dist/src/governor/processing-state.d.ts +66 -0
  76. package/dist/src/governor/processing-state.d.ts.map +1 -0
  77. package/dist/src/governor/processing-state.js +43 -0
  78. package/dist/src/governor/processing-state.test.d.ts +2 -0
  79. package/dist/src/governor/processing-state.test.d.ts.map +1 -0
  80. package/dist/src/governor/processing-state.test.js +96 -0
  81. package/dist/src/governor/top-of-funnel.d.ts +118 -0
  82. package/dist/src/governor/top-of-funnel.d.ts.map +1 -0
  83. package/dist/src/governor/top-of-funnel.js +168 -0
  84. package/dist/src/governor/top-of-funnel.test.d.ts +2 -0
  85. package/dist/src/governor/top-of-funnel.test.d.ts.map +1 -0
  86. package/dist/src/governor/top-of-funnel.test.js +331 -0
  87. package/dist/src/index.d.ts +11 -0
  88. package/dist/src/index.d.ts.map +1 -0
  89. package/dist/src/index.js +10 -0
  90. package/dist/src/linear-cli.d.ts +38 -0
  91. package/dist/src/linear-cli.d.ts.map +1 -0
  92. package/dist/src/linear-cli.js +674 -0
  93. package/dist/src/logger.d.ts +117 -0
  94. package/dist/src/logger.d.ts.map +1 -0
  95. package/dist/src/logger.js +430 -0
  96. package/dist/src/manifest/generate.d.ts +20 -0
  97. package/dist/src/manifest/generate.d.ts.map +1 -0
  98. package/dist/src/manifest/generate.js +65 -0
  99. package/dist/src/manifest/index.d.ts +4 -0
  100. package/dist/src/manifest/index.d.ts.map +1 -0
  101. package/dist/src/manifest/index.js +2 -0
  102. package/dist/src/manifest/route-manifest.d.ts +34 -0
  103. package/dist/src/manifest/route-manifest.d.ts.map +1 -0
  104. package/dist/src/manifest/route-manifest.js +148 -0
  105. package/dist/src/orchestrator/activity-emitter.d.ts +119 -0
  106. package/dist/src/orchestrator/activity-emitter.d.ts.map +1 -0
  107. package/dist/src/orchestrator/activity-emitter.js +306 -0
  108. package/dist/src/orchestrator/api-activity-emitter.d.ts +167 -0
  109. package/dist/src/orchestrator/api-activity-emitter.d.ts.map +1 -0
  110. package/dist/src/orchestrator/api-activity-emitter.js +417 -0
  111. package/dist/src/orchestrator/heartbeat-writer.d.ts +57 -0
  112. package/dist/src/orchestrator/heartbeat-writer.d.ts.map +1 -0
  113. package/dist/src/orchestrator/heartbeat-writer.js +137 -0
  114. package/dist/src/orchestrator/index.d.ts +20 -0
  115. package/dist/src/orchestrator/index.d.ts.map +1 -0
  116. package/dist/src/orchestrator/index.js +22 -0
  117. package/dist/src/orchestrator/log-analyzer.d.ts +160 -0
  118. package/dist/src/orchestrator/log-analyzer.d.ts.map +1 -0
  119. package/dist/src/orchestrator/log-analyzer.js +572 -0
  120. package/dist/src/orchestrator/log-config.d.ts +39 -0
  121. package/dist/src/orchestrator/log-config.d.ts.map +1 -0
  122. package/dist/src/orchestrator/log-config.js +45 -0
  123. package/dist/src/orchestrator/orchestrator.d.ts +316 -0
  124. package/dist/src/orchestrator/orchestrator.d.ts.map +1 -0
  125. package/dist/src/orchestrator/orchestrator.js +3290 -0
  126. package/dist/src/orchestrator/parse-work-result.d.ts +16 -0
  127. package/dist/src/orchestrator/parse-work-result.d.ts.map +1 -0
  128. package/dist/src/orchestrator/parse-work-result.js +135 -0
  129. package/dist/src/orchestrator/parse-work-result.test.d.ts +2 -0
  130. package/dist/src/orchestrator/parse-work-result.test.d.ts.map +1 -0
  131. package/dist/src/orchestrator/parse-work-result.test.js +234 -0
  132. package/dist/src/orchestrator/progress-logger.d.ts +72 -0
  133. package/dist/src/orchestrator/progress-logger.d.ts.map +1 -0
  134. package/dist/src/orchestrator/progress-logger.js +135 -0
  135. package/dist/src/orchestrator/session-logger.d.ts +159 -0
  136. package/dist/src/orchestrator/session-logger.d.ts.map +1 -0
  137. package/dist/src/orchestrator/session-logger.js +275 -0
  138. package/dist/src/orchestrator/state-recovery.d.ts +96 -0
  139. package/dist/src/orchestrator/state-recovery.d.ts.map +1 -0
  140. package/dist/src/orchestrator/state-recovery.js +302 -0
  141. package/dist/src/orchestrator/state-types.d.ts +165 -0
  142. package/dist/src/orchestrator/state-types.d.ts.map +1 -0
  143. package/dist/src/orchestrator/state-types.js +7 -0
  144. package/dist/src/orchestrator/stream-parser.d.ts +151 -0
  145. package/dist/src/orchestrator/stream-parser.d.ts.map +1 -0
  146. package/dist/src/orchestrator/stream-parser.js +137 -0
  147. package/dist/src/orchestrator/types.d.ts +232 -0
  148. package/dist/src/orchestrator/types.d.ts.map +1 -0
  149. package/dist/src/orchestrator/types.js +4 -0
  150. package/dist/src/orchestrator/validate-git-remote.test.d.ts +2 -0
  151. package/dist/src/orchestrator/validate-git-remote.test.d.ts.map +1 -0
  152. package/dist/src/orchestrator/validate-git-remote.test.js +61 -0
  153. package/dist/src/providers/a2a-auth.d.ts +81 -0
  154. package/dist/src/providers/a2a-auth.d.ts.map +1 -0
  155. package/dist/src/providers/a2a-auth.js +188 -0
  156. package/dist/src/providers/a2a-auth.test.d.ts +2 -0
  157. package/dist/src/providers/a2a-auth.test.d.ts.map +1 -0
  158. package/dist/src/providers/a2a-auth.test.js +232 -0
  159. package/dist/src/providers/a2a-provider.d.ts +254 -0
  160. package/dist/src/providers/a2a-provider.d.ts.map +1 -0
  161. package/dist/src/providers/a2a-provider.integration.test.d.ts +9 -0
  162. package/dist/src/providers/a2a-provider.integration.test.d.ts.map +1 -0
  163. package/dist/src/providers/a2a-provider.integration.test.js +665 -0
  164. package/dist/src/providers/a2a-provider.js +811 -0
  165. package/dist/src/providers/a2a-provider.test.d.ts +2 -0
  166. package/dist/src/providers/a2a-provider.test.d.ts.map +1 -0
  167. package/dist/src/providers/a2a-provider.test.js +681 -0
  168. package/dist/src/providers/amp-provider.d.ts +20 -0
  169. package/dist/src/providers/amp-provider.d.ts.map +1 -0
  170. package/dist/src/providers/amp-provider.js +24 -0
  171. package/dist/src/providers/claude-provider.d.ts +18 -0
  172. package/dist/src/providers/claude-provider.d.ts.map +1 -0
  173. package/dist/src/providers/claude-provider.js +437 -0
  174. package/dist/src/providers/codex-provider.d.ts +133 -0
  175. package/dist/src/providers/codex-provider.d.ts.map +1 -0
  176. package/dist/src/providers/codex-provider.js +381 -0
  177. package/dist/src/providers/codex-provider.test.d.ts +2 -0
  178. package/dist/src/providers/codex-provider.test.d.ts.map +1 -0
  179. package/dist/src/providers/codex-provider.test.js +387 -0
  180. package/dist/src/providers/index.d.ts +44 -0
  181. package/dist/src/providers/index.d.ts.map +1 -0
  182. package/dist/src/providers/index.js +85 -0
  183. package/dist/src/providers/spring-ai-provider.d.ts +90 -0
  184. package/dist/src/providers/spring-ai-provider.d.ts.map +1 -0
  185. package/dist/src/providers/spring-ai-provider.integration.test.d.ts +13 -0
  186. package/dist/src/providers/spring-ai-provider.integration.test.d.ts.map +1 -0
  187. package/dist/src/providers/spring-ai-provider.integration.test.js +351 -0
  188. package/dist/src/providers/spring-ai-provider.js +317 -0
  189. package/dist/src/providers/spring-ai-provider.test.d.ts +2 -0
  190. package/dist/src/providers/spring-ai-provider.test.d.ts.map +1 -0
  191. package/dist/src/providers/spring-ai-provider.test.js +200 -0
  192. package/dist/src/providers/types.d.ts +165 -0
  193. package/dist/src/providers/types.d.ts.map +1 -0
  194. package/dist/src/providers/types.js +13 -0
  195. package/dist/src/templates/adapters.d.ts +51 -0
  196. package/dist/src/templates/adapters.d.ts.map +1 -0
  197. package/dist/src/templates/adapters.js +104 -0
  198. package/dist/src/templates/adapters.test.d.ts +2 -0
  199. package/dist/src/templates/adapters.test.d.ts.map +1 -0
  200. package/dist/src/templates/adapters.test.js +165 -0
  201. package/dist/src/templates/agent-definition.d.ts +85 -0
  202. package/dist/src/templates/agent-definition.d.ts.map +1 -0
  203. package/dist/src/templates/agent-definition.js +97 -0
  204. package/dist/src/templates/agent-definition.test.d.ts +2 -0
  205. package/dist/src/templates/agent-definition.test.d.ts.map +1 -0
  206. package/dist/src/templates/agent-definition.test.js +209 -0
  207. package/dist/src/templates/index.d.ts +14 -0
  208. package/dist/src/templates/index.d.ts.map +1 -0
  209. package/dist/src/templates/index.js +11 -0
  210. package/dist/src/templates/loader.d.ts +41 -0
  211. package/dist/src/templates/loader.d.ts.map +1 -0
  212. package/dist/src/templates/loader.js +114 -0
  213. package/dist/src/templates/registry.d.ts +80 -0
  214. package/dist/src/templates/registry.d.ts.map +1 -0
  215. package/dist/src/templates/registry.js +177 -0
  216. package/dist/src/templates/registry.test.d.ts +2 -0
  217. package/dist/src/templates/registry.test.d.ts.map +1 -0
  218. package/dist/src/templates/registry.test.js +198 -0
  219. package/dist/src/templates/renderer.d.ts +29 -0
  220. package/dist/src/templates/renderer.d.ts.map +1 -0
  221. package/dist/src/templates/renderer.js +35 -0
  222. package/dist/src/templates/strategy-templates.test.d.ts +2 -0
  223. package/dist/src/templates/strategy-templates.test.d.ts.map +1 -0
  224. package/dist/src/templates/strategy-templates.test.js +619 -0
  225. package/dist/src/templates/types.d.ts +233 -0
  226. package/dist/src/templates/types.d.ts.map +1 -0
  227. package/dist/src/templates/types.js +127 -0
  228. package/dist/src/templates/types.test.d.ts +2 -0
  229. package/dist/src/templates/types.test.d.ts.map +1 -0
  230. package/dist/src/templates/types.test.js +232 -0
  231. package/dist/src/tools/index.d.ts +6 -0
  232. package/dist/src/tools/index.d.ts.map +1 -0
  233. package/dist/src/tools/index.js +3 -0
  234. package/dist/src/tools/linear-runner.d.ts +34 -0
  235. package/dist/src/tools/linear-runner.d.ts.map +1 -0
  236. package/dist/src/tools/linear-runner.js +700 -0
  237. package/dist/src/tools/plugins/linear.d.ts +9 -0
  238. package/dist/src/tools/plugins/linear.d.ts.map +1 -0
  239. package/dist/src/tools/plugins/linear.js +138 -0
  240. package/dist/src/tools/registry.d.ts +9 -0
  241. package/dist/src/tools/registry.d.ts.map +1 -0
  242. package/dist/src/tools/registry.js +18 -0
  243. package/dist/src/tools/types.d.ts +18 -0
  244. package/dist/src/tools/types.d.ts.map +1 -0
  245. package/dist/src/tools/types.js +1 -0
  246. package/package.json +78 -0
@@ -0,0 +1,200 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { mapSpringAiEvent, } from './spring-ai-provider.js';
3
+ function freshState() {
4
+ return {
5
+ sessionId: null,
6
+ totalInputTokens: 0,
7
+ totalOutputTokens: 0,
8
+ turnCount: 0,
9
+ };
10
+ }
11
+ describe('mapSpringAiEvent', () => {
12
+ it('maps session.started to init', () => {
13
+ const state = freshState();
14
+ const event = { type: 'session.started', session_id: 'sess-abc' };
15
+ const result = mapSpringAiEvent(event, state);
16
+ expect(result).toHaveLength(1);
17
+ expect(result[0]).toMatchObject({
18
+ type: 'init',
19
+ sessionId: 'sess-abc',
20
+ });
21
+ expect(state.sessionId).toBe('sess-abc');
22
+ });
23
+ it('maps turn.started to system with incrementing turn count', () => {
24
+ const state = freshState();
25
+ const event = { type: 'turn.started' };
26
+ const r1 = mapSpringAiEvent(event, state);
27
+ expect(r1[0]).toMatchObject({
28
+ type: 'system',
29
+ subtype: 'turn_started',
30
+ message: 'Turn 1 started',
31
+ });
32
+ expect(state.turnCount).toBe(1);
33
+ const r2 = mapSpringAiEvent(event, state);
34
+ expect(r2[0]).toMatchObject({ message: 'Turn 2 started' });
35
+ expect(state.turnCount).toBe(2);
36
+ });
37
+ it('maps turn.completed to result with accumulated usage', () => {
38
+ const state = freshState();
39
+ state.turnCount = 1;
40
+ const event = {
41
+ type: 'turn.completed',
42
+ usage: { input_tokens: 100, output_tokens: 50, model: 'gpt-4' },
43
+ };
44
+ const result = mapSpringAiEvent(event, state);
45
+ expect(result).toHaveLength(1);
46
+ expect(result[0]).toMatchObject({
47
+ type: 'result',
48
+ success: true,
49
+ cost: {
50
+ inputTokens: 100,
51
+ outputTokens: 50,
52
+ numTurns: 1,
53
+ },
54
+ });
55
+ expect(state.totalInputTokens).toBe(100);
56
+ expect(state.totalOutputTokens).toBe(50);
57
+ });
58
+ it('accumulates usage across multiple turns', () => {
59
+ const state = freshState();
60
+ state.turnCount = 2;
61
+ mapSpringAiEvent({ type: 'turn.completed', usage: { input_tokens: 100, output_tokens: 50 } }, state);
62
+ const result = mapSpringAiEvent({ type: 'turn.completed', usage: { input_tokens: 200, output_tokens: 80 } }, state);
63
+ expect(result[0]).toMatchObject({
64
+ type: 'result',
65
+ success: true,
66
+ cost: { inputTokens: 300, outputTokens: 130 },
67
+ });
68
+ });
69
+ it('maps turn.completed without usage', () => {
70
+ const state = freshState();
71
+ const result = mapSpringAiEvent({ type: 'turn.completed' }, state);
72
+ expect(result[0]).toMatchObject({ type: 'result', success: true });
73
+ });
74
+ it('maps turn.failed to failed result', () => {
75
+ const state = freshState();
76
+ const event = {
77
+ type: 'turn.failed',
78
+ error: { message: 'Model error', code: 'MODEL_ERROR' },
79
+ };
80
+ const result = mapSpringAiEvent(event, state);
81
+ expect(result[0]).toMatchObject({
82
+ type: 'result',
83
+ success: false,
84
+ errors: ['Model error'],
85
+ errorSubtype: 'turn_failed',
86
+ });
87
+ });
88
+ it('maps turn.failed without error message', () => {
89
+ const state = freshState();
90
+ const result = mapSpringAiEvent({ type: 'turn.failed' }, state);
91
+ expect(result[0]).toMatchObject({
92
+ type: 'result',
93
+ success: false,
94
+ errors: ['Turn failed'],
95
+ });
96
+ });
97
+ it('maps assistant.message to assistant_text', () => {
98
+ const state = freshState();
99
+ const event = {
100
+ type: 'assistant.message',
101
+ id: 'msg-1',
102
+ text: 'Analysis complete',
103
+ };
104
+ const result = mapSpringAiEvent(event, state);
105
+ expect(result).toEqual([{
106
+ type: 'assistant_text',
107
+ text: 'Analysis complete',
108
+ raw: event,
109
+ }]);
110
+ });
111
+ it('maps tool.invocation to tool_use', () => {
112
+ const state = freshState();
113
+ const event = {
114
+ type: 'tool.invocation',
115
+ id: 'tool-1',
116
+ tool_name: 'shell',
117
+ input: { command: 'ls -la' },
118
+ };
119
+ const result = mapSpringAiEvent(event, state);
120
+ expect(result[0]).toMatchObject({
121
+ type: 'tool_use',
122
+ toolName: 'shell',
123
+ toolUseId: 'tool-1',
124
+ input: { command: 'ls -la' },
125
+ });
126
+ });
127
+ it('maps tool.result to tool_result', () => {
128
+ const state = freshState();
129
+ const event = {
130
+ type: 'tool.result',
131
+ id: 'tool-1',
132
+ tool_name: 'shell',
133
+ content: 'file1.txt\nfile2.txt',
134
+ is_error: false,
135
+ };
136
+ const result = mapSpringAiEvent(event, state);
137
+ expect(result[0]).toMatchObject({
138
+ type: 'tool_result',
139
+ toolName: 'shell',
140
+ toolUseId: 'tool-1',
141
+ content: 'file1.txt\nfile2.txt',
142
+ isError: false,
143
+ });
144
+ });
145
+ it('maps tool.result with error', () => {
146
+ const state = freshState();
147
+ const event = {
148
+ type: 'tool.result',
149
+ id: 'tool-1',
150
+ tool_name: 'shell',
151
+ content: 'command not found',
152
+ is_error: true,
153
+ };
154
+ const result = mapSpringAiEvent(event, state);
155
+ expect(result[0]).toMatchObject({
156
+ type: 'tool_result',
157
+ isError: true,
158
+ content: 'command not found',
159
+ });
160
+ });
161
+ it('maps error event', () => {
162
+ const state = freshState();
163
+ const event = { type: 'error', message: 'Connection lost', code: 'CONN_ERROR' };
164
+ const result = mapSpringAiEvent(event, state);
165
+ expect(result[0]).toMatchObject({
166
+ type: 'error',
167
+ message: 'Connection lost',
168
+ code: 'CONN_ERROR',
169
+ });
170
+ });
171
+ it('maps error event without message', () => {
172
+ const state = freshState();
173
+ const result = mapSpringAiEvent({ type: 'error' }, state);
174
+ expect(result[0]).toMatchObject({
175
+ type: 'error',
176
+ message: 'Unknown error',
177
+ });
178
+ });
179
+ it('handles unknown event type gracefully', () => {
180
+ const state = freshState();
181
+ const event = { type: 'unknown.event' };
182
+ const result = mapSpringAiEvent(event, state);
183
+ expect(result[0]).toMatchObject({
184
+ type: 'system',
185
+ subtype: 'unknown',
186
+ });
187
+ });
188
+ });
189
+ describe('SpringAiProvider', () => {
190
+ it('exports SpringAiProvider class', async () => {
191
+ const { SpringAiProvider } = await import('./spring-ai-provider.js');
192
+ const provider = new SpringAiProvider();
193
+ expect(provider.name).toBe('spring-ai');
194
+ });
195
+ it('exports createSpringAiProvider factory', async () => {
196
+ const { createSpringAiProvider } = await import('./spring-ai-provider.js');
197
+ const provider = createSpringAiProvider();
198
+ expect(provider.name).toBe('spring-ai');
199
+ });
200
+ });
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Agent Provider Interface
3
+ *
4
+ * Abstracts the underlying agent SDK (Claude, Codex, Amp, etc.)
5
+ * so the orchestrator is provider-agnostic.
6
+ *
7
+ * All three providers follow the same pattern:
8
+ * 1. Initialize with config + working directory
9
+ * 2. Send a prompt
10
+ * 3. Iterate over a stream of events
11
+ * 4. Get a final result with cost/token data
12
+ */
13
+ /** Supported agent provider names */
14
+ export type AgentProviderName = 'claude' | 'codex' | 'amp' | 'spring-ai' | 'a2a';
15
+ /**
16
+ * Agent Provider
17
+ *
18
+ * Each provider implements spawn/resume to create an AgentHandle
19
+ * that streams normalized AgentEvents.
20
+ */
21
+ export interface AgentProvider {
22
+ /** Provider identifier */
23
+ readonly name: AgentProviderName;
24
+ /** Spawn a new agent session */
25
+ spawn(config: AgentSpawnConfig): AgentHandle;
26
+ /** Resume a previously interrupted session */
27
+ resume(sessionId: string, config: AgentSpawnConfig): AgentHandle;
28
+ }
29
+ /**
30
+ * Configuration passed to a provider when spawning an agent.
31
+ * Provider implementations translate these to SDK-specific options.
32
+ */
33
+ export interface AgentSpawnConfig {
34
+ /** The prompt/instruction for the agent */
35
+ prompt: string;
36
+ /** Working directory for the agent */
37
+ cwd: string;
38
+ /** Environment variables to pass to the agent process */
39
+ env: Record<string, string>;
40
+ /** AbortController for cancellation support */
41
+ abortController: AbortController;
42
+ /** Whether agent runs in autonomous mode (no user input) */
43
+ autonomous: boolean;
44
+ /** Sandbox level for filesystem/network restrictions */
45
+ sandboxEnabled: boolean;
46
+ /**
47
+ * Tools to auto-allow without prompting for permission.
48
+ * Uses Claude Code permission pattern format: 'Bash(prefix:glob)'.
49
+ * Examples: 'Bash(pnpm:*)', 'Bash(git commit:*)'.
50
+ * When omitted the provider may supply defaults for autonomous agents.
51
+ */
52
+ allowedTools?: string[];
53
+ /**
54
+ * Callback to capture PID when the agent process is spawned.
55
+ * Providers call this once the underlying process is created.
56
+ */
57
+ onProcessSpawned?: (pid: number | undefined) => void;
58
+ /**
59
+ * In-process MCP servers providing typed tools to the agent.
60
+ * Created by ToolRegistry.createServers() from registered plugins.
61
+ */
62
+ mcpServers?: Record<string, import('@anthropic-ai/claude-agent-sdk').McpServerConfig>;
63
+ /**
64
+ * Maximum number of agentic turns (API round-trips) before stopping.
65
+ * Coordinators need more turns than standard agents since they poll sub-agent status.
66
+ * When omitted, the provider's default applies.
67
+ */
68
+ maxTurns?: number;
69
+ }
70
+ /**
71
+ * Handle to a running agent session.
72
+ * Returned by AgentProvider.spawn() and AgentProvider.resume().
73
+ */
74
+ export interface AgentHandle {
75
+ /** Provider-specific session/thread ID (available after init event) */
76
+ sessionId: string | null;
77
+ /** Async iterable stream of normalized events */
78
+ stream: AsyncIterable<AgentEvent>;
79
+ /**
80
+ * Inject a follow-up user message into the running session.
81
+ * Used for user prompts without restarting the agent.
82
+ */
83
+ injectMessage(text: string): Promise<void>;
84
+ /**
85
+ * Stop the agent. Delegates to the provider's abort mechanism.
86
+ */
87
+ stop(): Promise<void>;
88
+ }
89
+ /**
90
+ * Normalized agent event.
91
+ * Each provider maps its native events to this common format.
92
+ */
93
+ export type AgentEvent = AgentInitEvent | AgentSystemEvent | AgentAssistantTextEvent | AgentToolUseEvent | AgentToolResultEvent | AgentToolProgressEvent | AgentResultEvent | AgentErrorEvent;
94
+ /** Agent initialized — contains session ID for resume */
95
+ export interface AgentInitEvent {
96
+ type: 'init';
97
+ sessionId: string;
98
+ raw: unknown;
99
+ }
100
+ /** System-level event (status changes, compaction, etc.) */
101
+ export interface AgentSystemEvent {
102
+ type: 'system';
103
+ subtype: string;
104
+ message?: string;
105
+ raw: unknown;
106
+ }
107
+ /** Assistant text output */
108
+ export interface AgentAssistantTextEvent {
109
+ type: 'assistant_text';
110
+ text: string;
111
+ raw: unknown;
112
+ }
113
+ /** Agent is invoking a tool */
114
+ export interface AgentToolUseEvent {
115
+ type: 'tool_use';
116
+ toolName: string;
117
+ toolUseId?: string;
118
+ input: Record<string, unknown>;
119
+ raw: unknown;
120
+ }
121
+ /** Tool execution result */
122
+ export interface AgentToolResultEvent {
123
+ type: 'tool_result';
124
+ toolName?: string;
125
+ toolUseId?: string;
126
+ content: string;
127
+ isError: boolean;
128
+ raw: unknown;
129
+ }
130
+ /** Tool execution progress update */
131
+ export interface AgentToolProgressEvent {
132
+ type: 'tool_progress';
133
+ toolName: string;
134
+ elapsedSeconds: number;
135
+ raw: unknown;
136
+ }
137
+ /** Final result — agent has finished */
138
+ export interface AgentResultEvent {
139
+ type: 'result';
140
+ success: boolean;
141
+ /** Completion message (only on success) */
142
+ message?: string;
143
+ /** Error messages (only on failure) */
144
+ errors?: string[];
145
+ /** Error subtype from the provider (e.g., 'error_during_execution', 'error_max_turns') */
146
+ errorSubtype?: string;
147
+ /** Cost/usage data */
148
+ cost?: AgentCostData;
149
+ raw: unknown;
150
+ }
151
+ /** Error event */
152
+ export interface AgentErrorEvent {
153
+ type: 'error';
154
+ message: string;
155
+ code?: string;
156
+ raw: unknown;
157
+ }
158
+ /** Cost and token usage data */
159
+ export interface AgentCostData {
160
+ inputTokens?: number;
161
+ outputTokens?: number;
162
+ totalCostUsd?: number;
163
+ numTurns?: number;
164
+ }
165
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/providers/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Agent Provider Interface
3
+ *
4
+ * Abstracts the underlying agent SDK (Claude, Codex, Amp, etc.)
5
+ * so the orchestrator is provider-agnostic.
6
+ *
7
+ * All three providers follow the same pattern:
8
+ * 1. Initialize with config + working directory
9
+ * 2. Send a prompt
10
+ * 3. Iterate over a stream of events
11
+ * 4. Get a final result with cost/token data
12
+ */
13
+ export {};
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Tool Permission Adapters
3
+ *
4
+ * Translate abstract tool permissions to provider-native format.
5
+ */
6
+ import type { ToolPermission, ToolPermissionAdapter } from './types.js';
7
+ import type { AgentProviderName } from '../providers/types.js';
8
+ /**
9
+ * Claude Code tool permission adapter.
10
+ *
11
+ * Translates abstract permissions to Claude Code's format:
12
+ * { shell: "pnpm *" } → "Bash(pnpm:*)"
13
+ * { shell: "git commit *" } → "Bash(git commit:*)"
14
+ * "user-input" → "AskUserQuestion"
15
+ */
16
+ export declare class ClaudeToolPermissionAdapter implements ToolPermissionAdapter {
17
+ translatePermissions(permissions: ToolPermission[]): string[];
18
+ private translateOne;
19
+ }
20
+ /**
21
+ * OpenAI Codex tool permission adapter.
22
+ *
23
+ * Codex uses sandbox policies (--full-auto / workspace-write / read-only)
24
+ * and TOML-based sandbox_permissions rather than per-tool allowlists.
25
+ * Shell permissions are passed through as command patterns for documentation
26
+ * and future granular support.
27
+ *
28
+ * { shell: "pnpm *" } → "shell:pnpm *"
29
+ * "user-input" → "user-input" (no-op — Codex exec is non-interactive)
30
+ */
31
+ export declare class CodexToolPermissionAdapter implements ToolPermissionAdapter {
32
+ translatePermissions(permissions: ToolPermission[]): string[];
33
+ private translateOne;
34
+ }
35
+ /**
36
+ * Spring AI tool permission adapter.
37
+ *
38
+ * Spring AI uses @Tool annotations and ToolCallAdvisor for tool configuration.
39
+ * Shell permissions map to Spring AI's tool-call allowlist format:
40
+ * { shell: "pnpm *" } → "spring-tool:shell:pnpm *"
41
+ * "user-input" → "user-input" (no-op — Spring AI agent is non-interactive)
42
+ */
43
+ export declare class SpringAiToolPermissionAdapter implements ToolPermissionAdapter {
44
+ translatePermissions(permissions: ToolPermission[]): string[];
45
+ private translateOne;
46
+ }
47
+ /**
48
+ * Create a tool permission adapter for the given provider.
49
+ */
50
+ export declare function createToolPermissionAdapter(provider: AgentProviderName): ToolPermissionAdapter;
51
+ //# sourceMappingURL=adapters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../../src/templates/adapters.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAE9D;;;;;;;GAOG;AACH,qBAAa,2BAA4B,YAAW,qBAAqB;IACvE,oBAAoB,CAAC,WAAW,EAAE,cAAc,EAAE,GAAG,MAAM,EAAE;IAI7D,OAAO,CAAC,YAAY;CAwBrB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,0BAA2B,YAAW,qBAAqB;IACtE,oBAAoB,CAAC,WAAW,EAAE,cAAc,EAAE,GAAG,MAAM,EAAE;IAI7D,OAAO,CAAC,YAAY;CAWrB;AAED;;;;;;;GAOG;AACH,qBAAa,6BAA8B,YAAW,qBAAqB;IACzE,oBAAoB,CAAC,WAAW,EAAE,cAAc,EAAE,GAAG,MAAM,EAAE;IAI7D,OAAO,CAAC,YAAY;CAWrB;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,iBAAiB,GAAG,qBAAqB,CAa9F"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Tool Permission Adapters
3
+ *
4
+ * Translate abstract tool permissions to provider-native format.
5
+ */
6
+ /**
7
+ * Claude Code tool permission adapter.
8
+ *
9
+ * Translates abstract permissions to Claude Code's format:
10
+ * { shell: "pnpm *" } → "Bash(pnpm:*)"
11
+ * { shell: "git commit *" } → "Bash(git commit:*)"
12
+ * "user-input" → "AskUserQuestion"
13
+ */
14
+ export class ClaudeToolPermissionAdapter {
15
+ translatePermissions(permissions) {
16
+ return permissions.map(p => this.translateOne(p));
17
+ }
18
+ translateOne(permission) {
19
+ if (typeof permission === 'string') {
20
+ if (permission === 'user-input') {
21
+ return 'AskUserQuestion';
22
+ }
23
+ // Pass through other string permissions as-is
24
+ return permission;
25
+ }
26
+ if ('shell' in permission) {
27
+ // Convert "pnpm *" → "Bash(pnpm:*)"
28
+ // Convert "git commit *" → "Bash(git commit:*)"
29
+ const pattern = permission.shell;
30
+ const spaceIndex = pattern.lastIndexOf(' ');
31
+ if (spaceIndex === -1) {
32
+ return `Bash(${pattern}:*)`;
33
+ }
34
+ const command = pattern.substring(0, spaceIndex);
35
+ const glob = pattern.substring(spaceIndex + 1);
36
+ return `Bash(${command}:${glob})`;
37
+ }
38
+ return String(permission);
39
+ }
40
+ }
41
+ /**
42
+ * OpenAI Codex tool permission adapter.
43
+ *
44
+ * Codex uses sandbox policies (--full-auto / workspace-write / read-only)
45
+ * and TOML-based sandbox_permissions rather than per-tool allowlists.
46
+ * Shell permissions are passed through as command patterns for documentation
47
+ * and future granular support.
48
+ *
49
+ * { shell: "pnpm *" } → "shell:pnpm *"
50
+ * "user-input" → "user-input" (no-op — Codex exec is non-interactive)
51
+ */
52
+ export class CodexToolPermissionAdapter {
53
+ translatePermissions(permissions) {
54
+ return permissions.map(p => this.translateOne(p));
55
+ }
56
+ translateOne(permission) {
57
+ if (typeof permission === 'string') {
58
+ return permission;
59
+ }
60
+ if ('shell' in permission) {
61
+ return `shell:${permission.shell}`;
62
+ }
63
+ return String(permission);
64
+ }
65
+ }
66
+ /**
67
+ * Spring AI tool permission adapter.
68
+ *
69
+ * Spring AI uses @Tool annotations and ToolCallAdvisor for tool configuration.
70
+ * Shell permissions map to Spring AI's tool-call allowlist format:
71
+ * { shell: "pnpm *" } → "spring-tool:shell:pnpm *"
72
+ * "user-input" → "user-input" (no-op — Spring AI agent is non-interactive)
73
+ */
74
+ export class SpringAiToolPermissionAdapter {
75
+ translatePermissions(permissions) {
76
+ return permissions.map(p => this.translateOne(p));
77
+ }
78
+ translateOne(permission) {
79
+ if (typeof permission === 'string') {
80
+ return permission;
81
+ }
82
+ if ('shell' in permission) {
83
+ return `spring-tool:shell:${permission.shell}`;
84
+ }
85
+ return String(permission);
86
+ }
87
+ }
88
+ /**
89
+ * Create a tool permission adapter for the given provider.
90
+ */
91
+ export function createToolPermissionAdapter(provider) {
92
+ switch (provider) {
93
+ case 'claude':
94
+ return new ClaudeToolPermissionAdapter();
95
+ case 'codex':
96
+ return new CodexToolPermissionAdapter();
97
+ case 'amp':
98
+ return new ClaudeToolPermissionAdapter();
99
+ case 'spring-ai':
100
+ return new SpringAiToolPermissionAdapter();
101
+ default:
102
+ return new ClaudeToolPermissionAdapter();
103
+ }
104
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=adapters.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.test.d.ts","sourceRoot":"","sources":["../../../src/templates/adapters.test.ts"],"names":[],"mappings":""}