nexus-agents 2.70.1 → 2.72.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/dist/{adaptive-memory-MKSYEBST.js → adaptive-memory-UPE76IP6.js} +5 -5
- package/dist/{chunk-DWLATKBK.js → child-mcp-config-5HRJGLCR.js} +6 -4
- package/dist/child-mcp-config-5HRJGLCR.js.map +1 -0
- package/dist/{chunk-TTZODPLI.js → chunk-2JMUX5UA.js} +25 -12
- package/dist/{chunk-TTZODPLI.js.map → chunk-2JMUX5UA.js.map} +1 -1
- package/dist/{chunk-ZPPX2K57.js → chunk-2KB63QGE.js} +2 -2
- package/dist/{chunk-L2LQ3TSV.js → chunk-2MD5MWCK.js} +2 -2
- package/dist/{chunk-ANC3HU6F.js → chunk-345KMHWH.js} +6 -6
- package/dist/chunk-345KMHWH.js.map +1 -0
- package/dist/{chunk-7ZPYV4HO.js → chunk-3FIDMWFC.js} +2 -2
- package/dist/chunk-3FIDMWFC.js.map +1 -0
- package/dist/{chunk-H5RKTUDD.js → chunk-3HR6UJ2E.js} +3243 -7299
- package/dist/chunk-3HR6UJ2E.js.map +1 -0
- package/dist/{chunk-UMLBVSW4.js → chunk-53K3KEKT.js} +51 -707
- package/dist/chunk-53K3KEKT.js.map +1 -0
- package/dist/chunk-5MHIWRKB.js +691 -0
- package/dist/chunk-5MHIWRKB.js.map +1 -0
- package/dist/{chunk-VGZJIR22.js → chunk-5WQ3SRSE.js} +2 -2
- package/dist/{chunk-TOYPY5XA.js → chunk-A35XORXU.js} +73 -10
- package/dist/chunk-A35XORXU.js.map +1 -0
- package/dist/chunk-BVETPIOQ.js +556 -0
- package/dist/chunk-BVETPIOQ.js.map +1 -0
- package/dist/{chunk-OF7CYMMA.js → chunk-DA5UDQYW.js} +2 -2
- package/dist/{chunk-XATH462F.js → chunk-ES6GFP35.js} +186 -34
- package/dist/chunk-ES6GFP35.js.map +1 -0
- package/dist/chunk-GOT7OAL5.js +59 -0
- package/dist/chunk-GOT7OAL5.js.map +1 -0
- package/dist/{chunk-LJT65EA7.js → chunk-I7ORMAO7.js} +2 -2
- package/dist/{chunk-LMRKHQG5.js → chunk-L6N2S3UB.js} +2 -2
- package/dist/{chunk-7OBFO4GF.js → chunk-O4KUCF5S.js} +125 -40
- package/dist/chunk-O4KUCF5S.js.map +1 -0
- package/dist/chunk-P5OFZWDW.js +303 -0
- package/dist/chunk-P5OFZWDW.js.map +1 -0
- package/dist/{chunk-MJHOSM5U.js → chunk-QECRZ3YA.js} +2 -2
- package/dist/{chunk-WYSHXPKK.js → chunk-QL4HCYRD.js} +4 -44
- package/dist/chunk-QL4HCYRD.js.map +1 -0
- package/dist/{chunk-E66KFRSJ.js → chunk-TF3GROMO.js} +2 -2
- package/dist/{chunk-U3HZQTUF.js → chunk-TQFRPFMG.js} +2 -2
- package/dist/{chunk-7QWNOE23.js → chunk-V7ATY4BG.js} +3 -3
- package/dist/{chunk-32RIOULO.js → chunk-VPC3YNFR.js} +2 -2
- package/dist/{chunk-L4XSIHF5.js → chunk-VTVKC4FS.js} +4 -4
- package/dist/{chunk-6ZLFULSQ.js → chunk-XHVDKY3X.js} +315 -31
- package/dist/chunk-XHVDKY3X.js.map +1 -0
- package/dist/cli-circuit-breaker-GFF2RLBZ.js +14 -0
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +1167 -2245
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-AYVJPIOS.js → composite-router-33F3F74I.js} +4 -4
- package/dist/{consensus-vote-WUGHRBYE.js → consensus-vote-5V4KVHBE.js} +12 -11
- package/dist/doctor-deep-AHDTNURD.js +13 -0
- package/dist/expert-bridge-DMDHHDEU.js +11 -0
- package/dist/factory-FVD7PZ6S.js +15 -0
- package/dist/{factory-KMBWFIX2.js → factory-VQS3HJ7V.js} +6 -6
- package/dist/index.d.ts +359 -3358
- package/dist/index.js +70 -807
- package/dist/index.js.map +1 -1
- package/dist/init-opencode-EIOIPVWL.js +158 -0
- package/dist/init-opencode-EIOIPVWL.js.map +1 -0
- package/dist/issue-triage-HJUJWGAD.js +16 -0
- package/dist/{learning-persistence-FILWP3IR.js → learning-persistence-N6ILD2HX.js} +3 -3
- package/dist/{mobimem-77W5ED4Z.js → mobimem-BOJFXQ7B.js} +4 -4
- package/dist/{nexus-data-dir-M6DYKIHJ.js → nexus-data-dir-77UO7N6J.js} +2 -2
- package/dist/{registry-command-BBLIXULQ.js → registry-command-NCWUJKAF.js} +4 -4
- package/dist/{repo-security-plan-7SNM7JQN.js → repo-security-plan-3J45VAD6.js} +5 -5
- package/dist/research-helpers-synthesize-UGQHZZJN.js +12 -0
- package/dist/{routing-memory-DCIZEEVC.js → routing-memory-NO7QEH7T.js} +4 -4
- package/dist/{session-memory-5TSAASQW.js → session-memory-DOXLEWEU.js} +5 -5
- package/dist/{setup-command-PU636ZJH.js → setup-command-DVEBFKR2.js} +10 -10
- package/dist/setup-config-E3JZYSLR.js +11 -0
- package/dist/{setup-custom-api-IQX3GD2D.js → setup-custom-api-DHJ5DRH2.js} +6 -6
- package/dist/{weather-report-NETGWTJX.js → weather-report-FNN4OX3N.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-6ZLFULSQ.js.map +0 -1
- package/dist/chunk-7OBFO4GF.js.map +0 -1
- package/dist/chunk-7ZPYV4HO.js.map +0 -1
- package/dist/chunk-ANC3HU6F.js.map +0 -1
- package/dist/chunk-DWLATKBK.js.map +0 -1
- package/dist/chunk-FDNWRZNJ.js +0 -22
- package/dist/chunk-FDNWRZNJ.js.map +0 -1
- package/dist/chunk-H5RKTUDD.js.map +0 -1
- package/dist/chunk-TOYPY5XA.js.map +0 -1
- package/dist/chunk-UMLBVSW4.js.map +0 -1
- package/dist/chunk-WYSHXPKK.js.map +0 -1
- package/dist/chunk-XATH462F.js.map +0 -1
- package/dist/cli-circuit-breaker-2CJ6NV52.js +0 -14
- package/dist/doctor-deep-BJFDBGPO.js +0 -13
- package/dist/expert-bridge-75WNNWI4.js +0 -11
- package/dist/factory-BHHC6C7W.js +0 -15
- package/dist/issue-triage-TXQ7J6GG.js +0 -16
- package/dist/mcp-config-OCWIXE2Y.js +0 -13
- package/dist/research-helpers-synthesize-7CI2FJE5.js +0 -12
- package/dist/setup-config-EA5RDIO2.js +0 -11
- package/dist/weather-report-NETGWTJX.js.map +0 -1
- /package/dist/{adaptive-memory-MKSYEBST.js.map → adaptive-memory-UPE76IP6.js.map} +0 -0
- /package/dist/{chunk-ZPPX2K57.js.map → chunk-2KB63QGE.js.map} +0 -0
- /package/dist/{chunk-L2LQ3TSV.js.map → chunk-2MD5MWCK.js.map} +0 -0
- /package/dist/{chunk-VGZJIR22.js.map → chunk-5WQ3SRSE.js.map} +0 -0
- /package/dist/{chunk-OF7CYMMA.js.map → chunk-DA5UDQYW.js.map} +0 -0
- /package/dist/{chunk-LJT65EA7.js.map → chunk-I7ORMAO7.js.map} +0 -0
- /package/dist/{chunk-LMRKHQG5.js.map → chunk-L6N2S3UB.js.map} +0 -0
- /package/dist/{chunk-MJHOSM5U.js.map → chunk-QECRZ3YA.js.map} +0 -0
- /package/dist/{chunk-E66KFRSJ.js.map → chunk-TF3GROMO.js.map} +0 -0
- /package/dist/{chunk-U3HZQTUF.js.map → chunk-TQFRPFMG.js.map} +0 -0
- /package/dist/{chunk-7QWNOE23.js.map → chunk-V7ATY4BG.js.map} +0 -0
- /package/dist/{chunk-32RIOULO.js.map → chunk-VPC3YNFR.js.map} +0 -0
- /package/dist/{chunk-L4XSIHF5.js.map → chunk-VTVKC4FS.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-2CJ6NV52.js.map → cli-circuit-breaker-GFF2RLBZ.js.map} +0 -0
- /package/dist/{composite-router-AYVJPIOS.js.map → composite-router-33F3F74I.js.map} +0 -0
- /package/dist/{consensus-vote-WUGHRBYE.js.map → consensus-vote-5V4KVHBE.js.map} +0 -0
- /package/dist/{doctor-deep-BJFDBGPO.js.map → doctor-deep-AHDTNURD.js.map} +0 -0
- /package/dist/{expert-bridge-75WNNWI4.js.map → expert-bridge-DMDHHDEU.js.map} +0 -0
- /package/dist/{factory-BHHC6C7W.js.map → factory-FVD7PZ6S.js.map} +0 -0
- /package/dist/{factory-KMBWFIX2.js.map → factory-VQS3HJ7V.js.map} +0 -0
- /package/dist/{issue-triage-TXQ7J6GG.js.map → issue-triage-HJUJWGAD.js.map} +0 -0
- /package/dist/{learning-persistence-FILWP3IR.js.map → learning-persistence-N6ILD2HX.js.map} +0 -0
- /package/dist/{mcp-config-OCWIXE2Y.js.map → mobimem-BOJFXQ7B.js.map} +0 -0
- /package/dist/{mobimem-77W5ED4Z.js.map → nexus-data-dir-77UO7N6J.js.map} +0 -0
- /package/dist/{registry-command-BBLIXULQ.js.map → registry-command-NCWUJKAF.js.map} +0 -0
- /package/dist/{nexus-data-dir-M6DYKIHJ.js.map → repo-security-plan-3J45VAD6.js.map} +0 -0
- /package/dist/{repo-security-plan-7SNM7JQN.js.map → research-helpers-synthesize-UGQHZZJN.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-7CI2FJE5.js.map → routing-memory-NO7QEH7T.js.map} +0 -0
- /package/dist/{routing-memory-DCIZEEVC.js.map → session-memory-DOXLEWEU.js.map} +0 -0
- /package/dist/{session-memory-5TSAASQW.js.map → setup-command-DVEBFKR2.js.map} +0 -0
- /package/dist/{setup-command-PU636ZJH.js.map → setup-config-E3JZYSLR.js.map} +0 -0
- /package/dist/{setup-custom-api-IQX3GD2D.js.map → setup-custom-api-DHJ5DRH2.js.map} +0 -0
- /package/dist/{setup-config-EA5RDIO2.js.map → weather-report-FNN4OX3N.js.map} +0 -0
|
@@ -0,0 +1,691 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConfigError,
|
|
3
|
+
ErrorCode,
|
|
4
|
+
ModelError,
|
|
5
|
+
NexusError,
|
|
6
|
+
TimeoutError,
|
|
7
|
+
createLogger,
|
|
8
|
+
err,
|
|
9
|
+
getErrorMessage,
|
|
10
|
+
getTokenEstimator,
|
|
11
|
+
isRateLimitLikeError,
|
|
12
|
+
ok
|
|
13
|
+
} from "./chunk-O4KUCF5S.js";
|
|
14
|
+
|
|
15
|
+
// src/adapters/base-adapter.ts
|
|
16
|
+
var AdapterModelError = class extends ModelError {
|
|
17
|
+
constructor(message, options) {
|
|
18
|
+
super(message, options);
|
|
19
|
+
this.name = "ModelError";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
function isApiKeyMissing(apiKey) {
|
|
23
|
+
return apiKey === void 0 || apiKey === "" || apiKey.trim() === "";
|
|
24
|
+
}
|
|
25
|
+
function requireApiKey(apiKey, providerName, modelId) {
|
|
26
|
+
if (isApiKeyMissing(apiKey)) {
|
|
27
|
+
throw new ConfigError(`${providerName} API key is required`, {
|
|
28
|
+
context: { providerId: providerName.toLowerCase(), modelId }
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function validateApiKeyPresence(apiKey, providerId, modelId) {
|
|
33
|
+
if (isApiKeyMissing(apiKey)) {
|
|
34
|
+
return err(
|
|
35
|
+
new ConfigError(`${providerId} API key is required`, {
|
|
36
|
+
context: { providerId, modelId }
|
|
37
|
+
})
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
return ok(void 0);
|
|
41
|
+
}
|
|
42
|
+
var BaseAdapter = class {
|
|
43
|
+
providerId;
|
|
44
|
+
modelId;
|
|
45
|
+
capabilities;
|
|
46
|
+
/** Logger for request/response logging */
|
|
47
|
+
logger;
|
|
48
|
+
/** Configuration for the adapter */
|
|
49
|
+
config;
|
|
50
|
+
/**
|
|
51
|
+
* Creates a new BaseAdapter instance.
|
|
52
|
+
*
|
|
53
|
+
* @param config - Adapter configuration
|
|
54
|
+
*/
|
|
55
|
+
constructor(config) {
|
|
56
|
+
this.providerId = config.providerId;
|
|
57
|
+
this.modelId = config.modelId;
|
|
58
|
+
this.capabilities = config.capabilities;
|
|
59
|
+
this.config = config;
|
|
60
|
+
this.logger = config.logger ?? createLogger({
|
|
61
|
+
adapter: config.providerId,
|
|
62
|
+
model: config.modelId
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Count tokens in text using the unified TokenEstimator.
|
|
67
|
+
*
|
|
68
|
+
* This provides a reasonable estimate for most use cases.
|
|
69
|
+
* Concrete adapters may override this with provider-specific tokenizers.
|
|
70
|
+
*
|
|
71
|
+
* @param text - Text to count tokens for
|
|
72
|
+
* @returns Approximate token count
|
|
73
|
+
*/
|
|
74
|
+
countTokens(text) {
|
|
75
|
+
return Promise.resolve(getTokenEstimator().estimateText(text));
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Validate adapter configuration.
|
|
79
|
+
*
|
|
80
|
+
* Checks that required configuration fields are present and valid.
|
|
81
|
+
* Concrete adapters may override to add provider-specific validation.
|
|
82
|
+
*
|
|
83
|
+
* @returns Ok if valid, ConfigError if invalid
|
|
84
|
+
*/
|
|
85
|
+
validateConfig() {
|
|
86
|
+
const errors = [];
|
|
87
|
+
if (!this.providerId || this.providerId.trim() === "") {
|
|
88
|
+
errors.push("Provider ID is required");
|
|
89
|
+
}
|
|
90
|
+
if (!this.modelId || this.modelId.trim() === "") {
|
|
91
|
+
errors.push("Model ID is required");
|
|
92
|
+
}
|
|
93
|
+
if (this.config.timeout !== void 0 && this.config.timeout <= 0) {
|
|
94
|
+
errors.push("Timeout must be positive");
|
|
95
|
+
}
|
|
96
|
+
if (this.config.maxRetries !== void 0 && this.config.maxRetries < 0) {
|
|
97
|
+
errors.push("Max retries cannot be negative");
|
|
98
|
+
}
|
|
99
|
+
if (errors.length > 0) {
|
|
100
|
+
return err(
|
|
101
|
+
new ConfigError(`Invalid adapter configuration: ${errors.join("; ")}`, {
|
|
102
|
+
context: {
|
|
103
|
+
providerId: this.providerId,
|
|
104
|
+
modelId: this.modelId,
|
|
105
|
+
errors
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
return ok(void 0);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Check if this adapter supports a specific capability.
|
|
114
|
+
*
|
|
115
|
+
* @param capability - The capability to check for
|
|
116
|
+
* @returns True if the capability is supported
|
|
117
|
+
*/
|
|
118
|
+
hasCapability(capability) {
|
|
119
|
+
return this.capabilities.includes(capability);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Log details about an outgoing request.
|
|
123
|
+
* Sanitizes sensitive information before logging.
|
|
124
|
+
*
|
|
125
|
+
* @param request - The completion request to log
|
|
126
|
+
*/
|
|
127
|
+
logRequest(request) {
|
|
128
|
+
const messageCount = request.messages.length;
|
|
129
|
+
const hasTools = request.tools !== void 0 && request.tools.length > 0;
|
|
130
|
+
const toolCount = request.tools?.length ?? 0;
|
|
131
|
+
this.logger.debug("Sending completion request", {
|
|
132
|
+
messageCount,
|
|
133
|
+
hasSystemPrompt: request.systemPrompt !== void 0,
|
|
134
|
+
temperature: request.temperature,
|
|
135
|
+
maxTokens: request.maxTokens,
|
|
136
|
+
hasTools,
|
|
137
|
+
toolCount,
|
|
138
|
+
responseFormat: request.responseFormat?.type,
|
|
139
|
+
stopSequences: request.stop?.length ?? 0
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Log details about a received response.
|
|
144
|
+
*
|
|
145
|
+
* @param response - The completion response to log
|
|
146
|
+
*/
|
|
147
|
+
logResponse(response) {
|
|
148
|
+
this.logger.debug("Received completion response", {
|
|
149
|
+
contentBlocks: response.content.length,
|
|
150
|
+
stopReason: response.stopReason,
|
|
151
|
+
inputTokens: response.usage.inputTokens,
|
|
152
|
+
outputTokens: response.usage.outputTokens,
|
|
153
|
+
totalTokens: response.usage.totalTokens,
|
|
154
|
+
model: response.model
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Transform a provider-specific error into a standardized ModelError.
|
|
159
|
+
*
|
|
160
|
+
* Maps common error patterns to appropriate error codes:
|
|
161
|
+
* - Rate limiting (429, quota exceeded)
|
|
162
|
+
* - Timeouts (ETIMEDOUT, ESOCKETTIMEDOUT)
|
|
163
|
+
* - Authentication (401, 403)
|
|
164
|
+
* - Model unavailable (503, 502)
|
|
165
|
+
*
|
|
166
|
+
* @param error - The original error from the provider
|
|
167
|
+
* @returns A standardized ModelError
|
|
168
|
+
*/
|
|
169
|
+
transformError(error) {
|
|
170
|
+
if (error instanceof ModelError) {
|
|
171
|
+
return error;
|
|
172
|
+
}
|
|
173
|
+
const errorMessage = getErrorMessage(error);
|
|
174
|
+
const errorCode = this.determineErrorCode(error);
|
|
175
|
+
const modelError = this.createModelError(errorMessage, errorCode, error);
|
|
176
|
+
this.logger.error("Model adapter error", modelError, {
|
|
177
|
+
errorCode,
|
|
178
|
+
providerId: this.providerId,
|
|
179
|
+
modelId: this.modelId
|
|
180
|
+
});
|
|
181
|
+
return modelError;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Create a ModelError with appropriate error code.
|
|
185
|
+
*/
|
|
186
|
+
createModelError(message, errorCode, originalError) {
|
|
187
|
+
const fullMessage = `${this.providerId}/${this.modelId}: ${message}`;
|
|
188
|
+
const options = {
|
|
189
|
+
code: errorCode,
|
|
190
|
+
context: {
|
|
191
|
+
providerId: this.providerId,
|
|
192
|
+
modelId: this.modelId
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
if (originalError instanceof Error) {
|
|
196
|
+
options.cause = originalError;
|
|
197
|
+
}
|
|
198
|
+
return new AdapterModelError(fullMessage, options);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Determine the appropriate error code based on error characteristics.
|
|
202
|
+
*/
|
|
203
|
+
determineErrorCode(error) {
|
|
204
|
+
if (!(error instanceof Error)) {
|
|
205
|
+
return ErrorCode.MODEL_ERROR;
|
|
206
|
+
}
|
|
207
|
+
const message = error.message.toLowerCase();
|
|
208
|
+
const errorObj = error;
|
|
209
|
+
if (isRateLimitLikeError(error)) {
|
|
210
|
+
return ErrorCode.MODEL_RATE_LIMITED;
|
|
211
|
+
}
|
|
212
|
+
if (this.isTimeoutError(message, errorObj)) {
|
|
213
|
+
return ErrorCode.MODEL_TIMEOUT;
|
|
214
|
+
}
|
|
215
|
+
if (this.isUnavailableError(message, errorObj)) {
|
|
216
|
+
return ErrorCode.MODEL_UNAVAILABLE;
|
|
217
|
+
}
|
|
218
|
+
return ErrorCode.MODEL_ERROR;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Check if error indicates a timeout.
|
|
222
|
+
*/
|
|
223
|
+
isTimeoutError(message, errorObj) {
|
|
224
|
+
const timeoutPatterns = ["timeout", "etimedout", "esockettimedout"];
|
|
225
|
+
return errorObj.code === "ETIMEDOUT" || errorObj.code === "ESOCKETTIMEDOUT" || timeoutPatterns.some((pattern) => message.includes(pattern));
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Check if error indicates model unavailability.
|
|
229
|
+
*/
|
|
230
|
+
isUnavailableError(message, errorObj) {
|
|
231
|
+
const unavailablePatterns = ["unavailable", "service unavailable", "overloaded"];
|
|
232
|
+
return errorObj.status === 502 || errorObj.status === 503 || unavailablePatterns.some((pattern) => message.includes(pattern));
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
// src/adapters/streaming-types.ts
|
|
237
|
+
var StreamError = class extends NexusError {
|
|
238
|
+
constructor(message, options) {
|
|
239
|
+
super(message, { code: ErrorCode.INTERNAL_ERROR, ...options });
|
|
240
|
+
this.name = "StreamError";
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
var StreamCancelledError = class extends NexusError {
|
|
244
|
+
constructor(reason) {
|
|
245
|
+
super(reason ?? "Stream was cancelled", { code: ErrorCode.INTERNAL_ERROR });
|
|
246
|
+
this.name = "StreamCancelledError";
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
var StreamController = class {
|
|
250
|
+
chunks = [];
|
|
251
|
+
waiters = [];
|
|
252
|
+
_state = "idle";
|
|
253
|
+
_error;
|
|
254
|
+
maxBufferSize;
|
|
255
|
+
abortHandler;
|
|
256
|
+
abortSignal;
|
|
257
|
+
/**
|
|
258
|
+
* Creates a new StreamController.
|
|
259
|
+
* @param options - Stream creation options
|
|
260
|
+
*/
|
|
261
|
+
constructor(options = {}) {
|
|
262
|
+
this.maxBufferSize = options.maxBufferSize ?? 100;
|
|
263
|
+
if (options.signal) {
|
|
264
|
+
this.abortSignal = options.signal;
|
|
265
|
+
this.abortHandler = () => {
|
|
266
|
+
this.cancel("AbortSignal triggered");
|
|
267
|
+
};
|
|
268
|
+
options.signal.addEventListener("abort", this.abortHandler);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Current state of the stream.
|
|
273
|
+
*/
|
|
274
|
+
get state() {
|
|
275
|
+
return this._state;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Whether the stream is still active (can receive chunks).
|
|
279
|
+
*/
|
|
280
|
+
get isActive() {
|
|
281
|
+
return this._state === "idle" || this._state === "streaming" || this._state === "paused";
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Current buffer size.
|
|
285
|
+
*/
|
|
286
|
+
get bufferSize() {
|
|
287
|
+
return this.chunks.length;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Push a chunk to the stream.
|
|
291
|
+
* @param chunk - The chunk to push
|
|
292
|
+
* @returns Result indicating success or backpressure
|
|
293
|
+
*/
|
|
294
|
+
push(chunk) {
|
|
295
|
+
if (!this.isActive) {
|
|
296
|
+
return err(new StreamError(`Cannot push to stream in state: ${this._state}`));
|
|
297
|
+
}
|
|
298
|
+
if (this._state === "idle") {
|
|
299
|
+
this._state = "streaming";
|
|
300
|
+
}
|
|
301
|
+
const waiter = this.waiters.shift();
|
|
302
|
+
if (waiter) {
|
|
303
|
+
waiter.resolve({ done: false, value: chunk });
|
|
304
|
+
return ok(void 0);
|
|
305
|
+
}
|
|
306
|
+
if (this.chunks.length >= this.maxBufferSize) {
|
|
307
|
+
this._state = "paused";
|
|
308
|
+
return err(
|
|
309
|
+
new StreamError("Buffer full - backpressure applied", {
|
|
310
|
+
context: { bufferSize: this.chunks.length, maxBufferSize: this.maxBufferSize }
|
|
311
|
+
})
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
this.chunks.push(chunk);
|
|
315
|
+
return ok(void 0);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Complete the stream successfully.
|
|
319
|
+
*/
|
|
320
|
+
complete() {
|
|
321
|
+
if (!this.isActive) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
this._state = "completed";
|
|
325
|
+
this.removeAbortListener();
|
|
326
|
+
this.resolveAllWaiters();
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Complete the stream with an error.
|
|
330
|
+
* @param error - The error that occurred
|
|
331
|
+
*/
|
|
332
|
+
error(error) {
|
|
333
|
+
if (!this.isActive) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
this._state = "error";
|
|
337
|
+
this._error = error;
|
|
338
|
+
this.removeAbortListener();
|
|
339
|
+
this.rejectAllWaiters(error);
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Cancel the stream.
|
|
343
|
+
* @param reason - Optional reason for cancellation
|
|
344
|
+
*/
|
|
345
|
+
cancel(reason) {
|
|
346
|
+
if (!this.isActive) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
this._state = "cancelled";
|
|
350
|
+
this._error = new StreamCancelledError(reason);
|
|
351
|
+
this.removeAbortListener();
|
|
352
|
+
this.rejectAllWaiters(this._error);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Get the AsyncIterable for consuming the stream.
|
|
356
|
+
*/
|
|
357
|
+
getIterable() {
|
|
358
|
+
const nextChunk = () => this.nextChunk();
|
|
359
|
+
const cancel = (reason) => {
|
|
360
|
+
this.cancel(reason);
|
|
361
|
+
};
|
|
362
|
+
return {
|
|
363
|
+
[Symbol.asyncIterator]() {
|
|
364
|
+
return {
|
|
365
|
+
async next() {
|
|
366
|
+
return nextChunk();
|
|
367
|
+
},
|
|
368
|
+
return() {
|
|
369
|
+
cancel("Iterator returned");
|
|
370
|
+
return Promise.resolve({ done: true, value: void 0 });
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
async nextChunk() {
|
|
377
|
+
const chunk = this.chunks.shift();
|
|
378
|
+
if (chunk !== void 0) {
|
|
379
|
+
if (this._state === "paused" && this.chunks.length < this.maxBufferSize / 2) {
|
|
380
|
+
this._state = "streaming";
|
|
381
|
+
}
|
|
382
|
+
return { done: false, value: chunk };
|
|
383
|
+
}
|
|
384
|
+
if (this._state === "completed") {
|
|
385
|
+
return { done: true, value: void 0 };
|
|
386
|
+
}
|
|
387
|
+
if (this._state === "cancelled" || this._state === "error") {
|
|
388
|
+
throw this._error ?? new StreamCancelledError();
|
|
389
|
+
}
|
|
390
|
+
return new Promise((resolve, reject) => {
|
|
391
|
+
this.waiters.push({ resolve, reject });
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
removeAbortListener() {
|
|
395
|
+
if (this.abortSignal && this.abortHandler) {
|
|
396
|
+
this.abortSignal.removeEventListener("abort", this.abortHandler);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
resolveAllWaiters() {
|
|
400
|
+
for (const waiter of this.waiters) {
|
|
401
|
+
waiter.resolve({ done: true, value: void 0 });
|
|
402
|
+
}
|
|
403
|
+
this.waiters.length = 0;
|
|
404
|
+
}
|
|
405
|
+
rejectAllWaiters(error) {
|
|
406
|
+
for (const waiter of this.waiters) {
|
|
407
|
+
waiter.reject(error);
|
|
408
|
+
}
|
|
409
|
+
this.waiters.length = 0;
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
function createStream(options = {}) {
|
|
413
|
+
const controller = new StreamController(options);
|
|
414
|
+
return [controller, controller.getIterable()];
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// src/adapters/stream-operators-helpers.ts
|
|
418
|
+
async function* take(stream, count, options = {}) {
|
|
419
|
+
if (count <= 0) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
let taken = 0;
|
|
423
|
+
for await (const chunk of stream) {
|
|
424
|
+
if (options.signal?.aborted === true) {
|
|
425
|
+
throw new StreamCancelledError("take aborted");
|
|
426
|
+
}
|
|
427
|
+
yield chunk;
|
|
428
|
+
taken++;
|
|
429
|
+
if (taken >= count) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
async function* skip(stream, count, options = {}) {
|
|
435
|
+
let skipped = 0;
|
|
436
|
+
for await (const chunk of stream) {
|
|
437
|
+
if (options.signal?.aborted === true) {
|
|
438
|
+
throw new StreamCancelledError("skip aborted");
|
|
439
|
+
}
|
|
440
|
+
if (skipped < count) {
|
|
441
|
+
skipped++;
|
|
442
|
+
continue;
|
|
443
|
+
}
|
|
444
|
+
yield chunk;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
async function* concatStreams(streams, options = {}) {
|
|
448
|
+
for (const stream of streams) {
|
|
449
|
+
if (options.signal?.aborted === true) {
|
|
450
|
+
throw new StreamCancelledError("concat aborted");
|
|
451
|
+
}
|
|
452
|
+
yield* stream;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
async function* fromArray(values, options = {}) {
|
|
456
|
+
for (const value of values) {
|
|
457
|
+
if (options.signal?.aborted === true) {
|
|
458
|
+
throw new StreamCancelledError("fromArray aborted");
|
|
459
|
+
}
|
|
460
|
+
if (options.delayMs !== void 0 && options.delayMs > 0) {
|
|
461
|
+
await new Promise((resolve) => setTimeout(resolve, options.delayMs));
|
|
462
|
+
}
|
|
463
|
+
yield value;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
async function* tapStream(stream, fn, options = {}) {
|
|
467
|
+
let index = 0;
|
|
468
|
+
for await (const chunk of stream) {
|
|
469
|
+
if (options.signal?.aborted === true) {
|
|
470
|
+
throw new StreamCancelledError("tap aborted");
|
|
471
|
+
}
|
|
472
|
+
await fn(chunk, index);
|
|
473
|
+
yield chunk;
|
|
474
|
+
index++;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
async function reduceStream(stream, reducer, initialValue, options = {}) {
|
|
478
|
+
let accumulator = initialValue;
|
|
479
|
+
let index = 0;
|
|
480
|
+
try {
|
|
481
|
+
for await (const chunk of stream) {
|
|
482
|
+
if (options.signal?.aborted === true) {
|
|
483
|
+
return err(new StreamError("Reduce aborted"));
|
|
484
|
+
}
|
|
485
|
+
accumulator = await reducer(accumulator, chunk, index);
|
|
486
|
+
index++;
|
|
487
|
+
}
|
|
488
|
+
return ok(accumulator);
|
|
489
|
+
} catch (error) {
|
|
490
|
+
return err(
|
|
491
|
+
new StreamError("Failed to reduce stream", {
|
|
492
|
+
cause: error instanceof Error ? error : new Error(String(error))
|
|
493
|
+
})
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// src/adapters/stream-operators.ts
|
|
499
|
+
async function* transformStream(stream, fn, options = {}) {
|
|
500
|
+
let index = 0;
|
|
501
|
+
for await (const chunk of stream) {
|
|
502
|
+
if (options.signal?.aborted === true) {
|
|
503
|
+
throw new StreamCancelledError("Transform aborted");
|
|
504
|
+
}
|
|
505
|
+
yield await fn(chunk, index);
|
|
506
|
+
index++;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
async function* mergeStreams(streams, options = {}) {
|
|
510
|
+
if (streams.length === 0) {
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
const streamOptions = {};
|
|
514
|
+
if (options.signal) {
|
|
515
|
+
streamOptions.signal = options.signal;
|
|
516
|
+
}
|
|
517
|
+
const [controller, merged] = createStream(streamOptions);
|
|
518
|
+
let activeCount = streams.length;
|
|
519
|
+
const consumers = streams.map(async (stream, streamIndex) => {
|
|
520
|
+
try {
|
|
521
|
+
for await (const chunk of stream) {
|
|
522
|
+
if (options.signal?.aborted === true) {
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
controller.push(chunk);
|
|
526
|
+
}
|
|
527
|
+
} catch (error) {
|
|
528
|
+
if (error instanceof StreamCancelledError) {
|
|
529
|
+
controller.cancel(`Stream ${String(streamIndex)} was cancelled`);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
controller.error(error instanceof Error ? error : new Error(String(error)));
|
|
533
|
+
return;
|
|
534
|
+
} finally {
|
|
535
|
+
activeCount--;
|
|
536
|
+
if (activeCount === 0) {
|
|
537
|
+
controller.complete();
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
Promise.all(consumers).catch((error) => {
|
|
542
|
+
controller.error(error instanceof Error ? error : new StreamError(String(error)));
|
|
543
|
+
});
|
|
544
|
+
yield* merged;
|
|
545
|
+
}
|
|
546
|
+
async function* takeUntil(stream, predicate, options = {}) {
|
|
547
|
+
let index = 0;
|
|
548
|
+
for await (const chunk of stream) {
|
|
549
|
+
if (options.signal?.aborted === true) {
|
|
550
|
+
throw new StreamCancelledError("takeUntil aborted");
|
|
551
|
+
}
|
|
552
|
+
const shouldStop = await predicate(chunk, index);
|
|
553
|
+
if (shouldStop) {
|
|
554
|
+
if (options.inclusive === true) {
|
|
555
|
+
yield chunk;
|
|
556
|
+
}
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
yield chunk;
|
|
560
|
+
index++;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
async function* filterStream(stream, predicate, options = {}) {
|
|
564
|
+
let index = 0;
|
|
565
|
+
for await (const chunk of stream) {
|
|
566
|
+
if (options.signal?.aborted === true) {
|
|
567
|
+
throw new StreamCancelledError("filter aborted");
|
|
568
|
+
}
|
|
569
|
+
if (await predicate(chunk, index)) {
|
|
570
|
+
yield chunk;
|
|
571
|
+
}
|
|
572
|
+
index++;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
async function* withTimeout(stream, timeoutMs, options = {}) {
|
|
576
|
+
const iterator = stream[Symbol.asyncIterator]();
|
|
577
|
+
try {
|
|
578
|
+
let running = true;
|
|
579
|
+
while (running) {
|
|
580
|
+
if (options.signal?.aborted === true) {
|
|
581
|
+
throw new StreamCancelledError("withTimeout aborted");
|
|
582
|
+
}
|
|
583
|
+
let timeoutId;
|
|
584
|
+
try {
|
|
585
|
+
const result = await Promise.race([
|
|
586
|
+
iterator.next().then((res) => {
|
|
587
|
+
if (timeoutId !== void 0) {
|
|
588
|
+
clearTimeout(timeoutId);
|
|
589
|
+
}
|
|
590
|
+
return res;
|
|
591
|
+
}),
|
|
592
|
+
new Promise((_, reject) => {
|
|
593
|
+
timeoutId = setTimeout(() => {
|
|
594
|
+
reject(
|
|
595
|
+
new TimeoutError(`Stream timed out after ${String(timeoutMs)}ms`, {
|
|
596
|
+
context: { timeoutMs }
|
|
597
|
+
})
|
|
598
|
+
);
|
|
599
|
+
}, timeoutMs);
|
|
600
|
+
})
|
|
601
|
+
]);
|
|
602
|
+
if (result.done === true) {
|
|
603
|
+
running = false;
|
|
604
|
+
} else {
|
|
605
|
+
yield result.value;
|
|
606
|
+
}
|
|
607
|
+
} finally {
|
|
608
|
+
if (timeoutId !== void 0) {
|
|
609
|
+
clearTimeout(timeoutId);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
} finally {
|
|
614
|
+
if (iterator.return !== void 0) {
|
|
615
|
+
await iterator.return();
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
async function* bufferStream(stream, size, options = {}) {
|
|
620
|
+
if (size <= 0) {
|
|
621
|
+
throw new StreamError("Buffer size must be positive");
|
|
622
|
+
}
|
|
623
|
+
let buffer = [];
|
|
624
|
+
for await (const chunk of stream) {
|
|
625
|
+
if (options.signal?.aborted === true) {
|
|
626
|
+
throw new StreamCancelledError("buffer aborted");
|
|
627
|
+
}
|
|
628
|
+
buffer.push(chunk);
|
|
629
|
+
if (buffer.length >= size) {
|
|
630
|
+
yield buffer;
|
|
631
|
+
buffer = [];
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
if (buffer.length > 0) {
|
|
635
|
+
yield buffer;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// src/adapters/streaming.ts
|
|
640
|
+
var DEFAULT_COLLECT_STREAM_MAX_CHUNKS = 1e5;
|
|
641
|
+
async function collectStream(stream, options = {}) {
|
|
642
|
+
const chunks = [];
|
|
643
|
+
const maxChunks = options.maxChunks ?? DEFAULT_COLLECT_STREAM_MAX_CHUNKS;
|
|
644
|
+
try {
|
|
645
|
+
for await (const chunk of stream) {
|
|
646
|
+
if (options.signal?.aborted === true) {
|
|
647
|
+
return err(new StreamError("Collection aborted"));
|
|
648
|
+
}
|
|
649
|
+
chunks.push(chunk);
|
|
650
|
+
if (chunks.length >= maxChunks) {
|
|
651
|
+
break;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
return ok(chunks);
|
|
655
|
+
} catch (error) {
|
|
656
|
+
if (error instanceof StreamCancelledError) {
|
|
657
|
+
return err(new StreamError("Stream was cancelled during collection", { cause: error }));
|
|
658
|
+
}
|
|
659
|
+
return err(
|
|
660
|
+
new StreamError("Failed to collect stream", {
|
|
661
|
+
cause: error instanceof Error ? error : new Error(String(error))
|
|
662
|
+
})
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
export {
|
|
668
|
+
AdapterModelError,
|
|
669
|
+
requireApiKey,
|
|
670
|
+
validateApiKeyPresence,
|
|
671
|
+
BaseAdapter,
|
|
672
|
+
StreamError,
|
|
673
|
+
StreamCancelledError,
|
|
674
|
+
StreamController,
|
|
675
|
+
createStream,
|
|
676
|
+
take,
|
|
677
|
+
skip,
|
|
678
|
+
concatStreams,
|
|
679
|
+
fromArray,
|
|
680
|
+
tapStream,
|
|
681
|
+
reduceStream,
|
|
682
|
+
transformStream,
|
|
683
|
+
mergeStreams,
|
|
684
|
+
takeUntil,
|
|
685
|
+
filterStream,
|
|
686
|
+
withTimeout,
|
|
687
|
+
bufferStream,
|
|
688
|
+
DEFAULT_COLLECT_STREAM_MAX_CHUNKS,
|
|
689
|
+
collectStream
|
|
690
|
+
};
|
|
691
|
+
//# sourceMappingURL=chunk-5MHIWRKB.js.map
|