Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1ede560
update middleware behavior
notunderctrl Aug 22, 2025
a5dede3
fix: context not throwing ckit errors
notunderctrl Aug 22, 2025
351564a
update legacy ready event to clientReady + prettier format
notunderctrl Aug 22, 2025
c08aa9b
cleanup imports
notunderctrl Aug 22, 2025
9777a81
Merge branch 'main' of https://github.com/underctrl-io/commandkit int…
twlite Aug 24, 2025
64e6f6e
chore: deps
twlite Aug 24, 2025
a25d29f
feat: force run env finalizer during runCommand phase
twlite Aug 24, 2025
dc6021d
Merge branch 'main' of https://github.com/underctrl-io/commandkit int…
twlite Aug 24, 2025
80b4bf4
chore: prettier
twlite Aug 24, 2025
35e7a14
fix: logging enhancements
twlite Aug 24, 2025
6e04012
chore: add after() logging in command-scoped middleware
twlite Aug 24, 2025
1ee01fc
mark `after` as unstable
notunderctrl Aug 25, 2025
ce5f4c4
merge main
notunderctrl Aug 25, 2025
7eab656
fix lockfile + add zod v3 support to ai tool param
notunderctrl Aug 25, 2025
3b5f1eb
docs: mark `after` as unstable + improve middleware docs
notunderctrl Aug 25, 2025
1c98367
docs: update parameters to inputSchema
notunderctrl Aug 25, 2025
7e56da4
docs: add command metadata
notunderctrl Aug 25, 2025
18df6ab
document cancelAfter + mark cancelAfter as unstable
notunderctrl Aug 25, 2025
020f050
increase hmr debounce to 700ms
notunderctrl Aug 25, 2025
2fa7d83
prettier format
notunderctrl Aug 25, 2025
c69dbfc
update tsdown
notunderctrl Aug 25, 2025
fede7ac
Merge remote-tracking branch 'origin/main' into update-middlewares
notunderctrl Aug 25, 2025
0935830
fix lockfile
notunderctrl Aug 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/test-bot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"discord.js": "catalog:discordjs",
"dotenv": "^16.4.7",
"ms": "^2.1.3",
"zod": "^3.25.56"
"zod": "^4.1.1"
},
"devDependencies": {
"@types/ms": "^2.1.0",
Expand Down
4 changes: 2 additions & 2 deletions apps/test-bot/src/app/commands/(developer)/+middleware.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Logger, MiddlewareContext } from 'commandkit';
import { Logger, MiddlewareContext, stopMiddlewares } from 'commandkit';
import { MessageFlags } from 'discord.js';

export function beforeExecute(ctx: MiddlewareContext) {
Expand All @@ -16,7 +16,7 @@ export function beforeExecute(ctx: MiddlewareContext) {
ctx.message.reply('You are not allowed to use this command.');
}

ctx.cancel();
stopMiddlewares();
}
}

Expand Down
6 changes: 5 additions & 1 deletion apps/test-bot/src/app/commands/(developer)/run-after.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { CommandData, after, ChatInputCommand } from 'commandkit';
import {
CommandData,
unstable_after as after,
ChatInputCommand,
} from 'commandkit';

export const command: CommandData = {
name: 'run-after',
Expand Down
3 changes: 2 additions & 1 deletion apps/test-bot/src/app/commands/(general)/+middleware.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Logger, MiddlewareContext } from 'commandkit';
import { Logger, MiddlewareContext, stopMiddlewares } from 'commandkit';

export function beforeExecute(ctx: MiddlewareContext) {
Logger.info(
`Directory-scoped middleware: ${ctx.commandName} will be executed!`,
);
// stopMiddlewares();
}

export function afterExecute(ctx: MiddlewareContext) {
Expand Down
20 changes: 18 additions & 2 deletions apps/test-bot/src/app/commands/(general)/+ping.middleware.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
import { Logger, MiddlewareContext } from 'commandkit';
import {
unstable_after as after,
Logger,
type MiddlewareContext,
stopMiddlewares,
} from 'commandkit';

export function beforeExecute(ctx: MiddlewareContext) {
// Logger.info(
// `Command-scoped middleware: ${ctx.commandName} will be executed!`,
// );

Logger.info(`Command-scoped middleware: ${ctx.commandName} will be stopped!`);
Logger.info(
`Command-scoped middleware: ${ctx.commandName} will be executed!`,
'None of the other beforeExecute middlewares are supposed to be executed',
);

after(() => {
Logger.info(`after() has been called in command-scoped middleware: ping`);
});

stopMiddlewares();
}

export function afterExecute(ctx: MiddlewareContext) {
Expand Down
31 changes: 27 additions & 4 deletions apps/test-bot/src/app/commands/(general)/ping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import {
AutocompleteCommandContext,
CommandMetadata,
MessageCommandContext,
stopMiddlewares,
Logger,
unstable_after as after,
CommandMetadataFunction,
} from 'commandkit';

export const command: CommandData = {
Expand All @@ -32,10 +36,25 @@ export const command: CommandData = {
// guilds: ['1314834483660455938'],
};

export const metadata: CommandMetadata = {
userPermissions: 'Administrator',
botPermissions: 'KickMembers',
// guilds: ['1314834483660455938'],
// export const metadata: CommandMetadata = {
// // userPermissions: 'Administrator',
// // botPermissions: 'KickMembers',
// // guilds: ['1314834483660455938'],
// aliases: [''],
// userPermissions: 'Administrator',
// botPermissions: 'KickMembers',
// guilds: ['1314834483660455938'],
// };

export const generateMetadata: CommandMetadataFunction = async () => {
// Dynamically determine the metadata for the command

return {
userPermissions: 'Administrator',
botPermissions: ['KickMembers', 'BanMembers'],
// guilds: ['1234567890', '1234567891'],
aliases: ['p', 'pong'],
};
};

const tests = Array.from({ length: 10 }, (_, i) => ({
Expand Down Expand Up @@ -98,4 +117,8 @@ export async function chatInput({
button.setDisabled(true);
message.edit({ components: [row] });
});

after(() => {
Logger.debug('after called in ping');
});
}
4 changes: 2 additions & 2 deletions apps/test-bot/src/app/commands/(interactions)/+middleware.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Logger, MiddlewareContext } from 'commandkit';
import { Logger, MiddlewareContext, stopMiddlewares } from 'commandkit';
import { MessageFlags } from 'discord.js';

export function beforeExecute(ctx: MiddlewareContext) {
Expand All @@ -18,7 +18,7 @@ export function beforeExecute(ctx: MiddlewareContext) {
ctx.message.reply('You are not allowed to use this command.');
}

ctx.cancel();
stopMiddlewares();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
OnButtonKitClick,
} from 'commandkit';
import { ButtonStyle, MessageFlags } from 'discord.js';
import { AiConfig, AiCommand } from '@commandkit/ai';
import { AiConfig, AiCommand, ToolParameterType } from '@commandkit/ai';
import { z } from 'zod';

export const command: CommandData = {
Expand All @@ -15,7 +15,7 @@ export const command: CommandData = {
};

export const aiConfig = {
parameters: z.object({
inputSchema: z.object({
message: z
.string()
.describe('The message to be shown in the confirmation.'),
Expand Down
4 changes: 2 additions & 2 deletions apps/test-bot/src/app/commands/(leveling)/xp.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChatInputCommandContext, CommandData } from 'commandkit';
import { database } from '@/database/store.ts';
import { database } from '@/database/store';
import { cacheTag } from '@commandkit/cache';
import { AiCommand, AiConfig } from '@commandkit/ai';
import { z } from 'zod';
Expand All @@ -11,7 +11,7 @@ export const command: CommandData = {

export const aiConfig = {
description: 'Get the XP of a user in a guild.',
parameters: z.object({
inputSchema: z.object({
guildId: z.string().describe('The ID of the guild.'),
userId: z.string().describe('The ID of the user.'),
}),
Expand Down
4 changes: 3 additions & 1 deletion apps/test-bot/src/app/commands/+global-middleware.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Logger, MiddlewareContext } from 'commandkit';
import { Logger, MiddlewareContext, stopMiddlewares } from 'commandkit';

export function beforeExecute(ctx: MiddlewareContext) {
Logger.info(`Global middleware: ${ctx.commandName} will be executed!`);
// ctx.message.reply('Global middleware: This command will not be executed!');
// stopMiddlewares();
}

export function afterExecute(ctx: MiddlewareContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';

## createTool

<GenerationInfo sourceFile="packages/ai/src/tools/common/index.ts" sourceLine="88" packageName="@commandkit/ai" />
<GenerationInfo sourceFile="packages/ai/src/tools/common/index.ts" sourceLine="90" packageName="@commandkit/ai" />

Creates a new AI tool with the specified configuration.
This function wraps the underlying AI library's tool creation with additional
Expand Down
26 changes: 13 additions & 13 deletions apps/website/docs/api-reference/ai/interfaces/configure-ai.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ interface ConfigureAI {
messageFilter?: MessageFilter;
selectAiModel: SelectAiModel;
prepareSystemPrompt?: (ctx: AiContext, message: Message) => Promise<string>;
preparePrompt?: (
ctx: AiContext,
message: Message,
preparePrompt?: (
ctx: AiContext,
message: Message,
) => Promise<string | AiMessage>;
onProcessingStart?: (ctx: AiContext, message: Message) => Promise<void>;
onProcessingFinish?: (ctx: AiContext, message: Message) => Promise<void>;
onResult?: (
ctx: AiContext,
message: Message,
result: AIGenerateResult,
onResult?: (
ctx: AiContext,
message: Message,
result: AIGenerateResult,
) => Promise<void>;
onError?: (ctx: AiContext, message: Message, error: Error) => Promise<void>;
}
Expand All @@ -49,24 +49,24 @@ Whether to disable the built-in tools. Default is false.

<MemberInfo kind="property" type={`<a href='/docs/next/api-reference/ai/types/message-filter#messagefilter'>MessageFilter</a>`} />

A filter function that determines whether a message should be processed by the AI.
A filter function that determines whether a message should be processed by the AI.
CommandKit invokes this function before processing the message.
### selectAiModel

<MemberInfo kind="property" type={`<a href='/docs/next/api-reference/ai/types/select-ai-model#selectaimodel'>SelectAiModel</a>`} />

A function that selects the AI model to use based on the message.
A function that selects the AI model to use based on the message.
This function should return a promise that resolves to an object containing the model and options.
### prepareSystemPrompt

<MemberInfo kind="property" type={`(ctx: <a href='/docs/next/api-reference/ai/classes/ai-context#aicontext'>AiContext</a>, message: Message) =&#62; Promise&#60;string&#62;`} />

A function that generates a system prompt based on the message.
This function should return a promise that resolves to a string containing the system prompt.
A function that generates a system prompt based on the message.
This function should return a promise that resolves to a string containing the system prompt.
If not provided, a default system prompt will be used.
### preparePrompt

<MemberInfo kind="property" type={`( ctx: <a href='/docs/next/api-reference/ai/classes/ai-context#aicontext'>AiContext</a>, message: Message, ) =&#62; Promise&#60;string | <a href='/docs/next/api-reference/ai/types/ai-message#aimessage'>AiMessage</a>&#62;`} />
<MemberInfo kind="property" type={`( ctx: <a href='/docs/next/api-reference/ai/classes/ai-context#aicontext'>AiContext</a>, message: Message, ) =&#62; Promise&#60;string | <a href='/docs/next/api-reference/ai/types/ai-message#aimessage'>AiMessage</a>&#62;`} />

A function that prepares the prompt for the AI model.
### onProcessingStart
Expand All @@ -81,7 +81,7 @@ A function that gets called when the AI starts processing a message.
A function that gets called when the AI finishes processing a message.
### onResult

<MemberInfo kind="property" type={`( ctx: <a href='/docs/next/api-reference/ai/classes/ai-context#aicontext'>AiContext</a>, message: Message, result: <a href='/docs/next/api-reference/ai/types/aigenerate-result#aigenerateresult'>AIGenerateResult</a>, ) =&#62; Promise&#60;void&#62;`} />
<MemberInfo kind="property" type={`( ctx: <a href='/docs/next/api-reference/ai/classes/ai-context#aicontext'>AiContext</a>, message: Message, result: <a href='/docs/next/api-reference/ai/types/aigenerate-result#aigenerateresult'>AIGenerateResult</a>, ) =&#62; Promise&#60;void&#62;`} />

A function that gets called upon receiving the result from the AI model.
### onError
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';

## CreateToolOptions

<GenerationInfo sourceFile="packages/ai/src/tools/common/index.ts" sourceLine="36" packageName="@commandkit/ai" />
<GenerationInfo sourceFile="packages/ai/src/tools/common/index.ts" sourceLine="38" packageName="@commandkit/ai" />

Configuration options for creating an AI tool.

Expand Down
6 changes: 4 additions & 2 deletions apps/website/docs/api-reference/ai/types/infer-parameters.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';

## InferParameters

<GenerationInfo sourceFile="packages/ai/src/tools/common/index.ts" sourceLine="24" packageName="@commandkit/ai" />
<GenerationInfo sourceFile="packages/ai/src/tools/common/index.ts" sourceLine="25" packageName="@commandkit/ai" />

Utility type that infers the TypeScript type from a tool parameter schema.
Supports both Zod schemas and AI library schemas.
Expand All @@ -23,5 +23,7 @@ type InferParameters<T extends ToolParameterType> = T extends Schema<any>
? T['_type']
: T extends z.ZodTypeAny
? z.infer<T>
: never
: T extends z3.ZodTypeAny
? z3.infer<T>
: never
```
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';

## ToolExecuteFunction

<GenerationInfo sourceFile="packages/ai/src/tools/common/index.ts" sourceLine="55" packageName="@commandkit/ai" />
<GenerationInfo sourceFile="packages/ai/src/tools/common/index.ts" sourceLine="57" packageName="@commandkit/ai" />

Type definition for a tool's execute function.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import MemberDescription from '@site/src/components/MemberDescription';

## ToolParameterType

<GenerationInfo sourceFile="packages/ai/src/tools/common/index.ts" sourceLine="17" packageName="@commandkit/ai" />
<GenerationInfo sourceFile="packages/ai/src/tools/common/index.ts" sourceLine="18" packageName="@commandkit/ai" />

Type representing the parameters schema for AI tools.
Extracted from the first parameter of the `tool` function from the 'ai' library.

```ts title="Signature"
type ToolParameterType = z.ZodType | Schema<any>
type ToolParameterType = z.ZodType | z3.ZodType | Schema<any>
```
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';

## UseCacheDirectivePlugin

<GenerationInfo sourceFile="packages/cache/src/use-cache-directive.ts" sourceLine="13" packageName="@commandkit/cache" />
<GenerationInfo sourceFile="packages/cache/src/use-cache-directive.ts" sourceLine="12" packageName="@commandkit/cache" />

Compiler plugin for the "use cache" directive.
This plugin transforms the "use cache" directive into a runtime cache operation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';

## AnalyticsEngine

<GenerationInfo sourceFile="packages/commandkit/src/analytics/analytics-engine.ts" sourceLine="26" packageName="commandkit" />
<GenerationInfo sourceFile="packages/commandkit/src/analytics/analytics-engine.ts" sourceLine="25" packageName="commandkit" />

AnalyticsEngine class for managing analytics providers and tracking events.
This class allows you to register a provider, set a filter for events, and track or identify events.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ class Context<ExecutionMode extends CommandExecutionMode = CommandExecutionMode,
clone(config?: Partial<ContextParameters<ExecutionMode>>) => Context<ExecutionMode>;
isMiddleware() => this is MiddlewareContext<ExecutionMode>;
args() => string[];
exit() => never;
}
```

Expand Down Expand Up @@ -201,14 +200,6 @@ Checks if this context is a middleware context.
<MemberInfo kind="method" type={`() => string[]`} />

Gets the command arguments (only available for message commands).
### exit

<MemberInfo kind="method" type={`() => never`} />

Stops upcoming middleware or current command execution.
If this is called inside pre-stage middleware, the next run will be the actual command, skipping all other pre-stage middlewares.
If this is called inside a command itself, it will skip all post-stage middlewares.
If this is called inside post-stage middleware, it will skip all other post-stage middlewares.


</div>
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ Extended context class for middleware execution with additional control methods.

```ts title="Signature"
class MiddlewareContext<T extends CommandExecutionMode = CommandExecutionMode> extends Context<T, MiddlewareContextArgs> {
cancelled: boolean
cancel() => void;
setCommandRunner(fn: RunCommand) => void;
}
```
Expand All @@ -30,16 +28,6 @@ class MiddlewareContext<T extends CommandExecutionMode = CommandExecutionMode> e

<div className="members-wrapper">

### cancelled

<MemberInfo kind="property" type={`boolean`} />

Whether the command execution was cancelled.
### cancel

<MemberInfo kind="method" type={`() => void`} />

Cancels the command execution.
### setCommandRunner

<MemberInfo kind="method" type={`(fn: <a href='/docs/next/api-reference/commandkit/types/run-command#runcommand'>RunCommand</a>) => void`} />
Expand Down

This file was deleted.

Loading