create-walle 0.1.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/bin/create-walle.js +134 -0
- package/package.json +18 -0
- package/template/.env.example +40 -0
- package/template/CLAUDE.md +12 -0
- package/template/LICENSE +21 -0
- package/template/README.md +167 -0
- package/template/bin/setup.js +100 -0
- package/template/claude-code-skill.md +60 -0
- package/template/claude-task-manager/api-prompts.js +1841 -0
- package/template/claude-task-manager/api-reviews.js +275 -0
- package/template/claude-task-manager/approval-agent.js +454 -0
- package/template/claude-task-manager/bin/restart-ctm.sh +16 -0
- package/template/claude-task-manager/db.js +1721 -0
- package/template/claude-task-manager/docs/PROMPT-MANAGEMENT-DESIGN.md +631 -0
- package/template/claude-task-manager/git-utils.js +214 -0
- package/template/claude-task-manager/package-lock.json +1607 -0
- package/template/claude-task-manager/package.json +31 -0
- package/template/claude-task-manager/prompt-harvest.js +1148 -0
- package/template/claude-task-manager/public/css/prompts.css +880 -0
- package/template/claude-task-manager/public/css/reviews.css +430 -0
- package/template/claude-task-manager/public/css/walle.css +732 -0
- package/template/claude-task-manager/public/favicon.ico +0 -0
- package/template/claude-task-manager/public/icon.svg +37 -0
- package/template/claude-task-manager/public/index.html +8346 -0
- package/template/claude-task-manager/public/js/prompts.js +3159 -0
- package/template/claude-task-manager/public/js/reviews.js +1292 -0
- package/template/claude-task-manager/public/js/walle.js +3081 -0
- package/template/claude-task-manager/public/manifest.json +13 -0
- package/template/claude-task-manager/public/prompts.html +4353 -0
- package/template/claude-task-manager/public/setup.html +216 -0
- package/template/claude-task-manager/queue-engine.js +404 -0
- package/template/claude-task-manager/server-state.js +5 -0
- package/template/claude-task-manager/server.js +2254 -0
- package/template/claude-task-manager/session-utils.js +124 -0
- package/template/claude-task-manager/start.sh +17 -0
- package/template/claude-task-manager/tests/test-ai-search.js +61 -0
- package/template/claude-task-manager/tests/test-editor-ux.js +76 -0
- package/template/claude-task-manager/tests/test-editor-ux2.js +51 -0
- package/template/claude-task-manager/tests/test-features-v2.js +127 -0
- package/template/claude-task-manager/tests/test-insights-cached.js +78 -0
- package/template/claude-task-manager/tests/test-insights.js +124 -0
- package/template/claude-task-manager/tests/test-permissions-v2.js +127 -0
- package/template/claude-task-manager/tests/test-permissions.js +122 -0
- package/template/claude-task-manager/tests/test-pin.js +51 -0
- package/template/claude-task-manager/tests/test-prompts.js +164 -0
- package/template/claude-task-manager/tests/test-recent-sessions.js +96 -0
- package/template/claude-task-manager/tests/test-review.js +104 -0
- package/template/claude-task-manager/tests/test-send-dropdown.js +76 -0
- package/template/claude-task-manager/tests/test-send-final.js +30 -0
- package/template/claude-task-manager/tests/test-send-fixes.js +76 -0
- package/template/claude-task-manager/tests/test-send-integration.js +107 -0
- package/template/claude-task-manager/tests/test-send-visual.js +34 -0
- package/template/claude-task-manager/tests/test-session-create.js +147 -0
- package/template/claude-task-manager/tests/test-sidebar-ux.js +83 -0
- package/template/claude-task-manager/tests/test-url-hash.js +68 -0
- package/template/claude-task-manager/tests/test-ux-crop.js +34 -0
- package/template/claude-task-manager/tests/test-ux-review.js +130 -0
- package/template/claude-task-manager/tests/test-zoom-card.js +76 -0
- package/template/claude-task-manager/tests/test-zoom.js +92 -0
- package/template/claude-task-manager/tests/test-zoom2.js +67 -0
- package/template/docs/site/api/README.md +187 -0
- package/template/docs/site/guides/claude-code.md +58 -0
- package/template/docs/site/guides/configuration.md +96 -0
- package/template/docs/site/guides/quickstart.md +158 -0
- package/template/docs/site/index.md +14 -0
- package/template/docs/site/skills/README.md +135 -0
- package/template/wall-e/.dockerignore +11 -0
- package/template/wall-e/Dockerfile +25 -0
- package/template/wall-e/adapters/adapter-base.js +37 -0
- package/template/wall-e/adapters/ctm.js +193 -0
- package/template/wall-e/adapters/slack.js +56 -0
- package/template/wall-e/agent.js +319 -0
- package/template/wall-e/api-walle.js +1073 -0
- package/template/wall-e/brain.js +1235 -0
- package/template/wall-e/channels/agent-api.js +172 -0
- package/template/wall-e/channels/channel-base.js +14 -0
- package/template/wall-e/channels/imessage-channel.js +113 -0
- package/template/wall-e/channels/slack-channel.js +118 -0
- package/template/wall-e/chat.js +778 -0
- package/template/wall-e/decision/confidence.js +93 -0
- package/template/wall-e/deploy.sh +35 -0
- package/template/wall-e/docs/specs/2026-04-01-publish-plan.md +112 -0
- package/template/wall-e/docs/specs/SKILL-FORMAT.md +326 -0
- package/template/wall-e/extraction/contradiction.js +168 -0
- package/template/wall-e/extraction/knowledge-extractor.js +190 -0
- package/template/wall-e/fly.toml +24 -0
- package/template/wall-e/loops/ingest.js +34 -0
- package/template/wall-e/loops/reflect.js +63 -0
- package/template/wall-e/loops/tasks.js +487 -0
- package/template/wall-e/loops/think.js +125 -0
- package/template/wall-e/package-lock.json +533 -0
- package/template/wall-e/package.json +18 -0
- package/template/wall-e/scripts/ingest-slack-search.js +85 -0
- package/template/wall-e/scripts/pull-slack-via-claude.js +98 -0
- package/template/wall-e/scripts/slack-backfill.js +295 -0
- package/template/wall-e/scripts/slack-channel-history.js +454 -0
- package/template/wall-e/server.js +93 -0
- package/template/wall-e/skills/_bundled/email-digest/SKILL.md +95 -0
- package/template/wall-e/skills/_bundled/email-sync/SKILL.md +65 -0
- package/template/wall-e/skills/_bundled/email-sync/mail-reader.jxa +104 -0
- package/template/wall-e/skills/_bundled/email-sync/run.js +213 -0
- package/template/wall-e/skills/_bundled/google-calendar/SKILL.md +73 -0
- package/template/wall-e/skills/_bundled/google-calendar/cal-reader.swift +81 -0
- package/template/wall-e/skills/_bundled/google-calendar/run.js +181 -0
- package/template/wall-e/skills/_bundled/memory-search/SKILL.md +92 -0
- package/template/wall-e/skills/_bundled/morning-briefing/SKILL.md +131 -0
- package/template/wall-e/skills/_bundled/morning-briefing/run.js +264 -0
- package/template/wall-e/skills/_bundled/slack-backfill/SKILL.md +60 -0
- package/template/wall-e/skills/_bundled/slack-sync/SKILL.md +55 -0
- package/template/wall-e/skills/claude-code-reader.js +144 -0
- package/template/wall-e/skills/mcp-client.js +407 -0
- package/template/wall-e/skills/skill-executor.js +163 -0
- package/template/wall-e/skills/skill-loader.js +410 -0
- package/template/wall-e/skills/skill-planner.js +88 -0
- package/template/wall-e/skills/slack-ingest.js +329 -0
- package/template/wall-e/skills/slack-pull-live.js +270 -0
- package/template/wall-e/skills/tool-executor.js +188 -0
- package/template/wall-e/tests/adapter-base.test.js +20 -0
- package/template/wall-e/tests/adapter-ctm.test.js +122 -0
- package/template/wall-e/tests/adapter-slack.test.js +98 -0
- package/template/wall-e/tests/agent-api.test.js +256 -0
- package/template/wall-e/tests/api-walle.test.js +222 -0
- package/template/wall-e/tests/brain.test.js +602 -0
- package/template/wall-e/tests/channels.test.js +104 -0
- package/template/wall-e/tests/chat.test.js +103 -0
- package/template/wall-e/tests/confidence.test.js +134 -0
- package/template/wall-e/tests/contradiction.test.js +217 -0
- package/template/wall-e/tests/ingest.test.js +113 -0
- package/template/wall-e/tests/mcp-client.test.js +71 -0
- package/template/wall-e/tests/reflect.test.js +103 -0
- package/template/wall-e/tests/server.test.js +111 -0
- package/template/wall-e/tests/skills.test.js +198 -0
- package/template/wall-e/tests/slack-ingest.test.js +103 -0
- package/template/wall-e/tests/think.test.js +435 -0
- package/template/wall-e/tools/local-tools.js +697 -0
- package/template/wall-e/tools/slack-mcp.js +290 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { v4: uuidv4 } = require('uuid');
|
|
3
|
+
const brain = require('../brain');
|
|
4
|
+
|
|
5
|
+
// Graduation thresholds from spec
|
|
6
|
+
const GRADUATION = {
|
|
7
|
+
'1_to_2': { memories_required: 50 },
|
|
8
|
+
'2_to_3': { approval_rate: 0.90, min_actions: 20 },
|
|
9
|
+
'3_to_4': { approval_rate: 0.95, min_actions: 50 },
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function getDomainConfidence(domain) {
|
|
13
|
+
const db = brain.getDb();
|
|
14
|
+
let row = db.prepare('SELECT * FROM domain_confidence WHERE domain = ?').get(domain);
|
|
15
|
+
if (!row) {
|
|
16
|
+
const id = uuidv4();
|
|
17
|
+
db.prepare('INSERT INTO domain_confidence (id, domain) VALUES (?, ?)').run(id, domain);
|
|
18
|
+
row = db.prepare('SELECT * FROM domain_confidence WHERE domain = ?').get(domain);
|
|
19
|
+
}
|
|
20
|
+
return row;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function checkGraduation(domain) {
|
|
24
|
+
const dc = getDomainConfidence(domain);
|
|
25
|
+
const currentTier = dc.current_tier;
|
|
26
|
+
let newTier = currentTier;
|
|
27
|
+
|
|
28
|
+
if (currentTier === 1) {
|
|
29
|
+
// Tier 1 -> 2: enough memories in domain
|
|
30
|
+
const memCount = brain.listMemories({ source: domain, limit: 51 }).length;
|
|
31
|
+
if (memCount > 50) newTier = 2;
|
|
32
|
+
} else if (currentTier === 2) {
|
|
33
|
+
const rate = dc.total_actions > 0 ? dc.approved_actions / dc.total_actions : 0;
|
|
34
|
+
if (rate > 0.90 && dc.total_actions > 20) newTier = 3;
|
|
35
|
+
} else if (currentTier === 3) {
|
|
36
|
+
const rate = dc.total_actions > 0 ? dc.approved_actions / dc.total_actions : 0;
|
|
37
|
+
if (rate > 0.95 && dc.total_actions > 50) newTier = 4;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (newTier !== currentTier) {
|
|
41
|
+
brain.getDb().prepare(
|
|
42
|
+
"UPDATE domain_confidence SET current_tier = ?, last_promotion = datetime('now'), updated_at = datetime('now') WHERE domain = ?"
|
|
43
|
+
).run(newTier, domain);
|
|
44
|
+
return { promoted: true, from: currentTier, to: newTier };
|
|
45
|
+
}
|
|
46
|
+
return { promoted: false, tier: currentTier };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function recordAction(domain, approved) {
|
|
50
|
+
const dc = getDomainConfidence(domain);
|
|
51
|
+
const updates = {
|
|
52
|
+
total_actions: dc.total_actions + 1,
|
|
53
|
+
approved_actions: approved ? dc.approved_actions + 1 : dc.approved_actions,
|
|
54
|
+
rejected_actions: approved ? dc.rejected_actions : dc.rejected_actions + 1,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// Check demotion: 3 rejections in a row
|
|
58
|
+
if (!approved) {
|
|
59
|
+
const recentActions = brain.getDb().prepare(
|
|
60
|
+
"SELECT status FROM agent_actions WHERE domain = ? ORDER BY created_at DESC LIMIT 3"
|
|
61
|
+
).all(domain);
|
|
62
|
+
const allRejected = recentActions.length === 3 && recentActions.every(a => a.status === 'rejected');
|
|
63
|
+
if (allRejected && dc.current_tier > 1) {
|
|
64
|
+
updates.current_tier = dc.current_tier - 1;
|
|
65
|
+
updates.last_demotion = new Date().toISOString();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const keys = Object.keys(updates);
|
|
70
|
+
const sets = keys.map(k => `${k} = ?`).join(', ');
|
|
71
|
+
const vals = keys.map(k => updates[k]);
|
|
72
|
+
brain.getDb().prepare(`UPDATE domain_confidence SET ${sets}, updated_at = datetime('now') WHERE domain = ?`)
|
|
73
|
+
.run(...vals, domain);
|
|
74
|
+
|
|
75
|
+
// Check graduation after recording
|
|
76
|
+
return checkGraduation(domain);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function canActAutonomously(domain, isHighRisk) {
|
|
80
|
+
const dc = getDomainConfidence(domain);
|
|
81
|
+
const tier = dc.current_tier;
|
|
82
|
+
|
|
83
|
+
if (tier <= 2) return false; // Always queue
|
|
84
|
+
if (tier === 3) return !isHighRisk; // Act on low-risk only
|
|
85
|
+
if (tier === 4) return true; // Full autonomy
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function listDomainConfidences() {
|
|
90
|
+
return brain.getDb().prepare('SELECT * FROM domain_confidence ORDER BY domain').all();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = { getDomainConfidence, checkGraduation, recordAction, canActAutonomously, listDomainConfidences };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
echo "=== WALL-E Cloud Deployment ==="
|
|
5
|
+
echo ""
|
|
6
|
+
|
|
7
|
+
# Check fly CLI
|
|
8
|
+
if ! command -v fly &> /dev/null; then
|
|
9
|
+
echo "Error: fly CLI not installed. Run: brew install flyctl"
|
|
10
|
+
exit 1
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
# Check if app exists
|
|
14
|
+
if ! fly apps list 2>/dev/null | grep -q wall-e-agent; then
|
|
15
|
+
echo "Creating Fly.io app..."
|
|
16
|
+
fly apps create wall-e-agent
|
|
17
|
+
fly volumes create wall_e_data --region sjc --size 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# Set secrets
|
|
21
|
+
echo "Setting secrets..."
|
|
22
|
+
echo "Make sure to set ANTHROPIC_API_KEY or Portkey headers:"
|
|
23
|
+
echo " fly secrets set ANTHROPIC_API_KEY=sk-..."
|
|
24
|
+
echo " fly secrets set ANTHROPIC_BASE_URL=https://..."
|
|
25
|
+
echo " fly secrets set ANTHROPIC_CUSTOM_HEADERS_B64=..."
|
|
26
|
+
echo ""
|
|
27
|
+
|
|
28
|
+
# Deploy
|
|
29
|
+
echo "Deploying..."
|
|
30
|
+
fly deploy
|
|
31
|
+
|
|
32
|
+
echo ""
|
|
33
|
+
echo "=== Deployment complete ==="
|
|
34
|
+
echo "WALL-E is running at: https://wall-e-agent.fly.dev"
|
|
35
|
+
echo "Health check: https://wall-e-agent.fly.dev/api/wall-e/health"
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Publishing Plan: CTM & Wall-E
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-04-01
|
|
4
|
+
**Author:** Juncao Li
|
|
5
|
+
**Domain:** https://walle.sh
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
Publish CTM (Claude Task Manager) and Wall-E (personal digital twin agent) as open-source tools that others can discover, install, and run locally.
|
|
10
|
+
|
|
11
|
+
## Phases
|
|
12
|
+
|
|
13
|
+
### Phase 1: Code Cleanup & Open Source (Current)
|
|
14
|
+
|
|
15
|
+
**Goal:** Make the codebase safe and portable for public GitHub.
|
|
16
|
+
|
|
17
|
+
#### Security Cleanup
|
|
18
|
+
|
|
19
|
+
| Issue | Severity | Files | Fix |
|
|
20
|
+
|---|---|---|---|
|
|
21
|
+
| Hardcoded Slack User ID `YOUR_SLACK_USER_ID` | Critical | 5 files in `scripts/`, `slack-ingest.js` | Env var `SLACK_OWNER_USER_ID` |
|
|
22
|
+
| `owner@example.com` in SKILL.md examples | High | `email-sync/SKILL.md`, `google-calendar/SKILL.md` | Replace with `owner@example.com` |
|
|
23
|
+
| Hardcoded `juncao.li` in Slack queries | High | `slack-backfill.js`, `slack-channel-history.js`, `morning-briefing/run.js` | Read from config/brain |
|
|
24
|
+
| `OWNER_NAME` owner name constant | High | `pull-slack-via-claude.js`, `slack-ingest.js` | Use `brain.getOwnerName()` |
|
|
25
|
+
| Hardcoded `.walle/data` | Medium | `server.js`, `db.js`, `brain.js`, `api-walle.js` | Default to `~/.walle/data` |
|
|
26
|
+
|
|
27
|
+
#### Repo Hygiene
|
|
28
|
+
|
|
29
|
+
- [ ] `.env.example` documenting all env vars
|
|
30
|
+
- [ ] `.gitignore` excludes `.db`, `.env`, compiled binaries, oauth tokens
|
|
31
|
+
- [ ] MIT `LICENSE` file
|
|
32
|
+
- [ ] Scrub git history or start fresh public repo (if secrets were ever committed)
|
|
33
|
+
|
|
34
|
+
#### Already Good
|
|
35
|
+
|
|
36
|
+
- API keys (ANTHROPIC_API_KEY, SLACK_TOKEN) read from env vars
|
|
37
|
+
- `.db` files not in repo
|
|
38
|
+
- `CTM_DATA_DIR` / `WALL_E_DATA_DIR` env vars already supported
|
|
39
|
+
|
|
40
|
+
### Phase 2: Distribution & Discovery
|
|
41
|
+
|
|
42
|
+
**Goal:** Make it easy for others to find and install.
|
|
43
|
+
|
|
44
|
+
| Channel | Effort | Reach | Priority |
|
|
45
|
+
|---|---|---|---|
|
|
46
|
+
| GitHub repo + README | Low | Devs who search GitHub | P0 |
|
|
47
|
+
| `npx create-walle` scaffolder | Medium | Anyone with Node.js | P1 |
|
|
48
|
+
| Claude Code skill registry | Low | Claude Code users | P1 |
|
|
49
|
+
| Homebrew tap | Medium | macOS users | P2 |
|
|
50
|
+
| walle.sh website | High | Broadest | P2 |
|
|
51
|
+
|
|
52
|
+
#### README Requirements
|
|
53
|
+
|
|
54
|
+
- One-paragraph pitch
|
|
55
|
+
- Screenshot / demo GIF
|
|
56
|
+
- "Try it in 2 minutes" quickstart
|
|
57
|
+
- Architecture diagram (CTM <-> Wall-E <-> Brain)
|
|
58
|
+
- List of bundled skills (calendar, slack, email, morning briefing)
|
|
59
|
+
- Configuration reference
|
|
60
|
+
|
|
61
|
+
#### npx Scaffolder
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx create-walle
|
|
65
|
+
# Clones repo, runs npm install, creates ~/.walle/data,
|
|
66
|
+
# prompts for ANTHROPIC_API_KEY, owner name, optional Slack token
|
|
67
|
+
# Starts CTM + Wall-E daemon
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Phase 3: Website — walle.sh
|
|
71
|
+
|
|
72
|
+
**Goal:** Landing page, docs, and eventually auth + cloud hosting.
|
|
73
|
+
|
|
74
|
+
| Sub-phase | What | Tech |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| 3a | Static landing page: pitch, screenshots, install guide | Cloudflare Pages (free, deploys from repo) |
|
|
77
|
+
| 3b | Interactive docs: skill catalog, API reference | Same, or Astro/Starlight |
|
|
78
|
+
| 3c | Auth + cloud DB | Fly.io (already deployed), Turso/Libsql for SQLite-compat cloud DB, Clerk or Passkeys for auth |
|
|
79
|
+
| 3d | Web-based setup wizard | Create account -> configure integrations -> download CLI |
|
|
80
|
+
|
|
81
|
+
#### Domain DNS Roadmap
|
|
82
|
+
|
|
83
|
+
| Record | Now | Later |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `walle.sh` | `127.0.0.1` (local alias) | Cloudflare Pages (landing) |
|
|
86
|
+
| `app.walle.sh` | — | Fly.io (cloud CTM + Wall-E) |
|
|
87
|
+
| `api.walle.sh` | — | Fly.io (public API) |
|
|
88
|
+
| `docs.walle.sh` | — | Cloudflare Pages (documentation) |
|
|
89
|
+
|
|
90
|
+
### Phase 4: Multi-User & Marketplace
|
|
91
|
+
|
|
92
|
+
**Goal:** Let others contribute skills; host as SaaS.
|
|
93
|
+
|
|
94
|
+
- Per-user data isolation (separate brain DBs)
|
|
95
|
+
- Skill marketplace: browse, install, rate community skills
|
|
96
|
+
- Usage-based pricing or free tier + pro
|
|
97
|
+
- Telemetry opt-in for usage insights
|
|
98
|
+
- Rate limiting / cost management (Wall-E daemon burns API tokens)
|
|
99
|
+
|
|
100
|
+
## Branding
|
|
101
|
+
|
|
102
|
+
- **Public name:** Wall-E (memorable, the face of the project)
|
|
103
|
+
- **CTM** is the task manager component (less catchy, keep as internal name)
|
|
104
|
+
- **Domain:** walle.sh
|
|
105
|
+
- **Tagline ideas:** "Your personal digital twin" / "An AI that knows you"
|
|
106
|
+
|
|
107
|
+
## Open Questions
|
|
108
|
+
|
|
109
|
+
1. Start fresh public repo or clean history of current repo?
|
|
110
|
+
2. Pricing model for cloud version? Free tier limits?
|
|
111
|
+
3. Skill contribution guidelines and review process?
|
|
112
|
+
4. Should the Slack/Email/Calendar sync skills require specific setup guides per-platform?
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
# WALL-E Skill Format Specification
|
|
2
|
+
|
|
3
|
+
**Version:** 1.0.0
|
|
4
|
+
**Date:** 2026-03-31
|
|
5
|
+
**Status:** Draft
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
A WALL-E skill is a **reusable capability** that the agent can invoke to accomplish work. Skills sit between raw tools (Slack MCP, file I/O, shell) and tasks (scheduled/triggered jobs).
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
┌─────────────────────────────────────┐
|
|
13
|
+
│ TASKS (scheduling) │ "Run slack-sync every 15m"
|
|
14
|
+
│ When to run, checkpoints, status │
|
|
15
|
+
├─────────────────────────────────────┤
|
|
16
|
+
│ SKILLS (capabilities) │ "How to sync Slack messages"
|
|
17
|
+
│ Reusable, composable, shareable │
|
|
18
|
+
├─────────────────────────────────────┤
|
|
19
|
+
│ TOOLS (primitives) │ Slack MCP, brain DB, shell
|
|
20
|
+
│ Raw APIs, MCP servers │
|
|
21
|
+
└─────────────────────────────────────┘
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Skill Directory Structure
|
|
25
|
+
|
|
26
|
+
Each skill is a directory containing a `SKILL.md` file and optional supporting files:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
skills/
|
|
30
|
+
slack-sync/
|
|
31
|
+
SKILL.md # Required: metadata + instructions
|
|
32
|
+
run.js # Optional: script entry point
|
|
33
|
+
lib/ # Optional: supporting code
|
|
34
|
+
README.md # Optional: human docs
|
|
35
|
+
morning-briefing/
|
|
36
|
+
SKILL.md # Agent-based skill (no script)
|
|
37
|
+
my-custom-skill/
|
|
38
|
+
SKILL.md
|
|
39
|
+
run.sh # Shell scripts work too
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## SKILL.md Format
|
|
43
|
+
|
|
44
|
+
A SKILL.md file has two parts: **YAML frontmatter** (metadata) and **Markdown body** (instructions).
|
|
45
|
+
|
|
46
|
+
### Minimal Example
|
|
47
|
+
|
|
48
|
+
```markdown
|
|
49
|
+
---
|
|
50
|
+
name: hello-world
|
|
51
|
+
description: A simple test skill that greets the user
|
|
52
|
+
version: 1.0.0
|
|
53
|
+
execution: agent
|
|
54
|
+
---
|
|
55
|
+
# Hello World
|
|
56
|
+
|
|
57
|
+
When invoked, respond with a friendly greeting that includes the owner's name.
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Full Example
|
|
61
|
+
|
|
62
|
+
```markdown
|
|
63
|
+
---
|
|
64
|
+
name: slack-sync
|
|
65
|
+
description: >
|
|
66
|
+
Pull latest Slack messages from active conversations.
|
|
67
|
+
Discovers recently active channels, fetches new messages,
|
|
68
|
+
and stores them in WALL-E's brain for search and context.
|
|
69
|
+
version: 1.2.0
|
|
70
|
+
author: juncao
|
|
71
|
+
|
|
72
|
+
# Execution mode: "script" (deterministic) or "agent" (LLM-driven)
|
|
73
|
+
execution: script
|
|
74
|
+
entry: run.js
|
|
75
|
+
args: ["--sync"]
|
|
76
|
+
|
|
77
|
+
# What this skill needs to run
|
|
78
|
+
requires:
|
|
79
|
+
env: [] # Environment variables (checked at load time)
|
|
80
|
+
tools: [slack-mcp] # MCP servers or tool modules
|
|
81
|
+
skills: [] # Other skills this depends on
|
|
82
|
+
|
|
83
|
+
# Default trigger for tasks that use this skill
|
|
84
|
+
trigger:
|
|
85
|
+
type: interval # interval | cron | manual | event
|
|
86
|
+
schedule: "every 15m" # Human-readable schedule
|
|
87
|
+
|
|
88
|
+
# Skill configuration schema (validated at runtime)
|
|
89
|
+
config:
|
|
90
|
+
mode:
|
|
91
|
+
type: string
|
|
92
|
+
enum: [incremental, full]
|
|
93
|
+
default: incremental
|
|
94
|
+
description: "incremental = only new messages, full = complete backfill"
|
|
95
|
+
max_channels:
|
|
96
|
+
type: number
|
|
97
|
+
default: 50
|
|
98
|
+
description: "Maximum channels to check per run"
|
|
99
|
+
|
|
100
|
+
# Tags for discovery
|
|
101
|
+
tags: [slack, messaging, sync, ingestion]
|
|
102
|
+
|
|
103
|
+
# Permissions this skill requires (shown to user before install)
|
|
104
|
+
permissions:
|
|
105
|
+
- slack:read # Read Slack messages
|
|
106
|
+
- brain:write # Write memories to brain DB
|
|
107
|
+
- network:outbound # Make HTTP requests
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
# Slack Conversation Sync
|
|
111
|
+
|
|
112
|
+
## What This Skill Does
|
|
113
|
+
|
|
114
|
+
Incrementally syncs Slack messages from your most active conversations
|
|
115
|
+
into WALL-E's brain. Only checks recently active channels (last 7 days)
|
|
116
|
+
to minimize API calls and run time.
|
|
117
|
+
|
|
118
|
+
## How It Works
|
|
119
|
+
|
|
120
|
+
1. Search Slack for YOUR recent messages to discover active channels
|
|
121
|
+
2. Query brain DB for channels with recent activity
|
|
122
|
+
3. For each active channel, fetch messages since last sync
|
|
123
|
+
4. Deduplicate and store new messages as memories
|
|
124
|
+
5. Emit checkpoint after each channel for resume support
|
|
125
|
+
|
|
126
|
+
## Configuration
|
|
127
|
+
|
|
128
|
+
- `mode: incremental` — Only pulls channels with activity in the last 7 days (~35 channels, ~1 min)
|
|
129
|
+
- `mode: full` — Pulls ALL known channels (~800 channels, ~15 min)
|
|
130
|
+
|
|
131
|
+
## Output
|
|
132
|
+
|
|
133
|
+
Returns: `{ new_messages, skipped, channels_done, total_after }`
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Frontmatter Fields
|
|
137
|
+
|
|
138
|
+
### Required
|
|
139
|
+
|
|
140
|
+
| Field | Type | Description |
|
|
141
|
+
|-------|------|-------------|
|
|
142
|
+
| `name` | string | Unique skill identifier (kebab-case, e.g., `slack-sync`) |
|
|
143
|
+
| `description` | string | What this skill does. **This is the primary field used for skill discovery.** Write it like search keywords. |
|
|
144
|
+
| `version` | string | Semver version |
|
|
145
|
+
| `execution` | string | `"script"` or `"agent"` |
|
|
146
|
+
|
|
147
|
+
### Optional
|
|
148
|
+
|
|
149
|
+
| Field | Type | Default | Description |
|
|
150
|
+
|-------|------|---------|-------------|
|
|
151
|
+
| `author` | string | — | Skill author |
|
|
152
|
+
| `entry` | string | `run.js` | Entry point file (for script execution) |
|
|
153
|
+
| `args` | string[] | `[]` | Default arguments passed to entry point |
|
|
154
|
+
| `requires.env` | string[] | `[]` | Required environment variables |
|
|
155
|
+
| `requires.tools` | string[] | `[]` | Required MCP servers or tool modules |
|
|
156
|
+
| `requires.skills` | string[] | `[]` | Other skills this depends on |
|
|
157
|
+
| `trigger.type` | string | `manual` | Default trigger: `interval`, `cron`, `manual`, `event` |
|
|
158
|
+
| `trigger.schedule` | string | — | Default schedule (e.g., `"every 15m"`, `"daily at 7am"`) |
|
|
159
|
+
| `config` | object | `{}` | Configuration schema (JSON Schema subset) |
|
|
160
|
+
| `tags` | string[] | `[]` | Discovery tags |
|
|
161
|
+
| `permissions` | string[] | `[]` | Required permissions (shown before install) |
|
|
162
|
+
|
|
163
|
+
## Execution Modes
|
|
164
|
+
|
|
165
|
+
### Script Mode (`execution: script`)
|
|
166
|
+
|
|
167
|
+
Deterministic execution. The skill runs a script file (Node.js, Python, shell) as a child process. No LLM tokens consumed. Fast and predictable.
|
|
168
|
+
|
|
169
|
+
```yaml
|
|
170
|
+
execution: script
|
|
171
|
+
entry: run.js # Relative to skill directory
|
|
172
|
+
args: ["--sync"] # Default CLI arguments
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The script receives configuration via environment variables:
|
|
176
|
+
- `WALL_E_SKILL_CONFIG` — JSON string of the config object
|
|
177
|
+
- `WALL_E_DATA_DIR` — Path to WALL-E's data directory
|
|
178
|
+
- `WALL_E_SKILL_DIR` — Path to this skill's directory
|
|
179
|
+
|
|
180
|
+
Script exit codes:
|
|
181
|
+
- `0` — Success
|
|
182
|
+
- `1` — Failure (stderr captured as error)
|
|
183
|
+
- `2` — Partial success (some work done, checkpoint saved)
|
|
184
|
+
|
|
185
|
+
### Agent Mode (`execution: agent`)
|
|
186
|
+
|
|
187
|
+
LLM-driven execution. WALL-E reads the SKILL.md instructions and uses available tools to accomplish the task. Flexible but costs tokens.
|
|
188
|
+
|
|
189
|
+
```yaml
|
|
190
|
+
execution: agent
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The Markdown body below the frontmatter becomes the agent's instructions. The agent can use any available tools (MCP servers, brain DB, shell) to follow the instructions.
|
|
194
|
+
|
|
195
|
+
Agent skills are ideal for:
|
|
196
|
+
- Tasks requiring judgment (summarization, analysis)
|
|
197
|
+
- Multi-step workflows that may vary each run
|
|
198
|
+
- Skills that compose other skills
|
|
199
|
+
- Natural language output (briefings, reports)
|
|
200
|
+
|
|
201
|
+
## Skill Discovery
|
|
202
|
+
|
|
203
|
+
When the agent needs to find relevant skills (e.g., user asks "sync my Slack"), it:
|
|
204
|
+
|
|
205
|
+
1. Loads all installed skill metadata (name, description, tags)
|
|
206
|
+
2. Matches against the user's request using description + tags
|
|
207
|
+
3. For agent-mode skills: reads the full SKILL.md instructions
|
|
208
|
+
4. For script-mode skills: executes the entry point
|
|
209
|
+
|
|
210
|
+
The `description` field is critical for discovery. Write it with:
|
|
211
|
+
- Action verbs: "Pull", "Sync", "Search", "Analyze"
|
|
212
|
+
- Domain keywords: "Slack", "messages", "channels"
|
|
213
|
+
- Use case phrases: "keep conversation context fresh"
|
|
214
|
+
|
|
215
|
+
## Skill Locations & Precedence
|
|
216
|
+
|
|
217
|
+
Skills are loaded from multiple locations. Higher precedence wins on name conflicts:
|
|
218
|
+
|
|
219
|
+
1. **Workspace skills** (highest): `<project>/.wall-e/skills/`
|
|
220
|
+
2. **User skills**: `~/.wall-e/skills/`
|
|
221
|
+
3. **Bundled skills**: `wall-e/skills/_bundled/`
|
|
222
|
+
4. **Registry skills** (lowest): `~/.wall-e/registry-skills/`
|
|
223
|
+
|
|
224
|
+
## Bundled Skills
|
|
225
|
+
|
|
226
|
+
WALL-E ships with these default skills:
|
|
227
|
+
|
|
228
|
+
| Skill | Execution | Description |
|
|
229
|
+
|-------|-----------|-------------|
|
|
230
|
+
| `slack-sync` | script | Incremental Slack message sync |
|
|
231
|
+
| `slack-backfill` | script | Full Slack history backfill |
|
|
232
|
+
| `slack-search` | agent | Search Slack messages with context |
|
|
233
|
+
| `morning-briefing` | agent | Daily meeting prep with calendar + Slack context |
|
|
234
|
+
| `team-pulse` | agent | Monitor team messages for urgent items |
|
|
235
|
+
| `memory-search` | agent | Search and summarize memories |
|
|
236
|
+
|
|
237
|
+
## Skill ↔ Task Relationship
|
|
238
|
+
|
|
239
|
+
Tasks reference skills by name. A task defines WHEN to run; the skill defines HOW.
|
|
240
|
+
|
|
241
|
+
```
|
|
242
|
+
Task: "Conversation Sync"
|
|
243
|
+
type: recurring
|
|
244
|
+
schedule: "every 15m"
|
|
245
|
+
skill: "slack-sync" # ← references the skill
|
|
246
|
+
skill_config: { mode: "incremental" } # ← overrides skill defaults
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
A task can also chain multiple skills:
|
|
250
|
+
```
|
|
251
|
+
Task: "Morning Briefing"
|
|
252
|
+
type: recurring
|
|
253
|
+
schedule: "daily at 7am"
|
|
254
|
+
skill: "morning-briefing" # Agent skill that internally uses:
|
|
255
|
+
# - slack-search (find recent context)
|
|
256
|
+
# - memory-search (find related memories)
|
|
257
|
+
# - calendar integration
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Configuration
|
|
261
|
+
|
|
262
|
+
Skills define a config schema in frontmatter. Tasks can override defaults:
|
|
263
|
+
|
|
264
|
+
```yaml
|
|
265
|
+
# In SKILL.md
|
|
266
|
+
config:
|
|
267
|
+
mode:
|
|
268
|
+
type: string
|
|
269
|
+
enum: [incremental, full]
|
|
270
|
+
default: incremental
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
```json
|
|
274
|
+
// In task definition
|
|
275
|
+
{
|
|
276
|
+
"skill": "slack-sync",
|
|
277
|
+
"skill_config": { "mode": "full" }
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Skill Development
|
|
282
|
+
|
|
283
|
+
### Creating a new skill
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
wall-e skill create my-skill # Scaffold a new skill directory
|
|
287
|
+
wall-e skill test my-skill # Run the skill locally
|
|
288
|
+
wall-e skill validate my-skill # Check SKILL.md format
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Publishing
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
wall-e skill publish my-skill # Publish to registry
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Installing third-party skills
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
wall-e skill install <name> # From registry
|
|
301
|
+
wall-e skill install <git-url> # From Git repo
|
|
302
|
+
wall-e skill list # Show installed skills
|
|
303
|
+
wall-e skill update --all # Update all skills
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Security Model
|
|
307
|
+
|
|
308
|
+
1. **Bundled skills** — Trusted, shipped with WALL-E
|
|
309
|
+
2. **User skills** — Created by the user, trusted by default
|
|
310
|
+
3. **Registry skills** — Third-party, require explicit permission grant
|
|
311
|
+
- Permissions declared in `permissions` field
|
|
312
|
+
- Shown to user before installation
|
|
313
|
+
- Sandboxed: no access beyond declared permissions
|
|
314
|
+
|
|
315
|
+
## Migration from Current System
|
|
316
|
+
|
|
317
|
+
### Current → New
|
|
318
|
+
|
|
319
|
+
| Current | New |
|
|
320
|
+
|---------|-----|
|
|
321
|
+
| `scripts/slack-backfill.js` | `skills/_bundled/slack-backfill/run.js` + `SKILL.md` |
|
|
322
|
+
| `scripts/slack-channel-history.js` | `skills/_bundled/slack-sync/run.js` + `SKILL.md` |
|
|
323
|
+
| `skills/slack-pull-live.js` | `skills/_bundled/slack-sync/incremental.js` |
|
|
324
|
+
| Task with `execution: script` | Task with `skill: "slack-sync"` |
|
|
325
|
+
| Task with `execution: chat` | Task with `skill: "morning-briefing"` |
|
|
326
|
+
| `skills` DB table | Filesystem-based skills + DB for execution history |
|