@mindstudio-ai/agent 0.0.16 → 0.0.18

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/index.js CHANGED
@@ -120,6 +120,21 @@ var RateLimiter = class {
120
120
  }
121
121
  };
122
122
 
123
+ // src/config.ts
124
+ import { readFileSync, writeFileSync, mkdirSync } from "fs";
125
+ import { join } from "path";
126
+ import { homedir } from "os";
127
+ var CONFIG_DIR = join(homedir(), ".mindstudio");
128
+ var CONFIG_PATH = join(CONFIG_DIR, "config.json");
129
+ function loadConfig() {
130
+ try {
131
+ const raw = readFileSync(CONFIG_PATH, "utf-8");
132
+ return JSON.parse(raw);
133
+ } catch {
134
+ return {};
135
+ }
136
+ }
137
+
123
138
  // src/generated/steps.ts
124
139
  function applyStepMethods(AgentClass) {
125
140
  const proto = AgentClass.prototype;
@@ -201,6 +216,15 @@ function applyStepMethods(AgentClass) {
201
216
  proto.detectPII = function(step, options) {
202
217
  return this.executeStep("detectPII", step, options);
203
218
  };
219
+ proto.discordEditMessage = function(step, options) {
220
+ return this.executeStep("discordEditMessage", step, options);
221
+ };
222
+ proto.discordSendFollowUp = function(step, options) {
223
+ return this.executeStep("discordSendFollowUp", step, options);
224
+ };
225
+ proto.discordSendMessage = function(step, options) {
226
+ return this.executeStep("discordSendMessage", step, options);
227
+ };
204
228
  proto.downloadVideo = function(step, options) {
205
229
  return this.executeStep("downloadVideo", step, options);
206
230
  };
@@ -477,6 +501,12 @@ function applyStepMethods(AgentClass) {
477
501
  proto.setVariable = function(step, options) {
478
502
  return this.executeStep("setVariable", step, options);
479
503
  };
504
+ proto.telegramEditMessage = function(step, options) {
505
+ return this.executeStep("telegramEditMessage", step, options);
506
+ };
507
+ proto.telegramReplyToMessage = function(step, options) {
508
+ return this.executeStep("telegramReplyToMessage", step, options);
509
+ };
480
510
  proto.telegramSendAudio = function(step, options) {
481
511
  return this.executeStep("telegramSendAudio", step, options);
482
512
  };
@@ -570,8 +600,9 @@ var MindStudioAgent = class {
570
600
  /** @internal */
571
601
  _threadId;
572
602
  constructor(options = {}) {
573
- const { token, authType } = resolveToken(options.apiKey);
574
- const baseUrl = options.baseUrl ?? process.env.MINDSTUDIO_BASE_URL ?? process.env.REMOTE_HOSTNAME ?? DEFAULT_BASE_URL;
603
+ const config = loadConfig();
604
+ const { token, authType } = resolveToken(options.apiKey, config);
605
+ const baseUrl = options.baseUrl ?? process.env.MINDSTUDIO_BASE_URL ?? process.env.REMOTE_HOSTNAME ?? config.baseUrl ?? DEFAULT_BASE_URL;
575
606
  this._reuseThreadId = options.reuseThreadId ?? /^(true|1)$/i.test(process.env.MINDSTUDIO_REUSE_THREAD_ID ?? "");
576
607
  this._httpConfig = {
577
608
  baseUrl,
@@ -715,14 +746,16 @@ function sleep2(ms) {
715
746
  }
716
747
  applyStepMethods(MindStudioAgent);
717
748
  applyHelperMethods(MindStudioAgent);
718
- function resolveToken(provided) {
749
+ function resolveToken(provided, config) {
719
750
  if (provided) return { token: provided, authType: "apiKey" };
720
751
  if (process.env.MINDSTUDIO_API_KEY)
721
752
  return { token: process.env.MINDSTUDIO_API_KEY, authType: "apiKey" };
753
+ if (config?.apiKey)
754
+ return { token: config.apiKey, authType: "apiKey" };
722
755
  if (process.env.CALLBACK_TOKEN)
723
756
  return { token: process.env.CALLBACK_TOKEN, authType: "internal" };
724
757
  throw new MindStudioError(
725
- "No API key provided. Pass `apiKey` to the MindStudioAgent constructor, or set the MINDSTUDIO_API_KEY environment variable.",
758
+ "No API key provided. Run `mindstudio login`, pass `apiKey` to the constructor, or set the MINDSTUDIO_API_KEY environment variable.",
726
759
  "missing_api_key",
727
760
  401
728
761
  );
@@ -756,6 +789,9 @@ var monacoSnippets = {
756
789
  "deleteGoogleCalendarEvent": { fields: [["eventId", "string"]], outputKeys: [] },
757
790
  "deleteGoogleSheetRows": { fields: [["documentId", "string"], ["startRow", "string"], ["endRow", "string"]], outputKeys: [] },
758
791
  "detectPII": { fields: [["input", "string"], ["language", "string"], ["entities", "array"]], outputKeys: ["detected", "detections"] },
792
+ "discordEditMessage": { fields: [["botToken", "string"], ["channelId", "string"], ["messageId", "string"], ["text", "string"]], outputKeys: [] },
793
+ "discordSendFollowUp": { fields: [["applicationId", "string"], ["interactionToken", "string"], ["text", "string"]], outputKeys: ["messageId"] },
794
+ "discordSendMessage": { fields: [["mode", ["edit", "send"]], ["text", "string"]], outputKeys: [] },
759
795
  "downloadVideo": { fields: [["videoUrl", "string"], ["format", ["mp4", "mp3"]]], outputKeys: ["videoUrl"] },
760
796
  "enhanceImageGenerationPrompt": { fields: [["initialPrompt", "string"], ["includeNegativePrompt", "boolean"], ["systemPrompt", "string"]], outputKeys: ["prompt"] },
761
797
  "enhanceVideoGenerationPrompt": { fields: [["initialPrompt", "string"], ["includeNegativePrompt", "boolean"], ["systemPrompt", "string"]], outputKeys: ["prompt"] },
@@ -850,10 +886,12 @@ var monacoSnippets = {
850
886
  "sendSMS": { fields: [["body", "string"]], outputKeys: [] },
851
887
  "setRunTitle": { fields: [["title", "string"]], outputKeys: [] },
852
888
  "setVariable": { fields: [["value", "string"]], outputKeys: [] },
889
+ "telegramEditMessage": { fields: [["botToken", "string"], ["chatId", "string"], ["messageId", "string"], ["text", "string"]], outputKeys: [] },
890
+ "telegramReplyToMessage": { fields: [["botToken", "string"], ["chatId", "string"], ["replyToMessageId", "string"], ["text", "string"]], outputKeys: ["messageId"] },
853
891
  "telegramSendAudio": { fields: [["botToken", "string"], ["chatId", "string"], ["audioUrl", "string"], ["mode", ["audio", "voice"]]], outputKeys: [] },
854
892
  "telegramSendFile": { fields: [["botToken", "string"], ["chatId", "string"], ["fileUrl", "string"]], outputKeys: [] },
855
893
  "telegramSendImage": { fields: [["botToken", "string"], ["chatId", "string"], ["imageUrl", "string"]], outputKeys: [] },
856
- "telegramSendMessage": { fields: [["botToken", "string"], ["chatId", "string"], ["text", "string"]], outputKeys: [] },
894
+ "telegramSendMessage": { fields: [["botToken", "string"], ["chatId", "string"], ["text", "string"]], outputKeys: ["messageId"] },
857
895
  "telegramSendVideo": { fields: [["botToken", "string"], ["chatId", "string"], ["videoUrl", "string"]], outputKeys: [] },
858
896
  "telegramSetTyping": { fields: [["botToken", "string"], ["chatId", "string"]], outputKeys: [] },
859
897
  "textToSpeech": { fields: [["text", "string"]], outputKeys: ["audioUrl"] },
@@ -1061,6 +1099,27 @@ var stepMetadata = {
1061
1099
  inputSchema: { "type": "object", "properties": { "input": { "type": "string", "description": "Text to scan for personally identifiable information" }, "language": { "type": "string", "description": 'Language code of the input text (e.g. "en")' }, "entities": { "type": "array", "items": { "type": "string" }, "description": 'PII entity types to scan for (e.g. ["PHONE_NUMBER", "EMAIL_ADDRESS"]). Empty array means nothing is scanned.' }, "detectedStepId": { "type": "string", "description": "Step to transition to if PII is detected (workflow mode)" }, "notDetectedStepId": { "type": "string", "description": "Step to transition to if no PII is detected (workflow mode)" }, "outputLogVariable": { "type": "string", "description": "Variable name to store the raw detection results" } }, "required": ["input", "language", "entities"] },
1062
1100
  outputSchema: { "type": "object", "properties": { "detected": { "type": "boolean", "description": "Whether any PII was found in the input text" }, "detections": { "type": "array", "items": { "type": "object", "properties": { "entity_type": { "type": "string", "description": 'PII entity type (e.g. "PHONE_NUMBER", "EMAIL_ADDRESS", "PERSON")' }, "start": { "type": "number", "description": "Start character index in the input text" }, "end": { "type": "number", "description": "End character index in the input text" }, "score": { "type": "number", "description": "Confidence score between 0 and 1" } }, "required": ["entity_type", "start", "end", "score"] }, "description": "List of detected PII entities with type, location, and confidence" } }, "required": ["detected", "detections"] }
1063
1101
  },
1102
+ "discordEditMessage": {
1103
+ stepType: "discordEditMessage",
1104
+ description: "Edit a previously sent Discord channel message. Use with the message ID returned by Send Discord Message.",
1105
+ usageNotes: "- Only messages sent by the bot can be edited.\n- The messageId is returned by the Send Discord Message step.\n- Optionally attach a file by providing a URL to attachmentUrl. The file is downloaded and uploaded to Discord.\n- When editing with an attachment, the new attachment replaces any previous attachments on the message.\n- URLs in the text are automatically embedded by Discord (link previews for images, videos, etc.).",
1106
+ inputSchema: { "type": "object", "properties": { "botToken": { "type": "string", "description": "Discord bot token for authentication" }, "channelId": { "type": "string", "description": "Discord channel ID containing the message" }, "messageId": { "type": "string", "description": "ID of the message to edit (returned by Send Discord Message)" }, "text": { "type": "string", "description": "New message text to replace the existing content" }, "attachmentUrl": { "type": "string", "description": "URL of a file to download and attach to the message (replaces any previous attachments)" } }, "required": ["botToken", "channelId", "messageId", "text"] },
1107
+ outputSchema: { "description": "This step does not produce output data." }
1108
+ },
1109
+ "discordSendFollowUp": {
1110
+ stepType: "discordSendFollowUp",
1111
+ description: "Send a follow-up message to a Discord slash command interaction.",
1112
+ usageNotes: "- Requires the applicationId and interactionToken from the Discord trigger variables.\n- Follow-up messages appear as new messages in the channel after the initial response.\n- Returns the sent message ID.\n- Interaction tokens expire after 15 minutes.\n- Optionally attach a file by providing a URL to attachmentUrl. The file is downloaded and uploaded to Discord.\n- URLs in the text are automatically embedded by Discord (link previews for images, videos, etc.).",
1113
+ inputSchema: { "type": "object", "properties": { "applicationId": { "type": "string", "description": "Discord application ID from the bot registration" }, "interactionToken": { "type": "string", "description": "Interaction token provided by the Discord trigger \u2014 expires after 15 minutes" }, "text": { "type": "string", "description": "Message text to send as a follow-up" }, "attachmentUrl": { "type": "string", "description": "URL of a file to download and attach to the message" } }, "required": ["applicationId", "interactionToken", "text"] },
1114
+ outputSchema: { "type": "object", "properties": { "messageId": { "type": "string", "description": "ID of the sent follow-up message" } }, "required": ["messageId"] }
1115
+ },
1116
+ "discordSendMessage": {
1117
+ stepType: "discordSendMessage",
1118
+ description: "Send a message to Discord \u2014 either edit the loading message or send a new channel message.",
1119
+ usageNotes: '- mode "edit" replaces the loading message (interaction response) with the final result. Uses applicationId and interactionToken from trigger variables. No bot permissions required.\n- mode "send" sends a new message to a channel. Uses botToken and channelId from trigger variables. Returns a messageId that can be used with Edit Discord Message.\n- Optionally attach a file by providing a URL to attachmentUrl. The file is downloaded and uploaded to Discord.\n- URLs in the text are automatically embedded by Discord (link previews for images, videos, etc.).\n- Interaction tokens expire after 15 minutes.',
1120
+ inputSchema: { "type": "object", "properties": { "mode": { "enum": ["edit", "send"], "type": "string", "description": '"edit" replaces the loading message, "send" sends a new channel message' }, "text": { "type": "string", "description": "Message text to send" }, "applicationId": { "type": "string", "description": 'Discord application ID from the bot registration (required for "reply" mode)' }, "interactionToken": { "type": "string", "description": 'Interaction token provided by the Discord trigger \u2014 expires after 15 minutes (required for "reply" mode)' }, "botToken": { "type": "string", "description": 'Discord bot token for authentication (required for "send" mode)' }, "channelId": { "type": "string", "description": 'Discord channel ID to send the message to (required for "send" mode)' }, "attachmentUrl": { "type": "string", "description": "URL of a file to download and attach to the message" } }, "required": ["mode", "text"] },
1121
+ outputSchema: { "type": "object", "properties": { "messageId": { "type": "string", "description": 'ID of the sent Discord message, only present in "send" mode (use with Edit Discord Message)' } } }
1122
+ },
1064
1123
  "downloadVideo": {
1065
1124
  stepType: "downloadVideo",
1066
1125
  description: "Download a video file",
@@ -1388,9 +1447,13 @@ var stepMetadata = {
1388
1447
  },
1389
1448
  "logic": {
1390
1449
  stepType: "logic",
1391
- description: "Use an AI model to evaluate which condition from a list is most true, given a context prompt.",
1392
- usageNotes: '- This is "fuzzy" logic evaluated by an AI model, not computational logic. The model picks the most accurate statement.\n- All possible cases must be specified \u2014 there is no default/fallback case.\n- Requires at least two cases.\n- In workflow mode, transitions to the destinationStepId of the winning case. In direct execution, returns the winning case ID and condition.',
1393
- inputSchema: { "type": "object", "properties": { "context": { "type": "string", "description": "Prompt text providing context for the AI evaluation" }, "cases": { "type": "array", "items": { "anyOf": [{ "type": "object", "properties": { "id": { "type": "string", "description": "Unique case identifier" }, "condition": { "type": "string", "description": 'The statement to evaluate (e.g., "User selected a dog")' }, "destinationStepId": { "type": "string", "description": "Step to transition to if this case wins (workflow mode only)" } }, "required": ["id", "condition"] }, { "type": "string" }] }, "description": "List of conditions to evaluate (objects for managed UIs, strings for code)" } }, "required": ["context", "cases"], "description": "Configuration for the logic evaluation step" },
1450
+ description: "Route execution to different branches based on AI evaluation, comparison operators, or workflow jumps.",
1451
+ usageNotes: `- Supports two modes: "ai" (default) uses an AI model to pick the most accurate statement; "comparison" uses operator-based checks.
1452
+ - In AI mode, the model picks the most accurate statement from the list. All possible cases must be specified.
1453
+ - In comparison mode, the context is the left operand and each case's condition is the right operand. First matching case wins. Use operator "default" as a fallback.
1454
+ - Requires at least two cases.
1455
+ - Each case can transition to a step in the current workflow (destinationStepId) or jump to another workflow (destinationWorkflowId).`,
1456
+ inputSchema: { "type": "object", "properties": { "mode": { "enum": ["ai", "comparison"], "type": "string", "description": "Evaluation mode: 'ai' for LLM-based, 'comparison' for operator-based. Default: 'ai'" }, "context": { "type": "string", "description": "AI mode: prompt context. Comparison mode: left operand (resolved via variables)." }, "cases": { "type": "array", "items": { "anyOf": [{ "type": "object", "properties": { "id": { "type": "string", "description": "Unique case identifier" }, "condition": { "type": "string", "description": "AI mode: statement to evaluate. Comparison mode: right operand value." }, "operator": { "enum": ["eq", "neq", "gt", "lt", "gte", "lte", "exists", "not_exists", "contains", "not_contains", "default"], "type": "string", "description": "Comparison operator (comparison mode only)" }, "destinationStepId": { "type": "string", "description": "Step to transition to if this case wins (workflow mode only)" }, "destinationWorkflowId": { "type": "string", "description": "Workflow to jump to if this case wins (uses that workflow's initial step)" } }, "required": ["id", "condition"] }, { "type": "string" }] }, "description": "List of conditions to evaluate (objects for managed UIs, strings for code)" }, "modelOverride": { "type": "object", "properties": { "model": { "type": "string", "description": 'Model identifier (e.g. "gpt-4", "claude-3-opus")' }, "temperature": { "type": "number", "description": "Sampling temperature for the model (0-2)" }, "maxResponseTokens": { "type": "number", "description": "Maximum number of tokens in the model's response" }, "ignorePreamble": { "type": "boolean", "description": "Whether to skip the system preamble/instructions" }, "userMessagePreprocessor": { "type": "object", "properties": { "dataSource": { "type": "string", "description": "Data source identifier for the preprocessor" }, "messageTemplate": { "type": "string", "description": "Template string applied to user messages before sending to the model" }, "maxResults": { "type": "number", "description": "Maximum number of results to include from the data source" }, "enabled": { "type": "boolean", "description": "Whether the preprocessor is active" }, "shouldInherit": { "type": "boolean", "description": "Whether child steps should inherit this preprocessor configuration" } }, "description": "Preprocessor applied to user messages before sending to the model" }, "preamble": { "type": "string", "description": "System preamble/instructions for the model" }, "multiModelEnabled": { "type": "boolean", "description": "Whether multi-model candidate generation is enabled" }, "editResponseEnabled": { "type": "boolean", "description": "Whether the user can edit the model's response" }, "config": { "type": "object", "description": "Additional model-specific configuration" } }, "required": ["model", "temperature", "maxResponseTokens"], "description": "Optional model settings override; uses the organization default if not specified (AI mode only)" } }, "required": ["context", "cases"], "description": "Configuration for the router step" },
1394
1457
  outputSchema: { "type": "object", "properties": { "selectedCase": { "type": "number", "description": "The index of the winning case" } }, "required": ["selectedCase"] }
1395
1458
  },
1396
1459
  "makeDotComRunScenario": {
@@ -1705,9 +1768,9 @@ var stepMetadata = {
1705
1768
  },
1706
1769
  "sendSMS": {
1707
1770
  stepType: "sendSMS",
1708
- description: "Send an SMS text message to a phone number configured via OAuth connection.",
1709
- usageNotes: "- User is responsible for configuring the connection to the number (MindStudio requires double opt-in to prevent spam)",
1710
- inputSchema: { "type": "object", "properties": { "body": { "type": "string", "description": "SMS message body text" }, "connectionId": { "type": "string", "description": "OAuth connection ID for the recipient phone number" } }, "required": ["body"] },
1771
+ description: "Send an SMS or MMS message to a phone number configured via OAuth connection.",
1772
+ usageNotes: "- User is responsible for configuring the connection to the number (MindStudio requires double opt-in to prevent spam)\n- If mediaUrls are provided, the message is sent as MMS instead of SMS\n- MMS supports up to 10 media URLs (images, video, audio, PDF) with a 5MB limit per file\n- MMS is only supported on US and Canadian carriers; international numbers will receive SMS only (media silently dropped)",
1773
+ inputSchema: { "type": "object", "properties": { "body": { "type": "string", "description": "SMS message body text" }, "connectionId": { "type": "string", "description": "OAuth connection ID for the recipient phone number" }, "mediaUrls": { "type": "array", "items": { "type": "string" }, "description": "Optional array of media URLs to send as MMS (up to 10, 5MB each)" } }, "required": ["body"] },
1711
1774
  outputSchema: { "description": "This step does not produce output data." }
1712
1775
  },
1713
1776
  "setRunTitle": {
@@ -1724,6 +1787,20 @@ var stepMetadata = {
1724
1787
  inputSchema: { "type": "object", "properties": { "value": { "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }] } }, "required": ["value"], "description": "Configuration for the set variable step" },
1725
1788
  outputSchema: { "type": "object" }
1726
1789
  },
1790
+ "telegramEditMessage": {
1791
+ stepType: "telegramEditMessage",
1792
+ description: "Edit a previously sent Telegram message. Use with the message ID returned by Send Telegram Message.",
1793
+ usageNotes: '- Only text messages sent by the bot can be edited.\n- The messageId is returned by the Send Telegram Message step.\n- Common pattern: send a "Processing..." message, do work, then edit it with the result.',
1794
+ inputSchema: { "type": "object", "properties": { "botToken": { "type": "string", "description": 'Telegram bot token in "botId:token" format' }, "chatId": { "type": "string", "description": "Telegram chat ID containing the message" }, "messageId": { "type": "string", "description": "ID of the message to edit" }, "text": { "type": "string", "description": "New message text (MarkdownV2 formatting supported)" } }, "required": ["botToken", "chatId", "messageId", "text"] },
1795
+ outputSchema: { "description": "This step does not produce output data." }
1796
+ },
1797
+ "telegramReplyToMessage": {
1798
+ stepType: "telegramReplyToMessage",
1799
+ description: "Send a reply to a specific Telegram message. The reply will be visually threaded in the chat.",
1800
+ usageNotes: "- Use the rawMessage.message_id from the incoming trigger variables to reply to the user's message.\n- Especially useful in group chats where replies provide context.\n- Returns the sent message ID, which can be used with Edit Telegram Message.",
1801
+ inputSchema: { "type": "object", "properties": { "botToken": { "type": "string", "description": 'Telegram bot token in "botId:token" format' }, "chatId": { "type": "string", "description": "Telegram chat ID to send the reply to" }, "replyToMessageId": { "type": "string", "description": "ID of the message to reply to" }, "text": { "type": "string", "description": "Reply text (MarkdownV2 formatting supported)" } }, "required": ["botToken", "chatId", "replyToMessageId", "text"] },
1802
+ outputSchema: { "type": "object", "properties": { "messageId": { "type": "number", "description": "ID of the sent reply message" } }, "required": ["messageId"] }
1803
+ },
1727
1804
  "telegramSendAudio": {
1728
1805
  stepType: "telegramSendAudio",
1729
1806
  description: "Send an audio file to a Telegram chat as music or a voice note via a bot.",
@@ -1748,9 +1825,9 @@ var stepMetadata = {
1748
1825
  "telegramSendMessage": {
1749
1826
  stepType: "telegramSendMessage",
1750
1827
  description: "Send a text message to a Telegram chat via a bot.",
1751
- usageNotes: '- Messages are sent using MarkdownV2 formatting. Special characters are auto-escaped.\n- botToken format is "botId:token" \u2014 both parts are required.',
1828
+ usageNotes: '- Messages are sent using MarkdownV2 formatting. Special characters are auto-escaped.\n- botToken format is "botId:token" \u2014 both parts are required.\n- Returns the sent message ID, which can be used with Edit Telegram Message to update the message later.',
1752
1829
  inputSchema: { "type": "object", "properties": { "botToken": { "type": "string", "description": 'Telegram bot token in "botId:token" format' }, "chatId": { "type": "string", "description": "Telegram chat ID to send the message to" }, "text": { "type": "string", "description": "Message text to send (MarkdownV2 formatting supported)" } }, "required": ["botToken", "chatId", "text"] },
1753
- outputSchema: { "description": "This step does not produce output data." }
1830
+ outputSchema: { "type": "object", "properties": { "messageId": { "type": "number", "description": "ID of the sent Telegram message" } }, "required": ["messageId"] }
1754
1831
  },
1755
1832
  "telegramSendVideo": {
1756
1833
  stepType: "telegramSendVideo",