gigaclaw 1.4.0
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/LICENSE +26 -0
- package/README.md +237 -0
- package/api/CLAUDE.md +19 -0
- package/api/index.js +265 -0
- package/bin/cli.js +823 -0
- package/bin/local.sh +85 -0
- package/bin/postinstall.js +63 -0
- package/config/index.js +26 -0
- package/config/instrumentation.js +62 -0
- package/drizzle/0000_initial.sql +52 -0
- package/drizzle/0001_nostalgic_sersi.sql +11 -0
- package/drizzle/0002_black_daimon_hellstrom.sql +19 -0
- package/drizzle/0003_rename_code_workspaces.sql +5 -0
- package/drizzle/meta/0000_snapshot.json +321 -0
- package/drizzle/meta/0001_snapshot.json +390 -0
- package/drizzle/meta/0002_snapshot.json +411 -0
- package/drizzle/meta/0003_snapshot.json +419 -0
- package/drizzle/meta/_journal.json +34 -0
- package/lib/actions.js +44 -0
- package/lib/ai/agent.js +86 -0
- package/lib/ai/index.js +342 -0
- package/lib/ai/model.js +180 -0
- package/lib/ai/tools.js +269 -0
- package/lib/ai/web-search.js +42 -0
- package/lib/auth/actions.js +28 -0
- package/lib/auth/config.js +27 -0
- package/lib/auth/edge-config.js +27 -0
- package/lib/auth/index.js +27 -0
- package/lib/auth/middleware.js +62 -0
- package/lib/channels/base.js +56 -0
- package/lib/channels/index.js +15 -0
- package/lib/channels/telegram.js +148 -0
- package/lib/chat/actions.js +579 -0
- package/lib/chat/api.js +140 -0
- package/lib/chat/components/app-sidebar.js +213 -0
- package/lib/chat/components/app-sidebar.jsx +279 -0
- package/lib/chat/components/chat-header.js +192 -0
- package/lib/chat/components/chat-header.jsx +223 -0
- package/lib/chat/components/chat-input.js +236 -0
- package/lib/chat/components/chat-input.jsx +249 -0
- package/lib/chat/components/chat-nav-context.js +11 -0
- package/lib/chat/components/chat-nav-context.jsx +11 -0
- package/lib/chat/components/chat-page.js +99 -0
- package/lib/chat/components/chat-page.jsx +121 -0
- package/lib/chat/components/chat.js +153 -0
- package/lib/chat/components/chat.jsx +199 -0
- package/lib/chat/components/chats-page.js +367 -0
- package/lib/chat/components/chats-page.jsx +394 -0
- package/lib/chat/components/code-mode-toggle.js +132 -0
- package/lib/chat/components/code-mode-toggle.jsx +163 -0
- package/lib/chat/components/crons-page.js +172 -0
- package/lib/chat/components/crons-page.jsx +244 -0
- package/lib/chat/components/greeting.js +11 -0
- package/lib/chat/components/greeting.jsx +16 -0
- package/lib/chat/components/icons.js +805 -0
- package/lib/chat/components/icons.jsx +751 -0
- package/lib/chat/components/index.js +20 -0
- package/lib/chat/components/message.js +363 -0
- package/lib/chat/components/message.jsx +422 -0
- package/lib/chat/components/messages.js +65 -0
- package/lib/chat/components/messages.jsx +74 -0
- package/lib/chat/components/notifications-page.js +56 -0
- package/lib/chat/components/notifications-page.jsx +87 -0
- package/lib/chat/components/page-layout.js +21 -0
- package/lib/chat/components/page-layout.jsx +28 -0
- package/lib/chat/components/pull-requests-page.js +103 -0
- package/lib/chat/components/pull-requests-page.jsx +113 -0
- package/lib/chat/components/settings-layout.js +39 -0
- package/lib/chat/components/settings-layout.jsx +53 -0
- package/lib/chat/components/settings-secrets-page.js +216 -0
- package/lib/chat/components/settings-secrets-page.jsx +264 -0
- package/lib/chat/components/sidebar-history-item.js +138 -0
- package/lib/chat/components/sidebar-history-item.jsx +119 -0
- package/lib/chat/components/sidebar-history.js +167 -0
- package/lib/chat/components/sidebar-history.jsx +220 -0
- package/lib/chat/components/sidebar-user-nav.js +61 -0
- package/lib/chat/components/sidebar-user-nav.jsx +77 -0
- package/lib/chat/components/swarm-page.js +157 -0
- package/lib/chat/components/swarm-page.jsx +210 -0
- package/lib/chat/components/tool-call.js +89 -0
- package/lib/chat/components/tool-call.jsx +107 -0
- package/lib/chat/components/triggers-page.js +153 -0
- package/lib/chat/components/triggers-page.jsx +221 -0
- package/lib/chat/components/ui/combobox.js +98 -0
- package/lib/chat/components/ui/combobox.jsx +114 -0
- package/lib/chat/components/ui/confirm-dialog.js +53 -0
- package/lib/chat/components/ui/confirm-dialog.jsx +57 -0
- package/lib/chat/components/ui/dropdown-menu.js +194 -0
- package/lib/chat/components/ui/dropdown-menu.jsx +215 -0
- package/lib/chat/components/ui/rename-dialog.js +78 -0
- package/lib/chat/components/ui/rename-dialog.jsx +74 -0
- package/lib/chat/components/ui/scroll-area.js +13 -0
- package/lib/chat/components/ui/scroll-area.jsx +17 -0
- package/lib/chat/components/ui/separator.js +21 -0
- package/lib/chat/components/ui/separator.jsx +18 -0
- package/lib/chat/components/ui/sheet.js +75 -0
- package/lib/chat/components/ui/sheet.jsx +95 -0
- package/lib/chat/components/ui/sidebar.js +228 -0
- package/lib/chat/components/ui/sidebar.jsx +246 -0
- package/lib/chat/components/ui/tooltip.js +56 -0
- package/lib/chat/components/ui/tooltip.jsx +66 -0
- package/lib/chat/components/upgrade-dialog.js +151 -0
- package/lib/chat/components/upgrade-dialog.jsx +170 -0
- package/lib/chat/utils.js +11 -0
- package/lib/code/actions.js +153 -0
- package/lib/code/code-page.js +22 -0
- package/lib/code/code-page.jsx +25 -0
- package/lib/code/index.js +1 -0
- package/lib/code/terminal-view.js +201 -0
- package/lib/code/terminal-view.jsx +224 -0
- package/lib/code/ws-proxy.js +80 -0
- package/lib/cron.js +246 -0
- package/lib/db/api-keys.js +163 -0
- package/lib/db/chats.js +168 -0
- package/lib/db/code-workspaces.js +110 -0
- package/lib/db/index.js +52 -0
- package/lib/db/notifications.js +99 -0
- package/lib/db/schema.js +66 -0
- package/lib/db/update-check.js +96 -0
- package/lib/db/users.js +89 -0
- package/lib/paths.js +42 -0
- package/lib/tools/create-job.js +97 -0
- package/lib/tools/docker.js +146 -0
- package/lib/tools/github.js +271 -0
- package/lib/tools/openai.js +35 -0
- package/lib/tools/telegram.js +292 -0
- package/lib/triggers.js +104 -0
- package/lib/utils/render-md.js +111 -0
- package/package.json +118 -0
- package/setup/lib/auth.mjs +81 -0
- package/setup/lib/env.mjs +21 -0
- package/setup/lib/fs-utils.mjs +20 -0
- package/setup/lib/github.mjs +149 -0
- package/setup/lib/prerequisites.mjs +155 -0
- package/setup/lib/prompts.mjs +267 -0
- package/setup/lib/providers.mjs +105 -0
- package/setup/lib/sync.mjs +125 -0
- package/setup/lib/targets.mjs +45 -0
- package/setup/lib/telegram-verify.mjs +63 -0
- package/setup/lib/telegram.mjs +76 -0
- package/setup/setup-cloud.mjs +833 -0
- package/setup/setup-local.mjs +377 -0
- package/setup/setup-telegram.mjs +265 -0
- package/setup/setup.mjs +87 -0
- package/templates/.dockerignore +5 -0
- package/templates/.env.example +104 -0
- package/templates/.github/workflows/auto-merge.yml +117 -0
- package/templates/.github/workflows/notify-job-failed.yml +64 -0
- package/templates/.github/workflows/notify-pr-complete.yml +119 -0
- package/templates/.github/workflows/rebuild-event-handler.yml +121 -0
- package/templates/.github/workflows/run-job.yml +89 -0
- package/templates/.github/workflows/upgrade-event-handler.yml +62 -0
- package/templates/.gitignore.template +45 -0
- package/templates/.pi/extensions/env-sanitizer/index.ts +48 -0
- package/templates/.pi/extensions/env-sanitizer/package.json +5 -0
- package/templates/CLAUDE.md +29 -0
- package/templates/CLAUDE.md.template +308 -0
- package/templates/app/api/[...gigaclaw]/route.js +1 -0
- package/templates/app/api/auth/[...nextauth]/route.js +1 -0
- package/templates/app/chat/[chatId]/page.js +9 -0
- package/templates/app/chats/page.js +7 -0
- package/templates/app/code/[codeWorkspaceId]/page.js +9 -0
- package/templates/app/components/ascii-logo.jsx +12 -0
- package/templates/app/components/login-form.jsx +92 -0
- package/templates/app/components/setup-form.jsx +82 -0
- package/templates/app/components/theme-provider.jsx +11 -0
- package/templates/app/components/theme-toggle.jsx +38 -0
- package/templates/app/components/ui/button.jsx +21 -0
- package/templates/app/components/ui/card.jsx +23 -0
- package/templates/app/components/ui/input.jsx +10 -0
- package/templates/app/components/ui/label.jsx +10 -0
- package/templates/app/crons/page.js +5 -0
- package/templates/app/globals.css +90 -0
- package/templates/app/layout.js +33 -0
- package/templates/app/login/page.js +15 -0
- package/templates/app/notifications/page.js +7 -0
- package/templates/app/page.js +7 -0
- package/templates/app/pull-requests/page.js +7 -0
- package/templates/app/settings/crons/page.js +5 -0
- package/templates/app/settings/layout.js +7 -0
- package/templates/app/settings/page.js +5 -0
- package/templates/app/settings/secrets/page.js +5 -0
- package/templates/app/settings/triggers/page.js +5 -0
- package/templates/app/stream/chat/route.js +1 -0
- package/templates/app/swarm/page.js +7 -0
- package/templates/app/triggers/page.js +5 -0
- package/templates/config/CODE_PLANNING.md +14 -0
- package/templates/config/CRONS.json +56 -0
- package/templates/config/HEARTBEAT.md +3 -0
- package/templates/config/JOB_AGENT.md +30 -0
- package/templates/config/JOB_PLANNING.md +240 -0
- package/templates/config/JOB_SUMMARY.md +130 -0
- package/templates/config/SKILL_BUILDING_GUIDE.md +96 -0
- package/templates/config/SOUL.md +48 -0
- package/templates/config/TRIGGERS.json +58 -0
- package/templates/config/WEB_SEARCH_AVAILABLE.md +5 -0
- package/templates/config/WEB_SEARCH_UNAVAILABLE.md +3 -0
- package/templates/docker/claude-code-job/Dockerfile +34 -0
- package/templates/docker/claude-code-job/entrypoint.sh +149 -0
- package/templates/docker/claude-code-workspace/.tmux.conf +5 -0
- package/templates/docker/claude-code-workspace/Dockerfile +61 -0
- package/templates/docker/claude-code-workspace/entrypoint.sh +51 -0
- package/templates/docker/event-handler/Dockerfile +20 -0
- package/templates/docker/event-handler/ecosystem.config.cjs +7 -0
- package/templates/docker/pi-coding-agent-job/Dockerfile +51 -0
- package/templates/docker/pi-coding-agent-job/entrypoint.sh +164 -0
- package/templates/docker-compose.local.yml +78 -0
- package/templates/docker-compose.yml +64 -0
- package/templates/instrumentation.js +6 -0
- package/templates/middleware.js +23 -0
- package/templates/next.config.mjs +3 -0
- package/templates/postcss.config.mjs +5 -0
- package/templates/public/favicon.ico +0 -0
- package/templates/server.js +25 -0
- package/templates/skills/LICENSE +21 -0
- package/templates/skills/README.md +119 -0
- package/templates/skills/brave-search/SKILL.md +79 -0
- package/templates/skills/brave-search/content.js +86 -0
- package/templates/skills/brave-search/package-lock.json +621 -0
- package/templates/skills/brave-search/package.json +14 -0
- package/templates/skills/brave-search/search.js +199 -0
- package/templates/skills/browser-tools/SKILL.md +196 -0
- package/templates/skills/browser-tools/browser-content.js +103 -0
- package/templates/skills/browser-tools/browser-cookies.js +35 -0
- package/templates/skills/browser-tools/browser-eval.js +53 -0
- package/templates/skills/browser-tools/browser-hn-scraper.js +108 -0
- package/templates/skills/browser-tools/browser-nav.js +44 -0
- package/templates/skills/browser-tools/browser-pick.js +162 -0
- package/templates/skills/browser-tools/browser-screenshot.js +34 -0
- package/templates/skills/browser-tools/browser-start.js +87 -0
- package/templates/skills/browser-tools/package-lock.json +2556 -0
- package/templates/skills/browser-tools/package.json +19 -0
- package/templates/skills/google-docs/SKILL.md +23 -0
- package/templates/skills/google-docs/create.sh +69 -0
- package/templates/skills/google-drive/SKILL.md +47 -0
- package/templates/skills/google-drive/delete.sh +47 -0
- package/templates/skills/google-drive/download.sh +50 -0
- package/templates/skills/google-drive/list.sh +41 -0
- package/templates/skills/google-drive/upload.sh +76 -0
- package/templates/skills/kie-ai/SKILL.md +38 -0
- package/templates/skills/kie-ai/generate-image.sh +77 -0
- package/templates/skills/kie-ai/generate-video.sh +69 -0
- package/templates/skills/llm-secrets/SKILL.md +34 -0
- package/templates/skills/llm-secrets/llm-secrets.js +33 -0
- package/templates/skills/modify-self/SKILL.md +12 -0
- package/templates/skills/youtube-transcript/SKILL.md +41 -0
- package/templates/skills/youtube-transcript/package-lock.json +24 -0
- package/templates/skills/youtube-transcript/package.json +8 -0
- package/templates/skills/youtube-transcript/transcript.js +84 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "browser-tools",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Minimal CDP tools for collaborative site exploration",
|
|
6
|
+
"author": "Mario Zechner",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@mozilla/readability": "^0.6.0",
|
|
10
|
+
"cheerio": "^1.1.2",
|
|
11
|
+
"jsdom": "^27.0.1",
|
|
12
|
+
"puppeteer": "^24.31.0",
|
|
13
|
+
"puppeteer-core": "^23.11.1",
|
|
14
|
+
"puppeteer-extra": "^3.3.6",
|
|
15
|
+
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
|
16
|
+
"turndown": "^7.2.2",
|
|
17
|
+
"turndown-plugin-gfm": "^1.0.2"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: google-docs
|
|
3
|
+
description: "Create and manage Google Docs on a shared drive via service account."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Google Docs
|
|
7
|
+
|
|
8
|
+
Create and manage Google Docs on a shared drive using a service account.
|
|
9
|
+
|
|
10
|
+
## Environment Variables
|
|
11
|
+
|
|
12
|
+
- `GOOGLE_SERVICE_ACCOUNT_JSON` — Service account credentials JSON
|
|
13
|
+
- `GOOGLE_SHARED_DRIVE_ID` — Shared drive ID
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
### Create a Google Doc
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
skills/google-docs/create.sh <title> <content> <parent_folder_id>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Creates a new Google Doc with the given title and text content in the specified folder. Returns the document ID and URL.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
TITLE="${1:?Usage: create.sh <title> <content> <parent_folder_id>}"
|
|
5
|
+
CONTENT="${2:?Usage: create.sh <title> <content> <parent_folder_id>}"
|
|
6
|
+
PARENT_FOLDER_ID="${3:?Usage: create.sh <title> <content> <parent_folder_id>}"
|
|
7
|
+
|
|
8
|
+
if [ -z "${GOOGLE_SERVICE_ACCOUNT_JSON:-}" ]; then
|
|
9
|
+
echo "Error: GOOGLE_SERVICE_ACCOUNT_JSON is not set" >&2
|
|
10
|
+
exit 1
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
# Extract service account email and private key
|
|
14
|
+
SA_EMAIL=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.client_email')
|
|
15
|
+
SA_KEY=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.private_key')
|
|
16
|
+
TOKEN_URI=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.token_uri')
|
|
17
|
+
|
|
18
|
+
# Build JWT with both drive and docs scopes
|
|
19
|
+
NOW=$(date +%s)
|
|
20
|
+
EXP=$((NOW + 3600))
|
|
21
|
+
HEADER=$(echo -n '{"alg":"RS256","typ":"JWT"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
22
|
+
CLAIMS=$(printf '{"iss":"%s","scope":"https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/documents","aud":"%s","iat":%d,"exp":%d}' \
|
|
23
|
+
"$SA_EMAIL" "$TOKEN_URI" "$NOW" "$EXP" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
24
|
+
SIGNING_INPUT="${HEADER}.${CLAIMS}"
|
|
25
|
+
SIGNATURE=$(printf '%s' "$SIGNING_INPUT" | openssl dgst -sha256 -sign <(echo "$SA_KEY") | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
26
|
+
JWT="${SIGNING_INPUT}.${SIGNATURE}"
|
|
27
|
+
|
|
28
|
+
# Exchange JWT for access token
|
|
29
|
+
ACCESS_TOKEN=$(curl -s -X POST "$TOKEN_URI" \
|
|
30
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
31
|
+
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${JWT}" | jq -r '.access_token')
|
|
32
|
+
|
|
33
|
+
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
|
|
34
|
+
echo "Error: Failed to obtain access token" >&2
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# Create Google Doc via Drive API (creates empty doc in the shared drive)
|
|
39
|
+
METADATA=$(jq -n --arg title "$TITLE" --arg parent "$PARENT_FOLDER_ID" \
|
|
40
|
+
'{name: $title, mimeType: "application/vnd.google-apps.document", parents: [$parent]}')
|
|
41
|
+
|
|
42
|
+
CREATE_RESPONSE=$(curl -s -X POST \
|
|
43
|
+
"https://www.googleapis.com/drive/v3/files?supportsAllDrives=true&includeItemsFromAllDrives=true" \
|
|
44
|
+
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
45
|
+
-H "Content-Type: application/json" \
|
|
46
|
+
-d "$METADATA")
|
|
47
|
+
|
|
48
|
+
DOC_ID=$(echo "$CREATE_RESPONSE" | jq -r '.id')
|
|
49
|
+
if [ -z "$DOC_ID" ] || [ "$DOC_ID" = "null" ]; then
|
|
50
|
+
echo "Error: Failed to create document" >&2
|
|
51
|
+
echo "$CREATE_RESPONSE" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Insert content using Docs API batchUpdate
|
|
56
|
+
if [ -n "$CONTENT" ]; then
|
|
57
|
+
UPDATE_BODY=$(jq -n --arg text "$CONTENT" \
|
|
58
|
+
'{requests: [{insertText: {location: {index: 1}, text: $text}}]}')
|
|
59
|
+
|
|
60
|
+
curl -s -X POST \
|
|
61
|
+
"https://docs.googleapis.com/v1/documents/${DOC_ID}:batchUpdate" \
|
|
62
|
+
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
63
|
+
-H "Content-Type: application/json" \
|
|
64
|
+
-d "$UPDATE_BODY" > /dev/null
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
echo "Created Google Doc: $TITLE"
|
|
68
|
+
echo "Doc ID: $DOC_ID"
|
|
69
|
+
echo "URL: https://docs.google.com/document/d/${DOC_ID}/edit"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: google-drive
|
|
3
|
+
description: "Interact with Google Drive shared drives via service account. Supports list, upload, download, delete operations."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Google Drive
|
|
7
|
+
|
|
8
|
+
Interact with Google Drive shared drives using a service account.
|
|
9
|
+
|
|
10
|
+
## Environment Variables
|
|
11
|
+
|
|
12
|
+
- `GOOGLE_SERVICE_ACCOUNT_JSON` — Service account credentials JSON
|
|
13
|
+
- `GOOGLE_SHARED_DRIVE_ID` — Shared drive ID
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
### List files in a folder
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
skills/google-drive/list.sh <folder_id>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Lists files and folders in the given folder. Use `$GOOGLE_SHARED_DRIVE_ID` for the root.
|
|
24
|
+
|
|
25
|
+
### Upload a file
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
skills/google-drive/upload.sh <local_file> <parent_folder_id> <filename>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Uploads a local file to the specified folder with the given name.
|
|
32
|
+
|
|
33
|
+
### Download a file
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
skills/google-drive/download.sh <file_id> <local_path>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Downloads a file by ID to a local path.
|
|
40
|
+
|
|
41
|
+
### Delete a file
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
skills/google-drive/delete.sh <file_id>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Deletes a file by ID.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
FILE_ID="${1:?Usage: delete.sh <file_id>}"
|
|
5
|
+
|
|
6
|
+
if [ -z "${GOOGLE_SERVICE_ACCOUNT_JSON:-}" ]; then
|
|
7
|
+
echo "Error: GOOGLE_SERVICE_ACCOUNT_JSON is not set" >&2
|
|
8
|
+
exit 1
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
# Extract service account email and private key
|
|
12
|
+
SA_EMAIL=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.client_email')
|
|
13
|
+
SA_KEY=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.private_key')
|
|
14
|
+
TOKEN_URI=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.token_uri')
|
|
15
|
+
|
|
16
|
+
# Build JWT
|
|
17
|
+
NOW=$(date +%s)
|
|
18
|
+
EXP=$((NOW + 3600))
|
|
19
|
+
HEADER=$(echo -n '{"alg":"RS256","typ":"JWT"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
20
|
+
CLAIMS=$(printf '{"iss":"%s","scope":"https://www.googleapis.com/auth/drive","aud":"%s","iat":%d,"exp":%d}' \
|
|
21
|
+
"$SA_EMAIL" "$TOKEN_URI" "$NOW" "$EXP" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
22
|
+
SIGNING_INPUT="${HEADER}.${CLAIMS}"
|
|
23
|
+
SIGNATURE=$(printf '%s' "$SIGNING_INPUT" | openssl dgst -sha256 -sign <(echo "$SA_KEY") | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
24
|
+
JWT="${SIGNING_INPUT}.${SIGNATURE}"
|
|
25
|
+
|
|
26
|
+
# Exchange JWT for access token
|
|
27
|
+
ACCESS_TOKEN=$(curl -s -X POST "$TOKEN_URI" \
|
|
28
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
29
|
+
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${JWT}" | jq -r '.access_token')
|
|
30
|
+
|
|
31
|
+
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
|
|
32
|
+
echo "Error: Failed to obtain access token" >&2
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Delete file
|
|
37
|
+
HTTP_CODE=$(curl -s -w "%{http_code}" -o /dev/null \
|
|
38
|
+
-X DELETE \
|
|
39
|
+
"https://www.googleapis.com/drive/v3/files/${FILE_ID}?supportsAllDrives=true" \
|
|
40
|
+
-H "Authorization: Bearer ${ACCESS_TOKEN}")
|
|
41
|
+
|
|
42
|
+
if [ "$HTTP_CODE" -ne 204 ] && [ "$HTTP_CODE" -ne 200 ]; then
|
|
43
|
+
echo "Error: Delete failed with HTTP $HTTP_CODE" >&2
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
echo "Deleted file: $FILE_ID"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
FILE_ID="${1:?Usage: download.sh <file_id> <local_path>}"
|
|
5
|
+
LOCAL_PATH="${2:?Usage: download.sh <file_id> <local_path>}"
|
|
6
|
+
|
|
7
|
+
if [ -z "${GOOGLE_SERVICE_ACCOUNT_JSON:-}" ]; then
|
|
8
|
+
echo "Error: GOOGLE_SERVICE_ACCOUNT_JSON is not set" >&2
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
# Extract service account email and private key
|
|
13
|
+
SA_EMAIL=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.client_email')
|
|
14
|
+
SA_KEY=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.private_key')
|
|
15
|
+
TOKEN_URI=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.token_uri')
|
|
16
|
+
|
|
17
|
+
# Build JWT
|
|
18
|
+
NOW=$(date +%s)
|
|
19
|
+
EXP=$((NOW + 3600))
|
|
20
|
+
HEADER=$(echo -n '{"alg":"RS256","typ":"JWT"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
21
|
+
CLAIMS=$(printf '{"iss":"%s","scope":"https://www.googleapis.com/auth/drive","aud":"%s","iat":%d,"exp":%d}' \
|
|
22
|
+
"$SA_EMAIL" "$TOKEN_URI" "$NOW" "$EXP" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
23
|
+
SIGNING_INPUT="${HEADER}.${CLAIMS}"
|
|
24
|
+
SIGNATURE=$(printf '%s' "$SIGNING_INPUT" | openssl dgst -sha256 -sign <(echo "$SA_KEY") | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
25
|
+
JWT="${SIGNING_INPUT}.${SIGNATURE}"
|
|
26
|
+
|
|
27
|
+
# Exchange JWT for access token
|
|
28
|
+
ACCESS_TOKEN=$(curl -s -X POST "$TOKEN_URI" \
|
|
29
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
30
|
+
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${JWT}" | jq -r '.access_token')
|
|
31
|
+
|
|
32
|
+
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
|
|
33
|
+
echo "Error: Failed to obtain access token" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# Download file
|
|
38
|
+
HTTP_CODE=$(curl -s -w "%{http_code}" -o "$LOCAL_PATH" \
|
|
39
|
+
"https://www.googleapis.com/drive/v3/files/${FILE_ID}?alt=media&supportsAllDrives=true&includeItemsFromAllDrives=true" \
|
|
40
|
+
-H "Authorization: Bearer ${ACCESS_TOKEN}")
|
|
41
|
+
|
|
42
|
+
if [ "$HTTP_CODE" -ne 200 ]; then
|
|
43
|
+
echo "Error: Download failed with HTTP $HTTP_CODE" >&2
|
|
44
|
+
cat "$LOCAL_PATH" >&2
|
|
45
|
+
rm -f "$LOCAL_PATH"
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
FILE_SIZE=$(stat -c%s "$LOCAL_PATH" 2>/dev/null || stat -f%z "$LOCAL_PATH" 2>/dev/null)
|
|
50
|
+
echo "Downloaded to: $LOCAL_PATH ($FILE_SIZE bytes)"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
FOLDER_ID="${1:?Usage: list.sh <folder_id>}"
|
|
5
|
+
|
|
6
|
+
if [ -z "${GOOGLE_SERVICE_ACCOUNT_JSON:-}" ]; then
|
|
7
|
+
echo "Error: GOOGLE_SERVICE_ACCOUNT_JSON is not set" >&2
|
|
8
|
+
exit 1
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
# Extract service account email and private key
|
|
12
|
+
SA_EMAIL=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.client_email')
|
|
13
|
+
SA_KEY=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.private_key')
|
|
14
|
+
TOKEN_URI=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.token_uri')
|
|
15
|
+
|
|
16
|
+
# Build JWT
|
|
17
|
+
NOW=$(date +%s)
|
|
18
|
+
EXP=$((NOW + 3600))
|
|
19
|
+
HEADER=$(echo -n '{"alg":"RS256","typ":"JWT"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
20
|
+
CLAIMS=$(printf '{"iss":"%s","scope":"https://www.googleapis.com/auth/drive","aud":"%s","iat":%d,"exp":%d}' \
|
|
21
|
+
"$SA_EMAIL" "$TOKEN_URI" "$NOW" "$EXP" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
22
|
+
SIGNING_INPUT="${HEADER}.${CLAIMS}"
|
|
23
|
+
SIGNATURE=$(printf '%s' "$SIGNING_INPUT" | openssl dgst -sha256 -sign <(echo "$SA_KEY") | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
24
|
+
JWT="${SIGNING_INPUT}.${SIGNATURE}"
|
|
25
|
+
|
|
26
|
+
# Exchange JWT for access token
|
|
27
|
+
ACCESS_TOKEN=$(curl -s -X POST "$TOKEN_URI" \
|
|
28
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
29
|
+
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${JWT}" | jq -r '.access_token')
|
|
30
|
+
|
|
31
|
+
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
|
|
32
|
+
echo "Error: Failed to obtain access token" >&2
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# List files
|
|
37
|
+
RESPONSE=$(curl -s -X GET \
|
|
38
|
+
"https://www.googleapis.com/drive/v3/files?q='${FOLDER_ID}'+in+parents&supportsAllDrives=true&includeItemsFromAllDrives=true&corpora=allDrives&fields=files(id,name,mimeType,size,modifiedTime)" \
|
|
39
|
+
-H "Authorization: Bearer ${ACCESS_TOKEN}")
|
|
40
|
+
|
|
41
|
+
echo "$RESPONSE" | jq -r '.files[] | "\(.id)\t\(.name)\t\(.mimeType)\t\(.size // "N/A")\t\(.modifiedTime)"' 2>/dev/null || echo "$RESPONSE"
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
LOCAL_FILE="${1:?Usage: upload.sh <local_file> <parent_folder_id> <filename>}"
|
|
5
|
+
PARENT_FOLDER_ID="${2:?Usage: upload.sh <local_file> <parent_folder_id> <filename>}"
|
|
6
|
+
FILENAME="${3:?Usage: upload.sh <local_file> <parent_folder_id> <filename>}"
|
|
7
|
+
|
|
8
|
+
if [ ! -f "$LOCAL_FILE" ]; then
|
|
9
|
+
echo "Error: File not found: $LOCAL_FILE" >&2
|
|
10
|
+
exit 1
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
if [ -z "${GOOGLE_SERVICE_ACCOUNT_JSON:-}" ]; then
|
|
14
|
+
echo "Error: GOOGLE_SERVICE_ACCOUNT_JSON is not set" >&2
|
|
15
|
+
exit 1
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
# Extract service account email and private key
|
|
19
|
+
SA_EMAIL=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.client_email')
|
|
20
|
+
SA_KEY=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.private_key')
|
|
21
|
+
TOKEN_URI=$(echo "$GOOGLE_SERVICE_ACCOUNT_JSON" | jq -r '.token_uri')
|
|
22
|
+
|
|
23
|
+
# Build JWT
|
|
24
|
+
NOW=$(date +%s)
|
|
25
|
+
EXP=$((NOW + 3600))
|
|
26
|
+
HEADER=$(echo -n '{"alg":"RS256","typ":"JWT"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
27
|
+
CLAIMS=$(printf '{"iss":"%s","scope":"https://www.googleapis.com/auth/drive","aud":"%s","iat":%d,"exp":%d}' \
|
|
28
|
+
"$SA_EMAIL" "$TOKEN_URI" "$NOW" "$EXP" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
29
|
+
SIGNING_INPUT="${HEADER}.${CLAIMS}"
|
|
30
|
+
SIGNATURE=$(printf '%s' "$SIGNING_INPUT" | openssl dgst -sha256 -sign <(echo "$SA_KEY") | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
|
|
31
|
+
JWT="${SIGNING_INPUT}.${SIGNATURE}"
|
|
32
|
+
|
|
33
|
+
# Exchange JWT for access token
|
|
34
|
+
ACCESS_TOKEN=$(curl -s -X POST "$TOKEN_URI" \
|
|
35
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
36
|
+
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${JWT}" | jq -r '.access_token')
|
|
37
|
+
|
|
38
|
+
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
|
|
39
|
+
echo "Error: Failed to obtain access token" >&2
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Detect MIME type from extension
|
|
44
|
+
EXT="${LOCAL_FILE##*.}"
|
|
45
|
+
case "${EXT,,}" in
|
|
46
|
+
jpg|jpeg) MIME_TYPE="image/jpeg" ;;
|
|
47
|
+
png) MIME_TYPE="image/png" ;;
|
|
48
|
+
gif) MIME_TYPE="image/gif" ;;
|
|
49
|
+
webp) MIME_TYPE="image/webp" ;;
|
|
50
|
+
mp4) MIME_TYPE="video/mp4" ;;
|
|
51
|
+
webm) MIME_TYPE="video/webm" ;;
|
|
52
|
+
pdf) MIME_TYPE="application/pdf" ;;
|
|
53
|
+
txt) MIME_TYPE="text/plain" ;;
|
|
54
|
+
json) MIME_TYPE="application/json" ;;
|
|
55
|
+
csv) MIME_TYPE="text/csv" ;;
|
|
56
|
+
*) MIME_TYPE="application/octet-stream" ;;
|
|
57
|
+
esac
|
|
58
|
+
|
|
59
|
+
# Upload file using multipart upload
|
|
60
|
+
METADATA=$(printf '{"name":"%s","parents":["%s"]}' "$FILENAME" "$PARENT_FOLDER_ID")
|
|
61
|
+
|
|
62
|
+
RESPONSE=$(curl -s -X POST \
|
|
63
|
+
"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&supportsAllDrives=true&includeItemsFromAllDrives=true" \
|
|
64
|
+
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
65
|
+
-F "metadata=${METADATA};type=application/json" \
|
|
66
|
+
-F "file=@${LOCAL_FILE};type=${MIME_TYPE}")
|
|
67
|
+
|
|
68
|
+
FILE_ID=$(echo "$RESPONSE" | jq -r '.id')
|
|
69
|
+
if [ -z "$FILE_ID" ] || [ "$FILE_ID" = "null" ]; then
|
|
70
|
+
echo "Error: Upload failed" >&2
|
|
71
|
+
echo "$RESPONSE" >&2
|
|
72
|
+
exit 1
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
echo "Uploaded: $FILENAME"
|
|
76
|
+
echo "File ID: $FILE_ID"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kie-ai
|
|
3
|
+
description: "Generate images and videos using kie.ai API. Use for AI image and video generation tasks."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# KIE AI
|
|
7
|
+
|
|
8
|
+
Generate images and videos using the kie.ai API.
|
|
9
|
+
|
|
10
|
+
## Environment Variables
|
|
11
|
+
|
|
12
|
+
- `KIE_AI_API_KEY` — API key for kie.ai
|
|
13
|
+
|
|
14
|
+
## Commands
|
|
15
|
+
|
|
16
|
+
### Generate an image
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
skills/kie-ai/generate-image.sh <prompt> [aspect_ratio] [resolution] [output_format]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
- `prompt` (required) — Text prompt for image generation
|
|
23
|
+
- `aspect_ratio` (optional, default: `auto`) — One of: `auto, 1:1, 1:4, 16:9, 1:8, 21:9, 2:3, 3:2, 3:4, 4:1, 4:3, 4:5, 5:4, 8:1, 9:16`
|
|
24
|
+
- `resolution` (optional, default: `1K`) — One of: `1K, 2K, 4K`
|
|
25
|
+
- `output_format` (optional, default: `jpg`) — One of: `jpg, png`
|
|
26
|
+
|
|
27
|
+
Downloads the generated image to a local file and prints the path.
|
|
28
|
+
|
|
29
|
+
### Generate a video
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
skills/kie-ai/generate-video.sh <prompt> [aspect_ratio]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- `prompt` (required) — Text prompt for video generation
|
|
36
|
+
- `aspect_ratio` (optional, default: `16:9`) — One of: `16:9, 9:16, Auto`
|
|
37
|
+
|
|
38
|
+
Downloads the generated video to a local file and prints the path.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
PROMPT="${1:?Usage: generate-image.sh <prompt> [aspect_ratio] [resolution] [output_format]}"
|
|
5
|
+
ASPECT_RATIO="${2:-auto}"
|
|
6
|
+
RESOLUTION="${3:-1K}"
|
|
7
|
+
OUTPUT_FORMAT="${4:-jpg}"
|
|
8
|
+
|
|
9
|
+
if [ -z "${KIE_AI_API_KEY:-}" ]; then
|
|
10
|
+
echo "Error: KIE_AI_API_KEY is not set" >&2
|
|
11
|
+
exit 1
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
# Create task
|
|
15
|
+
BODY=$(jq -n \
|
|
16
|
+
--arg prompt "$PROMPT" \
|
|
17
|
+
--arg ar "$ASPECT_RATIO" \
|
|
18
|
+
--arg res "$RESOLUTION" \
|
|
19
|
+
--arg fmt "$OUTPUT_FORMAT" \
|
|
20
|
+
'{
|
|
21
|
+
model: "nano-banana-2",
|
|
22
|
+
input: {
|
|
23
|
+
prompt: $prompt,
|
|
24
|
+
aspect_ratio: $ar,
|
|
25
|
+
resolution: $res,
|
|
26
|
+
output_format: $fmt
|
|
27
|
+
}
|
|
28
|
+
}')
|
|
29
|
+
|
|
30
|
+
echo "Creating image generation task..." >&2
|
|
31
|
+
CREATE_RESPONSE=$(curl -s -X POST \
|
|
32
|
+
"https://api.kie.ai/api/v1/jobs/createTask" \
|
|
33
|
+
-H "Authorization: Bearer ${KIE_AI_API_KEY}" \
|
|
34
|
+
-H "Content-Type: application/json" \
|
|
35
|
+
-d "$BODY")
|
|
36
|
+
|
|
37
|
+
TASK_ID=$(echo "$CREATE_RESPONSE" | jq -r '.data.taskId // .taskId // empty')
|
|
38
|
+
if [ -z "$TASK_ID" ]; then
|
|
39
|
+
echo "Error: Failed to create task" >&2
|
|
40
|
+
echo "$CREATE_RESPONSE" >&2
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
echo "Task ID: $TASK_ID — polling for completion..." >&2
|
|
45
|
+
|
|
46
|
+
# Poll for completion
|
|
47
|
+
while true; do
|
|
48
|
+
sleep 15
|
|
49
|
+
STATUS_RESPONSE=$(curl -s -X GET \
|
|
50
|
+
"https://api.kie.ai/api/v1/jobs/recordInfo?taskId=${TASK_ID}" \
|
|
51
|
+
-H "Authorization: Bearer ${KIE_AI_API_KEY}" \
|
|
52
|
+
-H "Content-Type: application/json")
|
|
53
|
+
|
|
54
|
+
STATE=$(echo "$STATUS_RESPONSE" | jq -r '.data.state // empty')
|
|
55
|
+
echo "State: $STATE" >&2
|
|
56
|
+
|
|
57
|
+
if [ "$STATE" = "success" ]; then
|
|
58
|
+
# .data.resultJson is a JSON string — parse it, then get .resultUrls[0]
|
|
59
|
+
IMAGE_URL=$(echo "$STATUS_RESPONSE" | jq -r '.data.resultJson' | jq -r '.resultUrls[0]')
|
|
60
|
+
if [ -z "$IMAGE_URL" ] || [ "$IMAGE_URL" = "null" ]; then
|
|
61
|
+
echo "Error: Could not extract image URL" >&2
|
|
62
|
+
echo "$STATUS_RESPONSE" >&2
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Download
|
|
67
|
+
OUTPUT_FILE="/tmp/kie-image-${TASK_ID}.${OUTPUT_FORMAT}"
|
|
68
|
+
curl -s -o "$OUTPUT_FILE" "$IMAGE_URL"
|
|
69
|
+
FILE_SIZE=$(stat -c%s "$OUTPUT_FILE" 2>/dev/null || stat -f%z "$OUTPUT_FILE" 2>/dev/null)
|
|
70
|
+
echo "Image downloaded: $OUTPUT_FILE ($FILE_SIZE bytes)"
|
|
71
|
+
exit 0
|
|
72
|
+
elif [ "$STATE" = "failed" ] || [ "$STATE" = "error" ]; then
|
|
73
|
+
echo "Error: Image generation failed" >&2
|
|
74
|
+
echo "$STATUS_RESPONSE" >&2
|
|
75
|
+
exit 1
|
|
76
|
+
fi
|
|
77
|
+
done
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
PROMPT="${1:?Usage: generate-video.sh <prompt> [aspect_ratio]}"
|
|
5
|
+
ASPECT_RATIO="${2:-16:9}"
|
|
6
|
+
|
|
7
|
+
if [ -z "${KIE_AI_API_KEY:-}" ]; then
|
|
8
|
+
echo "Error: KIE_AI_API_KEY is not set" >&2
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
# Create task
|
|
13
|
+
BODY=$(jq -n \
|
|
14
|
+
--arg prompt "$PROMPT" \
|
|
15
|
+
--arg ar "$ASPECT_RATIO" \
|
|
16
|
+
'{
|
|
17
|
+
prompt: $prompt,
|
|
18
|
+
model: "veo3_fast",
|
|
19
|
+
generationType: "TEXT_2_VIDEO",
|
|
20
|
+
aspect_ratio: $ar
|
|
21
|
+
}')
|
|
22
|
+
|
|
23
|
+
echo "Creating video generation task..." >&2
|
|
24
|
+
CREATE_RESPONSE=$(curl -s -X POST \
|
|
25
|
+
"https://api.kie.ai/api/v1/veo/generate" \
|
|
26
|
+
-H "Authorization: Bearer ${KIE_AI_API_KEY}" \
|
|
27
|
+
-H "Content-Type: application/json" \
|
|
28
|
+
-d "$BODY")
|
|
29
|
+
|
|
30
|
+
TASK_ID=$(echo "$CREATE_RESPONSE" | jq -r '.data.taskId // .taskId // empty')
|
|
31
|
+
if [ -z "$TASK_ID" ]; then
|
|
32
|
+
echo "Error: Failed to create task" >&2
|
|
33
|
+
echo "$CREATE_RESPONSE" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
echo "Task ID: $TASK_ID — polling for completion..." >&2
|
|
38
|
+
|
|
39
|
+
# Poll for completion
|
|
40
|
+
while true; do
|
|
41
|
+
sleep 15
|
|
42
|
+
STATUS_RESPONSE=$(curl -s -X GET \
|
|
43
|
+
"https://api.kie.ai/api/v1/veo/record-info?taskId=${TASK_ID}" \
|
|
44
|
+
-H "Authorization: Bearer ${KIE_AI_API_KEY}" \
|
|
45
|
+
-H "Content-Type: application/json")
|
|
46
|
+
|
|
47
|
+
SUCCESS_FLAG=$(echo "$STATUS_RESPONSE" | jq -r '.data.successFlag // empty')
|
|
48
|
+
echo "Status check... successFlag=$SUCCESS_FLAG" >&2
|
|
49
|
+
|
|
50
|
+
if [ "$SUCCESS_FLAG" = "1" ]; then
|
|
51
|
+
VIDEO_URL=$(echo "$STATUS_RESPONSE" | jq -r '.data.response.resultUrls[0]')
|
|
52
|
+
if [ -z "$VIDEO_URL" ] || [ "$VIDEO_URL" = "null" ]; then
|
|
53
|
+
echo "Error: Could not extract video URL" >&2
|
|
54
|
+
echo "$STATUS_RESPONSE" >&2
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# Download
|
|
59
|
+
OUTPUT_FILE="/tmp/kie-video-${TASK_ID}.mp4"
|
|
60
|
+
curl -s -o "$OUTPUT_FILE" "$VIDEO_URL"
|
|
61
|
+
FILE_SIZE=$(stat -c%s "$OUTPUT_FILE" 2>/dev/null || stat -f%z "$OUTPUT_FILE" 2>/dev/null)
|
|
62
|
+
echo "Video downloaded: $OUTPUT_FILE ($FILE_SIZE bytes)"
|
|
63
|
+
exit 0
|
|
64
|
+
elif [ "$SUCCESS_FLAG" = "-1" ]; then
|
|
65
|
+
echo "Error: Video generation failed" >&2
|
|
66
|
+
echo "$STATUS_RESPONSE" >&2
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
done
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: llm-secrets
|
|
3
|
+
description: List available LLM-accessible credentials. Use when you need API keys, passwords, or other secrets that have been made available to you.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# List Available Secrets
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
skills/llm-secrets/llm-secrets.js
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Shows the names of available secret keys (not values). Output example:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
Available secrets:
|
|
16
|
+
- BROWSER_PASSWORD
|
|
17
|
+
- SOME_API_KEY
|
|
18
|
+
|
|
19
|
+
To get a value: echo $KEY_NAME
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Get a Secret Value
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
echo $KEY_NAME
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Replace `KEY_NAME` with one of the available secret names.
|
|
29
|
+
|
|
30
|
+
## When to Use
|
|
31
|
+
|
|
32
|
+
- When a skill or tool needs authentication credentials
|
|
33
|
+
- When logging into a website via browser tools
|
|
34
|
+
- When calling an external API that requires a key
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* llm-secrets.js - List available LLM-accessible secret keys
|
|
5
|
+
*
|
|
6
|
+
* Usage: llm-secrets.js
|
|
7
|
+
*
|
|
8
|
+
* Lists the key names from LLM_SECRETS (not the values).
|
|
9
|
+
* To get a value, use: echo $KEY_NAME
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const secretsJson = process.env.LLM_SECRETS;
|
|
13
|
+
|
|
14
|
+
if (!secretsJson) {
|
|
15
|
+
console.log('No LLM_SECRETS configured.');
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const parsed = JSON.parse(secretsJson);
|
|
21
|
+
const keys = Object.keys(parsed);
|
|
22
|
+
|
|
23
|
+
if (keys.length === 0) {
|
|
24
|
+
console.log('LLM_SECRETS is empty.');
|
|
25
|
+
} else {
|
|
26
|
+
console.log('Available secrets:');
|
|
27
|
+
keys.forEach(key => console.log(` - ${key}`));
|
|
28
|
+
console.log('\nTo get a value: echo $KEY_NAME');
|
|
29
|
+
}
|
|
30
|
+
} catch (e) {
|
|
31
|
+
console.error('Error parsing LLM_SECRETS:', e.message);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: modify-self
|
|
3
|
+
description: Use when a job requires modifying the agent's own code, configuration, personality, cron jobs, skills, or operating system files.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Modify Self
|
|
7
|
+
|
|
8
|
+
Before making any changes, read the project documentation for a full understanding of the system architecture:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
cat CLAUDE.md
|
|
12
|
+
```
|