@ganju/utils 0.0.13 → 0.0.15
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/channelCustomer.d.ts +99 -0
- package/dist/channelCustomer.d.ts.map +1 -0
- package/dist/channelCustomer.js +533 -0
- package/dist/channelDebounce.d.ts +7 -0
- package/dist/channelDebounce.d.ts.map +1 -1
- package/dist/chunkOverlap.d.ts +2 -0
- package/dist/chunkOverlap.d.ts.map +1 -0
- package/dist/chunkOverlap.js +9 -0
- package/dist/chunking.d.ts.map +1 -1
- package/dist/chunking.js +24 -4
- package/dist/citations.d.ts +28 -0
- package/dist/citations.d.ts.map +1 -0
- package/dist/citations.js +111 -0
- package/dist/constants.d.ts +26 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +108 -10
- package/dist/index.d.ts +263 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +70 -0
- package/dist/jsonSchemaToZodShape.d.ts +5 -1
- package/dist/jsonSchemaToZodShape.d.ts.map +1 -1
- package/dist/jsonSchemaToZodShape.js +21 -9
- package/dist/pagination.d.ts +47 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +160 -0
- package/dist/processQueueBatch.d.ts +6 -1
- package/dist/processQueueBatch.d.ts.map +1 -1
- package/dist/processQueueBatch.js +23 -10
- package/dist/queueFailure.d.ts +14 -0
- package/dist/queueFailure.d.ts.map +1 -0
- package/dist/queueFailure.js +43 -0
- package/dist/resourceRerank.d.ts.map +1 -1
- package/dist/resourceRerank.js +3 -1
- package/dist/schema.d.ts +90 -26
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +87 -6
- package/dist/ssrf.d.ts +1 -0
- package/dist/ssrf.d.ts.map +1 -1
- package/dist/ssrf.js +48 -12
- package/dist/toolConfirmation.d.ts +48 -0
- package/dist/toolConfirmation.d.ts.map +1 -1
- package/dist/toolConfirmation.js +75 -1
- package/dist/toolCount.d.ts +13 -0
- package/dist/toolCount.d.ts.map +1 -0
- package/dist/toolCount.js +45 -0
- package/dist/toolLint.d.ts +1 -1
- package/dist/toolLint.d.ts.map +1 -1
- package/dist/toolLint.js +37 -3
- package/dist/untrustedContent.d.ts +135 -0
- package/dist/untrustedContent.d.ts.map +1 -0
- package/dist/untrustedContent.js +402 -0
- package/package.json +2 -1
- package/src/channelCustomer.ts +604 -0
- package/src/channelDebounce.ts +17 -0
- package/src/chunkOverlap.ts +6 -0
- package/src/chunking.ts +25 -4
- package/src/citations.ts +127 -0
- package/src/constants.ts +112 -10
- package/src/index.ts +152 -2
- package/src/jsonSchemaToZodShape.ts +31 -13
- package/src/pagination.ts +193 -0
- package/src/processQueueBatch.ts +42 -12
- package/src/queueFailure.ts +63 -0
- package/src/resourceRerank.ts +5 -1
- package/src/schema.ts +100 -4
- package/src/ssrf.ts +40 -11
- package/src/toolConfirmation.ts +123 -0
- package/src/toolCount.ts +53 -0
- package/src/toolLint.ts +46 -3
- package/src/untrustedContent.ts +476 -0
package/dist/index.js
CHANGED
|
@@ -17,6 +17,8 @@ const coerce_1 = require("./coerce");
|
|
|
17
17
|
const validateMessageVariables_1 = require("./validateMessageVariables");
|
|
18
18
|
const jsonSchemaToZodShape_1 = require("./jsonSchemaToZodShape");
|
|
19
19
|
const mcpProxy_1 = require("./mcpProxy");
|
|
20
|
+
const toolCount_1 = require("./toolCount");
|
|
21
|
+
const pagination_1 = require("./pagination");
|
|
20
22
|
const customCodeToken_1 = require("./customCodeToken");
|
|
21
23
|
const containmentToken_1 = require("./containmentToken");
|
|
22
24
|
const oauthProviders_1 = require("./oauthProviders");
|
|
@@ -45,11 +47,15 @@ const l2Normalize_1 = require("./l2Normalize");
|
|
|
45
47
|
const resourceRerank_1 = require("./resourceRerank");
|
|
46
48
|
const retry_1 = require("./retry");
|
|
47
49
|
const processQueueBatch_1 = require("./processQueueBatch");
|
|
50
|
+
const queueFailure_1 = require("./queueFailure");
|
|
48
51
|
const channelNotifier_1 = require("./channelNotifier");
|
|
49
52
|
const channelDebounce_1 = require("./channelDebounce");
|
|
50
53
|
const toolConfirmation_1 = require("./toolConfirmation");
|
|
54
|
+
const untrustedContent_1 = require("./untrustedContent");
|
|
55
|
+
const channelCustomer_1 = require("./channelCustomer");
|
|
51
56
|
const toolLint_1 = require("./toolLint");
|
|
52
57
|
const sources_1 = require("./sources");
|
|
58
|
+
const citations_1 = require("./citations");
|
|
53
59
|
const oauth_1 = require("./oauth");
|
|
54
60
|
const vendorTimeZone_1 = require("./vendorTimeZone");
|
|
55
61
|
const planLimitError_1 = require("./planLimitError");
|
|
@@ -93,6 +99,12 @@ exports.utils = {
|
|
|
93
99
|
jsonSchemaToZodShape: jsonSchemaToZodShape_1.jsonSchemaToZodShape,
|
|
94
100
|
validateAgainstJsonSchema: jsonSchemaToZodShape_1.validateAgainstJsonSchema,
|
|
95
101
|
buildProxyToolName: mcpProxy_1.buildProxyToolName,
|
|
102
|
+
countInstallTools: toolCount_1.countInstallTools,
|
|
103
|
+
capText: pagination_1.capText,
|
|
104
|
+
findNextCursor: pagination_1.findNextCursor,
|
|
105
|
+
paginate: pagination_1.paginate,
|
|
106
|
+
InvalidCursorError: pagination_1.InvalidCursorError,
|
|
107
|
+
listResourcesPage: pagination_1.listResourcesPage,
|
|
96
108
|
mintCustomCodeToken: customCodeToken_1.mintCustomCodeToken,
|
|
97
109
|
verifyCustomCodeToken: customCodeToken_1.verifyCustomCodeToken,
|
|
98
110
|
customCodeScriptName: customCodeToken_1.customCodeScriptName,
|
|
@@ -117,6 +129,7 @@ exports.utils = {
|
|
|
117
129
|
validateProjectPath: customCodeProject_1.validateProjectPath,
|
|
118
130
|
projectPathIssue: customCodeProject_1.projectPathIssue,
|
|
119
131
|
ipv4InPrivateRange: ssrf_1.ipv4InPrivateRange,
|
|
132
|
+
isBlockedUrl: ssrf_1.isBlockedUrl,
|
|
120
133
|
isBlockedHost: ssrf_1.isBlockedHost,
|
|
121
134
|
requiresLlmBaseUrl: llmBaseUrl_1.requiresLlmBaseUrl,
|
|
122
135
|
isAllowedLlmBaseUrl: llmBaseUrl_1.isAllowedLlmBaseUrl,
|
|
@@ -158,6 +171,8 @@ exports.utils = {
|
|
|
158
171
|
isRateLimitError: retry_1.isRateLimitError,
|
|
159
172
|
withRateLimitRetry: retry_1.withRateLimitRetry,
|
|
160
173
|
processQueueBatch: processQueueBatch_1.processQueueBatch,
|
|
174
|
+
PermanentJobError: queueFailure_1.PermanentJobError,
|
|
175
|
+
isPermanentJobError: queueFailure_1.isPermanentJobError,
|
|
161
176
|
getToolStatusMessage: channelNotifier_1.getToolStatusMessage,
|
|
162
177
|
resolveDebounceMs: channelDebounce_1.resolveDebounceMs,
|
|
163
178
|
channelBufferKey: channelDebounce_1.channelBufferKey,
|
|
@@ -172,7 +187,59 @@ exports.utils = {
|
|
|
172
187
|
annotationsForEffect: toolConfirmation_1.annotationsForEffect,
|
|
173
188
|
TOOL_EFFECTS: toolConfirmation_1.TOOL_EFFECTS,
|
|
174
189
|
isSensitiveTool: toolConfirmation_1.isSensitiveTool,
|
|
190
|
+
proxiedToolAnnotations: toolConfirmation_1.proxiedToolAnnotations,
|
|
191
|
+
proxiedToolTrust: toolConfirmation_1.proxiedToolTrust,
|
|
192
|
+
isSensitiveProxiedTool: toolConfirmation_1.isSensitiveProxiedTool,
|
|
193
|
+
keepProxiedToolMarks: toolConfirmation_1.keepProxiedToolMarks,
|
|
194
|
+
toolApprovalStatus: toolConfirmation_1.toolApprovalStatus,
|
|
195
|
+
toolApprovalUrl: toolConfirmation_1.toolApprovalUrl,
|
|
175
196
|
stableJson: toolConfirmation_1.stableJson,
|
|
197
|
+
wrapUntrustedContent: untrustedContent_1.wrapUntrustedContent,
|
|
198
|
+
unwrapUntrustedContent: untrustedContent_1.unwrapUntrustedContent,
|
|
199
|
+
isUntrustedToolResult: untrustedContent_1.isUntrustedToolResult,
|
|
200
|
+
findInstructionLikeText: untrustedContent_1.findInstructionLikeText,
|
|
201
|
+
UNTRUSTED_CONTENT_TAG: untrustedContent_1.UNTRUSTED_CONTENT_TAG,
|
|
202
|
+
UNTRUSTED_CONTENT_META_KEY: untrustedContent_1.UNTRUSTED_CONTENT_META_KEY,
|
|
203
|
+
UNTRUSTED_CONTENT_NOTE: untrustedContent_1.UNTRUSTED_CONTENT_NOTE,
|
|
204
|
+
INSTRUCTION_WARNING_METADATA_KEY: untrustedContent_1.INSTRUCTION_WARNING_METADATA_KEY,
|
|
205
|
+
untrustedToolResult: untrustedContent_1.untrustedToolResult,
|
|
206
|
+
ownWritingToolResult: untrustedContent_1.ownWritingToolResult,
|
|
207
|
+
labelOwnToolResult: untrustedContent_1.labelOwnToolResult,
|
|
208
|
+
labelProxiedToolResult: untrustedContent_1.labelProxiedToolResult,
|
|
209
|
+
untrustedErrorResult: untrustedContent_1.untrustedErrorResult,
|
|
210
|
+
readsLikeInstructions: untrustedContent_1.readsLikeInstructions,
|
|
211
|
+
labelResourceContents: untrustedContent_1.labelResourceContents,
|
|
212
|
+
PARTICIPANT_DAILY_LIMIT_DEFAULT: channelCustomer_1.PARTICIPANT_DAILY_LIMIT_DEFAULT,
|
|
213
|
+
PARTICIPANT_DAILY_LIMIT_MAX: channelCustomer_1.PARTICIPANT_DAILY_LIMIT_MAX,
|
|
214
|
+
PARTICIPANT_DAILY_LIMIT_OFF: channelCustomer_1.PARTICIPANT_DAILY_LIMIT_OFF,
|
|
215
|
+
PARTICIPANT_DAILY_LIMIT_WINDOW_MS: channelCustomer_1.PARTICIPANT_DAILY_LIMIT_WINDOW_MS,
|
|
216
|
+
PARTICIPANT_LIMIT_METADATA_KEY: channelCustomer_1.PARTICIPANT_LIMIT_METADATA_KEY,
|
|
217
|
+
resolveParticipantDailyLimit: channelCustomer_1.resolveParticipantDailyLimit,
|
|
218
|
+
resolveParticipantMemoryEnabled: channelCustomer_1.resolveParticipantMemoryEnabled,
|
|
219
|
+
VOICE_NOTE_MAX_BYTES: channelCustomer_1.VOICE_NOTE_MAX_BYTES,
|
|
220
|
+
VOICE_NOTE_MAX_SECONDS: channelCustomer_1.VOICE_NOTE_MAX_SECONDS,
|
|
221
|
+
audioDurationSeconds: channelCustomer_1.audioDurationSeconds,
|
|
222
|
+
oggDurationSeconds: channelCustomer_1.oggDurationSeconds,
|
|
223
|
+
VOICE_NOTE_TRANSCRIPTION_PROMPT: channelCustomer_1.VOICE_NOTE_TRANSCRIPTION_PROMPT,
|
|
224
|
+
VOICE_NOTE_METADATA_KEY: channelCustomer_1.VOICE_NOTE_METADATA_KEY,
|
|
225
|
+
VOICE_NOTE_UNREADABLE_METADATA_KEY: channelCustomer_1.VOICE_NOTE_UNREADABLE_METADATA_KEY,
|
|
226
|
+
PARTICIPANT_MEMORY_TOOL_NAME: channelCustomer_1.PARTICIPANT_MEMORY_TOOL_NAME,
|
|
227
|
+
PARTICIPANT_MEMORY_MAX_FACTS: channelCustomer_1.PARTICIPANT_MEMORY_MAX_FACTS,
|
|
228
|
+
PARTICIPANT_MEMORY_TOOL_DESCRIPTION: channelCustomer_1.PARTICIPANT_MEMORY_TOOL_DESCRIPTION,
|
|
229
|
+
PARTICIPANT_MEMORY_TOOL_SCHEMA: channelCustomer_1.PARTICIPANT_MEMORY_TOOL_SCHEMA,
|
|
230
|
+
PARTICIPANT_MEMORY_GROUP_NOTE: channelCustomer_1.PARTICIPANT_MEMORY_GROUP_NOTE,
|
|
231
|
+
readParticipantMemory: channelCustomer_1.readParticipantMemory,
|
|
232
|
+
applyParticipantMemoryUpdate: channelCustomer_1.applyParticipantMemoryUpdate,
|
|
233
|
+
redactParticipantMemoryArgs: channelCustomer_1.redactParticipantMemoryArgs,
|
|
234
|
+
redactParticipantMemoryConfirmation: channelCustomer_1.redactParticipantMemoryConfirmation,
|
|
235
|
+
participantMemoryUpdateReadsLikeInstructions: channelCustomer_1.participantMemoryUpdateReadsLikeInstructions,
|
|
236
|
+
CONVERSATION_UNTRUSTED_WINDOW_MS: channelCustomer_1.CONVERSATION_UNTRUSTED_WINDOW_MS,
|
|
237
|
+
CONVERSATION_UNTRUSTED_READ_AT_KEY: channelCustomer_1.CONVERSATION_UNTRUSTED_READ_AT_KEY,
|
|
238
|
+
conversationReadUntrustedRecently: channelCustomer_1.conversationReadUntrustedRecently,
|
|
239
|
+
formatParticipantMemoryPrompt: channelCustomer_1.formatParticipantMemoryPrompt,
|
|
240
|
+
participantLimitNotice: channelCustomer_1.participantLimitNotice,
|
|
241
|
+
voiceNoteUnreadableNotice: channelCustomer_1.voiceNoteUnreadableNotice,
|
|
242
|
+
voiceNoteTooLongNotice: channelCustomer_1.voiceNoteTooLongNotice,
|
|
176
243
|
lintTools: toolLint_1.lintTools,
|
|
177
244
|
TOOL_LINT_RULES: toolLint_1.TOOL_LINT_RULES,
|
|
178
245
|
TOOL_LINT_MAX_TOOLS: toolLint_1.TOOL_LINT_MAX_TOOLS,
|
|
@@ -183,6 +250,9 @@ exports.utils = {
|
|
|
183
250
|
buildResourceDownloadUrl: sources_1.buildResourceDownloadUrl,
|
|
184
251
|
formatSourcesAsMarkdown: sources_1.formatSourcesAsMarkdown,
|
|
185
252
|
formatSourcesAsButtons: sources_1.formatSourcesAsButtons,
|
|
253
|
+
citesUrl: citations_1.citesUrl,
|
|
254
|
+
citedPages: citations_1.citedPages,
|
|
255
|
+
selectCitedSources: citations_1.selectCitedSources,
|
|
186
256
|
refreshOAuthToken: oauth_1.refreshOAuthToken,
|
|
187
257
|
OAuthReauthRequiredError: oauth_1.OAuthReauthRequiredError,
|
|
188
258
|
buildReauthMetadata: oauth_1.buildReauthMetadata,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as z from 'zod';
|
|
2
2
|
export type JsonSchemaProperty = {
|
|
3
|
-
type: 'string' | 'number' | 'boolean' | 'object' | 'array';
|
|
3
|
+
type: 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array';
|
|
4
4
|
description?: string;
|
|
5
5
|
minimum?: number;
|
|
6
6
|
maximum?: number;
|
|
@@ -9,6 +9,10 @@ export type JsonSchemaProperty = {
|
|
|
9
9
|
pattern?: string;
|
|
10
10
|
enum?: string[];
|
|
11
11
|
items?: JsonSchemaProperty;
|
|
12
|
+
minItems?: number;
|
|
13
|
+
maxItems?: number;
|
|
14
|
+
properties?: Record<string, JsonSchemaProperty>;
|
|
15
|
+
required?: string[];
|
|
12
16
|
};
|
|
13
17
|
export type JsonSchema = {
|
|
14
18
|
type: 'object';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsonSchemaToZodShape.d.ts","sourceRoot":"","sources":["../src/jsonSchemaToZodShape.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"jsonSchemaToZodShape.d.ts","sourceRoot":"","sources":["../src/jsonSchemaToZodShape.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;IACvE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAChD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAChD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC;AAuEF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,UAAU,KACjB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CACe,CAAC;AAE9C,MAAM,WAAW,eAAe;IAE9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,GACpC,QAAQ,UAAU,EAClB,OAAO,OAAO,KACb,eAAe,EAOjB,CAAC"}
|
|
@@ -54,8 +54,9 @@ const propertyToZod = (prop) => {
|
|
|
54
54
|
}
|
|
55
55
|
break;
|
|
56
56
|
}
|
|
57
|
-
case 'number':
|
|
58
|
-
|
|
57
|
+
case 'number':
|
|
58
|
+
case 'integer': {
|
|
59
|
+
let num = prop.type === 'integer' ? z.number().int() : z.number();
|
|
59
60
|
if (prop.minimum !== undefined)
|
|
60
61
|
num = num.min(prop.minimum);
|
|
61
62
|
if (prop.maximum !== undefined)
|
|
@@ -66,11 +67,23 @@ const propertyToZod = (prop) => {
|
|
|
66
67
|
case 'boolean':
|
|
67
68
|
field = z.boolean();
|
|
68
69
|
break;
|
|
69
|
-
case 'array':
|
|
70
|
-
|
|
70
|
+
case 'array': {
|
|
71
|
+
let arr = z.array(prop.items ? propertyToZod(prop.items) : z.any());
|
|
72
|
+
if (prop.minItems !== undefined)
|
|
73
|
+
arr = arr.min(prop.minItems);
|
|
74
|
+
if (prop.maxItems !== undefined)
|
|
75
|
+
arr = arr.max(prop.maxItems);
|
|
76
|
+
field = arr;
|
|
71
77
|
break;
|
|
78
|
+
}
|
|
72
79
|
case 'object':
|
|
73
|
-
|
|
80
|
+
// With declared properties, keep them: this shape is also what
|
|
81
|
+
// `tools/list` advertises, and a bare record there tells the model an
|
|
82
|
+
// item is any object at all, so it invents the field names. Loose,
|
|
83
|
+
// because a schema without `additionalProperties: false` allows extras.
|
|
84
|
+
field = prop.properties
|
|
85
|
+
? z.looseObject(shapeOf(prop.properties, prop.required))
|
|
86
|
+
: z.record(z.string(), z.any());
|
|
74
87
|
break;
|
|
75
88
|
default:
|
|
76
89
|
field = z.any();
|
|
@@ -80,16 +93,15 @@ const propertyToZod = (prop) => {
|
|
|
80
93
|
}
|
|
81
94
|
return field;
|
|
82
95
|
};
|
|
83
|
-
|
|
84
|
-
const properties = schema.properties ?? {};
|
|
85
|
-
const required = schema.required ?? [];
|
|
96
|
+
function shapeOf(properties = {}, required = []) {
|
|
86
97
|
const shape = {};
|
|
87
98
|
for (const [key, prop] of Object.entries(properties)) {
|
|
88
99
|
const field = propertyToZod(prop);
|
|
89
100
|
shape[key] = required.includes(key) ? field : field.optional();
|
|
90
101
|
}
|
|
91
102
|
return shape;
|
|
92
|
-
}
|
|
103
|
+
}
|
|
104
|
+
const jsonSchemaToZodShape = (schema) => shapeOf(schema.properties, schema.required);
|
|
93
105
|
exports.jsonSchemaToZodShape = jsonSchemaToZodShape;
|
|
94
106
|
/**
|
|
95
107
|
* Check a value against a declared JSON schema, returning the violations.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The cursor for the next page a JSON result names at its top level, if any.
|
|
3
|
+
* Cut text can lose it, so it is read from the parsed value before cutting.
|
|
4
|
+
*/
|
|
5
|
+
export declare const findNextCursor: (value: unknown) => string | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* `text` within `maxBytes` of UTF-8, or its start with a note that says it was
|
|
8
|
+
* cut. A character split by the cut is dropped rather than shown broken.
|
|
9
|
+
* `next` names the result's own cursor, for "call again with it".
|
|
10
|
+
*/
|
|
11
|
+
export declare const capText: (text: string, maxBytes: number, next?: string) => string;
|
|
12
|
+
export declare class InvalidCursorError extends Error {
|
|
13
|
+
constructor();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* What `list-resources` answers, wherever it runs (the MCP worker, and the
|
|
17
|
+
* channel runner, which lists proxied resources too): one page by uri, how many
|
|
18
|
+
* there are in all, and the cursor for the next page when there is one.
|
|
19
|
+
*/
|
|
20
|
+
export declare const listResourcesPage: (resources: Array<{
|
|
21
|
+
uri: string;
|
|
22
|
+
title?: string | null;
|
|
23
|
+
description?: string | null;
|
|
24
|
+
mimeType?: string | null;
|
|
25
|
+
}>, args: {
|
|
26
|
+
cursor?: unknown;
|
|
27
|
+
limit?: unknown;
|
|
28
|
+
}, limits: {
|
|
29
|
+
defaultLimit: number;
|
|
30
|
+
maxLimit: number;
|
|
31
|
+
}) => string;
|
|
32
|
+
/**
|
|
33
|
+
* One page of `items`, ordered by `keyOf`, starting after the item the cursor
|
|
34
|
+
* names. Keyed rather than counted, so an item added or removed between calls
|
|
35
|
+
* doesn't shift the next page onto ones already seen.
|
|
36
|
+
*/
|
|
37
|
+
export declare const paginate: <T>(items: T[], keyOf: (item: T) => string, options: {
|
|
38
|
+
cursor?: string;
|
|
39
|
+
limit?: number;
|
|
40
|
+
defaultLimit: number;
|
|
41
|
+
maxLimit: number;
|
|
42
|
+
}) => {
|
|
43
|
+
page: T[];
|
|
44
|
+
nextCursor?: string;
|
|
45
|
+
total: number;
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=pagination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAUxD,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,OAAO,GAClB,MAAM,MAAM,EACZ,UAAU,MAAM,EAChB,OAAO,MAAM,KACZ,MAaF,CAAC;AAmCF,qBAAa,kBAAmB,SAAQ,KAAK;;CAO5C;AAED;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAC5B,WAAW,KAAK,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC,EACF,MAAM;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EAC3C,QAAQ;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,KACjD,MAgBF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,EACxB,OAAO,CAAC,EAAE,EACV,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,EAC1B,SAAS;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB,KACA;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CA4CjD,CAAC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Large tool results, in one shape: a list a tool owns is paged by a cursor the
|
|
3
|
+
// model passes back, and text that has to be cut says so, how much was left
|
|
4
|
+
// out, and where to continue when the result itself carried a cursor.
|
|
5
|
+
//
|
|
6
|
+
// Imports nothing, so node --test runs it directly.
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.paginate = exports.listResourcesPage = exports.InvalidCursorError = exports.capText = exports.findNextCursor = void 0;
|
|
9
|
+
// Keys a paged API commonly answers with. Read at the top level only: deeper
|
|
10
|
+
// than that, a key with one of these names is somebody's data.
|
|
11
|
+
const NEXT_CURSOR_KEYS = [
|
|
12
|
+
'nextCursor',
|
|
13
|
+
'next_cursor',
|
|
14
|
+
'nextPageToken',
|
|
15
|
+
'next_page_token',
|
|
16
|
+
'nextPage',
|
|
17
|
+
'next_page',
|
|
18
|
+
'next'
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* The cursor for the next page a JSON result names at its top level, if any.
|
|
22
|
+
* Cut text can lose it, so it is read from the parsed value before cutting.
|
|
23
|
+
*/
|
|
24
|
+
const findNextCursor = (value) => {
|
|
25
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
for (const key of NEXT_CURSOR_KEYS) {
|
|
29
|
+
const found = value[key];
|
|
30
|
+
if (typeof found === 'string' && found)
|
|
31
|
+
return `${key}: ${found}`;
|
|
32
|
+
if (typeof found === 'number')
|
|
33
|
+
return `${key}: ${found}`;
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
};
|
|
37
|
+
exports.findNextCursor = findNextCursor;
|
|
38
|
+
const kb = (bytes) => `${Math.max(1, Math.round(bytes / 1024))} KB`;
|
|
39
|
+
/**
|
|
40
|
+
* `text` within `maxBytes` of UTF-8, or its start with a note that says it was
|
|
41
|
+
* cut. A character split by the cut is dropped rather than shown broken.
|
|
42
|
+
* `next` names the result's own cursor, for "call again with it".
|
|
43
|
+
*/
|
|
44
|
+
const capText = (text, maxBytes, next) => {
|
|
45
|
+
const bytes = new TextEncoder().encode(text);
|
|
46
|
+
if (bytes.byteLength <= maxBytes)
|
|
47
|
+
return text;
|
|
48
|
+
const kept = new TextDecoder()
|
|
49
|
+
.decode(bytes.slice(0, maxBytes))
|
|
50
|
+
.replace(/�+$/, '');
|
|
51
|
+
const continueWith = next
|
|
52
|
+
? ` The result names its next page (${next}): call again with it to continue.`
|
|
53
|
+
: ' To see the rest, call again asking for less — narrower filters, a smaller page or fewer fields.';
|
|
54
|
+
return `${kept}\n\n[Truncated: showing the first ${kb(maxBytes)} of ${kb(bytes.byteLength)}.${continueWith}]`;
|
|
55
|
+
};
|
|
56
|
+
exports.capText = capText;
|
|
57
|
+
// Opaque to the model, so it is passed back as given rather than edited.
|
|
58
|
+
const encodeCursor = (key) => btoa(String.fromCharCode(...new TextEncoder().encode(key)))
|
|
59
|
+
.replace(/\+/g, '-')
|
|
60
|
+
.replace(/\//g, '_')
|
|
61
|
+
.replace(/=+$/, '');
|
|
62
|
+
const decodeCursor = (cursor) => {
|
|
63
|
+
try {
|
|
64
|
+
const base64 = cursor.replace(/-/g, '+').replace(/_/g, '/');
|
|
65
|
+
const binary = atob(base64);
|
|
66
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(Uint8Array.from(binary, char => char.charCodeAt(0)));
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
// Between a cursor's key and the count of items with that key already served.
|
|
73
|
+
// A key is a uri or a name, never a NUL.
|
|
74
|
+
const CURSOR_SEEN_SEPARATOR = '\u0000';
|
|
75
|
+
// A cursor with no count (one issued before the count was added) resumes
|
|
76
|
+
// after every item with its key.
|
|
77
|
+
const splitCursorKey = (decoded) => {
|
|
78
|
+
const at = decoded.lastIndexOf(CURSOR_SEEN_SEPARATOR);
|
|
79
|
+
if (at === -1)
|
|
80
|
+
return { key: decoded, seen: Infinity };
|
|
81
|
+
const count = decoded.slice(at + 1);
|
|
82
|
+
if (!/^\d+$/.test(count))
|
|
83
|
+
throw new InvalidCursorError();
|
|
84
|
+
return { key: decoded.slice(0, at), seen: Number(count) };
|
|
85
|
+
};
|
|
86
|
+
class InvalidCursorError extends Error {
|
|
87
|
+
constructor() {
|
|
88
|
+
super('That cursor is not valid. Call again without a cursor to start from the first page.');
|
|
89
|
+
this.name = 'InvalidCursorError';
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.InvalidCursorError = InvalidCursorError;
|
|
93
|
+
/**
|
|
94
|
+
* What `list-resources` answers, wherever it runs (the MCP worker, and the
|
|
95
|
+
* channel runner, which lists proxied resources too): one page by uri, how many
|
|
96
|
+
* there are in all, and the cursor for the next page when there is one.
|
|
97
|
+
*/
|
|
98
|
+
const listResourcesPage = (resources, args, limits) => {
|
|
99
|
+
const { page, total, nextCursor } = (0, exports.paginate)(resources, r => r.uri, {
|
|
100
|
+
cursor: typeof args.cursor === 'string' ? args.cursor : undefined,
|
|
101
|
+
limit: typeof args.limit === 'number' ? args.limit : undefined,
|
|
102
|
+
...limits
|
|
103
|
+
});
|
|
104
|
+
return JSON.stringify({
|
|
105
|
+
resources: page.map(r => ({
|
|
106
|
+
uri: r.uri,
|
|
107
|
+
title: r.title || undefined,
|
|
108
|
+
description: r.description || undefined,
|
|
109
|
+
mimeType: r.mimeType || undefined
|
|
110
|
+
})),
|
|
111
|
+
total,
|
|
112
|
+
...(nextCursor ? { nextCursor } : {})
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
exports.listResourcesPage = listResourcesPage;
|
|
116
|
+
/**
|
|
117
|
+
* One page of `items`, ordered by `keyOf`, starting after the item the cursor
|
|
118
|
+
* names. Keyed rather than counted, so an item added or removed between calls
|
|
119
|
+
* doesn't shift the next page onto ones already seen.
|
|
120
|
+
*/
|
|
121
|
+
const paginate = (items, keyOf, options) => {
|
|
122
|
+
const limit = Math.min(Math.max(Math.floor(Number(options.limit) || options.defaultLimit), 1), options.maxLimit);
|
|
123
|
+
const sorted = [...items].sort((a, b) => {
|
|
124
|
+
const left = keyOf(a);
|
|
125
|
+
const right = keyOf(b);
|
|
126
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
127
|
+
});
|
|
128
|
+
let start = 0;
|
|
129
|
+
if (options.cursor) {
|
|
130
|
+
const decoded = decodeCursor(options.cursor);
|
|
131
|
+
if (decoded === null)
|
|
132
|
+
throw new InvalidCursorError();
|
|
133
|
+
const { key: after, seen } = splitCursorKey(decoded);
|
|
134
|
+
start = sorted.findIndex(item => keyOf(item) >= after);
|
|
135
|
+
if (start === -1)
|
|
136
|
+
start = sorted.length;
|
|
137
|
+
// Items that share the cursor's key: skip the ones already served, in the
|
|
138
|
+
// order the sort (which is stable) keeps them.
|
|
139
|
+
for (let skipped = 0; start < sorted.length && keyOf(sorted[start]) === after && skipped < seen; skipped++) {
|
|
140
|
+
start++;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const page = sorted.slice(start, start + limit);
|
|
144
|
+
const more = start + limit < sorted.length;
|
|
145
|
+
if (!more || page.length === 0)
|
|
146
|
+
return { page, total: sorted.length };
|
|
147
|
+
// The last key served, and how many items with that key have been served
|
|
148
|
+
// so far, so a run of equal keys split across pages resumes inside the run.
|
|
149
|
+
const end = start + page.length;
|
|
150
|
+
const lastKey = keyOf(page[page.length - 1]);
|
|
151
|
+
let seen = 0;
|
|
152
|
+
for (let i = end - 1; i >= 0 && keyOf(sorted[i]) === lastKey; i--)
|
|
153
|
+
seen++;
|
|
154
|
+
return {
|
|
155
|
+
page,
|
|
156
|
+
total: sorted.length,
|
|
157
|
+
nextCursor: encodeCursor(`${lastKey}${CURSOR_SEEN_SEPARATOR}${seen}`)
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
exports.paginate = paginate;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export interface QueueMessageLike<T> {
|
|
2
2
|
body: T;
|
|
3
|
+
attempts?: number;
|
|
3
4
|
ack: () => void;
|
|
4
5
|
retry: (opts?: {
|
|
5
6
|
delaySeconds?: number;
|
|
@@ -9,9 +10,13 @@ export interface QueueBatchLike<T> {
|
|
|
9
10
|
queue: string;
|
|
10
11
|
messages: readonly QueueMessageLike<T>[];
|
|
11
12
|
}
|
|
13
|
+
export interface QueueFailureContext {
|
|
14
|
+
final: boolean;
|
|
15
|
+
}
|
|
12
16
|
export interface ProcessQueueBatchHandlers<T> {
|
|
13
17
|
process: (body: T) => Promise<void>;
|
|
14
|
-
onError: (error: unknown, body: T, queueName: string) => Promise<void>;
|
|
18
|
+
onError: (error: unknown, body: T, queueName: string, context: QueueFailureContext) => Promise<void>;
|
|
19
|
+
maxRetries?: number;
|
|
15
20
|
}
|
|
16
21
|
export declare const processQueueBatch: <T>(batch: QueueBatchLike<T>, handlers: ProcessQueueBatchHandlers<T>) => Promise<void>;
|
|
17
22
|
//# sourceMappingURL=processQueueBatch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processQueueBatch.d.ts","sourceRoot":"","sources":["../src/processQueueBatch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"processQueueBatch.d.ts","sourceRoot":"","sources":["../src/processQueueBatch.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC;IAER,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACnD;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,mBAAmB;IAIlC,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,EAAE,CACP,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,CAAC,EACP,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,mBAAmB,KACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AASD,eAAO,MAAM,iBAAiB,GAAU,CAAC,EACvC,OAAO,cAAc,CAAC,CAAC,CAAC,EACxB,UAAU,yBAAyB,CAAC,CAAC,CAAC,KACrC,OAAO,CAAC,IAAI,CA4Bd,CAAC"}
|
|
@@ -3,25 +3,38 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.processQueueBatch = void 0;
|
|
4
4
|
const retry_1 = require("./retry");
|
|
5
5
|
const constants_1 = require("./constants");
|
|
6
|
+
const queueFailure_1 = require("./queueFailure");
|
|
7
|
+
const failureKind = (error) => {
|
|
8
|
+
if ((0, queueFailure_1.isPermanentJobError)(error))
|
|
9
|
+
return 'permanent';
|
|
10
|
+
if ((0, retry_1.isTransientInfraError)(error))
|
|
11
|
+
return 'transient';
|
|
12
|
+
if ((0, retry_1.isRateLimitError)(error))
|
|
13
|
+
return 'rateLimit';
|
|
14
|
+
return 'other';
|
|
15
|
+
};
|
|
6
16
|
const processQueueBatch = async (batch, handlers) => {
|
|
17
|
+
const maxRetries = handlers.maxRetries ?? constants_1.constants.QUEUE_MAX_RETRIES;
|
|
7
18
|
for (const message of batch.messages) {
|
|
8
19
|
try {
|
|
9
20
|
await handlers.process(message.body);
|
|
10
21
|
message.ack();
|
|
11
22
|
}
|
|
12
23
|
catch (error) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
const plan = (0, queueFailure_1.planQueueFailure)(failureKind(error), message.attempts, maxRetries);
|
|
25
|
+
if (plan.report) {
|
|
26
|
+
await handlers.onError(error, message.body, batch.queue, {
|
|
27
|
+
final: plan.final
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (plan.action === 'ack') {
|
|
31
|
+
message.ack();
|
|
32
|
+
}
|
|
33
|
+
else if (plan.backoff === 'transient') {
|
|
17
34
|
message.retry({ delaySeconds: constants_1.constants.TRANSIENT_BACKOFF_SECONDS });
|
|
18
|
-
continue;
|
|
19
35
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
message.retry({
|
|
23
|
-
delaySeconds: constants_1.constants.RATE_LIMIT_BACKOFF_SECONDS
|
|
24
|
-
});
|
|
36
|
+
else if (plan.backoff === 'rateLimit') {
|
|
37
|
+
message.retry({ delaySeconds: constants_1.constants.RATE_LIMIT_BACKOFF_SECONDS });
|
|
25
38
|
}
|
|
26
39
|
else {
|
|
27
40
|
message.retry();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare class PermanentJobError extends Error {
|
|
2
|
+
readonly permanent = true;
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
export declare const isPermanentJobError: (error: unknown) => boolean;
|
|
6
|
+
export type QueueFailureKind = 'permanent' | 'transient' | 'rateLimit' | 'other';
|
|
7
|
+
export interface QueueFailurePlan {
|
|
8
|
+
report: boolean;
|
|
9
|
+
final: boolean;
|
|
10
|
+
action: 'ack' | 'retry';
|
|
11
|
+
backoff: 'transient' | 'rateLimit' | null;
|
|
12
|
+
}
|
|
13
|
+
export declare const planQueueFailure: (kind: QueueFailureKind, attempts: number | undefined, maxRetries: number) => QueueFailurePlan;
|
|
14
|
+
//# sourceMappingURL=queueFailure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queueFailure.d.ts","sourceRoot":"","sources":["../src/queueFailure.ts"],"names":[],"mappings":"AASA,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,SAAS,QAAQ;gBAEd,OAAO,EAAE,MAAM;CAI5B;AAED,eAAO,MAAM,mBAAmB,GAAI,OAAO,OAAO,KAAG,OAGE,CAAC;AAExD,MAAM,MAAM,gBAAgB,GACxB,WAAW,GACX,WAAW,GACX,WAAW,GACX,OAAO,CAAC;AAEZ,MAAM,WAAW,gBAAgB;IAE/B,MAAM,EAAE,OAAO,CAAC;IAEhB,KAAK,EAAE,OAAO,CAAC;IAEf,MAAM,EAAE,KAAK,GAAG,OAAO,CAAC;IAExB,OAAO,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI,CAAC;CAC3C;AAID,eAAO,MAAM,gBAAgB,GAC3B,MAAM,gBAAgB,EACtB,UAAU,MAAM,GAAG,SAAS,EAC5B,YAAY,MAAM,KACjB,gBAgBF,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// How a failed queue job is handled: retried, given up on, or reported. Kept
|
|
3
|
+
// apart from processQueueBatch, which applies it, so the decision is testable
|
|
4
|
+
// on its own.
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.planQueueFailure = exports.isPermanentJobError = exports.PermanentJobError = void 0;
|
|
7
|
+
// A failure that no retry can fix — a credential that needs the user to
|
|
8
|
+
// reconnect, a resource that no longer exists. The job is reported once and
|
|
9
|
+
// acknowledged rather than retried into the dead-letter queue. Recognised by
|
|
10
|
+
// its `permanent` flag rather than its class, so an error built by another
|
|
11
|
+
// copy of this module still counts.
|
|
12
|
+
class PermanentJobError extends Error {
|
|
13
|
+
permanent = true;
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = 'PermanentJobError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.PermanentJobError = PermanentJobError;
|
|
20
|
+
const isPermanentJobError = (error) => !!error &&
|
|
21
|
+
typeof error === 'object' &&
|
|
22
|
+
error.permanent === true;
|
|
23
|
+
exports.isPermanentJobError = isPermanentJobError;
|
|
24
|
+
// `attempts` is the queue's own count, 1 on the first delivery; a consumer
|
|
25
|
+
// with `maxRetries` retries gets maxRetries + 1 deliveries in all.
|
|
26
|
+
const planQueueFailure = (kind, attempts, maxRetries) => {
|
|
27
|
+
if (kind === 'permanent') {
|
|
28
|
+
return { report: true, final: true, action: 'ack', backoff: null };
|
|
29
|
+
}
|
|
30
|
+
const final = (attempts ?? 1) > maxRetries;
|
|
31
|
+
if (kind === 'transient') {
|
|
32
|
+
// A platform hiccup is retried quietly; only the last one is worth a
|
|
33
|
+
// report, since nothing will run the job after it.
|
|
34
|
+
return { report: final, final, action: 'retry', backoff: 'transient' };
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
report: true,
|
|
38
|
+
final,
|
|
39
|
+
action: 'retry',
|
|
40
|
+
backoff: kind === 'rateLimit' ? 'rateLimit' : null
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
exports.planQueueFailure = planQueueFailure;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resourceRerank.d.ts","sourceRoot":"","sources":["../src/resourceRerank.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAI1C,MAAM,WAAW,eAAe;IAC9B,GAAG,CACD,KAAK,EAAE,MAAM,EACb,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1E,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB;AAMD;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,GACjC,QAAQ,SAAS,KAEf,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,GAClE,
|
|
1
|
+
{"version":3,"file":"resourceRerank.d.ts","sourceRoot":"","sources":["../src/resourceRerank.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAI1C,MAAM,WAAW,eAAe;IAC9B,GAAG,CACD,KAAK,EAAE,MAAM,EACb,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1E,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB;AAMD;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,GACjC,QAAQ,SAAS,KAEf,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,GAClE,SA6BH,CAAC"}
|
package/dist/resourceRerank.js
CHANGED
|
@@ -20,7 +20,9 @@ const createResourceReranker = (source) => {
|
|
|
20
20
|
contexts: documents.map(text => ({ text })),
|
|
21
21
|
top_k: documents.length
|
|
22
22
|
}));
|
|
23
|
-
|
|
23
|
+
// Filled, not just sized: `some` skips the holes of a bare new Array(n), so
|
|
24
|
+
// a document the response left out would pass the check below unscored.
|
|
25
|
+
const scores = new Array(documents.length).fill(undefined);
|
|
24
26
|
for (const item of result?.response ?? []) {
|
|
25
27
|
if (typeof item.id === 'number' &&
|
|
26
28
|
typeof item.score === 'number' &&
|