@zhin.js/testing 1.0.6 → 1.0.8

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/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { realpath } from 'node:fs/promises';
2
2
  import { resolve } from 'node:path';
3
- import { defineAdapter } from 'zhin.js/adapter';
3
+ import { Adapter, createEndpointSpecification, endpointSpec, defineAdapter } from 'zhin.js/adapter';
4
4
  import { ImRuntime } from 'zhin.js/core/runtime';
5
5
  import { rootPluginId } from 'zhin.js/plugin-runtime';
6
6
  import { NativeDevelopmentModuleRuntime, NodePackageResolver, RootRuntime } from '@zhin.js/runtime';
@@ -10,7 +10,7 @@ export { FakeClock, FakeScheduleRootHost, parseCron } from './fake-clock.js';
10
10
  export { FakeDatabaseRootHost, FakeOutboundRootHost } from './fake-hosts.js';
11
11
  export { FakePlugin, createFakePlugin, runPluginSetup, resolvePluginConfig, PluginConfigValidationError, fakeResource } from './fake-plugin.js';
12
12
  export { fakeOf } from './partial.js';
13
- export { createFakeMessage, createCommandContext, runCommand, runMiddleware, runHandler, createToolContext, runTool, toolOriginFromMessage } from './fake-runners.js';
13
+ export { createFakeMessage, createFakeInteraction, createCommandContext, runCommand, runMiddleware, runHandler, createToolContext, runTool, toolOriginFromMessage } from './fake-runners.js';
14
14
  /**
15
15
  * Owns a test IM host and synthetic transports. Every operation enters the real Root Runtime.
16
16
  * It does not install dependencies or replace providers. Discovered plugins still execute normally;
@@ -37,30 +37,56 @@ export class PluginTestKit {
37
37
  || names.some(name => !/^[a-z][a-z0-9-]*$/.test(name))) {
38
38
  throw new TypeError('Test endpoints must have unique lowercase names');
39
39
  }
40
- this.#defaultEndpoint = names[0];
41
- const definitions = new Map(names.map(name => [name, defineAdapter({
42
- capabilities: ['inbound', 'outbound'],
43
- segments: options.segments ?? { html: 'text', interactive: 'text', markdown: 'text' },
44
- create: () => ({
45
- client: Object.freeze({ synthetic: true }),
46
- connect: ({ events, identity }) => {
47
- this.#identities.set(name, identity);
48
- this.#sinks.set(name, events);
49
- return () => { if (this.#sinks.get(name) === events) {
50
- this.#sinks.delete(name);
51
- this.#identities.delete(name);
52
- } };
53
- },
54
- send: (request) => {
55
- const id = `test-${this.#nextDelivery++}`;
56
- this.#attempts.push(Object.freeze({ endpoint: name, id,
57
- conversation: captureDeliveryValue(request.conversation),
58
- payload: captureDeliveryValue(request.payload),
59
- }));
60
- return id;
40
+ const [firstEndpoint = 'test'] = names;
41
+ this.#defaultEndpoint = firstEndpoint;
42
+ const recordAttempt = (endpoint, request) => {
43
+ const id = `test-${this.#nextDelivery++}`;
44
+ this.#attempts.push(Object.freeze({
45
+ endpoint,
46
+ id,
47
+ conversation: captureDeliveryValue(request.conversation),
48
+ payload: captureDeliveryValue(request.payload),
49
+ }));
50
+ return id;
51
+ };
52
+ const registerOpen = (endpoint, spec) => {
53
+ this.#identities.set(endpoint, spec.identity);
54
+ this.#sinks.set(endpoint, spec.events);
55
+ };
56
+ const releaseEndpoint = (endpoint, spec) => {
57
+ if (this.#sinks.get(endpoint) !== spec.events)
58
+ return;
59
+ this.#sinks.delete(endpoint);
60
+ this.#identities.delete(endpoint);
61
+ };
62
+ const definitions = new Map(names.map(name => {
63
+ class SyntheticClient {
64
+ synthetic = true;
65
+ send(request) {
66
+ return recordAttempt(name, request);
67
+ }
68
+ }
69
+ class SyntheticEndpoint extends SyntheticClient {
70
+ [endpointSpec] = createEndpointSpecification(this, {
71
+ start: signal => signal.throwIfAborted(),
72
+ open: () => {
73
+ registerOpen(name, this[endpointSpec]);
61
74
  },
62
- }),
63
- })]));
75
+ close: () => this.#release(), stop: () => this.#release(),
76
+ send: request => this.send(request),
77
+ });
78
+ #release() {
79
+ releaseEndpoint(name, this[endpointSpec]);
80
+ }
81
+ }
82
+ class SyntheticAdapter extends Adapter {
83
+ createEndpoint() { return new SyntheticEndpoint(); }
84
+ }
85
+ return [name, defineAdapter({ capabilities: ['inbound', 'outbound'],
86
+ segments: options.segments ?? { html: 'text', interactive: 'text', markdown: 'text' },
87
+ createAdapter: () => new SyntheticAdapter(),
88
+ })];
89
+ }));
64
90
  const modules = options.modules ?? new NativeDevelopmentModuleRuntime({ projectRoot, watch: false });
65
91
  this.#root = new RootRuntime({ projectRoot,
66
92
  modules: withTestEndpoints(modules, rootEntry, definitions),
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"test-module-runtime.d.ts","sourceRoot":"","sources":["../src/test-module-runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,gGAAgG;AAChG,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,aAAa,EACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAChD,aAAa,CA2Bf"}
1
+ {"version":3,"file":"test-module-runtime.d.ts","sourceRoot":"","sources":["../src/test-module-runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,gGAAgG;AAChG,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,aAAa,EACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAChD,aAAa,CA0Cf"}
@@ -19,7 +19,23 @@ export function withTestEndpoints(delegate, rootEntry, endpoints) {
19
19
  });
20
20
  return { ...loaded, default: definition };
21
21
  },
22
- ...(delegate.loadClientModule ? { loadClientModule: delegate.loadClientModule.bind(delegate) } : {}),
22
+ loadClientModule: delegate.loadClientModule
23
+ ? delegate.loadClientModule.bind(delegate)
24
+ : async (source) => {
25
+ let metadata;
26
+ try {
27
+ const loaded = await delegate.load(source);
28
+ metadata = loaded?.meta;
29
+ }
30
+ catch {
31
+ // Browser-only client modules may not load in headless Node test mode; fall back to default metadata.
32
+ }
33
+ return Object.freeze({
34
+ module: source,
35
+ hash: 'test',
36
+ ...(metadata !== undefined ? { metadata } : {}),
37
+ });
38
+ },
23
39
  ...(delegate.invalidate ? { invalidate: delegate.invalidate.bind(delegate) } : {}),
24
40
  ...(delegate.affectedSources ? { affectedSources: delegate.affectedSources.bind(delegate) } : {}),
25
41
  ...(delegate.requiresProcessRestart ? { requiresProcessRestart: delegate.requiresProcessRestart.bind(delegate) } : {}),
@@ -1 +1 @@
1
- {"version":3,"file":"test-module-runtime.js","sourceRoot":"","sources":["../src/test-module-runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test-module-runtime.js","sourceRoot":"","sources":["../src/test-module-runtime.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/testing",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "Real Plugin Runtime integration fixtures with synthetic IM endpoints",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -17,22 +17,22 @@
17
17
  "README.md"
18
18
  ],
19
19
  "peerDependencies": {
20
- "zhin.js": "^1.1.16",
21
- "@zhin.js/runtime": "^1.1.14",
22
- "@zhin.js/tool": "^1.1.10"
20
+ "zhin.js": "^1.1.22",
21
+ "@zhin.js/runtime": "^1.1.19",
22
+ "@zhin.js/tool": "^1.1.16"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/node": "^26.1.2",
26
26
  "typescript": "^6.0.3",
27
27
  "vitest": "^4.1.10",
28
- "@zhin.js/adapter": "1.1.23",
29
- "@zhin.js/command": "1.1.11",
30
- "@zhin.js/core": "1.1.51",
31
- "@zhin.js/middleware": "1.1.10",
32
- "@zhin.js/plugin-runtime": "1.1.17",
33
- "@zhin.js/runtime": "1.1.14",
34
- "@zhin.js/tool": "1.1.10",
35
- "zhin.js": "1.1.16"
28
+ "@zhin.js/adapter": "1.1.29",
29
+ "@zhin.js/command": "1.1.15",
30
+ "@zhin.js/core": "1.1.57",
31
+ "@zhin.js/middleware": "1.1.14",
32
+ "@zhin.js/plugin-runtime": "1.1.21",
33
+ "@zhin.js/runtime": "1.1.19",
34
+ "@zhin.js/tool": "1.1.16",
35
+ "zhin.js": "1.1.22"
36
36
  },
37
37
  "engines": {
38
38
  "node": ">=22.19.0"
package/src/fake-hosts.ts CHANGED
@@ -119,8 +119,8 @@ export class FakeOutboundRootHost implements OutboundRootHost {
119
119
  }
120
120
 
121
121
  send(input: OutboundSendInput): Promise<string | null> { return this.#record('send', input); }
122
- sendTarget(target: DeliveryTarget, content: unknown, requester: PluginId): Promise<string | null> {
123
- return this.#record('sendTarget', { target, content }, requester);
122
+ sendTarget(target: DeliveryTarget, content: unknown, requester: PluginId, options?: Readonly<{ locale?: import('@zhin.js/plugin-runtime').Locale }>): Promise<string | null> {
123
+ return this.#record('sendTarget', { target, content, ...(options?.locale ? { locale: options.locale } : {}) }, requester);
124
124
  }
125
125
  addReaction(input: OutboundReactionInput): Promise<string | null> { return this.#record('addReaction', input); }
126
126
  async removeReaction(input: unknown): Promise<void> { await this.#record('removeReaction', input, undefined, false); }
@@ -1,8 +1,8 @@
1
1
  import {
2
- DisposeStack, GenerationHandoffStack, PluginDatabaseHost, PluginOutboundHost, PluginScheduleHost,
2
+ DisposeStack, GenerationHandoffStack, PluginDatabaseHost, PluginOutboundHost, PluginScheduleHost, createPluginEventChannel,
3
3
  Scope, databaseHostToken, outboundHostToken, qualifyPluginResourceName, rootPluginId, scheduleHostToken,
4
4
  type Dispose, type FeatureId, type PluginDefinition, type PluginId, type PluginNodeSnapshot,
5
- type PluginSetupContext, type Token,
5
+ type PluginSetupContext, type Token, type PluginLifecycleEventMap,
6
6
  } from 'zhin.js/plugin-runtime';
7
7
  import type { CapabilityContext } from 'zhin.js';
8
8
  import { parsePluginConfigSchema } from '@zhin.js/runtime';
@@ -66,6 +66,7 @@ export class FakePlugin<TConfig = unknown> {
66
66
  readonly schedule: PluginScheduleHost;
67
67
  readonly outbound: PluginOutboundHost;
68
68
  readonly #abort = new AbortController();
69
+ readonly #events = createPluginEventChannel();
69
70
  readonly #context: PluginSetupContext<TConfig>;
70
71
 
71
72
  constructor(options: FakePluginOptions<TConfig> = {}) {
@@ -130,11 +131,18 @@ export class FakePlugin<TConfig = unknown> {
130
131
  /** Abort `signal` and run every disposer (reverse order). */
131
132
  async dispose(): Promise<void> {
132
133
  this.#abort.abort();
133
- await this.lifecycle.dispose();
134
+ try { await this.lifecycle.dispose(); }
135
+ finally { this.#events.dispose(); }
136
+ }
137
+
138
+ /** Deliver a Runtime lifecycle fact to this concrete test instance. */
139
+ dispatchLifecycle<TName extends keyof PluginLifecycleEventMap>(name: TName, event: PluginLifecycleEventMap[TName]): Promise<void> {
140
+ return this.#events.dispatch(name, event);
134
141
  }
135
142
 
136
143
  #createSetupContext(): PluginSetupContext<TConfig> {
137
144
  const base = {
145
+ events: this.#events.events,
138
146
  signal: this.signal,
139
147
  plugin: Object.freeze({ id: this.id, instanceKey: this.name, root: this.id, role: 'root' as const }),
140
148
  config: Object.freeze({ get: () => this.config as Readonly<TConfig> }),
@@ -1,6 +1,6 @@
1
1
  import { resolveLocale, type Locale } from 'zhin.js/i18n';
2
2
  import type {
3
- CommandContext, CommandDefinition, CommandMessage, CommandParameterValue,
3
+ CommandContext, CommandDefinition, CommandMessage, CommandParamSchema, CommandParameterValue, CommandSession,
4
4
  } from 'zhin.js/command';
5
5
  import type { HandlerContext, HandlerDefinition } from 'zhin.js/handler';
6
6
  import type {
@@ -11,14 +11,41 @@ import {
11
11
  type AgentToolDefinition, type ToolExecutionContext, type ToolInvocationOrigin,
12
12
  type ToolInvocationPolicy, type ToolQuestionPort,
13
13
  } from '@zhin.js/tool';
14
- import type { OperationClientPort } from 'zhin.js';
14
+ import { readOperationSession, type OperationClientPort } from 'zhin.js';
15
15
  import type { FakePlugin } from './fake-plugin.js';
16
16
  import { fileURLToPath } from 'node:url';
17
17
 
18
- /** Inbound message with recorded replies. */
18
+ export interface FakeSentDelivery {
19
+ readonly target: {
20
+ readonly kind: 'private' | 'group' | 'channel';
21
+ readonly id: string;
22
+ readonly parent?: { readonly kind: 'private' | 'group' | 'channel'; readonly id: string };
23
+ readonly threadId?: string;
24
+ };
25
+ readonly content: unknown;
26
+ }
27
+
28
+ /** Inbound message with recorded replies and targeted sends. */
19
29
  export interface FakeMessage extends CommandMessage {
20
- /** Everything passed to `$reply`, in order. */
30
+ /** Everything passed to `$reply`, `$sendTo`, `$replyToPrivate`, `$replyToGroup`, or `$replyToChannel`, in order. */
21
31
  readonly replies: unknown[];
32
+ /** Targeted sends invoked via `$sendTo`, `$replyToPrivate`, `$replyToGroup`, or `$replyToChannel`. */
33
+ readonly sent: FakeSentDelivery[];
34
+ $sendTo(
35
+ conversation: FakeSentDelivery['target'],
36
+ content: unknown,
37
+ ): Promise<string>;
38
+ $replyToPrivate(
39
+ content: unknown,
40
+ from?: boolean | { readonly kind: 'group' | 'channel'; readonly id: string },
41
+ ): Promise<string>;
42
+ $replyToGroup(groupIdOrContent: string | unknown, content?: unknown): Promise<string>;
43
+ $replyToChannel(
44
+ channelIdOrContent: string | unknown,
45
+ guildId?: string,
46
+ content?: unknown,
47
+ threadId?: string,
48
+ ): Promise<string>;
22
49
  }
23
50
 
24
51
  export interface FakeMessageInit {
@@ -33,17 +60,147 @@ export interface FakeMessageInit {
33
60
 
34
61
  export function createFakeMessage(init: FakeMessageInit = {}): FakeMessage {
35
62
  const replies: unknown[] = [];
63
+ const sent: FakeSentDelivery[] = [];
36
64
  const conversation: CommandMessage['conversation'] = {
37
65
  endpoint: { id: 'test', adapter: 'test' }, kind: 'group', id: 'test-group', ...init.conversation,
38
66
  };
67
+ const sender = init.sender ?? { id: 'test-user', name: 'Tester', roles: [] };
68
+ const recordSend = (target: FakeSentDelivery['target'], content: unknown): string => {
69
+ replies.push(content);
70
+ sent.push({ target, content });
71
+ return `reply-${replies.length}`;
72
+ };
39
73
  return {
40
74
  conversation, content: init.content ?? '', locale: resolveLocale(init.locale),
41
- sender: init.sender ?? { id: 'test-user', name: 'Tester', roles: [] },
75
+ sender,
42
76
  ...(init.id === undefined ? {} : { id: init.id }),
43
77
  ...(init.metadata === undefined ? {} : { metadata: init.metadata }),
44
78
  ...(init.$client === undefined ? {} : { $client: init.$client }),
45
79
  replies,
80
+ sent,
46
81
  async $reply(content: unknown) { replies.push(content); return `reply-${replies.length}`; },
82
+ async $sendTo(target, content) {
83
+ return recordSend(target, content);
84
+ },
85
+ async $replyToPrivate(content, from) {
86
+ let parent: FakeSentDelivery['target']['parent'];
87
+ if (from === true && (conversation.kind === 'group' || conversation.kind === 'channel')) {
88
+ parent = { kind: conversation.kind, id: conversation.id };
89
+ } else if (from != null && typeof from === 'object') {
90
+ parent = from;
91
+ }
92
+ return recordSend({
93
+ kind: 'private',
94
+ id: sender.id,
95
+ ...(parent ? { parent } : {}),
96
+ }, content);
97
+ },
98
+ async $replyToGroup(groupIdOrContent: string | unknown, maybeContent?: unknown) {
99
+ if (maybeContent === undefined) {
100
+ return recordSend({ kind: 'group', id: conversation.id }, groupIdOrContent);
101
+ }
102
+ return recordSend({ kind: 'group', id: String(groupIdOrContent) }, maybeContent);
103
+ },
104
+ async $replyToChannel(
105
+ channelIdOrContent: string | unknown,
106
+ guildId?: string,
107
+ content?: unknown,
108
+ threadId?: string,
109
+ ) {
110
+ if (guildId === undefined && content === undefined) {
111
+ return recordSend({ kind: 'channel', id: conversation.id }, channelIdOrContent);
112
+ }
113
+ return recordSend({
114
+ kind: 'channel',
115
+ id: String(channelIdOrContent),
116
+ ...(guildId ? { parent: { kind: 'channel', id: guildId } } : {}),
117
+ ...(threadId ? { threadId } : {}),
118
+ }, content);
119
+ },
120
+ };
121
+ }
122
+
123
+ export type FakeInteraction = NonNullable<CommandContext['interaction']> & {
124
+ /** Every interaction request presented via `ask`, `sequence`, `confirm`, or `select`, in order. */
125
+ readonly prompts: Parameters<NonNullable<CommandContext['interaction']>['ask']>[0][];
126
+ /** Append additional scripted answers to the queue. */
127
+ enqueue(...answers: unknown[]): void;
128
+ /** Convenience helper for confirm requests. */
129
+ confirm(title: string, defaultValue?: boolean): Promise<boolean>;
130
+ /** Convenience helper for select requests. */
131
+ select<V = string>(
132
+ title: string,
133
+ options: readonly (V | { readonly label: string; readonly value: V })[],
134
+ ): Promise<V>;
135
+ };
136
+
137
+ export interface FakeInteractionOptions {
138
+ readonly answers?: readonly unknown[];
139
+ }
140
+
141
+ /**
142
+ * Create a scripted `UserInteraction` double for unit-testing commands and handlers that use
143
+ * `interaction.ask()`, `interaction.sequence()`, `interaction.confirm()`, or `interaction.select()`.
144
+ */
145
+ export function createFakeInteraction(
146
+ init: readonly unknown[] | FakeInteractionOptions = [],
147
+ ): FakeInteraction {
148
+ type Interaction = NonNullable<CommandContext['interaction']>;
149
+ type Request = Parameters<Interaction['ask']>[0];
150
+ const queue: unknown[] = Array.isArray(init)
151
+ ? [...init]
152
+ : [...(init as FakeInteractionOptions).answers ?? []];
153
+ const prompts: Request[] = [];
154
+
155
+ const ask: Interaction['ask'] = (async (request: Request) => {
156
+ prompts.push(request);
157
+ if (queue.length > 0) {
158
+ const next = queue.shift();
159
+ return typeof next === 'function' ? await (next as (r: Request) => unknown)(request) : next;
160
+ }
161
+ if ('default' in request && request.default !== undefined) {
162
+ return request.default;
163
+ }
164
+ throw new Error(`No scripted answer remaining for interaction prompt: ${request.title}`);
165
+ }) as Interaction['ask'];
166
+
167
+ const sequence: Interaction['sequence'] = (async (seq) => {
168
+ const acc: Record<string, unknown> = {};
169
+ for (const step of seq.steps) {
170
+ acc[step.id] = await ask(step);
171
+ }
172
+ return Object.freeze({ ...acc });
173
+ }) as Interaction['sequence'];
174
+
175
+ return {
176
+ prompts,
177
+ enqueue(...answers: unknown[]) {
178
+ queue.push(...answers);
179
+ },
180
+ ask,
181
+ sequence,
182
+ confirm(title: string, defaultValue?: boolean): Promise<boolean> {
183
+ return ask({
184
+ type: 'confirm',
185
+ title,
186
+ ...(defaultValue === undefined ? {} : { default: defaultValue }),
187
+ });
188
+ },
189
+ select<V = string>(
190
+ title: string,
191
+ options: readonly (V | { readonly label: string; readonly value: V })[],
192
+ ): Promise<V> {
193
+ const normalized = options.map((opt) =>
194
+ opt !== null && typeof opt === 'object' && 'value' in opt && 'label' in opt
195
+ ? opt
196
+ : { label: String(opt), value: opt as V },
197
+ );
198
+ return ask({
199
+ type: 'select',
200
+ title,
201
+ options: normalized,
202
+ }) as Promise<V>;
203
+ },
47
204
  };
48
205
  }
49
206
 
@@ -83,6 +240,7 @@ export function createCommandContext<TConfig, TInput extends CommandMessage = Fa
83
240
  options: options.options ?? {},
84
241
  segments: options.segments ?? [],
85
242
  input,
243
+ get session() { return readOperationSession(input); },
86
244
  $client: input.$client as never,
87
245
  interaction: options.interaction,
88
246
  adapter: conversation.endpoint.adapter,
@@ -103,7 +261,77 @@ export async function runCommand<TConfig, TResult, TInput extends CommandMessage
103
261
  options?: RunCommandOptions<TInput>,
104
262
  ): Promise<TResult> {
105
263
  const command = options?.source === undefined ? definition : await bindSource(definition, options.source);
106
- return command.execute(createCommandContext(fake, options));
264
+ const resolvedOptions = populateCommandOptionsFromDefinition(command, options);
265
+ return command.execute(createCommandContext(fake, resolvedOptions));
266
+ }
267
+
268
+ function populateCommandOptionsFromDefinition<TConfig, TResult, TInput extends CommandMessage>(
269
+ command: CommandDefinition<TConfig, TResult, TInput, string | undefined>,
270
+ options?: RunCommandOptions<TInput>,
271
+ ): RunCommandOptions<TInput> | undefined {
272
+ if (!command.params && !command.options) return options;
273
+ const args = options?.args ?? [];
274
+ const input = (options?.input ?? createFakeMessage()) as TInput;
275
+ const session: CommandSession = {
276
+ adapter: input.conversation.endpoint.adapter,
277
+ endpoint: input.conversation.endpoint.id,
278
+ scene: input.scene ?? { id: input.conversation.id, type: input.conversation.kind },
279
+ ...(input.sender ? { sender: { id: input.sender.id, name: input.sender.name, role: input.sender.roles ?? [] } } : {}),
280
+ };
281
+ const resolveDefault = (def: CommandParamSchema['default']): CommandParameterValue | undefined => {
282
+ if (def === undefined) return undefined;
283
+ return typeof def === 'function' ? def(session) : def;
284
+ };
285
+ const inferredParams: Record<string, CommandParameterValue> = {};
286
+ if (command.params) {
287
+ const entries = Object.entries(command.params);
288
+ for (let i = 0; i < entries.length; i++) {
289
+ const [name, schema] = entries[i]!;
290
+ if (schema.rest) {
291
+ const rest = args.slice(i);
292
+ if (rest.length > 0) {
293
+ inferredParams[name] = rest.map((token) => coerceCommandScalar(token, schema));
294
+ } else {
295
+ const def = resolveDefault(schema.default);
296
+ if (def !== undefined) inferredParams[name] = def;
297
+ }
298
+ break;
299
+ }
300
+ const raw = args[i];
301
+ if (raw !== undefined) {
302
+ inferredParams[name] = coerceCommandScalar(raw, schema);
303
+ } else {
304
+ const def = resolveDefault(schema.default);
305
+ if (def !== undefined) inferredParams[name] = def;
306
+ }
307
+ }
308
+ }
309
+ const inferredOptions: Record<string, CommandParameterValue> = {};
310
+ if (command.options) {
311
+ for (const [name, opt] of Object.entries(command.options)) {
312
+ const def = resolveDefault(opt.default);
313
+ if (def !== undefined) {
314
+ inferredOptions[name] = def;
315
+ }
316
+ }
317
+ }
318
+ return {
319
+ ...options,
320
+ params: { ...inferredParams, ...(options?.params ?? {}) },
321
+ options: { ...inferredOptions, ...(options?.options ?? {}) },
322
+ };
323
+ }
324
+
325
+ function coerceCommandScalar(raw: string, schema: CommandParamSchema): string | number | boolean {
326
+ if (schema.type === 'number' || schema.type === 'integer' || schema.type === 'float' || schema.type === 'dice' || schema.type === 'rps') {
327
+ const parsed = Number(raw);
328
+ return Number.isNaN(parsed) ? raw : parsed;
329
+ }
330
+ if (schema.type === 'boolean') {
331
+ if (raw === 'true' || raw === '1') return true;
332
+ if (raw === 'false' || raw === '0') return false;
333
+ }
334
+ return raw;
107
335
  }
108
336
 
109
337
  async function bindSource<T extends CommandDefinition<never, unknown, never, string | undefined>>(
@@ -134,6 +362,7 @@ export async function runMiddleware<TConfig, TInput = FakeMessage>(
134
362
  const context: MiddlewareContext<TInput, TConfig, string | undefined> = {
135
363
  ...fake.capabilityContext(),
136
364
  input,
365
+ get session() { return readOperationSession(input); },
137
366
  $client: (input as { $client?: unknown } | undefined)?.$client as never,
138
367
  };
139
368
  const next = (async () => { continued = true; return undefined; }) as unknown as MiddlewareNext;
@@ -147,7 +376,10 @@ export async function runHandler<TConfig>(
147
376
  definition: HandlerDefinition,
148
377
  ...args: unknown[]
149
378
  ): Promise<void> {
150
- const context: HandlerContext<TConfig> = fake.capabilityContext();
379
+ const context: HandlerContext<TConfig> = {
380
+ ...fake.capabilityContext(),
381
+ get session() { return readOperationSession(args[0]); },
382
+ };
151
383
  await definition.handle.call(context as HandlerContext, ...args);
152
384
  }
153
385