thinkncollab-shell 0.0.20 → 2.0.0-beta.1.1

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 (201) hide show
  1. package/LICENSE +82 -0
  2. package/Readme.md +246 -502
  3. package/dist/bin/thinknsh.js +8 -0
  4. package/dist/src/commands/auth/login.js +7 -0
  5. package/dist/src/commands/auth/logout.js +7 -0
  6. package/dist/src/commands/auth/register.js +7 -0
  7. package/dist/src/commands/auth/whoami.js +7 -0
  8. package/dist/src/commands/dock/bench.js +7 -0
  9. package/dist/src/commands/dock/ci.js +7 -0
  10. package/dist/src/commands/dock/cluster.js +7 -0
  11. package/dist/src/commands/dock/containers.js +7 -0
  12. package/dist/src/commands/dock/dock.js +7 -0
  13. package/dist/src/commands/github/commits.js +7 -0
  14. package/dist/src/commands/github/issue-create.js +7 -0
  15. package/dist/src/commands/github/issues.js +7 -0
  16. package/dist/src/commands/github/pulls.js +7 -0
  17. package/dist/src/commands/github/statusgh.js +7 -0
  18. package/dist/src/commands/index.js +7 -0
  19. package/dist/src/commands/message/say.js +7 -0
  20. package/dist/src/commands/room/join.js +7 -0
  21. package/dist/src/commands/room/leave.js +7 -0
  22. package/dist/src/commands/room/rooms.js +7 -0
  23. package/dist/src/commands/room/sync.js +7 -0
  24. package/dist/src/commands/sandbox/console.js +7 -0
  25. package/dist/src/commands/sandbox/dep.js +7 -0
  26. package/dist/src/commands/sandbox/deploy.js +7 -0
  27. package/dist/src/commands/sandbox/dev.js +7 -0
  28. package/dist/src/commands/sandbox/exec.js +7 -0
  29. package/dist/src/commands/sandbox/freeze.js +7 -0
  30. package/dist/src/commands/sandbox/push.js +7 -0
  31. package/dist/src/commands/sandbox/resume.js +7 -0
  32. package/dist/src/commands/sandbox/sandbox.js +7 -0
  33. package/dist/src/commands/sandbox/share.js +7 -0
  34. package/dist/src/commands/sandbox/snapshot.js +7 -0
  35. package/dist/src/commands/sandbox/sync-deps.js +7 -0
  36. package/dist/src/commands/shell/doctor.js +7 -0
  37. package/dist/src/commands/shell/notifications.js +7 -0
  38. package/dist/src/commands/shell/notify.js +7 -0
  39. package/dist/src/commands/shell/status.js +7 -0
  40. package/dist/src/commands/shell/version.js +7 -0
  41. package/dist/src/commands/tasks/build.js +7 -0
  42. package/dist/src/commands/tasks/complete.js +7 -0
  43. package/dist/src/commands/tasks/create-task.js +7 -0
  44. package/dist/src/commands/tasks/loadtest.js +7 -0
  45. package/dist/src/commands/tasks/task-status.js +7 -0
  46. package/dist/src/commands/tasks/task.js +7 -0
  47. package/dist/src/commands/tasks/tasks.js +7 -0
  48. package/dist/src/commands/team/invite.js +7 -0
  49. package/dist/src/commands/team/myteam.js +7 -0
  50. package/dist/src/commands/team/teammates.js +7 -0
  51. package/dist/src/commands/terminal/share.js +7 -0
  52. package/dist/src/core/api-client.js +7 -0
  53. package/dist/src/core/crypto/e2ee-vault.js +7 -0
  54. package/dist/src/core/dep-store.js +7 -0
  55. package/dist/src/core/dependency-tracker.js +7 -0
  56. package/dist/src/core/geekload.js +7 -0
  57. package/dist/src/core/local-runner.js +7 -0
  58. package/dist/src/core/multi-lang-scanner.js +7 -0
  59. package/dist/src/core/notification-window.js +8 -0
  60. package/dist/src/core/notify-auth.js +7 -0
  61. package/dist/src/core/project-config.js +7 -0
  62. package/dist/src/core/sandbox/arch-shim.js +7 -0
  63. package/dist/src/core/sandbox/capsule-builder.js +7 -0
  64. package/dist/src/core/sandbox/cgroups.js +7 -0
  65. package/dist/src/core/sandbox/container-monitor.js +7 -0
  66. package/dist/src/core/sandbox/crun-manager.js +7 -0
  67. package/dist/src/core/sandbox/engine.js +7 -0
  68. package/dist/src/core/sandbox/image-manager.js +7 -0
  69. package/dist/src/core/sandbox/image-store.js +7 -0
  70. package/dist/src/core/sandbox/index.js +7 -0
  71. package/dist/src/core/sandbox/macos-sandbox.js +7 -0
  72. package/dist/src/core/sandbox/microvm-manager.js +7 -0
  73. package/dist/src/core/sandbox/native-service-manager.js +7 -0
  74. package/dist/src/core/sandbox/network.js +7 -0
  75. package/dist/src/core/sandbox/oci-exporter.js +7 -0
  76. package/dist/src/core/sandbox/oci-puller.js +7 -0
  77. package/dist/src/core/sandbox/oci-runtime-spec.js +7 -0
  78. package/dist/src/core/sandbox/policy-engine.js +7 -0
  79. package/dist/src/core/sandbox/port-proxy-daemon.js +7 -0
  80. package/dist/src/core/sandbox/room-sync-manager.js +7 -0
  81. package/dist/src/core/sandbox/runtime-manager.js +7 -0
  82. package/dist/src/core/sandbox/snapshot-manager.js +7 -0
  83. package/dist/src/core/sandbox/storage.js +7 -0
  84. package/dist/src/core/sandbox/supervisor.js +7 -0
  85. package/dist/src/core/sandbox/tunnel-daemon.js +7 -0
  86. package/dist/src/core/sandbox/tunnel.js +7 -0
  87. package/dist/src/core/sandbox/window-launcher.js +7 -0
  88. package/dist/src/core/sandbox/windows-wsl2.js +7 -0
  89. package/dist/src/core/sandbox-window.js +8 -0
  90. package/dist/src/core/shell.js +7 -0
  91. package/dist/src/core/websocket.js +7 -0
  92. package/dist/src/dock/api/routes.js +7 -0
  93. package/dist/src/dock/api/server.js +7 -0
  94. package/dist/src/dock/api/wire.js +7 -0
  95. package/dist/src/dock/bench/memory.js +7 -0
  96. package/dist/src/dock/bench/runner.js +7 -0
  97. package/dist/src/dock/build/builder.js +7 -0
  98. package/dist/src/dock/build/buildfile.js +7 -0
  99. package/dist/src/dock/build/buildkit.js +7 -0
  100. package/dist/src/dock/build/changes.js +7 -0
  101. package/dist/src/dock/ci/actions.js +7 -0
  102. package/dist/src/dock/ci/runner.js +7 -0
  103. package/dist/src/dock/ci/workflow.js +7 -0
  104. package/dist/src/dock/cli/api.js +7 -0
  105. package/dist/src/dock/cli/args.js +7 -0
  106. package/dist/src/dock/cli/commands.js +7 -0
  107. package/dist/src/dock/cli/compose.js +7 -0
  108. package/dist/src/dock/cli/context.js +7 -0
  109. package/dist/src/dock/cli/files.js +7 -0
  110. package/dist/src/dock/cli/format.js +7 -0
  111. package/dist/src/dock/cli/manage.js +7 -0
  112. package/dist/src/dock/cli/moved.js +7 -0
  113. package/dist/src/dock/cli/services.js +7 -0
  114. package/dist/src/dock/cli/session.js +7 -0
  115. package/dist/src/dock/cli/workspace.js +7 -0
  116. package/dist/src/dock/client.js +7 -0
  117. package/dist/src/dock/compat/cases.js +7 -0
  118. package/dist/src/dock/compat/runner.js +7 -0
  119. package/dist/src/dock/config.js +7 -0
  120. package/dist/src/dock/daemon-main.js +7 -0
  121. package/dist/src/dock/daemon.js +7 -0
  122. package/dist/src/dock/deploy/compose.js +7 -0
  123. package/dist/src/dock/engine.js +7 -0
  124. package/dist/src/dock/image/archive.js +7 -0
  125. package/dist/src/dock/image/auth.js +7 -0
  126. package/dist/src/dock/image/reference.js +7 -0
  127. package/dist/src/dock/image/registry.js +7 -0
  128. package/dist/src/dock/image/tar.js +7 -0
  129. package/dist/src/dock/index.js +7 -0
  130. package/dist/src/dock/linux/host.js +7 -0
  131. package/dist/src/dock/paths.js +7 -0
  132. package/dist/src/dock/runtime/emulation.js +7 -0
  133. package/dist/src/dock/runtime/fsevents.js +7 -0
  134. package/dist/src/dock/runtime/fsops.js +7 -0
  135. package/dist/src/dock/runtime/hostfwd.js +7 -0
  136. package/dist/src/dock/runtime/logs.js +7 -0
  137. package/dist/src/dock/runtime/network.js +7 -0
  138. package/dist/src/dock/runtime/ports.js +7 -0
  139. package/dist/src/dock/runtime/rootfs.js +7 -0
  140. package/dist/src/dock/runtime/seccomp-profile.LICENSE +202 -0
  141. package/dist/src/dock/runtime/seccomp-profile.json +1227 -0
  142. package/dist/src/dock/runtime/seccomp.js +7 -0
  143. package/dist/src/dock/runtime/spec.js +7 -0
  144. package/dist/src/dock/runtime/stats.js +7 -0
  145. package/dist/src/dock/runtime/volumes.js +7 -0
  146. package/dist/src/dock/selftest.js +7 -0
  147. package/dist/src/dock/setup/app.js +7 -0
  148. package/dist/src/dock/setup/autostart.js +7 -0
  149. package/dist/src/dock/setup/index.js +7 -0
  150. package/dist/src/dock/setup/integrate.js +7 -0
  151. package/dist/src/dock/setup/migrate.js +7 -0
  152. package/dist/src/dock/state/store.js +7 -0
  153. package/dist/src/dock/ui/page.js +385 -0
  154. package/dist/src/dock/ui/server.js +7 -0
  155. package/dist/src/dock/version.js +7 -0
  156. package/dist/src/dock/workspace/apps.js +7 -0
  157. package/dist/src/dock/workspace/workspace.js +7 -0
  158. package/dist/src/events/notifications.js +7 -0
  159. package/dist/src/utils/logger.js +7 -0
  160. package/dist/src/utils/terminalCrypto.js +7 -0
  161. package/package.json +41 -16
  162. package/bin/thinknsh.js +0 -71
  163. package/src/commands/auth/login.js +0 -84
  164. package/src/commands/auth/logout.js +0 -32
  165. package/src/commands/auth/register.js +0 -52
  166. package/src/commands/auth/whoami.js +0 -52
  167. package/src/commands/github/commits.js +0 -58
  168. package/src/commands/github/issue-create.js +0 -59
  169. package/src/commands/github/issues.js +0 -57
  170. package/src/commands/github/pulls.js +0 -58
  171. package/src/commands/github/statusgh.js +0 -50
  172. package/src/commands/index.js +0 -136
  173. package/src/commands/message/say.js +0 -49
  174. package/src/commands/room/join.js +0 -142
  175. package/src/commands/room/leave.js +0 -24
  176. package/src/commands/room/rooms.js +0 -66
  177. package/src/commands/shell/notify.js +0 -88
  178. package/src/commands/shell/status.js +0 -73
  179. package/src/commands/shell/version.js +0 -18
  180. package/src/commands/tasks/build.js +0 -190
  181. package/src/commands/tasks/complete.js +0 -940
  182. package/src/commands/tasks/create-task.js +0 -101
  183. package/src/commands/tasks/loadtest.js +0 -101
  184. package/src/commands/tasks/suggestTask.js +0 -0
  185. package/src/commands/tasks/task-status.js +0 -72
  186. package/src/commands/tasks/task.js +0 -182
  187. package/src/commands/tasks/tasks.js +0 -184
  188. package/src/commands/team/invite.js +0 -46
  189. package/src/commands/team/myteam.js +0 -78
  190. package/src/commands/team/teammates.js +0 -52
  191. package/src/commands/terminal/share.js +0 -261
  192. package/src/core/api-client.js +0 -246
  193. package/src/core/geekload.js +0 -524
  194. package/src/core/local-runner.js +0 -861
  195. package/src/core/notification-window.js +0 -165
  196. package/src/core/project-config.js +0 -100
  197. package/src/core/shell.js +0 -734
  198. package/src/core/websocket.js +0 -657
  199. package/src/events/notifications.js +0 -184
  200. package/src/utils/logger.js +0 -159
  201. package/src/utils/terminalCrypto.js +0 -47
@@ -1,101 +0,0 @@
1
- /*
2
- src/commands/tasks/create-task.js — Create a new task interactively
3
- */
4
- const chalk = require('chalk');
5
-
6
- module.exports = {
7
- name: 'create-task',
8
- description: 'Create a new task in current room',
9
- aliases: ['newtask', 'addtask'],
10
- requiresAuth: true,
11
- requiresRoom: true,
12
-
13
- async execute(args, shell) {
14
- const { input, select, confirm } = require('@inquirer/prompts');
15
- const roomId = shell.ws.getCurrentRoom();
16
-
17
- try {
18
- // Fetch columns of current room's board
19
- const { columns } = await shell.api._request('GET', `/thinknsh/${roomId}/cli/columns`);
20
- if (!columns?.length) {
21
- console.log(chalk.red('❌ No columns found in this room\'s board'));
22
- return;
23
- }
24
-
25
- console.log(chalk.cyan('\n // create-task\n'));
26
-
27
- const title = await input({
28
- message: 'Task title:',
29
- validate: v => v.trim().length >= 3 || 'Min 3 characters'
30
- });
31
-
32
- const description = await input({ message: 'Description (optional):' });
33
-
34
- const columnId = await select({
35
- message: 'Column:',
36
- choices: columns.map(c => ({ name: c.title, value: c._id }))
37
- });
38
-
39
- const priority = await select({
40
- message: 'Priority:',
41
- choices: [
42
- { name: 'low', value: 'low' },
43
- { name: 'medium', value: 'medium' },
44
- { name: 'high', value: 'high' },
45
- ],
46
- default: 'medium'
47
- });
48
-
49
- const categories = [
50
- 'Bugs', 'Feature Requests', 'Improvements / Enhancements',
51
- 'Production Critical Issues', 'Security Issues', 'Performance Issues',
52
- 'UI/UX Issues', 'Testing & QA', 'DevOps & Infrastructure',
53
- 'Refactoring & Code Quality', 'Documentation', 'Other'
54
- ];
55
- const category = await select({
56
- message: 'Category:',
57
- choices: categories.map(c => ({ name: c, value: c }))
58
- });
59
-
60
- const dueDateStr = await input({
61
- message: 'Due date (YYYY-MM-DD, optional):',
62
- validate: v => {
63
- if (!v) return true;
64
- return !isNaN(Date.parse(v)) || 'Invalid date format';
65
- }
66
- });
67
-
68
- const confirmed = await confirm({ message: 'Create task?', default: true });
69
- if (!confirmed) { console.log(chalk.dim(' Cancelled.')); return; }
70
-
71
- const payload = {
72
- title: title.trim(),
73
- description: description.trim() || undefined,
74
- columnId,
75
- priority,
76
- category: category === 'Other' ? undefined : category,
77
- dueDate: dueDateStr ? new Date(dueDateStr).toISOString() : undefined,
78
- source: 'cli',
79
- };
80
-
81
- const result = await shell.api._request('POST', `/thinknsh/${roomId}/cli/tasks`, payload);
82
-
83
- console.log(chalk.green(`\n✅ Task created: "${result.task.title}"`));
84
- console.log(chalk.dim(` ID: ${result.task._id}`));
85
- console.log(chalk.dim(` Column: ${result.task.columnId?.title || columnId}\n`));
86
-
87
- shell.pushNotification({
88
- type: 'notification',
89
- level: 'success',
90
- title: 'Task Created',
91
- message: result.task.title,
92
- });
93
-
94
- } catch (err) {
95
- if (err.message?.includes('403'))
96
- console.log(chalk.red('❌ You are not a member of this room'));
97
- else
98
- console.log(chalk.red(`❌ ${err.message}`));
99
- }
100
- }
101
- };
@@ -1,101 +0,0 @@
1
- const chalk = require('chalk');
2
- const path = require('path');
3
- const fs = require('fs-extra');
4
- const { runLoadTest } = require('../../core/geekload');
5
- const Table = require('cli-table3');
6
-
7
- module.exports = {
8
- name: 'loadtest',
9
- description: 'Run a local load test script using GeekLoad and sync stats to TNC',
10
- aliases: ['geekload'],
11
- requiresAuth: true,
12
- requiresRoom: true,
13
-
14
- async execute(args, shell) {
15
- if (!args[0]) {
16
- console.log(chalk.red('Usage: loadtest <script-path>'));
17
- return;
18
- }
19
-
20
- const scriptPath = path.resolve(process.cwd(), args[0]);
21
- if (!fs.existsSync(scriptPath)) {
22
- console.log(chalk.red(`❌ Script not found: ${args[0]}`));
23
- return;
24
- }
25
-
26
- console.log(chalk.cyan(`\n📋 Loading test script: ${args[0]}`));
27
-
28
- try {
29
- const results = await runLoadTest(scriptPath);
30
-
31
- const table = new Table({
32
- head: [chalk.green('Metric'), chalk.green('Value')],
33
- colWidths: [25, 20]
34
- });
35
-
36
- table.push(
37
- ['Virtual Users', results.virtual_users],
38
- ['Duration (sec)', results.duration_sec],
39
- ['Total Requests', results.total_requests],
40
- ['Failed Requests', results.failed_requests],
41
- ['Requests/sec (RPS)', results.requests_per_sec],
42
- ['Failure Rate', `${(results.failure_rate * 100).toFixed(2)}%`],
43
- ['Average Latency (ms)', results.avg_latency_ms],
44
- ['p95 Latency (ms)', results.p95_latency_ms],
45
- ['p99 Latency (ms)', results.p99_latency_ms]
46
- );
47
-
48
- console.log(table.toString());
49
-
50
- // Sync stats back to ThinkNCollab backend
51
- const roomId = shell.ws.getCurrentRoom();
52
- if (roomId) {
53
- process.stdout.write(chalk.dim(' Syncing stats to ThinkNCollab server...\r'));
54
- try {
55
- const stats = {
56
- targetUrl: args[0],
57
- duration: results.duration_sec,
58
- connections: results.virtual_users,
59
- requestsTotal: results.total_requests,
60
- throughputTotalBytes: results.total_requests * 512,
61
- latency: {
62
- p50: results.avg_latency_ms,
63
- p90: results.p95_latency_ms,
64
- p99: results.p99_latency_ms,
65
- average: results.avg_latency_ms,
66
- min: results.avg_latency_ms * 0.5,
67
- max: results.avg_latency_ms * 1.5
68
- },
69
- errors: results.failed_requests
70
- };
71
-
72
- await shell.api._request('POST', `/tncloadtest/api/save-run/${roomId}`, {
73
- targetUrl: args[0],
74
- duration: results.duration_sec,
75
- connections: results.virtual_users,
76
- stats
77
- });
78
- console.log(chalk.green(' ✅ Load test stats successfully synced to workspace!'));
79
- } catch (syncErr) {
80
- console.log(chalk.red(` ⚠️ Failed to sync stats to server: ${syncErr.message}`));
81
- }
82
- }
83
-
84
- if (results.failures.length > 0) {
85
- console.log(chalk.yellow(`\n⚠️ Recorded Failures (${results.failures.length}):`));
86
- results.failures.slice(0, 5).forEach((f, idx) => {
87
- console.log(chalk.dim(` ${idx + 1}. [${f.method}] ${f.url}`));
88
- f.failures.forEach(msg => {
89
- console.log(chalk.red(` - ${msg}`));
90
- });
91
- });
92
- if (results.failures.length > 5) {
93
- console.log(chalk.dim(` ... and ${results.failures.length - 5} more failures`));
94
- }
95
- }
96
-
97
- } catch (err) {
98
- console.log(chalk.red(`❌ Load test execution failed: ${err.message}`));
99
- }
100
- }
101
- };
File without changes
@@ -1,72 +0,0 @@
1
- // src/commands/tasks/task-status.js
2
- const chalk = require('chalk');
3
-
4
- const STATUS_MAP = {
5
- accept: 'accepted',
6
- start: 'inprogress',
7
- complete: 'completed',
8
- reject: 'rejected',
9
- done: 'completed',
10
- 'task-status': null, // requires explicit arg
11
- };
12
-
13
- module.exports = {
14
- name: 'task-status',
15
- description: 'Update your task status',
16
- aliases: ['accept', 'start', 'complete', 'reject', 'done'],
17
- requiresAuth: true,
18
- requiresRoom: true,
19
-
20
- async execute(args, shell, invokedAs) {
21
- const roomId = shell.ws.getCurrentRoom(); // ← top pe, ek baar
22
- const taskId = args[0];
23
- const verb = invokedAs || shell._lastCommand || 'task-status';
24
- const status = STATUS_MAP[verb] ?? args[1];
25
-
26
- if (!taskId) {
27
- console.log(chalk.yellow(' Usage: accept <taskId> | start <taskId> | complete <taskId>'));
28
- return;
29
- }
30
- if (!status) {
31
- console.log(chalk.yellow(' Usage: task-status <taskId> <accepted|inprogress|completed|rejected>'));
32
- return;
33
- }
34
-
35
- try {
36
- const result = await shell.api._request(
37
- 'POST',
38
- `/thinknsh/${roomId}/tasks/${taskId}/status`,
39
- { status }
40
- );
41
-
42
- const statusColors = {
43
- accepted: chalk.green,
44
- inprogress: chalk.blue,
45
- completed: chalk.green,
46
- rejected: chalk.red,
47
- };
48
-
49
- const col = statusColors[status] || chalk.white;
50
- console.log(col(`\n ✓ Task "${result.taskTitle}" → ${status}`));
51
-
52
- if (result.allCompleted) {
53
- console.log(chalk.green(' 🎉 All assignees done — task fully completed!\n'));
54
- } else {
55
- console.log('');
56
- }
57
-
58
- // Socket emit
59
- if (shell.ws.isConnected?.() && shell.ws.socket) {
60
- shell.ws.socket.emit('task:' + (status === 'inprogress' ? 'started' : status), {
61
- roomId,
62
- taskId,
63
- taskTitle: result.taskTitle,
64
- userId: shell.api.getUser()?._id,
65
- });
66
- }
67
-
68
- } catch (err) {
69
- console.log(chalk.red(`\n ❌ ${err.message}\n`));
70
- }
71
- }
72
- };
@@ -1,182 +0,0 @@
1
- /*
2
- src/commands/tasks/task-info.js — View task details + testConfig + webhook URL
3
- Usage: task-info <taskId> OR info <taskId> load
4
- */
5
- const chalk = require('chalk');
6
-
7
- module.exports = {
8
- name: 'task-info',
9
- description: 'View full task details including test config and webhook URL',
10
- aliases: ['task', 'info', 'taskInfo', '--t' ],
11
- requiresAuth: true,
12
-
13
- async execute(args, shell) {
14
- if (!args[0]) {
15
- console.log(chalk.red('Usage: task-info <task-id>'));
16
- console.log(chalk.dim(' Alias: info <task-id>'));
17
- return;
18
- }
19
-
20
- const taskId = args[0];
21
-
22
- let task;
23
- try {
24
- task = await shell.api._request('GET', `/thinknsh/${taskId}/cli`);
25
- } catch (err) {
26
- if (err.message?.includes('404')) console.log(chalk.red('❌ Task not found'));
27
- else if (err.message?.includes('403')) console.log(chalk.red('❌ Access denied'));
28
- else console.log(chalk.red(`❌ ${err.message}`));
29
- return;
30
- }
31
-
32
- const stColors = {
33
- pending: chalk.yellow,
34
- inprogress: chalk.blue,
35
- review: chalk.magenta,
36
- completed: chalk.green,
37
- reopened: chalk.cyan,
38
- };
39
- const prColors = { high: chalk.red, medium: chalk.yellow, low: chalk.green };
40
- const stColor = stColors[task.status] || chalk.white;
41
- const prColor = prColors[task.priority] || chalk.white;
42
-
43
- // ── Basic Info ────────────────────────────────────────────────────────────
44
- console.log(chalk.cyan('\n ─── Task Info ───────────────────────────────────'));
45
- console.log(` ${chalk.dim('id ')} ${chalk.dim(task._id)}${task.taskID ? chalk.cyan(' #' + task.taskID) : ''}`);
46
- console.log(` ${chalk.dim('title ')} ${chalk.bold(task.title)}`);
47
- console.log(` ${chalk.dim('status ')} ${stColor(task.status)}`);
48
- console.log(` ${chalk.dim('priority')} ${prColor(task.priority)}`);
49
- if (task.category)
50
- console.log(` ${chalk.dim('category')} ${chalk.dim(task.category)}`);
51
- if (task.dueDate)
52
- console.log(` ${chalk.dim('due ')} ${chalk.yellow(new Date(task.dueDate).toLocaleDateString())}`);
53
- if (task.description) {
54
- console.log(chalk.dim('\n description:'));
55
- task.description.split('\n').forEach(l => console.log(` ${chalk.white(l)}`));
56
- }
57
-
58
- if (task.referenceLinks && task.referenceLinks.length > 0) {
59
- console.log(chalk.cyan('\n ─── Supported Links ─────────────────────────────'));
60
- task.referenceLinks.forEach(link => {
61
- console.log(` ${chalk.dim(link.title.padEnd(12))} ${chalk.blue(link.url)}`);
62
- });
63
- }
64
-
65
- // ── Assignees ─────────────────────────────────────────────────────────────
66
- if (task.assignedTo?.length) {
67
- console.log(chalk.dim('\n assignees:'));
68
- task.assignedTo.forEach(a => {
69
- const name = a.userId?.name || 'Unknown';
70
- const stBadge = a.status === 'completed' ? chalk.green('✓') :
71
- a.status === 'accepted' ? chalk.blue('●') :
72
- a.status === 'rejected' ? chalk.red('✗') : chalk.dim('○');
73
- console.log(` ${stBadge} ${name} ${chalk.dim(`[${a.status}]`)}`);
74
- });
75
- }
76
-
77
- // ── Test Config ───────────────────────────────────────────────────────────
78
- if (task.testConfig?.type) {
79
- const tc = task.testConfig;
80
-
81
- console.log(chalk.cyan('\n ─── Test Config ─────────────────────────────────'));
82
- console.log(` ${chalk.dim('type ')} ${chalk.bold(tc.type)}`);
83
-
84
- if (tc.type === 'http') {
85
- console.log(` ${chalk.dim('method ')} ${chalk.green(tc.method || 'GET')}`);
86
- console.log(` ${chalk.dim('target ')} ${chalk.white((tc.baseUrl || '') + (tc.endpoint || ''))}`);
87
- if (tc.body && Object.keys(tc.body).length) {
88
- console.log(` ${chalk.dim('body ')} ${chalk.dim(JSON.stringify(tc.body))}`);
89
- }
90
- if (tc.expect) {
91
- console.log(chalk.dim('\n expect:'));
92
- if (tc.expect.status !== undefined)
93
- console.log(` ${chalk.dim('status')} ${chalk.green(tc.expect.status)}`);
94
- if (tc.expect.body) {
95
- Object.entries(tc.expect.body).forEach(([key, condition]) => {
96
- const condStr = typeof condition === 'object'
97
- ? Object.entries(condition).map(([op, val]) => `${op}: ${val}`).join(', ')
98
- : String(condition);
99
- console.log(` ${chalk.dim('body.' + key)} ${chalk.cyan(condStr)}`);
100
- });
101
- }
102
- }
103
- }
104
-
105
- if (tc.type === 'browser') {
106
- console.log(` ${chalk.dim('url ')} ${chalk.white(tc.url || '')}`);
107
- if (tc.flow?.length) {
108
- console.log(chalk.dim('\n flow:'));
109
- tc.flow.forEach((step, i) => {
110
- console.log(` ${chalk.dim(i + 1 + '.')} ${chalk.green(step.action)} ${chalk.dim(step.selector || '')} ${step.value ? chalk.white(`"${step.value}"`) : ''}`);
111
- });
112
- }
113
- if (tc.expect) {
114
- console.log(chalk.dim('\n expect:'));
115
- if (tc.expect.element)
116
- console.log(` ${chalk.dim('element ')} ${chalk.cyan(tc.expect.element)}`);
117
- if (tc.expect.text)
118
- console.log(` ${chalk.dim('text ')} ${chalk.cyan(`contains "${tc.expect.text}"`)}`);
119
- if (tc.expect.redirectUrl)
120
- console.log(` ${chalk.dim('redirectUrl')} ${chalk.cyan(tc.expect.redirectUrl)}`);
121
- }
122
- }
123
-
124
- if (tc.type === 'json') {
125
- if (tc.expect?.condition) {
126
- console.log(chalk.dim('\n conditions:'));
127
- Object.entries(tc.expect.condition).forEach(([key, ops]) => {
128
- const condStr = Object.entries(ops).map(([op, val]) => `${op} ${val}`).join(', ');
129
- console.log(` ${chalk.dim(key)} ${chalk.cyan(condStr)}`);
130
- });
131
- }
132
- }
133
-
134
- if (tc.type === 'exitCode')
135
- console.log(` ${chalk.dim('expect ')} exitCode ${chalk.green(tc.expect?.exitCode ?? 0)}`);
136
-
137
- if (tc.type === 'stdout')
138
- console.log(` ${chalk.dim('expect ')} stdout "${chalk.green(tc.expect?.stdout || '')}"`);
139
-
140
- if (tc.type === 'regex')
141
- console.log(` ${chalk.dim('expect ')} regex ${chalk.green(tc.expect?.regex || '')}`);
142
-
143
- if (tc.type === 'tnc-build')
144
- console.log(` ${chalk.dim('runner ')} ${chalk.green('Local tnc-ci.yml workflow execution')}`);
145
-
146
- } else {
147
- console.log(chalk.yellow('\n ⚠️ No test config — task will need manual completion'));
148
- console.log(chalk.dim(' Use: complete <task-id>'));
149
- }
150
-
151
- // ── Webhook ───────────────────────────────────────────────────────────────
152
- if (task.webhookSecret) {
153
- const apiUrl = shell.api.apiUrl || 'https://thinkncollab.com';
154
- const webhookUrl = `${apiUrl}/webhooks/tasks/${taskId}/judge`;
155
-
156
- console.log(chalk.cyan('\n ─── Webhook ─────────────────────────────────────'));
157
- console.log(` ${chalk.dim('url ')} ${chalk.white(webhookUrl)}`);
158
- console.log(` ${chalk.dim('secret ')} ${chalk.dim(task.webhookSecret)}`);
159
- console.log(` ${chalk.dim('header ')} ${chalk.dim('x-tnc-signature: sha256=<HMAC of body>')}`);
160
- console.log(chalk.dim('\n To submit from your project:'));
161
- console.log(chalk.cyan(' submit ' + taskId));
162
- }
163
-
164
- // ── Last Verdict ──────────────────────────────────────────────────────────
165
- if (task.lastVerdict?.at) {
166
- const v = task.lastVerdict;
167
- const passed = v.passed;
168
- const badge = passed ? chalk.bgGreen.black(' PASS ') : chalk.bgRed.white(' FAIL ');
169
- const ts = new Date(v.at).toLocaleString();
170
-
171
- console.log(chalk.cyan('\n ─── Last Verdict ────────────────────────────────'));
172
- console.log(` ${badge} ${passed ? chalk.green(v.reason) : chalk.red(v.reason)}`);
173
- console.log(` ${chalk.dim('at')} ${chalk.dim(ts)}`);
174
- if (v.diff) {
175
- console.log(` ${chalk.dim('expected')} ${chalk.cyan(JSON.stringify(v.diff.expected ?? v.diff.conditions))}`);
176
- console.log(` ${chalk.dim('actual ')} ${chalk.yellow(JSON.stringify(v.diff.actual))}`);
177
- }
178
- }
179
-
180
- console.log(chalk.cyan(' ─────────────────────────────────────────────────\n'));
181
- }
182
- };
@@ -1,184 +0,0 @@
1
- /*
2
- src/commands/tasks/tasks.js — List my tasks + suggestions in current room
3
- */
4
- const chalk = require('chalk');
5
-
6
- module.exports = {
7
- name: 'tasks',
8
- description: 'List your tasks + suggested tasks in the current room',
9
- aliases: ['mytasks', 'my-tasks'],
10
- requiresAuth: true,
11
- requiresRoom: true,
12
-
13
- async execute(args, shell) {
14
- const user = shell.api.getUser();
15
- const roomId = shell.ws.getCurrentRoom();
16
-
17
- if (!user) { console.log(chalk.red('❌ Please login first')); return; }
18
- if (!roomId) { console.log(chalk.yellow('⚠️ Join a room first: join <room-id>')); return; }
19
-
20
- // ── Flags ────────────────────────────────────────────────────────────
21
- const showAll = args.includes('--all') || args.includes('-a');
22
- const noSuggestions = args.includes('--no-suggest') || args.includes('-ns');
23
- const filterStatus = args.find(a => ['pending','inprogress','review','completed','reopened'].includes(a));
24
- const topN = args.find(a => /^\d+$/.test(a)) || 5;
25
-
26
- // ── Color maps ───────────────────────────────────────────────────────
27
- const stColors = {
28
- pending: chalk.yellow,
29
- inprogress: chalk.blue,
30
- review: chalk.magenta,
31
- completed: chalk.green,
32
- reopened: chalk.cyan,
33
- };
34
- const prColors = {
35
- critical: chalk.red,
36
- high: chalk.hex('#FF6B35'),
37
- medium: chalk.yellow,
38
- low: chalk.green,
39
- };
40
- const scoreColor = s => s >= 80 ? chalk.red(s) : s >= 60 ? chalk.yellow(s) : chalk.green(s);
41
- const plColor = pl => ({
42
- CRITICAL: chalk.red,
43
- HIGH: chalk.hex('#FF6B35'),
44
- MEDIUM: chalk.yellow,
45
- LOW: chalk.green,
46
- 'VERY LOW': chalk.dim,
47
- }[pl] || chalk.white);
48
-
49
- // ── Helpers ──────────────────────────────────────────────────────────
50
- const fmtDue = dueDate => {
51
- if (!dueDate) return '';
52
- const d = new Date(dueDate);
53
- const days = Math.ceil((d - new Date().setHours(0,0,0,0)) / 86400000);
54
- const str = d.toLocaleDateString('en-IN', { day:'2-digit', month:'short' });
55
- if (days < 0) return chalk.red(` due:${str}(!)`);
56
- if (days === 0) return chalk.yellow(` due:TODAY`);
57
- if (days === 1) return chalk.yellow(` due:${str}`);
58
- return chalk.dim(` due:${str}`);
59
- };
60
-
61
- const divider = (color = chalk.cyan) => color(' ' + '─'.repeat(58));
62
- const subline = (label, val) =>
63
- ` ${chalk.dim(label+':')} ${chalk.dim(val)}`;
64
-
65
- // ── Fetch ────────────────────────────────────────────────────────────
66
- process.stdout.write(chalk.dim(' Fetching tasks...\r'));
67
-
68
- let result;
69
- try {
70
- result = await shell.api._request('GET', `/thinknsh/${roomId}/tasks?n=${topN}`);
71
- } catch (err) {
72
- console.log(chalk.red(`\n ❌ ${err.message}\n`));
73
- return;
74
- }
75
-
76
- process.stdout.write(' '.repeat(30) + '\r'); // clear spinner line
77
-
78
- // ════════════════════════════════════════════════════════════════════
79
- // MY TASKS
80
- // ════════════════════════════════════════════════════════════════════
81
- let tasks = result.tasks || [];
82
-
83
- if (filterStatus) tasks = tasks.filter(t => t.status === filterStatus);
84
- if (!showAll) tasks = tasks.filter(t => !['completed','done'].includes(t.status));
85
-
86
- console.log(divider());
87
- console.log(chalk.cyan(` MY TASKS`) + chalk.dim(` (${tasks.length} active${result.total > tasks.length ? ` of ${result.total}` : ''})`));
88
- console.log(divider());
89
-
90
- if (!tasks.length) {
91
- console.log(chalk.dim('\n No assigned tasks.\n'));
92
- } else {
93
- tasks.forEach((task, i) => {
94
- const sc = stColors[task.status] || chalk.white;
95
- const pc = prColors[task.priority] || chalk.white;
96
-
97
- const num = chalk.dim(` ${String(i+1).padStart(2)}.`);
98
- const status = sc(`[${(task.status || 'unknown').padEnd(10)}]`);
99
- const title = task.status === 'completed'
100
- ? chalk.dim(task.title)
101
- : chalk.white(task.title);
102
- const due = fmtDue(task.dueDate);
103
- const myStatus = task.myStatus && task.myStatus !== task.status
104
- ? chalk.dim(` (${task.myStatus})`)
105
- : '';
106
- const col = task.column ? chalk.dim(` [${task.column}]`) : '';
107
-
108
- console.log(`\n${num} ${status} ${title}`);
109
-
110
- console.log(subline('id', `${task.taskID ? '#' + task.taskID : task._id}`) +
111
- ` ${chalk.dim('priority:')} ${pc(task.priority)}` +
112
- due + myStatus + col);
113
-
114
- if (task.description) {
115
- const desc = task.description.length > 90
116
- ? task.description.slice(0, 87) + '...'
117
- : task.description;
118
- console.log(` ${chalk.dim(desc)}`);
119
- }
120
- });
121
- }
122
-
123
- // ════════════════════════════════════════════════════════════════════
124
- // SUGGESTIONS
125
- // ════════════════════════════════════════════════════════════════════
126
- if (!noSuggestions) {
127
- const suggestions = result.suggestions?.tasks || [];
128
- const insights = result.suggestions?.insights || {};
129
- const meta = result.suggestions?.metadata || {};
130
-
131
- console.log('\n' + divider(chalk.magenta));
132
- console.log(chalk.magenta(` SUGGESTED FOR YOU`) +
133
- chalk.dim(` (top ${suggestions.length}${meta.totalScored ? ` of ${meta.totalScored} available` : ''})`));
134
- console.log(divider(chalk.magenta));
135
-
136
- if (!suggestions.length) {
137
- console.log(chalk.dim('\n No suggestions — all tasks are assigned.\n'));
138
- } else {
139
- suggestions.forEach((task, i) => {
140
- const pc = prColors[task.priority] || chalk.white;
141
- const plc = plColor(task.priorityLevel);
142
- const due = fmtDue(task.dueDate);
143
- const col = task.column ? chalk.dim(` [${task.column}]`) : '';
144
- const assignees = task.assigneeCount
145
- ? chalk.dim(` · ${task.assigneeCount} assigned`)
146
- : chalk.dim(' · unassigned');
147
- const urgentTag = task.isOverdue
148
- ? chalk.red(' ⚠ OVERDUE')
149
- : task.isUrgent ? chalk.yellow(' ⏰ URGENT') : '';
150
-
151
- const num = chalk.dim(` ${String(i+1).padStart(2)}.`);
152
- const score = `[score:${scoreColor(task.score)}]`;
153
- const level = plc(`[${task.priorityLevel}]`);
154
-
155
- console.log(`\n${num} ${score} ${level} ${chalk.white(task.title)}${urgentTag}`);
156
- console.log(subline('id', task._id) +
157
- ` ${chalk.dim('priority:')} ${pc(task.priority)}` +
158
- due + col + assignees);
159
-
160
- if (task.priorityReason) {
161
- console.log(` ${chalk.dim('↳ ' + task.priorityReason)}`);
162
- }
163
- });
164
-
165
- // ── Insights bar ─────────────────────────────────────────────
166
- console.log('\n' + divider(chalk.dim));
167
- if (insights.focusRecommendation) {
168
- console.log(` ${chalk.magenta('💡')} ${chalk.white(insights.focusRecommendation)}`);
169
- }
170
- if (insights.estimatedTime) {
171
- console.log(` ${chalk.dim('⏱ Est. time:')} ${chalk.white(insights.estimatedTime)}`);
172
- }
173
- if (meta.scoreRange) {
174
- console.log(` ${chalk.dim('📊 Score range:')} ${chalk.white(`${meta.scoreRange.min}–${meta.scoreRange.max}`)} ${chalk.dim('avg:')} ${chalk.white(meta.scoreRange.avg)}`);
175
- }
176
- }
177
- }
178
-
179
- // ── Footer ───────────────────────────────────────────────────────────
180
- console.log('\n' + divider());
181
- console.log(chalk.dim(' task <id> · complete <id> · tasks --all · tasks 10 · tasks --no-suggest'));
182
- console.log(divider() + '\n');
183
- }
184
- };