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
package/LICENSE
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gignaati (https://www.gignaati.com)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
This project is based on the open-source agent framework by the original authors,
|
|
26
|
+
also licensed under the MIT License.
|
package/README.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Giga Bot
|
|
4
|
+
|
|
5
|
+
### Autonomous AI Agent Platform — Powered by Gignaati
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/gigaclaw)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://github.com/gignaati/gigaclaw/stargazers)
|
|
10
|
+
[](https://www.gignaati.com)
|
|
11
|
+
|
|
12
|
+
**Build, deploy, and run autonomous AI agents 24/7.**
|
|
13
|
+
India-first. Edge-native. Zero vendor lock-in.
|
|
14
|
+
|
|
15
|
+
[Website](https://www.gignaati.com) · [Documentation](https://github.com/gignaati/gigaclaw/wiki) · [Issues](https://github.com/gignaati/gigaclaw/issues) · [Discussions](https://github.com/gignaati/gigaclaw/discussions)
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## What is Giga Bot?
|
|
22
|
+
|
|
23
|
+
Giga Bot is a self-hosted, autonomous AI agent platform. You deploy it to your own server or VPS, and it runs 24/7 — responding to messages, executing scheduled jobs, handling webhooks, writing code, managing files, and completing complex multi-step tasks.
|
|
24
|
+
|
|
25
|
+
It is built on a two-layer architecture:
|
|
26
|
+
|
|
27
|
+
- **Event Handler** — A Next.js server that handles real-time chat (web UI + Telegram), manages your agent's configuration, and creates jobs for the agent to execute.
|
|
28
|
+
- **Agent Engine** — A Docker container that runs your agent jobs using GitHub Actions or a local Docker daemon. The agent can write code, run shell commands, browse the web, and interact with GitHub.
|
|
29
|
+
|
|
30
|
+
Giga Bot is the only autonomous agent platform with **native PragatiGPT support** — India's indigenous Small Language Model for edge deployment, delivering 100% data privacy and zero foreign cloud dependency.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## One-Line Install
|
|
35
|
+
|
|
36
|
+
### Linux / macOS
|
|
37
|
+
```bash
|
|
38
|
+
curl -fsSL https://raw.githubusercontent.com/gignaati/gigaclaw/main/install.sh | bash
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Windows (PowerShell)
|
|
42
|
+
```powershell
|
|
43
|
+
irm https://raw.githubusercontent.com/gignaati/gigaclaw/main/install.ps1 | iex
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### All Platforms (npm / npx)
|
|
47
|
+
```bash
|
|
48
|
+
# Create a new Giga Bot project
|
|
49
|
+
mkdir my-gigaclaw && cd my-gigaclaw
|
|
50
|
+
npx gigaclaw@latest init
|
|
51
|
+
|
|
52
|
+
# Then run the interactive setup wizard
|
|
53
|
+
npm run setup
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
> **Prerequisites:** [Node.js 18+](https://nodejs.org), [Docker](https://docs.docker.com/get-docker/), [Git](https://git-scm.com)
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Quick Start (5 Steps)
|
|
61
|
+
|
|
62
|
+
**Step 1 — Create a new GitHub repository** for your agent (e.g., `my-gigaclaw`).
|
|
63
|
+
|
|
64
|
+
**Step 2 — Install Giga Bot** into a local folder with the same name:
|
|
65
|
+
```bash
|
|
66
|
+
mkdir my-gigaclaw && cd my-gigaclaw
|
|
67
|
+
npx gigaclaw@latest init
|
|
68
|
+
npm install
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Step 3 — Run the setup wizard:**
|
|
72
|
+
```bash
|
|
73
|
+
npm run setup
|
|
74
|
+
```
|
|
75
|
+
The wizard will ask for:
|
|
76
|
+
- Your GitHub Personal Access Token
|
|
77
|
+
- Your public URL (domain or ngrok URL)
|
|
78
|
+
- Your LLM provider and API key (Claude, GPT, Gemini, PragatiGPT, or Ollama)
|
|
79
|
+
|
|
80
|
+
**Step 4 — Start your agent:**
|
|
81
|
+
```bash
|
|
82
|
+
docker compose up -d
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Step 5 — Chat with your agent** at your APP_URL.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Supported LLM Providers
|
|
90
|
+
|
|
91
|
+
Giga Bot supports **6 LLM providers** — more than any other self-hosted agent platform:
|
|
92
|
+
|
|
93
|
+
| Provider | Description | Data Privacy |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| **PragatiGPT** | Gignaati's India-first SLM — edge-native, on-premise | 100% — no foreign cloud |
|
|
96
|
+
| **Ollama** | Run any open-source model locally (Llama, Mistral, Qwen, Phi) | 100% — fully local |
|
|
97
|
+
| **Claude (Anthropic)** | claude-opus-4, claude-sonnet-4, claude-haiku-4 | Anthropic's servers |
|
|
98
|
+
| **GPT (OpenAI)** | gpt-5.2, gpt-4o, o4-mini | OpenAI's servers |
|
|
99
|
+
| **Gemini (Google)** | gemini-3.1-pro, gemini-2.5-flash | Google's servers |
|
|
100
|
+
| **Custom API** | Any OpenAI-compatible endpoint (vLLM, LM Studio, Together AI) | Depends on endpoint |
|
|
101
|
+
|
|
102
|
+
Set your provider in `.env`:
|
|
103
|
+
```bash
|
|
104
|
+
LLM_PROVIDER=pragatigpt # India-first, edge-native
|
|
105
|
+
LLM_PROVIDER=ollama # Fully local, zero cloud
|
|
106
|
+
LLM_PROVIDER=anthropic # Claude (default)
|
|
107
|
+
LLM_PROVIDER=openai # GPT
|
|
108
|
+
LLM_PROVIDER=google # Gemini
|
|
109
|
+
LLM_PROVIDER=custom # Any OpenAI-compatible API
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Features
|
|
115
|
+
|
|
116
|
+
### Agent Capabilities
|
|
117
|
+
- **Web Chat** — Chat with your agent at your APP_URL
|
|
118
|
+
- **Telegram** — Connect a Telegram bot with `npm run setup-telegram`
|
|
119
|
+
- **Scheduled Jobs** — Cron-based recurring tasks via `config/CRONS.json`
|
|
120
|
+
- **Webhook Triggers** — POST to `/api/create-job` to trigger jobs programmatically
|
|
121
|
+
- **Code Workspace** — Full terminal and code editor in the browser
|
|
122
|
+
- **File Uploads** — Upload images, PDFs, and text files to the chat
|
|
123
|
+
|
|
124
|
+
### Agent Tools
|
|
125
|
+
- **Code execution** — Write and run code in any language
|
|
126
|
+
- **Shell commands** — Execute terminal commands
|
|
127
|
+
- **Web search** — Search the internet for up-to-date information
|
|
128
|
+
- **GitHub integration** — Create PRs, manage issues, push commits
|
|
129
|
+
- **File system** — Read, write, and manage files in the repository
|
|
130
|
+
|
|
131
|
+
### Infrastructure
|
|
132
|
+
- **Docker Compose** — One-command deployment with Traefik reverse proxy
|
|
133
|
+
- **Auto SSL** — Let's Encrypt certificates via Traefik
|
|
134
|
+
- **GitHub Actions** — Agent jobs run in isolated Docker containers
|
|
135
|
+
- **Auto-merge** — Agent can merge its own PRs after review
|
|
136
|
+
- **Hot reload** — Push to `main` triggers automatic rebuild and restart
|
|
137
|
+
|
|
138
|
+
### Giga Bot Exclusive Features
|
|
139
|
+
- **PragatiGPT** — India's indigenous SLM for edge deployment
|
|
140
|
+
- **Ollama** — Run any open-source model with zero cloud dependency
|
|
141
|
+
- **Multi-LLM routing** — Different LLMs for chat vs. agent jobs
|
|
142
|
+
- **Per-job LLM override** — Specify `llm_provider` and `llm_model` per cron job
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## CLI Commands
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
npx gigaclaw init # Scaffold or update project files
|
|
150
|
+
npx gigaclaw setup # Run interactive setup wizard
|
|
151
|
+
npx gigaclaw setup-telegram # Configure Telegram bot
|
|
152
|
+
npx gigaclaw upgrade [@beta|version] # Upgrade to latest version
|
|
153
|
+
npx gigaclaw reset-auth # Regenerate AUTH_SECRET
|
|
154
|
+
npx gigaclaw reset [file] # Restore a template file
|
|
155
|
+
npx gigaclaw diff [file] # Show differences vs. templates
|
|
156
|
+
npx gigaclaw set-agent-secret <KEY> [VALUE] # Set GitHub secret (AGENT_ prefix)
|
|
157
|
+
npx gigaclaw set-agent-llm-secret <KEY> [VALUE] # Set LLM secret (AGENT_LLM_ prefix)
|
|
158
|
+
npx gigaclaw set-var <KEY> [VALUE] # Set GitHub repository variable
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Configuration Files
|
|
164
|
+
|
|
165
|
+
These files in `config/` define your agent's personality and behavior. They are **yours to customize** — Giga Bot will never overwrite them:
|
|
166
|
+
|
|
167
|
+
| File | Purpose |
|
|
168
|
+
|---|---|
|
|
169
|
+
| `SOUL.md` | Your agent's identity, personality, and values |
|
|
170
|
+
| `JOB_PLANNING.md` | How your agent plans and breaks down jobs |
|
|
171
|
+
| `JOB_AGENT.md` | Instructions for executing jobs |
|
|
172
|
+
| `CRONS.json` | Scheduled recurring jobs |
|
|
173
|
+
| `TRIGGERS.json` | Webhook trigger definitions |
|
|
174
|
+
| `HEARTBEAT.md` | Tasks for the periodic heartbeat cron |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Updating
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
npx gigaclaw upgrade # Latest stable
|
|
182
|
+
npx gigaclaw upgrade @beta # Latest beta
|
|
183
|
+
npx gigaclaw upgrade 1.2.72 # Specific version
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Deployment
|
|
189
|
+
|
|
190
|
+
Giga Bot runs on any Linux server with Docker. Recommended:
|
|
191
|
+
|
|
192
|
+
| Provider | Spec | Monthly Cost |
|
|
193
|
+
|---|---|---|
|
|
194
|
+
| Hetzner CX22 | 2 vCPU, 4 GB RAM | ~€4 |
|
|
195
|
+
| DigitalOcean Droplet | 2 vCPU, 4 GB RAM | ~$24 |
|
|
196
|
+
| AWS EC2 t3.small | 2 vCPU, 2 GB RAM | ~$15 |
|
|
197
|
+
| Your own hardware | Any Linux machine | ₹0 |
|
|
198
|
+
|
|
199
|
+
For local development, use [ngrok](https://ngrok.com) to expose your machine:
|
|
200
|
+
```bash
|
|
201
|
+
ngrok http 80
|
|
202
|
+
# Then update APP_URL: npx gigaclaw set-var APP_URL https://your-url.ngrok.io
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Privacy & Legal
|
|
208
|
+
|
|
209
|
+
- [Privacy Policy](https://www.gignaati.com/privacy-policy)
|
|
210
|
+
- [Terms of Service](https://www.gignaati.com/terms-of-service)
|
|
211
|
+
- [Security Policy](SECURITY.md)
|
|
212
|
+
- [License](LICENSE) — MIT
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Contributing
|
|
217
|
+
|
|
218
|
+
Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) before submitting a pull request.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Support
|
|
223
|
+
|
|
224
|
+
- **GitHub Issues:** [github.com/gignaati/gigaclaw/issues](https://github.com/gignaati/gigaclaw/issues)
|
|
225
|
+
- **Discussions:** [github.com/gignaati/gigaclaw/discussions](https://github.com/gignaati/gigaclaw/discussions)
|
|
226
|
+
- **Email:** support@gignaati.com
|
|
227
|
+
- **Website:** [www.gignaati.com](https://www.gignaati.com)
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
<div align="center">
|
|
232
|
+
|
|
233
|
+
**Built with care by [Gignaati](https://www.gignaati.com) — India's Edge AI Ecosystem**
|
|
234
|
+
|
|
235
|
+
[Privacy Policy](https://www.gignaati.com/privacy-policy) · [Terms of Service](https://www.gignaati.com/terms-of-service) · [Security](SECURITY.md)
|
|
236
|
+
|
|
237
|
+
</div>
|
package/api/CLAUDE.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# /api — External API Routes
|
|
2
|
+
|
|
3
|
+
This directory contains the route handlers for all `/api/*` endpoints. These routes are for **external callers only** — GitHub Actions, Telegram, cURL, third-party webhooks.
|
|
4
|
+
|
|
5
|
+
## Auth
|
|
6
|
+
|
|
7
|
+
All routes (except `/telegram/webhook` and `/github/webhook`, which use their own webhook secrets) require a valid API key passed via the `x-api-key` header. API keys are stored in the SQLite database and managed through the admin UI — they are NOT environment variables.
|
|
8
|
+
|
|
9
|
+
Auth flow: `x-api-key` header -> `verifyApiKey()` -> database lookup (hashed, timing-safe comparison).
|
|
10
|
+
|
|
11
|
+
## Do NOT use these routes for browser UI
|
|
12
|
+
|
|
13
|
+
Browser-facing features must use **Server Actions** (`'use server'` functions) with `requireAuth()` session checks — never `/api` fetch calls. The only exception is chat streaming, which has its own dedicated route at `/stream/chat` with session auth.
|
|
14
|
+
|
|
15
|
+
| Caller | Mechanism | Auth |
|
|
16
|
+
|--------|-----------|------|
|
|
17
|
+
| External (cURL, GitHub Actions, Telegram) | `/api` route | `x-api-key` header |
|
|
18
|
+
| Browser UI (data/mutations) | Server Action | `requireAuth()` session |
|
|
19
|
+
| Browser UI (chat streaming) | `/stream/chat` | `auth()` session |
|
package/api/index.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { createHash, timingSafeEqual } from 'crypto';
|
|
2
|
+
import { createJob } from '../lib/tools/create-job.js';
|
|
3
|
+
import { setWebhook } from '../lib/tools/telegram.js';
|
|
4
|
+
import { getJobStatus, fetchJobLog } from '../lib/tools/github.js';
|
|
5
|
+
import { getTelegramAdapter } from '../lib/channels/index.js';
|
|
6
|
+
import { chat, summarizeJob } from '../lib/ai/index.js';
|
|
7
|
+
import { createNotification } from '../lib/db/notifications.js';
|
|
8
|
+
import { loadTriggers } from '../lib/triggers.js';
|
|
9
|
+
import { verifyApiKey } from '../lib/db/api-keys.js';
|
|
10
|
+
|
|
11
|
+
// Bot token from env, can be overridden by /telegram/register
|
|
12
|
+
let telegramBotToken = null;
|
|
13
|
+
|
|
14
|
+
// Cached trigger firing function (initialized on first request)
|
|
15
|
+
let _fireTriggers = null;
|
|
16
|
+
|
|
17
|
+
function getTelegramBotToken() {
|
|
18
|
+
if (!telegramBotToken) {
|
|
19
|
+
telegramBotToken = process.env.TELEGRAM_BOT_TOKEN || null;
|
|
20
|
+
}
|
|
21
|
+
return telegramBotToken;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getFireTriggers() {
|
|
25
|
+
if (!_fireTriggers) {
|
|
26
|
+
const result = loadTriggers();
|
|
27
|
+
_fireTriggers = result.fireTriggers;
|
|
28
|
+
}
|
|
29
|
+
return _fireTriggers;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Routes that have their own authentication
|
|
33
|
+
const PUBLIC_ROUTES = ['/telegram/webhook', '/github/webhook', '/ping'];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Timing-safe string comparison.
|
|
37
|
+
* @param {string} a
|
|
38
|
+
* @param {string} b
|
|
39
|
+
* @returns {boolean}
|
|
40
|
+
*/
|
|
41
|
+
function safeCompare(a, b) {
|
|
42
|
+
if (!a || !b) return false;
|
|
43
|
+
const bufA = Buffer.from(a);
|
|
44
|
+
const bufB = Buffer.from(b);
|
|
45
|
+
if (bufA.length !== bufB.length) return false;
|
|
46
|
+
return timingSafeEqual(bufA, bufB);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Centralized auth gate for all API routes.
|
|
51
|
+
* Public routes pass through; everything else requires a valid API key from the database.
|
|
52
|
+
* @param {string} routePath - The route path
|
|
53
|
+
* @param {Request} request - The incoming request
|
|
54
|
+
* @returns {Response|null} - Error response or null if authorized
|
|
55
|
+
*/
|
|
56
|
+
function checkAuth(routePath, request) {
|
|
57
|
+
if (PUBLIC_ROUTES.includes(routePath)) return null;
|
|
58
|
+
|
|
59
|
+
const apiKey = request.headers.get('x-api-key');
|
|
60
|
+
if (!apiKey) {
|
|
61
|
+
return Response.json({ error: 'Unauthorized' }, { status: 401 });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const record = verifyApiKey(apiKey);
|
|
65
|
+
if (!record) {
|
|
66
|
+
return Response.json({ error: 'Unauthorized' }, { status: 401 });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Extract job ID from branch name (e.g., "job/abc123" -> "abc123")
|
|
74
|
+
*/
|
|
75
|
+
function extractJobId(branchName) {
|
|
76
|
+
if (!branchName || !branchName.startsWith('job/')) return null;
|
|
77
|
+
return branchName.slice(4);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
81
|
+
// Route handlers
|
|
82
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
async function handleWebhook(request) {
|
|
85
|
+
const body = await request.json();
|
|
86
|
+
const { job } = body;
|
|
87
|
+
if (!job) return Response.json({ error: 'Missing job field' }, { status: 400 });
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const result = await createJob(job);
|
|
91
|
+
return Response.json(result);
|
|
92
|
+
} catch (err) {
|
|
93
|
+
console.error(err);
|
|
94
|
+
return Response.json({ error: 'Failed to create job' }, { status: 500 });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function handleTelegramRegister(request) {
|
|
99
|
+
const body = await request.json();
|
|
100
|
+
const { bot_token, webhook_url } = body;
|
|
101
|
+
if (!bot_token || !webhook_url) {
|
|
102
|
+
return Response.json({ error: 'Missing bot_token or webhook_url' }, { status: 400 });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
const result = await setWebhook(bot_token, webhook_url, process.env.TELEGRAM_WEBHOOK_SECRET);
|
|
107
|
+
telegramBotToken = bot_token;
|
|
108
|
+
return Response.json({ success: true, result });
|
|
109
|
+
} catch (err) {
|
|
110
|
+
console.error(err);
|
|
111
|
+
return Response.json({ error: 'Failed to register webhook' }, { status: 500 });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function handleTelegramWebhook(request) {
|
|
116
|
+
const botToken = getTelegramBotToken();
|
|
117
|
+
if (!botToken) return Response.json({ ok: true });
|
|
118
|
+
|
|
119
|
+
const adapter = getTelegramAdapter(botToken);
|
|
120
|
+
const normalized = await adapter.receive(request);
|
|
121
|
+
if (!normalized) return Response.json({ ok: true });
|
|
122
|
+
|
|
123
|
+
// Process message asynchronously (don't block the webhook response)
|
|
124
|
+
processChannelMessage(adapter, normalized).catch((err) => {
|
|
125
|
+
console.error('Failed to process message:', err);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
return Response.json({ ok: true });
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Process a normalized message through the AI layer with channel UX.
|
|
133
|
+
* Message persistence is handled centrally by the AI layer.
|
|
134
|
+
*/
|
|
135
|
+
async function processChannelMessage(adapter, normalized) {
|
|
136
|
+
await adapter.acknowledge(normalized.metadata);
|
|
137
|
+
const stopIndicator = adapter.startProcessingIndicator(normalized.metadata);
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
const response = await chat(
|
|
141
|
+
normalized.threadId,
|
|
142
|
+
normalized.text,
|
|
143
|
+
normalized.attachments,
|
|
144
|
+
{ userId: 'telegram', chatTitle: 'Telegram' }
|
|
145
|
+
);
|
|
146
|
+
await adapter.sendResponse(normalized.threadId, response, normalized.metadata);
|
|
147
|
+
} catch (err) {
|
|
148
|
+
console.error('Failed to process message with AI:', err);
|
|
149
|
+
await adapter
|
|
150
|
+
.sendResponse(
|
|
151
|
+
normalized.threadId,
|
|
152
|
+
'Sorry, I encountered an error processing your message.',
|
|
153
|
+
normalized.metadata
|
|
154
|
+
)
|
|
155
|
+
.catch(() => {});
|
|
156
|
+
} finally {
|
|
157
|
+
stopIndicator();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function handleGithubWebhook(request) {
|
|
162
|
+
const { GH_WEBHOOK_SECRET } = process.env;
|
|
163
|
+
|
|
164
|
+
// Validate webhook secret (timing-safe, required)
|
|
165
|
+
if (!GH_WEBHOOK_SECRET || !safeCompare(request.headers.get('x-github-webhook-secret-token'), GH_WEBHOOK_SECRET)) {
|
|
166
|
+
return Response.json({ error: 'Unauthorized' }, { status: 401 });
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const payload = await request.json();
|
|
170
|
+
const jobId = payload.job_id || extractJobId(payload.branch);
|
|
171
|
+
if (!jobId) return Response.json({ ok: true, skipped: true, reason: 'not a job' });
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
// Fetch log from repo via API (no longer sent in payload)
|
|
175
|
+
let log = payload.log || '';
|
|
176
|
+
if (!log) {
|
|
177
|
+
log = await fetchJobLog(jobId, payload.commit_sha);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const results = {
|
|
181
|
+
job: payload.job || '',
|
|
182
|
+
pr_url: payload.pr_url || payload.run_url || '',
|
|
183
|
+
run_url: payload.run_url || '',
|
|
184
|
+
status: payload.status || '',
|
|
185
|
+
merge_result: payload.merge_result || '',
|
|
186
|
+
log,
|
|
187
|
+
changed_files: payload.changed_files || [],
|
|
188
|
+
commit_message: payload.commit_message || '',
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const message = await summarizeJob(results);
|
|
192
|
+
await createNotification(message, payload);
|
|
193
|
+
|
|
194
|
+
console.log(`Notification saved for job ${jobId.slice(0, 8)}`);
|
|
195
|
+
|
|
196
|
+
return Response.json({ ok: true, notified: true });
|
|
197
|
+
} catch (err) {
|
|
198
|
+
console.error('Failed to process GitHub webhook:', err);
|
|
199
|
+
return Response.json({ error: 'Failed to process webhook' }, { status: 500 });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async function handleJobStatus(request) {
|
|
204
|
+
try {
|
|
205
|
+
const url = new URL(request.url);
|
|
206
|
+
const jobId = url.searchParams.get('job_id');
|
|
207
|
+
const result = await getJobStatus(jobId);
|
|
208
|
+
return Response.json(result);
|
|
209
|
+
} catch (err) {
|
|
210
|
+
console.error('Failed to get job status:', err);
|
|
211
|
+
return Response.json({ error: 'Failed to get job status' }, { status: 500 });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
216
|
+
// Next.js Route Handlers (catch-all)
|
|
217
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
218
|
+
|
|
219
|
+
async function POST(request) {
|
|
220
|
+
const url = new URL(request.url);
|
|
221
|
+
const routePath = url.pathname.replace(/^\/api/, '');
|
|
222
|
+
|
|
223
|
+
// Auth check
|
|
224
|
+
const authError = checkAuth(routePath, request);
|
|
225
|
+
if (authError) return authError;
|
|
226
|
+
|
|
227
|
+
// Fire triggers (non-blocking)
|
|
228
|
+
try {
|
|
229
|
+
const fireTriggers = getFireTriggers();
|
|
230
|
+
// Clone request to read body for triggers without consuming it for the handler
|
|
231
|
+
const clonedRequest = request.clone();
|
|
232
|
+
const body = await clonedRequest.json().catch(() => ({}));
|
|
233
|
+
const query = Object.fromEntries(url.searchParams);
|
|
234
|
+
const headers = Object.fromEntries(request.headers);
|
|
235
|
+
fireTriggers(routePath, body, query, headers);
|
|
236
|
+
} catch (e) {
|
|
237
|
+
// Trigger errors are non-fatal
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Route to handler
|
|
241
|
+
switch (routePath) {
|
|
242
|
+
case '/create-job': return handleWebhook(request);
|
|
243
|
+
case '/telegram/webhook': return handleTelegramWebhook(request);
|
|
244
|
+
case '/telegram/register': return handleTelegramRegister(request);
|
|
245
|
+
case '/github/webhook': return handleGithubWebhook(request);
|
|
246
|
+
default: return Response.json({ error: 'Not found' }, { status: 404 });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
async function GET(request) {
|
|
251
|
+
const url = new URL(request.url);
|
|
252
|
+
const routePath = url.pathname.replace(/^\/api/, '');
|
|
253
|
+
|
|
254
|
+
// Auth check
|
|
255
|
+
const authError = checkAuth(routePath, request);
|
|
256
|
+
if (authError) return authError;
|
|
257
|
+
|
|
258
|
+
switch (routePath) {
|
|
259
|
+
case '/ping': return Response.json({ message: 'Pong!' });
|
|
260
|
+
case '/jobs/status': return handleJobStatus(request);
|
|
261
|
+
default: return Response.json({ error: 'Not found' }, { status: 404 });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export { GET, POST };
|