@juspay/neurolink 9.40.0 → 9.42.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 (224) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +7 -1
  3. package/dist/auth/anthropicOAuth.d.ts +18 -3
  4. package/dist/auth/anthropicOAuth.js +137 -4
  5. package/dist/auth/providers/firebase.js +5 -1
  6. package/dist/auth/providers/jwt.js +5 -1
  7. package/dist/auth/providers/workos.js +5 -1
  8. package/dist/auth/sessionManager.d.ts +1 -1
  9. package/dist/auth/sessionManager.js +58 -27
  10. package/dist/browser/neurolink.min.js +471 -445
  11. package/dist/cli/commands/mcp.js +3 -0
  12. package/dist/cli/commands/proxy.d.ts +2 -1
  13. package/dist/cli/commands/proxy.js +279 -16
  14. package/dist/cli/commands/task.d.ts +56 -0
  15. package/dist/cli/commands/task.js +838 -0
  16. package/dist/cli/factories/commandFactory.d.ts +2 -0
  17. package/dist/cli/factories/commandFactory.js +38 -0
  18. package/dist/cli/parser.js +8 -4
  19. package/dist/client/aiSdkAdapter.js +3 -0
  20. package/dist/client/streamingClient.js +30 -10
  21. package/dist/core/modules/GenerationHandler.js +3 -2
  22. package/dist/core/redisConversationMemoryManager.js +7 -3
  23. package/dist/evaluation/BatchEvaluator.js +4 -1
  24. package/dist/evaluation/hooks/observabilityHooks.js +5 -3
  25. package/dist/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
  26. package/dist/evaluation/pipeline/evaluationPipeline.js +20 -8
  27. package/dist/evaluation/pipeline/strategies/batchStrategy.js +6 -3
  28. package/dist/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
  29. package/dist/lib/auth/anthropicOAuth.d.ts +18 -3
  30. package/dist/lib/auth/anthropicOAuth.js +137 -4
  31. package/dist/lib/auth/providers/firebase.js +5 -1
  32. package/dist/lib/auth/providers/jwt.js +5 -1
  33. package/dist/lib/auth/providers/workos.js +5 -1
  34. package/dist/lib/auth/sessionManager.d.ts +1 -1
  35. package/dist/lib/auth/sessionManager.js +58 -27
  36. package/dist/lib/client/aiSdkAdapter.js +3 -0
  37. package/dist/lib/client/streamingClient.js +30 -10
  38. package/dist/lib/core/modules/GenerationHandler.js +3 -2
  39. package/dist/lib/core/redisConversationMemoryManager.js +7 -3
  40. package/dist/lib/evaluation/BatchEvaluator.js +4 -1
  41. package/dist/lib/evaluation/hooks/observabilityHooks.js +5 -3
  42. package/dist/lib/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
  43. package/dist/lib/evaluation/pipeline/evaluationPipeline.js +20 -8
  44. package/dist/lib/evaluation/pipeline/strategies/batchStrategy.js +6 -3
  45. package/dist/lib/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
  46. package/dist/lib/neurolink.d.ts +18 -1
  47. package/dist/lib/neurolink.js +367 -484
  48. package/dist/lib/observability/otelBridge.d.ts +2 -2
  49. package/dist/lib/observability/otelBridge.js +12 -3
  50. package/dist/lib/providers/amazonBedrock.js +2 -4
  51. package/dist/lib/providers/anthropic.d.ts +9 -5
  52. package/dist/lib/providers/anthropic.js +19 -14
  53. package/dist/lib/providers/anthropicBaseProvider.d.ts +3 -3
  54. package/dist/lib/providers/anthropicBaseProvider.js +5 -4
  55. package/dist/lib/providers/azureOpenai.d.ts +1 -1
  56. package/dist/lib/providers/azureOpenai.js +5 -4
  57. package/dist/lib/providers/googleAiStudio.js +30 -1
  58. package/dist/lib/providers/googleVertex.js +28 -6
  59. package/dist/lib/providers/huggingFace.d.ts +3 -3
  60. package/dist/lib/providers/huggingFace.js +6 -8
  61. package/dist/lib/providers/litellm.js +41 -29
  62. package/dist/lib/providers/mistral.js +2 -1
  63. package/dist/lib/providers/ollama.js +80 -23
  64. package/dist/lib/providers/openAI.js +3 -2
  65. package/dist/lib/providers/openRouter.js +2 -1
  66. package/dist/lib/providers/openaiCompatible.d.ts +4 -4
  67. package/dist/lib/providers/openaiCompatible.js +4 -4
  68. package/dist/lib/proxy/claudeFormat.d.ts +3 -2
  69. package/dist/lib/proxy/claudeFormat.js +25 -20
  70. package/dist/lib/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
  71. package/dist/lib/proxy/cloaking/plugins/sessionIdentity.js +9 -33
  72. package/dist/lib/proxy/modelRouter.js +3 -0
  73. package/dist/lib/proxy/oauthFetch.d.ts +1 -1
  74. package/dist/lib/proxy/oauthFetch.js +65 -72
  75. package/dist/lib/proxy/proxyConfig.js +44 -24
  76. package/dist/lib/proxy/proxyEnv.d.ts +19 -0
  77. package/dist/lib/proxy/proxyEnv.js +73 -0
  78. package/dist/lib/proxy/proxyFetch.js +50 -4
  79. package/dist/lib/proxy/proxyTracer.d.ts +133 -0
  80. package/dist/lib/proxy/proxyTracer.js +645 -0
  81. package/dist/lib/proxy/rawStreamCapture.d.ts +10 -0
  82. package/dist/lib/proxy/rawStreamCapture.js +83 -0
  83. package/dist/lib/proxy/requestLogger.d.ts +32 -5
  84. package/dist/lib/proxy/requestLogger.js +406 -37
  85. package/dist/lib/proxy/sseInterceptor.d.ts +97 -0
  86. package/dist/lib/proxy/sseInterceptor.js +402 -0
  87. package/dist/lib/proxy/usageStats.d.ts +4 -3
  88. package/dist/lib/proxy/usageStats.js +25 -12
  89. package/dist/lib/rag/chunkers/MarkdownChunker.js +13 -5
  90. package/dist/lib/rag/chunking/markdownChunker.js +15 -6
  91. package/dist/lib/server/routes/claudeProxyRoutes.d.ts +7 -2
  92. package/dist/lib/server/routes/claudeProxyRoutes.js +1737 -508
  93. package/dist/lib/services/server/ai/observability/instrumentation.d.ts +7 -1
  94. package/dist/lib/services/server/ai/observability/instrumentation.js +240 -40
  95. package/dist/lib/tasks/backends/bullmqBackend.d.ts +33 -0
  96. package/dist/lib/tasks/backends/bullmqBackend.js +196 -0
  97. package/dist/lib/tasks/backends/nodeTimeoutBackend.d.ts +27 -0
  98. package/dist/lib/tasks/backends/nodeTimeoutBackend.js +141 -0
  99. package/dist/lib/tasks/backends/taskBackendRegistry.d.ts +31 -0
  100. package/dist/lib/tasks/backends/taskBackendRegistry.js +66 -0
  101. package/dist/lib/tasks/errors.d.ts +31 -0
  102. package/dist/lib/tasks/errors.js +18 -0
  103. package/dist/lib/tasks/store/fileTaskStore.d.ts +43 -0
  104. package/dist/lib/tasks/store/fileTaskStore.js +179 -0
  105. package/dist/lib/tasks/store/redisTaskStore.d.ts +43 -0
  106. package/dist/lib/tasks/store/redisTaskStore.js +197 -0
  107. package/dist/lib/tasks/taskExecutor.d.ts +21 -0
  108. package/dist/lib/tasks/taskExecutor.js +166 -0
  109. package/dist/lib/tasks/taskManager.d.ts +63 -0
  110. package/dist/lib/tasks/taskManager.js +426 -0
  111. package/dist/lib/tasks/tools/taskTools.d.ts +135 -0
  112. package/dist/lib/tasks/tools/taskTools.js +274 -0
  113. package/dist/lib/telemetry/index.d.ts +2 -1
  114. package/dist/lib/telemetry/index.js +2 -1
  115. package/dist/lib/telemetry/telemetryService.d.ts +3 -0
  116. package/dist/lib/telemetry/telemetryService.js +65 -5
  117. package/dist/lib/types/cli.d.ts +10 -0
  118. package/dist/lib/types/configTypes.d.ts +3 -0
  119. package/dist/lib/types/generateTypes.d.ts +13 -0
  120. package/dist/lib/types/index.d.ts +1 -0
  121. package/dist/lib/types/proxyTypes.d.ts +37 -5
  122. package/dist/lib/types/streamTypes.d.ts +25 -3
  123. package/dist/lib/types/taskTypes.d.ts +275 -0
  124. package/dist/lib/types/taskTypes.js +37 -0
  125. package/dist/lib/utils/messageBuilder.js +3 -2
  126. package/dist/lib/utils/providerHealth.d.ts +18 -0
  127. package/dist/lib/utils/providerHealth.js +240 -9
  128. package/dist/lib/utils/providerUtils.js +14 -8
  129. package/dist/lib/utils/toolChoice.d.ts +4 -0
  130. package/dist/lib/utils/toolChoice.js +7 -0
  131. package/dist/neurolink.d.ts +18 -1
  132. package/dist/neurolink.js +367 -484
  133. package/dist/observability/otelBridge.d.ts +2 -2
  134. package/dist/observability/otelBridge.js +12 -3
  135. package/dist/providers/amazonBedrock.js +2 -4
  136. package/dist/providers/anthropic.d.ts +9 -5
  137. package/dist/providers/anthropic.js +19 -14
  138. package/dist/providers/anthropicBaseProvider.d.ts +3 -3
  139. package/dist/providers/anthropicBaseProvider.js +5 -4
  140. package/dist/providers/azureOpenai.d.ts +1 -1
  141. package/dist/providers/azureOpenai.js +5 -4
  142. package/dist/providers/googleAiStudio.js +30 -1
  143. package/dist/providers/googleVertex.js +28 -6
  144. package/dist/providers/huggingFace.d.ts +3 -3
  145. package/dist/providers/huggingFace.js +6 -7
  146. package/dist/providers/litellm.js +41 -29
  147. package/dist/providers/mistral.js +2 -1
  148. package/dist/providers/ollama.js +80 -23
  149. package/dist/providers/openAI.js +3 -2
  150. package/dist/providers/openRouter.js +2 -1
  151. package/dist/providers/openaiCompatible.d.ts +4 -4
  152. package/dist/providers/openaiCompatible.js +4 -3
  153. package/dist/proxy/claudeFormat.d.ts +3 -2
  154. package/dist/proxy/claudeFormat.js +25 -20
  155. package/dist/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
  156. package/dist/proxy/cloaking/plugins/sessionIdentity.js +9 -33
  157. package/dist/proxy/modelRouter.js +3 -0
  158. package/dist/proxy/oauthFetch.d.ts +1 -1
  159. package/dist/proxy/oauthFetch.js +65 -72
  160. package/dist/proxy/proxyConfig.js +44 -24
  161. package/dist/proxy/proxyEnv.d.ts +19 -0
  162. package/dist/proxy/proxyEnv.js +72 -0
  163. package/dist/proxy/proxyFetch.js +50 -4
  164. package/dist/proxy/proxyTracer.d.ts +133 -0
  165. package/dist/proxy/proxyTracer.js +644 -0
  166. package/dist/proxy/rawStreamCapture.d.ts +10 -0
  167. package/dist/proxy/rawStreamCapture.js +82 -0
  168. package/dist/proxy/requestLogger.d.ts +32 -5
  169. package/dist/proxy/requestLogger.js +406 -37
  170. package/dist/proxy/sseInterceptor.d.ts +97 -0
  171. package/dist/proxy/sseInterceptor.js +401 -0
  172. package/dist/proxy/usageStats.d.ts +4 -3
  173. package/dist/proxy/usageStats.js +25 -12
  174. package/dist/rag/chunkers/MarkdownChunker.js +13 -5
  175. package/dist/rag/chunking/markdownChunker.js +15 -6
  176. package/dist/server/routes/claudeProxyRoutes.d.ts +7 -2
  177. package/dist/server/routes/claudeProxyRoutes.js +1737 -508
  178. package/dist/services/server/ai/observability/instrumentation.d.ts +7 -1
  179. package/dist/services/server/ai/observability/instrumentation.js +240 -40
  180. package/dist/tasks/backends/bullmqBackend.d.ts +33 -0
  181. package/dist/tasks/backends/bullmqBackend.js +195 -0
  182. package/dist/tasks/backends/nodeTimeoutBackend.d.ts +27 -0
  183. package/dist/tasks/backends/nodeTimeoutBackend.js +140 -0
  184. package/dist/tasks/backends/taskBackendRegistry.d.ts +31 -0
  185. package/dist/tasks/backends/taskBackendRegistry.js +65 -0
  186. package/dist/tasks/errors.d.ts +31 -0
  187. package/dist/tasks/errors.js +17 -0
  188. package/dist/tasks/store/fileTaskStore.d.ts +43 -0
  189. package/dist/tasks/store/fileTaskStore.js +178 -0
  190. package/dist/tasks/store/redisTaskStore.d.ts +43 -0
  191. package/dist/tasks/store/redisTaskStore.js +196 -0
  192. package/dist/tasks/taskExecutor.d.ts +21 -0
  193. package/dist/tasks/taskExecutor.js +165 -0
  194. package/dist/tasks/taskManager.d.ts +63 -0
  195. package/dist/tasks/taskManager.js +425 -0
  196. package/dist/tasks/tools/taskTools.d.ts +135 -0
  197. package/dist/tasks/tools/taskTools.js +273 -0
  198. package/dist/telemetry/index.d.ts +2 -1
  199. package/dist/telemetry/index.js +2 -1
  200. package/dist/telemetry/telemetryService.d.ts +3 -0
  201. package/dist/telemetry/telemetryService.js +65 -5
  202. package/dist/types/cli.d.ts +10 -0
  203. package/dist/types/configTypes.d.ts +3 -0
  204. package/dist/types/generateTypes.d.ts +13 -0
  205. package/dist/types/index.d.ts +1 -0
  206. package/dist/types/proxyTypes.d.ts +37 -5
  207. package/dist/types/streamTypes.d.ts +25 -3
  208. package/dist/types/taskTypes.d.ts +275 -0
  209. package/dist/types/taskTypes.js +36 -0
  210. package/dist/utils/messageBuilder.js +3 -2
  211. package/dist/utils/providerHealth.d.ts +18 -0
  212. package/dist/utils/providerHealth.js +240 -9
  213. package/dist/utils/providerUtils.js +14 -8
  214. package/dist/utils/toolChoice.d.ts +4 -0
  215. package/dist/utils/toolChoice.js +6 -0
  216. package/docs/assets/dashboards/neurolink-proxy-observability-dashboard.json +6609 -0
  217. package/docs/changelog.md +252 -0
  218. package/package.json +19 -1
  219. package/scripts/observability/check-proxy-telemetry.mjs +235 -0
  220. package/scripts/observability/docker-compose.proxy-observability.yaml +55 -0
  221. package/scripts/observability/import-openobserve-dashboard.mjs +240 -0
  222. package/scripts/observability/manage-local-openobserve.sh +184 -0
  223. package/scripts/observability/otel-collector.proxy-observability.yaml +78 -0
  224. package/scripts/observability/proxy-observability.env.example +23 -0
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Type definitions for the NeuroLink TaskManager system.
3
+ *
4
+ * TaskManager provides scheduled and self-running task capabilities,
5
+ * enabling AI agents to execute prompts on cron, interval, or one-shot schedules.
6
+ */
7
+ import type { Cron } from "croner";
8
+ import type { createClient } from "redis";
9
+ import type { ThinkingLevel } from "./configTypes.js";
10
+ export type TaskScheduleType = "cron" | "interval" | "once";
11
+ export type CronSchedule = {
12
+ type: "cron";
13
+ /** Standard 5-field cron expression, e.g. "0 9 * * *" */
14
+ expression: string;
15
+ /** IANA timezone, e.g. "America/New_York" */
16
+ timezone?: string;
17
+ };
18
+ export type IntervalSchedule = {
19
+ type: "interval";
20
+ /** Interval in milliseconds */
21
+ every: number;
22
+ };
23
+ export type OnceSchedule = {
24
+ type: "once";
25
+ /** ISO 8601 timestamp or Date object */
26
+ at: Date | string;
27
+ };
28
+ export type TaskSchedule = CronSchedule | IntervalSchedule | OnceSchedule;
29
+ /**
30
+ * - "isolated": Each run gets a fresh context. No memory of previous runs.
31
+ * - "continuation": Conversation history is preserved across runs.
32
+ */
33
+ export type TaskExecutionMode = "isolated" | "continuation";
34
+ export type TaskStatus = "pending" | "active" | "paused" | "completed" | "failed" | "cancelled";
35
+ export type TaskDefinition = {
36
+ name: string;
37
+ prompt: string;
38
+ schedule: TaskSchedule;
39
+ mode?: TaskExecutionMode;
40
+ provider?: string;
41
+ model?: string;
42
+ thinkingLevel?: ThinkingLevel;
43
+ systemPrompt?: string;
44
+ /** Enable/disable tools for this task. Default: true */
45
+ tools?: boolean;
46
+ maxTokens?: number;
47
+ temperature?: number;
48
+ /** Max number of executions. Omit for unlimited. */
49
+ maxRuns?: number;
50
+ /** Per-run timeout in ms. Default: 120000 */
51
+ timeout?: number;
52
+ retry?: {
53
+ /** Default: 3 */
54
+ maxAttempts?: number;
55
+ /** Default: [30000, 60000, 300000] */
56
+ backoffMs?: number[];
57
+ };
58
+ onSuccess?: (result: TaskRunResult) => void | Promise<void>;
59
+ onError?: (error: TaskRunError) => void | Promise<void>;
60
+ /** Called when task reaches a terminal state (completed, failed, cancelled) */
61
+ onComplete?: (task: Task) => void | Promise<void>;
62
+ metadata?: Record<string, unknown>;
63
+ };
64
+ export type Task = {
65
+ id: string;
66
+ name: string;
67
+ prompt: string;
68
+ schedule: TaskSchedule;
69
+ mode: TaskExecutionMode;
70
+ status: TaskStatus;
71
+ provider?: string;
72
+ model?: string;
73
+ thinkingLevel?: ThinkingLevel;
74
+ systemPrompt?: string;
75
+ tools: boolean;
76
+ maxTokens?: number;
77
+ temperature?: number;
78
+ maxRuns?: number;
79
+ timeout: number;
80
+ retry: {
81
+ maxAttempts: number;
82
+ backoffMs: number[];
83
+ };
84
+ runCount: number;
85
+ lastRunAt?: string;
86
+ nextRunAt?: string;
87
+ createdAt: string;
88
+ updatedAt: string;
89
+ /** Conversation session ID for continuation mode */
90
+ sessionId?: string;
91
+ metadata?: Record<string, unknown>;
92
+ };
93
+ /** Shape of the tasks.json file used by FileTaskStore */
94
+ export type TasksFile = {
95
+ version: number;
96
+ tasks: Record<string, Task>;
97
+ };
98
+ export type TaskRunResult = {
99
+ taskId: string;
100
+ runId: string;
101
+ status: "success" | "error";
102
+ /** AI response text */
103
+ output?: string;
104
+ toolCalls?: Array<{
105
+ name: string;
106
+ input: unknown;
107
+ output: unknown;
108
+ }>;
109
+ tokensUsed?: {
110
+ input: number;
111
+ output: number;
112
+ };
113
+ durationMs: number;
114
+ /** ISO 8601 */
115
+ timestamp: string;
116
+ error?: string;
117
+ };
118
+ export type TaskRunError = {
119
+ taskId: string;
120
+ runId: string;
121
+ error: string;
122
+ attempt: number;
123
+ maxAttempts: number;
124
+ willRetry: boolean;
125
+ /** ISO 8601 */
126
+ timestamp: string;
127
+ };
128
+ /**
129
+ * Abstracts task persistence. Auto-selected based on backend:
130
+ * - BullMQ → RedisTaskStore
131
+ * - NodeTimeout → FileTaskStore
132
+ */
133
+ export interface TaskStore {
134
+ readonly type: "redis" | "file";
135
+ initialize(): Promise<void>;
136
+ shutdown(): Promise<void>;
137
+ save(task: Task): Promise<void>;
138
+ get(taskId: string): Promise<Task | null>;
139
+ list(filter?: {
140
+ status?: TaskStatus;
141
+ }): Promise<Task[]>;
142
+ update(taskId: string, updates: Partial<Task>): Promise<Task>;
143
+ delete(taskId: string): Promise<void>;
144
+ appendRun(taskId: string, run: TaskRunResult): Promise<void>;
145
+ getRuns(taskId: string, options?: {
146
+ limit?: number;
147
+ status?: string;
148
+ }): Promise<TaskRunResult[]>;
149
+ appendHistory(taskId: string, messages: ConversationEntry[]): Promise<void>;
150
+ getHistory(taskId: string): Promise<ConversationEntry[]>;
151
+ clearHistory(taskId: string): Promise<void>;
152
+ }
153
+ export type ConversationEntry = {
154
+ role: "user" | "assistant";
155
+ content: string;
156
+ timestamp: string;
157
+ };
158
+ export type TaskExecutorFn = (task: Task) => Promise<TaskRunResult>;
159
+ /**
160
+ * Abstracts the scheduling/looping mechanism.
161
+ * Implementations: BullMQ (production), NodeTimeout (development).
162
+ */
163
+ export interface TaskBackend {
164
+ readonly name: string;
165
+ initialize(): Promise<void>;
166
+ shutdown(): Promise<void>;
167
+ /** Schedule a task for execution */
168
+ schedule(task: Task, executor: TaskExecutorFn): Promise<void>;
169
+ /** Cancel a scheduled task */
170
+ cancel(taskId: string): Promise<void>;
171
+ /** Pause a task's schedule */
172
+ pause(taskId: string): Promise<void>;
173
+ /** Resume a paused task */
174
+ resume(taskId: string): Promise<void>;
175
+ /** Check if backend is operational */
176
+ isHealthy(): Promise<boolean>;
177
+ }
178
+ /** Redis client type used by RedisTaskStore */
179
+ export type RedisClient = ReturnType<typeof createClient>;
180
+ /** Minimal interface for the NeuroLink SDK methods needed by TaskExecutor */
181
+ export type NeuroLinkExecutable = {
182
+ generate(optionsOrPrompt: unknown): Promise<{
183
+ content: string;
184
+ toolExecutions?: Array<{
185
+ name: string;
186
+ input: unknown;
187
+ output: unknown;
188
+ }>;
189
+ usage?: {
190
+ input?: number;
191
+ output?: number;
192
+ };
193
+ }>;
194
+ };
195
+ /** Internal scheduling entry used by NodeTimeoutBackend */
196
+ export type ScheduledEntry = {
197
+ taskId: string;
198
+ executor: TaskExecutorFn;
199
+ task: Task;
200
+ cronJob?: Cron;
201
+ intervalId?: ReturnType<typeof setInterval>;
202
+ timeoutId?: ReturnType<typeof setTimeout>;
203
+ };
204
+ export type TaskBackendName = "bullmq" | "node-timeout";
205
+ export type TaskBackendFactoryFn = (config: TaskManagerConfig) => Promise<TaskBackend>;
206
+ export type TaskRetentionConfig = {
207
+ /** Auto-delete completed tasks after N ms. Default: 30 days */
208
+ completedTTL?: number;
209
+ /** Auto-delete failed tasks after N ms. Default: 7 days */
210
+ failedTTL?: number;
211
+ /** Auto-delete cancelled tasks after N ms. Default: 7 days */
212
+ cancelledTTL?: number;
213
+ /** Auto-expire individual run log entries after N ms. Default: 30 days */
214
+ runLogTTL?: number;
215
+ };
216
+ export type TaskManagerConfig = {
217
+ /** Default: true */
218
+ enabled?: boolean;
219
+ /** Default: "bullmq" */
220
+ backend?: TaskBackendName;
221
+ redis?: {
222
+ host?: string;
223
+ port?: number;
224
+ password?: string;
225
+ db?: number;
226
+ /** Alternative: full Redis URL */
227
+ url?: string;
228
+ };
229
+ /** Default: ".neurolink/tasks/tasks.json" */
230
+ storePath?: string;
231
+ /** Default: ".neurolink/tasks/runs/" */
232
+ logsPath?: string;
233
+ /** Maximum number of tasks that can exist at once. Default: 100 */
234
+ maxTasks?: number;
235
+ /** Default: 5 */
236
+ maxConcurrentRuns?: number;
237
+ /** Max run log entries per task. Default: 2000 */
238
+ maxRunLogs?: number;
239
+ /** Max continuation history entries per task. Default: 200 (100 exchanges) */
240
+ maxHistoryEntries?: number;
241
+ taskRetention?: TaskRetentionConfig;
242
+ };
243
+ export declare const TASK_DEFAULTS: {
244
+ readonly enabled: true;
245
+ readonly maxTasks: 100;
246
+ readonly backend: TaskBackendName;
247
+ readonly mode: TaskExecutionMode;
248
+ readonly timeout: 120000;
249
+ readonly maxConcurrentRuns: 5;
250
+ readonly maxRunLogs: 2000;
251
+ readonly maxHistoryEntries: 200;
252
+ readonly tools: true;
253
+ readonly retry: {
254
+ readonly maxAttempts: 3;
255
+ readonly backoffMs: readonly [30000, 60000, 300000];
256
+ };
257
+ readonly storePath: ".neurolink/tasks/tasks.json";
258
+ readonly logsPath: ".neurolink/tasks/runs/";
259
+ readonly redis: {
260
+ readonly host: "localhost";
261
+ readonly port: 6379;
262
+ };
263
+ readonly retention: {
264
+ readonly completedTTL: number;
265
+ readonly failedTTL: number;
266
+ readonly cancelledTTL: number;
267
+ readonly runLogTTL: number;
268
+ };
269
+ };
270
+ /** State persisted by the CLI task worker daemon */
271
+ export type WorkerState = {
272
+ pid: number;
273
+ startedAt: string;
274
+ logFile: string;
275
+ };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Type definitions for the NeuroLink TaskManager system.
3
+ *
4
+ * TaskManager provides scheduled and self-running task capabilities,
5
+ * enabling AI agents to execute prompts on cron, interval, or one-shot schedules.
6
+ */
7
+ // ── Defaults ────────────────────────────────────────────
8
+ const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000;
9
+ const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
10
+ export const TASK_DEFAULTS = {
11
+ enabled: true,
12
+ maxTasks: 100,
13
+ backend: "bullmq",
14
+ mode: "isolated",
15
+ timeout: 120_000,
16
+ maxConcurrentRuns: 5,
17
+ maxRunLogs: 2000,
18
+ maxHistoryEntries: 200,
19
+ tools: true,
20
+ retry: {
21
+ maxAttempts: 3,
22
+ backoffMs: [30_000, 60_000, 300_000],
23
+ },
24
+ storePath: ".neurolink/tasks/tasks.json",
25
+ logsPath: ".neurolink/tasks/runs/",
26
+ redis: {
27
+ host: "localhost",
28
+ port: 6379,
29
+ },
30
+ retention: {
31
+ completedTTL: THIRTY_DAYS_MS,
32
+ failedTTL: SEVEN_DAYS_MS,
33
+ cancelledTTL: SEVEN_DAYS_MS,
34
+ runLogTTL: THIRTY_DAYS_MS,
35
+ },
36
+ };
@@ -775,6 +775,7 @@ async function processUnifiedFilesArray(options, maxSize, provider) {
775
775
  return;
776
776
  }
777
777
  const totalFiles = options.input.files.length;
778
+ const files = options.input.files;
778
779
  return withSpan({
779
780
  name: "neurolink.file.process_all",
780
781
  tracer: tracers.file,
@@ -787,8 +788,8 @@ async function processUnifiedFilesArray(options, maxSize, provider) {
787
788
  options.input.text = options.input.text || "";
788
789
  let includedCount = 0;
789
790
  const fileRegistry = options.fileRegistry;
790
- for (let fileIdx = 0; fileIdx < options.input.files.length; fileIdx++) {
791
- const file = options.input.files[fileIdx];
791
+ for (let fileIdx = 0; fileIdx < files.length; fileIdx++) {
792
+ const file = files[fileIdx];
792
793
  const filename = extractFilename(file, fileIdx);
793
794
  try {
794
795
  // ─── Lazy file registration path ──────────────────────────────
@@ -98,6 +98,20 @@ export declare class ProviderHealthChecker {
98
98
  * Check Azure OpenAI configuration
99
99
  */
100
100
  private static checkAzureConfig;
101
+ private static getLiteLLMBaseUrl;
102
+ private static getLiteLLMModelsUrl;
103
+ private static getConfiguredLiteLLMModel;
104
+ private static getOllamaBaseUrl;
105
+ private static getOllamaTagsUrl;
106
+ private static getConfiguredOllamaModel;
107
+ private static fetchJsonWithTimeout;
108
+ private static normalizeModelList;
109
+ private static hasRequestedModel;
110
+ private static getOllamaAvailableModels;
111
+ private static getLiteLLMAvailableModels;
112
+ private static checkOllamaAvailability;
113
+ private static checkLiteLLMAvailability;
114
+ private static checkLiteLLMConfig;
101
115
  /**
102
116
  * Check Ollama configuration
103
117
  */
@@ -169,6 +183,10 @@ export declare class ProviderHealthChecker {
169
183
  * Clear health cache for a provider or all providers
170
184
  */
171
185
  static clearHealthCache(providerName?: AIProviderName): void;
186
+ static checkFallbackProviderAvailability(providerName: string, model: string): Promise<{
187
+ available: boolean;
188
+ reason?: string;
189
+ }>;
172
190
  /**
173
191
  * Get the best healthy provider from a list of options (NON-BLOCKING)
174
192
  * Prioritizes healthy providers over configured but unhealthy ones
@@ -228,7 +228,8 @@ export class ProviderHealthChecker {
228
228
  }
229
229
  // Providers that don't use API keys directly
230
230
  if (providerName === AIProviderName.OLLAMA ||
231
- providerName === AIProviderName.BEDROCK) {
231
+ providerName === AIProviderName.BEDROCK ||
232
+ providerName === AIProviderName.LITELLM) {
232
233
  healthStatus.hasApiKey = true;
233
234
  return;
234
235
  }
@@ -368,6 +369,8 @@ export class ProviderHealthChecker {
368
369
  return [];
369
370
  case AIProviderName.AZURE:
370
371
  return ["AZURE_OPENAI_API_KEY", "AZURE_OPENAI_ENDPOINT"];
372
+ case AIProviderName.LITELLM:
373
+ return [];
371
374
  case AIProviderName.OLLAMA:
372
375
  return []; // Ollama typically doesn't require API keys
373
376
  default:
@@ -391,8 +394,10 @@ export class ProviderHealthChecker {
391
394
  return "AWS_ACCESS_KEY_ID";
392
395
  case AIProviderName.AZURE:
393
396
  return "AZURE_OPENAI_API_KEY";
397
+ case AIProviderName.LITELLM:
398
+ return "LITELLM_API_KEY";
394
399
  case AIProviderName.OLLAMA:
395
- return "OLLAMA_API_BASE";
400
+ return "OLLAMA_BASE_URL";
396
401
  default:
397
402
  return "";
398
403
  }
@@ -416,6 +421,8 @@ export class ProviderHealthChecker {
416
421
  return apiKey.length >= API_KEY_LENGTHS.AWS_ACCESS_KEY; // AWS access key length
417
422
  case AIProviderName.AZURE:
418
423
  return apiKey.length >= API_KEY_LENGTHS.AZURE_MIN; // Azure OpenAI API key length
424
+ case AIProviderName.LITELLM:
425
+ return apiKey.length > 0;
419
426
  case AIProviderName.OLLAMA:
420
427
  return true; // Ollama usually doesn't require specific format
421
428
  default:
@@ -437,8 +444,10 @@ export class ProviderHealthChecker {
437
444
  return null; // Complex authentication required
438
445
  case AIProviderName.BEDROCK:
439
446
  return null; // AWS endpoints vary by region
447
+ case AIProviderName.LITELLM:
448
+ return this.getLiteLLMModelsUrl();
440
449
  case AIProviderName.OLLAMA:
441
- return "http://localhost:11434/api/version";
450
+ return this.getOllamaTagsUrl();
442
451
  default:
443
452
  return null;
444
453
  }
@@ -457,6 +466,9 @@ export class ProviderHealthChecker {
457
466
  case AIProviderName.AZURE:
458
467
  await this.checkAzureConfig(healthStatus);
459
468
  break;
469
+ case AIProviderName.LITELLM:
470
+ await this.checkLiteLLMConfig(healthStatus);
471
+ break;
460
472
  case AIProviderName.OLLAMA:
461
473
  await this.checkOllamaConfig(healthStatus);
462
474
  break;
@@ -648,15 +660,177 @@ export class ProviderHealthChecker {
648
660
  healthStatus.recommendations.push("Set one of: AZURE_OPENAI_MODEL, AZURE_OPENAI_DEPLOYMENT, or AZURE_OPENAI_DEPLOYMENT_ID");
649
661
  }
650
662
  }
663
+ static getLiteLLMBaseUrl() {
664
+ return process.env.LITELLM_BASE_URL || "http://localhost:4000";
665
+ }
666
+ static getLiteLLMModelsUrl() {
667
+ return new URL("/v1/models", this.getLiteLLMBaseUrl()).toString();
668
+ }
669
+ static getConfiguredLiteLLMModel() {
670
+ return process.env.LITELLM_MODEL || "openai/gpt-4o-mini";
671
+ }
672
+ static getOllamaBaseUrl() {
673
+ return (process.env.OLLAMA_BASE_URL ||
674
+ process.env.OLLAMA_API_BASE ||
675
+ "http://localhost:11434");
676
+ }
677
+ static getOllamaTagsUrl() {
678
+ return new URL("/api/tags", this.getOllamaBaseUrl()).toString();
679
+ }
680
+ static getConfiguredOllamaModel() {
681
+ return process.env.OLLAMA_MODEL || "llama3.1:8b";
682
+ }
683
+ static async fetchJsonWithTimeout(url, options = {}) {
684
+ const controller = new AbortController();
685
+ const timeoutId = setTimeout(() => controller.abort(), options.timeout ?? this.DEFAULT_TIMEOUT);
686
+ try {
687
+ const proxyFetch = createProxyFetch();
688
+ const response = await proxyFetch(url, {
689
+ method: "GET",
690
+ headers: options.headers,
691
+ signal: controller.signal,
692
+ });
693
+ if (!response.ok) {
694
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
695
+ }
696
+ return await response.json();
697
+ }
698
+ finally {
699
+ clearTimeout(timeoutId);
700
+ }
701
+ }
702
+ static normalizeModelList(models) {
703
+ return models
704
+ .map((entry) => {
705
+ if (typeof entry === "string") {
706
+ return entry;
707
+ }
708
+ if (entry &&
709
+ typeof entry === "object" &&
710
+ "id" in entry &&
711
+ typeof entry.id === "string") {
712
+ return entry.id;
713
+ }
714
+ if (entry &&
715
+ typeof entry === "object" &&
716
+ "name" in entry &&
717
+ typeof entry.name === "string") {
718
+ return entry.name;
719
+ }
720
+ return null;
721
+ })
722
+ .filter((model) => typeof model === "string");
723
+ }
724
+ static hasRequestedModel(availableModels, requestedModel) {
725
+ return availableModels.some((model) => model === requestedModel ||
726
+ model.startsWith(`${requestedModel}:`) ||
727
+ requestedModel.startsWith(`${model}:`));
728
+ }
729
+ static async getOllamaAvailableModels(timeout = 2000) {
730
+ const payload = (await this.fetchJsonWithTimeout(this.getOllamaTagsUrl(), {
731
+ timeout,
732
+ }));
733
+ return this.normalizeModelList(payload.models ?? []);
734
+ }
735
+ static async getLiteLLMAvailableModels(timeout = 2000) {
736
+ const payload = (await this.fetchJsonWithTimeout(this.getLiteLLMModelsUrl(), {
737
+ timeout,
738
+ headers: {
739
+ Authorization: `Bearer ${process.env.LITELLM_API_KEY || "sk-anything"}`,
740
+ "Content-Type": "application/json",
741
+ },
742
+ }));
743
+ return this.normalizeModelList(payload.data ?? []);
744
+ }
745
+ static async checkOllamaAvailability(options) {
746
+ try {
747
+ const models = await this.getOllamaAvailableModels(options.timeout);
748
+ if (!this.hasRequestedModel(models, options.model)) {
749
+ return {
750
+ available: false,
751
+ reason: `Configured Ollama model '${options.model}' is not installed`,
752
+ models,
753
+ };
754
+ }
755
+ return { available: true, models };
756
+ }
757
+ catch (error) {
758
+ return {
759
+ available: false,
760
+ reason: error instanceof Error ? error.message : String(error),
761
+ models: [],
762
+ };
763
+ }
764
+ }
765
+ static async checkLiteLLMAvailability(options) {
766
+ try {
767
+ const models = await this.getLiteLLMAvailableModels(options.timeout);
768
+ if (models.length === 0) {
769
+ return {
770
+ available: false,
771
+ reason: "LiteLLM returned an empty model list",
772
+ models,
773
+ };
774
+ }
775
+ if (!this.hasRequestedModel(models, options.model)) {
776
+ return {
777
+ available: false,
778
+ reason: `Configured LiteLLM model '${options.model}' is not exposed by the proxy`,
779
+ models,
780
+ };
781
+ }
782
+ return { available: true, models };
783
+ }
784
+ catch (error) {
785
+ return {
786
+ available: false,
787
+ reason: error instanceof Error ? error.message : String(error),
788
+ models: [],
789
+ };
790
+ }
791
+ }
792
+ static async checkLiteLLMConfig(healthStatus) {
793
+ const liteLLMBase = this.getLiteLLMBaseUrl();
794
+ if (!liteLLMBase.startsWith("http")) {
795
+ healthStatus.isConfigured = false;
796
+ healthStatus.configurationIssues.push("Invalid LITELLM_BASE_URL format");
797
+ healthStatus.recommendations.push("Set LITELLM_BASE_URL to a valid URL (e.g., http://localhost:4000)");
798
+ return;
799
+ }
800
+ const availability = await this.checkLiteLLMAvailability({
801
+ model: this.getConfiguredLiteLLMModel(),
802
+ timeout: 2000,
803
+ });
804
+ if (!availability.available) {
805
+ healthStatus.isConfigured = false;
806
+ healthStatus.configurationIssues.push(`LiteLLM runtime check failed: ${availability.reason ?? "unknown error"}`);
807
+ healthStatus.recommendations.push("Start the LiteLLM proxy and ensure the configured model is available from /v1/models");
808
+ return;
809
+ }
810
+ healthStatus.isConfigured = true;
811
+ }
651
812
  /**
652
813
  * Check Ollama configuration
653
814
  */
654
815
  static async checkOllamaConfig(healthStatus) {
655
- const ollamaBase = process.env.OLLAMA_API_BASE || "http://localhost:11434";
816
+ const ollamaBase = this.getOllamaBaseUrl();
656
817
  if (!ollamaBase.startsWith("http")) {
657
- healthStatus.configurationIssues.push("Invalid OLLAMA_API_BASE format");
658
- healthStatus.recommendations.push("Set OLLAMA_API_BASE to a valid URL (e.g., http://localhost:11434)");
818
+ healthStatus.isConfigured = false;
819
+ healthStatus.configurationIssues.push("Invalid OLLAMA_BASE_URL format (OLLAMA_API_BASE is still accepted as a legacy alias)");
820
+ healthStatus.recommendations.push("Set OLLAMA_BASE_URL to a valid URL (e.g., http://localhost:11434). OLLAMA_API_BASE remains supported as a legacy alias.");
821
+ return;
659
822
  }
823
+ const availability = await this.checkOllamaAvailability({
824
+ model: this.getConfiguredOllamaModel(),
825
+ timeout: 2000,
826
+ });
827
+ if (!availability.available) {
828
+ healthStatus.isConfigured = false;
829
+ healthStatus.configurationIssues.push(`Ollama runtime check failed: ${availability.reason ?? "unknown error"}`);
830
+ healthStatus.recommendations.push("Start Ollama and install the configured model before using Ollama as a fallback provider");
831
+ return;
832
+ }
833
+ healthStatus.isConfigured = true;
660
834
  }
661
835
  /**
662
836
  * Get common models for a provider
@@ -703,8 +877,21 @@ export class ProviderHealthChecker {
703
877
  return [BedrockModels.CLAUDE_3_SONNET, BedrockModels.CLAUDE_3_HAIKU];
704
878
  case AIProviderName.AZURE:
705
879
  return [OpenAIModels.GPT_4O, OpenAIModels.GPT_4O_MINI, "gpt-35-turbo"];
706
- case AIProviderName.OLLAMA:
707
- return ["llama3.2:latest", "llama3.1:latest", "mistral:latest"];
880
+ case AIProviderName.LITELLM:
881
+ return [
882
+ "openai/gpt-4o-mini",
883
+ "anthropic/claude-3-haiku",
884
+ "google/gemini-2.5-flash",
885
+ ];
886
+ case AIProviderName.OLLAMA: {
887
+ const envModel = process.env.OLLAMA_MODEL;
888
+ const defaults = [
889
+ "llama3.2:latest",
890
+ "llama3.1:latest",
891
+ "mistral:latest",
892
+ ];
893
+ return envModel ? [envModel, ...defaults] : defaults;
894
+ }
708
895
  default:
709
896
  return [];
710
897
  }
@@ -1139,18 +1326,61 @@ export class ProviderHealthChecker {
1139
1326
  this.consecutiveFailures.clear();
1140
1327
  }
1141
1328
  }
1329
+ static async checkFallbackProviderAvailability(providerName, model) {
1330
+ const provider = providerName;
1331
+ if (provider === AIProviderName.OLLAMA) {
1332
+ const availability = await this.checkOllamaAvailability({
1333
+ model,
1334
+ timeout: 2000,
1335
+ });
1336
+ return {
1337
+ available: availability.available,
1338
+ reason: availability.reason,
1339
+ };
1340
+ }
1341
+ if (provider === AIProviderName.LITELLM) {
1342
+ const availability = await this.checkLiteLLMAvailability({
1343
+ model,
1344
+ timeout: 2000,
1345
+ });
1346
+ return {
1347
+ available: availability.available,
1348
+ reason: availability.reason,
1349
+ };
1350
+ }
1351
+ try {
1352
+ const health = await this.checkProviderHealth(provider, {
1353
+ includeConnectivityTest: false,
1354
+ cacheResults: true,
1355
+ maxCacheAge: 15_000,
1356
+ timeout: 2000,
1357
+ });
1358
+ return {
1359
+ available: health.isHealthy,
1360
+ reason: health.error || health.configurationIssues[0] || health.warning,
1361
+ };
1362
+ }
1363
+ catch (error) {
1364
+ return {
1365
+ available: false,
1366
+ reason: error instanceof Error ? error.message : String(error),
1367
+ };
1368
+ }
1369
+ }
1142
1370
  /**
1143
1371
  * Get the best healthy provider from a list of options (NON-BLOCKING)
1144
1372
  * Prioritizes healthy providers over configured but unhealthy ones
1145
1373
  * Uses fast, cached health checks to avoid blocking initialization
1146
1374
  */
1147
1375
  static async getBestHealthyProvider(preferredProviders = [
1376
+ "litellm",
1377
+ "ollama",
1148
1378
  "openai",
1149
1379
  "anthropic",
1150
1380
  "vertex",
1381
+ "google-ai",
1151
1382
  "bedrock",
1152
1383
  "azure",
1153
- "google-ai",
1154
1384
  ]) {
1155
1385
  const healthStatuses = await this.checkAllProvidersHealth({
1156
1386
  includeConnectivityTest: false, // Quick config check only
@@ -1191,6 +1421,7 @@ export class ProviderHealthChecker {
1191
1421
  AIProviderName.OPENAI,
1192
1422
  AIProviderName.BEDROCK,
1193
1423
  AIProviderName.AZURE,
1424
+ AIProviderName.LITELLM,
1194
1425
  AIProviderName.OLLAMA,
1195
1426
  ];
1196
1427
  const healthChecks = providers.map((provider) => this.checkProviderHealth(provider, options));