@mindstudio-ai/agent 0.1.140 → 0.1.142
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/cli.js +201 -437
- package/dist/index.d.ts +129 -15
- package/dist/index.js +329 -426
- package/dist/index.js.map +1 -1
- package/dist/postinstall.js +201 -437
- package/llms.txt +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -273,7 +273,6 @@ function getOrOpen(url, token) {
|
|
|
273
273
|
pending: /* @__PURE__ */ new Map(),
|
|
274
274
|
chunked: false,
|
|
275
275
|
inbound: /* @__PURE__ */ new Map(),
|
|
276
|
-
acksSeen: false,
|
|
277
276
|
retired: false
|
|
278
277
|
};
|
|
279
278
|
const c = self;
|
|
@@ -297,7 +296,6 @@ function getOrOpen(url, token) {
|
|
|
297
296
|
return;
|
|
298
297
|
}
|
|
299
298
|
if (msg.t === "db-ack") {
|
|
300
|
-
c.acksSeen = true;
|
|
301
299
|
const p = c.pending.get(msg.id);
|
|
302
300
|
if (p && !p.acked) {
|
|
303
301
|
p.acked = true;
|
|
@@ -373,15 +371,11 @@ async function executeDbBatchOverWs(url, token, databaseId, queries) {
|
|
|
373
371
|
}
|
|
374
372
|
return await new Promise((resolve, reject) => {
|
|
375
373
|
const pending = { resolve, reject, timer: null, acked: false };
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}, WS_ACK_TIMEOUT_MS);
|
|
382
|
-
} else {
|
|
383
|
-
armIdleTimer(self, id, pending);
|
|
384
|
-
}
|
|
374
|
+
pending.timer = setTimeout(() => {
|
|
375
|
+
forget(self, id);
|
|
376
|
+
retire(self, "a request went unacknowledged");
|
|
377
|
+
reject(new DbWsTransportError("ws ack timed out", true));
|
|
378
|
+
}, WS_ACK_TIMEOUT_MS);
|
|
385
379
|
self.pending.set(id, pending);
|
|
386
380
|
let started = false;
|
|
387
381
|
let complete = false;
|
|
@@ -3410,7 +3404,15 @@ var DataSource = class {
|
|
|
3410
3404
|
* as the new one is registered, before its build lands; a search in that
|
|
3411
3405
|
* window sees neither. **Throws `mapper_skipped`** (HTTP 422) when the
|
|
3412
3406
|
* mapper skipped the object — a specific thing it refused, which the caller
|
|
3413
|
-
* should see — and `mapper_error` when the mapper threw
|
|
3407
|
+
* should see — and `mapper_error` when the mapper threw, or when none of
|
|
3408
|
+
* its documents passed validation. A document that fails is left out and
|
|
3409
|
+
* reported in {@link AddResult.invalid}; the rest are registered.
|
|
3410
|
+
*
|
|
3411
|
+
* An object that maps to more than a thousand documents (a large export,
|
|
3412
|
+
* streamed out of the mapper as it parses) registers its first thousand
|
|
3413
|
+
* here and returns {@link AddResult.job}, a job that registers and builds
|
|
3414
|
+
* the rest; `documentCount` says how many there are in all. Another job on
|
|
3415
|
+
* the source refuses it with `data_source_busy`.
|
|
3414
3416
|
*/
|
|
3415
3417
|
async add(content, options) {
|
|
3416
3418
|
const bytes = typeof content === "string" ? Buffer.from(content) : Buffer.from(content);
|
|
@@ -3420,6 +3422,7 @@ var DataSource = class {
|
|
|
3420
3422
|
...options.contentType ? { contentType: options.contentType } : {},
|
|
3421
3423
|
...options.metadata !== void 0 ? { metadata: options.metadata } : {},
|
|
3422
3424
|
...options.entities !== void 0 ? { entities: options.entities } : {},
|
|
3425
|
+
...options.budgetDollars !== void 0 ? { budgetDollars: options.budgetDollars } : {},
|
|
3423
3426
|
body: bytes.toString("base64")
|
|
3424
3427
|
});
|
|
3425
3428
|
}
|
|
@@ -3631,6 +3634,15 @@ var DataSource = class {
|
|
|
3631
3634
|
...name ? { name } : {}
|
|
3632
3635
|
});
|
|
3633
3636
|
}
|
|
3637
|
+
/**
|
|
3638
|
+
* @internal A mapper frame's grant to store the next part of its spill: how
|
|
3639
|
+
* `defineMapper`'s executor hands the platform an object's documents a part
|
|
3640
|
+
* at a time once they outgrow the frame's record. Only a mapper frame's
|
|
3641
|
+
* token is granted one.
|
|
3642
|
+
*/
|
|
3643
|
+
async _mapSpillGrant(spillId) {
|
|
3644
|
+
return this._call("map/spill", { slug: this._slug, spillId });
|
|
3645
|
+
}
|
|
3634
3646
|
/**
|
|
3635
3647
|
* @internal Content hash of some bytes, matching what the server computes.
|
|
3636
3648
|
* Exposed for callers that want to check whether they already added a file.
|
|
@@ -3781,7 +3793,7 @@ function createEvents(call) {
|
|
|
3781
3793
|
};
|
|
3782
3794
|
}
|
|
3783
3795
|
|
|
3784
|
-
// src/task/
|
|
3796
|
+
// src/task/local.ts
|
|
3785
3797
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
3786
3798
|
|
|
3787
3799
|
// src/generated/metadata.ts
|
|
@@ -4926,6 +4938,51 @@ var stepMetadata = {
|
|
|
4926
4938
|
}
|
|
4927
4939
|
};
|
|
4928
4940
|
|
|
4941
|
+
// src/task/index.ts
|
|
4942
|
+
function resolveStepType(name) {
|
|
4943
|
+
const meta = stepMetadata[name];
|
|
4944
|
+
return meta ? meta.stepType : name;
|
|
4945
|
+
}
|
|
4946
|
+
function mapTools(tools) {
|
|
4947
|
+
return tools.map((t) => {
|
|
4948
|
+
if (typeof t === "object" && "execute" in t) {
|
|
4949
|
+
return {
|
|
4950
|
+
name: t.name,
|
|
4951
|
+
description: t.description,
|
|
4952
|
+
inputSchema: t.inputSchema ?? { type: "object", properties: {} }
|
|
4953
|
+
};
|
|
4954
|
+
}
|
|
4955
|
+
if (typeof t === "object" && "appMethod" in t) {
|
|
4956
|
+
return {
|
|
4957
|
+
appMethod: t.appMethod,
|
|
4958
|
+
...t.description ? { description: t.description } : {},
|
|
4959
|
+
...t.defaults ? { defaults: t.defaults } : {}
|
|
4960
|
+
};
|
|
4961
|
+
}
|
|
4962
|
+
const method = typeof t === "string" ? t : t.method;
|
|
4963
|
+
const stepType = resolveStepType(method);
|
|
4964
|
+
const defaults = typeof t === "object" ? t.defaults : void 0;
|
|
4965
|
+
return defaults ? { stepType, defaults } : { stepType };
|
|
4966
|
+
});
|
|
4967
|
+
}
|
|
4968
|
+
function sleep2(ms) {
|
|
4969
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4970
|
+
}
|
|
4971
|
+
function isDevMode() {
|
|
4972
|
+
return !!(process.env.CALLBACK_TOKEN || getRequestContext()?.callbackToken);
|
|
4973
|
+
}
|
|
4974
|
+
function logTaskResult(result) {
|
|
4975
|
+
if (!isDevMode()) {
|
|
4976
|
+
return;
|
|
4977
|
+
}
|
|
4978
|
+
const toolSummary = result.toolCalls.map(
|
|
4979
|
+
(tc) => `${tc.name} (${tc.durationMs}ms) ${tc.success ? "\u2713" : "\u2717"}` + (tc.truncated ? " \u26A0 result cut" : "")
|
|
4980
|
+
).join(", ");
|
|
4981
|
+
console.log(
|
|
4982
|
+
`[task] ${result.turns} turn${result.turns === 1 ? "" : "s"}` + (toolSummary ? `: ${toolSummary}` : "") + (result.hitMaxTurns ? " | \u26A0 ran out of turns" : "") + (result.stopReason === "max_tokens" ? " | \u26A0 answer cut at the output limit" : "") + ` | ${result.parsedSuccessfully ? "output OK" : "\u26A0 output not valid JSON"} | cost: ${result.usage.totalBillingCost} | trace: ${result.traceId}`
|
|
4983
|
+
);
|
|
4984
|
+
}
|
|
4985
|
+
|
|
4929
4986
|
// src/task/schema.ts
|
|
4930
4987
|
function describe(value) {
|
|
4931
4988
|
if (value === void 0) {
|
|
@@ -5066,38 +5123,6 @@ function assertSupportedNode(schema, path) {
|
|
|
5066
5123
|
assertSupportedNode(schema.items, `${path}[]`);
|
|
5067
5124
|
}
|
|
5068
5125
|
}
|
|
5069
|
-
function buildExampleFromSchema(schema) {
|
|
5070
|
-
if (schema.const !== void 0) {
|
|
5071
|
-
return schema.const;
|
|
5072
|
-
}
|
|
5073
|
-
if (schema.enum !== void 0 && schema.enum.length > 0) {
|
|
5074
|
-
return schema.enum[0];
|
|
5075
|
-
}
|
|
5076
|
-
const names = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
|
|
5077
|
-
const name = names.find((n) => n !== "null") ?? names[0];
|
|
5078
|
-
switch (name) {
|
|
5079
|
-
case "object": {
|
|
5080
|
-
const example = {};
|
|
5081
|
-
for (const [key, propSchema] of Object.entries(schema.properties ?? {})) {
|
|
5082
|
-
example[key] = buildExampleFromSchema(propSchema);
|
|
5083
|
-
}
|
|
5084
|
-
return example;
|
|
5085
|
-
}
|
|
5086
|
-
case "array":
|
|
5087
|
-
return schema.items ? [buildExampleFromSchema(schema.items)] : [];
|
|
5088
|
-
case "string":
|
|
5089
|
-
return "...";
|
|
5090
|
-
case "number":
|
|
5091
|
-
case "integer":
|
|
5092
|
-
return 0;
|
|
5093
|
-
case "boolean":
|
|
5094
|
-
return true;
|
|
5095
|
-
case "null":
|
|
5096
|
-
return null;
|
|
5097
|
-
default:
|
|
5098
|
-
return null;
|
|
5099
|
-
}
|
|
5100
|
-
}
|
|
5101
5126
|
function stripCodeFences(text) {
|
|
5102
5127
|
const match = /^```[a-zA-Z]*[ \t]*\r?\n([\s\S]*?)\r?\n?```$/.exec(
|
|
5103
5128
|
text.trim()
|
|
@@ -5105,262 +5130,7 @@ function stripCodeFences(text) {
|
|
|
5105
5130
|
return match ? match[1] : text;
|
|
5106
5131
|
}
|
|
5107
5132
|
|
|
5108
|
-
// src/task/index.ts
|
|
5109
|
-
function resolveStepType(name) {
|
|
5110
|
-
const meta = stepMetadata[name];
|
|
5111
|
-
return meta ? meta.stepType : name;
|
|
5112
|
-
}
|
|
5113
|
-
function mapTools(tools) {
|
|
5114
|
-
return tools.map((t) => {
|
|
5115
|
-
if (typeof t === "object" && "execute" in t) {
|
|
5116
|
-
return {
|
|
5117
|
-
name: t.name,
|
|
5118
|
-
description: t.description,
|
|
5119
|
-
inputSchema: t.inputSchema ?? { type: "object", properties: {} }
|
|
5120
|
-
};
|
|
5121
|
-
}
|
|
5122
|
-
if (typeof t === "object" && "appMethod" in t) {
|
|
5123
|
-
return {
|
|
5124
|
-
appMethod: t.appMethod,
|
|
5125
|
-
...t.description ? { description: t.description } : {},
|
|
5126
|
-
...t.defaults ? { defaults: t.defaults } : {}
|
|
5127
|
-
};
|
|
5128
|
-
}
|
|
5129
|
-
const method = typeof t === "string" ? t : t.method;
|
|
5130
|
-
const stepType = resolveStepType(method);
|
|
5131
|
-
const defaults = typeof t === "object" ? t.defaults : void 0;
|
|
5132
|
-
return defaults ? { stepType, defaults } : { stepType };
|
|
5133
|
-
});
|
|
5134
|
-
}
|
|
5135
|
-
function buildTaskRequestBody(options) {
|
|
5136
|
-
return {
|
|
5137
|
-
prompt: options.prompt,
|
|
5138
|
-
input: options.input,
|
|
5139
|
-
tools: mapTools(options.tools),
|
|
5140
|
-
// The legacy whole-task route requires structuredOutputExample and
|
|
5141
|
-
// composes its own prompt server-side, so in schema mode we synthesize a
|
|
5142
|
-
// skeleton example from the schema. Validation still happens client-side
|
|
5143
|
-
// after the result comes back (see _runTaskInner).
|
|
5144
|
-
structuredOutputExample: options.outputSchema ? JSON.stringify(buildExampleFromSchema(options.outputSchema)) : typeof options.structuredOutputExample === "string" ? options.structuredOutputExample : JSON.stringify(options.structuredOutputExample),
|
|
5145
|
-
model: options.model,
|
|
5146
|
-
...options.maxTurns != null && { maxTurns: options.maxTurns },
|
|
5147
|
-
...options.appId != null && { appId: options.appId },
|
|
5148
|
-
...options.threadId != null && { threadId: options.threadId }
|
|
5149
|
-
};
|
|
5150
|
-
}
|
|
5151
|
-
function sleep2(ms) {
|
|
5152
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5153
|
-
}
|
|
5154
|
-
function isDevMode() {
|
|
5155
|
-
return !!(process.env.CALLBACK_TOKEN || getRequestContext()?.callbackToken);
|
|
5156
|
-
}
|
|
5157
|
-
function logTaskResult(result) {
|
|
5158
|
-
if (!isDevMode()) {
|
|
5159
|
-
return;
|
|
5160
|
-
}
|
|
5161
|
-
const toolSummary = result.toolCalls.map((tc) => `${tc.name} (${tc.durationMs}ms) ${tc.success ? "\u2713" : "\u2717"}`).join(", ");
|
|
5162
|
-
console.log(
|
|
5163
|
-
`[task] ${result.turns} turn${result.turns === 1 ? "" : "s"}` + (toolSummary ? `: ${toolSummary}` : "") + ` | ${result.parsedSuccessfully ? "output OK" : "\u26A0 output not valid JSON"} | cost: ${result.usage.totalBillingCost} | trace: ${result.traceId}`
|
|
5164
|
-
);
|
|
5165
|
-
}
|
|
5166
|
-
async function runTaskPoll(httpConfig, body) {
|
|
5167
|
-
const traceId = randomUUID2();
|
|
5168
|
-
const { data } = await request(
|
|
5169
|
-
httpConfig,
|
|
5170
|
-
"POST",
|
|
5171
|
-
"/task",
|
|
5172
|
-
body
|
|
5173
|
-
);
|
|
5174
|
-
const pollUrl = `${httpConfig.baseUrl}/developer/v2/task/poll/${data.taskToken}`;
|
|
5175
|
-
let pollDelay = 300;
|
|
5176
|
-
while (true) {
|
|
5177
|
-
await sleep2(pollDelay);
|
|
5178
|
-
pollDelay = Math.min(pollDelay * 1.5, 3e3);
|
|
5179
|
-
const res = await fetch(pollUrl, {
|
|
5180
|
-
headers: { "User-Agent": "@mindstudio-ai/agent" }
|
|
5181
|
-
});
|
|
5182
|
-
if (res.status === 502 || res.status === 503 || res.status === 504) {
|
|
5183
|
-
continue;
|
|
5184
|
-
}
|
|
5185
|
-
if (res.status === 404) {
|
|
5186
|
-
throw new MindStudioError(
|
|
5187
|
-
"Task poll token not found or expired.",
|
|
5188
|
-
"poll_token_expired",
|
|
5189
|
-
404
|
|
5190
|
-
);
|
|
5191
|
-
}
|
|
5192
|
-
if (!res.ok) {
|
|
5193
|
-
const errorBody = await res.json().catch(() => ({}));
|
|
5194
|
-
throw new MindStudioError(
|
|
5195
|
-
errorBody.message ?? errorBody.error ?? `Task poll failed: ${res.status} ${res.statusText}`,
|
|
5196
|
-
errorCodeFrom(errorBody, "poll_error"),
|
|
5197
|
-
res.status,
|
|
5198
|
-
errorBody
|
|
5199
|
-
);
|
|
5200
|
-
}
|
|
5201
|
-
const poll = await res.json();
|
|
5202
|
-
if (poll.status === "pending") {
|
|
5203
|
-
if (isDevMode() && poll.currentTurn != null) {
|
|
5204
|
-
console.log(
|
|
5205
|
-
`[task] running... turn ${poll.currentTurn}/${poll.maxTurns ?? "?"}`
|
|
5206
|
-
);
|
|
5207
|
-
}
|
|
5208
|
-
continue;
|
|
5209
|
-
}
|
|
5210
|
-
if (poll.status === "error") {
|
|
5211
|
-
throw new MindStudioError(
|
|
5212
|
-
poll.error ?? "Task execution failed.",
|
|
5213
|
-
"task_execution_error",
|
|
5214
|
-
500
|
|
5215
|
-
);
|
|
5216
|
-
}
|
|
5217
|
-
const result = {
|
|
5218
|
-
output: poll.output,
|
|
5219
|
-
outputRaw: poll.outputRaw ?? "",
|
|
5220
|
-
parsedSuccessfully: poll.parsedSuccessfully ?? true,
|
|
5221
|
-
turns: poll.turns ?? 0,
|
|
5222
|
-
usage: poll.usage ?? {
|
|
5223
|
-
inputTokens: 0,
|
|
5224
|
-
outputTokens: 0,
|
|
5225
|
-
totalBillingCost: 0
|
|
5226
|
-
},
|
|
5227
|
-
toolCalls: poll.toolCalls ?? [],
|
|
5228
|
-
traceId
|
|
5229
|
-
};
|
|
5230
|
-
logTaskResult(result);
|
|
5231
|
-
return result;
|
|
5232
|
-
}
|
|
5233
|
-
}
|
|
5234
|
-
async function runTaskStream(httpConfig, body, onEvent) {
|
|
5235
|
-
const traceId = randomUUID2();
|
|
5236
|
-
const url = `${httpConfig.baseUrl}/developer/v2/task`;
|
|
5237
|
-
const res = await fetch(url, {
|
|
5238
|
-
method: "POST",
|
|
5239
|
-
headers: {
|
|
5240
|
-
Authorization: `Bearer ${httpConfig.token}`,
|
|
5241
|
-
"Content-Type": "application/json",
|
|
5242
|
-
"User-Agent": "@mindstudio-ai/agent",
|
|
5243
|
-
Accept: "text/event-stream"
|
|
5244
|
-
},
|
|
5245
|
-
body: JSON.stringify(body)
|
|
5246
|
-
});
|
|
5247
|
-
if (!res.ok) {
|
|
5248
|
-
let message = `${res.status} ${res.statusText}`;
|
|
5249
|
-
let code = "api_error";
|
|
5250
|
-
let details;
|
|
5251
|
-
try {
|
|
5252
|
-
const text = await res.text();
|
|
5253
|
-
try {
|
|
5254
|
-
const errBody = JSON.parse(text);
|
|
5255
|
-
details = errBody;
|
|
5256
|
-
const errMsg = (typeof errBody.error === "string" ? errBody.error : void 0) ?? (typeof errBody.message === "string" ? errBody.message : void 0);
|
|
5257
|
-
if (errMsg) {
|
|
5258
|
-
message = errMsg;
|
|
5259
|
-
}
|
|
5260
|
-
code = errorCodeFrom(errBody, code);
|
|
5261
|
-
} catch {
|
|
5262
|
-
const stripped = text.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
|
|
5263
|
-
if (stripped) {
|
|
5264
|
-
message = stripped.slice(0, 200);
|
|
5265
|
-
}
|
|
5266
|
-
}
|
|
5267
|
-
} catch {
|
|
5268
|
-
}
|
|
5269
|
-
throw new MindStudioError(`[task] ${message}`, code, res.status, details);
|
|
5270
|
-
}
|
|
5271
|
-
const reader = res.body.getReader();
|
|
5272
|
-
const decoder = new TextDecoder();
|
|
5273
|
-
let buffer = "";
|
|
5274
|
-
let result = null;
|
|
5275
|
-
while (true) {
|
|
5276
|
-
const { done, value } = await reader.read();
|
|
5277
|
-
if (done) {
|
|
5278
|
-
break;
|
|
5279
|
-
}
|
|
5280
|
-
buffer += decoder.decode(value, { stream: true });
|
|
5281
|
-
const lines = buffer.split("\n");
|
|
5282
|
-
buffer = lines.pop() ?? "";
|
|
5283
|
-
for (const line of lines) {
|
|
5284
|
-
if (!line.startsWith("data: ")) {
|
|
5285
|
-
continue;
|
|
5286
|
-
}
|
|
5287
|
-
try {
|
|
5288
|
-
const event = JSON.parse(line.slice(6));
|
|
5289
|
-
onEvent(event);
|
|
5290
|
-
if (event.type === "error") {
|
|
5291
|
-
throw new MindStudioError(
|
|
5292
|
-
event.error ?? "Task execution failed.",
|
|
5293
|
-
"task_execution_error",
|
|
5294
|
-
500
|
|
5295
|
-
);
|
|
5296
|
-
}
|
|
5297
|
-
if (event.type === "done") {
|
|
5298
|
-
result = {
|
|
5299
|
-
output: event.output,
|
|
5300
|
-
outputRaw: event.outputRaw ?? "",
|
|
5301
|
-
parsedSuccessfully: event.parsedSuccessfully ?? true,
|
|
5302
|
-
turns: event.turns ?? 0,
|
|
5303
|
-
usage: event.usage ?? {
|
|
5304
|
-
inputTokens: 0,
|
|
5305
|
-
outputTokens: 0,
|
|
5306
|
-
totalBillingCost: 0
|
|
5307
|
-
},
|
|
5308
|
-
toolCalls: event.toolCalls ?? [],
|
|
5309
|
-
traceId
|
|
5310
|
-
};
|
|
5311
|
-
}
|
|
5312
|
-
} catch (err) {
|
|
5313
|
-
if (err instanceof MindStudioError) {
|
|
5314
|
-
throw err;
|
|
5315
|
-
}
|
|
5316
|
-
}
|
|
5317
|
-
}
|
|
5318
|
-
}
|
|
5319
|
-
if (buffer.startsWith("data: ")) {
|
|
5320
|
-
try {
|
|
5321
|
-
const event = JSON.parse(buffer.slice(6));
|
|
5322
|
-
onEvent(event);
|
|
5323
|
-
if (event.type === "error") {
|
|
5324
|
-
throw new MindStudioError(
|
|
5325
|
-
event.error ?? "Task execution failed.",
|
|
5326
|
-
"task_execution_error",
|
|
5327
|
-
500
|
|
5328
|
-
);
|
|
5329
|
-
}
|
|
5330
|
-
if (event.type === "done") {
|
|
5331
|
-
result = {
|
|
5332
|
-
output: event.output,
|
|
5333
|
-
outputRaw: event.outputRaw ?? "",
|
|
5334
|
-
parsedSuccessfully: event.parsedSuccessfully ?? true,
|
|
5335
|
-
turns: event.turns ?? 0,
|
|
5336
|
-
usage: event.usage ?? {
|
|
5337
|
-
inputTokens: 0,
|
|
5338
|
-
outputTokens: 0,
|
|
5339
|
-
totalBillingCost: 0
|
|
5340
|
-
},
|
|
5341
|
-
toolCalls: event.toolCalls ?? [],
|
|
5342
|
-
traceId
|
|
5343
|
-
};
|
|
5344
|
-
}
|
|
5345
|
-
} catch (err) {
|
|
5346
|
-
if (err instanceof MindStudioError) {
|
|
5347
|
-
throw err;
|
|
5348
|
-
}
|
|
5349
|
-
}
|
|
5350
|
-
}
|
|
5351
|
-
if (!result) {
|
|
5352
|
-
throw new MindStudioError(
|
|
5353
|
-
"[task] Stream ended without a done event. The task execution may have been interrupted.",
|
|
5354
|
-
"stream_error",
|
|
5355
|
-
500
|
|
5356
|
-
);
|
|
5357
|
-
}
|
|
5358
|
-
logTaskResult(result);
|
|
5359
|
-
return result;
|
|
5360
|
-
}
|
|
5361
|
-
|
|
5362
5133
|
// src/task/local.ts
|
|
5363
|
-
import { randomUUID as randomUUID3 } from "crypto";
|
|
5364
5134
|
var DEFAULT_MAX_TURNS = 20;
|
|
5365
5135
|
var MAX_TURNS_LIMIT = 100;
|
|
5366
5136
|
var MAX_SCHEMA_REPAIR_ATTEMPTS = 3;
|
|
@@ -5368,7 +5138,6 @@ var MAX_TOOL_OUTPUT_CHARS = 5e4;
|
|
|
5368
5138
|
var MAX_TURN_ATTEMPTS = 5;
|
|
5369
5139
|
var INITIAL_BACKOFF_MS = 1e3;
|
|
5370
5140
|
var STALL_TIMEOUT_MS = 3e5;
|
|
5371
|
-
var TURN_UNAVAILABLE_CODE = "task_turn_unavailable";
|
|
5372
5141
|
var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
5373
5142
|
function isPlainObject(value) {
|
|
5374
5143
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
@@ -5388,9 +5157,20 @@ function mergeToolInput(modelInput, defaults) {
|
|
|
5388
5157
|
}
|
|
5389
5158
|
return merged;
|
|
5390
5159
|
}
|
|
5391
|
-
function truncateToolOutput(output) {
|
|
5160
|
+
function truncateToolOutput(output, maxChars) {
|
|
5392
5161
|
const serialized = JSON.stringify(output);
|
|
5393
|
-
|
|
5162
|
+
if (!serialized || serialized.length <= maxChars) {
|
|
5163
|
+
return { output, truncated: false };
|
|
5164
|
+
}
|
|
5165
|
+
return {
|
|
5166
|
+
output: {
|
|
5167
|
+
truncated: true,
|
|
5168
|
+
totalChars: serialized.length,
|
|
5169
|
+
shownChars: maxChars,
|
|
5170
|
+
content: serialized.slice(0, maxChars)
|
|
5171
|
+
},
|
|
5172
|
+
truncated: true
|
|
5173
|
+
};
|
|
5394
5174
|
}
|
|
5395
5175
|
var TurnError = class extends Error {
|
|
5396
5176
|
constructor(message, retryable, phase, status, errorCode) {
|
|
@@ -5614,7 +5394,8 @@ ${structuredOutputExample}
|
|
|
5614
5394
|
Math.max(options.maxTurns || DEFAULT_MAX_TURNS, 1),
|
|
5615
5395
|
MAX_TURNS_LIMIT
|
|
5616
5396
|
);
|
|
5617
|
-
const
|
|
5397
|
+
const maxToolOutputChars = options.maxToolOutputChars ?? MAX_TOOL_OUTPUT_CHARS;
|
|
5398
|
+
const traceId = randomUUID2();
|
|
5618
5399
|
const messages = [
|
|
5619
5400
|
{ role: "user", content: JSON.stringify(options.input) }
|
|
5620
5401
|
];
|
|
@@ -5628,11 +5409,13 @@ ${structuredOutputExample}
|
|
|
5628
5409
|
cacheReadTokens: 0,
|
|
5629
5410
|
totalBillingCost: 0
|
|
5630
5411
|
};
|
|
5631
|
-
const buildResult = (output2, outputRaw, parsedSuccessfully2, turns) => ({
|
|
5412
|
+
const buildResult = (output2, outputRaw, parsedSuccessfully2, turns, stopReason, hitMaxTurns = false) => ({
|
|
5632
5413
|
output: output2,
|
|
5633
5414
|
outputRaw,
|
|
5634
5415
|
parsedSuccessfully: parsedSuccessfully2,
|
|
5635
5416
|
turns,
|
|
5417
|
+
hitMaxTurns,
|
|
5418
|
+
stopReason,
|
|
5636
5419
|
usage: totalUsage,
|
|
5637
5420
|
toolCalls: toolCallLog,
|
|
5638
5421
|
traceId
|
|
@@ -5690,7 +5473,7 @@ ${structuredOutputExample}
|
|
|
5690
5473
|
}
|
|
5691
5474
|
);
|
|
5692
5475
|
}
|
|
5693
|
-
return finish(buildResult(null, "", false, loopCount));
|
|
5476
|
+
return finish(buildResult(null, "", false, loopCount, null));
|
|
5694
5477
|
}
|
|
5695
5478
|
if (err instanceof TurnError) {
|
|
5696
5479
|
throw new MindStudioError(
|
|
@@ -5714,13 +5497,6 @@ ${structuredOutputExample}
|
|
|
5714
5497
|
traceId
|
|
5715
5498
|
});
|
|
5716
5499
|
} catch (err) {
|
|
5717
|
-
if (loopCount === 1 && err instanceof TurnError && err.status === 404 && err.errorCode === "not_found") {
|
|
5718
|
-
throw new MindStudioError(
|
|
5719
|
-
"Task turn endpoint unavailable.",
|
|
5720
|
-
TURN_UNAVAILABLE_CODE,
|
|
5721
|
-
404
|
|
5722
|
-
);
|
|
5723
|
-
}
|
|
5724
5500
|
return turnFailure(err);
|
|
5725
5501
|
}
|
|
5726
5502
|
accumulate(turn);
|
|
@@ -5744,11 +5520,11 @@ ${structuredOutputExample}
|
|
|
5744
5520
|
let result;
|
|
5745
5521
|
if (kind === "function") {
|
|
5746
5522
|
try {
|
|
5747
|
-
const
|
|
5523
|
+
const output4 = await functionTools.get(toolCall.name)(
|
|
5748
5524
|
mergedInput
|
|
5749
5525
|
);
|
|
5750
5526
|
result = {
|
|
5751
|
-
output:
|
|
5527
|
+
output: output4 ?? null,
|
|
5752
5528
|
billingCost: 0,
|
|
5753
5529
|
isError: false
|
|
5754
5530
|
};
|
|
@@ -5769,29 +5545,40 @@ ${structuredOutputExample}
|
|
|
5769
5545
|
} else {
|
|
5770
5546
|
result = await deps.executeStepTool(toolCall.name, mergedInput);
|
|
5771
5547
|
}
|
|
5548
|
+
const { output: output3, truncated } = truncateToolOutput(
|
|
5549
|
+
result.output,
|
|
5550
|
+
maxToolOutputChars
|
|
5551
|
+
);
|
|
5772
5552
|
toolCallLog.push({
|
|
5773
5553
|
name: toolCall.name,
|
|
5774
5554
|
success: !result.isError,
|
|
5775
|
-
durationMs: Date.now() - startTime
|
|
5555
|
+
durationMs: Date.now() - startTime,
|
|
5556
|
+
truncated
|
|
5776
5557
|
});
|
|
5777
|
-
return { toolCall, ...result };
|
|
5558
|
+
return { toolCall, ...result, output: output3, truncated };
|
|
5778
5559
|
})
|
|
5779
5560
|
);
|
|
5780
|
-
for (const {
|
|
5561
|
+
for (const {
|
|
5562
|
+
toolCall,
|
|
5563
|
+
output: output3,
|
|
5564
|
+
truncated,
|
|
5565
|
+
billingCost,
|
|
5566
|
+
isError
|
|
5567
|
+
} of results) {
|
|
5781
5568
|
if (billingCost) {
|
|
5782
5569
|
totalUsage.totalBillingCost += billingCost;
|
|
5783
5570
|
}
|
|
5784
|
-
const truncated = truncateToolOutput(output3);
|
|
5785
5571
|
messages.push({
|
|
5786
5572
|
role: "user",
|
|
5787
|
-
content: JSON.stringify(
|
|
5573
|
+
content: JSON.stringify(output3),
|
|
5788
5574
|
toolCallId: toolCall.id,
|
|
5789
5575
|
...isError && { isToolError: true }
|
|
5790
5576
|
});
|
|
5791
5577
|
onEvent?.({
|
|
5792
5578
|
type: "tool_call_result",
|
|
5793
5579
|
id: toolCall.id,
|
|
5794
|
-
output:
|
|
5580
|
+
output: output3,
|
|
5581
|
+
...truncated && { truncated: true }
|
|
5795
5582
|
});
|
|
5796
5583
|
}
|
|
5797
5584
|
if (isDevMode()) {
|
|
@@ -5811,11 +5598,15 @@ ${structuredOutputExample}
|
|
|
5811
5598
|
}
|
|
5812
5599
|
if (parseOk) {
|
|
5813
5600
|
if (!outputSchema) {
|
|
5814
|
-
return finish(
|
|
5601
|
+
return finish(
|
|
5602
|
+
buildResult(output2, turn.text, true, loopCount, turn.stopReason)
|
|
5603
|
+
);
|
|
5815
5604
|
}
|
|
5816
5605
|
const errors = validateAgainstSchema(output2, outputSchema);
|
|
5817
5606
|
if (errors.length === 0) {
|
|
5818
|
-
return finish(
|
|
5607
|
+
return finish(
|
|
5608
|
+
buildResult(output2, turn.text, true, loopCount, turn.stopReason)
|
|
5609
|
+
);
|
|
5819
5610
|
}
|
|
5820
5611
|
if (loopCount < maxTurns && schemaRepairCount < MAX_SCHEMA_REPAIR_ATTEMPTS) {
|
|
5821
5612
|
schemaRepairCount++;
|
|
@@ -5840,13 +5631,16 @@ ${formatValidationErrors(errors)}`
|
|
|
5840
5631
|
{ path: "$", message: "output was not valid JSON" }
|
|
5841
5632
|
]);
|
|
5842
5633
|
}
|
|
5843
|
-
return finish(
|
|
5634
|
+
return finish(
|
|
5635
|
+
buildResult(turn.text, turn.text, false, loopCount, turn.stopReason)
|
|
5636
|
+
);
|
|
5844
5637
|
}
|
|
5845
5638
|
messages.push({
|
|
5846
5639
|
role: "user",
|
|
5847
5640
|
content: "You have reached the maximum number of turns. Please provide your final output now as JSON."
|
|
5848
5641
|
});
|
|
5849
5642
|
let finalText = "";
|
|
5643
|
+
let finalStopReason = null;
|
|
5850
5644
|
try {
|
|
5851
5645
|
const turn = await runTurnWithRetry(httpConfig, {
|
|
5852
5646
|
model: options.model,
|
|
@@ -5857,6 +5651,7 @@ ${formatValidationErrors(errors)}`
|
|
|
5857
5651
|
});
|
|
5858
5652
|
accumulate(turn);
|
|
5859
5653
|
finalText = turn.text;
|
|
5654
|
+
finalStopReason = turn.stopReason;
|
|
5860
5655
|
} catch (err) {
|
|
5861
5656
|
if (err instanceof TurnError && err.phase === "model") {
|
|
5862
5657
|
if (isDevMode()) {
|
|
@@ -5886,7 +5681,14 @@ ${formatValidationErrors(errors)}`
|
|
|
5886
5681
|
}
|
|
5887
5682
|
}
|
|
5888
5683
|
return finish(
|
|
5889
|
-
buildResult(
|
|
5684
|
+
buildResult(
|
|
5685
|
+
output,
|
|
5686
|
+
finalText,
|
|
5687
|
+
parsedSuccessfully,
|
|
5688
|
+
loopCount + 1,
|
|
5689
|
+
finalStopReason,
|
|
5690
|
+
true
|
|
5691
|
+
)
|
|
5890
5692
|
);
|
|
5891
5693
|
}
|
|
5892
5694
|
|
|
@@ -6945,108 +6747,75 @@ var MindStudioAgent = class {
|
|
|
6945
6747
|
}
|
|
6946
6748
|
async _runTaskInner(options) {
|
|
6947
6749
|
const httpConfig = this._currentHttpConfig;
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
)
|
|
6962
|
-
|
|
6963
|
-
billingCost = value;
|
|
6964
|
-
}
|
|
6965
|
-
if (!key.startsWith("$")) {
|
|
6966
|
-
output[key] = value;
|
|
6967
|
-
}
|
|
6750
|
+
return runTaskLocal(
|
|
6751
|
+
{
|
|
6752
|
+
httpConfig,
|
|
6753
|
+
executeStepTool: async (stepType, input) => {
|
|
6754
|
+
try {
|
|
6755
|
+
const result = await this.executeStep(stepType, input, {
|
|
6756
|
+
requestSource: "v2-task"
|
|
6757
|
+
});
|
|
6758
|
+
const output = {};
|
|
6759
|
+
let billingCost = 0;
|
|
6760
|
+
for (const [key, value] of Object.entries(
|
|
6761
|
+
result
|
|
6762
|
+
)) {
|
|
6763
|
+
if (key === "$billingCost" && typeof value === "number") {
|
|
6764
|
+
billingCost = value;
|
|
6968
6765
|
}
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
return {
|
|
6972
|
-
output: {
|
|
6973
|
-
error: err instanceof Error ? err.message : "Step execution failed"
|
|
6974
|
-
},
|
|
6975
|
-
billingCost: 0,
|
|
6976
|
-
isError: true
|
|
6977
|
-
};
|
|
6978
|
-
}
|
|
6979
|
-
},
|
|
6980
|
-
executeMethodTool: async (methodId, input, call) => {
|
|
6981
|
-
try {
|
|
6982
|
-
const { data } = await request(
|
|
6983
|
-
{ ...httpConfig, maxRetries: 0 },
|
|
6984
|
-
"POST",
|
|
6985
|
-
"/task/invoke-method",
|
|
6986
|
-
{
|
|
6987
|
-
methodId,
|
|
6988
|
-
input,
|
|
6989
|
-
traceId: call.traceId,
|
|
6990
|
-
toolCallId: call.toolCallId
|
|
6991
|
-
}
|
|
6992
|
-
);
|
|
6993
|
-
if (data.error) {
|
|
6994
|
-
return {
|
|
6995
|
-
output: { error: data.error },
|
|
6996
|
-
billingCost: 0,
|
|
6997
|
-
isError: true
|
|
6998
|
-
};
|
|
6766
|
+
if (!key.startsWith("$")) {
|
|
6767
|
+
output[key] = value;
|
|
6999
6768
|
}
|
|
7000
|
-
return {
|
|
7001
|
-
output: data.output ?? null,
|
|
7002
|
-
billingCost: 0,
|
|
7003
|
-
isError: false
|
|
7004
|
-
};
|
|
7005
|
-
} catch (err) {
|
|
7006
|
-
return {
|
|
7007
|
-
output: {
|
|
7008
|
-
error: err instanceof Error ? err.message : "Method execution failed"
|
|
7009
|
-
},
|
|
7010
|
-
billingCost: 0,
|
|
7011
|
-
isError: true
|
|
7012
|
-
};
|
|
7013
6769
|
}
|
|
6770
|
+
return { output, billingCost, isError: false };
|
|
6771
|
+
} catch (err) {
|
|
6772
|
+
return {
|
|
6773
|
+
output: {
|
|
6774
|
+
error: err instanceof Error ? err.message : "Step execution failed"
|
|
6775
|
+
},
|
|
6776
|
+
billingCost: 0,
|
|
6777
|
+
isError: true
|
|
6778
|
+
};
|
|
7014
6779
|
}
|
|
7015
6780
|
},
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
"[task] This server does not support the per-turn task endpoint required for function tools.",
|
|
7023
|
-
"task_function_tools_unsupported",
|
|
7024
|
-
404
|
|
7025
|
-
);
|
|
7026
|
-
}
|
|
7027
|
-
const body = buildTaskRequestBody(options);
|
|
7028
|
-
const result = options.onEvent ? await runTaskStream(httpConfig, body, options.onEvent) : await runTaskPoll(httpConfig, body);
|
|
7029
|
-
if (options.outputSchema) {
|
|
7030
|
-
const errors = result.parsedSuccessfully ? validateAgainstSchema(result.output, options.outputSchema) : [{ path: "$", message: "output was not valid JSON" }];
|
|
7031
|
-
if (errors.length > 0) {
|
|
7032
|
-
throw new MindStudioError(
|
|
7033
|
-
"[task] Output did not conform to outputSchema (legacy task route, no repair turns).",
|
|
7034
|
-
"task_output_schema_mismatch",
|
|
7035
|
-
422,
|
|
6781
|
+
executeMethodTool: async (methodId, input, call) => {
|
|
6782
|
+
try {
|
|
6783
|
+
const { data } = await request(
|
|
6784
|
+
{ ...httpConfig, maxRetries: 0 },
|
|
6785
|
+
"POST",
|
|
6786
|
+
"/task/invoke-method",
|
|
7036
6787
|
{
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
toolCalls: result.toolCalls
|
|
6788
|
+
methodId,
|
|
6789
|
+
input,
|
|
6790
|
+
traceId: call.traceId,
|
|
6791
|
+
toolCallId: call.toolCallId
|
|
7042
6792
|
}
|
|
7043
6793
|
);
|
|
6794
|
+
if (data.error) {
|
|
6795
|
+
return {
|
|
6796
|
+
output: { error: data.error },
|
|
6797
|
+
billingCost: 0,
|
|
6798
|
+
isError: true
|
|
6799
|
+
};
|
|
6800
|
+
}
|
|
6801
|
+
return {
|
|
6802
|
+
output: data.output ?? null,
|
|
6803
|
+
billingCost: 0,
|
|
6804
|
+
isError: false
|
|
6805
|
+
};
|
|
6806
|
+
} catch (err) {
|
|
6807
|
+
return {
|
|
6808
|
+
output: {
|
|
6809
|
+
error: err instanceof Error ? err.message : "Method execution failed"
|
|
6810
|
+
},
|
|
6811
|
+
billingCost: 0,
|
|
6812
|
+
isError: true
|
|
6813
|
+
};
|
|
7044
6814
|
}
|
|
7045
6815
|
}
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
}
|
|
6816
|
+
},
|
|
6817
|
+
options
|
|
6818
|
+
);
|
|
7050
6819
|
}
|
|
7051
6820
|
/**
|
|
7052
6821
|
* Get the authenticated user's identity and organization info.
|
|
@@ -8419,8 +8188,18 @@ function defineJewel(method, config) {
|
|
|
8419
8188
|
}
|
|
8420
8189
|
|
|
8421
8190
|
// src/mapper/index.ts
|
|
8191
|
+
import { gzipSync } from "zlib";
|
|
8422
8192
|
function documents(list) {
|
|
8423
|
-
return {
|
|
8193
|
+
return {
|
|
8194
|
+
kind: "documents",
|
|
8195
|
+
documents: isIterable(list) || isAsyncIterable(list) ? list : [list]
|
|
8196
|
+
};
|
|
8197
|
+
}
|
|
8198
|
+
function isIterable(value) {
|
|
8199
|
+
return value !== null && typeof value === "object" && typeof value[Symbol.iterator] === "function";
|
|
8200
|
+
}
|
|
8201
|
+
function isAsyncIterable(value) {
|
|
8202
|
+
return value !== null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
|
|
8424
8203
|
}
|
|
8425
8204
|
function passthrough(options) {
|
|
8426
8205
|
return {
|
|
@@ -8440,6 +8219,8 @@ function deletes(externalIds) {
|
|
|
8440
8219
|
}
|
|
8441
8220
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
8442
8221
|
var DEFAULT_CONCURRENCY2 = 4;
|
|
8222
|
+
var PART_DOCUMENTS = 1e3;
|
|
8223
|
+
var PART_BYTES = 8 * 1024 * 1024;
|
|
8443
8224
|
function errorInfo2(e) {
|
|
8444
8225
|
if (e instanceof Error) {
|
|
8445
8226
|
return { message: e.message, stack: e.stack };
|
|
@@ -8471,7 +8252,7 @@ function objectFor(input) {
|
|
|
8471
8252
|
etag: input.etag,
|
|
8472
8253
|
lastModified: input.lastModified,
|
|
8473
8254
|
metadata: input.metadata,
|
|
8474
|
-
entities: input.entities
|
|
8255
|
+
entities: input.entities,
|
|
8475
8256
|
bytes,
|
|
8476
8257
|
text: async () => new TextDecoder("utf-8").decode(await bytes()),
|
|
8477
8258
|
json: async () => JSON.parse(new TextDecoder("utf-8").decode(await bytes()))
|
|
@@ -8480,13 +8261,17 @@ function objectFor(input) {
|
|
|
8480
8261
|
var OUTCOME_KINDS = /* @__PURE__ */ new Set(["documents", "passthrough", "skip", "deletes"]);
|
|
8481
8262
|
function normalizeOutcome(value) {
|
|
8482
8263
|
const outcome = value;
|
|
8264
|
+
const invalid = () => ({
|
|
8265
|
+
kind: "error",
|
|
8266
|
+
error: {
|
|
8267
|
+
message: `map returned an invalid outcome: ${JSON.stringify(value)?.slice(0, 200)}. Return documents(), passthrough(), skip() or deletes().`
|
|
8268
|
+
}
|
|
8269
|
+
});
|
|
8483
8270
|
if (!outcome || typeof outcome !== "object" || !OUTCOME_KINDS.has(outcome.kind)) {
|
|
8484
|
-
return
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
}
|
|
8489
|
-
};
|
|
8271
|
+
return invalid();
|
|
8272
|
+
}
|
|
8273
|
+
if (outcome.kind === "documents" && !isIterable(outcome.documents) && !isAsyncIterable(outcome.documents)) {
|
|
8274
|
+
return invalid();
|
|
8490
8275
|
}
|
|
8491
8276
|
return outcome;
|
|
8492
8277
|
}
|
|
@@ -8508,13 +8293,107 @@ async function withTimeout(work, timeoutMs, key) {
|
|
|
8508
8293
|
}
|
|
8509
8294
|
}
|
|
8510
8295
|
}
|
|
8296
|
+
var PartWriter = class {
|
|
8297
|
+
constructor(source, spillId) {
|
|
8298
|
+
this.source = source;
|
|
8299
|
+
this.spillId = spillId;
|
|
8300
|
+
}
|
|
8301
|
+
source;
|
|
8302
|
+
spillId;
|
|
8303
|
+
parts = [];
|
|
8304
|
+
/** Objects whose documents did not all store, with why. */
|
|
8305
|
+
failed = /* @__PURE__ */ new Map();
|
|
8306
|
+
lines = [];
|
|
8307
|
+
objects = /* @__PURE__ */ new Set();
|
|
8308
|
+
bytes = 0;
|
|
8309
|
+
uploading = Promise.resolve();
|
|
8310
|
+
async write(o, i, d) {
|
|
8311
|
+
const line = JSON.stringify({ o, i, d });
|
|
8312
|
+
this.lines.push(line);
|
|
8313
|
+
this.objects.add(o);
|
|
8314
|
+
this.bytes += line.length;
|
|
8315
|
+
if (this.lines.length >= PART_DOCUMENTS || this.bytes >= PART_BYTES) {
|
|
8316
|
+
await this.flush();
|
|
8317
|
+
}
|
|
8318
|
+
}
|
|
8319
|
+
/** Store what the buffer holds; resolves once every upload so far is done. */
|
|
8320
|
+
async flush() {
|
|
8321
|
+
if (this.lines.length > 0) {
|
|
8322
|
+
const lines = this.lines;
|
|
8323
|
+
const objects = this.objects;
|
|
8324
|
+
this.lines = [];
|
|
8325
|
+
this.objects = /* @__PURE__ */ new Set();
|
|
8326
|
+
this.bytes = 0;
|
|
8327
|
+
this.uploading = this.uploading.then(() => this.store(lines, objects));
|
|
8328
|
+
}
|
|
8329
|
+
await this.uploading;
|
|
8330
|
+
}
|
|
8331
|
+
async store(lines, objects) {
|
|
8332
|
+
try {
|
|
8333
|
+
const grant = await this.source._mapSpillGrant(this.spillId);
|
|
8334
|
+
const form = new FormData();
|
|
8335
|
+
for (const [k, v] of Object.entries(grant.uploadFields)) {
|
|
8336
|
+
form.append(k, v);
|
|
8337
|
+
}
|
|
8338
|
+
form.append(
|
|
8339
|
+
"file",
|
|
8340
|
+
new Blob(
|
|
8341
|
+
[new Uint8Array(gzipSync(Buffer.from(lines.join("\n") + "\n")))],
|
|
8342
|
+
{ type: "application/gzip" }
|
|
8343
|
+
),
|
|
8344
|
+
`${grant.part}.ndjson.gz`
|
|
8345
|
+
);
|
|
8346
|
+
const response = await fetch(grant.uploadUrl, {
|
|
8347
|
+
method: "POST",
|
|
8348
|
+
body: form
|
|
8349
|
+
});
|
|
8350
|
+
if (!response.ok) {
|
|
8351
|
+
throw new Error(
|
|
8352
|
+
`Could not store part ${grant.part} of the documents: HTTP ${response.status}`
|
|
8353
|
+
);
|
|
8354
|
+
}
|
|
8355
|
+
this.parts.push({ part: grant.part, count: lines.length });
|
|
8356
|
+
} catch (e) {
|
|
8357
|
+
const err = e instanceof Error ? e : new Error(String(e));
|
|
8358
|
+
for (const o of objects) {
|
|
8359
|
+
if (!this.failed.has(o)) {
|
|
8360
|
+
this.failed.set(o, err);
|
|
8361
|
+
}
|
|
8362
|
+
}
|
|
8363
|
+
}
|
|
8364
|
+
}
|
|
8365
|
+
};
|
|
8366
|
+
async function writeDocuments(list, ctx) {
|
|
8367
|
+
const iterator = isAsyncIterable(list) ? list[Symbol.asyncIterator]() : list[Symbol.iterator]();
|
|
8368
|
+
let count = 0;
|
|
8369
|
+
try {
|
|
8370
|
+
while (true) {
|
|
8371
|
+
const step = await withTimeout(
|
|
8372
|
+
Promise.resolve(iterator.next()),
|
|
8373
|
+
ctx.timeoutMs,
|
|
8374
|
+
ctx.key
|
|
8375
|
+
);
|
|
8376
|
+
if (step.done) {
|
|
8377
|
+
return count;
|
|
8378
|
+
}
|
|
8379
|
+
await ctx.writer.write(ctx.o, count, step.value);
|
|
8380
|
+
count += 1;
|
|
8381
|
+
}
|
|
8382
|
+
} catch (e) {
|
|
8383
|
+
await Promise.resolve(iterator.return?.()).catch(() => {
|
|
8384
|
+
});
|
|
8385
|
+
throw e;
|
|
8386
|
+
}
|
|
8387
|
+
}
|
|
8511
8388
|
function defineMapper(source, config) {
|
|
8389
|
+
const handle = source;
|
|
8512
8390
|
const run = async (params) => {
|
|
8513
8391
|
const startedAt = Date.now();
|
|
8514
8392
|
const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
8515
8393
|
const concurrency = Math.max(1, params.concurrency ?? DEFAULT_CONCURRENCY2);
|
|
8516
8394
|
const objects = Array.isArray(params.objects) ? params.objects : [];
|
|
8517
8395
|
const outcomes = new Array(objects.length);
|
|
8396
|
+
const writer = params.spill?.id && typeof handle._mapSpillGrant === "function" ? new PartWriter(handle, params.spill.id) : null;
|
|
8518
8397
|
let next = 0;
|
|
8519
8398
|
const worker = async () => {
|
|
8520
8399
|
while (true) {
|
|
@@ -8526,13 +8405,30 @@ function defineMapper(source, config) {
|
|
|
8526
8405
|
const t = Date.now();
|
|
8527
8406
|
let outcome;
|
|
8528
8407
|
try {
|
|
8529
|
-
|
|
8408
|
+
const mapped = normalizeOutcome(
|
|
8530
8409
|
await withTimeout(
|
|
8531
8410
|
Promise.resolve().then(() => config.map(objectFor(input))),
|
|
8532
8411
|
timeoutMs,
|
|
8533
8412
|
input.key
|
|
8534
8413
|
)
|
|
8535
8414
|
);
|
|
8415
|
+
if (mapped.kind !== "documents") {
|
|
8416
|
+
outcome = mapped;
|
|
8417
|
+
} else if (!writer) {
|
|
8418
|
+
throw new Error(
|
|
8419
|
+
"documents() needs the platform to store what it produces, and this frame was given nowhere to store it."
|
|
8420
|
+
);
|
|
8421
|
+
} else {
|
|
8422
|
+
outcome = {
|
|
8423
|
+
kind: "documents",
|
|
8424
|
+
count: await writeDocuments(mapped.documents, {
|
|
8425
|
+
o: index,
|
|
8426
|
+
key: input.key,
|
|
8427
|
+
timeoutMs,
|
|
8428
|
+
writer
|
|
8429
|
+
})
|
|
8430
|
+
};
|
|
8431
|
+
}
|
|
8536
8432
|
} catch (e) {
|
|
8537
8433
|
outcome = { kind: "error", error: errorInfo2(e) };
|
|
8538
8434
|
}
|
|
@@ -8546,10 +8442,17 @@ function defineMapper(source, config) {
|
|
|
8546
8442
|
await Promise.all(
|
|
8547
8443
|
Array.from({ length: Math.min(concurrency, objects.length) }, worker)
|
|
8548
8444
|
);
|
|
8445
|
+
await writer?.flush();
|
|
8446
|
+
for (const [o, err] of writer?.failed ?? []) {
|
|
8447
|
+
if (outcomes[o]?.outcome.kind === "documents") {
|
|
8448
|
+
outcomes[o].outcome = { kind: "error", error: errorInfo2(err) };
|
|
8449
|
+
}
|
|
8450
|
+
}
|
|
8549
8451
|
return {
|
|
8550
8452
|
v: 1,
|
|
8551
8453
|
source: source.name,
|
|
8552
8454
|
outcomes,
|
|
8455
|
+
parts: writer?.parts ?? [],
|
|
8553
8456
|
startedAt,
|
|
8554
8457
|
durationMs: Date.now() - startedAt
|
|
8555
8458
|
};
|