@thinremote/thinr-cli 1.2.0-alpha.1 → 1.3.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 (92) hide show
  1. package/CHANGELOG.md +63 -1
  2. package/README.md +235 -30
  3. package/bin/thinr.js +43 -25
  4. package/commands/_shared.js +154 -0
  5. package/commands/dashboard.js +17 -0
  6. package/commands/device/_shared.js +17 -34
  7. package/commands/device/console.js +1 -0
  8. package/commands/device/delete.js +53 -0
  9. package/commands/device/exec.js +7 -6
  10. package/commands/device/fs.js +193 -0
  11. package/commands/device/index.js +9 -0
  12. package/commands/device/list.js +35 -23
  13. package/commands/device/logs.js +178 -0
  14. package/commands/device/property.js +30 -28
  15. package/commands/device/proxy.js +3 -0
  16. package/commands/device/resource.js +30 -29
  17. package/commands/device/status.js +35 -14
  18. package/commands/device/transfer.js +236 -0
  19. package/commands/device/update.js +15 -10
  20. package/commands/fleet/index.js +17 -0
  21. package/commands/fleet/upgrade.js +275 -0
  22. package/commands/logout.js +10 -11
  23. package/commands/playbook/_shared.js +12 -0
  24. package/commands/playbook/index.js +18 -0
  25. package/commands/playbook/run.js +302 -0
  26. package/commands/playbook/validate.js +38 -0
  27. package/commands/product/_shared.js +8 -0
  28. package/commands/product/exec.js +243 -0
  29. package/commands/product/fs.js +218 -0
  30. package/commands/product/index.js +35 -0
  31. package/commands/product/list.js +86 -0
  32. package/commands/product/logs.js +289 -0
  33. package/commands/product/metric.js +124 -0
  34. package/commands/product/playbook.js +911 -0
  35. package/commands/product/property.js +76 -0
  36. package/commands/product/props.js +125 -0
  37. package/commands/product/push.js +184 -0
  38. package/commands/product/resource.js +76 -0
  39. package/commands/product/status.js +213 -0
  40. package/commands/profile.js +76 -8
  41. package/dist/dashboard.js +5644 -0
  42. package/lib/agent-releases.js +59 -0
  43. package/lib/agent-versions.js +73 -0
  44. package/lib/alarms.js +252 -0
  45. package/lib/api.js +8 -2
  46. package/lib/auth.js +68 -20
  47. package/lib/bucket.js +87 -0
  48. package/lib/command-stream.js +213 -0
  49. package/lib/config.js +5 -3
  50. package/lib/console.js +19 -5
  51. package/lib/constants.js +83 -0
  52. package/lib/dashboard/event-stream.js +239 -0
  53. package/lib/dashboard/metric-aggregate.js +64 -0
  54. package/lib/dashboard/metric-filter.js +39 -0
  55. package/lib/debug-log.js +93 -0
  56. package/lib/device-api.js +131 -148
  57. package/lib/devices.js +18 -21
  58. package/lib/errors.js +12 -0
  59. package/lib/fleet-upgrade.js +106 -0
  60. package/lib/format.js +114 -0
  61. package/lib/mcp/registry.js +14 -0
  62. package/lib/mcp/tools-alarms.js +510 -0
  63. package/lib/mcp/tools-buckets.js +103 -0
  64. package/lib/mcp/tools-devices.js +33 -3
  65. package/lib/mcp/tools-exec.js +30 -17
  66. package/lib/mcp/tools-filesystem.js +102 -6
  67. package/lib/mcp/tools-install.js +153 -0
  68. package/lib/mcp/tools-logs.js +225 -0
  69. package/lib/mcp/tools-playbook.js +211 -0
  70. package/lib/mcp/tools-products.js +1226 -105
  71. package/lib/mcp/tools-profile.js +634 -0
  72. package/lib/mcp/tools-tokens.js +371 -0
  73. package/lib/monitoring.js +26 -1
  74. package/lib/playbook/actions.js +447 -0
  75. package/lib/playbook/expression.js +302 -0
  76. package/lib/playbook/fleet.js +175 -0
  77. package/lib/playbook/loader.js +247 -0
  78. package/lib/playbook/runner.js +300 -0
  79. package/lib/playbook/schema.js +209 -0
  80. package/lib/playbook/vars.js +209 -0
  81. package/lib/product/log-presets.js +196 -0
  82. package/lib/product/logs.js +485 -0
  83. package/lib/product-orchestrator.js +124 -0
  84. package/lib/product.js +523 -20
  85. package/lib/profile.js +665 -0
  86. package/lib/property.js +7 -40
  87. package/lib/proxy.js +9 -8
  88. package/lib/resource.js +10 -14
  89. package/lib/status.js +78 -37
  90. package/lib/tokens.js +374 -0
  91. package/package.json +14 -3
  92. package/commands/product.js +0 -407
@@ -1,22 +1,30 @@
1
1
  import chalk from 'chalk';
2
+ import { input } from '@inquirer/prompts';
2
3
  import {
3
4
  listProfiles,
4
5
  getActiveProfile,
5
6
  getProfile,
7
+ setActiveProfile,
6
8
  setDefaultProfile,
7
9
  deleteProfile,
8
10
  } from '../lib/config.js';
11
+ import { authenticate } from '../lib/auth.js';
9
12
  import { setJsonMode, isJsonMode, printOk, printErr } from '../lib/output.js';
13
+ import { hint, success, label } from '../lib/format.js';
10
14
 
11
15
  function applyJsonFlag(opts) {
12
16
  if (opts.json) setJsonMode(true);
13
17
  }
14
18
 
15
19
  export function profileCommand(program) {
16
- const profile = program.command('profile').description('Manage configuration profiles');
20
+ const profile = program
21
+ .command('profile')
22
+ .helpGroup('Configuration:')
23
+ .description('Manage configuration profiles');
17
24
 
18
25
  profile
19
26
  .command('list')
27
+ .helpGroup('Profile:')
20
28
  .description('List configured profiles')
21
29
  .option('-j, --json', 'Output as JSON')
22
30
  .action((opts) => {
@@ -37,19 +45,20 @@ export function profileCommand(program) {
37
45
  return;
38
46
  }
39
47
  if (!names.length) {
40
- console.log(chalk.gray('No profiles configured. Run thinr to set one up.'));
48
+ console.log(hint('No profiles configured. Run thinr to set one up.'));
41
49
  return;
42
50
  }
43
51
  for (const name of names) {
44
52
  const data = getProfile(name) || {};
45
- const marker = name === active ? chalk.green('* ') : ' ';
46
- const detail = chalk.gray(`${data.username || ''}@${data.server || name}`);
47
- console.log(`${marker}${chalk.bold(name)} ${detail}`);
53
+ const marker = name === active ? success('* ') : ' ';
54
+ const detail = hint(`${data.username || ''}@${data.server || name}`);
55
+ console.log(`${marker}${label(name)} ${detail}`);
48
56
  }
49
57
  });
50
58
 
51
59
  profile
52
60
  .command('current')
61
+ .helpGroup('Profile:')
53
62
  .description('Print the active profile')
54
63
  .option('-j, --json', 'Output as JSON')
55
64
  .action((opts) => {
@@ -60,7 +69,7 @@ export function profileCommand(program) {
60
69
  return;
61
70
  }
62
71
  if (!name) {
63
- console.log(chalk.gray('No active profile.'));
72
+ console.log(hint('No active profile.'));
64
73
  return;
65
74
  }
66
75
  console.log(name);
@@ -68,6 +77,7 @@ export function profileCommand(program) {
68
77
 
69
78
  profile
70
79
  .command('use <name>')
80
+ .helpGroup('Profile:')
71
81
  .description('Set the default profile')
72
82
  .option('-j, --json', 'Output as JSON')
73
83
  .action((name, opts) => {
@@ -82,11 +92,69 @@ export function profileCommand(program) {
82
92
  printOk({ active: name });
83
93
  return;
84
94
  }
85
- console.log(chalk.green(`Default profile set to ${name}`));
95
+ console.log(success(`Default profile set to ${name}`));
96
+ });
97
+
98
+ profile
99
+ .command('add [name]')
100
+ .description('Add a new profile via interactive authentication')
101
+ .option('--no-activate', 'Do not set the new profile as default')
102
+ .option('-j, --json', 'Output as JSON')
103
+ .action(async (nameArg, opts) => {
104
+ applyJsonFlag(opts);
105
+ let name = nameArg;
106
+ if (!name) {
107
+ try {
108
+ name = await input({
109
+ message: 'Profile name:',
110
+ validate: (v) => {
111
+ const trimmed = (v || '').trim();
112
+ if (!trimmed) return 'Profile name is required';
113
+ if (/\s/.test(trimmed)) return 'Profile name cannot contain whitespace';
114
+ return true;
115
+ },
116
+ });
117
+ } catch (error) {
118
+ printErr(error.message || 'Prompt cancelled');
119
+ return;
120
+ }
121
+ }
122
+ name = name.trim();
123
+ if (getProfile(name)) {
124
+ printErr(`Profile already exists: ${name}`, { code: 'already_exists' });
125
+ return;
126
+ }
127
+ setActiveProfile(name);
128
+ try {
129
+ await authenticate();
130
+ const saved = getProfile(name);
131
+ if (!saved || !saved.token || !saved.username) {
132
+ throw new Error('Authentication did not complete; profile discarded.');
133
+ }
134
+ } catch (error) {
135
+ setActiveProfile(null);
136
+ try {
137
+ deleteProfile(name);
138
+ } catch {
139
+ // Best-effort cleanup — ignore secondary failures
140
+ }
141
+ printErr(error.message || 'Authentication failed');
142
+ return;
143
+ }
144
+ const activate = opts.activate !== false;
145
+ if (activate) setDefaultProfile(name);
146
+ setActiveProfile(null);
147
+ if (isJsonMode()) {
148
+ printOk({ added: name, activated: activate, active: getActiveProfile() });
149
+ return;
150
+ }
151
+ const suffix = activate ? ' and set as default' : '';
152
+ console.log(chalk.green(`Profile ${name} added${suffix}`));
86
153
  });
87
154
 
88
155
  profile
89
156
  .command('delete <name>')
157
+ .helpGroup('Profile:')
90
158
  .description('Remove a profile')
91
159
  .option('-j, --json', 'Output as JSON')
92
160
  .action((name, opts) => {
@@ -100,6 +168,6 @@ export function profileCommand(program) {
100
168
  printOk({ removed: name });
101
169
  return;
102
170
  }
103
- console.log(chalk.green(`Removed profile ${name}`));
171
+ console.log(success(`Removed profile ${name}`));
104
172
  });
105
173
  }