citadel_cli 1.0.0 → 1.1.0

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.
Files changed (30) hide show
  1. package/README.md +148 -207
  2. package/dist/citadel.es.js +1289 -1449
  3. package/dist/citadel.umd.js +19 -19
  4. package/dist/command_examples/basic-commands.d.ts +2 -83
  5. package/dist/src/__test-utils__/factories.d.ts +29 -10
  6. package/dist/src/components/Citadel/Citadel.d.ts +11 -7
  7. package/dist/src/components/Citadel/components/AvailableCommands.d.ts +1 -8
  8. package/dist/src/components/Citadel/components/CommandInput.d.ts +0 -2
  9. package/dist/src/components/Citadel/config/CitadelConfigContext.d.ts +5 -2
  10. package/dist/src/components/Citadel/config/defaults.d.ts +15 -7
  11. package/dist/src/components/Citadel/config/types.d.ts +32 -20
  12. package/dist/src/components/Citadel/hooks/useCitadelState.d.ts +2 -1
  13. package/dist/src/components/Citadel/hooks/useCommandHistory.d.ts +19 -9
  14. package/dist/src/components/Citadel/hooks/useCommandParser.d.ts +18 -15
  15. package/dist/src/components/Citadel/hooks/useSegmentStack.d.ts +14 -0
  16. package/dist/src/components/Citadel/hooks/useSegmentStackVersion.d.ts +1 -0
  17. package/dist/src/components/Citadel/storage/BaseStorage.d.ts +2 -2
  18. package/dist/src/components/Citadel/storage/LocalStorage.d.ts +1 -1
  19. package/dist/src/components/Citadel/storage/MemoryStorage.d.ts +2 -2
  20. package/dist/src/components/Citadel/types/__tests__/command-registry.test.d.ts +1 -0
  21. package/dist/src/components/Citadel/types/__tests__/segment-stack.test.d.ts +1 -0
  22. package/dist/src/components/Citadel/types/command-registry.d.ts +84 -0
  23. package/dist/src/components/Citadel/types/command-trie.d.ts +49 -203
  24. package/dist/src/components/Citadel/types/help-command.d.ts +3 -3
  25. package/dist/src/components/Citadel/types/segment-stack.d.ts +62 -0
  26. package/dist/src/components/Citadel/types/state.d.ts +8 -22
  27. package/dist/src/components/Citadel/types/storage.d.ts +4 -3
  28. package/dist/src/components/Citadel/utils/logger.d.ts +21 -0
  29. package/dist/src/index.d.ts +0 -1
  30. package/package.json +3 -3
@@ -1,26 +1,42 @@
1
1
  import { CursorType } from '../types/cursor';
2
2
  import { StorageConfig } from '../types/storage';
3
+ import { LogLevel } from '../utils/logger';
3
4
  export interface CitadelConfig {
4
5
  /**
5
- * Configuration for command history storage
6
+ * The time in milliseconds before a command execution fails with a timeout.
6
7
  */
7
- storage?: StorageConfig;
8
+ commandTimeoutMs?: number;
8
9
  /**
9
- * Whether to include the default help command in the command trie.
10
+ * The color of the cursor.
11
+ * Accepts any valid CSS color value.
10
12
  */
11
- includeHelpCommand?: boolean;
13
+ cursorColor?: string;
12
14
  /**
13
- * Whether to reset the state when the interface is hidden (via Escape key or other means).
15
+ * The speed of the cursor animation in milliseconds.
16
+ * - For 'blink': Time between blinks (default: 530ms)
17
+ * - For 'spin' and 'bbs': Time between frame changes (default: 120ms)
18
+ * - For 'solid': Has no effect
14
19
  */
15
- resetStateOnHide?: boolean;
20
+ cursorSpeed?: number;
16
21
  /**
17
- * The keyboard key that shows the command interface.
22
+ * The type of cursor to display. Can be one of 'blink', 'spin', 'solid', or 'bbs'.
18
23
  */
19
- showCitadelKey?: string;
24
+ cursorType?: CursorType;
20
25
  /**
21
- * The time in milliseconds before a command execution fails with a timeout.
26
+ * Whether to include the default help command in the command regsitry.
22
27
  */
23
- commandTimeoutMs?: number;
28
+ includeHelpCommand?: boolean;
29
+ /**
30
+ * The initial height of the command interface.
31
+ * Accepts any valid CSS height value.
32
+ * Example: '400px' or '50vh'
33
+ */
34
+ initialHeight?: string;
35
+ /**
36
+ * The log level for Citadel's logger
37
+ * @default LogLevel.DEBUG in development, LogLevel.ERROR in production
38
+ */
39
+ logLevel?: LogLevel;
24
40
  /**
25
41
  * Optional CSS value for the maximum height of the command interface.
26
42
  * If provided, this value will be set as the `max-height` property of the interface.
@@ -38,19 +54,15 @@ export interface CitadelConfig {
38
54
  */
39
55
  outputFontSize?: string;
40
56
  /**
41
- * The type of cursor to display. Can be one of 'blink', 'spin', 'solid', or 'bbs'.
57
+ * Whether to reset the state when the interface is hidden (via Escape key or other means).
42
58
  */
43
- cursorType?: CursorType;
59
+ resetStateOnHide?: boolean;
44
60
  /**
45
- * The color of the cursor.
46
- * Accepts any valid CSS color value.
61
+ * The keyboard key that shows the command interface.
47
62
  */
48
- cursorColor?: string;
63
+ showCitadelKey?: string;
49
64
  /**
50
- * The speed of the cursor animation in milliseconds.
51
- * - For 'blink': Time between blinks (default: 530ms)
52
- * - For 'spin' and 'bbs': Time between frame changes (default: 120ms)
53
- * - For 'solid': Has no effect
65
+ * Configuration for command history storage
54
66
  */
55
- cursorSpeed?: number;
67
+ storage?: StorageConfig;
56
68
  }
@@ -2,5 +2,6 @@ import { CitadelState, CitadelActions } from '../types/state';
2
2
  export declare const useCitadelState: () => {
3
3
  state: CitadelState;
4
4
  actions: CitadelActions;
5
- getAvailableCommands: () => import('../types/command-trie').CommandNode[];
5
+ getAvailableCommands_s: () => string[];
6
+ getAvailableCommandSegments: () => import('../types/command-registry').CommandSegment[];
6
7
  };
@@ -1,17 +1,27 @@
1
1
  import { StoredCommand } from '../types/storage';
2
+ import { CommandSegment } from '../types/command-registry';
2
3
  export interface CommandHistory {
3
- commands: StoredCommand[];
4
+ storedCommands: StoredCommand[];
4
5
  position: number | null;
5
- savedInput: string | null;
6
6
  }
7
7
  export interface CommandHistoryActions {
8
- addCommand: (command: StoredCommand) => Promise<void>;
9
- getCommands: () => StoredCommand[];
10
- navigateHistory: (direction: 'up' | 'down', currentInput: string) => {
11
- command: StoredCommand | null;
8
+ addStoredCommand: (segments: CommandSegment[]) => Promise<void>;
9
+ getStoredCommands: () => Promise<StoredCommand[]>;
10
+ navigateHistory: (direction: 'up' | 'down', currentSegments: CommandSegment[]) => Promise<{
11
+ segments: CommandSegment[] | null;
12
12
  position: number | null;
13
- };
14
- saveInput: (input: string) => void;
13
+ }>;
15
14
  clear: () => Promise<void>;
16
15
  }
17
- export declare function useCommandHistory(): [CommandHistory, CommandHistoryActions];
16
+ export declare function createStoredCommand(segments: CommandSegment[]): StoredCommand;
17
+ export interface CommandHistoryHook {
18
+ history: CommandHistory;
19
+ addStoredCommand: (segments: CommandSegment[]) => Promise<void>;
20
+ getStoredCommands: () => Promise<StoredCommand[]>;
21
+ navigateHistory: (direction: 'up' | 'down', currentSegments: CommandSegment[]) => Promise<{
22
+ segments: CommandSegment[] | null;
23
+ position: number | null;
24
+ }>;
25
+ clear: () => Promise<void>;
26
+ }
27
+ export declare function useCommandHistory(): CommandHistoryHook;
@@ -1,19 +1,22 @@
1
- import { CommandNode, CommandTrie } from '../types/command-trie';
1
+ import { CommandNode, CommandSegment } from '../types/command-registry';
2
2
  import { CitadelState, CitadelActions } from '../types/state';
3
- import { StoredCommand } from '../types/storage';
4
- type InputState = 'idle' | 'entering_command' | 'entering_argument';
5
- interface UseCommandParserProps {
6
- commandTrie?: CommandTrie;
7
- }
8
- export declare function useCommandParser({ commandTrie: propsTrie }?: UseCommandParserProps): {
9
- handleInputChange: (newValue: string, state: CitadelState, actions: CitadelActions) => void;
10
- handleKeyDown: (e: KeyboardEvent, state: CitadelState, actions: CitadelActions) => void;
11
- executeCommand: (commandStack: string[], actions: CitadelActions, args?: string[]) => void;
3
+ export type InputState = 'idle' | 'entering_command' | 'entering_argument';
4
+ export declare const useCommandParser: () => {
5
+ handleInputChange: (newValue: string, actions: CitadelActions) => void;
6
+ handleKeyDown: (e: KeyboardEvent | React.KeyboardEvent, state: CitadelState, actions: CitadelActions) => Promise<void>;
12
7
  inputState: InputState;
13
- replayCommand: (command: StoredCommand, state: CitadelState, actions: CitadelActions) => Promise<void>;
8
+ setInputStateWithLogging: (newState: InputState) => void;
14
9
  findMatchingCommands: (input: string, availableNodes: CommandNode[]) => CommandNode[];
15
- getAutocompleteSuggestion: (input: string, availableNodes: CommandNode[]) => string | null;
16
- getAvailableNodes: (currentNode?: CommandNode) => CommandNode[];
17
- isValidCommandInput: (input: string, availableNodes: CommandNode[]) => boolean;
10
+ getAutocompleteSuggestion: (input: string) => CommandSegment;
11
+ getAvailableNodes: () => CommandNode[];
12
+ getNextExpectedSegment: () => CommandSegment;
13
+ isValidCommandInput: (input: string) => boolean;
18
14
  };
19
- export {};
15
+ export interface ParsedInput {
16
+ words: string[];
17
+ currentWord: string;
18
+ isQuoted: boolean;
19
+ quoteChar?: "'" | '"';
20
+ isComplete: boolean;
21
+ }
22
+ export declare function parseInput(input: string): ParsedInput;
@@ -0,0 +1,14 @@
1
+ import { ArgumentSegment, CommandSegment } from '../types/command-registry';
2
+ export interface SegmentStackActions {
3
+ push: (segment: CommandSegment) => void;
4
+ pop: () => CommandSegment;
5
+ peek: () => CommandSegment;
6
+ clear: () => void;
7
+ hasArguments: () => boolean;
8
+ getArguments: () => ArgumentSegment[];
9
+ path: () => string[];
10
+ segments: () => CommandSegment[];
11
+ isEmpty: () => boolean;
12
+ size: () => number;
13
+ }
14
+ export declare function useSegmentStack(): SegmentStackActions;
@@ -0,0 +1 @@
1
+ export declare const useSegmentStackVersion: () => number;
@@ -8,11 +8,11 @@ export declare abstract class BaseStorage implements CommandStorage {
8
8
  /**
9
9
  * Add a command to history, enforcing storage limits
10
10
  */
11
- addCommand(command: StoredCommand): Promise<void>;
11
+ addStoredCommand(command: StoredCommand): Promise<void>;
12
12
  /**
13
13
  * Get all stored commands, ordered by timestamp ascending
14
14
  */
15
- abstract getCommands(): Promise<StoredCommand[]>;
15
+ abstract getStoredCommands(): Promise<StoredCommand[]>;
16
16
  /**
17
17
  * Clear all stored commands
18
18
  */
@@ -6,7 +6,7 @@ import { BaseStorage } from './BaseStorage';
6
6
  export declare class LocalStorage extends BaseStorage {
7
7
  private readonly storageKey;
8
8
  constructor(config: StorageConfig);
9
- getCommands(): Promise<StoredCommand[]>;
9
+ getStoredCommands(): Promise<StoredCommand[]>;
10
10
  clear(): Promise<void>;
11
11
  protected saveCommands(commands: StoredCommand[]): Promise<void>;
12
12
  }
@@ -4,9 +4,9 @@ import { BaseStorage } from './BaseStorage';
4
4
  * In-memory command history storage
5
5
  */
6
6
  export declare class MemoryStorage extends BaseStorage {
7
- private commands;
7
+ private storedCommands;
8
8
  constructor(config?: StorageConfig);
9
- getCommands(): Promise<StoredCommand[]>;
9
+ getStoredCommands(): Promise<StoredCommand[]>;
10
10
  clear(): Promise<void>;
11
11
  protected saveCommands(commands: StoredCommand[]): Promise<void>;
12
12
  }
@@ -0,0 +1,84 @@
1
+ import { CommandResult } from './command-results';
2
+ /** Function type for handling command execution */
3
+ export type CommandHandler = (args: string[]) => Promise<CommandResult>;
4
+ /**
5
+ * A no-op handler that returns an empty string. Used as the default handler
6
+ * for CommandNodes that don't specify a handler.
7
+ */
8
+ export declare const NoopHandler: CommandHandler;
9
+ /** Base interface for command segments */
10
+ export declare abstract class BaseSegment {
11
+ readonly type: 'word' | 'argument' | 'null';
12
+ readonly name: string;
13
+ readonly description?: string | undefined;
14
+ constructor(type: 'word' | 'argument' | 'null', name: string, description?: string | undefined);
15
+ toString(): string;
16
+ }
17
+ /** Represents a null segment for empty stack operations */
18
+ export declare class NullSegment extends BaseSegment {
19
+ constructor();
20
+ }
21
+ /** Represents a segment in a command path - either a word or argument */
22
+ export type CommandSegment = WordSegment | ArgumentSegment | NullSegment;
23
+ /** Represents a literal word in a command path */
24
+ export declare class WordSegment extends BaseSegment {
25
+ constructor(name: string, description?: string);
26
+ }
27
+ /** Represents an argument that can be passed to a command, and its value*/
28
+ export declare class ArgumentSegment extends BaseSegment {
29
+ value?: string | undefined;
30
+ readonly valid?: (() => boolean) | undefined;
31
+ constructor(name: string, description?: string, value?: string | undefined, valid?: (() => boolean) | undefined);
32
+ }
33
+ /** Defines a complete command with its path and behavior */
34
+ export declare class CommandNode {
35
+ private readonly _segments;
36
+ private readonly _description?;
37
+ private readonly _handler;
38
+ constructor(segments: CommandSegment[], description?: string, handler?: CommandHandler);
39
+ get segments(): CommandSegment[];
40
+ get description(): string | undefined;
41
+ get handler(): CommandHandler;
42
+ get hasArguments(): boolean;
43
+ get fullPath(): string[];
44
+ get fullPath_s(): string;
45
+ equals(other: CommandNode): boolean;
46
+ }
47
+ /**
48
+ * Used to store user-defined commands.
49
+ */
50
+ export declare class CommandRegistry {
51
+ private _commands;
52
+ get commands(): CommandNode[];
53
+ /**
54
+ * Registers a new command
55
+ *
56
+ * @param newCommandNode The new command to add
57
+ * @throws {Error} If attempting to add a duplicate leaf command or a subcommand to a leaf
58
+ *
59
+ */
60
+ addCommand(segments: CommandSegment[], description: string, handler?: CommandHandler): void;
61
+ /**
62
+ * Retrieves a command from the registry for the given path.
63
+ *
64
+ * @param path The path of the command.
65
+ * @returns The command node or undefined if not found.
66
+ */
67
+ getCommand(path: string[]): CommandNode | undefined;
68
+ commandExistsForPath(path: string[]): boolean;
69
+ /**
70
+ * Gets possible matches for a given path.
71
+ *
72
+ * @param path The path to get completions for.
73
+ * @returns An array of completion strings.
74
+ */
75
+ getCompletions_s(path: string[]): string[];
76
+ /**
77
+ * Gets an array of segments reachable from a given path
78
+ *
79
+ * @param path The path to get completions for.
80
+ * @returns An array of completion strings.
81
+ */
82
+ getCompletions(path: string[]): CommandSegment[];
83
+ hasNextSegment(path: string[]): boolean;
84
+ }
@@ -1,146 +1,63 @@
1
1
  import { CommandResult } from './command-results';
2
2
  /** Function type for handling command execution */
3
3
  export type CommandHandler = (args: string[]) => Promise<CommandResult>;
4
- /**
5
- * Represents an argument that can be passed to a command
6
- */
7
- export interface CommandArgument {
8
- name: string;
9
- description: string;
10
- }
11
- export interface CommandNodeParams {
12
- fullPath: string[];
13
- description: string;
14
- parent?: CommandNode;
15
- argument?: CommandArgument;
16
- handler?: CommandHandler;
17
- }
18
- export interface CommandSignature {
19
- signature: string[];
20
- }
21
4
  /**
22
5
  * A no-op handler that returns an empty string. Used as the default handler
23
6
  * for CommandNodes that don't specify a handler.
24
7
  */
25
8
  export declare const NoopHandler: CommandHandler;
9
+ /** Base interface for command segments */
10
+ export declare abstract class BaseSegment {
11
+ readonly type: 'word' | 'argument' | 'null';
12
+ readonly name: string;
13
+ readonly description?: string | undefined;
14
+ constructor(type: 'word' | 'argument' | 'null', name: string, description?: string | undefined);
15
+ toString(): string;
16
+ }
17
+ /** Represents a null segment for empty stack operations */
18
+ export declare class NullSegment extends BaseSegment {
19
+ constructor();
20
+ }
21
+ /** Represents a segment in a command path - either a word or argument */
22
+ export type CommandSegment = WordSegment | ArgumentSegment | NullSegment;
23
+ /** Represents a literal word in a command path */
24
+ export declare class WordSegment extends BaseSegment {
25
+ constructor(name: string, description?: string);
26
+ }
27
+ /** Represents an argument that can be passed to a command, and its value*/
28
+ export declare class ArgumentSegment extends BaseSegment {
29
+ value?: string | undefined;
30
+ readonly valid?: (() => boolean) | undefined;
31
+ constructor(name: string, description?: string, value?: string | undefined, valid?: (() => boolean) | undefined);
32
+ }
33
+ /** Defines a complete command with its path and behavior */
26
34
  export declare class CommandNode {
27
- private _fullPath;
28
- private _description;
29
- private _children;
30
- private _argument?;
31
- private _handler;
32
- private _parent?;
33
- private _signature?;
34
- /**
35
- * Creates a new CommandNode representing a command the user can enter. From a
36
- * high level, a command is one or more words followed by an optional
37
- * argument, and with an optional handler.
38
- *
39
- * @param params Configuration parameters for the node
40
- * @param params.fullPath Complete path from root to this node (e.g., ['service', 'deploy'])
41
- * @param params.description Human-readable description of the command
42
- * @param params.parent Optional parent node in the command hierarchy
43
- * @param params.handler Optional async function to execute when command is invoked
44
- * @param params.argument Optional argument definition for the command
45
- * @throws {Error} If fullPath is empty or undefined
46
- *
47
- */
48
- constructor(params: CommandNodeParams);
49
- /**
50
- * Gets the name of this command (last segment of the path)
51
- */
52
- get name(): string;
53
- /**
54
- * Whether this is a leaf node (has no children)
55
- */
56
- get isLeaf(): boolean;
57
- /**
58
- * Whether this command has a handler
59
- */
60
- get hasHandler(): boolean;
61
- /**
62
- * Whether this command requires an argument
63
- */
64
- get requiresArgument(): boolean;
65
- /**
66
- * Gets the parent node if it exists
67
- */
68
- get parent(): CommandNode | undefined;
69
- /**
70
- * Gets the command's signature
71
- */
72
- get signature(): string | undefined;
73
- /**
74
- * Sets the signature for this command based on the current command trie state
75
- * @param trie The command trie to use for signature generation
76
- */
77
- setSignature(trie: CommandTrie): void;
78
- /**
79
- * Gets the map of child commands
80
- */
81
- get children(): ReadonlyMap<string, CommandNode>;
82
- /**
83
- * Whether this command has any children
84
- */
85
- get hasChildren(): boolean;
86
- /**
87
- * Adds a child command
88
- */
89
- addChild(segment: string, node: CommandNode): void;
90
- /**
91
- * Gets a child command by name
92
- */
93
- getChild(name: string): CommandNode | undefined;
94
- /**
95
- * Gets the full path from root to this command
96
- */
97
- get fullPath(): string[];
98
- /**
99
- * Gets the command's description
100
- */
101
- get description(): string;
102
- /**
103
- * Gets the command's argument definition if it exists
104
- */
105
- get argument(): CommandArgument | undefined;
106
- /**
107
- * Sets the command's argument definition
108
- */
109
- set argument(value: CommandArgument | undefined);
110
- /**
111
- * Gets the command's handler
112
- */
35
+ private readonly _segments;
36
+ private readonly _description?;
37
+ private readonly _handler;
38
+ constructor(segments: CommandSegment[], description?: string, handler?: CommandHandler);
39
+ get segments(): CommandSegment[];
40
+ get description(): string | undefined;
113
41
  get handler(): CommandHandler;
114
- /**
115
- * Sets the command's handler
116
- */
117
- set handler(value: CommandHandler);
42
+ get hasArguments(): boolean;
43
+ get fullPath(): string[];
44
+ get fullPath_s(): string;
45
+ equals(other: CommandNode): boolean;
118
46
  }
119
47
  /**
120
- * A trie data structure for managing hierarchical commands.
121
- * Provides functionality for adding commands, retrieving commands,
122
- * and getting command completions.
48
+ * Used to store user-defined commands.
123
49
  */
124
- export declare class CommandTrie {
125
- private readonly _root;
126
- /**
127
- * Creates a new CommandTrie instance.
128
- */
129
- constructor();
50
+ export declare class CommandRegistry {
51
+ private _commands;
52
+ get commands(): CommandNode[];
130
53
  /**
131
54
  * Adds a new command to the trie.
132
55
  *
133
- * @param params Parameters for the command.
134
- * @param params.path The path segments for the command (e.g., ['service', 'deploy'])
135
- * @param params.description Description of what the command does
136
- * @param params.handler Optional function to execute when command is invoked
137
- * @param params.argument Optional argument definition for the command
56
+ * @param newCommandNode The new command to add
138
57
  * @throws {Error} If attempting to add a duplicate leaf command or a subcommand to a leaf
139
58
  *
140
59
  */
141
- addCommand(params: Omit<ConstructorParameters<typeof CommandNode>[0], 'fullPath' | 'parent'> & {
142
- path: string[];
143
- }): void;
60
+ addCommand(segments: CommandSegment[], description: string, handler?: CommandHandler): void;
144
61
  /**
145
62
  * Retrieves a command from the trie.
146
63
  *
@@ -148,91 +65,20 @@ export declare class CommandTrie {
148
65
  * @returns The command node or undefined if not found.
149
66
  */
150
67
  getCommand(path: string[]): CommandNode | undefined;
68
+ commandExistsForPath(path: string[]): boolean;
151
69
  /**
152
- * Gets command completions for a given path.
70
+ * Gets possible matches for a given path.
153
71
  *
154
72
  * @param path The path to get completions for.
155
73
  * @returns An array of completion strings.
156
74
  */
157
- getCompletions(path: string[]): string[];
75
+ getCompletions_s(path: string[]): string[];
158
76
  /**
159
- * Executes a command with the given path and arguments.
160
- * @param path The command path
161
- * @param args Arguments to pass to the command handler
162
- * @returns The command result or undefined if command not found
163
- * @throws Error if command validation fails
164
- */
165
- executeCommand(path: string[], args?: string[]): Promise<CommandResult | undefined>;
166
- /**
167
- * Gets the root commands in the trie.
77
+ * Gets an array of segments reachable from a given path
168
78
  *
169
- * @returns An array of root command nodes.
170
- */
171
- getRootCommands(): CommandNode[];
172
- /**
173
- * Gets the leaf commands in the trie.
174
- *
175
- * @returns An array of leaf command nodes.
176
- */
177
- getLeafCommands(): CommandNode[];
178
- /**
179
- * Retrieves a command using its unique signature.
180
- * A signature is the minimal sequence of prefixes that uniquely identifies a command.
181
- *
182
- * @param signature Array of minimal prefixes that uniquely identify the command
183
- * @returns The matching command node or undefined if not found
184
- *
185
- * @example
186
- * // Will match 'image random cat' command
187
- * getCommandBySignature(['i', 'r', 'c'])
188
- * // Will match 'user show' command (not ambiguous with 'user status')
189
- * getCommandBySignature(['u', 'sh'])
190
- */
191
- getCommandBySignature(signature: CommandSignature): CommandNode | undefined;
192
- /**
193
- * Generates a minimal unique signature for a command node.
194
- * The signature consists of the shortest prefixes that uniquely identify each segment
195
- * in the path from root to this node.
196
- *
197
- * @param command The command node to generate a signature for
198
- * @returns Array of minimal prefixes that uniquely identify the command
199
- *
200
- * @example
201
- * // For commands: ['image', 'random', 'cat'] and ['image', 'random', 'dog']
202
- * buildSignatureForCommand(catCommand) // returns ['i', 'r', 'c']
203
- * // For commands: ['user', 'show'] and ['user', 'status']
204
- * buildSignatureForCommand(showCommand) // returns ['u', 'sh']
205
- */
206
- buildSignatureForCommand(command: CommandNode): CommandSignature;
207
- /**
208
- * Validates the command trie structure for common errors.
209
- *
210
- * Performs the following validations:
211
- * 1. Checks for duplicate command paths
212
- * 2. Ensures non-leaf nodes (nodes with children) use NoopHandler
213
- * 3. Ensures non-leaf nodes don't have arguments
214
- * 4. Verifies all nodes have a handler (either custom or NoopHandler)
215
- * 5. Validates command path uniqueness
216
- *
217
- * @returns An object containing:
218
- * - isValid: boolean indicating if the trie is valid
219
- * - errors: array of error messages describing any validation failures
220
- *
221
- * @example
222
- * ```typescript
223
- * const result = commandTrie.validate();
224
- * if (!result.isValid) {
225
- * console.error('Command trie validation failed:');
226
- * result.errors.forEach(error => console.error(error));
227
- * }
228
- * ```
229
- */
230
- /**
231
- * Updates signatures for all nodes in the trie
79
+ * @param path The path to get completions for.
80
+ * @returns An array of completion strings.
232
81
  */
233
- setSignatures(): void;
234
- validate(): {
235
- isValid: boolean;
236
- errors: string[];
237
- };
82
+ getCompletions(path: string[]): CommandSegment[];
83
+ hasNextSegment(path: string[]): boolean;
238
84
  }
@@ -1,3 +1,3 @@
1
- import { CommandNode, CommandTrie } from './command-trie';
2
- import { CitadelConfig } from '../config/types';
3
- export declare const createHelpCommand: (trie: CommandTrie, config: CitadelConfig) => [string, CommandNode];
1
+ import { CommandRegistry } from './command-registry';
2
+ import { TextCommandResult } from './command-results';
3
+ export declare const createHelpHandler: (cmdRegistry: CommandRegistry) => (_args: string[]) => Promise<TextCommandResult>;