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,222 @@
|
|
|
1
|
+
const { describe, it, before, after } = require('node:test');
|
|
2
|
+
const assert = require('node:assert/strict');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
|
|
7
|
+
const brain = require('../brain.js');
|
|
8
|
+
const api = require('../api-walle.js');
|
|
9
|
+
|
|
10
|
+
let testDir;
|
|
11
|
+
|
|
12
|
+
function setupTestDb() {
|
|
13
|
+
testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'wall-e-api-test-'));
|
|
14
|
+
const testDbPath = path.join(testDir, 'test-brain.db');
|
|
15
|
+
brain.initDb(testDbPath);
|
|
16
|
+
|
|
17
|
+
// Point the API read DB at the same test database
|
|
18
|
+
const Database = require('better-sqlite3');
|
|
19
|
+
const readDb = new Database(testDbPath, { readonly: true });
|
|
20
|
+
readDb.pragma('journal_mode = WAL');
|
|
21
|
+
api._setReadDb(readDb);
|
|
22
|
+
api._setBrain(brain);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function teardownTestDb() {
|
|
26
|
+
try { brain.closeDb(); } catch (_) {}
|
|
27
|
+
if (testDir && fs.existsSync(testDir)) {
|
|
28
|
+
fs.rmSync(testDir, { recursive: true, force: true });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function makeParams(obj = {}) {
|
|
33
|
+
return new URLSearchParams(obj);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Seed test data
|
|
37
|
+
function seedData() {
|
|
38
|
+
brain.setOwner('name', 'Test User');
|
|
39
|
+
|
|
40
|
+
brain.insertMemory({
|
|
41
|
+
source: 'slack', source_id: 'msg-1', memory_type: 'message',
|
|
42
|
+
content: 'Hello world', timestamp: '2025-01-15T10:00:00Z'
|
|
43
|
+
});
|
|
44
|
+
brain.insertMemory({
|
|
45
|
+
source: 'email', source_id: 'email-1', memory_type: 'email',
|
|
46
|
+
content: 'Project update', timestamp: '2025-01-15T11:00:00Z'
|
|
47
|
+
});
|
|
48
|
+
brain.insertMemory({
|
|
49
|
+
source: 'slack', source_id: 'msg-2', memory_type: 'message',
|
|
50
|
+
content: 'Older message', timestamp: '2025-01-14T09:00:00Z'
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
brain.insertKnowledge({
|
|
54
|
+
category: 'preference', subject: 'user', predicate: 'prefers', object: 'dark mode'
|
|
55
|
+
});
|
|
56
|
+
brain.insertKnowledge({
|
|
57
|
+
category: 'fact', subject: 'project-x', predicate: 'uses', object: 'Node.js'
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
brain.insertPerson({ name: 'Alice', relationship: 'colleague' });
|
|
61
|
+
brain.insertPerson({ name: 'Bob', relationship: 'friend' });
|
|
62
|
+
|
|
63
|
+
brain.insertQuestion({
|
|
64
|
+
question_type: 'clarification', question: 'What is the deploy schedule?'
|
|
65
|
+
});
|
|
66
|
+
brain.insertQuestion({
|
|
67
|
+
question_type: 'preference', question: 'Which editor do you prefer?'
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
describe('WALL-E API handlers', () => {
|
|
72
|
+
before(() => {
|
|
73
|
+
setupTestDb();
|
|
74
|
+
seedData();
|
|
75
|
+
});
|
|
76
|
+
after(() => teardownTestDb());
|
|
77
|
+
|
|
78
|
+
describe('getStatus', () => {
|
|
79
|
+
it('returns object with owner and stats fields', () => {
|
|
80
|
+
const result = api.getStatus();
|
|
81
|
+
assert.equal(result.owner, 'Test User');
|
|
82
|
+
assert.ok(result.stats);
|
|
83
|
+
assert.equal(typeof result.stats.memory_count, 'number');
|
|
84
|
+
assert.equal(typeof result.stats.knowledge_count, 'number');
|
|
85
|
+
assert.equal(typeof result.stats.people_count, 'number');
|
|
86
|
+
assert.equal(typeof result.stats.pattern_count, 'number');
|
|
87
|
+
assert.equal(typeof result.stats.pending_question_count, 'number');
|
|
88
|
+
assert.equal(result.stats.memory_count, 3);
|
|
89
|
+
assert.equal(result.stats.knowledge_count, 2);
|
|
90
|
+
assert.equal(result.stats.people_count, 2);
|
|
91
|
+
assert.equal(result.stats.pending_question_count, 2);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe('getKnowledgeList', () => {
|
|
96
|
+
it('returns all knowledge with no filters', () => {
|
|
97
|
+
const result = api.getKnowledgeList(makeParams());
|
|
98
|
+
assert.ok(Array.isArray(result));
|
|
99
|
+
assert.equal(result.length, 2);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('filters by category', () => {
|
|
103
|
+
const result = api.getKnowledgeList(makeParams({ category: 'preference' }));
|
|
104
|
+
assert.equal(result.length, 1);
|
|
105
|
+
assert.equal(result[0].subject, 'user');
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('filters by subject', () => {
|
|
109
|
+
const result = api.getKnowledgeList(makeParams({ subject: 'project-x' }));
|
|
110
|
+
assert.equal(result.length, 1);
|
|
111
|
+
assert.equal(result[0].object, 'Node.js');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('filters by status', () => {
|
|
115
|
+
const result = api.getKnowledgeList(makeParams({ status: 'active' }));
|
|
116
|
+
assert.equal(result.length, 2);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('respects limit and offset', () => {
|
|
120
|
+
const result = api.getKnowledgeList(makeParams({ limit: '1', offset: '0' }));
|
|
121
|
+
assert.equal(result.length, 1);
|
|
122
|
+
const result2 = api.getKnowledgeList(makeParams({ limit: '1', offset: '1' }));
|
|
123
|
+
assert.equal(result2.length, 1);
|
|
124
|
+
assert.notEqual(result[0].id, result2[0].id);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('getMemoriesList', () => {
|
|
129
|
+
it('returns all memories with no filters', () => {
|
|
130
|
+
const result = api.getMemoriesList(makeParams());
|
|
131
|
+
assert.ok(Array.isArray(result));
|
|
132
|
+
assert.equal(result.length, 3);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('filters by source', () => {
|
|
136
|
+
const result = api.getMemoriesList(makeParams({ source: 'slack' }));
|
|
137
|
+
assert.equal(result.length, 2);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('filters by since', () => {
|
|
141
|
+
const result = api.getMemoriesList(makeParams({ since: '2025-01-15T00:00:00Z' }));
|
|
142
|
+
assert.equal(result.length, 2);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('respects limit', () => {
|
|
146
|
+
const result = api.getMemoriesList(makeParams({ limit: '1' }));
|
|
147
|
+
assert.equal(result.length, 1);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('getPeopleList', () => {
|
|
152
|
+
it('returns all people', () => {
|
|
153
|
+
const result = api.getPeopleList();
|
|
154
|
+
assert.ok(Array.isArray(result));
|
|
155
|
+
assert.equal(result.length, 2);
|
|
156
|
+
// Ordered by name
|
|
157
|
+
assert.equal(result[0].name, 'Alice');
|
|
158
|
+
assert.equal(result[1].name, 'Bob');
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
describe('getTimeline', () => {
|
|
163
|
+
it('returns memories ordered by timestamp DESC', () => {
|
|
164
|
+
const result = api.getTimeline(makeParams());
|
|
165
|
+
assert.ok(Array.isArray(result));
|
|
166
|
+
assert.equal(result.length, 3);
|
|
167
|
+
// Most recent first
|
|
168
|
+
assert.ok(result[0].timestamp >= result[1].timestamp);
|
|
169
|
+
assert.ok(result[1].timestamp >= result[2].timestamp);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('respects limit and offset', () => {
|
|
173
|
+
const result = api.getTimeline(makeParams({ limit: '2' }));
|
|
174
|
+
assert.equal(result.length, 2);
|
|
175
|
+
const result2 = api.getTimeline(makeParams({ limit: '2', offset: '2' }));
|
|
176
|
+
assert.equal(result2.length, 1);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe('getQuestionsList', () => {
|
|
181
|
+
it('returns pending questions by default', () => {
|
|
182
|
+
const result = api.getQuestionsList(makeParams());
|
|
183
|
+
assert.ok(Array.isArray(result));
|
|
184
|
+
assert.equal(result.length, 2);
|
|
185
|
+
for (const q of result) {
|
|
186
|
+
assert.equal(q.status, 'pending');
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('filters by status', () => {
|
|
191
|
+
const result = api.getQuestionsList(makeParams({ status: 'answered' }));
|
|
192
|
+
assert.equal(result.length, 0);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe('getStats', () => {
|
|
197
|
+
it('returns brain stats', () => {
|
|
198
|
+
const result = api.getStats();
|
|
199
|
+
assert.equal(typeof result.memory_count, 'number');
|
|
200
|
+
assert.equal(typeof result.knowledge_count, 'number');
|
|
201
|
+
assert.equal(typeof result.people_count, 'number');
|
|
202
|
+
assert.equal(typeof result.pattern_count, 'number');
|
|
203
|
+
assert.equal(typeof result.pending_question_count, 'number');
|
|
204
|
+
assert.equal(result.memory_count, 3);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
describe('getBrief', () => {
|
|
209
|
+
it('returns null when no summary exists', () => {
|
|
210
|
+
const result = api.getBrief(makeParams({ date: '2025-01-15' }));
|
|
211
|
+
assert.equal(result, null);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('returns summary when it exists', () => {
|
|
215
|
+
brain.insertDailySummary('2025-01-15', 'A productive day', { tasks: 5 });
|
|
216
|
+
const result = api.getBrief(makeParams({ date: '2025-01-15' }));
|
|
217
|
+
assert.ok(result);
|
|
218
|
+
assert.equal(result.date, '2025-01-15');
|
|
219
|
+
assert.equal(result.summary, 'A productive day');
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
});
|