@mindstudio-ai/agent 0.1.140 → 0.1.141
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 +143 -421
- package/dist/index.d.ts +103 -15
- package/dist/index.js +271 -410
- package/dist/index.js.map +1 -1
- package/dist/postinstall.js +143 -421
- 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,49 @@ 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((tc) => `${tc.name} (${tc.durationMs}ms) ${tc.success ? "\u2713" : "\u2717"}`).join(", ");
|
|
4979
|
+
console.log(
|
|
4980
|
+
`[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}`
|
|
4981
|
+
);
|
|
4982
|
+
}
|
|
4983
|
+
|
|
4929
4984
|
// src/task/schema.ts
|
|
4930
4985
|
function describe(value) {
|
|
4931
4986
|
if (value === void 0) {
|
|
@@ -5066,38 +5121,6 @@ function assertSupportedNode(schema, path) {
|
|
|
5066
5121
|
assertSupportedNode(schema.items, `${path}[]`);
|
|
5067
5122
|
}
|
|
5068
5123
|
}
|
|
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
5124
|
function stripCodeFences(text) {
|
|
5102
5125
|
const match = /^```[a-zA-Z]*[ \t]*\r?\n([\s\S]*?)\r?\n?```$/.exec(
|
|
5103
5126
|
text.trim()
|
|
@@ -5105,262 +5128,7 @@ function stripCodeFences(text) {
|
|
|
5105
5128
|
return match ? match[1] : text;
|
|
5106
5129
|
}
|
|
5107
5130
|
|
|
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
5131
|
// src/task/local.ts
|
|
5363
|
-
import { randomUUID as randomUUID3 } from "crypto";
|
|
5364
5132
|
var DEFAULT_MAX_TURNS = 20;
|
|
5365
5133
|
var MAX_TURNS_LIMIT = 100;
|
|
5366
5134
|
var MAX_SCHEMA_REPAIR_ATTEMPTS = 3;
|
|
@@ -5368,7 +5136,6 @@ var MAX_TOOL_OUTPUT_CHARS = 5e4;
|
|
|
5368
5136
|
var MAX_TURN_ATTEMPTS = 5;
|
|
5369
5137
|
var INITIAL_BACKOFF_MS = 1e3;
|
|
5370
5138
|
var STALL_TIMEOUT_MS = 3e5;
|
|
5371
|
-
var TURN_UNAVAILABLE_CODE = "task_turn_unavailable";
|
|
5372
5139
|
var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
5373
5140
|
function isPlainObject(value) {
|
|
5374
5141
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
@@ -5614,7 +5381,7 @@ ${structuredOutputExample}
|
|
|
5614
5381
|
Math.max(options.maxTurns || DEFAULT_MAX_TURNS, 1),
|
|
5615
5382
|
MAX_TURNS_LIMIT
|
|
5616
5383
|
);
|
|
5617
|
-
const traceId =
|
|
5384
|
+
const traceId = randomUUID2();
|
|
5618
5385
|
const messages = [
|
|
5619
5386
|
{ role: "user", content: JSON.stringify(options.input) }
|
|
5620
5387
|
];
|
|
@@ -5714,13 +5481,6 @@ ${structuredOutputExample}
|
|
|
5714
5481
|
traceId
|
|
5715
5482
|
});
|
|
5716
5483
|
} 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
5484
|
return turnFailure(err);
|
|
5725
5485
|
}
|
|
5726
5486
|
accumulate(turn);
|
|
@@ -6945,108 +6705,75 @@ var MindStudioAgent = class {
|
|
|
6945
6705
|
}
|
|
6946
6706
|
async _runTaskInner(options) {
|
|
6947
6707
|
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
|
-
}
|
|
6708
|
+
return runTaskLocal(
|
|
6709
|
+
{
|
|
6710
|
+
httpConfig,
|
|
6711
|
+
executeStepTool: async (stepType, input) => {
|
|
6712
|
+
try {
|
|
6713
|
+
const result = await this.executeStep(stepType, input, {
|
|
6714
|
+
requestSource: "v2-task"
|
|
6715
|
+
});
|
|
6716
|
+
const output = {};
|
|
6717
|
+
let billingCost = 0;
|
|
6718
|
+
for (const [key, value] of Object.entries(
|
|
6719
|
+
result
|
|
6720
|
+
)) {
|
|
6721
|
+
if (key === "$billingCost" && typeof value === "number") {
|
|
6722
|
+
billingCost = value;
|
|
6968
6723
|
}
|
|
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
|
-
};
|
|
6724
|
+
if (!key.startsWith("$")) {
|
|
6725
|
+
output[key] = value;
|
|
6999
6726
|
}
|
|
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
6727
|
}
|
|
6728
|
+
return { output, billingCost, isError: false };
|
|
6729
|
+
} catch (err) {
|
|
6730
|
+
return {
|
|
6731
|
+
output: {
|
|
6732
|
+
error: err instanceof Error ? err.message : "Step execution failed"
|
|
6733
|
+
},
|
|
6734
|
+
billingCost: 0,
|
|
6735
|
+
isError: true
|
|
6736
|
+
};
|
|
7014
6737
|
}
|
|
7015
6738
|
},
|
|
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,
|
|
6739
|
+
executeMethodTool: async (methodId, input, call) => {
|
|
6740
|
+
try {
|
|
6741
|
+
const { data } = await request(
|
|
6742
|
+
{ ...httpConfig, maxRetries: 0 },
|
|
6743
|
+
"POST",
|
|
6744
|
+
"/task/invoke-method",
|
|
7036
6745
|
{
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
toolCalls: result.toolCalls
|
|
6746
|
+
methodId,
|
|
6747
|
+
input,
|
|
6748
|
+
traceId: call.traceId,
|
|
6749
|
+
toolCallId: call.toolCallId
|
|
7042
6750
|
}
|
|
7043
6751
|
);
|
|
6752
|
+
if (data.error) {
|
|
6753
|
+
return {
|
|
6754
|
+
output: { error: data.error },
|
|
6755
|
+
billingCost: 0,
|
|
6756
|
+
isError: true
|
|
6757
|
+
};
|
|
6758
|
+
}
|
|
6759
|
+
return {
|
|
6760
|
+
output: data.output ?? null,
|
|
6761
|
+
billingCost: 0,
|
|
6762
|
+
isError: false
|
|
6763
|
+
};
|
|
6764
|
+
} catch (err) {
|
|
6765
|
+
return {
|
|
6766
|
+
output: {
|
|
6767
|
+
error: err instanceof Error ? err.message : "Method execution failed"
|
|
6768
|
+
},
|
|
6769
|
+
billingCost: 0,
|
|
6770
|
+
isError: true
|
|
6771
|
+
};
|
|
7044
6772
|
}
|
|
7045
6773
|
}
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
}
|
|
6774
|
+
},
|
|
6775
|
+
options
|
|
6776
|
+
);
|
|
7050
6777
|
}
|
|
7051
6778
|
/**
|
|
7052
6779
|
* Get the authenticated user's identity and organization info.
|
|
@@ -8419,8 +8146,18 @@ function defineJewel(method, config) {
|
|
|
8419
8146
|
}
|
|
8420
8147
|
|
|
8421
8148
|
// src/mapper/index.ts
|
|
8149
|
+
import { gzipSync } from "zlib";
|
|
8422
8150
|
function documents(list) {
|
|
8423
|
-
return {
|
|
8151
|
+
return {
|
|
8152
|
+
kind: "documents",
|
|
8153
|
+
documents: isIterable(list) || isAsyncIterable(list) ? list : [list]
|
|
8154
|
+
};
|
|
8155
|
+
}
|
|
8156
|
+
function isIterable(value) {
|
|
8157
|
+
return value !== null && typeof value === "object" && typeof value[Symbol.iterator] === "function";
|
|
8158
|
+
}
|
|
8159
|
+
function isAsyncIterable(value) {
|
|
8160
|
+
return value !== null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
|
|
8424
8161
|
}
|
|
8425
8162
|
function passthrough(options) {
|
|
8426
8163
|
return {
|
|
@@ -8440,6 +8177,8 @@ function deletes(externalIds) {
|
|
|
8440
8177
|
}
|
|
8441
8178
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
8442
8179
|
var DEFAULT_CONCURRENCY2 = 4;
|
|
8180
|
+
var PART_DOCUMENTS = 1e3;
|
|
8181
|
+
var PART_BYTES = 8 * 1024 * 1024;
|
|
8443
8182
|
function errorInfo2(e) {
|
|
8444
8183
|
if (e instanceof Error) {
|
|
8445
8184
|
return { message: e.message, stack: e.stack };
|
|
@@ -8471,7 +8210,7 @@ function objectFor(input) {
|
|
|
8471
8210
|
etag: input.etag,
|
|
8472
8211
|
lastModified: input.lastModified,
|
|
8473
8212
|
metadata: input.metadata,
|
|
8474
|
-
entities: input.entities
|
|
8213
|
+
entities: input.entities,
|
|
8475
8214
|
bytes,
|
|
8476
8215
|
text: async () => new TextDecoder("utf-8").decode(await bytes()),
|
|
8477
8216
|
json: async () => JSON.parse(new TextDecoder("utf-8").decode(await bytes()))
|
|
@@ -8480,13 +8219,17 @@ function objectFor(input) {
|
|
|
8480
8219
|
var OUTCOME_KINDS = /* @__PURE__ */ new Set(["documents", "passthrough", "skip", "deletes"]);
|
|
8481
8220
|
function normalizeOutcome(value) {
|
|
8482
8221
|
const outcome = value;
|
|
8222
|
+
const invalid = () => ({
|
|
8223
|
+
kind: "error",
|
|
8224
|
+
error: {
|
|
8225
|
+
message: `map returned an invalid outcome: ${JSON.stringify(value)?.slice(0, 200)}. Return documents(), passthrough(), skip() or deletes().`
|
|
8226
|
+
}
|
|
8227
|
+
});
|
|
8483
8228
|
if (!outcome || typeof outcome !== "object" || !OUTCOME_KINDS.has(outcome.kind)) {
|
|
8484
|
-
return
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
}
|
|
8489
|
-
};
|
|
8229
|
+
return invalid();
|
|
8230
|
+
}
|
|
8231
|
+
if (outcome.kind === "documents" && !isIterable(outcome.documents) && !isAsyncIterable(outcome.documents)) {
|
|
8232
|
+
return invalid();
|
|
8490
8233
|
}
|
|
8491
8234
|
return outcome;
|
|
8492
8235
|
}
|
|
@@ -8508,13 +8251,107 @@ async function withTimeout(work, timeoutMs, key) {
|
|
|
8508
8251
|
}
|
|
8509
8252
|
}
|
|
8510
8253
|
}
|
|
8254
|
+
var PartWriter = class {
|
|
8255
|
+
constructor(source, spillId) {
|
|
8256
|
+
this.source = source;
|
|
8257
|
+
this.spillId = spillId;
|
|
8258
|
+
}
|
|
8259
|
+
source;
|
|
8260
|
+
spillId;
|
|
8261
|
+
parts = [];
|
|
8262
|
+
/** Objects whose documents did not all store, with why. */
|
|
8263
|
+
failed = /* @__PURE__ */ new Map();
|
|
8264
|
+
lines = [];
|
|
8265
|
+
objects = /* @__PURE__ */ new Set();
|
|
8266
|
+
bytes = 0;
|
|
8267
|
+
uploading = Promise.resolve();
|
|
8268
|
+
async write(o, i, d) {
|
|
8269
|
+
const line = JSON.stringify({ o, i, d });
|
|
8270
|
+
this.lines.push(line);
|
|
8271
|
+
this.objects.add(o);
|
|
8272
|
+
this.bytes += line.length;
|
|
8273
|
+
if (this.lines.length >= PART_DOCUMENTS || this.bytes >= PART_BYTES) {
|
|
8274
|
+
await this.flush();
|
|
8275
|
+
}
|
|
8276
|
+
}
|
|
8277
|
+
/** Store what the buffer holds; resolves once every upload so far is done. */
|
|
8278
|
+
async flush() {
|
|
8279
|
+
if (this.lines.length > 0) {
|
|
8280
|
+
const lines = this.lines;
|
|
8281
|
+
const objects = this.objects;
|
|
8282
|
+
this.lines = [];
|
|
8283
|
+
this.objects = /* @__PURE__ */ new Set();
|
|
8284
|
+
this.bytes = 0;
|
|
8285
|
+
this.uploading = this.uploading.then(() => this.store(lines, objects));
|
|
8286
|
+
}
|
|
8287
|
+
await this.uploading;
|
|
8288
|
+
}
|
|
8289
|
+
async store(lines, objects) {
|
|
8290
|
+
try {
|
|
8291
|
+
const grant = await this.source._mapSpillGrant(this.spillId);
|
|
8292
|
+
const form = new FormData();
|
|
8293
|
+
for (const [k, v] of Object.entries(grant.uploadFields)) {
|
|
8294
|
+
form.append(k, v);
|
|
8295
|
+
}
|
|
8296
|
+
form.append(
|
|
8297
|
+
"file",
|
|
8298
|
+
new Blob(
|
|
8299
|
+
[new Uint8Array(gzipSync(Buffer.from(lines.join("\n") + "\n")))],
|
|
8300
|
+
{ type: "application/gzip" }
|
|
8301
|
+
),
|
|
8302
|
+
`${grant.part}.ndjson.gz`
|
|
8303
|
+
);
|
|
8304
|
+
const response = await fetch(grant.uploadUrl, {
|
|
8305
|
+
method: "POST",
|
|
8306
|
+
body: form
|
|
8307
|
+
});
|
|
8308
|
+
if (!response.ok) {
|
|
8309
|
+
throw new Error(
|
|
8310
|
+
`Could not store part ${grant.part} of the documents: HTTP ${response.status}`
|
|
8311
|
+
);
|
|
8312
|
+
}
|
|
8313
|
+
this.parts.push({ part: grant.part, count: lines.length });
|
|
8314
|
+
} catch (e) {
|
|
8315
|
+
const err = e instanceof Error ? e : new Error(String(e));
|
|
8316
|
+
for (const o of objects) {
|
|
8317
|
+
if (!this.failed.has(o)) {
|
|
8318
|
+
this.failed.set(o, err);
|
|
8319
|
+
}
|
|
8320
|
+
}
|
|
8321
|
+
}
|
|
8322
|
+
}
|
|
8323
|
+
};
|
|
8324
|
+
async function writeDocuments(list, ctx) {
|
|
8325
|
+
const iterator = isAsyncIterable(list) ? list[Symbol.asyncIterator]() : list[Symbol.iterator]();
|
|
8326
|
+
let count = 0;
|
|
8327
|
+
try {
|
|
8328
|
+
while (true) {
|
|
8329
|
+
const step = await withTimeout(
|
|
8330
|
+
Promise.resolve(iterator.next()),
|
|
8331
|
+
ctx.timeoutMs,
|
|
8332
|
+
ctx.key
|
|
8333
|
+
);
|
|
8334
|
+
if (step.done) {
|
|
8335
|
+
return count;
|
|
8336
|
+
}
|
|
8337
|
+
await ctx.writer.write(ctx.o, count, step.value);
|
|
8338
|
+
count += 1;
|
|
8339
|
+
}
|
|
8340
|
+
} catch (e) {
|
|
8341
|
+
await Promise.resolve(iterator.return?.()).catch(() => {
|
|
8342
|
+
});
|
|
8343
|
+
throw e;
|
|
8344
|
+
}
|
|
8345
|
+
}
|
|
8511
8346
|
function defineMapper(source, config) {
|
|
8347
|
+
const handle = source;
|
|
8512
8348
|
const run = async (params) => {
|
|
8513
8349
|
const startedAt = Date.now();
|
|
8514
8350
|
const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
8515
8351
|
const concurrency = Math.max(1, params.concurrency ?? DEFAULT_CONCURRENCY2);
|
|
8516
8352
|
const objects = Array.isArray(params.objects) ? params.objects : [];
|
|
8517
8353
|
const outcomes = new Array(objects.length);
|
|
8354
|
+
const writer = params.spill?.id && typeof handle._mapSpillGrant === "function" ? new PartWriter(handle, params.spill.id) : null;
|
|
8518
8355
|
let next = 0;
|
|
8519
8356
|
const worker = async () => {
|
|
8520
8357
|
while (true) {
|
|
@@ -8526,13 +8363,30 @@ function defineMapper(source, config) {
|
|
|
8526
8363
|
const t = Date.now();
|
|
8527
8364
|
let outcome;
|
|
8528
8365
|
try {
|
|
8529
|
-
|
|
8366
|
+
const mapped = normalizeOutcome(
|
|
8530
8367
|
await withTimeout(
|
|
8531
8368
|
Promise.resolve().then(() => config.map(objectFor(input))),
|
|
8532
8369
|
timeoutMs,
|
|
8533
8370
|
input.key
|
|
8534
8371
|
)
|
|
8535
8372
|
);
|
|
8373
|
+
if (mapped.kind !== "documents") {
|
|
8374
|
+
outcome = mapped;
|
|
8375
|
+
} else if (!writer) {
|
|
8376
|
+
throw new Error(
|
|
8377
|
+
"documents() needs the platform to store what it produces, and this frame was given nowhere to store it."
|
|
8378
|
+
);
|
|
8379
|
+
} else {
|
|
8380
|
+
outcome = {
|
|
8381
|
+
kind: "documents",
|
|
8382
|
+
count: await writeDocuments(mapped.documents, {
|
|
8383
|
+
o: index,
|
|
8384
|
+
key: input.key,
|
|
8385
|
+
timeoutMs,
|
|
8386
|
+
writer
|
|
8387
|
+
})
|
|
8388
|
+
};
|
|
8389
|
+
}
|
|
8536
8390
|
} catch (e) {
|
|
8537
8391
|
outcome = { kind: "error", error: errorInfo2(e) };
|
|
8538
8392
|
}
|
|
@@ -8546,10 +8400,17 @@ function defineMapper(source, config) {
|
|
|
8546
8400
|
await Promise.all(
|
|
8547
8401
|
Array.from({ length: Math.min(concurrency, objects.length) }, worker)
|
|
8548
8402
|
);
|
|
8403
|
+
await writer?.flush();
|
|
8404
|
+
for (const [o, err] of writer?.failed ?? []) {
|
|
8405
|
+
if (outcomes[o]?.outcome.kind === "documents") {
|
|
8406
|
+
outcomes[o].outcome = { kind: "error", error: errorInfo2(err) };
|
|
8407
|
+
}
|
|
8408
|
+
}
|
|
8549
8409
|
return {
|
|
8550
8410
|
v: 1,
|
|
8551
8411
|
source: source.name,
|
|
8552
8412
|
outcomes,
|
|
8413
|
+
parts: writer?.parts ?? [],
|
|
8553
8414
|
startedAt,
|
|
8554
8415
|
durationMs: Date.now() - startedAt
|
|
8555
8416
|
};
|