freeturtle 0.1.14 → 0.1.16
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 +79 -59
- package/dist/bin/freeturtle.js +10 -2
- package/dist/bin/freeturtle.js.map +1 -1
- package/dist/src/cli/connect-gmail.d.ts +6 -0
- package/dist/src/cli/connect-gmail.js +128 -0
- package/dist/src/cli/connect-gmail.js.map +1 -0
- package/dist/src/cli/connection-tests.d.ts +4 -0
- package/dist/src/cli/connection-tests.js +10 -0
- package/dist/src/cli/connection-tests.js.map +1 -1
- package/dist/src/cli/init.js +51 -2
- package/dist/src/cli/init.js.map +1 -1
- package/dist/src/cli/webhooks.js +3 -0
- package/dist/src/cli/webhooks.js.map +1 -1
- package/dist/src/daemon.js +37 -4
- package/dist/src/daemon.js.map +1 -1
- package/dist/src/heartbeat.js +3 -1
- package/dist/src/heartbeat.js.map +1 -1
- package/dist/src/modules/gmail/client.d.ts +62 -0
- package/dist/src/modules/gmail/client.js +144 -0
- package/dist/src/modules/gmail/client.js.map +1 -0
- package/dist/src/modules/gmail/index.d.ts +9 -0
- package/dist/src/modules/gmail/index.js +45 -0
- package/dist/src/modules/gmail/index.js.map +1 -0
- package/dist/src/modules/gmail/tools.d.ts +2 -0
- package/dist/src/modules/gmail/tools.js +70 -0
- package/dist/src/modules/gmail/tools.js.map +1 -0
- package/dist/src/modules/loader.js +6 -1
- package/dist/src/modules/loader.js.map +1 -1
- package/dist/src/modules/onchain/chains.d.ts +12 -0
- package/dist/src/modules/onchain/chains.js +83 -0
- package/dist/src/modules/onchain/chains.js.map +1 -0
- package/dist/src/modules/onchain/client.js +1 -1
- package/dist/src/modules/onchain/client.js.map +1 -1
- package/dist/src/modules/onchain/index.d.ts +4 -0
- package/dist/src/modules/onchain/index.js +32 -4
- package/dist/src/modules/onchain/index.js.map +1 -1
- package/dist/src/modules/onchain/portfolio.d.ts +3 -0
- package/dist/src/modules/onchain/portfolio.js +180 -0
- package/dist/src/modules/onchain/portfolio.js.map +1 -0
- package/dist/src/modules/onchain/taskboard.d.ts +3 -0
- package/dist/src/modules/onchain/taskboard.js +532 -0
- package/dist/src/modules/onchain/taskboard.js.map +1 -0
- package/dist/src/modules/onchain/tools.js +1 -1
- package/dist/src/modules/onchain/tools.js.map +1 -1
- package/dist/src/oauth/google.d.ts +23 -0
- package/dist/src/oauth/google.js +110 -0
- package/dist/src/oauth/google.js.map +1 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -2,15 +2,58 @@
|
|
|
2
2
|
|
|
3
3
|
An open-source framework for deploying autonomous AI CEOs that run onchain businesses.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
### 1. Set Up a Server
|
|
8
|
+
|
|
9
|
+
You need a Linux server that runs 24/7. We recommend [Oracle Cloud's free ARM instance](docs/oracle-cloud-setup.md) — 2 CPUs, 12 GB RAM, always free.
|
|
10
|
+
|
|
11
|
+
> **New to servers?** The [Oracle Cloud setup guide](docs/oracle-cloud-setup.md) walks through everything from account creation to SSH. Paste it into an AI chat (ChatGPT, Claude, etc.) and ask it to guide you step by step.
|
|
12
|
+
|
|
13
|
+
### 2. Create Accounts for Your CEO
|
|
14
|
+
|
|
15
|
+
Before running init, create a separate identity for your CEO:
|
|
16
|
+
|
|
17
|
+
- **Google account** — use it to sign up for everything below
|
|
18
|
+
- **Farcaster** — the account your CEO will post from
|
|
19
|
+
- **Neynar** — API access for Farcaster (sign up at [dev.neynar.com](https://dev.neynar.com))
|
|
20
|
+
- **GitHub** (optional) — if your CEO will manage repos, give it its own account
|
|
21
|
+
|
|
22
|
+
The CEO is effectively a team member who needs its own accounts.
|
|
23
|
+
|
|
24
|
+
### 3. Install and Run
|
|
6
25
|
|
|
7
26
|
```bash
|
|
8
|
-
pnpm
|
|
27
|
+
# Install Node.js and pnpm (if not already installed)
|
|
28
|
+
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
|
|
29
|
+
sudo apt-get install -y nodejs
|
|
30
|
+
sudo npm install -g pnpm
|
|
31
|
+
|
|
32
|
+
# Install FreeTurtle
|
|
33
|
+
sudo pnpm install -g freeturtle
|
|
34
|
+
|
|
35
|
+
# Set up your CEO (interactive wizard)
|
|
9
36
|
freeturtle init
|
|
37
|
+
|
|
38
|
+
# Start the daemon
|
|
10
39
|
freeturtle start
|
|
40
|
+
|
|
41
|
+
# Keep it running after reboot (Linux)
|
|
42
|
+
freeturtle install-service
|
|
11
43
|
```
|
|
12
44
|
|
|
13
|
-
The setup wizard walks you through
|
|
45
|
+
The setup wizard walks you through naming your AI CEO, picking an LLM provider, connecting Farcaster, Telegram, GitHub, and more.
|
|
46
|
+
|
|
47
|
+
### 4. Set Up Webhooks (optional)
|
|
48
|
+
|
|
49
|
+
If you want your CEO to auto-respond to Farcaster mentions and replies, you need webhooks. This requires HTTPS, which means a domain and a reverse proxy.
|
|
50
|
+
|
|
51
|
+
The quickest path:
|
|
52
|
+
1. Get a free subdomain at [duckdns.org](https://www.duckdns.org)
|
|
53
|
+
2. Install Caddy (`sudo apt install -y caddy`) — it handles HTTPS automatically
|
|
54
|
+
3. Run `freeturtle webhooks` to register with Neynar
|
|
55
|
+
|
|
56
|
+
See the [Oracle Cloud setup guide](docs/oracle-cloud-setup.md#setting-up-webhooks-farcaster-mentionsreplies) for full instructions.
|
|
14
57
|
|
|
15
58
|
## What It Does
|
|
16
59
|
|
|
@@ -35,7 +78,7 @@ FreeTurtle is a Node.js daemon that mostly sleeps and wakes up when:
|
|
|
35
78
|
3. The **founder sends a message** via Terminal or Telegram
|
|
36
79
|
4. A **webhook event** arrives (e.g. someone mentions the CEO on Farcaster)
|
|
37
80
|
|
|
38
|
-
All
|
|
81
|
+
All four route to the same **task runner**, which:
|
|
39
82
|
|
|
40
83
|
1. Loads `soul.md` (the CEO's identity and voice)
|
|
41
84
|
2. Loads recent memory (posting log, post queue)
|
|
@@ -80,6 +123,24 @@ All three route to the same **task runner**, which:
|
|
|
80
123
|
└──────────────────────────────────────────────────────┘
|
|
81
124
|
```
|
|
82
125
|
|
|
126
|
+
## CLI Commands
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
freeturtle init # Set up a new AI CEO
|
|
130
|
+
freeturtle start # Start the daemon
|
|
131
|
+
freeturtle start --chat # Start with interactive terminal chat
|
|
132
|
+
freeturtle status # Show daemon status
|
|
133
|
+
freeturtle send "message" # Send a message to the running CEO
|
|
134
|
+
freeturtle setup # Reconfigure LLM provider
|
|
135
|
+
freeturtle connect farcaster # Set up Farcaster signer
|
|
136
|
+
freeturtle webhooks # Set up Neynar webhooks (mentions, replies, watched users/channels)
|
|
137
|
+
freeturtle approvals # List pending approval requests
|
|
138
|
+
freeturtle approve <id> # Approve a pending action
|
|
139
|
+
freeturtle reject <id> # Reject a pending action
|
|
140
|
+
freeturtle update # Update to the latest version
|
|
141
|
+
freeturtle install-service # Install as a systemd service (Linux)
|
|
142
|
+
```
|
|
143
|
+
|
|
83
144
|
## Modules
|
|
84
145
|
|
|
85
146
|
### Workspace (always loaded)
|
|
@@ -156,7 +217,7 @@ Read smart contracts, balances, and transactions on Base.
|
|
|
156
217
|
| `get_balance` | Get ETH balance of an address |
|
|
157
218
|
| `get_transactions` | Get recent transactions (requires BaseScan key) |
|
|
158
219
|
|
|
159
|
-
**Env:** `RPC_URL`, `
|
|
220
|
+
**Env:** `RPC_URL`, `BLOCK_EXPLORER_API_KEY` (optional)
|
|
160
221
|
|
|
161
222
|
## Configuration
|
|
162
223
|
|
|
@@ -189,7 +250,7 @@ Controls the daemon. Markdown format:
|
|
|
189
250
|
```markdown
|
|
190
251
|
## LLM
|
|
191
252
|
- provider: claude_api
|
|
192
|
-
- model: claude-sonnet-4-5
|
|
253
|
+
- model: claude-sonnet-4-5
|
|
193
254
|
- max_tokens: 4096
|
|
194
255
|
|
|
195
256
|
## Cron
|
|
@@ -236,46 +297,19 @@ DATABASE_URL=postgres://...
|
|
|
236
297
|
RPC_URL=https://mainnet.base.org
|
|
237
298
|
```
|
|
238
299
|
|
|
239
|
-
##
|
|
240
|
-
|
|
241
|
-
```bash
|
|
242
|
-
freeturtle init # Set up a new AI CEO
|
|
243
|
-
freeturtle start # Start the daemon
|
|
244
|
-
freeturtle start --chat # Start with interactive terminal chat
|
|
245
|
-
freeturtle status # Show daemon status
|
|
246
|
-
freeturtle send "message" # Send a message to the running CEO
|
|
247
|
-
freeturtle setup # Reconfigure LLM provider
|
|
248
|
-
freeturtle connect farcaster # Set up Farcaster signer
|
|
249
|
-
freeturtle webhooks # Set up Neynar webhooks (mentions, replies, watched users/channels)
|
|
250
|
-
freeturtle approvals # List pending approval requests
|
|
251
|
-
freeturtle approve <id> # Approve a pending action
|
|
252
|
-
freeturtle reject <id> # Reject a pending action
|
|
253
|
-
freeturtle update # Update to the latest version
|
|
254
|
-
freeturtle install-service # Install as a systemd service (Linux)
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
## Hosting
|
|
258
|
-
|
|
259
|
-
We recommend [Oracle Cloud's free ARM instance](docs/oracle-cloud-setup.md) — 4 CPUs, 24 GB RAM, always free. The setup guide walks through account creation, instance setup, networking, and installing FreeTurtle as a system service.
|
|
260
|
-
|
|
261
|
-
```bash
|
|
262
|
-
# On your server
|
|
263
|
-
pnpm install -g freeturtle
|
|
264
|
-
freeturtle init
|
|
265
|
-
freeturtle start
|
|
266
|
-
freeturtle install-service # auto-restart on reboot
|
|
267
|
-
```
|
|
300
|
+
## Self-Modification
|
|
268
301
|
|
|
269
|
-
|
|
302
|
+
FreeTurtle CEOs can modify their own behavior at runtime. Everything that defines the CEO — identity, voice, goals, config, memory — is a file in the workspace, and the CEO has tools to read and write those files.
|
|
270
303
|
|
|
271
|
-
|
|
304
|
+
Examples of what you can tell your CEO:
|
|
272
305
|
|
|
273
|
-
-
|
|
274
|
-
-
|
|
275
|
-
-
|
|
276
|
-
-
|
|
306
|
+
- **"Be more direct and honest"** — CEO edits the Voice section of `soul.md` (requires your approval)
|
|
307
|
+
- **"Remember that @rish posts interesting stuff"** — CEO writes a note to `workspace/memory/notes.md`
|
|
308
|
+
- **"Change posting to every 4 hours"** — CEO edits the cron schedule in `config.md` (requires approval, takes effect on restart)
|
|
309
|
+
- **"Add a goal about growing the Discord"** — CEO edits the Goals section of `soul.md` (requires approval)
|
|
310
|
+
- **"Write a brief on this week's engagement"** — CEO writes to `workspace/strategy/`
|
|
277
311
|
|
|
278
|
-
|
|
312
|
+
Changes to core files (`soul.md`, `config.md`, `.env`) always require founder approval. Memory and notes writes go through freely.
|
|
279
313
|
|
|
280
314
|
## Policy & Approvals
|
|
281
315
|
|
|
@@ -305,9 +339,9 @@ Add a `## Policy` section to `config.md`:
|
|
|
305
339
|
```
|
|
306
340
|
|
|
307
341
|
**Allowlist rules:**
|
|
308
|
-
- Not set
|
|
309
|
-
- Empty list
|
|
310
|
-
- Populated list
|
|
342
|
+
- Not set — allow all (no restriction)
|
|
343
|
+
- Empty list — deny everything
|
|
344
|
+
- Populated list — only allow listed values
|
|
311
345
|
|
|
312
346
|
### Approval Flow
|
|
313
347
|
|
|
@@ -392,20 +426,6 @@ Your `.env` file contains API keys and tokens. FreeTurtle automatically sets it
|
|
|
392
426
|
|
|
393
427
|
Your cloud provider (Oracle, AWS, GCP) has full access to the underlying infrastructure — they can technically read any file on your VM. This is true of all cloud computing and is covered by their terms of service. For most use cases this is fine. If this is unacceptable for your threat model, run FreeTurtle on hardware you physically control.
|
|
394
428
|
|
|
395
|
-
## Self-Modification
|
|
396
|
-
|
|
397
|
-
FreeTurtle CEOs can modify their own behavior at runtime. Everything that defines the CEO — identity, voice, goals, config, memory — is a file in the workspace, and the CEO has tools to read and write those files.
|
|
398
|
-
|
|
399
|
-
Examples of what you can tell your CEO:
|
|
400
|
-
|
|
401
|
-
- **"Be more direct and honest"** → CEO edits the Voice section of `soul.md` (requires your approval)
|
|
402
|
-
- **"Remember that @rish posts interesting stuff"** → CEO writes a note to `workspace/memory/notes.md`
|
|
403
|
-
- **"Change posting to every 4 hours"** → CEO edits the cron schedule in `config.md` (requires approval, takes effect on restart)
|
|
404
|
-
- **"Add a goal about growing the Discord"** → CEO edits the Goals section of `soul.md` (requires approval)
|
|
405
|
-
- **"Write a brief on this week's engagement"** → CEO writes to `workspace/strategy/`
|
|
406
|
-
|
|
407
|
-
Changes to core files (`soul.md`, `config.md`, `.env`) always require founder approval. Memory and notes writes go through freely.
|
|
408
|
-
|
|
409
429
|
## The Two-Turtle Vision (v0.2)
|
|
410
430
|
|
|
411
431
|
The current v0.1 is a single-process CEO. v0.2 will split it into two:
|
package/dist/bin/freeturtle.js
CHANGED
|
@@ -15,14 +15,14 @@ const program = new Command();
|
|
|
15
15
|
program
|
|
16
16
|
.name("freeturtle")
|
|
17
17
|
.description("An open-source framework for deploying autonomous AI CEOs that run onchain businesses.")
|
|
18
|
-
.version("0.1.
|
|
18
|
+
.version("0.1.15");
|
|
19
19
|
program
|
|
20
20
|
.command("hello")
|
|
21
21
|
.description("Verify the CLI is working")
|
|
22
22
|
.action(() => {
|
|
23
23
|
console.log(" \x1b[38;2;94;255;164m _____ ____\x1b[0m");
|
|
24
24
|
console.log(" \x1b[38;2;94;255;164m/ \\ | o |\x1b[0m");
|
|
25
|
-
console.log(" \x1b[38;2;94;255;164m| |/ ___\\|\x1b[0m FreeTurtle v0.1.
|
|
25
|
+
console.log(" \x1b[38;2;94;255;164m| |/ ___\\|\x1b[0m FreeTurtle v0.1.15");
|
|
26
26
|
console.log(" \x1b[38;2;94;255;164m|_________/\x1b[0m");
|
|
27
27
|
console.log(" \x1b[38;2;94;255;164m|_|_| |_|_|\x1b[0m");
|
|
28
28
|
});
|
|
@@ -125,6 +125,14 @@ connect
|
|
|
125
125
|
const { connectFarcaster } = await import("../src/cli/connect-farcaster.js");
|
|
126
126
|
await connectFarcaster(opts.dir);
|
|
127
127
|
});
|
|
128
|
+
connect
|
|
129
|
+
.command("gmail")
|
|
130
|
+
.description("Connect Gmail for reading and sending emails")
|
|
131
|
+
.option("--dir <path>", "Workspace directory", DEFAULT_DIR)
|
|
132
|
+
.action(async (opts) => {
|
|
133
|
+
const { connectGmail } = await import("../src/cli/connect-gmail.js");
|
|
134
|
+
await connectGmail(opts.dir);
|
|
135
|
+
});
|
|
128
136
|
program
|
|
129
137
|
.command("webhooks")
|
|
130
138
|
.description("Set up Neynar webhooks for Farcaster mentions")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"freeturtle.js","sourceRoot":"","sources":["../../bin/freeturtle.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"freeturtle.js","sourceRoot":"","sources":["../../bin/freeturtle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import { readFile, writeFile, chmod, mkdir } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { runGoogleOAuthFlow, createGoogleOAuth2Client, } from "../oauth/google.js";
|
|
5
|
+
import { GmailClient } from "../modules/gmail/client.js";
|
|
6
|
+
export async function connectGmail(dir) {
|
|
7
|
+
p.intro("Gmail Setup");
|
|
8
|
+
p.note([
|
|
9
|
+
"We recommend creating a dedicated Google account for your",
|
|
10
|
+
"CEO so emails come from its own identity. You can use this",
|
|
11
|
+
"same Google account to create a GitHub account for the CEO.",
|
|
12
|
+
].join("\n"), "Recommendation");
|
|
13
|
+
const email = await p.text({
|
|
14
|
+
message: "Gmail address for the CEO",
|
|
15
|
+
placeholder: "ceo@gmail.com",
|
|
16
|
+
validate: (v) => {
|
|
17
|
+
if (!v?.trim())
|
|
18
|
+
return "Required";
|
|
19
|
+
if (!v.includes("@"))
|
|
20
|
+
return "Must be a valid email address";
|
|
21
|
+
return undefined;
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
if (p.isCancel(email)) {
|
|
25
|
+
p.cancel("Cancelled.");
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
p.note([
|
|
29
|
+
"To connect Gmail, you need a Google Cloud OAuth client:",
|
|
30
|
+
"",
|
|
31
|
+
"1. Go to console.cloud.google.com/apis/credentials",
|
|
32
|
+
"2. Create a project (or use an existing one)",
|
|
33
|
+
"3. Enable the Gmail API:",
|
|
34
|
+
" APIs & Services > Library > search 'Gmail API' > Enable",
|
|
35
|
+
"4. Create OAuth 2.0 Client ID:",
|
|
36
|
+
" Credentials > Create Credentials > OAuth client ID",
|
|
37
|
+
" Application type: Desktop app",
|
|
38
|
+
"5. Copy the Client ID and Client Secret",
|
|
39
|
+
"",
|
|
40
|
+
"Tip: paste these instructions into an AI chat and ask it",
|
|
41
|
+
"to walk you through step by step.",
|
|
42
|
+
].join("\n"), "Google Cloud Setup");
|
|
43
|
+
const clientId = await p.text({
|
|
44
|
+
message: "OAuth Client ID",
|
|
45
|
+
validate: (v) => (v?.trim() ? undefined : "Required"),
|
|
46
|
+
});
|
|
47
|
+
if (p.isCancel(clientId)) {
|
|
48
|
+
p.cancel("Cancelled.");
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const clientSecret = await p.text({
|
|
52
|
+
message: "OAuth Client Secret",
|
|
53
|
+
validate: (v) => (v?.trim() ? undefined : "Required"),
|
|
54
|
+
});
|
|
55
|
+
if (p.isCancel(clientSecret)) {
|
|
56
|
+
p.cancel("Cancelled.");
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
p.note("A browser window will open for Gmail authorization.\nSign in with the CEO's Google account and grant access.", "OAuth Flow");
|
|
60
|
+
const s = p.spinner();
|
|
61
|
+
s.start("Waiting for browser authorization...");
|
|
62
|
+
let refreshToken;
|
|
63
|
+
try {
|
|
64
|
+
refreshToken = await runGoogleOAuthFlow(clientId.trim(), clientSecret.trim());
|
|
65
|
+
s.stop("Authorization successful!");
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
s.stop("Authorization failed");
|
|
69
|
+
p.log.error(`OAuth failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
// Test connection
|
|
73
|
+
s.start("Testing Gmail connection...");
|
|
74
|
+
try {
|
|
75
|
+
const auth = createGoogleOAuth2Client({
|
|
76
|
+
clientId: clientId.trim(),
|
|
77
|
+
clientSecret: clientSecret.trim(),
|
|
78
|
+
refreshToken,
|
|
79
|
+
});
|
|
80
|
+
const client = new GmailClient(auth);
|
|
81
|
+
const sendAs = await client.getSendAs();
|
|
82
|
+
const primary = sendAs.find((a) => a.isPrimary) || sendAs[0];
|
|
83
|
+
const displayName = primary?.displayName;
|
|
84
|
+
s.stop(displayName
|
|
85
|
+
? `Connected as ${displayName} (${primary?.email})`
|
|
86
|
+
: `Connected as ${primary?.email || email}`);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
s.stop("Connection test failed");
|
|
90
|
+
p.log.warn(`Could not verify Gmail access: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
91
|
+
p.log.warn("The credentials were saved — you can test later with: freeturtle status");
|
|
92
|
+
}
|
|
93
|
+
// Save to .env
|
|
94
|
+
const envPath = join(dir, ".env");
|
|
95
|
+
let envContent = "";
|
|
96
|
+
try {
|
|
97
|
+
envContent = await readFile(envPath, "utf-8");
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// No existing .env
|
|
101
|
+
}
|
|
102
|
+
const envVars = {
|
|
103
|
+
GOOGLE_CLIENT_ID: clientId.trim(),
|
|
104
|
+
GOOGLE_CLIENT_SECRET: clientSecret.trim(),
|
|
105
|
+
GOOGLE_GMAIL_REFRESH_TOKEN: refreshToken,
|
|
106
|
+
};
|
|
107
|
+
for (const [key, value] of Object.entries(envVars)) {
|
|
108
|
+
const regex = new RegExp(`^${key}=.*$`, "m");
|
|
109
|
+
if (regex.test(envContent)) {
|
|
110
|
+
envContent = envContent.replace(regex, `${key}=${value}`);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
envContent +=
|
|
114
|
+
`${envContent.endsWith("\n") || envContent === "" ? "" : "\n"}${key}=${value}\n`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
await mkdir(dirname(envPath), { recursive: true });
|
|
118
|
+
await writeFile(envPath, envContent, "utf-8");
|
|
119
|
+
await chmod(envPath, 0o600);
|
|
120
|
+
p.log.success("Gmail credentials saved to .env");
|
|
121
|
+
p.outro("Gmail connected!");
|
|
122
|
+
return {
|
|
123
|
+
clientId: clientId.trim(),
|
|
124
|
+
clientSecret: clientSecret.trim(),
|
|
125
|
+
email: email.trim(),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=connect-gmail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect-gmail.js","sourceRoot":"","sources":["../../../src/cli/connect-gmail.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,10 @@ export declare function testGitHub(token: string): Promise<void>;
|
|
|
10
10
|
* Test a Postgres connection URL by connecting and immediately disconnecting.
|
|
11
11
|
*/
|
|
12
12
|
export declare function testDatabase(url: string): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Test Gmail OAuth credentials by calling the profile endpoint.
|
|
15
|
+
*/
|
|
16
|
+
export declare function testGmail(clientId: string, clientSecret: string, refreshToken: string): Promise<void>;
|
|
13
17
|
/**
|
|
14
18
|
* Test an EVM RPC URL by calling eth_blockNumber.
|
|
15
19
|
*/
|
|
@@ -40,6 +40,16 @@ export async function testDatabase(url) {
|
|
|
40
40
|
await client.end().catch(() => { });
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Test Gmail OAuth credentials by calling the profile endpoint.
|
|
45
|
+
*/
|
|
46
|
+
export async function testGmail(clientId, clientSecret, refreshToken) {
|
|
47
|
+
const { createGoogleOAuth2Client } = await import("../oauth/google.js");
|
|
48
|
+
const { GmailClient } = await import("../modules/gmail/client.js");
|
|
49
|
+
const auth = createGoogleOAuth2Client({ clientId, clientSecret, refreshToken });
|
|
50
|
+
const client = new GmailClient(auth);
|
|
51
|
+
await client.getProfile();
|
|
52
|
+
}
|
|
43
53
|
/**
|
|
44
54
|
* Test an EVM RPC URL by calling eth_blockNumber.
|
|
45
55
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-tests.js","sourceRoot":"","sources":["../../../src/cli/connection-tests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa;IAC9C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,+BAA+B,KAAK,QAAQ,CAAC,CAAC;IACtE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA0C,CAAC;IACzE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAI,CAAC,WAAW,IAAI,SAAS,EAAE,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAa;IAC5C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,6BAA6B,EAAE;QACrD,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,KAAK,EAAE;YAChC,MAAM,EAAE,6BAA6B;SACtC;KACF,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAW;IAC5C,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC;IACxD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAc;IAC9C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;QAC9B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,iBAAiB;YACzB,MAAM,EAAE,EAAE;YACV,EAAE,EAAE,CAAC;SACN,CAAC;KACH,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,cAAc,GAAG,CAAC,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAoC,CAAC;IACnE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"connection-tests.js","sourceRoot":"","sources":["../../../src/cli/connection-tests.ts"],"names":[],"mappings":"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"}
|
package/dist/src/cli/init.js
CHANGED
|
@@ -5,6 +5,7 @@ import { createInterface } from "node:readline";
|
|
|
5
5
|
import { runSetup } from "../setup.js";
|
|
6
6
|
import { LLMClient } from "../llm.js";
|
|
7
7
|
import { connectFarcaster } from "./connect-farcaster.js";
|
|
8
|
+
import { connectGmail } from "./connect-gmail.js";
|
|
8
9
|
import { scanForSecrets, redactSecrets, condenseDocs } from "./intake.js";
|
|
9
10
|
import { testTelegram, testGitHub, testDatabase, testOnchain } from "./connection-tests.js";
|
|
10
11
|
import { createWebhook, channelToUrl } from "../webhooks/neynar.js";
|
|
@@ -15,7 +16,7 @@ const TURTLE = `
|
|
|
15
16
|
\x1b[38;2;94;255;164m|_________/\x1b[0m
|
|
16
17
|
\x1b[38;2;94;255;164m|_|_| |_|_|\x1b[0m
|
|
17
18
|
|
|
18
|
-
\x1b[1mFreeTurtle\x1b[0m \x1b[2mv0.1.
|
|
19
|
+
\x1b[1mFreeTurtle\x1b[0m \x1b[2mv0.1.15\x1b[0m
|
|
19
20
|
`;
|
|
20
21
|
const HATCH_FRAMES = [
|
|
21
22
|
" 🥚",
|
|
@@ -172,6 +173,11 @@ export async function runInit(dir) {
|
|
|
172
173
|
telegram: false,
|
|
173
174
|
telegramToken: "",
|
|
174
175
|
telegramOwner: "",
|
|
176
|
+
gmail: false,
|
|
177
|
+
googleClientId: "",
|
|
178
|
+
googleClientSecret: "",
|
|
179
|
+
googleRefreshToken: "",
|
|
180
|
+
gmailEmail: "",
|
|
175
181
|
github: false,
|
|
176
182
|
githubToken: "",
|
|
177
183
|
database: false,
|
|
@@ -379,6 +385,9 @@ export async function runInit(dir) {
|
|
|
379
385
|
" sudo systemctl restart caddy",
|
|
380
386
|
"",
|
|
381
387
|
"Your webhook URL will be: https://yourname.duckdns.org/webhook",
|
|
388
|
+
"",
|
|
389
|
+
"Tip: paste these instructions into an AI chat (ChatGPT, Claude,",
|
|
390
|
+
"etc.) and ask it to walk you through step by step.",
|
|
382
391
|
].join("\n"), "Webhooks");
|
|
383
392
|
const enable = await p.confirm({
|
|
384
393
|
message: "Set up webhooks?",
|
|
@@ -546,7 +555,37 @@ export async function runInit(dir) {
|
|
|
546
555
|
}
|
|
547
556
|
return true;
|
|
548
557
|
},
|
|
549
|
-
//
|
|
558
|
+
// Gmail
|
|
559
|
+
async () => {
|
|
560
|
+
const enable = await p.confirm({
|
|
561
|
+
message: "Connect Gmail? (read and send emails)",
|
|
562
|
+
initialValue: state.gmail,
|
|
563
|
+
});
|
|
564
|
+
if (p.isCancel(enable))
|
|
565
|
+
return false;
|
|
566
|
+
state.gmail = enable;
|
|
567
|
+
if (enable) {
|
|
568
|
+
const result = await connectGmail(dir);
|
|
569
|
+
if (result) {
|
|
570
|
+
state.googleClientId = result.clientId;
|
|
571
|
+
state.googleClientSecret = result.clientSecret;
|
|
572
|
+
state.gmailEmail = result.email;
|
|
573
|
+
// Read the refresh token that connectGmail saved to .env
|
|
574
|
+
try {
|
|
575
|
+
const envContent = await readFile(join(dir, ".env"), "utf-8");
|
|
576
|
+
const match = envContent.match(/^GOOGLE_GMAIL_REFRESH_TOKEN=(.+)$/m);
|
|
577
|
+
if (match)
|
|
578
|
+
state.googleRefreshToken = match[1];
|
|
579
|
+
}
|
|
580
|
+
catch { /* ignore */ }
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
state.gmail = false;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
return true;
|
|
587
|
+
},
|
|
588
|
+
// GitHub
|
|
550
589
|
async () => {
|
|
551
590
|
const enable = await p.confirm({
|
|
552
591
|
message: "Connect GitHub? (issues and file commits)",
|
|
@@ -768,6 +807,7 @@ export async function runInit(dir) {
|
|
|
768
807
|
const modules = [
|
|
769
808
|
state.farcaster && "Farcaster",
|
|
770
809
|
state.telegram && "Telegram",
|
|
810
|
+
state.gmail && "Gmail",
|
|
771
811
|
state.github && "GitHub",
|
|
772
812
|
state.database && "Database",
|
|
773
813
|
state.onchain && "Onchain",
|
|
@@ -861,6 +901,9 @@ ${state.founderName}.
|
|
|
861
901
|
"### database",
|
|
862
902
|
`- enabled: ${state.database}`,
|
|
863
903
|
"",
|
|
904
|
+
"### gmail",
|
|
905
|
+
`- enabled: ${state.gmail}`,
|
|
906
|
+
"",
|
|
864
907
|
"### github",
|
|
865
908
|
`- enabled: ${state.github}`,
|
|
866
909
|
"",
|
|
@@ -895,6 +938,12 @@ ${state.founderName}.
|
|
|
895
938
|
envLines.push(`TELEGRAM_BOT_TOKEN=${state.telegramToken}`);
|
|
896
939
|
if (state.telegramOwner)
|
|
897
940
|
envLines.push(`TELEGRAM_OWNER_ID=${state.telegramOwner}`);
|
|
941
|
+
if (state.googleClientId)
|
|
942
|
+
envLines.push(`GOOGLE_CLIENT_ID=${state.googleClientId}`);
|
|
943
|
+
if (state.googleClientSecret)
|
|
944
|
+
envLines.push(`GOOGLE_CLIENT_SECRET=${state.googleClientSecret}`);
|
|
945
|
+
if (state.googleRefreshToken)
|
|
946
|
+
envLines.push(`GOOGLE_GMAIL_REFRESH_TOKEN=${state.googleRefreshToken}`);
|
|
898
947
|
if (state.githubToken)
|
|
899
948
|
envLines.push(`GITHUB_TOKEN=${state.githubToken}`);
|
|
900
949
|
if (state.dbUrl)
|