@mindstudio-ai/agent 0.1.132 → 0.1.134
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/README.md +3 -4
- package/dist/cli.js +93 -78
- package/dist/index.d.ts +26 -13
- package/dist/index.js +81 -65
- package/dist/index.js.map +1 -1
- package/dist/postinstall.js +93 -78
- package/llms.txt +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -380,7 +380,6 @@ interface UserInfoResult {
|
|
|
380
380
|
userId: string;
|
|
381
381
|
displayName: string;
|
|
382
382
|
role: 'owner' | 'admin' | 'member' | 'guest' | 'agent';
|
|
383
|
-
isAgent: boolean;
|
|
384
383
|
}[];
|
|
385
384
|
}
|
|
386
385
|
/**
|
|
@@ -745,13 +744,21 @@ interface RunAgentResult {
|
|
|
745
744
|
}
|
|
746
745
|
|
|
747
746
|
type AuthType = 'internal' | 'apiKey';
|
|
747
|
+
/**
|
|
748
|
+
* Keeps an execution's calls within the server's concurrency limit, so a
|
|
749
|
+
* `Promise.all` over many steps queues here instead of being refused.
|
|
750
|
+
*
|
|
751
|
+
* The server's limits are per execution (per hook token), so the slots are
|
|
752
|
+
* too: each `runWithContext()` request gets its own, and a persistent sandbox
|
|
753
|
+
* worker's concurrent executions never wait on each other. Outside a request
|
|
754
|
+
* context (API-key use, or one execution per process) the instance holds one
|
|
755
|
+
* set. There is no call cap here: the server enforces it and answers 429 with
|
|
756
|
+
* `Retry-After`, which `http.ts` retries.
|
|
757
|
+
*/
|
|
748
758
|
declare class RateLimiter {
|
|
749
|
-
readonly authType: AuthType;
|
|
750
|
-
private inflight;
|
|
751
759
|
private concurrencyLimit;
|
|
752
|
-
private
|
|
753
|
-
private
|
|
754
|
-
private queue;
|
|
760
|
+
private perRequest;
|
|
761
|
+
private shared;
|
|
755
762
|
constructor(authType: AuthType);
|
|
756
763
|
/** Acquire a slot. Resolves when a concurrent slot is available. */
|
|
757
764
|
acquire(): Promise<void>;
|
|
@@ -759,11 +766,7 @@ declare class RateLimiter {
|
|
|
759
766
|
release(): void;
|
|
760
767
|
/** Update limits from response headers. */
|
|
761
768
|
updateFromHeaders(headers: Headers): void;
|
|
762
|
-
|
|
763
|
-
static parseHeaders(headers: Headers): {
|
|
764
|
-
remaining: number | undefined;
|
|
765
|
-
concurrencyRemaining: number | undefined;
|
|
766
|
-
};
|
|
769
|
+
private slots;
|
|
767
770
|
}
|
|
768
771
|
|
|
769
772
|
interface HttpClientConfig {
|
|
@@ -3980,9 +3983,9 @@ interface RunTaskResult<T = unknown> {
|
|
|
3980
3983
|
* 5. `https://v1.mindstudio-api.com` (production default)
|
|
3981
3984
|
*
|
|
3982
3985
|
* Rate limiting is handled automatically:
|
|
3983
|
-
* - Concurrent requests are queued to stay within server
|
|
3986
|
+
* - Concurrent requests are queued to stay within the server's concurrency
|
|
3987
|
+
* limit, per execution inside MindStudio
|
|
3984
3988
|
* - 429 responses are retried automatically using the `Retry-After` header
|
|
3985
|
-
* - Internal (hook) tokens are capped at 500 calls per execution
|
|
3986
3989
|
*/
|
|
3987
3990
|
declare class MindStudioAgent$1 {
|
|
3988
3991
|
/** @internal */
|
|
@@ -4055,6 +4058,11 @@ declare class MindStudioAgent$1 {
|
|
|
4055
4058
|
* ```
|
|
4056
4059
|
*/
|
|
4057
4060
|
executeStep<TOutput = unknown>(stepType: string, step: Record<string, unknown>, options?: StepExecutionOptions): Promise<StepExecutionResult<TOutput>>;
|
|
4061
|
+
/**
|
|
4062
|
+
* @internal Async step execution — POST, then poll until the step finishes.
|
|
4063
|
+
* Runs inside one concurrency slot (see `withSlot`).
|
|
4064
|
+
*/
|
|
4065
|
+
private _executeStepPolled;
|
|
4058
4066
|
/**
|
|
4059
4067
|
* @internal Streaming step execution — sends `Accept: text/event-stream`
|
|
4060
4068
|
* and parses SSE events for real-time debug logs.
|
|
@@ -4075,6 +4083,11 @@ declare class MindStudioAgent$1 {
|
|
|
4075
4083
|
* ```
|
|
4076
4084
|
*/
|
|
4077
4085
|
executeStepBatch(steps: BatchStepInput[], options?: ExecuteStepBatchOptions): Promise<ExecuteStepBatchResult>;
|
|
4086
|
+
/**
|
|
4087
|
+
* @internal Async batch execution — POST, then poll until the batch settles.
|
|
4088
|
+
* Runs inside one concurrency slot (see `withSlot`).
|
|
4089
|
+
*/
|
|
4090
|
+
private _executeStepBatchPolled;
|
|
4078
4091
|
/**
|
|
4079
4092
|
* Run a task agent — a multi-step tool-use loop that composes SDK actions
|
|
4080
4093
|
* to produce structured output. The model receives the prompt and tools,
|
package/dist/index.js
CHANGED
|
@@ -23,17 +23,36 @@ var MindStudioError = class extends Error {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
|
+
function errorCodeFrom(body, fallback) {
|
|
27
|
+
if (body == null || typeof body !== "object") {
|
|
28
|
+
return fallback;
|
|
29
|
+
}
|
|
30
|
+
const { code, errorString } = body;
|
|
31
|
+
if (typeof code === "string" && code) {
|
|
32
|
+
return code;
|
|
33
|
+
}
|
|
34
|
+
if (typeof errorString === "string" && /^\S+$/.test(errorString)) {
|
|
35
|
+
return errorString;
|
|
36
|
+
}
|
|
37
|
+
return fallback;
|
|
38
|
+
}
|
|
26
39
|
|
|
27
40
|
// src/http.ts
|
|
28
41
|
async function request(config, method, path, body) {
|
|
29
|
-
|
|
42
|
+
return withSlot(config, () => sendRequest(config, method, path, body));
|
|
43
|
+
}
|
|
44
|
+
async function withSlot(config, fn) {
|
|
30
45
|
await config.rateLimiter.acquire();
|
|
31
46
|
try {
|
|
32
|
-
return await
|
|
47
|
+
return await fn();
|
|
33
48
|
} finally {
|
|
34
49
|
config.rateLimiter.release();
|
|
35
50
|
}
|
|
36
51
|
}
|
|
52
|
+
async function sendRequest(config, method, path, body) {
|
|
53
|
+
const url = `${config.baseUrl}/developer/v2${path}`;
|
|
54
|
+
return requestWithRetry(config, method, url, body, 0);
|
|
55
|
+
}
|
|
37
56
|
async function requestWithRetry(config, method, url, body, attempt) {
|
|
38
57
|
const res = await fetch(url, {
|
|
39
58
|
method,
|
|
@@ -66,11 +85,7 @@ async function requestWithRetry(config, method, url, body, attempt) {
|
|
|
66
85
|
} else if (body2.error || body2.message || body2.details) {
|
|
67
86
|
message = JSON.stringify(body2.error ?? body2.message ?? body2.details);
|
|
68
87
|
}
|
|
69
|
-
|
|
70
|
-
code = typeof body2.code === "string" ? body2.code : JSON.stringify(body2.code);
|
|
71
|
-
} else if (typeof body2.errorString === "string") {
|
|
72
|
-
code = body2.errorString;
|
|
73
|
-
}
|
|
88
|
+
code = errorCodeFrom(body2, code);
|
|
74
89
|
} catch {
|
|
75
90
|
if (text) {
|
|
76
91
|
const stripped = text.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -393,48 +408,37 @@ async function executeDbBatchOverWs(url, token, databaseId, queries) {
|
|
|
393
408
|
}
|
|
394
409
|
|
|
395
410
|
// src/rate-limit.ts
|
|
396
|
-
var
|
|
397
|
-
internal:
|
|
398
|
-
apiKey:
|
|
411
|
+
var DEFAULT_CONCURRENCY = {
|
|
412
|
+
internal: 10,
|
|
413
|
+
apiKey: 20
|
|
399
414
|
};
|
|
400
415
|
var RateLimiter = class {
|
|
416
|
+
concurrencyLimit;
|
|
417
|
+
// Keyed by the request's context object, so an execution's slots go when it does.
|
|
418
|
+
perRequest = /* @__PURE__ */ new WeakMap();
|
|
419
|
+
shared = { inflight: 0, queue: [] };
|
|
401
420
|
constructor(authType) {
|
|
402
|
-
this.
|
|
403
|
-
this.concurrencyLimit = DEFAULTS[authType].concurrency;
|
|
404
|
-
this.callCap = DEFAULTS[authType].callCap;
|
|
421
|
+
this.concurrencyLimit = DEFAULT_CONCURRENCY[authType];
|
|
405
422
|
}
|
|
406
|
-
authType;
|
|
407
|
-
inflight = 0;
|
|
408
|
-
concurrencyLimit;
|
|
409
|
-
callCount = 0;
|
|
410
|
-
callCap;
|
|
411
|
-
queue = [];
|
|
412
423
|
/** Acquire a slot. Resolves when a concurrent slot is available. */
|
|
413
424
|
async acquire() {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
"call_cap_exceeded",
|
|
418
|
-
429
|
|
419
|
-
);
|
|
420
|
-
}
|
|
421
|
-
if (this.inflight < this.concurrencyLimit) {
|
|
422
|
-
this.inflight++;
|
|
423
|
-
this.callCount++;
|
|
425
|
+
const slots = this.slots();
|
|
426
|
+
if (slots.inflight < this.concurrencyLimit) {
|
|
427
|
+
slots.inflight++;
|
|
424
428
|
return;
|
|
425
429
|
}
|
|
426
430
|
return new Promise((resolve) => {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
this.callCount++;
|
|
431
|
+
slots.queue.push(() => {
|
|
432
|
+
slots.inflight++;
|
|
430
433
|
resolve();
|
|
431
434
|
});
|
|
432
435
|
});
|
|
433
436
|
}
|
|
434
437
|
/** Release a slot and let the next queued request proceed. */
|
|
435
438
|
release() {
|
|
436
|
-
this.
|
|
437
|
-
|
|
439
|
+
const slots = this.slots();
|
|
440
|
+
slots.inflight--;
|
|
441
|
+
const next = slots.queue.shift();
|
|
438
442
|
if (next) {
|
|
439
443
|
next();
|
|
440
444
|
}
|
|
@@ -445,21 +449,19 @@ var RateLimiter = class {
|
|
|
445
449
|
if (concurrency) {
|
|
446
450
|
this.concurrencyLimit = parseInt(concurrency, 10);
|
|
447
451
|
}
|
|
448
|
-
const limit = headers.get("x-ratelimit-limit");
|
|
449
|
-
if (limit && this.authType === "internal") {
|
|
450
|
-
this.callCap = parseInt(limit, 10);
|
|
451
|
-
}
|
|
452
452
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
453
|
+
// Release runs in the same async chain as its acquire, so both resolve the same request's slots.
|
|
454
|
+
slots() {
|
|
455
|
+
const ctx = getRequestContext();
|
|
456
|
+
if (!ctx) {
|
|
457
|
+
return this.shared;
|
|
458
|
+
}
|
|
459
|
+
let slots = this.perRequest.get(ctx);
|
|
460
|
+
if (!slots) {
|
|
461
|
+
slots = { inflight: 0, queue: [] };
|
|
462
|
+
this.perRequest.set(ctx, slots);
|
|
463
|
+
}
|
|
464
|
+
return slots;
|
|
463
465
|
}
|
|
464
466
|
};
|
|
465
467
|
|
|
@@ -5013,7 +5015,7 @@ async function runTaskPoll(httpConfig, body) {
|
|
|
5013
5015
|
const errorBody = await res.json().catch(() => ({}));
|
|
5014
5016
|
throw new MindStudioError(
|
|
5015
5017
|
errorBody.message ?? errorBody.error ?? `Task poll failed: ${res.status} ${res.statusText}`,
|
|
5016
|
-
errorBody
|
|
5018
|
+
errorCodeFrom(errorBody, "poll_error"),
|
|
5017
5019
|
res.status,
|
|
5018
5020
|
errorBody
|
|
5019
5021
|
);
|
|
@@ -5077,9 +5079,7 @@ async function runTaskStream(httpConfig, body, onEvent) {
|
|
|
5077
5079
|
if (errMsg) {
|
|
5078
5080
|
message = errMsg;
|
|
5079
5081
|
}
|
|
5080
|
-
|
|
5081
|
-
code = errBody.code;
|
|
5082
|
-
}
|
|
5082
|
+
code = errorCodeFrom(errBody, code);
|
|
5083
5083
|
} catch {
|
|
5084
5084
|
const stripped = text.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
|
|
5085
5085
|
if (stripped) {
|
|
@@ -6294,8 +6294,18 @@ var MindStudioAgent = class {
|
|
|
6294
6294
|
options
|
|
6295
6295
|
);
|
|
6296
6296
|
}
|
|
6297
|
+
return withSlot(
|
|
6298
|
+
this._httpConfig,
|
|
6299
|
+
() => this._executeStepPolled(stepType, step, options)
|
|
6300
|
+
);
|
|
6301
|
+
}
|
|
6302
|
+
/**
|
|
6303
|
+
* @internal Async step execution — POST, then poll until the step finishes.
|
|
6304
|
+
* Runs inside one concurrency slot (see `withSlot`).
|
|
6305
|
+
*/
|
|
6306
|
+
async _executeStepPolled(stepType, step, options) {
|
|
6297
6307
|
const threadId = options?.threadId ?? (this._reuseThreadId && !getRequestContext() ? this._threadId : void 0);
|
|
6298
|
-
const { data: asyncData, headers } = await
|
|
6308
|
+
const { data: asyncData, headers } = await sendRequest(this._currentHttpConfig, "POST", `/steps/${stepType}/execute-async`, {
|
|
6299
6309
|
step,
|
|
6300
6310
|
...options?.appId != null && { appId: options.appId },
|
|
6301
6311
|
...threadId != null && { threadId },
|
|
@@ -6335,7 +6345,7 @@ var MindStudioAgent = class {
|
|
|
6335
6345
|
const errorBody = await res.json().catch(() => ({}));
|
|
6336
6346
|
throw new MindStudioError(
|
|
6337
6347
|
errorBody.message ?? errorBody.error ?? `[${stepType}] Poll failed: ${res.status} ${res.statusText}`,
|
|
6338
|
-
errorBody
|
|
6348
|
+
errorCodeFrom(errorBody, "poll_error"),
|
|
6339
6349
|
res.status,
|
|
6340
6350
|
errorBody
|
|
6341
6351
|
);
|
|
@@ -6431,9 +6441,7 @@ var MindStudioAgent = class {
|
|
|
6431
6441
|
body2.error ?? body2.message ?? body2.details
|
|
6432
6442
|
);
|
|
6433
6443
|
}
|
|
6434
|
-
|
|
6435
|
-
code = body2.code;
|
|
6436
|
-
}
|
|
6444
|
+
code = errorCodeFrom(body2, code);
|
|
6437
6445
|
} catch {
|
|
6438
6446
|
const stripped = text.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
|
|
6439
6447
|
if (stripped) {
|
|
@@ -6585,8 +6593,18 @@ var MindStudioAgent = class {
|
|
|
6585
6593
|
* ```
|
|
6586
6594
|
*/
|
|
6587
6595
|
async executeStepBatch(steps, options) {
|
|
6596
|
+
return withSlot(
|
|
6597
|
+
this._httpConfig,
|
|
6598
|
+
() => this._executeStepBatchPolled(steps, options)
|
|
6599
|
+
);
|
|
6600
|
+
}
|
|
6601
|
+
/**
|
|
6602
|
+
* @internal Async batch execution — POST, then poll until the batch settles.
|
|
6603
|
+
* Runs inside one concurrency slot (see `withSlot`).
|
|
6604
|
+
*/
|
|
6605
|
+
async _executeStepBatchPolled(steps, options) {
|
|
6588
6606
|
const threadId = options?.threadId ?? (this._reuseThreadId && !getRequestContext() ? this._threadId : void 0);
|
|
6589
|
-
const { data: asyncData } = await
|
|
6607
|
+
const { data: asyncData } = await sendRequest(this._currentHttpConfig, "POST", "/steps/execute-batch-async", {
|
|
6590
6608
|
steps: steps.map((s) => ({
|
|
6591
6609
|
...s,
|
|
6592
6610
|
stepType: resolveStepType2(s.stepType)
|
|
@@ -6620,7 +6638,7 @@ var MindStudioAgent = class {
|
|
|
6620
6638
|
const errorBody = await res.json().catch(() => ({}));
|
|
6621
6639
|
throw new MindStudioError(
|
|
6622
6640
|
errorBody.message ?? errorBody.error ?? `Batch poll failed: ${res.status} ${res.statusText}`,
|
|
6623
|
-
errorBody
|
|
6641
|
+
errorCodeFrom(errorBody, "poll_error"),
|
|
6624
6642
|
res.status,
|
|
6625
6643
|
errorBody
|
|
6626
6644
|
);
|
|
@@ -6916,7 +6934,7 @@ var MindStudioAgent = class {
|
|
|
6916
6934
|
const errorBody = await res.json().catch(() => ({}));
|
|
6917
6935
|
throw new MindStudioError(
|
|
6918
6936
|
errorBody.message ?? errorBody.error ?? `Poll request failed: ${res.status} ${res.statusText}`,
|
|
6919
|
-
errorBody
|
|
6937
|
+
errorCodeFrom(errorBody, "poll_error"),
|
|
6920
6938
|
res.status,
|
|
6921
6939
|
errorBody
|
|
6922
6940
|
);
|
|
@@ -7604,9 +7622,7 @@ var MindStudioAgent = class {
|
|
|
7604
7622
|
body.error ?? body.message ?? body.details
|
|
7605
7623
|
);
|
|
7606
7624
|
}
|
|
7607
|
-
|
|
7608
|
-
code = body.code;
|
|
7609
|
-
}
|
|
7625
|
+
code = errorCodeFrom(body, code);
|
|
7610
7626
|
} catch {
|
|
7611
7627
|
if (text && text.length < 500) {
|
|
7612
7628
|
message = text;
|
|
@@ -8225,7 +8241,7 @@ function deletes(externalIds) {
|
|
|
8225
8241
|
};
|
|
8226
8242
|
}
|
|
8227
8243
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
8228
|
-
var
|
|
8244
|
+
var DEFAULT_CONCURRENCY2 = 4;
|
|
8229
8245
|
function errorInfo2(e) {
|
|
8230
8246
|
if (e instanceof Error) {
|
|
8231
8247
|
return { message: e.message, stack: e.stack };
|
|
@@ -8297,7 +8313,7 @@ function defineMapper(source, config) {
|
|
|
8297
8313
|
const run = async (params) => {
|
|
8298
8314
|
const startedAt = Date.now();
|
|
8299
8315
|
const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
8300
|
-
const concurrency = Math.max(1, params.concurrency ??
|
|
8316
|
+
const concurrency = Math.max(1, params.concurrency ?? DEFAULT_CONCURRENCY2);
|
|
8301
8317
|
const objects = Array.isArray(params.objects) ? params.objects : [];
|
|
8302
8318
|
const outcomes = new Array(objects.length);
|
|
8303
8319
|
let next = 0;
|