create-walle 0.6.2 → 0.7.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.
@@ -287,11 +287,14 @@ function stopQuiet(dir, port) {
287
287
  if (process.platform === 'darwin' && fs.existsSync(plist)) {
288
288
  try { execFileSync('launchctl', ['unload', plist], { stdio: 'ignore' }); } catch {}
289
289
  }
290
- // Kill process on the port directly
291
- try {
292
- const pids = execFileSync('lsof', ['-ti', ':' + port], { encoding: 'utf8', timeout: 3000 }).trim().split('\n').filter(Boolean);
293
- for (const pid of pids) { try { process.kill(parseInt(pid), 'SIGTERM'); } catch {} }
294
- } catch {}
290
+ // Kill CTM and Wall-E processes
291
+ const wallePort = String(parseInt(port) + 1);
292
+ for (const p of [port, wallePort]) {
293
+ try {
294
+ const pids = execFileSync('lsof', ['-ti', ':' + p], { encoding: 'utf8', timeout: 3000 }).trim().split('\n').filter(Boolean);
295
+ for (const pid of pids) { try { process.kill(parseInt(pid), 'SIGTERM'); } catch {} }
296
+ } catch {}
297
+ }
295
298
  // Brief wait for port to free
296
299
  const deadline = Date.now() + 5000;
297
300
  while (Date.now() < deadline) {
@@ -316,7 +319,7 @@ function startForegroundOrService(dir, port) {
316
319
  // Start in background without launchd
317
320
  const logDir = path.join(process.env.HOME, '.walle', 'logs');
318
321
  fs.mkdirSync(logDir, { recursive: true });
319
- const child = spawn('node', ['claude-task-manager/server.js'], {
322
+ const child = spawn(process.execPath, ['claude-task-manager/server.js'], {
320
323
  cwd: dir,
321
324
  detached: true,
322
325
  stdio: ['ignore', fs.openSync(path.join(logDir, 'walle.log'), 'a'), fs.openSync(path.join(logDir, 'walle.err'), 'a')],
@@ -380,7 +383,7 @@ ${envDict} </dict>
380
383
  try { execFileSync('launchctl', ['unload', plistPath], { stdio: 'ignore' }); } catch {}
381
384
  execFileSync('launchctl', ['load', plistPath]);
382
385
  } else {
383
- const child = spawn('node', ['claude-task-manager/server.js'], {
386
+ const child = spawn(process.execPath, ['claude-task-manager/server.js'], {
384
387
  cwd: walleDir,
385
388
  detached: true,
386
389
  stdio: ['ignore', fs.openSync(path.join(logDir, 'walle.log'), 'a'), fs.openSync(path.join(logDir, 'walle.err'), 'a')],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-walle",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "description": "Wall-E — your personal digital twin. AI agent that learns from Slack, email & calendar. Includes dashboard, chat, and 7 bundled skills.",
5
5
  "bin": {
6
6
  "create-walle": "bin/create-walle.js"
@@ -310,9 +310,10 @@ function handleApi(req, res, url) {
310
310
  while (lines.length && lines[lines.length - 1].trim() === '') lines.pop();
311
311
  lines.push('', `WALLE_MODEL=${model}`);
312
312
  fs.writeFileSync(envPath, lines.join('\n') + '\n', { mode: 0o600 });
313
+ const prevModel = process.env.WALLE_MODEL;
313
314
  process.env.WALLE_MODEL = model;
314
- // Restart Wall-E so it picks up the new model
315
- _restartWalleQuiet();
315
+ // Only restart if model actually changed (save already restarts)
316
+ if (model !== prevModel) _restartWalleQuiet();
316
317
  } catch {}
317
318
  res.end(JSON.stringify({ ok: true, model }));
318
319
  } else if (authError) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "walle",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "private": true,
5
5
  "description": "Wall-E — your personal digital twin",
6
6
  "scripts": {
@@ -97,6 +97,68 @@ function bootstrapSkills() {
97
97
  console.log('[wall-e] Bootstrapped initial skills');
98
98
  }
99
99
 
100
+ function bootstrapTasks() {
101
+ const existing = brain.listTasks({ limit: 100 });
102
+ if (existing.length > 0) return; // Already has tasks
103
+
104
+ const coreTasks = [
105
+ // Recurring scheduled tasks
106
+ {
107
+ title: 'Morning Briefing',
108
+ description: 'Generate a daily morning briefing with calendar, Slack activity, pending tasks, and mentions.',
109
+ type: 'recurring',
110
+ schedule: 'daily at 7am',
111
+ skill: 'morning-briefing',
112
+ priority: 'normal',
113
+ },
114
+ {
115
+ title: 'Sync Calendar',
116
+ description: 'Sync macOS Calendar events (Google, iCloud, Outlook) into Wall-E brain via EventKit.',
117
+ type: 'recurring',
118
+ schedule: 'every 30m',
119
+ skill: 'google-calendar',
120
+ priority: 'normal',
121
+ },
122
+ {
123
+ title: 'Slack: Conversation Sync',
124
+ description: 'Pull latest Slack messages from active conversations into Wall-E brain.',
125
+ type: 'recurring',
126
+ schedule: 'every 15m',
127
+ skill: 'slack-sync',
128
+ priority: 'normal',
129
+ },
130
+ {
131
+ title: 'Email: Conversation Sync',
132
+ description: 'Sync sent and inbox emails from macOS Mail into Wall-E brain.',
133
+ type: 'recurring',
134
+ schedule: 'every 6h',
135
+ skill: 'email-sync',
136
+ priority: 'normal',
137
+ },
138
+ // Manual one-time tasks
139
+ {
140
+ title: 'Slack: Full History Backfill',
141
+ description: 'One-time full Slack history pull (2022-present). Run manually to backfill all past conversations.',
142
+ type: 'once',
143
+ skill: 'slack-backfill',
144
+ priority: 'normal',
145
+ },
146
+ {
147
+ title: 'Email: Full Send History Pull',
148
+ description: 'One-time full sync of sent email history from macOS Mail. Run manually to backfill.',
149
+ type: 'once',
150
+ skill: 'email-sync',
151
+ skill_config: JSON.stringify({ days_back: 90, sync_inbox: true }),
152
+ priority: 'normal',
153
+ },
154
+ ];
155
+
156
+ for (const t of coreTasks) {
157
+ brain.insertTask(t);
158
+ }
159
+ console.log('[wall-e] Bootstrapped ' + coreTasks.length + ' core tasks');
160
+ }
161
+
100
162
  async function main() {
101
163
  console.log('[wall-e] Starting WALL-E agent daemon...');
102
164
 
@@ -111,6 +173,7 @@ async function main() {
111
173
  brain.initDb();
112
174
  brain.startDailyBackup();
113
175
  bootstrapSkills();
176
+ bootstrapTasks();
114
177
 
115
178
  // Set owner from config
116
179
  if (config.owner) {