@sulala/agent 0.1.5 β 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/context/airtable.md +35 -0
- package/context/asana.md +37 -0
- package/context/bluesky.md +26 -91
- package/context/calendar.md +63 -0
- package/context/country-info.md +13 -0
- package/context/create-skill.md +128 -0
- package/context/discord.md +30 -0
- package/context/docs.md +29 -0
- package/context/drive.md +49 -0
- package/context/dropbox.md +39 -0
- package/context/facebook.md +47 -0
- package/context/fetch-form-api.md +16 -0
- package/context/figma.md +30 -0
- package/context/github.md +58 -0
- package/context/gmail.md +52 -0
- package/context/google.md +28 -0
- package/context/hellohub.md +29 -0
- package/context/jira.md +46 -0
- package/context/linear.md +40 -0
- package/context/notion.md +45 -0
- package/context/portal-integrations.md +42 -0
- package/context/post-to-x.md +50 -0
- package/context/sheets.md +47 -0
- package/context/slack.md +48 -0
- package/context/slides.md +35 -0
- package/context/stripe.md +38 -0
- package/context/tes.md +7 -0
- package/context/test.md +7 -0
- package/context/zoom.md +28 -0
- package/dist/agent/google/calendar.d.ts +2 -0
- package/dist/agent/google/calendar.d.ts.map +1 -0
- package/dist/agent/google/calendar.js +119 -0
- package/dist/agent/google/calendar.js.map +1 -0
- package/dist/agent/google/drive.d.ts +2 -0
- package/dist/agent/google/drive.d.ts.map +1 -0
- package/dist/agent/google/drive.js +51 -0
- package/dist/agent/google/drive.js.map +1 -0
- package/dist/agent/google/get-token.d.ts +7 -0
- package/dist/agent/google/get-token.d.ts.map +1 -0
- package/dist/agent/google/get-token.js +37 -0
- package/dist/agent/google/get-token.js.map +1 -0
- package/dist/agent/google/gmail.d.ts +2 -0
- package/dist/agent/google/gmail.d.ts.map +1 -0
- package/dist/agent/google/gmail.js +138 -0
- package/dist/agent/google/gmail.js.map +1 -0
- package/dist/agent/google/index.d.ts +2 -0
- package/dist/agent/google/index.d.ts.map +1 -0
- package/dist/agent/google/index.js +13 -0
- package/dist/agent/google/index.js.map +1 -0
- package/dist/agent/loop.d.ts +8 -0
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +226 -40
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/memory.d.ts +21 -0
- package/dist/agent/memory.d.ts.map +1 -0
- package/dist/agent/memory.js +33 -0
- package/dist/agent/memory.js.map +1 -0
- package/dist/agent/pending-actions.d.ts +21 -0
- package/dist/agent/pending-actions.d.ts.map +1 -0
- package/dist/agent/pending-actions.js +65 -0
- package/dist/agent/pending-actions.js.map +1 -0
- package/dist/agent/pi-runner.d.ts +27 -0
- package/dist/agent/pi-runner.d.ts.map +1 -0
- package/dist/agent/pi-runner.js +300 -0
- package/dist/agent/pi-runner.js.map +1 -0
- package/dist/agent/skill-generate.d.ts +63 -0
- package/dist/agent/skill-generate.d.ts.map +1 -0
- package/dist/agent/skill-generate.js +128 -0
- package/dist/agent/skill-generate.js.map +1 -0
- package/dist/agent/skill-install.d.ts.map +1 -1
- package/dist/agent/skill-install.js +80 -31
- package/dist/agent/skill-install.js.map +1 -1
- package/dist/agent/skill-templates.d.ts +17 -0
- package/dist/agent/skill-templates.d.ts.map +1 -0
- package/dist/agent/skill-templates.js +26 -0
- package/dist/agent/skill-templates.js.map +1 -0
- package/dist/agent/skills-config.d.ts +24 -2
- package/dist/agent/skills-config.d.ts.map +1 -1
- package/dist/agent/skills-config.js +107 -8
- package/dist/agent/skills-config.js.map +1 -1
- package/dist/agent/skills-watcher.js +1 -1
- package/dist/agent/skills.d.ts +9 -3
- package/dist/agent/skills.d.ts.map +1 -1
- package/dist/agent/skills.js +104 -9
- package/dist/agent/skills.js.map +1 -1
- package/dist/agent/tools.d.ts +25 -3
- package/dist/agent/tools.d.ts.map +1 -1
- package/dist/agent/tools.integrations.test.d.ts +2 -0
- package/dist/agent/tools.integrations.test.d.ts.map +1 -0
- package/dist/agent/tools.integrations.test.js +269 -0
- package/dist/agent/tools.integrations.test.js.map +1 -0
- package/dist/agent/tools.js +692 -39
- package/dist/agent/tools.js.map +1 -1
- package/dist/ai/orchestrator.d.ts +4 -1
- package/dist/ai/orchestrator.d.ts.map +1 -1
- package/dist/ai/orchestrator.js +246 -14
- package/dist/ai/orchestrator.js.map +1 -1
- package/dist/ai/pricing.d.ts +6 -0
- package/dist/ai/pricing.d.ts.map +1 -0
- package/dist/ai/pricing.js +39 -0
- package/dist/ai/pricing.js.map +1 -0
- package/dist/channels/discord.d.ts +15 -0
- package/dist/channels/discord.d.ts.map +1 -0
- package/dist/channels/discord.js +55 -0
- package/dist/channels/discord.js.map +1 -0
- package/dist/channels/stripe.d.ts +15 -0
- package/dist/channels/stripe.d.ts.map +1 -0
- package/dist/channels/stripe.js +58 -0
- package/dist/channels/stripe.js.map +1 -0
- package/dist/channels/telegram.d.ts +60 -0
- package/dist/channels/telegram.d.ts.map +1 -0
- package/dist/channels/telegram.js +562 -0
- package/dist/channels/telegram.js.map +1 -0
- package/dist/cli.js +74 -10
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +14 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +85 -1
- package/dist/config.js.map +1 -1
- package/dist/db/index.d.ts +83 -0
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +174 -2
- package/dist/db/index.js.map +1 -1
- package/dist/db/schema.sql +35 -0
- package/dist/gateway/server.d.ts.map +1 -1
- package/dist/gateway/server.js +1219 -27
- package/dist/gateway/server.js.map +1 -1
- package/dist/index.js +149 -6
- package/dist/index.js.map +1 -1
- package/dist/ollama-setup.d.ts +27 -0
- package/dist/ollama-setup.d.ts.map +1 -0
- package/dist/ollama-setup.js +191 -0
- package/dist/ollama-setup.js.map +1 -0
- package/dist/onboard-env.d.ts +1 -1
- package/dist/onboard-env.d.ts.map +1 -1
- package/dist/onboard-env.js +2 -0
- package/dist/onboard-env.js.map +1 -1
- package/dist/onboard.d.ts +3 -1
- package/dist/onboard.d.ts.map +1 -1
- package/dist/onboard.js +7 -2
- package/dist/onboard.js.map +1 -1
- package/dist/plugins/index.d.ts +10 -0
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +32 -0
- package/dist/plugins/index.js.map +1 -1
- package/dist/redact.d.ts +15 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +56 -0
- package/dist/redact.js.map +1 -0
- package/dist/scheduler/cron.d.ts +21 -0
- package/dist/scheduler/cron.d.ts.map +1 -1
- package/dist/scheduler/cron.js +60 -0
- package/dist/scheduler/cron.js.map +1 -1
- package/dist/system-capabilities.d.ts +11 -0
- package/dist/system-capabilities.d.ts.map +1 -0
- package/dist/system-capabilities.js +109 -0
- package/dist/system-capabilities.js.map +1 -0
- package/dist/types.d.ts +62 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/watcher/index.d.ts +2 -0
- package/dist/watcher/index.d.ts.map +1 -1
- package/dist/watcher/index.js +31 -1
- package/dist/watcher/index.js.map +1 -1
- package/dist/workspace-automations.d.ts +16 -0
- package/dist/workspace-automations.d.ts.map +1 -0
- package/dist/workspace-automations.js +133 -0
- package/dist/workspace-automations.js.map +1 -0
- package/package.json +19 -3
- package/registry/bluesky.md +12 -89
- package/registry/skills-registry.json +6 -0
- package/src/db/schema.sql +35 -0
- package/src/index.ts +159 -6
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fetch-form-api
|
|
3
|
+
description: Fetches and returns data from a free API. Use when the user asks for specific data from a public API.
|
|
4
|
+
---
|
|
5
|
+
# Fetch Form API
|
|
6
|
+
|
|
7
|
+
Use when the user asks for data from a free API, such as forms, weather, or any public information.
|
|
8
|
+
|
|
9
|
+
## How to use
|
|
10
|
+
- Invoke this skill to fetch data from available public APIs by specifying the endpoint and any necessary parameters.
|
|
11
|
+
|
|
12
|
+
## Example
|
|
13
|
+
- To fetch weather information, specify the weather API endpoint along with location parameters.
|
|
14
|
+
|
|
15
|
+
## Limits
|
|
16
|
+
- Ensure the API has a rate limit that does not exceed the allowed number of requests.
|
package/context/figma.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: figma
|
|
3
|
+
description: Use Figma (files, projects) via the Portal. When the user asks about Figma files or designs, list connections with list_integrations_connections (provider figma) and use run_command with curl to the Figma API or gateway.
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"sulala": {
|
|
7
|
+
"emoji": "π¨",
|
|
8
|
+
"requires": { "bins": ["curl"] }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Figma
|
|
14
|
+
|
|
15
|
+
1. **list_integrations_connections** with `provider: "figma"` β get `connection_id`.
|
|
16
|
+
2. **get_connection_token** with that `connection_id` β returns `accessToken` (do not curl the portal).
|
|
17
|
+
3. **run_command (curl)** with `Authorization: Bearer <accessToken>` (or `X-Figma-Token` per Figma docs).
|
|
18
|
+
|
|
19
|
+
Base URL: `https://api.figma.com/v1`. Add `api.figma.com` to **ALLOWED_CURL_HOSTS**. Official docs: https://www.figma.com/developers/api
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Files and projects
|
|
24
|
+
|
|
25
|
+
- **Get file** (document structure, nodes): `GET https://api.figma.com/v1/files/<file_key>`. Returns document tree, pages, frames. `file_key` is the ID from the Figma file URL.
|
|
26
|
+
- **Get file nodes** (specific nodes): `GET https://api.figma.com/v1/files/<file_key>/nodes?ids=<node_id1>,<node_id2>`.
|
|
27
|
+
- **Get projects** (team): `GET https://api.figma.com/v1/teams/<team_id>/projects`. Returns `projects[].id`, `name`. Get `team_id` from user or from project response.
|
|
28
|
+
- **Get project files**: `GET https://api.figma.com/v1/projects/<project_id>/files`. Returns `files[].key`, `name`.
|
|
29
|
+
|
|
30
|
+
Requirements: **PORTAL_GATEWAY_URL**, **PORTAL_API_KEY**; user must connect Figma in the Portal. File/project must be accessible to the connected account.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: github
|
|
3
|
+
description: Use GitHub (repos, issues, PRs, comments) via the Portal. When the user asks about repos, issues, or pull requests, list connections with list_integrations_connections (provider github) and use run_command with curl to the GitHub API or gateway.
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"sulala": {
|
|
7
|
+
"emoji": "π",
|
|
8
|
+
"requires": { "bins": ["curl"] }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# GitHub
|
|
14
|
+
|
|
15
|
+
1. **list_integrations_connections** with `provider: "github"` β get `connection_id`.
|
|
16
|
+
2. **get_connection_token** with that `connection_id` β returns `accessToken` (do not curl the portal).
|
|
17
|
+
3. **run_command (curl)** with `Authorization: Bearer <accessToken>` and `Accept: application/vnd.github.v3+json` for all requests.
|
|
18
|
+
|
|
19
|
+
Base URL: `https://api.github.com`. Add `api.github.com` to **ALLOWED_CURL_HOSTS**.
|
|
20
|
+
|
|
21
|
+
Official docs: https://docs.github.com/en/rest
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Repositories
|
|
26
|
+
|
|
27
|
+
- **List repos** (authenticated user): `GET https://api.github.com/user/repos?per_page=20&sort=updated`. Returns `[].id`, `name`, `full_name`, `clone_url`, `private`.
|
|
28
|
+
- **List repos** (org): `GET https://api.github.com/orgs/<org>/repos?per_page=20`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Issues
|
|
33
|
+
|
|
34
|
+
- **List issues** (repo): `GET https://api.github.com/repos/<owner>/<repo>/issues?state=all&per_page=20`. Returns `[].number`, `title`, `state`, `body`, `user.login`.
|
|
35
|
+
- **Create issue**: `POST https://api.github.com/repos/<owner>/<repo>/issues` with body `{"title": "Title", "body": "Description"}`. Optional: `"labels": ["bug"]`, `"assignees": ["username"]`.
|
|
36
|
+
- **Get issue**: `GET https://api.github.com/repos/<owner>/<repo>/issues/<issue_number>`.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Comments
|
|
41
|
+
|
|
42
|
+
- **List comments** (on issue): `GET https://api.github.com/repos/<owner>/<repo>/issues/<issue_number>/comments`.
|
|
43
|
+
- **Create comment** (on issue): `POST https://api.github.com/repos/<owner>/<repo>/issues/<issue_number>/comments` with body `{"body": "Comment text"}`.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Pull requests
|
|
48
|
+
|
|
49
|
+
- **List PRs**: `GET https://api.github.com/repos/<owner>/<repo>/pulls?state=open&per_page=20`.
|
|
50
|
+
- **Create PR**: `POST https://api.github.com/repos/<owner>/<repo>/pulls` with body `{"title": "Title", "head": "<branch>", "base": "main", "body": "Description"}`. `head` is the branch with changes (e.g. `username:feature-branch` for fork).
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## File content
|
|
55
|
+
|
|
56
|
+
- **Get file**: `GET https://api.github.com/repos/<owner>/<repo>/contents/<path>`. Response has `content` (base64); decode to get file text. Optional: `?ref=<branch>`.
|
|
57
|
+
|
|
58
|
+
Requirements: **PORTAL_GATEWAY_URL**, **PORTAL_API_KEY**; user must connect GitHub in the Portal.
|
package/context/gmail.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gmail
|
|
3
|
+
description: Use Gmail via the Portal. When the user asks to read email, send email, list messages, or archive mail, use this skill with list_integrations_connections (provider gmail) and run_command + curl.
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"sulala": {
|
|
7
|
+
"emoji": "π§",
|
|
8
|
+
"requires": { "bins": ["curl"] }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Gmail
|
|
14
|
+
|
|
15
|
+
Use **list_integrations_connections** with `provider: "gmail"`, then **get_connection_token** to get an OAuth token (do not curl the portal from run_commandβuse the tool). Then call Gmail with that token.
|
|
16
|
+
|
|
17
|
+
**Required order:**
|
|
18
|
+
1. **list_integrations_connections** with `provider: "gmail"` β get `connection_id` (e.g. from `connections[0].id`).
|
|
19
|
+
2. **get_connection_token** with that `connection_id` β returns `accessToken`. This runs server-side; the agent does not curl the portal.
|
|
20
|
+
3. **run_command (curl)** β call Gmail APIs with header `Authorization: Bearer <accessToken>` (the value from step 2). Do **not** use the Portal API key on Gmail URLs.
|
|
21
|
+
|
|
22
|
+
If you get 401, you skipped step 2: call **get_connection_token** first, then use the returned `accessToken` in the Gmail curl.
|
|
23
|
+
|
|
24
|
+
Add `gmail.googleapis.com` to **ALLOWED_CURL_HOSTS**.
|
|
25
|
+
|
|
26
|
+
Base URL: `https://gmail.googleapis.com/gmail/v1`
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## List messages (inbox)
|
|
31
|
+
|
|
32
|
+
`GET https://gmail.googleapis.com/gmail/v1/users/me/messages?maxResults=20` (optional: `q=is:unread`, `pageToken`). Returns `messages[].id`; use `threadId` if needed.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Get message (body, subject, from)
|
|
37
|
+
|
|
38
|
+
`GET https://gmail.googleapis.com/gmail/v1/users/me/messages/<messageId>?format=full` (or `format=metadata`). Decode `payload.parts[].body.data` or `payload.body.data` (base64url) for body.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Send email
|
|
43
|
+
|
|
44
|
+
Build MIME (From, To, Subject, body); base64url-encode it. `POST https://gmail.googleapis.com/gmail/v1/users/me/messages/send` with body `{"raw": "<base64url-encoded-mime>"}`. Or use `{"raw": "<base64url>"}` where the MIME string is encoded (e.g. with a small script or base64).
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Archive message
|
|
49
|
+
|
|
50
|
+
`POST https://gmail.googleapis.com/gmail/v1/users/me/messages/<messageId>/modify` with body `{"removeLabelIds": ["INBOX"]}`.
|
|
51
|
+
|
|
52
|
+
Requirements: **PORTAL_GATEWAY_URL**, **PORTAL_API_KEY**; user must connect Gmail in the Portal or dashboard Integrations.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: google
|
|
3
|
+
description: Google services are split by product. Use the skill that matches the requestβcalendar for events, gmail for email, drive for files, docs/sheets/slides for Docs/Sheets/Slides. Do not loop over one doc; pick the right skill.
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"sulala": {
|
|
7
|
+
"emoji": "π·",
|
|
8
|
+
"requires": { "bins": ["curl"] }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Google (per-service skills)
|
|
14
|
+
|
|
15
|
+
**Use one skill per product.** The Portal has separate providers; there is no single "google" provider.
|
|
16
|
+
|
|
17
|
+
| User intent | Skill to use | Provider for list_integrations_connections |
|
|
18
|
+
|--------------------------|----------------|--------------------------------------------|
|
|
19
|
+
| Create event, calendar | **calendar** | `"calendar"` |
|
|
20
|
+
| Email, Gmail | **gmail** | `"gmail"` |
|
|
21
|
+
| Drive files, folders | **drive** | `"drive"` |
|
|
22
|
+
| Google Docs | **docs** | `"docs"` |
|
|
23
|
+
| Google Sheets | **sheets** | `"sheets"` |
|
|
24
|
+
| Google Slides | **slides** | `"slides"` |
|
|
25
|
+
|
|
26
|
+
For "create an event at 9 PM" β use the **calendar** skill only. For "send an email" β use the **gmail** skill only. No need to load or loop over multiple Google sections.
|
|
27
|
+
|
|
28
|
+
Each skill doc has the full flow: list_integrations_connections with that provider β get token from gateway β curl the API.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hellohub
|
|
3
|
+
description: hello
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
name: hello-hub
|
|
9
|
+
description: Example skill for testing install from hub. Use when the user asks for a greeting or hello.
|
|
10
|
+
metadata:
|
|
11
|
+
{
|
|
12
|
+
"sulala": {
|
|
13
|
+
"requires": { "bins": [] }
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Hello Hub
|
|
19
|
+
|
|
20
|
+
Example skill to test installing from the hub.
|
|
21
|
+
|
|
22
|
+
Use when the user asks for:
|
|
23
|
+
- A greeting
|
|
24
|
+
- Hello from hub
|
|
25
|
+
- Testing hub install
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
Respond with a friendly greeting. No external tools required.
|
package/context/jira.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jira
|
|
3
|
+
description: Use Jira (sites, issues, transitions) via the Portal. When the user asks about Jira issues or projects, list connections with list_integrations_connections (provider jira) and use run_command with curl to the Jira API or gateway.
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"sulala": {
|
|
7
|
+
"emoji": "π§",
|
|
8
|
+
"requires": { "bins": ["curl"] }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Jira
|
|
14
|
+
|
|
15
|
+
1. **list_integrations_connections** with `provider: "jira"` β get `connection_id`.
|
|
16
|
+
2. **get_connection_token** with that `connection_id` β returns `accessToken` (do not curl the portal).
|
|
17
|
+
3. **run_command (curl)** to the user's Jira site (`https://<site>.atlassian.net` or `https://api.atlassian.com/...`). All requests: `Authorization: Bearer <accessToken>`, `Content-Type: application/json`. Add `*.atlassian.net` (or the site host) to **ALLOWED_CURL_HOSTS**.
|
|
18
|
+
|
|
19
|
+
Official docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Cloud ID / Access
|
|
24
|
+
|
|
25
|
+
- **Get accessible resources** (to find cloud ID): `GET https://api.atlassian.com/oauth/token/accessible-resources`. Returns `[].id` (cloudId), `[].url` (e.g. `https://site.atlassian.net`). Use cloud ID in REST v3 URLs: `https://api.atlassian.com/ex/jira/<cloudId>/rest/api/3/...`.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Search issues
|
|
30
|
+
|
|
31
|
+
- **Search**: `POST https://api.atlassian.com/ex/jira/<cloudId>/rest/api/3/search` with body `{"jql": "project = MYPROJECT ORDER BY created DESC", "maxResults": 20, "fields": ["summary", "status", "assignee"]}`. Returns `issues[].key`, `issues[].fields.summary`, `issues[].fields.status.name`. JQL examples: `assignee = currentUser()`, `status = "In Progress"`.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Create issue
|
|
36
|
+
|
|
37
|
+
- **Create**: `POST https://api.atlassian.com/ex/jira/<cloudId>/rest/api/3/issue` with body `{"fields": {"project": {"key": "PROJ"}, "summary": "Title", "issuetype": {"name": "Task"}, "description": {"type": "doc", "version": 1, "content": [{"type": "paragraph", "content": [{"type": "text", "text": "Description"}]}]}}}`. Get project keys from `/rest/api/3/project`; issuetypes from `/rest/api/3/issue/createmeta`.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Transitions
|
|
42
|
+
|
|
43
|
+
- **Get transitions** (for an issue): `GET https://api.atlassian.com/ex/jira/<cloudId>/rest/api/3/issue/<issueKey>/transitions`. Returns `transitions[].id`, `transitions[].name`.
|
|
44
|
+
- **Transition issue**: `POST https://api.atlassian.com/ex/jira/<cloudId>/rest/api/3/issue/<issueKey>/transitions` with body `{"transition": {"id": "<transitionId>"}}`.
|
|
45
|
+
|
|
46
|
+
Requirements: **PORTAL_GATEWAY_URL**, **PORTAL_API_KEY**; user must connect Jira in the Portal.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: linear
|
|
3
|
+
description: Use Linear (teams, issues) via the Portal. When the user asks about Linear teams or issues, list connections with list_integrations_connections (provider linear) and use run_command with curl to the Linear API or gateway.
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"sulala": {
|
|
7
|
+
"emoji": "π",
|
|
8
|
+
"requires": { "bins": ["curl"] }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Linear
|
|
14
|
+
|
|
15
|
+
**Creating an issue:** First run the teams query to get a real team `id` (UUID). Then POST the issue with body `{"query": "mutation ... $teamId $title $description ...", "variables": {"teamId": "<from teams>", "title": "...", "description": "..."}}`. Never embed title or description in the query stringβuse variables only.
|
|
16
|
+
|
|
17
|
+
1. **list_integrations_connections** with `provider: "linear"` β get `connection_id`.
|
|
18
|
+
2. **get_connection_token** with that `connection_id` β returns `accessToken` (do not curl the portal).
|
|
19
|
+
3. **run_command (curl)** to `POST https://api.linear.app/graphql` with `Authorization: Bearer <accessToken>`, `Content-Type: application/json`, and body `{"query": "<GraphQL>", "variables": {...}}`. Use **variables** for any user-provided text (title, description) so quotes and newlines do not break the query.
|
|
20
|
+
|
|
21
|
+
Add `api.linear.app` to **ALLOWED_CURL_HOSTS**. Official docs: https://developers.linear.app/docs/graphql
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Teams
|
|
26
|
+
|
|
27
|
+
- **List teams**: Query `query { teams { nodes { id name key } } }`. Returns `data.teams.nodes`.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Issues
|
|
32
|
+
|
|
33
|
+
- **List issues** (filter by team or assignee): `query { issues(first: 20, filter: { team: { key: { eq: "ENG" } } }) { nodes { id identifier title state { name } assignee { name } } } }`. Or use `filter: { assignee: { id: { eq: "<userId>" } } }`.
|
|
34
|
+
|
|
35
|
+
- **Create issue** β you must do two steps. **Step 1:** Get a real team ID by sending a POST to `https://api.linear.app/graphql` with body `{"query":"query { teams { nodes { id name key } } }"}`. Use one of the returned `nodes[].id` values (UUID format like `23f232c2-7a1c-407e-8e6c-3c75bdfd0d41`). **Step 2:** Create the issue by POSTing to the same URL with a body that has **two keys only**: `query` (a mutation that uses variables, no literal title/description) and `variables` (JSON with the actual teamId, title, description). Do **not** put title or description inside the query stringβthat causes "Syntax Error: Unexpected }". Use this exact shape:
|
|
36
|
+
- Body: `{"query": "mutation IssueCreate($teamId: String!, $title: String!, $description: String) { issueCreate(input: { teamId: $teamId, title: $title, description: $description }) { success issue { id identifier url } } }", "variables": {"teamId": "<paste the team id from step 1>", "title": "Test Issue", "description": "Optional description"}}`
|
|
37
|
+
- The `query` string must contain only `$teamId`, `$title`, `$description`βno quoted literals for those. The `variables` object holds the real values.
|
|
38
|
+
- **Update issue** (e.g. state, assignee): `mutation { issueUpdate(id: "<issueId>", input: { stateId: "<stateId>" }) { success issue { id state { name } } } }`. List states with `query { workflowStates(filter: { team: { id: { eq: "<teamId>" } } }) { nodes { id name } } }`.
|
|
39
|
+
|
|
40
|
+
Requirements: **PORTAL_GATEWAY_URL**, **PORTAL_API_KEY**; user must connect Linear in the Portal.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: notion
|
|
3
|
+
description: Use Notion (search, pages, databases) via the Portal. When the user asks about Notion pages or databases, list connections with list_integrations_connections (provider notion) and use run_command with curl to the Notion API or gateway.
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"sulala": {
|
|
7
|
+
"emoji": "π",
|
|
8
|
+
"requires": { "bins": ["curl"] }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Notion
|
|
14
|
+
|
|
15
|
+
1. **list_integrations_connections** with `provider: "notion"` β get `connection_id`.
|
|
16
|
+
2. **get_connection_token** with that `connection_id` β returns `accessToken` (do not curl the portal).
|
|
17
|
+
3. **run_command (curl)** with `Authorization: Bearer <accessToken>`, `Notion-Version: 2022-06-28`, and `Content-Type: application/json` where applicable.
|
|
18
|
+
|
|
19
|
+
Base URL: `https://api.notion.com/v1`. Add `api.notion.com` to **ALLOWED_CURL_HOSTS**.
|
|
20
|
+
|
|
21
|
+
Official docs: https://developers.notion.com/reference
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Search
|
|
26
|
+
|
|
27
|
+
- **Search** (pages and databases): `POST https://api.notion.com/v1/search` with body `{"query": "optional search text", "filter": {"property": "object", "value": "page"}}` or `"value": "database"`. Returns `results[].id`, `url`, `object` (page/database). Omit filter to get both.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Pages
|
|
32
|
+
|
|
33
|
+
- **Get page** (content and properties): `GET https://api.notion.com/v1/pages/<page_id>`. Page ID is the UUID from a Notion URL (with hyphens).
|
|
34
|
+
- **Get page content** (blocks): `GET https://api.notion.com/v1/blocks/<page_id>/children?page_size=100`. Returns block objects (paragraph, heading, etc.); `type` and `paragraph.rich_text` or similar.
|
|
35
|
+
- **Create page** (under parent): `POST https://api.notion.com/v1/pages` with body `{"parent": {"page_id": "<parent_page_id>"}, "properties": {"title": {"title": [{"text": {"content": "Page title"}}]}}}`. Parent page must be shared with the integration.
|
|
36
|
+
- **Update page** (e.g. title): `PATCH https://api.notion.com/v1/pages/<page_id>` with body `{"properties": {"title": {"title": [{"text": {"content": "New title"}}]}}}`.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Databases
|
|
41
|
+
|
|
42
|
+
- **Create database** (under parent page): `POST https://api.notion.com/v1/databases` with body `{"parent": {"page_id": "<parent_page_id>"}, "title": [{"text": {"content": "DB name"}}], "properties": {"Name": {"title": {}}}}`. Default "Name" property is created.
|
|
43
|
+
- **Query database** (list rows): `POST https://api.notion.com/v1/databases/<database_id>/query` with body `{}` or `{"filter": {...}, "sorts": [{"property": "Name", "direction": "ascending"}]}`. Returns `results[]` (page objects with properties).
|
|
44
|
+
|
|
45
|
+
Requirements: **PORTAL_GATEWAY_URL**, **PORTAL_API_KEY**; user must connect Notion in the Portal. Pages/databases must be shared with the connected Notion integration.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: portal-integrations
|
|
3
|
+
description: Use connected apps (Gmail, Calendar, Zoom, Slack, GitHub, etc.) via the Portal. When the user asks about email, calendar, meetings, or other integrated apps, list connections with list_integrations_connections and use run_command with curl to the gateway or provider APIs (see per-integration skills: calendar, gmail, drive, docs, sheets, slides, github, notion, slack, linear, zoom, airtable, etc.).
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"sulala": {
|
|
7
|
+
"emoji": "π"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Portal integrations
|
|
13
|
+
|
|
14
|
+
The agent uses **connected apps** (Gmail, Google Calendar, Zoom, Slack, GitHub, Notion, Linear, Airtable, etc.) via **skills** and **run_command** with curl. The user connects apps in the Portal (or dashboard β Integrations); the agent gets `connection_id` from **list_integrations_connections** and performs actions by following the relevant integration skill (e.g. calendar.md, gmail.md, drive.md, github.md, slack.md) and calling **run_command** with `binary: "curl"` to the gateway or provider API.
|
|
15
|
+
|
|
16
|
+
## How it works
|
|
17
|
+
|
|
18
|
+
1. **User** creates an API key at the Portal and adds it in the agent (Settings β Portal API key or `PORTAL_API_KEY`). Optionally set `PORTAL_GATEWAY_URL`.
|
|
19
|
+
2. **User** connects apps in the Portal (or dashboard Integrations): Gmail, Calendar, Zoom, Slack, etc.
|
|
20
|
+
3. **Agent** uses:
|
|
21
|
+
- **list_integrations_connections** β returns `connection_id` and `provider` for each connected app. Call with optional `provider` to filter (e.g. `"calendar"`, `"gmail"`, `"slack"`, `"github"`).
|
|
22
|
+
- **get_connection_token** β call with `connection_id` to get an OAuth `accessToken`. Use this before each integration API call; the agent does not curl the portal from run_command.
|
|
23
|
+
- **run_command** with **curl** β use the `accessToken` from get_connection_token in the `Authorization: Bearer <accessToken>` header when curling the provider API (Gmail, Calendar, GitHub, Slack, etc.), as documented in each integration skill.
|
|
24
|
+
|
|
25
|
+
Integration behavior is **skill-driven**: use **list_integrations_connections** for OAuth apps (calendar, gmail, drive, github, slack, linear, etc.) and the instructions in the per-integration skills. **Stripe and Discord are not OAuth**βthey are "channels" configured in **Settings β Channels** (API key / bot token). Do not use list_integrations_connections for Stripe or Discord; use **stripe_list_customers** and **discord_list_guilds** / **discord_send_message** instead. See stripe.md and discord.md.
|
|
26
|
+
|
|
27
|
+
## When to use
|
|
28
|
+
|
|
29
|
+
- User asks to **create a calendar event**, read/send email, check calendar, list or create Zoom meetings, post in Slack, list GitHub repos/issues, query Notion, etc. For calendar events, always use the **calendar** skill (provider `calendar`) and the Calendar API via run_command + curl; do not use Apple Calendar, osascript, or local calendar apps.
|
|
30
|
+
- First call **list_integrations_connections** (optionally with `provider`, e.g. `calendar` for events), then follow the relevant integration skill and use **run_command** with curl as documented there.
|
|
31
|
+
|
|
32
|
+
## Requirements
|
|
33
|
+
|
|
34
|
+
- **PORTAL_GATEWAY_URL** and **PORTAL_API_KEY** must be set so the agent can list connections and get OAuth tokens. The agent loads them from **`~/.sulala/.env`** (e.g. when saved via dashboard Settings); you do not need them in the agent project `.env`. If both exist, the agent project `.env` overrides. Create the API key in the Portal β API Keys. Example in `~/.sulala/.env`: `PORTAL_GATEWAY_URL=https://portal.sulala.ai/api/gateway`, `PORTAL_API_KEY=<your key>`.
|
|
35
|
+
- The user must have connected the relevant app in the Portal before the agent can use it.
|
|
36
|
+
- Add required hosts to **ALLOWED_CURL_HOSTS** (e.g. api.github.com, slack.com, www.googleapis.com) as documented in each integration skill.
|
|
37
|
+
|
|
38
|
+
## Notes
|
|
39
|
+
|
|
40
|
+
- Connection count and subscription limits are enforced by the Portal; the agent only sees connections the user has already connected.
|
|
41
|
+
- If **list_integrations_connections** returns an error like "Portal not configured", prompt the user to add a Portal API key in Settings or at the Portal.
|
|
42
|
+
- For OAuth-backed actions, the Portal (or gateway) may expose action endpoints (e.g. `POST /api/gateway/actions/gmail/send`) that skills document for curl; until then, skills document calling the gateway for a token and then the provider API directly.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: post-to-x
|
|
3
|
+
description: >
|
|
4
|
+
Posts a tweet to X (formerly Twitter) using OAuth 1.0a user authentication.
|
|
5
|
+
Use this skill when the user asks to tweet, post to X/Twitter, or share an update on X.
|
|
6
|
+
metadata:
|
|
7
|
+
{
|
|
8
|
+
"sulala": {
|
|
9
|
+
"requires": {
|
|
10
|
+
"bins": ["python3"],
|
|
11
|
+
"env": [
|
|
12
|
+
"X_API_KEY",
|
|
13
|
+
"X_API_SECRET",
|
|
14
|
+
"X_ACCESS_TOKEN",
|
|
15
|
+
"X_ACCESS_TOKEN_SECRET"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"primaryEnv": "X_ACCESS_TOKEN",
|
|
19
|
+
"capabilities": ["write", "social", "automation"]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# Post to X (Twitter)
|
|
25
|
+
|
|
26
|
+
This skill posts a tweet to **:contentReference[oaicite:0]{index=0}** using **OAuth 1.0a (User Context)** authentication.
|
|
27
|
+
|
|
28
|
+
β οΈ **Important**
|
|
29
|
+
- App-only Bearer Tokens **cannot** post tweets.
|
|
30
|
+
- This skill requires **user-level OAuth 1.0a credentials** with **Read & Write** permissions.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## When to Use
|
|
35
|
+
Use this skill when the user asks to:
|
|
36
|
+
- Post a tweet
|
|
37
|
+
- Share content on X
|
|
38
|
+
- Announce something on Twitter/X
|
|
39
|
+
- Publish automated updates
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Requirements
|
|
44
|
+
|
|
45
|
+
### Environment Variables
|
|
46
|
+
```env
|
|
47
|
+
X_API_KEY=your_consumer_key
|
|
48
|
+
X_API_SECRET=your_consumer_secret
|
|
49
|
+
X_ACCESS_TOKEN=your_access_token
|
|
50
|
+
X_ACCESS_TOKEN_SECRET=your_access_token_secret
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sheets
|
|
3
|
+
description: Use Google Sheets via the Portal. When the user asks to list spreadsheets, read or append rows, or edit Sheets, use this skill with list_integrations_connections (provider sheets) and run_command + curl.
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"sulala": {
|
|
7
|
+
"emoji": "π",
|
|
8
|
+
"requires": { "bins": ["curl"] }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Google Sheets
|
|
14
|
+
|
|
15
|
+
Use **list_integrations_connections** with `provider: "sheets"`, then **get_connection_token** (do not curl the portal). Then call the API with that token.
|
|
16
|
+
|
|
17
|
+
1. **list_integrations_connections** with `provider: "sheets"` β get `connection_id`.
|
|
18
|
+
2. **get_connection_token** with that `connection_id` β returns `accessToken`.
|
|
19
|
+
3. **run_command (curl)** with `Authorization: Bearer <accessToken>` for all requests.
|
|
20
|
+
|
|
21
|
+
Add `www.googleapis.com` and `sheets.googleapis.com` to **ALLOWED_CURL_HOSTS**.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## List spreadsheets
|
|
26
|
+
|
|
27
|
+
List via Drive API (mimeType `application/vnd.google-apps.spreadsheet`).
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Read range
|
|
32
|
+
|
|
33
|
+
`GET https://sheets.googleapis.com/v4/spreadsheets/<spreadsheetId>/values/<range>`. Example range: `Sheet1!A1:D10`.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Append rows
|
|
38
|
+
|
|
39
|
+
`POST https://sheets.googleapis.com/v4/spreadsheets/<spreadsheetId>/values/<range>:append?valueInputOption=USER_ENTERED` with body `{"values": [[ "cell1", "cell2" ], [ "row2col1", "row2col2" ]]}`.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Update range
|
|
44
|
+
|
|
45
|
+
`PUT https://sheets.googleapis.com/v4/spreadsheets/<spreadsheetId>/values/<range>?valueInputOption=USER_ENTERED` with body `{"values": [[...]]}`.
|
|
46
|
+
|
|
47
|
+
Requirements: **PORTAL_GATEWAY_URL**, **PORTAL_API_KEY**; user must connect Google Sheets in the Portal or dashboard Integrations.
|
package/context/slack.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: slack
|
|
3
|
+
description: Use Slack (channels, messages, reactions) via the Portal. When the user asks to list channels, send a message, or read Slack, list connections with list_integrations_connections (provider slack) and use run_command with curl to the Slack API or gateway.
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"sulala": {
|
|
7
|
+
"emoji": "π¬",
|
|
8
|
+
"requires": { "bins": ["curl"] }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Slack
|
|
14
|
+
|
|
15
|
+
1. **list_integrations_connections** with `provider: "slack"` β get `connection_id`.
|
|
16
|
+
2. **get_connection_token** with that `connection_id` β returns `accessToken` (do not curl the portal).
|
|
17
|
+
3. **run_command (curl)** with `Authorization: Bearer <accessToken>` and `Content-Type: application/json` for POST.
|
|
18
|
+
|
|
19
|
+
Base URL: `https://slack.com/api`. Add `slack.com` to **ALLOWED_CURL_HOSTS**.
|
|
20
|
+
|
|
21
|
+
Official docs: https://api.slack.com/methods
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Channels
|
|
26
|
+
|
|
27
|
+
- **List channels** (public and private the app is in): `GET https://slack.com/api/conversations.list?types=public_channel,private_channel&limit=50`. Returns `channels[].id`, `channels[].name`. Pagination: `cursor` in response.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Messages
|
|
32
|
+
|
|
33
|
+
- **Send message**: `POST https://slack.com/api/chat.postMessage` with body `{"channel": "<channel_id>", "text": "Message text"}`. `channel` can be channel ID (from conversations.list) or channel name (e.g. `#general`).
|
|
34
|
+
- **Get channel history**: `GET https://slack.com/api/conversations.history?channel=<channel_id>&limit=20`. Returns `messages[]` with `text`, `user`, `ts`. Pagination: `cursor` or `oldest`/`latest` (timestamp).
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Users
|
|
39
|
+
|
|
40
|
+
- **List users**: `GET https://slack.com/api/users.list?limit=50`. Returns `members[].id`, `members[].real_name`, `members[].name`.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Reactions
|
|
45
|
+
|
|
46
|
+
- **Add reaction**: `POST https://slack.com/api/reactions.add` with body `{"channel": "<channel_id>", "timestamp": "<message_ts>", "name": "emoji_name"}`. `timestamp` is the `ts` of the message (e.g. `1234567890.123456`). `name` is the emoji without colons (e.g. `thumbsup`).
|
|
47
|
+
|
|
48
|
+
Requirements: **PORTAL_GATEWAY_URL**, **PORTAL_API_KEY**; user must connect Slack in the Portal. Bot must be in the workspace and invited to channels as needed.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: slides
|
|
3
|
+
description: Use Google Slides via the Portal. When the user asks to list presentations or read Slides content, use this skill with list_integrations_connections (provider slides) and run_command + curl.
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"sulala": {
|
|
7
|
+
"emoji": "π½οΈ",
|
|
8
|
+
"requires": { "bins": ["curl"] }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Google Slides
|
|
14
|
+
|
|
15
|
+
Use **list_integrations_connections** with `provider: "slides"`, then **get_connection_token** (do not curl the portal). Then call the API with that token.
|
|
16
|
+
|
|
17
|
+
1. **list_integrations_connections** with `provider: "slides"` β get `connection_id`.
|
|
18
|
+
2. **get_connection_token** with that `connection_id` β returns `accessToken`.
|
|
19
|
+
3. **run_command (curl)** with `Authorization: Bearer <accessToken>` for all requests.
|
|
20
|
+
|
|
21
|
+
Add `www.googleapis.com` and `slides.googleapis.com` to **ALLOWED_CURL_HOSTS**.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## List presentations
|
|
26
|
+
|
|
27
|
+
List via Drive API (mimeType `application/vnd.google-apps.presentation`).
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Get presentation
|
|
32
|
+
|
|
33
|
+
`GET https://slides.googleapis.com/v1/presentations/<presentationId>`. Returns slide structure and content.
|
|
34
|
+
|
|
35
|
+
Requirements: **PORTAL_GATEWAY_URL**, **PORTAL_API_KEY**; user must connect Google Slides in the Portal or dashboard Integrations.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stripe
|
|
3
|
+
description: Use Stripe (customers, invoices) via Settings β Channels or API key. Do not use list_integrations_connections for Stripeβit only lists OAuth apps. Use stripe_list_customers for listing customers; for invoices use run_command with curl and the key from Settings.
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"sulala": {
|
|
7
|
+
"emoji": "π³",
|
|
8
|
+
"requires": { "env": ["STRIPE_SECRET_KEY"] }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Stripe
|
|
14
|
+
|
|
15
|
+
Stripe is configured in **Settings β Channels (Stripe)** or via **STRIPE_SECRET_KEY** in the agent env. **Do not call list_integrations_connections for Stripe**βthat tool only returns OAuth connections (Gmail, Slack, etc.). Stripe uses an API key, not OAuth.
|
|
16
|
+
|
|
17
|
+
- **List customers**: use the **stripe_list_customers** tool (uses the key from Settings β Channels). Returns customers with id, email, name.
|
|
18
|
+
- **Invoices / other Stripe API calls**: use **run_command** with curl to `https://api.stripe.com/v1`. Add `api.stripe.com` to **ALLOWED_CURL_HOSTS**. Stripe API uses **form-encoded** body for POST (e.g. `key=value`), not JSON for most v1 endpoints. The key is in Settings β Channels; the agent must not expose it in chat.
|
|
19
|
+
|
|
20
|
+
Base URL: `https://api.stripe.com/v1`. Official docs: https://stripe.com/docs/api
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Customers
|
|
25
|
+
|
|
26
|
+
- **List customers**: use the **stripe_list_customers** tool (limit optional). For raw API: `GET https://api.stripe.com/v1/customers?limit=10`. Pagination: `starting_after=<id>`.
|
|
27
|
+
- **Get customer**: `GET https://api.stripe.com/v1/customers/<customer_id>`.
|
|
28
|
+
- **Create customer** (if needed for invoice): `POST https://api.stripe.com/v1/customers` with body `email=user@example.com&name=Name`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Invoices
|
|
33
|
+
|
|
34
|
+
- **List invoices**: `GET https://api.stripe.com/v1/invoices?limit=10&customer=<customer_id>` (optional). Returns `data[].id`, `data[].amount_due`, `data[].status`, `data[].invoice_pdf`, `data[].hosted_invoice_url`.
|
|
35
|
+
- **Get invoice**: `GET https://api.stripe.com/v1/invoices/<invoice_id>`.
|
|
36
|
+
- **Create invoice**: (1) Create invoice: `POST https://api.stripe.com/v1/invoices` with body `customer=<customer_id>`. Response has `id`. (2) Add line item: `POST https://api.stripe.com/v1/invoiceitems` with body `customer=<customer_id>&amount=<amount_in_cents>¤cy=usd&description=Item description`. (3) Finalize: `POST https://api.stripe.com/v1/invoices/<invoice_id>/finalize`. (4) Optional send: `POST https://api.stripe.com/v1/invoices/<invoice_id>/send`. Use idempotency header `Idempotency-Key: <unique_key>` for POST if retrying.
|
|
37
|
+
|
|
38
|
+
Requirements: Stripe secret key (starts with `sk_`) in Skills config. Do not expose in chat.
|
package/context/tes.md
ADDED