thinkncollab-shell 0.0.6 → 0.0.7

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/src/core/shell.js CHANGED
@@ -35,7 +35,7 @@ class ThinkNCollabShell extends EventEmitter {
35
35
  configDir: path.join(os.homedir(), '.thinkncollab'),
36
36
  maxHistory: 1000,
37
37
  websocket: {
38
- serverUrl: options.serverUrl || 'https://thinkncollab.com',
38
+ serverUrl: options.serverUrl || 'http://localhost:3001',
39
39
  autoConnect: options.autoConnect || false
40
40
  },
41
41
  ...options
@@ -54,8 +54,8 @@ class ThinkNCollabShell extends EventEmitter {
54
54
  this.tcpServer = null;
55
55
 
56
56
  this.api = new ThinkNCollabAPI({
57
- apiUrl: options.apiUrl || 'https://thinkncollab.com',
58
- wsUrl: options.wsUrl || 'https://thinkncollab.com'
57
+ apiUrl: options.apiUrl || 'http://localhost:3001',
58
+ wsUrl: options.wsUrl || 'http://localhost:3001'
59
59
  });
60
60
 
61
61
  this.commands = new Map();
@@ -138,49 +138,67 @@ class ThinkNCollabShell extends EventEmitter {
138
138
 
139
139
  // ─── WebSocket → Shell + TCP bridge ──────────────────────────────────────
140
140
 
141
- setupWebSocketHandlers() {
142
- this.ws.on('connected', (d) => this.pushNotification({ type: 'connected', socketId: d.socketId }));
143
- this.ws.on('disconnected', (d) => this.pushNotification({ type: 'disconnected', reason: d.reason }));
144
- this.ws.on('reconnected', () => this.pushNotification({ type: 'connected', socketId: 'reconnected' }));
141
+ setupWebSocketHandlers() {
142
+ this.ws.on('connected', (d) => {
143
+ this.api.logEvent('connected', null, { socketId: d?.socketId });
144
+ this.api.startHeartbeat();
145
+ this.pushNotification({ type: 'connected', socketId: d?.socketId });
146
+ });
145
147
 
146
- this.ws.on('message', (d) => {
147
- const myId = this.api.getUser()?._id;
148
- if (myId && d.userId === myId) return;
149
- this.pushNotification({ type: 'message', from: d.username, text: d.message });
150
- });
148
+ this.ws.on('disconnected', (d) => {
149
+ this.api.logEvent('disconnected', null, { reason: d?.reason });
150
+ this.api.stopHeartbeat();
151
+ this.pushNotification({ type: 'disconnected', reason: d?.reason });
152
+ });
151
153
 
152
- this.ws.on('messageHistory', (messages) => {
153
- if (!messages?.length) return;
154
- console.log(chalk.dim('\n ─── Room History ───────────────────────────────'));
155
- messages.forEach(msg => {
156
- const from = msg.name || msg.username || msg.sender?.name || 'Unknown';
157
- const text = msg.message || msg.content || msg.text || '';
158
- const ts = msg.timestamp || msg.createdAt;
159
- const timeStr = ts ? chalk.dim(`[${new Date(ts).toLocaleTimeString()}]`) : '';
160
- console.log(` ${timeStr} ${chalk.cyan(from + ':')} ${chalk.white(text)}`);
161
- });
162
- console.log(chalk.dim(' ────────────────────────────────────────────────\n'));
163
- });
154
+ this.ws.on('reconnected', () => {
155
+ this.api.logEvent('reconnected');
156
+ this.api.startHeartbeat();
157
+ this.pushNotification({ type: 'connected', socketId: 'reconnected' });
158
+ });
164
159
 
165
- this.ws.on('userJoined', (d) => this.pushNotification({ type: 'userJoined', username: d.username }));
166
- this.ws.on('userLeft', (d) => this.pushNotification({ type: 'userLeft', username: d.username }));
167
-
168
- this.ws.on('notification', (d) => {
169
- this.pushNotification({
170
- type: 'notification',
171
- level: d.type,
172
- title: d.title,
173
- message: d.message,
174
- taskTitle: d.taskTitle,
175
- assignedBy: d.assignedBy,
176
- });
160
+ this.ws.on('message', (d) => {
161
+ const myId = this.api.getUser()?._id;
162
+ if (myId && d.userId === myId) return;
163
+ this.pushNotification({ type: 'message', from: d.username, text: d.message });
164
+ });
165
+
166
+ this.ws.on('messageHistory', (messages) => {
167
+ if (!messages?.length) return;
168
+ console.log(chalk.dim('\n ─── Room History ───────────────────────────────'));
169
+ messages.forEach(msg => {
170
+ const from = msg.name || msg.username || msg.sender?.name || 'Unknown';
171
+ const text = msg.message || msg.content || msg.text || '';
172
+ const ts = msg.timestamp || msg.createdAt;
173
+ const timeStr = ts ? chalk.dim(`[${new Date(ts).toLocaleTimeString()}]`) : '';
174
+ console.log(` ${timeStr} ${chalk.cyan(from + ':')} ${chalk.white(text)}`);
177
175
  });
176
+ console.log(chalk.dim(' ────────────────────────────────────────────────\n'));
177
+ });
178
178
 
179
- this.ws.on('error', (e) => {
180
- console.log(chalk.red(`⚠️ WebSocket error: ${e.message}`));
181
- this.pushNotification({ type: 'notification', level: 'error', title: 'WebSocket Error', message: e.message });
179
+ this.ws.on('userJoined', (d) => this.pushNotification({ type: 'userJoined', username: d.username }));
180
+ this.ws.on('userLeft', (d) => this.pushNotification({ type: 'userLeft', username: d.username }));
181
+
182
+ // room join/leave events
183
+ this.ws.on('joined', (roomId) => this.api.logEvent('room_join', roomId));
184
+ this.ws.on('left', (roomId) => this.api.logEvent('room_leave', roomId));
185
+
186
+ this.ws.on('notification', (d) => {
187
+ this.pushNotification({
188
+ type: 'notification',
189
+ level: d.type,
190
+ title: d.title,
191
+ message: d.message,
192
+ taskTitle: d.taskTitle,
193
+ assignedBy: d.assignedBy,
182
194
  });
183
- }
195
+ });
196
+
197
+ this.ws.on('error', (e) => {
198
+ console.log(chalk.red(`⚠️ WebSocket error: ${e.message}`));
199
+ this.pushNotification({ type: 'notification', level: 'error', title: 'WebSocket Error', message: e.message });
200
+ });
201
+ }
184
202
 
185
203
  // ─── Start ────────────────────────────────────────────────────────────────
186
204
 
@@ -233,11 +251,11 @@ class ThinkNCollabShell extends EventEmitter {
233
251
  try {
234
252
  cfg = loadProjectConfig();
235
253
  } catch (err) {
236
- console.log(chalk.yellow(`⚠️ .tncproject: ${err.message}\n`));
254
+ console.log(chalk.yellow(`⚠️ tncproject: ${err.message}\n`));
237
255
  return false;
238
256
  }
239
257
 
240
- console.log(chalk.dim(` 📄 .tncproject found`));
258
+ console.log(chalk.dim(` 📄 tncproject found`));
241
259
  console.log(chalk.dim(` Room : ${cfg.roomId}`));
242
260
  console.log(chalk.dim(` File : ${cfg.filePath}\n`));
243
261
 
@@ -249,7 +267,7 @@ class ThinkNCollabShell extends EventEmitter {
249
267
  roomId: cfg.roomId,
250
268
  });
251
269
  } catch (err) {
252
- console.log(chalk.red(`❌ .tncproject auth failed: ${err.message}`));
270
+ console.log(chalk.red(`❌ tncproject auth failed: ${err.message}`));
253
271
  console.log(chalk.dim(' Falling back to manual login.\n'));
254
272
  return false;
255
273
  }
@@ -521,7 +539,7 @@ async execute(input) {
521
539
  try { const figlet = require('figlet'); console.log(chalk.cyan(figlet.textSync('ThinkNCollab', { font: 'Standard' }))); } catch {}
522
540
  console.log(chalk.cyan(`
523
541
  ╔══════════════════════════════════════════════════════╗
524
- ║ ThinkNCollab Shell v0.0.5 ║
542
+ ║ ThinkNCollab Shell v0.0.6 ║
525
543
  ║ Type 'help' for commands ║
526
544
  ╚══════════════════════════════════════════════════════╝`));
527
545
  }
@@ -537,11 +555,12 @@ async execute(input) {
537
555
  try { fs.writeFileSync(this.config.historyFile, this.history.slice(-this.config.maxHistory).join('\n')); } catch {}
538
556
  }
539
557
 
540
- cleanup() {
541
- if (this.tcpServer) { try { this.tcpServer.close(); } catch {} }
542
- if (this.ws) this.ws.disconnect();
543
- this.saveHistory();
544
- }
558
+ cleanup() {
559
+ this.api.logout(); // session end + heartbeat stop + lastSeen update
560
+ if (this.tcpServer) { try { this.tcpServer.close(); } catch {} }
561
+ if (this.ws) this.ws.disconnect();
562
+ this.saveHistory();
563
+ }
545
564
  }
546
565
 
547
566
  module.exports = ThinkNCollabShell;
@@ -10,7 +10,7 @@ class WebSocketManager extends EventEmitter {
10
10
  constructor(config = {}) {
11
11
  super();
12
12
  this.config = {
13
- serverUrl: config.serverUrl || 'https://thinkncollab.com',
13
+ serverUrl: config.serverUrl || 'http://localhost:3001',
14
14
  reconnectAttempts: config.reconnectAttempts || 5,
15
15
  reconnectDelay: config.reconnectDelay || 1000,
16
16
  ...config