@cmdop/bot 2026.2.26 → 2026.2.28

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/dist/index.d.cts CHANGED
@@ -1,9 +1,46 @@
1
1
  import { z } from 'zod/v4';
2
2
  import { CMDOPClient } from '@cmdop/node';
3
+ import { ConsolaInstance } from 'consola';
3
4
  import { WebClient } from '@slack/web-api';
4
5
  import { InlineKeyboardButton } from 'grammy/types';
5
6
  import { RESTPostAPIChatInputApplicationCommandsJSONBody } from 'discord.js';
6
7
 
8
+ declare const PermissionLevelSchema: z.ZodEnum<{
9
+ NONE: "NONE";
10
+ READ: "READ";
11
+ EXECUTE: "EXECUTE";
12
+ FILES: "FILES";
13
+ ADMIN: "ADMIN";
14
+ }>;
15
+ type PermissionLevel = z.infer<typeof PermissionLevelSchema>;
16
+ declare const PERMISSION_ORDER: Record<PermissionLevel, number>;
17
+ declare const UserIdentitySchema: z.ZodObject<{
18
+ platform: z.ZodString;
19
+ platformId: z.ZodString;
20
+ username: z.ZodOptional<z.ZodString>;
21
+ displayName: z.ZodOptional<z.ZodString>;
22
+ }, z.core.$strip>;
23
+ type UserIdentity = z.infer<typeof UserIdentitySchema>;
24
+ declare const BotUserSchema: z.ZodObject<{
25
+ id: z.ZodString;
26
+ identity: z.ZodObject<{
27
+ platform: z.ZodString;
28
+ platformId: z.ZodString;
29
+ username: z.ZodOptional<z.ZodString>;
30
+ displayName: z.ZodOptional<z.ZodString>;
31
+ }, z.core.$strip>;
32
+ permission: z.ZodEnum<{
33
+ NONE: "NONE";
34
+ READ: "READ";
35
+ EXECUTE: "EXECUTE";
36
+ FILES: "FILES";
37
+ ADMIN: "ADMIN";
38
+ }>;
39
+ createdAt: z.ZodCoercedDate<unknown>;
40
+ lastSeenAt: z.ZodCoercedDate<unknown>;
41
+ }, z.core.$strip>;
42
+ type BotUser = z.infer<typeof BotUserSchema>;
43
+
7
44
  declare const AttachmentSchema: z.ZodObject<{
8
45
  type: z.ZodEnum<{
9
46
  photo: "photo";
@@ -71,42 +108,6 @@ declare const OutgoingMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
71
108
  }, z.core.$strip>], "type">;
72
109
  type OutgoingMessage = z.infer<typeof OutgoingMessageSchema>;
73
110
 
74
- declare const PermissionLevelSchema: z.ZodEnum<{
75
- NONE: "NONE";
76
- READ: "READ";
77
- EXECUTE: "EXECUTE";
78
- FILES: "FILES";
79
- ADMIN: "ADMIN";
80
- }>;
81
- type PermissionLevel = z.infer<typeof PermissionLevelSchema>;
82
- declare const PERMISSION_ORDER: Record<PermissionLevel, number>;
83
- declare const UserIdentitySchema: z.ZodObject<{
84
- platform: z.ZodString;
85
- platformId: z.ZodString;
86
- username: z.ZodOptional<z.ZodString>;
87
- displayName: z.ZodOptional<z.ZodString>;
88
- }, z.core.$strip>;
89
- type UserIdentity = z.infer<typeof UserIdentitySchema>;
90
- declare const BotUserSchema: z.ZodObject<{
91
- id: z.ZodString;
92
- identity: z.ZodObject<{
93
- platform: z.ZodString;
94
- platformId: z.ZodString;
95
- username: z.ZodOptional<z.ZodString>;
96
- displayName: z.ZodOptional<z.ZodString>;
97
- }, z.core.$strip>;
98
- permission: z.ZodEnum<{
99
- NONE: "NONE";
100
- READ: "READ";
101
- EXECUTE: "EXECUTE";
102
- FILES: "FILES";
103
- ADMIN: "ADMIN";
104
- }>;
105
- createdAt: z.ZodCoercedDate<unknown>;
106
- lastSeenAt: z.ZodCoercedDate<unknown>;
107
- }, z.core.$strip>;
108
- type BotUser = z.infer<typeof BotUserSchema>;
109
-
110
111
  declare const ParsedCommandSchema: z.ZodObject<{
111
112
  name: z.ZodString;
112
113
  args: z.ZodArray<z.ZodString>;
@@ -346,6 +347,7 @@ declare abstract class BaseChannel implements ChannelProtocol {
346
347
  abstract onMessage(handler: (msg: IncomingMessage) => Promise<void>): void;
347
348
  /**
348
349
  * Process an incoming message: parse command → check permission → dispatch → send result.
350
+ * Plain text (non-command) is routed to the agent handler automatically.
349
351
  * Channels call this from their platform event handler.
350
352
  */
351
353
  protected processMessage(msg: IncomingMessage): Promise<void>;
@@ -450,9 +452,36 @@ declare const BotSettingsSchema: z.ZodObject<{
450
452
  type BotSettings = z.infer<typeof BotSettingsSchema>;
451
453
  declare function loadSettings(env?: NodeJS.ProcessEnv): BotSettings;
452
454
 
455
+ interface DemoChannelOptions {
456
+ /** Called for every outgoing message (default: JSON to stdout) */
457
+ onOutput?: (text: string, message: OutgoingMessage) => void;
458
+ }
459
+ /**
460
+ * DemoChannel — stdio-based channel for local testing and CLI usage.
461
+ * No real platform; messages are injected programmatically via injectMessage().
462
+ */
463
+ declare class DemoChannel extends BaseChannel {
464
+ private messageHandlers;
465
+ private readonly onOutput;
466
+ constructor(permissions: PermissionManager, dispatcher: MessageDispatcher, logger: LoggerProtocol, options?: DemoChannelOptions);
467
+ start(): Promise<void>;
468
+ stop(): Promise<void>;
469
+ send(_userId: string, message: OutgoingMessage): Promise<void>;
470
+ onMessage(handler: (msg: IncomingMessage) => Promise<void>): void;
471
+ /**
472
+ * Inject a message as if it came from a real platform user.
473
+ * Primarily used in tests and CLI demos.
474
+ */
475
+ injectMessage(input: {
476
+ userId?: string;
477
+ text: string;
478
+ }): Promise<void>;
479
+ }
480
+
453
481
  type TelegramOptions = TelegramChannelOptions;
454
482
  type DiscordOptions = DiscordChannelOptions;
455
483
  type SlackOptions = SlackChannelOptions;
484
+
456
485
  interface HubOptions {
457
486
  /** CMDOP cloud API key. If omitted, uses local IPC connection. */
458
487
  apiKey?: string;
@@ -464,6 +493,12 @@ interface HubOptions {
464
493
  permissionStore?: PermissionStoreProtocol;
465
494
  /** Admin user IDs (always have ADMIN permission). */
466
495
  adminUsers?: string[];
496
+ /**
497
+ * Default permission level for new/unknown users.
498
+ * Set to 'EXECUTE' to allow all users to run commands without explicit grants.
499
+ * Default: 'NONE'
500
+ */
501
+ defaultPermission?: PermissionLevel;
467
502
  /** Logger instance. Default: stderr JSON logger at info level. */
468
503
  logger?: LoggerProtocol;
469
504
  /** Bot settings. Default: loaded from environment variables. */
@@ -509,6 +544,11 @@ declare class IntegrationHub {
509
544
  * Requires `@slack/bolt` and `@slack/web-api` to be installed.
510
545
  */
511
546
  addSlack(options: SlackOptions): Promise<this>;
547
+ /**
548
+ * Create and register a DemoChannel for CLI testing.
549
+ * No external dependencies — messages are injected via the returned channel's `injectMessage()`.
550
+ */
551
+ addDemo(options?: DemoChannelOptions): DemoChannel;
512
552
  registerHandler(handler: HandlerProtocol): this;
513
553
  start(): Promise<void>;
514
554
  stop(): Promise<void>;
@@ -554,7 +594,13 @@ declare abstract class BaseHandler implements HandlerProtocol {
554
594
  }
555
595
 
556
596
  type LogLevel = 'debug' | 'info' | 'warn' | 'error';
557
- declare function createLogger(level?: LogLevel): LoggerProtocol;
597
+ /**
598
+ * Create a bot logger backed by consola.
599
+ * Pretty output in dev, structured JSON when CMDOP_LOG_JSON=1.
600
+ */
601
+ declare function createLogger(level?: LogLevel): LoggerProtocol & {
602
+ consola: ConsolaInstance;
603
+ };
558
604
 
559
605
  declare const UserSessionSchema: z.ZodObject<{
560
606
  userId: z.ZodString;
@@ -704,32 +750,6 @@ declare class HelpHandler extends BaseHandler {
704
750
  handle(_ctx: CommandContext): Promise<HandlerResult>;
705
751
  }
706
752
 
707
- interface DemoChannelOptions {
708
- /** Called for every outgoing message (default: JSON to stdout) */
709
- onOutput?: (text: string, message: OutgoingMessage) => void;
710
- }
711
- /**
712
- * DemoChannel — stdio-based channel for local testing and CLI usage.
713
- * No real platform; messages are injected programmatically via injectMessage().
714
- */
715
- declare class DemoChannel extends BaseChannel {
716
- private messageHandlers;
717
- private readonly onOutput;
718
- constructor(permissions: PermissionManager, dispatcher: MessageDispatcher, logger: LoggerProtocol, options?: DemoChannelOptions);
719
- start(): Promise<void>;
720
- stop(): Promise<void>;
721
- send(_userId: string, message: OutgoingMessage): Promise<void>;
722
- onMessage(handler: (msg: IncomingMessage) => Promise<void>): void;
723
- /**
724
- * Inject a message as if it came from a real platform user.
725
- * Primarily used in tests and CLI demos.
726
- */
727
- injectMessage(input: {
728
- userId?: string;
729
- text: string;
730
- }): Promise<void>;
731
- }
732
-
733
753
  declare class TelegramFormatter implements FormatterProtocol {
734
754
  /**
735
755
  * Escape plain text for safe inclusion in MarkdownV2 messages.
@@ -748,6 +768,23 @@ declare class TelegramFormatter implements FormatterProtocol {
748
768
  * Format a file listing entry line.
749
769
  */
750
770
  formatFileEntry(name: string, isDir: boolean, size?: number): string;
771
+ /**
772
+ * Escape HTML special chars, then convert basic markdown to HTML tags.
773
+ * Handles: **bold**, `code`, ```code blocks```, _italic_
774
+ */
775
+ formatTextHtml(text: string): string;
776
+ /**
777
+ * Format code block as HTML <pre>.
778
+ */
779
+ formatCodeHtml(code: string, language?: string): string;
780
+ /**
781
+ * Format error message as HTML.
782
+ */
783
+ formatErrorHtml(message: string): string;
784
+ /**
785
+ * Format file entry as HTML.
786
+ */
787
+ formatFileEntryHtml(name: string, isDir: boolean, size?: number): string;
751
788
  private escapeInline;
752
789
  }
753
790
 
package/dist/index.d.ts CHANGED
@@ -1,9 +1,46 @@
1
1
  import { z } from 'zod/v4';
2
2
  import { CMDOPClient } from '@cmdop/node';
3
+ import { ConsolaInstance } from 'consola';
3
4
  import { WebClient } from '@slack/web-api';
4
5
  import { InlineKeyboardButton } from 'grammy/types';
5
6
  import { RESTPostAPIChatInputApplicationCommandsJSONBody } from 'discord.js';
6
7
 
8
+ declare const PermissionLevelSchema: z.ZodEnum<{
9
+ NONE: "NONE";
10
+ READ: "READ";
11
+ EXECUTE: "EXECUTE";
12
+ FILES: "FILES";
13
+ ADMIN: "ADMIN";
14
+ }>;
15
+ type PermissionLevel = z.infer<typeof PermissionLevelSchema>;
16
+ declare const PERMISSION_ORDER: Record<PermissionLevel, number>;
17
+ declare const UserIdentitySchema: z.ZodObject<{
18
+ platform: z.ZodString;
19
+ platformId: z.ZodString;
20
+ username: z.ZodOptional<z.ZodString>;
21
+ displayName: z.ZodOptional<z.ZodString>;
22
+ }, z.core.$strip>;
23
+ type UserIdentity = z.infer<typeof UserIdentitySchema>;
24
+ declare const BotUserSchema: z.ZodObject<{
25
+ id: z.ZodString;
26
+ identity: z.ZodObject<{
27
+ platform: z.ZodString;
28
+ platformId: z.ZodString;
29
+ username: z.ZodOptional<z.ZodString>;
30
+ displayName: z.ZodOptional<z.ZodString>;
31
+ }, z.core.$strip>;
32
+ permission: z.ZodEnum<{
33
+ NONE: "NONE";
34
+ READ: "READ";
35
+ EXECUTE: "EXECUTE";
36
+ FILES: "FILES";
37
+ ADMIN: "ADMIN";
38
+ }>;
39
+ createdAt: z.ZodCoercedDate<unknown>;
40
+ lastSeenAt: z.ZodCoercedDate<unknown>;
41
+ }, z.core.$strip>;
42
+ type BotUser = z.infer<typeof BotUserSchema>;
43
+
7
44
  declare const AttachmentSchema: z.ZodObject<{
8
45
  type: z.ZodEnum<{
9
46
  photo: "photo";
@@ -71,42 +108,6 @@ declare const OutgoingMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
71
108
  }, z.core.$strip>], "type">;
72
109
  type OutgoingMessage = z.infer<typeof OutgoingMessageSchema>;
73
110
 
74
- declare const PermissionLevelSchema: z.ZodEnum<{
75
- NONE: "NONE";
76
- READ: "READ";
77
- EXECUTE: "EXECUTE";
78
- FILES: "FILES";
79
- ADMIN: "ADMIN";
80
- }>;
81
- type PermissionLevel = z.infer<typeof PermissionLevelSchema>;
82
- declare const PERMISSION_ORDER: Record<PermissionLevel, number>;
83
- declare const UserIdentitySchema: z.ZodObject<{
84
- platform: z.ZodString;
85
- platformId: z.ZodString;
86
- username: z.ZodOptional<z.ZodString>;
87
- displayName: z.ZodOptional<z.ZodString>;
88
- }, z.core.$strip>;
89
- type UserIdentity = z.infer<typeof UserIdentitySchema>;
90
- declare const BotUserSchema: z.ZodObject<{
91
- id: z.ZodString;
92
- identity: z.ZodObject<{
93
- platform: z.ZodString;
94
- platformId: z.ZodString;
95
- username: z.ZodOptional<z.ZodString>;
96
- displayName: z.ZodOptional<z.ZodString>;
97
- }, z.core.$strip>;
98
- permission: z.ZodEnum<{
99
- NONE: "NONE";
100
- READ: "READ";
101
- EXECUTE: "EXECUTE";
102
- FILES: "FILES";
103
- ADMIN: "ADMIN";
104
- }>;
105
- createdAt: z.ZodCoercedDate<unknown>;
106
- lastSeenAt: z.ZodCoercedDate<unknown>;
107
- }, z.core.$strip>;
108
- type BotUser = z.infer<typeof BotUserSchema>;
109
-
110
111
  declare const ParsedCommandSchema: z.ZodObject<{
111
112
  name: z.ZodString;
112
113
  args: z.ZodArray<z.ZodString>;
@@ -346,6 +347,7 @@ declare abstract class BaseChannel implements ChannelProtocol {
346
347
  abstract onMessage(handler: (msg: IncomingMessage) => Promise<void>): void;
347
348
  /**
348
349
  * Process an incoming message: parse command → check permission → dispatch → send result.
350
+ * Plain text (non-command) is routed to the agent handler automatically.
349
351
  * Channels call this from their platform event handler.
350
352
  */
351
353
  protected processMessage(msg: IncomingMessage): Promise<void>;
@@ -450,9 +452,36 @@ declare const BotSettingsSchema: z.ZodObject<{
450
452
  type BotSettings = z.infer<typeof BotSettingsSchema>;
451
453
  declare function loadSettings(env?: NodeJS.ProcessEnv): BotSettings;
452
454
 
455
+ interface DemoChannelOptions {
456
+ /** Called for every outgoing message (default: JSON to stdout) */
457
+ onOutput?: (text: string, message: OutgoingMessage) => void;
458
+ }
459
+ /**
460
+ * DemoChannel — stdio-based channel for local testing and CLI usage.
461
+ * No real platform; messages are injected programmatically via injectMessage().
462
+ */
463
+ declare class DemoChannel extends BaseChannel {
464
+ private messageHandlers;
465
+ private readonly onOutput;
466
+ constructor(permissions: PermissionManager, dispatcher: MessageDispatcher, logger: LoggerProtocol, options?: DemoChannelOptions);
467
+ start(): Promise<void>;
468
+ stop(): Promise<void>;
469
+ send(_userId: string, message: OutgoingMessage): Promise<void>;
470
+ onMessage(handler: (msg: IncomingMessage) => Promise<void>): void;
471
+ /**
472
+ * Inject a message as if it came from a real platform user.
473
+ * Primarily used in tests and CLI demos.
474
+ */
475
+ injectMessage(input: {
476
+ userId?: string;
477
+ text: string;
478
+ }): Promise<void>;
479
+ }
480
+
453
481
  type TelegramOptions = TelegramChannelOptions;
454
482
  type DiscordOptions = DiscordChannelOptions;
455
483
  type SlackOptions = SlackChannelOptions;
484
+
456
485
  interface HubOptions {
457
486
  /** CMDOP cloud API key. If omitted, uses local IPC connection. */
458
487
  apiKey?: string;
@@ -464,6 +493,12 @@ interface HubOptions {
464
493
  permissionStore?: PermissionStoreProtocol;
465
494
  /** Admin user IDs (always have ADMIN permission). */
466
495
  adminUsers?: string[];
496
+ /**
497
+ * Default permission level for new/unknown users.
498
+ * Set to 'EXECUTE' to allow all users to run commands without explicit grants.
499
+ * Default: 'NONE'
500
+ */
501
+ defaultPermission?: PermissionLevel;
467
502
  /** Logger instance. Default: stderr JSON logger at info level. */
468
503
  logger?: LoggerProtocol;
469
504
  /** Bot settings. Default: loaded from environment variables. */
@@ -509,6 +544,11 @@ declare class IntegrationHub {
509
544
  * Requires `@slack/bolt` and `@slack/web-api` to be installed.
510
545
  */
511
546
  addSlack(options: SlackOptions): Promise<this>;
547
+ /**
548
+ * Create and register a DemoChannel for CLI testing.
549
+ * No external dependencies — messages are injected via the returned channel's `injectMessage()`.
550
+ */
551
+ addDemo(options?: DemoChannelOptions): DemoChannel;
512
552
  registerHandler(handler: HandlerProtocol): this;
513
553
  start(): Promise<void>;
514
554
  stop(): Promise<void>;
@@ -554,7 +594,13 @@ declare abstract class BaseHandler implements HandlerProtocol {
554
594
  }
555
595
 
556
596
  type LogLevel = 'debug' | 'info' | 'warn' | 'error';
557
- declare function createLogger(level?: LogLevel): LoggerProtocol;
597
+ /**
598
+ * Create a bot logger backed by consola.
599
+ * Pretty output in dev, structured JSON when CMDOP_LOG_JSON=1.
600
+ */
601
+ declare function createLogger(level?: LogLevel): LoggerProtocol & {
602
+ consola: ConsolaInstance;
603
+ };
558
604
 
559
605
  declare const UserSessionSchema: z.ZodObject<{
560
606
  userId: z.ZodString;
@@ -704,32 +750,6 @@ declare class HelpHandler extends BaseHandler {
704
750
  handle(_ctx: CommandContext): Promise<HandlerResult>;
705
751
  }
706
752
 
707
- interface DemoChannelOptions {
708
- /** Called for every outgoing message (default: JSON to stdout) */
709
- onOutput?: (text: string, message: OutgoingMessage) => void;
710
- }
711
- /**
712
- * DemoChannel — stdio-based channel for local testing and CLI usage.
713
- * No real platform; messages are injected programmatically via injectMessage().
714
- */
715
- declare class DemoChannel extends BaseChannel {
716
- private messageHandlers;
717
- private readonly onOutput;
718
- constructor(permissions: PermissionManager, dispatcher: MessageDispatcher, logger: LoggerProtocol, options?: DemoChannelOptions);
719
- start(): Promise<void>;
720
- stop(): Promise<void>;
721
- send(_userId: string, message: OutgoingMessage): Promise<void>;
722
- onMessage(handler: (msg: IncomingMessage) => Promise<void>): void;
723
- /**
724
- * Inject a message as if it came from a real platform user.
725
- * Primarily used in tests and CLI demos.
726
- */
727
- injectMessage(input: {
728
- userId?: string;
729
- text: string;
730
- }): Promise<void>;
731
- }
732
-
733
753
  declare class TelegramFormatter implements FormatterProtocol {
734
754
  /**
735
755
  * Escape plain text for safe inclusion in MarkdownV2 messages.
@@ -748,6 +768,23 @@ declare class TelegramFormatter implements FormatterProtocol {
748
768
  * Format a file listing entry line.
749
769
  */
750
770
  formatFileEntry(name: string, isDir: boolean, size?: number): string;
771
+ /**
772
+ * Escape HTML special chars, then convert basic markdown to HTML tags.
773
+ * Handles: **bold**, `code`, ```code blocks```, _italic_
774
+ */
775
+ formatTextHtml(text: string): string;
776
+ /**
777
+ * Format code block as HTML <pre>.
778
+ */
779
+ formatCodeHtml(code: string, language?: string): string;
780
+ /**
781
+ * Format error message as HTML.
782
+ */
783
+ formatErrorHtml(message: string): string;
784
+ /**
785
+ * Format file entry as HTML.
786
+ */
787
+ formatFileEntryHtml(name: string, isDir: boolean, size?: number): string;
751
788
  private escapeInline;
752
789
  }
753
790