@witqq/agent-sdk 0.7.0 → 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 (147) hide show
  1. package/README.md +140 -34
  2. package/dist/{types-CqvUAYxt.d.cts → agent-CW9XbmG_.d.ts} +137 -102
  3. package/dist/{types-CqvUAYxt.d.ts → agent-DxY68NZL.d.cts} +137 -102
  4. package/dist/auth/index.cjs +72 -1
  5. package/dist/auth/index.cjs.map +1 -1
  6. package/dist/auth/index.d.cts +21 -154
  7. package/dist/auth/index.d.ts +21 -154
  8. package/dist/auth/index.js +72 -1
  9. package/dist/auth/index.js.map +1 -1
  10. package/dist/backends/claude.cjs +480 -261
  11. package/dist/backends/claude.cjs.map +1 -1
  12. package/dist/backends/claude.d.cts +3 -1
  13. package/dist/backends/claude.d.ts +3 -1
  14. package/dist/backends/claude.js +480 -261
  15. package/dist/backends/claude.js.map +1 -1
  16. package/dist/backends/copilot.cjs +329 -97
  17. package/dist/backends/copilot.cjs.map +1 -1
  18. package/dist/backends/copilot.d.cts +12 -4
  19. package/dist/backends/copilot.d.ts +12 -4
  20. package/dist/backends/copilot.js +329 -97
  21. package/dist/backends/copilot.js.map +1 -1
  22. package/dist/backends/vercel-ai.cjs +294 -61
  23. package/dist/backends/vercel-ai.cjs.map +1 -1
  24. package/dist/backends/vercel-ai.d.cts +3 -1
  25. package/dist/backends/vercel-ai.d.ts +3 -1
  26. package/dist/backends/vercel-ai.js +294 -61
  27. package/dist/backends/vercel-ai.js.map +1 -1
  28. package/dist/backends-BSrsBYFn.d.cts +39 -0
  29. package/dist/backends-BSrsBYFn.d.ts +39 -0
  30. package/dist/chat/accumulator.cjs +1 -1
  31. package/dist/chat/accumulator.cjs.map +1 -1
  32. package/dist/chat/accumulator.d.cts +5 -2
  33. package/dist/chat/accumulator.d.ts +5 -2
  34. package/dist/chat/accumulator.js +1 -1
  35. package/dist/chat/accumulator.js.map +1 -1
  36. package/dist/chat/backends.cjs +736 -746
  37. package/dist/chat/backends.cjs.map +1 -1
  38. package/dist/chat/backends.d.cts +10 -6
  39. package/dist/chat/backends.d.ts +10 -6
  40. package/dist/chat/backends.js +736 -725
  41. package/dist/chat/backends.js.map +1 -1
  42. package/dist/chat/context.cjs +50 -0
  43. package/dist/chat/context.cjs.map +1 -1
  44. package/dist/chat/context.d.cts +27 -3
  45. package/dist/chat/context.d.ts +27 -3
  46. package/dist/chat/context.js +50 -0
  47. package/dist/chat/context.js.map +1 -1
  48. package/dist/chat/core.cjs +25 -2
  49. package/dist/chat/core.cjs.map +1 -1
  50. package/dist/chat/core.d.cts +30 -381
  51. package/dist/chat/core.d.ts +30 -381
  52. package/dist/chat/core.js +24 -3
  53. package/dist/chat/core.js.map +1 -1
  54. package/dist/chat/errors.cjs +48 -26
  55. package/dist/chat/errors.cjs.map +1 -1
  56. package/dist/chat/errors.d.cts +6 -31
  57. package/dist/chat/errors.d.ts +6 -31
  58. package/dist/chat/errors.js +48 -25
  59. package/dist/chat/errors.js.map +1 -1
  60. package/dist/chat/events.cjs.map +1 -1
  61. package/dist/chat/events.d.cts +6 -2
  62. package/dist/chat/events.d.ts +6 -2
  63. package/dist/chat/events.js.map +1 -1
  64. package/dist/chat/index.cjs +1199 -1008
  65. package/dist/chat/index.cjs.map +1 -1
  66. package/dist/chat/index.d.cts +35 -10
  67. package/dist/chat/index.d.ts +35 -10
  68. package/dist/chat/index.js +1196 -987
  69. package/dist/chat/index.js.map +1 -1
  70. package/dist/chat/react/theme.css +2517 -0
  71. package/dist/chat/react.cjs +2003 -1153
  72. package/dist/chat/react.cjs.map +1 -1
  73. package/dist/chat/react.d.cts +590 -121
  74. package/dist/chat/react.d.ts +590 -121
  75. package/dist/chat/react.js +1984 -1151
  76. package/dist/chat/react.js.map +1 -1
  77. package/dist/chat/runtime.cjs +401 -186
  78. package/dist/chat/runtime.cjs.map +1 -1
  79. package/dist/chat/runtime.d.cts +92 -28
  80. package/dist/chat/runtime.d.ts +92 -28
  81. package/dist/chat/runtime.js +401 -186
  82. package/dist/chat/runtime.js.map +1 -1
  83. package/dist/chat/server.cjs +2234 -209
  84. package/dist/chat/server.cjs.map +1 -1
  85. package/dist/chat/server.d.cts +451 -90
  86. package/dist/chat/server.d.ts +451 -90
  87. package/dist/chat/server.js +2221 -210
  88. package/dist/chat/server.js.map +1 -1
  89. package/dist/chat/sessions.cjs +25 -43
  90. package/dist/chat/sessions.cjs.map +1 -1
  91. package/dist/chat/sessions.d.cts +37 -118
  92. package/dist/chat/sessions.d.ts +37 -118
  93. package/dist/chat/sessions.js +25 -43
  94. package/dist/chat/sessions.js.map +1 -1
  95. package/dist/chat/sqlite.cjs +441 -0
  96. package/dist/chat/sqlite.cjs.map +1 -0
  97. package/dist/chat/sqlite.d.cts +128 -0
  98. package/dist/chat/sqlite.d.ts +128 -0
  99. package/dist/chat/sqlite.js +435 -0
  100. package/dist/chat/sqlite.js.map +1 -0
  101. package/dist/chat/state.cjs +14 -1
  102. package/dist/chat/state.cjs.map +1 -1
  103. package/dist/chat/state.d.cts +5 -2
  104. package/dist/chat/state.d.ts +5 -2
  105. package/dist/chat/state.js +14 -1
  106. package/dist/chat/state.js.map +1 -1
  107. package/dist/chat/storage.cjs +19 -10
  108. package/dist/chat/storage.cjs.map +1 -1
  109. package/dist/chat/storage.d.cts +11 -5
  110. package/dist/chat/storage.d.ts +11 -5
  111. package/dist/chat/storage.js +19 -10
  112. package/dist/chat/storage.js.map +1 -1
  113. package/dist/errors-C-so0M4t.d.cts +33 -0
  114. package/dist/errors-C-so0M4t.d.ts +33 -0
  115. package/dist/errors-CmVvczxZ.d.cts +28 -0
  116. package/dist/errors-CmVvczxZ.d.ts +28 -0
  117. package/dist/{in-process-transport-C2oPTYs6.d.ts → in-process-transport-C1JnJGVR.d.ts} +28 -23
  118. package/dist/{in-process-transport-DG-w5G6k.d.cts → in-process-transport-C7DSqPyX.d.cts} +28 -23
  119. package/dist/index.cjs +340 -46
  120. package/dist/index.cjs.map +1 -1
  121. package/dist/index.d.cts +292 -123
  122. package/dist/index.d.ts +292 -123
  123. package/dist/index.js +334 -47
  124. package/dist/index.js.map +1 -1
  125. package/dist/provider-types-PTSlRPNB.d.cts +39 -0
  126. package/dist/provider-types-PTSlRPNB.d.ts +39 -0
  127. package/dist/refresh-manager-B81PpYBr.d.cts +153 -0
  128. package/dist/refresh-manager-Dlv_iNZi.d.ts +153 -0
  129. package/dist/testing.cjs +383 -0
  130. package/dist/testing.cjs.map +1 -0
  131. package/dist/testing.d.cts +132 -0
  132. package/dist/testing.d.ts +132 -0
  133. package/dist/testing.js +377 -0
  134. package/dist/testing.js.map +1 -0
  135. package/dist/token-store-CSUBgYwn.d.ts +48 -0
  136. package/dist/token-store-CuC4hB9Z.d.cts +48 -0
  137. package/dist/{transport-DX1Nhm4N.d.cts → transport-Cdh3M0tS.d.cts} +5 -4
  138. package/dist/{transport-D1OaUgRk.d.ts → transport-Ciap4PWK.d.ts} +5 -4
  139. package/dist/{types-CGF7AEX1.d.cts → types-4vbcmPTp.d.cts} +4 -2
  140. package/dist/{types-Bh5AhqD-.d.ts → types-BxggH0Yh.d.ts} +4 -2
  141. package/dist/types-DRgd_9R7.d.cts +363 -0
  142. package/dist/types-ajANVzf7.d.ts +363 -0
  143. package/package.json +31 -6
  144. package/dist/errors-BDLbNu9w.d.cts +0 -13
  145. package/dist/errors-BDLbNu9w.d.ts +0 -13
  146. package/dist/types-DLZzlJxt.d.ts +0 -39
  147. package/dist/types-tE0CXwBl.d.cts +0 -39
@@ -1,46 +1,130 @@
1
- import { IChatRuntime } from './runtime.js';
2
- import { W as WritableResponse$1 } from '../transport-D1OaUgRk.js';
3
- import { A as AuthToken, d as CopilotAuthToken, C as ClaudeAuthToken } from '../types-Bh5AhqD-.js';
4
- import './core.js';
5
- import '../types-CqvUAYxt.js';
6
- import 'zod';
7
- import '../types-DLZzlJxt.js';
1
+ import { IChatRuntime, ChatRuntimeOptions } from './runtime.js';
2
+ import { W as WritableResponse, I as IChatTransport } from '../transport-Ciap4PWK.js';
3
+ import { I as IProviderStore, P as ProviderConfig } from '../provider-types-PTSlRPNB.js';
4
+ import { I as ITokenStore } from '../token-store-CSUBgYwn.js';
5
+ export { F as FileTokenStore, a as FileTokenStoreOptions, b as InMemoryTokenStore } from '../token-store-CSUBgYwn.js';
6
+ import { M as ModelInfo } from '../agent-CW9XbmG_.js';
7
+ import { C as CopilotAuthToken, b as ClaudeAuthToken, A as AuthToken } from '../types-BxggH0Yh.js';
8
+ import { b as TokenRefreshOptions, a as TokenRefreshManager } from '../refresh-manager-Dlv_iNZi.js';
9
+ import '../types-ajANVzf7.js';
10
+ import '../errors-C-so0M4t.js';
8
11
  import './sessions.js';
9
12
  import './storage.js';
10
- import '../errors-BDLbNu9w.js';
13
+ import '../errors-CmVvczxZ.js';
14
+ import 'zod';
11
15
  import './context.js';
12
16
 
13
17
  /**
14
- * createChatHandler maps RemoteChatRuntime contract endpoints to IChatRuntime calls.
18
+ * Provider storage default implementations.
15
19
  *
16
- * Implements all 10 routes from the RemoteChatRuntime server endpoint contract:
17
- * - POST /sessions/create → runtime.createSession()
18
- * - GET /sessions/{id} → runtime.getSession()
19
- * - GET /sessions → runtime.listSessions()
20
- * - DELETE /sessions/{id} → runtime.deleteSession()
21
- * - POST /sessions/{id}/archive → runtime.archiveSession()
22
- * - POST /send → runtime.send() via SSE
23
- * - POST /abort → runtime.abort()
24
- * - GET /models → runtime.listModels()
25
- * - POST /backend/switch → runtime.switchBackend()
26
- * - POST /model/switch → runtime.switchModel()
20
+ * Types (ProviderConfig, IProviderStore) are defined in ../provider-types.ts
21
+ * and re-exported here for backward compatibility.
22
+ */
23
+
24
+ /** In-memory provider store for testing and ephemeral use */
25
+ declare class InMemoryProviderStore implements IProviderStore {
26
+ private readonly providers;
27
+ create(config: ProviderConfig): Promise<void>;
28
+ get(id: string): Promise<ProviderConfig | null>;
29
+ update(id: string, changes: Partial<Omit<ProviderConfig, "id" | "createdAt">>): Promise<void>;
30
+ delete(id: string): Promise<void>;
31
+ list(): Promise<ProviderConfig[]>;
32
+ }
33
+ /** Options for FileProviderStore */
34
+ interface FileProviderStoreOptions {
35
+ /** Directory to store provider JSON files */
36
+ directory: string;
37
+ }
38
+ /** Filesystem-based provider store using JSON files (one per provider) */
39
+ declare class FileProviderStore implements IProviderStore {
40
+ private readonly dir;
41
+ constructor(options: FileProviderStoreOptions);
42
+ create(config: ProviderConfig): Promise<void>;
43
+ get(id: string): Promise<ProviderConfig | null>;
44
+ update(id: string, changes: Partial<Omit<ProviderConfig, "id" | "createdAt">>): Promise<void>;
45
+ delete(id: string): Promise<void>;
46
+ list(): Promise<ProviderConfig[]>;
47
+ private filePath;
48
+ }
49
+
50
+ /**
51
+ * Shared types for route modules.
52
+ */
53
+
54
+ /**
55
+ * Handler state — intentionally empty after stateless refactor (STAT-01).
56
+ * Preserved as a type for backward compatibility with custom route modules.
57
+ * Model resolution is now fully per-request via resolveRequestContext.
58
+ * @deprecated Will be removed in next major version.
59
+ */
60
+ interface HandlerState {
61
+ /** @deprecated Model is now resolved per-request. This field is never set. */
62
+ currentModel?: string | undefined;
63
+ }
64
+ /**
65
+ * Shared context passed to every route module.
66
+ */
67
+ interface RouteContext {
68
+ readonly runtime: IChatRuntime;
69
+ readonly maxBodySize: number;
70
+ readonly heartbeatMs?: number;
71
+ readonly hooks?: ChatServerHooks;
72
+ readonly providerStore?: IProviderStore;
73
+ readonly tokenStore?: ITokenStore;
74
+ readonly transportFactory?: TransportFactory;
75
+ readonly state: HandlerState;
76
+ }
77
+ /**
78
+ * A route module handler.
79
+ * Returns `true` if the request was handled, `false` to try next module.
80
+ */
81
+ type RouteHandler = (method: string, path: string, req: ReadableRequest, res: WritableResponse, ctx: RouteContext) => Promise<boolean>;
82
+
83
+ /**
84
+ * createChatHandler — maps RemoteChatClient contract endpoints to IChatRuntime calls.
85
+ *
86
+ * Routes are delegated to composable route modules in ./routes/.
87
+ * This file is a thin router (~90 lines) that assembles modules and handles errors.
27
88
  */
28
89
 
29
90
  /** Minimal readable request interface (node:http IncomingMessage subset) */
30
91
  interface ReadableRequest {
31
92
  readonly method?: string;
32
93
  readonly url?: string;
33
- on(event: "data", listener: (chunk: Buffer | string) => void): void;
34
- on(event: "end", listener: () => void): void;
94
+ on(event: "data", listener: (chunk: Buffer | string) => void): unknown;
95
+ on(event: "end", listener: () => void): unknown;
35
96
  }
97
+
36
98
  /**
37
- * Writable HTTP response interface for chat handler.
38
- * Extends the transport's WritableResponse with setHeader() and body-accepting end().
99
+ * Server-side hooks for customizing chat handler behavior.
100
+ * Consolidates filter, guard, and lifecycle callbacks into a single interface.
39
101
  */
40
- interface WritableResponse extends WritableResponse$1 {
41
- setHeader(name: string, value: string): void;
42
- end(body?: string): void;
102
+ interface ChatServerHooks {
103
+ /** Filter the model list before returning to client. */
104
+ filterModels?(models: ModelInfo[]): ModelInfo[];
105
+ /** Validate model selection on /model/switch and /send model override. Throw to reject. */
106
+ onModelSwitch?(model: string): void | Promise<void>;
107
+ /** Called before provider switch. Receives providerId and resolved backend name. Throw to reject. */
108
+ onProviderSwitch?(info: {
109
+ providerId: string;
110
+ backend: string;
111
+ }): void | Promise<void>;
112
+ /** Called before backend switch. Throw to reject. */
113
+ onBackendSwitch?(backend: string): void | Promise<void>;
114
+ /** Called before sending a message. Throw to reject. */
115
+ onBeforeSend?(sessionId: string, message: string): void | Promise<void>;
116
+ /** Global error handler for unhandled route errors. */
117
+ onError?(error: Error, context: {
118
+ route: string;
119
+ method: string;
120
+ }): void;
43
121
  }
122
+ /**
123
+ * Factory for creating a chat transport for a /send request.
124
+ * Return an IChatTransport instance that will receive the event stream.
125
+ * Default: SSEChatTransport.
126
+ */
127
+ type TransportFactory = (req: ReadableRequest, res: WritableResponse) => IChatTransport;
44
128
  /** Configuration for createChatHandler */
45
129
  interface ChatHandlerOptions {
46
130
  /** Route prefix to strip from URL before matching. Default: "" (no prefix) */
@@ -49,72 +133,24 @@ interface ChatHandlerOptions {
49
133
  maxBodySize?: number;
50
134
  /** SSE heartbeat interval in milliseconds. 0 or undefined disables heartbeat. */
51
135
  heartbeatMs?: number;
136
+ /** Optional provider store for provider CRUD routes. */
137
+ providerStore?: IProviderStore;
138
+ /** Optional token store for resolveRequestContext in /send. */
139
+ tokenStore?: ITokenStore;
140
+ /** Consolidated server hooks. */
141
+ hooks?: ChatServerHooks;
142
+ /** Custom transport factory for /send endpoint. Default: SSEChatTransport. */
143
+ transportFactory?: TransportFactory;
52
144
  }
53
145
  /**
54
- * Create an HTTP request handler that maps RemoteChatRuntime contract
146
+ * Create an HTTP request handler that maps RemoteChatClient contract
55
147
  * endpoints to IChatRuntime method calls.
56
148
  *
57
- * @param runtime - The chat runtime instance to serve
58
- * @param options - Handler configuration
59
- * @returns Async request handler `(req, res) => Promise<void>`
60
- *
61
- * @example
62
- * ```ts
63
- * const handler = createChatHandler(runtime, { prefix: "/api/chat" });
64
- * http.createServer(async (req, res) => {
65
- * if (req.url?.startsWith("/api/chat")) {
66
- * await handler(req, res);
67
- * return;
68
- * }
69
- * res.writeHead(404).end();
70
- * });
71
- * ```
149
+ * Routes are handled by composable route modules (sessions, messages, config, providers).
150
+ * Model state is managed in a shared HandlerState object.
72
151
  */
73
152
  declare function createChatHandler(runtime: IChatRuntime, options?: ChatHandlerOptions): (req: ReadableRequest, res: WritableResponse) => Promise<void>;
74
153
 
75
- /**
76
- * Token storage abstraction and default filesystem implementation.
77
- */
78
-
79
- /** Token storage interface for server-side token management */
80
- interface ITokenStore {
81
- /** Save a token for a provider. Overwrites if exists. */
82
- save(provider: string, token: AuthToken): Promise<void>;
83
- /** Load a previously saved token. Returns null if not found. */
84
- load(provider: string): Promise<AuthToken | null>;
85
- /** Remove a specific provider's token. */
86
- clear(provider: string): Promise<void>;
87
- /** Remove all stored tokens. */
88
- clearAll(): Promise<void>;
89
- /** List provider names that have saved tokens. */
90
- list(): Promise<string[]>;
91
- }
92
- /** In-memory token store for testing and ephemeral use */
93
- declare class InMemoryTokenStore implements ITokenStore {
94
- private readonly tokens;
95
- save(provider: string, token: AuthToken): Promise<void>;
96
- load(provider: string): Promise<AuthToken | null>;
97
- clear(provider: string): Promise<void>;
98
- clearAll(): Promise<void>;
99
- list(): Promise<string[]>;
100
- }
101
- /** Options for FileTokenStore */
102
- interface FileTokenStoreOptions {
103
- /** Directory to store token JSON files. Default: ".tokens" in cwd */
104
- directory: string;
105
- }
106
- /** Filesystem-based token store using JSON files (one per provider) */
107
- declare class FileTokenStore implements ITokenStore {
108
- private readonly dir;
109
- constructor(options: FileTokenStoreOptions);
110
- save(provider: string, token: AuthToken): Promise<void>;
111
- load(provider: string): Promise<AuthToken | null>;
112
- clear(provider: string): Promise<void>;
113
- clearAll(): Promise<void>;
114
- list(): Promise<string[]>;
115
- private filePath;
116
- }
117
-
118
154
  /**
119
155
  * createAuthHandler — server-mediated authentication for all three backends.
120
156
  *
@@ -193,6 +229,30 @@ interface AuthHandlerOptions {
193
229
  */
194
230
  declare function createAuthHandler(options: AuthHandlerOptions): (req: ReadableRequest, res: WritableResponse) => Promise<void>;
195
231
 
232
+ /**
233
+ * createProviderHandler — CRUD handler for provider configurations.
234
+ *
235
+ * Routes (prefix already stripped by chat-server):
236
+ * - GET /providers → List all providers
237
+ * - GET /providers/{id} → Get single provider
238
+ * - POST /providers → Create provider
239
+ * - PUT /providers/{id} → Update provider
240
+ * - DELETE /providers/{id} → Delete provider
241
+ */
242
+
243
+ /** Configuration for createProviderHandler */
244
+ interface ProviderHandlerOptions {
245
+ /** Provider storage implementation */
246
+ providerStore: IProviderStore;
247
+ }
248
+ /**
249
+ * Create an HTTP request handler for provider CRUD operations.
250
+ *
251
+ * @param options - Provider handler configuration
252
+ * @returns Async request handler `(req, res) => Promise<void>`
253
+ */
254
+ declare function createProviderHandler(options: ProviderHandlerOptions): (req: ReadableRequest, res: WritableResponse) => Promise<void>;
255
+
196
256
  /**
197
257
  * CORS middleware — standalone composable function.
198
258
  * Returns true if it fully handled the request (OPTIONS preflight),
@@ -217,7 +277,7 @@ interface CorsRequest {
217
277
  /** Minimal response interface for CORS */
218
278
  interface CorsResponse {
219
279
  setHeader(name: string, value: string): void;
220
- writeHead(statusCode: number): void;
280
+ writeHead(statusCode: number, headers?: Record<string, string>): unknown;
221
281
  end(): void;
222
282
  }
223
283
  /**
@@ -229,6 +289,90 @@ interface CorsResponse {
229
289
  */
230
290
  declare function corsMiddleware(options?: CorsOptions): (req: CorsRequest, res: CorsResponse) => boolean;
231
291
 
292
+ /**
293
+ * ServiceManager — manages IAgentService lifecycle (create, cache, dispose).
294
+ *
295
+ * Reduces boilerplate in apps that need to create/dispose services on auth events.
296
+ * Pass to createChatServer to auto-wire onAuth/onLogout callbacks.
297
+ *
298
+ * @example
299
+ * ```ts
300
+ * const sm = new ServiceManager({
301
+ * createService: (backend, token) =>
302
+ * createAgentService(backend, { apiKey: token.accessToken }),
303
+ * });
304
+ *
305
+ * // Manual usage:
306
+ * await sm.handleAuth("copilot", token);
307
+ * const service = sm.getService("copilot");
308
+ *
309
+ * // Or auto-wired via createChatServer:
310
+ * createChatServer({ serviceManager: sm, auth: { tokenStore }, ... });
311
+ * ```
312
+ */
313
+
314
+ /** Minimal IAgentService interface (avoids importing from main package) */
315
+ interface ManagedService {
316
+ dispose(): Promise<void> | void;
317
+ }
318
+ /** Callback for building a token refresh function per backend */
319
+ type RefreshFactory = (backend: string) => ((token: AuthToken) => Promise<AuthToken>) | undefined;
320
+ /** Configuration for ServiceManager */
321
+ interface ServiceManagerOptions {
322
+ /**
323
+ * Factory to create a service for a backend.
324
+ * Called on every auth event (old service is disposed first).
325
+ */
326
+ createService: (backend: string, token: AuthToken) => ManagedService | Promise<ManagedService>;
327
+ /**
328
+ * Optional factory returning a refresh function per backend.
329
+ * If provided and the token has expiresIn, a TokenRefreshManager is started.
330
+ * On refresh → the stored token is updated and the service is recreated.
331
+ * On expiry → handleLogout() for that backend is called.
332
+ */
333
+ refreshFactory?: RefreshFactory;
334
+ /** Override TokenRefreshManager options (threshold, retries, etc.) */
335
+ refreshOptions?: Partial<Pick<TokenRefreshOptions, "refreshThreshold" | "maxRetries" | "retryDelayMs">>;
336
+ /** Called when a token expires (before logout). */
337
+ onTokenExpired?: (backend: string) => void;
338
+ }
339
+ /**
340
+ * Manages IAgentService lifecycle: create, cache, and dispose on re-auth or logout.
341
+ * Optionally starts background token refresh when `refreshFactory` is configured.
342
+ */
343
+ declare class ServiceManager {
344
+ private readonly _services;
345
+ private readonly _refreshManagers;
346
+ private readonly _options;
347
+ constructor(options: ServiceManagerOptions);
348
+ /**
349
+ * Handle auth event: dispose old service (if any) and create new one.
350
+ * If the token is refreshable and refreshFactory is configured, starts a
351
+ * TokenRefreshManager that auto-refreshes and recreates the service.
352
+ */
353
+ handleAuth(backend: string, token: AuthToken): Promise<ManagedService>;
354
+ /**
355
+ * Handle logout: dispose all services, stop all refresh managers, clear cache.
356
+ */
357
+ handleLogout(): Promise<void>;
358
+ /**
359
+ * Dispose the ServiceManager — stops all refresh managers and disposes all services.
360
+ */
361
+ dispose(): Promise<void>;
362
+ /** Get cached service for a backend (undefined if not authenticated). */
363
+ getService(backend: string): ManagedService | undefined;
364
+ /** Check if a service exists for the given backend. */
365
+ hasService(backend: string): boolean;
366
+ /** Get all backend names with active services. */
367
+ get activeBackends(): string[];
368
+ /** Get active refresh manager for a backend (for testing/introspection). */
369
+ getRefreshManager(backend: string): TokenRefreshManager | undefined;
370
+ private _startRefreshManager;
371
+ private _stopRefreshManager;
372
+ private _recreateService;
373
+ private _logoutBackend;
374
+ }
375
+
232
376
  /**
233
377
  * createChatServer — one-call setup combining runtime, chat handler, auth handler, CORS,
234
378
  * and static file serving into a single HTTP request handler.
@@ -241,10 +385,20 @@ declare function corsMiddleware(options?: CorsOptions): (req: CorsRequest, res:
241
385
  * - Everything else → 404
242
386
  */
243
387
 
388
+ /**
389
+ * Configuration for auto-creating a ChatRuntime from options.
390
+ * Alternative to providing a pre-built IChatRuntime instance.
391
+ * Uses the same shape as ChatRuntimeOptions from the runtime module.
392
+ */
393
+ type ChatRuntimeConfig = ChatRuntimeOptions;
244
394
  /** Configuration for createChatServer */
245
395
  interface ChatServerOptions {
246
- /** The chat runtime instance to serve */
247
- runtime: IChatRuntime;
396
+ /** Pre-built runtime instance. Either `runtime` or `runtimeConfig` must be provided. */
397
+ runtime?: IChatRuntime;
398
+ /** Config to auto-create a runtime. Used when `runtime` is not provided. */
399
+ runtimeConfig?: ChatRuntimeConfig;
400
+ /** Server-side hooks for customizing handler behavior. */
401
+ hooks?: ChatServerHooks;
248
402
  /** Prefix for chat API routes. Default: "/api/chat" */
249
403
  chatPrefix?: string;
250
404
  /** Auth handler options. If provided, auth routes are mounted. */
@@ -257,9 +411,38 @@ interface ChatServerOptions {
257
411
  staticDir?: string;
258
412
  /** Prefix for static file routes. Default: "/" */
259
413
  staticPrefix?: string;
414
+ /** Provider handler options. If provided, provider routes are mounted. */
415
+ providers?: ProviderHandlerOptions;
416
+ /** Prefix for provider routes. Default: "/api/providers" */
417
+ providerPrefix?: string;
260
418
  /** Chat handler options (maxBodySize, etc.) */
261
419
  chatHandlerOptions?: Omit<ChatHandlerOptions, "prefix">;
420
+ /**
421
+ * Path for the health check endpoint. Default: "/api/health".
422
+ * Set to `false` to disable. Returns `{ ok: true }`.
423
+ */
424
+ healthPath?: string | false;
425
+ /**
426
+ * Auto-create a default provider when a backend authenticates for the first time.
427
+ *
428
+ * - `true` — uses built-in default models per backend
429
+ * - `Record<string, string>` — custom backend→model mapping (e.g. `{ copilot: "gpt-5-mini" }`)
430
+ * - `false` / omitted — disabled
431
+ *
432
+ * Requires both `auth` and `providers` to be configured.
433
+ */
434
+ autoCreateProviders?: boolean | Record<string, string>;
435
+ /**
436
+ * Service lifecycle manager. When provided with `auth`, automatically wires:
437
+ * - `onAuth` → `serviceManager.handleAuth(backend, token)` (creates/caches service)
438
+ * - `onLogout` → `serviceManager.handleLogout()` (disposes all services)
439
+ *
440
+ * User's own `onAuth`/`onLogout` callbacks in `auth` are still called first.
441
+ */
442
+ serviceManager?: ServiceManager;
262
443
  }
444
+ /** Default model per backend for auto-created providers */
445
+ declare const DEFAULT_PROVIDER_MODELS: Record<string, string>;
263
446
  /** Request handler type returned by createChatServer */
264
447
  type RequestHandler = (req: ReadableRequest, res: WritableResponse) => Promise<void>;
265
448
  /**
@@ -284,4 +467,182 @@ type RequestHandler = (req: ReadableRequest, res: WritableResponse) => Promise<v
284
467
  */
285
468
  declare function createChatServer(options: ChatServerOptions): RequestHandler;
286
469
 
287
- export { type AuthHandlerOptions, type AuthProvider, type ChatHandlerOptions, type ChatServerOptions, type CorsOptions, FileTokenStore, type FileTokenStoreOptions, type IClaudeAuth, type ICopilotAuth, type ITokenStore, InMemoryTokenStore, type OnAuthCallback, type ReadableRequest, type RequestHandler, type WritableResponse, corsMiddleware, createAuthHandler, createChatHandler, createChatServer };
470
+ /**
471
+ * Shared server utilities — readBody and JSON response helpers.
472
+ */
473
+
474
+ /** Error thrown by readBody with an HTTP status code */
475
+ declare class BodyParseError extends Error {
476
+ readonly statusCode: number;
477
+ constructor(message: string, statusCode: number);
478
+ }
479
+ /**
480
+ * Read and parse JSON request body with size limit.
481
+ * Throws BodyParseError on oversized, malformed, or errored requests.
482
+ */
483
+ declare function readBody(req: ReadableRequest, maxSize?: number): Promise<Record<string, unknown>>;
484
+ /** Send a JSON response with given status code. */
485
+ declare function json(res: WritableResponse, data: unknown, status?: number): void;
486
+
487
+ /**
488
+ * AdapterPool — lazy adapter creation with concurrent dedup and eviction.
489
+ *
490
+ * Replaces the pattern where ServiceManager + backend factories create adapters
491
+ * eagerly on auth. AdapterPool creates adapters on first use, keyed by backend name.
492
+ *
493
+ * Key properties:
494
+ * - Lazy: adapters created on first getAdapter() call
495
+ * - Concurrent dedup: multiple concurrent getAdapter() calls for same backend share one creation
496
+ * - Never cache failures: if factory throws, next call retries
497
+ * - Eviction: evict(backend) disposes cached adapter (e.g. on token rotation)
498
+ *
499
+ * @example
500
+ * ```ts
501
+ * const pool = new AdapterPool({
502
+ * factory: async (backend) => {
503
+ * const token = await tokenStore.load(backend);
504
+ * const service = createAgentService(backend, { apiKey: token.accessToken });
505
+ * return new VercelAIChatAdapter({ agentConfig: { ... }, agentService: service });
506
+ * },
507
+ * });
508
+ *
509
+ * const adapter = await pool.getAdapter("vercel-ai");
510
+ * // On token rotation:
511
+ * await pool.evict("vercel-ai");
512
+ * ```
513
+ */
514
+ /** Minimal adapter interface (avoids importing full IChatBackend) */
515
+ interface PooledAdapter {
516
+ dispose(): Promise<void> | void;
517
+ }
518
+ /** Factory function to create an adapter for a given backend */
519
+ type AdapterFactory<T extends PooledAdapter = PooledAdapter> = (backend: string) => Promise<T>;
520
+ /** Configuration for AdapterPool */
521
+ interface AdapterPoolOptions<T extends PooledAdapter = PooledAdapter> {
522
+ /** Factory to create an adapter for a backend. Called lazily on first getAdapter(). */
523
+ factory: AdapterFactory<T>;
524
+ }
525
+ /**
526
+ * Lazy adapter pool with concurrent dedup and eviction.
527
+ * Thread-safe: concurrent getAdapter() calls for the same backend share a single creation promise.
528
+ */
529
+ declare class AdapterPool<T extends PooledAdapter = PooledAdapter> {
530
+ private readonly _cached;
531
+ private readonly _pending;
532
+ private readonly _factory;
533
+ private _disposed;
534
+ constructor(options: AdapterPoolOptions<T>);
535
+ /**
536
+ * Get or create an adapter for the given backend.
537
+ * Concurrent calls for the same backend share one creation promise.
538
+ * Failed creations are NOT cached — next call retries.
539
+ */
540
+ getAdapter(backend: string): Promise<T>;
541
+ /**
542
+ * Evict (dispose and remove) the cached adapter for a backend.
543
+ * Use after token rotation to force re-creation on next getAdapter().
544
+ */
545
+ evict(backend: string): Promise<void>;
546
+ /** Check if a backend has a cached adapter. */
547
+ has(backend: string): boolean;
548
+ /** Get all backend names with cached adapters. */
549
+ get activeBackends(): string[];
550
+ /** Dispose all cached adapters and mark pool as unusable. */
551
+ dispose(): Promise<void>;
552
+ private _create;
553
+ }
554
+
555
+ /**
556
+ * Request context resolution — per-request credential + model lookup.
557
+ *
558
+ * Resolves a providerId into a RequestContext containing backend name,
559
+ * credentials (AuthToken), and model identifier. This enables stateless
560
+ * request handling where each request carries its own context.
561
+ *
562
+ * @example
563
+ * ```ts
564
+ * const ctx = await resolveRequestContext("my-copilot-provider", {
565
+ * providerStore,
566
+ * tokenStore,
567
+ * });
568
+ * // ctx = { backend: "copilot", credentials: { accessToken: "..." }, model: "gpt-5-mini" }
569
+ * ```
570
+ */
571
+
572
+ /** Per-request context carrying backend, credentials, and model */
573
+ interface RequestContext {
574
+ /** Backend name (e.g. "copilot", "claude", "vercel-ai") */
575
+ backend: string;
576
+ /** Resolved authentication token */
577
+ credentials: AuthToken;
578
+ /** Model identifier from provider config */
579
+ model: string;
580
+ /** Original provider config for reference */
581
+ provider: ProviderConfig;
582
+ }
583
+ /** Dependencies for context resolution */
584
+ interface RequestContextDeps {
585
+ /** Provider store to look up provider config */
586
+ providerStore: IProviderStore;
587
+ /** Token store to load credentials for the backend */
588
+ tokenStore: ITokenStore;
589
+ }
590
+ /**
591
+ * Resolve a providerId into a full RequestContext.
592
+ *
593
+ * Flow: providerId → ProviderConfig (from providerStore) → AuthToken (from tokenStore) → RequestContext
594
+ *
595
+ * @throws ChatError with PROVIDER_NOT_FOUND if provider doesn't exist
596
+ * @throws ChatError with AUTH_REQUIRED if no token found for the provider's backend
597
+ */
598
+ declare function resolveRequestContext(providerId: string, deps: RequestContextDeps): Promise<RequestContext>;
599
+
600
+ /**
601
+ * Session CRUD route handlers.
602
+ *
603
+ * Routes:
604
+ * - POST /sessions/create → Create session
605
+ * - GET /sessions/:id → Get session
606
+ * - GET /sessions → List sessions
607
+ * - DELETE /sessions/:id → Delete session
608
+ * - GET /sessions/:id/context-stats → Get context window stats
609
+ */
610
+
611
+ declare const sessionRoutes: RouteHandler;
612
+
613
+ /**
614
+ * Message route handlers (send + abort).
615
+ *
616
+ * Routes:
617
+ * - POST /send → Stream response via transport (SSE by default)
618
+ * - POST /abort → Cancel in-flight stream
619
+ */
620
+
621
+ declare const messageRoutes: RouteHandler;
622
+
623
+ /**
624
+ * Configuration route handlers (model/backend/provider switching, listing).
625
+ *
626
+ * Routes:
627
+ * - GET /models → List available models
628
+ * - GET /backends → List available backends
629
+ * - POST /model/switch → Switch active model (handler state)
630
+ * - POST /provider/switch → Switch provider (resolves backend + model)
631
+ */
632
+
633
+ declare const configRoutes: RouteHandler;
634
+
635
+ /**
636
+ * Provider CRUD route handlers.
637
+ *
638
+ * Routes:
639
+ * - GET /providers → List all providers
640
+ * - GET /providers/:id → Get single provider
641
+ * - POST /providers → Create provider
642
+ * - PUT /providers/:id → Update provider
643
+ * - DELETE /providers/:id → Delete provider
644
+ */
645
+
646
+ declare const providerRoutes: RouteHandler;
647
+
648
+ export { type AdapterFactory, AdapterPool, type AdapterPoolOptions, type AuthHandlerOptions, type AuthProvider, BodyParseError, type ChatHandlerOptions, type ChatRuntimeConfig, type ChatServerHooks, type ChatServerOptions, type CorsOptions, DEFAULT_PROVIDER_MODELS, FileProviderStore, type FileProviderStoreOptions, type HandlerState, type IClaudeAuth, type ICopilotAuth, IProviderStore, ITokenStore, InMemoryProviderStore, type ManagedService, type OnAuthCallback, type PooledAdapter, ProviderConfig, type ProviderHandlerOptions, type ReadableRequest, type RefreshFactory, type RequestContext, type RequestContextDeps, type RequestHandler, type RouteContext, type RouteHandler, ServiceManager, type ServiceManagerOptions, type TransportFactory, WritableResponse, configRoutes, corsMiddleware, createAuthHandler, createChatHandler, createChatServer, createProviderHandler, json, messageRoutes, providerRoutes, readBody, resolveRequestContext, sessionRoutes };