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.
Files changed (136) hide show
  1. package/bin/create-walle.js +134 -0
  2. package/package.json +18 -0
  3. package/template/.env.example +40 -0
  4. package/template/CLAUDE.md +12 -0
  5. package/template/LICENSE +21 -0
  6. package/template/README.md +167 -0
  7. package/template/bin/setup.js +100 -0
  8. package/template/claude-code-skill.md +60 -0
  9. package/template/claude-task-manager/api-prompts.js +1841 -0
  10. package/template/claude-task-manager/api-reviews.js +275 -0
  11. package/template/claude-task-manager/approval-agent.js +454 -0
  12. package/template/claude-task-manager/bin/restart-ctm.sh +16 -0
  13. package/template/claude-task-manager/db.js +1721 -0
  14. package/template/claude-task-manager/docs/PROMPT-MANAGEMENT-DESIGN.md +631 -0
  15. package/template/claude-task-manager/git-utils.js +214 -0
  16. package/template/claude-task-manager/package-lock.json +1607 -0
  17. package/template/claude-task-manager/package.json +31 -0
  18. package/template/claude-task-manager/prompt-harvest.js +1148 -0
  19. package/template/claude-task-manager/public/css/prompts.css +880 -0
  20. package/template/claude-task-manager/public/css/reviews.css +430 -0
  21. package/template/claude-task-manager/public/css/walle.css +732 -0
  22. package/template/claude-task-manager/public/favicon.ico +0 -0
  23. package/template/claude-task-manager/public/icon.svg +37 -0
  24. package/template/claude-task-manager/public/index.html +8346 -0
  25. package/template/claude-task-manager/public/js/prompts.js +3159 -0
  26. package/template/claude-task-manager/public/js/reviews.js +1292 -0
  27. package/template/claude-task-manager/public/js/walle.js +3081 -0
  28. package/template/claude-task-manager/public/manifest.json +13 -0
  29. package/template/claude-task-manager/public/prompts.html +4353 -0
  30. package/template/claude-task-manager/public/setup.html +216 -0
  31. package/template/claude-task-manager/queue-engine.js +404 -0
  32. package/template/claude-task-manager/server-state.js +5 -0
  33. package/template/claude-task-manager/server.js +2254 -0
  34. package/template/claude-task-manager/session-utils.js +124 -0
  35. package/template/claude-task-manager/start.sh +17 -0
  36. package/template/claude-task-manager/tests/test-ai-search.js +61 -0
  37. package/template/claude-task-manager/tests/test-editor-ux.js +76 -0
  38. package/template/claude-task-manager/tests/test-editor-ux2.js +51 -0
  39. package/template/claude-task-manager/tests/test-features-v2.js +127 -0
  40. package/template/claude-task-manager/tests/test-insights-cached.js +78 -0
  41. package/template/claude-task-manager/tests/test-insights.js +124 -0
  42. package/template/claude-task-manager/tests/test-permissions-v2.js +127 -0
  43. package/template/claude-task-manager/tests/test-permissions.js +122 -0
  44. package/template/claude-task-manager/tests/test-pin.js +51 -0
  45. package/template/claude-task-manager/tests/test-prompts.js +164 -0
  46. package/template/claude-task-manager/tests/test-recent-sessions.js +96 -0
  47. package/template/claude-task-manager/tests/test-review.js +104 -0
  48. package/template/claude-task-manager/tests/test-send-dropdown.js +76 -0
  49. package/template/claude-task-manager/tests/test-send-final.js +30 -0
  50. package/template/claude-task-manager/tests/test-send-fixes.js +76 -0
  51. package/template/claude-task-manager/tests/test-send-integration.js +107 -0
  52. package/template/claude-task-manager/tests/test-send-visual.js +34 -0
  53. package/template/claude-task-manager/tests/test-session-create.js +147 -0
  54. package/template/claude-task-manager/tests/test-sidebar-ux.js +83 -0
  55. package/template/claude-task-manager/tests/test-url-hash.js +68 -0
  56. package/template/claude-task-manager/tests/test-ux-crop.js +34 -0
  57. package/template/claude-task-manager/tests/test-ux-review.js +130 -0
  58. package/template/claude-task-manager/tests/test-zoom-card.js +76 -0
  59. package/template/claude-task-manager/tests/test-zoom.js +92 -0
  60. package/template/claude-task-manager/tests/test-zoom2.js +67 -0
  61. package/template/docs/site/api/README.md +187 -0
  62. package/template/docs/site/guides/claude-code.md +58 -0
  63. package/template/docs/site/guides/configuration.md +96 -0
  64. package/template/docs/site/guides/quickstart.md +158 -0
  65. package/template/docs/site/index.md +14 -0
  66. package/template/docs/site/skills/README.md +135 -0
  67. package/template/wall-e/.dockerignore +11 -0
  68. package/template/wall-e/Dockerfile +25 -0
  69. package/template/wall-e/adapters/adapter-base.js +37 -0
  70. package/template/wall-e/adapters/ctm.js +193 -0
  71. package/template/wall-e/adapters/slack.js +56 -0
  72. package/template/wall-e/agent.js +319 -0
  73. package/template/wall-e/api-walle.js +1073 -0
  74. package/template/wall-e/brain.js +1235 -0
  75. package/template/wall-e/channels/agent-api.js +172 -0
  76. package/template/wall-e/channels/channel-base.js +14 -0
  77. package/template/wall-e/channels/imessage-channel.js +113 -0
  78. package/template/wall-e/channels/slack-channel.js +118 -0
  79. package/template/wall-e/chat.js +778 -0
  80. package/template/wall-e/decision/confidence.js +93 -0
  81. package/template/wall-e/deploy.sh +35 -0
  82. package/template/wall-e/docs/specs/2026-04-01-publish-plan.md +112 -0
  83. package/template/wall-e/docs/specs/SKILL-FORMAT.md +326 -0
  84. package/template/wall-e/extraction/contradiction.js +168 -0
  85. package/template/wall-e/extraction/knowledge-extractor.js +190 -0
  86. package/template/wall-e/fly.toml +24 -0
  87. package/template/wall-e/loops/ingest.js +34 -0
  88. package/template/wall-e/loops/reflect.js +63 -0
  89. package/template/wall-e/loops/tasks.js +487 -0
  90. package/template/wall-e/loops/think.js +125 -0
  91. package/template/wall-e/package-lock.json +533 -0
  92. package/template/wall-e/package.json +18 -0
  93. package/template/wall-e/scripts/ingest-slack-search.js +85 -0
  94. package/template/wall-e/scripts/pull-slack-via-claude.js +98 -0
  95. package/template/wall-e/scripts/slack-backfill.js +295 -0
  96. package/template/wall-e/scripts/slack-channel-history.js +454 -0
  97. package/template/wall-e/server.js +93 -0
  98. package/template/wall-e/skills/_bundled/email-digest/SKILL.md +95 -0
  99. package/template/wall-e/skills/_bundled/email-sync/SKILL.md +65 -0
  100. package/template/wall-e/skills/_bundled/email-sync/mail-reader.jxa +104 -0
  101. package/template/wall-e/skills/_bundled/email-sync/run.js +213 -0
  102. package/template/wall-e/skills/_bundled/google-calendar/SKILL.md +73 -0
  103. package/template/wall-e/skills/_bundled/google-calendar/cal-reader.swift +81 -0
  104. package/template/wall-e/skills/_bundled/google-calendar/run.js +181 -0
  105. package/template/wall-e/skills/_bundled/memory-search/SKILL.md +92 -0
  106. package/template/wall-e/skills/_bundled/morning-briefing/SKILL.md +131 -0
  107. package/template/wall-e/skills/_bundled/morning-briefing/run.js +264 -0
  108. package/template/wall-e/skills/_bundled/slack-backfill/SKILL.md +60 -0
  109. package/template/wall-e/skills/_bundled/slack-sync/SKILL.md +55 -0
  110. package/template/wall-e/skills/claude-code-reader.js +144 -0
  111. package/template/wall-e/skills/mcp-client.js +407 -0
  112. package/template/wall-e/skills/skill-executor.js +163 -0
  113. package/template/wall-e/skills/skill-loader.js +410 -0
  114. package/template/wall-e/skills/skill-planner.js +88 -0
  115. package/template/wall-e/skills/slack-ingest.js +329 -0
  116. package/template/wall-e/skills/slack-pull-live.js +270 -0
  117. package/template/wall-e/skills/tool-executor.js +188 -0
  118. package/template/wall-e/tests/adapter-base.test.js +20 -0
  119. package/template/wall-e/tests/adapter-ctm.test.js +122 -0
  120. package/template/wall-e/tests/adapter-slack.test.js +98 -0
  121. package/template/wall-e/tests/agent-api.test.js +256 -0
  122. package/template/wall-e/tests/api-walle.test.js +222 -0
  123. package/template/wall-e/tests/brain.test.js +602 -0
  124. package/template/wall-e/tests/channels.test.js +104 -0
  125. package/template/wall-e/tests/chat.test.js +103 -0
  126. package/template/wall-e/tests/confidence.test.js +134 -0
  127. package/template/wall-e/tests/contradiction.test.js +217 -0
  128. package/template/wall-e/tests/ingest.test.js +113 -0
  129. package/template/wall-e/tests/mcp-client.test.js +71 -0
  130. package/template/wall-e/tests/reflect.test.js +103 -0
  131. package/template/wall-e/tests/server.test.js +111 -0
  132. package/template/wall-e/tests/skills.test.js +198 -0
  133. package/template/wall-e/tests/slack-ingest.test.js +103 -0
  134. package/template/wall-e/tests/think.test.js +435 -0
  135. package/template/wall-e/tools/local-tools.js +697 -0
  136. 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
+ });