diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..c89c478 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,32 @@ +# Mintlify Starter Kit + +Click on `Use this template` to copy the Mintlify starter kit. The starter kit contains examples including + +- Guide pages +- Navigation +- Customizations +- API Reference pages +- Use of popular components + +### Development + +Install the [Mintlify CLI](https://www.npmjs.com/package/mintlify) to preview the documentation changes locally. To install, use the following command + +``` +npm i -g mintlify +``` + +Run the following command at the root of your documentation (where mint.json is) + +``` +mintlify dev +``` + +### Publishing Changes + +Install our Github App to autopropagate changes from youre repo to your deployment. Changes will be deployed to production automatically after pushing to the default branch. Find the link to install on your dashboard. + +#### Troubleshooting + +- Mintlify dev isn't running - Run `mintlify install` it'll re-install dependencies. +- Page loads as a 404 - Make sure you are running in a folder with `mint.json` diff --git a/docs/api-reference/endpoint/create.mdx b/docs/api-reference/endpoint/create.mdx new file mode 100644 index 0000000..5689f1b --- /dev/null +++ b/docs/api-reference/endpoint/create.mdx @@ -0,0 +1,4 @@ +--- +title: 'Create Plant' +openapi: 'POST /plants' +--- diff --git a/docs/api-reference/endpoint/delete.mdx b/docs/api-reference/endpoint/delete.mdx new file mode 100644 index 0000000..657dfc8 --- /dev/null +++ b/docs/api-reference/endpoint/delete.mdx @@ -0,0 +1,4 @@ +--- +title: 'Delete Plant' +openapi: 'DELETE /plants/{id}' +--- diff --git a/docs/api-reference/endpoint/get.mdx b/docs/api-reference/endpoint/get.mdx new file mode 100644 index 0000000..56aa09e --- /dev/null +++ b/docs/api-reference/endpoint/get.mdx @@ -0,0 +1,4 @@ +--- +title: 'Get Plants' +openapi: 'GET /plants' +--- diff --git a/docs/api-reference/introduction.mdx b/docs/api-reference/introduction.mdx new file mode 100644 index 0000000..c835b78 --- /dev/null +++ b/docs/api-reference/introduction.mdx @@ -0,0 +1,33 @@ +--- +title: 'Introduction' +description: 'Example section for showcasing API endpoints' +--- + + + If you're not looking to build API reference documentation, you can delete + this section by removing the api-reference folder. + + +## Welcome + +There are two ways to build API documentation: [OpenAPI](https://mintlify.com/docs/api-playground/openapi/setup) and [MDX components](https://mintlify.com/docs/api-playground/mdx/configuration). For the starter kit, we are using the following OpenAPI specification. + + + View the OpenAPI specification file + + +## Authentication + +All API endpoints are authenticated using Bearer tokens and picked up from the specification file. + +```json +"security": [ + { + "bearerAuth": [] + } +] +``` diff --git a/docs/api-reference/openapi.json b/docs/api-reference/openapi.json new file mode 100644 index 0000000..b1509be --- /dev/null +++ b/docs/api-reference/openapi.json @@ -0,0 +1,195 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "OpenAPI Plant Store", + "description": "A sample API that uses a plant store as an example to demonstrate features in the OpenAPI specification", + "license": { + "name": "MIT" + }, + "version": "1.0.0" + }, + "servers": [ + { + "url": "http://sandbox.mintlify.com" + } + ], + "security": [ + { + "bearerAuth": [] + } + ], + "paths": { + "/plants": { + "get": { + "description": "Returns all plants from the system that the user has access to", + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "The maximum number of results to return", + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "Plant response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Plant" + } + } + } + } + }, + "400": { + "description": "Unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "post": { + "description": "Creates a new plant in the store", + "requestBody": { + "description": "Plant to add to the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPlant" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "plant response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Plant" + } + } + } + }, + "400": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/plants/{id}": { + "delete": { + "description": "Deletes a single plant based on the ID supplied", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of plant to delete", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "Plant deleted", + "content": {} + }, + "400": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Plant": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "description": "The name of the plant", + "type": "string" + }, + "tag": { + "description": "Tag to specify the type", + "type": "string" + } + } + }, + "NewPlant": { + "allOf": [ + { + "$ref": "#/components/schemas/Plant" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "description": "Identification number of the plant", + "type": "integer", + "format": "int64" + } + } + } + ] + }, + "Error": { + "required": [ + "error", + "message" + ], + "type": "object", + "properties": { + "error": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + }, + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer" + } + } + } +} \ No newline at end of file diff --git a/docs/development.mdx b/docs/development.mdx new file mode 100644 index 0000000..8783008 --- /dev/null +++ b/docs/development.mdx @@ -0,0 +1,98 @@ +--- +title: 'Development' +description: 'Learn how to preview changes locally' +--- + + + **Prerequisite** You should have installed Node.js (version 18.10.0 or + higher). + + +Step 1. Install Mintlify on your OS: + + + +```bash npm +npm i -g mintlify +``` + +```bash yarn +yarn global add mintlify +``` + + + +Step 2. Go to the docs are located (where you can find `mint.json`) and run the following command: + +```bash +mintlify dev +``` + +The documentation website is now available at `http://localhost:3000`. + +### Custom Ports + +Mintlify uses port 3000 by default. You can use the `--port` flag to customize the port Mintlify runs on. For example, use this command to run in port 3333: + +```bash +mintlify dev --port 3333 +``` + +You will see an error like this if you try to run Mintlify in a port that's already taken: + +```md +Error: listen EADDRINUSE: address already in use :::3000 +``` + +## Mintlify Versions + +Each CLI is linked to a specific version of Mintlify. Please update the CLI if your local website looks different than production. + + + +```bash npm +npm i -g mintlify@latest +``` + +```bash yarn +yarn global upgrade mintlify +``` + + + +## Deployment + + + Unlimited editors available under the [Startup + Plan](https://mintlify.com/pricing) + + +You should see the following if the deploy successfully went through: + + + + + +## Troubleshooting + +Here's how to solve some common problems when working with the CLI. + + + + Update to Node v18. Run `mintlify install` and try again. + + +Go to the `C:/Users/Username/.mintlify/` directory and remove the `mint` +folder. Then Open the Git Bash in this location and run `git clone +https://github.com/mintlify/mint.git`. + +Repeat step 3. + + + + Try navigating to the root of your device and delete the ~/.mintlify folder. + Then run `mintlify dev` again. + + + +Curious about what changed in a CLI version? [Check out the CLI changelog.](/changelog/command-line) diff --git a/docs/essentials/code.mdx b/docs/essentials/code.mdx new file mode 100644 index 0000000..d2a462a --- /dev/null +++ b/docs/essentials/code.mdx @@ -0,0 +1,37 @@ +--- +title: 'Code Blocks' +description: 'Display inline code and code blocks' +icon: 'code' +--- + +## Basic + +### Inline Code + +To denote a `word` or `phrase` as code, enclose it in backticks (`). + +``` +To denote a `word` or `phrase` as code, enclose it in backticks (`). +``` + +### Code Block + +Use [fenced code blocks](https://www.markdownguide.org/extended-syntax/#fenced-code-blocks) by enclosing code in three backticks and follow the leading ticks with the programming language of your snippet to get syntax highlighting. Optionally, you can also write the name of your code after the programming language. + +```java HelloWorld.java +class HelloWorld { + public static void main(String[] args) { + System.out.println("Hello, World!"); + } +} +``` + +````md +```java HelloWorld.java +class HelloWorld { + public static void main(String[] args) { + System.out.println("Hello, World!"); + } +} +``` +```` diff --git a/docs/essentials/images.mdx b/docs/essentials/images.mdx new file mode 100644 index 0000000..60ad42d --- /dev/null +++ b/docs/essentials/images.mdx @@ -0,0 +1,59 @@ +--- +title: 'Images and Embeds' +description: 'Add image, video, and other HTML elements' +icon: 'image' +--- + + + +## Image + +### Using Markdown + +The [markdown syntax](https://www.markdownguide.org/basic-syntax/#images) lets you add images using the following code + +```md +![title](/path/image.jpg) +``` + +Note that the image file size must be less than 5MB. Otherwise, we recommend hosting on a service like [Cloudinary](https://cloudinary.com/) or [S3](https://aws.amazon.com/s3/). You can then use that URL and embed. + +### Using Embeds + +To get more customizability with images, you can also use [embeds](/writing-content/embed) to add images + +```html + +``` + +## Embeds and HTML elements + + + +
+ + + +Mintlify supports [HTML tags in Markdown](https://www.markdownguide.org/basic-syntax/#html). This is helpful if you prefer HTML tags to Markdown syntax, and lets you create documentation with infinite flexibility. + + + +### iFrames + +Loads another HTML page within the document. Most commonly used for embedding videos. + +```html + +``` diff --git a/docs/essentials/markdown.mdx b/docs/essentials/markdown.mdx new file mode 100644 index 0000000..c8ad9c1 --- /dev/null +++ b/docs/essentials/markdown.mdx @@ -0,0 +1,88 @@ +--- +title: 'Markdown Syntax' +description: 'Text, title, and styling in standard markdown' +icon: 'text-size' +--- + +## Titles + +Best used for section headers. + +```md +## Titles +``` + +### Subtitles + +Best use to subsection headers. + +```md +### Subtitles +``` + + + +Each **title** and **subtitle** creates an anchor and also shows up on the table of contents on the right. + + + +## Text Formatting + +We support most markdown formatting. Simply add `**`, `_`, or `~` around text to format it. + +| Style | How to write it | Result | +| ------------- | ----------------- | --------------- | +| Bold | `**bold**` | **bold** | +| Italic | `_italic_` | _italic_ | +| Strikethrough | `~strikethrough~` | ~strikethrough~ | + +You can combine these. For example, write `**_bold and italic_**` to get **_bold and italic_** text. + +You need to use HTML to write superscript and subscript text. That is, add `` or `` around your text. + +| Text Size | How to write it | Result | +| ----------- | ------------------------ | ---------------------- | +| Superscript | `superscript` | superscript | +| Subscript | `subscript` | subscript | + +## Linking to Pages + +You can add a link by wrapping text in `[]()`. You would write `[link to google](https://google.com)` to [link to google](https://google.com). + +Links to pages in your docs need to be root-relative. Basically, you should include the entire folder path. For example, `[link to text](/writing-content/text)` links to the page "Text" in our components section. + +Relative links like `[link to text](../text)` will open slower because we cannot optimize them as easily. + +## Blockquotes + +### Singleline + +To create a blockquote, add a `>` in front of a paragraph. + +> Dorothy followed her through many of the beautiful rooms in her castle. + +```md +> Dorothy followed her through many of the beautiful rooms in her castle. +``` + +### Multiline + +> Dorothy followed her through many of the beautiful rooms in her castle. +> +> The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood. + +```md +> Dorothy followed her through many of the beautiful rooms in her castle. +> +> The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood. +``` + +### LaTeX + +Mintlify supports [LaTeX](https://www.latex-project.org) through the Latex component. + +8 x (vk x H1 - H2) = (0,1) + +```md +8 x (vk x H1 - H2) = (0,1) +``` diff --git a/docs/essentials/navigation.mdx b/docs/essentials/navigation.mdx new file mode 100644 index 0000000..ca44bb6 --- /dev/null +++ b/docs/essentials/navigation.mdx @@ -0,0 +1,66 @@ +--- +title: 'Navigation' +description: 'The navigation field in mint.json defines the pages that go in the navigation menu' +icon: 'map' +--- + +The navigation menu is the list of links on every website. + +You will likely update `mint.json` every time you add a new page. Pages do not show up automatically. + +## Navigation syntax + +Our navigation syntax is recursive which means you can make nested navigation groups. You don't need to include `.mdx` in page names. + + + +```json Regular Navigation +"navigation": [ + { + "group": "Getting Started", + "pages": ["quickstart"] + } +] +``` + +```json Nested Navigation +"navigation": [ + { + "group": "Getting Started", + "pages": [ + "quickstart", + { + "group": "Nested Reference Pages", + "pages": ["nested-reference-page"] + } + ] + } +] +``` + + + +## Folders + +Simply put your MDX files in folders and update the paths in `mint.json`. + +For example, to have a page at `https://yoursite.com/your-folder/your-page` you would make a folder called `your-folder` containing an MDX file called `your-page.mdx`. + + + +You cannot use `api` for the name of a folder unless you nest it inside another folder. Mintlify uses Next.js which reserves the top-level `api` folder for internal server calls. A folder name such as `api-reference` would be accepted. + + + +```json Navigation With Folder +"navigation": [ + { + "group": "Group Name", + "pages": ["your-folder/your-page"] + } +] +``` + +## Hidden Pages + +MDX files not included in `mint.json` will not show up in the sidebar but are accessible through the search bar and by linking directly to them. diff --git a/docs/essentials/reusable-snippets.mdx b/docs/essentials/reusable-snippets.mdx new file mode 100644 index 0000000..a0a5529 --- /dev/null +++ b/docs/essentials/reusable-snippets.mdx @@ -0,0 +1,110 @@ +--- +title: Reusable Snippets +description: Reusable, custom snippets to keep content in sync +icon: 'recycle' +--- + +import SnippetIntro from '/snippets/snippet-intro.mdx'; + + + +## Creating a custom snippet + +**Pre-condition**: You must create your snippet file in the `snippets` directory. + + + Any page in the `snippets` directory will be treated as a snippet and will not + be rendered into a standalone page. If you want to create a standalone page + from the snippet, import the snippet into another file and call it as a + component. + + +### Default export + +1. Add content to your snippet file that you want to re-use across multiple + locations. Optionally, you can add variables that can be filled in via props + when you import the snippet. + +```mdx snippets/my-snippet.mdx +Hello world! This is my content I want to reuse across pages. My keyword of the +day is {word}. +``` + + + The content that you want to reuse must be inside the `snippets` directory in + order for the import to work. + + +2. Import the snippet into your destination file. + +```mdx destination-file.mdx +--- +title: My title +description: My Description +--- + +import MySnippet from '/snippets/path/to/my-snippet.mdx'; + +## Header + +Lorem impsum dolor sit amet. + + +``` + +### Reusable variables + +1. Export a variable from your snippet file: + +```mdx snippets/path/to/custom-variables.mdx +export const myName = 'my name'; + +export const myObject = { fruit: 'strawberries' }; +``` + +2. Import the snippet from your destination file and use the variable: + +```mdx destination-file.mdx +--- +title: My title +description: My Description +--- + +import { myName, myObject } from '/snippets/path/to/custom-variables.mdx'; + +Hello, my name is {myName} and I like {myObject.fruit}. +``` + +### Reusable components + +1. Inside your snippet file, create a component that takes in props by exporting + your component in the form of an arrow function. + +```mdx snippets/custom-component.mdx +export const MyComponent = ({ title }) => ( +
+

{title}

+

... snippet content ...

+
+); +``` + + + MDX does not compile inside the body of an arrow function. Stick to HTML + syntax when you can or use a default export if you need to use MDX. + + +2. Import the snippet into your destination file and pass in the props + +```mdx destination-file.mdx +--- +title: My title +description: My Description +--- + +import { MyComponent } from '/snippets/custom-component.mdx'; + +Lorem ipsum dolor sit amet. + + +``` diff --git a/docs/essentials/settings.mdx b/docs/essentials/settings.mdx new file mode 100644 index 0000000..ae6e7d6 --- /dev/null +++ b/docs/essentials/settings.mdx @@ -0,0 +1,318 @@ +--- +title: 'Global Settings' +description: 'Mintlify gives you complete control over the look and feel of your documentation using the mint.json file' +icon: 'gear' +--- + +Every Mintlify site needs a `mint.json` file with the core configuration settings. Learn more about the [properties](#properties) below. + +## Properties + + +Name of your project. Used for the global title. + +Example: `mintlify` + + + + + An array of groups with all the pages within that group + + + The name of the group. + + Example: `Settings` + + + + The relative paths to the markdown files that will serve as pages. + + Example: `["customization", "page"]` + + + + + + + + Path to logo image or object with path to "light" and "dark" mode logo images + + + Path to the logo in light mode + + + Path to the logo in dark mode + + + Where clicking on the logo links you to + + + + + + Path to the favicon image + + + + Hex color codes for your global theme + + + The primary color. Used for most often for highlighted content, section + headers, accents, in light mode + + + The primary color for dark mode. Used for most often for highlighted + content, section headers, accents, in dark mode + + + The primary color for important buttons + + + The color of the background in both light and dark mode + + + The hex color code of the background in light mode + + + The hex color code of the background in dark mode + + + + + + + + Array of `name`s and `url`s of links you want to include in the topbar + + + The name of the button. + + Example: `Contact us` + + + The url once you click on the button. Example: `https://mintlify.com/contact` + + + + + + + + + Link shows a button. GitHub shows the repo information at the url provided including the number of GitHub stars. + + + If `link`: What the button links to. + + If `github`: Link to the repository to load GitHub information from. + + + Text inside the button. Only required if `type` is a `link`. + + + + + + + Array of version names. Only use this if you want to show different versions + of docs with a dropdown in the navigation bar. + + + + An array of the anchors, includes the `icon`, `color`, and `url`. + + + The [Font Awesome](https://fontawesome.com/search?s=brands%2Cduotone) icon used to feature the anchor. + + Example: `comments` + + + The name of the anchor label. + + Example: `Community` + + + The start of the URL that marks what pages go in the anchor. Generally, this is the name of the folder you put your pages in. + + + The hex color of the anchor icon background. Can also be a gradient if you pass an object with the properties `from` and `to` that are each a hex color. + + + Used if you want to hide an anchor until the correct docs version is selected. + + + Pass `true` if you want to hide the anchor until you directly link someone to docs inside it. + + + One of: "brands", "duotone", "light", "sharp-solid", "solid", or "thin" + + + + + + + Override the default configurations for the top-most anchor. + + + The name of the top-most anchor + + + Font Awesome icon. + + + One of: "brands", "duotone", "light", "sharp-solid", "solid", or "thin" + + + + + + An array of navigational tabs. + + + The name of the tab label. + + + The start of the URL that marks what pages go in the tab. Generally, this + is the name of the folder you put your pages in. + + + + + + Configuration for API settings. Learn more about API pages at [API Components](/api-playground/demo). + + + The base url for all API endpoints. If `baseUrl` is an array, it will enable for multiple base url + options that the user can toggle. + + + + + + The authentication strategy used for all API endpoints. + + + The name of the authentication parameter used in the API playground. + + If method is `basic`, the format should be `[usernameName]:[passwordName]` + + + The default value that's designed to be a prefix for the authentication input field. + + E.g. If an `inputPrefix` of `AuthKey` would inherit the default input result of the authentication field as `AuthKey`. + + + + + + Configurations for the API playground + + + + Whether the playground is showing, hidden, or only displaying the endpoint with no added user interactivity `simple` + + Learn more at the [playground guides](/api-playground/demo) + + + + + + Enabling this flag ensures that key ordering in OpenAPI pages matches the key ordering defined in the OpenAPI file. + + This behavior will soon be enabled by default, at which point this field will be deprecated. + + + + + + + A string or an array of strings of URL(s) or relative path(s) pointing to your + OpenAPI file. + + Examples: + + ```json Absolute + "openapi": "https://example.com/openapi.json" + ``` + ```json Relative + "openapi": "/openapi.json" + ``` + ```json Multiple + "openapi": ["https://example.com/openapi1.json", "/openapi2.json", "/openapi3.json"] + ``` + + + + + + An object of social media accounts where the key:property pair represents the social media platform and the account url. + + Example: + ```json + { + "twitter": "https://twitter.com/mintlify", + "website": "https://mintlify.com" + } + ``` + + + One of the following values `website`, `facebook`, `twitter`, `discord`, `slack`, `github`, `linkedin`, `instagram`, `hacker-news` + + Example: `twitter` + + + The URL to the social platform. + + Example: `https://twitter.com/mintlify` + + + + + + Configurations to enable feedback buttons + + + + Enables a button to allow users to suggest edits via pull requests + + + Enables a button to allow users to raise an issue about the documentation + + + + + + Customize the dark mode toggle. + + + Set if you always want to show light or dark mode for new users. When not + set, we default to the same mode as the user's operating system. + + + Set to true to hide the dark/light mode toggle. You can combine `isHidden` with `default` to force your docs to only use light or dark mode. For example: + + + ```json Only Dark Mode + "modeToggle": { + "default": "dark", + "isHidden": true + } + ``` + + ```json Only Light Mode + "modeToggle": { + "default": "light", + "isHidden": true + } + ``` + + + + + + + + + A background image to be displayed behind every page. See example with + [Infisical](https://infisical.com/docs) and [FRPC](https://frpc.io). + diff --git a/docs/favicon.svg b/docs/favicon.svg new file mode 100644 index 0000000..6a32332 --- /dev/null +++ b/docs/favicon.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/checks-passed.png b/docs/images/checks-passed.png new file mode 100644 index 0000000..3303c77 Binary files /dev/null and b/docs/images/checks-passed.png differ diff --git a/docs/images/hero-dark.svg b/docs/images/hero-dark.svg new file mode 100644 index 0000000..c6a30e8 --- /dev/null +++ b/docs/images/hero-dark.svg @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/hero-light.svg b/docs/images/hero-light.svg new file mode 100644 index 0000000..297d68f --- /dev/null +++ b/docs/images/hero-light.svg @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/introduction.mdx b/docs/introduction.mdx new file mode 100644 index 0000000..2589c0b --- /dev/null +++ b/docs/introduction.mdx @@ -0,0 +1,71 @@ +--- +title: Introduction +description: 'Welcome to the home of your new documentation' +--- + +Hero Light +Hero Dark + +## Setting up + +The first step to world-class documentation is setting up your editing environments. + + + + Get your docs set up locally for easy development + + + Preview your changes before you push to make sure they're perfect + + + +## Make it yours + +Update your docs to your brand and add valuable content for the best user conversion. + + + + Customize your docs to your company's colors and brands + + + Automatically generate endpoints from an OpenAPI spec + + + Build interactive features and designs to guide your users + + + Check out our showcase of our favorite documentation + + diff --git a/docs/logo/dark.svg b/docs/logo/dark.svg new file mode 100644 index 0000000..a628378 --- /dev/null +++ b/docs/logo/dark.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/logo/light.svg b/docs/logo/light.svg new file mode 100644 index 0000000..582b3b9 --- /dev/null +++ b/docs/logo/light.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/mint.json b/docs/mint.json new file mode 100644 index 0000000..f660496 --- /dev/null +++ b/docs/mint.json @@ -0,0 +1,91 @@ +{ + "$schema": "https://mintlify.com/schema.json", + "name": "Starter Kit", + "logo": { + "dark": "/logo/dark.svg", + "light": "/logo/light.svg" + }, + "favicon": "/favicon.svg", + "colors": { + "primary": "#0D9373", + "light": "#07C983", + "dark": "#0D9373", + "anchors": { + "from": "#0D9373", + "to": "#07C983" + } + }, + "topbarLinks": [ + { + "name": "Support", + "url": "mailto:hi@mintlify.com" + } + ], + "topbarCtaButton": { + "name": "Dashboard", + "url": "https://dashboard.mintlify.com" + }, + "tabs": [ + { + "name": "API Reference", + "url": "api-reference" + } + ], + "anchors": [ + { + "name": "Documentation", + "icon": "book-open-cover", + "url": "https://mintlify.com/docs" + }, + { + "name": "Community", + "icon": "slack", + "url": "https://mintlify.com/community" + }, + { + "name": "Blog", + "icon": "newspaper", + "url": "https://mintlify.com/blog" + } + ], + "navigation": [ + { + "group": "Get Started", + "pages": [ + "introduction", + "quickstart", + "development" + ] + }, + { + "group": "Essentials", + "pages": [ + "essentials/markdown", + "essentials/code", + "essentials/images", + "essentials/settings", + "essentials/navigation", + "essentials/reusable-snippets" + ] + }, + { + "group": "API Documentation", + "pages": [ + "api-reference/introduction" + ] + }, + { + "group": "Endpoint Examples", + "pages": [ + "api-reference/endpoint/get", + "api-reference/endpoint/create", + "api-reference/endpoint/delete" + ] + } + ], + "footerSocials": { + "twitter": "https://twitter.com/mintlify", + "github": "https://github.com/mintlify", + "linkedin": "https://www.linkedin.com/company/mintsearch" + } +} \ No newline at end of file diff --git a/docs/quickstart.mdx b/docs/quickstart.mdx new file mode 100644 index 0000000..d7f3486 --- /dev/null +++ b/docs/quickstart.mdx @@ -0,0 +1,86 @@ +--- +title: 'Quickstart' +description: 'Start building awesome documentation in under 5 minutes' +--- + +## Setup your development + +Learn how to update your docs locally and and deploy them to the public. + +### Edit and preview + + + + During the onboarding process, we created a repository on your Github with + your docs content. You can find this repository on our + [dashboard](https://dashboard.mintlify.com). To clone the repository + locally, follow these + [instructions](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) + in your terminal. + + + Previewing helps you make sure your changes look as intended. We built a + command line interface to render these changes locally. 1. Install the + [Mintlify CLI](https://www.npmjs.com/package/mintlify) to preview the + documentation changes locally with this command: ``` npm i -g mintlify ``` + 2. Run the following command at the root of your documentation (where + `mint.json` is): ``` mintlify dev ``` + + + +### Deploy your changes + + + + + Our Github app automatically deploys your changes to your docs site, so you + don't need to manage deployments yourself. You can find the link to install on + your [dashboard](https://dashboard.mintlify.com). Once the bot has been + successfully installed, there should be a check mark next to the commit hash + of the repo. + + + [Commit and push your changes to + Git](https://docs.github.com/en/get-started/using-git/pushing-commits-to-a-remote-repository#about-git-push) + for your changes to update in your docs site. If you push and don't see that + the Github app successfully deployed your changes, you can also manually + update your docs through our [dashboard](https://dashboard.mintlify.com). + + + + +## Update your docs + +Add content directly in your files with MDX syntax and React components. You can use any of our components, or even build your own. + + + + + Add flair to your docs with personalized branding. + + + + Implement your OpenAPI spec and enable API user interaction. + + + + Draw insights from user interactions with your documentation. + + + + Keep your docs on your own website's subdomain. + + + diff --git a/docs/snippets/snippet-intro.mdx b/docs/snippets/snippet-intro.mdx new file mode 100644 index 0000000..c57e7c7 --- /dev/null +++ b/docs/snippets/snippet-intro.mdx @@ -0,0 +1,4 @@ +One of the core principles of software development is DRY (Don't Repeat +Yourself). This is a principle that apply to documentation as +well. If you find yourself repeating the same content in multiple places, you +should consider creating a custom snippet to keep your content in sync. diff --git a/poetry.lock b/poetry.lock index d53a0ca..36581ee 100644 --- a/poetry.lock +++ b/poetry.lock @@ -205,6 +205,52 @@ charset-normalizer = ["charset-normalizer"] html5lib = ["html5lib"] lxml = ["lxml"] +[[package]] +name = "black" +version = "24.2.0" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-24.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6981eae48b3b33399c8757036c7f5d48a535b962a7c2310d19361edeef64ce29"}, + {file = "black-24.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d533d5e3259720fdbc1b37444491b024003e012c5173f7d06825a77508085430"}, + {file = "black-24.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61a0391772490ddfb8a693c067df1ef5227257e72b0e4108482b8d41b5aee13f"}, + {file = "black-24.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:992e451b04667116680cb88f63449267c13e1ad134f30087dec8527242e9862a"}, + {file = "black-24.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:163baf4ef40e6897a2a9b83890e59141cc8c2a98f2dda5080dc15c00ee1e62cd"}, + {file = "black-24.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e37c99f89929af50ffaf912454b3e3b47fd64109659026b678c091a4cd450fb2"}, + {file = "black-24.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9de21bafcba9683853f6c96c2d515e364aee631b178eaa5145fc1c61a3cc92"}, + {file = "black-24.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:9db528bccb9e8e20c08e716b3b09c6bdd64da0dd129b11e160bf082d4642ac23"}, + {file = "black-24.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d84f29eb3ee44859052073b7636533ec995bd0f64e2fb43aeceefc70090e752b"}, + {file = "black-24.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e08fb9a15c914b81dd734ddd7fb10513016e5ce7e6704bdd5e1251ceee51ac9"}, + {file = "black-24.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:810d445ae6069ce64030c78ff6127cd9cd178a9ac3361435708b907d8a04c693"}, + {file = "black-24.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ba15742a13de85e9b8f3239c8f807723991fbfae24bad92d34a2b12e81904982"}, + {file = "black-24.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7e53a8c630f71db01b28cd9602a1ada68c937cbf2c333e6ed041390d6968faf4"}, + {file = "black-24.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:93601c2deb321b4bad8f95df408e3fb3943d85012dddb6121336b8e24a0d1218"}, + {file = "black-24.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0057f800de6acc4407fe75bb147b0c2b5cbb7c3ed110d3e5999cd01184d53b0"}, + {file = "black-24.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:faf2ee02e6612577ba0181f4347bcbcf591eb122f7841ae5ba233d12c39dcb4d"}, + {file = "black-24.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:057c3dc602eaa6fdc451069bd027a1b2635028b575a6c3acfd63193ced20d9c8"}, + {file = "black-24.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:08654d0797e65f2423f850fc8e16a0ce50925f9337fb4a4a176a7aa4026e63f8"}, + {file = "black-24.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca610d29415ee1a30a3f30fab7a8f4144e9d34c89a235d81292a1edb2b55f540"}, + {file = "black-24.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:4dd76e9468d5536abd40ffbc7a247f83b2324f0c050556d9c371c2b9a9a95e31"}, + {file = "black-24.2.0-py3-none-any.whl", hash = "sha256:e8a6ae970537e67830776488bca52000eaa37fa63b9988e8c487458d9cd5ace6"}, + {file = "black-24.2.0.tar.gz", hash = "sha256:bce4f25c27c3435e4dace4815bcb2008b87e167e3bf4ee47ccdc5ce906eb4894"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + [[package]] name = "cachetools" version = "5.3.3" @@ -390,6 +436,20 @@ files = [ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + [[package]] name = "cloud-sql-python-connector" version = "1.7.0" @@ -1062,6 +1122,20 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "isort" +version = "5.13.2" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, +] + +[package.extras] +colors = ["colorama (>=0.4.6)"] + [[package]] name = "jsonpatch" version = "1.33" @@ -1212,13 +1286,13 @@ pinecone-client = ">=3,<4" [[package]] name = "langsmith" -version = "0.1.9" +version = "0.1.10" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = ">=3.8.1,<4.0" files = [ - {file = "langsmith-0.1.9-py3-none-any.whl", hash = "sha256:f821b3cb07a87eac5cb2181ff0b61051811e4eef09ae4b46e700981f7ae5dfb9"}, - {file = "langsmith-0.1.9.tar.gz", hash = "sha256:9bd3e80607722c3d2db84cf3440005491a859b80b5e499bc988032d5c2da91f0"}, + {file = "langsmith-0.1.10-py3-none-any.whl", hash = "sha256:2997a80aea60ed235d83502a7ccdc1f62ffb4dd6b3b7dd4218e8fa4de68a6725"}, + {file = "langsmith-0.1.10.tar.gz", hash = "sha256:13e7e8b52e694aa4003370cefbb9e79cce3540c65dbf1517902bf7aa4dbbb653"}, ] [package.dependencies] @@ -1687,6 +1761,17 @@ sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-d test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] xml = ["lxml (>=4.9.2)"] +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + [[package]] name = "pg8000" version = "1.30.5" @@ -1722,6 +1807,21 @@ urllib3 = ">=1.26.0" [package.extras] grpc = ["googleapis-common-protos (>=1.53.0)", "grpc-gateway-protoc-gen-openapiv2 (==0.1.0)", "grpcio (>=1.44.0)", "lz4 (>=3.1.3)", "protobuf (>=3.20.0,<3.21.0)"] +[[package]] +name = "platformdirs" +version = "4.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] + [[package]] name = "pluggy" version = "1.4.0" @@ -2705,4 +2805,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.13" -content-hash = "19818bacabbb1c26aabaeccfd204f8c47391e6dd07e4dd600426a8325fc45deb" +content-hash = "046fc69456aa904e255345498cf7375399d04471731e1eeaa34465534c190244" diff --git a/pyproject.toml b/pyproject.toml index 2a37445..12d707a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,13 @@ pydantic = "2.6.1" langchain-pinecone = "^0.0.3" + + [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" + +[tool.poetry.dev-dependencies] +pytest = "^7.4.4" +black = "^24.2.0" +isort = "^5.13.2" diff --git a/src/sayvai_tools/tools/__init__.py b/src/sayvai_tools/tools/__init__.py index 80f0117..c0426fc 100644 --- a/src/sayvai_tools/tools/__init__.py +++ b/src/sayvai_tools/tools/__init__.py @@ -53,7 +53,7 @@ "InsertCommentTool", "ListCommentRepliesTool", "ReplyToCommentTool", - "load_tools" + "load_tools", ] diff --git a/src/sayvai_tools/tools/google_calendar/__init__.py b/src/sayvai_tools/tools/google_calendar/__init__.py index daf166b..ecf7cc0 100644 --- a/src/sayvai_tools/tools/google_calendar/__init__.py +++ b/src/sayvai_tools/tools/google_calendar/__init__.py @@ -1,4 +1,5 @@ -from sayvai_tools.tools.google_calendar.available_slots import AvailableSlotsTool +from sayvai_tools.tools.google_calendar.available_slots import \ + AvailableSlotsTool from sayvai_tools.tools.google_calendar.create_event import CreateEventTool from sayvai_tools.tools.google_calendar.display_events import DisplayEventsTool from sayvai_tools.tools.google_calendar.utils import get_calendar_credentials diff --git a/src/sayvai_tools/tools/google_calendar/create_event.py b/src/sayvai_tools/tools/google_calendar/create_event.py index 7601235..2bb5d60 100644 --- a/src/sayvai_tools/tools/google_calendar/create_event.py +++ b/src/sayvai_tools/tools/google_calendar/create_event.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timedelta from typing import List, Optional, Type from googleapiclient.errors import HttpError @@ -104,24 +104,18 @@ def _create_event( def _run( self, - calendar_id: str, - summary: str, - start_time: datetime, - end_time: datetime, - description: Optional[str] = None, - location: Optional[str] = None, - attendees: Optional[List[str]] = None, run_manager: Optional[CallbackManagerForToolRun] = None, + **kwargs, ) -> dict: try: created_event = self._create_event( - calendar_id, - summary, - start_time, - end_time, - description, - location, - attendees, + calendar_id=kwargs.get("calendar_id", "primary"), + summary=kwargs.get("summary", "meeting"), + start_time=kwargs.get("start_time", datetime.now()), + end_time=kwargs.get("end_time", datetime.now() + timedelta(hours=1)), + description=kwargs.get("description", None), + location=kwargs.get("location", None), + attendees=kwargs.get("attendees", None), ) return created_event except Exception as e: diff --git a/src/sayvai_tools/tools/google_calendar/display_events.py b/src/sayvai_tools/tools/google_calendar/display_events.py index c25742c..1639c88 100644 --- a/src/sayvai_tools/tools/google_calendar/display_events.py +++ b/src/sayvai_tools/tools/google_calendar/display_events.py @@ -26,7 +26,6 @@ class DisplayEventsTool(GoogleCalendarBaseTool): ) args_schema: Type[DisplayEventsSchema] = DisplayEventsSchema - @classmethod def create(cls) -> "DisplayEventsTool": return cls() @@ -62,12 +61,12 @@ def _display_events( def _run( self, - calendar_id: str, - max_results: int = 10, run_manager: Optional[CallbackManagerForToolRun] = None, + **kwargs, ) -> List[dict]: try: - events = self._display_events(calendar_id, max_results) + events = self._display_events(calendar_id=kwargs.get("calendar_id", "primary"), + max_results=kwargs.get("max_results", 10)) return events except Exception as e: raise Exception(f"An error occurred: {e}") diff --git a/src/sayvai_tools/tools/google_sheets/__init__.py b/src/sayvai_tools/tools/google_sheets/__init__.py index 35cfc8c..74fa33b 100644 --- a/src/sayvai_tools/tools/google_sheets/__init__.py +++ b/src/sayvai_tools/tools/google_sheets/__init__.py @@ -1,7 +1,9 @@ from sayvai_tools.tools.google_sheets.append_data import AppendDataTool -from sayvai_tools.tools.google_sheets.create_spreadsheet import CreateSpreadsheetTool +from sayvai_tools.tools.google_sheets.create_spreadsheet import \ + CreateSpreadsheetTool from sayvai_tools.tools.google_sheets.get_cell_values import GetCellValuesTool -from sayvai_tools.tools.google_sheets.update_spreadsheet import UpdateSpreadsheetTool +from sayvai_tools.tools.google_sheets.update_spreadsheet import \ + UpdateSpreadsheetTool from sayvai_tools.tools.google_sheets.utils import get_sheets_credentials __all__ = [ @@ -9,5 +11,5 @@ "get_sheets_credentials", "AppendDataTool", "GetCellValuesTool", - "UpdateSpreadsheetTool" + "UpdateSpreadsheetTool", ] diff --git a/src/sayvai_tools/tools/google_sheets/append_data.py b/src/sayvai_tools/tools/google_sheets/append_data.py index b2454a1..aba3ae4 100644 --- a/src/sayvai_tools/tools/google_sheets/append_data.py +++ b/src/sayvai_tools/tools/google_sheets/append_data.py @@ -20,8 +20,6 @@ class AppendDataSchema(BaseModel): ) - - class AppendDataTool(GoogleSheetsBaseTool): """Tool for appending data to a Google Sheets spreadsheet.""" diff --git a/src/sayvai_tools/tools/google_sheets/get_cell_values.py b/src/sayvai_tools/tools/google_sheets/get_cell_values.py index 1d5b62c..80a7831 100644 --- a/src/sayvai_tools/tools/google_sheets/get_cell_values.py +++ b/src/sayvai_tools/tools/google_sheets/get_cell_values.py @@ -1,4 +1,5 @@ from typing import List, Optional, Type + from googleapiclient.errors import HttpError from langchain_core.callbacks import CallbackManagerForToolRun from langchain_core.pydantic_v1 import BaseModel, Field @@ -30,7 +31,7 @@ class GetCellValuesTool(GoogleSheetsBaseTool): @classmethod def create(cls) -> "GetCellValuesTool": return cls() - + def _get_cell_values(self, spreadsheet_id: str, range_: str) -> List[List[str]]: """Retrieve cell values from the specified range in the Google Sheets spreadsheet. diff --git a/src/sayvai_tools/tools/google_sheets/update_spreadsheet.py b/src/sayvai_tools/tools/google_sheets/update_spreadsheet.py index f1fa77c..c6455d1 100644 --- a/src/sayvai_tools/tools/google_sheets/update_spreadsheet.py +++ b/src/sayvai_tools/tools/google_sheets/update_spreadsheet.py @@ -1,29 +1,31 @@ from typing import List, Optional, Type + from googleapiclient.errors import HttpError from langchain_core.callbacks import CallbackManagerForToolRun from langchain_core.pydantic_v1 import BaseModel, Field from sayvai_tools.tools.google_sheets.base import GoogleSheetsBaseTool + class UpdateSpreadsheetSchema(BaseModel): """Input schema for UpdateSpreadsheetTool.""" - spreadsheet_id: str = Field( - ..., - description="ID of the spreadsheet to update." - ) + + spreadsheet_id: str = Field(..., description="ID of the spreadsheet to update.") range_: str = Field( - ..., - description="The range of cells to update. For example, 'Sheet1!A1:B2'." + ..., description="The range of cells to update. For example, 'Sheet1!A1:B2'." ) values: List[List[str]] = Field( - ..., - description="New values to update in the specified range." + ..., description="New values to update in the specified range." ) + class UpdateSpreadsheetTool(GoogleSheetsBaseTool): """Tool for updating cell values in a Google Sheets spreadsheet.""" + name: str = "update_spreadsheet" - description: str = "Use this tool to update cell values in a specified range of a Google Sheets spreadsheet." + description: str = ( + "Use this tool to update cell values in a specified range of a Google Sheets spreadsheet." + ) args_schema: Type[UpdateSpreadsheetSchema] = UpdateSpreadsheetSchema @classmethod @@ -31,10 +33,7 @@ def create(cls) -> "UpdateSpreadsheetTool": return cls() def _update_spreadsheet( - self, - spreadsheet_id: str, - range_: str, - values: List[List[str]] + self, spreadsheet_id: str, range_: str, values: List[List[str]] ) -> None: """Update cell values in the specified range of the Google Sheets spreadsheet. @@ -47,15 +46,13 @@ def _update_spreadsheet( HttpError: If an HTTP error occurs during the API call. Exception: If any other error occurs. """ - body = { - "values": values - } + body = {"values": values} try: self.api_resource.spreadsheets().values().update( spreadsheetId=spreadsheet_id, range=range_, valueInputOption="USER_ENTERED", - body=body + body=body, ).execute() except HttpError as e: raise HttpError(f"An HTTP error occurred: {e}", e.resp) @@ -67,7 +64,7 @@ def _run( spreadsheet_id: str, range_: str, values: List[List[str]], - run_manager: Optional[CallbackManagerForToolRun] = None + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> None: try: self._update_spreadsheet(spreadsheet_id, range_, values) diff --git a/src/sayvai_tools/tools/pdfreader/__init__.py b/src/sayvai_tools/tools/pdfreader/__init__.py index 2aacddc..8d6b2ca 100644 --- a/src/sayvai_tools/tools/pdfreader/__init__.py +++ b/src/sayvai_tools/tools/pdfreader/__init__.py @@ -1,4 +1,5 @@ # init file from pdf reader tool -from sayvai_tools.tools.pdfreader.tool import ReadPagesTool, ReadPageTool, ReadPDFTool +from sayvai_tools.tools.pdfreader.tool import (ReadPagesTool, ReadPageTool, + ReadPDFTool) __all__ = ["ReadPagesTool", "ReadPDFTool", "ReadPageTool"] diff --git a/src/sayvai_tools/tools/pdfreader/tool.py b/src/sayvai_tools/tools/pdfreader/tool.py index f42a02a..0082bcc 100644 --- a/src/sayvai_tools/tools/pdfreader/tool.py +++ b/src/sayvai_tools/tools/pdfreader/tool.py @@ -15,7 +15,7 @@ class ReadPDFTool(BaseTool): @classmethod def create(cls) -> "ReadPDFTool": return cls() - + def _run(self, file_path: str) -> str: return read_pdf(file_path) diff --git a/src/sayvai_tools/tools/power_bi/__init__.py b/src/sayvai_tools/tools/power_bi/__init__.py index 85da054..6d06c94 100644 --- a/src/sayvai_tools/tools/power_bi/__init__.py +++ b/src/sayvai_tools/tools/power_bi/__init__.py @@ -5,5 +5,5 @@ # https://python.langchain.com/docs/integrations/toolkits/powerbi refer for integration # https://github.com/langchain-ai/langchain/blob/023cb59e8aaf3dfaad684b3fcf57a1c363b9abd1/libs/community/langchain_community/tools/powerbi/prompt.py # https://github.com/langchain-ai/langchain/blob/master/libs/community/tests/integration_tests/utilities/test_powerbi_api.py -# https://pbi-guy.com/2022/01/07/refresh-a-power-bi-dataset-with-python/ -# https://learn.microsoft.com/en-us/power-bi/developer/embedded/embed-sample-for-customers?tabs=python \ No newline at end of file +# https://pbi-guy.com/2022/01/07/refresh-a-power-bi-dataset-with-python/ +# https://learn.microsoft.com/en-us/power-bi/developer/embedded/embed-sample-for-customers?tabs=python diff --git a/src/sayvai_tools/tools/power_bi/dashboard_visualizations_to_csv.py b/src/sayvai_tools/tools/power_bi/dashboard_visualizations_to_csv.py index df6ed47..1207ec0 100644 --- a/src/sayvai_tools/tools/power_bi/dashboard_visualizations_to_csv.py +++ b/src/sayvai_tools/tools/power_bi/dashboard_visualizations_to_csv.py @@ -1,5 +1,5 @@ -import requests import pandas as pd +import requests # Azure AD App information client_id = "your_client_id" @@ -16,57 +16,69 @@ # Get Access Token for retrieving visualizations token_data = { - 'grant_type': 'client_credentials', - 'client_id': client_id, - 'client_secret': client_secret, - 'resource': 'https://graph.microsoft.com' + "grant_type": "client_credentials", + "client_id": client_id, + "client_secret": client_secret, + "resource": "https://graph.microsoft.com", } token_response = requests.post(token_url, data=token_data) -access_token = token_response.json().get('access_token') +access_token = token_response.json().get("access_token") # Retrieve visualizations from the Power BI report headers = { - 'Content-Type': 'application/json', - 'Authorization': f'Bearer {access_token}' + "Content-Type": "application/json", + "Authorization": f"Bearer {access_token}", } response = requests.get(report_visualizations_url, headers=headers) if response.status_code == 200: - visualizations_data = response.json()['value'] + visualizations_data = response.json()["value"] # Loop through each visualization and get the ID for visualization in visualizations_data: - visualization_id = visualization['id'] - visualization_name = visualization['displayName'] + visualization_id = visualization["id"] + visualization_name = visualization["displayName"] - print(f"Visualization Name: {visualization_name}, Visualization ID: {visualization_id}") + print( + f"Visualization Name: {visualization_name}, Visualization ID: {visualization_id}" + ) # Get Access Token for retrieving visualization data token_data = { - 'grant_type': 'client_credentials', - 'client_id': client_id, - 'client_secret': client_secret, - 'resource': 'https://graph.microsoft.com' + "grant_type": "client_credentials", + "client_id": client_id, + "client_secret": client_secret, + "resource": "https://graph.microsoft.com", } token_response = requests.post(token_url, data=token_data) - access_token = token_response.json().get('access_token') + access_token = token_response.json().get("access_token") # Retrieve data from the Power BI visualization visualization_data_url = f"https://api.powerbi.com/v1.0/myorg/groups/{workspace_id}/reports/{report_id}/visualizations/{visualization_id}/data" - response = requests.get(visualization_data_url, headers={'Authorization': f'Bearer {access_token}'}) + response = requests.get( + visualization_data_url, headers={"Authorization": f"Bearer {access_token}"} + ) if response.status_code == 200: # Convert JSON data to Pandas DataFrame - data = response.json()['dataPoints'] + data = response.json()["dataPoints"] df = pd.DataFrame(data) # Save DataFrame to CSV - df.to_csv(f'power_bi_visualization_data_{visualization_name}.csv', index=False) - print(f"Visualization data for {visualization_name} exported to CSV successfully.") + df.to_csv( + f"power_bi_visualization_data_{visualization_name}.csv", index=False + ) + print( + f"Visualization data for {visualization_name} exported to CSV successfully." + ) else: - print(f"Error retrieving visualization data. Status code: {response.status_code}, Response: {response.text}") + print( + f"Error retrieving visualization data. Status code: {response.status_code}, Response: {response.text}" + ) else: - print(f"Error retrieving visualizations. Status code: {response.status_code}, Response: {response.text}") + print( + f"Error retrieving visualizations. Status code: {response.status_code}, Response: {response.text}" + ) diff --git a/src/sayvai_tools/tools/power_bi/load_csv_to_powerbi.py b/src/sayvai_tools/tools/power_bi/load_csv_to_powerbi.py index 402e43e..42503da 100644 --- a/src/sayvai_tools/tools/power_bi/load_csv_to_powerbi.py +++ b/src/sayvai_tools/tools/power_bi/load_csv_to_powerbi.py @@ -1,6 +1,7 @@ -import requests import json + import pandas as pd +import requests # Azure AD App information client_id = "your_client_id" @@ -16,14 +17,14 @@ # Get Access Token token_data = { - 'grant_type': 'client_credentials', - 'client_id': client_id, - 'client_secret': client_secret, - 'resource': 'https://graph.microsoft.com' + "grant_type": "client_credentials", + "client_id": client_id, + "client_secret": client_secret, + "resource": "https://graph.microsoft.com", } token_response = requests.post(token_url, data=token_data) -access_token = token_response.json().get('access_token') +access_token = token_response.json().get("access_token") # Load CSV data into a Pandas DataFrame csv_file_path = "path/to/your/file.csv" @@ -32,23 +33,22 @@ # Convert DataFrame to JSON tables = [] for table_name, table_data in df.items(): - columns = [{'name': col} for col in table_data.columns] - tables.append({'name': table_name, 'columns': columns}) + columns = [{"name": col} for col in table_data.columns] + tables.append({"name": table_name, "columns": columns}) # Publish Dataset to Power BI headers = { - 'Content-Type': 'application/json', - 'Authorization': f'Bearer {access_token}' + "Content-Type": "application/json", + "Authorization": f"Bearer {access_token}", } -dataset_payload = { - 'name': 'YourDatasetName', - 'tables': tables -} +dataset_payload = {"name": "YourDatasetName", "tables": tables} response = requests.post(datasets_url, headers=headers, json=dataset_payload) if response.status_code == 201: print("Dataset published successfully.") else: - print(f"Error publishing dataset. Status code: {response.status_code}, Response: {response.text}") + print( + f"Error publishing dataset. Status code: {response.status_code}, Response: {response.text}" + ) diff --git a/src/sayvai_tools/tools/power_bi/prompt.py b/src/sayvai_tools/tools/power_bi/prompt.py index 660cd55..caf3275 100644 --- a/src/sayvai_tools/tools/power_bi/prompt.py +++ b/src/sayvai_tools/tools/power_bi/prompt.py @@ -67,4 +67,4 @@ ) BAD_REQUEST_RESPONSE = "Error on this question, the error was {error}, you can try to rephrase the question." SCHEMA_ERROR_RESPONSE = "Bad request, are you sure the table name is correct?" -UNAUTHORIZED_RESPONSE = "Unauthorized. Try changing your authentication, do not retry." \ No newline at end of file +UNAUTHORIZED_RESPONSE = "Unauthorized. Try changing your authentication, do not retry." diff --git a/src/sayvai_tools/tools/power_bi/test_api.py b/src/sayvai_tools/tools/power_bi/test_api.py index ee17754..6dddc1d 100644 --- a/src/sayvai_tools/tools/power_bi/test_api.py +++ b/src/sayvai_tools/tools/power_bi/test_api.py @@ -1,7 +1,6 @@ import pytest -from langchain_core.utils import get_from_env - from langchain_community.utilities.powerbi import PowerBIDataset +from langchain_core.utils import get_from_env def azure_installed() -> bool: @@ -32,4 +31,4 @@ def test_daxquery() -> None: output = powerbi.run(f'EVALUATE ROW("RowCount", COUNTROWS({TABLE_NAME}))') numrows = str(output["results"][0]["tables"][0]["rows"][0]["[RowCount]"]) - assert NUM_ROWS == numrows \ No newline at end of file + assert NUM_ROWS == numrows diff --git a/src/sayvai_tools/tools/power_bi/utils.py b/src/sayvai_tools/tools/power_bi/utils.py index bca4402..02a6555 100644 --- a/src/sayvai_tools/tools/power_bi/utils.py +++ b/src/sayvai_tools/tools/power_bi/utils.py @@ -1,22 +1,18 @@ """Tools for interacting with a Power BI dataset.""" + import logging from time import perf_counter from typing import Any, Dict, Optional, Tuple -from langchain_core.callbacks import ( - AsyncCallbackManagerForToolRun, - CallbackManagerForToolRun, -) -from langchain_core.pydantic_v1 import Field, validator -from langchain_core.tools import BaseTool - from langchain_community.chat_models.openai import _import_tiktoken -from langchain_community.tools.powerbi.prompt import ( - BAD_REQUEST_RESPONSE, - DEFAULT_FEWSHOT_EXAMPLES, - RETRY_RESPONSE, -) +from langchain_community.tools.powerbi.prompt import (BAD_REQUEST_RESPONSE, + DEFAULT_FEWSHOT_EXAMPLES, + RETRY_RESPONSE) from langchain_community.utilities.powerbi import PowerBIDataset, json_to_md +from langchain_core.callbacks import (AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun) +from langchain_core.pydantic_v1 import Field, validator +from langchain_core.tools import BaseTool logger = logging.getLogger(__name__) @@ -99,9 +95,9 @@ def _run( logger.debug(f"PBI Query duration: {end_time - start_time:0.6f}") result, error = self._parse_output(pbi_result) if error is not None and "TokenExpired" in error: - self.session_cache[ - tool_input - ] = "Authentication token expired or invalid, please try reauthenticate." + self.session_cache[tool_input] = ( + "Authentication token expired or invalid, please try reauthenticate." + ) return self.session_cache[tool_input] iterations = kwargs.get("iterations", 0) @@ -153,9 +149,9 @@ async def _arun( logger.debug(f"PBI Query duration: {end_time - start_time:0.6f}") result, error = self._parse_output(pbi_result) if error is not None and ("TokenExpired" in error or "TokenError" in error): - self.session_cache[ - tool_input - ] = "Authentication token expired or invalid, please try to reauthenticate or check the scope of the credential." # noqa: E501 + self.session_cache[tool_input] = ( + "Authentication token expired or invalid, please try to reauthenticate or check the scope of the credential." # noqa: E501 + ) return self.session_cache[tool_input] iterations = kwargs.get("iterations", 0) @@ -251,7 +247,9 @@ class ListPowerBITool(BaseTool): """Tool for getting tables names.""" name: str = "list_tables_powerbi" - description: str = "Input is an empty string, output is a comma separated list of tables in the database." # noqa: E501 # pylint: disable=C0301 + description: str = ( + "Input is an empty string, output is a comma separated list of tables in the database." # noqa: E501 # pylint: disable=C0301 + ) powerbi: PowerBIDataset = Field(exclude=True) class Config: @@ -273,4 +271,4 @@ async def _arun( run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ) -> str: """Get the names of the tables.""" - return ", ".join(self.powerbi.get_table_names()) \ No newline at end of file + return ", ".join(self.powerbi.get_table_names()) diff --git a/src/sayvai_tools/tools/twitter/__init__.py b/src/sayvai_tools/tools/twitter/__init__.py index 880f041..b509b68 100644 --- a/src/sayvai_tools/tools/twitter/__init__.py +++ b/src/sayvai_tools/tools/twitter/__init__.py @@ -1,3 +1,3 @@ from sayvai_tools.tools.twitter.tool import SendTweetMessage -__all__ = ["SendTweetMessage"] \ No newline at end of file +__all__ = ["SendTweetMessage"] diff --git a/src/sayvai_tools/tools/twitter/tool.py b/src/sayvai_tools/tools/twitter/tool.py index 542925e..3b8dad7 100644 --- a/src/sayvai_tools/tools/twitter/tool.py +++ b/src/sayvai_tools/tools/twitter/tool.py @@ -3,4 +3,4 @@ def __init__(self, message): self.message = message def send(self): - print(f"Sending tweet: {self.message}") \ No newline at end of file + print(f"Sending tweet: {self.message}") diff --git a/src/sayvai_tools/tools/youtube/__init__.py b/src/sayvai_tools/tools/youtube/__init__.py index 55a7842..9808498 100644 --- a/src/sayvai_tools/tools/youtube/__init__.py +++ b/src/sayvai_tools/tools/youtube/__init__.py @@ -1,3 +1,3 @@ from sayvai_tools.tools.youtube.utils import get_youtube_credentials -__all__ = ['get_youtube_credentials'] +__all__ = ["get_youtube_credentials"] diff --git a/src/sayvai_tools/tools/youtube/comment_threads/__init__.py b/src/sayvai_tools/tools/youtube/comment_threads/__init__.py index 38a63b3..8777ff2 100644 --- a/src/sayvai_tools/tools/youtube/comment_threads/__init__.py +++ b/src/sayvai_tools/tools/youtube/comment_threads/__init__.py @@ -1,5 +1,7 @@ -from sayvai_tools.tools.youtube.comment_threads.add_comment import InsertCommentTool -from sayvai_tools.tools.youtube.comment_threads.list_comments import ListCommentsTool +from sayvai_tools.tools.youtube.comment_threads.add_comment import \ + InsertCommentTool +from sayvai_tools.tools.youtube.comment_threads.list_comments import \ + ListCommentsTool __all__ = [ "ListCommentsTool", diff --git a/src/sayvai_tools/tools/youtube/comment_threads/add_comment.py b/src/sayvai_tools/tools/youtube/comment_threads/add_comment.py index 296a56b..6d3b732 100644 --- a/src/sayvai_tools/tools/youtube/comment_threads/add_comment.py +++ b/src/sayvai_tools/tools/youtube/comment_threads/add_comment.py @@ -9,18 +9,16 @@ class InsertCommentSchema(BaseModel): """Input schema for InsertCommentTool.""" + video_id: str = Field( - ..., - description="ID of the YouTube video to insert the comment to." - ) - text: str = Field( - ..., - description="Text of the comment to be inserted." + ..., description="ID of the YouTube video to insert the comment to." ) + text: str = Field(..., description="Text of the comment to be inserted.") class InsertCommentTool(YouTubeCommentsBaseTool): """Tool for inserting a comment on a YouTube video.""" + name: str = "insert_comment" description: str = "Use this tool to insert a comment on a YouTube video." args_schema: Type[InsertCommentSchema] = InsertCommentSchema @@ -29,11 +27,7 @@ class InsertCommentTool(YouTubeCommentsBaseTool): def create(cls) -> "InsertCommentTool": return cls() - def _insert_comment( - self, - video_id: str, - text: str - ) -> None: + def _insert_comment(self, video_id: str, text: str) -> None: """Insert a comment on the specified YouTube video. Args: @@ -49,14 +43,10 @@ def _insert_comment( part="snippet", body={ "snippet": { - "topLevelComment": { - "snippet": { - "textOriginal": text - } - }, + "topLevelComment": {"snippet": {"textOriginal": text}}, "videoId": video_id, } - } + }, ).execute() except HttpError as e: raise HttpError(f"An HTTP error occurred: {e}", e.resp) @@ -64,10 +54,10 @@ def _insert_comment( raise Exception(f"An error occurred: {e}") def _run( - self, - video_id: str, - text: str, - run_manager: Optional[CallbackManagerForToolRun] = None + self, + video_id: str, + text: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> None: try: self._insert_comment(video_id, text) diff --git a/src/sayvai_tools/tools/youtube/comment_threads/list_comments.py b/src/sayvai_tools/tools/youtube/comment_threads/list_comments.py index 24c7bab..31b6d57 100644 --- a/src/sayvai_tools/tools/youtube/comment_threads/list_comments.py +++ b/src/sayvai_tools/tools/youtube/comment_threads/list_comments.py @@ -9,14 +9,15 @@ class ListCommentsSchema(BaseModel): """Input schema for ListCommentsTool.""" + video_id: str = Field( - ..., - description="ID of the YouTube video to list comment_threads for." + ..., description="ID of the YouTube video to list comment_threads for." ) class ListCommentsTool(YouTubeCommentsBaseTool): """Tool for listing comment_threads on a YouTube video.""" + name: str = "list_comments" description: str = "Use this tool to list comment_threads on a YouTube video." args_schema: Type[ListCommentsSchema] = ListCommentsSchema @@ -26,8 +27,8 @@ def create(cls) -> "ListCommentsTool": return cls() def _list_comments( - self, - video_id: str, + self, + video_id: str, ) -> dict: """List comment_threads on the specified YouTube video. @@ -42,11 +43,11 @@ def _list_comments( Exception: If any other error occurs. """ try: - response = self.api_resource.commentThreads().list( - part="snippet", - videoId=video_id, - textFormat="plainText" - ).execute() + response = ( + self.api_resource.commentThreads() + .list(part="snippet", videoId=video_id, textFormat="plainText") + .execute() + ) return response except HttpError as e: raise HttpError(f"An HTTP error occurred: {e}", e.resp) @@ -54,9 +55,7 @@ def _list_comments( raise Exception(f"An error occurred: {e}") def _run( - self, - video_id: str, - run_manager: Optional[CallbackManagerForToolRun] = None + self, video_id: str, run_manager: Optional[CallbackManagerForToolRun] = None ) -> dict: try: comments = self._list_comments(video_id) diff --git a/src/sayvai_tools/tools/youtube/comments/__init__.py b/src/sayvai_tools/tools/youtube/comments/__init__.py index 0cc3865..90cbdc9 100644 --- a/src/sayvai_tools/tools/youtube/comments/__init__.py +++ b/src/sayvai_tools/tools/youtube/comments/__init__.py @@ -1,7 +1,6 @@ -from sayvai_tools.tools.youtube.comments.list_comments import ListCommentRepliesTool -from sayvai_tools.tools.youtube.comments.reply_to_comment import ReplyToCommentTool +from sayvai_tools.tools.youtube.comments.list_comments import \ + ListCommentRepliesTool +from sayvai_tools.tools.youtube.comments.reply_to_comment import \ + ReplyToCommentTool -__all__ = [ - "ListCommentRepliesTool", - "ReplyToCommentTool" -] +__all__ = ["ListCommentRepliesTool", "ReplyToCommentTool"] diff --git a/src/sayvai_tools/tools/youtube/comments/list_comments.py b/src/sayvai_tools/tools/youtube/comments/list_comments.py index 2dfa1d2..6b1e475 100644 --- a/src/sayvai_tools/tools/youtube/comments/list_comments.py +++ b/src/sayvai_tools/tools/youtube/comments/list_comments.py @@ -9,21 +9,22 @@ class ListCommentRepliesSchema(BaseModel): """Input schema for ListCommentRepliesTool.""" + parent_comment_id: str = Field( - ..., - description="ID of the parent comment to list replies for." + ..., description="ID of the parent comment to list replies for." ) class ListCommentRepliesTool(YouTubeCommentsBaseTool): """Tool for listing replies to a comment on a YouTube video.""" + name: str = "list_comment_replies" description: str = "Use this tool to list replies to a comment on a YouTube video." args_schema: Type[ListCommentRepliesSchema] = ListCommentRepliesSchema def _list_replies( - self, - parent_comment_id: str, + self, + parent_comment_id: str, ) -> dict: """List replies to the specified parent comment. @@ -38,11 +39,13 @@ def _list_replies( Exception: If any other error occurs. """ try: - response = self.api_resource.comments().list( - part="snippet", - parentId=parent_comment_id, - textFormat="plainText" - ).execute() + response = ( + self.api_resource.comments() + .list( + part="snippet", parentId=parent_comment_id, textFormat="plainText" + ) + .execute() + ) return response except HttpError as e: raise HttpError(f"An HTTP error occurred: {e}", e.resp) @@ -50,9 +53,9 @@ def _list_replies( raise Exception(f"An error occurred: {e}") def _run( - self, - parent_comment_id: str, - run_manager: Optional[CallbackManagerForToolRun] = None + self, + parent_comment_id: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> dict: try: replies = self._list_replies(parent_comment_id) diff --git a/src/sayvai_tools/tools/youtube/comments/reply_to_comment.py b/src/sayvai_tools/tools/youtube/comments/reply_to_comment.py index e6f5470..0b081ff 100644 --- a/src/sayvai_tools/tools/youtube/comments/reply_to_comment.py +++ b/src/sayvai_tools/tools/youtube/comments/reply_to_comment.py @@ -9,27 +9,21 @@ class ReplyToCommentSchema(BaseModel): """Input schema for ReplyToCommentTool.""" + parent_comment_id: str = Field( - ..., - description="ID of the parent comment to reply to." - ) - text: str = Field( - ..., - description="Text of the reply." + ..., description="ID of the parent comment to reply to." ) + text: str = Field(..., description="Text of the reply.") class ReplyToCommentTool(YouTubeCommentsBaseTool): """Tool for replying to a comment on a YouTube video.""" + name: str = "reply_to_comment" description: str = "Use this tool to reply to a comment on a YouTube video." args_schema: Type[ReplyToCommentSchema] = ReplyToCommentSchema - def _reply_to_comment( - self, - parent_comment_id: str, - text: str - ) -> None: + def _reply_to_comment(self, parent_comment_id: str, text: str) -> None: """Reply to the specified parent comment. Args: @@ -43,12 +37,7 @@ def _reply_to_comment( try: self.api_resource.comments().insert( part="snippet", - body={ - "snippet": { - "parentId": parent_comment_id, - "textOriginal": text - } - } + body={"snippet": {"parentId": parent_comment_id, "textOriginal": text}}, ).execute() except HttpError as e: raise HttpError(f"An HTTP error occurred: {e}", e.resp) @@ -56,10 +45,10 @@ def _reply_to_comment( raise Exception(f"An error occurred: {e}") def _run( - self, - parent_comment_id: str, - text: str, - run_manager: Optional[CallbackManagerForToolRun] = None + self, + parent_comment_id: str, + text: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> None: try: self._reply_to_comment(parent_comment_id, text) diff --git a/src/sayvai_tools/tools/youtube/utils.py b/src/sayvai_tools/tools/youtube/utils.py index f2a7c13..9d4a679 100644 --- a/src/sayvai_tools/tools/youtube/utils.py +++ b/src/sayvai_tools/tools/youtube/utils.py @@ -65,16 +65,19 @@ def import_googleapiclient_resource_builder() -> build_resource: return build -DEFAULT_SCOPES = ["https://www.googleapis.com/auth/youtube", "https://www.googleapis.com/auth/youtube.force-ssl", - "https://www.googleapis.com/auth/youtubepartner"] +DEFAULT_SCOPES = [ + "https://www.googleapis.com/auth/youtube", + "https://www.googleapis.com/auth/youtube.force-ssl", + "https://www.googleapis.com/auth/youtubepartner", +] DEFAULT_CREDS_TOKEN_FILE = "token.json" DEFAULT_CLIENT_SECRETS_FILE = "credentials.json" def get_youtube_credentials( - token_file: Optional[str] = None, - client_secrets_file: Optional[str] = None, - scopes: Optional[List[str]] = None, + token_file: Optional[str] = None, + client_secrets_file: Optional[str] = None, + scopes: Optional[List[str]] = None, ) -> Credentials: """Get credentials.""" Request, Credentials = import_google() @@ -99,9 +102,9 @@ def get_youtube_credentials( def build_youtube_service( - credentials: Optional[Credentials] = None, - service_name: str = "youtube", - service_version: str = "v3", + credentials: Optional[Credentials] = None, + service_name: str = "youtube", + service_version: str = "v3", ) -> Resource: """Build a YouTube service.""" credentials = credentials or get_youtube_credentials() diff --git a/src/sayvai_tools/utils/database/dbchain.py b/src/sayvai_tools/utils/database/dbchain.py index 62c795f..2a5106a 100644 --- a/src/sayvai_tools/utils/database/dbchain.py +++ b/src/sayvai_tools/utils/database/dbchain.py @@ -8,7 +8,8 @@ from langchain.callbacks.manager import CallbackManagerForChainRun from langchain.chains.base import Chain from langchain.chains.llm import LLMChain -from langchain.chains.sql_database.prompt import DECIDER_PROMPT, PROMPT, SQL_PROMPTS +from langchain.chains.sql_database.prompt import (DECIDER_PROMPT, PROMPT, + SQL_PROMPTS) from langchain.prompts.prompt import PromptTemplate from langchain.pydantic_v1 import Extra, Field, root_validator from langchain.schema import BasePromptTemplate diff --git a/src/sayvai_tools/utils/database/sheetschain.py b/src/sayvai_tools/utils/database/sheetschain.py index 0971533..be403bc 100644 --- a/src/sayvai_tools/utils/database/sheetschain.py +++ b/src/sayvai_tools/utils/database/sheetschain.py @@ -8,7 +8,8 @@ from langchain.callbacks.manager import CallbackManagerForChainRun from langchain.chains.base import Chain from langchain.chains.llm import LLMChain -from langchain.chains.sql_database.prompt import DECIDER_PROMPT, PROMPT, SQL_PROMPTS +from langchain.chains.sql_database.prompt import (DECIDER_PROMPT, PROMPT, + SQL_PROMPTS) from langchain.prompts.prompt import PromptTemplate from langchain.pydantic_v1 import Extra, Field, root_validator from langchain.schema import BasePromptTemplate diff --git a/src/sayvai_tools/utils/pdfreader/__init__.py b/src/sayvai_tools/utils/pdfreader/__init__.py index 073fe2a..5d60d23 100644 --- a/src/sayvai_tools/utils/pdfreader/__init__.py +++ b/src/sayvai_tools/utils/pdfreader/__init__.py @@ -1,4 +1,5 @@ # init file -from sayvai_tools.utils.pdfreader.readpdf import read_page, read_pages, read_pdf +from sayvai_tools.utils.pdfreader.readpdf import (read_page, read_pages, + read_pdf) __all__ = ["read_page", "read_pdf", "read_pages"] diff --git a/src/sayvai_tools/utils/system/properties/__init__.py b/src/sayvai_tools/utils/system/properties/__init__.py index 9d8ac5c..f12003a 100644 --- a/src/sayvai_tools/utils/system/properties/__init__.py +++ b/src/sayvai_tools/utils/system/properties/__init__.py @@ -1,9 +1,7 @@ """init file for properties utils""" from sayvai_tools.utils.system.properties.properties import ( - SystemProperties, - get_all_properties, -) + SystemProperties, get_all_properties) __properties__ = get_all_properties() __all__ = ["SystemProperties", "get_all_properties"] diff --git a/templates/calendar-events/gcalendar/calendaragent.py b/templates/calendar-events/gcalendar/calendaragent.py index e2cd5a5..4b9094f 100644 --- a/templates/calendar-events/gcalendar/calendaragent.py +++ b/templates/calendar-events/gcalendar/calendaragent.py @@ -67,7 +67,7 @@ def initialize_tools(self, tools=None) -> str: func=GetDate()._run, name="get_date", description="""A tool that retrieves the current date and time. - This tool does not require any input parameters.""", + This tool does not require any input parameters.(watch out for leap years)""", ), ] return "Tools Initialized" @@ -92,4 +92,5 @@ def invoke(self, message) -> str: dateagent = DateTimeAgent() dateagent.initialize_tools() dateagent.initialize_agent_executor() -print(dateagent.invoke("shedule an appointment tommorrow at 9.30pm for an hour for standup meeting")) +while True: + print(dateagent.invoke(input("Enter your message: "))) diff --git a/templates/calendar-events/gcalendar/create_event.py b/templates/calendar-events/gcalendar/create_event.py index bc34309..445ff0e 100644 --- a/templates/calendar-events/gcalendar/create_event.py +++ b/templates/calendar-events/gcalendar/create_event.py @@ -1,10 +1,9 @@ from datetime import datetime, timedelta -from sayvai_tools.tools.google_calendar import \ - get_calendar_credentials from sayvai_tools.tools.google_calendar import (AvailableSlotsTool, CreateEventTool, - DisplayEventsTool) + DisplayEventsTool, + get_calendar_credentials) # Get Google Calendar credentials credentials = get_calendar_credentials() @@ -14,6 +13,7 @@ event = create_event_tool.run( { 'summary': 'Meeting with John', + 'calendar_id': 'primary', 'start_time': datetime.now() + timedelta(days=1), 'end_time': datetime.now() + timedelta(days=1, hours=1), } diff --git a/templates/google_sheets/append_data.py b/templates/google_sheets/append_data.py index 9aa5cb9..afdbe43 100644 --- a/templates/google_sheets/append_data.py +++ b/templates/google_sheets/append_data.py @@ -1,4 +1,5 @@ -from sayvai_tools.tools.google_sheets import AppendDataTool, get_sheets_credentials +from sayvai_tools.tools.google_sheets import (AppendDataTool, + get_sheets_credentials) credentials = get_sheets_credentials() diff --git a/templates/google_sheets/create_spreedsheet.py b/templates/google_sheets/create_spreedsheet.py index a4706a6..0e61267 100644 --- a/templates/google_sheets/create_spreedsheet.py +++ b/templates/google_sheets/create_spreedsheet.py @@ -1,4 +1,5 @@ -from sayvai_tools.tools.google_sheets import CreateSpreadsheetTool, get_sheets_credentials +from sayvai_tools.tools.google_sheets import (CreateSpreadsheetTool, + get_sheets_credentials) credentials = get_sheets_credentials() diff --git a/templates/google_sheets/get_cell_values.py b/templates/google_sheets/get_cell_values.py index 851f31c..2c54049 100644 --- a/templates/google_sheets/get_cell_values.py +++ b/templates/google_sheets/get_cell_values.py @@ -1,4 +1,5 @@ -from sayvai_tools.tools.google_sheets import GetCellValuesTool, get_sheets_credentials +from sayvai_tools.tools.google_sheets import (GetCellValuesTool, + get_sheets_credentials) # Get Google Sheets credentials credentials = get_sheets_credentials() diff --git a/templates/google_sheets/update_spreedsheets.py b/templates/google_sheets/update_spreedsheets.py index 1c08bc7..0a7595e 100644 --- a/templates/google_sheets/update_spreedsheets.py +++ b/templates/google_sheets/update_spreedsheets.py @@ -1,4 +1,5 @@ -from sayvai_tools.tools.google_sheets import UpdateSpreadsheetTool, get_sheets_credentials +from sayvai_tools.tools.google_sheets import (UpdateSpreadsheetTool, + get_sheets_credentials) # Get Google Sheets credentials credentials = get_sheets_credentials() diff --git a/templates/sayvai-demo-agent/demoagent/agent.py b/templates/sayvai-demo-agent/demoagent/agent.py index 074e619..cbf95d4 100644 --- a/templates/sayvai-demo-agent/demoagent/agent.py +++ b/templates/sayvai-demo-agent/demoagent/agent.py @@ -5,6 +5,7 @@ from langchain_community.agent_toolkits import GmailToolkit from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_openai import ChatOpenAI + # langchain agent main' from sayvai_tools.tools import GetDate @@ -99,6 +100,7 @@ def invoke(self, message) -> str: import chainlit as cl + @cl.on_chat_start def start(): agent = SayvaiDemoAgent() diff --git a/templates/sayvai-demo-agent/run.py b/templates/sayvai-demo-agent/run.py index c00b52f..d15800c 100644 --- a/templates/sayvai-demo-agent/run.py +++ b/templates/sayvai-demo-agent/run.py @@ -1,8 +1,8 @@ -from langchain.llms import OpenAI -from demoagent.agent import SayvaiDemoAgent # from langchain.callbacks import StreamlitCallbackHandler import streamlit as st -from rich import print as rprint +from demoagent.agent import SayvaiDemoAgent +from langchain.llms import OpenAI +from rich import print as rprint demoag = SayvaiDemoAgent() demoag.initialize_tools() diff --git a/templates/youtube/comments/add_comment.py b/templates/youtube/comments/add_comment.py index 7925482..ea5c962 100644 --- a/templates/youtube/comments/add_comment.py +++ b/templates/youtube/comments/add_comment.py @@ -1,4 +1,5 @@ -from sayvai_tools.tools.youtube.comment_threads import InsertCommentTool, get_youtube_credentials +from sayvai_tools.tools.youtube.comment_threads import ( + InsertCommentTool, get_youtube_credentials) # Get YouTube credentials credentials = get_youtube_credentials() diff --git a/templates/youtube/comments/list_comments.py b/templates/youtube/comments/list_comments.py index b5bf908..4a104b1 100644 --- a/templates/youtube/comments/list_comments.py +++ b/templates/youtube/comments/list_comments.py @@ -1,4 +1,5 @@ -from sayvai_tools.tools.youtube.comment_threads import ListCommentsTool, get_youtube_credentials +from sayvai_tools.tools.youtube.comment_threads import ( + ListCommentsTool, get_youtube_credentials) # Get YouTube credentials credentials = get_youtube_credentials()