@gracefultools/astrid-sdk 0.7.15 → 0.8.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/README.md +127 -341
- package/dist/channel/channel.d.ts +33 -0
- package/dist/channel/channel.d.ts.map +1 -0
- package/dist/channel/channel.js +90 -0
- package/dist/channel/channel.js.map +1 -0
- package/dist/channel/index.d.ts +13 -0
- package/dist/channel/index.d.ts.map +1 -0
- package/dist/channel/index.js +23 -0
- package/dist/channel/index.js.map +1 -0
- package/dist/channel/message-formatter.d.ts +14 -0
- package/dist/channel/message-formatter.d.ts.map +1 -0
- package/dist/channel/message-formatter.js +71 -0
- package/dist/channel/message-formatter.js.map +1 -0
- package/dist/channel/oauth-client.d.ts +15 -0
- package/dist/channel/oauth-client.d.ts.map +1 -0
- package/dist/channel/oauth-client.js +45 -0
- package/dist/channel/oauth-client.js.map +1 -0
- package/dist/channel/rest-client.d.ts +16 -0
- package/dist/channel/rest-client.d.ts.map +1 -0
- package/dist/channel/rest-client.js +66 -0
- package/dist/channel/rest-client.js.map +1 -0
- package/dist/channel/session-mapper.d.ts +14 -0
- package/dist/channel/session-mapper.d.ts.map +1 -0
- package/dist/channel/session-mapper.js +37 -0
- package/dist/channel/session-mapper.js.map +1 -0
- package/dist/channel/sse-client.d.ts +31 -0
- package/dist/channel/sse-client.d.ts.map +1 -0
- package/dist/channel/sse-client.js +171 -0
- package/dist/channel/sse-client.js.map +1 -0
- package/dist/channel/types.d.ts +65 -0
- package/dist/channel/types.d.ts.map +1 -0
- package/dist/channel/types.js +3 -0
- package/dist/channel/types.js.map +1 -0
- package/dist/config/agent-workflow.js +7 -7
- package/dist/index.d.ts +1 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -30
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/agent-config.d.ts.map +1 -1
- package/dist/utils/agent-config.js +14 -0
- package/dist/utils/agent-config.js.map +1 -1
- package/openclaw.plugin.json +25 -0
- package/package.json +66 -77
- package/templates/.astrid.config.json +60 -60
- package/templates/ASTRID.template.md +74 -74
- package/dist/bin/cli.d.ts +0 -14
- package/dist/bin/cli.d.ts.map +0 -1
- package/dist/bin/cli.js +0 -1610
- package/dist/bin/cli.js.map +0 -1
- package/dist/executors/claude.d.ts +0 -65
- package/dist/executors/claude.d.ts.map +0 -1
- package/dist/executors/claude.js +0 -838
- package/dist/executors/claude.js.map +0 -1
- package/dist/executors/gemini.d.ts +0 -23
- package/dist/executors/gemini.d.ts.map +0 -1
- package/dist/executors/gemini.js +0 -558
- package/dist/executors/gemini.js.map +0 -1
- package/dist/executors/openai.d.ts +0 -17
- package/dist/executors/openai.d.ts.map +0 -1
- package/dist/executors/openai.js +0 -614
- package/dist/executors/openai.js.map +0 -1
- package/dist/executors/shared/index.d.ts +0 -9
- package/dist/executors/shared/index.d.ts.map +0 -1
- package/dist/executors/shared/index.js +0 -21
- package/dist/executors/shared/index.js.map +0 -1
- package/dist/executors/shared/tool-executor.d.ts +0 -52
- package/dist/executors/shared/tool-executor.d.ts.map +0 -1
- package/dist/executors/shared/tool-executor.js +0 -262
- package/dist/executors/shared/tool-executor.js.map +0 -1
- package/dist/executors/shared/tool-schemas.d.ts +0 -61
- package/dist/executors/shared/tool-schemas.d.ts.map +0 -1
- package/dist/executors/shared/tool-schemas.js +0 -135
- package/dist/executors/shared/tool-schemas.js.map +0 -1
- package/dist/executors/terminal-base.d.ts +0 -207
- package/dist/executors/terminal-base.d.ts.map +0 -1
- package/dist/executors/terminal-base.js +0 -552
- package/dist/executors/terminal-base.js.map +0 -1
- package/dist/executors/terminal-claude.d.ts +0 -116
- package/dist/executors/terminal-claude.d.ts.map +0 -1
- package/dist/executors/terminal-claude.js +0 -700
- package/dist/executors/terminal-claude.js.map +0 -1
- package/dist/executors/terminal-executors.test.d.ts +0 -8
- package/dist/executors/terminal-executors.test.d.ts.map +0 -1
- package/dist/executors/terminal-executors.test.js +0 -469
- package/dist/executors/terminal-executors.test.js.map +0 -1
- package/dist/executors/terminal-gemini.d.ts +0 -50
- package/dist/executors/terminal-gemini.d.ts.map +0 -1
- package/dist/executors/terminal-gemini.js +0 -401
- package/dist/executors/terminal-gemini.js.map +0 -1
- package/dist/executors/terminal-openai.d.ts +0 -50
- package/dist/executors/terminal-openai.d.ts.map +0 -1
- package/dist/executors/terminal-openai.js +0 -405
- package/dist/executors/terminal-openai.js.map +0 -1
- package/dist/server/astrid-client.d.ts +0 -77
- package/dist/server/astrid-client.d.ts.map +0 -1
- package/dist/server/astrid-client.js +0 -125
- package/dist/server/astrid-client.js.map +0 -1
- package/dist/server/index.d.ts +0 -38
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js +0 -408
- package/dist/server/index.js.map +0 -1
- package/dist/server/repo-manager.d.ts +0 -41
- package/dist/server/repo-manager.d.ts.map +0 -1
- package/dist/server/repo-manager.js +0 -177
- package/dist/server/repo-manager.js.map +0 -1
- package/dist/server/session-manager.d.ts +0 -93
- package/dist/server/session-manager.d.ts.map +0 -1
- package/dist/server/session-manager.js +0 -217
- package/dist/server/session-manager.js.map +0 -1
- package/dist/server/webhook-signature.d.ts +0 -23
- package/dist/server/webhook-signature.d.ts.map +0 -1
- package/dist/server/webhook-signature.js +0 -74
- package/dist/server/webhook-signature.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,341 +1,127 @@
|
|
|
1
|
-
# @gracefultools/astrid-sdk
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
###
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
##
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
### Example: Full PR + Preview Workflow (Recommended)
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
# Git workflow
|
|
133
|
-
export ASTRID_AGENT_CREATE_BRANCH=true # Create feature branches
|
|
134
|
-
export ASTRID_AGENT_CREATE_PR=true # Create pull requests
|
|
135
|
-
export ASTRID_AGENT_RUN_TESTS=true # Run tests before commit
|
|
136
|
-
|
|
137
|
-
# Vercel preview deployment
|
|
138
|
-
export ASTRID_AGENT_VERCEL_DEPLOY=true # Deploy to Vercel
|
|
139
|
-
export ASTRID_AGENT_PREVIEW_DOMAIN=astrid.cc # Custom subdomain (for passkey support)
|
|
140
|
-
export VERCEL_TOKEN=your-vercel-token # Required for deployment
|
|
141
|
-
export GITHUB_TOKEN=your-github-token # Required for PR creation
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### Example: Direct to Main (No PR)
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
export ASTRID_AGENT_CREATE_BRANCH=false
|
|
148
|
-
export ASTRID_AGENT_CREATE_PR=false
|
|
149
|
-
export ASTRID_AGENT_VERCEL_DEPLOY=false
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
### Preview URL Configuration
|
|
153
|
-
|
|
154
|
-
When `ASTRID_AGENT_PREVIEW_DOMAIN` is set (e.g., `astrid.cc`), preview URLs are aliased to subdomains:
|
|
155
|
-
|
|
156
|
-
- Branch: `task/abc12345` → Preview URL: `https://task-abc12345.astrid.cc`
|
|
157
|
-
|
|
158
|
-
This is required for features that need same-origin (passkeys, Google OAuth cookies).
|
|
159
|
-
|
|
160
|
-
### Programmatic Configuration
|
|
161
|
-
|
|
162
|
-
```typescript
|
|
163
|
-
import {
|
|
164
|
-
getAgentWorkflowConfig,
|
|
165
|
-
validateWorkflowConfig,
|
|
166
|
-
logWorkflowConfig,
|
|
167
|
-
deployToVercel,
|
|
168
|
-
} from '@gracefultools/astrid-sdk'
|
|
169
|
-
|
|
170
|
-
// Get current config (reads from env)
|
|
171
|
-
const config = getAgentWorkflowConfig()
|
|
172
|
-
|
|
173
|
-
// Validate config
|
|
174
|
-
const { valid, errors, warnings } = validateWorkflowConfig()
|
|
175
|
-
if (!valid) {
|
|
176
|
-
console.error('Config errors:', errors)
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Log config for debugging
|
|
180
|
-
logWorkflowConfig()
|
|
181
|
-
|
|
182
|
-
// Deploy to Vercel manually
|
|
183
|
-
const result = await deployToVercel('task/abc12345', '/path/to/project')
|
|
184
|
-
console.log('Preview URL:', result.previewUrl)
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
## Supported AI Providers
|
|
188
|
-
|
|
189
|
-
The SDK automatically routes tasks to the correct provider based on the assignee email:
|
|
190
|
-
|
|
191
|
-
| Agent Email | Provider | Model |
|
|
192
|
-
|-------------|----------|-------|
|
|
193
|
-
| `claude@astrid.cc` | Claude | claude-sonnet-4 |
|
|
194
|
-
| `openai@astrid.cc` | OpenAI | gpt-4o |
|
|
195
|
-
| `gemini@astrid.cc` | Gemini | gemini-2.0-flash |
|
|
196
|
-
|
|
197
|
-
## Deployment Examples
|
|
198
|
-
|
|
199
|
-
### Fly.io (Webhook Mode)
|
|
200
|
-
|
|
201
|
-
```toml
|
|
202
|
-
# fly.toml
|
|
203
|
-
app = "astrid-agent"
|
|
204
|
-
primary_region = "iad"
|
|
205
|
-
|
|
206
|
-
[http_service]
|
|
207
|
-
internal_port = 3001
|
|
208
|
-
|
|
209
|
-
[env]
|
|
210
|
-
PORT = "3001"
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
```bash
|
|
214
|
-
fly secrets set ANTHROPIC_API_KEY=sk-ant-...
|
|
215
|
-
fly secrets set ASTRID_WEBHOOK_SECRET=...
|
|
216
|
-
fly deploy
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Docker (Webhook Mode)
|
|
220
|
-
|
|
221
|
-
```dockerfile
|
|
222
|
-
FROM node:20-slim
|
|
223
|
-
RUN npm install -g @gracefultools/astrid-sdk express
|
|
224
|
-
WORKDIR /app
|
|
225
|
-
EXPOSE 3001
|
|
226
|
-
CMD ["npx", "astrid-agent", "serve", "--port=3001"]
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### PM2 (Polling Mode)
|
|
230
|
-
|
|
231
|
-
```bash
|
|
232
|
-
# ecosystem.config.js
|
|
233
|
-
module.exports = {
|
|
234
|
-
apps: [{
|
|
235
|
-
name: 'astrid-agent',
|
|
236
|
-
script: 'npx',
|
|
237
|
-
args: 'astrid-agent',
|
|
238
|
-
env: {
|
|
239
|
-
ANTHROPIC_API_KEY: 'sk-ant-...',
|
|
240
|
-
ASTRID_OAUTH_CLIENT_ID: '...',
|
|
241
|
-
ASTRID_OAUTH_CLIENT_SECRET: '...',
|
|
242
|
-
ASTRID_OAUTH_LIST_ID: '...'
|
|
243
|
-
}
|
|
244
|
-
}]
|
|
245
|
-
}
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
## Programmatic Usage
|
|
249
|
-
|
|
250
|
-
```typescript
|
|
251
|
-
import {
|
|
252
|
-
planWithClaude,
|
|
253
|
-
executeWithClaude,
|
|
254
|
-
AstridOAuthClient,
|
|
255
|
-
} from '@gracefultools/astrid-sdk'
|
|
256
|
-
|
|
257
|
-
// Connect to Astrid
|
|
258
|
-
const client = new AstridOAuthClient({
|
|
259
|
-
clientId: process.env.ASTRID_OAUTH_CLIENT_ID,
|
|
260
|
-
clientSecret: process.env.ASTRID_OAUTH_CLIENT_SECRET,
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
// Get tasks
|
|
264
|
-
const tasks = await client.getTasks(listId)
|
|
265
|
-
|
|
266
|
-
// Plan implementation
|
|
267
|
-
const planResult = await planWithClaude(
|
|
268
|
-
task.title,
|
|
269
|
-
task.description,
|
|
270
|
-
{
|
|
271
|
-
repoPath: '/path/to/repo',
|
|
272
|
-
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
273
|
-
maxBudgetUsd: 5.0,
|
|
274
|
-
logger: console.log,
|
|
275
|
-
onProgress: (msg) => console.log(msg),
|
|
276
|
-
}
|
|
277
|
-
)
|
|
278
|
-
|
|
279
|
-
// Execute the plan
|
|
280
|
-
if (planResult.success && planResult.plan) {
|
|
281
|
-
const execResult = await executeWithClaude(
|
|
282
|
-
planResult.plan,
|
|
283
|
-
task.title,
|
|
284
|
-
task.description,
|
|
285
|
-
config
|
|
286
|
-
)
|
|
287
|
-
|
|
288
|
-
console.log('Files modified:', execResult.files.length)
|
|
289
|
-
}
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
## CLI Reference
|
|
293
|
-
|
|
294
|
-
```bash
|
|
295
|
-
# Show help
|
|
296
|
-
npx astrid-agent --help
|
|
297
|
-
|
|
298
|
-
# API mode (default - cloud execution)
|
|
299
|
-
npx astrid-agent
|
|
300
|
-
|
|
301
|
-
# Terminal mode (local Claude Code CLI)
|
|
302
|
-
npx astrid-agent --terminal
|
|
303
|
-
npx astrid-agent --terminal --model=sonnet --cwd=/path/to/project
|
|
304
|
-
|
|
305
|
-
# Process a specific task
|
|
306
|
-
npx astrid-agent <taskId>
|
|
307
|
-
npx astrid-agent --terminal <taskId>
|
|
308
|
-
|
|
309
|
-
# Webhook mode
|
|
310
|
-
npx astrid-agent serve --port=3001
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
## Comparison: Terminal vs API vs Webhook
|
|
314
|
-
|
|
315
|
-
| Feature | Terminal | API | Webhook |
|
|
316
|
-
|---------|----------|-----|---------|
|
|
317
|
-
| Execution | Local CLI | Cloud API | Cloud API |
|
|
318
|
-
| Requires Claude Code CLI | Yes | No | No |
|
|
319
|
-
| Permanent IP needed | No | No | Yes |
|
|
320
|
-
| Works behind NAT | Yes | Yes | No |
|
|
321
|
-
| Session resume | Yes | No | No |
|
|
322
|
-
| Task notification | ~30s poll | ~30s poll | Instant |
|
|
323
|
-
| Best for | Local dev | CI/CD, servers | Always-on servers |
|
|
324
|
-
| Project access | Local files | Clones repo | Clones repo |
|
|
325
|
-
|
|
326
|
-
## Updating
|
|
327
|
-
|
|
328
|
-
```bash
|
|
329
|
-
# Update to latest version
|
|
330
|
-
npm update -g @gracefultools/astrid-sdk
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
## License
|
|
334
|
-
|
|
335
|
-
MIT
|
|
336
|
-
|
|
337
|
-
## Links
|
|
338
|
-
|
|
339
|
-
- [Astrid](https://astrid.cc)
|
|
340
|
-
- [Documentation](https://astrid.cc/docs)
|
|
341
|
-
- [GitHub](https://github.com/Graceful-Tools/astrid-res-www)
|
|
1
|
+
# @gracefultools/astrid-sdk
|
|
2
|
+
|
|
3
|
+
SDK for integrating AI agents with [Astrid.cc](https://www.astrid.cc) task management.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @gracefultools/astrid-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## What's Included
|
|
12
|
+
|
|
13
|
+
### OAuth API Client
|
|
14
|
+
Full Astrid REST API client with OAuth2 client_credentials flow:
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { AstridOAuthClient } from '@gracefultools/astrid-sdk'
|
|
18
|
+
|
|
19
|
+
const client = new AstridOAuthClient({
|
|
20
|
+
clientId: 'your-client-id',
|
|
21
|
+
clientSecret: 'your-client-secret',
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
// Get assigned tasks
|
|
25
|
+
const tasks = await client.getTasks({ completed: false })
|
|
26
|
+
|
|
27
|
+
// Post a comment
|
|
28
|
+
await client.addComment(taskId, 'Working on this now...')
|
|
29
|
+
|
|
30
|
+
// Complete a task
|
|
31
|
+
await client.updateTask(taskId, { completed: true })
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### OpenClaw Channel Plugin
|
|
35
|
+
Connect [OpenClaw](https://openclaw.ai) to Astrid as a task channel. Your agent receives tasks via SSE (outbound connection — works behind NAT/firewalls):
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { AstridChannel, SSEClient, RestClient, SessionMapper, taskToMessage } from '@gracefultools/astrid-sdk'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
#### How it works
|
|
42
|
+
|
|
43
|
+
1. Agent connects **outbound** to `astrid.cc/api/v1/agent/events` (SSE)
|
|
44
|
+
2. When a task is assigned → agent receives it in real-time
|
|
45
|
+
3. **List description = agent instructions** — each list's description tells the agent how to handle tasks
|
|
46
|
+
4. Agent posts results as task comments
|
|
47
|
+
5. Agent marks task complete when done
|
|
48
|
+
|
|
49
|
+
#### Quick Setup
|
|
50
|
+
|
|
51
|
+
Add to your OpenClaw config:
|
|
52
|
+
|
|
53
|
+
```json5
|
|
54
|
+
{
|
|
55
|
+
channels: {
|
|
56
|
+
astrid: {
|
|
57
|
+
enabled: true,
|
|
58
|
+
clientId: "your-client-id",
|
|
59
|
+
clientSecret: "your-client-secret"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Agent Protocol
|
|
66
|
+
|
|
67
|
+
The SDK uses the Astrid Agent Protocol:
|
|
68
|
+
|
|
69
|
+
| Endpoint | Method | Description |
|
|
70
|
+
|----------|--------|-------------|
|
|
71
|
+
| `/api/v1/agent/events` | GET | SSE stream (task.assigned, task.commented, etc.) |
|
|
72
|
+
| `/api/v1/agent/tasks` | GET | List assigned tasks |
|
|
73
|
+
| `/api/v1/agent/tasks/:id` | GET/PATCH | Get or update a task |
|
|
74
|
+
| `/api/v1/agent/tasks/:id/comments` | GET/POST | Read or post comments |
|
|
75
|
+
|
|
76
|
+
All endpoints require OAuth Bearer token with appropriate scopes.
|
|
77
|
+
|
|
78
|
+
### List Descriptions as Agent Instructions
|
|
79
|
+
|
|
80
|
+
Each Astrid list's **description** field serves as instructions for AI agents:
|
|
81
|
+
|
|
82
|
+
```markdown
|
|
83
|
+
# Example "Code Reviews" list description:
|
|
84
|
+
Review PRs for security issues, test coverage, and style.
|
|
85
|
+
Post findings as comments. Mark complete when done.
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
When an agent receives a task from this list, the description is included as context. Different lists = different agent behaviors. No code changes needed.
|
|
89
|
+
|
|
90
|
+
## Configuration
|
|
91
|
+
|
|
92
|
+
### Agent Config
|
|
93
|
+
```typescript
|
|
94
|
+
import { getAgentConfig, isRegisteredAgent } from '@gracefultools/astrid-sdk'
|
|
95
|
+
|
|
96
|
+
// Check if an email is a registered agent
|
|
97
|
+
isRegisteredAgent('claude@astrid.cc') // true
|
|
98
|
+
isRegisteredAgent('mybot.oc@astrid.cc') // true (OpenClaw pattern)
|
|
99
|
+
|
|
100
|
+
// Get agent configuration
|
|
101
|
+
const config = getAgentConfig('claude@astrid.cc')
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Workflow Config
|
|
105
|
+
```typescript
|
|
106
|
+
import { getAgentWorkflowConfig, buildWorkflowInstructions } from '@gracefultools/astrid-sdk'
|
|
107
|
+
|
|
108
|
+
const config = getAgentWorkflowConfig(task, list, repository)
|
|
109
|
+
const instructions = buildWorkflowInstructions(config)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Changelog
|
|
113
|
+
|
|
114
|
+
### 0.8.0
|
|
115
|
+
- **Channel plugin**: OpenClaw integration via outbound SSE (no inbound gateway needed)
|
|
116
|
+
- **Agent protocol**: SSE events, REST client, session mapper, message formatter
|
|
117
|
+
- **Removed**: Built-in AI executors (Claude, OpenAI, Gemini) — agents run externally now
|
|
118
|
+
- **Security**: Per-endpoint OAuth scope enforcement, comment rate limiting
|
|
119
|
+
|
|
120
|
+
### 0.7.x
|
|
121
|
+
- OAuth API client
|
|
122
|
+
- Agent workflow configuration
|
|
123
|
+
- Vercel deployment support
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { AstridChannelConfig, InboundMessage, OutboundMessage } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Astrid channel plugin for OpenClaw.
|
|
4
|
+
*/
|
|
5
|
+
export declare const astridChannel: {
|
|
6
|
+
id: "astrid";
|
|
7
|
+
meta: {
|
|
8
|
+
id: string;
|
|
9
|
+
label: string;
|
|
10
|
+
selectionLabel: string;
|
|
11
|
+
docsPath: string;
|
|
12
|
+
blurb: string;
|
|
13
|
+
};
|
|
14
|
+
capabilities: {
|
|
15
|
+
chatTypes: readonly ["direct"];
|
|
16
|
+
media: boolean;
|
|
17
|
+
reactions: boolean;
|
|
18
|
+
edit: boolean;
|
|
19
|
+
polls: boolean;
|
|
20
|
+
};
|
|
21
|
+
createAdapter(config: AstridChannelConfig): {
|
|
22
|
+
init(): Promise<void>;
|
|
23
|
+
connect(onMessage: (msg: InboundMessage) => void): Promise<void>;
|
|
24
|
+
disconnect(): Promise<void>;
|
|
25
|
+
send(msg: OutboundMessage): Promise<void>;
|
|
26
|
+
isConnected(): boolean;
|
|
27
|
+
getHealth(): {
|
|
28
|
+
connected: boolean;
|
|
29
|
+
activeSessions: number;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/channel/channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAOtF;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;0BAmBF,mBAAmB;gBAOvB,OAAO,CAAC,IAAI,CAAC;2BAaF,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;sBAyBlD,OAAO,CAAC,IAAI,CAAC;kBAIjB,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;uBAShC,OAAO;;;;;;CAY3B,CAAA"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.astridChannel = void 0;
|
|
4
|
+
const oauth_client_js_1 = require("./oauth-client.js");
|
|
5
|
+
const rest_client_js_1 = require("./rest-client.js");
|
|
6
|
+
const sse_client_js_1 = require("./sse-client.js");
|
|
7
|
+
const session_mapper_js_1 = require("./session-mapper.js");
|
|
8
|
+
const message_formatter_js_1 = require("./message-formatter.js");
|
|
9
|
+
/**
|
|
10
|
+
* Astrid channel plugin for OpenClaw.
|
|
11
|
+
*/
|
|
12
|
+
exports.astridChannel = {
|
|
13
|
+
id: 'astrid',
|
|
14
|
+
meta: {
|
|
15
|
+
id: 'astrid',
|
|
16
|
+
label: 'Astrid',
|
|
17
|
+
selectionLabel: 'Astrid.cc',
|
|
18
|
+
docsPath: '/channels/astrid',
|
|
19
|
+
blurb: 'Task management',
|
|
20
|
+
},
|
|
21
|
+
capabilities: {
|
|
22
|
+
chatTypes: ['direct'],
|
|
23
|
+
media: false,
|
|
24
|
+
reactions: false,
|
|
25
|
+
edit: false,
|
|
26
|
+
polls: false,
|
|
27
|
+
},
|
|
28
|
+
createAdapter(config) {
|
|
29
|
+
const oauth = new oauth_client_js_1.OAuthClient(config);
|
|
30
|
+
const rest = new rest_client_js_1.RestClient(config.apiBase, oauth);
|
|
31
|
+
const sse = new sse_client_js_1.SSEClient(config, oauth);
|
|
32
|
+
const sessions = new session_mapper_js_1.SessionMapper();
|
|
33
|
+
return {
|
|
34
|
+
async init() {
|
|
35
|
+
if (!config.clientId || !config.clientSecret) {
|
|
36
|
+
throw new Error('Astrid channel: clientId and clientSecret are required');
|
|
37
|
+
}
|
|
38
|
+
await oauth.ensureToken();
|
|
39
|
+
// Recover existing sessions
|
|
40
|
+
const tasks = await rest.getAssignedTasks(false);
|
|
41
|
+
for (const task of tasks) {
|
|
42
|
+
sessions.getOrCreate(task.id);
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
async connect(onMessage) {
|
|
46
|
+
sse.on('task.assigned', (event) => {
|
|
47
|
+
if (!event.data.task)
|
|
48
|
+
return;
|
|
49
|
+
const msg = (0, message_formatter_js_1.taskToMessage)(event.data.task);
|
|
50
|
+
sessions.getOrCreate(event.data.taskId);
|
|
51
|
+
onMessage(msg);
|
|
52
|
+
});
|
|
53
|
+
sse.on('task.commented', (event) => {
|
|
54
|
+
const sessionKey = sessions.get(event.data.taskId);
|
|
55
|
+
if (!sessionKey || !event.data.comment)
|
|
56
|
+
return;
|
|
57
|
+
onMessage((0, message_formatter_js_1.commentToMessage)(event.data.taskId, event.data.comment));
|
|
58
|
+
});
|
|
59
|
+
sse.on('task.completed', (event) => {
|
|
60
|
+
sessions.end(event.data.taskId);
|
|
61
|
+
});
|
|
62
|
+
sse.on('task.deleted', (event) => {
|
|
63
|
+
sessions.end(event.data.taskId);
|
|
64
|
+
});
|
|
65
|
+
await sse.connect();
|
|
66
|
+
},
|
|
67
|
+
async disconnect() {
|
|
68
|
+
sse.disconnect();
|
|
69
|
+
},
|
|
70
|
+
async send(msg) {
|
|
71
|
+
const taskId = sessions.getTaskId(msg.sessionKey);
|
|
72
|
+
if (!taskId) {
|
|
73
|
+
throw new Error(`No Astrid task mapped to session ${msg.sessionKey}`);
|
|
74
|
+
}
|
|
75
|
+
const content = (0, message_formatter_js_1.responseToComment)(msg);
|
|
76
|
+
await rest.postComment(taskId, content);
|
|
77
|
+
},
|
|
78
|
+
isConnected() {
|
|
79
|
+
return sse.isConnected();
|
|
80
|
+
},
|
|
81
|
+
getHealth() {
|
|
82
|
+
return {
|
|
83
|
+
connected: sse.isConnected(),
|
|
84
|
+
activeSessions: sessions.activeCount(),
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/channel/channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Astrid Channel Plugin for OpenClaw
|
|
3
|
+
*
|
|
4
|
+
* Connect OpenClaw to Astrid.cc via outbound SSE — no inbound gateway URL needed.
|
|
5
|
+
*/
|
|
6
|
+
export { astridChannel as AstridChannel } from './channel.js';
|
|
7
|
+
export { SSEClient } from './sse-client.js';
|
|
8
|
+
export { OAuthClient } from './oauth-client.js';
|
|
9
|
+
export { RestClient } from './rest-client.js';
|
|
10
|
+
export { SessionMapper } from './session-mapper.js';
|
|
11
|
+
export { taskToMessage, commentToMessage, responseToComment } from './message-formatter.js';
|
|
12
|
+
export type { AstridChannelConfig, AgentTask, AgentComment, AgentSSEEvent, InboundMessage, OutboundMessage, } from './types.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/channel/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,IAAI,aAAa,EAAE,MAAM,cAAc,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC3F,YAAY,EACV,mBAAmB,EACnB,SAAS,EACT,YAAY,EACZ,aAAa,EACb,cAAc,EACd,eAAe,GAChB,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Astrid Channel Plugin for OpenClaw
|
|
4
|
+
*
|
|
5
|
+
* Connect OpenClaw to Astrid.cc via outbound SSE — no inbound gateway URL needed.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.responseToComment = exports.commentToMessage = exports.taskToMessage = exports.SessionMapper = exports.RestClient = exports.OAuthClient = exports.SSEClient = exports.AstridChannel = void 0;
|
|
9
|
+
var channel_js_1 = require("./channel.js");
|
|
10
|
+
Object.defineProperty(exports, "AstridChannel", { enumerable: true, get: function () { return channel_js_1.astridChannel; } });
|
|
11
|
+
var sse_client_js_1 = require("./sse-client.js");
|
|
12
|
+
Object.defineProperty(exports, "SSEClient", { enumerable: true, get: function () { return sse_client_js_1.SSEClient; } });
|
|
13
|
+
var oauth_client_js_1 = require("./oauth-client.js");
|
|
14
|
+
Object.defineProperty(exports, "OAuthClient", { enumerable: true, get: function () { return oauth_client_js_1.OAuthClient; } });
|
|
15
|
+
var rest_client_js_1 = require("./rest-client.js");
|
|
16
|
+
Object.defineProperty(exports, "RestClient", { enumerable: true, get: function () { return rest_client_js_1.RestClient; } });
|
|
17
|
+
var session_mapper_js_1 = require("./session-mapper.js");
|
|
18
|
+
Object.defineProperty(exports, "SessionMapper", { enumerable: true, get: function () { return session_mapper_js_1.SessionMapper; } });
|
|
19
|
+
var message_formatter_js_1 = require("./message-formatter.js");
|
|
20
|
+
Object.defineProperty(exports, "taskToMessage", { enumerable: true, get: function () { return message_formatter_js_1.taskToMessage; } });
|
|
21
|
+
Object.defineProperty(exports, "commentToMessage", { enumerable: true, get: function () { return message_formatter_js_1.commentToMessage; } });
|
|
22
|
+
Object.defineProperty(exports, "responseToComment", { enumerable: true, get: function () { return message_formatter_js_1.responseToComment; } });
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/channel/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,2CAA6D;AAApD,2GAAA,aAAa,OAAiB;AACvC,iDAA2C;AAAlC,0GAAA,SAAS,OAAA;AAClB,qDAA+C;AAAtC,8GAAA,WAAW,OAAA;AACpB,mDAA6C;AAApC,4GAAA,UAAU,OAAA;AACnB,yDAAmD;AAA1C,kHAAA,aAAa,OAAA;AACtB,+DAA2F;AAAlF,qHAAA,aAAa,OAAA;AAAE,wHAAA,gBAAgB,OAAA;AAAE,yHAAA,iBAAiB,OAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AgentTask, AgentComment, InboundMessage, OutboundMessage } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Format an Astrid task as an OpenClaw inbound message.
|
|
4
|
+
*/
|
|
5
|
+
export declare function taskToMessage(task: AgentTask): InboundMessage;
|
|
6
|
+
/**
|
|
7
|
+
* Format a human comment as a follow-up inbound message.
|
|
8
|
+
*/
|
|
9
|
+
export declare function commentToMessage(taskId: string, comment: AgentComment): InboundMessage;
|
|
10
|
+
/**
|
|
11
|
+
* Strip agent response for posting as an Astrid comment.
|
|
12
|
+
*/
|
|
13
|
+
export declare function responseToComment(msg: OutboundMessage): string;
|
|
14
|
+
//# sourceMappingURL=message-formatter.d.ts.map
|