@mindstudio-ai/agent 0.1.93 → 0.1.95
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 +548 -17
- package/dist/index.d.ts +67 -1
- package/dist/index.js +536 -12
- package/dist/index.js.map +1 -1
- package/dist/postinstall.js +548 -17
- package/package.json +1 -1
package/dist/postinstall.js
CHANGED
|
@@ -3741,7 +3741,8 @@ async function runTaskPoll(httpConfig, body) {
|
|
|
3741
3741
|
const res = await fetch(pollUrl, {
|
|
3742
3742
|
headers: { "User-Agent": "@mindstudio-ai/agent" }
|
|
3743
3743
|
});
|
|
3744
|
-
if (res.status === 502 || res.status === 503 || res.status === 504)
|
|
3744
|
+
if (res.status === 502 || res.status === 503 || res.status === 504)
|
|
3745
|
+
continue;
|
|
3745
3746
|
if (res.status === 404) {
|
|
3746
3747
|
throw new MindStudioError(
|
|
3747
3748
|
"Task poll token not found or expired.",
|
|
@@ -3761,7 +3762,9 @@ async function runTaskPoll(httpConfig, body) {
|
|
|
3761
3762
|
const poll = await res.json();
|
|
3762
3763
|
if (poll.status === "pending") {
|
|
3763
3764
|
if (isDevMode() && poll.currentTurn != null) {
|
|
3764
|
-
console.log(
|
|
3765
|
+
console.log(
|
|
3766
|
+
`[task] running... turn ${poll.currentTurn}/${poll.maxTurns ?? "?"}`
|
|
3767
|
+
);
|
|
3765
3768
|
}
|
|
3766
3769
|
continue;
|
|
3767
3770
|
}
|
|
@@ -3777,7 +3780,11 @@ async function runTaskPoll(httpConfig, body) {
|
|
|
3777
3780
|
outputRaw: poll.outputRaw ?? "",
|
|
3778
3781
|
parsedSuccessfully: poll.parsedSuccessfully ?? true,
|
|
3779
3782
|
turns: poll.turns ?? 0,
|
|
3780
|
-
usage: poll.usage ?? {
|
|
3783
|
+
usage: poll.usage ?? {
|
|
3784
|
+
inputTokens: 0,
|
|
3785
|
+
outputTokens: 0,
|
|
3786
|
+
totalBillingCost: 0
|
|
3787
|
+
},
|
|
3781
3788
|
toolCalls: poll.toolCalls ?? []
|
|
3782
3789
|
};
|
|
3783
3790
|
logTaskResult(result);
|
|
@@ -3906,6 +3913,405 @@ var init_task = __esm({
|
|
|
3906
3913
|
}
|
|
3907
3914
|
});
|
|
3908
3915
|
|
|
3916
|
+
// src/task/local.ts
|
|
3917
|
+
function isPlainObject(value) {
|
|
3918
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3919
|
+
return false;
|
|
3920
|
+
}
|
|
3921
|
+
const proto = Object.getPrototypeOf(value);
|
|
3922
|
+
return proto === Object.prototype || proto === null;
|
|
3923
|
+
}
|
|
3924
|
+
function mergeToolInput(modelInput, defaults) {
|
|
3925
|
+
const merged = { ...modelInput };
|
|
3926
|
+
for (const [key, defaultValue] of Object.entries(defaults)) {
|
|
3927
|
+
if (UNSAFE_KEYS.has(key)) {
|
|
3928
|
+
continue;
|
|
3929
|
+
}
|
|
3930
|
+
const modelValue = merged[key];
|
|
3931
|
+
merged[key] = isPlainObject(defaultValue) && isPlainObject(modelValue) ? mergeToolInput(modelValue, defaultValue) : defaultValue;
|
|
3932
|
+
}
|
|
3933
|
+
return merged;
|
|
3934
|
+
}
|
|
3935
|
+
function truncateToolOutput(output) {
|
|
3936
|
+
const serialized = JSON.stringify(output);
|
|
3937
|
+
return serialized && serialized.length > MAX_TOOL_OUTPUT_CHARS ? serialized.slice(0, MAX_TOOL_OUTPUT_CHARS) + "... [truncated]" : output;
|
|
3938
|
+
}
|
|
3939
|
+
async function attemptTurn(httpConfig, body) {
|
|
3940
|
+
const url = `${httpConfig.baseUrl}/developer/v2/task/turn`;
|
|
3941
|
+
await httpConfig.rateLimiter.acquire();
|
|
3942
|
+
try {
|
|
3943
|
+
let res;
|
|
3944
|
+
try {
|
|
3945
|
+
res = await fetch(url, {
|
|
3946
|
+
method: "POST",
|
|
3947
|
+
headers: {
|
|
3948
|
+
Authorization: `Bearer ${httpConfig.token}`,
|
|
3949
|
+
"Content-Type": "application/json",
|
|
3950
|
+
"User-Agent": "@mindstudio-ai/agent",
|
|
3951
|
+
Accept: "text/event-stream"
|
|
3952
|
+
},
|
|
3953
|
+
body: JSON.stringify(body)
|
|
3954
|
+
});
|
|
3955
|
+
} catch (err) {
|
|
3956
|
+
throw new TurnError(
|
|
3957
|
+
`Network error: ${err instanceof Error ? err.message : "fetch failed"}`,
|
|
3958
|
+
true,
|
|
3959
|
+
"request"
|
|
3960
|
+
);
|
|
3961
|
+
}
|
|
3962
|
+
httpConfig.rateLimiter.updateFromHeaders(res.headers);
|
|
3963
|
+
if (!res.ok) {
|
|
3964
|
+
let message = `${res.status} ${res.statusText}`;
|
|
3965
|
+
let code;
|
|
3966
|
+
try {
|
|
3967
|
+
const errBody = await res.json();
|
|
3968
|
+
const errMsg = (typeof errBody.errorMessage === "string" ? errBody.errorMessage : void 0) ?? (typeof errBody.errorString === "string" ? errBody.errorString : void 0) ?? (typeof errBody.error === "string" ? errBody.error : void 0);
|
|
3969
|
+
if (errMsg) message = errMsg;
|
|
3970
|
+
if (typeof errBody.errorString === "string") code = errBody.errorString;
|
|
3971
|
+
} catch {
|
|
3972
|
+
}
|
|
3973
|
+
const retryable = res.status >= 500 || res.status === 429;
|
|
3974
|
+
throw new TurnError(message, retryable, "request", res.status, code);
|
|
3975
|
+
}
|
|
3976
|
+
const reader = res.body.getReader();
|
|
3977
|
+
const decoder = new TextDecoder();
|
|
3978
|
+
let buffer = "";
|
|
3979
|
+
const events = [];
|
|
3980
|
+
let text = "";
|
|
3981
|
+
const toolCalls = [];
|
|
3982
|
+
let turn = null;
|
|
3983
|
+
const handleLine = (line) => {
|
|
3984
|
+
if (!line.startsWith("data: ")) {
|
|
3985
|
+
return;
|
|
3986
|
+
}
|
|
3987
|
+
let event;
|
|
3988
|
+
try {
|
|
3989
|
+
event = JSON.parse(line.slice(6));
|
|
3990
|
+
} catch {
|
|
3991
|
+
return;
|
|
3992
|
+
}
|
|
3993
|
+
if (event.type === "error") {
|
|
3994
|
+
const status = typeof event.status === "number" ? event.status : 500;
|
|
3995
|
+
const message = typeof event.error === "string" ? event.error : "Model call failed";
|
|
3996
|
+
const retryable = status >= 500 || /overloaded|terminated|network/i.test(message);
|
|
3997
|
+
throw new TurnError(message, retryable, "model", status);
|
|
3998
|
+
}
|
|
3999
|
+
if (event.type === "turn") {
|
|
4000
|
+
turn = {
|
|
4001
|
+
events,
|
|
4002
|
+
text,
|
|
4003
|
+
toolCalls,
|
|
4004
|
+
stopReason: typeof event.stopReason === "string" ? event.stopReason : "end_turn",
|
|
4005
|
+
usage: event.usage ?? {},
|
|
4006
|
+
billingCost: typeof event.billingCost === "number" ? event.billingCost : 0
|
|
4007
|
+
};
|
|
4008
|
+
return;
|
|
4009
|
+
}
|
|
4010
|
+
if (event.type === "text" && typeof event.text === "string") {
|
|
4011
|
+
text += event.text;
|
|
4012
|
+
} else if (event.type === "tool_use") {
|
|
4013
|
+
toolCalls.push({
|
|
4014
|
+
id: event.id,
|
|
4015
|
+
name: event.name,
|
|
4016
|
+
input: event.input ?? {}
|
|
4017
|
+
});
|
|
4018
|
+
}
|
|
4019
|
+
events.push(event);
|
|
4020
|
+
};
|
|
4021
|
+
while (true) {
|
|
4022
|
+
let stallTimer;
|
|
4023
|
+
let readResult;
|
|
4024
|
+
try {
|
|
4025
|
+
readResult = await Promise.race([
|
|
4026
|
+
reader.read(),
|
|
4027
|
+
new Promise((_, reject) => {
|
|
4028
|
+
stallTimer = setTimeout(
|
|
4029
|
+
() => reject(new Error("stream_stall")),
|
|
4030
|
+
STALL_TIMEOUT_MS
|
|
4031
|
+
);
|
|
4032
|
+
})
|
|
4033
|
+
]);
|
|
4034
|
+
clearTimeout(stallTimer);
|
|
4035
|
+
} catch (err) {
|
|
4036
|
+
clearTimeout(stallTimer);
|
|
4037
|
+
try {
|
|
4038
|
+
await reader.cancel();
|
|
4039
|
+
} catch {
|
|
4040
|
+
}
|
|
4041
|
+
if (err instanceof TurnError) {
|
|
4042
|
+
throw err;
|
|
4043
|
+
}
|
|
4044
|
+
const isStall = err instanceof Error && err.message === "stream_stall";
|
|
4045
|
+
throw new TurnError(
|
|
4046
|
+
isStall ? "Turn stalled \u2014 no data received for 5 minutes" : `Network error: stream interrupted \u2014 ${err instanceof Error ? err.message : "unknown"}`,
|
|
4047
|
+
true,
|
|
4048
|
+
"request"
|
|
4049
|
+
);
|
|
4050
|
+
}
|
|
4051
|
+
if (readResult.done) {
|
|
4052
|
+
break;
|
|
4053
|
+
}
|
|
4054
|
+
buffer += decoder.decode(readResult.value, { stream: true });
|
|
4055
|
+
const lines = buffer.split("\n");
|
|
4056
|
+
buffer = lines.pop() ?? "";
|
|
4057
|
+
for (const line of lines) {
|
|
4058
|
+
handleLine(line);
|
|
4059
|
+
}
|
|
4060
|
+
}
|
|
4061
|
+
if (buffer) {
|
|
4062
|
+
handleLine(buffer);
|
|
4063
|
+
}
|
|
4064
|
+
if (!turn) {
|
|
4065
|
+
throw new TurnError(
|
|
4066
|
+
"Network error: stream ended before turn completion",
|
|
4067
|
+
true,
|
|
4068
|
+
"request"
|
|
4069
|
+
);
|
|
4070
|
+
}
|
|
4071
|
+
return turn;
|
|
4072
|
+
} finally {
|
|
4073
|
+
httpConfig.rateLimiter.release();
|
|
4074
|
+
}
|
|
4075
|
+
}
|
|
4076
|
+
async function runTurnWithRetry(httpConfig, body) {
|
|
4077
|
+
for (let attempt = 0; attempt < MAX_TURN_ATTEMPTS; attempt++) {
|
|
4078
|
+
try {
|
|
4079
|
+
return await attemptTurn(httpConfig, body);
|
|
4080
|
+
} catch (err) {
|
|
4081
|
+
if (!(err instanceof TurnError) || !err.retryable || attempt >= MAX_TURN_ATTEMPTS - 1) {
|
|
4082
|
+
throw err;
|
|
4083
|
+
}
|
|
4084
|
+
if (isDevMode()) {
|
|
4085
|
+
console.log(
|
|
4086
|
+
`[task] connection lost, retrying turn (attempt ${attempt + 2} of ${MAX_TURN_ATTEMPTS})`
|
|
4087
|
+
);
|
|
4088
|
+
}
|
|
4089
|
+
await sleep2(INITIAL_BACKOFF_MS * 2 ** attempt);
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4092
|
+
throw new TurnError("Turn retries exhausted", false, "request");
|
|
4093
|
+
}
|
|
4094
|
+
async function runTaskLocal(deps, options) {
|
|
4095
|
+
const { httpConfig } = deps;
|
|
4096
|
+
const onEvent = options.onEvent;
|
|
4097
|
+
const structuredOutputExample = typeof options.structuredOutputExample === "string" ? options.structuredOutputExample : JSON.stringify(options.structuredOutputExample);
|
|
4098
|
+
const system = `${options.prompt}
|
|
4099
|
+
|
|
4100
|
+
When you have completed the task, respond with your final output as JSON matching this example:
|
|
4101
|
+
${structuredOutputExample}
|
|
4102
|
+
<!-- cache_breakpoint -->`;
|
|
4103
|
+
const wireTools = mapTools(options.tools);
|
|
4104
|
+
const toolKinds = /* @__PURE__ */ new Map();
|
|
4105
|
+
const toolDefaults = /* @__PURE__ */ new Map();
|
|
4106
|
+
for (const t of wireTools) {
|
|
4107
|
+
if ("appMethod" in t) {
|
|
4108
|
+
toolKinds.set(t.appMethod, "method");
|
|
4109
|
+
if (t.defaults) toolDefaults.set(t.appMethod, t.defaults);
|
|
4110
|
+
} else {
|
|
4111
|
+
toolKinds.set(t.stepType, "step");
|
|
4112
|
+
if (t.defaults) toolDefaults.set(t.stepType, t.defaults);
|
|
4113
|
+
}
|
|
4114
|
+
}
|
|
4115
|
+
const maxTurns = Math.min(
|
|
4116
|
+
Math.max(options.maxTurns || DEFAULT_MAX_TURNS, 1),
|
|
4117
|
+
MAX_TURNS_LIMIT
|
|
4118
|
+
);
|
|
4119
|
+
const messages = [
|
|
4120
|
+
{ role: "user", content: JSON.stringify(options.input) }
|
|
4121
|
+
];
|
|
4122
|
+
let loopCount = 0;
|
|
4123
|
+
const toolCallLog = [];
|
|
4124
|
+
const totalUsage = {
|
|
4125
|
+
inputTokens: 0,
|
|
4126
|
+
outputTokens: 0,
|
|
4127
|
+
cacheCreationTokens: 0,
|
|
4128
|
+
cacheReadTokens: 0,
|
|
4129
|
+
totalBillingCost: 0
|
|
4130
|
+
};
|
|
4131
|
+
const buildResult = (output2, outputRaw, parsedSuccessfully2, turns) => ({
|
|
4132
|
+
output: output2,
|
|
4133
|
+
outputRaw,
|
|
4134
|
+
parsedSuccessfully: parsedSuccessfully2,
|
|
4135
|
+
turns,
|
|
4136
|
+
usage: totalUsage,
|
|
4137
|
+
toolCalls: toolCallLog
|
|
4138
|
+
});
|
|
4139
|
+
const accumulate = (turn) => {
|
|
4140
|
+
totalUsage.inputTokens += turn.usage.inputTokens ?? 0;
|
|
4141
|
+
totalUsage.outputTokens += turn.usage.outputTokens ?? 0;
|
|
4142
|
+
totalUsage.cacheCreationTokens += turn.usage.cacheCreationTokens ?? 0;
|
|
4143
|
+
totalUsage.cacheReadTokens += turn.usage.cacheReadTokens ?? 0;
|
|
4144
|
+
totalUsage.totalBillingCost += turn.billingCost;
|
|
4145
|
+
for (const event of turn.events) {
|
|
4146
|
+
onEvent?.(event);
|
|
4147
|
+
}
|
|
4148
|
+
};
|
|
4149
|
+
const finish = (result) => {
|
|
4150
|
+
onEvent?.({ type: "done", ...result });
|
|
4151
|
+
logTaskResult(result);
|
|
4152
|
+
return result;
|
|
4153
|
+
};
|
|
4154
|
+
const turnFailure = (err) => {
|
|
4155
|
+
if (err instanceof TurnError && err.phase === "model") {
|
|
4156
|
+
if (isDevMode()) {
|
|
4157
|
+
console.error(`[task] Model call failed: ${err.message}`);
|
|
4158
|
+
}
|
|
4159
|
+
return finish(buildResult(null, "", false, loopCount));
|
|
4160
|
+
}
|
|
4161
|
+
if (err instanceof TurnError) {
|
|
4162
|
+
throw new MindStudioError(
|
|
4163
|
+
`[task] ${err.message}`,
|
|
4164
|
+
err.errorCode ?? "task_turn_error",
|
|
4165
|
+
err.status ?? 500
|
|
4166
|
+
);
|
|
4167
|
+
}
|
|
4168
|
+
throw err;
|
|
4169
|
+
};
|
|
4170
|
+
while (loopCount < maxTurns) {
|
|
4171
|
+
loopCount++;
|
|
4172
|
+
let turn;
|
|
4173
|
+
try {
|
|
4174
|
+
turn = await runTurnWithRetry(httpConfig, {
|
|
4175
|
+
model: options.model,
|
|
4176
|
+
system,
|
|
4177
|
+
messages,
|
|
4178
|
+
tools: wireTools
|
|
4179
|
+
});
|
|
4180
|
+
} catch (err) {
|
|
4181
|
+
if (loopCount === 1 && err instanceof TurnError && err.status === 404 && err.errorCode === "not_found") {
|
|
4182
|
+
throw new MindStudioError(
|
|
4183
|
+
"Task turn endpoint unavailable.",
|
|
4184
|
+
TURN_UNAVAILABLE_CODE,
|
|
4185
|
+
404
|
|
4186
|
+
);
|
|
4187
|
+
}
|
|
4188
|
+
return turnFailure(err);
|
|
4189
|
+
}
|
|
4190
|
+
accumulate(turn);
|
|
4191
|
+
if (turn.stopReason === "tool_use" && turn.toolCalls.length > 0) {
|
|
4192
|
+
messages.push({
|
|
4193
|
+
role: "assistant",
|
|
4194
|
+
content: turn.text,
|
|
4195
|
+
toolCalls: turn.toolCalls
|
|
4196
|
+
});
|
|
4197
|
+
const results = await Promise.all(
|
|
4198
|
+
turn.toolCalls.map(async (toolCall) => {
|
|
4199
|
+
onEvent?.({
|
|
4200
|
+
type: "tool_call_start",
|
|
4201
|
+
id: toolCall.id,
|
|
4202
|
+
name: toolCall.name
|
|
4203
|
+
});
|
|
4204
|
+
const startTime = Date.now();
|
|
4205
|
+
const defaults = toolDefaults.get(toolCall.name) || {};
|
|
4206
|
+
const mergedInput = mergeToolInput(toolCall.input, defaults);
|
|
4207
|
+
const execute = toolKinds.get(toolCall.name) === "method" ? deps.executeMethodTool : deps.executeStepTool;
|
|
4208
|
+
const result = await execute(toolCall.name, mergedInput);
|
|
4209
|
+
toolCallLog.push({
|
|
4210
|
+
name: toolCall.name,
|
|
4211
|
+
success: !result.isError,
|
|
4212
|
+
durationMs: Date.now() - startTime
|
|
4213
|
+
});
|
|
4214
|
+
return { toolCall, ...result };
|
|
4215
|
+
})
|
|
4216
|
+
);
|
|
4217
|
+
for (const { toolCall, output: output2, billingCost, isError } of results) {
|
|
4218
|
+
if (billingCost) {
|
|
4219
|
+
totalUsage.totalBillingCost += billingCost;
|
|
4220
|
+
}
|
|
4221
|
+
const truncated = truncateToolOutput(output2);
|
|
4222
|
+
messages.push({
|
|
4223
|
+
role: "user",
|
|
4224
|
+
content: JSON.stringify(truncated),
|
|
4225
|
+
toolCallId: toolCall.id,
|
|
4226
|
+
...isError && { isToolError: true }
|
|
4227
|
+
});
|
|
4228
|
+
onEvent?.({
|
|
4229
|
+
type: "tool_call_result",
|
|
4230
|
+
id: toolCall.id,
|
|
4231
|
+
output: truncated
|
|
4232
|
+
});
|
|
4233
|
+
}
|
|
4234
|
+
if (isDevMode()) {
|
|
4235
|
+
console.log(`[task] running... turn ${loopCount}/${maxTurns}`);
|
|
4236
|
+
}
|
|
4237
|
+
continue;
|
|
4238
|
+
}
|
|
4239
|
+
messages.push({ role: "assistant", content: turn.text });
|
|
4240
|
+
try {
|
|
4241
|
+
const output2 = JSON.parse(turn.text);
|
|
4242
|
+
return finish(buildResult(output2, turn.text, true, loopCount));
|
|
4243
|
+
} catch {
|
|
4244
|
+
if (loopCount < maxTurns) {
|
|
4245
|
+
messages.push({
|
|
4246
|
+
role: "user",
|
|
4247
|
+
content: "Your response was not valid JSON. Please respond with ONLY the JSON output, no other text."
|
|
4248
|
+
});
|
|
4249
|
+
continue;
|
|
4250
|
+
}
|
|
4251
|
+
}
|
|
4252
|
+
return finish(buildResult(turn.text, turn.text, false, loopCount));
|
|
4253
|
+
}
|
|
4254
|
+
messages.push({
|
|
4255
|
+
role: "user",
|
|
4256
|
+
content: "You have reached the maximum number of turns. Please provide your final output now as JSON."
|
|
4257
|
+
});
|
|
4258
|
+
let finalText = "";
|
|
4259
|
+
try {
|
|
4260
|
+
const turn = await runTurnWithRetry(httpConfig, {
|
|
4261
|
+
model: options.model,
|
|
4262
|
+
system,
|
|
4263
|
+
messages,
|
|
4264
|
+
tools: []
|
|
4265
|
+
});
|
|
4266
|
+
accumulate(turn);
|
|
4267
|
+
finalText = turn.text;
|
|
4268
|
+
} catch (err) {
|
|
4269
|
+
if (err instanceof TurnError && err.phase === "model") {
|
|
4270
|
+
if (isDevMode()) {
|
|
4271
|
+
console.error(`[task] Final model call failed: ${err.message}`);
|
|
4272
|
+
}
|
|
4273
|
+
} else {
|
|
4274
|
+
return turnFailure(err);
|
|
4275
|
+
}
|
|
4276
|
+
}
|
|
4277
|
+
let parsedSuccessfully = true;
|
|
4278
|
+
let output;
|
|
4279
|
+
try {
|
|
4280
|
+
output = JSON.parse(finalText);
|
|
4281
|
+
} catch {
|
|
4282
|
+
output = finalText;
|
|
4283
|
+
parsedSuccessfully = false;
|
|
4284
|
+
}
|
|
4285
|
+
return finish(
|
|
4286
|
+
buildResult(output, finalText, parsedSuccessfully, loopCount + 1)
|
|
4287
|
+
);
|
|
4288
|
+
}
|
|
4289
|
+
var DEFAULT_MAX_TURNS, MAX_TURNS_LIMIT, MAX_TOOL_OUTPUT_CHARS, MAX_TURN_ATTEMPTS, INITIAL_BACKOFF_MS, STALL_TIMEOUT_MS, TURN_UNAVAILABLE_CODE, UNSAFE_KEYS, TurnError;
|
|
4290
|
+
var init_local = __esm({
|
|
4291
|
+
async "src/task/local.ts"() {
|
|
4292
|
+
"use strict";
|
|
4293
|
+
init_errors();
|
|
4294
|
+
await init_task();
|
|
4295
|
+
DEFAULT_MAX_TURNS = 20;
|
|
4296
|
+
MAX_TURNS_LIMIT = 100;
|
|
4297
|
+
MAX_TOOL_OUTPUT_CHARS = 5e4;
|
|
4298
|
+
MAX_TURN_ATTEMPTS = 5;
|
|
4299
|
+
INITIAL_BACKOFF_MS = 1e3;
|
|
4300
|
+
STALL_TIMEOUT_MS = 3e5;
|
|
4301
|
+
TURN_UNAVAILABLE_CODE = "task_turn_unavailable";
|
|
4302
|
+
UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
4303
|
+
TurnError = class extends Error {
|
|
4304
|
+
constructor(message, retryable, phase, status, errorCode) {
|
|
4305
|
+
super(message);
|
|
4306
|
+
this.retryable = retryable;
|
|
4307
|
+
this.phase = phase;
|
|
4308
|
+
this.status = status;
|
|
4309
|
+
this.errorCode = errorCode;
|
|
4310
|
+
}
|
|
4311
|
+
};
|
|
4312
|
+
}
|
|
4313
|
+
});
|
|
4314
|
+
|
|
3909
4315
|
// src/generated/steps.ts
|
|
3910
4316
|
var steps_exports = {};
|
|
3911
4317
|
__export(steps_exports, {
|
|
@@ -4474,6 +4880,7 @@ var init_client = __esm({
|
|
|
4474
4880
|
init_datasources();
|
|
4475
4881
|
init_voice();
|
|
4476
4882
|
await init_task();
|
|
4883
|
+
await init_local();
|
|
4477
4884
|
init_steps();
|
|
4478
4885
|
init_metadata();
|
|
4479
4886
|
DEFAULT_BASE_URL = "https://v1.mindstudio-api.com";
|
|
@@ -4608,8 +5015,8 @@ var init_client = __esm({
|
|
|
4608
5015
|
...options?.appId != null && { appId: options.appId },
|
|
4609
5016
|
...threadId != null && { threadId },
|
|
4610
5017
|
...this._currentStreamId != null && { streamId: this._currentStreamId },
|
|
4611
|
-
...this._requestSource != null && {
|
|
4612
|
-
requestSource: this._requestSource
|
|
5018
|
+
...(options?.requestSource ?? this._requestSource) != null && {
|
|
5019
|
+
requestSource: options?.requestSource ?? this._requestSource
|
|
4613
5020
|
},
|
|
4614
5021
|
...assetStoreBody(options?.store)
|
|
4615
5022
|
});
|
|
@@ -4695,8 +5102,8 @@ var init_client = __esm({
|
|
|
4695
5102
|
...options.appId != null && { appId: options.appId },
|
|
4696
5103
|
...threadId != null && { threadId },
|
|
4697
5104
|
...this._currentStreamId != null && { streamId: this._currentStreamId },
|
|
4698
|
-
...this._requestSource != null && {
|
|
4699
|
-
requestSource: this._requestSource
|
|
5105
|
+
...(options.requestSource ?? this._requestSource) != null && {
|
|
5106
|
+
requestSource: options.requestSource ?? this._requestSource
|
|
4700
5107
|
},
|
|
4701
5108
|
...assetStoreBody(options.store)
|
|
4702
5109
|
};
|
|
@@ -4998,11 +5405,135 @@ var init_client = __esm({
|
|
|
4998
5405
|
* ```
|
|
4999
5406
|
*/
|
|
5000
5407
|
async runTask(options) {
|
|
5001
|
-
const
|
|
5002
|
-
|
|
5003
|
-
|
|
5408
|
+
const taskPromise = this._runTaskInner(options);
|
|
5409
|
+
const hook = globalThis.__msWaitUntil;
|
|
5410
|
+
if (typeof hook === "function") {
|
|
5411
|
+
try {
|
|
5412
|
+
hook(taskPromise.catch(() => {
|
|
5413
|
+
}));
|
|
5414
|
+
} catch {
|
|
5415
|
+
}
|
|
5416
|
+
}
|
|
5417
|
+
return taskPromise;
|
|
5418
|
+
}
|
|
5419
|
+
/**
|
|
5420
|
+
* Register background work with the platform so the sandbox stays alive
|
|
5421
|
+
* until it settles (bounded at ~30 minutes) instead of being reaped as
|
|
5422
|
+
* idle, and so an interruption is recorded in the request log if the
|
|
5423
|
+
* sandbox is torn down anyway.
|
|
5424
|
+
*
|
|
5425
|
+
* Use it for the fire-and-forget pattern — kick off slow work, return
|
|
5426
|
+
* early, write results back when it finishes:
|
|
5427
|
+
*
|
|
5428
|
+
* ```ts
|
|
5429
|
+
* mindstudio.waitUntil(
|
|
5430
|
+
* enrichRecord(id)
|
|
5431
|
+
* .then((data) => Records.update(id, { ...data, status: 'ready' }))
|
|
5432
|
+
* .catch(() => Records.update(id, { status: 'failed' })),
|
|
5433
|
+
* );
|
|
5434
|
+
* return { status: 'processing' };
|
|
5435
|
+
* ```
|
|
5436
|
+
*
|
|
5437
|
+
* Failures of the registered promise are caught and logged to the request
|
|
5438
|
+
* log — they can never crash the sandbox. Outside a managed sandbox this
|
|
5439
|
+
* degrades to just that error-catching. If you need the result, keep your
|
|
5440
|
+
* own reference to the promise and `await` it — `waitUntil` returns void.
|
|
5441
|
+
*/
|
|
5442
|
+
waitUntil(promise) {
|
|
5443
|
+
const caught = Promise.resolve(promise).catch((err) => {
|
|
5444
|
+
console.error(
|
|
5445
|
+
"[waitUntil] Background work failed:",
|
|
5446
|
+
err instanceof Error ? err.stack ?? err.message : String(err)
|
|
5447
|
+
);
|
|
5448
|
+
});
|
|
5449
|
+
const hook = globalThis.__msWaitUntil;
|
|
5450
|
+
if (typeof hook === "function") {
|
|
5451
|
+
try {
|
|
5452
|
+
hook(caught);
|
|
5453
|
+
} catch {
|
|
5454
|
+
}
|
|
5455
|
+
}
|
|
5456
|
+
}
|
|
5457
|
+
async _runTaskInner(options) {
|
|
5458
|
+
const httpConfig = this._currentHttpConfig;
|
|
5459
|
+
try {
|
|
5460
|
+
return await runTaskLocal(
|
|
5461
|
+
{
|
|
5462
|
+
httpConfig,
|
|
5463
|
+
executeStepTool: async (stepType, input) => {
|
|
5464
|
+
try {
|
|
5465
|
+
const result = await this.executeStep(stepType, input, {
|
|
5466
|
+
requestSource: "v2-task"
|
|
5467
|
+
});
|
|
5468
|
+
const output = {};
|
|
5469
|
+
let billingCost = 0;
|
|
5470
|
+
for (const [key, value] of Object.entries(
|
|
5471
|
+
result
|
|
5472
|
+
)) {
|
|
5473
|
+
if (key === "$billingCost" && typeof value === "number") {
|
|
5474
|
+
billingCost = value;
|
|
5475
|
+
}
|
|
5476
|
+
if (!key.startsWith("$")) {
|
|
5477
|
+
output[key] = value;
|
|
5478
|
+
}
|
|
5479
|
+
}
|
|
5480
|
+
return { output, billingCost, isError: false };
|
|
5481
|
+
} catch (err) {
|
|
5482
|
+
return {
|
|
5483
|
+
output: {
|
|
5484
|
+
error: err instanceof Error ? err.message : "Step execution failed"
|
|
5485
|
+
},
|
|
5486
|
+
billingCost: 0,
|
|
5487
|
+
isError: true
|
|
5488
|
+
};
|
|
5489
|
+
}
|
|
5490
|
+
},
|
|
5491
|
+
executeMethodTool: async (methodId, input) => {
|
|
5492
|
+
try {
|
|
5493
|
+
const { data } = await request(
|
|
5494
|
+
{ ...httpConfig, maxRetries: 0 },
|
|
5495
|
+
"POST",
|
|
5496
|
+
"/task/invoke-method",
|
|
5497
|
+
{
|
|
5498
|
+
methodId,
|
|
5499
|
+
input
|
|
5500
|
+
}
|
|
5501
|
+
);
|
|
5502
|
+
if (data.error) {
|
|
5503
|
+
return {
|
|
5504
|
+
output: { error: data.error },
|
|
5505
|
+
billingCost: 0,
|
|
5506
|
+
isError: true
|
|
5507
|
+
};
|
|
5508
|
+
}
|
|
5509
|
+
return {
|
|
5510
|
+
output: data.output ?? null,
|
|
5511
|
+
billingCost: 0,
|
|
5512
|
+
isError: false
|
|
5513
|
+
};
|
|
5514
|
+
} catch (err) {
|
|
5515
|
+
return {
|
|
5516
|
+
output: {
|
|
5517
|
+
error: err instanceof Error ? err.message : "Method execution failed"
|
|
5518
|
+
},
|
|
5519
|
+
billingCost: 0,
|
|
5520
|
+
isError: true
|
|
5521
|
+
};
|
|
5522
|
+
}
|
|
5523
|
+
}
|
|
5524
|
+
},
|
|
5525
|
+
options
|
|
5526
|
+
);
|
|
5527
|
+
} catch (err) {
|
|
5528
|
+
if (err instanceof MindStudioError && err.code === TURN_UNAVAILABLE_CODE) {
|
|
5529
|
+
const body = buildTaskRequestBody(options);
|
|
5530
|
+
if (options.onEvent) {
|
|
5531
|
+
return runTaskStream(httpConfig, body, options.onEvent);
|
|
5532
|
+
}
|
|
5533
|
+
return runTaskPoll(httpConfig, body);
|
|
5534
|
+
}
|
|
5535
|
+
throw err;
|
|
5004
5536
|
}
|
|
5005
|
-
return runTaskPoll(this._currentHttpConfig, body);
|
|
5006
5537
|
}
|
|
5007
5538
|
/**
|
|
5008
5539
|
* Get the authenticated user's identity and organization info.
|
|
@@ -6802,7 +7333,7 @@ async function startMcpServer(options) {
|
|
|
6802
7333
|
capabilities: { tools: {} },
|
|
6803
7334
|
serverInfo: {
|
|
6804
7335
|
name: "mindstudio-agent",
|
|
6805
|
-
version: "0.1.
|
|
7336
|
+
version: "0.1.95"
|
|
6806
7337
|
},
|
|
6807
7338
|
instructions: 'Welcome to MindStudio \u2014 a platform with 200+ AI models, 850+ third-party integrations, and pre-built agents.\n\nGetting started:\n1. Call `ask` with any question about the SDK \u2014 it knows every action, model, and connector and returns working code with real model IDs and config options. Examples: ask("generate an image with FLUX"), ask("what models support vision?"), ask("how do I send a Slack message?").\n2. Call `changeName` to set your display name \u2014 use your name or whatever your user calls you. This is how you\'ll appear in MindStudio request logs.\n3. If you have a profile picture, pass its public image URL to `changeProfilePicture`.\n4. For manual browsing, call `listActions` to discover all available actions.\n\nThen use the tools to generate text, images, video, audio, search the web, work with data sources, run agents, and more.\n\nImportant:\n- AI-powered actions (text generation, image generation, video, audio, etc.) cost money. Before running these, call `estimateActionCost` and confirm with the user before proceeding \u2014 unless they\'ve explicitly told you to go ahead.\n- Not all agents from `listAgents` are configured for API use. Do not try to run an agent just because it appears in the list \u2014 it will likely fail. Only run agents the user specifically asks you to run.'
|
|
6808
7339
|
});
|
|
@@ -7690,7 +8221,7 @@ function isNewerVersion(current, latest) {
|
|
|
7690
8221
|
return false;
|
|
7691
8222
|
}
|
|
7692
8223
|
async function checkForUpdate() {
|
|
7693
|
-
const currentVersion = "0.1.
|
|
8224
|
+
const currentVersion = "0.1.95";
|
|
7694
8225
|
if (!currentVersion) return null;
|
|
7695
8226
|
try {
|
|
7696
8227
|
const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
@@ -7719,7 +8250,7 @@ async function checkForUpdate() {
|
|
|
7719
8250
|
}
|
|
7720
8251
|
}
|
|
7721
8252
|
function printUpdateNotice(latestVersion) {
|
|
7722
|
-
const currentVersion = "0.1.
|
|
8253
|
+
const currentVersion = "0.1.95";
|
|
7723
8254
|
process.stderr.write(
|
|
7724
8255
|
`
|
|
7725
8256
|
${ansi2.cyanBright("Update available")} ${ansi2.gray(currentVersion + " \u2192")} ${ansi2.cyanBold(latestVersion)}
|
|
@@ -7732,7 +8263,7 @@ function isStandaloneBinary() {
|
|
|
7732
8263
|
return !argv1.includes("node_modules");
|
|
7733
8264
|
}
|
|
7734
8265
|
async function cmdUpdate() {
|
|
7735
|
-
const currentVersion = "0.1.
|
|
8266
|
+
const currentVersion = "0.1.95";
|
|
7736
8267
|
process.stderr.write(
|
|
7737
8268
|
` ${ansi2.gray("Current version:")} ${currentVersion}
|
|
7738
8269
|
`
|
|
@@ -7847,7 +8378,7 @@ async function cmdLogin(options) {
|
|
|
7847
8378
|
process.stderr.write("\n");
|
|
7848
8379
|
printLogo();
|
|
7849
8380
|
process.stderr.write("\n");
|
|
7850
|
-
const ver = "0.1.
|
|
8381
|
+
const ver = "0.1.95";
|
|
7851
8382
|
process.stderr.write(
|
|
7852
8383
|
` ${ansi2.bold("MindStudio Agent")} ${ver ? " " + ansi2.gray("v" + ver) : ""}
|
|
7853
8384
|
`
|
|
@@ -8158,7 +8689,7 @@ async function main() {
|
|
|
8158
8689
|
try {
|
|
8159
8690
|
if (command === "version" || command === "-v") {
|
|
8160
8691
|
process.stdout.write(
|
|
8161
|
-
"0.1.
|
|
8692
|
+
"0.1.95\n"
|
|
8162
8693
|
);
|
|
8163
8694
|
return;
|
|
8164
8695
|
}
|