@mindstudio-ai/agent 0.1.33 → 0.1.35
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 +151 -33
- package/dist/index.d.ts +40 -1
- package/dist/index.js +1265 -1150
- package/dist/index.js.map +1 -1
- package/dist/postinstall.js +151 -33
- package/package.json +1 -1
package/dist/postinstall.js
CHANGED
|
@@ -1225,13 +1225,23 @@ async function requestWithRetry(config, method, url, body, attempt) {
|
|
|
1225
1225
|
return requestWithRetry(config, method, url, body, attempt + 1);
|
|
1226
1226
|
}
|
|
1227
1227
|
if (!res.ok) {
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
res.
|
|
1233
|
-
|
|
1234
|
-
|
|
1228
|
+
let message = `${res.status} ${res.statusText}`;
|
|
1229
|
+
let code = "api_error";
|
|
1230
|
+
let details;
|
|
1231
|
+
try {
|
|
1232
|
+
const text = await res.text();
|
|
1233
|
+
try {
|
|
1234
|
+
const body2 = JSON.parse(text);
|
|
1235
|
+
details = body2;
|
|
1236
|
+
const errMsg = body2.error ?? body2.message ?? body2.details;
|
|
1237
|
+
if (errMsg) message = errMsg;
|
|
1238
|
+
if (body2.code) code = body2.code;
|
|
1239
|
+
} catch {
|
|
1240
|
+
if (text && text.length < 500) message = text;
|
|
1241
|
+
}
|
|
1242
|
+
} catch {
|
|
1243
|
+
}
|
|
1244
|
+
throw new MindStudioError(message, code, res.status, details);
|
|
1235
1245
|
}
|
|
1236
1246
|
const data = await res.json();
|
|
1237
1247
|
return { data, headers: res.headers };
|
|
@@ -2515,6 +2525,9 @@ var init_table = __esm({
|
|
|
2515
2525
|
const items = (isArray ? data : [data]).map(
|
|
2516
2526
|
(item) => this._config.defaults ? { ...this._config.defaults, ...item } : item
|
|
2517
2527
|
);
|
|
2528
|
+
for (const item of items) {
|
|
2529
|
+
this._checkManagedColumns(item);
|
|
2530
|
+
}
|
|
2518
2531
|
const queries = items.map(
|
|
2519
2532
|
(item) => buildInsert(
|
|
2520
2533
|
this._config.tableName,
|
|
@@ -2532,7 +2545,13 @@ var init_table = __esm({
|
|
|
2532
2545
|
}
|
|
2533
2546
|
return void 0;
|
|
2534
2547
|
});
|
|
2535
|
-
|
|
2548
|
+
const result = isArray ? rows : rows[0];
|
|
2549
|
+
this._syncRolesIfNeeded(
|
|
2550
|
+
items,
|
|
2551
|
+
result,
|
|
2552
|
+
isArray
|
|
2553
|
+
);
|
|
2554
|
+
return result;
|
|
2536
2555
|
});
|
|
2537
2556
|
}
|
|
2538
2557
|
/**
|
|
@@ -2540,20 +2559,25 @@ var init_table = __esm({
|
|
|
2540
2559
|
* Returns the updated row via `UPDATE ... RETURNING *`.
|
|
2541
2560
|
*/
|
|
2542
2561
|
update(id, data) {
|
|
2562
|
+
this._checkManagedColumns(data);
|
|
2543
2563
|
const query = buildUpdate(
|
|
2544
2564
|
this._config.tableName,
|
|
2545
2565
|
id,
|
|
2546
2566
|
data,
|
|
2547
2567
|
this._config.columns
|
|
2548
2568
|
);
|
|
2549
|
-
return new Mutation(
|
|
2550
|
-
|
|
2551
|
-
[query],
|
|
2552
|
-
(results) => deserializeRow(
|
|
2569
|
+
return new Mutation(this._config, [query], (results) => {
|
|
2570
|
+
const result = deserializeRow(
|
|
2553
2571
|
results[0].rows[0],
|
|
2554
2572
|
this._config.columns
|
|
2555
|
-
)
|
|
2556
|
-
|
|
2573
|
+
);
|
|
2574
|
+
this._syncRolesIfNeeded(
|
|
2575
|
+
[data],
|
|
2576
|
+
result,
|
|
2577
|
+
false
|
|
2578
|
+
);
|
|
2579
|
+
return result;
|
|
2580
|
+
});
|
|
2557
2581
|
}
|
|
2558
2582
|
remove(id) {
|
|
2559
2583
|
const query = buildDelete(this._config.tableName, `id = ?`, [id]);
|
|
@@ -2608,24 +2632,65 @@ var init_table = __esm({
|
|
|
2608
2632
|
const conflictColumns = Array.isArray(conflictKey) ? conflictKey : [conflictKey];
|
|
2609
2633
|
this._validateUniqueConstraint(conflictColumns);
|
|
2610
2634
|
const withDefaults = this._config.defaults ? { ...this._config.defaults, ...data } : data;
|
|
2635
|
+
this._checkManagedColumns(withDefaults);
|
|
2611
2636
|
const query = buildUpsert(
|
|
2612
2637
|
this._config.tableName,
|
|
2613
2638
|
withDefaults,
|
|
2614
2639
|
conflictColumns,
|
|
2615
2640
|
this._config.columns
|
|
2616
2641
|
);
|
|
2617
|
-
return new Mutation(
|
|
2618
|
-
|
|
2619
|
-
[query],
|
|
2620
|
-
(results) => deserializeRow(
|
|
2642
|
+
return new Mutation(this._config, [query], (results) => {
|
|
2643
|
+
const result = deserializeRow(
|
|
2621
2644
|
results[0].rows[0],
|
|
2622
2645
|
this._config.columns
|
|
2623
|
-
)
|
|
2624
|
-
|
|
2646
|
+
);
|
|
2647
|
+
this._syncRolesIfNeeded([withDefaults], result, false);
|
|
2648
|
+
return result;
|
|
2649
|
+
});
|
|
2625
2650
|
}
|
|
2626
2651
|
// -------------------------------------------------------------------------
|
|
2627
2652
|
// Internal helpers
|
|
2628
2653
|
// -------------------------------------------------------------------------
|
|
2654
|
+
/** @internal Throw if data includes a platform-managed email/phone column. */
|
|
2655
|
+
_checkManagedColumns(data) {
|
|
2656
|
+
const mc = this._config.managedColumns;
|
|
2657
|
+
if (!mc) return;
|
|
2658
|
+
const keys = Object.keys(data);
|
|
2659
|
+
for (const key of keys) {
|
|
2660
|
+
if (mc.email && key === mc.email || mc.phone && key === mc.phone) {
|
|
2661
|
+
throw new MindStudioError(
|
|
2662
|
+
`Cannot write to "${key}" \u2014 this column is managed by auth. Use the auth API to change a user's ${key === mc.email ? "email" : "phone"}.`,
|
|
2663
|
+
"managed_column_write",
|
|
2664
|
+
400
|
|
2665
|
+
);
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
/**
|
|
2670
|
+
* @internal Fire role sync for rows that wrote to the roles column.
|
|
2671
|
+
* Called inside processResult (runs after SQL execution in both
|
|
2672
|
+
* standalone and batch paths). Fire-and-forget.
|
|
2673
|
+
*/
|
|
2674
|
+
_syncRolesIfNeeded(inputItems, result, isArray) {
|
|
2675
|
+
const rolesCol = this._config.managedColumns?.roles;
|
|
2676
|
+
const syncRoles = this._config.syncRoles;
|
|
2677
|
+
if (!rolesCol || !syncRoles) return;
|
|
2678
|
+
if (!inputItems.some((item) => rolesCol in item)) return;
|
|
2679
|
+
if (isArray) {
|
|
2680
|
+
for (const row of result) {
|
|
2681
|
+
if (row?.id) {
|
|
2682
|
+
syncRoles(row.id, row[rolesCol]).catch(() => {
|
|
2683
|
+
});
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
} else {
|
|
2687
|
+
const row = result;
|
|
2688
|
+
if (row?.id) {
|
|
2689
|
+
syncRoles(row.id, row[rolesCol]).catch(() => {
|
|
2690
|
+
});
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2629
2694
|
/** @internal Validate that the given columns match a declared unique constraint. */
|
|
2630
2695
|
_validateUniqueConstraint(columns) {
|
|
2631
2696
|
if (!this._config.unique?.length) {
|
|
@@ -2652,7 +2717,7 @@ var init_table = __esm({
|
|
|
2652
2717
|
});
|
|
2653
2718
|
|
|
2654
2719
|
// src/db/index.ts
|
|
2655
|
-
function createDb(databases, executeBatch) {
|
|
2720
|
+
function createDb(databases, executeBatch, authConfig, syncRoles) {
|
|
2656
2721
|
return {
|
|
2657
2722
|
defineTable(name, options) {
|
|
2658
2723
|
const resolved = resolveTable(databases, name, options?.database);
|
|
@@ -2662,6 +2727,8 @@ function createDb(databases, executeBatch) {
|
|
|
2662
2727
|
columns: resolved.columns,
|
|
2663
2728
|
unique: options?.unique,
|
|
2664
2729
|
defaults: options?.defaults,
|
|
2730
|
+
managedColumns: authConfig?.table === name ? authConfig.columns : void 0,
|
|
2731
|
+
syncRoles: authConfig?.table === name && authConfig.columns.roles ? syncRoles : void 0,
|
|
2665
2732
|
executeBatch: (queries) => executeBatch(resolved.databaseId, queries)
|
|
2666
2733
|
};
|
|
2667
2734
|
return new Table(config);
|
|
@@ -3295,6 +3362,10 @@ __export(client_exports, {
|
|
|
3295
3362
|
function sleep2(ms) {
|
|
3296
3363
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3297
3364
|
}
|
|
3365
|
+
function resolveStepType(name) {
|
|
3366
|
+
const meta = stepMetadata[name];
|
|
3367
|
+
return meta ? meta.stepType : name;
|
|
3368
|
+
}
|
|
3298
3369
|
function resolveToken(provided, config) {
|
|
3299
3370
|
if (process.env.CALLBACK_TOKEN)
|
|
3300
3371
|
return { token: process.env.CALLBACK_TOKEN, authType: "internal" };
|
|
@@ -3320,6 +3391,7 @@ var init_client = __esm({
|
|
|
3320
3391
|
init_auth();
|
|
3321
3392
|
init_db();
|
|
3322
3393
|
init_steps();
|
|
3394
|
+
init_metadata();
|
|
3323
3395
|
DEFAULT_BASE_URL = "https://v1.mindstudio-api.com";
|
|
3324
3396
|
DEFAULT_MAX_RETRIES = 3;
|
|
3325
3397
|
MindStudioAgent = class {
|
|
@@ -3616,7 +3688,7 @@ var init_client = __esm({
|
|
|
3616
3688
|
async executeStepBatch(steps, options) {
|
|
3617
3689
|
const threadId = options?.threadId ?? (this._reuseThreadId ? this._threadId : void 0);
|
|
3618
3690
|
const { data } = await request(this._httpConfig, "POST", "/steps/execute-batch", {
|
|
3619
|
-
steps,
|
|
3691
|
+
steps: steps.map((s) => ({ ...s, stepType: resolveStepType(s.stepType) })),
|
|
3620
3692
|
...options?.appId != null && { appId: options.appId },
|
|
3621
3693
|
...threadId != null && { threadId }
|
|
3622
3694
|
});
|
|
@@ -3849,7 +3921,7 @@ var init_client = __esm({
|
|
|
3849
3921
|
/** Estimate the cost of executing an action before running it. */
|
|
3850
3922
|
async estimateStepCost(stepType, step, options) {
|
|
3851
3923
|
const { data } = await request(this._httpConfig, "POST", "/helpers/step-cost-estimate", {
|
|
3852
|
-
step: { type: stepType, ...step },
|
|
3924
|
+
step: { type: resolveStepType(stepType), ...step },
|
|
3853
3925
|
...options
|
|
3854
3926
|
});
|
|
3855
3927
|
return data;
|
|
@@ -4006,7 +4078,9 @@ var init_client = __esm({
|
|
|
4006
4078
|
this._auth = new AuthContext(context.auth);
|
|
4007
4079
|
this._db = createDb(
|
|
4008
4080
|
context.databases,
|
|
4009
|
-
this._executeDbBatch.bind(this)
|
|
4081
|
+
this._executeDbBatch.bind(this),
|
|
4082
|
+
context.authConfig,
|
|
4083
|
+
this._syncRoles.bind(this)
|
|
4010
4084
|
);
|
|
4011
4085
|
}
|
|
4012
4086
|
/**
|
|
@@ -4022,7 +4096,8 @@ var init_client = __esm({
|
|
|
4022
4096
|
if (ai?.auth && ai?.databases) {
|
|
4023
4097
|
this._applyContext({
|
|
4024
4098
|
auth: ai.auth,
|
|
4025
|
-
databases: ai.databases
|
|
4099
|
+
databases: ai.databases,
|
|
4100
|
+
authConfig: ai.authConfig
|
|
4026
4101
|
});
|
|
4027
4102
|
}
|
|
4028
4103
|
}
|
|
@@ -4068,6 +4143,39 @@ var init_client = __esm({
|
|
|
4068
4143
|
const data = await res.json();
|
|
4069
4144
|
return data.results;
|
|
4070
4145
|
}
|
|
4146
|
+
/**
|
|
4147
|
+
* @internal Sync a user's roles to the platform after a successful
|
|
4148
|
+
* auth table write. Calls POST /_internal/v2/auth/sync-user.
|
|
4149
|
+
* Fire-and-forget: errors are caught and logged, never propagated.
|
|
4150
|
+
*/
|
|
4151
|
+
async _syncRoles(userId, roles) {
|
|
4152
|
+
try {
|
|
4153
|
+
const url = `${this._httpConfig.baseUrl}/_internal/v2/auth/sync-user`;
|
|
4154
|
+
const res = await fetch(url, {
|
|
4155
|
+
method: "POST",
|
|
4156
|
+
headers: {
|
|
4157
|
+
"Content-Type": "application/json",
|
|
4158
|
+
Authorization: this._token
|
|
4159
|
+
},
|
|
4160
|
+
body: JSON.stringify({
|
|
4161
|
+
appId: this._appId,
|
|
4162
|
+
userId,
|
|
4163
|
+
roles
|
|
4164
|
+
})
|
|
4165
|
+
});
|
|
4166
|
+
if (!res.ok) {
|
|
4167
|
+
const text = await res.text().catch(() => "");
|
|
4168
|
+
console.warn(
|
|
4169
|
+
`[mindstudio] Failed to sync roles for user ${userId}: ${res.status} ${text}`
|
|
4170
|
+
);
|
|
4171
|
+
}
|
|
4172
|
+
} catch (err) {
|
|
4173
|
+
console.warn(
|
|
4174
|
+
`[mindstudio] Failed to sync roles for user ${userId}:`,
|
|
4175
|
+
err
|
|
4176
|
+
);
|
|
4177
|
+
}
|
|
4178
|
+
}
|
|
4071
4179
|
/**
|
|
4072
4180
|
* @internal Create a lazy Db proxy that auto-hydrates context.
|
|
4073
4181
|
*
|
|
@@ -4080,7 +4188,7 @@ var init_client = __esm({
|
|
|
4080
4188
|
return {
|
|
4081
4189
|
defineTable(name, options) {
|
|
4082
4190
|
const databaseHint = options?.database;
|
|
4083
|
-
|
|
4191
|
+
const tableConfig = {
|
|
4084
4192
|
databaseId: "",
|
|
4085
4193
|
tableName: name,
|
|
4086
4194
|
columns: [],
|
|
@@ -4088,6 +4196,13 @@ var init_client = __esm({
|
|
|
4088
4196
|
defaults: options?.defaults,
|
|
4089
4197
|
executeBatch: async (queries) => {
|
|
4090
4198
|
await agent.ensureContext();
|
|
4199
|
+
const ac = agent._context.authConfig;
|
|
4200
|
+
if (ac && ac.table === name && !tableConfig.managedColumns) {
|
|
4201
|
+
tableConfig.managedColumns = ac.columns;
|
|
4202
|
+
if (ac.columns.roles) {
|
|
4203
|
+
tableConfig.syncRoles = agent._syncRoles.bind(agent);
|
|
4204
|
+
}
|
|
4205
|
+
}
|
|
4091
4206
|
const databases = agent._context.databases;
|
|
4092
4207
|
let targetDb;
|
|
4093
4208
|
if (databaseHint) {
|
|
@@ -4102,7 +4217,8 @@ var init_client = __esm({
|
|
|
4102
4217
|
const databaseId = targetDb?.id ?? databases[0]?.id ?? "";
|
|
4103
4218
|
return agent._executeDbBatch(databaseId, queries);
|
|
4104
4219
|
}
|
|
4105
|
-
}
|
|
4220
|
+
};
|
|
4221
|
+
return new Table(tableConfig);
|
|
4106
4222
|
},
|
|
4107
4223
|
// Time helpers work without context
|
|
4108
4224
|
now: () => Date.now(),
|
|
@@ -4561,6 +4677,8 @@ var init_instructions = __esm({
|
|
|
4561
4677
|
- **Missing MindStudioError handling** \u2014 the SDK has structured errors with \`code\`, \`status\`, \`details\`. Catching generic \`Error\` loses actionable information. Always include \`MindStudioError\` handling in code examples.
|
|
4562
4678
|
- **One-at-a-time db writes when batch exists** \u2014 N sequential \`update()\` or \`push()\` calls should be a single \`db.batch()\` call. One round trip instead of N.
|
|
4563
4679
|
- **Hardcoded model IDs without context** \u2014 model IDs can change. When writing code with a specific model, include a comment noting which model it is and why it was chosen, so the caller can swap it later.
|
|
4680
|
+
- Do not recommend using thread persistence. This is an advanced feature - if someone needs this they will discover it on their own.
|
|
4681
|
+
- Generate text is great for one-off text generation requests to models. For sustained conversations, conversations that require history, persistence, or multiple threads or tool use, recommend that the developer add an Agent interface to their MindStudio app and use that directly. They will understand what you mean by this.
|
|
4564
4682
|
</anti_patterns>
|
|
4565
4683
|
|
|
4566
4684
|
<model_guidance>
|
|
@@ -4880,7 +4998,7 @@ async function startMcpServer(options) {
|
|
|
4880
4998
|
capabilities: { tools: {} },
|
|
4881
4999
|
serverInfo: {
|
|
4882
5000
|
name: "mindstudio-agent",
|
|
4883
|
-
version: "0.1.
|
|
5001
|
+
version: "0.1.35"
|
|
4884
5002
|
},
|
|
4885
5003
|
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 or icon, call `uploadFile` to upload it, then `changeProfilePicture` with the returned URL.\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.'
|
|
4886
5004
|
});
|
|
@@ -5740,7 +5858,7 @@ function isNewerVersion(current, latest) {
|
|
|
5740
5858
|
return false;
|
|
5741
5859
|
}
|
|
5742
5860
|
async function checkForUpdate() {
|
|
5743
|
-
const currentVersion = "0.1.
|
|
5861
|
+
const currentVersion = "0.1.35";
|
|
5744
5862
|
if (!currentVersion) return null;
|
|
5745
5863
|
try {
|
|
5746
5864
|
const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
@@ -5769,7 +5887,7 @@ async function checkForUpdate() {
|
|
|
5769
5887
|
}
|
|
5770
5888
|
}
|
|
5771
5889
|
function printUpdateNotice(latestVersion) {
|
|
5772
|
-
const currentVersion = "0.1.
|
|
5890
|
+
const currentVersion = "0.1.35";
|
|
5773
5891
|
process.stderr.write(
|
|
5774
5892
|
`
|
|
5775
5893
|
${ansi2.cyanBright("Update available")} ${ansi2.gray(currentVersion + " \u2192")} ${ansi2.cyanBold(latestVersion)}
|
|
@@ -5782,7 +5900,7 @@ function isStandaloneBinary() {
|
|
|
5782
5900
|
return !argv1.includes("node_modules");
|
|
5783
5901
|
}
|
|
5784
5902
|
async function cmdUpdate() {
|
|
5785
|
-
const currentVersion = "0.1.
|
|
5903
|
+
const currentVersion = "0.1.35";
|
|
5786
5904
|
process.stderr.write(
|
|
5787
5905
|
` ${ansi2.gray("Current version:")} ${currentVersion}
|
|
5788
5906
|
`
|
|
@@ -5897,7 +6015,7 @@ async function cmdLogin(options) {
|
|
|
5897
6015
|
process.stderr.write("\n");
|
|
5898
6016
|
printLogo();
|
|
5899
6017
|
process.stderr.write("\n");
|
|
5900
|
-
const ver = "0.1.
|
|
6018
|
+
const ver = "0.1.35";
|
|
5901
6019
|
process.stderr.write(
|
|
5902
6020
|
` ${ansi2.bold("MindStudio Agent")} ${ver ? " " + ansi2.gray("v" + ver) : ""}
|
|
5903
6021
|
`
|
|
@@ -6208,7 +6326,7 @@ async function main() {
|
|
|
6208
6326
|
try {
|
|
6209
6327
|
if (command === "version" || command === "-v") {
|
|
6210
6328
|
process.stdout.write(
|
|
6211
|
-
"0.1.
|
|
6329
|
+
"0.1.35\n"
|
|
6212
6330
|
);
|
|
6213
6331
|
return;
|
|
6214
6332
|
}
|