Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions components/x_ai/actions/get-model/get-model.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import app from "../../x_ai.app.mjs";

export default {
key: "x_ai-get-model",
name: "Get Model",
description: "List all language and embedding models available. [See the documentation](https://docs.x.ai/api/endpoints#get-model)",
version: "0.0.1",
type: "action",
props: {
app,
model: {
propDefinition: [
app,
"model"
]
},
},

async run({ $ }) {
const response = await this.app.getModel({
$,
model: this.model,
});

$.export("$summary", `Successfully retrieved the '${this.model}' model`);

return response;
},
Comment on lines +19 to +28
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for robustness.

The current implementation lacks error handling which could lead to unclear error messages for users.

Consider implementing try-catch:

   async run({ $ }) {
+    try {
       const response = await this.app.getModel({
         $,
         model: this.model,
       });
 
       $.export("$summary", `Successfully retrieved the '${this.model}' model`);
 
       return response;
+    } catch (error) {
+      $.export("$summary", `Failed to retrieve model: ${error.message}`);
+      throw error;
+    }
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async run({ $ }) {
const response = await this.app.getModel({
$,
model: this.model,
});
$.export("$summary", `Successfully retrieved the '${this.model}' model`);
return response;
},
async run({ $ }) {
try {
const response = await this.app.getModel({
$,
model: this.model,
});
$.export("$summary", `Successfully retrieved the '${this.model}' model`);
return response;
} catch (error) {
$.export("$summary", `Failed to retrieve model: ${error.message}`);
throw error;
}
},

};
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import app from "../../x_ai.app.mjs";

export default {
key: "x_ai-post-chat-completion",
name: "Post Chat Completion",
description: "Create a language model response for a chat conversation. [See the documentation](https://docs.x.ai/api/endpoints#chat-completions)",
version: "0.0.1",
type: "action",
Comment on lines +1 to +8
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Documentation link appears to be broken or inaccessible

The documentation URL (https://docs.x.ai/api/endpoints#chat-completions) returns a 500 error, indicating it's not accessible. Consider updating the description with a valid documentation URL or removing the link until proper documentation is available.

🔗 Analysis chain

LGTM! Verify the documentation link accessibility.

The module configuration is well-structured with appropriate metadata. The documentation link is a good addition for developer reference.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the documentation link is accessible
curl -I "https://docs.x.ai/api/endpoints#chat-completions"

Length of output: 1559

props: {
app,
model: {
propDefinition: [
app,
"model"
]
},
message: {
propDefinition: [
app,
"message"
]
},
},

async run({ $ }) {
const response = await this.app.postChatCompletion({
$,
data: {
model: this.model,
messages: [
{ role: "user", content: this.message },
],
},
});

$.export("$summary", `Successfully sent message to the model '${this.model}'`);

return response;
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling and response validation.

The current implementation could be more robust:

  1. Add try-catch block for API error handling
  2. Validate the response structure before returning
  3. Consider implementing rate limiting protection
   async run({ $ }) {
+    try {
       const response = await this.app.postChatCompletion({
         $,
         data: {
           model: this.model,
           messages: [
             { role: "user", content: this.message },
           ],
         },
       });

+      if (!response || !response.choices?.[0]?.message) {
+        throw new Error('Invalid response structure from API');
+      }

       $.export("$summary", `Successfully sent message to the model '${this.model}'`);

       return response;
+    } catch (error) {
+      $.export("$summary", `Failed to send message: ${error.message}`);
+      throw error;
+    }
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async run({ $ }) {
const response = await this.app.postChatCompletion({
$,
data: {
model: this.model,
messages: [
{ role: "user", content: this.message },
],
},
});
$.export("$summary", `Successfully sent message to the model '${this.model}'`);
return response;
},
async run({ $ }) {
try {
const response = await this.app.postChatCompletion({
$,
data: {
model: this.model,
messages: [
{ role: "user", content: this.message },
],
},
});
if (!response || !response.choices?.[0]?.message) {
throw new Error('Invalid response structure from API');
}
$.export("$summary", `Successfully sent message to the model '${this.model}'`);
return response;
} catch (error) {
$.export("$summary", `Failed to send message: ${error.message}`);
throw error;
}
},
🧰 Tools
🪛 eslint

[error] 31-31: Expected a line break after this opening brace.

(object-curly-newline)


[error] 31-31: Object properties must go on a new line.

(object-property-newline)


[error] 31-31: Expected a line break before this closing brace.

(object-curly-newline)

};
38 changes: 38 additions & 0 deletions components/x_ai/actions/post-completion/post-completion.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import app from "../../x_ai.app.mjs";

export default {
key: "x_ai-post-completion",
name: "Post Completion",
description: "Create a language model response for a given prompt. [See the documentation](https://docs.x.ai/api/endpoints#completions)",
version: "0.0.1",
type: "action",
Comment on lines +3 to +8
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Documentation link is broken and version needs revision

The documentation link returns a 500 error, indicating it's not accessible. Additionally, the version number should be reconsidered for production readiness.

  • Update the documentation URL to point to a valid endpoint reference
  • Consider using version "1.0.0" if this component is ready for production use, as 0.x versions typically indicate beta/unstable features
🔗 Analysis chain

Verify documentation link and consider version strategy.

The metadata is well-structured, but a few considerations:

  1. Ensure the documentation link is accessible and points to the correct endpoint reference
  2. Consider starting with version "1.0.0" if this is intended for production use, as 0.x versions typically indicate beta/unstable features
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify if the documentation URL is accessible
curl -I "https://docs.x.ai/api/endpoints#completions"

Length of output: 1633

props: {
app,
model: {
propDefinition: [
app,
"model"
]
},
prompt: {
propDefinition: [
app,
"prompt"
]
},
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add missing trailing commas.

Fix the linting errors by adding trailing commas to the prop definitions.

      propDefinition: [
        app,
-        "model"
+        "model",
      ]
    },
    prompt: {
      propDefinition: [
        app,
-        "prompt"
+        "prompt",
      ]
-    },
+    },

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 14-15: Missing trailing comma.

(comma-dangle)


[error] 15-16: Missing trailing comma.

(comma-dangle)


[error] 20-21: Missing trailing comma.

(comma-dangle)


[error] 21-22: Missing trailing comma.

(comma-dangle)


async run({ $ }) {
const response = await this.app.postCompletion({
$,
data: {
model: this.model,
prompt: this.prompt,
},
});

$.export("$summary", `Successfully sent prompt to the model '${this.model}'`);

return response;
},
Comment on lines +25 to +37
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance error handling and response processing.

The current implementation could benefit from several improvements:

  1. Add try-catch block for error handling
  2. Validate response structure
  3. Include more details in the summary message (e.g., response length, tokens used)

Here's a suggested implementation:

   async run({ $ }) {
+    try {
       const response = await this.app.postCompletion({
         $,
         data: {
           model: this.model,
           prompt: this.prompt,
         },
       });
 
-      $.export("$summary", `Successfully sent prompt to the model '${this.model}'`);
+      const completionText = response.content || response.text || '';
+      $.export("$summary", `Successfully generated completion using model '${this.model}'. Output length: ${completionText.length} characters`);
 
+      if (!completionText) {
+        throw new Error('Received empty response from the model');
+      }
+
       return response;
+    } catch (error) {
+      throw new Error(`Failed to generate completion: ${error.message}`);
+    }
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async run({ $ }) {
const response = await this.app.postCompletion({
$,
data: {
model: this.model,
prompt: this.prompt,
},
});
$.export("$summary", `Successfully sent prompt to the model '${this.model}'`);
return response;
},
async run({ $ }) {
try {
const response = await this.app.postCompletion({
$,
data: {
model: this.model,
prompt: this.prompt,
},
});
const completionText = response.content || response.text || '';
$.export("$summary", `Successfully generated completion using model '${this.model}'. Output length: ${completionText.length} characters`);
if (!completionText) {
throw new Error('Received empty response from the model');
}
return response;
} catch (error) {
throw new Error(`Failed to generate completion: ${error.message}`);
}
},

};
7 changes: 5 additions & 2 deletions components/x_ai/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/x_ai",
"version": "0.0.1",
"version": "0.1.0",
"description": "Pipedream X AI Components",
"main": "x_ai.app.mjs",
"keywords": [
Expand All @@ -11,5 +11,8 @@
"author": "Pipedream <[email protected]> (https://pipedream.com/)",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@pipedream/platform": "^3.0.3"
}
}
}
74 changes: 70 additions & 4 deletions components/x_ai/x_ai.app.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,77 @@
import { axios } from "@pipedream/platform";

export default {
type: "app",
app: "x_ai",
propDefinitions: {},
propDefinitions: {
model: {
type: "string",
label: "Model",
description: "Specifies the model to be used for the request",
async options() {
const response = await this.listModels();
const modelsIds = response.data;
return modelsIds.map(({ id }) => ({
value: id
}));
}
},
prompt: {
type: "string",
label: "Prompt",
description: "Prompt for the request",
},
message: {
type: "string",
label: "Message",
description: "Message for the chat completion",
},
},
methods: {
// this.$auth contains connected account data
authKeys() {
console.log(Object.keys(this.$auth));
_baseUrl() {
return `https://api.x.ai`;
},
async _makeRequest(opts = {}) {
const {
$ = this,
path,
headers,
...otherOpts
} = opts;
return axios($, {
...otherOpts,
url: this._baseUrl() + path,
headers: {
...headers,
Authorization: `Bearer ${this.$auth.api_key}`,
},
});
},
Comment on lines +34 to +49
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance API request handling with timeouts and better error management

The _makeRequest method needs additional safety measures:

  1. Missing request timeout
  2. No specific error handling
  3. No rate limiting implementation

Consider these improvements:

 async _makeRequest(opts = {}) {
   const {
     $ = this,
     path,
     headers,
+    timeout = 30000, // 30 second timeout
     ...otherOpts
   } = opts;
-  return axios($, {
-    ...otherOpts,
-    url: this._baseUrl() + path,
-    headers: {
-      ...headers,
-      Authorization: `Bearer ${this.$auth.api_key}`,
-    },
-  });
+  try {
+    return await axios($, {
+      ...otherOpts,
+      url: this._baseUrl() + path,
+      timeout,
+      headers: {
+        ...headers,
+        Authorization: `Bearer ${this.$auth.api_key}`,
+      },
+    });
+  } catch (error) {
+    if (error.response) {
+      throw new Error(`API Error: ${error.response.status} - ${error.response.data?.error || 'Unknown error'}`);
+    }
+    throw new Error(`Network Error: ${error.message}`);
+  }
 },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async _makeRequest(opts = {}) {
const {
$ = this,
path,
headers,
...otherOpts
} = opts;
return axios($, {
...otherOpts,
url: this._baseUrl() + path,
headers: {
...headers,
Authorization: `Bearer ${this.$auth.api_key}`,
},
});
},
async _makeRequest(opts = {}) {
const {
$ = this,
path,
headers,
timeout = 30000, // 30 second timeout
...otherOpts
} = opts;
try {
return await axios($, {
...otherOpts,
url: this._baseUrl() + path,
timeout,
headers: {
...headers,
Authorization: `Bearer ${this.$auth.api_key}`,
},
});
} catch (error) {
if (error.response) {
throw new Error(`API Error: ${error.response.status} - ${error.response.data?.error || 'Unknown error'}`);
}
throw new Error(`Network Error: ${error.message}`);
}
},

async postChatCompletion(args = {}) {
return this._makeRequest({
path: "/v1/chat/completions",
method: "post",
...args,
});
},
async postCompletion(args = {}) {
return this._makeRequest({
path: `/v1/completions`,
method: "post",
...args,
});
},
async getModel({ model, ...args }) {
return this._makeRequest({
path: `/v1/models/${model}`,
...args,
});
},
async listModels(args = {}) {
return this._makeRequest({
path: "/v1/models",
...args,
});
},
},
};
Loading