nonotify 0.1.2 → 0.1.3

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/cli.ts CHANGED
@@ -1,200 +1,225 @@
1
1
  #!/usr/bin/env node
2
- import { Cli, z } from 'incur'
3
- import { askConfirm, askRequired, askRequiredWithInitial, askSelect } from './prompt.js'
4
- import { getConfigPath, loadConfig, saveConfig } from './config.js'
5
- import { printKeyValueTable, printProfilesTable } from './display.js'
6
- import { getLatestUpdateOffset, sendTelegramMessage, waitForChatId } from './telegram.js'
7
-
8
- const profileCli = Cli.create('profile', {
9
- description: 'Manage notification profiles',
10
- })
11
2
 
12
- profileCli.command('add', {
13
- description: 'Add a notification profile',
14
- outputPolicy: 'agent-only',
3
+ import { Cli, z } from "incur";
4
+ import {
5
+ askConfirm,
6
+ askRequired,
7
+ askRequiredWithInitial,
8
+ askSelect,
9
+ } from "./prompt.js";
10
+ import { getConfigPath, loadConfig, saveConfig } from "./config.js";
11
+ import { printKeyValueTable, printProfilesTable } from "./display.js";
12
+ import {
13
+ getLatestUpdateOffset,
14
+ sendTelegramMessage,
15
+ waitForChatId,
16
+ } from "./telegram.js";
17
+
18
+ const profileCli = Cli.create("profile", {
19
+ description: "Manage notification profiles",
20
+ });
21
+
22
+ profileCli.command("add", {
23
+ description: "Add a notification profile",
24
+ outputPolicy: "agent-only",
15
25
  args: z.object({
16
- provider: z.enum(['telegram']).default('telegram').describe('Profile provider'),
26
+ provider: z
27
+ .enum(["telegram"])
28
+ .default("telegram")
29
+ .describe("Profile provider"),
17
30
  }),
18
31
  async run(c) {
19
- if (c.args.provider !== 'telegram') {
20
- throw new Error(`Unsupported provider: ${c.args.provider}`)
32
+ if (c.args.provider !== "telegram") {
33
+ throw new Error(`Unsupported provider: ${c.args.provider}`);
21
34
  }
22
35
 
23
- const config = await loadConfig()
24
- const profileName = await askRequired('Profile name: ')
36
+ const config = await loadConfig();
37
+ const profileName = await askRequired("Profile name: ");
25
38
 
26
39
  if (config.profiles[profileName]) {
27
- throw new Error(`Profile "${profileName}" already exists.`)
40
+ throw new Error(`Profile "${profileName}" already exists.`);
28
41
  }
29
42
 
30
- const botToken = await askRequired('Telegram bot token: ')
43
+ const botToken = await askRequired("Telegram bot token: ");
31
44
 
32
45
  if (shouldRenderPretty(c.agent)) {
33
- process.stdout.write('\nSend any message to your bot in Telegram.\n')
34
- process.stdout.write('Waiting for message to detect chat_id (up to 120s)...\n')
46
+ process.stdout.write("\nSend any message to your bot in Telegram.\n");
47
+ process.stdout.write(
48
+ "Waiting for message to detect chat_id (up to 120s)...\n",
49
+ );
35
50
  }
36
51
 
37
- const offset = await getLatestUpdateOffset(botToken)
38
- const connection = await waitForChatId(botToken, offset, 120)
39
- const chatId = connection.chatId
52
+ const offset = await getLatestUpdateOffset(botToken);
53
+ const connection = await waitForChatId(botToken, offset, 120);
54
+ const chatId = connection.chatId;
40
55
 
41
56
  if (shouldRenderPretty(c.agent)) {
42
57
  if (connection.username) {
43
- process.stdout.write(`Connected Telegram username: @${connection.username}\n`)
44
- }
45
- else {
46
- process.stdout.write('Connected Telegram user has no username set.\n')
58
+ process.stdout.write(
59
+ `Connected Telegram username: @${connection.username}\n`,
60
+ );
61
+ } else {
62
+ process.stdout.write("Connected Telegram user has no username set.\n");
47
63
  }
48
64
  }
49
65
 
50
66
  config.profiles[profileName] = {
51
- type: 'telegram',
67
+ type: "telegram",
52
68
  name: profileName,
53
69
  botToken,
54
70
  chatId,
55
71
  createdAt: new Date().toISOString(),
56
- }
72
+ };
57
73
 
58
74
  if (!config.defaultProfile) {
59
- config.defaultProfile = profileName
75
+ config.defaultProfile = profileName;
60
76
  }
61
77
 
62
- await saveConfig(config)
78
+ await saveConfig(config);
63
79
 
64
- let confirmationSent = false
65
- let confirmationWarning: string | null = null
80
+ let confirmationSent = false;
81
+ let confirmationWarning: string | null = null;
66
82
 
67
83
  try {
68
84
  await sendTelegramMessage(
69
85
  botToken,
70
86
  chatId,
71
87
  `nnt: profile "${profileName}" connected successfully. You can now send notifications from CLI.`,
72
- )
73
- confirmationSent = true
74
- }
75
- catch (error) {
76
- confirmationWarning = error instanceof Error ? error.message : 'Unknown error while sending confirmation'
88
+ );
89
+ confirmationSent = true;
90
+ } catch (error) {
91
+ confirmationWarning =
92
+ error instanceof Error
93
+ ? error.message
94
+ : "Unknown error while sending confirmation";
77
95
  }
78
96
 
79
97
  if (shouldRenderPretty(c.agent)) {
80
- printKeyValueTable('Profile added', [
81
- { key: 'profile', value: profileName },
82
- { key: 'provider', value: 'telegram' },
83
- { key: 'chat_id', value: chatId },
84
- { key: 'username', value: connection.username ? `@${connection.username}` : '(none)' },
85
- { key: 'default', value: config.defaultProfile ?? '(none)' },
86
- ])
98
+ printKeyValueTable("Profile added", [
99
+ { key: "profile", value: profileName },
100
+ { key: "provider", value: "telegram" },
101
+ { key: "chat_id", value: chatId },
102
+ {
103
+ key: "username",
104
+ value: connection.username ? `@${connection.username}` : "(none)",
105
+ },
106
+ { key: "default", value: config.defaultProfile ?? "(none)" },
107
+ ]);
87
108
  }
88
109
 
89
110
  return {
90
111
  added: true,
91
112
  profile: profileName,
92
- provider: 'telegram',
113
+ provider: "telegram",
93
114
  chatId,
94
115
  username: connection.username,
95
116
  defaultProfile: config.defaultProfile,
96
117
  configPath: getConfigPath(),
97
118
  confirmationSent,
98
119
  confirmationWarning,
99
- }
120
+ };
100
121
  },
101
- })
122
+ });
102
123
 
103
- profileCli.command('list', {
104
- description: 'List configured profiles',
105
- outputPolicy: 'agent-only',
124
+ profileCli.command("list", {
125
+ description: "List configured profiles",
126
+ outputPolicy: "agent-only",
106
127
  async run(c) {
107
- const config = await loadConfig()
108
- const names = Object.keys(config.profiles).sort((a, b) => a.localeCompare(b))
109
- const profiles = names.map(name => ({
128
+ const config = await loadConfig();
129
+ const names = Object.keys(config.profiles).sort((a, b) =>
130
+ a.localeCompare(b),
131
+ );
132
+ const profiles = names.map((name) => ({
110
133
  name,
111
134
  provider: config.profiles[name].type,
112
135
  isDefault: name === config.defaultProfile,
113
- }))
136
+ }));
114
137
 
115
138
  if (shouldRenderPretty(c.agent)) {
116
- printProfilesTable(profiles)
139
+ printProfilesTable(profiles);
117
140
  }
118
141
 
119
142
  return {
120
143
  defaultProfile: config.defaultProfile,
121
144
  totalProfiles: names.length,
122
145
  profiles,
123
- }
146
+ };
124
147
  },
125
- })
148
+ });
126
149
 
127
- profileCli.command('default', {
128
- description: 'Get or set default profile',
129
- outputPolicy: 'agent-only',
150
+ profileCli.command("default", {
151
+ description: "Get or set default profile",
152
+ outputPolicy: "agent-only",
130
153
  args: z.object({
131
- profile: z.string().optional().describe('Profile name to set as default'),
154
+ profile: z.string().optional().describe("Profile name to set as default"),
132
155
  }),
133
156
  async run(c) {
134
- const config = await loadConfig()
157
+ const config = await loadConfig();
135
158
 
136
159
  if (!c.args.profile) {
137
160
  if (shouldRenderPretty(c.agent)) {
138
- printKeyValueTable('Default profile', [
139
- { key: 'default', value: config.defaultProfile ?? '(not set)' },
140
- ])
161
+ printKeyValueTable("Default profile", [
162
+ { key: "default", value: config.defaultProfile ?? "(not set)" },
163
+ ]);
141
164
  }
142
165
 
143
166
  return {
144
167
  defaultProfile: config.defaultProfile,
145
- }
168
+ };
146
169
  }
147
170
 
148
171
  if (!config.profiles[c.args.profile]) {
149
- throw new Error(`Profile "${c.args.profile}" not found.`)
172
+ throw new Error(`Profile "${c.args.profile}" not found.`);
150
173
  }
151
174
 
152
- config.defaultProfile = c.args.profile
153
- await saveConfig(config)
175
+ config.defaultProfile = c.args.profile;
176
+ await saveConfig(config);
154
177
 
155
178
  if (shouldRenderPretty(c.agent)) {
156
- printKeyValueTable('Default profile updated', [
157
- { key: 'default', value: config.defaultProfile ?? '(not set)' },
158
- ])
179
+ printKeyValueTable("Default profile updated", [
180
+ { key: "default", value: config.defaultProfile ?? "(not set)" },
181
+ ]);
159
182
  }
160
183
 
161
184
  return {
162
185
  updated: true,
163
186
  defaultProfile: config.defaultProfile,
164
- }
187
+ };
165
188
  },
166
- })
189
+ });
167
190
 
168
- profileCli.command('delete', {
169
- description: 'Delete a profile',
170
- outputPolicy: 'agent-only',
191
+ profileCli.command("delete", {
192
+ description: "Delete a profile",
193
+ outputPolicy: "agent-only",
171
194
  args: z.object({
172
- profile: z.string().describe('Profile name to delete'),
195
+ profile: z.string().describe("Profile name to delete"),
173
196
  }),
174
197
  async run(c) {
175
- const config = await loadConfig()
176
- const targetName = c.args.profile
177
- const profile = config.profiles[targetName]
198
+ const config = await loadConfig();
199
+ const targetName = c.args.profile;
200
+ const profile = config.profiles[targetName];
178
201
 
179
202
  if (!profile) {
180
- throw new Error(`Profile "${targetName}" not found.`)
203
+ throw new Error(`Profile "${targetName}" not found.`);
181
204
  }
182
205
 
183
- delete config.profiles[targetName]
206
+ delete config.profiles[targetName];
184
207
 
185
208
  if (config.defaultProfile === targetName) {
186
- const remaining = Object.keys(config.profiles).sort((a, b) => a.localeCompare(b))
187
- config.defaultProfile = remaining[0] ?? null
209
+ const remaining = Object.keys(config.profiles).sort((a, b) =>
210
+ a.localeCompare(b),
211
+ );
212
+ config.defaultProfile = remaining[0] ?? null;
188
213
  }
189
214
 
190
- await saveConfig(config)
215
+ await saveConfig(config);
191
216
 
192
217
  if (shouldRenderPretty(c.agent)) {
193
- printKeyValueTable('Profile deleted', [
194
- { key: 'profile', value: targetName },
195
- { key: 'provider', value: profile.type },
196
- { key: 'default', value: config.defaultProfile ?? '(not set)' },
197
- ])
218
+ printKeyValueTable("Profile deleted", [
219
+ { key: "profile", value: targetName },
220
+ { key: "provider", value: profile.type },
221
+ { key: "default", value: config.defaultProfile ?? "(not set)" },
222
+ ]);
198
223
  }
199
224
 
200
225
  return {
@@ -202,110 +227,142 @@ profileCli.command('delete', {
202
227
  profile: targetName,
203
228
  provider: profile.type,
204
229
  defaultProfile: config.defaultProfile,
205
- }
230
+ };
206
231
  },
207
- })
232
+ });
208
233
 
209
- profileCli.command('edit', {
210
- description: 'Edit profile data',
211
- outputPolicy: 'agent-only',
234
+ profileCli.command("edit", {
235
+ description: "Edit profile data",
236
+ outputPolicy: "agent-only",
212
237
  args: z.object({
213
- profile: z.string().optional().describe('Existing profile name'),
238
+ profile: z.string().optional().describe("Existing profile name"),
214
239
  }),
215
240
  options: z.object({
216
- newName: z.string().optional().describe('Rename profile to a new name'),
217
- botToken: z.string().optional().describe('Replace Telegram bot token'),
218
- chatId: z.string().optional().describe('Replace Telegram chat id'),
219
- reconnect: z.boolean().optional().describe('Re-detect chat id from next Telegram message'),
241
+ newName: z.string().optional().describe("Rename profile to a new name"),
242
+ botToken: z.string().optional().describe("Replace Telegram bot token"),
243
+ chatId: z.string().optional().describe("Replace Telegram chat id"),
244
+ reconnect: z
245
+ .boolean()
246
+ .optional()
247
+ .describe("Re-detect chat id from next Telegram message"),
220
248
  }),
221
249
  alias: {
222
- newName: 'n',
223
- botToken: 't',
224
- chatId: 'c',
225
- reconnect: 'r',
250
+ newName: "n",
251
+ botToken: "t",
252
+ chatId: "c",
253
+ reconnect: "r",
226
254
  },
227
255
  async run(c) {
228
- const config = await loadConfig()
229
- const profileNames = Object.keys(config.profiles).sort((a, b) => a.localeCompare(b))
256
+ const config = await loadConfig();
257
+ const profileNames = Object.keys(config.profiles).sort((a, b) =>
258
+ a.localeCompare(b),
259
+ );
230
260
 
231
261
  if (profileNames.length === 0) {
232
- throw new Error('No profiles found. Run `nnt profile add` first.')
262
+ throw new Error("No profiles found. Run `nnt profile add` first.");
233
263
  }
234
264
 
235
- const hasDirectEditOptions = Boolean(c.options.newName || c.options.botToken || c.options.chatId || c.options.reconnect)
265
+ const hasDirectEditOptions = Boolean(
266
+ c.options.newName ||
267
+ c.options.botToken ||
268
+ c.options.chatId ||
269
+ c.options.reconnect,
270
+ );
236
271
 
237
- const sourceName = await resolveProfileForEdit(c.args.profile, profileNames, hasDirectEditOptions)
238
- const sourceProfile = config.profiles[sourceName]
272
+ const sourceName = await resolveProfileForEdit(
273
+ c.args.profile,
274
+ profileNames,
275
+ hasDirectEditOptions,
276
+ );
277
+ const sourceProfile = config.profiles[sourceName];
239
278
 
240
279
  if (!sourceProfile) {
241
- throw new Error(`Profile "${sourceName}" not found.`)
280
+ throw new Error(`Profile "${sourceName}" not found.`);
242
281
  }
243
282
 
244
- const targetName = c.options.newName ?? sourceName
283
+ const targetName = c.options.newName ?? sourceName;
245
284
 
246
285
  if (targetName !== sourceName && config.profiles[targetName]) {
247
- throw new Error(`Profile "${targetName}" already exists.`)
286
+ throw new Error(`Profile "${targetName}" already exists.`);
248
287
  }
249
288
 
250
- const botToken = c.options.botToken ?? sourceProfile.botToken
251
- let nextName = targetName
252
- let nextBotToken = botToken
253
- let chatId = c.options.chatId ?? sourceProfile.chatId
254
- let connectedUsername: string | null = null
289
+ const botToken = c.options.botToken ?? sourceProfile.botToken;
290
+ let nextName = targetName;
291
+ let nextBotToken = botToken;
292
+ let chatId = c.options.chatId ?? sourceProfile.chatId;
293
+ let connectedUsername: string | null = null;
255
294
 
256
295
  if (!hasDirectEditOptions && canPromptInteractively()) {
257
- nextName = await askRequiredWithInitial('Profile name', sourceName)
296
+ nextName = await askRequiredWithInitial("Profile name", sourceName);
258
297
 
259
298
  if (nextName !== sourceName && config.profiles[nextName]) {
260
- throw new Error(`Profile "${nextName}" already exists.`)
299
+ throw new Error(`Profile "${nextName}" already exists.`);
261
300
  }
262
301
 
263
- nextBotToken = await askRequiredWithInitial('Telegram bot token', sourceProfile.botToken)
302
+ nextBotToken = await askRequiredWithInitial(
303
+ "Telegram bot token",
304
+ sourceProfile.botToken,
305
+ );
264
306
 
265
- const shouldReconnect = await askConfirm('Reconnect and detect chat_id from a new message?', false)
307
+ const shouldReconnect = await askConfirm(
308
+ "Reconnect and detect chat_id from a new message?",
309
+ false,
310
+ );
266
311
 
267
312
  if (shouldReconnect) {
268
313
  if (shouldRenderPretty(c.agent)) {
269
- process.stdout.write('\nSend any message to your bot in Telegram.\n')
270
- process.stdout.write('Waiting for message to detect chat_id (up to 120s)...\n')
314
+ process.stdout.write("\nSend any message to your bot in Telegram.\n");
315
+ process.stdout.write(
316
+ "Waiting for message to detect chat_id (up to 120s)...\n",
317
+ );
271
318
  }
272
319
 
273
- const offset = await getLatestUpdateOffset(nextBotToken)
274
- const connection = await waitForChatId(nextBotToken, offset, 120)
275
- chatId = connection.chatId
276
- connectedUsername = connection.username
320
+ const offset = await getLatestUpdateOffset(nextBotToken);
321
+ const connection = await waitForChatId(nextBotToken, offset, 120);
322
+ chatId = connection.chatId;
323
+ connectedUsername = connection.username;
277
324
 
278
325
  if (shouldRenderPretty(c.agent)) {
279
326
  if (connection.username) {
280
- process.stdout.write(`Connected Telegram username: @${connection.username}\n`)
281
- }
282
- else {
283
- process.stdout.write('Connected Telegram user has no username set.\n')
327
+ process.stdout.write(
328
+ `Connected Telegram username: @${connection.username}\n`,
329
+ );
330
+ } else {
331
+ process.stdout.write(
332
+ "Connected Telegram user has no username set.\n",
333
+ );
284
334
  }
285
335
  }
286
- }
287
- else {
288
- chatId = await askRequiredWithInitial('Telegram chat_id', sourceProfile.chatId)
336
+ } else {
337
+ chatId = await askRequiredWithInitial(
338
+ "Telegram chat_id",
339
+ sourceProfile.chatId,
340
+ );
289
341
  }
290
342
  }
291
343
 
292
344
  if (c.options.reconnect) {
293
345
  if (shouldRenderPretty(c.agent)) {
294
- process.stdout.write('\nSend any message to your bot in Telegram.\n')
295
- process.stdout.write('Waiting for message to detect chat_id (up to 120s)...\n')
346
+ process.stdout.write("\nSend any message to your bot in Telegram.\n");
347
+ process.stdout.write(
348
+ "Waiting for message to detect chat_id (up to 120s)...\n",
349
+ );
296
350
  }
297
351
 
298
- const offset = await getLatestUpdateOffset(nextBotToken)
299
- const connection = await waitForChatId(nextBotToken, offset, 120)
300
- chatId = connection.chatId
301
- connectedUsername = connection.username
352
+ const offset = await getLatestUpdateOffset(nextBotToken);
353
+ const connection = await waitForChatId(nextBotToken, offset, 120);
354
+ chatId = connection.chatId;
355
+ connectedUsername = connection.username;
302
356
 
303
357
  if (shouldRenderPretty(c.agent)) {
304
358
  if (connection.username) {
305
- process.stdout.write(`Connected Telegram username: @${connection.username}\n`)
306
- }
307
- else {
308
- process.stdout.write('Connected Telegram user has no username set.\n')
359
+ process.stdout.write(
360
+ `Connected Telegram username: @${connection.username}\n`,
361
+ );
362
+ } else {
363
+ process.stdout.write(
364
+ "Connected Telegram user has no username set.\n",
365
+ );
309
366
  }
310
367
  }
311
368
  }
@@ -315,22 +372,22 @@ profileCli.command('edit', {
315
372
  name: nextName,
316
373
  botToken: nextBotToken,
317
374
  chatId,
318
- }
375
+ };
319
376
 
320
377
  if (nextName !== sourceName) {
321
- delete config.profiles[sourceName]
378
+ delete config.profiles[sourceName];
322
379
  }
323
380
 
324
- config.profiles[nextName] = updatedProfile
381
+ config.profiles[nextName] = updatedProfile;
325
382
 
326
383
  if (config.defaultProfile === sourceName) {
327
- config.defaultProfile = nextName
384
+ config.defaultProfile = nextName;
328
385
  }
329
386
 
330
387
  const hasChanges =
331
- nextName !== sourceName
332
- || nextBotToken !== sourceProfile.botToken
333
- || chatId !== sourceProfile.chatId
388
+ nextName !== sourceName ||
389
+ nextBotToken !== sourceProfile.botToken ||
390
+ chatId !== sourceProfile.chatId;
334
391
 
335
392
  if (!hasChanges) {
336
393
  return {
@@ -339,19 +396,24 @@ profileCli.command('edit', {
339
396
  provider: sourceProfile.type,
340
397
  defaultProfile: config.defaultProfile,
341
398
  connectedUsername,
342
- }
399
+ };
343
400
  }
344
401
 
345
- await saveConfig(config)
402
+ await saveConfig(config);
346
403
 
347
404
  if (shouldRenderPretty(c.agent)) {
348
- printKeyValueTable('Profile updated', [
349
- { key: 'profile', value: nextName },
350
- { key: 'provider', value: updatedProfile.type },
351
- { key: 'chat_id', value: chatId },
352
- { key: 'username', value: connectedUsername ? `@${connectedUsername}` : '(unchanged/none)' },
353
- { key: 'default', value: config.defaultProfile ?? '(not set)' },
354
- ])
405
+ printKeyValueTable("Profile updated", [
406
+ { key: "profile", value: nextName },
407
+ { key: "provider", value: updatedProfile.type },
408
+ { key: "chat_id", value: chatId },
409
+ {
410
+ key: "username",
411
+ value: connectedUsername
412
+ ? `@${connectedUsername}`
413
+ : "(unchanged/none)",
414
+ },
415
+ { key: "default", value: config.defaultProfile ?? "(not set)" },
416
+ ]);
355
417
  }
356
418
 
357
419
  return {
@@ -361,108 +423,122 @@ profileCli.command('edit', {
361
423
  provider: updatedProfile.type,
362
424
  defaultProfile: config.defaultProfile,
363
425
  connectedUsername,
364
- }
426
+ };
365
427
  },
366
- })
428
+ });
367
429
 
368
- const cli = Cli.create('nnt', {
369
- description: 'Send Telegram notifications from terminal and agents',
430
+ const cli = Cli.create("nnt", {
431
+ description: "Send Telegram notifications from terminal and agents",
370
432
  })
371
- .command('send', {
372
- description: 'Send a message via a saved profile',
433
+ .command("send", {
434
+ description: "Send a message via a saved profile",
373
435
  args: z.object({
374
- message: z.string().describe('Message text to send'),
436
+ message: z.string().describe("Message text to send"),
375
437
  }),
376
438
  options: z.object({
377
- profile: z.string().optional().describe('Profile name from config'),
439
+ profile: z.string().optional().describe("Profile name from config"),
378
440
  }),
379
441
  alias: {
380
- profile: 'p',
442
+ profile: "p",
381
443
  },
382
444
  async run(c) {
383
- const config = await loadConfig()
384
- const profileName = c.options.profile ?? config.defaultProfile
445
+ const config = await loadConfig();
446
+ const profileName = c.options.profile ?? config.defaultProfile;
385
447
 
386
448
  if (!profileName) {
387
- throw new Error('No default profile found. Run `nnt profile add` first.')
449
+ throw new Error(
450
+ "No default profile found. Run `nnt profile add` first.",
451
+ );
388
452
  }
389
453
 
390
- const profile = config.profiles[profileName]
454
+ const profile = config.profiles[profileName];
391
455
 
392
456
  if (!profile) {
393
- throw new Error(`Profile "${profileName}" not found.`)
457
+ throw new Error(`Profile "${profileName}" not found.`);
394
458
  }
395
459
 
396
- await sendTelegramMessage(profile.botToken, profile.chatId, c.args.message)
460
+ await sendTelegramMessage(
461
+ profile.botToken,
462
+ profile.chatId,
463
+ c.args.message,
464
+ );
397
465
 
398
466
  return {
399
467
  sent: true,
400
468
  profile: profileName,
401
469
  provider: profile.type,
402
- }
470
+ };
403
471
  },
404
472
  })
405
- .command(profileCli)
473
+ .command(profileCli);
406
474
 
407
475
  function routeDefaultCommand(argv: string[]): string[] {
408
476
  if (argv.length === 0) {
409
- return argv
477
+ return argv;
410
478
  }
411
479
 
412
- const topLevelCommands = new Set(['profile', 'send', 'skills', 'mcp'])
413
- const bareGlobalFlags = new Set(['--help', '-h', '--version', '--llms', '--mcp', '--json', '--verbose'])
414
-
415
- let index = 0
480
+ const topLevelCommands = new Set(["profile", "send", "skills", "mcp"]);
481
+ const bareGlobalFlags = new Set([
482
+ "--help",
483
+ "-h",
484
+ "--version",
485
+ "--llms",
486
+ "--mcp",
487
+ "--json",
488
+ "--verbose",
489
+ ]);
490
+
491
+ let index = 0;
416
492
  while (index < argv.length) {
417
- const token = argv[index]
493
+ const token = argv[index];
418
494
 
419
- if (token === '--format') {
420
- index += 2
421
- continue
495
+ if (token === "--format") {
496
+ index += 2;
497
+ continue;
422
498
  }
423
499
 
424
500
  if (bareGlobalFlags.has(token)) {
425
- index += 1
426
- continue
501
+ index += 1;
502
+ continue;
427
503
  }
428
504
 
429
- break
505
+ break;
430
506
  }
431
507
 
432
508
  if (index >= argv.length) {
433
- return argv
509
+ return argv;
434
510
  }
435
511
 
436
512
  if (topLevelCommands.has(argv[index])) {
437
- return argv
513
+ return argv;
438
514
  }
439
515
 
440
- return [...argv.slice(0, index), 'send', ...argv.slice(index)]
516
+ return [...argv.slice(0, index), "send", ...argv.slice(index)];
441
517
  }
442
518
 
443
519
  function normalizeFormatFlag(argv: string[]): string[] {
444
- const normalized: string[] = []
520
+ const normalized: string[] = [];
445
521
 
446
522
  for (const token of argv) {
447
- if (token.startsWith('--format=')) {
448
- normalized.push('--format', token.slice('--format='.length))
449
- continue
523
+ if (token.startsWith("--format=")) {
524
+ normalized.push("--format", token.slice("--format=".length));
525
+ continue;
450
526
  }
451
527
 
452
- normalized.push(token)
528
+ normalized.push(token);
453
529
  }
454
530
 
455
- return normalized
531
+ return normalized;
456
532
  }
457
533
 
458
534
  function isStrictOutputRequested(argv: string[]): boolean {
459
535
  for (const token of argv) {
460
- if (token === '--json' || token === '--verbose' || token === '--format') {
461
- return true
536
+ if (token === "--json" || token === "--verbose" || token === "--format") {
537
+ return true;
462
538
  }
463
539
  }
464
540
 
465
- return false
541
+ return false;
466
542
  }
467
543
 
468
544
  function isAgentEnvironment(): boolean {
@@ -472,19 +548,22 @@ function isAgentEnvironment(): boolean {
472
548
  process.env.CURSOR_AGENT,
473
549
  process.env.AIDER_SESSION,
474
550
  process.env.NNT_AGENT_MODE,
475
- ].some(Boolean)
551
+ ].some(Boolean);
476
552
  }
477
553
 
478
- function withAgentDefaultFormat(argv: string[], strictOutputRequested: boolean): string[] {
554
+ function withAgentDefaultFormat(
555
+ argv: string[],
556
+ strictOutputRequested: boolean,
557
+ ): string[] {
479
558
  if (strictOutputRequested || !isAgentEnvironment()) {
480
- return argv
559
+ return argv;
481
560
  }
482
561
 
483
- return ['--format', 'toon', ...argv]
562
+ return ["--format", "toon", ...argv];
484
563
  }
485
564
 
486
565
  function canPromptInteractively(): boolean {
487
- return Boolean(process.stdin.isTTY && process.stdout.isTTY)
566
+ return Boolean(process.stdin.isTTY && process.stdout.isTTY);
488
567
  }
489
568
 
490
569
  async function resolveProfileForEdit(
@@ -493,28 +572,34 @@ async function resolveProfileForEdit(
493
572
  hasDirectEditOptions: boolean,
494
573
  ): Promise<string> {
495
574
  if (profileFromArgs) {
496
- return profileFromArgs
575
+ return profileFromArgs;
497
576
  }
498
577
 
499
578
  if (hasDirectEditOptions || !canPromptInteractively()) {
500
- throw new Error('Profile name is required in non-interactive mode.')
579
+ throw new Error("Profile name is required in non-interactive mode.");
501
580
  }
502
581
 
503
- return askSelect('Select profile to edit', profileNames.map(name => ({
504
- value: name,
505
- label: name,
506
- })))
582
+ return askSelect(
583
+ "Select profile to edit",
584
+ profileNames.map((name) => ({
585
+ value: name,
586
+ label: name,
587
+ })),
588
+ );
507
589
  }
508
590
 
509
- const normalizedArgv = normalizeFormatFlag(process.argv.slice(2))
510
- const strictOutputRequested = isStrictOutputRequested(normalizedArgv)
511
- const argvWithAgentDefaults = withAgentDefaultFormat(normalizedArgv, strictOutputRequested)
591
+ const normalizedArgv = normalizeFormatFlag(process.argv.slice(2));
592
+ const strictOutputRequested = isStrictOutputRequested(normalizedArgv);
593
+ const argvWithAgentDefaults = withAgentDefaultFormat(
594
+ normalizedArgv,
595
+ strictOutputRequested,
596
+ );
512
597
 
513
598
  function shouldRenderPretty(agent: boolean): boolean {
514
- return !agent && !strictOutputRequested && !isAgentEnvironment()
599
+ return !agent && !strictOutputRequested && !isAgentEnvironment();
515
600
  }
516
601
 
517
- const routedArgv = routeDefaultCommand(argvWithAgentDefaults)
518
- await cli.serve(routedArgv)
602
+ const routedArgv = routeDefaultCommand(argvWithAgentDefaults);
603
+ await cli.serve(routedArgv);
519
604
 
520
- export default cli
605
+ export default cli;