@hardlydifficult/chat 1.1.59 → 1.1.61

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.
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Message dispatcher — routes messages to commands, handles typing indicators,
3
+ * and cleans up user messages after processing.
4
+ *
5
+ * Application-specific behavior (e.g., AI command suggestions for unrecognized
6
+ * input) is plugged in via the `onUnrecognized` callback.
7
+ */
8
+ import type { Channel } from "../Channel";
9
+ import type { Message } from "../Message";
10
+ import type { CommandRegistry } from "./CommandRegistry";
11
+ import type { CommandContext, CoreBotState } from "./types";
12
+ export interface DispatcherOptions<TState extends CoreBotState = CoreBotState> {
13
+ /** Channel to dispatch messages for */
14
+ channel: Channel;
15
+ /** Command registry */
16
+ registry: CommandRegistry<TState>;
17
+ /** Shared mutable bot state */
18
+ state: TState;
19
+ /** Only handle messages from this username (if set) */
20
+ ownerUsername?: string;
21
+ /** Owner user ID for dismissable messages */
22
+ ownerUserId?: string;
23
+ /** Called when the owner's user ID is first captured from an incoming message */
24
+ onOwnerIdCaptured?: (userId: string) => void;
25
+ /** Called when no command matches. Receives a CommandContext for executing suggestions. If not provided, sends a dismissable error. */
26
+ onUnrecognized?: (input: string, ctx: CommandContext<TState>) => Promise<void>;
27
+ /** Called when a parse fails (invalid args). Default: post dismissable error. */
28
+ onParseError?: (error: string) => void;
29
+ }
30
+ /** Message dispatcher — routes messages to commands, handles typing indicators, and cleans up user messages after processing. */
31
+ export declare class CommandDispatcher<TState extends CoreBotState = CoreBotState> {
32
+ private readonly options;
33
+ /** Messages that have threads created on them — skip deletion in finally block */
34
+ private readonly messagesWithThreads;
35
+ constructor(options: DispatcherOptions<TState>);
36
+ /**
37
+ * Handle an incoming message from the chat library.
38
+ */
39
+ handleMessage(message: Message): Promise<void>;
40
+ private sendDismissable;
41
+ private createContext;
42
+ /** Remove a command from in-flight tracking and stop typing if all commands are done */
43
+ private completeInFlight;
44
+ }
45
+ //# sourceMappingURL=CommandDispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandDispatcher.d.ts","sourceRoot":"","sources":["../../src/commands/CommandDispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5D,MAAM,WAAW,iBAAiB,CAAC,MAAM,SAAS,YAAY,GAAG,YAAY;IAC3E,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,uBAAuB;IACvB,QAAQ,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAClC,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,uIAAuI;IACvI,cAAc,CAAC,EAAE,CACf,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,cAAc,CAAC,MAAM,CAAC,KACxB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,iFAAiF;IACjF,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,iIAAiI;AACjI,qBAAa,iBAAiB,CAAC,MAAM,SAAS,YAAY,GAAG,YAAY;IAI3D,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,kFAAkF;IAClF,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;gBAE5B,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC;IAE/D;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAwEpD,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,aAAa;IAwCrB,wFAAwF;IACxF,OAAO,CAAC,gBAAgB;CAOzB"}
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ /**
3
+ * Message dispatcher — routes messages to commands, handles typing indicators,
4
+ * and cleans up user messages after processing.
5
+ *
6
+ * Application-specific behavior (e.g., AI command suggestions for unrecognized
7
+ * input) is plugged in via the `onUnrecognized` callback.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.CommandDispatcher = void 0;
11
+ /** Message dispatcher — routes messages to commands, handles typing indicators, and cleans up user messages after processing. */
12
+ class CommandDispatcher {
13
+ options;
14
+ /** Messages that have threads created on them — skip deletion in finally block */
15
+ messagesWithThreads = new Set();
16
+ constructor(options) {
17
+ this.options = options;
18
+ }
19
+ /**
20
+ * Handle an incoming message from the chat library.
21
+ */
22
+ async handleMessage(message) {
23
+ const { channel, registry, state, ownerUsername } = this.options;
24
+ const content = message.content ?? "";
25
+ const { author } = message;
26
+ // Only respond to the owner (if configured)
27
+ if (ownerUsername !== undefined && author?.username !== ownerUsername) {
28
+ return;
29
+ }
30
+ // Capture owner's user ID on first message
31
+ if (author?.id !== undefined && this.options.ownerUserId === undefined) {
32
+ this.options.ownerUserId = author.id;
33
+ this.options.onOwnerIdCaptured?.(author.id);
34
+ }
35
+ const input = content.trim();
36
+ const normalizedInput = input.toLowerCase();
37
+ // De-dupe check: if this command is already in-flight, skip it
38
+ if (state.inFlightCommands.has(normalizedInput)) {
39
+ return;
40
+ }
41
+ // Track this command as in-flight and manage typing indicator
42
+ const wasEmpty = state.inFlightCommands.size === 0;
43
+ state.inFlightCommands.add(normalizedInput);
44
+ if (wasEmpty) {
45
+ channel.beginTyping();
46
+ }
47
+ // Skip empty messages (e.g., voice messages handled elsewhere)
48
+ if (!input) {
49
+ this.completeInFlight(normalizedInput);
50
+ return;
51
+ }
52
+ try {
53
+ const match = registry.match(input);
54
+ const ctx = this.createContext(message);
55
+ if (!match) {
56
+ if (this.options.onUnrecognized) {
57
+ await this.options.onUnrecognized(input, ctx);
58
+ }
59
+ else {
60
+ this.sendDismissable(`Unrecognized command: \`${input}\`. Type \`help\` for available commands.`);
61
+ }
62
+ }
63
+ else if (!match.parsed.valid) {
64
+ const errorMsg = match.parsed.error;
65
+ if (this.options.onParseError) {
66
+ this.options.onParseError(errorMsg);
67
+ }
68
+ else {
69
+ this.sendDismissable(errorMsg);
70
+ }
71
+ }
72
+ else {
73
+ await match.command.execute(ctx, match.parsed.args);
74
+ }
75
+ }
76
+ finally {
77
+ // Delete the user's command message unless a thread was created on it
78
+ if (!this.messagesWithThreads.delete(message.id)) {
79
+ message.delete().catch(() => {
80
+ /* swallow */
81
+ });
82
+ }
83
+ // Remove from in-flight commands and stop typing if all done
84
+ this.completeInFlight(normalizedInput);
85
+ }
86
+ }
87
+ sendDismissable(content) {
88
+ const { channel } = this.options;
89
+ const ownerId = this.options.ownerUserId;
90
+ if (ownerId !== undefined) {
91
+ void channel.postDismissable(content, ownerId);
92
+ }
93
+ else {
94
+ void channel.postMessage(content);
95
+ }
96
+ }
97
+ createContext(incomingMessage) {
98
+ const { channel, state } = this.options;
99
+ return {
100
+ channelId: incomingMessage.channelId,
101
+ state,
102
+ channel,
103
+ incomingMessage,
104
+ send: (content) => {
105
+ void channel.postMessage(content);
106
+ return Promise.resolve();
107
+ },
108
+ sendMessage: async (content) => {
109
+ return await channel.postMessage(content);
110
+ },
111
+ sendDismissable: async (content) => {
112
+ const ownerId = this.options.ownerUserId;
113
+ if (ownerId !== undefined) {
114
+ return await channel.postDismissable(content, ownerId);
115
+ }
116
+ return await channel.postMessage(content);
117
+ },
118
+ sendFile: (content, filename, msg) => {
119
+ const buffer = typeof content === "string" ? Buffer.from(content, "utf-8") : content;
120
+ void channel.postMessage(msg ?? "", {
121
+ files: [{ content: buffer, name: filename }],
122
+ });
123
+ return Promise.resolve();
124
+ },
125
+ startThread: async (name, autoArchiveDuration) => {
126
+ const thread = await incomingMessage.startThread(name, autoArchiveDuration);
127
+ this.messagesWithThreads.add(incomingMessage.id);
128
+ return thread;
129
+ },
130
+ };
131
+ }
132
+ /** Remove a command from in-flight tracking and stop typing if all commands are done */
133
+ completeInFlight(normalizedInput) {
134
+ const { state, channel } = this.options;
135
+ state.inFlightCommands.delete(normalizedInput);
136
+ if (state.inFlightCommands.size === 0) {
137
+ channel.endTyping();
138
+ }
139
+ }
140
+ }
141
+ exports.CommandDispatcher = CommandDispatcher;
142
+ //# sourceMappingURL=CommandDispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandDispatcher.js","sourceRoot":"","sources":["../../src/commands/CommandDispatcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Command registry with conflict detection and auto-parsing
3
+ *
4
+ * Commands declare their argument shape via `args` and the registry
5
+ * auto-generates the parse function. Longest-prefix-first matching
6
+ * ensures unambiguous command resolution.
7
+ */
8
+ import type { Command, CoreBotState, ParseResult } from "./types";
9
+ export interface RegisteredCommand<TState extends CoreBotState = CoreBotState> extends Command<TState> {
10
+ readonly agentName: string;
11
+ }
12
+ /** Command registry with conflict detection, auto-parsing, and longest-prefix-first matching. */
13
+ export declare class CommandRegistry<TState extends CoreBotState = CoreBotState> {
14
+ private readonly commands;
15
+ private readonly parsers;
16
+ /**
17
+ * Register a command, checking for prefix conflicts.
18
+ */
19
+ register(agentName: string, command: Command<TState>): void;
20
+ /**
21
+ * Find the command that matches the input, trying longest prefix first.
22
+ */
23
+ match(input: string): {
24
+ command: RegisteredCommand<TState>;
25
+ parsed: ParseResult;
26
+ } | null;
27
+ /**
28
+ * Get all commands grouped by agent for help generation.
29
+ */
30
+ getCommandsByAgent(): Map<string, RegisteredCommand<TState>[]>;
31
+ /**
32
+ * Get all registered commands.
33
+ */
34
+ getAllCommands(): readonly RegisteredCommand<TState>[];
35
+ /**
36
+ * Check if two prefixes conflict (one is prefix of the other).
37
+ */
38
+ private prefixesConflict;
39
+ }
40
+ //# sourceMappingURL=CommandRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandRegistry.d.ts","sourceRoot":"","sources":["../../src/commands/CommandRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAElE,MAAM,WAAW,iBAAiB,CAChC,MAAM,SAAS,YAAY,GAAG,YAAY,CAC1C,SAAQ,OAAO,CAAC,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAkED,iGAAiG;AACjG,qBAAa,eAAe,CAAC,MAAM,SAAS,YAAY,GAAG,YAAY;IACrE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAGpB;IAEJ;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI;IAc3D;;OAEG;IACH,KAAK,CACH,KAAK,EAAE,MAAM,GACZ;QAAE,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,GAAG,IAAI;IAsBrE;;OAEG;IACH,kBAAkB,IAAI,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;IAU9D;;OAEG;IACH,cAAc,IAAI,SAAS,iBAAiB,CAAC,MAAM,CAAC,EAAE;IAItD;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAOzB"}
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ /**
3
+ * Command registry with conflict detection and auto-parsing
4
+ *
5
+ * Commands declare their argument shape via `args` and the registry
6
+ * auto-generates the parse function. Longest-prefix-first matching
7
+ * ensures unambiguous command resolution.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.CommandRegistry = void 0;
11
+ /**
12
+ * Escape special regex characters in a string.
13
+ */
14
+ function escapeRegex(str) {
15
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
16
+ }
17
+ /**
18
+ * Build a parse function from a command's ArgShape declaration.
19
+ */
20
+ function buildParser(command) {
21
+ const { prefix, args, usage } = command;
22
+ const usageStr = usage ?? prefix;
23
+ switch (args.type) {
24
+ case "none": {
25
+ const escaped = escapeRegex(prefix);
26
+ const regex = new RegExp(`^!?${escaped}$`);
27
+ return (normalizedInput) => {
28
+ if (regex.test(normalizedInput)) {
29
+ return { valid: true, args: {} };
30
+ }
31
+ return null;
32
+ };
33
+ }
34
+ case "rest": {
35
+ const { argName, optional } = args;
36
+ const escaped = escapeRegex(prefix);
37
+ const prefixRegex = new RegExp(`^!?${escaped}\\s+(.+)$`);
38
+ const bareRegex = new RegExp(`^!?${escaped}$`);
39
+ return (normalizedInput, originalInput) => {
40
+ const match = prefixRegex.exec(normalizedInput);
41
+ if (match) {
42
+ // Extract from originalInput to preserve case
43
+ const originalMatch = new RegExp(`^!?\\S+\\s+(.+)$`).exec(originalInput);
44
+ const value = originalMatch?.[1].trim() ?? match[1].trim();
45
+ return { valid: true, args: { [argName]: value } };
46
+ }
47
+ if (bareRegex.test(normalizedInput)) {
48
+ if (optional === true) {
49
+ return { valid: true, args: { [argName]: "" } };
50
+ }
51
+ return { valid: false, error: `Usage: ${usageStr}` };
52
+ }
53
+ return null;
54
+ };
55
+ }
56
+ case "custom":
57
+ return args.parse;
58
+ default:
59
+ throw new Error(`Unknown arg type: ${args.type}`);
60
+ }
61
+ }
62
+ /** Command registry with conflict detection, auto-parsing, and longest-prefix-first matching. */
63
+ class CommandRegistry {
64
+ commands = [];
65
+ parsers = new Map();
66
+ /**
67
+ * Register a command, checking for prefix conflicts.
68
+ */
69
+ register(agentName, command) {
70
+ for (const existing of this.commands) {
71
+ if (this.prefixesConflict(existing.prefix, command.prefix)) {
72
+ const error = `Command prefix conflict: "${command.prefix}" (${agentName}) ` +
73
+ `conflicts with "${existing.prefix}" (${existing.agentName})`;
74
+ throw new Error(error);
75
+ }
76
+ }
77
+ this.commands.push({ ...command, agentName });
78
+ this.parsers.set(command.prefix, buildParser(command));
79
+ }
80
+ /**
81
+ * Find the command that matches the input, trying longest prefix first.
82
+ */
83
+ match(input) {
84
+ const normalizedInput = input.toLowerCase();
85
+ // Sort by prefix length descending for longest-match-first
86
+ const sorted = [...this.commands].sort((a, b) => b.prefix.length - a.prefix.length);
87
+ for (const command of sorted) {
88
+ const parse = this.parsers.get(command.prefix);
89
+ if (parse === undefined) {
90
+ continue;
91
+ }
92
+ const parsed = parse(normalizedInput, input);
93
+ if (parsed !== null) {
94
+ return { command, parsed };
95
+ }
96
+ }
97
+ return null;
98
+ }
99
+ /**
100
+ * Get all commands grouped by agent for help generation.
101
+ */
102
+ getCommandsByAgent() {
103
+ const byAgent = new Map();
104
+ for (const cmd of this.commands) {
105
+ const list = byAgent.get(cmd.agentName) ?? [];
106
+ list.push(cmd);
107
+ byAgent.set(cmd.agentName, list);
108
+ }
109
+ return byAgent;
110
+ }
111
+ /**
112
+ * Get all registered commands.
113
+ */
114
+ getAllCommands() {
115
+ return this.commands;
116
+ }
117
+ /**
118
+ * Check if two prefixes conflict (one is prefix of the other).
119
+ */
120
+ prefixesConflict(a, b) {
121
+ if (a === b) {
122
+ return true;
123
+ }
124
+ // "merge" and "merge all" conflict, but "prs" and "push" don't
125
+ return a.startsWith(`${b} `) || b.startsWith(`${a} `);
126
+ }
127
+ }
128
+ exports.CommandRegistry = CommandRegistry;
129
+ //# sourceMappingURL=CommandRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandRegistry.js","sourceRoot":"","sources":["../../src/commands/CommandRegistry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export type { Command, CommandContext, ArgShape, ParseResult, Agent, CoreBotState, } from "./types";
2
+ export { CommandRegistry, type RegisteredCommand } from "./CommandRegistry";
3
+ export { CommandDispatcher, type DispatcherOptions } from "./CommandDispatcher";
4
+ export { setupJobLifecycle, type JobLifecycleOptions, type JobLifecycleHandle, EMOJI_CANCEL, EMOJI_DISMISS, } from "./jobLifecycle";
5
+ export { formatWorkerError, RECOVERABLE_WORKER_ERRORS } from "./workerErrors";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,OAAO,EACP,cAAc,EACd,QAAQ,EACR,WAAW,EACX,KAAK,EACL,YAAY,GACb,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGhF,OAAO,EACL,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,YAAY,EACZ,aAAa,GACd,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RECOVERABLE_WORKER_ERRORS = exports.formatWorkerError = exports.EMOJI_DISMISS = exports.EMOJI_CANCEL = exports.setupJobLifecycle = exports.CommandDispatcher = exports.CommandRegistry = void 0;
4
+ // Registry & Dispatcher
5
+ var CommandRegistry_1 = require("./CommandRegistry");
6
+ Object.defineProperty(exports, "CommandRegistry", { enumerable: true, get: function () { return CommandRegistry_1.CommandRegistry; } });
7
+ var CommandDispatcher_1 = require("./CommandDispatcher");
8
+ Object.defineProperty(exports, "CommandDispatcher", { enumerable: true, get: function () { return CommandDispatcher_1.CommandDispatcher; } });
9
+ // Job Lifecycle
10
+ var jobLifecycle_1 = require("./jobLifecycle");
11
+ Object.defineProperty(exports, "setupJobLifecycle", { enumerable: true, get: function () { return jobLifecycle_1.setupJobLifecycle; } });
12
+ Object.defineProperty(exports, "EMOJI_CANCEL", { enumerable: true, get: function () { return jobLifecycle_1.EMOJI_CANCEL; } });
13
+ Object.defineProperty(exports, "EMOJI_DISMISS", { enumerable: true, get: function () { return jobLifecycle_1.EMOJI_DISMISS; } });
14
+ // Helpers
15
+ var workerErrors_1 = require("./workerErrors");
16
+ Object.defineProperty(exports, "formatWorkerError", { enumerable: true, get: function () { return workerErrors_1.formatWorkerError; } });
17
+ Object.defineProperty(exports, "RECOVERABLE_WORKER_ERRORS", { enumerable: true, get: function () { return workerErrors_1.RECOVERABLE_WORKER_ERRORS; } });
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":";;;AAUA,wBAAwB;AACxB,qDAA4E;AAAnE,kHAAA,eAAe,OAAA;AACxB,yDAAgF;AAAvE,sHAAA,iBAAiB,OAAA;AAE1B,gBAAgB;AAChB,+CAMwB;AALtB,iHAAA,iBAAiB,OAAA;AAGjB,4GAAA,YAAY,OAAA;AACZ,6GAAA,aAAa,OAAA;AAGf,UAAU;AACV,+CAA8E;AAArE,iHAAA,iBAAiB,OAAA;AAAE,yHAAA,yBAAyB,OAAA"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Job lifecycle management for threaded commands
3
+ *
4
+ * Manages the cancel/delete emoji flow for long-running jobs:
5
+ * - While running: cancel emoji on the original message to cancel
6
+ * - Thread replies of "cancel" or "stop" also cancel the job
7
+ * - On completion: swaps cancel for dismiss emoji to delete message + thread
8
+ */
9
+ import type { Message } from "../Message";
10
+ import type { Thread } from "../Thread";
11
+ /** Cancel emoji shown while a job is running */
12
+ export declare const EMOJI_CANCEL = "\u274C";
13
+ /** Dismiss emoji shown after a job completes (click to delete) */
14
+ export declare const EMOJI_DISMISS = "\uD83D\uDDD1\uFE0F";
15
+ export interface JobLifecycleOptions {
16
+ /** The original user message (thread anchor — will have emojis added) */
17
+ originalMessage: Message;
18
+ /** The thread created for this job's output */
19
+ thread: Thread;
20
+ /** AbortController to signal cancellation */
21
+ abortController: AbortController;
22
+ /** Only react to this user's emoji clicks and thread replies */
23
+ ownerUsername: string;
24
+ }
25
+ export interface JobLifecycleHandle {
26
+ /** Call when the job completes (success or failure). Swaps cancel for delete emoji. */
27
+ complete(): void;
28
+ }
29
+ /**
30
+ * Set up cancel emoji on the original message and cancel-text listener in the thread.
31
+ * Returns a handle whose `complete()` method swaps to the delete emoji.
32
+ */
33
+ export declare function setupJobLifecycle(options: JobLifecycleOptions): JobLifecycleHandle;
34
+ //# sourceMappingURL=jobLifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobLifecycle.d.ts","sourceRoot":"","sources":["../../src/commands/jobLifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,gDAAgD;AAChD,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC,kEAAkE;AAClE,eAAO,MAAM,aAAa,uBAAuB,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,yEAAyE;IACzE,eAAe,EAAE,OAAO,CAAC;IACzB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,eAAe,EAAE,eAAe,CAAC;IACjC,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,uFAAuF;IACvF,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,mBAAmB,GAC3B,kBAAkB,CA+DpB"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ /**
3
+ * Job lifecycle management for threaded commands
4
+ *
5
+ * Manages the cancel/delete emoji flow for long-running jobs:
6
+ * - While running: cancel emoji on the original message to cancel
7
+ * - Thread replies of "cancel" or "stop" also cancel the job
8
+ * - On completion: swaps cancel for dismiss emoji to delete message + thread
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.EMOJI_DISMISS = exports.EMOJI_CANCEL = void 0;
12
+ exports.setupJobLifecycle = setupJobLifecycle;
13
+ /** Cancel emoji shown while a job is running */
14
+ exports.EMOJI_CANCEL = "\u274C"; // ❌
15
+ /** Dismiss emoji shown after a job completes (click to delete) */
16
+ exports.EMOJI_DISMISS = "\uD83D\uDDD1\uFE0F"; // 🗑️
17
+ /**
18
+ * Set up cancel emoji on the original message and cancel-text listener in the thread.
19
+ * Returns a handle whose `complete()` method swaps to the delete emoji.
20
+ */
21
+ function setupJobLifecycle(options) {
22
+ const { originalMessage, thread, abortController, ownerUsername } = options;
23
+ let completed = false;
24
+ // Add cancel emoji and listen for clicks
25
+ originalMessage.addReactions([exports.EMOJI_CANCEL]);
26
+ originalMessage.onReaction((event) => {
27
+ if (completed) {
28
+ return;
29
+ }
30
+ if (event.emoji !== exports.EMOJI_CANCEL) {
31
+ return;
32
+ }
33
+ if (event.user.username !== ownerUsername) {
34
+ return;
35
+ }
36
+ abortController.abort();
37
+ });
38
+ // Listen for "cancel" / "stop" text replies in the thread
39
+ const unsubReply = thread.onReply((msg) => {
40
+ if (completed) {
41
+ return;
42
+ }
43
+ if (msg.author?.username !== ownerUsername) {
44
+ return;
45
+ }
46
+ const text = (msg.content ?? "").trim().toLowerCase();
47
+ if (text === "cancel" || text === "stop") {
48
+ abortController.abort();
49
+ }
50
+ });
51
+ return {
52
+ complete() {
53
+ if (completed) {
54
+ return;
55
+ }
56
+ completed = true;
57
+ // Stop listening for cancel signals
58
+ originalMessage.offReaction();
59
+ unsubReply();
60
+ // Swap cancel emoji for delete emoji
61
+ originalMessage.setReactions([exports.EMOJI_DISMISS], (event) => {
62
+ if (event.emoji !== exports.EMOJI_DISMISS) {
63
+ return;
64
+ }
65
+ if (event.user.username !== ownerUsername) {
66
+ return;
67
+ }
68
+ // Delete the original message and the entire thread
69
+ originalMessage.delete().catch(() => {
70
+ /* swallow */
71
+ });
72
+ thread.delete().catch(() => {
73
+ /* swallow */
74
+ });
75
+ });
76
+ },
77
+ };
78
+ }
79
+ //# sourceMappingURL=jobLifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobLifecycle.js","sourceRoot":"","sources":["../../src/commands/jobLifecycle.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AA+BH,8CAiEC;AA3FD,gDAAgD;AACnC,QAAA,YAAY,GAAG,QAAQ,CAAC,CAAC,IAAI;AAE1C,kEAAkE;AACrD,QAAA,aAAa,GAAG,oBAAoB,CAAC,CAAC,MAAM;AAkBzD;;;GAGG;AACH,SAAgB,iBAAiB,CAC/B,OAA4B;IAE5B,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IAC5E,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,yCAAyC;IACzC,eAAe,CAAC,YAAY,CAAC,CAAC,oBAAY,CAAC,CAAC,CAAC;IAC7C,eAAe,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,EAAE;QACnC,IAAI,SAAS,EAAE,CAAC;YACd,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,KAAK,oBAAY,EAAE,CAAC;YACjC,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;YAC1C,OAAO;QACT,CAAC;QACD,eAAe,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,0DAA0D;IAC1D,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACxC,IAAI,SAAS,EAAE,CAAC;YACd,OAAO;QACT,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,KAAK,aAAa,EAAE,CAAC;YAC3C,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACtD,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACzC,eAAe,CAAC,KAAK,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,QAAQ;YACN,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO;YACT,CAAC;YACD,SAAS,GAAG,IAAI,CAAC;YAEjB,oCAAoC;YACpC,eAAe,CAAC,WAAW,EAAE,CAAC;YAC9B,UAAU,EAAE,CAAC;YAEb,qCAAqC;YACrC,eAAe,CAAC,YAAY,CAAC,CAAC,qBAAa,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE;gBACtD,IAAI,KAAK,CAAC,KAAK,KAAK,qBAAa,EAAE,CAAC;oBAClC,OAAO;gBACT,CAAC;gBACD,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;oBAC1C,OAAO;gBACT,CAAC;gBAED,oDAAoD;gBACpD,eAAe,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;oBAClC,aAAa;gBACf,CAAC,CAAC,CAAC;gBACH,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;oBACzB,aAAa;gBACf,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Bot framework types — Agent, Command, Context, and State interfaces
3
+ *
4
+ * Commands declare their argument shape via the `args` field rather than
5
+ * writing a manual `parse()` function. The framework auto-generates the
6
+ * parser based on the declared shape.
7
+ */
8
+ import type { Channel } from "../Channel";
9
+ import type { Message } from "../Message";
10
+ import type { Thread } from "../Thread";
11
+ /**
12
+ * Minimal shared state required by the framework.
13
+ * Extend this in your app with domain-specific fields.
14
+ */
15
+ export interface CoreBotState {
16
+ /** Commands currently being processed (for de-dupe and typing indicator) */
17
+ inFlightCommands: Set<string>;
18
+ }
19
+ /**
20
+ * Result of parsing a command.
21
+ */
22
+ export type ParseResult = {
23
+ valid: true;
24
+ args: Record<string, unknown>;
25
+ } | {
26
+ valid: false;
27
+ error: string;
28
+ };
29
+ /**
30
+ * Argument shape declaration for auto-parsing.
31
+ *
32
+ * - `'none'` — no arguments (exact prefix match). Parse returns `{}`.
33
+ * - `'rest'` — single string arg = everything after the prefix.
34
+ * Requires `argName` to name the key. Parse returns `{ [argName]: string }`.
35
+ * - `'custom'` — full control for complex multi-arg parsing.
36
+ */
37
+ export type ArgShape = {
38
+ type: "none";
39
+ } | {
40
+ type: "rest";
41
+ argName: string;
42
+ optional?: boolean;
43
+ } | {
44
+ type: "custom";
45
+ parse: (normalizedInput: string, originalInput: string) => ParseResult | null;
46
+ };
47
+ /**
48
+ * Context passed to command execute() — everything a command needs
49
+ * to interact with the chat channel.
50
+ */
51
+ export interface CommandContext<TState extends CoreBotState = CoreBotState> {
52
+ readonly channelId: string;
53
+ readonly state: TState;
54
+ readonly channel: Channel;
55
+ /** The incoming user message that triggered this command */
56
+ readonly incomingMessage: Message;
57
+ /** Send a message (fire and forget) */
58
+ send(content: string): Promise<void>;
59
+ /** Send a message and return the Message object (for editing, reactions) */
60
+ sendMessage(content: string): Promise<Message>;
61
+ /** Send a dismissable informative message (adds dismiss reaction) */
62
+ sendDismissable(content: string): Promise<Message>;
63
+ /** Send a file as an attachment */
64
+ sendFile(content: string | Buffer, filename: string, message?: string): Promise<void>;
65
+ /** Start a thread and return a Thread for posting into it */
66
+ startThread(name: string, autoArchiveDuration?: number): Promise<Thread>;
67
+ }
68
+ /**
69
+ * A single command definition.
70
+ *
71
+ * When `args` is 'none' or 'rest', the framework auto-generates the parser.
72
+ * When `args` is 'custom', the provided parse function is used directly.
73
+ */
74
+ export interface Command<TState extends CoreBotState = CoreBotState> {
75
+ /** Command prefix for matching (e.g., "prs", "merge all") */
76
+ readonly prefix: string;
77
+ /** Human-readable description for help */
78
+ readonly description: string;
79
+ /** Optional usage example for help */
80
+ readonly usage?: string;
81
+ /** Argument shape — determines how input is parsed */
82
+ readonly args: ArgShape;
83
+ /**
84
+ * Execute the command.
85
+ * The user's command message is automatically deleted on completion.
86
+ */
87
+ execute(ctx: CommandContext<TState>, args: Record<string, unknown>): Promise<void>;
88
+ }
89
+ /**
90
+ * An agent is a named group of related commands.
91
+ */
92
+ export interface Agent<TState extends CoreBotState = CoreBotState> {
93
+ readonly name: string;
94
+ readonly commands: readonly Command<TState>[];
95
+ }
96
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/commands/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC9C;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpC;;;;;;;GAOG;AACH,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACrD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,CACL,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,KAClB,WAAW,GAAG,IAAI,CAAC;CACzB,CAAC;AAEN;;;GAGG;AACH,MAAM,WAAW,cAAc,CAAC,MAAM,SAAS,YAAY,GAAG,YAAY;IACxE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,4DAA4D;IAC5D,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,uCAAuC;IACvC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,4EAA4E;IAC5E,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,qEAAqE;IACrE,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,mCAAmC;IACnC,QAAQ,CACN,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,6DAA6D;IAC7D,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1E;AAED;;;;;GAKG;AACH,MAAM,WAAW,OAAO,CAAC,MAAM,SAAS,YAAY,GAAG,YAAY;IACjE,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0CAA0C;IAC1C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,sCAAsC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB;;;OAGG;IACH,OAAO,CACL,GAAG,EAAE,cAAc,CAAC,MAAM,CAAC,EAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,KAAK,CAAC,MAAM,SAAS,YAAY,GAAG,YAAY;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;CAC/C"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /**
3
+ * Bot framework types — Agent, Command, Context, and State interfaces
4
+ *
5
+ * Commands declare their argument shape via the `args` field rather than
6
+ * writing a manual `parse()` function. The framework auto-generates the
7
+ * parser based on the declared shape.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/commands/types.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Worker error formatting — maps error codes to user-friendly messages
3
+ */
4
+ /**
5
+ * Error codes that indicate a transient worker issue where a fallback
6
+ * (e.g., a different AI provider) is worth attempting.
7
+ */
8
+ export declare const RECOVERABLE_WORKER_ERRORS: readonly ["MODEL_NOT_AVAILABLE", "WORKER_DISCONNECTED", "WORKER_OVERLOADED", "INTERNAL_ERROR"];
9
+ /**
10
+ * Format a worker error code into a user-friendly message.
11
+ *
12
+ * @param errorCode - The error code from the worker result
13
+ * @param fallbackMessage - Message to use if the error code is not recognized
14
+ */
15
+ export declare function formatWorkerError(errorCode: string, fallbackMessage?: string): string;
16
+ //# sourceMappingURL=workerErrors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workerErrors.d.ts","sourceRoot":"","sources":["../../src/commands/workerErrors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH;;;GAGG;AACH,eAAO,MAAM,yBAAyB,gGAK5B,CAAC;AAEX;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,eAAe,CAAC,EAAE,MAAM,GACvB,MAAM,CAIR"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /**
3
+ * Worker error formatting — maps error codes to user-friendly messages
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RECOVERABLE_WORKER_ERRORS = void 0;
7
+ exports.formatWorkerError = formatWorkerError;
8
+ const WORKER_ERROR_MESSAGES = {
9
+ MODEL_NOT_AVAILABLE: "No AI worker is available to handle this request. Please try again later.",
10
+ TIMEOUT: "The request timed out. Please try a simpler question or try again later.",
11
+ RATE_LIMITED: "Rate limited. Please wait a moment and try again.",
12
+ WORKER_OVERLOADED: "Workers are busy. Please try again in a moment.",
13
+ WORKER_DISCONNECTED: "The worker disconnected unexpectedly. Please try again.",
14
+ };
15
+ /**
16
+ * Error codes that indicate a transient worker issue where a fallback
17
+ * (e.g., a different AI provider) is worth attempting.
18
+ */
19
+ exports.RECOVERABLE_WORKER_ERRORS = [
20
+ "MODEL_NOT_AVAILABLE",
21
+ "WORKER_DISCONNECTED",
22
+ "WORKER_OVERLOADED",
23
+ "INTERNAL_ERROR",
24
+ ];
25
+ /**
26
+ * Format a worker error code into a user-friendly message.
27
+ *
28
+ * @param errorCode - The error code from the worker result
29
+ * @param fallbackMessage - Message to use if the error code is not recognized
30
+ */
31
+ function formatWorkerError(errorCode, fallbackMessage) {
32
+ return (WORKER_ERROR_MESSAGES[errorCode] ?? fallbackMessage ?? `Error: ${errorCode}`);
33
+ }
34
+ //# sourceMappingURL=workerErrors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workerErrors.js","sourceRoot":"","sources":["../../src/commands/workerErrors.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AA8BH,8CAOC;AAnCD,MAAM,qBAAqB,GAAoC;IAC7D,mBAAmB,EACjB,2EAA2E;IAC7E,OAAO,EACL,0EAA0E;IAC5E,YAAY,EAAE,mDAAmD;IACjE,iBAAiB,EAAE,iDAAiD;IACpE,mBAAmB,EACjB,yDAAyD;CAC5D,CAAC;AAEF;;;GAGG;AACU,QAAA,yBAAyB,GAAG;IACvC,qBAAqB;IACrB,qBAAqB;IACrB,mBAAmB;IACnB,gBAAgB;CACR,CAAC;AAEX;;;;;GAKG;AACH,SAAgB,iBAAiB,CAC/B,SAAiB,EACjB,eAAwB;IAExB,OAAO,CACL,qBAAqB,CAAC,SAAS,CAAC,IAAI,eAAe,IAAI,UAAU,SAAS,EAAE,CAC7E,CAAC;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export { Thread } from "./Thread";
10
10
  export { createMessageTracker, type MessageTracker } from "./MessageTracker";
11
11
  export { DiscordChatClient } from "./discord";
12
12
  export { SlackChatClient } from "./slack";
13
+ export { type Command, type CommandContext, type ArgShape, type ParseResult, type Agent, type CoreBotState, CommandRegistry, type RegisteredCommand, CommandDispatcher, type DispatcherOptions, setupJobLifecycle, type JobLifecycleOptions, type JobLifecycleHandle, EMOJI_CANCEL, EMOJI_DISMISS, formatWorkerError, RECOVERABLE_WORKER_ERRORS, } from "./commands";
13
14
  import { type ChatClient } from "./ChatClient";
14
15
  import type { ChatConfig } from "./types";
15
16
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,IAAI,EACT,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,aAAa,GACnB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAG7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAW/D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,IAAI,EACT,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,aAAa,GACnB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAG7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,eAAe,EACf,KAAK,iBAAiB,EACtB,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAW/D"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SlackChatClient = exports.DiscordChatClient = exports.createMessageTracker = exports.Thread = exports.StreamingReply = exports.EditableStreamReply = exports.MessageBatch = exports.Message = exports.Channel = exports.ChatClient = exports.MESSAGE_LIMITS = void 0;
3
+ exports.RECOVERABLE_WORKER_ERRORS = exports.formatWorkerError = exports.EMOJI_DISMISS = exports.EMOJI_CANCEL = exports.setupJobLifecycle = exports.CommandDispatcher = exports.CommandRegistry = exports.SlackChatClient = exports.DiscordChatClient = exports.createMessageTracker = exports.Thread = exports.StreamingReply = exports.EditableStreamReply = exports.MessageBatch = exports.Message = exports.Channel = exports.ChatClient = exports.MESSAGE_LIMITS = void 0;
4
4
  exports.createChatClient = createChatClient;
5
5
  // Constants
6
6
  var constants_1 = require("./constants");
@@ -27,6 +27,15 @@ var discord_1 = require("./discord");
27
27
  Object.defineProperty(exports, "DiscordChatClient", { enumerable: true, get: function () { return discord_1.DiscordChatClient; } });
28
28
  var slack_1 = require("./slack");
29
29
  Object.defineProperty(exports, "SlackChatClient", { enumerable: true, get: function () { return slack_1.SlackChatClient; } });
30
+ // Commands
31
+ var commands_1 = require("./commands");
32
+ Object.defineProperty(exports, "CommandRegistry", { enumerable: true, get: function () { return commands_1.CommandRegistry; } });
33
+ Object.defineProperty(exports, "CommandDispatcher", { enumerable: true, get: function () { return commands_1.CommandDispatcher; } });
34
+ Object.defineProperty(exports, "setupJobLifecycle", { enumerable: true, get: function () { return commands_1.setupJobLifecycle; } });
35
+ Object.defineProperty(exports, "EMOJI_CANCEL", { enumerable: true, get: function () { return commands_1.EMOJI_CANCEL; } });
36
+ Object.defineProperty(exports, "EMOJI_DISMISS", { enumerable: true, get: function () { return commands_1.EMOJI_DISMISS; } });
37
+ Object.defineProperty(exports, "formatWorkerError", { enumerable: true, get: function () { return commands_1.formatWorkerError; } });
38
+ Object.defineProperty(exports, "RECOVERABLE_WORKER_ERRORS", { enumerable: true, get: function () { return commands_1.RECOVERABLE_WORKER_ERRORS; } });
30
39
  const discord_2 = require("./discord");
31
40
  const slack_2 = require("./slack");
32
41
  /**
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAwEA,4CAWC;AAtDD,YAAY;AACZ,yCAA6C;AAApC,2GAAA,cAAc,OAAA;AAEvB,eAAe;AACf,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AACnB,qCAAoC;AAA3B,kGAAA,OAAO,OAAA;AAChB,qCAAoC;AAA3B,kGAAA,OAAO,OAAA;AAChB,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AACrB,6DAA4D;AAAnD,0HAAA,mBAAmB,OAAA;AAC5B,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,mCAAkC;AAAzB,gGAAA,MAAM,OAAA;AACf,mDAA6E;AAApE,sHAAA,oBAAoB,OAAA;AAE7B,2BAA2B;AAC3B,qCAA8C;AAArC,4GAAA,iBAAiB,OAAA;AAC1B,iCAA0C;AAAjC,wGAAA,eAAe,OAAA;AAIxB,uCAA8C;AAC9C,mCAA0C;AAG1C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAgB,gBAAgB,CAAC,MAAkB;IACjD,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,IAAI,2BAAiB,CAAC,MAAM,CAAC,CAAC;QACvC,KAAK,OAAO;YACV,OAAO,IAAI,uBAAe,CAAC,MAAM,CAAC,CAAC;QACrC;YACE,MAAM,IAAI,KAAK,CACb,0BAA2B,MAA2B,CAAC,IAAI,EAAE,CAC9D,CAAC;IACN,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AA6FA,4CAWC;AA3ED,YAAY;AACZ,yCAA6C;AAApC,2GAAA,cAAc,OAAA;AAEvB,eAAe;AACf,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AACnB,qCAAoC;AAA3B,kGAAA,OAAO,OAAA;AAChB,qCAAoC;AAA3B,kGAAA,OAAO,OAAA;AAChB,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AACrB,6DAA4D;AAAnD,0HAAA,mBAAmB,OAAA;AAC5B,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,mCAAkC;AAAzB,gGAAA,MAAM,OAAA;AACf,mDAA6E;AAApE,sHAAA,oBAAoB,OAAA;AAE7B,2BAA2B;AAC3B,qCAA8C;AAArC,4GAAA,iBAAiB,OAAA;AAC1B,iCAA0C;AAAjC,wGAAA,eAAe,OAAA;AAExB,WAAW;AACX,uCAkBoB;AAXlB,2GAAA,eAAe,OAAA;AAEf,6GAAA,iBAAiB,OAAA;AAEjB,6GAAA,iBAAiB,OAAA;AAGjB,wGAAA,YAAY,OAAA;AACZ,yGAAA,aAAa,OAAA;AACb,6GAAA,iBAAiB,OAAA;AACjB,qHAAA,yBAAyB,OAAA;AAK3B,uCAA8C;AAC9C,mCAA0C;AAG1C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAgB,gBAAgB,CAAC,MAAkB;IACjD,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,IAAI,2BAAiB,CAAC,MAAM,CAAC,CAAC;QACvC,KAAK,OAAO;YACV,OAAO,IAAI,uBAAe,CAAC,MAAM,CAAC,CAAC;QACrC;YACE,MAAM,IAAI,KAAK,CACb,0BAA2B,MAA2B,CAAC,IAAI,EAAE,CAC9D,CAAC;IACN,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardlydifficult/chat",
3
- "version": "1.1.59",
3
+ "version": "1.1.61",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [