@jaypie/mcp 0.2.3 → 0.2.4

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.
@@ -361,4 +361,137 @@ Deploy using AWS CDK or other deployment tool. The Lambda handler will be refere
361
361
  - Use double quotes, trailing commas, semicolons
362
362
  - Alphabetize imports and properties
363
363
  - Define constants for hard-coded values at file top
364
- - Never throw vanilla Error; use errors from `@jaypie/errors`
364
+ - Never throw vanilla Error; use errors from `@jaypie/errors`
365
+
366
+ ## Streaming Lambda Functions
367
+
368
+ Use `lambdaStreamHandler` for AWS Lambda Response Streaming. This enables real-time streaming responses for LLM interactions, large file processing, and SSE endpoints.
369
+
370
+ ### Lambda Streaming Setup
371
+
372
+ Create a streaming Lambda handler with `awslambda.streamifyResponse`:
373
+
374
+ ```typescript
375
+ // src/streamWorker.ts
376
+ import { log } from "@jaypie/core";
377
+ import { lambdaStreamHandler, createLambdaStream, Llm } from "jaypie";
378
+ import type { StreamHandlerContext } from "@jaypie/lambda";
379
+
380
+ export interface StreamWorkerEvent {
381
+ prompt?: string;
382
+ }
383
+
384
+ const streamWorker = lambdaStreamHandler(
385
+ async (event: StreamWorkerEvent, context: StreamHandlerContext) => {
386
+ log.trace("streamWorker: start");
387
+
388
+ const llm = new Llm("anthropic");
389
+ const stream = llm.stream(event.prompt || "Hello");
390
+
391
+ // createLambdaStream pipes LLM chunks as SSE events
392
+ await createLambdaStream(stream, context.responseStream);
393
+
394
+ log.trace("streamWorker: complete");
395
+ },
396
+ {
397
+ name: "streamWorker",
398
+ contentType: "text/event-stream",
399
+ }
400
+ );
401
+
402
+ // Wrap with AWS streamifyResponse
403
+ declare const awslambda: { streamifyResponse: <T>(handler: T) => T };
404
+ export const handler = awslambda.streamifyResponse(streamWorker);
405
+ ```
406
+
407
+ ### Manual Stream Writing
408
+
409
+ Write directly to the response stream for custom SSE events:
410
+
411
+ ```typescript
412
+ import { lambdaStreamHandler } from "jaypie";
413
+ import type { StreamHandlerContext } from "@jaypie/lambda";
414
+
415
+ const manualStreamHandler = lambdaStreamHandler(
416
+ async (event: unknown, context: StreamHandlerContext) => {
417
+ const { responseStream } = context;
418
+
419
+ // Write SSE events directly
420
+ responseStream.write("event: start\ndata: {\"status\": \"processing\"}\n\n");
421
+
422
+ // Process data in chunks
423
+ for (const item of items) {
424
+ const result = await process(item);
425
+ responseStream.write(`event: data\ndata: ${JSON.stringify(result)}\n\n`);
426
+ }
427
+
428
+ responseStream.write("event: done\ndata: {\"status\": \"complete\"}\n\n");
429
+ // Handler automatically calls responseStream.end()
430
+ },
431
+ {
432
+ name: "manualStream",
433
+ }
434
+ );
435
+ ```
436
+
437
+ ### Stream Handler Options
438
+
439
+ ```typescript
440
+ import type { LambdaStreamHandlerOptions } from "@jaypie/lambda";
441
+
442
+ const options: LambdaStreamHandlerOptions = {
443
+ name: "myStreamHandler", // Handler name for logging
444
+ contentType: "text/event-stream", // Response content type (default)
445
+ chaos: "low", // Chaos testing level
446
+ secrets: ["API_KEY"], // AWS secrets to load into process.env
447
+ setup: [], // Setup function(s)
448
+ teardown: [], // Teardown function(s)
449
+ validate: [], // Validation function(s)
450
+ throw: false, // Re-throw errors instead of SSE error
451
+ unavailable: false, // Return 503 if true
452
+ };
453
+ ```
454
+
455
+ ### Stream Handler Types
456
+
457
+ ```typescript
458
+ import type {
459
+ LambdaStreamHandlerOptions,
460
+ StreamHandlerContext,
461
+ ResponseStream,
462
+ AwsStreamingHandler,
463
+ } from "@jaypie/lambda";
464
+ ```
465
+
466
+ ### CDK Configuration for Streaming
467
+
468
+ Enable Lambda Response Streaming via Function URL in CDK:
469
+
470
+ ```typescript
471
+ import { JaypieLambda } from "@jaypie/constructs";
472
+ import { FunctionUrlAuthType, InvokeMode } from "aws-cdk-lib/aws-lambda";
473
+
474
+ const streamingLambda = new JaypieLambda(this, "StreamingFunction", {
475
+ code: "dist",
476
+ handler: "streamWorker.handler",
477
+ timeout: Duration.minutes(5),
478
+ });
479
+
480
+ // Add Function URL with streaming enabled
481
+ streamingLambda.addFunctionUrl({
482
+ authType: FunctionUrlAuthType.NONE, // or AWS_IAM for auth
483
+ invokeMode: InvokeMode.RESPONSE_STREAM,
484
+ });
485
+ ```
486
+
487
+ ### Error Handling in Streams
488
+
489
+ Errors are formatted as SSE error events:
490
+
491
+ ```typescript
492
+ // Jaypie errors written as:
493
+ // event: error
494
+ // data: {"errors":[{"status":500,"title":"Internal Error"}]}
495
+ ```
496
+
497
+ Set `throw: true` to re-throw errors instead of writing to stream.
@@ -312,6 +312,60 @@ type LlmStreamChunk =
312
312
  | LlmStreamChunkError; // { type: "error", error: { status, title, detail? } }
313
313
  ```
314
314
 
315
+ ### Streaming to Express
316
+
317
+ Use `createExpressStream` to pipe LLM streams to Express responses:
318
+
319
+ ```javascript
320
+ import { expressStreamHandler, Llm, createExpressStream } from "jaypie";
321
+
322
+ const chatRoute = expressStreamHandler(async (req, res) => {
323
+ const llm = new Llm("anthropic");
324
+ const stream = llm.stream(req.body.prompt);
325
+ await createExpressStream(stream, res);
326
+ });
327
+
328
+ app.post("/chat", chatRoute);
329
+ ```
330
+
331
+ ### Streaming to Lambda
332
+
333
+ Use `createLambdaStream` with Lambda Response Streaming:
334
+
335
+ ```javascript
336
+ import { lambdaStreamHandler, Llm, createLambdaStream } from "jaypie";
337
+
338
+ const handler = awslambda.streamifyResponse(
339
+ lambdaStreamHandler(async (event, context) => {
340
+ const llm = new Llm("openai");
341
+ const stream = llm.stream(event.prompt);
342
+ await createLambdaStream(stream, context.responseStream);
343
+ })
344
+ );
345
+ ```
346
+
347
+ ### JaypieStream Wrapper
348
+
349
+ Use `JaypieStream` or `createJaypieStream` for fluent piping:
350
+
351
+ ```javascript
352
+ import { createJaypieStream, Llm } from "jaypie";
353
+
354
+ const llm = new Llm("gemini");
355
+ const stream = createJaypieStream(llm.stream("Hello"));
356
+
357
+ // Pipe to Express
358
+ await stream.toExpress(res);
359
+
360
+ // Or pipe to Lambda
361
+ await stream.toLambda(responseStream);
362
+
363
+ // Or iterate manually
364
+ for await (const chunk of stream) {
365
+ console.log(chunk);
366
+ }
367
+ ```
368
+
315
369
  ## Hooks
316
370
 
317
371
  Use hooks to intercept and observe the LLM lifecycle:
@@ -365,6 +419,29 @@ const result = await llm.operate("Roll dice and check weather", {
365
419
  });
366
420
  ```
367
421
 
422
+ ### Zod Schema Support
423
+
424
+ Tool parameters can be defined using Zod schemas instead of JSON Schema:
425
+
426
+ ```javascript
427
+ import { z } from "zod/v4";
428
+ import { Llm, Toolkit } from "jaypie";
429
+
430
+ const weatherTool = {
431
+ name: "get_weather",
432
+ description: "Get weather for a city",
433
+ parameters: z.object({
434
+ city: z.string().describe("City name"),
435
+ unit: z.enum(["celsius", "fahrenheit"]),
436
+ }),
437
+ type: "function",
438
+ call: async ({ city, unit }) => ({ city, temp: 72, unit }),
439
+ };
440
+
441
+ const toolkit = new Toolkit([weatherTool]);
442
+ // Zod schemas are automatically converted to JSON Schema
443
+ ```
444
+
368
445
  ## Footnotes
369
446
 
370
447
  Llm.operate(input, options)
@@ -16,10 +16,12 @@ Create and integrate tools that enable LLMs to perform specific functions beyond
16
16
  Implement the `LlmTool` interface:
17
17
 
18
18
  ```typescript
19
+ import { z } from "zod/v4";
20
+
19
21
  interface LlmTool {
20
22
  description: string;
21
23
  name: string;
22
- parameters: JsonObject;
24
+ parameters: JsonObject | z.ZodType; // JSON Schema or Zod schema
23
25
  type: "function" | string;
24
26
  call: (args?: JsonObject) => Promise<AnyValue> | AnyValue;
25
27
  }
@@ -28,11 +30,11 @@ interface LlmTool {
28
30
  Properties:
29
31
  - `description`: Clear explanation of tool functionality
30
32
  - `name`: Unique identifier
31
- - `parameters`: JSON Schema defining input parameters
33
+ - `parameters`: JSON Schema or Zod schema defining input parameters
32
34
  - `type`: Usually "function" (OpenAI convention)
33
35
  - `call`: Implementation function executed on invocation
34
36
 
35
- ## Example: Dice Roller
37
+ ## Example: Dice Roller (JSON Schema)
36
38
 
37
39
  ```typescript
38
40
  import { LlmTool } from "../types/LlmTool.interface.js";
@@ -84,6 +86,27 @@ export const roll: LlmTool = {
84
86
  };
85
87
  ```
86
88
 
89
+ ## Example: Weather Tool (Zod Schema)
90
+
91
+ ```typescript
92
+ import { z } from "zod/v4";
93
+ import { LlmTool } from "jaypie";
94
+
95
+ export const getWeather: LlmTool = {
96
+ description: "Get current weather for a city",
97
+ name: "get_weather",
98
+ parameters: z.object({
99
+ city: z.string().describe("City name"),
100
+ unit: z.enum(["celsius", "fahrenheit"]).describe("Temperature unit"),
101
+ }),
102
+ type: "function",
103
+ call: async ({ city, unit }) => {
104
+ // Implementation here
105
+ return { city, temperature: 72, unit };
106
+ },
107
+ };
108
+ ```
109
+
87
110
  ## Best Practices
88
111
 
89
112
  ### Input Validation
@@ -0,0 +1,411 @@
1
+ ---
2
+ description: Commander.js CLI integration with serviceHandler callbacks (onMessage, onComplete, onError, onFatal)
3
+ include: "**/cli/**"
4
+ ---
5
+
6
+ # Jaypie Vocabulary Commander Adapter
7
+
8
+ The Commander adapter (`@jaypie/vocabulary/commander`) integrates Jaypie service handlers with Commander.js CLI applications, providing automatic option generation, type coercion, and callback hooks for progress reporting.
9
+
10
+ **See also:** [Jaypie_Vocabulary_Package.md](Jaypie_Vocabulary_Package.md) for core serviceHandler documentation.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @jaypie/vocabulary commander
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ```typescript
21
+ import { Command } from "commander";
22
+ import { serviceHandler } from "@jaypie/vocabulary";
23
+ import { registerServiceCommand } from "@jaypie/vocabulary/commander";
24
+
25
+ const handler = serviceHandler({
26
+ alias: "greet",
27
+ description: "Greet a user",
28
+ input: {
29
+ userName: { type: String, flag: "user", letter: "u" },
30
+ loud: { type: Boolean, letter: "l", default: false },
31
+ },
32
+ service: ({ loud, userName }) => {
33
+ const greeting = `Hello, ${userName}!`;
34
+ console.log(loud ? greeting.toUpperCase() : greeting);
35
+ },
36
+ });
37
+
38
+ const program = new Command();
39
+ registerServiceCommand({ handler, program });
40
+ program.parse();
41
+ // Usage: greet --user Alice -l
42
+ ```
43
+
44
+ ## registerServiceCommand
45
+
46
+ The primary function for registering a service handler as a Commander command.
47
+
48
+ ### Options
49
+
50
+ | Option | Type | Description |
51
+ |--------|------|-------------|
52
+ | `handler` | `ServiceHandlerFunction` | Required. The service handler to register |
53
+ | `program` | `Command` | Required. Commander program or command |
54
+ | `name` | `string` | Override command name (default: handler.alias) |
55
+ | `description` | `string` | Override description (default: handler.description) |
56
+ | `exclude` | `string[]` | Field names to exclude from CLI options |
57
+ | `onComplete` | `OnCompleteCallback` | Called with handler's return value on success |
58
+ | `onError` | `OnErrorCallback` | Receives errors reported via `context.onError()` |
59
+ | `onFatal` | `OnFatalCallback` | Receives fatal errors (thrown or via `context.onFatal()`) |
60
+ | `onMessage` | `OnMessageCallback` | Receives messages from `context.sendMessage` |
61
+ | `overrides` | `Record<string, override>` | Per-field option overrides |
62
+
63
+ ## Callback Hooks
64
+
65
+ ### onMessage
66
+
67
+ Receives progress messages sent by the service via `context.sendMessage`:
68
+
69
+ ```typescript
70
+ import { Command } from "commander";
71
+ import { serviceHandler } from "@jaypie/vocabulary";
72
+ import { registerServiceCommand } from "@jaypie/vocabulary/commander";
73
+
74
+ const handler = serviceHandler({
75
+ alias: "process",
76
+ input: { jobId: { type: String, letter: "j" } },
77
+ service: async ({ jobId }, context) => {
78
+ // Send progress messages during execution
79
+ context?.sendMessage?.({ content: `Starting job ${jobId}` });
80
+
81
+ // Simulate work
82
+ await doStep1();
83
+ context?.sendMessage?.({ content: "Step 1 complete", level: "debug" });
84
+
85
+ await doStep2();
86
+ context?.sendMessage?.({ content: "Step 2 complete", level: "debug" });
87
+
88
+ context?.sendMessage?.({ content: "Job finished!", level: "info" });
89
+ return { jobId, status: "complete" };
90
+ },
91
+ });
92
+
93
+ const program = new Command();
94
+ registerServiceCommand({
95
+ handler,
96
+ program,
97
+ onMessage: (msg) => {
98
+ // msg: { content: string, level?: "trace"|"debug"|"info"|"warn"|"error" }
99
+ const level = msg.level || "info";
100
+ console[level](msg.content);
101
+ },
102
+ });
103
+ program.parse();
104
+ ```
105
+
106
+ **Important:** Errors in `onMessage` are swallowed to ensure messaging failures never halt service execution.
107
+
108
+ ### onComplete
109
+
110
+ Called with the handler's return value on successful completion:
111
+
112
+ ```typescript
113
+ registerServiceCommand({
114
+ handler,
115
+ program,
116
+ onComplete: (response) => {
117
+ // Called after service completes successfully
118
+ console.log("Result:", JSON.stringify(response, null, 2));
119
+
120
+ // Common patterns:
121
+ // - Save results to file
122
+ // - Display formatted output
123
+ // - Trigger follow-up actions
124
+ },
125
+ });
126
+ ```
127
+
128
+ ### onError
129
+
130
+ Receives errors that the service explicitly reports via `context.onError()`. Use this for recoverable errors that don't halt execution:
131
+
132
+ ```typescript
133
+ registerServiceCommand({
134
+ handler,
135
+ program,
136
+ onError: (error) => {
137
+ // Log recoverable errors
138
+ console.warn("Warning:", error.message);
139
+ },
140
+ });
141
+ ```
142
+
143
+ ### onFatal
144
+
145
+ Receives fatal errors - either thrown errors or errors reported via `context.onFatal()`. Any error that escapes the service (is thrown) is treated as fatal:
146
+
147
+ ```typescript
148
+ registerServiceCommand({
149
+ handler,
150
+ program,
151
+ onFatal: (error) => {
152
+ console.error("Fatal error:", error.message);
153
+ process.exit(1);
154
+ },
155
+ });
156
+ ```
157
+
158
+ **Error handling priority:**
159
+ 1. If `onFatal` is provided, thrown errors go to `onFatal`
160
+ 2. If only `onError` is provided, thrown errors fall back to `onError`
161
+ 3. If neither is provided, errors are re-thrown
162
+
163
+ ## Complete Example with All Callbacks
164
+
165
+ ```typescript
166
+ import { Command } from "commander";
167
+ import { serviceHandler } from "@jaypie/vocabulary";
168
+ import { registerServiceCommand } from "@jaypie/vocabulary/commander";
169
+
170
+ const evaluateHandler = serviceHandler({
171
+ alias: "evaluate",
172
+ description: "Run an evaluation job",
173
+ input: {
174
+ jobId: {
175
+ type: String,
176
+ flag: "job",
177
+ letter: "j",
178
+ description: "Job identifier",
179
+ },
180
+ priority: {
181
+ type: [1, 2, 3, 4, 5],
182
+ default: 3,
183
+ letter: "p",
184
+ description: "Job priority (1-5)",
185
+ },
186
+ tags: {
187
+ type: [String],
188
+ letter: "t",
189
+ required: false,
190
+ description: "Tags to apply",
191
+ },
192
+ dryRun: {
193
+ type: Boolean,
194
+ letter: "d",
195
+ default: false,
196
+ description: "Run without executing",
197
+ },
198
+ },
199
+ service: async ({ dryRun, jobId, priority, tags }, context) => {
200
+ context?.sendMessage?.({ content: `Initializing job ${jobId}...` });
201
+
202
+ if (dryRun) {
203
+ context?.sendMessage?.({ content: "Dry run mode - skipping execution", level: "warn" });
204
+ return { jobId, status: "dry-run", skipped: true };
205
+ }
206
+
207
+ // Handle recoverable errors without throwing
208
+ try {
209
+ await riskyOperation();
210
+ } catch (err) {
211
+ context?.onError?.(err); // Reports error but continues
212
+ }
213
+
214
+ context?.sendMessage?.({ content: `Running with priority ${priority}` });
215
+
216
+ if (tags?.length) {
217
+ context?.sendMessage?.({ content: `Applying tags: ${tags.join(", ")}`, level: "debug" });
218
+ }
219
+
220
+ // Simulate processing
221
+ for (let i = 1; i <= 5; i++) {
222
+ await new Promise(resolve => setTimeout(resolve, 100));
223
+ context?.sendMessage?.({ content: `Progress: ${i * 20}%`, level: "debug" });
224
+ }
225
+
226
+ context?.sendMessage?.({ content: "Evaluation complete!" });
227
+ return { jobId, status: "complete", results: 42 };
228
+ },
229
+ });
230
+
231
+ const program = new Command();
232
+ program.version("1.0.0").description("Evaluation CLI");
233
+
234
+ registerServiceCommand({
235
+ handler: evaluateHandler,
236
+ program,
237
+ onMessage: (msg) => {
238
+ const prefix = msg.level === "warn" ? "WARNING: " :
239
+ msg.level === "error" ? "ERROR: " : "";
240
+ console.log(`${prefix}${msg.content}`);
241
+ },
242
+ onComplete: (response) => {
243
+ console.log("\n--- Results ---");
244
+ console.log(JSON.stringify(response, null, 2));
245
+ },
246
+ onError: (error) => {
247
+ // Recoverable errors reported via context.onError()
248
+ console.warn("Warning:", error.message);
249
+ },
250
+ onFatal: (error) => {
251
+ // Fatal errors (thrown or via context.onFatal())
252
+ console.error("\nFatal:", error.message);
253
+ process.exit(1);
254
+ },
255
+ });
256
+
257
+ program.parse();
258
+ ```
259
+
260
+ Usage:
261
+ ```bash
262
+ # Basic execution
263
+ cli evaluate --job abc123
264
+
265
+ # With all options
266
+ cli evaluate -j abc123 -p 1 -t urgent -t critical --dry-run
267
+
268
+ # Help
269
+ cli evaluate --help
270
+ ```
271
+
272
+ ## Input Flag and Letter Properties
273
+
274
+ Define CLI flags directly in input definitions:
275
+
276
+ ```typescript
277
+ input: {
278
+ userName: {
279
+ type: String,
280
+ flag: "user", // Long flag: --user (instead of --user-name)
281
+ letter: "u", // Short flag: -u
282
+ description: "User name to greet",
283
+ },
284
+ verbose: {
285
+ type: Boolean,
286
+ letter: "v", // -v
287
+ },
288
+ }
289
+ // Generates: --user <userName>, -u and --verbose, -v
290
+ ```
291
+
292
+ ### Naming Convention
293
+
294
+ | Property | CLI Flag | Example |
295
+ |----------|----------|---------|
296
+ | `userName` (camelCase) | `--user-name` | Default behavior |
297
+ | `flag: "user"` | `--user` | Override long flag |
298
+ | `letter: "u"` | `-u` | Short flag |
299
+
300
+ ## Boolean Flag Behavior
301
+
302
+ Commander.js automatically handles boolean flags:
303
+ - `--verbose` sets to `true`
304
+ - `--no-verbose` sets to `false` (for flags with `default: true`)
305
+
306
+ ## Manual Integration
307
+
308
+ For more control, use `createCommanderOptions` and `parseCommanderOptions`:
309
+
310
+ ```typescript
311
+ import { Command } from "commander";
312
+ import { serviceHandler } from "@jaypie/vocabulary";
313
+ import {
314
+ createCommanderOptions,
315
+ parseCommanderOptions,
316
+ } from "@jaypie/vocabulary/commander";
317
+
318
+ const handler = serviceHandler({
319
+ input: {
320
+ userName: { type: String, description: "User name" },
321
+ maxRetries: { type: Number, default: 3 },
322
+ verbose: { type: Boolean },
323
+ },
324
+ service: (input) => console.log(input),
325
+ });
326
+
327
+ const program = new Command();
328
+
329
+ // Create options from handler input
330
+ const { options } = createCommanderOptions(handler.input, {
331
+ exclude: ["internalField"],
332
+ overrides: {
333
+ userName: { short: "u", description: "Override description" },
334
+ },
335
+ });
336
+ options.forEach((opt) => program.addOption(opt));
337
+
338
+ // Wire up action
339
+ program.action(async (opts) => {
340
+ const input = parseCommanderOptions(opts, { input: handler.input });
341
+ await handler(input);
342
+ });
343
+
344
+ program.parse();
345
+ ```
346
+
347
+ ## TypeScript Types
348
+
349
+ ```typescript
350
+ import type {
351
+ CommanderOptionOverride,
352
+ CreateCommanderOptionsConfig,
353
+ CreateCommanderOptionsResult,
354
+ OnCompleteCallback,
355
+ OnErrorCallback,
356
+ OnFatalCallback,
357
+ OnMessageCallback,
358
+ ParseCommanderOptionsConfig,
359
+ RegisterServiceCommandConfig,
360
+ RegisterServiceCommandResult,
361
+ } from "@jaypie/vocabulary/commander";
362
+ ```
363
+
364
+ ### Callback Type Definitions
365
+
366
+ ```typescript
367
+ // Message received from context.sendMessage
368
+ interface Message {
369
+ content: string;
370
+ level?: "trace" | "debug" | "info" | "warn" | "error";
371
+ }
372
+
373
+ // onMessage callback
374
+ type OnMessageCallback = (message: Message) => void | Promise<void>;
375
+
376
+ // onComplete callback - receives handler return value
377
+ type OnCompleteCallback<T = unknown> = (response: T) => void | Promise<void>;
378
+
379
+ // onError callback - receives errors from context.onError()
380
+ type OnErrorCallback = (error: unknown) => void | Promise<void>;
381
+
382
+ // onFatal callback - receives fatal errors (thrown or context.onFatal())
383
+ type OnFatalCallback = (error: unknown) => void | Promise<void>;
384
+ ```
385
+
386
+ ## Exports
387
+
388
+ ```typescript
389
+ // @jaypie/vocabulary/commander
390
+ export { createCommanderOptions } from "./createCommanderOptions.js";
391
+ export { parseCommanderOptions } from "./parseCommanderOptions.js";
392
+ export { registerServiceCommand } from "./registerServiceCommand.js";
393
+
394
+ export type {
395
+ CommanderOptionOverride,
396
+ CreateCommanderOptionsConfig,
397
+ CreateCommanderOptionsResult,
398
+ OnCompleteCallback,
399
+ OnErrorCallback,
400
+ OnFatalCallback,
401
+ OnMessageCallback,
402
+ ParseCommanderOptionsConfig,
403
+ RegisterServiceCommandConfig,
404
+ RegisterServiceCommandResult,
405
+ } from "./types.js";
406
+ ```
407
+
408
+ ## Related
409
+
410
+ - [Jaypie_Commander_CLI_Package.md](Jaypie_Commander_CLI_Package.md) - Setting up a Commander CLI project from scratch
411
+ - [Jaypie_Vocabulary_Package.md](Jaypie_Vocabulary_Package.md) - Core serviceHandler and type coercion