@stackmemoryai/stackmemory 1.12.0 → 1.14.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 (162) hide show
  1. package/LICENSE +131 -64
  2. package/README.md +3 -1
  3. package/bin/claude-sm +16 -1
  4. package/bin/claude-smd +16 -1
  5. package/bin/codex-smd +16 -1
  6. package/bin/gemini-sm +16 -1
  7. package/bin/hermes-sm +21 -0
  8. package/bin/hermes-smd +21 -0
  9. package/bin/opencode-sm +16 -1
  10. package/dist/src/cli/codex-sm.js +51 -11
  11. package/dist/src/cli/commands/brain.js +206 -0
  12. package/dist/src/cli/commands/company-os.js +184 -0
  13. package/dist/src/cli/commands/context.js +5 -0
  14. package/dist/src/cli/commands/operator.js +127 -0
  15. package/dist/src/cli/commands/orchestrate.js +2 -0
  16. package/dist/src/cli/commands/orchestrator.js +3 -2
  17. package/dist/src/cli/commands/patterns.js +254 -0
  18. package/dist/src/cli/commands/portal.js +161 -0
  19. package/dist/src/cli/commands/scaffold.js +92 -0
  20. package/dist/src/cli/commands/setup.js +1 -4
  21. package/dist/src/cli/commands/sync.js +253 -0
  22. package/dist/src/cli/commands/tasks.js +130 -1
  23. package/dist/src/cli/commands/vision.js +221 -0
  24. package/dist/src/cli/hermes-sm.js +224 -0
  25. package/dist/src/cli/index.js +15 -10
  26. package/dist/src/cli/utils/real-cli-bin.js +72 -0
  27. package/dist/src/core/brain/brain-store.js +187 -0
  28. package/dist/src/core/brain/brain-sync.js +193 -0
  29. package/dist/src/core/brain/index.js +78 -0
  30. package/dist/src/core/brain/types.js +10 -0
  31. package/dist/src/core/cache/token-estimator.js +24 -1
  32. package/dist/src/core/config/feature-flags.js +2 -6
  33. package/dist/src/core/context/frame-database.js +44 -0
  34. package/dist/src/core/context/recursive-context-manager.js +1 -1
  35. package/dist/src/core/context/rehydration.js +2 -1
  36. package/dist/src/core/database/sqlite-adapter.js +14 -1
  37. package/dist/src/core/models/model-router.js +33 -1
  38. package/dist/src/core/models/provider-pricing.js +58 -4
  39. package/dist/src/core/patterns/index.js +22 -0
  40. package/dist/src/core/patterns/pattern-applier.js +39 -0
  41. package/dist/src/core/patterns/pattern-observer.js +157 -0
  42. package/dist/src/core/patterns/pattern-store.js +259 -0
  43. package/dist/src/core/patterns/types.js +19 -0
  44. package/dist/src/core/retrieval/llm-context-retrieval.js +5 -4
  45. package/dist/src/core/retrieval/unified-context-assembler.js +11 -66
  46. package/dist/src/core/skill-packs/types.js +14 -1
  47. package/dist/src/core/storage/cloud-sync-manager.js +116 -0
  48. package/dist/src/core/storage/cloud-sync.js +574 -0
  49. package/dist/src/core/storage/two-tier-storage.js +5 -1
  50. package/dist/src/core/tasks/master-tasks-template.js +43 -0
  51. package/dist/src/core/tasks/md-task-parser.js +138 -0
  52. package/dist/src/core/vision/index.js +27 -0
  53. package/dist/src/core/vision/signals.js +79 -0
  54. package/dist/src/core/vision/types.js +22 -0
  55. package/dist/src/core/vision/vision-file.js +146 -0
  56. package/dist/src/core/vision/vision-loop.js +220 -0
  57. package/dist/src/core/wiki/wiki-compiler.js +103 -1
  58. package/dist/src/daemon/daemon-config.js +45 -0
  59. package/dist/src/daemon/services/desire-path-service.js +566 -0
  60. package/dist/src/daemon/services/research-stream-service.js +320 -0
  61. package/dist/src/daemon/services/telemetry-service.js +192 -0
  62. package/dist/src/daemon/unified-daemon.js +28 -1
  63. package/dist/src/features/browser/cli-browser-agent.js +417 -0
  64. package/dist/src/features/browser/stagehand-workflows.js +578 -0
  65. package/dist/src/features/operator/adapter-factory.js +62 -0
  66. package/dist/src/features/operator/browser-adapter.js +109 -0
  67. package/dist/src/features/operator/desktop-adapter.js +125 -0
  68. package/dist/src/features/operator/index.js +39 -0
  69. package/dist/src/features/operator/llm-decision.js +137 -0
  70. package/dist/src/features/operator/operator-logger.js +92 -0
  71. package/dist/src/features/operator/overnight-runner.js +327 -0
  72. package/dist/src/features/operator/screen-adapter.js +91 -0
  73. package/dist/src/features/operator/session-manager.js +127 -0
  74. package/dist/src/features/operator/state-machine.js +227 -0
  75. package/dist/src/features/operator/task-queue.js +81 -0
  76. package/dist/src/features/portal/index.js +26 -0
  77. package/dist/src/features/portal/server.js +240 -0
  78. package/dist/src/features/portal/types.js +14 -0
  79. package/dist/src/features/portal/ui.js +195 -0
  80. package/dist/src/features/tasks/task-aware-context.js +2 -1
  81. package/dist/src/features/tui/simple-monitor.js +0 -23
  82. package/dist/src/features/tui/swarm-monitor.js +8 -66
  83. package/dist/src/{integrations/diffmem/index.js → features/web/client/hooks/use-socket.js} +6 -5
  84. package/dist/src/features/web/client/lib/utils.js +12 -0
  85. package/dist/src/features/web/client/stores/session-store.js +12 -0
  86. package/dist/src/features/web/server/gcp-billing.js +76 -0
  87. package/dist/src/features/web/server/index.js +10 -0
  88. package/dist/src/features/web/server/spend-calculator.js +228 -0
  89. package/dist/src/hooks/schemas.js +4 -1
  90. package/dist/src/integrations/anthropic/client.js +3 -2
  91. package/dist/src/integrations/claude-code/agent-bridge.js +0 -3
  92. package/dist/src/integrations/claude-code/subagent-client.js +218 -11
  93. package/dist/src/integrations/claude-code/task-coordinator.js +2 -1
  94. package/dist/src/integrations/linear/webhook-retry.js +196 -0
  95. package/dist/src/integrations/linear/webhook-server.js +18 -22
  96. package/dist/src/integrations/mcp/handlers/cloud-sync-handlers.js +101 -0
  97. package/dist/src/integrations/mcp/handlers/index.js +27 -52
  98. package/dist/src/integrations/mcp/server.js +122 -335
  99. package/dist/src/integrations/mcp/tool-alias-registry.js +0 -73
  100. package/dist/src/integrations/mcp/tool-definitions.js +111 -510
  101. package/dist/src/mcp/stackmemory-mcp-server.js +404 -379
  102. package/dist/src/orchestrators/multimodal/determinism.js +2 -1
  103. package/dist/src/orchestrators/multimodal/harness.js +2 -1
  104. package/dist/src/skills/recursive-agent-orchestrator.js +2 -4
  105. package/dist/src/utils/process-cleanup.js +1 -7
  106. package/docs/README.md +42 -0
  107. package/docs/guides/README_INSTALL.md +208 -0
  108. package/package.json +18 -9
  109. package/scripts/claude-code-wrapper.sh +11 -0
  110. package/scripts/claude-sm-setup.sh +12 -1
  111. package/scripts/codex-wrapper.sh +11 -0
  112. package/scripts/git-hooks/branch-context-manager.sh +11 -0
  113. package/scripts/git-hooks/post-checkout-stackmemory.sh +11 -0
  114. package/scripts/git-hooks/post-commit-stackmemory.sh +11 -0
  115. package/scripts/git-hooks/pre-commit-stackmemory.sh +11 -0
  116. package/scripts/hooks/cleanup-shell.sh +12 -1
  117. package/scripts/hooks/task-complete.sh +12 -1
  118. package/scripts/install-code-execution-hooks.sh +12 -1
  119. package/scripts/install-sweep-hook.sh +12 -0
  120. package/scripts/install.sh +11 -0
  121. package/scripts/opencode-wrapper.sh +11 -0
  122. package/scripts/portal/cloud-init.yaml +69 -0
  123. package/scripts/portal/setup.sh +69 -0
  124. package/scripts/portal/stackmemory-portal.service +34 -0
  125. package/scripts/setup-claude-integration.sh +12 -1
  126. package/scripts/smoke-init-db.sh +23 -0
  127. package/scripts/stackmemory-daemon.sh +11 -0
  128. package/scripts/verify-dist.cjs +11 -4
  129. package/dist/src/cli/commands/ralph.js +0 -1053
  130. package/dist/src/hooks/diffmem-hooks.js +0 -376
  131. package/dist/src/integrations/diffmem/client.js +0 -208
  132. package/dist/src/integrations/diffmem/config.js +0 -14
  133. package/dist/src/integrations/greptile/client.js +0 -101
  134. package/dist/src/integrations/greptile/config.js +0 -14
  135. package/dist/src/integrations/greptile/index.js +0 -11
  136. package/dist/src/integrations/mcp/handlers/cross-search-handlers.js +0 -188
  137. package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +0 -455
  138. package/dist/src/integrations/mcp/handlers/greptile-handlers.js +0 -456
  139. package/dist/src/integrations/mcp/handlers/provider-handlers.js +0 -227
  140. package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +0 -863
  141. package/dist/src/integrations/ralph/context/context-budget-manager.js +0 -308
  142. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +0 -354
  143. package/dist/src/integrations/ralph/index.js +0 -17
  144. package/dist/src/integrations/ralph/learning/pattern-learner.js +0 -416
  145. package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +0 -448
  146. package/dist/src/integrations/ralph/loopmax.js +0 -488
  147. package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +0 -293
  148. package/dist/src/integrations/ralph/monitoring/swarm-registry.js +0 -107
  149. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +0 -508
  150. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +0 -407
  151. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +0 -495
  152. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +0 -387
  153. package/dist/src/integrations/ralph/performance/performance-optimizer.js +0 -357
  154. package/dist/src/integrations/ralph/recovery/crash-recovery.js +0 -461
  155. package/dist/src/integrations/ralph/state/state-reconciler.js +0 -420
  156. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +0 -444
  157. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -1005
  158. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +0 -635
  159. package/scripts/ralph-loop-implementation.js +0 -404
  160. /package/dist/src/{integrations/diffmem/types.js → core/storage/cloud-sync-types.js} +0 -0
  161. /package/dist/src/{integrations/greptile → features/operator}/types.js +0 -0
  162. /package/dist/src/{integrations/ralph/types.js → features/web/client/next-env.d.js} +0 -0
@@ -1,456 +0,0 @@
1
- import { fileURLToPath as __fileURLToPath } from 'url';
2
- import { dirname as __pathDirname } from 'path';
3
- const __filename = __fileURLToPath(import.meta.url);
4
- const __dirname = __pathDirname(__filename);
5
- import { DEFAULT_GREPTILE_CONFIG } from "../../greptile/config.js";
6
- import { GreptileClient, GreptileClientError } from "../../greptile/client.js";
7
- import { logger } from "../../../core/monitoring/logger.js";
8
- class GreptileHandlers {
9
- config;
10
- client = null;
11
- constructor(deps) {
12
- this.config = { ...DEFAULT_GREPTILE_CONFIG, ...deps?.config };
13
- if (this.config.enabled && this.config.apiKey) {
14
- try {
15
- this.client = new GreptileClient(this.config);
16
- } catch {
17
- this.client = null;
18
- }
19
- }
20
- }
21
- getToolDefinitions() {
22
- return [
23
- {
24
- name: "greptile_pr_comments",
25
- description: "Get PR review comments from Greptile. Returns unaddressed comments with suggestedCode for auto-fix workflows.",
26
- inputSchema: {
27
- type: "object",
28
- properties: {
29
- name: {
30
- type: "string",
31
- description: 'Repository full name (e.g., "owner/repo")'
32
- },
33
- remote: {
34
- type: "string",
35
- enum: ["github", "gitlab", "azure", "bitbucket"],
36
- description: "Remote provider"
37
- },
38
- defaultBranch: {
39
- type: "string",
40
- description: 'Default branch (e.g., "main")'
41
- },
42
- prNumber: {
43
- type: "number",
44
- description: "Pull request number"
45
- },
46
- greptileGenerated: {
47
- type: "boolean",
48
- description: "Filter for only Greptile review comments"
49
- },
50
- addressed: {
51
- type: "boolean",
52
- description: "Filter by comment addressed status"
53
- }
54
- },
55
- required: ["name", "remote", "defaultBranch", "prNumber"]
56
- }
57
- },
58
- {
59
- name: "greptile_pr_details",
60
- description: "Get detailed PR information including metadata, statistics, and review analysis from Greptile.",
61
- inputSchema: {
62
- type: "object",
63
- properties: {
64
- name: {
65
- type: "string",
66
- description: 'Repository full name (e.g., "owner/repo")'
67
- },
68
- remote: {
69
- type: "string",
70
- enum: ["github", "gitlab", "azure", "bitbucket"],
71
- description: "Remote provider"
72
- },
73
- defaultBranch: {
74
- type: "string",
75
- description: "Default branch"
76
- },
77
- prNumber: {
78
- type: "number",
79
- description: "Pull request number"
80
- }
81
- },
82
- required: ["name", "remote", "defaultBranch", "prNumber"]
83
- }
84
- },
85
- {
86
- name: "greptile_list_prs",
87
- description: "List pull requests. Filter by repository, branch, author, or state.",
88
- inputSchema: {
89
- type: "object",
90
- properties: {
91
- name: {
92
- type: "string",
93
- description: 'Repository full name (e.g., "owner/repo")'
94
- },
95
- remote: {
96
- type: "string",
97
- enum: ["github", "gitlab", "azure", "bitbucket"],
98
- description: "Remote provider"
99
- },
100
- defaultBranch: {
101
- type: "string",
102
- description: "Default branch"
103
- },
104
- sourceBranch: {
105
- type: "string",
106
- description: "Filter by source branch name"
107
- },
108
- authorLogin: {
109
- type: "string",
110
- description: "Filter by PR author username"
111
- },
112
- state: {
113
- type: "string",
114
- enum: ["open", "closed", "merged"],
115
- description: "Filter by PR state"
116
- },
117
- limit: {
118
- type: "number",
119
- description: "Max results (default 20)"
120
- }
121
- }
122
- }
123
- },
124
- {
125
- name: "greptile_trigger_review",
126
- description: "Trigger a Greptile code review for a pull request.",
127
- inputSchema: {
128
- type: "object",
129
- properties: {
130
- name: {
131
- type: "string",
132
- description: 'Repository full name (e.g., "owner/repo")'
133
- },
134
- remote: {
135
- type: "string",
136
- enum: ["github", "gitlab", "azure", "bitbucket"],
137
- description: "Remote provider"
138
- },
139
- defaultBranch: {
140
- type: "string",
141
- description: "Default branch"
142
- },
143
- prNumber: {
144
- type: "number",
145
- description: "Pull request number"
146
- },
147
- branch: {
148
- type: "string",
149
- description: "Current working branch"
150
- }
151
- },
152
- required: ["name", "remote", "prNumber"]
153
- }
154
- },
155
- {
156
- name: "greptile_search_patterns",
157
- description: "Search custom coding patterns and instructions in Greptile.",
158
- inputSchema: {
159
- type: "object",
160
- properties: {
161
- query: {
162
- type: "string",
163
- description: "Search query for pattern content"
164
- },
165
- limit: {
166
- type: "number",
167
- description: "Max results (default 10)"
168
- }
169
- },
170
- required: ["query"]
171
- }
172
- },
173
- {
174
- name: "greptile_create_pattern",
175
- description: "Create a new custom coding pattern or instruction in Greptile.",
176
- inputSchema: {
177
- type: "object",
178
- properties: {
179
- body: {
180
- type: "string",
181
- description: "Pattern content"
182
- },
183
- type: {
184
- type: "string",
185
- enum: ["CUSTOM_INSTRUCTION", "PATTERN"],
186
- description: "Context type (default: CUSTOM_INSTRUCTION)"
187
- },
188
- scopes: {
189
- type: "object",
190
- description: "Boolean expression defining where this pattern applies"
191
- }
192
- },
193
- required: ["body"]
194
- }
195
- },
196
- {
197
- name: "greptile_status",
198
- description: "Check Greptile integration connection status.",
199
- inputSchema: {
200
- type: "object",
201
- properties: {}
202
- }
203
- }
204
- ];
205
- }
206
- async handleListPRComments(args) {
207
- if (!this.client) return this.disabledResponse();
208
- try {
209
- const toolArgs = {
210
- name: args.name,
211
- remote: args.remote,
212
- defaultBranch: args.defaultBranch,
213
- prNumber: args.prNumber
214
- };
215
- if (args.greptileGenerated !== void 0)
216
- toolArgs.greptileGenerated = args.greptileGenerated;
217
- if (args.addressed !== void 0) toolArgs.addressed = args.addressed;
218
- const result = await this.client.callTool(
219
- "list_merge_request_comments",
220
- toolArgs
221
- );
222
- let actionableCount = 0;
223
- if (Array.isArray(result)) {
224
- actionableCount = result.filter(
225
- (c) => !c.addressed && (c.suggestedCode || typeof c.body === "string" && c.body.includes("```suggestion"))
226
- ).length;
227
- }
228
- return {
229
- content: [
230
- {
231
- type: "text",
232
- text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
233
- }
234
- ],
235
- metadata: { actionableCount, tool: "list_merge_request_comments" }
236
- };
237
- } catch (error) {
238
- return this.handleError("listPRComments", error);
239
- }
240
- }
241
- async handleGetMergeRequest(args) {
242
- if (!this.client) return this.disabledResponse();
243
- try {
244
- const result = await this.client.callTool("get_merge_request", {
245
- name: args.name,
246
- remote: args.remote,
247
- defaultBranch: args.defaultBranch,
248
- prNumber: args.prNumber
249
- });
250
- return {
251
- content: [
252
- {
253
- type: "text",
254
- text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
255
- }
256
- ],
257
- metadata: { tool: "get_merge_request" }
258
- };
259
- } catch (error) {
260
- return this.handleError("getMergeRequest", error);
261
- }
262
- }
263
- async handleListPullRequests(args) {
264
- if (!this.client) return this.disabledResponse();
265
- try {
266
- const toolArgs = {};
267
- if (args.name) toolArgs.name = args.name;
268
- if (args.remote) toolArgs.remote = args.remote;
269
- if (args.defaultBranch) toolArgs.defaultBranch = args.defaultBranch;
270
- if (args.sourceBranch) toolArgs.sourceBranch = args.sourceBranch;
271
- if (args.authorLogin) toolArgs.authorLogin = args.authorLogin;
272
- if (args.state) toolArgs.state = args.state;
273
- if (args.limit) toolArgs.limit = args.limit;
274
- const result = await this.client.callTool("list_pull_requests", toolArgs);
275
- return {
276
- content: [
277
- {
278
- type: "text",
279
- text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
280
- }
281
- ],
282
- metadata: { tool: "list_pull_requests" }
283
- };
284
- } catch (error) {
285
- return this.handleError("listPullRequests", error);
286
- }
287
- }
288
- async handleTriggerCodeReview(args) {
289
- if (!this.client) return this.disabledResponse();
290
- try {
291
- const toolArgs = {
292
- name: args.name,
293
- remote: args.remote,
294
- prNumber: args.prNumber
295
- };
296
- if (args.defaultBranch) toolArgs.defaultBranch = args.defaultBranch;
297
- if (args.branch) toolArgs.branch = args.branch;
298
- const result = await this.client.callTool(
299
- "trigger_code_review",
300
- toolArgs
301
- );
302
- return {
303
- content: [
304
- {
305
- type: "text",
306
- text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
307
- }
308
- ],
309
- metadata: { tool: "trigger_code_review" }
310
- };
311
- } catch (error) {
312
- return this.handleError("triggerCodeReview", error);
313
- }
314
- }
315
- async handleSearchPatterns(args) {
316
- if (!this.client) return this.disabledResponse();
317
- try {
318
- const toolArgs = { query: args.query };
319
- if (args.limit) toolArgs.limit = args.limit;
320
- const result = await this.client.callTool(
321
- "search_custom_context",
322
- toolArgs
323
- );
324
- return {
325
- content: [
326
- {
327
- type: "text",
328
- text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
329
- }
330
- ],
331
- metadata: { tool: "search_custom_context" }
332
- };
333
- } catch (error) {
334
- return this.handleError("searchPatterns", error);
335
- }
336
- }
337
- async handleCreatePattern(args) {
338
- if (!this.client) return this.disabledResponse();
339
- try {
340
- const toolArgs = { body: args.body };
341
- if (args.type) toolArgs.type = args.type;
342
- if (args.scopes) toolArgs.scopes = args.scopes;
343
- const result = await this.client.callTool(
344
- "create_custom_context",
345
- toolArgs
346
- );
347
- return {
348
- content: [
349
- {
350
- type: "text",
351
- text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
352
- }
353
- ],
354
- metadata: { tool: "create_custom_context" }
355
- };
356
- } catch (error) {
357
- return this.handleError("createPattern", error);
358
- }
359
- }
360
- async handleStatus() {
361
- if (!this.client) {
362
- return {
363
- content: [
364
- {
365
- type: "text",
366
- text: JSON.stringify(
367
- {
368
- connected: false,
369
- message: "Greptile integration disabled (GREPTILE_API_KEY not set)"
370
- },
371
- null,
372
- 2
373
- )
374
- }
375
- ],
376
- metadata: { connected: false }
377
- };
378
- }
379
- try {
380
- await this.client.callTool("list_pull_requests", { limit: 1 });
381
- return {
382
- content: [
383
- {
384
- type: "text",
385
- text: JSON.stringify(
386
- {
387
- connected: true,
388
- endpoint: this.config.mcpEndpoint
389
- },
390
- null,
391
- 2
392
- )
393
- }
394
- ],
395
- metadata: { connected: true }
396
- };
397
- } catch (error) {
398
- const msg = error instanceof Error ? error.message : String(error);
399
- return {
400
- content: [
401
- {
402
- type: "text",
403
- text: JSON.stringify(
404
- {
405
- connected: false,
406
- error: msg,
407
- endpoint: this.config.mcpEndpoint
408
- },
409
- null,
410
- 2
411
- )
412
- }
413
- ],
414
- metadata: { connected: false, error: msg }
415
- };
416
- }
417
- }
418
- disabledResponse() {
419
- return {
420
- content: [
421
- {
422
- type: "text",
423
- text: "Greptile integration disabled (GREPTILE_API_KEY not set)"
424
- }
425
- ]
426
- };
427
- }
428
- handleError(operation, error) {
429
- const msg = error instanceof Error ? error.message : String(error);
430
- const isConnectionError = msg.includes("ECONNREFUSED") || msg.includes("fetch failed") || msg.includes("network") || error instanceof GreptileClientError;
431
- logger.debug(`Greptile ${operation} failed`, { error: msg });
432
- if (isConnectionError) {
433
- return {
434
- content: [
435
- {
436
- type: "text",
437
- text: `Greptile unavailable (${operation}). The service may be temporarily unreachable.`
438
- }
439
- ],
440
- metadata: { error: true, unavailable: true, operation }
441
- };
442
- }
443
- return {
444
- content: [
445
- {
446
- type: "text",
447
- text: `Greptile ${operation} error: ${msg}`
448
- }
449
- ],
450
- metadata: { error: true, operation, message: msg }
451
- };
452
- }
453
- }
454
- export {
455
- GreptileHandlers
456
- };
@@ -1,227 +0,0 @@
1
- import { fileURLToPath as __fileURLToPath } from 'url';
2
- import { dirname as __pathDirname } from 'path';
3
- const __filename = __fileURLToPath(import.meta.url);
4
- const __dirname = __pathDirname(__filename);
5
- import { logger } from "../../../core/monitoring/logger.js";
6
- import { isFeatureEnabled } from "../../../core/config/feature-flags.js";
7
- import {
8
- createProvider
9
- } from "../../../core/extensions/provider-adapter.js";
10
- import {
11
- getOptimalProvider
12
- } from "../../../core/models/model-router.js";
13
- import { scoreComplexity } from "../../../core/models/complexity-scorer.js";
14
- import {
15
- AnthropicBatchClient
16
- } from "../../anthropic/batch-client.js";
17
- function errorResponse(err) {
18
- return {
19
- content: [{ type: "text", text: JSON.stringify(err, null, 2) }]
20
- };
21
- }
22
- function classifyApiError(error, provider) {
23
- const msg = error.message || String(error);
24
- const status = error.status || (msg.match(/(\d{3})/)?.[1] ? parseInt(msg.match(/(\d{3})/)[1]) : void 0);
25
- if (status === 429) {
26
- return {
27
- errorType: "rate_limit",
28
- message: msg,
29
- recommendation: `Rate limited by ${provider}. Retry after a delay or switch to a different provider.`,
30
- provider
31
- };
32
- }
33
- if (status && status >= 500) {
34
- return {
35
- errorType: "server_error",
36
- message: msg,
37
- recommendation: `${provider} returned a server error. Try a different provider or retry later.`,
38
- provider
39
- };
40
- }
41
- return {
42
- errorType: "api_error",
43
- message: msg,
44
- recommendation: `API call to ${provider} failed. Check the model name, API key, and base URL.`,
45
- provider
46
- };
47
- }
48
- class ProviderHandlers {
49
- batchClient;
50
- constructor(_deps) {
51
- }
52
- getBatchClient() {
53
- if (!this.batchClient) {
54
- this.batchClient = new AnthropicBatchClient();
55
- }
56
- return this.batchClient;
57
- }
58
- /**
59
- * delegate_to_model — route a prompt to a specific provider+model
60
- */
61
- async handleDelegateToModel(args) {
62
- if (!isFeatureEnabled("multiProvider")) {
63
- return errorResponse({
64
- errorType: "feature_disabled",
65
- message: "Multi-provider routing is disabled.",
66
- recommendation: "Set STACKMEMORY_MULTI_PROVIDER=true to enable multi-provider routing."
67
- });
68
- }
69
- const taskType = args.taskType || "default";
70
- const preference = args.provider;
71
- const complexity = scoreComplexity(args.prompt);
72
- const optimal = getOptimalProvider(taskType, preference, {
73
- task: args.prompt
74
- });
75
- logger.info("delegate_to_model routing", {
76
- taskType,
77
- complexity: complexity.tier,
78
- score: complexity.score,
79
- provider: optimal.provider
80
- });
81
- const providerModel = args.model || optimal.model;
82
- const apiKey = process.env[optimal.apiKeyEnv] || "";
83
- if (!apiKey) {
84
- return errorResponse({
85
- errorType: "missing_api_key",
86
- message: `No API key found for ${optimal.provider} (env: ${optimal.apiKeyEnv})`,
87
- recommendation: `Set the ${optimal.apiKeyEnv} environment variable or choose a different provider.`,
88
- provider: optimal.provider
89
- });
90
- }
91
- try {
92
- const adapter = createProvider(optimal.provider, {
93
- apiKey,
94
- baseUrl: optimal.baseUrl
95
- });
96
- const messages = [{ role: "user", content: args.prompt }];
97
- const result = await adapter.complete(messages, {
98
- model: providerModel,
99
- maxTokens: args.maxTokens || 4096,
100
- temperature: args.temperature,
101
- system: args.system
102
- });
103
- const text = result.content.filter((c) => c.type === "text").map((c) => c.text).join("");
104
- return {
105
- content: [
106
- {
107
- type: "text",
108
- text: JSON.stringify(
109
- {
110
- provider: optimal.provider,
111
- model: providerModel,
112
- response: text,
113
- usage: result.usage
114
- },
115
- null,
116
- 2
117
- )
118
- }
119
- ]
120
- };
121
- } catch (error) {
122
- logger.error("delegate_to_model failed", { error: error.message });
123
- return errorResponse(classifyApiError(error, optimal.provider));
124
- }
125
- }
126
- /**
127
- * batch_submit — submit prompts to Anthropic Batch API
128
- */
129
- async handleBatchSubmit(args) {
130
- if (!isFeatureEnabled("multiProvider")) {
131
- return errorResponse({
132
- errorType: "feature_disabled",
133
- message: "Multi-provider routing is disabled.",
134
- recommendation: "Set STACKMEMORY_MULTI_PROVIDER=true to enable multi-provider routing."
135
- });
136
- }
137
- try {
138
- const batchClient = this.getBatchClient();
139
- const requests = args.prompts.map((p) => ({
140
- custom_id: p.id,
141
- params: {
142
- model: p.model || "claude-sonnet-4-5-20250929",
143
- max_tokens: p.maxTokens || 4096,
144
- messages: [{ role: "user", content: p.prompt }],
145
- system: p.system
146
- }
147
- }));
148
- const batchId = await batchClient.submit(requests, args.description);
149
- return {
150
- content: [
151
- {
152
- type: "text",
153
- text: JSON.stringify(
154
- {
155
- batchId,
156
- status: "submitted",
157
- requestCount: requests.length
158
- },
159
- null,
160
- 2
161
- )
162
- }
163
- ]
164
- };
165
- } catch (error) {
166
- return errorResponse({
167
- errorType: "batch_error",
168
- message: error.message,
169
- recommendation: "Check ANTHROPIC_API_KEY and batch request format."
170
- });
171
- }
172
- }
173
- /**
174
- * batch_check — poll status / retrieve results
175
- */
176
- async handleBatchCheck(args) {
177
- if (!isFeatureEnabled("multiProvider")) {
178
- return errorResponse({
179
- errorType: "feature_disabled",
180
- message: "Multi-provider routing is disabled.",
181
- recommendation: "Set STACKMEMORY_MULTI_PROVIDER=true to enable multi-provider routing."
182
- });
183
- }
184
- try {
185
- const batchClient = this.getBatchClient();
186
- const job = await batchClient.poll(args.batchId);
187
- if (args.retrieve && job.processing_status === "ended") {
188
- const results = await batchClient.retrieve(args.batchId);
189
- return {
190
- content: [
191
- {
192
- type: "text",
193
- text: JSON.stringify({ job, results }, null, 2)
194
- }
195
- ]
196
- };
197
- }
198
- return {
199
- content: [
200
- {
201
- type: "text",
202
- text: JSON.stringify(
203
- {
204
- batchId: args.batchId,
205
- status: job.processing_status,
206
- counts: job.request_counts,
207
- createdAt: job.created_at,
208
- endedAt: job.ended_at
209
- },
210
- null,
211
- 2
212
- )
213
- }
214
- ]
215
- };
216
- } catch (error) {
217
- return errorResponse({
218
- errorType: "batch_error",
219
- message: error.message,
220
- recommendation: "Check the batchId is valid and ANTHROPIC_API_KEY is set."
221
- });
222
- }
223
- }
224
- }
225
- export {
226
- ProviderHandlers
227
- };