@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.
- package/README.md +140 -34
- package/dist/{types-CqvUAYxt.d.cts → agent-CW9XbmG_.d.ts} +137 -102
- package/dist/{types-CqvUAYxt.d.ts → agent-DxY68NZL.d.cts} +137 -102
- package/dist/auth/index.cjs +72 -1
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.d.cts +21 -154
- package/dist/auth/index.d.ts +21 -154
- package/dist/auth/index.js +72 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/backends/claude.cjs +480 -261
- package/dist/backends/claude.cjs.map +1 -1
- package/dist/backends/claude.d.cts +3 -1
- package/dist/backends/claude.d.ts +3 -1
- package/dist/backends/claude.js +480 -261
- package/dist/backends/claude.js.map +1 -1
- package/dist/backends/copilot.cjs +329 -97
- package/dist/backends/copilot.cjs.map +1 -1
- package/dist/backends/copilot.d.cts +12 -4
- package/dist/backends/copilot.d.ts +12 -4
- package/dist/backends/copilot.js +329 -97
- package/dist/backends/copilot.js.map +1 -1
- package/dist/backends/vercel-ai.cjs +294 -61
- package/dist/backends/vercel-ai.cjs.map +1 -1
- package/dist/backends/vercel-ai.d.cts +3 -1
- package/dist/backends/vercel-ai.d.ts +3 -1
- package/dist/backends/vercel-ai.js +294 -61
- package/dist/backends/vercel-ai.js.map +1 -1
- package/dist/backends-BSrsBYFn.d.cts +39 -0
- package/dist/backends-BSrsBYFn.d.ts +39 -0
- package/dist/chat/accumulator.cjs +1 -1
- package/dist/chat/accumulator.cjs.map +1 -1
- package/dist/chat/accumulator.d.cts +5 -2
- package/dist/chat/accumulator.d.ts +5 -2
- package/dist/chat/accumulator.js +1 -1
- package/dist/chat/accumulator.js.map +1 -1
- package/dist/chat/backends.cjs +736 -746
- package/dist/chat/backends.cjs.map +1 -1
- package/dist/chat/backends.d.cts +10 -6
- package/dist/chat/backends.d.ts +10 -6
- package/dist/chat/backends.js +736 -725
- package/dist/chat/backends.js.map +1 -1
- package/dist/chat/context.cjs +50 -0
- package/dist/chat/context.cjs.map +1 -1
- package/dist/chat/context.d.cts +27 -3
- package/dist/chat/context.d.ts +27 -3
- package/dist/chat/context.js +50 -0
- package/dist/chat/context.js.map +1 -1
- package/dist/chat/core.cjs +25 -2
- package/dist/chat/core.cjs.map +1 -1
- package/dist/chat/core.d.cts +30 -381
- package/dist/chat/core.d.ts +30 -381
- package/dist/chat/core.js +24 -3
- package/dist/chat/core.js.map +1 -1
- package/dist/chat/errors.cjs +48 -26
- package/dist/chat/errors.cjs.map +1 -1
- package/dist/chat/errors.d.cts +6 -31
- package/dist/chat/errors.d.ts +6 -31
- package/dist/chat/errors.js +48 -25
- package/dist/chat/errors.js.map +1 -1
- package/dist/chat/events.cjs.map +1 -1
- package/dist/chat/events.d.cts +6 -2
- package/dist/chat/events.d.ts +6 -2
- package/dist/chat/events.js.map +1 -1
- package/dist/chat/index.cjs +1199 -1008
- package/dist/chat/index.cjs.map +1 -1
- package/dist/chat/index.d.cts +35 -10
- package/dist/chat/index.d.ts +35 -10
- package/dist/chat/index.js +1196 -987
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react/theme.css +2517 -0
- package/dist/chat/react.cjs +2003 -1153
- package/dist/chat/react.cjs.map +1 -1
- package/dist/chat/react.d.cts +590 -121
- package/dist/chat/react.d.ts +590 -121
- package/dist/chat/react.js +1984 -1151
- package/dist/chat/react.js.map +1 -1
- package/dist/chat/runtime.cjs +401 -186
- package/dist/chat/runtime.cjs.map +1 -1
- package/dist/chat/runtime.d.cts +92 -28
- package/dist/chat/runtime.d.ts +92 -28
- package/dist/chat/runtime.js +401 -186
- package/dist/chat/runtime.js.map +1 -1
- package/dist/chat/server.cjs +2234 -209
- package/dist/chat/server.cjs.map +1 -1
- package/dist/chat/server.d.cts +451 -90
- package/dist/chat/server.d.ts +451 -90
- package/dist/chat/server.js +2221 -210
- package/dist/chat/server.js.map +1 -1
- package/dist/chat/sessions.cjs +25 -43
- package/dist/chat/sessions.cjs.map +1 -1
- package/dist/chat/sessions.d.cts +37 -118
- package/dist/chat/sessions.d.ts +37 -118
- package/dist/chat/sessions.js +25 -43
- package/dist/chat/sessions.js.map +1 -1
- package/dist/chat/sqlite.cjs +441 -0
- package/dist/chat/sqlite.cjs.map +1 -0
- package/dist/chat/sqlite.d.cts +128 -0
- package/dist/chat/sqlite.d.ts +128 -0
- package/dist/chat/sqlite.js +435 -0
- package/dist/chat/sqlite.js.map +1 -0
- package/dist/chat/state.cjs +14 -1
- package/dist/chat/state.cjs.map +1 -1
- package/dist/chat/state.d.cts +5 -2
- package/dist/chat/state.d.ts +5 -2
- package/dist/chat/state.js +14 -1
- package/dist/chat/state.js.map +1 -1
- package/dist/chat/storage.cjs +19 -10
- package/dist/chat/storage.cjs.map +1 -1
- package/dist/chat/storage.d.cts +11 -5
- package/dist/chat/storage.d.ts +11 -5
- package/dist/chat/storage.js +19 -10
- package/dist/chat/storage.js.map +1 -1
- package/dist/errors-C-so0M4t.d.cts +33 -0
- package/dist/errors-C-so0M4t.d.ts +33 -0
- package/dist/errors-CmVvczxZ.d.cts +28 -0
- package/dist/errors-CmVvczxZ.d.ts +28 -0
- package/dist/{in-process-transport-C2oPTYs6.d.ts → in-process-transport-C1JnJGVR.d.ts} +28 -23
- package/dist/{in-process-transport-DG-w5G6k.d.cts → in-process-transport-C7DSqPyX.d.cts} +28 -23
- package/dist/index.cjs +340 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +292 -123
- package/dist/index.d.ts +292 -123
- package/dist/index.js +334 -47
- package/dist/index.js.map +1 -1
- package/dist/provider-types-PTSlRPNB.d.cts +39 -0
- package/dist/provider-types-PTSlRPNB.d.ts +39 -0
- package/dist/refresh-manager-B81PpYBr.d.cts +153 -0
- package/dist/refresh-manager-Dlv_iNZi.d.ts +153 -0
- package/dist/testing.cjs +383 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +132 -0
- package/dist/testing.d.ts +132 -0
- package/dist/testing.js +377 -0
- package/dist/testing.js.map +1 -0
- package/dist/token-store-CSUBgYwn.d.ts +48 -0
- package/dist/token-store-CuC4hB9Z.d.cts +48 -0
- package/dist/{transport-DX1Nhm4N.d.cts → transport-Cdh3M0tS.d.cts} +5 -4
- package/dist/{transport-D1OaUgRk.d.ts → transport-Ciap4PWK.d.ts} +5 -4
- package/dist/{types-CGF7AEX1.d.cts → types-4vbcmPTp.d.cts} +4 -2
- package/dist/{types-Bh5AhqD-.d.ts → types-BxggH0Yh.d.ts} +4 -2
- package/dist/types-DRgd_9R7.d.cts +363 -0
- package/dist/types-ajANVzf7.d.ts +363 -0
- package/package.json +31 -6
- package/dist/errors-BDLbNu9w.d.cts +0 -13
- package/dist/errors-BDLbNu9w.d.ts +0 -13
- package/dist/types-DLZzlJxt.d.ts +0 -39
- package/dist/types-tE0CXwBl.d.cts +0 -39
package/dist/chat/errors.js
CHANGED
|
@@ -1,10 +1,52 @@
|
|
|
1
|
+
// src/types/errors.ts
|
|
2
|
+
var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
|
|
3
|
+
ErrorCode2["AUTH_EXPIRED"] = "AUTH_EXPIRED";
|
|
4
|
+
ErrorCode2["AUTH_INVALID"] = "AUTH_INVALID";
|
|
5
|
+
ErrorCode2["RATE_LIMIT"] = "RATE_LIMIT";
|
|
6
|
+
ErrorCode2["NETWORK"] = "NETWORK";
|
|
7
|
+
ErrorCode2["TIMEOUT"] = "TIMEOUT";
|
|
8
|
+
ErrorCode2["PROVIDER_ERROR"] = "PROVIDER_ERROR";
|
|
9
|
+
ErrorCode2["MODEL_NOT_FOUND"] = "MODEL_NOT_FOUND";
|
|
10
|
+
ErrorCode2["MODEL_OVERLOADED"] = "MODEL_OVERLOADED";
|
|
11
|
+
ErrorCode2["CONTEXT_OVERFLOW"] = "CONTEXT_OVERFLOW";
|
|
12
|
+
ErrorCode2["INVALID_INPUT"] = "INVALID_INPUT";
|
|
13
|
+
ErrorCode2["INVALID_RESPONSE"] = "INVALID_RESPONSE";
|
|
14
|
+
ErrorCode2["REENTRANCY"] = "REENTRANCY";
|
|
15
|
+
ErrorCode2["DISPOSED"] = "DISPOSED";
|
|
16
|
+
ErrorCode2["ABORTED"] = "ABORTED";
|
|
17
|
+
ErrorCode2["INVALID_TRANSITION"] = "INVALID_TRANSITION";
|
|
18
|
+
ErrorCode2["DEPENDENCY_MISSING"] = "DEPENDENCY_MISSING";
|
|
19
|
+
ErrorCode2["BACKEND_NOT_INSTALLED"] = "BACKEND_NOT_INSTALLED";
|
|
20
|
+
ErrorCode2["TOOL_EXECUTION"] = "TOOL_EXECUTION";
|
|
21
|
+
ErrorCode2["PERMISSION_DENIED"] = "PERMISSION_DENIED";
|
|
22
|
+
ErrorCode2["SESSION_NOT_FOUND"] = "SESSION_NOT_FOUND";
|
|
23
|
+
ErrorCode2["SESSION_EXPIRED"] = "SESSION_EXPIRED";
|
|
24
|
+
ErrorCode2["PROVIDER_NOT_FOUND"] = "PROVIDER_NOT_FOUND";
|
|
25
|
+
ErrorCode2["AUTH_REQUIRED"] = "AUTH_REQUIRED";
|
|
26
|
+
ErrorCode2["STORAGE_ERROR"] = "STORAGE_ERROR";
|
|
27
|
+
ErrorCode2["STORAGE_NOT_FOUND"] = "STORAGE_NOT_FOUND";
|
|
28
|
+
ErrorCode2["STORAGE_DUPLICATE_KEY"] = "STORAGE_DUPLICATE_KEY";
|
|
29
|
+
ErrorCode2["STORAGE_IO_ERROR"] = "STORAGE_IO_ERROR";
|
|
30
|
+
ErrorCode2["STORAGE_SERIALIZATION_ERROR"] = "STORAGE_SERIALIZATION_ERROR";
|
|
31
|
+
return ErrorCode2;
|
|
32
|
+
})(ErrorCode || {});
|
|
33
|
+
|
|
1
34
|
// src/errors.ts
|
|
2
35
|
var AgentSDKError = class extends Error {
|
|
3
36
|
/** @internal Marker for cross-bundle identity checks */
|
|
4
37
|
_agentSDKError = true;
|
|
38
|
+
/** Machine-readable error code. Prefer values from the ErrorCode enum. */
|
|
39
|
+
code;
|
|
40
|
+
/** Whether this error is safe to retry */
|
|
41
|
+
retryable;
|
|
42
|
+
/** HTTP status code hint for error classification */
|
|
43
|
+
httpStatus;
|
|
5
44
|
constructor(message, options) {
|
|
6
45
|
super(message, options);
|
|
7
46
|
this.name = "AgentSDKError";
|
|
47
|
+
this.code = options?.code;
|
|
48
|
+
this.retryable = options?.retryable ?? false;
|
|
49
|
+
this.httpStatus = options?.httpStatus;
|
|
8
50
|
}
|
|
9
51
|
/** Check if an error is an AgentSDKError (works across bundled copies) */
|
|
10
52
|
static is(error) {
|
|
@@ -13,36 +55,17 @@ var AgentSDKError = class extends Error {
|
|
|
13
55
|
};
|
|
14
56
|
|
|
15
57
|
// src/chat/errors.ts
|
|
16
|
-
var ChatErrorCode = /* @__PURE__ */ ((ChatErrorCode2) => {
|
|
17
|
-
ChatErrorCode2["NETWORK"] = "NETWORK";
|
|
18
|
-
ChatErrorCode2["TIMEOUT"] = "TIMEOUT";
|
|
19
|
-
ChatErrorCode2["AUTH_EXPIRED"] = "AUTH_EXPIRED";
|
|
20
|
-
ChatErrorCode2["AUTH_INVALID"] = "AUTH_INVALID";
|
|
21
|
-
ChatErrorCode2["RATE_LIMIT"] = "RATE_LIMIT";
|
|
22
|
-
ChatErrorCode2["PROVIDER_ERROR"] = "PROVIDER_ERROR";
|
|
23
|
-
ChatErrorCode2["MODEL_NOT_FOUND"] = "MODEL_NOT_FOUND";
|
|
24
|
-
ChatErrorCode2["MODEL_OVERLOADED"] = "MODEL_OVERLOADED";
|
|
25
|
-
ChatErrorCode2["CONTEXT_OVERFLOW"] = "CONTEXT_OVERFLOW";
|
|
26
|
-
ChatErrorCode2["INVALID_INPUT"] = "INVALID_INPUT";
|
|
27
|
-
ChatErrorCode2["INVALID_RESPONSE"] = "INVALID_RESPONSE";
|
|
28
|
-
ChatErrorCode2["PERMISSION_DENIED"] = "PERMISSION_DENIED";
|
|
29
|
-
ChatErrorCode2["BACKEND_NOT_INSTALLED"] = "BACKEND_NOT_INSTALLED";
|
|
30
|
-
ChatErrorCode2["SESSION_NOT_FOUND"] = "SESSION_NOT_FOUND";
|
|
31
|
-
ChatErrorCode2["STORAGE_ERROR"] = "STORAGE_ERROR";
|
|
32
|
-
ChatErrorCode2["SESSION_EXPIRED"] = "SESSION_EXPIRED";
|
|
33
|
-
ChatErrorCode2["DISPOSED"] = "DISPOSED";
|
|
34
|
-
ChatErrorCode2["ABORTED"] = "ABORTED";
|
|
35
|
-
ChatErrorCode2["INVALID_TRANSITION"] = "INVALID_TRANSITION";
|
|
36
|
-
ChatErrorCode2["REENTRANCY"] = "REENTRANCY";
|
|
37
|
-
return ChatErrorCode2;
|
|
38
|
-
})(ChatErrorCode || {});
|
|
39
58
|
var ChatError = class extends AgentSDKError {
|
|
40
59
|
code;
|
|
41
60
|
retryable;
|
|
42
61
|
retryAfter;
|
|
43
62
|
timestamp;
|
|
44
63
|
constructor(message, options) {
|
|
45
|
-
super(message, {
|
|
64
|
+
super(message, {
|
|
65
|
+
cause: options.cause,
|
|
66
|
+
code: options.code,
|
|
67
|
+
retryable: options.retryable
|
|
68
|
+
});
|
|
46
69
|
this.name = "ChatError";
|
|
47
70
|
this.code = options.code;
|
|
48
71
|
this.retryable = options.retryable ?? false;
|
|
@@ -238,6 +261,6 @@ function sleep(ms, signal) {
|
|
|
238
261
|
});
|
|
239
262
|
}
|
|
240
263
|
|
|
241
|
-
export { ChatError,
|
|
264
|
+
export { ChatError, ErrorCode, ExponentialBackoffStrategy, classifyError, isRetryable, withRetry };
|
|
242
265
|
//# sourceMappingURL=errors.js.map
|
|
243
266
|
//# sourceMappingURL=errors.js.map
|
package/dist/chat/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/errors.ts","../../src/chat/errors.ts"],"names":["ChatErrorCode"],"mappings":"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","file":"errors.js","sourcesContent":["/** Base error class for agent-sdk.\n *\n * Use `AgentSDKError.is(err)` for reliable cross-module `instanceof` checks\n * (works across separately bundled entry points where `instanceof` may fail). */\nexport class AgentSDKError extends Error {\n /** @internal Marker for cross-bundle identity checks */\n readonly _agentSDKError = true as const;\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"AgentSDKError\";\n }\n\n /** Check if an error is an AgentSDKError (works across bundled copies) */\n static is(error: unknown): error is AgentSDKError {\n return (\n error instanceof Error &&\n \"_agentSDKError\" in error &&\n (error as AgentSDKError)._agentSDKError === true\n );\n }\n}\n\n/** Thrown when agent.run() is called while already running (M8 re-entrancy guard) */\nexport class ReentrancyError extends AgentSDKError {\n constructor() {\n super(\"Agent is already running. Await the current run before starting another.\");\n this.name = \"ReentrancyError\";\n }\n}\n\n/** Thrown when an operation is attempted on a disposed agent/service */\nexport class DisposedError extends AgentSDKError {\n constructor(entity: string) {\n super(`${entity} has been disposed and cannot be used.`);\n this.name = \"DisposedError\";\n }\n}\n\n/** Thrown when a backend is not found in the registry */\nexport class BackendNotFoundError extends AgentSDKError {\n constructor(backend: string) {\n super(\n `Unknown backend: \"${backend}\". ` +\n `Built-in: copilot, claude, vercel-ai. ` +\n `Custom: use registerBackend() first.`,\n );\n this.name = \"BackendNotFoundError\";\n }\n}\n\n/** Thrown when a backend is already registered */\nexport class BackendAlreadyRegisteredError extends AgentSDKError {\n constructor(backend: string) {\n super(`Backend \"${backend}\" is already registered. Use a different name or unregister first.`);\n this.name = \"BackendAlreadyRegisteredError\";\n }\n}\n\n/** Thrown when subprocess management fails */\nexport class SubprocessError extends AgentSDKError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"SubprocessError\";\n }\n}\n\n/** Thrown when a required peer dependency is not installed */\nexport class DependencyError extends AgentSDKError {\n public readonly packageName: string;\n\n constructor(packageName: string) {\n super(`${packageName} is not installed. Install it: npm install ${packageName}`);\n this.name = \"DependencyError\";\n this.packageName = packageName;\n }\n}\n\n/** Thrown when an agent run is aborted */\nexport class AbortError extends AgentSDKError {\n constructor() {\n super(\"Agent run was aborted.\");\n this.name = \"AbortError\";\n }\n}\n\n/** Thrown when a tool execution fails */\nexport class ToolExecutionError extends AgentSDKError {\n public readonly toolName: string;\n\n constructor(toolName: string, message: string, options?: ErrorOptions) {\n super(`Tool \"${toolName}\" failed: ${message}`, options);\n this.name = \"ToolExecutionError\";\n this.toolName = toolName;\n }\n}\n\n/** Thrown when structured output parsing fails */\nexport class StructuredOutputError extends AgentSDKError {\n constructor(message: string, options?: ErrorOptions) {\n super(`Structured output error: ${message}`, options);\n this.name = \"StructuredOutputError\";\n }\n}\n","/**\n * @witqq/agent-sdk/chat/errors\n *\n * Flat error taxonomy with ChatErrorCode enum, unified ChatError class,\n * pattern-matching classifier, retry strategies with exponential backoff.\n * Extends the existing AgentSDKError from @witqq/agent-sdk.\n */\n\nimport { AgentSDKError } from \"../errors.js\";\n\n// ─── Error Code Enum ───────────────────────────────────────────\n\n/** Error codes for chat-specific errors — used by classifyError() and ChatError */\nexport enum ChatErrorCode {\n NETWORK = \"NETWORK\",\n TIMEOUT = \"TIMEOUT\",\n AUTH_EXPIRED = \"AUTH_EXPIRED\",\n AUTH_INVALID = \"AUTH_INVALID\",\n RATE_LIMIT = \"RATE_LIMIT\",\n PROVIDER_ERROR = \"PROVIDER_ERROR\",\n MODEL_NOT_FOUND = \"MODEL_NOT_FOUND\",\n MODEL_OVERLOADED = \"MODEL_OVERLOADED\",\n CONTEXT_OVERFLOW = \"CONTEXT_OVERFLOW\",\n INVALID_INPUT = \"INVALID_INPUT\",\n INVALID_RESPONSE = \"INVALID_RESPONSE\",\n PERMISSION_DENIED = \"PERMISSION_DENIED\",\n BACKEND_NOT_INSTALLED = \"BACKEND_NOT_INSTALLED\",\n SESSION_NOT_FOUND = \"SESSION_NOT_FOUND\",\n STORAGE_ERROR = \"STORAGE_ERROR\",\n SESSION_EXPIRED = \"SESSION_EXPIRED\",\n DISPOSED = \"DISPOSED\",\n ABORTED = \"ABORTED\",\n INVALID_TRANSITION = \"INVALID_TRANSITION\",\n REENTRANCY = \"REENTRANCY\",\n}\n\n// ─── Error Options ─────────────────────────────────────────────\n\n/** Options for constructing a ChatError */\nexport interface ChatErrorOptions {\n /** Machine-readable error code */\n code: ChatErrorCode;\n /** Whether this error is retryable (default: false) */\n retryable?: boolean;\n /** Retry delay hint in milliseconds */\n retryAfter?: number;\n /** Original cause, if wrapping another error */\n cause?: unknown;\n}\n\n/** @deprecated Use ChatErrorOptions */\nexport type ChatSDKErrorOptions = ChatErrorOptions;\n\n// ─── Unified Error Class ───────────────────────────────────────\n\n/** Unified error class for all chat SDK errors */\nexport class ChatError extends AgentSDKError {\n readonly code: ChatErrorCode;\n readonly retryable: boolean;\n readonly retryAfter?: number;\n readonly timestamp: string;\n\n constructor(message: string, options: ChatErrorOptions) {\n super(message, { cause: options.cause });\n this.name = \"ChatError\";\n this.code = options.code;\n this.retryable = options.retryable ?? false;\n this.retryAfter = options.retryAfter;\n this.timestamp = new Date().toISOString();\n }\n}\n\n/** @deprecated Use ChatError */\nexport { ChatError as ChatSDKError };\n\n// ─── Classification ────────────────────────────────────────────\n\n/**\n * Classify an unknown thrown value into a ChatError with the appropriate code.\n * Pattern-matches against common error shapes:\n * - Already a ChatError → returned as-is\n * - Fetch/network errors (ECONNREFUSED, ETIMEDOUT, etc.)\n * - HTTP status codes (401→AUTH_INVALID, 429→RATE_LIMIT, 5xx→PROVIDER_ERROR)\n * - Timeout patterns\n * - Zod validation errors\n * - Context overflow patterns\n * - Unknown → wrapped as ChatError with PROVIDER_ERROR\n *\n * @param error - The thrown value to classify\n * @returns ChatError with appropriate error code and retryable flag\n */\nexport function classifyError(error: unknown): ChatError {\n if (error instanceof ChatError) {\n return error;\n }\n\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n\n // Network errors\n if (isNetworkError(msg)) {\n return new ChatError(error.message, {\n code: ChatErrorCode.NETWORK,\n retryable: true,\n cause: error,\n });\n }\n\n // Timeout errors\n if (isTimeoutPattern(msg)) {\n return new ChatError(error.message, {\n code: ChatErrorCode.TIMEOUT,\n retryable: true,\n cause: error,\n });\n }\n\n // Zod validation errors\n if (isZodError(error)) {\n return new ChatError(error.message, {\n code: ChatErrorCode.INVALID_INPUT,\n retryable: false,\n cause: error,\n });\n }\n\n // HTTP status code errors\n const statusCode = extractStatusCode(error);\n if (statusCode !== null) {\n return classifyByStatusCode(statusCode, error);\n }\n\n // Context overflow patterns\n if (isContextOverflow(msg)) {\n return new ChatError(error.message, {\n code: ChatErrorCode.CONTEXT_OVERFLOW,\n retryable: false,\n cause: error,\n });\n }\n }\n\n // Unknown errors\n const message =\n error instanceof Error ? error.message : String(error);\n return new ChatError(message, {\n code: ChatErrorCode.PROVIDER_ERROR,\n retryable: false,\n cause: error,\n });\n}\n\n// ─── Classification Helpers ────────────────────────────────────\n\nconst NETWORK_PATTERNS = [\n \"econnrefused\",\n \"econnreset\",\n \"enotfound\",\n \"etimedout\",\n \"enetunreach\",\n \"epipe\",\n \"fetch failed\",\n \"network error\",\n \"network request failed\",\n \"failed to fetch\",\n \"dns lookup failed\",\n] as const;\n\nfunction isNetworkError(msg: string): boolean {\n return NETWORK_PATTERNS.some((p) => msg.includes(p));\n}\n\nfunction isTimeoutPattern(msg: string): boolean {\n return (\n msg.includes(\"timeout\") ||\n msg.includes(\"timed out\") ||\n msg.includes(\"deadline exceeded\") ||\n msg.includes(\"aborted due to timeout\")\n );\n}\n\nfunction isZodError(error: Error): boolean {\n return (\n error.name === \"ZodError\" ||\n (\"issues\" in error && Array.isArray((error as unknown as Record<string, unknown>).issues))\n );\n}\n\nfunction extractStatusCode(error: Error): number | null {\n const errRecord = error as unknown as Record<string, unknown>;\n if (typeof errRecord.status === \"number\") return errRecord.status;\n if (typeof errRecord.statusCode === \"number\") return errRecord.statusCode;\n\n // Check message for HTTP status codes\n const match = error.message.match(/\\b(4\\d{2}|5\\d{2})\\b/);\n return match ? parseInt(match[1], 10) : null;\n}\n\nfunction classifyByStatusCode(status: number, error: Error): ChatError {\n if (status === 401 || status === 403) {\n return new ChatError(error.message, {\n code: ChatErrorCode.AUTH_INVALID,\n retryable: false,\n cause: error,\n });\n }\n if (status === 429) {\n const retryAfterSeconds = extractRetryAfter(error);\n return new ChatError(error.message, {\n code: ChatErrorCode.RATE_LIMIT,\n retryable: true,\n retryAfter: retryAfterSeconds != null ? retryAfterSeconds * 1000 : undefined,\n cause: error,\n });\n }\n if (status >= 500) {\n return new ChatError(error.message, {\n code: ChatErrorCode.PROVIDER_ERROR,\n retryable: true,\n cause: error,\n });\n }\n // 4xx other than auth/rate-limit → invalid input\n if (status >= 400 && status < 500) {\n return new ChatError(error.message, {\n code: ChatErrorCode.INVALID_INPUT,\n retryable: false,\n cause: error,\n });\n }\n return new ChatError(error.message, {\n code: ChatErrorCode.NETWORK,\n retryable: true,\n cause: error,\n });\n}\n\nfunction extractRetryAfter(error: Error): number | undefined {\n const errRecord = error as unknown as Record<string, unknown>;\n if (typeof errRecord.retryAfter === \"number\") return errRecord.retryAfter;\n const match = error.message.match(/retry.after[:\\s]*(\\d+)/i);\n return match ? parseInt(match[1], 10) : undefined;\n}\n\nfunction isContextOverflow(msg: string): boolean {\n return (\n msg.includes(\"context length exceeded\") ||\n msg.includes(\"maximum context length\") ||\n msg.includes(\"context window\") ||\n msg.includes(\"token limit\") ||\n msg.includes(\"too many tokens\")\n );\n}\n\n// ─── Retry Strategy ────────────────────────────────────────────\n\n/** Strategy for computing retry delays */\nexport interface RetryStrategy {\n /** Return delay in ms for the given attempt (0-based), or null to stop */\n nextDelay(attempt: number, error: ChatError): number | null;\n}\n\n/** Options for ExponentialBackoffStrategy */\nexport interface ExponentialBackoffOptions {\n /** Base delay in ms (default: 1000) */\n baseMs?: number;\n /** Maximum delay in ms (default: 30000) */\n maxMs?: number;\n /** Maximum number of attempts (default: 3) */\n maxAttempts?: number;\n /** Jitter factor 0–1 (default: 0.1) */\n jitter?: number;\n}\n\n/** Exponential backoff with optional jitter */\nexport class ExponentialBackoffStrategy implements RetryStrategy {\n private readonly baseMs: number;\n private readonly maxMs: number;\n private readonly maxAttempts: number;\n private readonly jitter: number;\n\n constructor(options?: ExponentialBackoffOptions) {\n this.baseMs = options?.baseMs ?? 1000;\n this.maxMs = options?.maxMs ?? 30000;\n this.maxAttempts = options?.maxAttempts ?? 3;\n this.jitter = Math.max(0, Math.min(1, options?.jitter ?? 0.1));\n }\n\n nextDelay(attempt: number, error: ChatError): number | null {\n if (attempt >= this.maxAttempts) return null;\n if (!error.retryable) return null;\n\n // Rate-limit errors with retryAfter (already in ms) take priority\n if (error.code === ChatErrorCode.RATE_LIMIT && error.retryAfter) {\n return error.retryAfter;\n }\n\n const delay = Math.min(this.baseMs * Math.pow(2, attempt), this.maxMs);\n const jitterAmount = delay * this.jitter * (Math.random() * 2 - 1);\n return Math.max(0, Math.round(delay + jitterAmount));\n }\n}\n\n// ─── Retry Execution ───────────────────────────────────────────\n\n/** Options for withRetry execution */\nexport interface RetryOptions {\n /** Abort signal to cancel retries */\n signal?: AbortSignal;\n /** Called before each retry with the error and delay */\n onRetry?: (error: ChatError, attempt: number, delayMs: number) => void;\n}\n\n/**\n * Execute an async function with automatic retries using the provided strategy.\n * Respects ChatError.retryable and ChatError.retryAfter.\n * Classifies non-ChatError errors before deciding on retry.\n *\n * @param fn - Async function to execute\n * @param strategy - Retry strategy providing delay calculations\n * @param options - Optional abort signal and retry callback\n * @returns Result of fn on success\n * @throws ChatError when all retries exhausted or error is non-retryable\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n strategy: RetryStrategy,\n options?: RetryOptions,\n): Promise<T> {\n let attempt = 0;\n\n for (;;) {\n try {\n return await fn();\n } catch (raw) {\n const error = classifyError(raw);\n const delay = strategy.nextDelay(attempt, error);\n\n if (delay === null) {\n throw error;\n }\n\n if (options?.signal?.aborted) {\n throw error;\n }\n\n options?.onRetry?.(error, attempt, delay);\n\n await sleep(delay, options?.signal);\n attempt++;\n }\n }\n}\n\n/**\n * Type guard: check if an error is retryable\n * @param error - The error to check\n * @returns True if error is a retryable ChatError\n */\nexport function isRetryable(error: unknown): boolean {\n if (error instanceof ChatError) {\n return error.retryable;\n }\n const classified = classifyError(error);\n return classified.retryable;\n}\n\n// ─── Internal Helpers ──────────────────────────────────────────\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new ChatError(\"Retry aborted\", { code: ChatErrorCode.ABORTED }));\n return;\n }\n\n const timer = setTimeout(resolve, ms);\n\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timer);\n reject(new ChatError(\"Retry aborted\", { code: ChatErrorCode.ABORTED }));\n },\n { once: true },\n );\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/types/errors.ts","../../src/errors.ts","../../src/chat/errors.ts"],"names":["ErrorCode"],"mappings":"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","file":"errors.js","sourcesContent":["// ─── Unified Error Code Enum ───────────────────────────────────\n\n/** Unified error codes for all SDK errors — single source of truth. */\nexport enum ErrorCode {\n // Auth\n AUTH_EXPIRED = \"AUTH_EXPIRED\",\n AUTH_INVALID = \"AUTH_INVALID\",\n\n // Rate limiting\n RATE_LIMIT = \"RATE_LIMIT\",\n\n // Network\n NETWORK = \"NETWORK\",\n TIMEOUT = \"TIMEOUT\",\n\n // Provider\n PROVIDER_ERROR = \"PROVIDER_ERROR\",\n MODEL_NOT_FOUND = \"MODEL_NOT_FOUND\",\n MODEL_OVERLOADED = \"MODEL_OVERLOADED\",\n CONTEXT_OVERFLOW = \"CONTEXT_OVERFLOW\",\n\n // Input / Response\n INVALID_INPUT = \"INVALID_INPUT\",\n INVALID_RESPONSE = \"INVALID_RESPONSE\",\n\n // SDK internal\n REENTRANCY = \"REENTRANCY\",\n DISPOSED = \"DISPOSED\",\n ABORTED = \"ABORTED\",\n INVALID_TRANSITION = \"INVALID_TRANSITION\",\n DEPENDENCY_MISSING = \"DEPENDENCY_MISSING\",\n BACKEND_NOT_INSTALLED = \"BACKEND_NOT_INSTALLED\",\n\n // Tool\n TOOL_EXECUTION = \"TOOL_EXECUTION\",\n PERMISSION_DENIED = \"PERMISSION_DENIED\",\n\n // Session\n SESSION_NOT_FOUND = \"SESSION_NOT_FOUND\",\n SESSION_EXPIRED = \"SESSION_EXPIRED\",\n\n // Provider resolution\n PROVIDER_NOT_FOUND = \"PROVIDER_NOT_FOUND\",\n AUTH_REQUIRED = \"AUTH_REQUIRED\",\n\n // Storage (generic)\n STORAGE_ERROR = \"STORAGE_ERROR\",\n // Storage (specific)\n STORAGE_NOT_FOUND = \"STORAGE_NOT_FOUND\",\n STORAGE_DUPLICATE_KEY = \"STORAGE_DUPLICATE_KEY\",\n STORAGE_IO_ERROR = \"STORAGE_IO_ERROR\",\n STORAGE_SERIALIZATION_ERROR = \"STORAGE_SERIALIZATION_ERROR\",\n}\n\n// ─── Classification ────────────────────────────────────────────\n\n/** Error codes that are typically recoverable (retry-safe) */\nconst RECOVERABLE_CODES = new Set<ErrorCode>([\n ErrorCode.TIMEOUT,\n ErrorCode.RATE_LIMIT,\n ErrorCode.NETWORK,\n ErrorCode.TOOL_EXECUTION,\n ErrorCode.MODEL_OVERLOADED,\n ErrorCode.PROVIDER_ERROR,\n]);\n\n/** Check if an error code is recoverable */\nexport function isRecoverableErrorCode(code: ErrorCode): boolean {\n return RECOVERABLE_CODES.has(code);\n}\n\n/** Classify an error message string into an ErrorCode */\nexport function classifyAgentError(error: string | Error): ErrorCode {\n const msg = (error instanceof Error ? error.message : error).toLowerCase();\n\n if (msg.includes(\"timeout\") || msg.includes(\"timed out\") || msg.includes(\"timedout\") || msg.includes(\"etimedout\")) {\n return ErrorCode.TIMEOUT;\n }\n\n if (msg.includes(\"rate limit\") || msg.includes(\"rate_limit\") || msg.includes(\"429\") || msg.includes(\"too many requests\")) {\n return ErrorCode.RATE_LIMIT;\n }\n\n if (msg.includes(\"unauthorized\") || msg.includes(\"401\") || msg.includes(\"auth\") && (msg.includes(\"expired\") || msg.includes(\"invalid\") || msg.includes(\"denied\") || msg.includes(\"failed\"))) {\n return ErrorCode.AUTH_EXPIRED;\n }\n\n if (msg.includes(\"econnrefused\") || msg.includes(\"econnreset\") || msg.includes(\"enotfound\") || msg.includes(\"network\") || msg.includes(\"fetch failed\") || msg.includes(\"socket hang up\")) {\n return ErrorCode.NETWORK;\n }\n\n if (msg.includes(\"subprocess\") || msg.includes(\"process exited\") || msg.includes(\"spawn\") || msg.includes(\"enoent\") || msg.includes(\"killed\")) {\n return ErrorCode.DEPENDENCY_MISSING;\n }\n\n if (msg.includes(\"abort\") || msg.includes(\"cancel\")) {\n return ErrorCode.ABORTED;\n }\n\n if (msg.includes(\"500\") || msg.includes(\"502\") || msg.includes(\"503\") || msg.includes(\"internal server error\") || msg.includes(\"service unavailable\") || msg.includes(\"bad gateway\") || msg.includes(\"overloaded\")) {\n return ErrorCode.PROVIDER_ERROR;\n }\n\n return ErrorCode.PROVIDER_ERROR;\n}\n","import { ErrorCode } from \"./types/errors.js\";\n\n/** Options for constructing an AgentSDKError */\nexport interface AgentSDKErrorOptions extends ErrorOptions {\n /** Machine-readable error code */\n code?: string;\n /** Whether this error is retryable (default: false) */\n retryable?: boolean;\n /** HTTP status code hint (e.g. 401, 429, 500) */\n httpStatus?: number;\n}\n\n/** Base error class for agent-sdk.\n *\n * Use `AgentSDKError.is(err)` for reliable cross-module `instanceof` checks\n * (works across separately bundled entry points where `instanceof` may fail). */\nexport class AgentSDKError extends Error {\n /** @internal Marker for cross-bundle identity checks */\n readonly _agentSDKError = true as const;\n /** Machine-readable error code. Prefer values from the ErrorCode enum. */\n readonly code?: string;\n /** Whether this error is safe to retry */\n readonly retryable: boolean;\n /** HTTP status code hint for error classification */\n readonly httpStatus?: number;\n\n constructor(message: string, options?: AgentSDKErrorOptions) {\n super(message, options);\n this.name = \"AgentSDKError\";\n this.code = options?.code;\n this.retryable = options?.retryable ?? false;\n this.httpStatus = options?.httpStatus;\n }\n\n /** Check if an error is an AgentSDKError (works across bundled copies) */\n static is(error: unknown): error is AgentSDKError {\n return (\n error instanceof Error &&\n \"_agentSDKError\" in error &&\n (error as AgentSDKError)._agentSDKError === true\n );\n }\n}\n\n/** Thrown when agent.run() is called while already running (M8 re-entrancy guard) */\nexport class ReentrancyError extends AgentSDKError {\n constructor() {\n super(\"Agent is already running. Await the current run before starting another.\", {\n code: ErrorCode.REENTRANCY,\n });\n this.name = \"ReentrancyError\";\n }\n}\n\n/** Thrown when an operation is attempted on a disposed agent/service */\nexport class DisposedError extends AgentSDKError {\n constructor(entity: string) {\n super(`${entity} has been disposed and cannot be used.`, {\n code: ErrorCode.DISPOSED,\n });\n this.name = \"DisposedError\";\n }\n}\n\n/** Thrown when a backend is not found in the registry */\nexport class BackendNotFoundError extends AgentSDKError {\n constructor(backend: string) {\n super(\n `Unknown backend: \"${backend}\". ` +\n `Built-in: copilot, claude, vercel-ai. ` +\n `Custom: use registerBackend() first.`,\n { code: ErrorCode.BACKEND_NOT_INSTALLED },\n );\n this.name = \"BackendNotFoundError\";\n }\n}\n\n/** Thrown when a backend is already registered */\nexport class BackendAlreadyRegisteredError extends AgentSDKError {\n constructor(backend: string) {\n super(`Backend \"${backend}\" is already registered. Use a different name or unregister first.`);\n this.name = \"BackendAlreadyRegisteredError\";\n }\n}\n\n/** Thrown when subprocess management fails */\nexport class SubprocessError extends AgentSDKError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, { ...options, code: ErrorCode.DEPENDENCY_MISSING });\n this.name = \"SubprocessError\";\n }\n}\n\n/** Thrown when a required peer dependency is not installed */\nexport class DependencyError extends AgentSDKError {\n public readonly packageName: string;\n\n constructor(packageName: string) {\n super(`${packageName} is not installed. Install it: npm install ${packageName}`, {\n code: ErrorCode.DEPENDENCY_MISSING,\n });\n this.name = \"DependencyError\";\n this.packageName = packageName;\n }\n}\n\n/** Thrown when an agent run is aborted */\nexport class AbortError extends AgentSDKError {\n constructor() {\n super(\"Agent run was aborted.\", { code: ErrorCode.ABORTED });\n this.name = \"AbortError\";\n }\n}\n\n/** Thrown when a tool execution fails */\nexport class ToolExecutionError extends AgentSDKError {\n public readonly toolName: string;\n\n constructor(toolName: string, message: string, options?: ErrorOptions) {\n super(`Tool \"${toolName}\" failed: ${message}`, { ...options, code: ErrorCode.TOOL_EXECUTION });\n this.name = \"ToolExecutionError\";\n this.toolName = toolName;\n }\n}\n\n/** Thrown when a stream has no activity within the configured timeout */\nexport class ActivityTimeoutError extends AgentSDKError {\n constructor(timeoutMs: number) {\n super(`Stream activity timeout: no event received within ${timeoutMs}ms.`, {\n code: ErrorCode.TIMEOUT,\n retryable: true,\n });\n this.name = \"ActivityTimeoutError\";\n }\n}\n\n/** Thrown when structured output parsing fails */\nexport class StructuredOutputError extends AgentSDKError {\n constructor(message: string, options?: ErrorOptions) {\n super(`Structured output error: ${message}`, { ...options, code: ErrorCode.INVALID_RESPONSE });\n this.name = \"StructuredOutputError\";\n }\n}\n","/**\n * @witqq/agent-sdk/chat/errors\n *\n * Flat error taxonomy with unified ErrorCode enum, ChatError class,\n * pattern-matching classifier, retry strategies with exponential backoff.\n * Extends the existing AgentSDKError from @witqq/agent-sdk.\n */\n\nimport { AgentSDKError } from \"../errors.js\";\nimport { ErrorCode } from \"../types/errors.js\";\n\n// ─── Re-export ErrorCode ───────────────────────────────────────\n\nexport { ErrorCode };\n\n// ─── Error Options ─────────────────────────────────────────────\n\n/** Options for constructing a ChatError */\nexport interface ChatErrorOptions {\n /** Machine-readable error code */\n code: ErrorCode;\n /** Whether this error is retryable (default: false) */\n retryable?: boolean;\n /** Retry delay hint in milliseconds */\n retryAfter?: number;\n /** Original cause, if wrapping another error */\n cause?: unknown;\n}\n\n// ─── Unified Error Class ───────────────────────────────────────\n\n/** Unified error class for all chat SDK errors */\nexport class ChatError extends AgentSDKError {\n readonly code: ErrorCode;\n readonly retryable: boolean;\n readonly retryAfter?: number;\n readonly timestamp: string;\n\n constructor(message: string, options: ChatErrorOptions) {\n super(message, {\n cause: options.cause,\n code: options.code,\n retryable: options.retryable,\n });\n this.name = \"ChatError\";\n this.code = options.code;\n this.retryable = options.retryable ?? false;\n this.retryAfter = options.retryAfter;\n this.timestamp = new Date().toISOString();\n }\n}\n\n// ─── Classification ────────────────────────────────────────────\n\n/**\n * Classify an unknown thrown value into a ChatError with the appropriate code.\n * Pattern-matches against common error shapes:\n * - Already a ChatError → returned as-is\n * - Fetch/network errors (ECONNREFUSED, ETIMEDOUT, etc.)\n * - HTTP status codes (401→AUTH_INVALID, 429→RATE_LIMIT, 5xx→PROVIDER_ERROR)\n * - Timeout patterns\n * - Zod validation errors\n * - Context overflow patterns\n * - Unknown → wrapped as ChatError with PROVIDER_ERROR\n *\n * @param error - The thrown value to classify\n * @returns ChatError with appropriate error code and retryable flag\n */\nexport function classifyError(error: unknown): ChatError {\n if (error instanceof ChatError) {\n return error;\n }\n\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n\n // Network errors\n if (isNetworkError(msg)) {\n return new ChatError(error.message, {\n code: ErrorCode.NETWORK,\n retryable: true,\n cause: error,\n });\n }\n\n // Timeout errors\n if (isTimeoutPattern(msg)) {\n return new ChatError(error.message, {\n code: ErrorCode.TIMEOUT,\n retryable: true,\n cause: error,\n });\n }\n\n // Zod validation errors\n if (isZodError(error)) {\n return new ChatError(error.message, {\n code: ErrorCode.INVALID_INPUT,\n retryable: false,\n cause: error,\n });\n }\n\n // HTTP status code errors\n const statusCode = extractStatusCode(error);\n if (statusCode !== null) {\n return classifyByStatusCode(statusCode, error);\n }\n\n // Context overflow patterns\n if (isContextOverflow(msg)) {\n return new ChatError(error.message, {\n code: ErrorCode.CONTEXT_OVERFLOW,\n retryable: false,\n cause: error,\n });\n }\n }\n\n // Unknown errors\n const message =\n error instanceof Error ? error.message : String(error);\n return new ChatError(message, {\n code: ErrorCode.PROVIDER_ERROR,\n retryable: false,\n cause: error,\n });\n}\n\n// ─── Classification Helpers ────────────────────────────────────\n\nconst NETWORK_PATTERNS = [\n \"econnrefused\",\n \"econnreset\",\n \"enotfound\",\n \"etimedout\",\n \"enetunreach\",\n \"epipe\",\n \"fetch failed\",\n \"network error\",\n \"network request failed\",\n \"failed to fetch\",\n \"dns lookup failed\",\n] as const;\n\nfunction isNetworkError(msg: string): boolean {\n return NETWORK_PATTERNS.some((p) => msg.includes(p));\n}\n\nfunction isTimeoutPattern(msg: string): boolean {\n return (\n msg.includes(\"timeout\") ||\n msg.includes(\"timed out\") ||\n msg.includes(\"deadline exceeded\") ||\n msg.includes(\"aborted due to timeout\")\n );\n}\n\nfunction isZodError(error: Error): boolean {\n return (\n error.name === \"ZodError\" ||\n (\"issues\" in error && Array.isArray((error as unknown as Record<string, unknown>).issues))\n );\n}\n\nfunction extractStatusCode(error: Error): number | null {\n const errRecord = error as unknown as Record<string, unknown>;\n if (typeof errRecord.status === \"number\") return errRecord.status;\n if (typeof errRecord.statusCode === \"number\") return errRecord.statusCode;\n\n // Check message for HTTP status codes\n const match = error.message.match(/\\b(4\\d{2}|5\\d{2})\\b/);\n return match ? parseInt(match[1], 10) : null;\n}\n\nfunction classifyByStatusCode(status: number, error: Error): ChatError {\n if (status === 401 || status === 403) {\n return new ChatError(error.message, {\n code: ErrorCode.AUTH_INVALID,\n retryable: false,\n cause: error,\n });\n }\n if (status === 429) {\n const retryAfterSeconds = extractRetryAfter(error);\n return new ChatError(error.message, {\n code: ErrorCode.RATE_LIMIT,\n retryable: true,\n retryAfter: retryAfterSeconds != null ? retryAfterSeconds * 1000 : undefined,\n cause: error,\n });\n }\n if (status >= 500) {\n return new ChatError(error.message, {\n code: ErrorCode.PROVIDER_ERROR,\n retryable: true,\n cause: error,\n });\n }\n // 4xx other than auth/rate-limit → invalid input\n if (status >= 400 && status < 500) {\n return new ChatError(error.message, {\n code: ErrorCode.INVALID_INPUT,\n retryable: false,\n cause: error,\n });\n }\n return new ChatError(error.message, {\n code: ErrorCode.NETWORK,\n retryable: true,\n cause: error,\n });\n}\n\nfunction extractRetryAfter(error: Error): number | undefined {\n const errRecord = error as unknown as Record<string, unknown>;\n if (typeof errRecord.retryAfter === \"number\") return errRecord.retryAfter;\n const match = error.message.match(/retry.after[:\\s]*(\\d+)/i);\n return match ? parseInt(match[1], 10) : undefined;\n}\n\nfunction isContextOverflow(msg: string): boolean {\n return (\n msg.includes(\"context length exceeded\") ||\n msg.includes(\"maximum context length\") ||\n msg.includes(\"context window\") ||\n msg.includes(\"token limit\") ||\n msg.includes(\"too many tokens\")\n );\n}\n\n// ─── Retry Strategy ────────────────────────────────────────────\n\n/** Strategy for computing retry delays */\nexport interface RetryStrategy {\n /** Return delay in ms for the given attempt (0-based), or null to stop */\n nextDelay(attempt: number, error: ChatError): number | null;\n}\n\n/** Options for ExponentialBackoffStrategy */\nexport interface ExponentialBackoffOptions {\n /** Base delay in ms (default: 1000) */\n baseMs?: number;\n /** Maximum delay in ms (default: 30000) */\n maxMs?: number;\n /** Maximum number of attempts (default: 3) */\n maxAttempts?: number;\n /** Jitter factor 0–1 (default: 0.1) */\n jitter?: number;\n}\n\n/** Exponential backoff with optional jitter */\nexport class ExponentialBackoffStrategy implements RetryStrategy {\n private readonly baseMs: number;\n private readonly maxMs: number;\n private readonly maxAttempts: number;\n private readonly jitter: number;\n\n constructor(options?: ExponentialBackoffOptions) {\n this.baseMs = options?.baseMs ?? 1000;\n this.maxMs = options?.maxMs ?? 30000;\n this.maxAttempts = options?.maxAttempts ?? 3;\n this.jitter = Math.max(0, Math.min(1, options?.jitter ?? 0.1));\n }\n\n nextDelay(attempt: number, error: ChatError): number | null {\n if (attempt >= this.maxAttempts) return null;\n if (!error.retryable) return null;\n\n // Rate-limit errors with retryAfter (already in ms) take priority\n if (error.code === ErrorCode.RATE_LIMIT && error.retryAfter) {\n return error.retryAfter;\n }\n\n const delay = Math.min(this.baseMs * Math.pow(2, attempt), this.maxMs);\n const jitterAmount = delay * this.jitter * (Math.random() * 2 - 1);\n return Math.max(0, Math.round(delay + jitterAmount));\n }\n}\n\n// ─── Retry Execution ───────────────────────────────────────────\n\n/** Options for withRetry execution */\nexport interface RetryOptions {\n /** Abort signal to cancel retries */\n signal?: AbortSignal;\n /** Called before each retry with the error and delay */\n onRetry?: (error: ChatError, attempt: number, delayMs: number) => void;\n}\n\n/**\n * Execute an async function with automatic retries using the provided strategy.\n * Respects ChatError.retryable and ChatError.retryAfter.\n * Classifies non-ChatError errors before deciding on retry.\n *\n * @param fn - Async function to execute\n * @param strategy - Retry strategy providing delay calculations\n * @param options - Optional abort signal and retry callback\n * @returns Result of fn on success\n * @throws ChatError when all retries exhausted or error is non-retryable\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n strategy: RetryStrategy,\n options?: RetryOptions,\n): Promise<T> {\n let attempt = 0;\n\n for (;;) {\n try {\n return await fn();\n } catch (raw) {\n const error = classifyError(raw);\n const delay = strategy.nextDelay(attempt, error);\n\n if (delay === null) {\n throw error;\n }\n\n if (options?.signal?.aborted) {\n throw error;\n }\n\n options?.onRetry?.(error, attempt, delay);\n\n await sleep(delay, options?.signal);\n attempt++;\n }\n }\n}\n\n/**\n * Type guard: check if an error is retryable\n * @param error - The error to check\n * @returns True if error is a retryable ChatError\n */\nexport function isRetryable(error: unknown): boolean {\n if (error instanceof ChatError) {\n return error.retryable;\n }\n const classified = classifyError(error);\n return classified.retryable;\n}\n\n// ─── Internal Helpers ──────────────────────────────────────────\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new ChatError(\"Retry aborted\", { code: ErrorCode.ABORTED }));\n return;\n }\n\n const timer = setTimeout(resolve, ms);\n\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timer);\n reject(new ChatError(\"Retry aborted\", { code: ErrorCode.ABORTED }));\n },\n { once: true },\n );\n });\n}\n"]}
|
package/dist/chat/events.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/chat/events.ts"],"names":[],"mappings":"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","file":"events.cjs","sourcesContent":["/**\n * @witqq/agent-sdk/chat/events\n *\n * Type-safe event emitter, chat event bus, and middleware pipeline.\n * Generic TypedEventEmitter<EventMap> for arbitrary typed event maps.\n * ChatEventBus specializing TypedEventEmitter for ChatEvent types.\n * Middleware support for event interception, transformation, and suppression.\n * Utility functions for filtering and mapping event streams.\n */\n\nimport type { ChatEvent, ChatEventType } from \"./core.js\";\n\n// ─── EventMap constraint ──────────────────────────────────────\n\n/** Constraint for event maps: keys are strings, values are payloads */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type EventMap = Record<string, any>;\n\n// ─── Listener types ───────────────────────────────────────────\n\n/** Listener callback for a specific event */\nexport type Listener<T> = (payload: T) => void;\n\n/** Unsubscribe function returned by on/once */\nexport type Unsubscribe = () => void;\n\n// ─── TypedEventEmitter ────────────────────────────────────────\n\n/**\n * Generic type-safe event emitter parameterized by an EventMap.\n *\n * @typeParam T - Map of event names to payload types\n *\n * @example\n * ```typescript\n * type MyEvents = {\n * message: string;\n * count: number;\n * done: void;\n * };\n * const emitter = new TypedEventEmitter<MyEvents>();\n * emitter.on(\"message\", (text) => console.log(text));\n * emitter.emit(\"message\", \"hello\");\n * ```\n */\nexport class TypedEventEmitter<T extends EventMap> {\n private readonly listeners = new Map<keyof T, Set<Listener<unknown>>>();\n\n /**\n * Subscribe to an event.\n * @param event - Event name\n * @param listener - Callback receiving the event payload\n * @returns Unsubscribe function\n */\n on<K extends keyof T>(event: K, listener: Listener<T[K]>): Unsubscribe {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n const fn = listener as Listener<unknown>;\n set.add(fn);\n return () => {\n set!.delete(fn);\n if (set!.size === 0) {\n this.listeners.delete(event);\n }\n };\n }\n\n /**\n * Subscribe to an event, firing the listener at most once.\n * @param event - Event name\n * @param listener - Callback receiving the event payload\n * @returns Unsubscribe function\n */\n once<K extends keyof T>(event: K, listener: Listener<T[K]>): Unsubscribe {\n const unsub = this.on(event, (payload) => {\n unsub();\n listener(payload);\n });\n return unsub;\n }\n\n /**\n * Remove a specific listener from an event.\n * @param event - Event name\n * @param listener - The listener to remove\n */\n off<K extends keyof T>(event: K, listener: Listener<T[K]>): void {\n const set = this.listeners.get(event);\n if (!set) return;\n set.delete(listener as Listener<unknown>);\n if (set.size === 0) {\n this.listeners.delete(event);\n }\n }\n\n /**\n * Emit an event, calling all registered listeners synchronously.\n * @param event - Event name\n * @param payload - Event payload\n */\n emit<K extends keyof T>(event: K, payload: T[K]): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const fn of [...set]) {\n fn(payload);\n }\n }\n\n /**\n * Remove all listeners for a specific event, or all events if no event specified.\n * @param event - Optional event name\n */\n removeAllListeners<K extends keyof T>(event?: K): void {\n if (event !== undefined) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n\n /**\n * Get the number of listeners for a specific event.\n * @param event - Event name\n * @returns Number of listeners\n */\n listenerCount<K extends keyof T>(event: K): number {\n const set = this.listeners.get(event);\n return set ? set.size : 0;\n }\n\n /**\n * Get all event names that have at least one listener.\n * @returns Array of event names\n */\n eventNames(): Array<keyof T> {\n return [...this.listeners.keys()];\n }\n}\n\n// ─── ChatEventMap ─────────────────────────────────────────────\n\n/**\n * Map of ChatEvent type strings to their corresponding ChatEvent payloads.\n * Used to parameterize TypedEventEmitter for chat events.\n */\nexport type ChatEventMap = {\n [K in ChatEventType]: Extract<ChatEvent, { type: K }>;\n};\n\n// ─── Middleware ────────────────────────────────────────────────\n\n/**\n * Context passed to middleware functions.\n * Contains the event and control methods for the middleware pipeline.\n */\nexport interface MiddlewareContext {\n /** The current event (may be transformed by prior middleware) */\n event: ChatEvent;\n /** Call the next middleware in the chain, or deliver to listeners if last */\n next: () => void;\n /** Suppress the event — do not deliver to listeners or subsequent middleware */\n suppress: () => void;\n}\n\n/**\n * Middleware function for intercepting, transforming, or suppressing events.\n *\n * @param ctx - Middleware context with event, next(), and suppress()\n *\n * @example\n * ```typescript\n * // Logging middleware\n * const logger: EventMiddleware = (ctx) => {\n * console.log(`Event: ${ctx.event.type}`);\n * ctx.next();\n * };\n *\n * // Suppressing middleware\n * const filter: EventMiddleware = (ctx) => {\n * if (ctx.event.type === \"heartbeat\") {\n * ctx.suppress();\n * } else {\n * ctx.next();\n * }\n * };\n * ```\n */\nexport type EventMiddleware = (ctx: MiddlewareContext) => void;\n\n// ─── ChatEventBus ─────────────────────────────────────────────\n\n/**\n * Chat event bus: a typed event emitter specialized for ChatEvent types\n * with middleware pipeline support.\n *\n * Events pass through the middleware pipeline before reaching listeners.\n * Middleware can inspect, transform, or suppress events.\n *\n * @example\n * ```typescript\n * const bus = new ChatEventBus();\n *\n * // Add middleware\n * bus.use((ctx) => {\n * console.log(`[${ctx.event.type}]`);\n * ctx.next();\n * });\n *\n * // Listen for events\n * bus.on(\"message:delta\", (event) => {\n * console.log(event.text);\n * });\n *\n * // Emit events\n * bus.emit(\"message:delta\", { type: \"message:delta\", messageId: id, text: \"hi\" });\n * ```\n */\nexport class ChatEventBus extends TypedEventEmitter<ChatEventMap> {\n private readonly middlewares: EventMiddleware[] = [];\n\n /**\n * Register a middleware function. Middleware runs in registration order.\n * @param middleware - Middleware function\n * @returns Unsubscribe function to remove the middleware\n */\n use(middleware: EventMiddleware): Unsubscribe {\n this.middlewares.push(middleware);\n return () => {\n const idx = this.middlewares.indexOf(middleware);\n if (idx !== -1) {\n this.middlewares.splice(idx, 1);\n }\n };\n }\n\n /**\n * Emit a chat event through the middleware pipeline, then to listeners.\n *\n * @param event - ChatEvent type string\n * @param payload - The full ChatEvent object\n */\n override emit<K extends ChatEventType>(\n event: K,\n payload: ChatEventMap[K],\n ): void {\n if (this.middlewares.length === 0) {\n super.emit(event, payload);\n return;\n }\n\n let suppressed = false;\n let currentEvent: ChatEvent = payload;\n let index = 0;\n\n const runNext = (): void => {\n if (suppressed) return;\n\n if (index >= this.middlewares.length) {\n super.emit(\n currentEvent.type as K,\n currentEvent as ChatEventMap[K],\n );\n return;\n }\n\n const mw = this.middlewares[index++];\n const ctx: MiddlewareContext = {\n event: currentEvent,\n next: () => {\n currentEvent = ctx.event;\n runNext();\n },\n suppress: () => {\n suppressed = true;\n },\n };\n mw(ctx);\n };\n\n runNext();\n }\n\n /**\n * Replace the event in the middleware context.\n * Middleware should mutate ctx.event or create a new MiddlewareContext\n * to transform events passing through the pipeline.\n */\n\n /**\n * Remove all middleware functions.\n */\n clearMiddleware(): void {\n this.middlewares.length = 0;\n }\n\n /**\n * Get the number of registered middleware functions.\n * @returns Number of middleware\n */\n middlewareCount(): number {\n return this.middlewares.length;\n }\n}\n\n// ─── Utility: Event Filtering ─────────────────────────────────\n\n/**\n * Create a filter function that passes only events of specified types.\n *\n * @param types - Event types to allow through\n * @returns Predicate function for filtering ChatEvents\n *\n * @example\n * ```typescript\n * const isTextEvent = eventFilter(\"message:start\", \"message:delta\", \"message:complete\");\n * const textEvents = allEvents.filter(isTextEvent);\n * ```\n */\nexport function eventFilter(\n ...types: ChatEventType[]\n): (event: ChatEvent) => boolean {\n const allowed = new Set<string>(types);\n return (event: ChatEvent) => allowed.has(event.type);\n}\n\n/**\n * Filter an async iterable of ChatEvents to only specified types.\n *\n * @param source - Async iterable of ChatEvents\n * @param types - Event types to keep\n * @returns Async iterable of filtered ChatEvents\n *\n * @example\n * ```typescript\n * for await (const event of filterEvents(stream, \"message:delta\", \"message:complete\")) {\n * // only message:delta and message:complete events\n * }\n * ```\n */\nexport async function* filterEvents(\n source: AsyncIterable<ChatEvent>,\n ...types: ChatEventType[]\n): AsyncIterable<ChatEvent> {\n const pred = eventFilter(...types);\n for await (const event of source) {\n if (pred(event)) {\n yield event;\n }\n }\n}\n\n// ─── Utility: Event Mapping ───────────────────────────────────\n\n/**\n * Map/transform events from an async iterable.\n *\n * @param source - Async iterable of ChatEvents\n * @param transform - Function to transform each event (return null to skip)\n * @returns Async iterable of transformed values\n *\n * @example\n * ```typescript\n * // Extract text from message:delta events\n * const texts = mapEvents(stream, (event) =>\n * event.type === \"message:delta\" ? event.text : null\n * );\n * ```\n */\nexport async function* mapEvents<R>(\n source: AsyncIterable<ChatEvent>,\n transform: (event: ChatEvent) => R | null,\n): AsyncIterable<R> {\n for await (const event of source) {\n const result = transform(event);\n if (result !== null) {\n yield result;\n }\n }\n}\n\n/**\n * Collect text from message:delta events into a single string.\n *\n * @param source - Async iterable of ChatEvents\n * @returns Complete text assembled from message:delta payloads\n *\n * @example\n * ```typescript\n * const fullText = await collectText(stream);\n * ```\n */\nexport async function collectText(\n source: AsyncIterable<ChatEvent>,\n): Promise<string> {\n const parts: string[] = [];\n for await (const event of source) {\n if (event.type === \"message:delta\") {\n parts.push(event.text);\n }\n }\n return parts.join(\"\");\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/chat/events.ts"],"names":[],"mappings":"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","file":"events.cjs","sourcesContent":["/**\n * @witqq/agent-sdk/chat/events\n *\n * Type-safe event emitter, chat event bus, and middleware pipeline.\n * Generic TypedEventEmitter<EventMap> for arbitrary typed event maps.\n * ChatEventBus specializing TypedEventEmitter for ChatEvent types.\n * Middleware support for event interception, transformation, and suppression.\n * Utility functions for filtering and mapping event streams.\n */\n\nimport type { ChatEvent, ChatEventType } from \"./core.js\";\n\n// ─── EventMap constraint ──────────────────────────────────────\n\n/** Constraint for event maps: keys are strings, values are payloads */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type EventMap = Record<string, any>;\n\n// ─── Listener types ───────────────────────────────────────────\n\n/** Listener callback for a specific event */\nexport type Listener<T> = (payload: T) => void;\n\n/** Unsubscribe function returned by on/once */\nexport type Unsubscribe = () => void;\n\n// ─── TypedEventEmitter ────────────────────────────────────────\n\n/**\n * Generic type-safe event emitter parameterized by an EventMap.\n *\n * @typeParam T - Map of event names to payload types\n *\n * @example\n * ```typescript\n * type MyEvents = {\n * message: string;\n * count: number;\n * done: void;\n * };\n * const emitter = new TypedEventEmitter<MyEvents>();\n * emitter.on(\"message\", (text) => console.log(text));\n * emitter.emit(\"message\", \"hello\");\n * ```\n */\nexport class TypedEventEmitter<T extends EventMap> {\n private readonly listeners = new Map<keyof T, Set<Listener<unknown>>>();\n\n /**\n * Subscribe to an event.\n * @param event - Event name\n * @param listener - Callback receiving the event payload\n * @returns Unsubscribe function\n */\n on<K extends keyof T>(event: K, listener: Listener<T[K]>): Unsubscribe {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n const fn = listener as Listener<unknown>;\n set.add(fn);\n return () => {\n set!.delete(fn);\n if (set!.size === 0) {\n this.listeners.delete(event);\n }\n };\n }\n\n /**\n * Subscribe to an event, firing the listener at most once.\n * @param event - Event name\n * @param listener - Callback receiving the event payload\n * @returns Unsubscribe function\n */\n once<K extends keyof T>(event: K, listener: Listener<T[K]>): Unsubscribe {\n const unsub = this.on(event, (payload) => {\n unsub();\n listener(payload);\n });\n return unsub;\n }\n\n /**\n * Remove a specific listener from an event.\n * @param event - Event name\n * @param listener - The listener to remove\n */\n off<K extends keyof T>(event: K, listener: Listener<T[K]>): void {\n const set = this.listeners.get(event);\n if (!set) return;\n set.delete(listener as Listener<unknown>);\n if (set.size === 0) {\n this.listeners.delete(event);\n }\n }\n\n /**\n * Emit an event, calling all registered listeners synchronously.\n * @param event - Event name\n * @param payload - Event payload\n */\n emit<K extends keyof T>(event: K, payload: T[K]): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const fn of [...set]) {\n fn(payload);\n }\n }\n\n /**\n * Remove all listeners for a specific event, or all events if no event specified.\n * @param event - Optional event name\n */\n removeAllListeners<K extends keyof T>(event?: K): void {\n if (event !== undefined) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n\n /**\n * Get the number of listeners for a specific event.\n * @param event - Event name\n * @returns Number of listeners\n */\n listenerCount<K extends keyof T>(event: K): number {\n const set = this.listeners.get(event);\n return set ? set.size : 0;\n }\n\n /**\n * Get all event names that have at least one listener.\n * @returns Array of event names\n */\n eventNames(): Array<keyof T> {\n return [...this.listeners.keys()];\n }\n}\n\n// ─── ChatEventMap ─────────────────────────────────────────────\n\n/**\n * Map of ChatEvent type strings to their corresponding ChatEvent payloads.\n * Used to parameterize TypedEventEmitter for chat events.\n */\nexport type ChatEventMap = {\n [K in ChatEventType]: Extract<ChatEvent, { type: K }>;\n};\n\n// ─── Middleware ────────────────────────────────────────────────\n\n/**\n * Context passed to middleware functions.\n * Contains the event and control methods for the middleware pipeline.\n */\nexport interface MiddlewareContext {\n /** The current event (may be transformed by prior middleware) */\n event: ChatEvent;\n /** Call the next middleware in the chain, or deliver to listeners if last */\n next: () => void;\n /** Suppress the event — do not deliver to listeners or subsequent middleware */\n suppress: () => void;\n}\n\n/**\n * Middleware function for intercepting, transforming, or suppressing events.\n * EventMiddleware operates at the ChatEventBus level.\n *\n * @param ctx - Middleware context with event, next(), and suppress()\n *\n * @example\n * ```typescript\n * // Logging middleware\n * const logger: EventMiddleware = (ctx) => {\n * console.log(`Event: ${ctx.event.type}`);\n * ctx.next();\n * };\n *\n * // Suppressing middleware\n * const filter: EventMiddleware = (ctx) => {\n * if (ctx.event.type === \"heartbeat\") {\n * ctx.suppress();\n * } else {\n * ctx.next();\n * }\n * };\n * ```\n */\nexport type EventMiddleware = (ctx: MiddlewareContext) => void;\n\n// ─── ChatEventBus ─────────────────────────────────────────────\n\n/**\n * Chat event bus: a typed event emitter specialized for ChatEvent types\n * with middleware pipeline support.\n *\n * Events pass through the middleware pipeline before reaching listeners.\n * Middleware can inspect, transform, or suppress events.\n *\n * @example\n * ```typescript\n * const bus = new ChatEventBus();\n *\n * // Add middleware\n * bus.use((ctx) => {\n * console.log(`[${ctx.event.type}]`);\n * ctx.next();\n * });\n *\n * // Listen for events\n * bus.on(\"message:delta\", (event) => {\n * console.log(event.text);\n * });\n *\n * // Emit events\n * bus.emit(\"message:delta\", { type: \"message:delta\", messageId: id, text: \"hi\" });\n * ```\n */\nexport class ChatEventBus extends TypedEventEmitter<ChatEventMap> {\n private readonly middlewares: EventMiddleware[] = [];\n\n /**\n * Register a middleware function. Middleware runs in registration order.\n * @param middleware - Middleware function\n * @returns Unsubscribe function to remove the middleware\n */\n use(middleware: EventMiddleware): Unsubscribe {\n this.middlewares.push(middleware);\n return () => {\n const idx = this.middlewares.indexOf(middleware);\n if (idx !== -1) {\n this.middlewares.splice(idx, 1);\n }\n };\n }\n\n /**\n * Emit a chat event through the middleware pipeline, then to listeners.\n *\n * @param event - ChatEvent type string\n * @param payload - The full ChatEvent object\n */\n override emit<K extends ChatEventType>(\n event: K,\n payload: ChatEventMap[K],\n ): void {\n if (this.middlewares.length === 0) {\n super.emit(event, payload);\n return;\n }\n\n let suppressed = false;\n let currentEvent: ChatEvent = payload;\n let index = 0;\n\n const runNext = (): void => {\n if (suppressed) return;\n\n if (index >= this.middlewares.length) {\n super.emit(\n currentEvent.type as K,\n currentEvent as ChatEventMap[K],\n );\n return;\n }\n\n const mw = this.middlewares[index++];\n const ctx: MiddlewareContext = {\n event: currentEvent,\n next: () => {\n currentEvent = ctx.event;\n runNext();\n },\n suppress: () => {\n suppressed = true;\n },\n };\n mw(ctx);\n };\n\n runNext();\n }\n\n /**\n * Replace the event in the middleware context.\n * Middleware should mutate ctx.event or create a new MiddlewareContext\n * to transform events passing through the pipeline.\n */\n\n /**\n * Remove all middleware functions.\n */\n clearMiddleware(): void {\n this.middlewares.length = 0;\n }\n\n /**\n * Get the number of registered middleware functions.\n * @returns Number of middleware\n */\n middlewareCount(): number {\n return this.middlewares.length;\n }\n}\n\n// ─── Utility: Event Filtering ─────────────────────────────────\n\n/**\n * Create a filter function that passes only events of specified types.\n *\n * @param types - Event types to allow through\n * @returns Predicate function for filtering ChatEvents\n *\n * @example\n * ```typescript\n * const isTextEvent = eventFilter(\"message:start\", \"message:delta\", \"message:complete\");\n * const textEvents = allEvents.filter(isTextEvent);\n * ```\n */\nexport function eventFilter(\n ...types: ChatEventType[]\n): (event: ChatEvent) => boolean {\n const allowed = new Set<string>(types);\n return (event: ChatEvent) => allowed.has(event.type);\n}\n\n/**\n * Filter an async iterable of ChatEvents to only specified types.\n *\n * @param source - Async iterable of ChatEvents\n * @param types - Event types to keep\n * @returns Async iterable of filtered ChatEvents\n *\n * @example\n * ```typescript\n * for await (const event of filterEvents(stream, \"message:delta\", \"message:complete\")) {\n * // only message:delta and message:complete events\n * }\n * ```\n */\nexport async function* filterEvents(\n source: AsyncIterable<ChatEvent>,\n ...types: ChatEventType[]\n): AsyncIterable<ChatEvent> {\n const pred = eventFilter(...types);\n for await (const event of source) {\n if (pred(event)) {\n yield event;\n }\n }\n}\n\n// ─── Utility: Event Mapping ───────────────────────────────────\n\n/**\n * Map/transform events from an async iterable.\n *\n * @param source - Async iterable of ChatEvents\n * @param transform - Function to transform each event (return null to skip)\n * @returns Async iterable of transformed values\n *\n * @example\n * ```typescript\n * // Extract text from message:delta events\n * const texts = mapEvents(stream, (event) =>\n * event.type === \"message:delta\" ? event.text : null\n * );\n * ```\n */\nexport async function* mapEvents<R>(\n source: AsyncIterable<ChatEvent>,\n transform: (event: ChatEvent) => R | null,\n): AsyncIterable<R> {\n for await (const event of source) {\n const result = transform(event);\n if (result !== null) {\n yield result;\n }\n }\n}\n\n/**\n * Collect text from message:delta events into a single string.\n *\n * @param source - Async iterable of ChatEvents\n * @returns Complete text assembled from message:delta payloads\n *\n * @example\n * ```typescript\n * const fullText = await collectText(stream);\n * ```\n */\nexport async function collectText(\n source: AsyncIterable<ChatEvent>,\n): Promise<string> {\n const parts: string[] = [];\n for await (const event of source) {\n if (event.type === \"message:delta\") {\n parts.push(event.text);\n }\n }\n return parts.join(\"\");\n}\n"]}
|
package/dist/chat/events.d.cts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { ChatEventType, ChatEvent } from '
|
|
2
|
-
import '../
|
|
1
|
+
import { C as ChatEventType, a as ChatEvent } from '../types-DRgd_9R7.cjs';
|
|
2
|
+
import '../agent-DxY68NZL.cjs';
|
|
3
3
|
import 'zod';
|
|
4
|
+
import '../errors-C-so0M4t.cjs';
|
|
5
|
+
import '../types-4vbcmPTp.cjs';
|
|
6
|
+
import '../errors-CmVvczxZ.cjs';
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* @witqq/agent-sdk/chat/events
|
|
@@ -103,6 +106,7 @@ interface MiddlewareContext {
|
|
|
103
106
|
}
|
|
104
107
|
/**
|
|
105
108
|
* Middleware function for intercepting, transforming, or suppressing events.
|
|
109
|
+
* EventMiddleware operates at the ChatEventBus level.
|
|
106
110
|
*
|
|
107
111
|
* @param ctx - Middleware context with event, next(), and suppress()
|
|
108
112
|
*
|
package/dist/chat/events.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { ChatEventType, ChatEvent } from '
|
|
2
|
-
import '../
|
|
1
|
+
import { C as ChatEventType, a as ChatEvent } from '../types-ajANVzf7.js';
|
|
2
|
+
import '../agent-CW9XbmG_.js';
|
|
3
3
|
import 'zod';
|
|
4
|
+
import '../errors-C-so0M4t.js';
|
|
5
|
+
import '../types-BxggH0Yh.js';
|
|
6
|
+
import '../errors-CmVvczxZ.js';
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* @witqq/agent-sdk/chat/events
|
|
@@ -103,6 +106,7 @@ interface MiddlewareContext {
|
|
|
103
106
|
}
|
|
104
107
|
/**
|
|
105
108
|
* Middleware function for intercepting, transforming, or suppressing events.
|
|
109
|
+
* EventMiddleware operates at the ChatEventBus level.
|
|
106
110
|
*
|
|
107
111
|
* @param ctx - Middleware context with event, next(), and suppress()
|
|
108
112
|
*
|
package/dist/chat/events.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/chat/events.ts"],"names":[],"mappings":"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","file":"events.js","sourcesContent":["/**\n * @witqq/agent-sdk/chat/events\n *\n * Type-safe event emitter, chat event bus, and middleware pipeline.\n * Generic TypedEventEmitter<EventMap> for arbitrary typed event maps.\n * ChatEventBus specializing TypedEventEmitter for ChatEvent types.\n * Middleware support for event interception, transformation, and suppression.\n * Utility functions for filtering and mapping event streams.\n */\n\nimport type { ChatEvent, ChatEventType } from \"./core.js\";\n\n// ─── EventMap constraint ──────────────────────────────────────\n\n/** Constraint for event maps: keys are strings, values are payloads */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type EventMap = Record<string, any>;\n\n// ─── Listener types ───────────────────────────────────────────\n\n/** Listener callback for a specific event */\nexport type Listener<T> = (payload: T) => void;\n\n/** Unsubscribe function returned by on/once */\nexport type Unsubscribe = () => void;\n\n// ─── TypedEventEmitter ────────────────────────────────────────\n\n/**\n * Generic type-safe event emitter parameterized by an EventMap.\n *\n * @typeParam T - Map of event names to payload types\n *\n * @example\n * ```typescript\n * type MyEvents = {\n * message: string;\n * count: number;\n * done: void;\n * };\n * const emitter = new TypedEventEmitter<MyEvents>();\n * emitter.on(\"message\", (text) => console.log(text));\n * emitter.emit(\"message\", \"hello\");\n * ```\n */\nexport class TypedEventEmitter<T extends EventMap> {\n private readonly listeners = new Map<keyof T, Set<Listener<unknown>>>();\n\n /**\n * Subscribe to an event.\n * @param event - Event name\n * @param listener - Callback receiving the event payload\n * @returns Unsubscribe function\n */\n on<K extends keyof T>(event: K, listener: Listener<T[K]>): Unsubscribe {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n const fn = listener as Listener<unknown>;\n set.add(fn);\n return () => {\n set!.delete(fn);\n if (set!.size === 0) {\n this.listeners.delete(event);\n }\n };\n }\n\n /**\n * Subscribe to an event, firing the listener at most once.\n * @param event - Event name\n * @param listener - Callback receiving the event payload\n * @returns Unsubscribe function\n */\n once<K extends keyof T>(event: K, listener: Listener<T[K]>): Unsubscribe {\n const unsub = this.on(event, (payload) => {\n unsub();\n listener(payload);\n });\n return unsub;\n }\n\n /**\n * Remove a specific listener from an event.\n * @param event - Event name\n * @param listener - The listener to remove\n */\n off<K extends keyof T>(event: K, listener: Listener<T[K]>): void {\n const set = this.listeners.get(event);\n if (!set) return;\n set.delete(listener as Listener<unknown>);\n if (set.size === 0) {\n this.listeners.delete(event);\n }\n }\n\n /**\n * Emit an event, calling all registered listeners synchronously.\n * @param event - Event name\n * @param payload - Event payload\n */\n emit<K extends keyof T>(event: K, payload: T[K]): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const fn of [...set]) {\n fn(payload);\n }\n }\n\n /**\n * Remove all listeners for a specific event, or all events if no event specified.\n * @param event - Optional event name\n */\n removeAllListeners<K extends keyof T>(event?: K): void {\n if (event !== undefined) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n\n /**\n * Get the number of listeners for a specific event.\n * @param event - Event name\n * @returns Number of listeners\n */\n listenerCount<K extends keyof T>(event: K): number {\n const set = this.listeners.get(event);\n return set ? set.size : 0;\n }\n\n /**\n * Get all event names that have at least one listener.\n * @returns Array of event names\n */\n eventNames(): Array<keyof T> {\n return [...this.listeners.keys()];\n }\n}\n\n// ─── ChatEventMap ─────────────────────────────────────────────\n\n/**\n * Map of ChatEvent type strings to their corresponding ChatEvent payloads.\n * Used to parameterize TypedEventEmitter for chat events.\n */\nexport type ChatEventMap = {\n [K in ChatEventType]: Extract<ChatEvent, { type: K }>;\n};\n\n// ─── Middleware ────────────────────────────────────────────────\n\n/**\n * Context passed to middleware functions.\n * Contains the event and control methods for the middleware pipeline.\n */\nexport interface MiddlewareContext {\n /** The current event (may be transformed by prior middleware) */\n event: ChatEvent;\n /** Call the next middleware in the chain, or deliver to listeners if last */\n next: () => void;\n /** Suppress the event — do not deliver to listeners or subsequent middleware */\n suppress: () => void;\n}\n\n/**\n * Middleware function for intercepting, transforming, or suppressing events.\n *\n * @param ctx - Middleware context with event, next(), and suppress()\n *\n * @example\n * ```typescript\n * // Logging middleware\n * const logger: EventMiddleware = (ctx) => {\n * console.log(`Event: ${ctx.event.type}`);\n * ctx.next();\n * };\n *\n * // Suppressing middleware\n * const filter: EventMiddleware = (ctx) => {\n * if (ctx.event.type === \"heartbeat\") {\n * ctx.suppress();\n * } else {\n * ctx.next();\n * }\n * };\n * ```\n */\nexport type EventMiddleware = (ctx: MiddlewareContext) => void;\n\n// ─── ChatEventBus ─────────────────────────────────────────────\n\n/**\n * Chat event bus: a typed event emitter specialized for ChatEvent types\n * with middleware pipeline support.\n *\n * Events pass through the middleware pipeline before reaching listeners.\n * Middleware can inspect, transform, or suppress events.\n *\n * @example\n * ```typescript\n * const bus = new ChatEventBus();\n *\n * // Add middleware\n * bus.use((ctx) => {\n * console.log(`[${ctx.event.type}]`);\n * ctx.next();\n * });\n *\n * // Listen for events\n * bus.on(\"message:delta\", (event) => {\n * console.log(event.text);\n * });\n *\n * // Emit events\n * bus.emit(\"message:delta\", { type: \"message:delta\", messageId: id, text: \"hi\" });\n * ```\n */\nexport class ChatEventBus extends TypedEventEmitter<ChatEventMap> {\n private readonly middlewares: EventMiddleware[] = [];\n\n /**\n * Register a middleware function. Middleware runs in registration order.\n * @param middleware - Middleware function\n * @returns Unsubscribe function to remove the middleware\n */\n use(middleware: EventMiddleware): Unsubscribe {\n this.middlewares.push(middleware);\n return () => {\n const idx = this.middlewares.indexOf(middleware);\n if (idx !== -1) {\n this.middlewares.splice(idx, 1);\n }\n };\n }\n\n /**\n * Emit a chat event through the middleware pipeline, then to listeners.\n *\n * @param event - ChatEvent type string\n * @param payload - The full ChatEvent object\n */\n override emit<K extends ChatEventType>(\n event: K,\n payload: ChatEventMap[K],\n ): void {\n if (this.middlewares.length === 0) {\n super.emit(event, payload);\n return;\n }\n\n let suppressed = false;\n let currentEvent: ChatEvent = payload;\n let index = 0;\n\n const runNext = (): void => {\n if (suppressed) return;\n\n if (index >= this.middlewares.length) {\n super.emit(\n currentEvent.type as K,\n currentEvent as ChatEventMap[K],\n );\n return;\n }\n\n const mw = this.middlewares[index++];\n const ctx: MiddlewareContext = {\n event: currentEvent,\n next: () => {\n currentEvent = ctx.event;\n runNext();\n },\n suppress: () => {\n suppressed = true;\n },\n };\n mw(ctx);\n };\n\n runNext();\n }\n\n /**\n * Replace the event in the middleware context.\n * Middleware should mutate ctx.event or create a new MiddlewareContext\n * to transform events passing through the pipeline.\n */\n\n /**\n * Remove all middleware functions.\n */\n clearMiddleware(): void {\n this.middlewares.length = 0;\n }\n\n /**\n * Get the number of registered middleware functions.\n * @returns Number of middleware\n */\n middlewareCount(): number {\n return this.middlewares.length;\n }\n}\n\n// ─── Utility: Event Filtering ─────────────────────────────────\n\n/**\n * Create a filter function that passes only events of specified types.\n *\n * @param types - Event types to allow through\n * @returns Predicate function for filtering ChatEvents\n *\n * @example\n * ```typescript\n * const isTextEvent = eventFilter(\"message:start\", \"message:delta\", \"message:complete\");\n * const textEvents = allEvents.filter(isTextEvent);\n * ```\n */\nexport function eventFilter(\n ...types: ChatEventType[]\n): (event: ChatEvent) => boolean {\n const allowed = new Set<string>(types);\n return (event: ChatEvent) => allowed.has(event.type);\n}\n\n/**\n * Filter an async iterable of ChatEvents to only specified types.\n *\n * @param source - Async iterable of ChatEvents\n * @param types - Event types to keep\n * @returns Async iterable of filtered ChatEvents\n *\n * @example\n * ```typescript\n * for await (const event of filterEvents(stream, \"message:delta\", \"message:complete\")) {\n * // only message:delta and message:complete events\n * }\n * ```\n */\nexport async function* filterEvents(\n source: AsyncIterable<ChatEvent>,\n ...types: ChatEventType[]\n): AsyncIterable<ChatEvent> {\n const pred = eventFilter(...types);\n for await (const event of source) {\n if (pred(event)) {\n yield event;\n }\n }\n}\n\n// ─── Utility: Event Mapping ───────────────────────────────────\n\n/**\n * Map/transform events from an async iterable.\n *\n * @param source - Async iterable of ChatEvents\n * @param transform - Function to transform each event (return null to skip)\n * @returns Async iterable of transformed values\n *\n * @example\n * ```typescript\n * // Extract text from message:delta events\n * const texts = mapEvents(stream, (event) =>\n * event.type === \"message:delta\" ? event.text : null\n * );\n * ```\n */\nexport async function* mapEvents<R>(\n source: AsyncIterable<ChatEvent>,\n transform: (event: ChatEvent) => R | null,\n): AsyncIterable<R> {\n for await (const event of source) {\n const result = transform(event);\n if (result !== null) {\n yield result;\n }\n }\n}\n\n/**\n * Collect text from message:delta events into a single string.\n *\n * @param source - Async iterable of ChatEvents\n * @returns Complete text assembled from message:delta payloads\n *\n * @example\n * ```typescript\n * const fullText = await collectText(stream);\n * ```\n */\nexport async function collectText(\n source: AsyncIterable<ChatEvent>,\n): Promise<string> {\n const parts: string[] = [];\n for await (const event of source) {\n if (event.type === \"message:delta\") {\n parts.push(event.text);\n }\n }\n return parts.join(\"\");\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/chat/events.ts"],"names":[],"mappings":"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","file":"events.js","sourcesContent":["/**\n * @witqq/agent-sdk/chat/events\n *\n * Type-safe event emitter, chat event bus, and middleware pipeline.\n * Generic TypedEventEmitter<EventMap> for arbitrary typed event maps.\n * ChatEventBus specializing TypedEventEmitter for ChatEvent types.\n * Middleware support for event interception, transformation, and suppression.\n * Utility functions for filtering and mapping event streams.\n */\n\nimport type { ChatEvent, ChatEventType } from \"./core.js\";\n\n// ─── EventMap constraint ──────────────────────────────────────\n\n/** Constraint for event maps: keys are strings, values are payloads */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type EventMap = Record<string, any>;\n\n// ─── Listener types ───────────────────────────────────────────\n\n/** Listener callback for a specific event */\nexport type Listener<T> = (payload: T) => void;\n\n/** Unsubscribe function returned by on/once */\nexport type Unsubscribe = () => void;\n\n// ─── TypedEventEmitter ────────────────────────────────────────\n\n/**\n * Generic type-safe event emitter parameterized by an EventMap.\n *\n * @typeParam T - Map of event names to payload types\n *\n * @example\n * ```typescript\n * type MyEvents = {\n * message: string;\n * count: number;\n * done: void;\n * };\n * const emitter = new TypedEventEmitter<MyEvents>();\n * emitter.on(\"message\", (text) => console.log(text));\n * emitter.emit(\"message\", \"hello\");\n * ```\n */\nexport class TypedEventEmitter<T extends EventMap> {\n private readonly listeners = new Map<keyof T, Set<Listener<unknown>>>();\n\n /**\n * Subscribe to an event.\n * @param event - Event name\n * @param listener - Callback receiving the event payload\n * @returns Unsubscribe function\n */\n on<K extends keyof T>(event: K, listener: Listener<T[K]>): Unsubscribe {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n const fn = listener as Listener<unknown>;\n set.add(fn);\n return () => {\n set!.delete(fn);\n if (set!.size === 0) {\n this.listeners.delete(event);\n }\n };\n }\n\n /**\n * Subscribe to an event, firing the listener at most once.\n * @param event - Event name\n * @param listener - Callback receiving the event payload\n * @returns Unsubscribe function\n */\n once<K extends keyof T>(event: K, listener: Listener<T[K]>): Unsubscribe {\n const unsub = this.on(event, (payload) => {\n unsub();\n listener(payload);\n });\n return unsub;\n }\n\n /**\n * Remove a specific listener from an event.\n * @param event - Event name\n * @param listener - The listener to remove\n */\n off<K extends keyof T>(event: K, listener: Listener<T[K]>): void {\n const set = this.listeners.get(event);\n if (!set) return;\n set.delete(listener as Listener<unknown>);\n if (set.size === 0) {\n this.listeners.delete(event);\n }\n }\n\n /**\n * Emit an event, calling all registered listeners synchronously.\n * @param event - Event name\n * @param payload - Event payload\n */\n emit<K extends keyof T>(event: K, payload: T[K]): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const fn of [...set]) {\n fn(payload);\n }\n }\n\n /**\n * Remove all listeners for a specific event, or all events if no event specified.\n * @param event - Optional event name\n */\n removeAllListeners<K extends keyof T>(event?: K): void {\n if (event !== undefined) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n\n /**\n * Get the number of listeners for a specific event.\n * @param event - Event name\n * @returns Number of listeners\n */\n listenerCount<K extends keyof T>(event: K): number {\n const set = this.listeners.get(event);\n return set ? set.size : 0;\n }\n\n /**\n * Get all event names that have at least one listener.\n * @returns Array of event names\n */\n eventNames(): Array<keyof T> {\n return [...this.listeners.keys()];\n }\n}\n\n// ─── ChatEventMap ─────────────────────────────────────────────\n\n/**\n * Map of ChatEvent type strings to their corresponding ChatEvent payloads.\n * Used to parameterize TypedEventEmitter for chat events.\n */\nexport type ChatEventMap = {\n [K in ChatEventType]: Extract<ChatEvent, { type: K }>;\n};\n\n// ─── Middleware ────────────────────────────────────────────────\n\n/**\n * Context passed to middleware functions.\n * Contains the event and control methods for the middleware pipeline.\n */\nexport interface MiddlewareContext {\n /** The current event (may be transformed by prior middleware) */\n event: ChatEvent;\n /** Call the next middleware in the chain, or deliver to listeners if last */\n next: () => void;\n /** Suppress the event — do not deliver to listeners or subsequent middleware */\n suppress: () => void;\n}\n\n/**\n * Middleware function for intercepting, transforming, or suppressing events.\n * EventMiddleware operates at the ChatEventBus level.\n *\n * @param ctx - Middleware context with event, next(), and suppress()\n *\n * @example\n * ```typescript\n * // Logging middleware\n * const logger: EventMiddleware = (ctx) => {\n * console.log(`Event: ${ctx.event.type}`);\n * ctx.next();\n * };\n *\n * // Suppressing middleware\n * const filter: EventMiddleware = (ctx) => {\n * if (ctx.event.type === \"heartbeat\") {\n * ctx.suppress();\n * } else {\n * ctx.next();\n * }\n * };\n * ```\n */\nexport type EventMiddleware = (ctx: MiddlewareContext) => void;\n\n// ─── ChatEventBus ─────────────────────────────────────────────\n\n/**\n * Chat event bus: a typed event emitter specialized for ChatEvent types\n * with middleware pipeline support.\n *\n * Events pass through the middleware pipeline before reaching listeners.\n * Middleware can inspect, transform, or suppress events.\n *\n * @example\n * ```typescript\n * const bus = new ChatEventBus();\n *\n * // Add middleware\n * bus.use((ctx) => {\n * console.log(`[${ctx.event.type}]`);\n * ctx.next();\n * });\n *\n * // Listen for events\n * bus.on(\"message:delta\", (event) => {\n * console.log(event.text);\n * });\n *\n * // Emit events\n * bus.emit(\"message:delta\", { type: \"message:delta\", messageId: id, text: \"hi\" });\n * ```\n */\nexport class ChatEventBus extends TypedEventEmitter<ChatEventMap> {\n private readonly middlewares: EventMiddleware[] = [];\n\n /**\n * Register a middleware function. Middleware runs in registration order.\n * @param middleware - Middleware function\n * @returns Unsubscribe function to remove the middleware\n */\n use(middleware: EventMiddleware): Unsubscribe {\n this.middlewares.push(middleware);\n return () => {\n const idx = this.middlewares.indexOf(middleware);\n if (idx !== -1) {\n this.middlewares.splice(idx, 1);\n }\n };\n }\n\n /**\n * Emit a chat event through the middleware pipeline, then to listeners.\n *\n * @param event - ChatEvent type string\n * @param payload - The full ChatEvent object\n */\n override emit<K extends ChatEventType>(\n event: K,\n payload: ChatEventMap[K],\n ): void {\n if (this.middlewares.length === 0) {\n super.emit(event, payload);\n return;\n }\n\n let suppressed = false;\n let currentEvent: ChatEvent = payload;\n let index = 0;\n\n const runNext = (): void => {\n if (suppressed) return;\n\n if (index >= this.middlewares.length) {\n super.emit(\n currentEvent.type as K,\n currentEvent as ChatEventMap[K],\n );\n return;\n }\n\n const mw = this.middlewares[index++];\n const ctx: MiddlewareContext = {\n event: currentEvent,\n next: () => {\n currentEvent = ctx.event;\n runNext();\n },\n suppress: () => {\n suppressed = true;\n },\n };\n mw(ctx);\n };\n\n runNext();\n }\n\n /**\n * Replace the event in the middleware context.\n * Middleware should mutate ctx.event or create a new MiddlewareContext\n * to transform events passing through the pipeline.\n */\n\n /**\n * Remove all middleware functions.\n */\n clearMiddleware(): void {\n this.middlewares.length = 0;\n }\n\n /**\n * Get the number of registered middleware functions.\n * @returns Number of middleware\n */\n middlewareCount(): number {\n return this.middlewares.length;\n }\n}\n\n// ─── Utility: Event Filtering ─────────────────────────────────\n\n/**\n * Create a filter function that passes only events of specified types.\n *\n * @param types - Event types to allow through\n * @returns Predicate function for filtering ChatEvents\n *\n * @example\n * ```typescript\n * const isTextEvent = eventFilter(\"message:start\", \"message:delta\", \"message:complete\");\n * const textEvents = allEvents.filter(isTextEvent);\n * ```\n */\nexport function eventFilter(\n ...types: ChatEventType[]\n): (event: ChatEvent) => boolean {\n const allowed = new Set<string>(types);\n return (event: ChatEvent) => allowed.has(event.type);\n}\n\n/**\n * Filter an async iterable of ChatEvents to only specified types.\n *\n * @param source - Async iterable of ChatEvents\n * @param types - Event types to keep\n * @returns Async iterable of filtered ChatEvents\n *\n * @example\n * ```typescript\n * for await (const event of filterEvents(stream, \"message:delta\", \"message:complete\")) {\n * // only message:delta and message:complete events\n * }\n * ```\n */\nexport async function* filterEvents(\n source: AsyncIterable<ChatEvent>,\n ...types: ChatEventType[]\n): AsyncIterable<ChatEvent> {\n const pred = eventFilter(...types);\n for await (const event of source) {\n if (pred(event)) {\n yield event;\n }\n }\n}\n\n// ─── Utility: Event Mapping ───────────────────────────────────\n\n/**\n * Map/transform events from an async iterable.\n *\n * @param source - Async iterable of ChatEvents\n * @param transform - Function to transform each event (return null to skip)\n * @returns Async iterable of transformed values\n *\n * @example\n * ```typescript\n * // Extract text from message:delta events\n * const texts = mapEvents(stream, (event) =>\n * event.type === \"message:delta\" ? event.text : null\n * );\n * ```\n */\nexport async function* mapEvents<R>(\n source: AsyncIterable<ChatEvent>,\n transform: (event: ChatEvent) => R | null,\n): AsyncIterable<R> {\n for await (const event of source) {\n const result = transform(event);\n if (result !== null) {\n yield result;\n }\n }\n}\n\n/**\n * Collect text from message:delta events into a single string.\n *\n * @param source - Async iterable of ChatEvents\n * @returns Complete text assembled from message:delta payloads\n *\n * @example\n * ```typescript\n * const fullText = await collectText(stream);\n * ```\n */\nexport async function collectText(\n source: AsyncIterable<ChatEvent>,\n): Promise<string> {\n const parts: string[] = [];\n for await (const event of source) {\n if (event.type === \"message:delta\") {\n parts.push(event.text);\n }\n }\n return parts.join(\"\");\n}\n"]}
|