@mindstudio-ai/agent 0.1.34 → 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 +144 -31
- package/dist/index.d.ts +40 -1
- package/dist/index.js +136 -25
- package/dist/index.js.map +1 -1
- package/dist/postinstall.js +144 -31
- 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);
|
|
@@ -4011,7 +4078,9 @@ var init_client = __esm({
|
|
|
4011
4078
|
this._auth = new AuthContext(context.auth);
|
|
4012
4079
|
this._db = createDb(
|
|
4013
4080
|
context.databases,
|
|
4014
|
-
this._executeDbBatch.bind(this)
|
|
4081
|
+
this._executeDbBatch.bind(this),
|
|
4082
|
+
context.authConfig,
|
|
4083
|
+
this._syncRoles.bind(this)
|
|
4015
4084
|
);
|
|
4016
4085
|
}
|
|
4017
4086
|
/**
|
|
@@ -4027,7 +4096,8 @@ var init_client = __esm({
|
|
|
4027
4096
|
if (ai?.auth && ai?.databases) {
|
|
4028
4097
|
this._applyContext({
|
|
4029
4098
|
auth: ai.auth,
|
|
4030
|
-
databases: ai.databases
|
|
4099
|
+
databases: ai.databases,
|
|
4100
|
+
authConfig: ai.authConfig
|
|
4031
4101
|
});
|
|
4032
4102
|
}
|
|
4033
4103
|
}
|
|
@@ -4073,6 +4143,39 @@ var init_client = __esm({
|
|
|
4073
4143
|
const data = await res.json();
|
|
4074
4144
|
return data.results;
|
|
4075
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
|
+
}
|
|
4076
4179
|
/**
|
|
4077
4180
|
* @internal Create a lazy Db proxy that auto-hydrates context.
|
|
4078
4181
|
*
|
|
@@ -4085,7 +4188,7 @@ var init_client = __esm({
|
|
|
4085
4188
|
return {
|
|
4086
4189
|
defineTable(name, options) {
|
|
4087
4190
|
const databaseHint = options?.database;
|
|
4088
|
-
|
|
4191
|
+
const tableConfig = {
|
|
4089
4192
|
databaseId: "",
|
|
4090
4193
|
tableName: name,
|
|
4091
4194
|
columns: [],
|
|
@@ -4093,6 +4196,13 @@ var init_client = __esm({
|
|
|
4093
4196
|
defaults: options?.defaults,
|
|
4094
4197
|
executeBatch: async (queries) => {
|
|
4095
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
|
+
}
|
|
4096
4206
|
const databases = agent._context.databases;
|
|
4097
4207
|
let targetDb;
|
|
4098
4208
|
if (databaseHint) {
|
|
@@ -4107,7 +4217,8 @@ var init_client = __esm({
|
|
|
4107
4217
|
const databaseId = targetDb?.id ?? databases[0]?.id ?? "";
|
|
4108
4218
|
return agent._executeDbBatch(databaseId, queries);
|
|
4109
4219
|
}
|
|
4110
|
-
}
|
|
4220
|
+
};
|
|
4221
|
+
return new Table(tableConfig);
|
|
4111
4222
|
},
|
|
4112
4223
|
// Time helpers work without context
|
|
4113
4224
|
now: () => Date.now(),
|
|
@@ -4566,6 +4677,8 @@ var init_instructions = __esm({
|
|
|
4566
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.
|
|
4567
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.
|
|
4568
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.
|
|
4569
4682
|
</anti_patterns>
|
|
4570
4683
|
|
|
4571
4684
|
<model_guidance>
|
|
@@ -4885,7 +4998,7 @@ async function startMcpServer(options) {
|
|
|
4885
4998
|
capabilities: { tools: {} },
|
|
4886
4999
|
serverInfo: {
|
|
4887
5000
|
name: "mindstudio-agent",
|
|
4888
|
-
version: "0.1.
|
|
5001
|
+
version: "0.1.35"
|
|
4889
5002
|
},
|
|
4890
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.'
|
|
4891
5004
|
});
|
|
@@ -5745,7 +5858,7 @@ function isNewerVersion(current, latest) {
|
|
|
5745
5858
|
return false;
|
|
5746
5859
|
}
|
|
5747
5860
|
async function checkForUpdate() {
|
|
5748
|
-
const currentVersion = "0.1.
|
|
5861
|
+
const currentVersion = "0.1.35";
|
|
5749
5862
|
if (!currentVersion) return null;
|
|
5750
5863
|
try {
|
|
5751
5864
|
const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
@@ -5774,7 +5887,7 @@ async function checkForUpdate() {
|
|
|
5774
5887
|
}
|
|
5775
5888
|
}
|
|
5776
5889
|
function printUpdateNotice(latestVersion) {
|
|
5777
|
-
const currentVersion = "0.1.
|
|
5890
|
+
const currentVersion = "0.1.35";
|
|
5778
5891
|
process.stderr.write(
|
|
5779
5892
|
`
|
|
5780
5893
|
${ansi2.cyanBright("Update available")} ${ansi2.gray(currentVersion + " \u2192")} ${ansi2.cyanBold(latestVersion)}
|
|
@@ -5787,7 +5900,7 @@ function isStandaloneBinary() {
|
|
|
5787
5900
|
return !argv1.includes("node_modules");
|
|
5788
5901
|
}
|
|
5789
5902
|
async function cmdUpdate() {
|
|
5790
|
-
const currentVersion = "0.1.
|
|
5903
|
+
const currentVersion = "0.1.35";
|
|
5791
5904
|
process.stderr.write(
|
|
5792
5905
|
` ${ansi2.gray("Current version:")} ${currentVersion}
|
|
5793
5906
|
`
|
|
@@ -5902,7 +6015,7 @@ async function cmdLogin(options) {
|
|
|
5902
6015
|
process.stderr.write("\n");
|
|
5903
6016
|
printLogo();
|
|
5904
6017
|
process.stderr.write("\n");
|
|
5905
|
-
const ver = "0.1.
|
|
6018
|
+
const ver = "0.1.35";
|
|
5906
6019
|
process.stderr.write(
|
|
5907
6020
|
` ${ansi2.bold("MindStudio Agent")} ${ver ? " " + ansi2.gray("v" + ver) : ""}
|
|
5908
6021
|
`
|
|
@@ -6213,7 +6326,7 @@ async function main() {
|
|
|
6213
6326
|
try {
|
|
6214
6327
|
if (command === "version" || command === "-v") {
|
|
6215
6328
|
process.stdout.write(
|
|
6216
|
-
"0.1.
|
|
6329
|
+
"0.1.35\n"
|
|
6217
6330
|
);
|
|
6218
6331
|
return;
|
|
6219
6332
|
}
|