@mindstudio-ai/agent 0.1.1 → 0.1.3

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 CHANGED
@@ -8,11 +8,31 @@ Generate text, images, video, and audio. Scrape the web. Search Google. Post to
8
8
 
9
9
  ## Install
10
10
 
11
+ ### CLI / MCP (standalone binary)
12
+
13
+ No dependencies required — downloads a standalone binary:
14
+
15
+ **macOS / Linux:**
16
+ ```bash
17
+ curl -fsSL https://msagent.ai/install.sh | bash
18
+ mindstudio login
19
+ ```
20
+
21
+ **Windows (PowerShell):**
22
+ ```
23
+ irm https://msagent.ai/install.ps1 | iex
24
+ mindstudio login
25
+ ```
26
+
27
+ To update, run the same command again. To uninstall, `rm /usr/local/bin/mindstudio` (macOS/Linux) or delete `%USERPROFILE%\.mindstudio\bin\mindstudio.exe` (Windows).
28
+
29
+ ### SDK (npm)
30
+
11
31
  ```bash
12
32
  npm install @mindstudio-ai/agent
13
33
  ```
14
34
 
15
- Requires Node.js 18+.
35
+ Requires Node.js 18+. Also installs the CLI as `mindstudio`.
16
36
 
17
37
  ## Quick start
18
38
 
@@ -77,6 +97,22 @@ npx @mindstudio-ai/agent generate-text --message "Hello"
77
97
 
78
98
  Add to your MCP client config (Claude Code, Cursor, VS Code, etc.):
79
99
 
100
+ **With standalone binary** (recommended — faster startup, no Node required):
101
+ ```json
102
+ {
103
+ "mcpServers": {
104
+ "mindstudio": {
105
+ "command": "mindstudio",
106
+ "args": ["mcp"],
107
+ "env": {
108
+ "MINDSTUDIO_API_KEY": "your-api-key"
109
+ }
110
+ }
111
+ }
112
+ }
113
+ ```
114
+
115
+ **With npx** (no install needed):
80
116
  ```json
81
117
  {
82
118
  "mcpServers": {
@@ -454,14 +490,14 @@ Start manually:
454
490
  mindstudio mcp
455
491
  ```
456
492
 
457
- Or configure your MCP client:
493
+ Or configure your MCP client (standalone binary or npx):
458
494
 
459
495
  ```json
460
496
  {
461
497
  "mcpServers": {
462
498
  "mindstudio": {
463
- "command": "npx",
464
- "args": ["-y", "@mindstudio-ai/agent", "mcp"],
499
+ "command": "mindstudio",
500
+ "args": ["mcp"],
465
501
  "env": {
466
502
  "MINDSTUDIO_API_KEY": "your-api-key"
467
503
  }
package/dist/cli.js CHANGED
@@ -1840,6 +1840,26 @@ function applyHelperMethods(AgentClass) {
1840
1840
  proto.estimateStepCost = function(stepType, step, options) {
1841
1841
  return this._request("POST", "/helpers/step-cost-estimate", { step: { type: stepType, ...step }, ...options }).then((r) => r.data);
1842
1842
  };
1843
+ proto.changeName = function(displayName) {
1844
+ return this._request("POST", "/account/change-name", { displayName }).then(() => {
1845
+ });
1846
+ };
1847
+ proto.changeProfilePicture = function(profilePictureUrl) {
1848
+ return this._request("POST", "/account/change-profile-picture", { profilePictureUrl }).then(() => {
1849
+ });
1850
+ };
1851
+ proto.uploadFile = async function(content, options) {
1852
+ const { data } = await this._request("POST", "/account/upload", { extension: options.extension, ...options.type != null && { type: options.type } });
1853
+ const { uploadUrl, url } = data;
1854
+ const buf = content.buffer.slice(content.byteOffset, content.byteOffset + content.byteLength);
1855
+ const res = await fetch(uploadUrl, {
1856
+ method: "PUT",
1857
+ body: buf,
1858
+ headers: options.type ? { "Content-Type": options.type } : {}
1859
+ });
1860
+ if (!res.ok) throw new Error(`Upload failed: ${res.status} ${res.statusText}`);
1861
+ return { url };
1862
+ };
1843
1863
  }
1844
1864
  var init_helpers = __esm({
1845
1865
  "src/generated/helpers.ts"() {
@@ -2041,6 +2061,8 @@ __export(mcp_exports, {
2041
2061
  startMcpServer: () => startMcpServer
2042
2062
  });
2043
2063
  import { createInterface } from "readline";
2064
+ import { readFileSync as readFileSync2 } from "fs";
2065
+ import { extname } from "path";
2044
2066
  function send(message) {
2045
2067
  process.stdout.write(JSON.stringify(message) + "\n");
2046
2068
  }
@@ -2093,8 +2115,9 @@ async function startMcpServer(options) {
2093
2115
  capabilities: { tools: {} },
2094
2116
  serverInfo: {
2095
2117
  name: "mindstudio-agent",
2096
- version: "0.1.1"
2097
- }
2118
+ version: "0.1.3"
2119
+ },
2120
+ instructions: "Welcome to MindStudio \u2014 a platform with 200+ AI models, 850+ third-party integrations, and pre-built agents.\n\nGetting started:\n1. Call `listAgents` to verify your connection and see available agents.\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. This helps users identify your requests in their logs.\n4. Call `listSteps` to discover all available step methods and helpers.\n\nThen use the tools to generate text, images, video, audio, search the web, work with data sources, run agents, and more."
2098
2121
  });
2099
2122
  break;
2100
2123
  case "notifications/initialized":
@@ -2153,6 +2176,26 @@ async function startMcpServer(options) {
2153
2176
  workflowId: args.workflowId
2154
2177
  }
2155
2178
  );
2179
+ } else if (toolName === "changeName") {
2180
+ await getAgent().changeName(
2181
+ args.displayName
2182
+ );
2183
+ result = { success: true };
2184
+ } else if (toolName === "changeProfilePicture") {
2185
+ await getAgent().changeProfilePicture(
2186
+ args.profilePictureUrl
2187
+ );
2188
+ result = { success: true };
2189
+ } else if (toolName === "uploadFile") {
2190
+ const filePath = args.filePath;
2191
+ const ext = extname(filePath).slice(1).toLowerCase();
2192
+ if (!ext) throw new Error("Cannot determine file extension from path.");
2193
+ const content = readFileSync2(filePath);
2194
+ const mimeType = MIME_TYPES[ext];
2195
+ result = await getAgent().uploadFile(content, {
2196
+ extension: ext,
2197
+ ...mimeType && { type: mimeType }
2198
+ });
2156
2199
  } else if (toolName === "listAgents") {
2157
2200
  result = await getAgent().listAgents();
2158
2201
  } else if (toolName === "runAgent") {
@@ -2207,12 +2250,28 @@ async function startMcpServer(options) {
2207
2250
  }
2208
2251
  }
2209
2252
  }
2210
- var MCP_PROTOCOL_VERSION, HELPER_DESCRIPTIONS, HELPER_TOOLS;
2253
+ var MCP_PROTOCOL_VERSION, MIME_TYPES, HELPER_DESCRIPTIONS, HELPER_TOOLS;
2211
2254
  var init_mcp = __esm({
2212
2255
  "src/mcp.ts"() {
2213
2256
  "use strict";
2214
2257
  init_client();
2215
2258
  MCP_PROTOCOL_VERSION = "2024-11-05";
2259
+ MIME_TYPES = {
2260
+ png: "image/png",
2261
+ jpg: "image/jpeg",
2262
+ jpeg: "image/jpeg",
2263
+ gif: "image/gif",
2264
+ webp: "image/webp",
2265
+ svg: "image/svg+xml",
2266
+ mp4: "video/mp4",
2267
+ webm: "video/webm",
2268
+ mp3: "audio/mpeg",
2269
+ wav: "audio/wav",
2270
+ pdf: "application/pdf",
2271
+ json: "application/json",
2272
+ txt: "text/plain",
2273
+ csv: "text/csv"
2274
+ };
2216
2275
  HELPER_DESCRIPTIONS = {
2217
2276
  listModels: "List all available AI models.",
2218
2277
  listModelsByType: "List AI models filtered by type.",
@@ -2223,13 +2282,16 @@ var init_mcp = __esm({
2223
2282
  getConnectorAction: "Get full configuration for a connector action.",
2224
2283
  listConnections: "List OAuth connections for the organization.",
2225
2284
  estimateStepCost: "Estimate the cost of executing a step before running it.",
2285
+ changeName: "Update the display name of the authenticated agent.",
2286
+ changeProfilePicture: "Update the profile picture of the authenticated agent.",
2287
+ uploadFile: "Upload a file to the MindStudio CDN.",
2226
2288
  listAgents: "List all pre-built agents in the organization.",
2227
2289
  runAgent: "Run a pre-built agent and wait for the result."
2228
2290
  };
2229
2291
  HELPER_TOOLS = [
2230
2292
  {
2231
2293
  name: "listSteps",
2232
- description: "List all available methods with their descriptions. Returns a compact { method: description } map. Use this first to discover what steps and helpers are available, then call a specific method by name.",
2294
+ description: "List all available methods with their descriptions. Returns a compact { method: description } map. Call this to discover what steps and helpers are available, then call a specific method by name. Tip: if you haven't already, call `changeName` to set your display name first.",
2233
2295
  inputSchema: { type: "object", properties: {} }
2234
2296
  },
2235
2297
  {
@@ -2350,6 +2412,48 @@ var init_mcp = __esm({
2350
2412
  required: ["stepType"]
2351
2413
  }
2352
2414
  },
2415
+ {
2416
+ name: "changeName",
2417
+ description: "Update the display name of the authenticated agent. Useful for agents to set their own name after connecting.",
2418
+ inputSchema: {
2419
+ type: "object",
2420
+ properties: {
2421
+ displayName: {
2422
+ type: "string",
2423
+ description: "The new display name."
2424
+ }
2425
+ },
2426
+ required: ["displayName"]
2427
+ }
2428
+ },
2429
+ {
2430
+ name: "changeProfilePicture",
2431
+ description: "Update the profile picture of the authenticated agent. Useful for agents to set their own avatar after connecting.",
2432
+ inputSchema: {
2433
+ type: "object",
2434
+ properties: {
2435
+ profilePictureUrl: {
2436
+ type: "string",
2437
+ description: "URL of the new profile picture."
2438
+ }
2439
+ },
2440
+ required: ["profilePictureUrl"]
2441
+ }
2442
+ },
2443
+ {
2444
+ name: "uploadFile",
2445
+ description: "Upload a local file to the MindStudio CDN. Returns the permanent public URL.",
2446
+ inputSchema: {
2447
+ type: "object",
2448
+ properties: {
2449
+ filePath: {
2450
+ type: "string",
2451
+ description: "Absolute or relative path to the file to upload."
2452
+ }
2453
+ },
2454
+ required: ["filePath"]
2455
+ }
2456
+ },
2353
2457
  {
2354
2458
  name: "listAgents",
2355
2459
  description: "List all pre-built agents in the organization along with org metadata.",
@@ -2389,12 +2493,15 @@ var init_mcp = __esm({
2389
2493
  // src/cli.ts
2390
2494
  import { parseArgs } from "util";
2391
2495
  import { execSync } from "child_process";
2496
+ import { readFileSync as readFileSync3 } from "fs";
2497
+ import { extname as extname2 } from "path";
2392
2498
  var HELP = `Usage: mindstudio <command | method> [options]
2393
2499
 
2394
2500
  Commands:
2395
2501
  login Authenticate with MindStudio (opens browser)
2396
2502
  logout Clear stored credentials
2397
2503
  whoami Show current authentication status
2504
+ upload <filepath> Upload a file to the MindStudio CDN
2398
2505
  <method> [json | --flags] Execute a step method (shorthand for exec)
2399
2506
  exec <method> [json | --flags] Execute a step method
2400
2507
  list [--json] [--summary] List available methods (--summary for compact JSON)
@@ -2495,7 +2602,9 @@ var HELPER_NAMES = /* @__PURE__ */ new Set([
2495
2602
  "getConnector",
2496
2603
  "getConnectorAction",
2497
2604
  "listConnections",
2498
- "estimateStepCost"
2605
+ "estimateStepCost",
2606
+ "changeName",
2607
+ "changeProfilePicture"
2499
2608
  ]);
2500
2609
  function resolveMethodOrFail(name, metadataKeys) {
2501
2610
  if (metadataKeys.has(name)) return name;
@@ -2530,6 +2639,8 @@ var HELPER_DESCRIPTIONS2 = {
2530
2639
  getConnectorAction: "Get full configuration for a connector action.",
2531
2640
  listConnections: "List OAuth connections for the organization.",
2532
2641
  estimateStepCost: "Estimate the cost of executing a step before running it.",
2642
+ changeName: "Update the display name of the authenticated agent.",
2643
+ changeProfilePicture: "Update the profile picture of the authenticated agent.",
2533
2644
  listAgents: "List all pre-built agents in the organization.",
2534
2645
  runAgent: "Run a pre-built agent and wait for the result."
2535
2646
  };
@@ -2546,9 +2657,7 @@ function buildSummary(stepMetadata2) {
2546
2657
  async function cmdList(asJson, asSummary) {
2547
2658
  const { stepMetadata: stepMetadata2 } = await Promise.resolve().then(() => (init_metadata(), metadata_exports));
2548
2659
  if (asSummary) {
2549
- process.stdout.write(
2550
- JSON.stringify(buildSummary(stepMetadata2)) + "\n"
2551
- );
2660
+ process.stdout.write(JSON.stringify(buildSummary(stepMetadata2)) + "\n");
2552
2661
  } else if (asJson) {
2553
2662
  const entries = Object.entries(stepMetadata2).map(([name, meta]) => ({
2554
2663
  method: camelToKebab(name),
@@ -2579,15 +2688,61 @@ async function cmdInfo(rawMethod) {
2579
2688
  const method = resolveMethodOrFail(rawMethod, allKeys);
2580
2689
  if (HELPER_NAMES.has(method)) {
2581
2690
  const helpers = {
2582
- listModels: { desc: "List all available AI models.", input: "(none)", output: "{ models: MindStudioModel[] }" },
2583
- listModelsByType: { desc: "List AI models filtered by type.", input: "modelType: string (required)", output: "{ models: MindStudioModel[] }" },
2584
- listModelsSummary: { desc: "List all AI models (summary: id, name, type, tags).", input: "(none)", output: "{ models: MindStudioModelSummary[] }" },
2585
- listModelsSummaryByType: { desc: "List AI models (summary) filtered by type.", input: "modelType: string (required)", output: "{ models: MindStudioModelSummary[] }" },
2586
- listConnectors: { desc: "List available connector services and their actions.", input: "(none)", output: "{ services: ConnectorService[] }" },
2587
- getConnector: { desc: "Get details for a connector service.", input: "serviceId: string (required)", output: "{ service: ConnectorService }" },
2588
- getConnectorAction: { desc: "Get full configuration for a connector action.", input: "serviceId: string, actionId: string (both required)", output: "{ action: ConnectorActionDetail }" },
2589
- listConnections: { desc: "List OAuth connections for the organization.", input: "(none)", output: "{ connections: Connection[] }" },
2590
- estimateStepCost: { desc: "Estimate the cost of executing a step before running it.", input: "stepType: string (required), step: object, appId?: string, workflowId?: string", output: "{ costType?: string, estimates?: StepCostEstimateEntry[] }" }
2691
+ listModels: {
2692
+ desc: "List all available AI models.",
2693
+ input: "(none)",
2694
+ output: "{ models: MindStudioModel[] }"
2695
+ },
2696
+ listModelsByType: {
2697
+ desc: "List AI models filtered by type.",
2698
+ input: "modelType: string (required)",
2699
+ output: "{ models: MindStudioModel[] }"
2700
+ },
2701
+ listModelsSummary: {
2702
+ desc: "List all AI models (summary: id, name, type, tags).",
2703
+ input: "(none)",
2704
+ output: "{ models: MindStudioModelSummary[] }"
2705
+ },
2706
+ listModelsSummaryByType: {
2707
+ desc: "List AI models (summary) filtered by type.",
2708
+ input: "modelType: string (required)",
2709
+ output: "{ models: MindStudioModelSummary[] }"
2710
+ },
2711
+ listConnectors: {
2712
+ desc: "List available connector services and their actions.",
2713
+ input: "(none)",
2714
+ output: "{ services: ConnectorService[] }"
2715
+ },
2716
+ getConnector: {
2717
+ desc: "Get details for a connector service.",
2718
+ input: "serviceId: string (required)",
2719
+ output: "{ service: ConnectorService }"
2720
+ },
2721
+ getConnectorAction: {
2722
+ desc: "Get full configuration for a connector action.",
2723
+ input: "serviceId: string, actionId: string (both required)",
2724
+ output: "{ action: ConnectorActionDetail }"
2725
+ },
2726
+ listConnections: {
2727
+ desc: "List OAuth connections for the organization.",
2728
+ input: "(none)",
2729
+ output: "{ connections: Connection[] }"
2730
+ },
2731
+ estimateStepCost: {
2732
+ desc: "Estimate the cost of executing a step before running it.",
2733
+ input: "stepType: string (required), step: object, appId?: string, workflowId?: string",
2734
+ output: "{ costType?: string, estimates?: StepCostEstimateEntry[] }"
2735
+ },
2736
+ changeName: {
2737
+ desc: "Update the display name of the authenticated agent.",
2738
+ input: "displayName: string (required)",
2739
+ output: "(none)"
2740
+ },
2741
+ changeProfilePicture: {
2742
+ desc: "Update the profile picture of the authenticated agent.",
2743
+ input: "profilePictureUrl: string (required)",
2744
+ output: "(none)"
2745
+ }
2591
2746
  };
2592
2747
  const h = helpers[method];
2593
2748
  process.stderr.write(`
@@ -2646,10 +2801,12 @@ async function cmdInfo(rawMethod) {
2646
2801
  process.stderr.write(out.join("\n") + "\n");
2647
2802
  }
2648
2803
  function formatPropType(prop) {
2649
- if (prop.enum) return prop.enum.map((v) => JSON.stringify(v)).join(" | ");
2804
+ if (prop.enum)
2805
+ return prop.enum.map((v) => JSON.stringify(v)).join(" | ");
2650
2806
  if (prop.type === "array") return "array";
2651
2807
  if (prop.type === "object") return "object";
2652
- if (typeof prop.type === "string") return prop.type === "integer" ? "number" : prop.type;
2808
+ if (typeof prop.type === "string")
2809
+ return prop.type === "integer" ? "number" : prop.type;
2653
2810
  return "string";
2654
2811
  }
2655
2812
  async function cmdExec(method, input, options) {
@@ -2672,9 +2829,7 @@ async function cmdExec(method, input, options) {
2672
2829
  } else if (method === "listModelsSummary") {
2673
2830
  result = await agent.listModelsSummary();
2674
2831
  } else if (method === "listModelsSummaryByType") {
2675
- result = await agent.listModelsSummaryByType(
2676
- input.modelType
2677
- );
2832
+ result = await agent.listModelsSummaryByType(input.modelType);
2678
2833
  } else if (method === "listConnectors") {
2679
2834
  result = await agent.listConnectors();
2680
2835
  } else if (method === "getConnector") {
@@ -2695,6 +2850,12 @@ async function cmdExec(method, input, options) {
2695
2850
  workflowId: input.workflowId
2696
2851
  }
2697
2852
  );
2853
+ } else if (method === "changeName") {
2854
+ await agent.changeName(input.displayName);
2855
+ result = { success: true };
2856
+ } else if (method === "changeProfilePicture") {
2857
+ await agent.changeProfilePicture(input.profilePictureUrl);
2858
+ result = { success: true };
2698
2859
  } else {
2699
2860
  const { stepMetadata: stepMetadata2 } = await Promise.resolve().then(() => (init_metadata(), metadata_exports));
2700
2861
  const meta = stepMetadata2[method];
@@ -2749,10 +2910,8 @@ async function cmdAgents(asJson, options) {
2749
2910
  );
2750
2911
  for (const app of result.apps) {
2751
2912
  const desc = app.description || "(no description)";
2752
- process.stdout.write(
2753
- `${app.name.padEnd(maxLen)} ${app.id} ${desc}
2754
- `
2755
- );
2913
+ process.stdout.write(`${app.name.padEnd(maxLen)} ${app.id} ${desc}
2914
+ `);
2756
2915
  }
2757
2916
  }
2758
2917
  }
@@ -2786,6 +2945,41 @@ async function cmdRun(appId, variables, options) {
2786
2945
  process.stdout.write(JSON.stringify(result, null, 2) + "\n");
2787
2946
  }
2788
2947
  }
2948
+ var MIME_TYPES2 = {
2949
+ png: "image/png",
2950
+ jpg: "image/jpeg",
2951
+ jpeg: "image/jpeg",
2952
+ gif: "image/gif",
2953
+ webp: "image/webp",
2954
+ svg: "image/svg+xml",
2955
+ mp4: "video/mp4",
2956
+ webm: "video/webm",
2957
+ mp3: "audio/mpeg",
2958
+ wav: "audio/wav",
2959
+ pdf: "application/pdf",
2960
+ json: "application/json",
2961
+ txt: "text/plain",
2962
+ csv: "text/csv"
2963
+ };
2964
+ async function cmdUpload(filePath, options) {
2965
+ const ext = extname2(filePath).slice(1).toLowerCase();
2966
+ if (!ext) fatal("Cannot determine file extension. Please provide a file with an extension.");
2967
+ const content = readFileSync3(filePath);
2968
+ const mimeType = MIME_TYPES2[ext];
2969
+ const { MindStudioAgent: MindStudioAgent2 } = await Promise.resolve().then(() => (init_client(), client_exports));
2970
+ await Promise.resolve().then(() => (init_helpers(), helpers_exports)).then(
2971
+ (m) => m.applyHelperMethods(MindStudioAgent2)
2972
+ );
2973
+ const agent = new MindStudioAgent2({
2974
+ apiKey: options.apiKey,
2975
+ baseUrl: options.baseUrl
2976
+ });
2977
+ const { url } = await agent.uploadFile(content, {
2978
+ extension: ext,
2979
+ ...mimeType && { type: mimeType }
2980
+ });
2981
+ process.stdout.write(url + "\n");
2982
+ }
2789
2983
  var ansi = {
2790
2984
  cyan: (s) => `\x1B[36m${s}\x1B[0m`,
2791
2985
  cyanBright: (s) => `\x1B[96m${s}\x1B[0m`,
@@ -2809,7 +3003,7 @@ function isNewerVersion(current, latest) {
2809
3003
  return false;
2810
3004
  }
2811
3005
  async function checkForUpdate() {
2812
- const currentVersion = "0.1.1";
3006
+ const currentVersion = "0.1.3";
2813
3007
  if (!currentVersion) return null;
2814
3008
  try {
2815
3009
  const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
@@ -2838,7 +3032,7 @@ async function checkForUpdate() {
2838
3032
  }
2839
3033
  }
2840
3034
  function printUpdateNotice(latestVersion) {
2841
- const currentVersion = "0.1.1";
3035
+ const currentVersion = "0.1.3";
2842
3036
  process.stderr.write(
2843
3037
  `
2844
3038
  ${ansi.cyanBright("Update available")} ${ansi.gray(currentVersion + " \u2192")} ${ansi.cyanBold(latestVersion)}
@@ -2912,9 +3106,9 @@ async function cmdLogin(options) {
2912
3106
  process.stderr.write("\n");
2913
3107
  printLogo();
2914
3108
  process.stderr.write("\n");
2915
- const ver = "0.1.1";
3109
+ const ver = "0.1.3";
2916
3110
  process.stderr.write(
2917
- ` ${ansi.bold("MindStudio")} ${ansi.gray("CLI")}${ver ? " " + ansi.gray("v" + ver) : ""}
3111
+ ` ${ansi.bold("MindStudio Agent")} ${ver ? " " + ansi.gray("v" + ver) : ""}
2918
3112
  `
2919
3113
  );
2920
3114
  process.stderr.write(
@@ -2931,12 +3125,10 @@ async function cmdLogin(options) {
2931
3125
  );
2932
3126
  await waitForKeypress();
2933
3127
  process.stderr.write("\x1B[4A\r\x1B[J");
2934
- process.stderr.write(
2935
- ` ${ansi.gray("Requesting authorization...")}
2936
- `
2937
- );
3128
+ process.stderr.write(` ${ansi.gray("Requesting authorization...")}
3129
+ `);
2938
3130
  const authRes = await fetch(
2939
- `${baseUrl}/developer/v2/request-auth-url`,
3131
+ `${baseUrl}/developer/v2/request-auth-url?agent=true`,
2940
3132
  {
2941
3133
  headers: {
2942
3134
  "Content-Type": "application/json",
@@ -2980,9 +3172,7 @@ async function cmdLogin(options) {
2980
3172
  });
2981
3173
  if (!pollRes.ok) {
2982
3174
  process.stderr.write("\n");
2983
- fatal(
2984
- `Poll request failed: ${pollRes.status} ${pollRes.statusText}`
2985
- );
3175
+ fatal(`Poll request failed: ${pollRes.status} ${pollRes.statusText}`);
2986
3176
  }
2987
3177
  const result = await pollRes.json();
2988
3178
  if (result.status === "completed" && result.apiKey) {
@@ -3015,10 +3205,8 @@ async function cmdLogout() {
3015
3205
  const { loadConfig: loadConfig2, clearConfig: clearConfig2, getConfigPath: getConfigPath2 } = await Promise.resolve().then(() => (init_config(), config_exports));
3016
3206
  const config = loadConfig2();
3017
3207
  if (!config.apiKey) {
3018
- process.stderr.write(
3019
- ` ${ansi.gray("Not currently logged in.")}
3020
- `
3021
- );
3208
+ process.stderr.write(` ${ansi.gray("Not currently logged in.")}
3209
+ `);
3022
3210
  return;
3023
3211
  }
3024
3212
  clearConfig2();
@@ -3149,9 +3337,24 @@ async function main() {
3149
3337
  help: { type: "boolean", default: false }
3150
3338
  }
3151
3339
  });
3152
- if (values.help || positionals.length === 0) {
3340
+ if (values.help) {
3341
+ printHelp();
3342
+ process.exit(0);
3343
+ }
3344
+ if (positionals.length === 0) {
3345
+ const hasAuth = values["api-key"] || process.env.MINDSTUDIO_API_KEY || process.env.CALLBACK_TOKEN;
3346
+ if (!hasAuth) {
3347
+ const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
3348
+ const config = loadConfig2();
3349
+ if (!config.apiKey) {
3350
+ await cmdLogin({
3351
+ baseUrl: values["base-url"]
3352
+ });
3353
+ return;
3354
+ }
3355
+ }
3153
3356
  printHelp();
3154
- process.exit(positionals.length === 0 ? 1 : 0);
3357
+ process.exit(1);
3155
3358
  }
3156
3359
  const command = positionals[0];
3157
3360
  const updatePromise = command !== "mcp" && command !== "login" ? checkForUpdate() : Promise.resolve(null);
@@ -3174,10 +3377,7 @@ async function main() {
3174
3377
  return;
3175
3378
  }
3176
3379
  if (command === "list") {
3177
- await cmdList(
3178
- values.json,
3179
- values.summary
3180
- );
3380
+ await cmdList(values.json, values.summary);
3181
3381
  return;
3182
3382
  }
3183
3383
  if (command === "agents") {
@@ -3191,9 +3391,7 @@ async function main() {
3191
3391
  const appId = positionals[1];
3192
3392
  if (!appId)
3193
3393
  fatal("Missing app ID. Usage: mindstudio run <appId> [json | --flags]");
3194
- const runArgv = process.argv.slice(
3195
- process.argv.indexOf("run") + 2
3196
- );
3394
+ const runArgv = process.argv.slice(process.argv.indexOf("run") + 2);
3197
3395
  const stepArgs = [];
3198
3396
  for (let i = 0; i < runArgv.length; i++) {
3199
3397
  const arg = runArgv[i];
@@ -3238,6 +3436,16 @@ async function main() {
3238
3436
  });
3239
3437
  return;
3240
3438
  }
3439
+ if (command === "upload") {
3440
+ const filePath = positionals[1];
3441
+ if (!filePath)
3442
+ fatal("Missing file path. Usage: mindstudio upload <filepath>");
3443
+ await cmdUpload(filePath, {
3444
+ apiKey: values["api-key"],
3445
+ baseUrl: values["base-url"]
3446
+ });
3447
+ return;
3448
+ }
3241
3449
  if (command === "mcp") {
3242
3450
  const { startMcpServer: startMcpServer2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
3243
3451
  await startMcpServer2({
@@ -3255,9 +3463,7 @@ async function main() {
3255
3463
  }
3256
3464
  const split = findMethodSplit(process.argv.slice(2));
3257
3465
  if (!split)
3258
- fatal(
3259
- "Missing method name. Usage: mindstudio <method> [json | --flags]"
3260
- );
3466
+ fatal("Missing method name. Usage: mindstudio <method> [json | --flags]");
3261
3467
  const { rawMethod, stepArgv } = split;
3262
3468
  const allKeys = await getAllMethodKeys();
3263
3469
  const method = resolveMethodOrFail(rawMethod, allKeys);
package/dist/index.d.ts CHANGED
@@ -6580,6 +6580,8 @@ interface StepCostEstimateEntry {
6580
6580
  estimatedCost?: number;
6581
6581
  /** Number of billable units. */
6582
6582
  quantity?: number;
6583
+ /** Estimated latency based on recent global model metrics. null when no metrics are available. */
6584
+ latency?: unknown;
6583
6585
  }
6584
6586
  /** Supported model type categories for filtering. */
6585
6587
  type ModelType = "llm_chat" | "image_generation" | "video_generation" | "video_analysis" | "text_to_speech" | "vision" | "transcription";
@@ -6665,6 +6667,38 @@ interface HelperMethods {
6665
6667
  costType?: string;
6666
6668
  estimates?: StepCostEstimateEntry[];
6667
6669
  }>;
6670
+ /**
6671
+ * Update the display name of the authenticated agent.
6672
+ *
6673
+ * Useful for agents to set their own name after connecting.
6674
+ *
6675
+ * @param displayName - The new display name.
6676
+ */
6677
+ changeName(displayName: string): Promise<void>;
6678
+ /**
6679
+ * Update the profile picture of the authenticated agent.
6680
+ *
6681
+ * Useful for agents to set their own avatar after connecting.
6682
+ *
6683
+ * @param profilePictureUrl - URL of the new profile picture.
6684
+ */
6685
+ changeProfilePicture(profilePictureUrl: string): Promise<void>;
6686
+ /**
6687
+ * Upload a file to the MindStudio CDN.
6688
+ *
6689
+ * Gets a signed upload URL, PUTs the file content, and returns the permanent public URL.
6690
+ *
6691
+ * @param content - File content as a Buffer or Uint8Array.
6692
+ * @param options - Upload options.
6693
+ * @param options.extension - File extension without the dot (e.g. "png", "jpg", "mp4").
6694
+ * @param options.type - MIME type of the file (e.g. "image/png"). Determines which CDN subdomain is used.
6695
+ */
6696
+ uploadFile(content: Buffer | Uint8Array, options: {
6697
+ extension: string;
6698
+ type?: string;
6699
+ }): Promise<{
6700
+ url: string;
6701
+ }>;
6668
6702
  }
6669
6703
 
6670
6704
  /**
package/dist/index.js CHANGED
@@ -640,6 +640,26 @@ function applyHelperMethods(AgentClass) {
640
640
  proto.estimateStepCost = function(stepType, step, options) {
641
641
  return this._request("POST", "/helpers/step-cost-estimate", { step: { type: stepType, ...step }, ...options }).then((r) => r.data);
642
642
  };
643
+ proto.changeName = function(displayName) {
644
+ return this._request("POST", "/account/change-name", { displayName }).then(() => {
645
+ });
646
+ };
647
+ proto.changeProfilePicture = function(profilePictureUrl) {
648
+ return this._request("POST", "/account/change-profile-picture", { profilePictureUrl }).then(() => {
649
+ });
650
+ };
651
+ proto.uploadFile = async function(content, options) {
652
+ const { data } = await this._request("POST", "/account/upload", { extension: options.extension, ...options.type != null && { type: options.type } });
653
+ const { uploadUrl, url } = data;
654
+ const buf = content.buffer.slice(content.byteOffset, content.byteOffset + content.byteLength);
655
+ const res = await fetch(uploadUrl, {
656
+ method: "PUT",
657
+ body: buf,
658
+ headers: options.type ? { "Content-Type": options.type } : {}
659
+ });
660
+ if (!res.ok) throw new Error(`Upload failed: ${res.status} ${res.statusText}`);
661
+ return { url };
662
+ };
643
663
  }
644
664
 
645
665
  // src/client.ts