@mindstudio-ai/agent 0.1.46 → 0.1.48
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 +113 -49
- package/dist/index.d.ts +20 -7
- package/dist/index.js +106 -43
- package/dist/index.js.map +1 -1
- package/dist/postinstall.js +113 -49
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -42,9 +42,9 @@ async function requestWithRetry(config, method, url, body, attempt) {
|
|
|
42
42
|
body: body != null ? JSON.stringify(body) : void 0
|
|
43
43
|
});
|
|
44
44
|
config.rateLimiter.updateFromHeaders(res.headers);
|
|
45
|
-
if (res.status === 429
|
|
45
|
+
if (attempt < config.maxRetries && (res.status === 429 || res.status === 502 || res.status === 503 || res.status === 504)) {
|
|
46
46
|
const retryAfter = res.headers.get("retry-after");
|
|
47
|
-
const waitMs = retryAfter ? parseFloat(retryAfter) * 1e3 : 1e3;
|
|
47
|
+
const waitMs = retryAfter ? parseFloat(retryAfter) * 1e3 : Math.min(1e3 * Math.pow(2, attempt), 1e4);
|
|
48
48
|
await sleep(waitMs);
|
|
49
49
|
return requestWithRetry(config, method, url, body, attempt + 1);
|
|
50
50
|
}
|
|
@@ -1493,15 +1493,16 @@ var Table = class {
|
|
|
1493
1493
|
// -------------------------------------------------------------------------
|
|
1494
1494
|
// Internal helpers
|
|
1495
1495
|
// -------------------------------------------------------------------------
|
|
1496
|
-
/** @internal Throw if data includes a platform-managed
|
|
1496
|
+
/** @internal Throw if data includes a platform-managed read-only column. */
|
|
1497
1497
|
_checkManagedColumns(data) {
|
|
1498
1498
|
const mc = this._config.managedColumns;
|
|
1499
1499
|
if (!mc) return;
|
|
1500
1500
|
const keys = Object.keys(data);
|
|
1501
1501
|
for (const key of keys) {
|
|
1502
|
-
if (mc.email && key === mc.email || mc.phone && key === mc.phone) {
|
|
1502
|
+
if (mc.email && key === mc.email || mc.phone && key === mc.phone || mc.apiKey && key === mc.apiKey) {
|
|
1503
|
+
const friendly = key === mc.email ? "email" : key === mc.phone ? "phone" : "API key";
|
|
1503
1504
|
throw new MindStudioError(
|
|
1504
|
-
`Cannot write to "${key}" \u2014 this column is managed by auth. Use the auth API to change a user's ${
|
|
1505
|
+
`Cannot write to "${key}" \u2014 this column is managed by auth. Use the auth API to change a user's ${friendly}.`,
|
|
1505
1506
|
"managed_column_write",
|
|
1506
1507
|
400
|
|
1507
1508
|
);
|
|
@@ -2884,7 +2885,7 @@ function buildTaskRequestBody(options) {
|
|
|
2884
2885
|
prompt: options.prompt,
|
|
2885
2886
|
input: options.input,
|
|
2886
2887
|
tools: mapTools(options.tools),
|
|
2887
|
-
structuredOutputExample: options.structuredOutputExample,
|
|
2888
|
+
structuredOutputExample: typeof options.structuredOutputExample === "string" ? options.structuredOutputExample : JSON.stringify(options.structuredOutputExample),
|
|
2888
2889
|
model: options.model,
|
|
2889
2890
|
...options.maxTurns != null && { maxTurns: options.maxTurns },
|
|
2890
2891
|
...options.appId != null && { appId: options.appId },
|
|
@@ -2894,6 +2895,16 @@ function buildTaskRequestBody(options) {
|
|
|
2894
2895
|
function sleep2(ms) {
|
|
2895
2896
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2896
2897
|
}
|
|
2898
|
+
function isDevMode() {
|
|
2899
|
+
return !!(process.env.CALLBACK_TOKEN || getRequestContext()?.callbackToken);
|
|
2900
|
+
}
|
|
2901
|
+
function logTaskResult(result) {
|
|
2902
|
+
if (!isDevMode()) return;
|
|
2903
|
+
const toolSummary = result.toolCalls.map((tc) => `${tc.name} (${tc.durationMs}ms) ${tc.success ? "\u2713" : "\u2717"}`).join(", ");
|
|
2904
|
+
console.log(
|
|
2905
|
+
`[task] ${result.turns} turn${result.turns === 1 ? "" : "s"}` + (toolSummary ? `: ${toolSummary}` : "") + ` | ${result.parsedSuccessfully ? "output OK" : "\u26A0 output not valid JSON"} | cost: ${result.usage.totalBillingCost}`
|
|
2906
|
+
);
|
|
2907
|
+
}
|
|
2897
2908
|
async function runTaskPoll(httpConfig, body) {
|
|
2898
2909
|
const { data } = await request(
|
|
2899
2910
|
httpConfig,
|
|
@@ -2909,6 +2920,7 @@ async function runTaskPoll(httpConfig, body) {
|
|
|
2909
2920
|
const res = await fetch(pollUrl, {
|
|
2910
2921
|
headers: { "User-Agent": "@mindstudio-ai/agent" }
|
|
2911
2922
|
});
|
|
2923
|
+
if (res.status === 502 || res.status === 503 || res.status === 504) continue;
|
|
2912
2924
|
if (res.status === 404) {
|
|
2913
2925
|
throw new MindStudioError(
|
|
2914
2926
|
"Task poll token not found or expired.",
|
|
@@ -2926,7 +2938,12 @@ async function runTaskPoll(httpConfig, body) {
|
|
|
2926
2938
|
);
|
|
2927
2939
|
}
|
|
2928
2940
|
const poll = await res.json();
|
|
2929
|
-
if (poll.status === "pending")
|
|
2941
|
+
if (poll.status === "pending") {
|
|
2942
|
+
if (isDevMode() && poll.currentTurn != null) {
|
|
2943
|
+
console.log(`[task] running... turn ${poll.currentTurn}/${poll.maxTurns ?? "?"}`);
|
|
2944
|
+
}
|
|
2945
|
+
continue;
|
|
2946
|
+
}
|
|
2930
2947
|
if (poll.status === "error") {
|
|
2931
2948
|
throw new MindStudioError(
|
|
2932
2949
|
poll.error ?? "Task execution failed.",
|
|
@@ -2934,11 +2951,16 @@ async function runTaskPoll(httpConfig, body) {
|
|
|
2934
2951
|
500
|
|
2935
2952
|
);
|
|
2936
2953
|
}
|
|
2937
|
-
|
|
2954
|
+
const result = {
|
|
2938
2955
|
output: poll.output,
|
|
2956
|
+
outputRaw: poll.outputRaw ?? "",
|
|
2957
|
+
parsedSuccessfully: poll.parsedSuccessfully ?? true,
|
|
2939
2958
|
turns: poll.turns ?? 0,
|
|
2940
|
-
usage: poll.usage ?? { inputTokens: 0, outputTokens: 0, totalBillingCost: 0 }
|
|
2959
|
+
usage: poll.usage ?? { inputTokens: 0, outputTokens: 0, totalBillingCost: 0 },
|
|
2960
|
+
toolCalls: poll.toolCalls ?? []
|
|
2941
2961
|
};
|
|
2962
|
+
logTaskResult(result);
|
|
2963
|
+
return result;
|
|
2942
2964
|
}
|
|
2943
2965
|
}
|
|
2944
2966
|
async function runTaskStream(httpConfig, body, onEvent) {
|
|
@@ -2998,12 +3020,15 @@ async function runTaskStream(httpConfig, body, onEvent) {
|
|
|
2998
3020
|
if (event.type === "done") {
|
|
2999
3021
|
result = {
|
|
3000
3022
|
output: event.output,
|
|
3023
|
+
outputRaw: event.outputRaw ?? "",
|
|
3024
|
+
parsedSuccessfully: event.parsedSuccessfully ?? true,
|
|
3001
3025
|
turns: event.turns ?? 0,
|
|
3002
3026
|
usage: event.usage ?? {
|
|
3003
3027
|
inputTokens: 0,
|
|
3004
3028
|
outputTokens: 0,
|
|
3005
3029
|
totalBillingCost: 0
|
|
3006
|
-
}
|
|
3030
|
+
},
|
|
3031
|
+
toolCalls: event.toolCalls ?? []
|
|
3007
3032
|
};
|
|
3008
3033
|
}
|
|
3009
3034
|
} catch (err) {
|
|
@@ -3025,12 +3050,15 @@ async function runTaskStream(httpConfig, body, onEvent) {
|
|
|
3025
3050
|
if (event.type === "done") {
|
|
3026
3051
|
result = {
|
|
3027
3052
|
output: event.output,
|
|
3053
|
+
outputRaw: event.outputRaw ?? "",
|
|
3054
|
+
parsedSuccessfully: event.parsedSuccessfully ?? true,
|
|
3028
3055
|
turns: event.turns ?? 0,
|
|
3029
3056
|
usage: event.usage ?? {
|
|
3030
3057
|
inputTokens: 0,
|
|
3031
3058
|
outputTokens: 0,
|
|
3032
3059
|
totalBillingCost: 0
|
|
3033
|
-
}
|
|
3060
|
+
},
|
|
3061
|
+
toolCalls: event.toolCalls ?? []
|
|
3034
3062
|
};
|
|
3035
3063
|
}
|
|
3036
3064
|
} catch (err) {
|
|
@@ -3044,6 +3072,7 @@ async function runTaskStream(httpConfig, body, onEvent) {
|
|
|
3044
3072
|
500
|
|
3045
3073
|
);
|
|
3046
3074
|
}
|
|
3075
|
+
logTaskResult(result);
|
|
3047
3076
|
return result;
|
|
3048
3077
|
}
|
|
3049
3078
|
|
|
@@ -3644,48 +3673,80 @@ var MindStudioAgent = class {
|
|
|
3644
3673
|
);
|
|
3645
3674
|
}
|
|
3646
3675
|
const threadId = options?.threadId ?? (this._reuseThreadId && !getRequestContext() ? this._threadId : void 0);
|
|
3647
|
-
const { data, headers } = await request(this.
|
|
3676
|
+
const { data: asyncData, headers } = await request(this._currentHttpConfig, "POST", `/steps/${stepType}/execute-async`, {
|
|
3648
3677
|
step,
|
|
3649
3678
|
...options?.appId != null && { appId: options.appId },
|
|
3650
3679
|
...threadId != null && { threadId },
|
|
3651
3680
|
...this._currentStreamId != null && { streamId: this._currentStreamId }
|
|
3652
3681
|
});
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3682
|
+
const remaining = headers.get("x-ratelimit-remaining");
|
|
3683
|
+
const returnedThreadId = asyncData.threadId ?? "";
|
|
3684
|
+
if (this._reuseThreadId && returnedThreadId && !getRequestContext()) {
|
|
3685
|
+
this._threadId = returnedThreadId;
|
|
3686
|
+
}
|
|
3687
|
+
if (!this._appId && asyncData.appId && !getRequestContext()) {
|
|
3688
|
+
this._appId = asyncData.appId;
|
|
3689
|
+
}
|
|
3690
|
+
const pollUrl = `${this._currentHttpConfig.baseUrl}/developer/v2/steps/${stepType}/execute-async/poll/${asyncData.executionToken}`;
|
|
3691
|
+
let pollDelay = 100;
|
|
3692
|
+
while (true) {
|
|
3693
|
+
await sleep3(pollDelay);
|
|
3694
|
+
pollDelay = Math.min(pollDelay * 2, 5e3);
|
|
3695
|
+
const res = await fetch(pollUrl, {
|
|
3696
|
+
headers: { "User-Agent": "@mindstudio-ai/agent" }
|
|
3697
|
+
});
|
|
3698
|
+
if (res.status === 502 || res.status === 503 || res.status === 504) continue;
|
|
3699
|
+
if (res.status === 404) {
|
|
3700
|
+
throw new MindStudioError(
|
|
3701
|
+
`[${stepType}] Execution token expired.`,
|
|
3702
|
+
"poll_token_expired",
|
|
3703
|
+
404
|
|
3704
|
+
);
|
|
3705
|
+
}
|
|
3658
3706
|
if (!res.ok) {
|
|
3707
|
+
const errorBody = await res.json().catch(() => ({}));
|
|
3659
3708
|
throw new MindStudioError(
|
|
3660
|
-
|
|
3661
|
-
"
|
|
3662
|
-
res.status
|
|
3709
|
+
errorBody.message ?? errorBody.error ?? `[${stepType}] Poll failed: ${res.status} ${res.statusText}`,
|
|
3710
|
+
errorBody.code ?? "poll_error",
|
|
3711
|
+
res.status,
|
|
3712
|
+
errorBody
|
|
3663
3713
|
);
|
|
3664
3714
|
}
|
|
3665
|
-
const
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3715
|
+
const poll = await res.json();
|
|
3716
|
+
if (poll.status === "pending") continue;
|
|
3717
|
+
if (poll.status === "error") {
|
|
3718
|
+
throw new MindStudioError(
|
|
3719
|
+
`[${stepType}] ${poll.error ?? "Step execution failed."}`,
|
|
3720
|
+
"step_error",
|
|
3721
|
+
500
|
|
3722
|
+
);
|
|
3723
|
+
}
|
|
3724
|
+
let output;
|
|
3725
|
+
if (poll.output != null) {
|
|
3726
|
+
output = poll.output;
|
|
3727
|
+
} else if (poll.outputUrl) {
|
|
3728
|
+
const s3Res = await fetch(poll.outputUrl);
|
|
3729
|
+
if (!s3Res.ok) {
|
|
3730
|
+
throw new MindStudioError(
|
|
3731
|
+
`Failed to fetch ${stepType} output from S3: ${s3Res.status} ${s3Res.statusText}`,
|
|
3732
|
+
"output_fetch_error",
|
|
3733
|
+
s3Res.status
|
|
3734
|
+
);
|
|
3735
|
+
}
|
|
3736
|
+
const envelope = await s3Res.json();
|
|
3737
|
+
output = envelope.value;
|
|
3738
|
+
} else {
|
|
3739
|
+
output = void 0;
|
|
3740
|
+
}
|
|
3741
|
+
return {
|
|
3742
|
+
...output,
|
|
3743
|
+
$appId: poll.appId ?? asyncData.appId ?? "",
|
|
3744
|
+
$threadId: poll.threadId ?? returnedThreadId,
|
|
3745
|
+
$rateLimitRemaining: remaining != null ? parseInt(remaining, 10) : void 0,
|
|
3746
|
+
$billingCost: poll.billingCost,
|
|
3747
|
+
$billingEvents: poll.billingEvents
|
|
3748
|
+
};
|
|
3677
3749
|
}
|
|
3678
|
-
const remaining = headers.get("x-ratelimit-remaining");
|
|
3679
|
-
const billingCost = headers.get("x-mindstudio-billing-cost");
|
|
3680
|
-
const billingEvents = headers.get("x-mindstudio-billing-events");
|
|
3681
|
-
return {
|
|
3682
|
-
...output,
|
|
3683
|
-
$appId: headers.get("x-mindstudio-app-id") ?? "",
|
|
3684
|
-
$threadId: returnedThreadId,
|
|
3685
|
-
$rateLimitRemaining: remaining != null ? parseInt(remaining, 10) : void 0,
|
|
3686
|
-
$billingCost: billingCost != null ? parseFloat(billingCost) : void 0,
|
|
3687
|
-
$billingEvents: billingEvents != null ? JSON.parse(billingEvents) : void 0
|
|
3688
|
-
};
|
|
3689
3750
|
}
|
|
3690
3751
|
/**
|
|
3691
3752
|
* @internal Streaming step execution — sends `Accept: text/event-stream`
|
|
@@ -3884,6 +3945,7 @@ var MindStudioAgent = class {
|
|
|
3884
3945
|
const res = await fetch(pollUrl, {
|
|
3885
3946
|
headers: { "User-Agent": "@mindstudio-ai/agent" }
|
|
3886
3947
|
});
|
|
3948
|
+
if (res.status === 502 || res.status === 503 || res.status === 504) continue;
|
|
3887
3949
|
if (res.status === 404) {
|
|
3888
3950
|
throw new MindStudioError(
|
|
3889
3951
|
"Batch poll token not found or expired.",
|
|
@@ -4047,6 +4109,7 @@ var MindStudioAgent = class {
|
|
|
4047
4109
|
const res = await fetch(pollUrl, {
|
|
4048
4110
|
headers: { "User-Agent": "@mindstudio-ai/agent" }
|
|
4049
4111
|
});
|
|
4112
|
+
if (res.status === 502 || res.status === 503 || res.status === 504) continue;
|
|
4050
4113
|
if (res.status === 404) {
|
|
4051
4114
|
throw new MindStudioError(
|
|
4052
4115
|
"Poll token not found or expired.",
|