@teamvibe/poller 0.1.39 → 0.1.40

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.
@@ -4,6 +4,7 @@ import { uninstall } from './uninstall.js';
4
4
  import { update } from './update.js';
5
5
  import { logs } from './logs.js';
6
6
  import { start, stop, restart, status } from './service.js';
7
+ import { reset } from './reset.js';
7
8
  function showHelp() {
8
9
  console.log(`TeamVibe Poller
9
10
 
@@ -18,6 +19,7 @@ Commands:
18
19
  start Start the installed service
19
20
  stop Stop the installed service
20
21
  restart Restart the installed service
22
+ reset Stop, kill Claude processes, clean locks, restart
21
23
  status Show service status
22
24
  logs Tail service logs
23
25
  --version, -v Show version
@@ -55,6 +57,9 @@ export async function handleCommand(command) {
55
57
  case 'restart':
56
58
  restart();
57
59
  break;
60
+ case 'reset':
61
+ await reset();
62
+ break;
58
63
  case 'status':
59
64
  console.log(`Version: ${getVersion()}`);
60
65
  status();
@@ -0,0 +1 @@
1
+ export declare function reset(): Promise<void>;
@@ -0,0 +1,118 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { execSync } from 'child_process';
4
+ import { stop, start } from './service.js';
5
+ import { PLIST_PATH } from './plist.js';
6
+ const DEFAULT_DATA_DIR = `${process.env['HOME']}/.teamvibe`;
7
+ function getBaseBrainPath() {
8
+ return process.env['BASE_BRAIN_PATH'] || `${DEFAULT_DATA_DIR}/base-brain`;
9
+ }
10
+ function cleanClaudeSessionLocks() {
11
+ const baseBrainPath = getBaseBrainPath();
12
+ let cleaned = 0;
13
+ // Claude Code stores session locks in the config dir (which is base-brain for poller)
14
+ // Look for .lock files in tasks/ and projects/ subdirectories
15
+ const lockDirs = [
16
+ path.join(baseBrainPath, 'tasks'),
17
+ path.join(baseBrainPath, 'projects'),
18
+ ];
19
+ for (const dir of lockDirs) {
20
+ if (!fs.existsSync(dir))
21
+ continue;
22
+ cleanLocksRecursive(dir);
23
+ }
24
+ // Also check ~/.claude for lock files (default Claude config dir)
25
+ const claudeDir = `${process.env['HOME']}/.claude`;
26
+ if (fs.existsSync(claudeDir)) {
27
+ cleaned += cleanLocksRecursive(path.join(claudeDir, 'tasks'));
28
+ cleaned += cleanLocksRecursive(path.join(claudeDir, 'projects'));
29
+ }
30
+ return cleaned;
31
+ }
32
+ function cleanLocksRecursive(dir) {
33
+ if (!fs.existsSync(dir))
34
+ return 0;
35
+ let cleaned = 0;
36
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
37
+ for (const entry of entries) {
38
+ const fullPath = path.join(dir, entry.name);
39
+ if (entry.isDirectory()) {
40
+ cleaned += cleanLocksRecursive(fullPath);
41
+ }
42
+ else if (entry.name === '.lock') {
43
+ fs.unlinkSync(fullPath);
44
+ console.log(` Removed: ${fullPath}`);
45
+ cleaned++;
46
+ }
47
+ }
48
+ return cleaned;
49
+ }
50
+ function killClaudeProcesses() {
51
+ try {
52
+ const output = execSync('pgrep -f "claude.*--print" 2>/dev/null || true', {
53
+ encoding: 'utf-8',
54
+ }).trim();
55
+ if (!output)
56
+ return 0;
57
+ const pids = output.split('\n').filter(Boolean);
58
+ for (const pid of pids) {
59
+ try {
60
+ process.kill(parseInt(pid), 'SIGTERM');
61
+ console.log(` Killed Claude process: ${pid}`);
62
+ }
63
+ catch {
64
+ // Process may have already exited
65
+ }
66
+ }
67
+ return pids.length;
68
+ }
69
+ catch {
70
+ return 0;
71
+ }
72
+ }
73
+ export async function reset() {
74
+ const isServiceInstalled = fs.existsSync(PLIST_PATH);
75
+ console.log('Resetting TeamVibe Poller...\n');
76
+ // Step 1: Stop service if installed
77
+ if (isServiceInstalled) {
78
+ console.log('1. Stopping service...');
79
+ try {
80
+ stop();
81
+ }
82
+ catch {
83
+ console.log(' Service was not running');
84
+ }
85
+ }
86
+ else {
87
+ console.log('1. No service installed, skipping stop');
88
+ }
89
+ // Step 2: Kill any lingering Claude processes
90
+ console.log('\n2. Killing lingering Claude processes...');
91
+ const killed = killClaudeProcesses();
92
+ if (killed === 0) {
93
+ console.log(' No Claude processes found');
94
+ }
95
+ else {
96
+ console.log(` Killed ${killed} process(es)`);
97
+ // Give processes time to exit and release locks
98
+ await new Promise((resolve) => setTimeout(resolve, 2000));
99
+ }
100
+ // Step 3: Clean session lock files
101
+ console.log('\n3. Cleaning session lock files...');
102
+ const cleaned = cleanClaudeSessionLocks();
103
+ if (cleaned === 0) {
104
+ console.log(' No lock files found');
105
+ }
106
+ else {
107
+ console.log(` Cleaned ${cleaned} lock file(s)`);
108
+ }
109
+ // Step 4: Restart service if it was installed
110
+ if (isServiceInstalled) {
111
+ console.log('\n4. Restarting service...');
112
+ start();
113
+ }
114
+ else {
115
+ console.log('\n4. No service to restart');
116
+ }
117
+ console.log('\nReset complete!');
118
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamvibe/poller",
3
- "version": "0.1.39",
3
+ "version": "0.1.40",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {